diff --git a/includes/ping.h b/includes/ping.h index 38651c0..9125063 100644 --- a/includes/ping.h +++ b/includes/ping.h @@ -1,10 +1,14 @@ #pragma once -#include "bits/types/struct_timeval.h" -#include "help.h" -#include "opt_parse.h" +#include "netinet/in.h" +#include +#include + +#include #include #include +#include +#include extern char *exec_name; extern int tx_count; @@ -21,6 +25,7 @@ typedef struct { uint16_t interval; } options_t; +// TODO: implement the verbose mode !!! #define DEFAULT_VERBOSE false #define DEFAULT_SIZE 64 @@ -29,4 +34,14 @@ typedef struct { #define DEFAULT_COUNT -1 #define DEFAULT_LINGER 10 -int send_ping(args_t *args); +int send_ping(int socket, struct sockaddr_in *dest, args_t *args); +int init_socket(args_t *args); +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); +void process_icmp(char *buf, int bytes, struct sockaddr_in *addr, int seq, + struct timeval *tv_start, struct timeval *tv_end); + +// Internal +unsigned short get_checksum(unsigned short *addr, int count); diff --git a/includes/utils.h b/includes/utils.h index 3e0ff6a..0361136 100644 --- a/includes/utils.h +++ b/includes/utils.h @@ -1,15 +1,30 @@ #pragma once -void append_time(double time); +#include +#include + +void append_time(double time); /** * @brief Can be used to get the avarage rtt */ double get_avg_rtt(void); /** - * @brief Can be used to get the + * @brief Can be used to get the min rtt */ double get_min_rtt(void); +/** + * @brief Can be used to get the max rtt + */ double get_max_rtt(void); +/** + * @brief Can be used to get the stddev rtt + */ double get_stddev_rtt(void); +/** + * @brief Can be used to check if the timeout in passed + */ +bool check_for_timeout(struct timeval start, options_t opt); + +void print_stats(void); diff --git a/src/ping/init_ping.c b/src/ping/init_ping.c index 6e19d4f..d40c378 100644 --- a/src/ping/init_ping.c +++ b/src/ping/init_ping.c @@ -13,7 +13,7 @@ struct icmp test; -int init_socket(args_t *args) { +int init_socket(options_t opt) { int sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); if (sock < 0) { fprintf(stderr, @@ -23,8 +23,7 @@ int init_socket(args_t *args) { } struct linger linger; - linger.l_linger = - args->arg[LINGER] == -1 ? DEFAULT_TIMEOUT : args->arg[LINGER]; + linger.l_linger = opt.linger; linger.l_onoff = true; if (setsockopt(sock, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)) < 0) { fprintf(stderr, diff --git a/src/ping/send_ping.c b/src/ping/send_ping.c index 31cfff0..eb65294 100644 --- a/src/ping/send_ping.c +++ b/src/ping/send_ping.c @@ -1,9 +1,11 @@ #include "help.h" +#include #include #include #include #include +#include #include #include #include @@ -16,10 +18,9 @@ #include void sigint(int sig) { - printf("--- %s ping statistics ---", address); - printf("%d packets transmitted, %d packets received, %f%% packet loss", - tx_count, rx_count, (tx_count - rx_count / 2.0) * 100); - printf("round-trip min/avg/max/stddev = %f/%f/%f/%f", get_min_rtt(), get_avg_rtt(), get_max_rtt(), get_stddev_rtt()); + (void)sig; + + exit(EXIT_SUCCESS); } options_t init_opt(args_t *args) { @@ -36,13 +37,57 @@ options_t init_opt(args_t *args) { return opt; } -int send_ping(args_t *args) { - options_t opt = init_opt(args); - struct timeval loop_start; - struct timeval loop_end; +int send_ping(int socket, struct sockaddr_in *dest, args_t *args) { + options_t opt = init_opt(args); + struct timeval loop_start, loop_end; + struct timeval pkt_start, pkt_end; + struct sockaddr_in addr; + int bytes; + + char sendbuf[opt.size]; + char recvbuf[opt.size + sizeof(struct ip)]; gettimeofday(&loop_start, 0); - while () { + while (727) { + init_packet(sendbuf, tx_count++, opt.size); + gettimeofday(&pkt_start, NULL); + bytes = send_icmp(socket, sendbuf, &addr, opt.size); + sleep(1); + if (check_for_timeout(loop_start, opt)) { + print_stats(); + return EXIT_SUCCESS; + } + bytes = receive_icmp(socket, recvbuf, sizeof(recvbuf), &addr); + gettimeofday(&pkt_end, NULL); + if (bytes < 0) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { + printf("Request timeout for icmp_seq=%d\n", tx_count - 1); + } else { + fprintf(stderr, "recv failed"); + } + } else + process_icmp(recvbuf, bytes, &addr, tx_count - 1, &pkt_end, + &pkt_end); } return EXIT_SUCCESS; } + +int ping(args_t *args) { + int ret; + for (int i = 0; args->hosts[i] != NULL; i++) { + struct sockaddr_in addr; + if (inet_pton(AF_INET, args->hosts[i], &addr) <= 0) { + fprintf(stderr, "Bar address: %s\n", args->hosts[i]); + return EXIT_FAILURE; + } + int socket = init_socket(args); + if (socket < 0) { + } + + printf("PING %s (%s): %d data bytes\n", args->hosts[i], args->hosts[i], + args->opts[SIZE]); + + ret = send_ping(socket, &addr, args); + } + return ret; +} diff --git a/src/utils.c b/src/utils.c index ab1013b..bb1c2d7 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,4 +1,7 @@ #include + +#include +#include #include #include @@ -43,3 +46,22 @@ double get_stddev_rtt(void) { double stddev = 0; return stddev; } + +bool check_for_timeout(struct timeval start, options_t opt) { + struct timeval end; + gettimeofday(&end, NULL); + + double span = + (end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec) / 1000000.0; + if (span > opt.timeout) + return true; + return false; +} + +void print_stats(void) { + printf("--- %s ping statistics ---", address); + printf("%d packets transmitted, %d packets received, %f%% packet loss", + tx_count, rx_count, (tx_count - rx_count / 2.0) * 100); + printf("round-trip min/avg/max/stddev = %f/%f/%f/%f", get_min_rtt(), + get_avg_rtt(), get_max_rtt(), get_stddev_rtt()); +}