From e5cccc35c38e889545fad60588c64c9ab8daea67 Mon Sep 17 00:00:00 2001 From: Michael Tuexen Date: Tue, 12 Sep 2017 13:34:43 +0000 Subject: [PATCH] Add support to print the TCP stack being used. Sponsored by: Netflix, Inc. --- sys/netinet/tcp_var.h | 2 +- usr.bin/sockstat/sockstat.1 | 15 +++++++-- usr.bin/sockstat/sockstat.c | 61 ++++++++++++++++++++++++++----------- 3 files changed, 57 insertions(+), 21 deletions(-) diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index 48305788d097..967a51398630 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -655,7 +655,7 @@ struct tcp_hhook_data { struct xtcpcb { size_t xt_len; /* length of this structure */ struct xinpcb xt_inp; - char xt_stack[TCP_FUNCTION_NAME_LEN_MAX]; /* (n) */ + char xt_stack[TCP_FUNCTION_NAME_LEN_MAX]; /* (s) */ int64_t spare64[8]; int32_t t_state; /* (s,p) */ uint32_t t_flags; /* (s,p) */ diff --git a/usr.bin/sockstat/sockstat.1 b/usr.bin/sockstat/sockstat.1 index 95247e4f8efa..3117eba4e038 100644 --- a/usr.bin/sockstat/sockstat.1 +++ b/usr.bin/sockstat/sockstat.1 @@ -27,7 +27,7 @@ .\" .\" $FreeBSD$ .\" -.Dd August 27, 2015 +.Dd September 12, 2017 .Dt SOCKSTAT 1 .Os .Sh NAME @@ -35,7 +35,7 @@ .Nd list open sockets .Sh SYNOPSIS .Nm -.Op Fl 46cLlsu +.Op Fl 46cLlSsu .Op Fl j Ar jid .Op Fl p Ar ports .Op Fl P Ar protocols @@ -83,6 +83,9 @@ The argument is a comma-separated list of protocol names, as they are defined in .Xr protocols 5 . +.It Fl S +Display the protocol stack, if applicable. +This is currently only implemented for TCP. .It Fl s Display the protocol state, if applicable. This is currently only implemented for SCTP and TCP. @@ -143,6 +146,14 @@ if the endpoint could not be determined. (Internet sockets only) The address the foreign end of the socket is bound to (see .Xr getpeername 2 ) . +.It Li STATE +The protocol state if +.Fl s +is specified (only for SCTP or TCP). +.It Li STACK +The protocol stack if +.Fl S +is specified (only for TCP). .El .Pp If a socket is associated with more than one file descriptor, diff --git a/usr.bin/sockstat/sockstat.c b/usr.bin/sockstat/sockstat.c index 6235f8285793..71d21cc467ee 100644 --- a/usr.bin/sockstat/sockstat.c +++ b/usr.bin/sockstat/sockstat.c @@ -73,6 +73,7 @@ static int opt_c; /* Show connected sockets */ static int opt_j; /* Show specified jail */ static int opt_L; /* Don't show IPv4 or IPv6 loopback sockets */ static int opt_l; /* Show listening sockets */ +static int opt_S; /* Show protocol stack if applicable */ static int opt_s; /* Show protocol state if applicable */ static int opt_u; /* Show Unix domain sockets */ static int opt_v; /* Verbose mode */ @@ -106,6 +107,7 @@ struct sock { int proto; int state; const char *protoname; + char stack[TCP_FUNCTION_NAME_LEN_MAX]; struct addr *laddr; struct addr *faddr; struct sock *next; @@ -698,8 +700,11 @@ gather_inet(int proto) sock->laddr = laddr; sock->faddr = faddr; sock->vflag = xip->inp_vflag; - if (proto == IPPROTO_TCP) + if (proto == IPPROTO_TCP) { sock->state = xtp->t_state; + memcpy(sock->stack, xtp->xt_stack, + TCP_FUNCTION_NAME_LEN_MAX); + } sock->protoname = protoname; hash = (int)((uintptr_t)sock->socket % HASHSIZE); sock->next = sockhash[hash]; @@ -1040,21 +1045,36 @@ displaysock(struct sock *s, int pos) default: abort(); } - if (first && opt_s && - (s->proto == IPPROTO_SCTP || s->proto == IPPROTO_TCP)) { - while (pos < 80) - pos += xprintf(" "); - switch (s->proto) { - case IPPROTO_SCTP: - pos += xprintf("%s", sctp_state(s->state)); - break; - case IPPROTO_TCP: - if (s->state >= 0 && s->state < TCP_NSTATES) - pos += - xprintf("%s", tcpstates[s->state]); - else - pos += xprintf("?"); - break; + if (first) { + if (opt_s && + (s->proto == IPPROTO_SCTP || + s->proto == IPPROTO_TCP)) { + while (pos < 80) + pos += xprintf(" "); + switch (s->proto) { + case IPPROTO_SCTP: + pos += xprintf("%s", + sctp_state(s->state)); + break; + case IPPROTO_TCP: + if (s->state >= 0 && + s->state < TCP_NSTATES) + pos += + xprintf("%s", + tcpstates[s->state]); + else + pos += xprintf("?"); + break; + } + } + if (opt_S && s->proto == IPPROTO_TCP) { + while (pos < 80) + pos += xprintf(" "); + if (opt_s) + while (pos < 93) + pos += xprintf(" "); + xprintf("%.*s", TCP_FUNCTION_NAME_LEN_MAX, + s->stack); } } if (laddr != NULL) @@ -1083,6 +1103,8 @@ display(void) "LOCAL ADDRESS", "FOREIGN ADDRESS"); if (opt_s) printf(" %-12s", "STATE"); + if (opt_S) + printf(" %.*s", TCP_FUNCTION_NAME_LEN_MAX, "STACK"); printf("\n"); setpassent(1); for (xf = xfiles, n = 0; n < nxfiles; ++n, ++xf) { @@ -1153,7 +1175,7 @@ static void usage(void) { fprintf(stderr, - "usage: sockstat [-46cLlsu] [-j jid] [-p ports] [-P protocols]\n"); + "usage: sockstat [-46cLlSsu] [-j jid] [-p ports] [-P protocols]\n"); exit(1); } @@ -1164,7 +1186,7 @@ main(int argc, char *argv[]) int o, i; opt_j = -1; - while ((o = getopt(argc, argv, "46cj:Llp:P:suv")) != -1) + while ((o = getopt(argc, argv, "46cj:Llp:P:Ssuv")) != -1) switch (o) { case '4': opt_4 = 1; @@ -1190,6 +1212,9 @@ main(int argc, char *argv[]) case 'P': protos_defined = parse_protos(optarg); break; + case 'S': + opt_S = 1; + break; case 's': opt_s = 1; break;