diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c872ae..59b9ce2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,15 +8,21 @@ fping 5.0 (unreleased) ``` $ fping -D -c2 8.8.8.8 8.8.8.7 - [1596092373.18423] 8.8.8.8 : [0], 84 bytes, 12.8 ms (12.8 avg, 0% loss) + [1596092373.18423] 8.8.8.8 : [0], 64 bytes, 12.8 ms (12.8 avg, 0% loss) [1596092374.18223] 8.8.8.7 : [0], timed out (NaN avg, 100% loss) - [1596092374.18424] 8.8.8.8 : [1], 84 bytes, 12.3 ms (12.5 avg, 0% loss) + [1596092374.18424] 8.8.8.8 : [1], 64 bytes, 12.3 ms (12.5 avg, 0% loss) [1596092375.18344] 8.8.8.7 : [1], timed out (NaN avg, 100% loss) 8.8.8.8 : xmt/rcv/%loss = 2/2/0%, min/avg/max = 12.3/12.5/12.8 8.8.8.7 : xmt/rcv/%loss = 2/0/100% ``` +- The returned size in bytes now always excludes the IP header, so if before it + reported '84 bytes' e.g. when using 'fping -l', now it reports '64 bytes'. + This is to make the reported size consistent with ping(8) from iputils and + also with fping when pinging a IPv6 host (which never included the IPv6 + header size). + ## New features - The number of sent pings is only counted when the pings are received or have @@ -27,6 +33,10 @@ fping 5.0 (unreleased) - Improved precision of measurements from 10us to 1us (#136, thanks @tycho) +## Bugfixes and other changes + +- The reported size of received packets is now always correct on Linux even for + packets > 4096 bytes. fping 4.4 (2020-07-24) ====================== diff --git a/ci/test-01-basics.pl b/ci/test-01-basics.pl index d3499f3..47f1910 100755 --- a/ci/test-01-basics.pl +++ b/ci/test-01-basics.pl @@ -27,9 +27,9 @@ SKIP: { { my $cmd = Test::Command->new(cmd => "fping -p 100 -C3 127.0.0.1"); $cmd->exit_is_num(0); - $cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) -127\.0\.0\.1 : \[1\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) -127\.0\.0\.1 : \[2\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) + $cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[2\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) }); $cmd->stderr_like(qr{127\.0\.0\.1 : \d\.\d+ \d\.\d+ \d\.\d+\n}); } diff --git a/ci/test-05-options-c-e.pl b/ci/test-05-options-c-e.pl index 536f3ad..7c3b0ac 100755 --- a/ci/test-05-options-c-e.pl +++ b/ci/test-05-options-c-e.pl @@ -11,10 +11,10 @@ use Test::Command tests => 12; { my $cmd = Test::Command->new(cmd => "fping -4 -c 2 -p 100 localhost 127.0.0.1"); $cmd->exit_is_num(0); -$cmd->stdout_like(qr{localhost : \[0\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) -127\.0\.0\.1 : \[0\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) -localhost : \[1\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) -127\.0\.0\.1 : \[1\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) }); $cmd->stderr_like(qr{localhost : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ @@ -26,10 +26,10 @@ $cmd->stderr_like(qr{localhost : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\ { my $cmd = Test::Command->new(cmd => "fping -4 -C 2 -p 100 localhost 127.0.0.1"); $cmd->exit_is_num(0); -$cmd->stdout_like(qr{localhost : \[0\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) -127\.0\.0\.1 : \[0\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) -localhost : \[1\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) -127\.0\.0\.1 : \[1\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) }); $cmd->stderr_like(qr{localhost : \d\.\d+ \d\.\d+ @@ -41,8 +41,8 @@ $cmd->stderr_like(qr{localhost : \d\.\d+ \d\.\d+ { my $cmd = Test::Command->new(cmd => "fping -D -c 2 -p 100 127.0.0.1"); $cmd->exit_is_num(0); -$cmd->stdout_like(qr{\[\d+\.\d+\] 127\.0\.0\.1 : \[0\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) -\[\d+\.\d+\] 127\.0\.0\.1 : \[1\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +$cmd->stdout_like(qr{\[\d+\.\d+\] 127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +\[\d+\.\d+\] 127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) }); $cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ diff --git a/ci/test-07-options-i-m.pl b/ci/test-07-options-i-m.pl index 6ba20de..781377f 100755 --- a/ci/test-07-options-i-m.pl +++ b/ci/test-07-options-i-m.pl @@ -19,19 +19,19 @@ $cmd->stderr_is_eq(""); # fping -l { my $cmd = Test::Command->new(cmd => '(sleep 2; pkill fping)& fping -p 900 -l 127.0.0.1'); -$cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) -127\.0\.0\.1 : \[1\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +$cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) }); } # fping -l with SIGQUIT { my $cmd = Test::Command->new(cmd => '(sleep 2; pkill -QUIT fping; sleep 2; pkill fping)& fping -p 900 -l 127.0.0.1'); -$cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) -127\.0\.0\.1 : \[1\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) -127\.0\.0\.1 : \[2\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) -127\.0\.0\.1 : \[3\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) -127\.0\.0\.1 : \[4\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +$cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[2\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[3\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[4\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) }); $cmd->stderr_like(qr{\[\d+:\d+:\d+\] 127\.0\.0\.1 : xmt/rcv/%loss = \d+/\d+/\d+%, min/avg/max = \d+\.\d+/\d+\.\d+/\d+\.\d+ diff --git a/src/fping.c b/src/fping.c index cab4af1..0b8d780 100644 --- a/src/fping.c +++ b/src/fping.c @@ -95,6 +95,15 @@ extern "C" { #define AI_UNUSABLE 0 #endif +/* MSG_TRUNC available on Linux kernel 2.2+, makes recvmsg return the full + * length of the raw packet received, even if the buffer is smaller */ +#ifndef MSG_TRUNC +#define MSG_TRUNC 0 +#define RECV_BUFSIZE 4096 +#else +#define RECV_BUFSIZE 128 +#endif + /*** externals ***/ extern char* optarg; @@ -1925,7 +1934,7 @@ int receive_packet(int64_t wait_time, return 0; /* timeout */ } - recv_len = recvmsg(s, &recv_msghdr, 0); + recv_len = recvmsg(s, &recv_msghdr, MSG_TRUNC); if (recv_len <= 0) { return 0; } @@ -1936,7 +1945,8 @@ int receive_packet(int64_t wait_time, struct timespec reply_timestamp_ts; for (cmsg = CMSG_FIRSTHDR(&recv_msghdr); cmsg != NULL; - cmsg = CMSG_NXTHDR(&recv_msghdr, cmsg)) { + cmsg = CMSG_NXTHDR(&recv_msghdr, cmsg)) + { if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_TIMESTAMPNS) { memcpy(&reply_timestamp_ts, CMSG_DATA(cmsg), sizeof(reply_timestamp_ts)); *reply_timestamp = timespec_ns(&reply_timestamp_ts); @@ -2044,6 +2054,7 @@ int decode_icmp_ipv4( #endif } + if (reply_buf_len < hlen + ICMP_MINLEN) { /* too short */ if (verbose_flag) { @@ -2051,7 +2062,7 @@ int decode_icmp_ipv4( getnameinfo((struct sockaddr*)&response_addr, sizeof(response_addr), buf, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST); printf("received packet too short for ICMP (%d bytes from %s)\n", (int)reply_buf_len, buf); } - return 0; + return -1; } icp = (struct icmp*)(reply_buf + hlen); @@ -2066,19 +2077,19 @@ int decode_icmp_ipv4( /* reply icmp packet (hlen + ICMP_MINLEN) followed by "sent packet" (ip + icmp headers) */ if (reply_buf_len < hlen + ICMP_MINLEN + sizeof(struct ip) + ICMP_MINLEN) { /* discard ICMP message if we can't tell that it was caused by us (i.e. if the "sent packet" is not included). */ - return 0; + return -1; } sent_icmp = (struct icmp*)(reply_buf + hlen + ICMP_MINLEN + sizeof(struct ip)); if (sent_icmp->icmp_type != ICMP_ECHO || sent_icmp->icmp_id != ident4) { /* not caused by us */ - return 0; + return -1; } seqmap_value = seqmap_fetch(ntohs(sent_icmp->icmp_seq), current_time_ns); if (seqmap_value == NULL) { - return 0; + return -1; } getnameinfo(response_addr, response_addr_len, addr_ascii, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST); @@ -2117,13 +2128,13 @@ int decode_icmp_ipv4( break; } - return 0; + return -1; } *id = icp->icmp_id; *seq = ntohs(icp->icmp_seq); - return 1; + return hlen; } #ifdef IPV6 @@ -2222,7 +2233,7 @@ int decode_icmp_ipv6( int wait_for_reply(int64_t wait_time) { int result; - static char buffer[4096]; + static char buffer[RECV_BUFSIZE]; struct sockaddr_storage response_addr; int n, avg; HOST_ENTRY* h; @@ -2251,21 +2262,23 @@ int wait_for_reply(int64_t wait_time) /* Process ICMP packet and retrieve id/seq */ if (response_addr.ss_family == AF_INET) { - if (!decode_icmp_ipv4( + int ip_hlen = decode_icmp_ipv4( (struct sockaddr*)&response_addr, sizeof(response_addr), buffer, sizeof(buffer), &id, - &seq)) { + &seq); + if (ip_hlen < 0) { return 1; } if (id != ident4) { return 1; /* packet received, but not the one we are looking for! */ } - if (using_sock_dgram4) { - /* IP header is not included in read SOCK_DGRAM ICMP responses */ - result += sizeof(struct ip); + if (!using_sock_dgram4) { + /* do not include IP header in returned size, to be consistent with ping(8) and also + * with fping with IPv6 hosts */ + result -= ip_hlen; } } #ifdef IPV6