diff options
Diffstat (limited to 'usr.bin/sockstat')
| -rw-r--r-- | usr.bin/sockstat/main.c | 331 | ||||
| -rw-r--r-- | usr.bin/sockstat/sockstat.1 | 9 | ||||
| -rw-r--r-- | usr.bin/sockstat/tests/Makefile | 3 |
3 files changed, 234 insertions, 109 deletions
diff --git a/usr.bin/sockstat/main.c b/usr.bin/sockstat/main.c index 3b989c4283e4..1f174d827e1a 100644 --- a/usr.bin/sockstat/main.c +++ b/usr.bin/sockstat/main.c @@ -88,6 +88,7 @@ static bool opt_A; /* Show kernel address of pcb */ static bool opt_b; /* Show BBLog state */ static bool opt_C; /* Show congestion control */ static bool opt_c; /* Show connected sockets */ +static bool opt_F; /* Show sockets for selected user only */ static bool opt_f; /* Show FIB numbers */ static bool opt_I; /* Show spliced socket addresses */ static bool opt_i; /* Show inp_gencnt */ @@ -103,16 +104,24 @@ static bool opt_u; /* Show Unix domain sockets */ static u_int opt_v; /* Verbose mode */ static bool opt_w; /* Automatically size the columns */ static bool is_xo_style_encoding; +static bool show_path_state = false; /* * Default protocols to use if no -P was defined. */ -static const char *default_protos[] = {"sctp", "tcp", "udp", "divert" }; +static const char *default_protos[] = {"sctp", "tcp", "udp", "udplite", + "divert" }; static size_t default_numprotos = nitems(default_protos); static int *protos; /* protocols to use */ static size_t numprotos; /* allocated size of protos[] */ +/* + * Show sockets for user username or UID specified + */ +static char *filter_user_optarg = NULL; /* saved optarg for username/UID resolving */ +static uid_t filter_user_uid; /* UID to show sockets for */ + struct addr { union { struct sockaddr_storage address; @@ -215,6 +224,18 @@ _enforce_ksize(size_t received_size, size_t expected_size, const char *struct_na } #define enforce_ksize(_sz, _struct) (_enforce_ksize(_sz, sizeof(_struct), #_struct)) +static inline bool +filtered_uid(uid_t i_uid) +{ + return ((i_uid) == filter_user_uid); +} + +static inline bool +need_nosocks(void) +{ + return !(opt_F || (opt_j >= 0)); +} + static int get_proto_type(const char *proto) { @@ -584,6 +605,7 @@ gather_sctp(void) !(local_all_loopback || foreign_all_loopback))) { RB_INSERT(socks_t, &socks, sock); + show_path_state = true; } else { free_socket(sock); } @@ -624,6 +646,10 @@ gather_inet(int proto) varname = "net.inet.udp.pcblist"; protoname = "udp"; break; + case IPPROTO_UDPLITE: + varname = "net.inet.udplite.pcblist"; + protoname = "udplite"; + break; case IPPROTO_DIVERT: varname = "net.inet.divert.pcblist"; protoname = "div"; @@ -672,6 +698,7 @@ gather_inet(int proto) protoname = xtp->t_flags & TF_TOE ? "toe" : "tcp"; break; case IPPROTO_UDP: + case IPPROTO_UDPLITE: case IPPROTO_DIVERT: xip = (struct xinpcb *)xig; if (!check_ksize(xip->xi_len, struct xinpcb)) @@ -750,7 +777,8 @@ gather_inet(int proto) if (sock->socket != 0) RB_INSERT(socks_t, &socks, sock); else - SLIST_INSERT_HEAD(&nosocks, sock, socket_list); + if (need_nosocks()) + SLIST_INSERT_HEAD(&nosocks, sock, socket_list); } out: free(buf); @@ -854,6 +882,8 @@ getfiles(void) struct xfile *xfiles; size_t len, olen; + int filenum = 0; + olen = len = sizeof(*xfiles); if ((xfiles = malloc(len)) == NULL) xo_err(1, "malloc()"); @@ -872,14 +902,23 @@ getfiles(void) if ((files = malloc(nfiles * sizeof(struct file))) == NULL) xo_err(1, "malloc()"); + /* Fill files structure, optionally for specified user */ for (int i = 0; i < nfiles; i++) { - files[i].xf_data = xfiles[i].xf_data; - files[i].xf_pid = xfiles[i].xf_pid; - files[i].xf_uid = xfiles[i].xf_uid; - files[i].xf_fd = xfiles[i].xf_fd; - RB_INSERT(files_t, &ftree, &files[i]); + if (opt_F && !filtered_uid(xfiles[i].xf_uid)) + continue; + files[filenum].xf_data = xfiles[i].xf_data; + files[filenum].xf_pid = xfiles[i].xf_pid; + files[filenum].xf_uid = xfiles[i].xf_uid; + files[filenum].xf_fd = xfiles[i].xf_fd; + RB_INSERT(files_t, &ftree, &files[filenum]); + filenum++; } + /* Adjust global nfiles to match the number of files we + * actually filled into files[] array + */ + nfiles = filenum; + free(xfiles); } @@ -1194,7 +1233,9 @@ calculate_sock_column_widths(struct col_widths *cw, struct sock *s) first = true; len = strlen(s->protoname); - if (s->vflag & (INP_IPV4 | INP_IPV6)) + if (s->vflag & INP_IPV4) + len += 1; + if (s->vflag & INP_IPV6) len += 1; cw->proto = MAX(cw->proto, len); @@ -1230,40 +1271,40 @@ calculate_sock_column_widths(struct col_widths *cw, struct sock *s) { .socket = s->splice_socket }); if (sp != NULL) { len = formataddr(&sp->laddr->address, - NULL, 0); + NULL, 0); cw->splice_address = MAX( - cw->splice_address, len); + cw->splice_address, len); } } } if (opt_i) { - if (s->proto == IPPROTO_TCP || s->proto == IPPROTO_UDP) - { + if (s->proto == IPPROTO_TCP || + s->proto == IPPROTO_UDP) { len = snprintf(NULL, 0, - "%" PRIu64, s->inp_gencnt); + "%" PRIu64, s->inp_gencnt); cw->inp_gencnt = MAX(cw->inp_gencnt, len); } } if (opt_U) { if (faddr != NULL && - ((s->proto == IPPROTO_SCTP && - s->state != SCTP_CLOSED && - s->state != SCTP_BOUND && - s->state != SCTP_LISTEN) || - (s->proto == IPPROTO_TCP && - s->state != TCPS_CLOSED && - s->state != TCPS_LISTEN))) { + ((s->proto == IPPROTO_SCTP && + s->state != SCTP_CLOSED && + s->state != SCTP_BOUND && + s->state != SCTP_LISTEN) || + (s->proto == IPPROTO_TCP && + s->state != TCPS_CLOSED && + s->state != TCPS_LISTEN))) { len = snprintf(NULL, 0, "%u", - ntohs(faddr->encaps_port)); + ntohs(faddr->encaps_port)); cw->encaps = MAX(cw->encaps, len); } } if (opt_s) { if (faddr != NULL && - s->proto == IPPROTO_SCTP && - s->state != SCTP_CLOSED && - s->state != SCTP_BOUND && - s->state != SCTP_LISTEN) { + s->proto == IPPROTO_SCTP && + s->state != SCTP_CLOSED && + s->state != SCTP_BOUND && + s->state != SCTP_LISTEN) { len = strlen(sctp_path_state(faddr->state)); cw->path_state = MAX(cw->path_state, len); } @@ -1271,21 +1312,22 @@ 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) { + s->proto == IPPROTO_TCP) { switch (s->proto) { case IPPROTO_SCTP: len = strlen( sctp_conn_state(s->state)); cw->conn_state = MAX( - cw->conn_state, len); + 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); + len = strlen( + tcpstates[s->state]); + cw->conn_state = MAX( + cw->conn_state, + len); } break; } @@ -1462,8 +1504,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 == IPPROTO_TCP || + s->proto == IPPROTO_UDP) { snprintf(buf, bufsize, "%" PRIu64, s->inp_gencnt); xo_emit(" {:id/%*s}", cw->inp_gencnt, buf); @@ -1472,29 +1514,29 @@ 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->state != SCTP_CLOSED && - s->state != SCTP_BOUND && - s->state != SCTP_LISTEN) || - (s->proto == IPPROTO_TCP && - s->state != TCPS_CLOSED && - s->state != TCPS_LISTEN))) { + ((s->proto == IPPROTO_SCTP && + s->state != SCTP_CLOSED && + s->state != SCTP_BOUND && + s->state != SCTP_LISTEN) || + (s->proto == IPPROTO_TCP && + s->state != TCPS_CLOSED && + s->state != TCPS_LISTEN))) { xo_emit(" {:encaps/%*u}", cw->encaps, - ntohs(faddr->encaps_port)); + ntohs(faddr->encaps_port)); } else if (!is_xo_style_encoding) xo_emit(" {:encaps/%*s}", cw->encaps, "??"); } - if (opt_s) { + if (opt_s && show_path_state) { if (faddr != NULL && - s->proto == IPPROTO_SCTP && - s->state != SCTP_CLOSED && - s->state != SCTP_BOUND && - s->state != SCTP_LISTEN) { + s->proto == IPPROTO_SCTP && + s->state != SCTP_CLOSED && + s->state != SCTP_BOUND && + s->state != SCTP_LISTEN) { xo_emit(" {:path-state/%-*s}", cw->path_state, - sctp_path_state(faddr->state)); + sctp_path_state(faddr->state)); } else if (!is_xo_style_encoding) xo_emit(" {:path-state/%-*s}", cw->path_state, - "??"); + "??"); } if (first) { if (opt_s) { @@ -1503,40 +1545,40 @@ display_sock(struct sock *s, struct col_widths *cw, char *buf, size_t bufsize) switch (s->proto) { case IPPROTO_SCTP: xo_emit(" {:conn-state/%-*s}", - cw->conn_state, - sctp_conn_state(s->state)); + cw->conn_state, + sctp_conn_state(s->state)); break; case IPPROTO_TCP: if (s->state >= 0 && - s->state < TCP_NSTATES) + s->state < TCP_NSTATES) xo_emit(" {:conn-state/%-*s}", - cw->conn_state, - tcpstates[s->state]); + cw->conn_state, + tcpstates[s->state]); else if (!is_xo_style_encoding) xo_emit(" {:conn-state/%-*s}", - cw->conn_state, "??"); + cw->conn_state, "??"); break; } } else if (!is_xo_style_encoding) xo_emit(" {:conn-state/%-*s}", - cw->conn_state, "??"); + cw->conn_state, "??"); } if (opt_b) { if (s->proto == IPPROTO_TCP) xo_emit(" {:bblog-state/%-*s}", - cw->bblog_state, - bblog_state(s->bblog_state)); + cw->bblog_state, + bblog_state(s->bblog_state)); else if (!is_xo_style_encoding) xo_emit(" {:bblog-state/%-*s}", - cw->bblog_state, "??"); + cw->bblog_state, "??"); } if (opt_S) { if (s->proto == IPPROTO_TCP) xo_emit(" {:stack/%-*s}", - cw->stack, s->stack); + cw->stack, s->stack); else if (!is_xo_style_encoding) xo_emit(" {:stack/%-*s}", - cw->stack, "??"); + cw->stack, "??"); } if (opt_C) { if (s->proto == IPPROTO_TCP) @@ -1544,23 +1586,53 @@ display_sock(struct sock *s, struct col_widths *cw, char *buf, size_t bufsize) else if (!is_xo_style_encoding) xo_emit(" {:cc/%-*s}", cw->cc, "??"); } + } else if (!is_xo_style_encoding) { + if (opt_s) + xo_emit(" {:conn-state/%-*s}", cw->conn_state, + "??"); + if (opt_b) + xo_emit(" {:bblog-state/%-*s}", cw->bblog_state, + "??"); + if (opt_S) + xo_emit(" {:stack/%-*s}", cw->stack, "??"); + if (opt_C) + xo_emit(" {:cc/%-*s}", cw->cc, "??"); } if (laddr != NULL) laddr = laddr->next; if (faddr != NULL) faddr = faddr->next; + xo_emit("\n"); if (!is_xo_style_encoding && (laddr != NULL || faddr != NULL)) xo_emit("{:user/%-*s} {:command/%-*s} {:pid/%*s}" - " {:fd/%*s}", cw->user, "??", cw->command, "??", - cw->pid, "??", cw->fd, "??"); + " {:fd/%*s} {:proto/%-*s}", cw->user, "??", + cw->command, "??", cw->pid, "??", cw->fd, "??", + cw->proto, "??"); first = false; } - xo_emit("\n"); } static void display(void) { + static const char *__HDR_USER="USER", + *__HDR_COMMAND="COMMAND", + *__HDR_PID="PID", + *__HDR_FD="FD", + *__HDR_PROTO="PROTO", + *__HDR_LOCAL_ADDRESS="LOCAL ADDRESS", + *__HDR_FOREIGN_ADDRESS="FOREIGN ADDRESS", + *__HDR_PCB_KVA="PCB KVA", + *__HDR_FIB="FIB", + *__HDR_SPLICE_ADDRESS="SPLICE ADDRESS", + *__HDR_ID="ID", + *__HDR_ENCAPS="ENCAPS", + *__HDR_PATH_STATE="PATH STATE", + *__HDR_CONN_STATE="CONN STATE", + *__HDR_BBLOG_STATE="BBLOG STATE", + *__HDR_STACK="STACK", + *__HDR_CC="CC"; + struct passwd *pwd; struct file *xf; struct sock *s; @@ -1575,23 +1647,23 @@ display(void) if (!is_xo_style_encoding) { cw = (struct col_widths) { - .user = strlen("USER"), + .user = strlen(__HDR_USER), .command = 10, - .pid = strlen("PID"), - .fd = strlen("FD"), - .proto = strlen("PROTO"), - .local_addr = opt_w ? strlen("LOCAL ADDRESS") : 21, - .foreign_addr = opt_w ? strlen("FOREIGN ADDRESS") : 21, + .pid = strlen(__HDR_PID), + .fd = strlen(__HDR_FD), + .proto = strlen(__HDR_PROTO), + .local_addr = opt_w ? strlen(__HDR_LOCAL_ADDRESS) : 21, + .foreign_addr = opt_w ? strlen(__HDR_FOREIGN_ADDRESS) : 21, .pcb_kva = 18, - .fib = strlen("FIB"), - .splice_address = strlen("SPLICE ADDRESS"), - .inp_gencnt = strlen("ID"), - .encaps = strlen("ENCAPS"), - .path_state = strlen("PATH STATE"), - .conn_state = strlen("CONN STATE"), - .bblog_state = strlen("BBLOG STATE"), - .stack = strlen("STACK"), - .cc = strlen("CC"), + .fib = strlen(__HDR_FIB), + .splice_address = strlen(__HDR_SPLICE_ADDRESS), + .inp_gencnt = strlen(__HDR_ID), + .encaps = strlen(__HDR_ENCAPS), + .path_state = strlen(__HDR_PATH_STATE), + .conn_state = strlen(__HDR_CONN_STATE), + .bblog_state = strlen(__HDR_BBLOG_STATE), + .stack = strlen(__HDR_STACK), + .cc = strlen(__HDR_CC), }; calculate_column_widths(&cw); } else @@ -1602,32 +1674,34 @@ display(void) xo_open_list("socket"); if (!opt_q) { xo_emit("{T:/%-*s} {T:/%-*s} {T:/%*s} {T:/%*s} {T:/%-*s} " - "{T:/%-*s} {T:/%-*s}", cw.user, "USER", cw.command, - "COMMAND", cw.pid, "PID", cw.fd, "FD", cw.proto, - "PROTO", cw.local_addr, "LOCAL ADDRESS", - cw.foreign_addr, "FOREIGN ADDRESS"); + "{T:/%-*s} {T:/%-*s}", cw.user, __HDR_USER, cw.command, + __HDR_COMMAND, cw.pid, __HDR_PID, cw.fd, __HDR_FD, cw.proto, + __HDR_PROTO, cw.local_addr, __HDR_LOCAL_ADDRESS, + cw.foreign_addr, __HDR_FOREIGN_ADDRESS); if (opt_A) - xo_emit(" {T:/%-*s}", cw.pcb_kva, "PCB KVA"); + xo_emit(" {T:/%-*s}", cw.pcb_kva, __HDR_PCB_KVA); if (opt_f) /* RT_MAXFIBS is 65535. */ - xo_emit(" {T:/%*s}", cw.fib, "FIB"); + xo_emit(" {T:/%*s}", cw.fib, __HDR_FIB); if (opt_I) xo_emit(" {T:/%-*s}", cw.splice_address, - "SPLICE ADDRESS"); + __HDR_SPLICE_ADDRESS); if (opt_i) - xo_emit(" {T:/%*s}", cw.inp_gencnt, "ID"); + xo_emit(" {T:/%*s}", cw.inp_gencnt, __HDR_ID); if (opt_U) - xo_emit(" {T:/%*s}", cw.encaps, "ENCAPS"); + xo_emit(" {T:/%*s}", cw.encaps, __HDR_ENCAPS); if (opt_s) { - xo_emit(" {T:/%-*s}", cw.path_state, "PATH STATE"); - xo_emit(" {T:/%-*s}", cw.conn_state, "CONN STATE"); + if (show_path_state) + xo_emit(" {T:/%-*s}", cw.path_state, + __HDR_PATH_STATE); + xo_emit(" {T:/%-*s}", cw.conn_state, __HDR_CONN_STATE); } if (opt_b) - xo_emit(" {T:/%-*s}", cw.bblog_state, "BBLOG STATE"); + xo_emit(" {T:/%-*s}", cw.bblog_state, __HDR_BBLOG_STATE); if (opt_S) - xo_emit(" {T:/%-*s}", cw.stack, "STACK"); + xo_emit(" {T:/%-*s}", cw.stack, __HDR_STACK); if (opt_C) - xo_emit(" {T:/%-*s}", cw.cc, "CC"); + xo_emit(" {T:/%-*s}", cw.cc, __HDR_CC); xo_emit("\n"); } cap_setpassent(cappwd, 1); @@ -1644,22 +1718,22 @@ display(void) if (opt_n || (pwd = cap_getpwuid(cappwd, xf->xf_uid)) == NULL) xo_emit("{:user/%-*lu}", cw.user, - (u_long)xf->xf_uid); + (u_long)xf->xf_uid); else xo_emit("{:user/%-*s}", cw.user, pwd->pw_name); if (!is_xo_style_encoding) xo_emit(" {:command/%-*.10s}", cw.command, - getprocname(xf->xf_pid)); + getprocname(xf->xf_pid)); else xo_emit(" {:command/%-*s}", cw.command, - getprocname(xf->xf_pid)); + getprocname(xf->xf_pid)); xo_emit(" {:pid/%*lu}", cw.pid, (u_long)xf->xf_pid); xo_emit(" {:fd/%*d}", cw.fd, xf->xf_fd); display_sock(s, &cw, buf, bufsize); xo_close_instance("socket"); } } - if (opt_j >= 0) + if (!need_nosocks()) goto out; SLIST_FOREACH(s, &nosocks, socket_list) { if (!check_ports(s)) @@ -1667,8 +1741,8 @@ display(void) xo_open_instance("socket"); if (!is_xo_style_encoding) xo_emit("{:user/%-*s} {:command/%-*s} {:pid/%*s}" - " {:fd/%*s}", cw.user, "??", cw.command, "??", - cw.pid, "??", cw.fd, "??"); + " {:fd/%*s}", cw.user, "??", cw.command, "??", + cw.pid, "??", cw.fd, "??"); display_sock(s, &cw, buf, bufsize); xo_close_instance("socket"); } @@ -1680,8 +1754,8 @@ display(void) xo_open_instance("socket"); if (!is_xo_style_encoding) xo_emit("{:user/%-*s} {:command/%-*s} {:pid/%*s}" - " {:fd/%*s}", cw.user, "??", cw.command, "??", - cw.pid, "??", cw.fd, "??"); + " {:fd/%*s}", cw.user, "??", cw.command, "??", + cw.pid, "??", cw.fd, "??"); display_sock(s, &cw, buf, bufsize); xo_close_instance("socket"); } @@ -1750,11 +1824,44 @@ jail_getvnet(int jid) return (vnet); } +/* + * Parse username and/or UID + */ +static bool +parse_filter_user(void) +{ + struct passwd *pwd; + char *ep; + uid_t uid; + bool rv = false; + + uid = (uid_t)strtol(filter_user_optarg, &ep, 10); + + /* Open and/or rewind capsicumized password file */ + cap_setpassent(cappwd, 1); + + if (*ep == '\0') { + /* We have an UID specified, check if it's valid */ + if ((pwd = cap_getpwuid(cappwd, uid)) == NULL) + goto out; + filter_user_uid = uid; + } else { + /* Check if we have a valid username */ + if ((pwd = cap_getpwnam(cappwd, filter_user_optarg)) == NULL) + goto out; + filter_user_uid = pwd->pw_uid; + } + + rv = true; +out: + return (rv); +} + static void usage(void) { xo_error( -"usage: sockstat [--libxo ...] [-46AbCcfIiLlnqSsUuvw] [-j jid] [-p ports]\n" +"usage: sockstat [--libxo ...] [-46AbCcfIiLlnqSsUuvw] [-F uid/username] [-j jid] [-p ports]\n" " [-P protocols]\n"); exit(1); } @@ -1764,19 +1871,21 @@ main(int argc, char *argv[]) { cap_channel_t *capcas; cap_net_limit_t *limit; - const char *pwdcmds[] = { "setpassent", "getpwuid" }; - const char *pwdfields[] = { "pw_name" }; + const char *pwdcmds[] = { "setpassent", "getpwuid", "getpwnam" }; + const char *pwdfields[] = { "pw_name", "pw_uid" }; int protos_defined = -1; int o, i, err; argc = xo_parse_args(argc, argv); if (argc < 0) exit(1); - if (xo_get_style(NULL) != XO_STYLE_TEXT && - xo_get_style(NULL) != XO_STYLE_HTML) - is_xo_style_encoding = true; + if (xo_get_style(NULL) != XO_STYLE_TEXT) { + show_path_state = true; + if (xo_get_style(NULL) != XO_STYLE_HTML) + is_xo_style_encoding = true; + } opt_j = -1; - while ((o = getopt(argc, argv, "46AbCcfIij:Llnp:P:qSsUuvw")) != -1) + while ((o = getopt(argc, argv, "46AbCcF:fIij:Llnp:P:qSsUuvw")) != -1) switch (o) { case '4': opt_4 = true; @@ -1796,6 +1905,11 @@ main(int argc, char *argv[]) case 'c': opt_c = true; break; + case 'F': + /* Save optarg for later use when we enter capabilities mode */ + filter_user_optarg = optarg; + opt_F = true; + break; case 'f': opt_f = true; break; @@ -1907,6 +2021,9 @@ main(int argc, char *argv[]) if (cap_pwd_limit_fields(cappwd, pwdfields, nitems(pwdfields)) < 0) xo_err(1, "Unable to apply pwd commands limits"); + if (opt_F && !parse_filter_user()) + xo_errx(1, "Invalid username or UID specified"); + if ((!opt_4 && !opt_6) && protos_defined != -1) opt_4 = opt_6 = true; if (!opt_4 && !opt_6 && !opt_u) diff --git a/usr.bin/sockstat/sockstat.1 b/usr.bin/sockstat/sockstat.1 index dabb3042bfd4..b0fae81ee566 100644 --- a/usr.bin/sockstat/sockstat.1 +++ b/usr.bin/sockstat/sockstat.1 @@ -25,7 +25,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd October 7, 2025 +.Dd October 29, 2025 .Dt SOCKSTAT 1 .Os .Sh NAME @@ -35,6 +35,7 @@ .Nm .Op Fl -libxo .Op Fl 46AbCcfIiLlnqSsUuvw +.Op Fl F Ar user .Op Fl j Ar jail .Op Fl p Ar ports .Op Fl P Ar protocols @@ -73,6 +74,10 @@ Display the congestion control module, if applicable. This is currently only implemented for TCP. .It Fl c Show connected sockets. +.It Fl F Ar user +Show sockets for specified +.Ar user +(user name or UID) only. .It Fl f Show the FIB number of each socket. .It Fl I @@ -205,6 +210,8 @@ is specified (only for SCTP or TCP). The path state if .Fl s is specified (only for SCTP). +When using traditional text output, this column is only shown when there is at +least one path state to show. .It Li CONN STATE The connection state if .Fl s diff --git a/usr.bin/sockstat/tests/Makefile b/usr.bin/sockstat/tests/Makefile index 9971bca2d474..5412e9d842aa 100644 --- a/usr.bin/sockstat/tests/Makefile +++ b/usr.bin/sockstat/tests/Makefile @@ -1,5 +1,6 @@ ATF_TESTS_C+= sockstat_test -SRCS.sockstat_test= sockstat_test.c ../sockstat.c +SRCS.sockstat_test= sockstat_test.c sockstat.c +.PATH: ${.CURDIR:H} LIBADD= xo |
