Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 12 Mar 2026 16:40:51 +0000
From:      Gleb Smirnoff <glebius@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 985ac741384e - main - systat: remove kvm(3) support for -netstat mode
Message-ID:  <69b2ec93.44d2a.2c71c859@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch main has been updated by glebius:

URL: https://cgit.FreeBSD.org/src/commit/?id=985ac741384ec65463669edee5e1d90dee4c895a

commit 985ac741384ec65463669edee5e1d90dee4c895a
Author:     Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2026-03-12 04:16:44 +0000
Commit:     Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2026-03-12 16:37:52 +0000

    systat: remove kvm(3) support for -netstat mode
    
    The kvm(3) mode was actually non-functional since FreeBSD 8 for kernels
    with VIMAGE, since FreeBSD 12 for the GENERIC kernel and since FreeBSD 14
    for all kernels.  The reason for that is that systat(1) tried to lookup
    symbol "tcb" to check if kvm(3) is working.  The symbol no longer exist in
    the kernel.
    
    A side effect was that systat(1) lost true kvm(3) support for all other
    modes, e.g. -swap or -pigs.  The tool was still working, but libkvm was
    just a shim to sysctl(3) API.
    
    So, contrary to what the header line says, this change actually restores
    the kvm(3) support for other modes.  Now we read the "allproc" symbol.
    
    This was the last tool that abused _WANT_INPCB.
---
 usr.bin/systat/extern.h  |   2 -
 usr.bin/systat/main.c    |   5 +-
 usr.bin/systat/netstat.c | 132 ++++-------------------------------------------
 usr.bin/systat/systat.h  |  11 ----
 4 files changed, 14 insertions(+), 136 deletions(-)

diff --git a/usr.bin/systat/extern.h b/usr.bin/systat/extern.h
index 8d19aec024b4..4d9f686dcc65 100644
--- a/usr.bin/systat/extern.h
+++ b/usr.bin/systat/extern.h
@@ -69,8 +69,6 @@ extern int			num_selected;
 extern int			num_selections;
 extern long			select_generation;
 
-extern struct nlist		namelist[];
-
 int	 checkhost(struct in_conninfo *);
 int	 checkport(struct in_conninfo *);
 void	 closeicmp(WINDOW *);
diff --git a/usr.bin/systat/main.c b/usr.bin/systat/main.c
index dbb82ebbb1c0..3582447281b6 100644
--- a/usr.bin/systat/main.c
+++ b/usr.bin/systat/main.c
@@ -64,7 +64,6 @@ char    *namp;
 char    hostname[MAXHOSTNAMELEN];
 WINDOW  *wnd;
 int     CMDLINE;
-int     use_kvm = 1;
 
 static	WINDOW *wload;			/* one line window for load average */
 
