```
$ 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
- 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)
======================
{
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});
}
{
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+
{
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+
{
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+
# 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+
#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;
return 0; /* timeout */
}
- recv_len = recvmsg(s, &recv_msghdr, 0);
+ recv_len = recvmsg(s, &recv_msghdr, MSG_TRUNC);
if (recv_len <= 0) {
return 0;
}
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);
#endif
}
+
if (reply_buf_len < hlen + ICMP_MINLEN) {
/* too short */
if (verbose_flag) {
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);
/* 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);
break;
}
- return 0;
+ return -1;
}
*id = icp->icmp_id;
*seq = ntohs(icp->icmp_seq);
- return 1;
+ return hlen;
}
#ifdef 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;
/* 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