mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-11-07 04:36:52 -10:00
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
This commit is contained in:
1 parent
3a58a50dd4
commit
8b2b62b49d
2 files changed
+120
-106
No files matched your search
+109
-105
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user