@@ -166,6 +165,9 @@ main(int argc, char **argv)
 	}
 	kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
 	if (kd != NULL) {
+		struct nlist namelist[] = { { .n_name = "allproc" },
+		    { .n_name = NULL } };
+
 		/*
 		 * Try to actually read something, we may be in a jail, and
 		 * have /dev/null opened as /dev/mem.
@@ -182,7 +184,6 @@ main(int argc, char **argv)
 		 * Maybe we are lacking permissions? Retry, this time with bogus
 		 * devices. We can now use sysctl only.
 		 */
-		use_kvm = 0;
 		kd = kvm_openfiles(_PATH_DEVNULL, _PATH_DEVNULL, _PATH_DEVNULL,
 		    O_RDONLY, errbuf);
 		if (kd == NULL) {
diff --git a/usr.bin/systat/netstat.c b/usr.bin/systat/netstat.c
index d9a0266aaea4..31838fc207d8 100644
--- a/usr.bin/systat/netstat.c
+++ b/usr.bin/systat/netstat.c
@@ -38,7 +38,6 @@
 #include <sys/queue.h>
 #include <sys/socket.h>
 #include <sys/callout.h>
-#define	_WANT_SOCKET
 #include <sys/socketvar.h>
 #include <sys/protosw.h>
 
@@ -50,7 +49,6 @@
 #ifdef INET6
 #include <netinet/ip6.h>
 #endif
-#define	_WANT_INPCB
 #include <netinet/in_pcb.h>
 #include <netinet/ip_icmp.h>
 #include <netinet/icmp_var.h>
@@ -60,7 +58,6 @@
 #include <netinet/tcp_seq.h>
 #define TCPSTATES
 #include <netinet/tcp_fsm.h>
-#define	_WANT_TCPCB
 #include <netinet/tcp_var.h>
 #include <netinet/udp.h>
 #include <netinet/udp_var.h>
@@ -74,11 +71,7 @@
 #include "systat.h"
 #include "extern.h"
 
-static struct netinfo *enter(struct in_conninfo *, uint8_t, int, const char *);
-static void enter_kvm(struct inpcb *, struct socket *, int, const char *);
-static void enter_sysctl(struct xinpcb *, struct xsocket *, int, const char *);
-static void fetchnetstat_kvm(void);
-static void fetchnetstat_sysctl(void);
+static void enter(struct xinpcb *, struct xsocket *so, int, const char *);
 static char *inetname(struct sockaddr *);
 static void inetprint(struct sockaddr *, const char *);
 
@@ -138,16 +131,6 @@ static const char *miblist[] = {
 	"net.inet.udp.pcblist"
 };
 
-static char tcb[] = "tcb", udb[] = "udb";
-
-struct nlist namelist[] = {
-#define	X_TCB	0
-	{ .n_name = tcb },
-#define	X_UDB	1
-	{ .n_name = udb },
-	{ .n_name = NULL },
-};
-
 int
 initnetstat(void)
 {
@@ -157,77 +140,6 @@ initnetstat(void)
 
 void
 fetchnetstat(void)
-{
-	if (use_kvm)
-		fetchnetstat_kvm();
-	else
-		fetchnetstat_sysctl();
-}
-
-static void
-fetchnetstat_kvm(void)
-{
-	struct netinfo *p;
-	struct inpcbhead head;
-	struct socket sockb;
-	struct tcpcb tcpcb;
-	struct inpcb *inpcb;
-	void *off;
-	int istcp;
-
-	if (namelist[X_TCB].n_value == 0)
-		return;
-	TAILQ_FOREACH(p, &netcb, chain)
-		p->ni_seen = 0;
-	if (protos&TCP) {
-		off = NPTR(X_TCB);
-		istcp = 1;
-	}
-	else if (protos&UDP) {
-		off = NPTR(X_UDB);
-		istcp = 0;
-	}
-	else {
-		error("No protocols to display");
-		return;
-	}
-again:
-	KREAD(off, &head, sizeof (struct inpcbhead));
-	LIST_FOREACH(inpcb, &head, inp_list) {
-		KREAD(inpcb, &tcpcb, istcp ? sizeof(tcpcb) : sizeof(inpcb));
-		inpcb = (struct inpcb *)&tcpcb;
-		if (!aflag) {
-			if (inpcb->inp_vflag & INP_IPV4) {
-				if (inpcb->inp_laddr.s_addr == INADDR_ANY)
-					continue;
-			}
-#ifdef INET6
-			else if (inpcb->inp_vflag & INP_IPV6) {
-				if (memcmp(&inpcb->in6p_laddr,
-				    &in6addr_any, sizeof(in6addr_any)) == 0)
-					continue;
-			}
-#endif
-		}
-		if (nhosts && !checkhost(&inpcb->inp_inc))
-			continue;
-		if (nports && !checkport(&inpcb->inp_inc))
-			continue;
-		if (istcp) {
-			KREAD(inpcb->inp_socket, &sockb, sizeof (sockb));
-			enter_kvm(inpcb, &sockb, tcpcb.t_state, "tcp");
-		} else
-			enter_kvm(inpcb, &sockb, 0, "udp");
-	}
-	if (istcp && (protos&UDP)) {
-		istcp = 0;
-		off = NPTR(X_UDB);
-		goto again;
-	}
-}
-
-static void
-fetchnetstat_sysctl(void)
 {
 	struct netinfo *p;
 	int idx;
@@ -303,41 +215,20 @@ fetchnetstat_sysctl(void)
 			if (nports && !checkport(&xip->inp_inc))
 				continue;
 			if (idx == 0)
-				enter_sysctl(xip, &xip->xi_socket,
-				    xtp->t_state, "tcp");
+				enter(xip, &xip->xi_socket, xtp->t_state,
+				    "tcp");
 			else
-				enter_sysctl(xip, &xip->xi_socket, 0, "udp");
+				enter(xip, &xip->xi_socket, 0, "udp");
 		}
 		free(inpg);
 	}
 }
 
 static void
-enter_kvm(struct inpcb *inp, struct socket *so, int state, const char *proto)
-{
-	struct netinfo *p;
-
-	if ((p = enter(&inp->inp_inc, inp->inp_vflag, state, proto)) != NULL) {
-		p->ni_rcvcc = so->so_rcv.sb_ccc;
-		p->ni_sndcc = so->so_snd.sb_ccc;
-	}
-}
-
-static void
-enter_sysctl(struct xinpcb *xip, struct xsocket *so, int state,
-    const char *proto)
-{
-	struct netinfo *p;
-
-	if ((p = enter(&xip->inp_inc, xip->inp_vflag, state, proto)) != NULL) {
-		p->ni_rcvcc = so->so_rcv.sb_cc;
-		p->ni_sndcc = so->so_snd.sb_cc;
-	}
-}
-
-static struct netinfo *
-enter(struct in_conninfo *inc, uint8_t vflag, int state, const char *proto)
+enter(struct xinpcb *xip, struct xsocket *so, int state, const char *proto)
 {
+	struct in_conninfo *inc = &xip->inp_inc;
+	uint8_t vflag = xip->inp_vflag;
 	struct netinfo *p;
 	struct sockaddr_storage lsa, fsa;
 	struct sockaddr_in *sa4;
@@ -378,7 +269,7 @@ enter(struct in_conninfo *inc, uint8_t vflag, int state, const char *proto)
 	}
 #endif
 	else
-		return NULL;
+		return;
 
 	/*
 	 * Only take exact matches, any sockets with
@@ -400,7 +291,7 @@ enter(struct in_conninfo *inc, uint8_t vflag, int state, const char *proto)
 	if (p == NULL) {
 		if ((p = malloc(sizeof(*p))) == NULL) {
 			error("Out of memory");
-			return NULL;
+			return;
 		}
 		TAILQ_INSERT_HEAD(&netcb, p, chain);
 		p->ni_line = -1;
@@ -411,7 +302,8 @@ enter(struct in_conninfo *inc, uint8_t vflag, int state, const char *proto)
 	}
 	p->ni_state = state;
 	p->ni_seen = 1;
-	return p;
+	p->ni_rcvcc = so->so_rcv.sb_cc;
+	p->ni_sndcc = so->so_snd.sb_cc;
 }
 
 /* column locations */
@@ -425,8 +317,6 @@ enter(struct in_conninfo *inc, uint8_t vflag, int state, const char *proto)
 void
 labelnetstat(void)
 {
-	if (use_kvm && namelist[X_TCB].n_type == 0)
-		return;
 	wmove(wnd, 0, 0); wclrtobot(wnd);
 	mvwaddstr(wnd, 0, LADDR, "Local Address");
 	mvwaddstr(wnd, 0, FADDR, "Foreign Address");
diff --git a/usr.bin/systat/systat.h b/usr.bin/systat/systat.h
index 55a21a04998a..371fdf57f6fc 100644
--- a/usr.bin/systat/systat.h
+++ b/usr.bin/systat/systat.h
@@ -45,13 +45,6 @@ struct  cmdtab {
 	char	c_flags;		/* see below */
 };
 
-/*
- * If we are started with privileges, use a kmem interface for netstat handling,
- * otherwise use sysctl.
- * In case of many open sockets, the sysctl handling might become slow.
- */
-extern int use_kvm;
-
 #define	CF_INIT		0x1		/* been initialized */
 #define	CF_LOADAV	0x2		/* display w/ load average */
 #define	CF_ZFSARC	0x4		/* display w/ ZFS cache usage */
@@ -62,10 +55,6 @@ extern int use_kvm;
 #define	MAINWIN_ROW	3		/* top row for the main/lower window */
 
 #define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var))
-#define KREAD(addr, buf, len)  kvm_ckread((addr), (buf), (len))
-#define NVAL(indx)  namelist[(indx)].n_value
-#define NPTR(indx)  (void *)NVAL((indx))
-#define NREAD(indx, buf, len) kvm_ckread(NPTR((indx)), (buf), (len))
 
 extern void putint(int, int, int, int);
 extern void putfloat(double, int, int, int, int, int);


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69b2ec93.44d2a.2c71c859>