ping: don't measure times if ping payload is less than 8 bytes; commonalize some ping code.
No binary (build failed)
—
(log yok)
| @@ -10,8 +10,6 @@ | |
| #include <sys/types.h> | |
| #include <netdb.h> | |
| #include <sys/socket.h> | |
| - | #include <errno.h> |
| - | #include <unistd.h> |
| #include "libbb.h" | |
| #ifdef CONFIG_FEATURE_IPV6 | |
| @@ -23,12 +21,12 @@ int create_icmp6_socket(void) | |
| proto = getprotobyname("ipv6-icmp"); | |
| /* if getprotobyname failed, just silently force | |
| * proto->p_proto to have the correct value for "ipv6-icmp" */ | |
| - | if ((sock = socket(AF_INET6, SOCK_RAW, |
| - | (proto ? proto->p_proto : IPPROTO_ICMPV6))) < 0) { |
| + | sock = socket(AF_INET6, SOCK_RAW, |
| + | (proto ? proto->p_proto : IPPROTO_ICMPV6)); |
| + | if (sock < 0) { |
| if (errno == EPERM) | |
| bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); | |
| - | else |
| - | bb_perror_msg_and_die(bb_msg_can_not_create_raw_socket); |
| + | bb_perror_msg_and_die(bb_msg_can_not_create_raw_socket); |
| } | |
| /* drop root privs if running setuid */ | |
| @@ -10,8 +10,6 @@ | |
| #include <sys/types.h> | |
| #include <netdb.h> | |
| #include <sys/socket.h> | |
| - | #include <errno.h> |
| - | #include <unistd.h> |
| #include "libbb.h" | |
| int create_icmp_socket(void) | |
| @@ -22,12 +20,12 @@ int create_icmp_socket(void) | |
| proto = getprotobyname("icmp"); | |
| /* if getprotobyname failed, just silently force | |
| * proto->p_proto to have the correct value for "icmp" */ | |
| - | if ((sock = socket(AF_INET, SOCK_RAW, |
| - | (proto ? proto->p_proto : 1))) < 0) { /* 1 == ICMP */ |
| + | sock = socket(AF_INET, SOCK_RAW, |
| + | (proto ? proto->p_proto : 1)); /* 1 == ICMP */ |
| + | if (sock < 0) { |
| if (errno == EPERM) | |
| bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); | |
| - | else |
| - | bb_perror_msg_and_die(bb_msg_can_not_create_raw_socket); |
| + | bb_perror_msg_and_die(bb_msg_can_not_create_raw_socket); |
| } | |
| /* drop root privs if running setuid */ | |
| @@ -262,7 +262,8 @@ static int if_index; | |
| static unsigned long ntransmitted, nreceived, nrepeats, pingcount; | |
| static int myid; | |
| - | static unsigned long tmin = ULONG_MAX, tmax, tsum; |
| + | static unsigned tmin = UINT_MAX, tmax; |
| + | static unsigned long tsum; |
| static char rcvd_tbl[MAX_DUP_CHK / 8]; | |
| static const char *hostname; | |
| @@ -278,8 +279,6 @@ static const char *dotted; | |
| static void pingstats(int junk ATTRIBUTE_UNUSED) | |
| { | |
| - | int status; |
| - | |
| signal(SIGINT, SIG_IGN); | |
| printf("\n--- %s ping statistics ---\n", hostname); | |
| @@ -290,16 +289,12 @@ static void pingstats(int junk ATTRIBUTE_UNUSED) | |
| if (ntransmitted) | |
| ntransmitted = (ntransmitted - nreceived) * 100 / ntransmitted; | |
| printf("%lu%% packet loss\n", ntransmitted); | |
| - | if (nreceived) |
| - | printf("round-trip min/avg/max = %lu.%lu/%lu.%lu/%lu.%lu ms\n", |
| + | if (tmin != UINT_MAX) |
| + | printf("round-trip min/avg/max = %u.%u/%lu.%lu/%u.%u ms\n", |
| tmin / 10, tmin % 10, | |
| (tsum / (nreceived + nrepeats)) / 10, | |
| (tsum / (nreceived + nrepeats)) % 10, tmax / 10, tmax % 10); | |
| - | if (nreceived != 0) |
| - | status = EXIT_SUCCESS; |
| - | else |
| - | status = EXIT_FAILURE; |
| - | exit(status); |
| + | exit(nreceived == 0); /* (nreceived == 0) is true (1) -- 'failure' */ |
| } | |
| static void sendping_tail(void (*sp)(int), const void *pkt, int size_pkt) | |
| @@ -406,15 +401,57 @@ static const char *icmp6_type_name(int id) | |
| } | |
| #endif | |
| + | static void unpack_tail(int sz, struct timeval *tp, |
| + | const char *from_str, |
| + | uint16_t recv_seq, int ttl) |
| + | { |
| + | const char *dupmsg = " (DUP!)"; |
| + | unsigned triptime = triptime; /* for gcc */ |
| + | |
| + | ++nreceived; |
| + | |
| + | if (tp) { |
| + | struct timeval tv; |
| + | |
| + | gettimeofday(&tv, NULL); |
| + | tv.tv_usec -= tp->tv_usec; |
| + | if (tv.tv_usec < 0) { |
| + | --tv.tv_sec; |
| + | tv.tv_usec += 1000000; |
| + | } |
| + | tv.tv_sec -= tp->tv_sec; |
| + | |
| + | triptime = tv.tv_sec * 10000 + (tv.tv_usec / 100); |
| + | tsum += triptime; |
| + | if (triptime < tmin) |
| + | tmin = triptime; |
| + | if (triptime > tmax) |
| + | tmax = triptime; |
| + | } |
| + | |
| + | if (TST(recv_seq % MAX_DUP_CHK)) { |
| + | ++nrepeats; |
| + | --nreceived; |
| + | } else { |
| + | SET(recv_seq % MAX_DUP_CHK); |
| + | dupmsg += 7; |
| + | } |
| + | |
| + | if (option_mask32 & OPT_QUIET) |
| + | return; |
| + | |
| + | printf("%d bytes from %s: seq=%u ttl=%d", sz, |
| + | from_str, recv_seq, ttl); |
| + | if (tp) |
| + | printf(" time=%u.%u ms", triptime / 10, triptime % 10); |
| + | puts(dupmsg); |
| + | fflush(stdout); |
| + | } |
| static void unpack4(char *buf, int sz, struct sockaddr_in *from) | |
| { | |
| struct icmp *icmppkt; | |
| struct iphdr *iphdr; | |
| - | struct timeval tv, *tp; |
| - | int hlen, dupflag; |
| - | unsigned long triptime; |
| - | |
| - | gettimeofday(&tv, NULL); |
| + | int hlen; |
| /* discard if too short */ | |
| if (sz < (datalen + ICMP_MINLEN)) | |
| @@ -430,61 +467,25 @@ static void unpack4(char *buf, int sz, struct sockaddr_in *from) | |
| if (icmppkt->icmp_type == ICMP_ECHOREPLY) { | |
| uint16_t recv_seq = ntohs(icmppkt->icmp_seq); | |
| - | ++nreceived; |
| - | tp = (struct timeval *) icmppkt->icmp_data; |
| - | |
| - | if ((tv.tv_usec -= tp->tv_usec) < 0) { |
| - | --tv.tv_sec; |
| - | tv.tv_usec += 1000000; |
| - | } |
| - | tv.tv_sec -= tp->tv_sec; |
| - | |
| - | triptime = tv.tv_sec * 10000 + (tv.tv_usec / 100); |
| - | tsum += triptime; |
| - | if (triptime < tmin) |
| - | tmin = triptime; |
| - | if (triptime > tmax) |
| - | tmax = triptime; |
| - | |
| - | if (TST(recv_seq % MAX_DUP_CHK)) { |
| - | ++nrepeats; |
| - | --nreceived; |
| - | dupflag = 1; |
| - | } else { |
| - | SET(recv_seq % MAX_DUP_CHK); |
| - | dupflag = 0; |
| - | } |
| - | |
| - | if (option_mask32 & OPT_QUIET) |
| - | return; |
| - | |
| - | printf("%d bytes from %s: icmp_seq=%u", sz, |
| - | inet_ntoa(*(struct in_addr *) &from->sin_addr.s_addr), |
| - | recv_seq); |
| - | printf(" ttl=%d", iphdr->ttl); |
| - | printf(" time=%lu.%lu ms", triptime / 10, triptime % 10); |
| - | if (dupflag) |
| - | printf(" (DUP!)"); |
| - | puts(""); |
| - | } else { |
| - | if (icmppkt->icmp_type != ICMP_ECHO) |
| - | bb_error_msg("warning: got ICMP %d (%s)", |
| - | icmppkt->icmp_type, |
| - | icmp_type_name(icmppkt->icmp_type)); |
| + | struct timeval *tp = NULL; |
| + | |
| + | if (sz >= ICMP_MINLEN + sizeof(struct timeval)) |
| + | tp = (struct timeval *) icmppkt->icmp_data; |
| + | unpack_tail(sz, tp, |
| + | inet_ntoa(*(struct in_addr *) &from->sin_addr.s_addr), |
| + | recv_seq, iphdr->ttl); |
| + | } else if (icmppkt->icmp_type != ICMP_ECHO) { |
| + | bb_error_msg("warning: got ICMP %d (%s)", |
| + | icmppkt->icmp_type, |
| + | icmp_type_name(icmppkt->icmp_type)); |
| } | |
| - | fflush(stdout); |
| } | |
| #if ENABLE_PING6 | |
| static void unpack6(char *packet, int sz, struct sockaddr_in6 *from, int hoplimit) | |
| { | |
| struct icmp6_hdr *icmppkt; | |
| - | struct timeval tv, *tp; |
| - | int dupflag; |
| - | unsigned long triptime; |
| char buf[INET6_ADDRSTRLEN]; | |
| - | gettimeofday(&tv, NULL); |
| - | |
| /* discard if too short */ | |
| if (sz < (datalen + sizeof(struct icmp6_hdr))) | |
| return; | |
| @@ -495,50 +496,19 @@ static void unpack6(char *packet, int sz, struct sockaddr_in6 *from, int hoplimi | |
| if (icmppkt->icmp6_type == ICMP6_ECHO_REPLY) { | |
| uint16_t recv_seq = ntohs(icmppkt->icmp6_seq); | |
| - | ++nreceived; |
| - | tp = (struct timeval *) &icmppkt->icmp6_data8[4]; |
| - | |
| - | if ((tv.tv_usec -= tp->tv_usec) < 0) { |
| - | --tv.tv_sec; |
| - | tv.tv_usec += 1000000; |
| - | } |
| - | tv.tv_sec -= tp->tv_sec; |
| - | |
| - | triptime = tv.tv_sec * 10000 + (tv.tv_usec / 100); |
| - | tsum += triptime; |
| - | if (triptime < tmin) |
| - | tmin = triptime; |
| - | if (triptime > tmax) |
| - | tmax = triptime; |
| - | |
| - | if (TST(recv_seq % MAX_DUP_CHK)) { |
| - | ++nrepeats; |
| - | --nreceived; |
| - | dupflag = 1; |
| - | } else { |
| - | SET(recv_seq % MAX_DUP_CHK); |
| - | dupflag = 0; |
| - | } |
| - | |
| - | if (option_mask32 & OPT_QUIET) |
| - | return; |
| - | |
| - | printf("%d bytes from %s: icmp6_seq=%u", sz, |
| - | inet_ntop(AF_INET6, &pingaddr.sin6.sin6_addr, |
| - | buf, sizeof(buf)), |
| - | recv_seq); |
| - | printf(" ttl=%d time=%lu.%lu ms", hoplimit, |
| - | triptime / 10, triptime % 10); |
| - | if (dupflag) |
| - | printf(" (DUP!)"); |
| - | puts(""); |
| - | } else { |
| - | if (icmppkt->icmp6_type != ICMP6_ECHO_REQUEST) |
| - | bb_error_msg("warning: got ICMP %d (%s)", |
| - | icmppkt->icmp6_type, |
| - | icmp6_type_name(icmppkt->icmp6_type)); |
| + | struct timeval *tp = NULL; |
| + | |
| + | if (sz >= sizeof(struct icmp6_hdr) + sizeof(struct timeval)) |
| + | tp = (struct timeval *) &icmppkt->icmp6_data8[4]; |
| + | unpack_tail(sz, tp, |
| + | inet_ntop(AF_INET6, &pingaddr.sin6.sin6_addr, |
| + | buf, sizeof(buf)), |
| + | recv_seq, hoplimit); |
| + | } else if (icmppkt->icmp6_type != ICMP6_ECHO_REQUEST) { |
| + | bb_error_msg("warning: got ICMP %d (%s)", |
| + | icmppkt->icmp6_type, |
| + | icmp6_type_name(icmppkt->icmp6_type)); |
| } | |
| - | fflush(stdout); |
| } | |
| #endif | |