🏗️」 wip: wtf is happening

This commit is contained in:
2025-08-17 21:14:31 +02:00
parent 4c13d78559
commit de4d18ccb7
4 changed files with 94 additions and 40 deletions

View File

@ -1,6 +1,7 @@
#pragma once
#include "netinet/in.h"
#include "netinet/ip_icmp.h"
#include <help.h>
#include <opt_parse.h>
@ -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);

View File

@ -7,6 +7,7 @@
#include <netinet/ip_icmp.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
@ -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);
}

View File

@ -3,6 +3,7 @@
#include <utils.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
@ -14,6 +15,7 @@
#include <unistd.h>
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);
}
}

View File

@ -6,19 +6,21 @@
#include <arpa/inet.h>
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
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;