From nobody Tue Jun 16 17:03:26 2026 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4gftby4mQ6z6hT2G for ; Tue, 16 Jun 2026 17:03:26 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R13" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4gftby1bNCz4K1N for ; Tue, 16 Jun 2026 17:03:26 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1781629406; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=nJ12D59eGYZbtRuR7b04pynvDIaCW8U/pO/Cansqnvk=; b=KMS17BvgOyU2p1T/8r77LQWax43qqzxhOS98L4u73eMLf2BCL/ypKaUjupLR5rjbzBWwZf N4OZCnYUyDuYbbyfMvL5kRR1DgXrQSkUdTiG7meAq+IGkaBO1iSGc8vSlIYvuICH4kEgoD +TeKI+W1rwcsa1IHaEDVrePNvyufxAwxXx5dlzzVVx+/2GTvqhtpI4+AuWFnUSbMzu9/h5 EeYL/HZ3ayF+lGoZiv4Y2jwUGn5hoNyAaNas2uTo/W21GfkaWl9zGa+QMY77WKA0yjZ8uw rtfeubI4ypsvn3PZoYj6RQAfB0TKrQfzFBlv4zqf82xxyq50ikGewqBMZ3M9EA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1781629406; a=rsa-sha256; cv=none; b=I8R/J6G21u/7sLOYdDNUOsTyHXnwXbInuj+91+d87prufxJGCdmDRmkp060BzunxmftRhK w9BqDdmmqeTlWMpJhjWQ5QW0mf5unjbk5884n347Ncyp2K9rcbb9n/iUDtz1cy+u+6qkRr HsnpxB6zXnsnOYgVKu1H61K0PtHeWZEpyjBdG8pCS7+x0AJdSEjwQ6SJmEkF7iAbBnKbUA 8Xa9msSjvryoEXNlvB2EmCz2AOJdc4OStRNIxWKO3/sf8IjgsN51W+rUFVBFlJqGinMv5v Y4n3/kfYvY7Xj2exq5E4SWlGGf2rvYAPEkshotEKrhQOcDOgoccl1I+NpVBb3g== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1781629406; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=nJ12D59eGYZbtRuR7b04pynvDIaCW8U/pO/Cansqnvk=; b=Nv8f1SnziL1RWfJ0NXLLq4Ljyxnlv7VxmozVrxHZiMLTkOTZlZcSsckVUJA9qeB2Al61oV 1jTJGCnbK69onUlq8NR0Ouro37+7jovNcbhCzN3SWaAgalkf+RUX5bLVRkjAGhWdmzUQIA iHOcAyldIzeiBi1U0/MjFWv8sIXkSWdE27iGWPdsZLY5pYdzMvLoazSglJWeH9wOrBbyCU VFlPD8PxW6ow8Z5fJdfjXtwpo0C1HffD4eh63n75PtCKwMgemg4qmLVUyhN5cwGJFgh9Qb x77aqINyHRlRZoQbnTTTghAxg4IgHkGyaLP7RX4BN0qHS5ShAHS7kqKKRrBfiQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4gftby17Fxzbc1 for ; Tue, 16 Jun 2026 17:03:26 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 19e57 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Tue, 16 Jun 2026 17:03:26 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Gleb Smirnoff Subject: git: 8b2b62b49d88 - main - sockstat: consolidate unix(4) protocols in the array of protocols List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: glebius X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 8b2b62b49d886816213fb6b39258afb1373ef43b Auto-Submitted: auto-generated Date: Tue, 16 Jun 2026 17:03:26 +0000 Message-Id: <6a3181de.19e57.30da57e9@gitrepo.freebsd.org> The branch main has been updated by glebius: URL: https://cgit.FreeBSD.org/src/commit/?id=8b2b62b49d886816213fb6b39258afb1373ef43b commit 8b2b62b49d886816213fb6b39258afb1373ef43b Author: Gleb Smirnoff AuthorDate: 2026-06-16 16:59:01 +0000 Commit: Gleb Smirnoff CommitDate: 2026-06-16 16:59:01 +0000 sockstat: consolidate unix(4) protocols in the array of protocols This makes it possible to list unix(4) protocols in -P, which was not possible before. Update the manual page and provide an example. In 'struct sock' make member proto a pointer into the protocols table instead of a number. This removes namespace collision that mixed IPPROTO_TCP and etc with SOCK_STREAM and etc. There were no known bugs due to this collision, though. Preserve all current UI bugs for possible combinations of protocol selection options. Should be no UI changes outside the improved -P. Reviewed by: pouria, tuexen Differential Revision: https://reviews.freebsd.org/D57508 --- usr.bin/sockstat/main.c | 214 ++++++++++++++++++++++---------------------- 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