#include #include #include #include #include #include #include #include #include #include #include #define BUFSIZE 1024 using namespace std; /* Funkce checksum je opsaná z přísluąných RFC dokumentů. */ unsigned short checksum(unsigned char *addr, int count) { register long sum = 0; while( count > 1 ) { /* This is the inner loop */ sum += * ((unsigned short *) addr)++; count -= 2; } /* Add left-over byte, if any */ if( count > 0 ) sum += * (unsigned char *) addr; /* Fold 32-bit sum to 16 bits */ while (sum>>16) sum = (sum & 0xffff) + (sum >> 16); return ~sum; } int main(int argc, char *argv[]) { size_t size; hostent *host; icmphdr *icmp, *icmpRecv; iphdr *ip; int sock, lenght; unsigned int ttl; sockaddr_in sendSockAddr, receiveSockAddr; char buffer[BUFSIZE]; fd_set mySet; timeval tv; char *addrString; unsigned short int pid = getpid(), p; if (argc != 2) { cerr << "Syntaxe:\n\t" << argv[0] << " " << "adresa" << endl; return -1; } /* Zjistíme info o vzdáleném počítači */ if ((host = gethostbyname(argv[1])) == NULL) { cerr << "©patná adresa" << endl; return -1; } /* Vytvořím soket */ if ((sock = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP)) == -1) { cerr << "Nelze vytvořit soket" << endl; return -1; } setsockopt(sock, SOL_IP, IP_TTL, (const char *)&ttl, sizeof(ttl)); /* Zaplníme poloľky ICMP hlavičky */ icmp = (icmphdr *)malloc(sizeof(icmphdr)); icmp->type = ICMP_ECHO; icmp->code = 0; icmp->un.echo.id = pid; /* Připravíme sendto */ sendSockAddr.sin_family = AF_INET; sendSockAddr.sin_port = 0; memcpy(&(sendSockAddr.sin_addr), host->h_addr, host->h_length); for (p = 1; p <= 5; p++) { icmp->checksum = 0; icmp->un.echo.sequence = p; icmp->checksum = checksum((unsigned char *)icmp, sizeof(icmphdr)); sendto(sock, (char *)icmp, sizeof(icmphdr), 0, (sockaddr *)&sendSockAddr, sizeof(sockaddr)); tv.tv_sec = 5; tv.tv_usec = 0; do { FD_ZERO(&mySet); FD_SET(sock, &mySet); if (select(sock + 1, &mySet, NULL, NULL, &tv) < 0) { cerr << "Selhal select" << endl; break; } if (FD_ISSET(sock, &mySet)) { size = sizeof(sockaddr_in); if ((lenght = recvfrom(sock, buffer, BUFSIZE, 0, (sockaddr *)&receiveSockAddr, &size)) == -1) { cerr << "Problem při přijímáni dat" << endl; } /* Přiąel blok dat IP hlavička + ICMP hlavička. */ ip = (iphdr *) buffer; icmpRecv = (icmphdr *) (buffer + ip->ihl * 4); if ((icmpRecv->un.echo.id == pid) && (icmpRecv->type == ICMP_ECHOREPLY) && (icmpRecv->un.echo.sequence == p)) { addrString = strdup(inet_ntoa(receiveSockAddr.sin_addr)); host = gethostbyaddr(&receiveSockAddr.sin_addr, 4, AF_INET); cout << lenght << " bytů z " << (host == NULL? "?" : host->h_name) << " (" << addrString << "): icmp_seq=" << icmpRecv->un.echo.sequence << " ttl=" << (int)ip->ttl << " čas=nevím, neměřil jsem:-)" << endl; free(addrString); } } else { cout << "Čas vyprąel" << endl; break; } } while (!((icmpRecv->un.echo.id == pid) && (icmpRecv->type == ICMP_ECHOREPLY) && (icmpRecv->un.echo.sequence == p))); } close(sock); free(icmp); return 0; }