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.

Reply via email to