Page MenuHomeFreeBSD

D53458.id165361.diff
No OneTemporary

D53458.id165361.diff

diff --git a/usr.bin/sockstat/main.c b/usr.bin/sockstat/main.c
--- a/usr.bin/sockstat/main.c
+++ b/usr.bin/sockstat/main.c
@@ -89,6 +89,7 @@
static bool opt_C; /* Show congestion control */
static bool opt_c; /* Show connected sockets */
static bool opt_f; /* Show FIB numbers */
+static bool opt_F; /* Show sockets for selected user only */
static bool opt_I; /* Show spliced socket addresses */
static bool opt_i; /* Show inp_gencnt */
static int opt_j; /* Show specified jail */
@@ -115,6 +116,15 @@
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 */
+
+#define FILTERED_USER(i_uid) \
+ (((i_uid) == filter_user_uid))
+
struct addr {
union {
struct sockaddr_storage address;
@@ -862,6 +872,8 @@
struct xfile *xfiles;
size_t len, olen;
+ int filenum = 0;
+
olen = len = sizeof(*xfiles);
if ((xfiles = malloc(len)) == NULL)
xo_err(1, "malloc()");
@@ -881,13 +893,22 @@
xo_err(1, "malloc()");
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_USER(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++;
}
+ if ((nfiles != filenum) &&
+ ((files = realloc(files, filenum * sizeof(struct file))) == NULL))
+ xo_err(1, "malloc()");
+
+ nfiles = filenum;
+
free(xfiles);
}
@@ -1584,6 +1605,24 @@
static void
display(void)
{
+ #define __HDR_USER "USER"
+ #define __HDR_COMMAND "COMMAND"
+ #define __HDR_PID "PID"
+ #define __HDR_FD "FD"
+ #define __HDR_PROTO "PROTO"
+ #define __HDR_LOCAL_ADDRESS "LOCAL ADDRESS"
+ #define __HDR_FOREIGN_ADDRESS "FOREIGN ADDRESS"
+ #define __HDR_PCB_KVA "PCB KVA"
+ #define __HDR_FIB "FIB"
+ #define __HDR_SPLICE_ADDRESS "SPLICE ADDRESS"
+ #define __HDR_ID "ID"
+ #define __HDR_ENCAPS "ENCAPS"
+ #define __HDR_PATH_STATE "PATH STATE"
+ #define __HDR_CONN_STATE "CONN STATE"
+ #define __HDR_BBLOG_STATE "BBLOG STATE"
+ #define __HDR_STACK "STACK"
+ #define __HDR_CC "CC"
+
struct passwd *pwd;
struct file *xf;
struct sock *s;
@@ -1598,23 +1637,23 @@
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
@@ -1625,34 +1664,34 @@
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) {
if (show_path_state)
xo_emit(" {T:/%-*s}", cw.path_state,
- "PATH STATE");
- xo_emit(" {T:/%-*s}", cw.conn_state, "CONN 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);
@@ -1775,11 +1814,44 @@
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);
}
@@ -1789,8 +1861,8 @@
{
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;
@@ -1803,7 +1875,7 @@
is_xo_style_encoding = true;
}
opt_j = -1;
- while ((o = getopt(argc, argv, "46AbCcfIij:Llnp:P:qSsUuvw")) != -1)
+ while ((o = getopt(argc, argv, "46AbCcfF:Iij:Llnp:P:qSsUuvw")) != -1)
switch (o) {
case '4':
opt_4 = true;
@@ -1826,6 +1898,15 @@
case 'f':
opt_f = true;
break;
+ case 'F':
+ /* Filter only on first occurence of -F
+ */
+ if (!opt_F) {
+ /* Save optarg for later use when we enter capabilities mode */
+ filter_user_optarg = optarg;
+ opt_F = true;
+ }
+ break;
case 'I':
opt_I = true;
break;
@@ -1934,6 +2015,9 @@
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
--- 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 14, 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
@@ -75,6 +76,10 @@
Show connected sockets.
.It Fl f
Show the FIB number of each socket.
+.It Fl F Ar user
+Show sockets for specified
+.Ar user
+(user name or UID) only.
.It Fl I
Show the local address of the socket to which the current socket is spliced, if
any.

File Metadata

Mime Type
text/plain
Expires
Sat, Jul 25, 3:45 AM (5 h, 10 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35461009
Default Alt Text
D53458.id165361.diff (8 KB)

Event Timeline