From nobody Thu Jul 07 05:20:37 2022 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 6C69D1CFF47F; Thu, 7 Jul 2022 05:20:38 +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 "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4Ldl9f1gmgz3J3k; Thu, 7 Jul 2022 05:20:38 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1657171238; 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=ci0hxbD82PA1/QUbirG+WR+H5JBWhFo8x/OtyqQX8Tk=; b=vlnEaUcJ5yIMGGuYzNxdrkcRlNYZkgKKg2pZdHXQEDI2zTg7VodVhy8Ra3QWxDNeJTsTa6 Z5DYXIT4JwuJk4Cg1cl7O/g1AROk1wRXrqwQ6YGQp6yZLOuih2gdUmoOlIj1NWIbc3MYSk qKYmCMjS3+vsDBj7mLPl/8EePYJ/Y9BMggBJxiqyGDQEhQGrWJZ9kP6rNojvSSfOxtOFol 4OlKcpR+bYIQQpzopmFNq40TwPRsOOgC/ujcSgvp99edzVXoUGwUfPWuLYS9x6Lc6FNlpd SyH/R95A1Qnvwc9vEHkIj/jAwMvue19MhCmzK48UKKYWF1kAudPdZIrFF4/1yA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (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 did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4Ldl9d6hVkzWsS; Thu, 7 Jul 2022 05:20:37 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 2675KbRX082113; Thu, 7 Jul 2022 05:20:37 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 2675KbCK082099; Thu, 7 Jul 2022 05:20:37 GMT (envelope-from git) Date: Thu, 7 Jul 2022 05:20:37 GMT Message-Id: <202207070520.2675KbCK082099@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Gleb Smirnoff Subject: git: 2c436d4890c7 - main - sockstat(1): print out full connection graph for unix(4) sockets 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: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@freebsd.org 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: 2c436d4890c7ed7f50321725dee229834114166b Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1657171238; 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=ci0hxbD82PA1/QUbirG+WR+H5JBWhFo8x/OtyqQX8Tk=; b=qNgeSjoZ04k573qLCi8e5KvR0lLKt3nIq9CL1ixgnFRFWUeWKnqYMDIb3SymaXX91TYada ntocQw9I8yaNTs/G0A3f4+oXNS55zTZ8hX25WCKQ2WYz38Gh3XVx0TNZ8OE9kje6PM6A4z KHI5tyLbIqi5kl5xTiUTgTlv19SYlLbZ/hs6rvFf6NRHHAZSmxV2SVQCQ7/wbxE6PHemra R83vlPFJmYxeA4u2l1+3bG7ETRwfMoWs+YOqmJHuXCcO5YJpRg9n/mcYuaUeQN1yv4xiJk Jj7e+XzuGesudY4g/yZlNo/X9iaTl5vtr8HDwwBvIDy+9XKVBoYikNMCcxoJqg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1657171238; a=rsa-sha256; cv=none; b=olO21VpU8nXuhFvWZH+7k2aL2jJ7DRJJDDfSjtmfiEp+vC2MhLhx1ExlkAzjfkdE4cnhQJ ip9lAe+oXWLhRRsmlsb1+WwZLMFZ40TaqYdQqzFpXiKutsecMu/eqFfYujbTwOIKFqLAsF d8ANyg4ffH8XnbxzdJ6b51a4OvmfhXTvkbH0WSeHJBsruwY43tqAnto7xsgO4yDeoiUuTA oGYGK4ldR2+hMz79SAzncWJdmdsGgCneD6fpTUt4RIks/d6uwucffMsoFWhlHKI+0/Ux0X htUeth0CTxvGLtLFajZr9M8wtm4/zGcps+WbbF+k91uC1CkKw3Km2m1S3ef29Q== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by glebius: URL: https://cgit.FreeBSD.org/src/commit/?id=2c436d4890c7ed7f50321725dee229834114166b commit 2c436d4890c7ed7f50321725dee229834114166b Author: Gleb Smirnoff AuthorDate: 2022-07-07 05:19:08 +0000 Commit: Gleb Smirnoff CommitDate: 2022-07-07 05:19:08 +0000 sockstat(1): print out full connection graph for unix(4) sockets Kernel provides us with enough information to display all possible connections between UNIX sockets. o Store unp_conn, xu_firstref and xu_nextref in the faddr of a UNIX sock. o Build tree of file descriptors, indexed by the socket pointer. o In displaysock() print out all possible information: 1) if socket is bound, print name of this socket 2) if socket has connected to a peer with a name, print peers name 3) if socket has connected to a peer without a name, print [pid fd] 4) if a bound socket has received connections, print list of them as [pid fd] Previously, only 1) either 2) were printed. Reviewed by: tuexen Differential revision: https://reviews.freebsd.org/D35726 --- usr.bin/sockstat/sockstat.1 | 25 +++++++--- usr.bin/sockstat/sockstat.c | 119 ++++++++++++++++++++++++++++++++++---------- 2 files changed, 110 insertions(+), 34 deletions(-) diff --git a/usr.bin/sockstat/sockstat.1 b/usr.bin/sockstat/sockstat.1 index bc8fa628f725..d01b7dba08f0 100644 --- a/usr.bin/sockstat/sockstat.1 +++ b/usr.bin/sockstat/sockstat.1 @@ -27,7 +27,7 @@ .\" .\" $FreeBSD$ .\" -.Dd February 2, 2022 +.Dd June 6, 2022 .Dt SOCKSTAT 1 .Os .Sh NAME @@ -151,18 +151,27 @@ sockets. For Internet sockets, this is the address the local end of the socket is bound to (see .Xr getsockname 2 ) . +.Pp For bound .Ux -sockets, it is the socket's filename. -For other +sockets, socket's filename is printed. +For not bound .Ux -sockets, it is a right arrow followed by the endpoint's filename, or -.Dq Li ?? -if the endpoint could not be determined. +sockets, the field is empty. .It Li FOREIGN ADDRESS -(Internet sockets only) -The address the foreign end of the socket is bound to (see +For Internet sockets, this is the address the foreign end of the socket +is bound to (see .Xr getpeername 2 ) . +.Pp +For bound +.Ux +sockets a left arrow followed by the peer list is printed. +For +.Ux +sockets that went through +.Xr connect 2 +system call a right arrow followed by the peer is printed. +Peers are printed in square brackets as [PID FD]. .It Li ID The inp_gencnt if .Fl i diff --git a/usr.bin/sockstat/sockstat.c b/usr.bin/sockstat/sockstat.c index 143f4f0f7aca..d813b3adfd42 100644 --- a/usr.bin/sockstat/sockstat.c +++ b/usr.bin/sockstat/sockstat.c @@ -114,7 +114,14 @@ static int *ports; #define CHK_PORT(p) (ports[p / INT_BIT] & (1 << (p % INT_BIT))) struct addr { - struct sockaddr_storage address; + union { + struct sockaddr_storage address; + struct { /* unix(4) faddr */ + kvaddr_t conn; + kvaddr_t firstref; + kvaddr_t nextref; + }; + }; unsigned int encaps_port; int state; struct addr *next; @@ -159,8 +166,24 @@ RB_GENERATE_STATIC(pcbs_t, sock, pcb_tree, pcb_compare); static SLIST_HEAD(, sock) nosocks = SLIST_HEAD_INITIALIZER(&nosocks); -static struct xfile *xfiles; -static int nxfiles; +struct file { + RB_ENTRY(file) file_tree; + kvaddr_t xf_data; + pid_t xf_pid; + uid_t xf_uid; + int xf_fd; +}; + +static RB_HEAD(files_t, file) ftree = RB_INITIALIZER(&ftree); +static int64_t +file_compare(const struct file *a, const struct file *b) +{ + return ((int64_t)(a->xf_data/2 - b->xf_data/2)); +} +RB_GENERATE_STATIC(files_t, file, file_tree, file_compare); + +static struct file *files; +static int nfiles; static cap_channel_t *capnet; static cap_channel_t *capnetdb; @@ -862,8 +885,9 @@ gather_unix(int proto) if (xup->xu_addr.sun_family == AF_UNIX) laddr->address = *(struct sockaddr_storage *)(void *)&xup->xu_addr; - else if (xup->unp_conn != 0) - *(kvaddr_t*)&(faddr->address) = xup->unp_conn; + faddr->conn = xup->unp_conn; + faddr->firstref = xup->xu_firstref; + faddr->nextref = xup->xu_nextref; laddr->next = NULL; faddr->next = NULL; sock->laddr = laddr; @@ -878,6 +902,7 @@ out: static void getfiles(void) { + struct xfile *xfiles; size_t len, olen; olen = len = sizeof(*xfiles); @@ -893,7 +918,20 @@ getfiles(void) } if (len > 0) enforce_ksize(xfiles->xf_size, struct xfile); - nxfiles = len / sizeof(*xfiles); + nfiles = len / sizeof(*xfiles); + + if ((files = malloc(nfiles * sizeof(struct file))) == NULL) + 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]); + } + + free(xfiles); } static int @@ -1066,10 +1104,8 @@ sctp_path_state(int state) static void displaysock(struct sock *s, int pos) { - kvaddr_t p; int first, offset; struct addr *laddr, *faddr; - struct sock *s_tmp; while (pos < 30) pos += xprintf(" "); @@ -1106,26 +1142,57 @@ displaysock(struct sock *s, int pos) if ((laddr == NULL) || (faddr == NULL)) errx(1, "laddr = %p or faddr = %p is NULL", (void *)laddr, (void *)faddr); - /* server */ - if (laddr->address.ss_len > 0) { - pos += printaddr(&laddr->address); - break; - } - /* client */ - p = *(kvaddr_t*)&(faddr->address); - if (p == 0) { + if (laddr->address.ss_len == 0 && faddr->conn == 0) { pos += xprintf("(not connected)"); offset += opt_w ? 92 : 44; break; } - pos += xprintf("-> "); - s_tmp = RB_FIND(pcbs_t, &pcbs, - &(struct sock){ .pcb = p }); - if (s_tmp == NULL || s_tmp->laddr == NULL || - s_tmp->laddr->address.ss_len == 0) - pos += xprintf("??"); - else - pos += printaddr(&s_tmp->laddr->address); + /* Local bind(2) address, if any. */ + if (laddr->address.ss_len > 0) + pos += printaddr(&laddr->address); + /* Remote peer we connect(2) to, if any. */ + if (faddr->conn != 0) { + struct sock *p; + + pos += xprintf("%s-> ", + laddr->address.ss_len > 0 ? " " : ""); + p = RB_FIND(pcbs_t, &pcbs, + &(struct sock){ .pcb = faddr->conn }); + if (__predict_false(p == NULL)) { + /* XXGL: can this happen at all? */ + pos += xprintf("??"); + } else if (p->laddr->address.ss_len == 0) { + struct file *f; + + f = RB_FIND(files_t, &ftree, + &(struct file){ .xf_data = + p->socket }); + pos += xprintf("[%lu %d]", + (u_long)f->xf_pid, f->xf_fd); + } else + pos += printaddr(&p->laddr->address); + } + /* Remote peer(s) connect(2)ed to us, if any. */ + if (faddr->firstref != 0) { + struct sock *p; + struct file *f; + kvaddr_t ref = faddr->firstref; + bool fref = true; + + pos += xprintf(" <- "); + + while ((p = RB_FIND(pcbs_t, &pcbs, + &(struct sock){ .pcb = ref })) != 0) { + f = RB_FIND(files_t, &ftree, + &(struct file){ .xf_data = + p->socket }); + pos += xprintf("%s[%lu %d]", + fref ? "" : ",", + (u_long)f->xf_pid, f->xf_fd); + ref = p->faddr->nextref; + fref = false; + } + } offset += opt_w ? 92 : 44; break; default: @@ -1228,7 +1295,7 @@ static void display(void) { struct passwd *pwd; - struct xfile *xf; + struct file *xf; struct sock *s; int n, pos; @@ -1253,7 +1320,7 @@ display(void) printf("\n"); } cap_setpassent(cappwd, 1); - for (xf = xfiles, n = 0; n < nxfiles; ++n, ++xf) { + for (xf = files, n = 0; n < nfiles; ++n, ++xf) { if (xf->xf_data == 0) continue; if (opt_j >= 0 && opt_j != getprocjid(xf->xf_pid))