sockstat: Also show sockets not associated with a file descriptor.

Sockets not associated with a file descriptor include TCP TIME_WAIT states
and sockets created via the socket(9) API such as from rpc.lockd and the NFS
client.

PR:		bin/164081
MFC after:	2 weeks
No objection:	des
This commit is contained in:
Jilles Tjoelker 2012-01-24 21:33:34 +00:00
parent 53b95d1799
commit 61149f8d7c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=230512
2 changed files with 75 additions and 69 deletions

View File

@ -27,7 +27,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd July 9, 2009
.Dd January 24, 2012
.Dt SOCKSTAT 1
.Os
.Sh NAME
@ -137,19 +137,10 @@ 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.
If a socket is associated with more than one file descriptor,
it is shown multiple times.
If a socket is not associated with any file descriptor,
the first four columns have no meaning.
.Sh SEE ALSO
.Xr fstat 1 ,
.Xr netstat 1 ,
@ -167,10 +158,3 @@ The
.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 .

View File

@ -86,6 +86,7 @@ static int *ports;
struct sock {
void *socket;
void *pcb;
int shown;
int vflag;
int family;
int proto;
@ -570,13 +571,68 @@ check_ports(struct sock *s)
return (0);
}
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 @@ display(void)
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 @@ display(void)
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");
}
}