「🏗️」 wip: wtf is happening
This commit is contained in:
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
Reference in New Issue
Block a user