diff options
Diffstat (limited to 'usr.bin/sockstat/sockstat.c')
-rw-r--r-- | usr.bin/sockstat/sockstat.c | 88 |
1 files changed, 82 insertions, 6 deletions
diff --git a/usr.bin/sockstat/sockstat.c b/usr.bin/sockstat/sockstat.c index 8a8afc0..98d86b5 100644 --- a/usr.bin/sockstat/sockstat.c +++ b/usr.bin/sockstat/sockstat.c @@ -45,6 +45,8 @@ __FBSDID("$FreeBSD$"); #include <netinet/in_pcb.h> #include <netinet/sctp.h> #include <netinet/tcp.h> +#define TCPSTATES /* load state names */ +#include <netinet/tcp_fsm.h> #include <netinet/tcp_seq.h> #include <netinet/tcp_var.h> #include <arpa/inet.h> @@ -71,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 state if applicable */ static int opt_u; /* Show Unix domain sockets */ static int opt_v; /* Verbose mode */ @@ -101,6 +104,7 @@ struct sock { int vflag; int family; int proto; + int state; const char *protoname; struct addr *laddr; struct addr *faddr; @@ -328,6 +332,10 @@ gather_sctp(void) sock->socket = xinpcb->socket; sock->proto = IPPROTO_SCTP; sock->protoname = "sctp"; + if (xinpcb->maxqlen == 0) + sock->state = SCTP_CLOSED; + else + sock->state = SCTP_LISTEN; if (xinpcb->flags & SCTP_PCB_FLAGS_BOUND_V6) { sock->family = AF_INET6; sock->vflag = INP_IPV6; @@ -417,6 +425,7 @@ gather_sctp(void) sock->socket = xinpcb->socket; sock->proto = IPPROTO_SCTP; sock->protoname = "sctp"; + sock->state = (int)xstcb->state; if (xinpcb->flags & SCTP_PCB_FLAGS_BOUND_V6) { sock->family = AF_INET6; sock->vflag = INP_IPV6; @@ -594,9 +603,10 @@ gather_inet(int proto) xig = (struct xinpgen *)(void *)((char *)xig + xig->xig_len); if (xig >= exig) break; + xip = (struct xinpcb *)xig; + xtp = (struct xtcpcb *)xig; switch (proto) { case IPPROTO_TCP: - xtp = (struct xtcpcb *)xig; if (xtp->xt_len != sizeof(*xtp)) { warnx("struct xtcpcb size mismatch"); goto out; @@ -607,7 +617,6 @@ gather_inet(int proto) break; case IPPROTO_UDP: case IPPROTO_DIVERT: - xip = (struct xinpcb *)xig; if (xip->xi_len != sizeof(*xip)) { warnx("struct xinpcb size mismatch"); goto out; @@ -670,6 +679,8 @@ gather_inet(int proto) sock->laddr = laddr; sock->faddr = faddr; sock->vflag = inp->inp_vflag; + if (proto == IPPROTO_TCP) + sock->state = xtp->xt_tp.t_state; sock->protoname = protoname; hash = (int)((uintptr_t)sock->socket % HASHSIZE); sock->next = sockhash[hash]; @@ -900,11 +911,51 @@ check_ports(struct sock *s) return (0); } +static const char * +sctp_state(int state) +{ + switch (state) { + case SCTP_CLOSED: + return "CLOSED"; + break; + case SCTP_BOUND: + return "BOUND"; + break; + case SCTP_LISTEN: + return "LISTEN"; + break; + case SCTP_COOKIE_WAIT: + return "COOKIE_WAIT"; + break; + case SCTP_COOKIE_ECHOED: + return "COOKIE_ECHOED"; + break; + case SCTP_ESTABLISHED: + return "ESTABLISHED"; + break; + case SCTP_SHUTDOWN_SENT: + return "SHUTDOWN_SENT"; + break; + case SCTP_SHUTDOWN_RECEIVED: + return "SHUTDOWN_RECEIVED"; + break; + case SCTP_SHUTDOWN_ACK_SENT: + return "SHUTDOWN_ACK_SENT"; + break; + case SCTP_SHUTDOWN_PENDING: + return "SHUTDOWN_PENDING"; + break; + default: + return "UNKNOWN"; + break; + } +} + static void displaysock(struct sock *s, int pos) { void *p; - int hash; + int hash, first; struct addr *laddr, *faddr; struct sock *s_tmp; @@ -917,6 +968,7 @@ displaysock(struct sock *s, int pos) pos += xprintf("6 "); laddr = s->laddr; faddr = s->faddr; + first = 1; while (laddr != NULL || faddr != NULL) { while (pos < 36) pos += xprintf(" "); @@ -968,6 +1020,23 @@ 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 (laddr != NULL) laddr = laddr->next; if (faddr != NULL) @@ -976,6 +1045,7 @@ displaysock(struct sock *s, int pos) xprintf("\n"); pos = 0; } + first = 0; } xprintf("\n"); } @@ -988,9 +1058,12 @@ display(void) struct sock *s; int hash, n, pos; - printf("%-8s %-10s %-5s %-2s %-6s %-21s %-21s\n", + printf("%-8s %-10s %-5s %-2s %-6s %-21s %-21s", "USER", "COMMAND", "PID", "FD", "PROTO", "LOCAL ADDRESS", "FOREIGN ADDRESS"); + if (opt_s) + printf(" %-12s", "STATE"); + printf("\n"); setpassent(1); for (xf = xfiles, n = 0; n < nxfiles; ++n, ++xf) { if (xf->xf_data == NULL) @@ -1061,7 +1134,7 @@ static void usage(void) { fprintf(stderr, - "Usage: sockstat [-46cLlu] [-j jid] [-p ports] [-P protocols]\n"); + "usage: sockstat [-46cLlsu] [-j jid] [-p ports] [-P protocols]\n"); exit(1); } @@ -1072,7 +1145,7 @@ main(int argc, char *argv[]) int o, i; opt_j = -1; - while ((o = getopt(argc, argv, "46cj:Llp:P:uv")) != -1) + while ((o = getopt(argc, argv, "46cj:Llp:P:suv")) != -1) switch (o) { case '4': opt_4 = 1; @@ -1098,6 +1171,9 @@ main(int argc, char *argv[]) case 'P': protos_defined = parse_protos(optarg); break; + case 's': + opt_s = 1; + break; case 'u': opt_u = 1; break; |