The following reply was made to PR bin/164081; it has been noted by GNATS.

From: Jilles Tjoelker <jil...@stack.nl>
To: Jim Pirzyk <pir...@freebsd.org>, d...@freebsd.org
Cc: bug-follo...@freebsd.org
Subject: Re: bin/164081: sockstat not reporting all open sockets
Date: Sun, 22 Jan 2012 23:01:30 +0100

 On Tue, Jan 17, 2012 at 08:13:59AM -0500, Jim Pirzyk wrote:
 > On Jan 13, 2012, at 7:03 PM, Jilles Tjoelker wrote:
 
 > >> [netstat reports sockets that sockstat does not]
 
 > > The sockstat utility checks all file descriptors open by all processes
 > > looking for sockets, while netstat shows all kernel-level sockets. This
 > > may mismatch in many ways: a process may have closed its descriptor but
 > > TCP still needs to maintain some state like TIME_WAIT (as mentioned in
 > > the sockstat(1) man page), multiple descriptors may exist for a single
 > > socket and kernel code (like nlockmgr) may use the socket(9) API
 > > directly so there is no descriptor. However, any socket file descriptor
 > > shown by sockstat must correspond to a kernel-level socket shown by
 > > netstat.
 
 > > This does appear to be intended, although it is surprising and not
 > > documented very well.
 
 > So maybe in light of that, we should change this ticket to update the
 > man page to document this case too?
 
 I looked in the code and tried to make sockstat show sockets that are
 not associated with any open file. This turned out to be fairly easy.
 
 I have tested this on 10-current and 8-stable. On 8-stable there will be
 a conflict in sockstat.1 which can safely be ignored (it is because
 r200779 was not MFCed).
 
 On a machine that runs UDP nfsd it adds at least two lines to the
 output:
 
 ?        ?          ?     ?  udp6   *:2049                *:*
 ?        ?          ?     ?  udp4   *:2049                *:*
 
 DES, what do you think of this?
 
 Index: usr.bin/sockstat/sockstat.1
 ===================================================================
 --- usr.bin/sockstat/sockstat.1        (revision 230388)
 +++ usr.bin/sockstat/sockstat.1        (working copy)
 @@ -136,20 +136,6 @@
  The address the foreign end of the socket is bound to (see
  .Xr getpeername 2 ) .
  .El
 -.Pp
 -Note that TCP sockets in the
 -.Dv AF_INET
 -or
 -.Dv AF_INET6
 -domains that are not in one of the
 -.Dv LISTEN , SYN_SENT ,
 -or
 -.Dv ESTABLISHED
 -states may not be shown by
 -.Nm ;
 -use
 -.Xr netstat 1
 -to examine them instead.
  .Sh SEE ALSO
  .Xr fstat 1 ,
  .Xr netstat 1 ,
 @@ -167,10 +153,3 @@
  .Nm
  command and this manual page were written by
  .An Dag-Erling Sm\(/orgrav Aq d...@freebsd.org .
 -.Sh BUGS
 -Unlike
 -.Xr netstat 1 ,
 -.Nm
 -lists sockets by walking file descriptor tables and will not output
 -the ones owned by the kernel, e.g. NLM sockets created by
 -.Xr rpc.lockd 8 .
 Index: usr.bin/sockstat/sockstat.c
 ===================================================================
 --- usr.bin/sockstat/sockstat.c        (revision 230388)
 +++ usr.bin/sockstat/sockstat.c        (working copy)
 @@ -86,6 +86,7 @@
  struct sock {
        void *socket;
        void *pcb;
 +      int shown;
        int vflag;
        int family;
        int proto;
 @@ -571,12 +572,67 @@
  }
  
  static void
 +displaysock(struct sock *s, int pos)
 +{
 +      void *p;
 +      int hash;
 +
 +      while (pos < 29)
 +              pos += xprintf(" ");
 +      pos += xprintf("%s", s->protoname);
 +      if (s->vflag & INP_IPV4)
 +              pos += xprintf("4 ");
 +      if (s->vflag & INP_IPV6)
 +              pos += xprintf("6 ");
 +      while (pos < 36)
 +              pos += xprintf(" ");
 +      switch (s->family) {
 +      case AF_INET:
 +      case AF_INET6:
 +              pos += printaddr(s->family, &s->laddr);
 +              if (s->family == AF_INET6 && pos >= 58)
 +                      pos += xprintf(" ");
 +              while (pos < 58)
 +                      pos += xprintf(" ");
 +              pos += printaddr(s->family, &s->faddr);
 +              break;
 +      case AF_UNIX:
 +              /* server */
 +              if (s->laddr.ss_len > 0) {
 +                      pos += printaddr(s->family, &s->laddr);
 +                      break;
 +              }
 +              /* client */
 +              p = *(void **)&s->faddr;
 +              if (p == NULL) {
 +                      pos += xprintf("(not connected)");
 +                      break;
 +              }
 +              pos += xprintf("-> ");
 +              for (hash = 0; hash < HASHSIZE; ++hash) {
 +                      for (s = sockhash[hash]; s != NULL; s = s->next)
 +                              if (s->pcb == p)
 +                                      break;
 +                      if (s != NULL)
 +                              break;
 +              }
 +              if (s == NULL || s->laddr.ss_len == 0)
 +                      pos += xprintf("??");
 +              else
 +                      pos += printaddr(s->family, &s->laddr);
 +              break;
 +      default:
 +              abort();
 +      }
 +      xprintf("\n");
 +}
 +
 +static void
  display(void)
  {
        struct passwd *pwd;
        struct xfile *xf;
        struct sock *s;
 -      void *p;
        int hash, n, pos;
  
        printf("%-8s %-10s %-5s %-2s %-6s %-21s %-21s\n",
 @@ -594,6 +650,7 @@
                        continue;
                if (!check_ports(s))
                        continue;
 +              s->shown = 1;
                pos = 0;
                if ((pwd = getpwuid(xf->xf_uid)) == NULL)
                        pos += xprintf("%lu ", (u_long)xf->xf_uid);
 @@ -608,54 +665,19 @@
                while (pos < 26)
                        pos += xprintf(" ");
                pos += xprintf("%d ", xf->xf_fd);
 -              while (pos < 29)
 -                      pos += xprintf(" ");
 -              pos += xprintf("%s", s->protoname);
 -              if (s->vflag & INP_IPV4)
 -                      pos += xprintf("4 ");
 -              if (s->vflag & INP_IPV6)
 -                      pos += xprintf("6 ");
 -              while (pos < 36)
 -                      pos += xprintf(" ");
 -              switch (s->family) {
 -              case AF_INET:
 -              case AF_INET6:
 -                      pos += printaddr(s->family, &s->laddr);
 -                      if (s->family == AF_INET6 && pos >= 58)
 -                              pos += xprintf(" ");
 -                      while (pos < 58)
 -                              pos += xprintf(" ");
 -                      pos += printaddr(s->family, &s->faddr);
 -                      break;
 -              case AF_UNIX:
 -                      /* server */
 -                      if (s->laddr.ss_len > 0) {
 -                              pos += printaddr(s->family, &s->laddr);
 -                              break;
 -                      }
 -                      /* client */
 -                      p = *(void **)&s->faddr;
 -                      if (p == NULL) {
 -                              pos += xprintf("(not connected)");
 -                              break;
 -                      }
 -                      pos += xprintf("-> ");
 -                      for (hash = 0; hash < HASHSIZE; ++hash) {
 -                              for (s = sockhash[hash]; s != NULL; s = s->next)
 -                                      if (s->pcb == p)
 -                                              break;
 -                              if (s != NULL)
 -                                      break;
 -                      }
 -                      if (s == NULL || s->laddr.ss_len == 0)
 -                              pos += xprintf("??");
 -                      else
 -                              pos += printaddr(s->family, &s->laddr);
 -                      break;
 -              default:
 -                      abort();
 +              displaysock(s, pos);
 +      }
 +      for (hash = 0; hash < HASHSIZE; hash++) {
 +              for (s = sockhash[hash]; s != NULL; s = s->next) {
 +                      if (s->shown)
 +                              continue;
 +                      if (!check_ports(s))
 +                              continue;
 +                      pos = 0;
 +                      pos += xprintf("%-8s %-10s %-5s %-2s ",
 +                          "?", "?", "?", "?");
 +                      displaysock(s, pos);
                }
 -              xprintf("\n");
        }
  }
  
 -- 
 Jilles Tjoelker
_______________________________________________
freebsd-bugs@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bugs
To unsubscribe, send any mail to "freebsd-bugs-unsubscr...@freebsd.org"

Reply via email to