diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2015-03-12 01:03:01 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2015-03-12 01:03:01 +0000 |
commit | 6ffe49baa29b2696710ac6ef38765cd7067fdb00 (patch) | |
tree | 1adc68de5709641af0f065ef7d9240ef8ae05aec | |
parent | 326d9eabceb5a47747e1fbd7f53c971c26eac012 (diff) |
Switch the netstat view of systat to use the same kvm_getfiles()
function similar to netstat(1). The output still shows the same
info but may be a bit differently sorted. Also it will now show
connections that are not UDP or TCP. This was the last bit of
systat that needed kvm access and so now systat no longer needs
to be setgid kmem.
With this commit OpenBSD is officially setgid kmem free and an
almost 10 year journey finally comes to an end.
OK deraadt@
-rw-r--r-- | usr.bin/systat/Makefile | 4 | ||||
-rw-r--r-- | usr.bin/systat/main.c | 4 | ||||
-rw-r--r-- | usr.bin/systat/netstat.c | 321 | ||||
-rw-r--r-- | usr.bin/systat/systat.1 | 6 | ||||
-rw-r--r-- | usr.bin/systat/systat.h | 5 |
5 files changed, 183 insertions, 157 deletions
diff --git a/usr.bin/systat/Makefile b/usr.bin/systat/Makefile index 83d233abfbe..3cd881775d6 100644 --- a/usr.bin/systat/Makefile +++ b/usr.bin/systat/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.26 2014/07/16 20:06:27 okan Exp $ +# $OpenBSD: Makefile,v 1.27 2015/03/12 01:03:00 claudio Exp $ PROG= systat @@ -13,7 +13,5 @@ SRCS= dkstats.c engine.c if.c inetname.c iostat.c main.c mbufs.c netstat.c \ DPADD= ${LIBCURSES} ${LIBM} ${LIBKVM} LDADD= -lcurses -lm -lkvm -BINGRP= kmem -BINMODE=2555 .include <bsd.prog.mk> diff --git a/usr.bin/systat/main.c b/usr.bin/systat/main.c index 9a7ff7194a1..c61954ae643 100644 --- a/usr.bin/systat/main.c +++ b/usr.bin/systat/main.c @@ -1,4 +1,4 @@ -/* $Id: main.c,v 1.61 2015/01/16 00:03:37 deraadt Exp $ */ +/* $Id: main.c,v 1.62 2015/03/12 01:03:00 claudio Exp $ */ /* * Copyright (c) 2001, 2007 Can Erkin Acar * Copyright (c) 2001 Daniel Hartmeier @@ -397,7 +397,7 @@ main(int argc, char *argv[]) warn("No utmp"); } - kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf); + kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf); gid = getgid(); if (setresgid(gid, gid, gid) == -1) diff --git a/usr.bin/systat/netstat.c b/usr.bin/systat/netstat.c index 6c418ee26ea..1e13de5feec 100644 --- a/usr.bin/systat/netstat.c +++ b/usr.bin/systat/netstat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: netstat.c,v 1.44 2015/01/20 18:26:57 deraadt Exp $ */ +/* $OpenBSD: netstat.c,v 1.45 2015/03/12 01:03:00 claudio Exp $ */ /* $NetBSD: netstat.c,v 1.3 1995/06/18 23:53:07 cgd Exp $ */ /*- @@ -34,30 +34,23 @@ * netstat */ -#include <sys/signal.h> +#include <kvm.h> +#include <sys/types.h> +#include <sys/sysctl.h> #include <sys/socket.h> -#include <sys/socketvar.h> -#include <sys/mbuf.h> -#include <sys/protosw.h> +#define _KERNEL +#include <sys/file.h> +#undef _KERNEL #include <netinet/in.h> -#include <net/route.h> -#include <netinet/ip.h> -#include <netinet/in_pcb.h> -#include <netinet/ip_icmp.h> -#include <netinet/icmp_var.h> -#include <netinet/ip_var.h> #include <netinet/tcp.h> #include <netinet/tcp_seq.h> #define TCPSTATES #include <netinet/tcp_fsm.h> -#include <netinet/tcp_timer.h> -#include <netinet/tcp_var.h> -#include <netinet/udp.h> -#include <netinet/udp_var.h> #include <arpa/inet.h> #include <netdb.h> +#include <signal.h> #include <stdlib.h> #include <string.h> #include <err.h> @@ -66,6 +59,10 @@ #include "systat.h" #include "engine.h" +#define TCP 0x1 +#define UDP 0x2 +#define OTHER 0x4 + struct netinfo { union { struct in_addr nif_laddr; /* local address */ @@ -75,13 +72,14 @@ struct netinfo { struct in_addr nif_faddr; /* foreign address */ struct in6_addr nif_faddr6; /* foreign address */ } f; - char *nif_proto; /* protocol */ long nif_rcvcc; /* rcv buffer character count */ long nif_sndcc; /* snd buffer character count */ short nif_lport; /* local port */ short nif_fport; /* foreign port */ short nif_state; /* tcp state */ short nif_family; + short nif_proto; /* protocol */ + short nif_ipproto; }; #define nif_laddr l.nif_laddr @@ -89,7 +87,8 @@ struct netinfo { #define nif_faddr f.nif_faddr #define nif_faddr6 f.nif_faddr6 -static void enter(struct inpcb *, struct socket *, int, char *); +static void enter(struct kinfo_file *); +static int kf_comp(const void *, const void *); static void inetprint(struct in_addr *, int, char *, field_def *); static void inet6print(struct in6_addr *, int, char *, field_def *); static void shownetstat(struct netinfo *p); @@ -103,16 +102,8 @@ int ns_keyboard_callback(int); static int aflag = 0; -static struct nlist namelist[] = { -#define X_TCBTABLE 0 /* no sysctl */ - { "_tcbtable" }, -#define X_UDBTABLE 1 /* no sysctl */ - { "_udbtable" }, - { "" }, -}; #define ADD_ALLOC 1000 - int protos; struct netinfo *netinfos = NULL; @@ -175,33 +166,84 @@ next_ns(void) } static void -enter(struct inpcb *inp, struct socket *so, int state, char *proto) +enter(struct kinfo_file *kf) { +#define s6_addr32 __u6_addr.__u6_addr32 struct netinfo *p; + /* first filter out unwanted sockets */ + if (kf->so_family != AF_INET && kf->so_family != AF_INET6) + return; + + switch (kf->so_protocol) { + case IPPROTO_TCP: + if ((protos & TCP) == 0) + return; + break; + case IPPROTO_UDP: + if ((protos & UDP) == 0) + return; + break; + default: + if ((protos & OTHER) == 0) + return; + break; + } + + if (!aflag) { + struct in6_addr faddr6; + + switch (kf->so_family) { + case AF_INET: + if (kf->inp_faddru[0] == INADDR_ANY) + return; + break; + case AF_INET6: + faddr6.s6_addr32[0] = kf->inp_faddru[0]; + faddr6.s6_addr32[1] = kf->inp_faddru[1]; + faddr6.s6_addr32[2] = kf->inp_faddru[2]; + faddr6.s6_addr32[3] = kf->inp_faddru[3]; + if (IN6_IS_ADDR_UNSPECIFIED(&faddr6)) + return; + break; + } + } + + /* finally enter the socket to the table */ p = next_ns(); if (p == NULL) { error("Out of Memory!"); return; } - p->nif_lport = inp->inp_lport; - p->nif_fport = inp->inp_fport; - p->nif_proto = proto; - - if (inp->inp_flags & INP_IPV6) { - p->nif_laddr6 = inp->inp_laddr6; - p->nif_faddr6 = inp->inp_faddr6; - p->nif_family = AF_INET6; - } else { - p->nif_laddr = inp->inp_laddr; - p->nif_faddr = inp->inp_faddr; + p->nif_lport = kf->inp_lport; + p->nif_fport = kf->inp_fport; + p->nif_proto = kf->so_protocol; + p->nif_ipproto = kf->inp_proto; + + switch (kf->so_family) { + case AF_INET: p->nif_family = AF_INET; + p->nif_laddr.s_addr = kf->inp_laddru[0]; + p->nif_faddr.s_addr = kf->inp_faddru[0]; + break; + case AF_INET6: + p->nif_family = AF_INET6; + p->nif_laddr6.s6_addr32[0] = kf->inp_laddru[0]; + p->nif_laddr6.s6_addr32[1] = kf->inp_laddru[1]; + p->nif_laddr6.s6_addr32[2] = kf->inp_laddru[2]; + p->nif_laddr6.s6_addr32[3] = kf->inp_laddru[3]; + p->nif_faddr6.s6_addr32[0] = kf->inp_faddru[0]; + p->nif_faddr6.s6_addr32[1] = kf->inp_faddru[1]; + p->nif_faddr6.s6_addr32[2] = kf->inp_faddru[2]; + p->nif_faddr6.s6_addr32[3] = kf->inp_faddru[3]; + break; } - p->nif_rcvcc = so->so_rcv.sb_cc; - p->nif_sndcc = so->so_snd.sb_cc; - p->nif_state = state; + p->nif_rcvcc = kf->so_rcv_cc; + p->nif_sndcc = kf->so_snd_cc; + p->nif_state = kf->t_state; +#undef s6_addr32 } @@ -210,85 +252,78 @@ enter(struct inpcb *inp, struct socket *so, int state, char *proto) int select_ns(void) { - if (kd == NULL) { - num_disp = 1; - return (0); - } num_disp = num_ns; return (0); } +static int type_map[] = { -1, 2, 3, 1, 4, 5 }; + +static int +kf_comp(const void *a, const void *b) +{ + const struct kinfo_file *ka = a, *kb = b; + + if (ka->so_family != kb->so_family) { + /* AF_INET < AF_INET6 < AF_LOCAL */ + if (ka->so_family == AF_INET) + return (-1); + if (ka->so_family == AF_LOCAL) + return (1); + if (kb->so_family == AF_LOCAL) + return (-1); + return (1); + } + if (ka->so_family == AF_LOCAL) { + if (type_map[ka->so_type] < type_map[kb->so_type]) + return (-1); + if (type_map[ka->so_type] > type_map[kb->so_type]) + return (1); + } else if (ka->so_family == AF_INET || ka->so_family == AF_INET6) { + if (ka->so_protocol < kb->so_protocol) + return (-1); + if (ka->so_protocol > kb->so_protocol) + return (1); + if (ka->so_type == SOCK_DGRAM || ka->so_type == SOCK_STREAM) { + /* order sockets by remote port desc */ + if (ka->inp_fport > kb->inp_fport) + return (-1); + if (ka->inp_fport < kb->inp_fport) + return (1); + } else if (ka->so_type == SOCK_RAW) { + if (ka->inp_proto > kb->inp_proto) + return (-1); + if (ka->inp_proto < kb->inp_proto) + return (1); + } + } + return (0); +} + + int read_ns(void) { - struct inpcbtable pcbtable; - struct inpcb *next, *prev; - struct inpcb inpcb, prevpcb; - struct socket sockb; - struct tcpcb tcpcb; - void *off; - int istcp; + struct kinfo_file *kf; + int i, fcnt; if (kd == NULL) { + error("Failed to initialize KVM!"); return (0); } - - num_ns = 0; - - if (namelist[X_TCBTABLE].n_value == 0) - return 0; - - if (protos & TCP) { - off = NPTR(X_TCBTABLE); - istcp = 1; - } else if (protos & UDP) { - off = NPTR(X_UDBTABLE); - istcp = 0; - } else { - error("No protocols to display"); - return 0; + kf = kvm_getfiles(kd, KERN_FILE_BYFILE, DTYPE_SOCKET, + sizeof(*kf), &fcnt); + if (kf == NULL) { + error("Out of Memory!"); + return (0); } -again: - KREAD(off, &pcbtable, sizeof (struct inpcbtable)); + /* sort sockets by AF, proto and type */ + qsort(kf, fcnt, sizeof(*kf), kf_comp); - prev = NULL; - next = TAILQ_FIRST(&pcbtable.inpt_queue); + num_ns = 0; - while (next != NULL) { - KREAD(next, &inpcb, sizeof (inpcb)); - if (prev != NULL) { - KREAD(prev, &prevpcb, sizeof (prevpcb)); - if (TAILQ_NEXT(&prevpcb, inp_queue) != next) { - error("Kernel state in transition"); - return 0; - } - } - prev = next; - next = TAILQ_NEXT(&inpcb, inp_queue); - - if (!aflag) { - if (!(inpcb.inp_flags & INP_IPV6) && - inet_lnaof(inpcb.inp_faddr) == INADDR_ANY) - continue; - if ((inpcb.inp_flags & INP_IPV6) && - IN6_IS_ADDR_UNSPECIFIED(&inpcb.inp_faddr6)) - continue; - } - KREAD(inpcb.inp_socket, &sockb, sizeof (sockb)); - if (istcp) { - KREAD(inpcb.inp_ppcb, &tcpcb, sizeof (tcpcb)); - if (!aflag && tcpcb.t_state <= TCPS_LISTEN) - continue; - enter(&inpcb, &sockb, tcpcb.t_state, "tcp"); - } else - enter(&inpcb, &sockb, 0, "udp"); - } - if (istcp && (protos & UDP)) { - istcp = 0; - off = NPTR(X_UDBTABLE); - goto again; - } + for (i = 0; i < fcnt; i++) + enter(&kf[i]); num_disp = num_ns; return 0; @@ -299,13 +334,6 @@ print_ns(void) { int n, count = 0; - if (kd == NULL) { - print_fld_str(FLD_NS_LOCAL, "Failed to initialize KVM!"); - print_fld_str(FLD_NS_FOREIGN, "Failed to initialize KVM!"); - end_line(); - return; - } - for (n = dispstart; n < num_disp; n++) { shownetstat(netinfos + n); count++; @@ -319,21 +347,8 @@ int initnetstat(void) { field_view *v; - int ret; - - if (kd) { - if ((ret = kvm_nlist(kd, namelist)) == -1) - errx(1, "%s", kvm_geterr(kd)); - else if (ret) - nlisterr(namelist); - - if (namelist[X_TCBTABLE].n_value == 0) { - error("No symbols in namelist"); - return(0); - } - } - protos = TCP|UDP; + protos = TCP|UDP|OTHER; for (v = views_ns; v->name != NULL; v++) add_view(v); @@ -343,32 +358,56 @@ initnetstat(void) static void shownetstat(struct netinfo *p) { + char *proto = NULL; + + switch (p->nif_proto) { + case IPPROTO_TCP: + proto = "tcp"; + break; + case IPPROTO_UDP: + proto = "udp"; + break; + } + switch (p->nif_family) { case AF_INET: inetprint(&p->nif_laddr, p->nif_lport, - p->nif_proto, FLD_NS_LOCAL); + proto, FLD_NS_LOCAL); inetprint(&p->nif_faddr, p->nif_fport, - p->nif_proto, FLD_NS_FOREIGN); + proto, FLD_NS_FOREIGN); break; case AF_INET6: inet6print(&p->nif_laddr6, p->nif_lport, - p->nif_proto, FLD_NS_LOCAL); + proto, FLD_NS_LOCAL); inet6print(&p->nif_faddr6, p->nif_fport, - p->nif_proto, FLD_NS_FOREIGN); + proto, FLD_NS_FOREIGN); break; } tb_start(); - tbprintf("%s", p->nif_proto); - if (p->nif_family == AF_INET6) - tbprintf("6"); + switch (p->nif_proto) { + case IPPROTO_TCP: + case IPPROTO_UDP: + tbprintf(proto); + if (p->nif_family == AF_INET6) + tbprintf("6"); + break; + case IPPROTO_DIVERT: + tbprintf("divert"); + if (p->nif_family == AF_INET6) + tbprintf("6"); + break; + default: + tbprintf("%d", p->nif_ipproto); + break; + } print_fld_tb(FLD_NS_PROTO); print_fld_size(FLD_NS_RECV_Q, p->nif_rcvcc); print_fld_size(FLD_NS_SEND_Q, p->nif_sndcc); - if (streq(p->nif_proto, "tcp")) { + if (p->nif_proto == IPPROTO_TCP) { if (p->nif_state < 0 || p->nif_state >= TCP_NSTATES) print_fld_uint(FLD_NS_STATE, p->nif_state); else @@ -418,18 +457,6 @@ inet6print(struct in6_addr *in6, int port, char *proto, field_def *fld) } int -kvm_ckread(void *a, void *b, size_t l) -{ - if (kvm_read(kd, (u_long)a, b, l) != l) { - if (verbose) - error("error reading kmem\n"); - return (0); - } else - return (1); -} - - -int ns_keyboard_callback(int ch) { switch (ch) { @@ -441,6 +468,10 @@ ns_keyboard_callback(int ch) nflag = !nflag; gotsig_alarm = 1; break; + case 'o': + protos ^= OTHER; + gotsig_alarm = 1; + break; case 'r': aflag = 0; nflag = 1; diff --git a/usr.bin/systat/systat.1 b/usr.bin/systat/systat.1 index 3d287fb5379..c7f8d78bdf8 100644 --- a/usr.bin/systat/systat.1 +++ b/usr.bin/systat/systat.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: systat.1,v 1.100 2015/02/28 21:51:57 bentley Exp $ +.\" $OpenBSD: systat.1,v 1.101 2015/03/12 01:03:00 claudio Exp $ .\" $NetBSD: systat.1,v 1.6 1996/05/10 23:16:39 thorpej Exp $ .\" .\" Copyright (c) 1985, 1990, 1993 @@ -30,7 +30,7 @@ .\" .\" @(#)systat.1 8.2 (Berkeley) 12/30/93 .\" -.Dd $Mdocdate: February 28 2015 $ +.Dd $Mdocdate: March 12 2015 $ .Dt SYSTAT 1 .Os .Sh NAME @@ -338,7 +338,7 @@ Reset matching mechanisms to the default. .\"If an argument is supplied to .\".Cm show , .\"then only the requested information will be displayed. -.It Cm tcp | udp +.It Cm tcp | udp | other Display only network connections using the indicated protocol. .El .It Ic nfsclient diff --git a/usr.bin/systat/systat.h b/usr.bin/systat/systat.h index 372c18536cd..22297573b1f 100644 --- a/usr.bin/systat/systat.h +++ b/usr.bin/systat/systat.h @@ -1,4 +1,4 @@ -/* $OpenBSD: systat.h,v 1.20 2014/07/10 14:39:18 deraadt Exp $ */ +/* $OpenBSD: systat.h,v 1.21 2015/03/12 01:03:00 claudio Exp $ */ /* $NetBSD: systat.h,v 1.2 1995/01/20 08:52:14 jtc Exp $ */ /*- @@ -44,9 +44,6 @@ #define CF_INIT 0x1 /* been initialized */ #define CF_LOADAV 0x2 /* display w/ load average */ -#define TCP 0x1 -#define UDP 0x2 - #define FIELD_ADDR(struct, x) (&struct[x]) #define KREAD(addr, buf, len) kvm_ckread((addr), (buf), (len)) #define NVAL(indx) namelist[(indx)].n_value |