diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..70e34ec --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "C_Cpp.errorSquiggles": "disabled" +} \ No newline at end of file diff --git a/includes/main.h b/includes/main.h index e769fe2..c65cf60 100644 --- a/includes/main.h +++ b/includes/main.h @@ -13,6 +13,9 @@ #include #include #include +#include +#include +#include struct arguments { char* args[1]; diff --git a/srcs/main.c b/srcs/main.c index f37a315..87a0877 100644 --- a/srcs/main.c +++ b/srcs/main.c @@ -25,7 +25,7 @@ static error_t parse_opt(int key, char* arg, struct argp_state* state) { break; case ARG_TTL: arguments->ttl = strtoul(arg, NULL, 10); - __attribute__ ((fallthrough)); + __attribute__((fallthrough)); case ARGP_KEY_ARG: if (state->arg_num >= 2) argp_usage(state); @@ -49,6 +49,8 @@ int sock = 0; static struct sockaddr_in destination; +struct timespec sendt; + unsigned long xmit = 0; unsigned long recvd = 0; @@ -56,31 +58,45 @@ double min = 0; double max = 0; double avg = 0; -uint16_t calc_checksum(void * b, const size_t l) { - uint16_t sum = 0; +uint16_t calc_checksum(void* b, size_t len) { + unsigned short* buf = b; + unsigned int sum = 0; + unsigned short result; - for (size_t i = 0; i < l; i++) { - sum += *((uint16_t*)b + i); + for (sum = 0; len > 1; len -= 2) { + sum += *buf++; } - return ~sum; + if (len == 1) { + sum += *(unsigned char*)buf; + } + + sum = (sum >> 16) + (sum & 0xFFFF); + sum += (sum >> 16); + result = ~sum; + return result; } void send_ping() { struct ping_pkt packet = {0}; packet.hdr.type = ICMP_ECHO; + packet.hdr.code = 0; packet.hdr.un.echo.id = getpid(); packet.hdr.un.echo.sequence = xmit++; - for (long unsigned i = 0; i < sizeof(packet.msg) - 1; ++i) { - packet.msg[i] = (char)i; + struct timeval tmp_tv; + gettimeofday(&tmp_tv, NULL); + + memcpy(packet.msg, &tmp_tv, sizeof(tmp_tv)); + for (long unsigned i = 0; i < sizeof(packet.msg) - sizeof(tmp_tv); ++i) { + packet.msg[sizeof(tmp_tv) + i] = (char)i; } - packet.msg[sizeof(packet.msg) - 1] = '\0'; packet.hdr.checksum = calc_checksum(&packet, sizeof(packet)); sendto(sock, &packet, sizeof(packet), 0, (struct sockaddr*)&destination, sizeof(destination)); + clock_gettime(CLOCK_MONOTONIC, &sendt); alarm(1); } @@ -94,6 +110,10 @@ void sig_handler(int sig) { int main(int argc, char** argv) { struct arguments arguments; + int timeout = 3000; + struct timespec recvt; + struct pollfd fds[1]; + arguments.verbose = 0; arguments.ttl = 64; argp_parse(&argp, argc, argv, 0, 0, &arguments); @@ -121,6 +141,9 @@ int main(int argc, char** argv) { exit(1); } + fds[0].fd = sock; + fds[0].events = POLLIN; + struct sigaction sig_handle; sig_handle.sa_handler = sig_handler; @@ -128,17 +151,49 @@ int main(int argc, char** argv) { sigaction(SIGINT, &sig_handle, 0); sigaction(SIGALRM, &sig_handle, 0); - alarm(1); + send_ping(); while (true) { + int ret = poll(fds, 1, timeout); + if (ret > 0) { + if (fds[0].revents & POLLIN) { + char buf[100]; + + long int bytes_received = recvfrom(sock, buf, 100, 0, NULL, NULL); + + if (bytes_received < 0) { + perror("recvfrom failed"); + return 1; + } + + clock_gettime(CLOCK_MONOTONIC, &recvt); + + struct ip* ip_header = (struct ip*)buf; + struct icmphdr* icmp_reply = (struct icmphdr*)(buf + (ip_header->ip_hl << 2)); + + int rtt_n = + ((recvt.tv_sec * 1000 + recvt.tv_nsec / 1000000) - (sendt.tv_sec * 1000 + sendt.tv_nsec / 1000000)); + int rtt_r = ((recvt.tv_nsec - sendt.tv_nsec) % 1000000 / 1000); + + printf("%zd bytes from %s: icmp_seq=%d ttl=%d time=%d.%d ms \n", bytes_received, arguments.args[0], + icmp_reply->un.echo.sequence, ip_header->ip_ttl, rtt_n, rtt_r); + recvd++; + } + } else if (ret == 0) { + printf("No reply received within the timeout period\n"); + } else { + perror("Poll failed"); + } + + pause(); if (stop) { break; } } printf("---- %s ping statistics ----\n", arguments.args[0]); - printf("%zu packets transmitted, %zu packets received, %%zu%% packet loss\n", xmit, - recvd /*, (xmit - recv) / xmit * 100*/); + printf("%zu packets transmitted, %zu packets received, %zu%% packet loss\n", xmit, recvd, + (xmit - recvd) / xmit * 100); // printf("round-trip min/avg/max/stddev = %f/%f/%f/%f ms\n"); close(sock); } \ No newline at end of file