Subject: bin/21459: ping holding onto mbufs in receive buffer.
To: None <gnats-bugs@gnats.netbsd.org>
From: None <seanb@qnx.com>
List: netbsd-bugs
Date: 05/05/2003 17:28:04
>Number:         21459
>Category:       bin
>Synopsis:       ping holding onto mbufs in receive buffer.
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon May 05 17:29:00 UTC 2003
>Closed-Date:
>Last-Modified:
>Originator:     Sean Boudreau
>Release:        1-6
>Organization:
QNX
>Environment:
NetBSD  1.6 NetBSD 1.6 (GENERIC) #0: Sun Sep  8 19:43:40 UTC 2002     autobuild@tgm.daemon.org:/autobuild/i386/OBJ/autobuild/src/sys/arch/i386/compile/GENERIC i386
>Description:
Since the 'sloop' socket is never read on, mbufs
Q in its recv buffer until full and remain until
the ping is terminated.  This is easy to see with
netstat -m.  Also, the knocking down / resetting
of IP_HDRINCL on 'sloop' isn't necessary.

Here's a suggested diff:

-seanb


Index: ping.c
===================================================================
RCS file: /cvsroot/src/sbin/ping/ping.c,v
retrieving revision 1.63
diff -c -r1.63 ping.c
*** ping.c      2001/12/20 20:10:38     1.63
--- ping.c      2003/04/25 20:54:36
***************
*** 258,263 ****
--- 258,264 ----
        char *policy_in = NULL;
        char *policy_out = NULL;
  #endif
+       int one = 1;
  #endif


***************
*** 468,486 ****
                        warn("SO_DONTROUTE");
        }

-       if ((sloop = cap_socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
-               err(1, "Cannot create socket");
-       if (options & SO_DEBUG) {
-               if (setsockopt(sloop, SOL_SOCKET, SO_DEBUG,
-                              (char *)&on, sizeof(on)) == -1)
-                       warn("Can't turn on socket debugging");
-       }
-       if (options & SO_DONTROUTE) {
-               if (setsockopt(sloop, SOL_SOCKET, SO_DONTROUTE,
-                              (char *)&on, sizeof(on)) == -1)
-                       warn("SO_DONTROUTE");
-       }
-
        if (pingflags & F_SOURCE_ROUTE) {
                optspace[IPOPT_OPTVAL] = IPOPT_LSRR;
                optspace[IPOPT_OLEN] = optlen = 7;
--- 469,474 ----
***************
*** 539,544 ****
--- 527,551 ----
                        err(1, "Can't set source interface/address");
        }
  #ifdef IPSEC
+       if ((sloop = cap_socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
+               err(1, "Cannot create socket");
+       if (options & SO_DEBUG) {
+               if (setsockopt(sloop, SOL_SOCKET, SO_DEBUG,
+                              (char *)&on, sizeof(on)) == -1)
+                       warn("Can't turn on socket debugging");
+       }
+       if (options & SO_DONTROUTE) {
+               if (setsockopt(sloop, SOL_SOCKET, SO_DONTROUTE,
+                              (char *)&on, sizeof(on)) == -1)
+                       warn("SO_DONTROUTE");
+       }
+       /*
+        * Set to lowest value to prevent packets from filing
+        * up the recv buffer as this socket is never read on.
+        */
+       if (setsockopt(sloop, SOL_SOCKET, SO_RCVBUF, &one, sizeof(one)) == -1)
+               warn("SO_RCVBUF");
+
  #ifdef IPSEC_POLICY_IPSEC
      {
        char *buf;
***************
*** 607,612 ****
--- 614,621 ----
                (char *)&optval, sizeof(optval));
      }
  #endif /*IPSEC_POLICY_IPSEC*/
+ #else
+       sloop = s;
  #endif /*IPSEC*/

        (void)printf("PING %s (%s): %d data bytes\n", hostname,
***************
*** 837,845 ****
--- 846,856 ----
                opack_icmp.icmp_cksum = in_cksum((u_short*)&opack_icmp,
                                                 PHDR_LEN);
                sw = 0;
+ #ifndef IPSEC
                if (setsockopt(sloop,IPPROTO_IP,IP_HDRINCL,
                               (char *)&sw,sizeof(sw)) < 0)
                        err(1, "Can't turn off special IP header");
+ #endif
                if (sendto(sloop, (char *) &opack_icmp, PHDR_LEN, MSG_DONTROUTE,
                           (struct sockaddr *)&loc_addr,
                           sizeof(struct sockaddr_in)) < 0) {
***************
*** 853,861 ****
--- 864,874 ----
                                warn("failed to clear cached route");
                }
                sw = 1;
+ #ifndef IPSEC
                if (setsockopt(sloop,IPPROTO_IP,IP_HDRINCL,
                               (char *)&sw, sizeof(sw)) < 0)
                        err(1, "Can't set special IP header");
+ #endif

                (void)gettimeofday(&clear_cache,0);
        }
>How-To-Repeat:
ping something and look at 'netstat -m' stats.
>Fix:
see description.
>Release-Note:
>Audit-Trail:
>Unformatted: