bin/151023: [patch] ping6(8) exits before all ICMPv6 echo replies are received

Tianjie Mao tjmao at tjmao.net
Tue Sep 28 09:00:24 UTC 2010


>Number:         151023
>Category:       bin
>Synopsis:       [patch] ping6(8) exits before all ICMPv6 echo replies are received
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Sep 28 09:00:23 UTC 2010
>Closed-Date:
>Last-Modified:
>Originator:     Tianjie Mao
>Release:        7.2-RELEASE
>Organization:
>Environment:
FreeBSD venus 7.2-RELEASE FreeBSD 7.2-RELEASE #5: Sat Jun 26 11:02:12 CST 2010     root at venus:/usr/src/sys/amd64/compile/IPSEC  amd64
>Description:
An interval timer (itimer) allows a process to do repeated work at a given frequency.  If an -i or -f option is specified, the FreeBSD ping6(8) will use this value to call setitimer(2) to register the timer, then the signal handler is called at every expiry of the timer, sending an ICMPv6 packet each time.

However, the KAME version of ping6 utility immediately exits the loop after knowing that it is the last packet to send, which causes unread replies from a remote host to be ignored.

This is a bug and can be fixed by setting itimer to zero as soon as the last packet is sent, then continue the loop to see if any replies are received.
>How-To-Repeat:
Suppose there is an average RTT seconds round-trip delay between v6host1 and v6host2.
INT is the interval (seconds) between packets.
CNT is the total number of packets to send.

Run as root on v6host1:
v6host1# ping6 -i $INT -c $CNT -q v6host2

Then the reply might look like this (0.01 interval, 245.816 ms delay, 100 packets):

--- ipv6.sjtu.edu.cn ping6 statistics ---
100 packets transmitted, 76 packets received, 24.0% packet loss
round-trip min/avg/max/std-dev = 244.446/245.816/247.826/0.705 ms

After re-adjusting $INT and switching to another destination host with a different RTT, one would simply conclude with the following formula:

estimated-packets-lost = RTT / INT
>Fix:
Apply the attached patch to src/sbin/ping6/ping6.c and the problem will be fixed.

Tested against CVS revision 1.39 but this is supposed to work on older versions as well.

Patch attached with submission follows:

diff -uNr ping6.c.orig ping6.c
--- ping6.c.orig        2010-06-16 23:49:17.000000000 +0800
+++ ping6.c     2010-09-28 15:41:22.000000000 +0800
@@ -1091,8 +1091,14 @@
                /* signal handling */
                if (seenalrm) {
                        /* last packet sent, timeout reached? */
-                       if (npackets && ntransmitted >= npackets)
-                               break;
+                       if (npackets && ntransmitted >= npackets) {
+                               struct timeval zerotime = {0, 0};
+                               itimer.it_value = zerotime;
+                               itimer.it_interval = zerotime;
+                               (void)setitimer(ITIMER_REAL, &itimer, NULL);
+                               seenalrm = 0;   /* clear flag */
+                               continue;
+                       }
                        retransmit();
                        seenalrm = 0;
                        continue;


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list