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>
