diff --git a/includes/help.h b/includes/help.h index 67d0190..d7cf224 100644 --- a/includes/help.h +++ b/includes/help.h @@ -1,15 +1,27 @@ #pragma once #include -typedef struct { +struct options{ char *name; char opt; char *doc; uint8_t arg_nb; uint8_t grp; -} options_t; +}; -static options_t options[] = { +typedef enum { + USAGE, + HELP, + VERSION, + VERBOSE, + COUNT, + SIZE, + TIMEOUT, + LINGER, + INTERVAL +} options_nb_t; + +static struct options options[] = { #define GRP 0 // AKA random useless sh*t {"usage", 'u', "give a short usage message", 0, GRP}, {"help", '?', "give this help list", 0, GRP}, @@ -22,12 +34,12 @@ static options_t options[] = { {"count", 'c', "stop after sending NUMBER packets", 1, GRP}, {"size", 's', "send NUMBER data octets", 1, GRP}, {"timeout", 'w', "stop after N seconds", 1, GRP}, - {"ttl", 't', "specify N as time-to-live", 1, GRP}, + {"linger", 'W', "number of seconds to wait for response", 1, GRP}, {"interval", 'i', "wait NUMBER seconds between sending each packet", 1, GRP} #undef GRP }; -#define OPT_NB 9 +#define OPT_NB 10 #define FT_PING_V "0.1" diff --git a/includes/ping.h b/includes/ping.h index 5b3f83a..38651c0 100644 --- a/includes/ping.h +++ b/includes/ping.h @@ -1,20 +1,32 @@ #pragma once +#include "bits/types/struct_timeval.h" +#include "help.h" +#include "opt_parse.h" #include +#include -extern char *exec_name; +extern char *exec_name; +extern int tx_count; +extern int rx_count; +extern char *address; +extern double *times; typedef struct { - bool verbose; - int count; - int size; - int timeout; - int ttl; - int interval; -} ping_t; + bool verbose; + uint32_t count; + uint16_t size; + uint16_t timeout; + uint16_t linger; + uint16_t interval; +} options_t; -#define DEFAULT_COUNT -1 #define DEFAULT_VERBOSE false -#define DEFAULT_SIZE 0 -#define DEFAULT_INTERVAL 0 -#define DEFAULT_TIMEOUT 0 + +#define DEFAULT_SIZE 64 +#define DEFAULT_INTERVAL 1 +#define DEFAULT_TIMEOUT -1 +#define DEFAULT_COUNT -1 +#define DEFAULT_LINGER 10 + +int send_ping(args_t *args); diff --git a/includes/utils.h b/includes/utils.h new file mode 100644 index 0000000..f640d62 --- /dev/null +++ b/includes/utils.h @@ -0,0 +1,3 @@ +#pragma once + +void append_time(double time); diff --git a/src/main.c b/src/main.c index 24a8c08..c1e4fb3 100644 --- a/src/main.c +++ b/src/main.c @@ -6,18 +6,21 @@ #include #include -char *exec_name; +char *exec_name; +double *times = NULL; +int rx_count = 0; +int tx_count = 0; void init_args_t(args_t *args) { OPT_WHILE { args->opts[i] = false; - args->arg[i] = 0; + args->arg[i] = -1; i++; } args->hosts = NULL; } -int handle_options(args_t *args, char **av) { +int handle_options(args_t *args) { if (args->opts[1]) { print_help(); return EXIT_SUCCESS; @@ -37,8 +40,11 @@ int handle_options(args_t *args, char **av) { int main(int ac, char **av) { exec_name = *av; + args_t args; + init_args_t(&args); + if (ac > 1) { int ret = opt_parse(av, &args); if (ret == -1) { @@ -48,7 +54,7 @@ int main(int ac, char **av) { free(args.hosts); return ret; } else { - ret = handle_options(&args, av); + ret = handle_options(&args); free(args.hosts); return ret; } diff --git a/src/help.c b/src/parsing/help.c similarity index 85% rename from src/help.c rename to src/parsing/help.c index a37623a..b4fa37d 100644 --- a/src/help.c +++ b/src/parsing/help.c @@ -57,20 +57,22 @@ void print_help(void) { void print_parse_err(error_t err, char *opt) { switch (err) { case MISSING_HOST: - printf("%s: missing host operand\n", exec_name); + fprintf(stderr, "%s: missing host operand\n", exec_name); break; case INVALID_OPT: - printf("%s: invalid option -- %s\n", exec_name, opt); + fprintf(stderr, "%s: invalid option -- %s\n", exec_name, opt); break; case NEED_ARG: - printf("%s: option '%s' requires an argument\n", exec_name, opt); + fprintf(stderr, "%s: option '%s' requires an argument\n", exec_name, + opt); break; case ERR_ARG: - printf("%s: option '%s' invalid argument \n", exec_name, opt); + fprintf(stderr, "%s: option '%s' invalid argument \n", exec_name, opt); break; } - printf("Try 'ping --help' or 'ping --usage' for more information.\n"); + fprintf(stderr, + "Try 'ping --help' or 'ping --usage' for more information.\n"); } void print_usage(void) { diff --git a/src/opt_parse.c b/src/parsing/opt_parse.c similarity index 100% rename from src/opt_parse.c rename to src/parsing/opt_parse.c diff --git a/src/ping/init_ping.c b/src/ping/init_ping.c new file mode 100644 index 0000000..6e19d4f --- /dev/null +++ b/src/ping/init_ping.c @@ -0,0 +1,67 @@ +#include "help.h" +#include "opt_parse.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +struct icmp test; + +int init_socket(args_t *args) { + int sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); + if (sock < 0) { + fprintf(stderr, + "%s: can't create socket maybe try in root next time :D", + exec_name); + return -1; + } + + struct linger linger; + linger.l_linger = + args->arg[LINGER] == -1 ? DEFAULT_TIMEOUT : args->arg[LINGER]; + linger.l_onoff = true; + if (setsockopt(sock, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)) < 0) { + fprintf(stderr, + "can't setsockopt for the linger maybe try a different one"); + 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; + } + + sum = (sum >> 16) + (sum & 0xFFFF); + sum += (sum >> 16); + + return (~sum); +} + +void init_packet(char *buf, int seq, uint32_t size) { + memset(buf, 0, size); + struct icmp *packet = (struct icmp *)buf; + + packet->icmp_type = ICMP_ECHO; + packet->icmp_code = 0; + packet->icmp_id = getpid() & 0xFFFF; + packet->icmp_seq = seq; + + memset(buf + sizeof(struct icmphdr), 0x42, size - sizeof(struct icmphdr)); + + packet->icmp_cksum = 0; + packet->icmp_cksum = gen_checksum((unsigned short *)packet, size); +} diff --git a/src/ping/send_icmp.c b/src/ping/send_icmp.c new file mode 100644 index 0000000..ae7b59f --- /dev/null +++ b/src/ping/send_icmp.c @@ -0,0 +1,54 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int send_icmp(int socket, char *buf, struct sockaddr_in *addr, uint32_t size) { + int bytes_send = sendto(socket, buf, (unsigned long)size, 0, + (struct sockaddr *)addr, sizeof(*addr)); + + if (bytes_send < 0) { + fprintf(stderr, "sendto failed can't send packet"); + return -1; + } + return bytes_send; +} + +int receive_icmp(int socket, char *buf, uint32_t size, + struct sockaddr_in *addr) { + socklen_t addr_len = sizeof(*addr); + int bytes = + recvfrom(socket, buf, size, 0, (struct sockaddr *)addr, &addr_len); + + 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); + + if (icmp->icmp_type == ICMP_ECHOREPLY && + icmp->icmp_type == (getpid() & 0xFFFF)) { + rx_count++; + + 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); + + printf("%d bytes from %s: icmp_seq=%d ttl=%d time=%.3f", bytes - len, + inet_ntoa(addr->sin_addr), icmp->icmp_seq, ip->ip_ttl, rtt); + } +} diff --git a/src/ping/send_ping.c b/src/ping/send_ping.c new file mode 100644 index 0000000..c0ae910 --- /dev/null +++ b/src/ping/send_ping.c @@ -0,0 +1,47 @@ +#include "help.h" +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 = %d/%d/%d/%d"); +} + +options_t init_opt(args_t *args) { + options_t opt; + opt.verbose = args->opts[VERBOSE] != false ? true : DEFAULT_VERBOSE; + opt.count = args->arg[COUNT] != -1 ? args->arg[COUNT] : DEFAULT_COUNT; + opt.size = args->arg[SIZE] != -1 ? args->arg[SIZE] : DEFAULT_SIZE; + opt.timeout = + args->arg[TIMEOUT] != -1 ? args->arg[TIMEOUT] : DEFAULT_TIMEOUT; + opt.interval = + args->arg[INTERVAL] != -1 ? args->arg[INTERVAL] : DEFAULT_INTERVAL; + opt.linger = args->arg[LINGER] != -1 ? args->arg[LINGER] : DEFAULT_LINGER; + + return opt; +} + +int send_ping(args_t *args) { + options_t opt = init_opt(args); + struct timeval loop_start; + struct timeval loop_end; + + gettimeofday(&loop_start, 0); + while () { + } + return EXIT_SUCCESS; +} diff --git a/src/send_ping.c b/src/send_ping.c deleted file mode 100644 index f5a68c2..0000000 --- a/src/send_ping.c +++ /dev/null @@ -1,5 +0,0 @@ -#include - -int send_ping(args_t *args) { - -} diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000..829e10f --- /dev/null +++ b/src/utils.c @@ -0,0 +1,14 @@ +#include +#include +#include + +void append_time(double time) { + if (times == NULL) { + times = malloc(sizeof(double)); + times[0] = time; + } else { + times = reallocarray(times, rx_count, sizeof(double)); + times[rx_count - 1] = time; + } +} +