diff --git a/src/main.c b/src/main.c index 3b529d9..6252c6e 100644 --- a/src/main.c +++ b/src/main.c @@ -31,7 +31,7 @@ bool loop = true; -void signal_handler(int code) +static void signal_handler(int code) { (void) code; loop = false; @@ -76,7 +76,6 @@ static int get_setting(char * const *av, struct setting *setting) {NULL, "v", OPTION, false}, {NULL, "f", OPTION, false}, {NULL, "n", OPTION, false}, - {NULL, "W",ARGUMENT, "0"}, {"ttl", NULL, ARGUMENT, "116"}, {NULL, "s", ARGUMENT, "56"}, {NULL, NULL, 0, NULL}, @@ -90,15 +89,57 @@ static int get_setting(char * const *av, struct setting *setting) setting->verbose = parameters[1].value; setting->flood = parameters[2].value; setting->numeric_only = parameters[3].value; - if (parsing_number(parameters[4].value, 0, 2147483647, &setting->timeout)) - return 1; - if (parsing_number(parameters[5].value, 0, 255, &setting->ttl)) + size_t ttl; + if (parsing_number(parameters[4].value, 0, 255, &ttl)) return 2; - if (parsing_number(parameters[6].value, 0, 2147483647, &setting->payload_size)) + if (parsing_number(parameters[5].value, 0, 2147483647, &setting->payload_size)) return 3; + setting->ttl = ttl; return 0; } +static int create_socket(struct setting const *setting) +{ + int ret; + + int sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); + + if (sockfd == -1) + { + print_err("open socket failed, maybe try in root (:"); + return -1; + } + + ret = setsockopt(sockfd, IPPROTO_IP, IP_TTL, &setting->ttl, sizeof(uint8_t)); + if (ret != 0) + { + print_err("Failed to setsockopt(): ttl"); + return -1; + } + + struct timeval tv = {1, 0}; + ret = setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + if (ret != 0) + { + print_err("Failed to setsockopt(): recv timeout"); + return -1; + } + + return sockfd; +} + +static int set_destination(struct hostenv *host) +{ + if (dns_lookup(host)) + return 1; + + host->ip.sin_family = AF_INET; + host->ip.sin_port = htons(0); + inet_pton(AF_INET, host->ipstr, &host->ip.sin_addr); + + return 0; +} + int main(int ac, char **av) { (void) ac; @@ -112,22 +153,12 @@ int main(int ac, char **av) signal(SIGINT, signal_handler); - if (dns_lookup(&settings.dest)) - return 5; - - settings.dest.ip.sin_family = AF_INET; - settings.dest.ip.sin_port = htons(0); - inet_pton(AF_INET, settings.dest.ipstr, &settings.dest.ip.sin_addr); - - dns_reverse_lookup(&settings.dest); - - int sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); - - if (sockfd == -1) - { - print_err("open socket failed, maybe try in root (:"); + if (set_destination(&settings.dest)) + return 1; + + int sockfd = create_socket(&settings); + if (sockfd == -1) return 1; - } char *packet = packet_create(settings.payload_size); if (packet == NULL) @@ -166,9 +197,12 @@ int main(int ac, char **av) stats.packets_sent++; + int ret = 0; do { - if (recvfrom(sockfd, buffer, packet_size, 0, (struct sockaddr *) &sender, &len) < 0) + buffer[0] = 0; + ret = recvfrom(sockfd, buffer, packet_size, 0, (struct sockaddr *) &sender, &len) < 0; + if (ret == -1) { print_err("error: receive packet failed."); close(sockfd); @@ -178,13 +212,13 @@ int main(int ac, char **av) } gettimeofday(&stop, NULL); } - while (len == packet_size && packet_check(buffer, packet_size) == 0 && packet_compare(packet, buffer, packet_size) == 0); + while (!(ret == 1 && buffer[0] == '\0') || (len == packet_size && packet_check(buffer, packet_size) == 0 && packet_compare(packet, buffer, packet_size) == 0)); - stats.packets_received++; - - struct icmphdr *hdr = (struct icmphdr *) packet; - - print_ping(&settings, hdr, &start, &stop); + if (*buffer != 0) + { + stats.packets_received++; + print_recv(&settings, (struct icmphdr *)buffer, &start, &stop); + } sleep(1); diff --git a/src/print.c b/src/print.c index f0b71df..db4b288 100644 --- a/src/print.c +++ b/src/print.c @@ -52,7 +52,7 @@ void print_statistics(struct statistics const *stats, struct setting const *sett void print_recv(const struct setting *settings, const struct icmphdr *header, const struct timeval *start, const struct timeval *stop) { - printf("%zu bytes from %s: icmp_seq=%d ttl=%zu time=%.3f ms\n", + printf("%zu bytes from %s: icmp_seq=%d ttl=%d time=%.3f ms\n", settings->payload_size + sizeof(struct icmphdr), settings->dest.ipstr, htons(header->un.echo.sequence), diff --git a/src/setting.h b/src/setting.h index 7b0f1a1..950e225 100644 --- a/src/setting.h +++ b/src/setting.h @@ -2,6 +2,7 @@ #include "host.h" +#include #include #include @@ -12,7 +13,7 @@ struct setting bool flood; bool numeric_only; size_t timeout; - size_t ttl; + uint8_t ttl; size_t payload_size; struct hostenv dest; };