I tried to fix this before in 2018. Claudio had pointed out that a flood ping with a count given would wait forever on a lossy link so we made sure a timeout was set.
However we would also exit after the first answer received if we had already send out all flood pings. Flooding something in farawayistan we are able to send out the all 10 pings before the first answer comes back: $ time doas ping -f -c10 target.host PING target.host (xxx.xxx.xxx.xxx): 56 data bytes .......... --- target.host ping statistics --- 10 packets transmitted, 1 packets received, 90.0% packet loss round-trip min/avg/max/std-dev = 241.168/241.168/241.168/0.000 ms 0m00.26s real 0m00.00s user 0m00.00s system The 90% loss is just wrong, all those packets come in immediately after the first one, we just don't read them. $ time doas obj/ping -f -c10 target.host PING target.host (xxx.xxx.xxx.xxx): 56 data bytes .......... --- target.host ping statistics --- 10 packets transmitted, 10 packets received, 0.0% packet loss round-trip min/avg/max/std-dev = 238.791/241.277/250.184/3.469 ms 0m00.42s real 0m00.00s user 0m00.00s system OK? diff --git ping.c ping.c index 2af4ded0b6b..0b69d754ab7 100644 --- ping.c +++ ping.c @@ -251,7 +251,7 @@ main(int argc, char *argv[]) struct passwd *pw; socklen_t maxsizelen; int64_t preload; - int ch, i, optval = 1, packlen, maxsize, error, s; + int ch, i, optval = 1, packlen, maxsize, error, s, flooddone = 0; int df = 0, tos = 0, bufspace = IP_MAXPACKET, hoplimit = -1, mflag = 0; u_char *datap, *packet; u_char ttl = MAXTTL; @@ -870,6 +870,8 @@ main(int argc, char *argv[]) if (seenint) break; if (seenalrm) { + if (flooddone) + break; retransmit(s); seenalrm = 0; if (ntransmitted - nreceived - 1 > nmissedmax) { @@ -886,7 +888,7 @@ main(int argc, char *argv[]) continue; } - if (options & F_FLOOD) { + if ((options & F_FLOOD && !flooddone)) { if (pinger(s) != 0) { (void)signal(SIGALRM, onsignal); timeout = INFTIM; @@ -901,7 +903,7 @@ main(int argc, char *argv[]) (void)setitimer(ITIMER_REAL, &itimer, NULL); /* When the alarm goes off we are done. */ - seenint = 1; + flooddone = 1; } else timeout = 10; } else -- I'm not entirely sure you are real.