summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2015-03-12 01:03:01 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2015-03-12 01:03:01 +0000
commit6ffe49baa29b2696710ac6ef38765cd7067fdb00 (patch)
tree1adc68de5709641af0f065ef7d9240ef8ae05aec
parent326d9eabceb5a47747e1fbd7f53c971c26eac012 (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/Makefile4
-rw-r--r--usr.bin/systat/main.c4
-rw-r--r--usr.bin/systat/netstat.c321
-rw-r--r--usr.bin/systat/systat.16
-rw-r--r--usr.bin/systat/systat.h5
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