「🏗️」 wip: wtf is happening
This commit is contained in:
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "netinet/in.h"
|
#include "netinet/in.h"
|
||||||
|
#include "netinet/ip_icmp.h"
|
||||||
#include <help.h>
|
#include <help.h>
|
||||||
#include <opt_parse.h>
|
#include <opt_parse.h>
|
||||||
|
|
||||||
@ -26,6 +27,13 @@ typedef struct {
|
|||||||
uint16_t interval;
|
uint16_t interval;
|
||||||
} options_t;
|
} options_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct icmphdr hdr;
|
||||||
|
char *msg;
|
||||||
|
} icmp_pckt_t;
|
||||||
|
|
||||||
|
#define MAX_WAIT_TIME 5
|
||||||
|
|
||||||
// TODO: implement the verbose mode !!!
|
// TODO: implement the verbose mode !!!
|
||||||
#define DEFAULT_VERBOSE false
|
#define DEFAULT_VERBOSE false
|
||||||
|
|
||||||
@ -38,6 +46,7 @@ typedef struct {
|
|||||||
int send_ping(int socket, struct sockaddr_in *dest, options_t opt);
|
int send_ping(int socket, struct sockaddr_in *dest, options_t opt);
|
||||||
int init_socket(options_t opt);
|
int init_socket(options_t opt);
|
||||||
void init_packet(char *buf, int seq, uint32_t size);
|
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 send_icmp(int socket, char *buf, struct sockaddr_in *addr, uint32_t size);
|
||||||
int receive_icmp(int socket, char *buf, uint32_t size,
|
int receive_icmp(int socket, char *buf, uint32_t size,
|
||||||
struct sockaddr_in *addr);
|
struct sockaddr_in *addr);
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <netinet/ip_icmp.h>
|
#include <netinet/ip_icmp.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <unistd.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");
|
"can't setsockopt for the linger maybe try a different one");
|
||||||
return -1;
|
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;
|
return sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned short gen_checksum(unsigned short *addr, int count) {
|
unsigned short gen_checksum(unsigned short *buf, int count) {
|
||||||
unsigned long sum = 0;
|
unsigned int sum = 0;
|
||||||
|
unsigned short result;
|
||||||
while (count > 1) {
|
|
||||||
sum += *addr++;
|
|
||||||
count -= 2;
|
|
||||||
}
|
|
||||||
if (count > 0) {
|
|
||||||
sum += *(unsigned char *)addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
for (sum = 0; count > 1; count -= 2)
|
||||||
|
sum += *buf++;
|
||||||
|
if (count == 1)
|
||||||
|
sum += *(unsigned char *)buf;
|
||||||
sum = (sum >> 16) + (sum & 0xFFFF);
|
sum = (sum >> 16) + (sum & 0xFFFF);
|
||||||
sum += (sum >> 16);
|
sum += (sum >> 16);
|
||||||
|
result = ~sum;
|
||||||
return (~sum);
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_packet(char *buf, int seq, uint32_t size) {
|
void init_packet(char *buf, int seq, uint32_t size) {
|
||||||
memset(buf, 0, size);
|
bzero(buf, size);
|
||||||
struct icmp *packet = (struct icmp *)buf;
|
struct icmphdr *header = (struct icmphdr *)buf;
|
||||||
|
|
||||||
packet->icmp_type = ICMP_ECHO;
|
header->type = ICMP_ECHO;
|
||||||
packet->icmp_code = 0;
|
header->code = 0;
|
||||||
packet->icmp_id = (getpid() & 0xffff);
|
header->un.echo.id = htons(getpid() & 0xffff);
|
||||||
packet->icmp_seq = seq;
|
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;
|
header->checksum = 0;
|
||||||
packet->icmp_cksum = gen_checksum((unsigned short *)packet, size);
|
header->checksum = gen_checksum((unsigned short *)buf, size);
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include <utils.h>
|
#include <utils.h>
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <netdb.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <netinet/ip.h>
|
#include <netinet/ip.h>
|
||||||
#include <netinet/ip_icmp.h>
|
#include <netinet/ip_icmp.h>
|
||||||
@ -14,6 +15,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
int send_icmp(int socket, char *buf, struct sockaddr_in *addr, uint32_t size) {
|
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,
|
int bytes_send = sendto(socket, buf, (unsigned long)size, 0,
|
||||||
(struct sockaddr *)addr, sizeof(*addr));
|
(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,
|
int receive_icmp(int socket, char *buf, uint32_t size,
|
||||||
struct sockaddr_in *addr) {
|
struct sockaddr_in *addr) {
|
||||||
|
printf("received\n");
|
||||||
socklen_t addr_len = sizeof(*addr);
|
socklen_t addr_len = sizeof(*addr);
|
||||||
int bytes =
|
int bytes =
|
||||||
recvfrom(socket, buf, size, 0, (struct sockaddr *)addr, &addr_len);
|
recvfrom(socket, buf, size, 0, (struct sockaddr *)addr, &addr_len);
|
||||||
|
|
||||||
|
printf("%d\n", bytes);
|
||||||
|
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
void process_icmp(char *buf, int bytes, struct sockaddr_in *addr, int seq,
|
void process_icmp(char *buf, int bytes, struct sockaddr_in *addr, int seq,
|
||||||
struct timeval *tv_start, struct timeval *tv_end) {
|
struct timeval *tv_start, struct timeval *tv_end) {
|
||||||
struct ip *ip = (struct ip *)buf;
|
struct ip *ip = (struct ip *)buf;
|
||||||
int len = ip->ip_hl << 2;
|
int len = ip->ip_hl << 2;
|
||||||
struct icmp *icmp = (struct icmp *)(buf + len);
|
if (len < 20) {
|
||||||
|
fprintf(stderr, "Invalid IP header length\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (icmp->icmp_type == ICMP_ECHOREPLY &&
|
struct icmphdr *icmp = (struct icmphdr *)(buf + len);
|
||||||
icmp->icmp_id == (getpid() & 0xffff)) {
|
|
||||||
|
if (icmp->type == ICMP_ECHOREPLY &&
|
||||||
|
ntohs(icmp->un.echo.id) == (getpid() & 0xffff)) {
|
||||||
|
// ntohs(icmp->un.echo.sequence) == seq) {
|
||||||
|
|
||||||
rx_count++;
|
rx_count++;
|
||||||
|
|
||||||
double rtt = (tv_end->tv_sec - tv_start->tv_sec) / 1000.0 +
|
double rtt = (tv_end->tv_sec - tv_start->tv_sec) * 1000.0 +
|
||||||
(tv_end->tv_usec - tv_start->tv_usec) * 1000.0;
|
(tv_end->tv_usec - tv_start->tv_usec) / 1000.0;
|
||||||
|
|
||||||
append_time(rtt);
|
append_time(rtt);
|
||||||
|
|
||||||
// TODO: fix the time and put the hostname with the ip
|
// 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,
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,19 +6,21 @@
|
|||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <netdb.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <netinet/ip.h>
|
#include <netinet/ip.h>
|
||||||
#include <netinet/ip_icmp.h>
|
#include <netinet/ip_icmp.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
char *address = NULL;
|
char *address = NULL;
|
||||||
int sock = -1;
|
int sock = -1;
|
||||||
|
|
||||||
void sigint(int sig) {
|
void sigint(int sig) {
|
||||||
(void)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) {
|
int send_ping(int socket, struct sockaddr_in *dest, options_t opt) {
|
||||||
struct timeval loop_start, loop_end;
|
struct timeval loop_start, loop_end;
|
||||||
struct timeval pkt_start, pkt_end;
|
struct timeval pkt_start, pkt_end;
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr = *dest;
|
||||||
int bytes;
|
int bytes;
|
||||||
|
|
||||||
char sendbuf[opt.size];
|
char sendbuf[opt.size];
|
||||||
@ -54,24 +56,33 @@ int send_ping(int socket, struct sockaddr_in *dest, options_t opt) {
|
|||||||
|
|
||||||
gettimeofday(&loop_start, 0);
|
gettimeofday(&loop_start, 0);
|
||||||
while (727) {
|
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);
|
gettimeofday(&pkt_start, NULL);
|
||||||
bytes = send_icmp(socket, sendbuf, &addr, opt.size);
|
bytes = send_icmp(socket, sendbuf, &addr, opt.size);
|
||||||
|
tx_count++;
|
||||||
|
|
||||||
bytes = receive_icmp(socket, recvbuf, sizeof(recvbuf), &addr);
|
bytes = receive_icmp(socket, recvbuf, sizeof(recvbuf), &addr);
|
||||||
gettimeofday(&pkt_end, NULL);
|
gettimeofday(&pkt_end, NULL);
|
||||||
if (bytes < 0) {
|
|
||||||
|
if (bytes <= 0) {
|
||||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
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 {
|
} else {
|
||||||
fprintf(stderr, "recv failed\n");
|
fprintf(stderr, "recv failed: %s\n", strerror(errno));
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
process_icmp(recvbuf, bytes, &addr, tx_count - 1, &pkt_end,
|
process_icmp(recvbuf, bytes, &addr, seq, &pkt_start,
|
||||||
&pkt_end);
|
&pkt_end);
|
||||||
if (check_for_count(opt)) {
|
if (check_for_count(opt)) {
|
||||||
print_stats();
|
print_stats();
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
sleep(opt.interval);
|
sleep(opt.interval);
|
||||||
if (check_for_timeout(loop_start, opt)) {
|
if (check_for_timeout(loop_start, opt)) {
|
||||||
print_stats();
|
print_stats();
|
||||||
@ -89,11 +100,23 @@ int ping(args_t *args) {
|
|||||||
for (int i = 0; args->hosts[i] != NULL; i++) {
|
for (int i = 0; args->hosts[i] != NULL; i++) {
|
||||||
address = args->hosts[i];
|
address = args->hosts[i];
|
||||||
struct sockaddr_in addr;
|
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);
|
sock = init_socket(opt);
|
||||||
if (sock < 0) {
|
if (sock < 0) {
|
||||||
break;
|
break;
|
||||||
|
Reference in New Issue
Block a user