From 566213c178c9a693c61054444e715f2afe0b433e Mon Sep 17 00:00:00 2001 From: Jolan Rathelot Date: Wed, 2 Apr 2025 11:05:25 -0400 Subject: [PATCH] stddev --- Makefile | 2 +- includes/main.h | 1 + srcs/main.c | 94 ++++++++++++++++++++++++++++++++++++++----------- 3 files changed, 76 insertions(+), 21 deletions(-) diff --git a/Makefile b/Makefile index 931b725..b8f79b9 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ # Project Meta Settings NAME = ft_ping -RELEASE_TYPE = Release +RELEASE_TYPE = Debug CURRENT_DIR = ${CURDIR} # Project Build Output Settings diff --git a/includes/main.h b/includes/main.h index c65cf60..4826f87 100644 --- a/includes/main.h +++ b/includes/main.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include diff --git a/srcs/main.c b/srcs/main.c index 6589b6c..87094b0 100644 --- a/srcs/main.c +++ b/srcs/main.c @@ -1,5 +1,21 @@ #include +// ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ +// ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⠉⠀⢻⣿⣿⣿⣿⣿⣿⡿⠁⠀⠙⢿⣿⣿ +// ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏⠀⠀⠀⣾⣿⣿⣿⣿⣿⣿⠇⠀⠀⠀⠈⣿⣿ +// ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠿⠛⠛⠛⠛⠿⣿⠀⠀⠀⠀⢀⣿⣿ +// ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⣀⣤⡀⠀⠀⠀⠀⣀⡀⠀⠀⠀⢀⠀⢸⣿⣿ +// ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⣴⣿⣿⠇⠀⠀⢠⣾⣿⣿⣆⠀⠀⠀⠀⣿⣿⣿ +// ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⢡⣿⣿⣿⠀⠀⢀⣿⣿⣿⣿⣿⠀⠀⠀⢸⣿⣿⣿ +// ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠁⢸⣿⡿⠃⠀⠀⢸⣿⣿⣿⣿⠏⠀⠀⠀⡘⣿⣿⣿ +// ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡀⠀⠈⠀⠈⠭⠀⠈⠛⠿⠛⠋⠀⠀⠀⠀⠠⣿⣿⣿ +// ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡑⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿ +// ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⠈⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿ +// ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡏⠀⢣⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿ +// ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠀⠀⠈⢃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿ +// ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿ +// ⣿⣿⣿⣿⣿⣿⣿⣿⡿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿ + const char* argp_program_version = "ft_ping 1.0"; const char* argp_program_bug_address = ""; static char doc[] = "Send ICMP ECHO_REQUEST packets to network hosts.\vMandatory or optional arguments to long options " @@ -54,10 +70,6 @@ struct timespec sendt; unsigned long xmit = 0; unsigned long recvd = 0; -double min = 0; -double max = 0; -double avg = 0; - uint16_t calc_checksum(void* b, size_t len) { unsigned short* buf = b; unsigned int sum = 0; @@ -88,7 +100,7 @@ void send_ping() { struct timeval tmp_tv; gettimeofday(&tmp_tv, NULL); - memcpy(packet.msg, &tmp_tv, sizeof(tmp_tv)); + memcpy(packet.msg, &tmp_tv, sizeof(struct timeval)); for (long unsigned i = 0; i < sizeof(packet.msg) - sizeof(tmp_tv); ++i) { packet.msg[sizeof(tmp_tv) + i] = (char)i; } @@ -108,18 +120,36 @@ void sig_handler(int sig) { } } +double nabs(double a) { return (a < 0) ? -a : a; } + +double nsqrt(double a, double prec) { + double b; + double c; + + if (a < 0) { + return 0; + } + if (a < prec) { + return 0; + } + c = a / 2; + do { + b = c; + c = (b + a / b) / 2; + } while (nabs(c - b) > prec); + + return c; +} + int main(int argc, char** argv) { struct arguments arguments; int timeout = 3000; struct timespec recvt; struct pollfd fds[1]; - float min; - float max; - float avg; - - min = INT32_MAX; - max = 0; - avg = 0; + double min = INT32_MAX; + double max = 0; + double avg = 0; + double stddev = 0; arguments.verbose = 0; arguments.ttl = 64; @@ -151,20 +181,22 @@ int main(int argc, char** argv) { fds[0].fd = sock; fds[0].events = POLLIN; - struct sigaction sig_handle; + struct sigaction sig_handle = {0}; sig_handle.sa_handler = sig_handler; sigaction(SIGINT, &sig_handle, 0); sigaction(SIGALRM, &sig_handle, 0); + printf("PING %s (%s): %ld data bytes\n", arguments.args[0], arguments.args[0], 64 - sizeof(struct icmphdr)); + send_ping(); while (!stop) { int ret = poll(fds, 1, timeout); if (ret > 0) { if (fds[0].revents & POLLIN) { - char buf[100]; + char buf[100] = {0}; long int bytes_received = recvfrom(sock, buf, 100, 0, NULL, NULL); @@ -173,34 +205,56 @@ int main(int argc, char** argv) { return 1; } + if ((size_t)bytes_received < sizeof(struct ip) + sizeof(struct icmphdr) + 8) { + dprintf(STDERR_FILENO, "packet too short (%ld bytes) from %s\n", bytes_received, arguments.args[0]); + pause(); + continue; + } + 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 old_checksum = icmp_reply->checksum; + icmp_reply->checksum = 0; + + if (old_checksum != calc_checksum(icmp_reply, bytes_received - (ip_header->ip_hl << 2))) { + dprintf(STDERR_FILENO, "checksum mismatch from %s\n", arguments.args[0]); + pause(); + continue; + } + + icmp_reply->checksum = old_checksum; + float tmp = ((recvt.tv_sec * 1000 + recvt.tv_nsec / 1000000) - (sendt.tv_sec * 1000 + sendt.tv_nsec / 1000000)); - tmp += ((float) ((recvt.tv_nsec - sendt.tv_nsec) % 1000000) / 1000000.0); + tmp += ((float)((recvt.tv_nsec - sendt.tv_nsec) % 1000000) / 1000000.0); - printf("%zd bytes from %s: icmp_seq=%d ttl=%d time=%.3f ms \n", bytes_received, arguments.args[0], - icmp_reply->un.echo.sequence, ip_header->ip_ttl, tmp); + printf("%zd bytes from %s: icmp_seq=%d ttl=%d time=%.3f ms \n", bytes_received - sizeof(struct ip), + arguments.args[0], icmp_reply->un.echo.sequence + 1, ip_header->ip_ttl, tmp); min = (((min) < (tmp)) ? (min) : (tmp)); max = (((max) > (tmp)) ? (max) : (tmp)); avg += tmp; + stddev += tmp * tmp; recvd++; } } else if (ret == 0) { printf("No reply received within the timeout period\n"); - } else { - perror("Poll failed"); } + // else { + // perror("Poll failed"); + // } pause(); } + fflush(stdout); printf("---- %s ping statistics ----\n", arguments.args[0]); printf("%zu packets transmitted, %zu packets received, %zu%% packet loss\n", xmit, recvd, (xmit - recvd) / xmit * 100); - printf("round-trip min/avg/max/stddev = %.3f/%.3f/%.3f/%%.3f ms\n", min, max, avg / recvd); + avg /= recvd; + stddev = stddev / recvd - avg * avg; + printf("round-trip min/avg/max/stddev = %.3f/%.3f/%.3f/%.3f ms\n", min, max, avg, nsqrt(stddev, 0.0005)); close(sock); } \ No newline at end of file