Date: Sun, 22 Jan 2012 22:10:11 GMT From: Jilles Tjoelker <jilles@stack.nl> To: freebsd-bugs@FreeBSD.org Subject: Re: bin/164081: sockstat not reporting all open sockets Message-ID: <201201222210.q0MMABeD027857@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
The following reply was made to PR bin/164081; it has been noted by GNATS.
From: Jilles Tjoelker <jilles@stack.nl>
To: Jim Pirzyk <pirzyk@FreeBSD.org>, des@FreeBSD.org
Cc: bug-followup@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 des@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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201201222210.q0MMABeD027857>
