summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2007-07-16 17:15:55 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2007-07-16 17:15:55 +0000
commitfeda1a4372d5e340da97042375dfb783dea52eda (patch)
tree165174828db97bceab2299030940226f1b6620cf
parent72d73315396520151f86f8c6cb42b09d5a1073e5 (diff)
Notes
-rw-r--r--usr.bin/netstat/atalk.c6
-rw-r--r--usr.bin/netstat/bpf.c1
-rw-r--r--usr.bin/netstat/if.c22
-rw-r--r--usr.bin/netstat/inet.c403
-rw-r--r--usr.bin/netstat/inet6.c94
-rw-r--r--usr.bin/netstat/ipsec.c10
-rw-r--r--usr.bin/netstat/ipx.c8
-rw-r--r--usr.bin/netstat/main.c217
-rw-r--r--usr.bin/netstat/mbuf.c4
-rw-r--r--usr.bin/netstat/mcast.c1
-rw-r--r--usr.bin/netstat/mroute.c43
-rw-r--r--usr.bin/netstat/mroute6.c42
-rw-r--r--usr.bin/netstat/netgraph.c7
-rw-r--r--usr.bin/netstat/netstat.h78
-rw-r--r--usr.bin/netstat/pfkey.c4
-rw-r--r--usr.bin/netstat/route.c1
-rw-r--r--usr.bin/netstat/sctp.c23
-rw-r--r--usr.bin/netstat/unix.c152
18 files changed, 750 insertions, 366 deletions
diff --git a/usr.bin/netstat/atalk.c b/usr.bin/netstat/atalk.c
index 8353e1399d423..7c19c561d5f4d 100644
--- a/usr.bin/netstat/atalk.c
+++ b/usr.bin/netstat/atalk.c
@@ -217,7 +217,8 @@ atalk_print2(struct sockaddr *sa, struct sockaddr *mask, int what)
}
void
-atalkprotopr(u_long off __unused, const char *name, int af1 __unused)
+atalkprotopr(u_long off __unused, const char *name, int af1 __unused,
+ int proto __unused)
{
struct ddpcb *this, *next;
@@ -266,7 +267,8 @@ atalkprotopr(u_long off __unused, const char *name, int af1 __unused)
* Dump DDP statistics structure.
*/
void
-ddp_stats(u_long off __unused, const char *name, int af1 __unused)
+ddp_stats(u_long off __unused, const char *name, int af1 __unused,
+ int proto __unused)
{
struct ddpstat ddpstat;
diff --git a/usr.bin/netstat/bpf.c b/usr.bin/netstat/bpf.c
index 90fa623d10604..73cc018b816fa 100644
--- a/usr.bin/netstat/bpf.c
+++ b/usr.bin/netstat/bpf.c
@@ -28,6 +28,7 @@
#include <sys/types.h>
#include <sys/protosw.h>
#include <sys/socket.h>
+#include <sys/socketvar.h>
#include <sys/sysctl.h>
#include <sys/param.h>
#include <sys/user.h>
diff --git a/usr.bin/netstat/if.c b/usr.bin/netstat/if.c
index dc280eb97aae9..9acd37ca2db1a 100644
--- a/usr.bin/netstat/if.c
+++ b/usr.bin/netstat/if.c
@@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/protosw.h>
#include <sys/socket.h>
+#include <sys/socketvar.h>
#include <sys/sysctl.h>
#include <sys/time.h>
@@ -85,19 +86,22 @@ static char ntop_buf[INET6_ADDRSTRLEN]; /* for inet_ntop() */
* Dump pfsync statistics structure.
*/
void
-pfsync_stats(u_long off __unused, const char *name, int af1 __unused)
+pfsync_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
{
struct pfsyncstats pfsyncstat, zerostat;
size_t len = sizeof(struct pfsyncstats);
- if (zflag)
- memset(&zerostat, 0, len);
- if (sysctlbyname("net.inet.pfsync.stats", &pfsyncstat, &len,
- zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
- if (errno != ENOENT)
- warn("sysctl: net.inet.pfsync.stats");
- return;
- }
+ if (live) {
+ if (zflag)
+ memset(&zerostat, 0, len);
+ if (sysctlbyname("net.inet.pfsync.stats", &pfsyncstat, &len,
+ zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+ if (errno != ENOENT)
+ warn("sysctl: net.inet.pfsync.stats");
+ return;
+ }
+ } else
+ kread(off, &pfsyncstat, len);
printf("%s:\n", name);
diff --git a/usr.bin/netstat/inet.c b/usr.bin/netstat/inet.c
index 1be7b874b58ff..eee2fefec066f 100644
--- a/usr.bin/netstat/inet.c
+++ b/usr.bin/netstat/inet.c
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/queue.h>
+#include <sys/domain.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/sysctl.h>
@@ -90,6 +91,208 @@ void inetprint (struct in_addr *, int, const char *, int);
static int udp_done, tcp_done;
#endif /* INET6 */
+static int
+pcblist_sysctl(int proto, char **bufp, int istcp)
+{
+ const char *mibvar;
+ char *buf;
+ size_t len;
+
+ switch (proto) {
+ case IPPROTO_TCP:
+ mibvar = "net.inet.tcp.pcblist";
+ break;
+ case IPPROTO_UDP:
+ mibvar = "net.inet.udp.pcblist";
+ break;
+ case IPPROTO_DIVERT:
+ mibvar = "net.inet.divert.pcblist";
+ break;
+ default:
+ mibvar = "net.inet.raw.pcblist";
+ break;
+ }
+
+ len = 0;
+ if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
+ if (errno != ENOENT)
+ warn("sysctl: %s", mibvar);
+ return (0);
+ }
+ if ((buf = malloc(len)) == 0) {
+ warnx("malloc %lu bytes", (u_long)len);
+ return (0);
+ }
+ if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
+ warn("sysctl: %s", mibvar);
+ free(buf);
+ return (0);
+ }
+ *bufp = buf;
+ return (1);
+}
+
+/*
+ * Copied directly from uipc_socket2.c. We leave out some fields that are in
+ * nested structures that aren't used to avoid extra work.
+ */
+static void
+sbtoxsockbuf(struct sockbuf *sb, struct xsockbuf *xsb)
+{
+ xsb->sb_cc = sb->sb_cc;
+ xsb->sb_hiwat = sb->sb_hiwat;
+ xsb->sb_mbcnt = sb->sb_mbcnt;
+ xsb->sb_mbmax = sb->sb_mbmax;
+ xsb->sb_lowat = sb->sb_lowat;
+ xsb->sb_flags = sb->sb_flags;
+ xsb->sb_timeo = sb->sb_timeo;
+}
+
+int
+sotoxsocket(struct socket *so, struct xsocket *xso)
+{
+ struct protosw proto;
+ struct domain domain;
+
+ bzero(xso, sizeof *xso);
+ xso->xso_len = sizeof *xso;
+ xso->xso_so = so;
+ xso->so_type = so->so_type;
+ xso->so_options = so->so_options;
+ xso->so_linger = so->so_linger;
+ xso->so_state = so->so_state;
+ xso->so_pcb = so->so_pcb;
+ if (kread((uintptr_t)so->so_proto, &proto, sizeof(proto)) != 0)
+ return (-1);
+ xso->xso_protocol = proto.pr_protocol;
+ if (kread((uintptr_t)proto.pr_domain, &domain, sizeof(domain)) != 0)
+ return (-1);
+ xso->xso_family = domain.dom_family;
+ xso->so_qlen = so->so_qlen;
+ xso->so_incqlen = so->so_incqlen;
+ xso->so_qlimit = so->so_qlimit;
+ xso->so_timeo = so->so_timeo;
+ xso->so_error = so->so_error;
+ xso->so_oobmark = so->so_oobmark;
+ sbtoxsockbuf(&so->so_snd, &xso->so_snd);
+ sbtoxsockbuf(&so->so_rcv, &xso->so_rcv);
+ return (0);
+}
+
+static int
+pcblist_kvm(u_long off, char **bufp, int istcp)
+{
+ struct inpcbinfo pcbinfo;
+ struct inpcbhead listhead;
+ struct inpcb *inp;
+ struct xinpcb xi;
+ struct xinpgen xig;
+ struct xtcpcb xt;
+ struct socket so;
+ struct xsocket *xso;
+ char *buf, *p;
+ size_t len;
+
+ if (off == 0)
+ return (0);
+ kread(off, &pcbinfo, sizeof(pcbinfo));
+ if (istcp)
+ len = 2 * sizeof(xig) +
+ (pcbinfo.ipi_count + pcbinfo.ipi_count / 8) *
+ sizeof(struct xtcpcb);
+ else
+ len = 2 * sizeof(xig) +
+ (pcbinfo.ipi_count + pcbinfo.ipi_count / 8) *
+ sizeof(struct xinpcb);
+ if ((buf = malloc(len)) == 0) {
+ warnx("malloc %lu bytes", (u_long)len);
+ return (0);
+ }
+ p = buf;
+
+#define COPYOUT(obj, size) do { \
+ if (len < (size)) { \
+ warnx("buffer size exceeded"); \
+ goto fail; \
+ } \
+ bcopy((obj), p, (size)); \
+ len -= (size); \
+ p += (size); \
+} while (0)
+
+#define KREAD(off, buf, len) do { \
+ if (kread((uintptr_t)(off), (buf), (len)) != 0) \
+ goto fail; \
+} while (0)
+
+ /* Write out header. */
+ xig.xig_len = sizeof xig;
+ xig.xig_count = pcbinfo.ipi_count;
+ xig.xig_gen = pcbinfo.ipi_gencnt;
+ xig.xig_sogen = 0;
+ COPYOUT(&xig, sizeof xig);
+
+ /* Walk the PCB list. */
+ xt.xt_len = sizeof xt;
+ xi.xi_len = sizeof xi;
+ if (istcp)
+ xso = &xt.xt_socket;
+ else
+ xso = &xi.xi_socket;
+ KREAD(pcbinfo.ipi_listhead, &listhead, sizeof(listhead));
+ LIST_FOREACH(inp, &listhead, inp_list) {
+ if (istcp) {
+ KREAD(inp, &xt.xt_inp, sizeof(*inp));
+ inp = &xt.xt_inp;
+ } else {
+ KREAD(inp, &xi.xi_inp, sizeof(*inp));
+ inp = &xi.xi_inp;
+ }
+
+ if (inp->inp_gencnt > pcbinfo.ipi_gencnt)
+ continue;
+
+ if (istcp) {
+ if (inp->inp_ppcb == NULL)
+ bzero(&xt.xt_tp, sizeof xt.xt_tp);
+ else if (inp->inp_vflag & INP_TIMEWAIT) {
+ bzero(&xt.xt_tp, sizeof xt.xt_tp);
+ xt.xt_tp.t_state = TCPS_TIME_WAIT;
+ } else
+ KREAD(inp->inp_ppcb, &xt.xt_tp,
+ sizeof xt.xt_tp);
+ }
+ if (inp->inp_socket) {
+ KREAD(inp->inp_socket, &so, sizeof(so));
+ if (sotoxsocket(&so, xso) != 0)
+ goto fail;
+ } else {
+ bzero(xso, sizeof(*xso));
+ if (istcp)
+ xso->xso_protocol = IPPROTO_TCP;
+ }
+ if (istcp)
+ COPYOUT(&xt, sizeof xt);
+ else
+ COPYOUT(&xi, sizeof xi);
+ }
+
+ /* Reread the pcbinfo and write out the footer. */
+ kread(off, &pcbinfo, sizeof(pcbinfo));
+ xig.xig_count = pcbinfo.ipi_count;
+ xig.xig_gen = pcbinfo.ipi_gencnt;
+ COPYOUT(&xig, sizeof xig);
+
+ *bufp = buf;
+ return (1);
+
+fail:
+ free(buf);
+ return (0);
+#undef COPYOUT
+#undef KREAD
+}
+
/*
* Print a summary of connections related to an Internet
* protocol. For TCP, also give state of connection.
@@ -97,18 +300,16 @@ static int udp_done, tcp_done;
* -a (all) flag is specified.
*/
void
-protopr(u_long proto, /* for sysctl version we pass proto # */
- const char *name, int af1)
+protopr(u_long off, const char *name, int af1, int proto)
{
int istcp;
static int first = 1;
char *buf;
- const char *mibvar, *vchar;
+ const char *vchar;
struct tcpcb *tp = NULL;
struct inpcb *inp;
struct xinpgen *xig, *oxig;
struct xsocket *so;
- size_t len;
istcp = 0;
switch (proto) {
@@ -120,7 +321,6 @@ protopr(u_long proto, /* for sysctl version we pass proto # */
tcp_done = 1;
#endif
istcp = 1;
- mibvar = "net.inet.tcp.pcblist";
break;
case IPPROTO_UDP:
#ifdef INET6
@@ -129,29 +329,14 @@ protopr(u_long proto, /* for sysctl version we pass proto # */
else
udp_done = 1;
#endif
- mibvar = "net.inet.udp.pcblist";
- break;
- case IPPROTO_DIVERT:
- mibvar = "net.inet.divert.pcblist";
- break;
- default:
- mibvar = "net.inet.raw.pcblist";
break;
}
- len = 0;
- if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
- if (errno != ENOENT)
- warn("sysctl: %s", mibvar);
- return;
- }
- if ((buf = malloc(len)) == 0) {
- warnx("malloc %lu bytes", (u_long)len);
- return;
- }
- if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
- warn("sysctl: %s", mibvar);
- free(buf);
- return;
+ if (live) {
+ if (!pcblist_sysctl(proto, &buf, istcp))
+ return;
+ } else {
+ if (!pcblist_kvm(off, &buf, istcp))
+ return;
}
oxig = xig = (struct xinpgen *)buf;
@@ -168,7 +353,7 @@ protopr(u_long proto, /* for sysctl version we pass proto # */
}
/* Ignore sockets for protocols other than the desired one. */
- if (so->xso_protocol != (int)proto)
+ if (so->xso_protocol != proto)
continue;
/* Ignore PCBs which were freed during copyout. */
@@ -347,18 +532,10 @@ protopr(u_long proto, /* for sysctl version we pass proto # */
* Dump TCP statistics structure.
*/
void
-tcp_stats(u_long off __unused, const char *name, int af1 __unused)
+tcp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
{
struct tcpstat tcpstat, zerostat;
size_t len = sizeof tcpstat;
-
- if (zflag)
- memset(&zerostat, 0, len);
- if (sysctlbyname("net.inet.tcp.stats", &tcpstat, &len,
- zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
- warn("sysctl: net.inet.tcp.stats");
- return;
- }
#ifdef INET6
if (tcp_done != 0)
@@ -367,6 +544,17 @@ tcp_stats(u_long off __unused, const char *name, int af1 __unused)
tcp_done = 1;
#endif
+ if (live) {
+ if (zflag)
+ memset(&zerostat, 0, len);
+ if (sysctlbyname("net.inet.tcp.stats", &tcpstat, &len,
+ zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+ warn("sysctl: net.inet.tcp.stats");
+ return;
+ }
+ } else
+ kread(off, &tcpstat, len);
+
printf ("%s:\n", name);
#define p(f, m) if (tcpstat.f || sflag <= 1) \
@@ -480,20 +668,12 @@ tcp_stats(u_long off __unused, const char *name, int af1 __unused)
* Dump UDP statistics structure.
*/
void
-udp_stats(u_long off __unused, const char *name, int af1 __unused)
+udp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
{
struct udpstat udpstat, zerostat;
size_t len = sizeof udpstat;
u_long delivered;
- if (zflag)
- memset(&zerostat, 0, len);
- if (sysctlbyname("net.inet.udp.stats", &udpstat, &len,
- zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
- warn("sysctl: net.inet.udp.stats");
- return;
- }
-
#ifdef INET6
if (udp_done != 0)
return;
@@ -501,6 +681,17 @@ udp_stats(u_long off __unused, const char *name, int af1 __unused)
udp_done = 1;
#endif
+ if (live) {
+ if (zflag)
+ memset(&zerostat, 0, len);
+ if (sysctlbyname("net.inet.udp.stats", &udpstat, &len,
+ zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+ warn("sysctl: net.inet.udp.stats");
+ return;
+ }
+ } else
+ kread(off, &udpstat, len);
+
printf("%s:\n", name);
#define p(f, m) if (udpstat.f || sflag <= 1) \
printf(m, udpstat.f, plural(udpstat.f))
@@ -537,18 +728,24 @@ udp_stats(u_long off __unused, const char *name, int af1 __unused)
* Dump CARP statistics structure.
*/
void
-carp_stats(u_long off __unused, const char *name, int af1 __unused)
+carp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
{
struct carpstats carpstat, zerostat;
size_t len = sizeof(struct carpstats);
- if (zflag)
- memset(&zerostat, 0, len);
- if (sysctlbyname("net.inet.carp.stats", &carpstat, &len,
- zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
- if (errno != ENOENT)
- warn("sysctl: net.inet.carp.stats");
- return;
+ if (live) {
+ if (zflag)
+ memset(&zerostat, 0, len);
+ if (sysctlbyname("net.inet.carp.stats", &carpstat, &len,
+ zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+ if (errno != ENOENT)
+ warn("sysctl: net.inet.carp.stats");
+ return;
+ }
+ } else {
+ if (off == 0)
+ return;
+ kread(off, &carpstat, len);
}
printf("%s:\n", name);
@@ -582,18 +779,21 @@ carp_stats(u_long off __unused, const char *name, int af1 __unused)
* Dump IP statistics structure.
*/
void
-ip_stats(u_long off __unused, const char *name, int af1 __unused)
+ip_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
{
struct ipstat ipstat, zerostat;
size_t len = sizeof ipstat;
- if (zflag)
- memset(&zerostat, 0, len);
- if (sysctlbyname("net.inet.ip.stats", &ipstat, &len,
- zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
- warn("sysctl: net.inet.ip.stats");
- return;
- }
+ if (live) {
+ if (zflag)
+ memset(&zerostat, 0, len);
+ if (sysctlbyname("net.inet.ip.stats", &ipstat, &len,
+ zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+ warn("sysctl: net.inet.ip.stats");
+ return;
+ }
+ } else
+ kread(off, &ipstat, len);
printf("%s:\n", name);
@@ -687,26 +887,23 @@ static const char *icmpnames[ICMP_MAXTYPE + 1] = {
* Dump ICMP statistics.
*/
void
-icmp_stats(u_long off __unused, const char *name, int af1 __unused)
+icmp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
{
struct icmpstat icmpstat, zerostat;
int i, first;
- int mib[4]; /* CTL_NET + PF_INET + IPPROTO_ICMP + req */
size_t len;
- mib[0] = CTL_NET;
- mib[1] = PF_INET;
- mib[2] = IPPROTO_ICMP;
- mib[3] = ICMPCTL_STATS;
-
len = sizeof icmpstat;
- if (zflag)
- memset(&zerostat, 0, len);
- if (sysctl(mib, 4, &icmpstat, &len,
- zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
- warn("sysctl: net.inet.icmp.stats");
- return;
- }
+ if (live) {
+ if (zflag)
+ memset(&zerostat, 0, len);
+ if (sysctlbyname("net.inet.icmp.stats", &icmpstat, &len,
+ zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+ warn("sysctl: net.inet.icmp.stats");
+ return;
+ }
+ } else
+ kread(off, &icmpstat, len);
printf("%s:\n", name);
@@ -758,30 +955,35 @@ icmp_stats(u_long off __unused, const char *name, int af1 __unused)
#undef p
#undef p1a
#undef p2
- mib[3] = ICMPCTL_MASKREPL;
- len = sizeof i;
- if (sysctl(mib, 4, &i, &len, (void *)0, 0) < 0)
- return;
- printf("\tICMP address mask responses are %sabled\n",
- i ? "en" : "dis");
+ if (live) {
+ len = sizeof i;
+ if (sysctlbyname("net.inet.icmp.maskrepl", &i, &len, NULL, 0) <
+ 0)
+ return;
+ printf("\tICMP address mask responses are %sabled\n",
+ i ? "en" : "dis");
+ }
}
/*
* Dump IGMP statistics structure.
*/
void
-igmp_stats(u_long off __unused, const char *name, int af1 __unused)
+igmp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
{
struct igmpstat igmpstat, zerostat;
size_t len = sizeof igmpstat;
- if (zflag)
- memset(&zerostat, 0, len);
- if (sysctlbyname("net.inet.igmp.stats", &igmpstat, &len,
- zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
- warn("sysctl: net.inet.igmp.stats");
- return;
- }
+ if (live) {
+ if (zflag)
+ memset(&zerostat, 0, len);
+ if (sysctlbyname("net.inet.igmp.stats", &igmpstat, &len,
+ zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+ warn("sysctl: net.inet.igmp.stats");
+ return;
+ }
+ } else
+ kread(off, &igmpstat, len);
printf("%s:\n", name);
@@ -806,18 +1008,25 @@ igmp_stats(u_long off __unused, const char *name, int af1 __unused)
* Dump PIM statistics structure.
*/
void
-pim_stats(u_long off __unused, const char *name, int af1 __unused)
+pim_stats(u_long off __unused, const char *name, int af1 __unused,
+ int proto __unused)
{
struct pimstat pimstat, zerostat;
size_t len = sizeof pimstat;
- if (zflag)
- memset(&zerostat, 0, len);
- if (sysctlbyname("net.inet.pim.stats", &pimstat, &len,
- zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
- if (errno != ENOENT)
- warn("sysctl: net.inet.pim.stats");
- return;
+ if (live) {
+ if (zflag)
+ memset(&zerostat, 0, len);
+ if (sysctlbyname("net.inet.pim.stats", &pimstat, &len,
+ zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+ if (errno != ENOENT)
+ warn("sysctl: net.inet.pim.stats");
+ return;
+ }
+ } else {
+ if (off == 0)
+ return;
+ kread(off, &pimstat, len);
}
printf("%s:\n", name);
diff --git a/usr.bin/netstat/inet6.c b/usr.bin/netstat/inet6.c
index 7b4f54dc39fa4..945075ce6d27d 100644
--- a/usr.bin/netstat/inet6.c
+++ b/usr.bin/netstat/inet6.c
@@ -362,22 +362,24 @@ static char *srcrule_str[] = {
* Dump IP6 statistics structure.
*/
void
-ip6_stats(u_long off __unused, const char *name, int af1 __unused)
+ip6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
{
struct ip6stat ip6stat;
int first, i;
- int mib[4];
size_t len;
- mib[0] = CTL_NET;
- mib[1] = PF_INET6;
- mib[2] = IPPROTO_IPV6;
- mib[3] = IPV6CTL_STATS;
-
len = sizeof ip6stat;
- memset(&ip6stat, 0, len);
- if (sysctl(mib, 4, &ip6stat, &len, (void *)0, 0) < 0)
- return;
+ if (live) {
+ memset(&ip6stat, 0, len);
+ if (sysctlbyname("net.inet6.ip6.stats", &ip6stat, &len, NULL,
+ 0) < 0) {
+ if (errno != ENOENT)
+ warn("sysctl: net.inet6.ip6.stats");
+ return;
+ }
+ } else
+ kread(off, &ip6stat, len);
+
printf("%s:\n", name);
#define p(f, m) if (ip6stat.f || sflag <= 1) \
@@ -842,22 +844,24 @@ static const char *icmp6names[] = {
* Dump ICMP6 statistics.
*/
void
-icmp6_stats(u_long off __unused, const char *name, int af1 __unused)
+icmp6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
{
struct icmp6stat icmp6stat;
int i, first;
- int mib[4];
size_t len;
- mib[0] = CTL_NET;
- mib[1] = PF_INET6;
- mib[2] = IPPROTO_ICMPV6;
- mib[3] = ICMPV6CTL_STATS;
-
len = sizeof icmp6stat;
- memset(&icmp6stat, 0, len);
- if (sysctl(mib, 4, &icmp6stat, &len, (void *)0, 0) < 0)
- return;
+ if (live) {
+ memset(&icmp6stat, 0, len);
+ if (sysctlbyname("net.inet6.icmp6.stats", &icmp6stat, &len,
+ NULL, 0) < 0) {
+ if (errno != ENOENT)
+ warn("sysctl: net.inet6.icmp6.stats");
+ return;
+ }
+ } else
+ kread(off, &icmp6stat, len);
+
printf("%s:\n", name);
#define p(f, m) if (icmp6stat.f || sflag <= 1) \
@@ -994,20 +998,26 @@ icmp6_ifstats(char *ifname)
* Dump PIM statistics structure.
*/
void
-pim6_stats(u_long off __unused, const char *name, int af1 __unused)
+pim6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
{
struct pim6stat pim6stat, zerostat;
size_t len = sizeof pim6stat;
- /* TODO put back the KVM functionality for -M switch ie coredumps. */
- if (zflag)
- memset(&zerostat, 0, len);
- if (sysctlbyname("net.inet6.pim.stats", &pim6stat, &len,
- zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
- if (errno != ENOENT)
- warn("sysctl: net.inet6.pim.stats");
- return;
+ if (live) {
+ if (zflag)
+ memset(&zerostat, 0, len);
+ if (sysctlbyname("net.inet6.pim.stats", &pim6stat, &len,
+ zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+ if (errno != ENOENT)
+ warn("sysctl: net.inet6.pim.stats");
+ return;
+ }
+ } else {
+ if (off == 0)
+ return;
+ kread(off, &pim6stat, len);
}
+
printf("%s:\n", name);
#define p(f, m) if (pim6stat.f || sflag <= 1) \
@@ -1026,24 +1036,22 @@ pim6_stats(u_long off __unused, const char *name, int af1 __unused)
* Dump raw ip6 statistics structure.
*/
void
-rip6_stats(u_long off __unused, const char *name, int af1 __unused)
+rip6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
{
struct rip6stat rip6stat;
u_quad_t delivered;
- int mib[4];
- size_t l;
+ size_t len;
- mib[0] = CTL_NET;
- mib[1] = PF_INET6;
- mib[2] = IPPROTO_IPV6;
- mib[3] = IPV6CTL_RIP6STATS;
- l = sizeof(rip6stat);
- if (sysctl(mib, 4, &rip6stat, &l, NULL, 0) < 0) {
- /* Just shut up if the kernel doesn't have ipv6. */
- if (errno != ENOENT)
- perror("Warning: sysctl(net.inet6.ip6.rip6stats)");
- return;
- }
+ len = sizeof(rip6stat);
+ if (live) {
+ if (sysctlbyname("net.inet6.ip6.rip6stats", &rip6stat, &len,
+ NULL, 0) < 0) {
+ if (errno != ENOENT)
+ warn("sysctl: net.inet6.ip6.rip6stats");
+ return;
+ }
+ } else
+ kread(off, &rip6stat, len);
printf("%s:\n", name);
diff --git a/usr.bin/netstat/ipsec.c b/usr.bin/netstat/ipsec.c
index 2dc64108b4534..ef3e78f49d94a 100644
--- a/usr.bin/netstat/ipsec.c
+++ b/usr.bin/netstat/ipsec.c
@@ -101,6 +101,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/socket.h>
+#include <sys/socketvar.h>
#include <netinet/in.h>
@@ -267,7 +268,7 @@ print_ipsecstats(const struct ipsecstat *ipsecstat)
}
void
-ipsec_stats(u_long off, const char *name, int af1 __unused)
+ipsec_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
{
struct ipsecstat ipsecstat;
@@ -355,7 +356,7 @@ print_ahstats(const struct ahstat *ahstat)
}
void
-ah_stats(u_long off, const char *name, int family __unused)
+ah_stats(u_long off, const char *name, int family __unused, int proto __unused)
{
struct ahstat ahstat;
@@ -405,7 +406,7 @@ print_espstats(const struct espstat *espstat)
}
void
-esp_stats(u_long off, const char *name, int family __unused)
+esp_stats(u_long off, const char *name, int family __unused, int proto __unused)
{
struct espstat espstat;
@@ -450,7 +451,8 @@ print_ipcompstats(const struct ipcompstat *ipcompstat)
}
void
-ipcomp_stats(u_long off, const char *name, int family __unused)
+ipcomp_stats(u_long off, const char *name, int family __unused,
+ int proto __unused)
{
struct ipcompstat ipcompstat;
diff --git a/usr.bin/netstat/ipx.c b/usr.bin/netstat/ipx.c
index b8f50e30a474d..dad5ae88db0bd 100644
--- a/usr.bin/netstat/ipx.c
+++ b/usr.bin/netstat/ipx.c
@@ -82,7 +82,7 @@ extern char *tcpstates[];
*/
void
-ipxprotopr(u_long off, const char *name, int af1 __unused)
+ipxprotopr(u_long off, const char *name, int af1 __unused, int proto __unused)
{
struct ipxpcbhead cb;
struct ipxpcb *ipxp;
@@ -155,7 +155,7 @@ ipxprotopr(u_long off, const char *name, int af1 __unused)
* Dump SPX statistics structure.
*/
void
-spx_stats(u_long off, const char *name, int af1 __unused)
+spx_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
{
struct spx_istat spx_istat;
#define spxstat spx_istat.newstats
@@ -231,7 +231,7 @@ spx_stats(u_long off, const char *name, int af1 __unused)
* Dump IPX statistics structure.
*/
void
-ipx_stats(u_long off, const char *name, int af1 __unused)
+ipx_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
{
struct ipxstat ipxstat;
@@ -274,7 +274,7 @@ static struct {
*/
/*ARGSUSED*/
void
-ipxerr_stats(u_long off, const char *name, int af __unused)
+ipxerr_stats(u_long off, const char *name, int af __unused, int proto __unused)
{
struct ipx_errstat ipx_errstat;
int j;
diff --git a/usr.bin/netstat/main.c b/usr.bin/netstat/main.c
index 434121f8f75f5..c1decb7e16b36 100644
--- a/usr.bin/netstat/main.c
+++ b/usr.bin/netstat/main.c
@@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$");
#include <sys/file.h>
#include <sys/protosw.h>
#include <sys/socket.h>
+#include <sys/socketvar.h>
#include <netinet/in.h>
@@ -141,121 +142,154 @@ static struct nlist nl[] = {
{ .n_name = "_carpstats" },
#define N_PFSYNCSTAT 34
{ .n_name = "_pfsyncstats" },
-#define N_AHSTAT 36
+#define N_AHSTAT 35
{ .n_name = "_ahstat" },
-#define N_ESPSTAT 37
+#define N_ESPSTAT 36
{ .n_name = "_espstat" },
-#define N_IPCOMPSTAT 38
+#define N_IPCOMPSTAT 37
{ .n_name = "_ipcompstat" },
+#define N_TCPSTAT 38
+ { .n_name = "_tcpstat" },
+#define N_UDPSTAT 39
+ { .n_name = "_udpstat" },
+#define N_IPSTAT 40
+ { .n_name = "_ipstat" },
+#define N_ICMPSTAT 41
+ { .n_name = "_icmpstat" },
+#define N_IGMPSTAT 42
+ { .n_name = "_igmpstat" },
+#define N_PIMSTAT 43
+ { .n_name = "_pimstat" },
+#define N_TCBINFO 44
+ { .n_name = "_tcbinfo" },
+#define N_UDBINFO 45
+ { .n_name = "_udbinfo" },
+#define N_DIVCBINFO 46
+ { .n_name = "_divcbinfo" },
+#define N_RIPCBINFO 47
+ { .n_name = "_ripcbinfo" },
+#define N_UNP_COUNT 48
+ { .n_name = "_unp_count" },
+#define N_UNP_GENCNT 49
+ { .n_name = "_unp_gencnt" },
+#define N_UNP_DHEAD 50
+ { .n_name = "_unp_dhead" },
+#define N_UNP_SHEAD 51
+ { .n_name = "_unp_shead" },
+#define N_RIP6STAT 52
+ { .n_name = "_rip6stat" },
+#define N_SCTPSTAT 53
+ { .n_name = "_sctpstat" },
{ .n_name = NULL },
};
struct protox {
- u_char pr_index; /* index into nlist of cb head */
- u_char pr_sindex; /* index into nlist of stat block */
+ int pr_index; /* index into nlist of cb head */
+ int pr_sindex; /* index into nlist of stat block */
u_char pr_wanted; /* 1 if wanted, 0 otherwise */
- void (*pr_cblocks)(u_long, const char *, int);
+ void (*pr_cblocks)(u_long, const char *, int, int);
/* control blocks printing routine */
- void (*pr_stats)(u_long, const char *, int);
+ void (*pr_stats)(u_long, const char *, int, int);
/* statistics printing routine */
void (*pr_istats)(char *); /* per/if statistics printing routine */
const char *pr_name; /* well-known name */
u_long pr_usesysctl; /* non-zero if we use sysctl, not kvm */
+ int pr_protocol;
} protox[] = {
- { -1, -1, 1, protopr,
- tcp_stats, NULL, "tcp", IPPROTO_TCP },
- { -1, -1, 1, protopr,
- udp_stats, NULL, "udp", IPPROTO_UDP },
+ { N_TCBINFO, N_TCPSTAT, 1, protopr,
+ tcp_stats, NULL, "tcp", 1, IPPROTO_TCP },
+ { N_UDBINFO, N_UDPSTAT, 1, protopr,
+ udp_stats, NULL, "udp", 1, IPPROTO_UDP },
#ifdef SCTP
- { -1, -1, 1, sctp_protopr,
- sctp_stats, NULL, "sctp", IPPROTO_SCTP },
+ { -1, N_SCTPSTAT, 1, sctp_protopr,
+ sctp_stats, NULL, "sctp", 1, IPPROTO_SCTP },
#endif
- { -1, -1, 1, protopr,
- NULL, NULL, "divert",IPPROTO_DIVERT },
- { -1, -1, 1, protopr,
- ip_stats, NULL, "ip", IPPROTO_RAW },
- { -1, -1, 1, protopr,
- icmp_stats, NULL, "icmp", IPPROTO_ICMP },
- { -1, -1, 1, protopr,
- igmp_stats, NULL, "igmp", IPPROTO_IGMP },
+ { N_DIVCBINFO, -1, 1, protopr,
+ NULL, NULL, "divert", 1, IPPROTO_DIVERT },
+ { N_RIPCBINFO, N_IPSTAT, 1, protopr,
+ ip_stats, NULL, "ip", 1, IPPROTO_RAW },
+ { N_RIPCBINFO, N_ICMPSTAT, 1, protopr,
+ icmp_stats, NULL, "icmp", 1, IPPROTO_ICMP },
+ { N_RIPCBINFO, N_IGMPSTAT, 1, protopr,
+ igmp_stats, NULL, "igmp", 1, IPPROTO_IGMP },
#ifdef IPSEC
{ -1, N_IPSECSTAT, 1, NULL, /* keep as compat */
- ipsec_stats, NULL, "ipsec", 0},
+ ipsec_stats, NULL, "ipsec", 0, 0},
{ -1, N_AHSTAT, 1, NULL,
- ah_stats, NULL, "ah", 0},
+ ah_stats, NULL, "ah", 0, 0},
{ -1, N_ESPSTAT, 1, NULL,
- esp_stats, NULL, "esp", 0},
+ esp_stats, NULL, "esp", 0, 0},
{ -1, N_IPCOMPSTAT, 1, NULL,
- ipcomp_stats, NULL, "ipcomp", 0},
+ ipcomp_stats, NULL, "ipcomp", 0, 0},
#endif
- { -1, -1, 1, protopr,
- pim_stats, NULL, "pim", IPPROTO_PIM },
- { -1, N_CARPSTAT, 1, 0,
- carp_stats, NULL, "carp", 0},
- { -1, -1, 1, NULL,
- pfsync_stats, NULL, "pfsync", 1},
+ { N_RIPCBINFO, N_PIMSTAT, 1, protopr,
+ pim_stats, NULL, "pim", 1, IPPROTO_PIM },
+ { -1, N_CARPSTAT, 1, NULL,
+ carp_stats, NULL, "carp", 1, 0 },
+ { -1, N_PFSYNCSTAT, 1, NULL,
+ pfsync_stats, NULL, "pfsync", 1, 0 },
{ -1, -1, 0, NULL,
- NULL, NULL, NULL, 0 }
+ NULL, NULL, NULL, 0, 0 }
};
#ifdef INET6
struct protox ip6protox[] = {
- { -1, -1, 1, protopr,
- tcp_stats, NULL, "tcp", IPPROTO_TCP },
- { -1, -1, 1, protopr,
- udp_stats, NULL, "udp", IPPROTO_UDP },
- { -1, N_IP6STAT, 1, protopr,
- ip6_stats, ip6_ifstats, "ip6", IPPROTO_RAW },
- { -1, N_ICMP6STAT, 1, protopr,
- icmp6_stats, icmp6_ifstats, "icmp6",IPPROTO_ICMPV6 },
+ { N_TCBINFO, N_TCPSTAT, 1, protopr,
+ tcp_stats, NULL, "tcp", 1, IPPROTO_TCP },
+ { N_UDBINFO, N_UDPSTAT, 1, protopr,
+ udp_stats, NULL, "udp", 1, IPPROTO_UDP },
+ { N_RIPCBINFO, N_IP6STAT, 1, protopr,
+ ip6_stats, ip6_ifstats, "ip6", 1, IPPROTO_RAW },
+ { N_RIPCBINFO, N_ICMP6STAT, 1, protopr,
+ icmp6_stats, icmp6_ifstats, "icmp6", 1, IPPROTO_ICMPV6 },
#ifdef IPSEC
{ -1, N_IPSEC6STAT, 1, NULL,
- ipsec_stats, NULL, "ipsec6",0 },
+ ipsec_stats, NULL, "ipsec6", 0, 0 },
#endif
#ifdef notyet
{ -1, N_PIM6STAT, 1, NULL,
- pim6_stats, NULL, "pim6", 0 },
+ pim6_stats, NULL, "pim6", 1, 0 },
#endif
- { -1, -1, 1, NULL,
- rip6_stats, NULL, "rip6", 0 },
+ { -1, N_RIP6STAT, 1, NULL,
+ rip6_stats, NULL, "rip6", 1, 0 },
{ -1, -1, 0, NULL,
- NULL, NULL, NULL, 0 }
+ NULL, NULL, NULL, 0, 0 }
};
#endif /*INET6*/
#ifdef IPSEC
struct protox pfkeyprotox[] = {
{ -1, N_PFKEYSTAT, 1, NULL,
- pfkey_stats, NULL, "pfkey", 0 },
+ pfkey_stats, NULL, "pfkey", 0, 0 },
{ -1, -1, 0, NULL,
- NULL, NULL, NULL, 0 }
+ NULL, NULL, NULL, 0, 0 }
};
#endif
struct protox atalkprotox[] = {
{ N_DDPCB, N_DDPSTAT, 1, atalkprotopr,
- ddp_stats, NULL, "ddp", 0 },
+ ddp_stats, NULL, "ddp", 0, 0 },
{ -1, -1, 0, NULL,
- NULL, NULL, NULL, 0 }
+ NULL, NULL, NULL, 0, 0 }
};
struct protox netgraphprotox[] = {
{ N_NGSOCKS, -1, 1, netgraphprotopr,
- NULL, NULL, "ctrl", 0 },
+ NULL, NULL, "ctrl", 0, 0 },
{ N_NGSOCKS, -1, 1, netgraphprotopr,
- NULL, NULL, "data", 0 },
+ NULL, NULL, "data", 0, 0 },
{ -1, -1, 0, NULL,
- NULL, NULL, NULL, 0 }
+ NULL, NULL, NULL, 0, 0 }
};
#ifdef IPX
struct protox ipxprotox[] = {
{ N_IPX, N_IPXSTAT, 1, ipxprotopr,
- ipx_stats, NULL, "ipx", 0 },
+ ipx_stats, NULL, "ipx", 0, 0 },
{ N_IPX, N_SPXSTAT, 1, ipxprotopr,
- spx_stats, NULL, "spx", 0 },
+ spx_stats, NULL, "spx", 0, 0 },
{ -1, -1, 0, NULL,
- NULL, NULL, 0, 0 }
+ NULL, NULL, 0, 0, 0 }
};
#endif
@@ -305,6 +339,7 @@ char *interface; /* desired i/f for stats, or NULL for all i/fs */
int unit; /* unit number for above */
int af; /* address family */
+int live; /* true if we are examining a live system */
int
main(int argc, char *argv[])
@@ -453,16 +488,19 @@ main(int argc, char *argv[])
* Discard setgid privileges if not the running kernel so that bad
* guys can't print interesting stuff from kernel memory.
*/
- if (nlistf != NULL || memf != NULL)
+ live = (nlistf == NULL && memf == NULL);
+ if (!live)
setgid(getgid());
if (Bflag) {
+ if (!live)
+ usage();
bpf_stats(interface);
exit(0);
}
if (mflag) {
if (memf != NULL) {
- if (kread(0, 0, 0) == 0)
+ if (kread(0, NULL, 0) == 0)
mbpr(kvmd, nl[N_MBSTAT].n_value);
} else
mbpr(NULL, 0);
@@ -482,13 +520,12 @@ main(int argc, char *argv[])
* used for the queries, which is slower.
*/
#endif
+ kread(0, NULL, 0);
if (iflag && !sflag) {
- kread(0, 0, 0);
intpr(interval, nl[N_IFNET].n_value, NULL);
exit(0);
}
if (rflag) {
- kread(0, 0, 0);
if (sflag)
rt_stats(nl[N_RTSTAT].n_value, nl[N_RTTRASH].n_value);
else
@@ -496,7 +533,6 @@ main(int argc, char *argv[])
exit(0);
}
if (gflag) {
- kread(0, 0, 0);
if (sflag) {
if (af == AF_INET || af == AF_UNSPEC)
mrt_stats(nl[N_MRTSTAT].n_value);
@@ -518,7 +554,6 @@ main(int argc, char *argv[])
exit(0);
}
- kread(0, 0, 0);
if (tp) {
printproto(tp, tp->pr_name);
exit(0);
@@ -538,7 +573,6 @@ main(int argc, char *argv[])
#endif /*IPSEC*/
#ifdef IPX
if (af == AF_IPX || af == AF_UNSPEC) {
- kread(0, 0, 0);
for (tp = ipxprotox; tp->pr_name; tp++)
printproto(tp, tp->pr_name);
}
@@ -550,7 +584,8 @@ main(int argc, char *argv[])
for (tp = netgraphprotox; tp->pr_name; tp++)
printproto(tp, tp->pr_name);
if ((af == AF_UNIX || af == AF_UNSPEC) && !Lflag && !sflag)
- unixpr();
+ unixpr(nl[N_UNP_COUNT].n_value, nl[N_UNP_GENCNT].n_value,
+ nl[N_UNP_DHEAD].n_value, nl[N_UNP_SHEAD].n_value);
exit(0);
}
@@ -564,7 +599,7 @@ printproto(tp, name)
struct protox *tp;
const char *name;
{
- void (*pr)(u_long, const char *, int);
+ void (*pr)(u_long, const char *, int, int);
u_long off;
if (sflag) {
@@ -576,17 +611,24 @@ printproto(tp, name)
printf("%s: no per-interface stats routine\n",
tp->pr_name);
return;
- }
- else {
+ } else {
pr = tp->pr_stats;
if (!pr) {
if (pflag)
printf("%s: no stats routine\n",
tp->pr_name);
return;
- }
- off = tp->pr_usesysctl ? tp->pr_usesysctl
- : nl[tp->pr_sindex].n_value;
+ }
+ if (tp->pr_usesysctl && live)
+ off = 0;
+ else if (tp->pr_sindex < 0) {
+ if (pflag)
+ printf(
+ "%s: stats routine doesn't work on cores\n",
+ tp->pr_name);
+ return;
+ } else
+ off = nl[tp->pr_sindex].n_value;
}
} else {
pr = tp->pr_cblocks;
@@ -595,28 +637,36 @@ printproto(tp, name)
printf("%s: no PCB routine\n", tp->pr_name);
return;
}
- off = tp->pr_usesysctl ? tp->pr_usesysctl
- : nl[tp->pr_index].n_value;
+ if (tp->pr_usesysctl && live)
+ off = 0;
+ else if (tp->pr_index < 0) {
+ if (pflag)
+ printf(
+ "%s: PCB routine doesn't work on cores\n",
+ tp->pr_name);
+ return;
+ } else
+ off = nl[tp->pr_index].n_value;
}
- if (pr != NULL && (off || af != AF_UNSPEC))
- (*pr)(off, name, af);
+ if (pr != NULL && (off || (live && tp->pr_usesysctl) ||
+ af != AF_UNSPEC))
+ (*pr)(off, name, af, tp->pr_protocol);
}
/*
* Read kernel memory, return 0 on success.
*/
int
-kread(u_long addr, char *buf, int size)
+kread(u_long addr, void *buf, size_t size)
{
- if (kvmd == 0) {
- /*
- * XXX.
- */
- kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf);
+ char errbuf[_POSIX2_LINE_MAX];
+
+ if (kvmd == NULL) {
+ kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
setgid(getgid());
if (kvmd != NULL) {
if (kvm_nlist(kvmd, nl) < 0) {
- if(nlistf)
+ if (nlistf)
errx(1, "%s: kvm_nlist: %s", nlistf,
kvm_geterr(kvmd));
else
@@ -624,20 +674,21 @@ kread(u_long addr, char *buf, int size)
}
if (nl[0].n_type == 0) {
- if(nlistf)
+ if (nlistf)
errx(1, "%s: no namelist", nlistf);
else
errx(1, "no namelist");
}
} else {
- warnx("kvm not available");
+ warnx("kvm not available: %s", errbuf);
return(-1);
}
}
if (!buf)
return (0);
- if (kvm_read(kvmd, addr, buf, size) != size) {
+ if (kvm_read(kvmd, addr, buf, size) != (ssize_t)size) {
warnx("%s", kvm_geterr(kvmd));
+ abort();
return (-1);
}
return (0);
diff --git a/usr.bin/netstat/mbuf.c b/usr.bin/netstat/mbuf.c
index 911fc1f7da278..7e09a1e5bc768 100644
--- a/usr.bin/netstat/mbuf.c
+++ b/usr.bin/netstat/mbuf.c
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
#include <sys/mbuf.h>
#include <sys/protosw.h>
#include <sys/socket.h>
+#include <sys/socketvar.h>
#include <sys/sysctl.h>
#include <err.h>
@@ -80,9 +81,8 @@ mbpr(void *kvmd, u_long mbaddr)
int nsfbufs, nsfbufspeak, nsfbufsused;
struct mbstat mbstat;
size_t mlen;
- int error, live;
+ int error;
- live = (kvmd == NULL);
mtlp = memstat_mtl_alloc();
if (mtlp == NULL) {
warn("memstat_mtl_alloc");
diff --git a/usr.bin/netstat/mcast.c b/usr.bin/netstat/mcast.c
index ce0d042fc95c7..734893427c883 100644
--- a/usr.bin/netstat/mcast.c
+++ b/usr.bin/netstat/mcast.c
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/socketvar.h>
#include <net/if.h>
#include <net/if_var.h>
diff --git a/usr.bin/netstat/mroute.c b/usr.bin/netstat/mroute.c
index acf6ddcdde937..d3cf740ad6e76 100644
--- a/usr.bin/netstat/mroute.c
+++ b/usr.bin/netstat/mroute.c
@@ -84,32 +84,24 @@ mroutepr(u_long mfcaddr, u_long vifaddr)
size_t len;
len = sizeof(mfctable);
- if (sysctlbyname("net.inet.ip.mfctable", mfctable, &len, NULL, 0) < 0) {
- warn("sysctl: net.inet.ip.mfctable");
- if (mfcaddr == 0) {
- printf("No IPv4 multicast forwarding configured in "
- "the running system.\n");
+ if (live) {
+ if (sysctlbyname("net.inet.ip.mfctable", mfctable, &len, NULL,
+ 0) < 0) {
+ warn("sysctl: net.inet.ip.mfctable");
return;
}
- /*
- * XXX: Try KVM if the module is neither compiled nor loaded.
- * The correct behaviour would be to always use KVM if
- * the -M option is specified to netstat(1).
- */
+ } else
kread(mfcaddr, (char *)mfctable, sizeof(mfctable));
- }
len = sizeof(viftable);
- if (sysctlbyname("net.inet.ip.viftable", viftable, &len, NULL, 0) < 0) {
- warn("sysctl: net.inet.ip.viftable");
- if (vifaddr == 0) {
- printf("No IPv4 multicast forwarding configured in "
- "the running system.\n");
+ if (live) {
+ if (sysctlbyname("net.inet.ip.viftable", viftable, &len, NULL,
+ 0) < 0) {
+ warn("sysctl: net.inet.ip.viftable");
return;
}
- /* XXX KVM */
+ } else
kread(vifaddr, (char *)viftable, sizeof(viftable));
- }
saved_numeric_addr = numeric_addr;
numeric_addr = 1;
@@ -276,18 +268,15 @@ mrt_stats(u_long mstaddr)
struct mrtstat mrtstat;
size_t len = sizeof mrtstat;
- if (sysctlbyname("net.inet.ip.mrtstat", &mrtstat, &len,
- NULL, 0) < 0) {
- warn("sysctl: net.inet.ip.mrtstat");
- /* Compatability with older kernels - candidate for removal */
- if (mstaddr == 0) {
- printf("No IPv4 multicast forwarding configured in "
- "the running system.\n");
+ if (live) {
+ if (sysctlbyname("net.inet.ip.mrtstat", &mrtstat, &len, NULL,
+ 0) < 0) {
+ warn("sysctl: net.inet.ip.mrtstat");
return;
}
- /* XXX KVM */
+ } else
kread(mstaddr, (char *)&mrtstat, sizeof(mrtstat));
- }
+
printf("IPv4 multicast forwarding:\n");
#define p(f, m) if (mrtstat.f || sflag <= 1) \
diff --git a/usr.bin/netstat/mroute6.c b/usr.bin/netstat/mroute6.c
index f071b5bb623b0..6b4230d7765cd 100644
--- a/usr.bin/netstat/mroute6.c
+++ b/usr.bin/netstat/mroute6.c
@@ -116,16 +116,14 @@ mroute6pr(u_long mfcaddr, u_long mifaddr)
size_t len;
len = sizeof(mif6table);
- if (sysctlbyname("net.inet6.ip6.mif6table", mif6table, &len,
- NULL, 0) < 0) {
- warn("sysctl: net.inet6.ip6.mif6table");
- if (mifaddr == 0) {
- printf("No IPv6 multicast forwarding configured in "
- "the running system.\n");
+ if (live) {
+ if (sysctlbyname("net.inet6.ip6.mif6table", mif6table, &len,
+ NULL, 0) < 0) {
+ warn("sysctl: net.inet6.ip6.mif6table");
return;
}
+ } else
kread(mifaddr, (char *)mif6table, sizeof(mif6table));
- }
saved_numeric_addr = numeric_addr;
numeric_addr = 1;
@@ -161,21 +159,14 @@ mroute6pr(u_long mfcaddr, u_long mifaddr)
printf("\nIPv6 Multicast Interface Table is empty\n");
len = sizeof(mf6ctable);
- if (sysctlbyname("net.inet6.ip6.mf6ctable", mf6ctable, &len,
- NULL, 0) < 0) {
- warn("sysctl: net.inet6.ip6.mf6ctable");
- if (mfcaddr == 0) {
- printf("No IPv6 multicast forwarding configured in "
- "the running system.\n");
+ if (live) {
+ if (sysctlbyname("net.inet6.ip6.mf6ctable", mf6ctable, &len,
+ NULL, 0) < 0) {
+ warn("sysctl: net.inet6.ip6.mf6ctable");
return;
}
- /*
- * XXX: Try KVM if the module is neither compiled nor loaded.
- * The correct behaviour would be to always use KVM if
- * the -M option is specified to netstat(1).
- */
+ } else
kread(mfcaddr, (char *)mf6ctable, sizeof(mf6ctable));
- }
banner_printed = 0;
@@ -232,16 +223,15 @@ mrt6_stats(u_long mstaddr)
struct mrt6stat mrtstat;
size_t len = sizeof mrtstat;
- if (sysctlbyname("net.inet6.ip6.mrt6stat", &mrtstat, &len,
- NULL, 0) < 0) {
- warn("sysctl: net.inet6.ip6.mrt6stat");
- if (mstaddr == 0) {
- printf("No IPv6 multicast forwarding configured in the "
- "running system.\n");
+ if (live) {
+ if (sysctlbyname("net.inet6.ip6.mrt6stat", &mrtstat, &len,
+ NULL, 0) < 0) {
+ warn("sysctl: net.inet6.ip6.mrt6stat");
return;
}
+ } else
kread(mstaddr, (char *)&mrtstat, sizeof(mrtstat));
- }
+
printf("IPv6 multicast forwarding:\n");
#define p(f, m) if (mrtstat.f || sflag <= 1) \
diff --git a/usr.bin/netstat/netgraph.c b/usr.bin/netstat/netgraph.c
index 77db23f35d531..8ca9e5cd7e315 100644
--- a/usr.bin/netstat/netgraph.c
+++ b/usr.bin/netstat/netgraph.c
@@ -62,7 +62,8 @@ static int first = 1;
static int csock = -1;
void
-netgraphprotopr(u_long off, const char *name, int af1 __unused)
+netgraphprotopr(u_long off, const char *name, int af1 __unused,
+ int proto __unused)
{
struct ngpcb *this, *next;
struct ngpcb ngpcb;
@@ -81,6 +82,10 @@ netgraphprotopr(u_long off, const char *name, int af1 __unused)
struct kld_file_stat ks;
int fileid;
+ /* Can't do this for core dumps. */
+ if (!live)
+ return;
+
/* See if module is loaded */
if ((fileid = kldfind(modname)) < 0) {
if (debug)
diff --git a/usr.bin/netstat/netstat.h b/usr.bin/netstat/netstat.h
index a2df187f65ab0..0c6f7339c31bf 100644
--- a/usr.bin/netstat/netstat.h
+++ b/usr.bin/netstat/netstat.h
@@ -59,39 +59,41 @@ extern char *interface; /* desired i/f for stats, or NULL for all i/fs */
extern int unit; /* unit number for above */
extern int af; /* address family */
+extern int live; /* true if we are examining a live system */
-int kread(u_long addr, char *buf, int size);
+int kread(u_long addr, void *buf, size_t size);
const char *plural(uintmax_t);
const char *plurales(uintmax_t);
const char *pluralies(uintmax_t);
-void protopr(u_long, const char *, int);
-void tcp_stats(u_long, const char *, int);
-void udp_stats(u_long, const char *, int);
+int sotoxsocket(struct socket *, struct xsocket *);
+void protopr(u_long, const char *, int, int);
+void tcp_stats(u_long, const char *, int, int);
+void udp_stats(u_long, const char *, int, int);
#ifdef SCTP
-void sctp_protopr(u_long, const char *, int);
-void sctp_stats(u_long, const char *, int);
+void sctp_protopr(u_long, const char *, int, int);
+void sctp_stats(u_long, const char *, int, int);
#endif
-void ip_stats(u_long, const char *, int);
-void icmp_stats(u_long, const char *, int);
-void igmp_stats(u_long, const char *, int);
-void pim_stats(u_long, const char *, int);
-void carp_stats (u_long, const char *, int);
-void pfsync_stats (u_long, const char *, int);
+void ip_stats(u_long, const char *, int, int);
+void icmp_stats(u_long, const char *, int, int);
+void igmp_stats(u_long, const char *, int, int);
+void pim_stats(u_long, const char *, int, int);
+void carp_stats (u_long, const char *, int, int);
+void pfsync_stats (u_long, const char *, int, int);
#ifdef IPSEC
-void ipsec_stats(u_long, const char *, int);
-void esp_stats (u_long, const char *, int);
-void ah_stats (u_long, const char *, int);
-void ipcomp_stats (u_long, const char *, int);
+void ipsec_stats(u_long, const char *, int, int);
+void esp_stats (u_long, const char *, int, int);
+void ah_stats (u_long, const char *, int, int);
+void ipcomp_stats (u_long, const char *, int, int);
#endif
#ifdef INET6
-void ip6_stats(u_long, const char *, int);
+void ip6_stats(u_long, const char *, int, int);
void ip6_ifstats(char *);
-void icmp6_stats(u_long, const char *, int);
+void icmp6_stats(u_long, const char *, int, int);
void icmp6_ifstats(char *);
-void pim6_stats(u_long, const char *, int);
-void rip6_stats(u_long, const char *, int);
+void pim6_stats(u_long, const char *, int, int);
+void rip6_stats(u_long, const char *, int, int);
void mroute6pr(u_long, u_long);
void mrt6_stats(u_long);
@@ -103,7 +105,7 @@ void inet6print(struct in6_addr *, int, const char *, int);
#endif /*INET6*/
#ifdef IPSEC
-void pfkey_stats(u_long, const char *, int);
+void pfkey_stats(u_long, const char *, int, int);
#endif
void mbpr(void *, u_long);
@@ -129,29 +131,29 @@ char *ipx_print(struct sockaddr *);
char *ns_print(struct sockaddr *);
void routepr(u_long);
-void ipxprotopr(u_long, const char *, int);
-void spx_stats(u_long, const char *, int);
-void ipx_stats(u_long, const char *, int);
-void ipxerr_stats(u_long, const char *, int);
+void ipxprotopr(u_long, const char *, int, int);
+void spx_stats(u_long, const char *, int, int);
+void ipx_stats(u_long, const char *, int, int);
+void ipxerr_stats(u_long, const char *, int, int);
-void nsprotopr(u_long, const char *, int);
-void spp_stats(u_long, const char *, int);
-void idp_stats(u_long, const char *, int);
-void nserr_stats(u_long, const char *, int);
+void nsprotopr(u_long, const char *, int, int);
+void spp_stats(u_long, const char *, int, int);
+void idp_stats(u_long, const char *, int, int);
+void nserr_stats(u_long, const char *, int, int);
-void atalkprotopr(u_long, const char *, int);
-void ddp_stats(u_long, const char *, int);
+void atalkprotopr(u_long, const char *, int, int);
+void ddp_stats(u_long, const char *, int, int);
-void netgraphprotopr(u_long, const char *, int);
+void netgraphprotopr(u_long, const char *, int, int);
-void unixpr(void);
+void unixpr(u_long, u_long, u_long, u_long);
-void esis_stats(u_long, const char *, int);
-void clnp_stats(u_long, const char *, int);
-void cltp_stats(u_long, const char *, int);
-void iso_protopr(u_long, const char *, int);
+void esis_stats(u_long, const char *, int, int);
+void clnp_stats(u_long, const char *, int, int);
+void cltp_stats(u_long, const char *, int, int);
+void iso_protopr(u_long, const char *, int, int);
void iso_protopr1(u_long, int);
-void tp_protopr(u_long, const char *, int);
+void tp_protopr(u_long, const char *, int, int);
void tp_inproto(u_long);
void tp_stats(caddr_t, caddr_t);
diff --git a/usr.bin/netstat/pfkey.c b/usr.bin/netstat/pfkey.c
index ad22ae86107be..47fccb7826cb3 100644
--- a/usr.bin/netstat/pfkey.c
+++ b/usr.bin/netstat/pfkey.c
@@ -76,6 +76,7 @@ static const char rcsid[] =
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/socket.h>
+#include <sys/socketvar.h>
#include <netinet/in.h>
@@ -116,7 +117,8 @@ pfkey_msgtype_names(int x)
}
void
-pfkey_stats(u_long off, const char *name, int family __unused)
+pfkey_stats(u_long off, const char *name, int family __unused,
+ int proto __unused)
{
struct pfkeystat pfkeystat;
unsigned first, type;
diff --git a/usr.bin/netstat/route.c b/usr.bin/netstat/route.c
index f13dff8c2d293..a0a8990a17bdf 100644
--- a/usr.bin/netstat/route.c
+++ b/usr.bin/netstat/route.c
@@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/protosw.h>
#include <sys/socket.h>
+#include <sys/socketvar.h>
#include <sys/time.h>
#include <net/ethernet.h>
diff --git a/usr.bin/netstat/sctp.c b/usr.bin/netstat/sctp.c
index b3038d3e3ab93..feb9a25b28852 100644
--- a/usr.bin/netstat/sctp.c
+++ b/usr.bin/netstat/sctp.c
@@ -432,8 +432,8 @@ sctp_process_inpcb(struct xsctp_inpcb *xinpcb, const char *name,
* protocol.
*/
void
-sctp_protopr(u_long proto,
- const char *name, int af1)
+sctp_protopr(u_long off __unused,
+ const char *name, int af1, int proto)
{
char *buf;
const char *mibvar = "net.inet.sctp.assoclist";
@@ -511,18 +511,21 @@ sctp_statesprint(uint32_t state)
* Dump SCTP statistics structure.
*/
void
-sctp_stats(u_long off __unused, const char *name, int af1 __unused)
+sctp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
{
struct sctpstat sctpstat, zerostat;
size_t len = sizeof(sctpstat);
- if (zflag)
- memset(&zerostat, 0, len);
- if (sysctlbyname("net.inet.sctp.stats", &sctpstat, &len,
- zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
- warn("sysctl: net.inet.sctp.stats");
- return;
- }
+ if (live) {
+ if (zflag)
+ memset(&zerostat, 0, len);
+ if (sysctlbyname("net.inet.sctp.stats", &sctpstat, &len,
+ zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+ warn("sysctl: net.inet.sctp.stats");
+ return;
+ }
+ } else
+ kread(off, &sctpstat, len);
printf ("%s:\n", name);
diff --git a/usr.bin/netstat/unix.c b/usr.bin/netstat/unix.c
index be70d5bacdc59..03bef85b7f7a7 100644
--- a/usr.bin/netstat/unix.c
+++ b/usr.bin/netstat/unix.c
@@ -61,6 +61,7 @@ __FBSDID("$FreeBSD$");
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
+#include <strings.h>
#include <kvm.h>
#include "netstat.h"
@@ -69,35 +70,148 @@ static void unixdomainpr (struct xunpcb *, struct xsocket *);
static const char *const socktype[] =
{ "#0", "stream", "dgram", "raw", "rdm", "seqpacket" };
-void
-unixpr(void)
+static int
+pcblist_sysctl(int type, char **bufp)
{
char *buf;
- int type;
size_t len;
- struct xsocket *so;
- struct xunpgen *xug, *oxug;
- struct xunpcb *xunp;
char mibvar[sizeof "net.local.seqpacket.pcblist"];
- for (type = SOCK_STREAM; type <= SOCK_SEQPACKET; type++) {
- sprintf(mibvar, "net.local.%s.pcblist", socktype[type]);
+ sprintf(mibvar, "net.local.%s.pcblist", socktype[type]);
+
+ len = 0;
+ if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
+ if (errno != ENOENT)
+ warn("sysctl: %s", mibvar);
+ return (-1);
+ }
+ if ((buf = malloc(len)) == 0) {
+ warnx("malloc %lu bytes", (u_long)len);
+ return (-2);
+ }
+ if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
+ warn("sysctl: %s", mibvar);
+ free(buf);
+ return (-2);
+ }
+ *bufp = buf;
+ return (0);
+}
+
+static int
+pcblist_kvm(u_long count_off, u_long gencnt_off, u_long head_off, char **bufp)
+{
+ struct unp_head head;
+ struct unpcb *unp, unp_conn;
+ u_char sun_len;
+ struct socket so;
+ struct xunpgen xug;
+ struct xunpcb xu;
+ unp_gen_t unp_gencnt;
+ u_int unp_count;
+ char *buf, *p;
+ size_t len;
+
+ if (count_off == 0 || gencnt_off == 0)
+ return (-2);
+ if (head_off == 0)
+ return (-1);
+ kread(count_off, &unp_count, sizeof(unp_count));
+ len = 2 * sizeof(xug) + (unp_count + unp_count / 8) * sizeof(xu);
+ if ((buf = malloc(len)) == 0) {
+ warnx("malloc %lu bytes", (u_long)len);
+ return (-2);
+ }
+ p = buf;
+
+#define COPYOUT(obj, size) do { \
+ if (len < (size)) { \
+ warnx("buffer size exceeded"); \
+ goto fail; \
+ } \
+ bcopy((obj), p, (size)); \
+ len -= (size); \
+ p += (size); \
+} while (0)
+
+#define KREAD(off, buf, len) do { \
+ if (kread((uintptr_t)(off), (buf), (len)) != 0) \
+ goto fail; \
+} while (0)
+
+ /* Write out header. */
+ kread(gencnt_off, &unp_gencnt, sizeof(unp_gencnt));
+ xug.xug_len = sizeof xug;
+ xug.xug_count = unp_count;
+ xug.xug_gen = unp_gencnt;
+ xug.xug_sogen = 0;
+ COPYOUT(&xug, sizeof xug);
- len = 0;
- if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
- if (errno != ENOENT)
- warn("sysctl: %s", mibvar);
+ /* Walk the PCB list. */
+ xu.xu_len = sizeof xu;
+ KREAD(head_off, &head, sizeof(head));
+ LIST_FOREACH(unp, &head, unp_link) {
+ xu.xu_unpp = unp;
+ KREAD(unp, &xu.xu_unp, sizeof (*unp));
+ unp = &xu.xu_unp;
+
+ if (unp->unp_gencnt > unp_gencnt)
continue;
+ if (unp->unp_addr != NULL) {
+ KREAD(unp->unp_addr, &sun_len, sizeof(sun_len));
+ KREAD(unp->unp_addr, &xu.xu_addr, sun_len);
}
- if ((buf = malloc(len)) == 0) {
- warnx("malloc %lu bytes", (u_long)len);
- return;
+ if (unp->unp_conn != NULL) {
+ KREAD(unp->unp_conn, &unp_conn, sizeof(unp_conn));
+ if (unp_conn.unp_addr != NULL) {
+ KREAD(unp_conn.unp_addr, &sun_len,
+ sizeof(sun_len));
+ KREAD(unp_conn.unp_addr, &xu.xu_caddr, sun_len);
+ }
}
- if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
- warn("sysctl: %s", mibvar);
- free(buf);
+ KREAD(unp->unp_socket, &so, sizeof(so));
+ if (sotoxsocket(&so, &xu.xu_socket) != 0)
+ goto fail;
+ COPYOUT(&xu, sizeof(xu));
+ }
+
+ /* Reread the counts and write the footer. */
+ kread(count_off, &unp_count, sizeof(unp_count));
+ kread(gencnt_off, &unp_gencnt, sizeof(unp_gencnt));
+ xug.xug_count = unp_count;
+ xug.xug_gen = unp_gencnt;
+ COPYOUT(&xug, sizeof xug);
+
+ *bufp = buf;
+ return (0);
+
+fail:
+ free(buf);
+ return (-1);
+#undef COPYOUT
+#undef KREAD
+}
+
+void
+unixpr(u_long count_off, u_long gencnt_off, u_long dhead_off, u_long shead_off)
+{
+ char *buf;
+ int ret, type;
+ struct xsocket *so;
+ struct xunpgen *xug, *oxug;
+ struct xunpcb *xunp;
+
+ for (type = SOCK_STREAM; type <= SOCK_SEQPACKET; type++) {
+ if (live)
+ ret = pcblist_sysctl(type, &buf);
+ else
+ ret = pcblist_kvm(count_off, gencnt_off,
+ type == SOCK_STREAM ? shead_off :
+ (type == SOCK_DGRAM ? dhead_off : 0), &buf);
+ if (ret == -1)
+ continue;
+ if (ret < 0)
return;
- }
oxug = xug = (struct xunpgen *)buf;
for (xug = (struct xunpgen *)((char *)xug + xug->xug_len);