From de4d18ccb72a110d6446d0f63820bc4999763ad6 Mon Sep 17 00:00:00 2001 From: adjoly Date: Sun, 17 Aug 2025 21:14:31 +0200 Subject: [PATCH] =?UTF-8?q?=E3=80=8C=F0=9F=8F=97=EF=B8=8F=E3=80=8D=20wip:?= =?UTF-8?q?=20wtf=20is=20happening?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- includes/ping.h | 9 ++++++++ src/ping/init_ping.c | 52 ++++++++++++++++++++++++++------------------ src/ping/send_icmp.c | 28 +++++++++++++++++------- src/ping/send_ping.c | 45 ++++++++++++++++++++++++++++---------- 4 files changed, 94 insertions(+), 40 deletions(-) diff --git a/includes/ping.h b/includes/ping.h index 57f619c..004919d 100644 --- a/includes/ping.h +++ b/includes/ping.h @@ -1,6 +1,7 @@ #pragma once #include "netinet/in.h" +#include "netinet/ip_icmp.h" #include #include @@ -26,6 +27,13 @@ typedef struct { uint16_t interval; } options_t; +typedef struct { + struct icmphdr hdr; + char *msg; +} icmp_pckt_t; + +#define MAX_WAIT_TIME 5 + // TODO: implement the verbose mode !!! #define DEFAULT_VERBOSE false @@ -38,6 +46,7 @@ typedef struct { int send_ping(int socket, struct sockaddr_in *dest, options_t opt); int init_socket(options_t opt); void init_packet(char *buf, int seq, uint32_t size); + int send_icmp(int socket, char *buf, struct sockaddr_in *addr, uint32_t size); int receive_icmp(int socket, char *buf, uint32_t size, struct sockaddr_in *addr); diff --git a/src/ping/init_ping.c b/src/ping/init_ping.c index 9d8b97d..08bf811 100644 --- a/src/ping/init_ping.c +++ b/src/ping/init_ping.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -30,37 +31,46 @@ int init_socket(options_t opt) { "can't setsockopt for the linger maybe try a different one"); return -1; } + + struct timeval tv_out; + tv_out.tv_sec = MAX_WAIT_TIME; + tv_out.tv_usec = 0; + + if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv_out, sizeof(tv_out)) < + 0) { + perror("setsockopt"); + fprintf(stderr, "can't setsockopt for the receive timeout"); + return -1; + } return sock; } -unsigned short gen_checksum(unsigned short *addr, int count) { - unsigned long sum = 0; - - while (count > 1) { - sum += *addr++; - count -= 2; - } - if (count > 0) { - sum += *(unsigned char *)addr; - } +unsigned short gen_checksum(unsigned short *buf, int count) { + unsigned int sum = 0; + unsigned short result; + for (sum = 0; count > 1; count -= 2) + sum += *buf++; + if (count == 1) + sum += *(unsigned char *)buf; sum = (sum >> 16) + (sum & 0xFFFF); sum += (sum >> 16); - - return (~sum); + result = ~sum; + return result; } void init_packet(char *buf, int seq, uint32_t size) { - memset(buf, 0, size); - struct icmp *packet = (struct icmp *)buf; + bzero(buf, size); + struct icmphdr *header = (struct icmphdr *)buf; - packet->icmp_type = ICMP_ECHO; - packet->icmp_code = 0; - packet->icmp_id = (getpid() & 0xffff); - packet->icmp_seq = seq; + header->type = ICMP_ECHO; + header->code = 0; + header->un.echo.id = htons(getpid() & 0xffff); + header->un.echo.sequence = htons(seq); - memset(buf + sizeof(struct icmphdr), 0x42, size - sizeof(struct icmphdr)); + int payload_size = size - sizeof(struct icmphdr); + memset(buf + sizeof(struct icmphdr), 0x42, payload_size); - packet->icmp_cksum = 0; - packet->icmp_cksum = gen_checksum((unsigned short *)packet, size); + header->checksum = 0; + header->checksum = gen_checksum((unsigned short *)buf, size); } diff --git a/src/ping/send_icmp.c b/src/ping/send_icmp.c index 33d1ecd..1b47c6a 100644 --- a/src/ping/send_icmp.c +++ b/src/ping/send_icmp.c @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -14,6 +15,7 @@ #include int send_icmp(int socket, char *buf, struct sockaddr_in *addr, uint32_t size) { + printf("sending\n"); int bytes_send = sendto(socket, buf, (unsigned long)size, 0, (struct sockaddr *)addr, sizeof(*addr)); @@ -26,31 +28,41 @@ int send_icmp(int socket, char *buf, struct sockaddr_in *addr, uint32_t size) { int receive_icmp(int socket, char *buf, uint32_t size, struct sockaddr_in *addr) { + printf("received\n"); socklen_t addr_len = sizeof(*addr); int bytes = recvfrom(socket, buf, size, 0, (struct sockaddr *)addr, &addr_len); + + printf("%d\n", bytes); return bytes; } void process_icmp(char *buf, int bytes, struct sockaddr_in *addr, int seq, struct timeval *tv_start, struct timeval *tv_end) { - struct ip *ip = (struct ip *)buf; - int len = ip->ip_hl << 2; - struct icmp *icmp = (struct icmp *)(buf + len); + struct ip *ip = (struct ip *)buf; + int len = ip->ip_hl << 2; + if (len < 20) { + fprintf(stderr, "Invalid IP header length\n"); + return; + } - if (icmp->icmp_type == ICMP_ECHOREPLY && - icmp->icmp_id == (getpid() & 0xffff)) { + struct icmphdr *icmp = (struct icmphdr *)(buf + len); + + if (icmp->type == ICMP_ECHOREPLY && + ntohs(icmp->un.echo.id) == (getpid() & 0xffff)) { + // ntohs(icmp->un.echo.sequence) == seq) { rx_count++; - double rtt = (tv_end->tv_sec - tv_start->tv_sec) / 1000.0 + - (tv_end->tv_usec - tv_start->tv_usec) * 1000.0; + double rtt = (tv_end->tv_sec - tv_start->tv_sec) * 1000.0 + + (tv_end->tv_usec - tv_start->tv_usec) / 1000.0; append_time(rtt); // TODO: fix the time and put the hostname with the ip printf("%d bytes from %s: icmp_seq=%d ttl=%d time=%.3f\n", bytes - len, - inet_ntoa(addr->sin_addr), icmp->icmp_seq, ip->ip_ttl, rtt); + inet_ntoa(addr->sin_addr), ntohs(icmp->un.echo.sequence), + ip->ip_ttl, rtt); } } diff --git a/src/ping/send_ping.c b/src/ping/send_ping.c index 89490c5..27d8208 100644 --- a/src/ping/send_ping.c +++ b/src/ping/send_ping.c @@ -6,19 +6,21 @@ #include #include +#include #include #include #include #include #include #include +#include #include #include #include #include char *address = NULL; -int sock = -1; +int sock = -1; void sigint(int sig) { (void)sig; @@ -46,7 +48,7 @@ options_t init_opt(args_t *args) { int send_ping(int socket, struct sockaddr_in *dest, options_t opt) { struct timeval loop_start, loop_end; struct timeval pkt_start, pkt_end; - struct sockaddr_in addr; + struct sockaddr_in addr = *dest; int bytes; char sendbuf[opt.size]; @@ -54,24 +56,33 @@ int send_ping(int socket, struct sockaddr_in *dest, options_t opt) { gettimeofday(&loop_start, 0); while (727) { - init_packet(sendbuf, tx_count++, opt.size); + int seq = tx_count; + + printf("seq = %d\n", seq); + init_packet(sendbuf, seq, opt.size); + // write(1, sendbuf, opt.size); + gettimeofday(&pkt_start, NULL); bytes = send_icmp(socket, sendbuf, &addr, opt.size); + tx_count++; + bytes = receive_icmp(socket, recvbuf, sizeof(recvbuf), &addr); gettimeofday(&pkt_end, NULL); - if (bytes < 0) { + + if (bytes <= 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { - printf("Request timeout for icmp_seq=%d\n", tx_count - 1); + printf("Request timeout for icmp_seq=%d\n", seq); } else { - fprintf(stderr, "recv failed\n"); + fprintf(stderr, "recv failed: %s\n", strerror(errno)); } } else - process_icmp(recvbuf, bytes, &addr, tx_count - 1, &pkt_end, + process_icmp(recvbuf, bytes, &addr, seq, &pkt_start, &pkt_end); if (check_for_count(opt)) { print_stats(); return EXIT_SUCCESS; } + sleep(opt.interval); if (check_for_timeout(loop_start, opt)) { print_stats(); @@ -89,11 +100,23 @@ int ping(args_t *args) { for (int i = 0; args->hosts[i] != NULL; i++) { address = args->hosts[i]; struct sockaddr_in addr; + struct addrinfo hints, *res; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_RAW; + hints.ai_protocol = IPPROTO_ICMP; + + int status = getaddrinfo(address, NULL, &hints, &res); + if (status != 0) { + fprintf(stderr, "Bad address: %s\n", address); + ret = EXIT_FAILURE; + continue; + } + + memcpy(&addr, res->ai_addr, res->ai_addrlen); + freeaddrinfo(res); - if (inet_pton(AF_INET, args->hosts[i], &addr) <= 0) { - fprintf(stderr, "Bad address: %s\n", args->hosts[i]); - return EXIT_FAILURE; - } sock = init_socket(opt); if (sock < 0) { break;