diff options
| -rw-r--r-- | usr.bin/sockstat/main.c | 214 | ||||
| -rw-r--r-- | usr.bin/sockstat/sockstat.1 | 12 |
2 files changed, 120 insertions, 106 deletions
diff --git a/usr.bin/sockstat/main.c b/usr.bin/sockstat/main.c index aa7d8f3d378c..0edf8dcbd431 100644 --- a/usr.bin/sockstat/main.c +++ b/usr.bin/sockstat/main.c @@ -107,49 +107,59 @@ static bool show_path_state = false; /* * Protocols that we support. - * TODO: merge unix(4) protocols into here. */ +enum sockstatproto { + SCTP = 0, TCP, UDP, UDPLITE, DIVERT, STREAM, DGRAM, SEQPACK +}; struct proto; typedef void gather_func_t(struct proto *); -static gather_func_t gather_sctp, gather_inet; +static gather_func_t gather_sctp, gather_inet, gather_unix; static struct proto { gather_func_t *gather; const char *name; const char *pcblist; - union { - int protonum; /* gather_inet() */ - }; bool disabled; } protos[] = { - { + [SCTP] = { .name = "sctp", .gather = gather_sctp, .pcblist = "net.inet.sctp.assoclist", - .protonum = IPPROTO_SCTP, }, - { + [TCP] = { .name = "tcp", .gather = gather_inet, .pcblist = "net.inet.tcp.pcblist", - .protonum = IPPROTO_TCP, }, - { + [UDP] = { .name = "udp", .gather = gather_inet, .pcblist = "net.inet.udp.pcblist", - .protonum = IPPROTO_UDP, }, - { + [UDPLITE] = { .name = "udplite", .gather = gather_inet, .pcblist = "net.inet.udplite.pcblist", - .protonum = IPPROTO_UDPLITE, }, - { + [DIVERT] = { .name = "divert", .gather = gather_inet, .pcblist = "net.inet.divert.pcblist", }, + [STREAM] = { + .name = "unix/stream", + .gather = gather_unix, + .pcblist = "net.local.stream.pcblist", + }, + [DGRAM] = { + .name = "unix/dgram", + .gather = gather_unix, + .pcblist = "net.local.dgram.pcblist", + }, + [SEQPACK] = { + .name = "unix/seqpack", + .gather = gather_unix, + .pcblist = "net.local.seqpacket.pcblist", + }, }; /* @@ -185,10 +195,10 @@ struct sock { int shown; int vflag; int family; - int proto; int state; int fibnum; int bblog_state; + const struct proto *proto; const char *protoname; char stack[TCP_FUNCTION_NAME_LEN_MAX]; char cc[TCP_CA_NAME_MAX]; @@ -387,8 +397,7 @@ gather_sctp(struct proto *proto) if ((sock = calloc(1, sizeof *sock)) == NULL) xo_err(1, "malloc()"); sock->socket = xinpcb->socket; - sock->proto = IPPROTO_SCTP; - sock->protoname = "sctp"; + sock->proto = proto; if (xinpcb->maxqlen == 0) sock->state = SCTP_CLOSED; else @@ -488,8 +497,7 @@ gather_sctp(struct proto *proto) if ((sock = calloc(1, sizeof *sock)) == NULL) xo_err(1, "malloc()"); sock->socket = xinpcb->socket; - sock->proto = IPPROTO_SCTP; - sock->protoname = "sctp"; + sock->proto = proto; sock->state = (int)xstcb->state; if (xinpcb->flags & SCTP_PCB_FLAGS_BOUND_V6) { sock->family = AF_INET6; @@ -665,7 +673,7 @@ gather_inet(struct proto *proto) xig = (struct xinpgen *)(void *)((char *)xig + xig->xig_len); if (xig >= exig) break; - if (proto->protonum == IPPROTO_TCP) { + if (proto == &protos[TCP]) { xtp = (struct xtcpcb *)xig; xip = &xtp->xt_inp; if (!check_ksize(xtp->xt_len, struct xtcpcb)) @@ -713,7 +721,7 @@ gather_inet(struct proto *proto) sock->socket = so->xso_so; sock->pcb = so->so_pcb; sock->splice_socket = so->so_splice_so; - sock->proto = proto->protonum; + sock->proto = proto; sock->inp_gencnt = xip->inp_gencnt; sock->fibnum = so->so_fibnum; if (xip->inp_vflag & INP_IPV4) { @@ -729,14 +737,14 @@ gather_inet(struct proto *proto) sockaddr(&faddr->address, sock->family, &xip->in6p_faddr, xip->inp_fport); } - if (proto->protonum == IPPROTO_TCP) + if (proto == &protos[TCP]) faddr->encaps_port = xtp->xt_encaps_port; laddr->next = NULL; faddr->next = NULL; sock->laddr = laddr; sock->faddr = faddr; sock->vflag = xip->inp_vflag; - if (proto->protonum == IPPROTO_TCP) { + if (proto == &protos[TCP]) { sock->state = xtp->t_state; sock->bblog_state = xtp->t_logstate; memcpy(sock->stack, xtp->xt_stack, @@ -755,33 +763,22 @@ out: } static void -gather_unix(int proto) +gather_unix(struct proto *proto) { struct xunpgen *xug, *exug; struct xunpcb *xup; struct sock *sock; struct addr *laddr, *faddr; - const char *varname, *protoname; + const char *protoname; size_t len, bufsize; void *buf; int retry; - switch (proto) { - case SOCK_STREAM: - varname = "net.local.stream.pcblist"; - protoname = "stream"; - break; - case SOCK_DGRAM: - varname = "net.local.dgram.pcblist"; - protoname = "dgram"; - break; - case SOCK_SEQPACKET: - varname = "net.local.seqpacket.pcblist"; - protoname = is_xo_style_encoding ? "seqpacket" : "seqpack"; - break; - default: - abort(); - } + if (proto == &protos[SEQPACK] && is_xo_style_encoding) + protoname = "seqpacket"; + else + protoname = strchr(proto->name, '/') + 1; + buf = NULL; bufsize = 8192; retry = 5; @@ -790,8 +787,8 @@ gather_unix(int proto) if ((buf = realloc(buf, bufsize)) == NULL) xo_err(1, "realloc()"); len = bufsize; - if (cap_sysctlbyname(capsysctl, varname, buf, &len, - NULL, 0) == 0) + if (cap_sysctlbyname(capsysctl, proto->pcblist, buf, + &len, NULL, 0) == 0) break; if (errno != ENOMEM || len != bufsize) xo_err(1, "cap_sysctlbyname()"); @@ -1256,8 +1253,8 @@ calculate_sock_column_widths(struct col_widths *cw, struct sock *s) } } if (opt_i) { - if (s->proto == IPPROTO_TCP || - s->proto == IPPROTO_UDP) { + if (s->proto == &protos[TCP] || + s->proto == &protos[UDP]) { len = snprintf(NULL, 0, "%" PRIu64, s->inp_gencnt); cw->inp_gencnt = MAX(cw->inp_gencnt, len); @@ -1265,11 +1262,11 @@ calculate_sock_column_widths(struct col_widths *cw, struct sock *s) } if (opt_U) { if (faddr != NULL && - ((s->proto == IPPROTO_SCTP && + ((s->proto == &protos[SCTP] && s->state != SCTP_CLOSED && s->state != SCTP_BOUND && s->state != SCTP_LISTEN) || - (s->proto == IPPROTO_TCP && + (s->proto == &protos[TCP] && s->state != TCPS_CLOSED && s->state != TCPS_LISTEN))) { len = snprintf(NULL, 0, "%u", @@ -1279,7 +1276,7 @@ calculate_sock_column_widths(struct col_widths *cw, struct sock *s) } if (opt_s) { if (faddr != NULL && - s->proto == IPPROTO_SCTP && + s->proto == &protos[SCTP] && s->state != SCTP_CLOSED && s->state != SCTP_BOUND && s->state != SCTP_LISTEN) { @@ -1289,33 +1286,27 @@ calculate_sock_column_widths(struct col_widths *cw, struct sock *s) } if (first) { if (opt_s) { - if (s->proto == IPPROTO_SCTP || - s->proto == IPPROTO_TCP) { - switch (s->proto) { - case IPPROTO_SCTP: + if (s->proto == &protos[SCTP]) { + len = strlen(sctp_conn_state(s->state)); + cw->conn_state = MAX(cw->conn_state, + len); + } + if (s->proto == &protos[TCP]) { + if (s->state >= 0 && + s->state < TCP_NSTATES) { len = strlen( - sctp_conn_state(s->state)); + tcpstates[s->state]); cw->conn_state = MAX( - cw->conn_state, len); - break; - case IPPROTO_TCP: - if (s->state >= 0 && - s->state < TCP_NSTATES) { - len = strlen( - tcpstates[s->state]); - cw->conn_state = MAX( - cw->conn_state, - len); - } - break; + cw->conn_state, + len); } } } - if (opt_S && s->proto == IPPROTO_TCP) { + if (opt_S && s->proto == &protos[TCP]) { len = strlen(s->stack); cw->stack = MAX(cw->stack, len); } - if (opt_C && s->proto == IPPROTO_TCP) { + if (opt_C && s->proto == &protos[TCP]) { len = strlen(s->cc); cw->cc = MAX(cw->cc, len); } @@ -1482,8 +1473,8 @@ display_sock(struct sock *s, struct col_widths *cw, char *buf, size_t bufsize) cw->splice_address, buf); } if (opt_i) { - if (s->proto == IPPROTO_TCP || - s->proto == IPPROTO_UDP) { + if (s->proto == &protos[TCP] || + s->proto == &protos[UDP]) { snprintf(buf, bufsize, "%" PRIu64, s->inp_gencnt); xo_emit(" {:id/%*s}", cw->inp_gencnt, buf); @@ -1492,11 +1483,11 @@ display_sock(struct sock *s, struct col_widths *cw, char *buf, size_t bufsize) } if (opt_U) { if (faddr != NULL && - ((s->proto == IPPROTO_SCTP && + ((s->proto == &protos[SCTP] && s->state != SCTP_CLOSED && s->state != SCTP_BOUND && s->state != SCTP_LISTEN) || - (s->proto == IPPROTO_TCP && + (s->proto == &protos[TCP] && s->state != TCPS_CLOSED && s->state != TCPS_LISTEN))) { xo_emit(" {:encaps/%*u}", cw->encaps, @@ -1506,7 +1497,7 @@ display_sock(struct sock *s, struct col_widths *cw, char *buf, size_t bufsize) } if (opt_s && show_path_state) { if (faddr != NULL && - s->proto == IPPROTO_SCTP && + s->proto == &protos[SCTP] && s->state != SCTP_CLOSED && s->state != SCTP_BOUND && s->state != SCTP_LISTEN) { @@ -1518,31 +1509,25 @@ display_sock(struct sock *s, struct col_widths *cw, char *buf, size_t bufsize) } if (first) { if (opt_s) { - if (s->proto == IPPROTO_SCTP || - s->proto == IPPROTO_TCP) { - switch (s->proto) { - case IPPROTO_SCTP: + if (s->proto == &protos[SCTP]) { + xo_emit(" {:conn-state/%-*s}", + cw->conn_state, + sctp_conn_state(s->state)); + } else if (s->proto == &protos[TCP]) { + if (s->state >= 0 && + s->state < TCP_NSTATES) xo_emit(" {:conn-state/%-*s}", cw->conn_state, - sctp_conn_state(s->state)); - break; - case IPPROTO_TCP: - if (s->state >= 0 && - s->state < TCP_NSTATES) - xo_emit(" {:conn-state/%-*s}", - cw->conn_state, - tcpstates[s->state]); - else if (!is_xo_style_encoding) - xo_emit(" {:conn-state/%-*s}", - cw->conn_state, "??"); - break; - } + tcpstates[s->state]); + else if (!is_xo_style_encoding) + xo_emit(" {:conn-state/%-*s}", + cw->conn_state, "??"); } else if (!is_xo_style_encoding) xo_emit(" {:conn-state/%-*s}", cw->conn_state, "??"); } if (opt_b) { - if (s->proto == IPPROTO_TCP) + if (s->proto == &protos[TCP]) xo_emit(" {:bblog-state/%-*s}", cw->bblog_state, bblog_state(s->bblog_state)); @@ -1551,7 +1536,7 @@ display_sock(struct sock *s, struct col_widths *cw, char *buf, size_t bufsize) cw->bblog_state, "??"); } if (opt_S) { - if (s->proto == IPPROTO_TCP) + if (s->proto == &protos[TCP]) xo_emit(" {:stack/%-*s}", cw->stack, s->stack); else if (!is_xo_style_encoding) @@ -1559,7 +1544,7 @@ display_sock(struct sock *s, struct col_widths *cw, char *buf, size_t bufsize) cw->stack, "??"); } if (opt_C) { - if (s->proto == IPPROTO_TCP) + if (s->proto == &protos[TCP]) xo_emit(" {:cc/%-*s}", cw->cc, s->cc); else if (!is_xo_style_encoding) xo_emit(" {:cc/%-*s}", cw->cc, "??"); @@ -1983,23 +1968,42 @@ main(int argc, char *argv[]) if (opt_F && !parse_filter_user()) xo_errx(1, "Invalid username or UID specified"); - if ((!opt_4 && !opt_6) && protos_defined) - opt_4 = opt_6 = true; - if (!opt_4 && !opt_6 && !opt_u) - opt_4 = opt_6 = opt_u = true; if (!opt_c && !opt_l) opt_c = opt_l = true; - if (opt_4 || opt_6) - for (u_int i = 0; i < nitems(protos); i++) - if (!protos[i].disabled) - protos[i].gather(&protos[i]); - - if (opt_u || (!protos_defined && !opt_4 && !opt_6)) { - gather_unix(SOCK_STREAM); - gather_unix(SOCK_DGRAM); - gather_unix(SOCK_SEQPACKET); + /* + * By default all protocols are gathered. + * + * With -u and without -[46] disables all but unix(4). + * With -[46] and without -u disables unix(4). + * With -P only specified are gathered and -4 and -6 are ignored, + * however -u is not ignored (historical bug). + * + * divert(4) is controlled by -4 (historical bug). + * + * NB: opt_4 and opt_6 are used outside this function, thus need to + * be set to true if both are false. + */ + if (protos_defined) { + if (opt_u) + protos[STREAM].disabled = protos[DGRAM].disabled = + protos[SEQPACK].disabled = false; + } else { + if (!opt_u && (opt_4 || opt_6)) + protos[STREAM].disabled = protos[DGRAM].disabled = + protos[SEQPACK].disabled = true; + if (opt_u && !(opt_4 || opt_6)) + protos[SCTP].disabled = protos[TCP].disabled = + protos[UDP].disabled = protos[UDPLITE].disabled = + true; } + if (!opt_4 && !opt_6) + opt_4 = opt_6 = true; + + for (u_int i = 0; i < nitems(protos); i++) + if (!protos[i].disabled) + protos[i].gather(&protos[i]); + getfiles(); display(); exit(0); diff --git a/usr.bin/sockstat/sockstat.1 b/usr.bin/sockstat/sockstat.1 index 385b1c4952dc..b8fb420bb105 100644 --- a/usr.bin/sockstat/sockstat.1 +++ b/usr.bin/sockstat/sockstat.1 @@ -119,7 +119,10 @@ Recognized protocols are .Qq tcp , .Qq sctp , .Qq udp , -.Qq udplite +.Qq udplite , +.Qq unix/stream , +.Qq unix/dgram , +.Qq unix/seqpack , and .Qq divert . .It Fl q @@ -257,6 +260,13 @@ Show TCP IPv6 sockets which are listening and connected (default): $ sockstat -6 -P tcp .Ed .Pp +Show all listening +.Xr unix 4 +datagram sockets: +.Bd -literal -offset indent +$ sockstat -P unix/dgram -l +.Ed +.Pp Show all sockets in JSON format with neat alignment: .Bd -literal -offset indent $ sockstat --libxo json,pretty |
