./usr/bin/netpgp minix-base crypto
./usr/bin/netpgpkeys minix-base crypto
./usr/bin/netpgpverify minix-base crypto
+./usr/bin/netstat minix-base
./usr/bin/newgrp minix-base
./usr/bin/nice minix-base
./usr/bin/nl minix-base
./usr/libdata/debug/usr/bin/netpgp.debug minix-debug debug
./usr/libdata/debug/usr/bin/netpgpkeys.debug minix-debug debug
./usr/libdata/debug/usr/bin/netpgpverify.debug minix-debug debug
+./usr/libdata/debug/usr/bin/netstat.debug minix-debug debug
./usr/libdata/debug/usr/bin/newgrp.debug minix-debug debug
./usr/libdata/debug/usr/bin/nice.debug minix-debug debug
./usr/libdata/debug/usr/bin/nl.debug minix-debug debug
./usr/man/man1/netpgp.1 minix-man crypto
./usr/man/man1/netpgpkeys.1 minix-man crypto
./usr/man/man1/netpgpverify.1 minix-man crypto
+./usr/man/man1/netstat.1 minix-man
./usr/man/man1/newfs_mfs.1 minix-man
./usr/man/man1/newgrp.1 minix-man
./usr/man/man1/nice.1 minix-man
machine make man menuc mesg \
mkcsmapper mkdep mkesdb mkfifo mklocale mkstr mktemp \
msgc \
- nbperf newgrp nice nl nohup \
+ nbperf netstat newgrp nice nl nohup \
pagesize passwd paste patch pathchk pr \
printenv printf pwhash \
renice rev rsh \
--- /dev/null
+# $NetBSD: Makefile,v 1.43 2015/06/06 13:48:37 joerg Exp $
+# from: @(#)Makefile 8.1 (Berkeley) 6/12/93
+
+.include <bsd.own.mk>
+
+USE_FORT?= yes # setgid
+
+RUMPPRG=netstat
+#SRCS= atalk.c bpf.c fast_ipsec.c if.c inet.c inet6.c
+SRCS= atalk.c bpf.c if.c inet.c inet6.c \
+ main.c mbuf.c mroute.c mroute6.c pfkey.c pfsync.c route.c \
+ unix.c vtw.c rtutil.c
+.if !defined(__MINIX)
+BINGRP= kmem
+BINMODE=2555
+.endif # !defined(__MINIX)
+LDADD= -lutil -lkvm
+DPADD= ${LIBUTIL} ${LIBKVM}
+.if !defined(__MINIX)
+CPPFLAGS+= -DIPSEC -I${.CURDIR}
+.else # defined(__MINIX)
+CPPFLAGS+= -I${.CURDIR}
+.endif # defined(__MINIX)
+CPPFLAGS+= -I${NETBSDSRCDIR}/sys/dist/pf
+CPPFLAGS+= -I${NETBSDSRCDIR}/sbin/route
+
+.PATH: ${.CURDIR}/../../lib/libc/gen
+.PATH: ${.CURDIR}/../../lib/libc/net
+.PATH: ${.CURDIR}/../../sbin/route
+CPPFLAGS+= -DRUMP_ACTION
+RUMPSRCS+= sysctlbyname.c sysctlgetmibinfo.c sysctlnametomib.c
+RUMPSRCS+= if_indextoname.c getifaddrs.c getnameinfo.c
+
+.if (${USE_INET6} != "no")
+CPPFLAGS+= -DINET6
+.endif
+
+.if defined(__MINIX)
+# FIXME: compilation on ARM fails on a format string warning because of a
+# mismatch between the PRIxPTR format and the uintptr_t type, which should not
+# be possible. This is a bug in the ARM port, but I have no idea how to solve
+# that. For now, simply do not fail the build on this error. --dcvmoole
+CPPFLAGS+= -Wno-error=format
+.endif # defined(__MINIX)
+
+.include <bsd.prog.mk>
--- /dev/null
+/* $NetBSD: atalk.c,v 1.16 2015/06/06 13:08:31 joerg Exp $ */
+
+/*
+ * Copyright (c) 1983, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "from @(#)atalk.c 1.1 (Whistle) 6/6/96";
+#else
+__RCSID("$NetBSD: atalk.c,v 1.16 2015/06/06 13:08:31 joerg Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/mbuf.h>
+#include <sys/protosw.h>
+#include <sys/sysctl.h>
+
+#include <net/route.h>
+#include <net/if.h>
+
+#include <netinet/tcp_fsm.h>
+
+#include <netatalk/at.h>
+#include <netatalk/ddp_var.h>
+
+#include <err.h>
+#include <nlist.h>
+#include <kvm.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include "netstat.h"
+
+struct ddpcb ddpcb;
+struct socket sockb;
+
+static int first = 1;
+
+/*
+ * Print a summary of connections related to a Network Systems
+ * protocol. For XXX, also give state of connection.
+ * Listening processes (aflag) are suppressed unless the
+ * -a (all) flag is specified.
+ */
+
+static const char *
+at_pr_net(const struct sockaddr_at *sat, int numeric)
+{
+ static char mybuf[50];
+
+ if (!numeric) {
+ switch (sat->sat_addr.s_net) {
+ case 0xffff:
+ return "????";
+ case ATADDR_ANYNET:
+ return ("*");
+ }
+ }
+ (void)snprintf(mybuf, sizeof(mybuf), "%hu", ntohs(sat->sat_addr.s_net));
+ return (mybuf);
+}
+
+static const char *
+at_pr_host(const struct sockaddr_at *sat, int numeric)
+{
+ static char mybuf[50];
+
+ if (!numeric) {
+ switch (sat->sat_addr.s_node) {
+ case ATADDR_BCAST:
+ return "bcast";
+ case ATADDR_ANYNODE:
+ return ("*");
+ }
+ }
+ (void)snprintf(mybuf, sizeof(mybuf), "%d",
+ (unsigned int)sat->sat_addr.s_node);
+ return (mybuf);
+}
+
+static const char *
+at_pr_port(const struct sockaddr_at *sat)
+{
+ static char mybuf[50];
+
+ switch (sat->sat_port) {
+ case ATADDR_ANYPORT:
+ return ("*");
+ case 0xff:
+ return "????";
+ default:
+ (void)snprintf(mybuf, sizeof(mybuf), "%d",
+ (unsigned int)sat->sat_port);
+ return (mybuf);
+ }
+}
+
+static const char *
+at_pr_range(const struct sockaddr_at *sat)
+{
+ static char mybuf[50];
+
+ if (sat->sat_range.r_netrange.nr_firstnet
+ != sat->sat_range.r_netrange.nr_lastnet) {
+ (void)snprintf(mybuf, sizeof(mybuf), "%d-%d",
+ ntohs(sat->sat_range.r_netrange.nr_firstnet),
+ ntohs(sat->sat_range.r_netrange.nr_lastnet));
+ } else {
+ (void)snprintf(mybuf, sizeof(mybuf), "%d",
+ ntohs(sat->sat_range.r_netrange.nr_firstnet));
+ }
+ return (mybuf);
+}
+
+
+/* what == 0 for addr only == 3
+ * 1 for net
+ * 2 for host
+ * 4 for port
+ * 8 for numeric only
+ */
+const char *
+atalk_print(const struct sockaddr *sa, int what)
+{
+ const struct sockaddr_at *sat = (const struct sockaddr_at *) sa;
+ static char mybuf[50];
+ int numeric = (what & 0x08);
+
+ mybuf[0] = 0;
+ switch (what & 0x13) {
+ case 0:
+ mybuf[0] = 0;
+ break;
+ case 1:
+ (void)snprintf(mybuf, sizeof(mybuf), "%s",
+ at_pr_net(sat, numeric));
+ break;
+ case 2:
+ (void)snprintf(mybuf, sizeof(mybuf), "%s",
+ at_pr_host(sat, numeric));
+ break;
+ case 3:
+ (void)snprintf(mybuf, sizeof(mybuf), "%s.%s",
+ at_pr_net(sat, numeric),
+ at_pr_host(sat, numeric));
+ break;
+ case 0x10:
+ (void)snprintf(mybuf, sizeof(mybuf), "%s", at_pr_range(sat));
+ }
+ if (what & 4) {
+ (void)snprintf(mybuf + strlen(mybuf),
+ sizeof(mybuf) - strlen(mybuf), ".%s", at_pr_port(sat));
+ }
+ return (mybuf);
+}
+
+const char *
+atalk_print2(const struct sockaddr *sa, const struct sockaddr *mask, int what)
+{
+ int n, l;
+ static char buf[100];
+ const struct sockaddr_at *sat1, *sat2;
+ struct sockaddr_at thesockaddr;
+ struct sockaddr *sa2;
+
+ sat1 = (const struct sockaddr_at *) sa;
+ sat2 = (const struct sockaddr_at *) mask;
+ sa2 = (struct sockaddr *) & thesockaddr;
+
+ thesockaddr.sat_addr.s_net = sat1->sat_addr.s_net &
+ sat2->sat_addr.s_net;
+ n = snprintf(buf, sizeof(buf), "%s", atalk_print(sa2, 1 | (what & 8)));
+ if (n >= (int)sizeof(buf))
+ n = sizeof(buf) - 1;
+ else if (n == -1)
+ n = 0; /* What else can be done ? */
+ if (sat2->sat_addr.s_net != 0xFFFF) {
+ thesockaddr.sat_addr.s_net = sat1->sat_addr.s_net |
+ ~sat2->sat_addr.s_net;
+ l = snprintf(buf + n, sizeof(buf) - n,
+ "-%s", atalk_print(sa2, 1 | (what & 8)));
+ if (l >= (int)(sizeof(buf) - n))
+ l = sizeof(buf) - n - 1;
+ if (l > 0)
+ n += l;
+ }
+ if (what & 2) {
+ l = snprintf(buf + n, sizeof(buf) - n, ".%s",
+ atalk_print(sa, what & (~1)));
+ if (l >= (int)(sizeof(buf) - n))
+ l = sizeof(buf) - n - 1;
+ if (l > 0)
+ n += l;
+ }
+ return (buf);
+}
+
+void
+atalkprotopr(u_long off, const char *name)
+{
+ struct ddpcb *next;
+ struct ddpcb *initial;
+ int width = 22;
+ if (off == 0)
+ return;
+ if (kread(off, (char *)&initial, sizeof(struct ddpcb *)) < 0)
+ return;
+ for (next = initial; next != NULL;) {
+ u_long ppcb = (u_long)next;
+
+ if (kread((u_long)next, (char *)&ddpcb, sizeof(ddpcb)) < 0)
+ return;
+ next = ddpcb.ddp_next;
+#if 0
+ if (!aflag && atalk_nullhost(ddpcb.ddp_lsat)) {
+ continue;
+ }
+#endif
+ if (kread((u_long)ddpcb.ddp_socket,
+ (char *)&sockb, sizeof(sockb)) < 0)
+ return;
+ if (first) {
+ printf("Active ATALK connections");
+ if (aflag)
+ printf(" (including servers)");
+ putchar('\n');
+ if (Aflag) {
+ width = 18;
+ printf("%-8.8s ", "PCB");
+ }
+ printf("%-5.5s %-6.6s %-6.6s %*.*s %*.*s %s\n",
+ "Proto", "Recv-Q", "Send-Q",
+ -width, width, "Local Address",
+ -width, width, "Foreign Address", "(state)");
+ first = 0;
+ }
+ if (Aflag)
+ printf("%8lx ", ppcb);
+ printf("%-5.5s %6ld %6ld ", name, sockb.so_rcv.sb_cc,
+ sockb.so_snd.sb_cc);
+ printf(" %*.*s", -width, width,
+ atalk_print((struct sockaddr *)&ddpcb.ddp_lsat, 7));
+ printf(" %*.*s", -width, width,
+ atalk_print((struct sockaddr *)&ddpcb.ddp_fsat, 7));
+ putchar('\n');
+ }
+}
+#define ANY(x,y,z) \
+ ((sflag==1 || (x)) ? printf("\t%llu %s%s%s\n",(unsigned long long)x,y,plural(x),z) : 0)
+
+/*
+ * Dump DDP statistics structure.
+ */
+void
+ddp_stats(u_long off, const char *name)
+{
+ uint64_t ddpstat[DDP_NSTATS];
+
+ if (use_sysctl) {
+ size_t size = sizeof(ddpstat);
+
+ if (sysctlbyname("net.atalk.ddp.stats", ddpstat, &size,
+ NULL, 0) == -1)
+ return;
+ } else {
+ warnx("%s stats not available via KVM.", name);
+ return;
+ }
+
+ printf("%s:\n", name);
+
+ ANY(ddpstat[DDP_STAT_SHORT], "packet", " with short headers ");
+ ANY(ddpstat[DDP_STAT_LONG], "packet", " with long headers ");
+ ANY(ddpstat[DDP_STAT_NOSUM], "packet", " with no checksum ");
+ ANY(ddpstat[DDP_STAT_TOOSHORT], "packet", " too short ");
+ ANY(ddpstat[DDP_STAT_BADSUM], "packet", " with bad checksum ");
+ ANY(ddpstat[DDP_STAT_TOOSMALL], "packet", " with not enough data ");
+ ANY(ddpstat[DDP_STAT_FORWARD], "packet", " forwarded ");
+ ANY(ddpstat[DDP_STAT_ENCAP], "packet", " encapsulated ");
+ ANY(ddpstat[DDP_STAT_CANTFORWARD], "packet", " rcvd for unreachable dest ");
+ ANY(ddpstat[DDP_STAT_NOSOCKSPACE], "packet", " dropped due to no socket space ");
+}
+#undef ANY
--- /dev/null
+/* $NetBSD: bpf.c,v 1.11 2012/12/14 08:15:44 msaitoh Exp $ */
+
+/*
+ * Copyright (c) 2005 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Rui Paulo.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <kvm.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <net/if.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <net/bpfdesc.h>
+#include <net/bpf.h>
+#include "netstat.h"
+#include "prog_ops.h"
+
+void
+bpf_stats(void)
+{
+ struct bpf_stat bpf_s;
+ size_t len = sizeof(bpf_s);
+
+ if (use_sysctl) {
+ if (sysctlbyname("net.bpf.stats", &bpf_s, &len, NULL, 0) == -1)
+ err(1, "net.bpf.stats");
+
+ printf("bpf:\n");
+ printf("\t%" PRIu64 " total packets received\n",
+ bpf_s.bs_recv);
+ printf("\t%" PRIu64 " total packets captured\n",
+ bpf_s.bs_capt);
+ printf("\t%" PRIu64 " total packets dropped\n",
+ bpf_s.bs_drop);
+ } else {
+ warnx("BPF stats not available via KVM.");
+ }
+}
+
+void
+bpf_dump(const char *bpfif)
+{
+ struct bpf_d_ext *dpe;
+
+ if (use_sysctl) {
+ int name[CTL_MAXNAME], rc;
+ size_t i, sz, szproc;
+ u_int namelen;
+ void *v;
+ struct kinfo_proc2 p;
+
+ /* adapted from sockstat.c by Andrew Brown */
+
+ sz = CTL_MAXNAME;
+ if (sysctlnametomib("net.bpf.peers", &name[0], &sz) == -1)
+ err(1, "sysctlnametomib: net.bpf.peers");
+ namelen = sz;
+
+ name[namelen++] = sizeof(*dpe);
+ name[namelen++] = INT_MAX;
+
+ v = NULL;
+ sz = 0;
+ do {
+ rc = prog_sysctl(&name[0], namelen,
+ v, &sz, NULL, 0);
+ if (rc == -1 && errno != ENOMEM)
+ err(1, "sysctl: net.bpf.peers");
+ if (rc == -1 && v != NULL) {
+ free(v);
+ v = NULL;
+ }
+ if (v == NULL) {
+ v = malloc(sz);
+ rc = -1;
+ }
+ if (v == NULL)
+ err(1, "malloc");
+ } while (rc == -1);
+
+ dpe = v;
+
+ puts("Active BPF peers\nPID\tInt\tRecv Drop Capt" \
+ " Flags Bufsize Comm");
+
+#define BPFEXT(entry) dpe->entry
+
+ for (i = 0; i < (sz / sizeof(*dpe)); i++, dpe++) {
+ if (bpfif &&
+ strncmp(BPFEXT(bde_ifname), bpfif, IFNAMSIZ))
+ continue;
+
+ printf("%-7d ", BPFEXT(bde_pid));
+ printf("%-7s ",
+ (BPFEXT(bde_ifname)[0] == '\0') ? "-" :
+ BPFEXT(bde_ifname));
+
+ printf("%-8" PRIu64 " %-8" PRIu64 " %-8" PRIu64 " ",
+ BPFEXT(bde_rcount), BPFEXT(bde_dcount),
+ BPFEXT(bde_ccount));
+
+ switch (BPFEXT(bde_state)) {
+ case BPF_IDLE:
+ printf("I");
+ break;
+ case BPF_WAITING:
+ printf("W");
+ break;
+ case BPF_TIMED_OUT:
+ printf("T");
+ break;
+ default:
+ printf("-");
+ break;
+ }
+
+ printf("%c", BPFEXT(bde_promisc) ? 'P' : '-');
+ printf("%c", BPFEXT(bde_immediate) ? 'R' : '-');
+ printf("%c", BPFEXT(bde_seesent) ? 'S' : '-');
+ printf("%c", BPFEXT(bde_hdrcmplt) ? 'H' : '-');
+ printf(" %-8d ", BPFEXT(bde_bufsize));
+
+ szproc = sizeof(p);
+ namelen = 0;
+ name[namelen++] = CTL_KERN;
+ name[namelen++] = KERN_PROC2;
+ name[namelen++] = KERN_PROC_PID;
+ name[namelen++] = BPFEXT(bde_pid);
+ name[namelen++] = szproc;
+ name[namelen++] = 1;
+
+ if (prog_sysctl(&name[0], namelen, &p, &szproc,
+ NULL, 0) == -1)
+ printf("-\n");
+ else
+ printf("%s\n", p.p_comm);
+#undef BPFEXT
+ }
+ free(v);
+ } else {
+ /* XXX */
+ errx(1, "bpf_dump not implemented using kvm");
+ }
+}
--- /dev/null
+/* $NetBSD: fast_ipsec.c,v 1.20 2013/04/15 21:20:39 christos Exp $ */
+/* $FreeBSD: src/tools/tools/crypto/ipsecstats.c,v 1.1.4.1 2003/06/03 00:13:13 sam Exp $ */
+
+/*-
+ * Copyright (c) 2003, 2004 Jonathan Stone
+ * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/tools/tools/crypto/ipsecstats.c,v 1.1.4.1 2003/06/03 00:13:13 sam Exp $
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#ifdef __NetBSD__
+__RCSID("$NetBSD: fast_ipsec.c,v 1.20 2013/04/15 21:20:39 christos Exp $");
+#endif
+#endif /* not lint*/
+
+/* Kernel headers required, but not included, by netstat.h */
+#include <sys/types.h>
+#include <sys/socket.h>
+
+/* Kernel headers for sysctl(3). */
+#include <sys/param.h>
+#include <sys/sysctl.h>
+
+/* Kernel headers for FAST_IPSEC statistics */
+#include <net/pfkeyv2.h>
+#include <netipsec/esp_var.h>
+#include <netipsec/ah_var.h>
+#include <netipsec/ipip_var.h>
+#include <netipsec/ipcomp_var.h>
+#include <netipsec/ipsec_var.h>
+
+#include <machine/int_fmtio.h>
+
+#include <kvm.h>
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "netstat.h"
+
+/*
+ * Table-driven mapping from SADB algorithm codes to string names.
+ */
+struct alg {
+ int a;
+ const char *name;
+};
+static const struct alg aalgs[] = {
+ { SADB_AALG_NONE, "none", },
+ { SADB_AALG_MD5HMAC, "hmac-md5", },
+ { SADB_AALG_SHA1HMAC, "hmac-sha1", },
+ { SADB_X_AALG_MD5, "md5", },
+ { SADB_X_AALG_SHA, "sha", },
+ { SADB_X_AALG_NULL, "null", },
+ { SADB_X_AALG_SHA2_256, "hmac-sha2-256", },
+ { SADB_X_AALG_SHA2_384, "hmac-sha2-384", },
+ { SADB_X_AALG_SHA2_512, "hmac-sha2-512", },
+ { SADB_X_AALG_AES_XCBC_MAC, "aes-xcbc-mac", },
+ { SADB_X_AALG_AES128GMAC, "aes-128-gmac", },
+ { SADB_X_AALG_AES192GMAC, "aes-192-gmac", },
+ { SADB_X_AALG_AES256GMAC, "aes-256-gmac", },
+};
+static const struct alg espalgs[] = {
+ { SADB_EALG_NONE, "none", },
+ { SADB_EALG_DESCBC, "des-cbc", },
+ { SADB_EALG_3DESCBC, "3des-cbc", },
+ { SADB_EALG_NULL, "null", },
+ { SADB_X_EALG_CAST128CBC, "cast128-cbc", },
+ { SADB_X_EALG_BLOWFISHCBC, "blowfish-cbc", },
+ { SADB_X_EALG_RIJNDAELCBC, "aes-cbc", },
+ { SADB_X_EALG_CAMELLIACBC, "camellia-cbc", },
+ { SADB_X_EALG_AESCTR, "aes-ctr", },
+ { SADB_X_EALG_AESGCM16, "aes-gcm-16", },
+ { SADB_X_EALG_AESGMAC, "aes-gmac", },
+};
+static const struct alg ipcompalgs[] = {
+ { SADB_X_CALG_NONE, "none", },
+ { SADB_X_CALG_OUI, "oui", },
+ { SADB_X_CALG_DEFLATE, "deflate", },
+ { SADB_X_CALG_LZS, "lzs", },
+};
+#define N(a) (sizeof(a)/sizeof(a[0]))
+
+static const char*
+algname(int a, const struct alg algs[], int nalgs)
+{
+ static char buf[80];
+ int i;
+
+ for (i = 0; i < nalgs; i++)
+ if (algs[i].a == a)
+ return algs[i].name;
+ snprintf(buf, sizeof(buf), "alg#%u", a);
+ return buf;
+}
+
+/*
+ * Print the fast_ipsec statistics.
+ * Since NetBSD's netstat(1) seems not to find us for "netstat -s",
+ * but does(?) find KAME, be prepared to be called explicitly from
+ * netstat's main program for "netstat -s"; but silently do nothing
+ * if that happens when we are running on KAME IPsec.
+ */
+void
+fast_ipsec_stats(u_long off, const char *name)
+{
+ uint64_t ipsecstats[IPSEC_NSTATS];
+ uint64_t ahstats[AH_NSTATS];
+ uint64_t espstats[ESP_NSTATS];
+ uint64_t ipcs[IPCOMP_NSTATS];
+ uint64_t ipips[IPIP_NSTATS];
+ int status;
+ size_t slen;
+ int i;
+
+ if (! use_sysctl) {
+ warnx("IPsec stats not available via KVM.");
+ return;
+ }
+
+ memset(ipsecstats, 0, sizeof(ipsecstats));
+ memset(ahstats, 0, sizeof(ahstats));
+ memset(espstats, 0, sizeof(espstats));
+ memset(ipcs, 0, sizeof(ipcs));
+ memset(ipips, 0, sizeof(ipips));
+
+ slen = sizeof(ipsecstats);
+ status = sysctlbyname("net.inet.ipsec.ipsecstats", ipsecstats, &slen,
+ NULL, 0);
+ if (status < 0) {
+ if (errno == ENOENT)
+ return;
+ if (errno != ENOMEM)
+ err(1, "net.inet.ipsec.ipsecstats");
+ }
+
+ slen = sizeof (ahstats);
+ status = sysctlbyname("net.inet.ah.ah_stats", ahstats, &slen, NULL, 0);
+ if (status < 0 && errno != ENOMEM)
+ err(1, "net.inet.ah.ah_stats");
+
+ slen = sizeof (espstats);
+ status = sysctlbyname("net.inet.esp.esp_stats", espstats, &slen, NULL, 0);
+ if (status < 0 && errno != ENOMEM)
+ err(1, "net.inet.esp.esp_stats");
+
+ slen = sizeof(ipcs);
+ status = sysctlbyname("net.inet.ipcomp.ipcomp_stats", ipcs, &slen, NULL, 0);
+ if (status < 0 && errno != ENOMEM)
+ err(1, "net.inet.ipcomp.ipcomp_stats");
+
+ slen = sizeof(ipips);
+ status = sysctlbyname("net.inet.ipip.ipip_stats", ipips, &slen, NULL, 0);
+ if (status < 0 && errno != ENOMEM)
+ err(1, "net.inet.ipip.ipip_stats");
+
+ printf("(Fast) IPsec:\n");
+
+#define STAT(x,fmt) if ((x) || sflag <= 1) printf("\t%"PRIu64" " fmt "\n", x)
+ if (ipsecstats[IPSEC_STAT_IN_POLVIO]+ipsecstats[IPSEC_STAT_OUT_POLVIO])
+ printf("\t%"PRIu64" policy violations: %"PRIu64" input %"PRIu64" output\n",
+ ipsecstats[IPSEC_STAT_IN_POLVIO] + ipsecstats[IPSEC_STAT_OUT_POLVIO],
+ ipsecstats[IPSEC_STAT_IN_POLVIO], ipsecstats[IPSEC_STAT_OUT_POLVIO]);
+ STAT(ipsecstats[IPSEC_STAT_OUT_NOSA], "no SA found (output)");
+ STAT(ipsecstats[IPSEC_STAT_OUT_NOMEM], "no memory available (output)");
+ STAT(ipsecstats[IPSEC_STAT_OUT_NOROUTE], "no route available (output)");
+ STAT(ipsecstats[IPSEC_STAT_OUT_INVAL], "generic errors (output)");
+ STAT(ipsecstats[IPSEC_STAT_OUT_BUNDLESA], "bundled SA processed (output)");
+ STAT(ipsecstats[IPSEC_STAT_SPDCACHELOOKUP], "SPD cache lookups");
+ STAT(ipsecstats[IPSEC_STAT_SPDCACHEMISS], "SPD cache misses");
+#undef STAT
+ printf("\n");
+
+ printf("IPsec ah:\n");
+#define AHSTAT(x,fmt) if ((x) || sflag <= 1) printf("\t%"PRIu64" ah " fmt "\n", x)
+ AHSTAT(ahstats[AH_STAT_INPUT], "input packets processed");
+ AHSTAT(ahstats[AH_STAT_OUTPUT], "output packets processed");
+ AHSTAT(ahstats[AH_STAT_HDROPS], "headers too short");
+ AHSTAT(ahstats[AH_STAT_NOPF], "headers for unsupported address family");
+ AHSTAT(ahstats[AH_STAT_NOTDB], "packets with no SA");
+ AHSTAT(ahstats[AH_STAT_BADKCR], "packets dropped by crypto returning NULL mbuf");
+ AHSTAT(ahstats[AH_STAT_BADAUTH], "packets with bad authentication");
+ AHSTAT(ahstats[AH_STAT_NOXFORM], "packets with no xform");
+ AHSTAT(ahstats[AH_STAT_QFULL], "packets dropped due to queue full");
+ AHSTAT(ahstats[AH_STAT_WRAP], "packets dropped for replay counter wrap");
+ AHSTAT(ahstats[AH_STAT_REPLAY], "packets dropped for possible replay");
+ AHSTAT(ahstats[AH_STAT_BADAUTHL],"packets dropped for bad authenticator length");
+ AHSTAT(ahstats[AH_STAT_INVALID], "packets with an invalid SA");
+ AHSTAT(ahstats[AH_STAT_TOOBIG], "packets too big");
+ AHSTAT(ahstats[AH_STAT_PDROPS], "packets blocked due to policy");
+ AHSTAT(ahstats[AH_STAT_CRYPTO], "failed crypto requests");
+ AHSTAT(ahstats[AH_STAT_TUNNEL], "tunnel sanity check failures");
+
+ printf("\tah histogram:\n");
+ for (i = 0; i < AH_ALG_MAX; i++)
+ if (ahstats[AH_STAT_HIST + i])
+ printf("\t\tah packets with %s: %"PRIu64"\n"
+ , algname(i, aalgs, N(aalgs))
+ , ahstats[AH_STAT_HIST + i]
+ );
+ AHSTAT(ahstats[AH_STAT_IBYTES], "bytes received");
+ AHSTAT(ahstats[AH_STAT_OBYTES], "bytes transmitted");
+#undef AHSTAT
+ printf("\n");
+
+ printf("IPsec esp:\n");
+#define ESPSTAT(x,fmt) if ((x) || sflag <= 1) printf("\t%"PRIu64" esp " fmt "\n", x)
+ ESPSTAT(espstats[ESP_STAT_INPUT],"input packets processed");
+ ESPSTAT(espstats[ESP_STAT_OUTPUT],"output packets processed");
+ ESPSTAT(espstats[ESP_STAT_HDROPS],"headers too short");
+ ESPSTAT(espstats[ESP_STAT_NOPF], "headers for unsupported address family");
+ ESPSTAT(espstats[ESP_STAT_NOTDB],"packets with no SA");
+ ESPSTAT(espstats[ESP_STAT_BADKCR],"packets dropped by crypto returning NULL mbuf");
+ ESPSTAT(espstats[ESP_STAT_QFULL],"packets dropped due to queue full");
+ ESPSTAT(espstats[ESP_STAT_NOXFORM],"packets with no xform");
+ ESPSTAT(espstats[ESP_STAT_BADILEN],"packets with bad ilen");
+ ESPSTAT(espstats[ESP_STAT_BADENC],"packets with bad encryption");
+ ESPSTAT(espstats[ESP_STAT_BADAUTH],"packets with bad authentication");
+ ESPSTAT(espstats[ESP_STAT_WRAP], "packets dropped for replay counter wrap");
+ ESPSTAT(espstats[ESP_STAT_REPLAY],"packets dropped for possible replay");
+ ESPSTAT(espstats[ESP_STAT_INVALID],"packets with an invalid SA");
+ ESPSTAT(espstats[ESP_STAT_TOOBIG],"packets too big");
+ ESPSTAT(espstats[ESP_STAT_PDROPS],"packets blocked due to policy");
+ ESPSTAT(espstats[ESP_STAT_CRYPTO],"failed crypto requests");
+ ESPSTAT(espstats[ESP_STAT_TUNNEL],"tunnel sanity check failures");
+ printf("\tesp histogram:\n");
+ for (i = 0; i < ESP_ALG_MAX; i++)
+ if (espstats[ESP_STAT_HIST + i])
+ printf("\t\tesp packets with %s: %"PRIu64"\n"
+ , algname(i, espalgs, N(espalgs))
+ , espstats[ESP_STAT_HIST + i]
+ );
+ ESPSTAT(espstats[ESP_STAT_IBYTES], "bytes received");
+ ESPSTAT(espstats[ESP_STAT_OBYTES], "bytes transmitted");
+#undef ESPSTAT
+ printf("IPsec ipip:\n");
+
+#define IPIPSTAT(x,fmt) \
+ if ((x) || sflag <= 1) printf("\t%"PRIu64" ipip " fmt "\n", x)
+ IPIPSTAT(ipips[IPIP_STAT_IPACKETS],"total input packets");
+ IPIPSTAT(ipips[IPIP_STAT_OPACKETS],"total output packets");
+ IPIPSTAT(ipips[IPIP_STAT_HDROPS],"packets too short for header length");
+ IPIPSTAT(ipips[IPIP_STAT_QFULL],"packets dropped due to queue full");
+ IPIPSTAT(ipips[IPIP_STAT_PDROPS],"packets blocked due to policy");
+ IPIPSTAT(ipips[IPIP_STAT_SPOOF],"IP spoofing attempts");
+ IPIPSTAT(ipips[IPIP_STAT_FAMILY],"protocol family mismatched");
+ IPIPSTAT(ipips[IPIP_STAT_UNSPEC],"missing tunnel-endpoint address");
+ IPIPSTAT(ipips[IPIP_STAT_IBYTES],"input bytes received");
+ IPIPSTAT(ipips[IPIP_STAT_OBYTES],"output bytes processed");
+#undef IPIPSTAT
+
+ printf("IPsec ipcomp:\n");
+#define IPCOMP(x,fmt) \
+ if ((x) || sflag <= 1) printf("\t%"PRIu64" ipcomp " fmt "\n", x)
+
+ IPCOMP(ipcs[IPCOMP_STAT_HDROPS],"packets too short for header length");
+ IPCOMP(ipcs[IPCOMP_STAT_NOPF], "protocol family not supported");
+ IPCOMP(ipcs[IPCOMP_STAT_NOTDB], "packets with no SA");
+ IPCOMP(ipcs[IPCOMP_STAT_BADKCR],"packets dropped by crypto returning NULL mbuf");
+ IPCOMP(ipcs[IPCOMP_STAT_QFULL], "queue full");
+ IPCOMP(ipcs[IPCOMP_STAT_NOXFORM],"no support for transform");
+ IPCOMP(ipcs[IPCOMP_STAT_WRAP], "packets dropped for replay counter wrap");
+ IPCOMP(ipcs[IPCOMP_STAT_INPUT], "input IPcomp packets");
+ IPCOMP(ipcs[IPCOMP_STAT_OUTPUT],"output IPcomp packets");
+ IPCOMP(ipcs[IPCOMP_STAT_INVALID],"packets with an invalid SA");
+ IPCOMP(ipcs[IPCOMP_STAT_TOOBIG],"packets decompressed as too big");
+ IPCOMP(ipcs[IPCOMP_STAT_MINLEN], "packets too short to be compressed");
+ IPCOMP(ipcs[IPCOMP_STAT_USELESS],"packet for which compression was useless");
+ IPCOMP(ipcs[IPCOMP_STAT_PDROPS],"packets blocked due to policy");
+ IPCOMP(ipcs[IPCOMP_STAT_CRYPTO],"failed crypto requests");
+
+ printf("\tIPcomp histogram:\n");
+ for (i = 0; i < IPCOMP_ALG_MAX; i++)
+ if (ipcs[IPCOMP_STAT_HIST + i])
+ printf("\t\tIPcomp packets with %s: %"PRIu64"\n"
+ , algname(i, ipcompalgs, N(ipcompalgs))
+ , ipcs[IPCOMP_STAT_HIST + i]
+ );
+ IPCOMP(ipcs[IPCOMP_STAT_IBYTES],"input bytes");
+ IPCOMP(ipcs[IPCOMP_STAT_OBYTES],"output bytes");
+#undef IPCOMP
+}
--- /dev/null
+/* $NetBSD: if.c,v 1.82 2015/09/20 00:30:04 mrg Exp $ */
+
+/*
+ * Copyright (c) 1983, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "from: @(#)if.c 8.2 (Berkeley) 2/21/94";
+#else
+__RCSID("$NetBSD: if.c,v 1.82 2015/09/20 00:30:04 mrg Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/sysctl.h>
+#include <sys/ioctl.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/in_var.h>
+#include <arpa/inet.h>
+
+#include <kvm.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <err.h>
+
+#include "netstat.h"
+#include "rtutil.h"
+#include "prog_ops.h"
+
+#define MAXIF 100
+
+#define HUMBUF_SIZE 7
+
+struct iftot {
+ char ift_name[IFNAMSIZ]; /* interface name */
+ u_quad_t ift_ip; /* input packets */
+ u_quad_t ift_ib; /* input bytes */
+ u_quad_t ift_ie; /* input errors */
+ u_quad_t ift_op; /* output packets */
+ u_quad_t ift_ob; /* output bytes */
+ u_quad_t ift_oe; /* output errors */
+ u_quad_t ift_co; /* collisions */
+ int ift_dr; /* drops */
+};
+
+static void set_lines(void);
+static void print_addr(struct sockaddr *, struct sockaddr **, struct if_data *,
+ struct ifnet *);
+static void sidewaysintpr(u_int, u_long);
+
+static void iftot_banner(struct iftot *);
+static void iftot_print_sum(struct iftot *, struct iftot *);
+static void iftot_print(struct iftot *, struct iftot *);
+
+static void catchalarm __P((int));
+static void get_rtaddrs(int, struct sockaddr *, struct sockaddr **);
+static void fetchifs(void);
+
+static void intpr_sysctl(void);
+static void intpr_kvm(u_long, void (*)(const char *));
+
+struct iftot iftot[MAXIF], ip_cur, ip_old, sum_cur, sum_old;
+bool signalled; /* set if alarm goes off "early" */
+
+static unsigned redraw_lines = 21;
+
+static void
+set_lines(void)
+{
+ static bool first = true;
+ struct ttysize ts;
+
+ if (!first)
+ return;
+ first = false;
+ if (ioctl(STDOUT_FILENO, TIOCGSIZE, &ts) != -1 && ts.ts_lines)
+ redraw_lines = ts.ts_lines - 3;
+}
+
+
+/*
+ * Print a description of the network interfaces.
+ * NOTE: ifnetaddr is the location of the kernel global "ifnet",
+ * which is a TAILQ_HEAD.
+ */
+void
+intpr(int interval, u_long ifnetaddr, void (*pfunc)(const char *))
+{
+
+ if (interval) {
+ sidewaysintpr((unsigned)interval, ifnetaddr);
+ return;
+ }
+
+ if (use_sysctl) {
+ intpr_sysctl();
+ } else {
+ intpr_kvm(ifnetaddr, pfunc);
+ }
+
+}
+
+static void
+intpr_header(void)
+{
+
+ if (!sflag & !pflag) {
+ if (bflag) {
+ printf("%-5.5s %-5.5s %-13.13s %-17.17s "
+ "%10.10s %10.10s",
+ "Name", "Mtu", "Network", "Address",
+ "Ibytes", "Obytes");
+ } else {
+ printf("%-5.5s %-5.5s %-13.13s %-17.17s "
+ "%8.8s %5.5s %8.8s %5.5s %5.5s",
+ "Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs",
+ "Opkts", "Oerrs", "Colls");
+ }
+ if (tflag)
+ printf(" %4.4s", "Time");
+ if (dflag)
+ printf(" %5.5s", "Drops");
+ putchar('\n');
+ }
+}
+
+static void
+intpr_sysctl(void)
+{
+ struct if_msghdr *ifm;
+ int mib[6] = { CTL_NET, AF_ROUTE, 0, 0, NET_RT_IFLIST, 0 };
+ char *buf = NULL, *next, *lim, *cp;
+ struct rt_msghdr *rtm;
+ struct ifa_msghdr *ifam;
+ struct if_data *ifd = NULL;
+ struct sockaddr *sa, *rti_info[RTAX_MAX];
+ struct sockaddr_dl *sdl;
+ uint64_t total = 0;
+ size_t len;
+ char name[IFNAMSIZ + 1]; /* + 1 for `*' */
+
+ if (prog_sysctl(mib, 6, NULL, &len, NULL, 0) == -1)
+ err(1, "sysctl");
+ if ((buf = malloc(len)) == NULL)
+ err(1, NULL);
+ if (prog_sysctl(mib, 6, buf, &len, NULL, 0) == -1)
+ err(1, "sysctl");
+
+ intpr_header();
+
+ lim = buf + len;
+ for (next = buf; next < lim; next += rtm->rtm_msglen) {
+ rtm = (struct rt_msghdr *)next;
+ if (rtm->rtm_version != RTM_VERSION)
+ continue;
+ switch (rtm->rtm_type) {
+ case RTM_IFINFO:
+ total = 0;
+ ifm = (struct if_msghdr *)next;
+ ifd = &ifm->ifm_data;
+
+ sa = (struct sockaddr *)(ifm + 1);
+ get_rtaddrs(ifm->ifm_addrs, sa, rti_info);
+
+ sdl = (struct sockaddr_dl *)rti_info[RTAX_IFP];
+ if (sdl == NULL || sdl->sdl_family != AF_LINK) {
+ continue;
+ }
+ bzero(name, sizeof(name));
+ if (sdl->sdl_nlen >= IFNAMSIZ)
+ memcpy(name, sdl->sdl_data, IFNAMSIZ - 1);
+ else if (sdl->sdl_nlen > 0)
+ memcpy(name, sdl->sdl_data, sdl->sdl_nlen);
+
+ if (interface != 0 && strcmp(name, interface) != 0)
+ continue;
+
+ /* mark inactive interfaces with a '*' */
+ cp = strchr(name, '\0');
+ if ((ifm->ifm_flags & IFF_UP) == 0)
+ *cp++ = '*';
+ *cp = '\0';
+
+ if (qflag) {
+ total = ifd->ifi_ibytes + ifd->ifi_obytes +
+ ifd->ifi_ipackets + ifd->ifi_ierrors +
+ ifd->ifi_opackets + ifd->ifi_oerrors +
+ ifd->ifi_collisions;
+ if (tflag)
+ total += 0; // XXX-elad ifnet.if_timer;
+ if (dflag)
+ total += 0; // XXX-elad ifnet.if_snd.ifq_drops;
+ if (total == 0)
+ continue;
+ }
+
+ printf("%-5s %-5" PRIu64, name, ifd->ifi_mtu);
+#ifdef __minix
+ /* There should be a space between Mtu and Network. */
+ printf(" ");
+#endif /* __minix */
+ print_addr(rti_info[RTAX_IFP], rti_info, ifd, NULL);
+ break;
+
+ case RTM_NEWADDR:
+ if (qflag && total == 0)
+ continue;
+ if (interface != 0 && strcmp(name, interface) != 0)
+ continue;
+ ifam = (struct ifa_msghdr *)next;
+ if ((ifam->ifam_addrs & (RTA_NETMASK | RTA_IFA |
+ RTA_BRD)) == 0)
+ break;
+
+ sa = (struct sockaddr *)(ifam + 1);
+
+ get_rtaddrs(ifam->ifam_addrs, sa, rti_info);
+
+ printf("%-5s %-5" PRIu64, name, ifd->ifi_mtu);
+#ifdef __minix
+ /*
+ * There should be a space between Mtu and Network.
+ * Maintainer's note: this has been fixed in NetBSD
+ * upstream already; drop this change as soon as it
+ * creates any conflict at all! --dcvmoole
+ */
+ printf(" ");
+#endif /* __minix */
+ print_addr(rti_info[RTAX_IFA], rti_info, ifd, NULL);
+ break;
+ }
+ }
+}
+
+union ifaddr_u {
+ struct ifaddr ifa;
+ struct in_ifaddr in;
+#ifdef INET6
+ struct in6_ifaddr in6;
+#endif /* INET6 */
+};
+
+static void
+intpr_kvm(u_long ifnetaddr, void (*pfunc)(const char *))
+{
+ struct ifnet ifnet;
+ union ifaddr_u ifaddr;
+ u_long ifaddraddr;
+ struct ifnet_head ifhead; /* TAILQ_HEAD */
+ char name[IFNAMSIZ + 1]; /* + 1 for `*' */
+
+ if (ifnetaddr == 0) {
+ printf("ifnet: symbol not defined\n");
+ return;
+ }
+
+ /*
+ * Find the pointer to the first ifnet structure. Replace
+ * the pointer to the TAILQ_HEAD with the actual pointer
+ * to the first list element.
+ */
+ if (kread(ifnetaddr, (char *)&ifhead, sizeof ifhead))
+ return;
+ ifnetaddr = (u_long)ifhead.tqh_first;
+
+ intpr_header();
+
+ ifaddraddr = 0;
+ while (ifnetaddr || ifaddraddr) {
+ char *cp;
+ int n;
+
+ if (ifaddraddr == 0) {
+ if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet))
+ return;
+ memmove(name, ifnet.if_xname, IFNAMSIZ);
+ name[IFNAMSIZ - 1] = '\0'; /* sanity */
+ ifnetaddr = (u_long)ifnet.if_list.tqe_next;
+ if (interface != 0 && strcmp(name, interface) != 0)
+ continue;
+ cp = strchr(name, '\0');
+
+ if (pfunc) {
+ (*pfunc)(name);
+ continue;
+ }
+
+ if ((ifnet.if_flags & IFF_UP) == 0)
+ *cp++ = '*';
+ *cp = '\0';
+ ifaddraddr = (u_long)ifnet.if_addrlist.tqh_first;
+ }
+ if (vflag)
+ n = strlen(name) < 5 ? 5 : strlen(name);
+ else
+ n = 5;
+ printf("%-*.*s %-5llu ", n, n, name,
+ (unsigned long long)ifnet.if_mtu);
+ if (ifaddraddr == 0) {
+ printf("%-13.13s ", "none");
+ printf("%-17.17s ", "none");
+ } else {
+ struct sockaddr *sa;
+
+ if (kread(ifaddraddr, (char *)&ifaddr, sizeof ifaddr)) {
+ ifaddraddr = 0;
+ continue;
+ }
+#define CP(x) ((char *)(x))
+ cp = (CP(ifaddr.ifa.ifa_addr) - CP(ifaddraddr)) +
+ CP(&ifaddr);
+ sa = (struct sockaddr *)cp;
+ print_addr(sa, (void *)&ifaddr, &ifnet.if_data, &ifnet);
+ }
+ ifaddraddr = (u_long)ifaddr.ifa.ifa_list.tqe_next;
+ }
+
+}
+
+static void
+print_addr(struct sockaddr *sa, struct sockaddr **rtinfo, struct if_data *ifd,
+ struct ifnet *ifnet)
+{
+ char hexsep = '.'; /* for hexprint */
+ static const char hexfmt[] = "%02x%c"; /* for hexprint */
+ char hbuf[NI_MAXHOST]; /* for getnameinfo() */
+#ifdef INET6
+ const int niflag = NI_NUMERICHOST;
+ struct sockaddr_in6 *sin6, *netmask6;
+#endif
+ struct sockaddr_in netmask;
+ struct sockaddr_in *sin;
+ char *cp;
+ int n, m;
+
+ switch (sa->sa_family) {
+ case AF_UNSPEC:
+ printf("%-13.13s ", "none");
+ printf("%-17.17s ", "none");
+ break;
+ case AF_INET:
+ sin = (struct sockaddr_in *)sa;
+ if (use_sysctl) {
+ netmask = *((struct sockaddr_in *)rtinfo[RTAX_NETMASK]);
+ } else {
+ struct in_ifaddr *ifaddr_in = (void *)rtinfo;
+ netmask.sin_addr.s_addr = ifaddr_in->ia_subnetmask;
+ }
+ cp = netname4(sin, &netmask, nflag);
+ if (vflag)
+ n = strlen(cp) < 13 ? 13 : strlen(cp);
+ else
+ n = 13;
+ printf("%-*.*s ", n, n, cp);
+ cp = routename4(sin->sin_addr.s_addr, nflag);
+ if (vflag)
+ n = strlen(cp) < 17 ? 17 : strlen(cp);
+ else
+ n = 17;
+ printf("%-*.*s ", n, n, cp);
+
+ if (aflag && ifnet) {
+ u_long multiaddr;
+ struct in_multi inm;
+ union ifaddr_u *ifaddr = (union ifaddr_u *)rtinfo;
+
+ multiaddr = (u_long)
+ ifaddr->in.ia_multiaddrs.lh_first;
+ while (multiaddr != 0) {
+ kread(multiaddr, (char *)&inm,
+ sizeof inm);
+ printf("\n%25s %-17.17s ", "",
+ routename4(
+ inm.inm_addr.s_addr, nflag));
+ multiaddr =
+ (u_long)inm.inm_list.le_next;
+ }
+ }
+ break;
+#ifdef INET6
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *)sa;
+ inet6_getscopeid(sin6, INET6_IS_ADDR_LINKLOCAL);
+#ifdef __KAME__
+ if (!vflag)
+ sin6->sin6_scope_id = 0;
+#endif
+
+ if (use_sysctl) {
+ netmask6 = (struct sockaddr_in6 *)rtinfo[RTAX_NETMASK];
+ } else {
+ struct in6_ifaddr *ifaddr_in6 = (void *)rtinfo;
+ netmask6 = &ifaddr_in6->ia_prefixmask;
+ }
+
+ cp = netname6(sin6, netmask6, nflag);
+ if (vflag)
+ n = strlen(cp) < 13 ? 13 : strlen(cp);
+ else
+ n = 13;
+ printf("%-*.*s ", n, n, cp);
+ if (getnameinfo((struct sockaddr *)sin6,
+ sin6->sin6_len,
+ hbuf, sizeof(hbuf), NULL, 0,
+ niflag) != 0) {
+ strlcpy(hbuf, "?", sizeof(hbuf));
+ }
+ cp = hbuf;
+ if (vflag)
+ n = strlen(cp) < 17 ? 17 : strlen(cp);
+ else
+ n = 17;
+ printf("%-*.*s ", n, n, cp);
+
+ if (aflag && ifnet) {
+ u_long multiaddr;
+ struct in6_multi inm;
+ struct sockaddr_in6 as6;
+ union ifaddr_u *ifaddr = (union ifaddr_u *)rtinfo;
+
+ multiaddr = (u_long)
+ ifaddr->in6.ia6_multiaddrs.lh_first;
+ while (multiaddr != 0) {
+ kread(multiaddr, (char *)&inm,
+ sizeof inm);
+ memset(&as6, 0, sizeof(as6));
+ as6.sin6_len = sizeof(struct sockaddr_in6);
+ as6.sin6_family = AF_INET6;
+ as6.sin6_addr = inm.in6m_addr;
+ inet6_getscopeid(&as6,
+ INET6_IS_ADDR_MC_LINKLOCAL);
+ if (getnameinfo((struct sockaddr *)&as6,
+ as6.sin6_len, hbuf,
+ sizeof(hbuf), NULL, 0,
+ niflag) != 0) {
+ strlcpy(hbuf, "??",
+ sizeof(hbuf));
+ }
+ cp = hbuf;
+ if (vflag)
+ n = strlen(cp) < 17
+ ? 17 : strlen(cp);
+ else
+ n = 17;
+ printf("\n%25s %-*.*s ", "",
+ n, n, cp);
+ multiaddr =
+ (u_long)inm.in6m_entry.le_next;
+ }
+ }
+ break;
+#endif /*INET6*/
+#ifndef SMALL
+ case AF_APPLETALK:
+ printf("atalk:%-7.7s ",
+ atalk_print(sa,0x10));
+ printf("%-17.17s ", atalk_print(sa,0x0b));
+ break;
+#endif
+ case AF_LINK:
+ printf("%-13.13s ", "<Link>");
+ if (getnameinfo(sa, sa->sa_len,
+ hbuf, sizeof(hbuf), NULL, 0,
+ NI_NUMERICHOST) != 0) {
+ strlcpy(hbuf, "?", sizeof(hbuf));
+ }
+ cp = hbuf;
+ if (vflag)
+ n = strlen(cp) < 17 ? 17 : strlen(cp);
+ else
+ n = 17;
+ printf("%-*.*s ", n, n, cp);
+ break;
+
+ default:
+ m = printf("(%d)", sa->sa_family);
+ for (cp = sa->sa_len + (char *)sa;
+ --cp > sa->sa_data && (*cp == 0);) {}
+ n = cp - sa->sa_data + 1;
+ cp = sa->sa_data;
+
+ while (--n >= 0)
+ m += printf(hexfmt, *cp++ & 0xff,
+ n > 0 ? hexsep : ' ');
+ m = 32 - m;
+ while (m-- > 0)
+ putchar(' ');
+ break;
+ }
+
+ if (bflag) {
+ char humbuf[HUMBUF_SIZE];
+
+ if (hflag && humanize_number(humbuf, sizeof(humbuf),
+ ifd->ifi_ibytes, "", HN_AUTOSCALE, HN_NOSPACE | HN_B) > 0)
+ printf("%10s ", humbuf);
+ else
+ printf("%10llu ", (unsigned long long)ifd->ifi_ibytes);
+
+ if (hflag && humanize_number(humbuf, sizeof(humbuf),
+ ifd->ifi_obytes, "", HN_AUTOSCALE, HN_NOSPACE | HN_B) > 0)
+ printf("%10s", humbuf);
+ else
+ printf("%10llu", (unsigned long long)ifd->ifi_obytes);
+ } else {
+ printf("%8llu %5llu %8llu %5llu %5llu",
+ (unsigned long long)ifd->ifi_ipackets,
+ (unsigned long long)ifd->ifi_ierrors,
+ (unsigned long long)ifd->ifi_opackets,
+ (unsigned long long)ifd->ifi_oerrors,
+ (unsigned long long)ifd->ifi_collisions);
+ }
+ if (tflag)
+ printf(" %4d", ifnet ? ifnet->if_timer : 0);
+ if (dflag)
+ printf(" %5d", ifnet ? ifnet->if_snd.ifq_drops : 0);
+ putchar('\n');
+}
+
+static void
+iftot_banner(struct iftot *ift)
+{
+ if (bflag)
+ printf("%7.7s in %8.8s %6.6s out %5.5s",
+ ift->ift_name, " ",
+ ift->ift_name, " ");
+ else
+ printf("%5.5s in %5.5s%5.5s out %5.5s %5.5s",
+ ift->ift_name, " ",
+ ift->ift_name, " ", " ");
+ if (dflag)
+ printf(" %5.5s", " ");
+
+ if (bflag)
+ printf(" %7.7s in %8.8s %6.6s out %5.5s",
+ "total", " ", "total", " ");
+ else
+ printf(" %5.5s in %5.5s%5.5s out %5.5s %5.5s",
+ "total", " ", "total", " ", " ");
+ if (dflag)
+ printf(" %5.5s", " ");
+ putchar('\n');
+ if (bflag)
+ printf("%10.10s %8.8s %10.10s %5.5s",
+ "bytes", " ", "bytes", " ");
+ else
+ printf("%8.8s %5.5s %8.8s %5.5s %5.5s",
+ "packets", "errs", "packets", "errs", "colls");
+ if (dflag)
+ printf(" %5.5s", "drops");
+
+ if (bflag)
+ printf(" %10.10s %8.8s %10.10s %5.5s",
+ "bytes", " ", "bytes", " ");
+ else
+ printf(" %8.8s %5.5s %8.8s %5.5s %5.5s",
+ "packets", "errs", "packets", "errs", "colls");
+ if (dflag)
+ printf(" %5.5s", "drops");
+ putchar('\n');
+ fflush(stdout);
+}
+
+static void
+iftot_print(struct iftot *cur, struct iftot *old)
+{
+ if (bflag)
+ printf("%10" PRIu64 " %8.8s %10" PRIu64 " %5.5s",
+ cur->ift_ib - old->ift_ib, " ",
+ cur->ift_ob - old->ift_ob, " ");
+ else
+ printf("%8" PRIu64 " %5" PRIu64 " %8" PRIu64 " %5" PRIu64 " %5" PRIu64,
+ cur->ift_ip - old->ift_ip,
+ cur->ift_ie - old->ift_ie,
+ cur->ift_op - old->ift_op,
+ cur->ift_oe - old->ift_oe,
+ cur->ift_co - old->ift_co);
+ if (dflag)
+ printf(" %5llu",
+ /* XXX ifnet.if_snd.ifq_drops - ip->ift_dr); */
+ 0LL);
+}
+
+static void
+iftot_print_sum(struct iftot *cur, struct iftot *old)
+{
+ if (bflag)
+ printf(" %10" PRIu64 " %8.8s %10" PRIu64 " %5.5s",
+ cur->ift_ib - old->ift_ib, " ",
+ cur->ift_ob - old->ift_ob, " ");
+ else
+ printf(" %8" PRIu64 " %5" PRIu64 " %8" PRIu64 " %5" PRIu64 " %5" PRIu64,
+ cur->ift_ip - old->ift_ip,
+ cur->ift_ie - old->ift_ie,
+ cur->ift_op - old->ift_op,
+ cur->ift_oe - old->ift_oe,
+ cur->ift_co - old->ift_co);
+
+ if (dflag)
+ printf(" %5llu", (unsigned long long)(cur->ift_dr - old->ift_dr));
+}
+
+__dead static void
+sidewaysintpr_sysctl(unsigned interval)
+{
+ sigset_t emptyset;
+ unsigned line;
+
+ set_lines();
+
+ fetchifs();
+ if (ip_cur.ift_name[0] == '\0') {
+ fprintf(stderr, "%s: %s: unknown interface\n",
+ getprogname(), interface);
+ exit(1);
+ }
+
+ (void)signal(SIGALRM, catchalarm);
+ signalled = 0;
+ (void)alarm(interval);
+banner:
+ iftot_banner(&ip_cur);
+
+ line = 0;
+ bzero(&ip_old, sizeof(ip_old));
+ bzero(&sum_old, sizeof(sum_old));
+loop:
+ bzero(&sum_cur, sizeof(sum_cur));
+
+ fetchifs();
+
+ iftot_print(&ip_cur, &ip_old);
+
+ ip_old = ip_cur;
+
+ iftot_print_sum(&sum_cur, &sum_old);
+
+ sum_old = sum_cur;
+
+ putchar('\n');
+ fflush(stdout);
+ line++;
+ sigemptyset(&emptyset);
+ if (!signalled)
+ sigsuspend(&emptyset);
+ signalled = 0;
+ (void)alarm(interval);
+ if (line == redraw_lines)
+ goto banner;
+ goto loop;
+ /*NOTREACHED*/
+}
+
+static void
+sidewaysintpr_kvm(unsigned interval, u_long off)
+{
+ struct itimerval it;
+ struct ifnet ifnet;
+ u_long firstifnet;
+ struct iftot *ip, *total;
+ unsigned line;
+ struct iftot *lastif, *sum, *interesting;
+ struct ifnet_head ifhead; /* TAILQ_HEAD */
+ int oldmask;
+
+ set_lines();
+
+ /*
+ * Find the pointer to the first ifnet structure. Replace
+ * the pointer to the TAILQ_HEAD with the actual pointer
+ * to the first list element.
+ */
+ if (kread(off, (char *)&ifhead, sizeof ifhead))
+ return;
+ firstifnet = (u_long)ifhead.tqh_first;
+
+ lastif = iftot;
+ sum = iftot + MAXIF - 1;
+ total = sum - 1;
+ interesting = (interface == NULL) ? iftot : NULL;
+ for (off = firstifnet, ip = iftot; off;) {
+ if (kread(off, (char *)&ifnet, sizeof ifnet))
+ break;
+ memset(ip->ift_name, 0, sizeof(ip->ift_name));
+ snprintf(ip->ift_name, IFNAMSIZ, "%s", ifnet.if_xname);
+ if (interface && strcmp(ifnet.if_xname, interface) == 0)
+ interesting = ip;
+ ip++;
+ if (ip >= iftot + MAXIF - 2)
+ break;
+ off = (u_long)ifnet.if_list.tqe_next;
+ }
+ if (interesting == NULL) {
+ fprintf(stderr, "%s: %s: unknown interface\n",
+ getprogname(), interface);
+ exit(1);
+ }
+ lastif = ip;
+
+ (void)signal(SIGALRM, catchalarm);
+ signalled = false;
+
+ it.it_interval.tv_sec = it.it_value.tv_sec = interval;
+ it.it_interval.tv_usec = it.it_value.tv_usec = 0;
+ setitimer(ITIMER_REAL, &it, NULL);
+
+banner:
+ if (bflag)
+ printf("%7.7s in %8.8s %6.6s out %5.5s",
+ interesting->ift_name, " ",
+ interesting->ift_name, " ");
+ else
+ printf("%5.5s in %5.5s%5.5s out %5.5s %5.5s",
+ interesting->ift_name, " ",
+ interesting->ift_name, " ", " ");
+ if (dflag)
+ printf(" %5.5s", " ");
+ if (lastif - iftot > 0) {
+ if (bflag)
+ printf(" %7.7s in %8.8s %6.6s out %5.5s",
+ "total", " ", "total", " ");
+ else
+ printf(" %5.5s in %5.5s%5.5s out %5.5s %5.5s",
+ "total", " ", "total", " ", " ");
+ if (dflag)
+ printf(" %5.5s", " ");
+ }
+ for (ip = iftot; ip < iftot + MAXIF; ip++) {
+ ip->ift_ip = 0;
+ ip->ift_ib = 0;
+ ip->ift_ie = 0;
+ ip->ift_op = 0;
+ ip->ift_ob = 0;
+ ip->ift_oe = 0;
+ ip->ift_co = 0;
+ ip->ift_dr = 0;
+ }
+ putchar('\n');
+ if (bflag)
+ printf("%10.10s %8.8s %10.10s %5.5s",
+ "bytes", " ", "bytes", " ");
+ else
+ printf("%8.8s %5.5s %8.8s %5.5s %5.5s",
+ "packets", "errs", "packets", "errs", "colls");
+ if (dflag)
+ printf(" %5.5s", "drops");
+ if (lastif - iftot > 0) {
+ if (bflag)
+ printf(" %10.10s %8.8s %10.10s %5.5s",
+ "bytes", " ", "bytes", " ");
+ else
+ printf(" %8.8s %5.5s %8.8s %5.5s %5.5s",
+ "packets", "errs", "packets", "errs", "colls");
+ if (dflag)
+ printf(" %5.5s", "drops");
+ }
+ putchar('\n');
+ fflush(stdout);
+ line = 0;
+loop:
+ sum->ift_ip = 0;
+ sum->ift_ib = 0;
+ sum->ift_ie = 0;
+ sum->ift_op = 0;
+ sum->ift_ob = 0;
+ sum->ift_oe = 0;
+ sum->ift_co = 0;
+ sum->ift_dr = 0;
+ for (off = firstifnet, ip = iftot; off && ip < lastif; ip++) {
+ if (kread(off, (char *)&ifnet, sizeof ifnet)) {
+ off = 0;
+ continue;
+ }
+ if (ip == interesting) {
+ if (bflag) {
+ char humbuf[HUMBUF_SIZE];
+
+ if (hflag && humanize_number(humbuf,
+ sizeof(humbuf),
+ ifnet.if_ibytes - ip->ift_ib, "",
+ HN_AUTOSCALE, HN_NOSPACE | HN_B) > 0)
+ printf("%10s %8.8s ", humbuf, " ");
+ else
+ printf("%10llu %8.8s ",
+ (unsigned long long)
+ (ifnet.if_ibytes-ip->ift_ib), " ");
+
+ if (hflag && humanize_number(humbuf,
+ sizeof(humbuf),
+ ifnet.if_obytes - ip->ift_ob, "",
+ HN_AUTOSCALE, HN_NOSPACE | HN_B) > 0)
+ printf("%10s %5.5s", humbuf, " ");
+ else
+ printf("%10llu %5.5s",
+ (unsigned long long)
+ (ifnet.if_obytes-ip->ift_ob), " ");
+ } else {
+ printf("%8llu %5llu %8llu %5llu %5llu",
+ (unsigned long long)
+ (ifnet.if_ipackets - ip->ift_ip),
+ (unsigned long long)
+ (ifnet.if_ierrors - ip->ift_ie),
+ (unsigned long long)
+ (ifnet.if_opackets - ip->ift_op),
+ (unsigned long long)
+ (ifnet.if_oerrors - ip->ift_oe),
+ (unsigned long long)
+ (ifnet.if_collisions - ip->ift_co));
+ }
+ if (dflag)
+ printf(" %5llu",
+ (unsigned long long)
+ (ifnet.if_snd.ifq_drops - ip->ift_dr));
+ }
+ ip->ift_ip = ifnet.if_ipackets;
+ ip->ift_ib = ifnet.if_ibytes;
+ ip->ift_ie = ifnet.if_ierrors;
+ ip->ift_op = ifnet.if_opackets;
+ ip->ift_ob = ifnet.if_obytes;
+ ip->ift_oe = ifnet.if_oerrors;
+ ip->ift_co = ifnet.if_collisions;
+ ip->ift_dr = ifnet.if_snd.ifq_drops;
+ sum->ift_ip += ip->ift_ip;
+ sum->ift_ib += ip->ift_ib;
+ sum->ift_ie += ip->ift_ie;
+ sum->ift_op += ip->ift_op;
+ sum->ift_ob += ip->ift_ob;
+ sum->ift_oe += ip->ift_oe;
+ sum->ift_co += ip->ift_co;
+ sum->ift_dr += ip->ift_dr;
+ off = (u_long)ifnet.if_list.tqe_next;
+ }
+ if (lastif - iftot > 0) {
+ if (bflag) {
+ char humbuf[HUMBUF_SIZE];
+
+ if (hflag && humanize_number(humbuf,
+ sizeof(humbuf), sum->ift_ib - total->ift_ib, "",
+ HN_AUTOSCALE, HN_NOSPACE | HN_B) > 0)
+ printf(" %10s %8.8s ", humbuf, " ");
+ else
+ printf(" %10llu %8.8s ",
+ (unsigned long long)
+ (sum->ift_ib - total->ift_ib), " ");
+
+ if (hflag && humanize_number(humbuf,
+ sizeof(humbuf), sum->ift_ob - total->ift_ob, "",
+ HN_AUTOSCALE, HN_NOSPACE | HN_B) > 0)
+ printf("%10s %5.5s", humbuf, " ");
+ else
+ printf("%10llu %5.5s",
+ (unsigned long long)
+ (sum->ift_ob - total->ift_ob), " ");
+ } else {
+ printf(" %8llu %5llu %8llu %5llu %5llu",
+ (unsigned long long)
+ (sum->ift_ip - total->ift_ip),
+ (unsigned long long)
+ (sum->ift_ie - total->ift_ie),
+ (unsigned long long)
+ (sum->ift_op - total->ift_op),
+ (unsigned long long)
+ (sum->ift_oe - total->ift_oe),
+ (unsigned long long)
+ (sum->ift_co - total->ift_co));
+ }
+ if (dflag)
+ printf(" %5llu",
+ (unsigned long long)(sum->ift_dr - total->ift_dr));
+ }
+ *total = *sum;
+ putchar('\n');
+ fflush(stdout);
+ line++;
+ oldmask = sigblock(sigmask(SIGALRM));
+ if (! signalled) {
+ sigpause(0);
+ }
+ sigsetmask(oldmask);
+ signalled = false;
+ if (line == redraw_lines)
+ goto banner;
+ goto loop;
+ /*NOTREACHED*/
+}
+
+/*
+ * Print a running summary of interface statistics.
+ * Repeat display every interval seconds, showing statistics
+ * collected over that interval. Assumes that interval is non-zero.
+ * First line printed at top of screen is always cumulative.
+ */
+static void
+sidewaysintpr(unsigned int interval, u_long off)
+{
+
+ if (use_sysctl) {
+ sidewaysintpr_sysctl(interval);
+ } else {
+ sidewaysintpr_kvm(interval, off);
+ }
+}
+
+/*
+ * Called if an interval expires before sidewaysintpr has completed a loop.
+ * Sets a flag to not wait for the alarm.
+ */
+static void
+catchalarm(int signo)
+{
+
+ signalled = true;
+}
+
+static void
+get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
+{
+ int i;
+
+ for (i = 0; i < RTAX_MAX; i++) {
+ if (addrs & (1 << i)) {
+ rti_info[i] = sa;
+ sa = (struct sockaddr *)((char *)(sa) +
+ RT_ROUNDUP(sa->sa_len));
+ } else
+ rti_info[i] = NULL;
+ }
+}
+
+static void
+fetchifs(void)
+{
+ struct if_msghdr *ifm;
+ int mib[6] = { CTL_NET, AF_ROUTE, 0, 0, NET_RT_IFLIST, 0 };
+ struct rt_msghdr *rtm;
+ struct if_data *ifd = NULL;
+ struct sockaddr *sa, *rti_info[RTAX_MAX];
+ struct sockaddr_dl *sdl;
+ char *buf, *next, *lim;
+ char name[IFNAMSIZ];
+ size_t len;
+
+ if (prog_sysctl(mib, 6, NULL, &len, NULL, 0) == -1)
+ err(1, "sysctl");
+ if ((buf = malloc(len)) == NULL)
+ err(1, NULL);
+ if (prog_sysctl(mib, 6, buf, &len, NULL, 0) == -1)
+ err(1, "sysctl");
+
+ lim = buf + len;
+ for (next = buf; next < lim; next += rtm->rtm_msglen) {
+ rtm = (struct rt_msghdr *)next;
+ if (rtm->rtm_version != RTM_VERSION)
+ continue;
+ switch (rtm->rtm_type) {
+ case RTM_IFINFO:
+ ifm = (struct if_msghdr *)next;
+ ifd = &ifm->ifm_data;
+
+ sa = (struct sockaddr *)(ifm + 1);
+ get_rtaddrs(ifm->ifm_addrs, sa, rti_info);
+
+ sdl = (struct sockaddr_dl *)rti_info[RTAX_IFP];
+ if (sdl == NULL || sdl->sdl_family != AF_LINK)
+ continue;
+ bzero(name, sizeof(name));
+ if (sdl->sdl_nlen >= IFNAMSIZ)
+ memcpy(name, sdl->sdl_data, IFNAMSIZ - 1);
+ else if (sdl->sdl_nlen > 0)
+ memcpy(name, sdl->sdl_data, sdl->sdl_nlen);
+
+ if (interface != 0 && !strcmp(name, interface)) {
+ strlcpy(ip_cur.ift_name, name,
+ sizeof(ip_cur.ift_name));
+ ip_cur.ift_ip = ifd->ifi_ipackets;
+ ip_cur.ift_ib = ifd->ifi_ibytes;
+ ip_cur.ift_ie = ifd->ifi_ierrors;
+ ip_cur.ift_op = ifd->ifi_opackets;
+ ip_cur.ift_ob = ifd->ifi_obytes;
+ ip_cur.ift_oe = ifd->ifi_oerrors;
+ ip_cur.ift_co = ifd->ifi_collisions;
+ ip_cur.ift_dr = 0;
+ /* XXX-elad ifnet.if_snd.ifq_drops */
+ }
+
+ sum_cur.ift_ip += ifd->ifi_ipackets;
+ sum_cur.ift_ib += ifd->ifi_ibytes;
+ sum_cur.ift_ie += ifd->ifi_ierrors;
+ sum_cur.ift_op += ifd->ifi_opackets;
+ sum_cur.ift_ob += ifd->ifi_obytes;
+ sum_cur.ift_oe += ifd->ifi_oerrors;
+ sum_cur.ift_co += ifd->ifi_collisions;
+ sum_cur.ift_dr += 0; /* XXX-elad ifnet.if_snd.ifq_drops */
+ break;
+ }
+ }
+ if (interface == NULL) {
+ strlcpy(ip_cur.ift_name, name,
+ sizeof(ip_cur.ift_name));
+ ip_cur.ift_ip = ifd->ifi_ipackets;
+ ip_cur.ift_ib = ifd->ifi_ibytes;
+ ip_cur.ift_ie = ifd->ifi_ierrors;
+ ip_cur.ift_op = ifd->ifi_opackets;
+ ip_cur.ift_ob = ifd->ifi_obytes;
+ ip_cur.ift_oe = ifd->ifi_oerrors;
+ ip_cur.ift_co = ifd->ifi_collisions;
+ ip_cur.ift_dr = 0;
+ /* XXX-elad ifnet.if_snd.ifq_drops */
+ }
+}
--- /dev/null
+/* $NetBSD: inet.c,v 1.106 2015/02/08 15:09:45 christos Exp $ */
+
+/*
+ * Copyright (c) 1983, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "from: @(#)inet.c 8.4 (Berkeley) 4/20/94";
+#else
+__RCSID("$NetBSD: inet.c,v 1.106 2015/02/08 15:09:45 christos Exp $");
+#endif
+#endif /* not lint */
+
+#define _CALLOUT_PRIVATE /* for defs in sys/callout.h */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/mbuf.h>
+#include <sys/protosw.h>
+#include <sys/sysctl.h>
+
+#include <net/if_arp.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/in_pcb.h>
+#define ICMP_STRINGS
+#include <netinet/ip_icmp.h>
+
+#ifdef INET6
+#include <netinet/ip6.h>
+#endif
+
+#include <netinet/icmp_var.h>
+#include <netinet/igmp_var.h>
+#include <netinet/ip_var.h>
+#include <netinet/pim_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+#include <netinet/tcp_seq.h>
+#define TCPSTATES
+#include <netinet/tcp_fsm.h>
+#define TCPTIMERS
+#include <netinet/tcp_timer.h>
+#include <netinet/tcp_var.h>
+#include <netinet/tcp_debug.h>
+#include <netinet/udp.h>
+#include <netinet/ip_carp.h>
+#include <netinet/udp_var.h>
+#include <netinet/tcp_vtw.h>
+
+#include <arpa/inet.h>
+#include <kvm.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <err.h>
+#include <util.h>
+#include "netstat.h"
+#include "vtw.h"
+#include "prog_ops.h"
+
+char *inetname(struct in_addr *);
+void inetprint(struct in_addr *, u_int16_t, const char *, int);
+
+void print_vtw_v4(const vtw_t *);
+
+/*
+ * Print a summary of connections related to an Internet
+ * protocol. For TCP, also give state of connection.
+ * Listening processes (aflag) are suppressed unless the
+ * -a (all) flag is specified.
+ */
+static int width;
+static int compact;
+
+/* VTW-related variables. */
+static struct timeval now;
+
+static void
+protoprhdr(void)
+{
+ printf("Active Internet connections");
+ if (aflag)
+ printf(" (including servers)");
+ putchar('\n');
+ if (Aflag)
+ printf("%-8.8s ", "PCB");
+ printf(
+ Vflag ? "%-5.5s %-6.6s %-6.6s %s%-*.*s %-*.*s %-13.13s Expires\n"
+ : "%-5.5s %-6.6s %-6.6s %s%-*.*s %-*.*s %s\n",
+ "Proto", "Recv-Q", "Send-Q", compact ? "" : " ",
+ width, width, "Local Address",
+ width, width, "Foreign Address",
+ "State");
+}
+
+static void
+protopr0(intptr_t ppcb, u_long rcv_sb_cc, u_long snd_sb_cc,
+ struct in_addr *laddr, u_int16_t lport,
+ struct in_addr *faddr, u_int16_t fport,
+ short t_state, const char *name, int inp_flags,
+ const struct timeval *expires)
+{
+ static const char *shorttcpstates[] = {
+ "CLOSED", "LISTEN", "SYNSEN", "SYSRCV",
+ "ESTABL", "CLWAIT", "FWAIT1", "CLOSNG",
+ "LASTAK", "FWAIT2", "TMWAIT",
+ };
+ int istcp;
+
+ istcp = strcmp(name, "tcp") == 0;
+
+ if (Aflag) {
+ printf("%8" PRIxPTR " ", ppcb);
+ }
+ printf("%-5.5s %6ld %6ld%s", name, rcv_sb_cc, snd_sb_cc,
+ compact ? "" : " ");
+ if (numeric_port) {
+ inetprint(laddr, lport, name, 1);
+ inetprint(faddr, fport, name, 1);
+ } else if (inp_flags & INP_ANONPORT) {
+ inetprint(laddr, lport, name, 1);
+ inetprint(faddr, fport, name, 0);
+ } else {
+ inetprint(laddr, lport, name, 0);
+ inetprint(faddr, fport, name, 0);
+ }
+ if (istcp) {
+ if (t_state < 0 || t_state >= TCP_NSTATES)
+ printf(" %d", t_state);
+ else
+ printf(" %s", compact ? shorttcpstates[t_state] :
+ tcpstates[t_state]);
+ }
+ if (Vflag && expires != NULL) {
+ if (expires->tv_sec == 0 && expires->tv_usec == -1)
+ printf(" reclaimed");
+ else {
+ struct timeval delta;
+
+ timersub(expires, &now, &delta);
+ printf(" %.3fms",
+ delta.tv_sec * 1000.0 + delta.tv_usec / 1000.0);
+ }
+ }
+ putchar('\n');
+}
+
+static void
+dbg_printf(const char *fmt, ...)
+{
+ return;
+}
+
+void
+print_vtw_v4(const vtw_t *vtw)
+{
+ const vtw_v4_t *v4 = (const vtw_v4_t *)vtw;
+ struct timeval delta;
+ struct in_addr la, fa;
+ char buf[2][32];
+ static const struct timeval zero = {.tv_sec = 0, .tv_usec = 0};
+
+ la.s_addr = v4->laddr;
+ fa.s_addr = v4->faddr;
+
+ snprintf(&buf[0][0], 32, "%s", inet_ntoa(la));
+ snprintf(&buf[1][0], 32, "%s", inet_ntoa(fa));
+
+ timersub(&vtw->expire, &now, &delta);
+
+ if (vtw->expire.tv_sec == 0 && vtw->expire.tv_usec == -1) {
+ dbg_printf("%15.15s:%d %15.15s:%d reclaimed\n"
+ ,buf[0], ntohs(v4->lport)
+ ,buf[1], ntohs(v4->fport));
+ if (!(Vflag && vflag))
+ return;
+ } else if (vtw->expire.tv_sec == 0)
+ return;
+ else if (timercmp(&delta, &zero, <) && !(Vflag && vflag)) {
+ dbg_printf("%15.15s:%d %15.15s:%d expired\n"
+ ,buf[0], ntohs(v4->lport)
+ ,buf[1], ntohs(v4->fport));
+ return;
+ } else {
+ dbg_printf("%15.15s:%d %15.15s:%d expires in %.3fms\n"
+ ,buf[0], ntohs(v4->lport)
+ ,buf[1], ntohs(v4->fport)
+ ,delta.tv_sec * 1000.0 + delta.tv_usec / 1000.0);
+ }
+ protopr0(0, 0, 0,
+ &la, v4->lport,
+ &fa, v4->fport,
+ TCPS_TIME_WAIT, "tcp", 0, &vtw->expire);
+}
+
+struct kinfo_pcb *
+getpcblist_sysctl(const char *name, size_t *len) {
+ int mib[8];
+ size_t namelen = 0, size = 0;
+ char *mibname = NULL;
+ struct kinfo_pcb *pcblist;
+
+ memset(mib, 0, sizeof(mib));
+
+ if (asprintf(&mibname, "net.inet%s.%s.pcblist", name + 3, name) == -1)
+ err(1, "asprintf");
+
+ /* get dynamic pcblist node */
+ if (sysctlnametomib(mibname, mib, &namelen) == -1)
+ err(1, "sysctlnametomib: %s", mibname);
+
+ free(mibname);
+
+ if (prog_sysctl(mib, __arraycount(mib), NULL, &size, NULL, 0) == -1)
+ err(1, "sysctl (query)");
+
+ if ((pcblist = malloc(size)) == NULL)
+ err(1, "malloc");
+ memset(pcblist, 0, size);
+
+ mib[6] = sizeof(*pcblist);
+ mib[7] = size / sizeof(*pcblist);
+
+ if (prog_sysctl(mib, __arraycount(mib), pcblist, &size, NULL, 0) == -1)
+ err(1, "sysctl (copy)");
+
+ *len = size / sizeof(*pcblist);
+ return pcblist;
+
+}
+
+static struct kinfo_pcb *
+getpcblist_kmem(u_long off, const char *name, size_t *len) {
+ struct inpcbtable table;
+ struct inpcb_hdr *next, *prev;
+ struct inpcb inpcb;
+ struct tcpcb tcpcb;
+ struct socket sockb;
+ int istcp = strcmp(name, "tcp") == 0;
+ struct kinfo_pcb *pcblist;
+ size_t size = 100, i;
+ struct sockaddr_in sin;
+ struct inpcbqueue *head;
+
+ if (off == 0) {
+ *len = 0;
+ return NULL;
+ }
+
+ kread(off, (char *)&table, sizeof table);
+ head = &table.inpt_queue;
+ next = TAILQ_FIRST(head);
+ prev = TAILQ_END(head);
+
+ if ((pcblist = malloc(size * sizeof(*pcblist))) == NULL)
+ err(1, "malloc");
+
+ i = 0;
+ while (next != TAILQ_END(head)) {
+ kread((u_long)next, (char *)&inpcb, sizeof inpcb);
+ prev = next;
+ next = TAILQ_NEXT(&inpcb, inp_queue);
+
+ if (inpcb.inp_af != AF_INET)
+ continue;
+
+ kread((u_long)inpcb.inp_socket, (char *)&sockb, sizeof(sockb));
+ if (istcp) {
+ kread((u_long)inpcb.inp_ppcb,
+ (char *)&tcpcb, sizeof (tcpcb));
+ }
+ pcblist[i].ki_ppcbaddr =
+ istcp ? (uintptr_t) inpcb.inp_ppcb : (uintptr_t) prev;
+ pcblist[i].ki_rcvq = (uint64_t)sockb.so_rcv.sb_cc;
+ pcblist[i].ki_sndq = (uint64_t)sockb.so_snd.sb_cc;
+
+ sin.sin_addr = inpcb.inp_laddr;
+ sin.sin_port = inpcb.inp_lport;
+ memcpy(&pcblist[i].ki_s, &sin, sizeof(sin));
+ sin.sin_addr = inpcb.inp_faddr;
+ sin.sin_port = inpcb.inp_fport;
+ memcpy(&pcblist[i].ki_d, &sin, sizeof(sin));
+ pcblist[i].ki_tstate = tcpcb.t_state;
+ pcblist[i].ki_pflags = inpcb.inp_flags;
+ if (i++ == size) {
+ size += 100;
+ struct kinfo_pcb *n = realloc(pcblist,
+ size * sizeof(*pcblist));
+ if (n == NULL)
+ err(1, "realloc");
+ pcblist = n;
+ }
+ }
+ *len = i;
+ return pcblist;
+}
+
+void
+protopr(u_long off, const char *name)
+{
+ static int first = 1;
+ struct kinfo_pcb *pcblist;
+ size_t i, len;
+
+ compact = 0;
+ if (Aflag) {
+ if (!numeric_addr)
+ width = 18;
+ else {
+ width = 21;
+ compact = 1;
+ }
+ } else
+ width = 22;
+
+ if (use_sysctl)
+ pcblist = getpcblist_sysctl(name, &len);
+ else
+ pcblist = getpcblist_kmem(off, name, &len);
+
+ for (i = 0; i < len; i++) {
+ struct sockaddr_in src, dst;
+
+ memcpy(&src, &pcblist[i].ki_s, sizeof(src));
+ memcpy(&dst, &pcblist[i].ki_d, sizeof(dst));
+
+ if (!aflag &&
+ inet_lnaof(dst.sin_addr) == INADDR_ANY)
+ continue;
+
+ if (first) {
+ protoprhdr();
+ first = 0;
+ }
+ protopr0((intptr_t) pcblist[i].ki_ppcbaddr,
+ pcblist[i].ki_rcvq, pcblist[i].ki_sndq,
+ &src.sin_addr, src.sin_port,
+ &dst.sin_addr, dst.sin_port,
+ pcblist[i].ki_tstate, name,
+ pcblist[i].ki_pflags, NULL);
+ }
+
+ free(pcblist);
+
+#ifndef __minix
+ if (strcmp(name, "tcp") == 0) {
+ struct timeval t;
+ timebase(&t);
+ gettimeofday(&now, NULL);
+ timersub(&now, &t, &now);
+ show_vtw_v4(print_vtw_v4);
+ }
+#endif /* !__minix */
+}
+
+/*
+ * Dump TCP statistics structure.
+ */
+void
+tcp_stats(u_long off, const char *name)
+{
+ uint64_t tcpstat[TCP_NSTATS];
+
+ if (use_sysctl) {
+ size_t size = sizeof(tcpstat);
+
+ if (sysctlbyname("net.inet.tcp.stats", tcpstat, &size,
+ NULL, 0) == -1)
+ return;
+ } else {
+ warnx("%s stats not available via KVM.", name);
+ return;
+ }
+
+ printf ("%s:\n", name);
+
+#define ps(f, m) if (tcpstat[f] || sflag <= 1) \
+ printf(m, tcpstat[f])
+#define p(f, m) if (tcpstat[f] || sflag <= 1) \
+ printf(m, tcpstat[f], plural(tcpstat[f]))
+#define p2(f1, f2, m) if (tcpstat[f1] || tcpstat[f2] || sflag <= 1) \
+ printf(m, tcpstat[f1], plural(tcpstat[f1]), \
+ tcpstat[f2], plural(tcpstat[f2]))
+#define p2s(f1, f2, m) if (tcpstat[f1] || tcpstat[f2] || sflag <= 1) \
+ printf(m, tcpstat[f1], plural(tcpstat[f1]), \
+ tcpstat[f2])
+#define p3(f, m) if (tcpstat[f] || sflag <= 1) \
+ printf(m, tcpstat[f], plurales(tcpstat[f]))
+
+ p(TCP_STAT_SNDTOTAL, "\t%" PRIu64 " packet%s sent\n");
+ p2(TCP_STAT_SNDPACK,TCP_STAT_SNDBYTE,
+ "\t\t%" PRIu64 " data packet%s (%" PRIu64 " byte%s)\n");
+ p2(TCP_STAT_SNDREXMITPACK, TCP_STAT_SNDREXMITBYTE,
+ "\t\t%" PRIu64 " data packet%s (%" PRIu64 " byte%s) retransmitted\n");
+ p2s(TCP_STAT_SNDACKS, TCP_STAT_DELACK,
+ "\t\t%" PRIu64 " ack-only packet%s (%" PRIu64 " delayed)\n");
+ p(TCP_STAT_SNDURG, "\t\t%" PRIu64 " URG only packet%s\n");
+ p(TCP_STAT_SNDPROBE, "\t\t%" PRIu64 " window probe packet%s\n");
+ p(TCP_STAT_SNDWINUP, "\t\t%" PRIu64 " window update packet%s\n");
+ p(TCP_STAT_SNDCTRL, "\t\t%" PRIu64 " control packet%s\n");
+ p(TCP_STAT_SELFQUENCH,
+ "\t\t%" PRIu64 " send attempt%s resulted in self-quench\n");
+ p(TCP_STAT_RCVTOTAL, "\t%" PRIu64 " packet%s received\n");
+ p2(TCP_STAT_RCVACKPACK, TCP_STAT_RCVACKBYTE,
+ "\t\t%" PRIu64 " ack%s (for %" PRIu64 " byte%s)\n");
+ p(TCP_STAT_RCVDUPACK, "\t\t%" PRIu64 " duplicate ack%s\n");
+ p(TCP_STAT_RCVACKTOOMUCH, "\t\t%" PRIu64 " ack%s for unsent data\n");
+ p2(TCP_STAT_RCVPACK, TCP_STAT_RCVBYTE,
+ "\t\t%" PRIu64 " packet%s (%" PRIu64 " byte%s) received in-sequence\n");
+ p2(TCP_STAT_RCVDUPPACK, TCP_STAT_RCVDUPBYTE,
+ "\t\t%" PRIu64 " completely duplicate packet%s (%" PRIu64 " byte%s)\n");
+ p(TCP_STAT_PAWSDROP, "\t\t%" PRIu64 " old duplicate packet%s\n");
+ p2(TCP_STAT_RCVPARTDUPPACK, TCP_STAT_RCVPARTDUPBYTE,
+ "\t\t%" PRIu64 " packet%s with some dup. data (%" PRIu64 " byte%s duped)\n");
+ p2(TCP_STAT_RCVOOPACK, TCP_STAT_RCVOOBYTE,
+ "\t\t%" PRIu64 " out-of-order packet%s (%" PRIu64 " byte%s)\n");
+ p2(TCP_STAT_RCVPACKAFTERWIN, TCP_STAT_RCVBYTEAFTERWIN,
+ "\t\t%" PRIu64 " packet%s (%" PRIu64 " byte%s) of data after window\n");
+ p(TCP_STAT_RCVWINPROBE, "\t\t%" PRIu64 " window probe%s\n");
+ p(TCP_STAT_RCVWINUPD, "\t\t%" PRIu64 " window update packet%s\n");
+ p(TCP_STAT_RCVAFTERCLOSE, "\t\t%" PRIu64 " packet%s received after close\n");
+ p(TCP_STAT_RCVBADSUM, "\t\t%" PRIu64 " discarded for bad checksum%s\n");
+ p(TCP_STAT_RCVBADOFF, "\t\t%" PRIu64 " discarded for bad header offset field%s\n");
+ ps(TCP_STAT_RCVSHORT, "\t\t%" PRIu64 " discarded because packet too short\n");
+ p(TCP_STAT_CONNATTEMPT, "\t%" PRIu64 " connection request%s\n");
+ p(TCP_STAT_ACCEPTS, "\t%" PRIu64 " connection accept%s\n");
+ p(TCP_STAT_CONNECTS,
+ "\t%" PRIu64 " connection%s established (including accepts)\n");
+ p2(TCP_STAT_CLOSED, TCP_STAT_DROPS,
+ "\t%" PRIu64 " connection%s closed (including %" PRIu64 " drop%s)\n");
+ p(TCP_STAT_CONNDROPS, "\t%" PRIu64 " embryonic connection%s dropped\n");
+ p(TCP_STAT_DELAYED_FREE, "\t%" PRIu64 " delayed free%s of tcpcb\n");
+ p2(TCP_STAT_RTTUPDATED, TCP_STAT_SEGSTIMED,
+ "\t%" PRIu64 " segment%s updated rtt (of %" PRIu64 " attempt%s)\n");
+ p(TCP_STAT_REXMTTIMEO, "\t%" PRIu64 " retransmit timeout%s\n");
+ p(TCP_STAT_TIMEOUTDROP,
+ "\t\t%" PRIu64 " connection%s dropped by rexmit timeout\n");
+ p2(TCP_STAT_PERSISTTIMEO, TCP_STAT_PERSISTDROPS,
+ "\t%" PRIu64 " persist timeout%s (resulting in %" PRIu64 " dropped "
+ "connection%s)\n");
+ p(TCP_STAT_KEEPTIMEO, "\t%" PRIu64 " keepalive timeout%s\n");
+ p(TCP_STAT_KEEPPROBE, "\t\t%" PRIu64 " keepalive probe%s sent\n");
+ p(TCP_STAT_KEEPDROPS, "\t\t%" PRIu64 " connection%s dropped by keepalive\n");
+ p(TCP_STAT_PREDACK, "\t%" PRIu64 " correct ACK header prediction%s\n");
+ p(TCP_STAT_PREDDAT, "\t%" PRIu64 " correct data packet header prediction%s\n");
+ p3(TCP_STAT_PCBHASHMISS, "\t%" PRIu64 " PCB hash miss%s\n");
+ ps(TCP_STAT_NOPORT, "\t%" PRIu64 " dropped due to no socket\n");
+ p(TCP_STAT_CONNSDRAINED, "\t%" PRIu64 " connection%s drained due to memory "
+ "shortage\n");
+ p(TCP_STAT_PMTUBLACKHOLE, "\t%" PRIu64 " PMTUD blackhole%s detected\n");
+
+ p(TCP_STAT_BADSYN, "\t%" PRIu64 " bad connection attempt%s\n");
+ ps(TCP_STAT_SC_ADDED, "\t%" PRIu64 " SYN cache entries added\n");
+ p(TCP_STAT_SC_COLLISIONS, "\t\t%" PRIu64 " hash collision%s\n");
+ ps(TCP_STAT_SC_COMPLETED, "\t\t%" PRIu64 " completed\n");
+ ps(TCP_STAT_SC_ABORTED, "\t\t%" PRIu64 " aborted (no space to build PCB)\n");
+ ps(TCP_STAT_SC_TIMED_OUT, "\t\t%" PRIu64 " timed out\n");
+ ps(TCP_STAT_SC_OVERFLOWED, "\t\t%" PRIu64 " dropped due to overflow\n");
+ ps(TCP_STAT_SC_BUCKETOVERFLOW, "\t\t%" PRIu64 " dropped due to bucket overflow\n");
+ ps(TCP_STAT_SC_RESET, "\t\t%" PRIu64 " dropped due to RST\n");
+ ps(TCP_STAT_SC_UNREACH, "\t\t%" PRIu64 " dropped due to ICMP unreachable\n");
+ ps(TCP_STAT_SC_DELAYED_FREE, "\t\t%" PRIu64 " delayed free of SYN cache "
+ "entries\n");
+ p(TCP_STAT_SC_RETRANSMITTED, "\t%" PRIu64 " SYN,ACK%s retransmitted\n");
+ p(TCP_STAT_SC_DUPESYN, "\t%" PRIu64 " duplicate SYN%s received for entries "
+ "already in the cache\n");
+ p(TCP_STAT_SC_DROPPED, "\t%" PRIu64 " SYN%s dropped (no route or no space)\n");
+ p(TCP_STAT_BADSIG, "\t%" PRIu64 " packet%s with bad signature\n");
+ p(TCP_STAT_GOODSIG, "\t%" PRIu64 " packet%s with good signature\n");
+
+ p(TCP_STAT_ECN_SHS, "\t%" PRIu64 " successful ECN handshake%s\n");
+ p(TCP_STAT_ECN_CE, "\t%" PRIu64 " packet%s with ECN CE bit\n");
+ p(TCP_STAT_ECN_ECT, "\t%" PRIu64 " packet%s ECN ECT(0) bit\n");
+#undef p
+#undef ps
+#undef p2
+#undef p2s
+#undef p3
+ show_vtw_stats();
+}
+
+/*
+ * Dump UDP statistics structure.
+ */
+void
+udp_stats(u_long off, const char *name)
+{
+ uint64_t udpstat[UDP_NSTATS];
+ u_quad_t delivered;
+
+ if (use_sysctl) {
+ size_t size = sizeof(udpstat);
+
+ if (sysctlbyname("net.inet.udp.stats", udpstat, &size,
+ NULL, 0) == -1)
+ return;
+ } else {
+ warnx("%s stats not available via KVM.", name);
+ return;
+ }
+
+ printf ("%s:\n", name);
+
+#define ps(f, m) if (udpstat[f] || sflag <= 1) \
+ printf(m, udpstat[f])
+#define p(f, m) if (udpstat[f] || sflag <= 1) \
+ printf(m, udpstat[f], plural(udpstat[f]))
+#define p3(f, m) if (udpstat[f] || sflag <= 1) \
+ printf(m, udpstat[f], plurales(udpstat[f]))
+
+ p(UDP_STAT_IPACKETS, "\t%" PRIu64 " datagram%s received\n");
+ ps(UDP_STAT_HDROPS, "\t%" PRIu64 " with incomplete header\n");
+ ps(UDP_STAT_BADLEN, "\t%" PRIu64 " with bad data length field\n");
+ ps(UDP_STAT_BADSUM, "\t%" PRIu64 " with bad checksum\n");
+ ps(UDP_STAT_NOPORT, "\t%" PRIu64 " dropped due to no socket\n");
+ p(UDP_STAT_NOPORTBCAST,
+ "\t%" PRIu64 " broadcast/multicast datagram%s dropped due to no socket\n");
+ ps(UDP_STAT_FULLSOCK, "\t%" PRIu64 " dropped due to full socket buffers\n");
+ delivered = udpstat[UDP_STAT_IPACKETS] -
+ udpstat[UDP_STAT_HDROPS] -
+ udpstat[UDP_STAT_BADLEN] -
+ udpstat[UDP_STAT_BADSUM] -
+ udpstat[UDP_STAT_NOPORT] -
+ udpstat[UDP_STAT_NOPORTBCAST] -
+ udpstat[UDP_STAT_FULLSOCK];
+ if (delivered || sflag <= 1)
+ printf("\t%" PRIu64 " delivered\n", delivered);
+ p3(UDP_STAT_PCBHASHMISS, "\t%" PRIu64 " PCB hash miss%s\n");
+ p(UDP_STAT_OPACKETS, "\t%" PRIu64 " datagram%s output\n");
+
+#undef ps
+#undef p
+#undef p3
+}
+
+/*
+ * Dump IP statistics structure.
+ */
+void
+ip_stats(u_long off, const char *name)
+{
+ uint64_t ipstat[IP_NSTATS];
+
+ if (use_sysctl) {
+ size_t size = sizeof(ipstat);
+
+ if (sysctlbyname("net.inet.ip.stats", ipstat, &size,
+ NULL, 0) == -1)
+ return;
+ } else {
+ warnx("%s stats not available via KVM.", name);
+ return;
+ }
+
+ printf("%s:\n", name);
+
+#define ps(f, m) if (ipstat[f] || sflag <= 1) \
+ printf(m, ipstat[f])
+#define p(f, m) if (ipstat[f] || sflag <= 1) \
+ printf(m, ipstat[f], plural(ipstat[f]))
+
+ p(IP_STAT_TOTAL, "\t%" PRIu64 " total packet%s received\n");
+ p(IP_STAT_BADSUM, "\t%" PRIu64 " bad header checksum%s\n");
+ ps(IP_STAT_TOOSMALL, "\t%" PRIu64 " with size smaller than minimum\n");
+ ps(IP_STAT_TOOSHORT, "\t%" PRIu64 " with data size < data length\n");
+ ps(IP_STAT_TOOLONG, "\t%" PRIu64 " with length > max ip packet size\n");
+ ps(IP_STAT_BADHLEN, "\t%" PRIu64 " with header length < data size\n");
+ ps(IP_STAT_BADLEN, "\t%" PRIu64 " with data length < header length\n");
+ ps(IP_STAT_BADOPTIONS, "\t%" PRIu64 " with bad options\n");
+ ps(IP_STAT_BADVERS, "\t%" PRIu64 " with incorrect version number\n");
+ p(IP_STAT_FRAGMENTS, "\t%" PRIu64 " fragment%s received\n");
+ p(IP_STAT_FRAGDROPPED, "\t%" PRIu64 " fragment%s dropped (dup or out of space)\n");
+ p(IP_STAT_RCVMEMDROP, "\t%" PRIu64 " fragment%s dropped (out of ipqent)\n");
+ p(IP_STAT_BADFRAGS, "\t%" PRIu64 " malformed fragment%s dropped\n");
+ p(IP_STAT_FRAGTIMEOUT, "\t%" PRIu64 " fragment%s dropped after timeout\n");
+ p(IP_STAT_REASSEMBLED, "\t%" PRIu64 " packet%s reassembled ok\n");
+ p(IP_STAT_DELIVERED, "\t%" PRIu64 " packet%s for this host\n");
+ p(IP_STAT_NOPROTO, "\t%" PRIu64 " packet%s for unknown/unsupported protocol\n");
+ p(IP_STAT_FORWARD, "\t%" PRIu64 " packet%s forwarded");
+ p(IP_STAT_FASTFORWARD, " (%" PRIu64 " packet%s fast forwarded)");
+ if (ipstat[IP_STAT_FORWARD] || sflag <= 1)
+ putchar('\n');
+ p(IP_STAT_CANTFORWARD, "\t%" PRIu64 " packet%s not forwardable\n");
+ p(IP_STAT_REDIRECTSENT, "\t%" PRIu64 " redirect%s sent\n");
+ p(IP_STAT_NOGIF, "\t%" PRIu64 " packet%s no matching gif found\n");
+ p(IP_STAT_LOCALOUT, "\t%" PRIu64 " packet%s sent from this host\n");
+ p(IP_STAT_RAWOUT, "\t%" PRIu64 " packet%s sent with fabricated ip header\n");
+ p(IP_STAT_ODROPPED, "\t%" PRIu64 " output packet%s dropped due to no bufs, etc.\n");
+ p(IP_STAT_NOROUTE, "\t%" PRIu64 " output packet%s discarded due to no route\n");
+ p(IP_STAT_FRAGMENTED, "\t%" PRIu64 " output datagram%s fragmented\n");
+ p(IP_STAT_OFRAGMENTS, "\t%" PRIu64 " fragment%s created\n");
+ p(IP_STAT_CANTFRAG, "\t%" PRIu64 " datagram%s that can't be fragmented\n");
+ p(IP_STAT_BADADDR, "\t%" PRIu64 " datagram%s with bad address in header\n");
+#undef ps
+#undef p
+}
+
+/*
+ * Dump ICMP statistics.
+ */
+void
+icmp_stats(u_long off, const char *name)
+{
+ uint64_t icmpstat[ICMP_NSTATS];
+ int i, first;
+
+ if (use_sysctl) {
+ size_t size = sizeof(icmpstat);
+
+ if (sysctlbyname("net.inet.icmp.stats", icmpstat, &size,
+ NULL, 0) == -1)
+ return;
+ } else {
+ warnx("%s stats not available via KVM.", name);
+ return;
+ }
+
+ printf("%s:\n", name);
+
+#define p(f, m) if (icmpstat[f] || sflag <= 1) \
+ printf(m, icmpstat[f], plural(icmpstat[f]))
+
+ p(ICMP_STAT_ERROR, "\t%" PRIu64 " call%s to icmp_error\n");
+ p(ICMP_STAT_OLDICMP,
+ "\t%" PRIu64 " error%s not generated because old message was icmp\n");
+ for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
+ if (icmpstat[ICMP_STAT_OUTHIST + i] != 0) {
+ if (first) {
+ printf("\tOutput histogram:\n");
+ first = 0;
+ }
+ printf("\t\t%s: %" PRIu64 "\n", icmp_type[i],
+ icmpstat[ICMP_STAT_OUTHIST + i]);
+ }
+ p(ICMP_STAT_BADCODE, "\t%" PRIu64 " message%s with bad code fields\n");
+ p(ICMP_STAT_TOOSHORT, "\t%" PRIu64 " message%s < minimum length\n");
+ p(ICMP_STAT_CHECKSUM, "\t%" PRIu64 " bad checksum%s\n");
+ p(ICMP_STAT_BADLEN, "\t%" PRIu64 " message%s with bad length\n");
+ p(ICMP_STAT_BMCASTECHO, "\t%" PRIu64 " multicast echo request%s ignored\n");
+ p(ICMP_STAT_BMCASTTSTAMP, "\t%" PRIu64 " multicast timestamp request%s ignored\n");
+ for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
+ if (icmpstat[ICMP_STAT_INHIST + i] != 0) {
+ if (first) {
+ printf("\tInput histogram:\n");
+ first = 0;
+ }
+ printf("\t\t%s: %" PRIu64 "\n", icmp_type[i],
+ icmpstat[ICMP_STAT_INHIST + i]);
+ }
+ p(ICMP_STAT_REFLECT, "\t%" PRIu64 " message response%s generated\n");
+ p(ICMP_STAT_PMTUCHG, "\t%" PRIu64 " path MTU change%s\n");
+#undef p
+}
+
+/*
+ * Dump IGMP statistics structure.
+ */
+void
+igmp_stats(u_long off, const char *name)
+{
+ uint64_t igmpstat[IGMP_NSTATS];
+
+ if (use_sysctl) {
+ size_t size = sizeof(igmpstat);
+
+ if (sysctlbyname("net.inet.igmp.stats", igmpstat, &size,
+ NULL, 0) == -1)
+ return;
+ } else {
+ warnx("%s stats not available via KVM.", name);
+ return;
+ }
+
+ printf("%s:\n", name);
+
+#define p(f, m) if (igmpstat[f] || sflag <= 1) \
+ printf(m, igmpstat[f], plural(igmpstat[f]))
+#define py(f, m) if (igmpstat[f] || sflag <= 1) \
+ printf(m, igmpstat[f], igmpstat[f] != 1 ? "ies" : "y")
+ p(IGMP_STAT_RCV_TOTAL, "\t%" PRIu64 " message%s received\n");
+ p(IGMP_STAT_RCV_TOOSHORT, "\t%" PRIu64 " message%s received with too few bytes\n");
+ p(IGMP_STAT_RCV_BADSUM, "\t%" PRIu64 " message%s received with bad checksum\n");
+ py(IGMP_STAT_RCV_QUERIES, "\t%" PRIu64 " membership quer%s received\n");
+ py(IGMP_STAT_RCV_BADQUERIES, "\t%" PRIu64 " membership quer%s received with invalid field(s)\n");
+ p(IGMP_STAT_RCV_REPORTS, "\t%" PRIu64 " membership report%s received\n");
+ p(IGMP_STAT_RCV_BADREPORTS, "\t%" PRIu64 " membership report%s received with invalid field(s)\n");
+ p(IGMP_STAT_RCV_OURREPORTS, "\t%" PRIu64 " membership report%s received for groups to which we belong\n");
+ p(IGMP_STAT_SND_REPORTS, "\t%" PRIu64 " membership report%s sent\n");
+#undef p
+#undef py
+}
+
+/*
+ * Dump CARP statistics structure.
+ */
+void
+carp_stats(u_long off, const char *name)
+{
+ uint64_t carpstat[CARP_NSTATS];
+
+ if (use_sysctl) {
+ size_t size = sizeof(carpstat);
+
+ if (sysctlbyname("net.inet.carp.stats", carpstat, &size,
+ NULL, 0) == -1)
+ return;
+ } else {
+ warnx("%s stats not available via KVM.", name);
+ return;
+ }
+
+ printf("%s:\n", name);
+
+#define p(f, m) if (carpstat[f] || sflag <= 1) \
+ printf(m, carpstat[f], plural(carpstat[f]))
+#define p2(f, m) if (carpstat[f] || sflag <= 1) \
+ printf(m, carpstat[f])
+
+ p(CARP_STAT_IPACKETS, "\t%" PRIu64 " packet%s received (IPv4)\n");
+ p(CARP_STAT_IPACKETS6, "\t%" PRIu64 " packet%s received (IPv6)\n");
+ p(CARP_STAT_BADIF,
+ "\t\t%" PRIu64 " packet%s discarded for bad interface\n");
+ p(CARP_STAT_BADTTL,
+ "\t\t%" PRIu64 " packet%s discarded for wrong TTL\n");
+ p(CARP_STAT_HDROPS, "\t\t%" PRIu64 " packet%s shorter than header\n");
+ p(CARP_STAT_BADSUM, "\t\t%" PRIu64
+ " packet%s discarded for bad checksum\n");
+ p(CARP_STAT_BADVER,
+ "\t\t%" PRIu64 " packet%s discarded with a bad version\n");
+ p2(CARP_STAT_BADLEN,
+ "\t\t%" PRIu64 " discarded because packet was too short\n");
+ p(CARP_STAT_BADAUTH,
+ "\t\t%" PRIu64 " packet%s discarded for bad authentication\n");
+ p(CARP_STAT_BADVHID, "\t\t%" PRIu64 " packet%s discarded for bad vhid\n");
+ p(CARP_STAT_BADADDRS, "\t\t%" PRIu64
+ " packet%s discarded because of a bad address list\n");
+ p(CARP_STAT_OPACKETS, "\t%" PRIu64 " packet%s sent (IPv4)\n");
+ p(CARP_STAT_OPACKETS6, "\t%" PRIu64 " packet%s sent (IPv6)\n");
+ p2(CARP_STAT_ONOMEM,
+ "\t\t%" PRIu64 " send failed due to mbuf memory error\n");
+#undef p
+#undef p2
+}
+
+/*
+ * Dump PIM statistics structure.
+ */
+void
+pim_stats(u_long off, const char *name)
+{
+ struct pimstat pimstat;
+
+ if (off == 0)
+ return;
+ if (kread(off, (char *)&pimstat, sizeof (pimstat)) != 0) {
+ /* XXX: PIM is probably not enabled in the kernel */
+ return;
+ }
+
+ printf("%s:\n", name);
+
+#define p(f, m) if (pimstat.f || sflag <= 1) \
+ printf(m, pimstat.f, plural(pimstat.f))
+
+ p(pims_rcv_total_msgs, "\t%" PRIu64 " message%s received\n");
+ p(pims_rcv_total_bytes, "\t%" PRIu64 " byte%s received\n");
+ p(pims_rcv_tooshort, "\t%" PRIu64 " message%s received with too few bytes\n");
+ p(pims_rcv_badsum, "\t%" PRIu64 " message%s received with bad checksum\n");
+ p(pims_rcv_badversion, "\t%" PRIu64 " message%s received with bad version\n");
+ p(pims_rcv_registers_msgs, "\t%" PRIu64 " data register message%s received\n");
+ p(pims_rcv_registers_bytes, "\t%" PRIu64 " data register byte%s received\n");
+ p(pims_rcv_registers_wrongiif, "\t%" PRIu64 " data register message%s received on wrong iif\n");
+ p(pims_rcv_badregisters, "\t%" PRIu64 " bad register%s received\n");
+ p(pims_snd_registers_msgs, "\t%" PRIu64 " data register message%s sent\n");
+ p(pims_snd_registers_bytes, "\t%" PRIu64 " data register byte%s sent\n");
+#undef p
+}
+
+/*
+ * Dump the ARP statistics structure.
+ */
+void
+arp_stats(u_long off, const char *name)
+{
+ uint64_t arpstat[ARP_NSTATS];
+
+ if (use_sysctl) {
+ size_t size = sizeof(arpstat);
+
+ if (sysctlbyname("net.inet.arp.stats", arpstat, &size,
+ NULL, 0) == -1)
+ return;
+ } else {
+ warnx("%s stats not available via KVM.", name);
+ return;
+ }
+
+ printf("%s:\n", name);
+
+#define ps(f, m) if (arpstat[f] || sflag <= 1) \
+ printf(m, arpstat[f])
+#define p(f, m) if (arpstat[f] || sflag <= 1) \
+ printf(m, arpstat[f], plural(arpstat[f]))
+
+ p(ARP_STAT_SNDTOTAL, "\t%" PRIu64 " packet%s sent\n");
+ p(ARP_STAT_SNDREPLY, "\t\t%" PRIu64 " reply packet%s\n");
+ p(ARP_STAT_SENDREQUEST, "\t\t%" PRIu64 " request packet%s\n");
+
+ p(ARP_STAT_RCVTOTAL, "\t%" PRIu64 " packet%s received\n");
+ p(ARP_STAT_RCVREPLY, "\t\t%" PRIu64 " reply packet%s\n");
+ p(ARP_STAT_RCVREQUEST, "\t\t%" PRIu64 " valid request packet%s\n");
+ p(ARP_STAT_RCVMCAST, "\t\t%" PRIu64 " broadcast/multicast packet%s\n");
+ p(ARP_STAT_RCVBADPROTO, "\t\t%" PRIu64 " packet%s with unknown protocol type\n");
+ p(ARP_STAT_RCVBADLEN, "\t\t%" PRIu64 " packet%s with bad (short) length\n");
+ p(ARP_STAT_RCVZEROTPA, "\t\t%" PRIu64 " packet%s with null target IP address\n");
+ p(ARP_STAT_RCVZEROSPA, "\t\t%" PRIu64 " packet%s with null source IP address\n");
+ ps(ARP_STAT_RCVNOINT, "\t\t%" PRIu64 " could not be mapped to an interface\n");
+ p(ARP_STAT_RCVLOCALSHA, "\t\t%" PRIu64 " packet%s sourced from a local hardware "
+ "address\n");
+ p(ARP_STAT_RCVBCASTSHA, "\t\t%" PRIu64 " packet%s with a broadcast "
+ "source hardware address\n");
+ p(ARP_STAT_RCVLOCALSPA, "\t\t%" PRIu64 " duplicate%s for a local IP address\n");
+ p(ARP_STAT_RCVOVERPERM, "\t\t%" PRIu64 " attempt%s to overwrite a static entry\n");
+ p(ARP_STAT_RCVOVERINT, "\t\t%" PRIu64 " packet%s received on wrong interface\n");
+ p(ARP_STAT_RCVOVER, "\t\t%" PRIu64 " entry%s overwritten\n");
+ p(ARP_STAT_RCVLENCHG, "\t\t%" PRIu64 " change%s in hardware address length\n");
+
+ p(ARP_STAT_DFRTOTAL, "\t%" PRIu64 " packet%s deferred pending ARP resolution\n");
+ ps(ARP_STAT_DFRSENT, "\t\t%" PRIu64 " sent\n");
+ ps(ARP_STAT_DFRDROPPED, "\t\t%" PRIu64 " dropped\n");
+
+ p(ARP_STAT_ALLOCFAIL, "\t%" PRIu64 " failure%s to allocate llinfo\n");
+
+#undef ps
+#undef p
+}
+
+/*
+ * Pretty print an Internet address (net address + port).
+ * Take numeric_addr and numeric_port into consideration.
+ */
+void
+inetprint(struct in_addr *in, uint16_t port, const char *proto,
+ int port_numeric)
+{
+ struct servent *sp = 0;
+ char line[80], *cp;
+ size_t space;
+
+ (void)snprintf(line, sizeof line, "%.*s.",
+ (Aflag && !numeric_addr) ? 12 : 16, inetname(in));
+ cp = strchr(line, '\0');
+ if (!port_numeric && port)
+ sp = getservbyport((int)port, proto);
+ space = sizeof line - (cp-line);
+ if (sp || port == 0)
+ (void)snprintf(cp, space, "%s", sp ? sp->s_name : "*");
+ else
+ (void)snprintf(cp, space, "%u", ntohs(port));
+ (void)printf(" %-*.*s", width, width, line);
+}
+
+/*
+ * Construct an Internet address representation.
+ * If numeric_addr has been supplied, give
+ * numeric value, otherwise try for symbolic name.
+ */
+char *
+inetname(struct in_addr *inp)
+{
+ char *cp;
+ static char line[50];
+ struct hostent *hp;
+ struct netent *np;
+ static char domain[MAXHOSTNAMELEN + 1];
+ static int first = 1;
+
+ if (first && !numeric_addr) {
+ first = 0;
+ if (gethostname(domain, sizeof domain) == 0) {
+ domain[sizeof(domain) - 1] = '\0';
+ if ((cp = strchr(domain, '.')))
+ (void) strlcpy(domain, cp + 1, sizeof(domain));
+ else
+ domain[0] = 0;
+ } else
+ domain[0] = 0;
+ }
+ cp = 0;
+ if (!numeric_addr && inp->s_addr != INADDR_ANY) {
+ int net = inet_netof(*inp);
+ int lna = inet_lnaof(*inp);
+
+ if (lna == INADDR_ANY) {
+ np = getnetbyaddr(net, AF_INET);
+ if (np)
+ cp = np->n_name;
+ }
+ if (cp == 0) {
+ hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET);
+ if (hp) {
+ if ((cp = strchr(hp->h_name, '.')) &&
+ !strcmp(cp + 1, domain))
+ *cp = 0;
+ cp = hp->h_name;
+ }
+ }
+ }
+ if (inp->s_addr == INADDR_ANY)
+ strlcpy(line, "*", sizeof line);
+ else if (cp)
+ strlcpy(line, cp, sizeof line);
+ else {
+ inp->s_addr = ntohl(inp->s_addr);
+#define C(x) ((x) & 0xff)
+ (void)snprintf(line, sizeof line, "%u.%u.%u.%u",
+ C(inp->s_addr >> 24), C(inp->s_addr >> 16),
+ C(inp->s_addr >> 8), C(inp->s_addr));
+#undef C
+ }
+ return (line);
+}
+
+/*
+ * Dump the contents of a TCP PCB.
+ */
+void
+tcp_dump(u_long off, const char *name, u_long pcbaddr)
+{
+ callout_impl_t *ci;
+ struct tcpcb tcpcb;
+ int i, hardticks;
+ struct kinfo_pcb *pcblist;
+ size_t j, len;
+
+ if (use_sysctl)
+ pcblist = getpcblist_sysctl(name, &len);
+ else
+ pcblist = getpcblist_kmem(off, name, &len);
+
+ for (j = 0; j < len; j++)
+ if (pcblist[j].ki_ppcbaddr == pcbaddr)
+ break;
+ free(pcblist);
+
+ if (j == len)
+ errx(1, "0x%lx is not a valid pcb address", pcbaddr);
+
+ kread(pcbaddr, (char *)&tcpcb, sizeof(tcpcb));
+ hardticks = get_hardticks();
+
+ printf("TCP Protocol Control Block at 0x%08lx:\n\n", pcbaddr);
+
+ printf("Timers:\n");
+ for (i = 0; i < TCPT_NTIMERS; i++) {
+ char buf[128];
+ ci = (callout_impl_t *)&tcpcb.t_timer[i];
+ snprintb(buf, sizeof(buf), CALLOUT_FMT, ci->c_flags);
+ printf("\t%s\t%s", tcptimers[i], buf);
+ if (ci->c_flags & CALLOUT_PENDING)
+ printf("\t%d\n", ci->c_time - hardticks);
+ else
+ printf("\n");
+ }
+ printf("\n\n");
+
+ if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES)
+ printf("State: %d", tcpcb.t_state);
+ else
+ printf("State: %s", tcpstates[tcpcb.t_state]);
+ printf(", flags 0x%x, inpcb 0x%lx, in6pcb 0x%lx\n\n", tcpcb.t_flags,
+ (u_long)tcpcb.t_inpcb, (u_long)tcpcb.t_in6pcb);
+
+ printf("rxtshift %d, rxtcur %d, dupacks %d\n", tcpcb.t_rxtshift,
+ tcpcb.t_rxtcur, tcpcb.t_dupacks);
+ printf("peermss %u, ourmss %u, segsz %u, segqlen %u\n\n",
+ tcpcb.t_peermss, tcpcb.t_ourmss, tcpcb.t_segsz, tcpcb.t_segqlen);
+
+ printf("snd_una %u, snd_nxt %u, snd_up %u\n",
+ tcpcb.snd_una, tcpcb.snd_nxt, tcpcb.snd_up);
+ printf("snd_wl1 %u, snd_wl2 %u, iss %u, snd_wnd %lu\n\n",
+ tcpcb.snd_wl1, tcpcb.snd_wl2, tcpcb.iss, tcpcb.snd_wnd);
+
+ printf("rcv_wnd %lu, rcv_nxt %u, rcv_up %u, irs %u\n\n",
+ tcpcb.rcv_wnd, tcpcb.rcv_nxt, tcpcb.rcv_up, tcpcb.irs);
+
+ printf("rcv_adv %u, snd_max %u, snd_cwnd %lu, snd_ssthresh %lu\n",
+ tcpcb.rcv_adv, tcpcb.snd_max, tcpcb.snd_cwnd, tcpcb.snd_ssthresh);
+
+ printf("rcvtime %u, rtttime %u, rtseq %u, srtt %d, rttvar %d, "
+ "rttmin %d, max_sndwnd %lu\n\n", tcpcb.t_rcvtime, tcpcb.t_rtttime,
+ tcpcb.t_rtseq, tcpcb.t_srtt, tcpcb.t_rttvar, tcpcb.t_rttmin,
+ tcpcb.max_sndwnd);
+
+ printf("oobflags %d, iobc %d, softerror %d\n\n", tcpcb.t_oobflags,
+ tcpcb.t_iobc, tcpcb.t_softerror);
+
+ printf("snd_scale %d, rcv_scale %d, req_r_scale %d, req_s_scale %d\n",
+ tcpcb.snd_scale, tcpcb.rcv_scale, tcpcb.request_r_scale,
+ tcpcb.requested_s_scale);
+ printf("ts_recent %u, ts_regent_age %d, last_ack_sent %u\n",
+ tcpcb.ts_recent, tcpcb.ts_recent_age, tcpcb.last_ack_sent);
+}
--- /dev/null
+/* $NetBSD: inet6.c,v 1.68 2015/02/08 15:09:45 christos Exp $ */
+/* BSDI inet.c,v 2.3 1995/10/24 02:19:29 prb Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1983, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)inet.c 8.4 (Berkeley) 4/20/94";
+#else
+__RCSID("$NetBSD: inet6.c,v 1.68 2015/02/08 15:09:45 christos Exp $");
+#endif
+#endif /* not lint */
+
+#define _CALLOUT_PRIVATE
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/ioctl.h>
+#include <sys/mbuf.h>
+#include <sys/protosw.h>
+#include <sys/sysctl.h>
+
+#include <net/route.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/ip6.h>
+#include <netinet/icmp6.h>
+#include <netinet/in_systm.h>
+#ifndef TCP6
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#endif
+#include <netinet6/ip6_var.h>
+#include <netinet6/in6_pcb.h>
+#include <netinet6/in6_var.h>
+#ifdef TCP6
+#include <netinet/tcp6.h>
+#include <netinet/tcp6_seq.h>
+#define TCP6STATES
+#include <netinet/tcp6_fsm.h>
+#define TCP6TIMERS
+#include <netinet/tcp6_timer.h>
+#include <netinet/tcp6_var.h>
+#include <netinet/tcp6_debug.h>
+#else
+#define TCP6T_NTIMERS TCPT_NTIMERS
+#define tcp6timers tcptimers
+#define tcp6states tcpstates
+#define TCP6_NSTATES TCP_NSTATES
+#define tcp6cb tcpcb
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+#include <netinet/tcp_seq.h>
+#include <netinet/tcp_fsm.h>
+extern const char * const tcpstates[];
+extern const char * const tcptimers[];
+#include <netinet/tcp_timer.h>
+#include <netinet/tcp_var.h>
+#include <netinet/tcp_debug.h>
+#endif /*TCP6*/
+#include <netinet6/udp6.h>
+#include <netinet6/udp6_var.h>
+#include <netinet6/pim6_var.h>
+#include <netinet6/raw_ip6.h>
+#include <netinet/tcp_vtw.h>
+
+#include <arpa/inet.h>
+#if 0
+#include "gethostbyname2.h"
+#endif
+#include <netdb.h>
+
+#include <err.h>
+#include <errno.h>
+#include <kvm.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <util.h>
+#include "netstat.h"
+#include "vtw.h"
+#include "prog_ops.h"
+
+#ifdef INET6
+
+struct in6pcb in6pcb;
+#ifdef TCP6
+struct tcp6cb tcp6cb;
+#else
+struct tcpcb tcpcb;
+#endif
+struct socket sockb;
+
+char *inet6name(const struct in6_addr *);
+void inet6print(const struct in6_addr *, int, const char *);
+void print_vtw_v6(const vtw_t *);
+
+/*
+ * Print a summary of connections related to an Internet
+ * protocol. For TCP, also give state of connection.
+ * Listening processes (aflag) are suppressed unless the
+ * -a (all) flag is specified.
+ */
+static int width;
+static int compact;
+
+/* VTW-related variables. */
+static struct timeval now;
+
+static void
+ip6protoprhdr(void)
+{
+
+ printf("Active Internet6 connections");
+
+ if (aflag)
+ printf(" (including servers)");
+ putchar('\n');
+
+ if (Aflag) {
+ printf("%-8.8s ", "PCB");
+ width = 18;
+ }
+ printf(
+ Vflag ? "%-5.5s %-6.6s %-6.6s %*.*s %*.*s %-13.13s Expires\n"
+ : "%-5.5s %-6.6s %-6.6s %*.*s %*.*s %s\n",
+ "Proto", "Recv-Q", "Send-Q",
+ -width, width, "Local Address",
+ -width, width, "Foreign Address", "(state)");
+}
+
+static void
+ip6protopr0(intptr_t ppcb, u_long rcv_sb_cc, u_long snd_sb_cc,
+ const struct in6_addr *laddr, u_int16_t lport,
+ const struct in6_addr *faddr, u_int16_t fport,
+ short t_state, const char *name, const struct timeval *expires)
+{
+ static const char *shorttcpstates[] = {
+ "CLOSED", "LISTEN", "SYNSEN", "SYSRCV",
+ "ESTABL", "CLWAIT", "FWAIT1", "CLOSNG",
+ "LASTAK", "FWAIT2", "TMWAIT",
+ };
+ int istcp;
+
+ istcp = strcmp(name, "tcp6") == 0;
+ if (Aflag)
+ printf("%8" PRIxPTR " ", ppcb);
+
+ printf("%-5.5s %6ld %6ld%s", name, rcv_sb_cc, snd_sb_cc,
+ compact ? "" : " ");
+
+ inet6print(laddr, (int)lport, name);
+ inet6print(faddr, (int)fport, name);
+ if (istcp) {
+#ifdef TCP6
+ if (t_state < 0 || t_state >= TCP6_NSTATES)
+ printf(" %d", t_state);
+ else
+ printf(" %s", tcp6states[t_state]);
+#else
+ if (t_state < 0 || t_state >= TCP_NSTATES)
+ printf(" %d", t_state);
+ else
+ printf(" %s", compact ? shorttcpstates[t_state] :
+ tcpstates[t_state]);
+#endif
+ }
+ if (Vflag && expires != NULL) {
+ if (expires->tv_sec == 0 && expires->tv_usec == -1)
+ printf(" reclaimed");
+ else {
+ struct timeval delta;
+
+ timersub(expires, &now, &delta);
+ printf(" %.3fms",
+ delta.tv_sec * 1000.0 + delta.tv_usec / 1000.0);
+ }
+ }
+ putchar('\n');
+}
+
+static void
+dbg_printf(const char *fmt, ...)
+{
+ return;
+}
+
+void
+print_vtw_v6(const vtw_t *vtw)
+{
+ const vtw_v6_t *v6 = (const vtw_v6_t *)vtw;
+ struct timeval delta;
+ char buf[2][128];
+ static const struct timeval zero = {.tv_sec = 0, .tv_usec = 0};
+
+ inet_ntop(AF_INET6, &v6->laddr, buf[0], sizeof(buf[0]));
+ inet_ntop(AF_INET6, &v6->faddr, buf[1], sizeof(buf[1]));
+
+ timersub(&vtw->expire, &now, &delta);
+
+ if (vtw->expire.tv_sec == 0 && vtw->expire.tv_usec == -1) {
+ dbg_printf("%15.15s:%d %15.15s:%d reclaimed\n"
+ ,buf[0], ntohs(v6->lport)
+ ,buf[1], ntohs(v6->fport));
+ if (!(Vflag && vflag))
+ return;
+ } else if (vtw->expire.tv_sec == 0)
+ return;
+ else if (timercmp(&delta, &zero, <) && !(Vflag && vflag)) {
+ dbg_printf("%15.15s:%d %15.15s:%d expired\n"
+ ,buf[0], ntohs(v6->lport)
+ ,buf[1], ntohs(v6->fport));
+ return;
+ } else {
+ dbg_printf("%15.15s:%d %15.15s:%d expires in %.3fms\n"
+ ,buf[0], ntohs(v6->lport)
+ ,buf[1], ntohs(v6->fport)
+ ,delta.tv_sec * 1000.0 + delta.tv_usec / 1000.0);
+ }
+ ip6protopr0(0, 0, 0,
+ &v6->laddr, v6->lport,
+ &v6->faddr, v6->fport,
+ TCPS_TIME_WAIT, "tcp6", &vtw->expire);
+}
+
+
+static struct kinfo_pcb *
+getpcblist_kmem(u_long off, const char *name, size_t *len) {
+
+ struct inpcbtable table;
+ struct inpcb_hdr *next, *prev;
+ int istcp = strcmp(name, "tcp6") == 0;
+ struct kinfo_pcb *pcblist;
+ size_t size = 100, i;
+ struct sockaddr_in6 sin6;
+ struct inpcbqueue *head;
+
+ if (off == 0) {
+ *len = 0;
+ return NULL;
+ }
+ kread(off, (char *)&table, sizeof (table));
+ head = &table.inpt_queue;
+ next = TAILQ_FIRST(head);
+ prev = TAILQ_END(head);
+
+ if ((pcblist = malloc(size * sizeof(*pcblist))) == NULL)
+ err(1, "malloc");
+
+ i = 0;
+ while (next != TAILQ_END(head)) {
+ kread((u_long)next, (char *)&in6pcb, sizeof in6pcb);
+ next = TAILQ_NEXT(&in6pcb, in6p_queue);
+ prev = next;
+
+ if (in6pcb.in6p_af != AF_INET6)
+ continue;
+
+ kread((u_long)in6pcb.in6p_socket, (char *)&sockb,
+ sizeof (sockb));
+ if (istcp) {
+#ifdef TCP6
+ kread((u_long)in6pcb.in6p_ppcb,
+ (char *)&tcp6cb, sizeof (tcp6cb));
+#else
+ kread((u_long)in6pcb.in6p_ppcb,
+ (char *)&tcpcb, sizeof (tcpcb));
+#endif
+ }
+ pcblist[i].ki_ppcbaddr =
+ istcp ? (uintptr_t) in6pcb.in6p_ppcb : (uintptr_t) prev;
+ pcblist[i].ki_rcvq = (uint64_t)sockb.so_rcv.sb_cc;
+ pcblist[i].ki_sndq = (uint64_t)sockb.so_snd.sb_cc;
+ sin6.sin6_addr = in6pcb.in6p_laddr;
+ sin6.sin6_port = in6pcb.in6p_lport;
+ memcpy(&pcblist[i].ki_s, &sin6, sizeof(sin6));
+ sin6.sin6_addr = in6pcb.in6p_faddr;
+ sin6.sin6_port = in6pcb.in6p_fport;
+ memcpy(&pcblist[i].ki_d, &sin6, sizeof(sin6));
+ pcblist[i].ki_tstate = tcpcb.t_state;
+ if (i++ == size) {
+ size += 100;
+ struct kinfo_pcb *n = realloc(pcblist,
+ size * sizeof(*pcblist));
+ if (n == NULL)
+ err(1, "realloc");
+ pcblist = n;
+ }
+ }
+ *len = i;
+ return pcblist;
+}
+
+void
+ip6protopr(u_long off, const char *name)
+{
+ struct kinfo_pcb *pcblist;
+ size_t i, len;
+ static int first = 1;
+
+ compact = 0;
+ if (Aflag) {
+ if (!numeric_addr)
+ width = 18;
+ else {
+ width = 21;
+ compact = 1;
+ }
+ } else
+ width = 22;
+
+ if (use_sysctl)
+ pcblist = getpcblist_sysctl(name, &len);
+ else
+ pcblist = getpcblist_kmem(off, name, &len);
+
+ for (i = 0; i < len; i++) {
+ struct sockaddr_in6 src, dst;
+
+ memcpy(&src, &pcblist[i].ki_s, sizeof(src));
+ memcpy(&dst, &pcblist[i].ki_d, sizeof(dst));
+
+ if (!aflag && IN6_IS_ADDR_UNSPECIFIED(&dst.sin6_addr))
+ continue;
+
+ if (first) {
+ ip6protoprhdr();
+ first = 0;
+ }
+
+ ip6protopr0((intptr_t) pcblist[i].ki_ppcbaddr,
+ pcblist[i].ki_rcvq, pcblist[i].ki_sndq,
+ &src.sin6_addr, src.sin6_port,
+ &dst.sin6_addr, dst.sin6_port,
+ pcblist[i].ki_tstate, name, NULL);
+ }
+
+ free(pcblist);
+
+#ifndef __minix
+ if (strcmp(name, "tcp6") == 0) {
+ struct timeval t;
+ timebase(&t);
+ gettimeofday(&now, NULL);
+ timersub(&now, &t, &now);
+ show_vtw_v6(print_vtw_v6);
+ }
+#endif /* !__minix */
+}
+
+#ifdef TCP6
+/*
+ * Dump TCP6 statistics structure.
+ */
+void
+tcp6_stats(u_long off, const char *name)
+{
+ struct tcp6stat tcp6stat;
+
+ if (use_sysctl) {
+ size_t size = sizeof(tcp6stat);
+
+ if (sysctlbyname("net.inet6.tcp6.stats", &tcp6stat, &size,
+ NULL, 0) == -1)
+ return;
+ } else {
+ warnx("%s stats not available via KVM.", name);
+ return;
+ }
+
+ printf ("%s:\n", name);
+
+#define p(f, m) if (tcp6stat.f || sflag <= 1) \
+ printf(m, tcp6stat.f, plural(tcp6stat.f))
+#define p2(f1, f2, m) if (tcp6stat.f1 || tcp6stat.f2 || sflag <= 1) \
+ printf(m, tcp6stat.f1, plural(tcp6stat.f1), tcp6stat.f2, plural(tcp6stat.f2))
+#define p3(f, m) if (tcp6stat.f || sflag <= 1) \
+ printf(m, tcp6stat.f, plurales(tcp6stat.f))
+
+ p(tcp6s_sndtotal, "\t%ld packet%s sent\n");
+ p2(tcp6s_sndpack,tcp6s_sndbyte,
+ "\t\t%ld data packet%s (%ld byte%s)\n");
+ p2(tcp6s_sndrexmitpack, tcp6s_sndrexmitbyte,
+ "\t\t%ld data packet%s (%ld byte%s) retransmitted\n");
+ p2(tcp6s_sndacks, tcp6s_delack,
+ "\t\t%ld ack-only packet%s (%ld packet%s delayed)\n");
+ p(tcp6s_sndurg, "\t\t%ld URG only packet%s\n");
+ p(tcp6s_sndprobe, "\t\t%ld window probe packet%s\n");
+ p(tcp6s_sndwinup, "\t\t%ld window update packet%s\n");
+ p(tcp6s_sndctrl, "\t\t%ld control packet%s\n");
+ p(tcp6s_rcvtotal, "\t%ld packet%s received\n");
+ p2(tcp6s_rcvackpack, tcp6s_rcvackbyte, "\t\t%ld ack%s (for %ld byte%s)\n");
+ p(tcp6s_rcvdupack, "\t\t%ld duplicate ack%s\n");
+ p(tcp6s_rcvacktoomuch, "\t\t%ld ack%s for unsent data\n");
+ p2(tcp6s_rcvpack, tcp6s_rcvbyte,
+ "\t\t%ld packet%s (%ld byte%s) received in-sequence\n");
+ p2(tcp6s_rcvduppack, tcp6s_rcvdupbyte,
+ "\t\t%ld completely duplicate packet%s (%ld byte%s)\n");
+ p(tcp6s_pawsdrop, "\t\t%ld old duplicate packet%s\n");
+ p2(tcp6s_rcvpartduppack, tcp6s_rcvpartdupbyte,
+ "\t\t%ld packet%s with some dup. data (%ld byte%s duped)\n");
+ p2(tcp6s_rcvoopack, tcp6s_rcvoobyte,
+ "\t\t%ld out-of-order packet%s (%ld byte%s)\n");
+ p2(tcp6s_rcvpackafterwin, tcp6s_rcvbyteafterwin,
+ "\t\t%ld packet%s (%ld byte%s) of data after window\n");
+ p(tcp6s_rcvwinprobe, "\t\t%ld window probe%s\n");
+ p(tcp6s_rcvwinupd, "\t\t%ld window update packet%s\n");
+ p(tcp6s_rcvafterclose, "\t\t%ld packet%s received after close\n");
+ p(tcp6s_rcvbadsum, "\t\t%ld discarded for bad checksum%s\n");
+ p(tcp6s_rcvbadoff, "\t\t%ld discarded for bad header offset field%s\n");
+ p(tcp6s_rcvshort, "\t\t%ld discarded because packet%s too short\n");
+ p(tcp6s_connattempt, "\t%ld connection request%s\n");
+ p(tcp6s_accepts, "\t%ld connection accept%s\n");
+ p(tcp6s_badsyn, "\t%ld bad connection attempt%s\n");
+ p(tcp6s_connects, "\t%ld connection%s established (including accepts)\n");
+ p2(tcp6s_closed, tcp6s_drops,
+ "\t%ld connection%s closed (including %ld drop%s)\n");
+ p(tcp6s_conndrops, "\t%ld embryonic connection%s dropped\n");
+ p2(tcp6s_rttupdated, tcp6s_segstimed,
+ "\t%ld segment%s updated rtt (of %ld attempt%s)\n");
+ p(tcp6s_rexmttimeo, "\t%ld retransmit timeout%s\n");
+ p(tcp6s_timeoutdrop, "\t\t%ld connection%s dropped by rexmit timeout\n");
+ p(tcp6s_persisttimeo, "\t%ld persist timeout%s\n");
+ p(tcp6s_persistdrop, "\t%ld connection%s timed out in persist\n");
+ p(tcp6s_keeptimeo, "\t%ld keepalive timeout%s\n");
+ p(tcp6s_keepprobe, "\t\t%ld keepalive probe%s sent\n");
+ p(tcp6s_keepdrops, "\t\t%ld connection%s dropped by keepalive\n");
+ p(tcp6s_predack, "\t%ld correct ACK header prediction%s\n");
+ p(tcp6s_preddat, "\t%ld correct data packet header prediction%s\n");
+ p3(tcp6s_pcbcachemiss, "\t%ld PCB cache miss%s\n");
+#undef p
+#undef p2
+#undef p3
+}
+#endif
+
+/*
+ * Dump UDP6 statistics structure.
+ */
+void
+udp6_stats(u_long off, const char *name)
+{
+ uint64_t udp6stat[UDP6_NSTATS];
+ u_quad_t delivered;
+
+ if (use_sysctl) {
+ size_t size = sizeof(udp6stat);
+
+ if (sysctlbyname("net.inet6.udp6.stats", udp6stat, &size,
+ NULL, 0) == -1)
+ return;
+ } else {
+ warnx("%s stats not available via KVM.", name);
+ return;
+ }
+ printf("%s:\n", name);
+#define p(f, m) if (udp6stat[f] || sflag <= 1) \
+ printf(m, (unsigned long long)udp6stat[f], plural(udp6stat[f]))
+#define p1(f, m) if (udp6stat[f] || sflag <= 1) \
+ printf(m, (unsigned long long)udp6stat[f])
+ p(UDP6_STAT_IPACKETS, "\t%llu datagram%s received\n");
+ p1(UDP6_STAT_HDROPS, "\t%llu with incomplete header\n");
+ p1(UDP6_STAT_BADLEN, "\t%llu with bad data length field\n");
+ p1(UDP6_STAT_BADSUM, "\t%llu with bad checksum\n");
+ p1(UDP6_STAT_NOSUM, "\t%llu with no checksum\n");
+ p1(UDP6_STAT_NOPORT, "\t%llu dropped due to no socket\n");
+ p(UDP6_STAT_NOPORTMCAST,
+ "\t%llu multicast datagram%s dropped due to no socket\n");
+ p1(UDP6_STAT_FULLSOCK, "\t%llu dropped due to full socket buffers\n");
+ delivered = udp6stat[UDP6_STAT_IPACKETS] -
+ udp6stat[UDP6_STAT_HDROPS] -
+ udp6stat[UDP6_STAT_BADLEN] -
+ udp6stat[UDP6_STAT_BADSUM] -
+ udp6stat[UDP6_STAT_NOPORT] -
+ udp6stat[UDP6_STAT_NOPORTMCAST] -
+ udp6stat[UDP6_STAT_FULLSOCK];
+ if (delivered || sflag <= 1)
+ printf("\t%llu delivered\n", (unsigned long long)delivered);
+ p(UDP6_STAT_OPACKETS, "\t%llu datagram%s output\n");
+#undef p
+#undef p1
+}
+
+static const char *ip6nh[] = {
+/*0*/ "hop by hop",
+ "ICMP",
+ "IGMP",
+ NULL,
+ "IP",
+/*5*/ NULL,
+ "TCP",
+ NULL,
+ NULL,
+ NULL,
+/*10*/ NULL, NULL, NULL, NULL, NULL,
+/*15*/ NULL,
+ NULL,
+ "UDP",
+ NULL,
+ NULL,
+/*20*/ NULL,
+ NULL,
+ "IDP",
+ NULL,
+ NULL,
+/*25*/ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+/*40*/ NULL,
+ "IP6",
+ NULL,
+ "routing",
+ "fragment",
+/*45*/ NULL, NULL, NULL, NULL, NULL,
+/*50*/ "ESP",
+ "AH",
+ NULL,
+ NULL,
+ NULL,
+/*55*/ NULL,
+ NULL,
+ NULL,
+ "ICMP6",
+ "no next header",
+/*60*/ "destination option",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+/*65*/ NULL, NULL, NULL, NULL, NULL,
+/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+/*80*/ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "OSPF",
+/*90*/ NULL, NULL, NULL, NULL, NULL,
+/*95*/ NULL,
+ NULL,
+ "Ethernet",
+ NULL,
+ NULL,
+/*100*/ NULL,
+ NULL,
+ NULL,
+ "PIM",
+ NULL,
+/*105*/ NULL, NULL, NULL, NULL, NULL,
+/*110*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+/*120*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+/*130*/ NULL,
+ NULL,
+ "SCTP",
+ NULL,
+ NULL,
+/*135*/ NULL, NULL, NULL, NULL, NULL,
+/*140*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+/*160*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+/*180*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+/*200*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+/*220*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+/*240*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL,
+};
+
+/*
+ * Dump IP6 statistics structure.
+ */
+void
+ip6_stats(u_long off, const char *name)
+{
+ uint64_t ip6stat[IP6_NSTATS];
+ int first, i;
+ struct protoent *ep;
+ const char *n;
+
+ if (use_sysctl) {
+ size_t size = sizeof(ip6stat);
+
+ if (sysctlbyname("net.inet6.ip6.stats", ip6stat, &size,
+ NULL, 0) == -1)
+ return;
+ } else {
+ warnx("%s stats not available via KVM.", name);
+ return;
+ }
+ printf("%s:\n", name);
+
+#define p(f, m) if (ip6stat[f] || sflag <= 1) \
+ printf(m, (unsigned long long)ip6stat[f], plural(ip6stat[f]))
+#define p1(f, m) if (ip6stat[f] || sflag <= 1) \
+ printf(m, (unsigned long long)ip6stat[f])
+
+ p(IP6_STAT_TOTAL, "\t%llu total packet%s received\n");
+ p1(IP6_STAT_TOOSMALL, "\t%llu with size smaller than minimum\n");
+ p1(IP6_STAT_TOOSHORT, "\t%llu with data size < data length\n");
+ p1(IP6_STAT_BADOPTIONS, "\t%llu with bad options\n");
+ p1(IP6_STAT_BADVERS, "\t%llu with incorrect version number\n");
+ p(IP6_STAT_FRAGMENTS, "\t%llu fragment%s received\n");
+ p(IP6_STAT_FRAGDROPPED,
+ "\t%llu fragment%s dropped (dup or out of space)\n");
+ p(IP6_STAT_FRAGTIMEOUT, "\t%llu fragment%s dropped after timeout\n");
+ p(IP6_STAT_FRAGOVERFLOW, "\t%llu fragment%s that exceeded limit\n");
+ p(IP6_STAT_REASSEMBLED, "\t%llu packet%s reassembled ok\n");
+ p(IP6_STAT_DELIVERED, "\t%llu packet%s for this host\n");
+ p(IP6_STAT_FORWARD, "\t%llu packet%s forwarded\n");
+ p(IP6_STAT_FASTFORWARD, "\t%llu packet%s fast forwarded\n");
+ p1(IP6_STAT_FASTFORWARDFLOWS, "\t%llu fast forward flows\n");
+ p(IP6_STAT_CANTFORWARD, "\t%llu packet%s not forwardable\n");
+ p(IP6_STAT_REDIRECTSENT, "\t%llu redirect%s sent\n");
+ p(IP6_STAT_LOCALOUT, "\t%llu packet%s sent from this host\n");
+ p(IP6_STAT_RAWOUT, "\t%llu packet%s sent with fabricated ip header\n");
+ p(IP6_STAT_ODROPPED,
+ "\t%llu output packet%s dropped due to no bufs, etc.\n");
+ p(IP6_STAT_NOROUTE, "\t%llu output packet%s discarded due to no route\n");
+ p(IP6_STAT_FRAGMENTED, "\t%llu output datagram%s fragmented\n");
+ p(IP6_STAT_OFRAGMENTS, "\t%llu fragment%s created\n");
+ p(IP6_STAT_CANTFRAG, "\t%llu datagram%s that can't be fragmented\n");
+ p(IP6_STAT_BADSCOPE, "\t%llu packet%s that violated scope rules\n");
+ p(IP6_STAT_NOTMEMBER, "\t%llu multicast packet%s which we don't join\n");
+ for (first = 1, i = 0; i < 256; i++)
+ if (ip6stat[IP6_STAT_NXTHIST + i] != 0) {
+ if (first) {
+ printf("\tInput packet histogram:\n");
+ first = 0;
+ }
+ n = NULL;
+ if (ip6nh[i])
+ n = ip6nh[i];
+ else if ((ep = getprotobynumber(i)) != NULL)
+ n = ep->p_name;
+ if (n)
+ printf("\t\t%s: %llu\n", n,
+ (unsigned long long)ip6stat[IP6_STAT_NXTHIST + i]);
+ else
+ printf("\t\t#%d: %llu\n", i,
+ (unsigned long long)ip6stat[IP6_STAT_NXTHIST + i]);
+ }
+ printf("\tMbuf statistics:\n");
+ p(IP6_STAT_M1, "\t\t%llu one mbuf%s\n");
+ for (first = 1, i = 0; i < 32; i++) {
+ char ifbuf[IFNAMSIZ];
+ if (ip6stat[IP6_STAT_M2M + i] != 0) {
+ if (first) {
+ printf("\t\ttwo or more mbuf:\n");
+ first = 0;
+ }
+ printf("\t\t\t%s = %llu\n",
+ if_indextoname(i, ifbuf),
+ (unsigned long long)ip6stat[IP6_STAT_M2M + i]);
+ }
+ }
+ p(IP6_STAT_MEXT1, "\t\t%llu one ext mbuf%s\n");
+ p(IP6_STAT_MEXT2M, "\t\t%llu two or more ext mbuf%s\n");
+ p(IP6_STAT_EXTHDRTOOLONG,
+ "\t%llu packet%s whose headers are not continuous\n");
+ p(IP6_STAT_NOGIF, "\t%llu tunneling packet%s that can't find gif\n");
+ p(IP6_STAT_TOOMANYHDR,
+ "\t%llu packet%s discarded due to too many headers\n");
+
+ /* for debugging source address selection */
+#define PRINT_SCOPESTAT(s,i) do {\
+ switch(i) { /* XXX hardcoding in each case */\
+ case 1:\
+ p(s, "\t\t%llu node-local%s\n");\
+ break;\
+ case 2:\
+ p(s, "\t\t%llu link-local%s\n");\
+ break;\
+ case 5:\
+ p(s, "\t\t%llu site-local%s\n");\
+ break;\
+ case 14:\
+ p(s, "\t\t%llu global%s\n");\
+ break;\
+ default:\
+ printf("\t\t%llu addresses scope=%x\n",\
+ (unsigned long long)ip6stat[s], i);\
+ }\
+ } while(/*CONSTCOND*/0);
+
+ p(IP6_STAT_SOURCES_NONE,
+ "\t%llu failure%s of source address selection\n");
+ for (first = 1, i = 0; i < 16; i++) {
+ if (ip6stat[IP6_STAT_SOURCES_SAMEIF + i]) {
+ if (first) {
+ printf("\tsource addresses on an outgoing I/F\n");
+ first = 0;
+ }
+ PRINT_SCOPESTAT(IP6_STAT_SOURCES_SAMEIF + i, i);
+ }
+ }
+ for (first = 1, i = 0; i < 16; i++) {
+ if (ip6stat[IP6_STAT_SOURCES_OTHERIF + i]) {
+ if (first) {
+ printf("\tsource addresses on a non-outgoing I/F\n");
+ first = 0;
+ }
+ PRINT_SCOPESTAT(IP6_STAT_SOURCES_OTHERIF + i, i);
+ }
+ }
+ for (first = 1, i = 0; i < 16; i++) {
+ if (ip6stat[IP6_STAT_SOURCES_SAMESCOPE + i]) {
+ if (first) {
+ printf("\tsource addresses of same scope\n");
+ first = 0;
+ }
+ PRINT_SCOPESTAT(IP6_STAT_SOURCES_SAMESCOPE + i, i);
+ }
+ }
+ for (first = 1, i = 0; i < 16; i++) {
+ if (ip6stat[IP6_STAT_SOURCES_OTHERSCOPE + i]) {
+ if (first) {
+ printf("\tsource addresses of a different scope\n");
+ first = 0;
+ }
+ PRINT_SCOPESTAT(IP6_STAT_SOURCES_OTHERSCOPE + i, i);
+ }
+ }
+ for (first = 1, i = 0; i < 16; i++) {
+ if (ip6stat[IP6_STAT_SOURCES_DEPRECATED + i]) {
+ if (first) {
+ printf("\tdeprecated source addresses\n");
+ first = 0;
+ }
+ PRINT_SCOPESTAT(IP6_STAT_SOURCES_DEPRECATED + i, i);
+ }
+ }
+
+ p1(IP6_STAT_FORWARD_CACHEHIT, "\t%llu forward cache hit\n");
+ p1(IP6_STAT_FORWARD_CACHEMISS, "\t%llu forward cache miss\n");
+#undef p
+#undef p1
+}
+
+/*
+ * Dump IPv6 per-interface statistics based on RFC 2465.
+ */
+void
+ip6_ifstats(const char *ifname)
+{
+ struct in6_ifreq ifr;
+ int s;
+#define p(f, m) if (ifr.ifr_ifru.ifru_stat.f || sflag <= 1) \
+ printf(m, (unsigned long long)ifr.ifr_ifru.ifru_stat.f, \
+ plural(ifr.ifr_ifru.ifru_stat.f))
+#define p_5(f, m) if (ifr.ifr_ifru.ifru_stat.f || sflag <= 1) \
+ printf(m, (unsigned long long)ip6stat.f)
+
+ if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+ perror("Warning: socket(AF_INET6)");
+ return;
+ }
+
+ strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ printf("ip6 on %s:\n", ifname);
+
+ if (ioctl(s, SIOCGIFSTAT_IN6, (char *)&ifr) < 0) {
+ perror("Warning: ioctl(SIOCGIFSTAT_IN6)");
+ goto end;
+ }
+
+ p(ifs6_in_receive, "\t%llu total input datagram%s\n");
+ p(ifs6_in_hdrerr, "\t%llu datagram%s with invalid header received\n");
+ p(ifs6_in_toobig, "\t%llu datagram%s exceeded MTU received\n");
+ p(ifs6_in_noroute, "\t%llu datagram%s with no route received\n");
+ p(ifs6_in_addrerr, "\t%llu datagram%s with invalid dst received\n");
+ p(ifs6_in_truncated, "\t%llu truncated datagram%s received\n");
+ p(ifs6_in_protounknown, "\t%llu datagram%s with unknown proto received\n");
+ p(ifs6_in_discard, "\t%llu input datagram%s discarded\n");
+ p(ifs6_in_deliver,
+ "\t%llu datagram%s delivered to an upper layer protocol\n");
+ p(ifs6_out_forward, "\t%llu datagram%s forwarded to this interface\n");
+ p(ifs6_out_request,
+ "\t%llu datagram%s sent from an upper layer protocol\n");
+ p(ifs6_out_discard, "\t%llu total discarded output datagram%s\n");
+ p(ifs6_out_fragok, "\t%llu output datagram%s fragmented\n");
+ p(ifs6_out_fragfail, "\t%llu output datagram%s failed on fragment\n");
+ p(ifs6_out_fragcreat, "\t%llu output datagram%s succeeded on fragment\n");
+ p(ifs6_reass_reqd, "\t%llu incoming datagram%s fragmented\n");
+ p(ifs6_reass_ok, "\t%llu datagram%s reassembled\n");
+ p(ifs6_reass_fail, "\t%llu datagram%s failed on reassembling\n");
+ p(ifs6_in_mcast, "\t%llu multicast datagram%s received\n");
+ p(ifs6_out_mcast, "\t%llu multicast datagram%s sent\n");
+
+ end:
+ close(s);
+
+#undef p
+#undef p_5
+}
+
+static const char *icmp6names[] = {
+ "#0",
+ "unreach",
+ "packet too big",
+ "time exceed",
+ "parameter problem",
+ "#5",
+ "#6",
+ "#7",
+ "#8",
+ "#9",
+ "#10",
+ "#11",
+ "#12",
+ "#13",
+ "#14",
+ "#15",
+ "#16",
+ "#17",
+ "#18",
+ "#19",
+ "#20",
+ "#21",
+ "#22",
+ "#23",
+ "#24",
+ "#25",
+ "#26",
+ "#27",
+ "#28",
+ "#29",
+ "#30",
+ "#31",
+ "#32",
+ "#33",
+ "#34",
+ "#35",
+ "#36",
+ "#37",
+ "#38",
+ "#39",
+ "#40",
+ "#41",
+ "#42",
+ "#43",
+ "#44",
+ "#45",
+ "#46",
+ "#47",
+ "#48",
+ "#49",
+ "#50",
+ "#51",
+ "#52",
+ "#53",
+ "#54",
+ "#55",
+ "#56",
+ "#57",
+ "#58",
+ "#59",
+ "#60",
+ "#61",
+ "#62",
+ "#63",
+ "#64",
+ "#65",
+ "#66",
+ "#67",
+ "#68",
+ "#69",
+ "#70",
+ "#71",
+ "#72",
+ "#73",
+ "#74",
+ "#75",
+ "#76",
+ "#77",
+ "#78",
+ "#79",
+ "#80",
+ "#81",
+ "#82",
+ "#83",
+ "#84",
+ "#85",
+ "#86",
+ "#87",
+ "#88",
+ "#89",
+ "#80",
+ "#91",
+ "#92",
+ "#93",
+ "#94",
+ "#95",
+ "#96",
+ "#97",
+ "#98",
+ "#99",
+ "#100",
+ "#101",
+ "#102",
+ "#103",
+ "#104",
+ "#105",
+ "#106",
+ "#107",
+ "#108",
+ "#109",
+ "#110",
+ "#111",
+ "#112",
+ "#113",
+ "#114",
+ "#115",
+ "#116",
+ "#117",
+ "#118",
+ "#119",
+ "#120",
+ "#121",
+ "#122",
+ "#123",
+ "#124",
+ "#125",
+ "#126",
+ "#127",
+ "echo",
+ "echo reply",
+ "multicast listener query",
+ "multicast listener report",
+ "multicast listener done",
+ "router solicitation",
+ "router advertisement",
+ "neighbor solicitation",
+ "neighbor advertisement",
+ "redirect",
+ "router renumbering",
+ "node information request",
+ "node information reply",
+ "#141",
+ "#142",
+ "#143",
+ "#144",
+ "#145",
+ "#146",
+ "#147",
+ "#148",
+ "#149",
+ "#150",
+ "#151",
+ "#152",
+ "#153",
+ "#154",
+ "#155",
+ "#156",
+ "#157",
+ "#158",
+ "#159",
+ "#160",
+ "#161",
+ "#162",
+ "#163",
+ "#164",
+ "#165",
+ "#166",
+ "#167",
+ "#168",
+ "#169",
+ "#170",
+ "#171",
+ "#172",
+ "#173",
+ "#174",
+ "#175",
+ "#176",
+ "#177",
+ "#178",
+ "#179",
+ "#180",
+ "#181",
+ "#182",
+ "#183",
+ "#184",
+ "#185",
+ "#186",
+ "#187",
+ "#188",
+ "#189",
+ "#180",
+ "#191",
+ "#192",
+ "#193",
+ "#194",
+ "#195",
+ "#196",
+ "#197",
+ "#198",
+ "#199",
+ "#200",
+ "#201",
+ "#202",
+ "#203",
+ "#204",
+ "#205",
+ "#206",
+ "#207",
+ "#208",
+ "#209",
+ "#210",
+ "#211",
+ "#212",
+ "#213",
+ "#214",
+ "#215",
+ "#216",
+ "#217",
+ "#218",
+ "#219",
+ "#220",
+ "#221",
+ "#222",
+ "#223",
+ "#224",
+ "#225",
+ "#226",
+ "#227",
+ "#228",
+ "#229",
+ "#230",
+ "#231",
+ "#232",
+ "#233",
+ "#234",
+ "#235",
+ "#236",
+ "#237",
+ "#238",
+ "#239",
+ "#240",
+ "#241",
+ "#242",
+ "#243",
+ "#244",
+ "#245",
+ "#246",
+ "#247",
+ "#248",
+ "#249",
+ "#250",
+ "#251",
+ "#252",
+ "#253",
+ "#254",
+ "#255",
+};
+
+/*
+ * Dump ICMPv6 statistics.
+ */
+void
+icmp6_stats(u_long off, const char *name)
+{
+ uint64_t icmp6stat[ICMP6_NSTATS];
+ int i, first;
+
+ if (use_sysctl) {
+ size_t size = sizeof(icmp6stat);
+
+ if (sysctlbyname("net.inet6.icmp6.stats", icmp6stat, &size,
+ NULL, 0) == -1)
+ return;
+ } else {
+ warnx("%s stats not available via KVM.", name);
+ return;
+ }
+
+ printf("%s:\n", name);
+
+#define p(f, m) if (icmp6stat[f] || sflag <= 1) \
+ printf(m, (unsigned long long)icmp6stat[f], plural(icmp6stat[f]))
+#define p_oerr(f, m) if (icmp6stat[ICMP6_STAT_OUTERRHIST + f] || sflag <= 1) \
+ printf(m, (unsigned long long)icmp6stat[ICMP6_STAT_OUTERRHIST + f])
+
+ p(ICMP6_STAT_ERROR, "\t%llu call%s to icmp6_error\n");
+ p(ICMP6_STAT_CANTERROR,
+ "\t%llu error%s not generated because old message was icmp6 or so\n");
+ p(ICMP6_STAT_TOOFREQ,
+ "\t%llu error%s not generated because of rate limitation\n");
+ for (first = 1, i = 0; i < 256; i++)
+ if (icmp6stat[ICMP6_STAT_OUTHIST + i] != 0) {
+ if (first) {
+ printf("\tOutput packet histogram:\n");
+ first = 0;
+ }
+ printf("\t\t%s: %llu\n", icmp6names[i],
+ (unsigned long long)icmp6stat[ICMP6_STAT_OUTHIST + i]);
+ }
+ p(ICMP6_STAT_BADCODE, "\t%llu message%s with bad code fields\n");
+ p(ICMP6_STAT_TOOSHORT, "\t%llu message%s < minimum length\n");
+ p(ICMP6_STAT_CHECKSUM, "\t%llu bad checksum%s\n");
+ p(ICMP6_STAT_BADLEN, "\t%llu message%s with bad length\n");
+ for (first = 1, i = 0; i < ICMP6_MAXTYPE; i++)
+ if (icmp6stat[ICMP6_STAT_INHIST + i] != 0) {
+ if (first) {
+ printf("\tInput packet histogram:\n");
+ first = 0;
+ }
+ printf("\t\t%s: %llu\n", icmp6names[i],
+ (unsigned long long)icmp6stat[ICMP6_STAT_INHIST + i]);
+ }
+ printf("\tHistogram of error messages to be generated:\n");
+ p_oerr(ICMP6_ERRSTAT_DST_UNREACH_NOROUTE, "\t\t%llu no route\n");
+ p_oerr(ICMP6_ERRSTAT_DST_UNREACH_ADMIN, "\t\t%llu administratively prohibited\n");
+ p_oerr(ICMP6_ERRSTAT_DST_UNREACH_BEYONDSCOPE, "\t\t%llu beyond scope\n");
+ p_oerr(ICMP6_ERRSTAT_DST_UNREACH_ADDR, "\t\t%llu address unreachable\n");
+ p_oerr(ICMP6_ERRSTAT_DST_UNREACH_NOPORT, "\t\t%llu port unreachable\n");
+ p_oerr(ICMP6_ERRSTAT_PACKET_TOO_BIG, "\t\t%llu packet too big\n");
+ p_oerr(ICMP6_ERRSTAT_TIME_EXCEED_TRANSIT, "\t\t%llu time exceed transit\n");
+ p_oerr(ICMP6_ERRSTAT_TIME_EXCEED_REASSEMBLY, "\t\t%llu time exceed reassembly\n");
+ p_oerr(ICMP6_ERRSTAT_PARAMPROB_HEADER, "\t\t%llu erroneous header field\n");
+ p_oerr(ICMP6_ERRSTAT_PARAMPROB_NEXTHEADER, "\t\t%llu unrecognized next header\n");
+ p_oerr(ICMP6_ERRSTAT_PARAMPROB_OPTION, "\t\t%llu unrecognized option\n");
+ p_oerr(ICMP6_ERRSTAT_REDIRECT, "\t\t%llu redirect\n");
+ p_oerr(ICMP6_ERRSTAT_UNKNOWN, "\t\t%llu unknown\n");
+
+ p(ICMP6_STAT_REFLECT, "\t%llu message response%s generated\n");
+ p(ICMP6_STAT_ND_TOOMANYOPT, "\t%llu message%s with too many ND options\n");
+ p(ICMP6_STAT_ND_BADOPT, "\t%llu message%s with bad ND options\n");
+ p(ICMP6_STAT_BADNS, "\t%llu bad neighbor solicitation message%s\n");
+ p(ICMP6_STAT_BADNA, "\t%llu bad neighbor advertisement message%s\n");
+ p(ICMP6_STAT_BADRS, "\t%llu bad router solicitation message%s\n");
+ p(ICMP6_STAT_BADRA, "\t%llu bad router advertisement message%s\n");
+ p(ICMP6_STAT_DROPPED_RAROUTE, "\t%llu router advertisement route%s dropped\n");
+ p(ICMP6_STAT_BADREDIRECT, "\t%llu bad redirect message%s\n");
+ p(ICMP6_STAT_PMTUCHG, "\t%llu path MTU change%s\n");
+#undef p
+#undef p_oerr
+}
+
+/*
+ * Dump ICMPv6 per-interface statistics based on RFC 2466.
+ */
+void
+icmp6_ifstats(const char *ifname)
+{
+ struct in6_ifreq ifr;
+ int s;
+#define p(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1) \
+ printf(m, (unsigned long long)ifr.ifr_ifru.ifru_icmp6stat.f, \
+ plural(ifr.ifr_ifru.ifru_icmp6stat.f))
+
+ if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+ perror("Warning: socket(AF_INET6)");
+ return;
+ }
+
+ strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ printf("icmp6 on %s:\n", ifname);
+
+ if (ioctl(s, SIOCGIFSTAT_ICMP6, (char *)&ifr) < 0) {
+ perror("Warning: ioctl(SIOCGIFSTAT_ICMP6)");
+ goto end;
+ }
+
+ p(ifs6_in_msg, "\t%llu total input message%s\n");
+ p(ifs6_in_error, "\t%llu total input error message%s\n");
+ p(ifs6_in_dstunreach, "\t%llu input destination unreachable error%s\n");
+ p(ifs6_in_adminprohib, "\t%llu input administratively prohibited error%s\n");
+ p(ifs6_in_timeexceed, "\t%llu input time exceeded error%s\n");
+ p(ifs6_in_paramprob, "\t%llu input parameter problem error%s\n");
+ p(ifs6_in_pkttoobig, "\t%llu input packet too big error%s\n");
+ p(ifs6_in_echo, "\t%llu input echo request%s\n");
+ p(ifs6_in_echoreply, "\t%llu input echo reply%s\n");
+ p(ifs6_in_routersolicit, "\t%llu input router solicitation%s\n");
+ p(ifs6_in_routeradvert, "\t%llu input router advertisement%s\n");
+ p(ifs6_in_neighborsolicit, "\t%llu input neighbor solicitation%s\n");
+ p(ifs6_in_neighboradvert, "\t%llu input neighbor advertisement%s\n");
+ p(ifs6_in_redirect, "\t%llu input redirect%s\n");
+ p(ifs6_in_mldquery, "\t%llu input MLD query%s\n");
+ p(ifs6_in_mldreport, "\t%llu input MLD report%s\n");
+ p(ifs6_in_mlddone, "\t%llu input MLD done%s\n");
+
+ p(ifs6_out_msg, "\t%llu total output message%s\n");
+ p(ifs6_out_error, "\t%llu total output error message%s\n");
+ p(ifs6_out_dstunreach, "\t%llu output destination unreachable error%s\n");
+ p(ifs6_out_adminprohib, "\t%llu output administratively prohibited error%s\n");
+ p(ifs6_out_timeexceed, "\t%llu output time exceeded error%s\n");
+ p(ifs6_out_paramprob, "\t%llu output parameter problem error%s\n");
+ p(ifs6_out_pkttoobig, "\t%llu output packet too big error%s\n");
+ p(ifs6_out_echo, "\t%llu output echo request%s\n");
+ p(ifs6_out_echoreply, "\t%llu output echo reply%s\n");
+ p(ifs6_out_routersolicit, "\t%llu output router solicitation%s\n");
+ p(ifs6_out_routeradvert, "\t%llu output router advertisement%s\n");
+ p(ifs6_out_neighborsolicit, "\t%llu output neighbor solicitation%s\n");
+ p(ifs6_out_neighboradvert, "\t%llu output neighbor advertisement%s\n");
+ p(ifs6_out_redirect, "\t%llu output redirect%s\n");
+ p(ifs6_out_mldquery, "\t%llu output MLD query%s\n");
+ p(ifs6_out_mldreport, "\t%llu output MLD report%s\n");
+ p(ifs6_out_mlddone, "\t%llu output MLD done%s\n");
+
+ end:
+ close(s);
+#undef p
+}
+
+/*
+ * Dump PIM statistics structure.
+ */
+void
+pim6_stats(u_long off, const char *name)
+{
+ uint64_t pim6stat[PIM6_NSTATS];
+
+ if (use_sysctl) {
+ size_t size = sizeof(pim6stat);
+
+ if (sysctlbyname("net.inet6.pim6.stats", pim6stat, &size,
+ NULL, 0) == -1)
+ return;
+ } else {
+ warnx("%s stats not available via KVM.", name);
+ return;
+ }
+ printf("%s:\n", name);
+
+#define p(f, m) if (pim6stat[f] || sflag <= 1) \
+ printf(m, (unsigned long long)pim6stat[f], plural(pim6stat[f]))
+ p(PIM6_STAT_RCV_TOTAL, "\t%llu message%s received\n");
+ p(PIM6_STAT_RCV_TOOSHORT, "\t%llu message%s received with too few bytes\n");
+ p(PIM6_STAT_RCV_BADSUM, "\t%llu message%s received with bad checksum\n");
+ p(PIM6_STAT_RCV_BADVERSION, "\t%llu message%s received with bad version\n");
+ p(PIM6_STAT_RCV_REGISTERS, "\t%llu register%s received\n");
+ p(PIM6_STAT_RCV_BADREGISTERS, "\t%llu bad register%s received\n");
+ p(PIM6_STAT_SND_REGISTERS, "\t%llu register%s sent\n");
+#undef p
+}
+
+/*
+ * Dump raw ip6 statistics structure.
+ */
+void
+rip6_stats(u_long off, const char *name)
+{
+ uint64_t rip6stat[RIP6_NSTATS];
+ u_quad_t delivered;
+
+ if (use_sysctl) {
+ size_t size = sizeof(rip6stat);
+
+ if (sysctlbyname("net.inet6.raw6.stats", rip6stat, &size,
+ NULL, 0) == -1)
+ return;
+ } else {
+ warnx("%s stats not available via KVM.", name);
+ return;
+ }
+ printf("%s:\n", name);
+
+#define p(f, m) if (rip6stat[f] || sflag <= 1) \
+ printf(m, (unsigned long long)rip6stat[f], plural(rip6stat[f]))
+ p(RIP6_STAT_IPACKETS, "\t%llu message%s received\n");
+ p(RIP6_STAT_ISUM, "\t%llu checksum calculation%s on inbound\n");
+ p(RIP6_STAT_BADSUM, "\t%llu message%s with bad checksum\n");
+ p(RIP6_STAT_NOSOCK, "\t%llu message%s dropped due to no socket\n");
+ p(RIP6_STAT_NOSOCKMCAST,
+ "\t%llu multicast message%s dropped due to no socket\n");
+ p(RIP6_STAT_FULLSOCK,
+ "\t%llu message%s dropped due to full socket buffers\n");
+ delivered = rip6stat[RIP6_STAT_IPACKETS] -
+ rip6stat[RIP6_STAT_BADSUM] -
+ rip6stat[RIP6_STAT_NOSOCK] -
+ rip6stat[RIP6_STAT_NOSOCKMCAST] -
+ rip6stat[RIP6_STAT_FULLSOCK];
+ if (delivered || sflag <= 1)
+ printf("\t%llu delivered\n", (unsigned long long)delivered);
+ p(RIP6_STAT_OPACKETS, "\t%llu datagram%s output\n");
+#undef p
+}
+
+/*
+ * Pretty print an Internet address (net address + port).
+ * Take numeric_addr and numeric_port into consideration.
+ */
+void
+inet6print(const struct in6_addr *in6, int port, const char *proto)
+{
+#define GETSERVBYPORT6(port, proto, ret)\
+do {\
+ if (strcmp((proto), "tcp6") == 0)\
+ (ret) = getservbyport((int)(port), "tcp");\
+ else if (strcmp((proto), "udp6") == 0)\
+ (ret) = getservbyport((int)(port), "udp");\
+ else\
+ (ret) = getservbyport((int)(port), (proto));\
+} while (0)
+ struct servent *sp = 0;
+ char line[80], *cp;
+ int lwidth;
+
+ lwidth = Aflag ? 12 : 16;
+ if (vflag && lwidth < (int)strlen(inet6name(in6)))
+ lwidth = strlen(inet6name(in6));
+ snprintf(line, sizeof(line), "%.*s.", lwidth, inet6name(in6));
+ cp = strchr(line, '\0');
+ if (!numeric_port && port)
+ GETSERVBYPORT6(port, proto, sp);
+ if (sp || port == 0)
+ snprintf(cp, sizeof(line) - (cp - line),
+ "%s", sp ? sp->s_name : "*");
+ else
+ snprintf(cp, sizeof(line) - (cp - line),
+ "%d", ntohs((u_short)port));
+ lwidth = Aflag ? 18 : 22;
+ if (vflag && lwidth < (int)strlen(line))
+ lwidth = strlen(line);
+ printf(" %-*.*s", lwidth, lwidth, line);
+}
+
+/*
+ * Construct an Internet address representation.
+ * If the numeric_addr has been supplied, give
+ * numeric value, otherwise try for symbolic name.
+ */
+
+char *
+inet6name(const struct in6_addr *in6p)
+{
+ char *cp;
+ static char line[NI_MAXHOST];
+ struct hostent *hp;
+ static char domain[MAXHOSTNAMELEN + 1];
+ static int first = 1;
+ char hbuf[NI_MAXHOST];
+ struct sockaddr_in6 sin6;
+ const int niflag = NI_NUMERICHOST;
+
+ if (first && !numeric_addr) {
+ first = 0;
+ if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
+ (cp = strchr(domain, '.')))
+ (void) strlcpy(domain, cp + 1, sizeof(domain));
+ else
+ domain[0] = 0;
+ }
+ cp = 0;
+ if (!numeric_addr && !IN6_IS_ADDR_UNSPECIFIED(in6p)) {
+ hp = gethostbyaddr((const char *)in6p, sizeof(*in6p), AF_INET6);
+ if (hp) {
+ if ((cp = strchr(hp->h_name, '.')) &&
+ !strcmp(cp + 1, domain))
+ *cp = 0;
+ cp = hp->h_name;
+ }
+ }
+ if (IN6_IS_ADDR_UNSPECIFIED(in6p))
+ strlcpy(line, "*", sizeof(line));
+ else if (cp)
+ strlcpy(line, cp, sizeof(line));
+ else {
+ memset(&sin6, 0, sizeof(sin6));
+ sin6.sin6_len = sizeof(sin6);
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_addr = *in6p;
+ inet6_getscopeid(&sin6, INET6_IS_ADDR_LINKLOCAL|
+ INET6_IS_ADDR_MC_LINKLOCAL);
+ if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
+ hbuf, sizeof(hbuf), NULL, 0, niflag) != 0)
+ strlcpy(hbuf, "?", sizeof(hbuf));
+ strlcpy(line, hbuf, sizeof(line));
+ }
+ return (line);
+}
+
+/*
+ * Dump the contents of a TCP6 PCB.
+ */
+void
+tcp6_dump(u_long off, const char *name, u_long pcbaddr)
+{
+ callout_impl_t *ci;
+ int i, hardticks;
+ struct kinfo_pcb *pcblist;
+#ifdef TCP6
+#define mypcb tcp6cb
+#else
+#define mypcb tcpcb
+#endif
+ size_t j, len;
+
+ if (use_sysctl)
+ pcblist = getpcblist_sysctl(name, &len);
+ else
+ pcblist = getpcblist_kmem(off, name, &len);
+
+ for (j = 0; j < len; j++)
+ if (pcblist[j].ki_ppcbaddr == pcbaddr)
+ break;
+ free(pcblist);
+
+ if (j == len)
+ errx(1, "0x%lx is not a valid pcb address", pcbaddr);
+
+ kread(pcbaddr, (char *)&mypcb, sizeof(mypcb));
+ hardticks = get_hardticks();
+
+ printf("TCP Protocol Control Block at 0x%08lx:\n\n", pcbaddr);
+ printf("Timers:\n");
+ for (i = 0; i < TCP6T_NTIMERS; i++) {
+ char buf[128];
+ ci = (callout_impl_t *)&tcpcb.t_timer[i];
+ snprintb(buf, sizeof(buf), CALLOUT_FMT, ci->c_flags);
+ printf("\t%s\t%s", tcptimers[i], buf);
+ if (ci->c_flags & CALLOUT_PENDING)
+ printf("\t%d\n", ci->c_time - hardticks);
+ else
+ printf("\n");
+ }
+ printf("\n\n");
+
+ if (mypcb.t_state < 0 || mypcb.t_state >= TCP6_NSTATES)
+ printf("State: %d", mypcb.t_state);
+ else
+ printf("State: %s", tcp6states[mypcb.t_state]);
+ printf(", flags 0x%x, in6pcb 0x%lx\n\n", mypcb.t_flags,
+ (u_long)mypcb.t_in6pcb);
+
+ printf("rxtshift %d, rxtcur %d, dupacks %d\n", mypcb.t_rxtshift,
+ mypcb.t_rxtcur, mypcb.t_dupacks);
+#ifdef TCP6
+ printf("peermaxseg %u, maxseg %u, force %d\n\n", mypcb.t_peermaxseg,
+ mypcb.t_maxseg, mypcb.t_force);
+#endif
+
+ printf("snd_una %u, snd_nxt %u, snd_up %u\n",
+ mypcb.snd_una, mypcb.snd_nxt, mypcb.snd_up);
+ printf("snd_wl1 %u, snd_wl2 %u, iss %u, snd_wnd %llu\n\n",
+ mypcb.snd_wl1, mypcb.snd_wl2, mypcb.iss,
+ (unsigned long long)mypcb.snd_wnd);
+
+ printf("rcv_wnd %llu, rcv_nxt %u, rcv_up %u, irs %u\n\n",
+ (unsigned long long)mypcb.rcv_wnd, mypcb.rcv_nxt,
+ mypcb.rcv_up, mypcb.irs);
+
+ printf("rcv_adv %u, snd_max %u, snd_cwnd %llu, snd_ssthresh %llu\n",
+ mypcb.rcv_adv, mypcb.snd_max, (unsigned long long)mypcb.snd_cwnd,
+ (unsigned long long)mypcb.snd_ssthresh);
+
+#ifdef TCP6
+ printf("idle %d, rtt %d, " mypcb.t_idle, mypcb.t_rtt)
+#endif
+ printf("rtseq %u, srtt %d, rttvar %d, rttmin %d, "
+ "max_sndwnd %llu\n\n", mypcb.t_rtseq,
+ mypcb.t_srtt, mypcb.t_rttvar, mypcb.t_rttmin,
+ (unsigned long long)mypcb.max_sndwnd);
+
+ printf("oobflags %d, iobc %d, softerror %d\n\n", mypcb.t_oobflags,
+ mypcb.t_iobc, mypcb.t_softerror);
+
+ printf("snd_scale %d, rcv_scale %d, req_r_scale %d, req_s_scale %d\n",
+ mypcb.snd_scale, mypcb.rcv_scale, mypcb.request_r_scale,
+ mypcb.requested_s_scale);
+ printf("ts_recent %u, ts_regent_age %d, last_ack_sent %u\n",
+ mypcb.ts_recent, mypcb.ts_recent_age, mypcb.last_ack_sent);
+}
+
+#endif /*INET6*/
--- /dev/null
+/* $NetBSD: main.c,v 1.95 2014/11/12 03:34:59 christos Exp $ */
+
+/*
+ * Copyright (c) 1983, 1988, 1993
+ * Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__COPYRIGHT("@(#) Copyright (c) 1983, 1988, 1993\
+ Regents of the University of California. All rights reserved.");
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "from: @(#)main.c 8.4 (Berkeley) 3/1/94";
+#else
+__RCSID("$NetBSD: main.c,v 1.95 2014/11/12 03:34:59 christos Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <kvm.h>
+#include <limits.h>
+#include <netdb.h>
+#include <nlist.h>
+#include <paths.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "netstat.h"
+#include "rtutil.h"
+#include "prog_ops.h"
+
+struct nlist nl[] = {
+#define N_MBSTAT 0
+ { "_mbstat", 0, 0, 0, 0 },
+#define N_IPSTAT 1
+ { "_ipstat", 0, 0, 0, 0 }, /* not available via kvm */
+#define N_TCBTABLE 2
+ { "_tcbtable", 0, 0, 0, 0 },
+#define N_TCPSTAT 3
+ { "_tcpstat", 0, 0, 0, 0 }, /* not available via kvm */
+#define N_UDBTABLE 4
+ { "_udbtable", 0, 0, 0, 0 },
+#define N_UDPSTAT 5
+ { "_udpstat", 0, 0, 0, 0 }, /* not available via kvm */
+#define N_IFNET_LIST 6
+ { "_ifnet_list", 0, 0, 0, 0 },
+#define N_ICMPSTAT 7
+ { "_icmpstat", 0, 0, 0, 0 }, /* not available via kvm */
+#define N_RTSTAT 8
+ { "_rtstat", 0, 0, 0, 0 },
+#define N_UNIXSW 9
+ { "_unixsw", 0, 0, 0, 0 },
+#define N_RTREE 10
+ { "_rt_tables", 0, 0, 0, 0 },
+#define N_NFILE 11
+ { "_nfile", 0, 0, 0, 0 },
+#define N_IGMPSTAT 12
+ { "_igmpstat", 0, 0, 0, 0 }, /* not available via kvm */
+#define N_MRTPROTO 13
+ { "_ip_mrtproto", 0, 0, 0, 0 },
+#define N_MRTSTAT 14
+ { "_mrtstat", 0, 0, 0, 0 },
+#define N_MFCHASHTBL 15
+ { "_mfchashtbl", 0, 0, 0, 0 },
+#define N_MFCHASH 16
+ { "_mfchash", 0, 0, 0, 0 },
+#define N_VIFTABLE 17
+ { "_viftable", 0, 0, 0, 0 },
+#define N_MSIZE 18
+ { "_msize", 0, 0, 0, 0 },
+#define N_MCLBYTES 19
+ { "_mclbytes", 0, 0, 0, 0 },
+#define N_DDPSTAT 20
+ { "_ddpstat", 0, 0, 0, 0 }, /* not available via kvm */
+#define N_DDPCB 21
+ { "_ddpcb", 0, 0, 0, 0 },
+#define N_MBPOOL 22
+ { "_mbpool", 0, 0, 0, 0 },
+#define N_MCLPOOL 23
+ { "_mclpool", 0, 0, 0, 0 },
+#define N_IP6STAT 24
+ { "_ip6stat", 0, 0, 0, 0 }, /* not available via kvm */
+#define N_TCP6STAT 25
+ { "_tcp6stat", 0, 0, 0, 0 }, /* not available via kvm */
+#define N_UDP6STAT 26
+ { "_udp6stat", 0, 0, 0, 0 }, /* not available via kvm */
+#define N_ICMP6STAT 27
+ { "_icmp6stat", 0, 0, 0, 0 }, /* not available via kvm */
+#define N_IPSECSTAT 28
+ { "_ipsecstat", 0, 0, 0, 0 }, /* not available via kvm */
+#define N_IPSEC6STAT 29
+ { "_ipsec6stat", 0, 0, 0, 0 }, /* not available via kvm */
+#define N_PIM6STAT 30
+ { "_pim6stat", 0, 0, 0, 0 }, /* not available via kvm */
+#define N_MRT6PROTO 31
+ { "_ip6_mrtproto", 0, 0, 0, 0 },
+#define N_MRT6STAT 32
+ { "_mrt6stat", 0, 0, 0, 0 },
+#define N_MF6CTABLE 33
+ { "_mf6ctable", 0, 0, 0, 0 },
+#define N_MIF6TABLE 34
+ { "_mif6table", 0, 0, 0, 0 },
+#define N_PFKEYSTAT 35
+ { "_pfkeystat", 0, 0, 0, 0 }, /* not available via kvm */
+#define N_ARPSTAT 36
+ { "_arpstat", 0, 0, 0, 0 }, /* not available via kvm */
+#define N_RIP6STAT 37
+ { "_rip6stat", 0, 0, 0, 0 }, /* not available via kvm */
+#define N_ARPINTRQ 38
+ { "_arpintrq", 0, 0, 0, 0 },
+#define N_IPINTRQ 39
+ { "_ipintrq", 0, 0, 0, 0 },
+#define N_IP6INTRQ 40
+ { "_ip6intrq", 0, 0, 0, 0 },
+#define N_ATINTRQ1 41
+ { "_atintrq1", 0, 0, 0, 0 },
+#define N_ATINTRQ2 42
+ { "_atintrq2", 0, 0, 0, 0 },
+#define N_NSINTRQ 43
+ { "_nsintrq", 0, 0, 0, 0 },
+#define N_LLCINTRQ 44
+ { "_llcintrq", 0, 0, 0, 0 },
+#define N_HDINTRQ 45
+ { "_hdintrq", 0, 0, 0, 0 },
+#define N_NATMINTRQ 46
+ { "_natmintrq", 0, 0, 0, 0 },
+#define N_PPPOEDISCINQ 47
+ { "_ppoediscinq", 0, 0, 0, 0 },
+#define N_PPPOEINQ 48
+ { "_ppoeinq", 0, 0, 0, 0 },
+#define N_PKINTRQ 49
+ { "_pkintrq", 0, 0, 0, 0 },
+#define N_HARDCLOCK_TICKS 50
+ { "_hardclock_ticks", 0, 0, 0, 0 },
+#define N_PIMSTAT 51
+ { "_pimstat", 0, 0, 0, 0 },
+#define N_CARPSTAT 52
+ { "_carpstats", 0, 0, 0, 0 }, /* not available via kvm */
+#define N_PFSYNCSTAT 53
+ { "_pfsyncstats", 0, 0, 0, 0}, /* not available via kvm */
+ { "", 0, 0, 0, 0 },
+};
+
+struct protox {
+ u_char pr_index; /* index into nlist of cb head */
+ u_char pr_sindex; /* index into nlist of stat block */
+ u_char pr_wanted; /* 1 if wanted, 0 otherwise */
+ void (*pr_cblocks) /* control blocks printing routine */
+ __P((u_long, const char *));
+ void (*pr_stats) /* statistics printing routine */
+ __P((u_long, const char *));
+ void (*pr_istats)
+ __P((const char *)); /* per/if statistics printing routine */
+ void (*pr_dump) /* PCB state dump routine */
+ __P((u_long, const char *, u_long));
+ const char *pr_name; /* well-known name */
+} protox[] = {
+ { N_TCBTABLE, N_TCPSTAT, 1, protopr,
+ tcp_stats, NULL, tcp_dump, "tcp" },
+ { N_UDBTABLE, N_UDPSTAT, 1, protopr,
+ udp_stats, NULL, 0, "udp" },
+ { -1, N_IPSTAT, 1, 0,
+ ip_stats, NULL, 0, "ip" },
+ { -1, N_ICMPSTAT, 1, 0,
+ icmp_stats, NULL, 0, "icmp" },
+ { -1, N_IGMPSTAT, 1, 0,
+ igmp_stats, NULL, 0, "igmp" },
+ { -1, N_CARPSTAT, 1, 0,
+ carp_stats, NULL, 0, "carp" },
+#ifdef IPSEC
+ { -1, N_IPSECSTAT, 1, 0,
+ fast_ipsec_stats, NULL, 0, "ipsec" },
+#endif
+ { -1, N_PIMSTAT, 1, 0,
+ pim_stats, NULL, 0, "pim" },
+ { -1, N_PFSYNCSTAT, 1, 0,
+ pfsync_stats, NULL, 0, "pfsync" },
+ { -1, -1, 0, 0,
+ 0, NULL, 0, 0 }
+};
+
+#ifdef INET6
+struct protox ip6protox[] = {
+ { -1, N_IP6STAT, 1, 0,
+ ip6_stats, ip6_ifstats, 0, "ip6" },
+ { -1, N_ICMP6STAT, 1, 0,
+ icmp6_stats, icmp6_ifstats, 0, "icmp6" },
+#ifdef TCP6
+ { N_TCBTABLE, N_TCP6STAT, 1, ip6protopr,
+ tcp6_stats, NULL, tcp6_dump, "tcp6" },
+#else
+ { N_TCBTABLE, N_TCP6STAT, 1, ip6protopr,
+ tcp_stats, NULL, tcp6_dump, "tcp6" },
+#endif
+ { N_UDBTABLE, N_UDP6STAT, 1, ip6protopr,
+ udp6_stats, NULL, 0, "udp6" },
+#ifdef IPSEC
+ { -1, N_IPSEC6STAT, 1, 0,
+ fast_ipsec_stats, NULL, 0, "ipsec6" },
+#endif
+ { -1, N_PIM6STAT, 1, 0,
+ pim6_stats, NULL, 0, "pim6" },
+ { -1, N_RIP6STAT, 1, 0,
+ rip6_stats, NULL, 0, "rip6" },
+ { -1, -1, 0, 0,
+ 0, NULL, 0, 0 }
+};
+#endif
+
+struct protox arpprotox[] = {
+ { -1, N_ARPSTAT, 1, 0,
+ arp_stats, NULL, 0, "arp" },
+ { -1, -1, 0, 0,
+ 0, NULL, 0, 0 }
+};
+
+#ifdef IPSEC
+struct protox pfkeyprotox[] = {
+ { -1, N_PFKEYSTAT, 1, 0,
+ pfkey_stats, NULL, 0, "pfkey" },
+ { -1, -1, 0, 0,
+ 0, NULL, 0, 0 }
+};
+#endif
+
+#ifndef SMALL
+struct protox atalkprotox[] = {
+ { N_DDPCB, N_DDPSTAT, 1, atalkprotopr,
+ ddp_stats, NULL, 0, "ddp" },
+ { -1, -1, 0, 0,
+ 0, NULL, 0, NULL }
+};
+#endif
+
+struct protox *protoprotox[] = { protox,
+#ifdef INET6
+ ip6protox,
+#endif
+ arpprotox,
+#ifdef IPSEC
+ pfkeyprotox,
+#endif
+#ifndef SMALL
+ atalkprotox,
+#endif
+ NULL };
+
+const struct softintrq {
+ const char *siq_name;
+ int siq_index;
+} softintrq[] = {
+ { "arpintrq", N_ARPINTRQ },
+ { "ipintrq", N_IPINTRQ },
+ { "ip6intrq", N_IP6INTRQ },
+ { "atintrq1", N_ATINTRQ1 },
+ { "atintrq2", N_ATINTRQ2 },
+ { "llcintrq", N_LLCINTRQ },
+ { "hdintrq", N_HDINTRQ },
+ { "natmintrq", N_NATMINTRQ },
+ { "ppoediscinq", N_PPPOEDISCINQ },
+ { "ppoeinq", N_PPPOEINQ },
+ { "pkintrq", N_PKINTRQ },
+ { NULL, -1 },
+};
+
+int main __P((int, char *[]));
+static void printproto __P((struct protox *, const char *));
+static void print_softintrq __P((void));
+__dead static void usage(void);
+static struct protox *name2protox __P((const char *));
+static struct protox *knownname __P((const char *));
+static void prepare(const char *, const char *, struct protox *tp);
+static kvm_t *prepare_kvmd(const char *, const char *, char *);
+
+static kvm_t *kvmd = NULL;
+gid_t egid;
+int interval; /* repeat interval for i/f stats */
+static const char *nlistf = NULL, *memf = NULL;
+
+kvm_t *
+get_kvmd(void)
+{
+ char buf[_POSIX2_LINE_MAX];
+
+ if (kvmd != NULL)
+ return kvmd;
+ if ((kvmd = prepare_kvmd(nlistf, memf, buf)) == NULL)
+ errx(1, "kvm error: %s", buf);
+ return kvmd;
+}
+
+static kvm_t *
+prepare_kvmd(const char *nf, const char *mf, char *errbuf)
+{
+ kvm_t *k;
+
+ (void)setegid(egid);
+ k = kvm_openfiles(nf, mf, NULL, O_RDONLY, errbuf);
+ (void)setgid(getgid());
+ return k;
+}
+
+void
+prepare(const char *nf, const char *mf, struct protox *tp)
+{
+ char buf[_POSIX2_LINE_MAX];
+ /*
+ * Try to figure out if we can use sysctl or not.
+ */
+ if (nf != NULL || mf != NULL) {
+ /* Of course, we can't use sysctl with dumps. */
+ if (force_sysctl)
+ errx(EXIT_FAILURE, "can't use sysctl with dumps");
+
+ /*
+ * If we have -M or -N, we're not dealing with live memory
+ * or want to use kvm interface explicitly. It is sometimes
+ * useful to dig inside of kernel without extending
+ * sysctl interface (i.e., without rebuilding kernel).
+ */
+ use_sysctl = 0;
+ } else if (qflag ||
+ iflag ||
+#ifndef SMALL
+ gflag ||
+#endif
+ (pflag && tp->pr_sindex == N_PIMSTAT) ||
+ Pflag) {
+ /* These flags are not yet supported via sysctl(3). */
+ use_sysctl = 0;
+ } else {
+ /* We can use sysctl(3). */
+ use_sysctl = 1;
+ }
+
+ if (force_sysctl && !use_sysctl) {
+ /* Let the user know what's about to happen. */
+ warnx("forcing sysctl usage even though it might not be "\
+ "supported");
+ use_sysctl = 1;
+ }
+
+#ifdef __minix
+ use_sysctl = 1;
+#endif /* __minix */
+
+ kvmd = prepare_kvmd(nf, mf, buf);
+
+ if (!use_sysctl) {
+
+ if (kvmd == NULL)
+ errx(1, "kvm error: %s", buf);
+ if (kvm_nlist(kvmd, nl) < 0 || nl[0].n_type == 0) {
+ if (nf)
+ errx(1, "%s: no namelist", nf);
+ else
+ errx(1, "no namelist");
+ }
+ } else
+ (void)setgid(getgid());
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct protoent *p;
+ struct protox *tp; /* for printing cblocks & stats */
+ int ch;
+ char *cp;
+ char *afname, *afnames;
+ u_long pcbaddr;
+
+ if (prog_init) {
+ if (prog_init() == -1)
+ err(1, "init failed");
+ force_sysctl = 1; /* cheap trick */
+ }
+
+ egid = getegid();
+ (void)setegid(getgid());
+ tp = NULL;
+ af = AF_UNSPEC;
+ afnames = NULL;
+ pcbaddr = 0;
+
+ while ((ch = getopt(argc, argv,
+ "AabBdf:ghI:LliM:mN:nP:p:qrsStTuVvw:X")) != -1)
+ switch (ch) {
+ case 'A':
+ Aflag = RT_AFLAG;
+ break;
+ case 'a':
+ aflag = 1;
+ break;
+ case 'b':
+ bflag = 1;
+ break;
+ case 'B':
+ Bflag = 1;
+ break;
+ case 'd':
+ dflag = 1;
+ break;
+ case 'f':
+ afnames = optarg;
+ break;
+#ifndef SMALL
+ case 'g':
+ gflag = 1;
+ break;
+#endif
+ case 'h':
+ hflag = 1;
+ break;
+ case 'I':
+ iflag = 1;
+ interface = optarg;
+ break;
+ case 'i':
+ iflag = 1;
+ break;
+ case 'L':
+ Lflag = RT_LFLAG;
+ break;
+ case 'l':
+ lflag = 1;
+ break;
+ case 'M':
+ memf = optarg;
+ break;
+ case 'm':
+ mflag = 1;
+ break;
+ case 'N':
+ nlistf = optarg;
+ break;
+ case 'n':
+ numeric_addr = numeric_port = nflag = RT_NFLAG;
+ break;
+ case 'P':
+ errno = 0;
+ pcbaddr = strtoul(optarg, &cp, 16);
+ if (*cp != '\0' || errno == ERANGE)
+ errx(1, "invalid PCB address %s",
+ optarg);
+ Pflag = 1;
+ break;
+ case 'p':
+ if ((tp = name2protox(optarg)) == NULL)
+ errx(1, "%s: unknown or uninstrumented protocol",
+ optarg);
+ pflag = 1;
+ break;
+ case 'q':
+ qflag = 1;
+ break;
+ case 'r':
+ rflag = 1;
+ break;
+ case 's':
+ ++sflag;
+ break;
+ case 'S':
+ numeric_addr = 1;
+ break;
+ case 't':
+ tflag = 1;
+ break;
+ case 'T':
+ tagflag = RT_TFLAG;
+ break;
+ case 'u':
+ af = AF_LOCAL;
+ break;
+ case 'V':
+ Vflag++;
+ break;
+ case 'v':
+ vflag = RT_VFLAG;
+ break;
+ case 'w':
+ interval = atoi(optarg);
+ iflag = 1;
+ break;
+ case 'X':
+ force_sysctl = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argv += optind;
+ argc -= optind;
+
+#define BACKWARD_COMPATIBILITY
+#ifdef BACKWARD_COMPATIBILITY
+ if (*argv) {
+ if (isdigit((unsigned char)**argv)) {
+ interval = atoi(*argv);
+ if (interval <= 0)
+ usage();
+ ++argv;
+ iflag = 1;
+ }
+ if (*argv) {
+ nlistf = *argv;
+ if (*++argv)
+ memf = *argv;
+ }
+ }
+#endif
+
+ prepare(nlistf, memf, tp);
+
+#ifndef SMALL
+ if (Bflag) {
+ if (sflag)
+ bpf_stats();
+ else
+ bpf_dump(interface);
+ exit(0);
+ }
+#endif
+
+ if (mflag) {
+ mbpr(nl[N_MBSTAT].n_value, nl[N_MSIZE].n_value,
+ nl[N_MCLBYTES].n_value, nl[N_MBPOOL].n_value,
+ nl[N_MCLPOOL].n_value);
+ exit(0);
+ }
+ if (Pflag) {
+ if (tp == NULL) {
+ /* Default to TCP. */
+ tp = name2protox("tcp");
+ }
+ if (tp->pr_dump)
+ (*tp->pr_dump)(nl[tp->pr_index].n_value, tp->pr_name,
+ pcbaddr);
+ else
+ printf("%s: no PCB dump routine\n", tp->pr_name);
+ exit(0);
+ }
+ if (pflag) {
+ if (iflag && tp->pr_istats)
+ intpr(interval, nl[N_IFNET_LIST].n_value, tp->pr_istats);
+ else if (tp->pr_stats)
+ (*tp->pr_stats)(nl[tp->pr_sindex].n_value,
+ tp->pr_name);
+ else
+ printf("%s: no stats routine\n", tp->pr_name);
+ exit(0);
+ }
+ if (qflag) {
+ print_softintrq();
+ exit(0);
+ }
+ /*
+ * Keep file descriptors open to avoid overhead
+ * of open/close on each call to get* routines.
+ */
+ sethostent(1);
+ setnetent(1);
+ /*
+ * If -f was used afnames != NULL, loop over the address families.
+ * Otherwise do this at least once (with af == AF_UNSPEC).
+ */
+ afname = NULL;
+ do {
+ if (afnames != NULL) {
+ afname = strsep(&afnames, ",");
+ if (afname == NULL)
+ break; /* Exit early */
+ if (strcmp(afname, "inet") == 0)
+ af = AF_INET;
+ else if (strcmp(afname, "inet6") == 0)
+ af = AF_INET6;
+ else if (strcmp(afname, "arp") == 0)
+ af = AF_ARP;
+ else if (strcmp(afname, "pfkey") == 0)
+ af = PF_KEY;
+ else if (strcmp(afname, "unix") == 0
+ || strcmp(afname, "local") == 0)
+ af = AF_LOCAL;
+ else if (strcmp(afname, "atalk") == 0)
+ af = AF_APPLETALK;
+ else if (strcmp(afname, "mpls") == 0)
+ af = AF_MPLS;
+ else {
+ warnx("%s: unknown address family",
+ afname);
+ continue;
+ }
+ }
+
+ if (iflag) {
+ if (af != AF_UNSPEC)
+ goto protostat;
+
+ intpr(interval, nl[N_IFNET_LIST].n_value, NULL);
+ break;
+ }
+ if (rflag) {
+ if (sflag)
+ rt_stats(use_sysctl ? 0 : nl[N_RTSTAT].n_value);
+ else {
+ if (use_sysctl)
+ p_rttables(af,
+ nflag|tagflag|vflag|Lflag, 0, ~0);
+ else
+ routepr(nl[N_RTREE].n_value);
+ }
+ break;
+ }
+#ifndef SMALL
+ if (gflag) {
+ if (sflag) {
+ if (af == AF_INET || af == AF_UNSPEC)
+ mrt_stats(nl[N_MRTPROTO].n_value,
+ nl[N_MRTSTAT].n_value);
+#ifdef INET6
+ if (af == AF_INET6 || af == AF_UNSPEC)
+ mrt6_stats(nl[N_MRT6PROTO].n_value,
+ nl[N_MRT6STAT].n_value);
+#endif
+ }
+ else {
+ if (af == AF_INET || af == AF_UNSPEC)
+ mroutepr(nl[N_MRTPROTO].n_value,
+ nl[N_MFCHASHTBL].n_value,
+ nl[N_MFCHASH].n_value,
+ nl[N_VIFTABLE].n_value);
+#ifdef INET6
+ if (af == AF_INET6 || af == AF_UNSPEC)
+ mroute6pr(nl[N_MRT6PROTO].n_value,
+ nl[N_MF6CTABLE].n_value,
+ nl[N_MIF6TABLE].n_value);
+#endif
+ }
+ break;
+ }
+#endif
+ protostat:
+ if (af == AF_INET || af == AF_UNSPEC) {
+ setprotoent(1);
+ setservent(1);
+ /* ugh, this is O(MN) ... why do we do this? */
+ while ((p = getprotoent()) != NULL) {
+ for (tp = protox; tp->pr_name; tp++)
+ if (strcmp(tp->pr_name, p->p_name) == 0)
+ break;
+ if (tp->pr_name == 0 || tp->pr_wanted == 0)
+ continue;
+ printproto(tp, p->p_name);
+ tp->pr_wanted = 0;
+ }
+ endprotoent();
+ for (tp = protox; tp->pr_name; tp++)
+ if (tp->pr_wanted)
+ printproto(tp, tp->pr_name);
+ }
+#ifdef INET6
+ if (af == AF_INET6 || af == AF_UNSPEC)
+ for (tp = ip6protox; tp->pr_name; tp++)
+ printproto(tp, tp->pr_name);
+#endif
+ if (af == AF_ARP || af == AF_UNSPEC)
+ for (tp = arpprotox; tp->pr_name; tp++)
+ printproto(tp, tp->pr_name);
+#ifdef IPSEC
+ if (af == PF_KEY || af == AF_UNSPEC)
+ for (tp = pfkeyprotox; tp->pr_name; tp++)
+ printproto(tp, tp->pr_name);
+#endif
+#ifndef SMALL
+ if (af == AF_APPLETALK || af == AF_UNSPEC)
+ for (tp = atalkprotox; tp->pr_name; tp++)
+ printproto(tp, tp->pr_name);
+ if ((af == AF_LOCAL || af == AF_UNSPEC) && !sflag)
+ unixpr(nl[N_UNIXSW].n_value);
+#endif
+ } while (afnames != NULL && afname != NULL);
+ exit(0);
+}
+
+/*
+ * Print out protocol statistics or control blocks (per sflag).
+ * If the interface was not specifically requested, and the symbol
+ * is not in the namelist, ignore this one.
+ */
+static void
+printproto(struct protox *tp, const char *name)
+{
+ void (*pr) __P((u_long, const char *));
+ u_long off;
+
+ if (sflag) {
+ if (iflag) {
+ if (tp->pr_istats)
+ intpr(interval, nl[N_IFNET_LIST].n_value,
+ tp->pr_istats);
+ return;
+ }
+ else {
+ pr = tp->pr_stats;
+ off = nl[tp->pr_sindex].n_value;
+ }
+ } else {
+ pr = tp->pr_cblocks;
+ off = nl[tp->pr_index].n_value;
+ }
+ if (pr != NULL && ((off || af != AF_UNSPEC) || use_sysctl)) {
+ (*pr)(off, name);
+ }
+}
+
+/*
+ * Print softintrq status.
+ */
+void
+print_softintrq(void)
+{
+ struct ifqueue intrq, *ifq = &intrq;
+ const struct softintrq *siq;
+ u_long off;
+
+ for (siq = softintrq; siq->siq_name != NULL; siq++) {
+ off = nl[siq->siq_index].n_value;
+ if (off == 0)
+ continue;
+
+ kread(off, (char *)ifq, sizeof(*ifq));
+ printf("%s:\n", siq->siq_name);
+ printf("\tqueue length: %d\n", ifq->ifq_len);
+ printf("\tmaximum queue length: %d\n", ifq->ifq_maxlen);
+ printf("\tpackets dropped: %d\n", ifq->ifq_drops);
+ }
+}
+
+/*
+ * Read kernel memory, return 0 on success.
+ */
+int
+kread(u_long addr, char *buf, int size)
+{
+
+ if (kvm_read(kvmd, addr, buf, size) != size) {
+ warnx("%s", kvm_geterr(kvmd));
+ return (-1);
+ }
+ return (0);
+}
+
+const char *
+plural(int n)
+{
+
+ return (n != 1 ? "s" : "");
+}
+
+const char *
+plurales(int n)
+{
+
+ return (n != 1 ? "es" : "");
+}
+
+int
+get_hardticks(void)
+{
+ int hardticks;
+
+ kread(nl[N_HARDCLOCK_TICKS].n_value, (char *)&hardticks,
+ sizeof(hardticks));
+ return (hardticks);
+}
+
+/*
+ * Find the protox for the given "well-known" name.
+ */
+static struct protox *
+knownname(const char *name)
+{
+ struct protox **tpp, *tp;
+
+ for (tpp = protoprotox; *tpp; tpp++)
+ for (tp = *tpp; tp->pr_name; tp++)
+ if (strcmp(tp->pr_name, name) == 0)
+ return (tp);
+ return (NULL);
+}
+
+/*
+ * Find the protox corresponding to name.
+ */
+static struct protox *
+name2protox(const char *name)
+{
+ struct protox *tp;
+ char **alias; /* alias from p->aliases */
+ struct protoent *p;
+
+ /*
+ * Try to find the name in the list of "well-known" names. If that
+ * fails, check if name is an alias for an Internet protocol.
+ */
+ if ((tp = knownname(name)) != NULL)
+ return (tp);
+
+ setprotoent(1); /* make protocol lookup cheaper */
+ while ((p = getprotoent()) != NULL) {
+ /* assert: name not same as p->name */
+ for (alias = p->p_aliases; *alias; alias++)
+ if (strcmp(name, *alias) == 0) {
+ endprotoent();
+ return (knownname(p->p_name));
+ }
+ }
+ endprotoent();
+ return (NULL);
+}
+
+static void
+usage(void)
+{
+ const char *progname = getprogname();
+
+ (void)fprintf(stderr,
+"usage: %s [-Aan] [-f address_family[,family ...]] [-M core] [-N system]\n", progname);
+ (void)fprintf(stderr,
+" %s [-bdgiLmnqrsSv] [-f address_family[,family ...]] [-M core] [-N system]\n",
+ progname);
+ (void)fprintf(stderr,
+" %s [-dn] [-I interface] [-M core] [-N system] [-w wait]\n", progname);
+ (void)fprintf(stderr,
+" %s [-p protocol] [-M core] [-N system]\n", progname);
+ (void)fprintf(stderr,
+" %s [-p protocol] [-M core] [-N system] -P pcbaddr\n", progname);
+ (void)fprintf(stderr,
+" %s [-p protocol] [-i] [-I Interface] \n", progname);
+ (void)fprintf(stderr,
+" %s [-s] [-f address_family[,family ...]] [-i] [-I Interface]\n", progname);
+ (void)fprintf(stderr,
+" %s [-s] [-B] [-I interface]\n", progname);
+ exit(1);
+}
--- /dev/null
+/* $NetBSD: mbuf.c,v 1.33 2015/07/28 19:46:42 christos Exp $ */
+
+/*
+ * Copyright (c) 1983, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "from: @(#)mbuf.c 8.1 (Berkeley) 6/6/93";
+#else
+__RCSID("$NetBSD: mbuf.c,v 1.33 2015/07/28 19:46:42 christos Exp $");
+#endif
+#endif /* not lint */
+
+#define __POOL_EXPOSE
+
+#include <sys/param.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/mbuf.h>
+#include <sys/pool.h>
+#include <sys/sysctl.h>
+
+#include <stdio.h>
+#include <kvm.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <errno.h>
+#include <err.h>
+#include "netstat.h"
+#include "prog_ops.h"
+
+#define YES 1
+
+struct mbstat mbstat;
+struct pool mbpool, mclpool;
+struct pool_allocator mbpa, mclpa;
+
+static struct mbtypes {
+ int mt_type;
+ const char *mt_name;
+} mbtypes[] = {
+ { MT_DATA, "data" },
+ { MT_OOBDATA, "oob data" },
+ { MT_CONTROL, "ancillary data" },
+ { MT_HEADER, "packet headers" },
+ { MT_FTABLE, "fragment reassembly queue headers" }, /* XXX */
+ { MT_SONAME, "socket names and addresses" },
+ { MT_SOOPTS, "socket options" },
+ { 0, 0 }
+};
+
+const int nmbtypes = sizeof(mbstat.m_mtypes) / sizeof(short);
+bool seen[256]; /* "have we seen this type yet?" */
+
+int mbstats_ctl[] = { CTL_KERN, KERN_MBUF, MBUF_STATS };
+int mowners_ctl[] = { CTL_KERN, KERN_MBUF, MBUF_MOWNERS };
+
+/*
+ * Print mbuf statistics.
+ */
+void
+mbpr(u_long mbaddr, u_long msizeaddr, u_long mclbaddr, u_long mbpooladdr,
+ u_long mclpooladdr)
+{
+ u_long totmem, totused, totpct;
+ u_int totmbufs;
+ int i, lines;
+ struct mbtypes *mp;
+ size_t len;
+ void *data;
+ struct mowner_user *mo;
+ int mclbytes, msize;
+
+ if (nmbtypes != 256) {
+ fprintf(stderr,
+ "%s: unexpected change to mbstat; check source\n",
+ getprogname());
+ return;
+ }
+
+ if (use_sysctl) {
+ size_t mbstatlen = sizeof(mbstat);
+ if (prog_sysctl(mbstats_ctl,
+ sizeof(mbstats_ctl) / sizeof(mbstats_ctl[0]),
+ &mbstat, &mbstatlen, NULL, 0) < 0) {
+ warn("mbstat: sysctl failed");
+ return;
+ }
+ goto printit;
+ }
+
+ if (mbaddr == 0) {
+ fprintf(stderr, "%s: mbstat: symbol not in namelist\n",
+ getprogname());
+ return;
+ }
+/*XXX*/
+ if (msizeaddr != 0)
+ kread(msizeaddr, (char *)&msize, sizeof (msize));
+ else
+ msize = MSIZE;
+ if (mclbaddr != 0)
+ kread(mclbaddr, (char *)&mclbytes, sizeof (mclbytes));
+ else
+ mclbytes = MCLBYTES;
+/*XXX*/
+
+ if (kread(mbaddr, (char *)&mbstat, sizeof (mbstat)))
+ return;
+
+ if (kread(mbpooladdr, (char *)&mbpool, sizeof (mbpool)))
+ return;
+
+ if (kread(mclpooladdr, (char *)&mclpool, sizeof (mclpool)))
+ return;
+
+ mbpooladdr = (u_long) mbpool.pr_alloc;
+ mclpooladdr = (u_long) mclpool.pr_alloc;
+
+ if (kread(mbpooladdr, (char *)&mbpa, sizeof (mbpa)))
+ return;
+
+ if (kread(mclpooladdr, (char *)&mclpa, sizeof (mclpa)))
+ return;
+
+ printit:
+ totmbufs = 0;
+ for (mp = mbtypes; mp->mt_name; mp++)
+ totmbufs += mbstat.m_mtypes[mp->mt_type];
+ printf("%u mbufs in use:\n", totmbufs);
+ for (mp = mbtypes; mp->mt_name; mp++)
+ if (mbstat.m_mtypes[mp->mt_type]) {
+ seen[mp->mt_type] = YES;
+ printf("\t%u mbufs allocated to %s\n",
+ mbstat.m_mtypes[mp->mt_type], mp->mt_name);
+ }
+ seen[MT_FREE] = YES;
+ for (i = 0; i < nmbtypes; i++)
+ if (!seen[i] && mbstat.m_mtypes[i]) {
+ printf("\t%u mbufs allocated to <mbuf type %d>\n",
+ mbstat.m_mtypes[i], i);
+ }
+
+ if (use_sysctl) /* XXX */
+ goto dump_drain;
+
+ printf("%lu/%lu mapped pages in use\n",
+ (u_long)(mclpool.pr_nget - mclpool.pr_nput),
+ ((u_long)mclpool.pr_npages * mclpool.pr_itemsperpage));
+ totmem = (mbpool.pr_npages << mbpa.pa_pageshift) +
+ (mclpool.pr_npages << mclpa.pa_pageshift);
+ totused = (mbpool.pr_nget - mbpool.pr_nput) * mbpool.pr_size +
+ (mclpool.pr_nget - mclpool.pr_nput) * mclpool.pr_size;
+ if (totmem == 0)
+ totpct = 0;
+ else if (totused < (ULONG_MAX/100))
+ totpct = (totused * 100)/totmem;
+ else {
+ u_long totmem1 = totmem/100;
+ u_long totused1 = totused/100;
+ totpct = (totused1 * 100)/totmem1;
+ }
+
+ printf("%lu Kbytes allocated to network (%lu%% in use)\n",
+ totmem / 1024, totpct);
+
+dump_drain:
+ printf("%lu calls to protocol drain routines\n", mbstat.m_drain);
+
+ if (sflag < 2)
+ return;
+
+ if (!use_sysctl)
+ return;
+
+ if (prog_sysctl(mowners_ctl,
+ sizeof(mowners_ctl)/sizeof(mowners_ctl[0]),
+ NULL, &len, NULL, 0) < 0) {
+ if (errno == ENOENT)
+ return;
+ warn("mowners: sysctl test");
+ return;
+ }
+ len += 10 * sizeof(*mo); /* add some slop */
+ data = malloc(len);
+ if (data == NULL) {
+ warn("malloc(%lu)", (u_long)len);
+ return;
+ }
+
+ if (prog_sysctl(mowners_ctl,
+ sizeof(mowners_ctl)/sizeof(mowners_ctl[0]),
+ data, &len, NULL, 0) < 0) {
+ warn("mowners: sysctl get");
+ free(data);
+ return;
+ }
+
+ for (mo = (void *) data, lines = 0; len >= sizeof(*mo);
+ len -= sizeof(*mo), mo++) {
+ char buf[32];
+ if (vflag == 1 &&
+ mo->mo_counter[MOWNER_COUNTER_CLAIMS] == 0 &&
+ mo->mo_counter[MOWNER_COUNTER_EXT_CLAIMS] == 0 &&
+ mo->mo_counter[MOWNER_COUNTER_CLUSTER_CLAIMS] == 0)
+ continue;
+ if (vflag == 0 &&
+ mo->mo_counter[MOWNER_COUNTER_CLAIMS] ==
+ mo->mo_counter[MOWNER_COUNTER_RELEASES] &&
+ mo->mo_counter[MOWNER_COUNTER_EXT_CLAIMS] ==
+ mo->mo_counter[MOWNER_COUNTER_EXT_RELEASES] &&
+ mo->mo_counter[MOWNER_COUNTER_CLUSTER_CLAIMS] ==
+ mo->mo_counter[MOWNER_COUNTER_CLUSTER_RELEASES])
+ continue;
+ snprintf(buf, sizeof(buf), "%16s %-13s",
+ mo->mo_name, mo->mo_descr);
+ if ((lines % 24) == 0 || lines > 24) {
+ printf("%30s %-8s %10s %10s %10s\n",
+ "", "", "small", "ext", "cluster");
+ lines = 1;
+ }
+ printf("%30s %-8s %10lu %10lu %10lu\n",
+ buf, "inuse",
+ mo->mo_counter[MOWNER_COUNTER_CLAIMS] -
+ mo->mo_counter[MOWNER_COUNTER_RELEASES],
+ mo->mo_counter[MOWNER_COUNTER_EXT_CLAIMS] -
+ mo->mo_counter[MOWNER_COUNTER_EXT_RELEASES],
+ mo->mo_counter[MOWNER_COUNTER_CLUSTER_CLAIMS] -
+ mo->mo_counter[MOWNER_COUNTER_CLUSTER_RELEASES]);
+ lines++;
+ if (vflag) {
+ printf("%30s %-8s %10lu %10lu %10lu\n",
+ "", "claims",
+ mo->mo_counter[MOWNER_COUNTER_CLAIMS],
+ mo->mo_counter[MOWNER_COUNTER_EXT_CLAIMS],
+ mo->mo_counter[MOWNER_COUNTER_CLUSTER_CLAIMS]);
+ printf("%30s %-8s %10lu %10lu %10lu\n",
+ "", "releases",
+ mo->mo_counter[MOWNER_COUNTER_RELEASES],
+ mo->mo_counter[MOWNER_COUNTER_EXT_RELEASES],
+ mo->mo_counter[MOWNER_COUNTER_CLUSTER_RELEASES]);
+ lines += 2;
+ }
+ }
+ free(data);
+}
--- /dev/null
+/* $NetBSD: mroute.c,v 1.25 2014/11/06 21:30:09 christos Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Stephen Deering of Stanford University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)mroute.c 8.1 (Berkeley) 6/6/93
+ */
+
+/*
+ * Copyright (c) 1989 Stephen Deering
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Stephen Deering of Stanford University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)mroute.c 8.1 (Berkeley) 6/6/93
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "from: @(#)mroute.c 8.1 (Berkeley) 6/6/93";
+#else
+__RCSID("$NetBSD: mroute.c,v 1.25 2014/11/06 21:30:09 christos Exp $");
+#endif
+#endif /* not lint */
+
+/*
+ * Print multicast routing structures and statistics.
+ *
+ * MROUTING 1.0
+ */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/protosw.h>
+
+#include <net/if.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/igmp.h>
+#define _KERNEL
+#include <netinet/ip_mroute.h>
+#undef _KERNEL
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <kvm.h>
+#include "netstat.h"
+#include "rtutil.h"
+
+static char *pktscale(u_long);
+static void print_bw_meter(struct bw_meter *, int *);
+
+static char *
+pktscale(u_long n)
+{
+ static char buf[20];
+ char t;
+
+ if (n < 1024)
+ t = ' ';
+ else if (n < 1024 * 1024) {
+ t = 'k';
+ n /= 1024;
+ } else {
+ t = 'm';
+ n /= 1048576;
+ }
+
+ (void)snprintf(buf, sizeof buf, "%lu%c", n, t);
+ return (buf);
+}
+
+void
+mroutepr(u_long mrpaddr, u_long mfchashtbladdr, u_long mfchashaddr,
+ u_long vifaddr)
+{
+ u_int mrtproto;
+ LIST_HEAD(, mfc) *mfchashtbl;
+ u_long mfchash, i;
+ struct vif viftable[MAXVIFS];
+ struct mfc *mfcp, mfc;
+ struct vif *v;
+ vifi_t vifi;
+ int banner_printed;
+ int saved_numeric_addr;
+ int numvifs;
+ int nmfc; /* No. of cache entries */
+
+ if (mrpaddr == 0) {
+ printf("ip_mrtproto: symbol not in namelist\n");
+ return;
+ }
+
+ kread(mrpaddr, (char *)&mrtproto, sizeof(mrtproto));
+ switch (mrtproto) {
+ case 0:
+ printf("no multicast routing compiled into this system\n");
+ return;
+
+ case IGMP_DVMRP:
+ break;
+
+ default:
+ printf("multicast routing protocol %u, unknown\n", mrtproto);
+ return;
+ }
+
+ if (mfchashtbladdr == 0) {
+ printf("mfchashtbl: symbol not in namelist\n");
+ return;
+ }
+ if (mfchashaddr == 0) {
+ printf("mfchash: symbol not in namelist\n");
+ return;
+ }
+ if (vifaddr == 0) {
+ printf("viftable: symbol not in namelist\n");
+ return;
+ }
+
+ saved_numeric_addr = numeric_addr;
+ numeric_addr = 1;
+
+ kread(vifaddr, (char *)&viftable, sizeof(viftable));
+ banner_printed = 0;
+ numvifs = 0;
+
+ for (vifi = 0, v = viftable; vifi < MAXVIFS; ++vifi, ++v) {
+ if (v->v_lcl_addr.s_addr == 0)
+ continue;
+ numvifs = vifi;
+
+ if (!banner_printed) {
+ printf("\nVirtual Interface Table\n %s%s",
+ "Vif Thresh Limit Local-Address ",
+ "Remote-Address Pkt_in Pkt_out\n");
+ banner_printed = 1;
+ }
+
+ printf(" %3u %3u %5u %-15.15s",
+ vifi, v->v_threshold, v->v_rate_limit,
+ routename4(v->v_lcl_addr.s_addr, nflag));
+ printf(" %-15.15s %6lu %7lu\n", (v->v_flags & VIFF_TUNNEL) ?
+ routename4(v->v_rmt_addr.s_addr, nflag) : "",
+ v->v_pkt_in, v->v_pkt_out);
+ }
+ if (!banner_printed)
+ printf("\nVirtual Interface Table is empty\n");
+
+ kread(mfchashtbladdr, (char *)&mfchashtbl, sizeof(mfchashtbl));
+ kread(mfchashaddr, (char *)&mfchash, sizeof(mfchash));
+ banner_printed = 0;
+ nmfc = 0;
+
+ if (mfchashtbl != 0)
+ for (i = 0; i <= mfchash; ++i) {
+ kread((u_long)&mfchashtbl[i], (char *)&mfcp, sizeof(mfcp));
+
+ for (; mfcp != 0; mfcp = mfc.mfc_hash.le_next) {
+ if (!banner_printed) {
+ printf("\nMulticast Forwarding Cache\n %s%s",
+ "Hash Origin Mcastgroup ",
+ "Traffic In-Vif Out-Vifs/Forw-ttl\n");
+ banner_printed = 1;
+ }
+
+ kread((u_long)mfcp, (char *)&mfc, sizeof(mfc));
+ printf(" %3lu %-15.15s",
+ i, routename4(mfc.mfc_origin.s_addr, nflag));
+ printf(" %-15.15s %7s %3u ",
+ routename4(mfc.mfc_mcastgrp.s_addr, nflag),
+ pktscale(mfc.mfc_pkt_cnt), mfc.mfc_parent);
+ for (vifi = 0; vifi <= numvifs; ++vifi)
+ if (mfc.mfc_ttls[vifi])
+ printf(" %u/%u", vifi, mfc.mfc_ttls[vifi]);
+
+ printf("\n");
+
+ /* Print the bw meter information */
+ {
+ struct bw_meter bw_meter, *bwm;
+ int banner_printed2 = 0;
+
+ bwm = mfc.mfc_bw_meter;
+ while (bwm) {
+ kread((u_long)bwm,
+ (char *)&bw_meter,
+ sizeof bw_meter);
+ print_bw_meter(&bw_meter,
+ &banner_printed2);
+ bwm = bw_meter.bm_mfc_next;
+ }
+#if 0 /* Don't ever print it? */
+ if (! banner_printed2)
+ printf("\n No Bandwidth Meters\n");
+#endif
+ }
+
+ nmfc++;
+ }
+ }
+ if (!banner_printed)
+ printf("\nMulticast Forwarding Cache is empty\n");
+ else
+ printf("\nTotal no. of entries in cache: %d\n", nmfc);
+
+ printf("\n");
+ numeric_addr = saved_numeric_addr;
+}
+
+static void
+print_bw_meter(struct bw_meter *bw_meter, int *banner_printed)
+{
+ char s0[256], s1[256], s2[256], s3[256];
+ struct timeval now, end, delta;
+
+ gettimeofday(&now, NULL);
+
+ if (! *banner_printed) {
+ printf(" Bandwidth Meters\n");
+ printf(" %-30s", "Measured(Start|Packets|Bytes)");
+ printf(" %s", "Type");
+ printf(" %-30s", "Thresh(Interval|Packets|Bytes)");
+ printf(" Remain");
+ printf("\n");
+ *banner_printed = 1;
+ }
+
+ /* The measured values */
+ if (bw_meter->bm_flags & BW_METER_UNIT_PACKETS)
+ sprintf(s1, "%llu", (unsigned long long)bw_meter->bm_measured.b_packets);
+ else
+ sprintf(s1, "?");
+ if (bw_meter->bm_flags & BW_METER_UNIT_BYTES)
+ sprintf(s2, "%llu", (unsigned long long)bw_meter->bm_measured.b_bytes);
+ else
+ sprintf(s2, "?");
+ sprintf(s0, "%lld.%ld|%s|%s",
+ (long long)bw_meter->bm_start_time.tv_sec,
+ (long)bw_meter->bm_start_time.tv_usec,
+ s1, s2);
+ printf(" %-30s", s0);
+
+ /* The type of entry */
+ sprintf(s0, "%s", "?");
+ if (bw_meter->bm_flags & BW_METER_GEQ)
+ sprintf(s0, "%s", ">=");
+ else if (bw_meter->bm_flags & BW_METER_LEQ)
+ sprintf(s0, "%s", "<=");
+ printf(" %-3s", s0);
+
+ /* The threshold values */
+ if (bw_meter->bm_flags & BW_METER_UNIT_PACKETS)
+ sprintf(s1, "%llu", (unsigned long long)bw_meter->bm_threshold.b_packets);
+ else
+ sprintf(s1, "?");
+ if (bw_meter->bm_flags & BW_METER_UNIT_BYTES)
+ sprintf(s2, "%llu", (unsigned long long)bw_meter->bm_threshold.b_bytes);
+ else
+ sprintf(s2, "?");
+ sprintf(s0, "%lld.%ld|%s|%s",
+ (long long)bw_meter->bm_threshold.b_time.tv_sec,
+ (long)bw_meter->bm_threshold.b_time.tv_usec,
+ s1, s2);
+ printf(" %-30s", s0);
+
+ /* Remaining time */
+ timeradd(&bw_meter->bm_start_time,
+ &bw_meter->bm_threshold.b_time, &end);
+ if (timercmp(&now, &end, <=)) {
+ timersub(&end, &now, &delta);
+ sprintf(s3, "%lld.%ld",
+ (long long)delta.tv_sec, (long)delta.tv_usec);
+ } else {
+ /* Negative time */
+ timersub(&now, &end, &delta);
+ sprintf(s3, "-%lld.%ld",
+ (long long)delta.tv_sec, (long)delta.tv_usec);
+ }
+ printf(" %s", s3);
+
+ printf("\n");
+}
+
+void
+mrt_stats(u_long mrpaddr, u_long mstaddr)
+{
+ u_int mrtproto;
+ struct mrtstat mrtstat;
+
+ if (mrpaddr == 0) {
+ printf("ip_mrtproto: symbol not in namelist\n");
+ return;
+ }
+
+ kread(mrpaddr, (char *)&mrtproto, sizeof(mrtproto));
+ switch (mrtproto) {
+ case 0:
+ printf("no multicast routing compiled into this system\n");
+ return;
+
+ case IGMP_DVMRP:
+ break;
+
+ default:
+ printf("multicast routing protocol %u, unknown\n", mrtproto);
+ return;
+ }
+
+ if (mstaddr == 0) {
+ printf("mrtstat: symbol not in namelist\n");
+ return;
+ }
+
+ kread(mstaddr, (char *)&mrtstat, sizeof(mrtstat));
+ printf("multicast routing:\n");
+ printf("\t%lu datagram%s with no route for origin\n",
+ mrtstat.mrts_no_route, plural(mrtstat.mrts_no_route));
+ printf("\t%lu upcall%s made to mrouted\n",
+ mrtstat.mrts_upcalls, plural(mrtstat.mrts_upcalls));
+ printf("\t%lu datagram%s with malformed tunnel options\n",
+ mrtstat.mrts_bad_tunnel, plural(mrtstat.mrts_bad_tunnel));
+ printf("\t%lu datagram%s with no room for tunnel options\n",
+ mrtstat.mrts_cant_tunnel, plural(mrtstat.mrts_cant_tunnel));
+ printf("\t%lu datagram%s arrived on wrong interface\n",
+ mrtstat.mrts_wrong_if, plural(mrtstat.mrts_wrong_if));
+ printf("\t%lu datagram%s dropped due to upcall Q overflow\n",
+ mrtstat.mrts_upq_ovflw, plural(mrtstat.mrts_upq_ovflw));
+ printf("\t%lu datagram%s dropped due to upcall socket overflow\n",
+ mrtstat.mrts_upq_sockfull, plural(mrtstat.mrts_upq_sockfull));
+ printf("\t%lu datagram%s cleaned up by the cache\n",
+ mrtstat.mrts_cache_cleanups, plural(mrtstat.mrts_cache_cleanups));
+ printf("\t%lu datagram%s dropped selectively by ratelimiter\n",
+ mrtstat.mrts_drop_sel, plural(mrtstat.mrts_drop_sel));
+ printf("\t%lu datagram%s dropped - bucket Q overflow\n",
+ mrtstat.mrts_q_overflow, plural(mrtstat.mrts_q_overflow));
+ printf("\t%lu datagram%s dropped - larger than bkt size\n",
+ mrtstat.mrts_pkt2large, plural(mrtstat.mrts_pkt2large));
+}
--- /dev/null
+/* $NetBSD: mroute6.c,v 1.15 2014/11/06 21:30:09 christos Exp $ */
+
+/*
+ * Copyright (C) 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Stephen Deering of Stanford University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)mroute.c 8.2 (Berkeley) 4/28/95
+ */
+
+/*
+ * Copyright (c) 1989 Stephen Deering
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Stephen Deering of Stanford University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)mroute.c 8.2 (Berkeley) 4/28/95
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/protosw.h>
+
+#include <net/if.h>
+
+#include <netinet/in.h>
+
+#define _KERNEL 1
+#include <netinet6/ip6_mroute.h>
+#undef _KERNEL
+
+#include <stdio.h>
+#include <kvm.h>
+#include "netstat.h"
+#include "rtutil.h"
+
+#ifdef INET6
+
+#define WID_ORG (lflag ? 39 : (numeric_addr ? 29 : 18)) /* width of origin column */
+#define WID_GRP (lflag ? 18 : (numeric_addr ? 16 : 18)) /* width of group column */
+
+void
+mroute6pr(u_long mrpaddr, u_long mfcaddr, u_long mifaddr)
+{
+ u_int mrtproto;
+ struct mf6c *mf6ctable[MF6CTBLSIZ], *mfcp;
+ struct mif6 mif6table[MAXMIFS];
+ struct mf6c mfc;
+ struct rtdetq rte, *rtep;
+ register struct mif6 *mifp;
+ register mifi_t mifi;
+ register int i;
+ register int banner_printed;
+ register int saved_numeric_addr;
+ int waitings;
+
+ if (mrpaddr == 0) {
+ printf("mroute6pr: symbol not in namelist\n");
+ return;
+ }
+
+ kread(mrpaddr, (char *)&mrtproto, sizeof(mrtproto));
+ switch (mrtproto) {
+ case 0:
+ printf("no IPv6 multicast routing compiled into this system\n");
+ return;
+
+ case IPPROTO_PIM:
+ break;
+
+ default:
+ printf("IPv6 multicast routing protocol %u, unknown\n",
+ mrtproto);
+ return;
+ }
+
+ if (mfcaddr == 0) {
+ printf("mf6ctable: symbol not in namelist\n");
+ return;
+ }
+ if (mifaddr == 0) {
+ printf("miftable: symbol not in namelist\n");
+ return;
+ }
+
+ saved_numeric_addr = numeric_addr;
+ numeric_addr = 1;
+
+ kread(mifaddr, (char *)&mif6table, sizeof(mif6table));
+ banner_printed = 0;
+ for (mifi = 0, mifp = mif6table; mifi < MAXMIFS; ++mifi, ++mifp) {
+ struct ifnet ifnet;
+ char ifname[IFNAMSIZ];
+
+ if (mifp->m6_ifp == NULL)
+ continue;
+
+ kread((u_long)mifp->m6_ifp, (char *)&ifnet, sizeof(ifnet));
+ if (!banner_printed) {
+ printf("\nIPv6 Multicast Interface Table\n"
+ " Mif Rate PhyIF Pkts-In Pkts-Out\n");
+ banner_printed = 1;
+ }
+
+ printf(" %2u %4d", mifi, mifp->m6_rate_limit);
+ printf(" %5s", (mifp->m6_flags & MIFF_REGISTER) ?
+ "reg0" : if_indextoname(ifnet.if_index, ifname));
+
+ printf(" %9llu %9llu\n", (unsigned long long)mifp->m6_pkt_in,
+ (unsigned long long)mifp->m6_pkt_out);
+ }
+ if (!banner_printed)
+ printf("\nIPv6 Multicast Interface Table is empty\n");
+
+ kread(mfcaddr, (char *)&mf6ctable, sizeof(mf6ctable));
+ banner_printed = 0;
+ for (i = 0; i < MF6CTBLSIZ; ++i) {
+ mfcp = mf6ctable[i];
+ while(mfcp) {
+ kread((u_long)mfcp, (char *)&mfc, sizeof(mfc));
+ if (!banner_printed) {
+ printf ("\nIPv6 Multicast Forwarding Cache\n");
+ printf(" %-*.*s %-*.*s %s",
+ WID_ORG, WID_ORG, "Origin",
+ WID_GRP, WID_GRP, "Group",
+ " Packets Waits In-Mif Out-Mifs\n");
+ banner_printed = 1;
+ }
+
+ printf(" %-*.*s", WID_ORG, WID_ORG,
+ routename6(&mfc.mf6c_origin, nflag));
+ printf(" %-*.*s", WID_GRP, WID_GRP,
+ routename6(&mfc.mf6c_mcastgrp, nflag));
+ printf(" %9llu", (unsigned long long)mfc.mf6c_pkt_cnt);
+
+ for (waitings = 0, rtep = mfc.mf6c_stall; rtep; ) {
+ waitings++;
+ kread((u_long)rtep, (char *)&rte, sizeof(rte));
+ rtep = rte.next;
+ }
+ printf(" %3d", waitings);
+
+ if (mfc.mf6c_parent == MF6C_INCOMPLETE_PARENT)
+ printf(" --- ");
+ else
+ printf(" %3d ", mfc.mf6c_parent);
+ for (mifi = 0; mifi <= MAXMIFS; mifi++) {
+ if (IF_ISSET(mifi, &mfc.mf6c_ifset))
+ printf(" %u", mifi);
+ }
+ printf("\n");
+
+ mfcp = mfc.mf6c_next;
+ }
+ }
+ if (!banner_printed)
+ printf("\nIPv6 Multicast Routing Table is empty\n");
+
+ printf("\n");
+ numeric_addr = saved_numeric_addr;
+}
+
+void
+mrt6_stats(u_long mrpaddr, u_long mstaddr)
+{
+#define p(f, m) printf(m, (unsigned long long)mrtstat.f, plural(mrtstat.f))
+#define pes(f, m) printf(m, (unsigned long long)mrtstat.f, plurales(mrtstat.f))
+ u_int mrtproto;
+ struct mrt6stat mrtstat;
+
+ if (mrpaddr == 0) {
+ printf("mrt6_stats: symbol not in namelist\n");
+ return;
+ }
+
+ kread(mrpaddr, (char *)&mrtproto, sizeof(mrtproto));
+ switch (mrtproto) {
+ case 0:
+ printf("no IPv6 multicast routing compiled into this system\n");
+ return;
+
+ case IPPROTO_PIM:
+ break;
+
+ default:
+ printf("IPv6 multicast routing protocol %u, unknown\n",
+ mrtproto);
+ return;
+ }
+
+ if (mstaddr == 0) {
+ printf("mrt6_stats: symbol not in namelist\n");
+ return;
+ }
+
+ kread(mstaddr, (char *)&mrtstat, sizeof(mrtstat));
+ printf("multicast forwarding:\n");
+ p(mrt6s_mfc_lookups, " %10llu multicast forwarding cache lookup%s\n");
+ pes(mrt6s_mfc_misses, " %10llu multicast forwarding cache miss%s\n");
+ p(mrt6s_upcalls, " %10llu upcall%s to mrouted\n");
+ p(mrt6s_upq_ovflw, " %10llu upcall queue overflow%s\n");
+ p(mrt6s_upq_sockfull,
+ " %10llu upcall%s dropped due to full socket buffer\n");
+ p(mrt6s_cache_cleanups, " %10llu cache cleanup%s\n");
+ p(mrt6s_no_route, " %10llu datagram%s with no route for origin\n");
+ p(mrt6s_bad_tunnel, " %10llu datagram%s arrived with bad tunneling\n");
+ p(mrt6s_cant_tunnel, " %10llu datagram%s could not be tunneled\n");
+ p(mrt6s_wrong_if, " %10llu datagram%s arrived on wrong interface\n");
+ p(mrt6s_drop_sel, " %10llu datagram%s selectively dropped\n");
+ p(mrt6s_q_overflow,
+ " %10llu datagram%s dropped due to queue overflow\n");
+ p(mrt6s_pkt2large, " %10llu datagram%s dropped for being too large\n");
+#undef p
+#undef pes
+}
+#endif /*INET6*/
--- /dev/null
+.\" $NetBSD: netstat.1,v 1.72 2015/03/23 18:33:17 roy Exp $
+.\"
+.\" Copyright (c) 1983, 1990, 1992, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)netstat.1 8.8 (Berkeley) 4/18/94
+.\"
+.Dd March 19, 2015
+.Dt NETSTAT 1
+.Os
+.Sh NAME
+.Nm netstat
+.Nd show network status
+.Sh SYNOPSIS
+.ds address_family Fl f Ar address_family Ns Op , Ns Ar family ...
+.Nm
+.Op Fl Aan
+.Op \*[address_family]
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Nm
+.Op Fl bdghiLlmnqrSsTtv
+.Op \*[address_family]
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Nm
+.Op Fl dn
+.Op Fl I Ar interface
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Op Fl w Ar wait
+.Nm
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Op Fl p Ar protocol
+.Nm
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Op Fl p Ar protocol
+.Fl P Ar pcbaddr
+.Nm
+.Op Fl i
+.Op Fl I Ar Interface
+.Op Fl p Ar protocol
+.Nm
+.Op Fl is
+.Op \*[address_family]
+.Op Fl I Ar Interface
+.Nm
+.Op Fl s
+.Op Fl I Ar Interface
+.Fl B
+.Sh DESCRIPTION
+The
+.Nm
+command symbolically displays the contents of various network-related
+data structures.
+There are a number of output formats,
+depending on the options for the information presented.
+The first form of the command displays a list of active sockets for
+each protocol.
+The second form presents the contents of one of the other network
+data structures according to the option selected.
+Using the third form, with a
+.Ar wait
+interval specified,
+.Nm
+will continuously display the information regarding packet
+traffic on the configured network interfaces.
+The fourth form displays statistics about the named protocol.
+The fifth and sixth forms display per interface statistics for
+the specified protocol or address family.
+.Pp
+The options have the following meaning:
+.Bl -tag -width flag
+.It Fl A
+With the default display,
+show the address of any protocol control blocks associated with sockets; used
+for debugging.
+.It Fl a
+With the default display,
+show the state of all sockets; normally sockets used by
+server processes are not shown.
+.It Fl B
+With the default display,
+show the current
+.Xr bpf 4
+peers.
+To show only the peers listening to a specific interface,
+use the
+.Fl I
+option.
+If the
+.Fl s
+option is present, show the current
+.Xr bpf 4
+statistics.
+.It Fl b
+With the interface display (option
+.Fl i ) ,
+show bytes in and out, instead of packets in and out.
+.It Fl d
+With either interface display (option
+.Fl i
+or an interval, as described below),
+show the number of dropped packets.
+.It \*[address_family]
+Limit statistics or address control block reports to those
+of the specified
+.Ar address_families .
+The following address families
+are recognized:
+.Ar inet ,
+for
+.Dv AF_INET ;
+.Ar inet6 ,
+for
+.Dv AF_INET6 ;
+.Ar arp ,
+for
+.Dv AF_ARP ;
+.Ar ns ,
+for
+.Dv AF_NS ;
+.Ar atalk ,
+for
+.Dv AF_APPLETALK ;
+.Ar mpls ,
+for
+.Dv AF_MPLS ;
+and
+.Ar local
+or
+.Ar unix ,
+for
+.Dv AF_LOCAL .
+.It Fl g
+Show information related to multicast (group address) routing.
+By default, show the IP Multicast virtual-interface and routing tables.
+If the
+.Fl s
+option is also present, show multicast routing statistics.
+.It Fl h
+When used with
+.Fl b
+in combination with either
+.Fl i
+or
+.Fl I ,
+output "human-readable" byte counts.
+.It Fl I Ar interface
+Show information about the specified interface;
+used with a
+.Ar wait
+interval as described below.
+If the
+.Fl f Ar address_family
+option (with the
+.Fl s
+option) or the
+.Fl p Ar protocol
+option is present, show per-interface statistics on the
+.Ar interface
+for the specified
+.Ar address_family
+or
+.Ar protocol ,
+respectively.
+.It Fl i
+Show the state of interfaces which have been auto-configured
+(interfaces statically configured into a system, but not
+located at boot time are not shown).
+If the
+.Fl a
+options is also present, multicast addresses currently in use are shown
+for each Ethernet interface and for each IP interface address.
+Multicast addresses are shown on separate lines following the interface
+address with which they are associated.
+If the
+.Fl f Ar address_family
+option (with the
+.Fl s
+option) or the
+.Fl p Ar protocol
+option is present, show per-interface statistics on all interfaces
+for the specified
+.Ar address_family
+or
+.Ar protocol ,
+respectively.
+.It Fl L
+Don't show link-level routes (e.g., IPv4 ARP or IPv6 neighbour cache).
+.It Fl l
+With the
+.Fl g
+option, display wider fields for the IPv6 multicast routing table
+.Qq Origin
+and
+.Qq Group
+columns.
+.It Fl M Ar core
+Use
+.Xr kvm 3
+instead of
+.Xr sysctl 3
+to retrieve information and
+extract values associated with the name list from the specified core.
+If the
+.Fl M
+option is not given but the
+.Fl N
+option is given, the default
+.Pa /dev/mem
+is used.
+.It Fl m
+Show statistics recorded by the mbuf memory management routines
+(the network manages a private pool of memory buffers).
+.It Fl N Ar system
+Use
+.Xr kvm 3
+instead of
+.Xr sysctl 3
+to retrieve information and extract the name list from the specified system.
+For the default behavior when only
+.Fl M
+option is given, see the description about when
+.Fa execfile
+is
+.Dv NULL
+in
+.Xr kvm_openfiles 3 .
+.It Fl n
+Show network addresses and ports as numbers (normally
+.Nm
+interprets addresses and ports and attempts to display them
+symbolically).
+This option may be used with any of the display formats.
+.It Fl P Ar pcbaddr
+Dump the contents of the protocol control block (PCB) located at kernel
+virtual address
+.Ar pcbaddr .
+This address may be obtained using the
+.Fl A
+flag.
+The default protocol is TCP, but may be overridden using the
+.Fl p
+flag.
+.It Fl p Ar protocol
+Show statistics about
+.Ar protocol ,
+which is either a well-known name for a protocol or an alias for it.
+Some protocol names and aliases are listed in the file
+.Pa /etc/protocols .
+A null response typically means that there are no interesting numbers to
+report.
+The program will complain if
+.Ar protocol
+is unknown or if there is no statistics routine for it.
+.It Fl q
+Show software interrupt queue setting/statistics for all protocols.
+.It Fl r
+Show the routing tables.
+When
+.Fl s
+is also present, show routing statistics instead.
+.It Fl S
+Show network addresses as numbers (as with
+.Fl n ,
+but show ports symbolically).
+.It Fl s
+Show per-protocol statistics.
+If this option is repeated, counters with a value of zero are suppressed.
+.It Fl T
+Show MPLS Tags for the routing tables.
+If multiple tags exists, they will
+be comma separated, first tag being the BoS one.
+.It Fl t
+With the
+.Fl i
+option, display the current value of the watchdog timer function.
+.It Fl v
+Show extra (verbose) detail for the routing tables
+.Pq Fl r ,
+or avoid truncation of long addresses.
+.It Fl w Ar wait
+Show network interface statistics at intervals of
+.Ar wait
+seconds.
+.It Fl X
+Force use of
+.Xr sysctl 3
+when retrieving information.
+Some features of
+.Nm
+may not be (fully) supported when using
+.Xr sysctl 3 .
+This flag forces the use of the latter regardless, and emits a message if a
+not yet fully supported feature is used in conjunction with it.
+This flag might be removed at any time; do not rely on its presence.
+.El
+.Pp
+The default display, for active sockets, shows the local
+and remote addresses, send and receive queue sizes (in bytes), protocol,
+and the internal state of the protocol.
+Address formats are of the form ``host.port'' or ``network.port''
+if a socket's address specifies a network but no specific host address.
+When known the host and network addresses are displayed symbolically
+according to the data bases
+.Pa /etc/hosts
+and
+.Pa /etc/networks ,
+respectively.
+If a symbolic name for an address is unknown, or if
+the
+.Fl n
+option is specified, the address is printed numerically, according
+to the address family.
+For more information regarding
+the Internet ``dot format,''
+refer to
+.Xr inet 3 ) .
+Unspecified,
+or ``wildcard'', addresses and ports appear as ``*''.
+You can use the
+.Xr fstat 1
+command to find out which process or processes hold references to a socket.
+.Pp
+The interface display provides a table of cumulative
+statistics regarding packets transferred, errors, and collisions.
+The network addresses of the interface
+and the maximum transmission unit (``mtu'') are also displayed.
+.Pp
+The routing table display indicates the available routes and
+their status.
+Each route consists of a destination host or network
+and a gateway to use in forwarding packets.
+The flags field shows
+a collection of information about the route stored as
+binary choices.
+The individual flags are discussed in more
+detail in the
+.Xr route 8
+and
+.Xr route 4
+manual pages.
+The mapping between letters and flags is:
+.Bl -column XXXX RTF_BLACKHOLE
+.It 1 RTF_PROTO1 Protocol specific routing flag #1
+.It 2 RTF_PROTO2 Protocol specific routing flag #2
+.It B RTF_BLACKHOLE Just discard pkts (during updates)
+.It b RTF_BROADCAST Route represents a broadcast address
+.It C RTF_CLONING Generate new routes on use
+.It c RTF_CLONED Cloned routes (generated from RTF_CLONING)
+.It D RTF_DYNAMIC Created dynamically (by redirect)
+.It G RTF_GATEWAY Destination requires forwarding by intermediary
+.It H RTF_HOST Host entry (net otherwise)
+.It L RTF_LLINFO Valid protocol to link address translation.
+.It l RTF_LOCAL Route represents a local address
+.It M RTF_MODIFIED Modified dynamically (by redirect)
+.It p RTF_ANNOUNCE Link level proxy
+.It R RTF_REJECT Host or net unreachable
+.It S RTF_STATIC Manually added
+.It U RTF_UP Route usable
+.It X RTF_XRESOLVE External daemon translates proto to link address
+.El
+.Pp
+Direct routes are created for each
+interface attached to the local host;
+the gateway field for such entries shows the address of the outgoing interface.
+The refcnt field gives the
+current number of active uses of the route.
+Connection oriented
+protocols normally hold on to a single route for the duration of
+a connection while connectionless protocols obtain a route while sending
+to the same destination.
+The use field provides a count of the number of packets
+sent using that route.
+The mtu entry shows the mtu associated with
+that route.
+This mtu value is used as the basis for the TCP maximum
+segment size.
+The 'L' flag appended to the mtu value indicates that
+the value is locked, and that path mtu discovery is turned off for
+that route.
+A
+.Sq -
+indicates that the mtu for this route has not been set, and a default
+TCP maximum segment size will be used.
+The interface entry indicates
+the network interface used for the route.
+.Pp
+When
+.Nm
+is invoked with the
+.Fl w
+option and a
+.Ar wait
+interval argument, it displays a running count of statistics related to
+network interfaces.
+An obsolescent version of this option used a numeric parameter
+with no option, and is currently supported for backward compatibility.
+This display consists of a column for the primary interface (the first
+interface found during autoconfiguration) and a column summarizing
+information for all interfaces.
+The primary interface may be replaced with another interface with the
+.Fl I
+option.
+The first line of each screen of information contains a summary since the
+system was last rebooted.
+Subsequent lines of output show values
+accumulated over the preceding interval.
+.Pp
+The first character of the flags column in the
+.Fl B
+option shows the status of the
+.Xr bpf 4
+descriptor which has three different values:
+Idle ('I'), Waiting ('W') and Timed Out ('T').
+The second character indicates whether the promisc flag is set.
+The third character indicates the status of the immediate mode.
+The fourth character indicates whether the peer will have the ability
+to see the packets sent.
+And the fifth character shows the header complete flag status.
+.Sh SEE ALSO
+.Xr fstat 1 ,
+.Xr nfsstat 1 ,
+.Xr ps 1 ,
+.Xr sockstat 1 ,
+.Xr vmstat 1 ,
+.Xr inet 3 ,
+.Xr bpf 4 ,
+.Xr hosts 5 ,
+.Xr networks 5 ,
+.Xr protocols 5 ,
+.Xr services 5 ,
+.Xr iostat 8 ,
+.Xr trpt 8
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
+IPv6 support was added by WIDE/KAME project.
+.\" .Sh FILES
+.\" .Bl -tag -width /dev/mem -compact
+.\" .It Pa /netbsd
+.\" default kernel namelist
+.\" .It Pa /dev/mem
+.\" default memory file
+.\" .El
+.Sh BUGS
+The notion of errors is ill-defined.
--- /dev/null
+/* $NetBSD: netstat.h,v 1.51 2014/11/06 21:30:09 christos Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)netstat.h 8.2 (Berkeley) 1/4/94
+ */
+
+#include <sys/cdefs.h>
+#include <kvm.h>
+
+int Aflag; /* show addresses of protocol control block */
+int aflag; /* show all sockets (including servers) */
+int Bflag; /* show Berkeley Packet Filter information */
+int bflag; /* show i/f byte stats */
+int dflag; /* show i/f dropped packets */
+#ifndef SMALL
+int gflag; /* show group (multicast) routing or stats */
+#endif
+int hflag; /* humanize byte counts */
+int iflag; /* show interfaces */
+int Lflag; /* don't show LLINFO entries */
+int lflag; /* show routing table with use and ref */
+int mflag; /* show memory stats */
+int numeric_addr; /* show addresses numerically */
+int numeric_port; /* show ports numerically */
+int nflag; /* same as above, for show.c compat */
+int Pflag; /* dump a PCB */
+int pflag; /* show given protocol */
+int qflag; /* show softintrq */
+int rflag; /* show routing tables (or routing stats) */
+int sflag; /* show protocol statistics */
+int tagflag; /* show route tags */
+int tflag; /* show i/f watchdog timers */
+int Vflag; /* show Vestigial TIME_WAIT (VTW) information */
+int vflag; /* verbose route information or don't truncate names */
+
+char *interface; /* desired i/f for stats, or NULL for all i/fs */
+
+int af; /* address family */
+int use_sysctl; /* use sysctl instead of kmem */
+int force_sysctl; /* force use of sysctl (or exit) - for testing */
+
+
+int kread(u_long addr, char *buf, int size);
+const char *plural(int);
+const char *plurales(int);
+int get_hardticks(void);
+
+void protopr(u_long, const char *);
+void tcp_stats(u_long, const char *);
+void tcp_dump(u_long, const char *, u_long);
+void udp_stats(u_long, const char *);
+void ip_stats(u_long, const char *);
+void icmp_stats(u_long, const char *);
+void igmp_stats(u_long, const char *);
+void pim_stats(u_long, const char *);
+void arp_stats(u_long, const char *);
+void carp_stats(u_long, const char *);
+void pfsync_stats(u_long, const char*);
+#ifdef IPSEC
+void fast_ipsec_stats(u_long, const char *);
+#endif
+
+#ifdef INET6
+struct sockaddr_in6;
+struct in6_addr;
+void ip6protopr(u_long, const char *);
+void tcp6_stats(u_long, const char *);
+void tcp6_dump(u_long, const char *, u_long);
+void udp6_stats(u_long, const char *);
+void ip6_stats(u_long, const char *);
+void ip6_ifstats(const char *);
+void icmp6_stats(u_long, const char *);
+void icmp6_ifstats(const char *);
+void pim6_stats(u_long, const char *);
+void rip6_stats(u_long, const char *);
+void mroute6pr(u_long, u_long, u_long);
+void mrt6_stats(u_long, u_long);
+#endif /*INET6*/
+
+#ifdef IPSEC
+void pfkey_stats(u_long, const char *);
+#endif
+
+void mbpr(u_long, u_long, u_long, u_long, u_long);
+
+void hostpr(u_long, u_long);
+void impstats(u_long, u_long);
+
+void rt_stats(u_long);
+char *ns_phost(struct sockaddr *);
+
+const char *atalk_print(const struct sockaddr *, int);
+const char *atalk_print2(const struct sockaddr *, const struct sockaddr *,
+ int);
+char *ns_print(struct sockaddr *);
+
+void nsprotopr(u_long, const char *);
+void spp_stats(u_long, const char *);
+void idp_stats(u_long, const char *);
+void nserr_stats(u_long, const char *);
+
+void atalkprotopr(u_long, const char *);
+void ddp_stats(u_long, const char *);
+
+void intpr(int, u_long, void (*)(const char *));
+
+void unixpr(u_long);
+
+void routepr(u_long);
+void mroutepr(u_long, u_long, u_long, u_long);
+void mrt_stats(u_long, u_long);
+
+void bpf_stats(void);
+void bpf_dump(const char *);
+
+kvm_t *get_kvmd(void);
+
+char *mpls_ntoa(const struct sockaddr *);
+
+struct kinfo_pcb *getpcblist_sysctl(const char *, size_t *);
+
+#define PLEN (LONG_BIT / 4 + 2)
--- /dev/null
+/* $NetBSD: netstat_hostops.c,v 1.1 2010/12/13 21:15:30 pooka Exp $ */
+
+/*
+ * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: netstat_hostops.c,v 1.1 2010/12/13 21:15:30 pooka Exp $");
+#endif /* !lint */
+
+#include <sys/types.h>
+#include <sys/sysctl.h>
+
+#include "prog_ops.h"
+
+const struct prog_ops prog_ops = {
+ .op_sysctl = sysctl,
+};
--- /dev/null
+/* $NetBSD: netstat_rumpops.c,v 1.1 2010/12/13 21:15:30 pooka Exp $ */
+
+/*
+ * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: netstat_rumpops.c,v 1.1 2010/12/13 21:15:30 pooka Exp $");
+#endif /* !lint */
+
+#include <sys/types.h>
+
+#include <rump/rump.h>
+#include <rump/rumpclient.h>
+#include <rump/rump_syscalls.h>
+
+#include "prog_ops.h"
+
+const struct prog_ops prog_ops = {
+ .op_init = rumpclient_init,
+
+ .op_sysctl = rump_sys___sysctl,
+};
--- /dev/null
+/* $NetBSD: pfkey.c,v 1.1 2012/01/06 14:21:16 drochner Exp $ */
+/* $KAME: ipsec.c,v 1.33 2003/07/25 09:54:32 itojun Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1983, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "from: @(#)inet.c 8.4 (Berkeley) 4/20/94";
+#else
+#ifdef __NetBSD__
+__RCSID("$NetBSD: pfkey.c,v 1.1 2012/01/06 14:21:16 drochner Exp $");
+#endif
+#endif
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#ifdef IPSEC
+#include <netipsec/keysock.h>
+#endif
+
+#include <err.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include "netstat.h"
+
+#ifdef IPSEC
+
+static const char *pfkey_msgtypenames[] = {
+ "reserved", "getspi", "update", "add", "delete",
+ "get", "acquire", "register", "expire", "flush",
+ "dump", "x_promisc", "x_pchange", "x_spdupdate", "x_spdadd",
+ "x_spddelete", "x_spdget", "x_spdacquire", "x_spddump", "x_spdflush",
+ "x_spdsetidx", "x_spdexpire", "x_spddelete2"
+};
+
+static const char *pfkey_msgtype_names(int);
+
+static const char *
+pfkey_msgtype_names(int x)
+{
+ const int max =
+ sizeof(pfkey_msgtypenames)/sizeof(pfkey_msgtypenames[0]);
+ static char buf[20];
+
+ if (x < max && pfkey_msgtypenames[x])
+ return pfkey_msgtypenames[x];
+ snprintf(buf, sizeof(buf), "#%d", x);
+ return buf;
+}
+
+void
+pfkey_stats(u_long off, const char *name)
+{
+ uint64_t pfkeystat[PFKEY_NSTATS];
+ int first, type;
+
+ if (use_sysctl) {
+ size_t size = sizeof(pfkeystat);
+
+ if (sysctlbyname("net.key.stats", pfkeystat, &size,
+ NULL, 0) == -1)
+ return;
+ } else {
+ warnx("%s stats not available via KVM.", name);
+ return;
+ }
+
+ printf ("%s:\n", name);
+
+#define p(f, m) if (pfkeystat[f] || sflag <= 1) \
+ printf(m, (unsigned long long)pfkeystat[f], plural(pfkeystat[f]))
+
+ /* userland -> kernel */
+ p(PFKEY_STAT_OUT_TOTAL, "\t%llu request%s sent from userland\n");
+ p(PFKEY_STAT_OUT_BYTES, "\t%llu byte%s sent from userland\n");
+ for (first = 1, type = 0; type < 256; type++) {
+ if (pfkeystat[PFKEY_STAT_OUT_MSGTYPE + type] == 0)
+ continue;
+ if (first) {
+ printf("\thistogram by message type:\n");
+ first = 0;
+ }
+ printf("\t\t%s: %llu\n", pfkey_msgtype_names(type),
+ (unsigned long long)pfkeystat[PFKEY_STAT_OUT_MSGTYPE + type]);
+ }
+ p(PFKEY_STAT_OUT_INVLEN, "\t%llu message%s with invalid length field\n");
+ p(PFKEY_STAT_OUT_INVVER, "\t%llu message%s with invalid version field\n");
+ p(PFKEY_STAT_OUT_INVMSGTYPE, "\t%llu message%s with invalid message type field\n");
+ p(PFKEY_STAT_OUT_TOOSHORT, "\t%llu message%s too short\n");
+ p(PFKEY_STAT_OUT_NOMEM, "\t%llu message%s with memory allocation failure\n");
+ p(PFKEY_STAT_OUT_DUPEXT, "\t%llu message%s with duplicate extension\n");
+ p(PFKEY_STAT_OUT_INVEXTTYPE, "\t%llu message%s with invalid extension type\n");
+ p(PFKEY_STAT_OUT_INVSATYPE, "\t%llu message%s with invalid sa type\n");
+ p(PFKEY_STAT_OUT_INVADDR, "\t%llu message%s with invalid address extension\n");
+
+ /* kernel -> userland */
+ p(PFKEY_STAT_IN_TOTAL, "\t%llu request%s sent to userland\n");
+ p(PFKEY_STAT_IN_BYTES, "\t%llu byte%s sent to userland\n");
+ for (first = 1, type = 0; type < 256; type++) {
+ if (pfkeystat[PFKEY_STAT_IN_MSGTYPE + type] == 0)
+ continue;
+ if (first) {
+ printf("\thistogram by message type:\n");
+ first = 0;
+ }
+ printf("\t\t%s: %llu\n", pfkey_msgtype_names(type),
+ (unsigned long long)pfkeystat[PFKEY_STAT_IN_MSGTYPE + type]);
+ }
+ p(PFKEY_STAT_IN_MSGTARGET + KEY_SENDUP_ONE,
+ "\t%llu message%s toward single socket\n");
+ p(PFKEY_STAT_IN_MSGTARGET + KEY_SENDUP_ALL,
+ "\t%llu message%s toward all sockets\n");
+ p(PFKEY_STAT_IN_MSGTARGET + KEY_SENDUP_REGISTERED,
+ "\t%llu message%s toward registered sockets\n");
+ p(PFKEY_STAT_IN_NOMEM, "\t%llu message%s with memory allocation failure\n");
+#undef p
+}
+#endif /*IPSEC*/
--- /dev/null
+/* $NetBSD: pfsync.c,v 1.1 2011/03/01 19:01:59 dyoung Exp $ */
+
+/*
+ * Copyright (c) 1983, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: pfsync.c,v 1.1 2011/03/01 19:01:59 dyoung Exp $");
+#endif /* not lint */
+
+#define _CALLOUT_PRIVATE /* for defs in sys/callout.h */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/mbuf.h>
+#include <sys/protosw.h>
+#include <sys/sysctl.h>
+
+#include <net/if_arp.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/in_pcb.h>
+#include <netinet/ip_icmp.h>
+
+#ifdef INET6
+#include <netinet/ip6.h>
+#endif
+
+#include <net/pfvar.h>
+#include <net/if_pfsync.h>
+
+#include <arpa/inet.h>
+#include <kvm.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <err.h>
+#include "netstat.h"
+#include "prog_ops.h"
+
+/*
+ * Dump PFSYNC statistics structure.
+ */
+void
+pfsync_stats(u_long off, const char *name)
+{
+ uint64_t pfsyncstat[PFSYNC_NSTATS];
+
+ if (use_sysctl) {
+ size_t size = sizeof(pfsyncstat);
+
+ if (sysctlbyname("net.inet.pfsync.stats", pfsyncstat, &size,
+ NULL, 0) == -1)
+ return;
+ } else {
+ warnx("%s stats not available via KVM.", name);
+ return;
+ }
+
+ printf("%s:\n", name);
+
+#define p(f, m) if (pfsyncstat[f] || sflag <= 1) \
+ printf(m, pfsyncstat[f], plural(pfsyncstat[f]))
+#define p2(f, m) if (pfsyncstat[f] || sflag <= 1) \
+ printf(m, pfsyncstat[f])
+
+ p(PFSYNC_STAT_IPACKETS, "\t%" PRIu64 " packet%s received (IPv4)\n");
+ p(PFSYNC_STAT_IPACKETS6,"\t%" PRIu64 " packet%s received (IPv6)\n");
+ p(PFSYNC_STAT_BADIF, "\t\t%" PRIu64 " packet%s discarded for bad interface\n");
+ p(PFSYNC_STAT_BADTTL, "\t\t%" PRIu64 " packet%s discarded for bad ttl\n");
+ p(PFSYNC_STAT_HDROPS, "\t\t%" PRIu64 " packet%s shorter than header\n");
+ p(PFSYNC_STAT_BADVER, "\t\t%" PRIu64 " packet%s discarded for bad version\n");
+ p(PFSYNC_STAT_BADAUTH, "\t\t%" PRIu64 " packet%s discarded for bad HMAC\n");
+ p(PFSYNC_STAT_BADACT,"\t\t%" PRIu64 " packet%s discarded for bad action\n");
+ p(PFSYNC_STAT_BADLEN, "\t\t%" PRIu64 " packet%s discarded for short packet\n");
+ p(PFSYNC_STAT_BADVAL, "\t\t%" PRIu64 " state%s discarded for bad values\n");
+ p(PFSYNC_STAT_STALE, "\t\t%" PRIu64 " stale state%s\n");
+ p(PFSYNC_STAT_BADSTATE, "\t\t%" PRIu64 " failed state lookup/insert%s\n");
+ p(PFSYNC_STAT_OPACKETS, "\t%" PRIu64 " packet%s sent (IPv4)\n");
+ p(PFSYNC_STAT_OPACKETS6, "\t%" PRIu64 " packet%s sent (IPv6)\n");
+ p2(PFSYNC_STAT_ONOMEM, "\t\t%" PRIu64 " send failed due to mbuf memory error\n");
+ p2(PFSYNC_STAT_OERRORS, "\t\t%" PRIu64 " send error\n");
+#undef p
+#undef p2
+}
+
+
--- /dev/null
+/* $NetBSD: prog_ops.h,v 1.2 2010/12/15 11:22:41 pooka Exp $ */
+
+/*
+ * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _PROG_OPS_H_
+#define _PROG_OPS_H_
+
+#include <sys/types.h>
+
+#ifndef CRUNCHOPS
+struct prog_ops {
+ int (*op_init)(void);
+
+ int (*op_sysctl)(const int *, u_int, void *, size_t *,
+ const void *, size_t);
+};
+extern const struct prog_ops prog_ops;
+
+#define prog_init prog_ops.op_init
+#define prog_sysctl prog_ops.op_sysctl
+#else
+#define prog_init ((int (*)(void))NULL)
+#define prog_sysctl sysctl
+#endif
+
+#endif /* _PROG_OPS_H_ */
--- /dev/null
+/* $NetBSD: route.c,v 1.84 2015/05/25 03:56:20 manu Exp $ */
+
+/*
+ * Copyright (c) 1983, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "from: @(#)route.c 8.3 (Berkeley) 3/9/94";
+#else
+__RCSID("$NetBSD: route.c,v 1.84 2015/05/25 03:56:20 manu Exp $");
+#endif
+#endif /* not lint */
+
+#include <stdbool.h>
+#include <sys/param.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/mbuf.h>
+#include <sys/un.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netatalk/at.h>
+#include <netmpls/mpls.h>
+
+#include <sys/sysctl.h>
+
+#include <arpa/inet.h>
+
+#include <err.h>
+#include <kvm.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "netstat.h"
+#include "rtutil.h"
+
+#define kget(p, d) (kread((u_long)(p), (char *)&(d), sizeof (d)))
+
+/*
+ * XXX we put all of the sockaddr types in here to force the alignment
+ * to be correct.
+ */
+static union sockaddr_union {
+ struct sockaddr u_sa;
+ struct sockaddr_in u_in;
+ struct sockaddr_un u_un;
+ struct sockaddr_at u_at;
+ struct sockaddr_dl u_dl;
+ u_short u_data[128];
+ int u_dummy; /* force word-alignment */
+} pt_u;
+
+int do_rtent = 0;
+struct rtentry rtentry;
+struct radix_node rnode;
+struct radix_mask rmask;
+
+static struct sockaddr *kgetsa(const struct sockaddr *);
+static void p_tree(struct radix_node *);
+static void p_rtnode(void);
+static void p_krtentry(struct rtentry *);
+
+/*
+ * Print routing tables.
+ */
+void
+routepr(u_long rtree)
+{
+ struct radix_node_head *rnh, head;
+ struct radix_node_head *rt_nodes[AF_MAX+1];
+ int i;
+
+ printf("Routing tables\n");
+
+ if (rtree == 0) {
+ printf("rt_tables: symbol not in namelist\n");
+ return;
+ }
+
+ kget(rtree, rt_nodes);
+ for (i = 0; i <= AF_MAX; i++) {
+ if ((rnh = rt_nodes[i]) == 0)
+ continue;
+ kget(rnh, head);
+ if (i == AF_UNSPEC) {
+ if (Aflag && (af == 0 || af == 0xff)) {
+ printf("Netmasks:\n");
+ p_tree(head.rnh_treetop);
+ }
+ } else if (af == AF_UNSPEC || af == i) {
+ p_family(i);
+ do_rtent = 1;
+ p_rthdr(i, Aflag);
+ p_tree(head.rnh_treetop);
+ }
+ }
+}
+
+static struct sockaddr *
+kgetsa(const struct sockaddr *dst)
+{
+
+ kget(dst, pt_u.u_sa);
+ if (pt_u.u_sa.sa_len > sizeof (pt_u.u_sa))
+ kread((u_long)dst, (char *)pt_u.u_data, pt_u.u_sa.sa_len);
+ return (&pt_u.u_sa);
+}
+
+static void
+p_tree(struct radix_node *rn)
+{
+
+again:
+ kget(rn, rnode);
+ if (rnode.rn_b < 0) {
+ if (Aflag)
+ printf("%-8.8lx ", (u_long) rn);
+ if (rnode.rn_flags & RNF_ROOT) {
+ if (Aflag)
+ printf("(root node)%s",
+ rnode.rn_dupedkey ? " =>\n" : "\n");
+ } else if (do_rtent) {
+ kget(rn, rtentry);
+ p_krtentry(&rtentry);
+ if (Aflag)
+ p_rtnode();
+ } else {
+ p_sockaddr(kgetsa((const struct sockaddr *)rnode.rn_key),
+ NULL, 0, 44, nflag);
+ putchar('\n');
+ }
+ if ((rn = rnode.rn_dupedkey) != NULL)
+ goto again;
+ } else {
+ if (Aflag && do_rtent) {
+ printf("%-8.8lx ", (u_long) rn);
+ p_rtnode();
+ }
+ rn = rnode.rn_r;
+ p_tree(rnode.rn_l);
+ p_tree(rn);
+ }
+}
+
+static void
+p_rtnode(void)
+{
+ struct radix_mask *rm = rnode.rn_mklist;
+ char nbuf[20];
+
+ if (rnode.rn_b < 0) {
+ if (rnode.rn_mask) {
+ printf("\t mask ");
+ p_sockaddr(kgetsa((const struct sockaddr *)rnode.rn_mask),
+ NULL, 0, -1, nflag);
+ } else if (rm == 0)
+ return;
+ } else {
+ (void)snprintf(nbuf, sizeof nbuf, "(%d)", rnode.rn_b);
+ printf("%6.6s %8.8lx : %8.8lx", nbuf, (u_long) rnode.rn_l,
+ (u_long) rnode.rn_r);
+ }
+ while (rm) {
+ kget(rm, rmask);
+ (void)snprintf(nbuf, sizeof nbuf, " %d refs, ", rmask.rm_refs);
+ printf(" mk = %8.8lx {(%d),%s", (u_long) rm,
+ -1 - rmask.rm_b, rmask.rm_refs ? nbuf : " ");
+ if (rmask.rm_flags & RNF_NORMAL) {
+ struct radix_node rnode_aux;
+ printf(" <normal>, ");
+ kget(rmask.rm_leaf, rnode_aux);
+ p_sockaddr(kgetsa((const struct sockaddr *)rnode_aux.rn_mask),
+ NULL, 0, -1, nflag);
+ } else
+ p_sockaddr(kgetsa((const struct sockaddr *)rmask.rm_mask),
+ NULL, 0, -1, nflag);
+ putchar('}');
+ if ((rm = rmask.rm_mklist) != NULL)
+ printf(" ->");
+ }
+ putchar('\n');
+}
+
+static struct sockaddr *sockcopy(struct sockaddr *, union sockaddr_union *);
+
+/*
+ * copy a sockaddr into an allocated region, allocate at least sockaddr
+ * bytes and zero unused
+ */
+static struct sockaddr *
+sockcopy(struct sockaddr *sp, union sockaddr_union *dp)
+{
+ int len;
+
+ if (sp == 0 || sp->sa_len == 0)
+ (void)memset(dp, 0, sizeof (*sp));
+ else {
+ len = (sp->sa_len >= sizeof (*sp)) ? sp->sa_len : sizeof (*sp);
+ (void)memcpy(dp, sp, len);
+ }
+ return ((struct sockaddr *)dp);
+}
+
+static void
+p_krtentry(struct rtentry *rt)
+{
+ static struct ifnet ifnet, *lastif;
+ union sockaddr_union addr_un, mask_un;
+ struct sockaddr *addr, *mask;
+
+ if (Lflag && (rt->rt_flags & RTF_LLINFO))
+ return;
+
+ memset(&addr_un, 0, sizeof(addr_un));
+ memset(&mask_un, 0, sizeof(mask_un));
+ addr = sockcopy(kgetsa(rt_getkey(rt)), &addr_un);
+ if (rt_mask(rt))
+ mask = sockcopy(kgetsa(rt_mask(rt)), &mask_un);
+ else
+ mask = sockcopy(NULL, &mask_un);
+ p_addr(addr, mask, rt->rt_flags, nflag);
+ p_gwaddr(kgetsa(rt->rt_gateway), kgetsa(rt->rt_gateway)->sa_family, nflag);
+ p_flags(rt->rt_flags);
+ printf("%6d %8"PRIu64" ", rt->rt_refcnt, rt->rt_use);
+ if (rt->rt_rmx.rmx_mtu)
+ printf("%6"PRIu64, rt->rt_rmx.rmx_mtu);
+ else
+ printf("%6s", "-");
+ putchar((rt->rt_rmx.rmx_locks & RTV_MTU) ? 'L' : ' ');
+ if (tagflag == 1) {
+#ifndef SMALL
+ if (rt->rt_tag != NULL) {
+ const struct sockaddr *tagsa = kgetsa(rt->rt_tag);
+ char *tagstr;
+
+ if (tagsa->sa_family == AF_MPLS) {
+ tagstr = mpls_ntoa(tagsa);
+ if (strlen(tagstr) < 7)
+ printf("%7s", tagstr);
+ else
+ printf("%s", tagstr);
+ }
+ else
+ printf("%7s", "-");
+ } else
+#endif
+ printf("%7s", "-");
+ }
+ if (rt->rt_ifp) {
+ if (rt->rt_ifp != lastif) {
+ kget(rt->rt_ifp, ifnet);
+ lastif = rt->rt_ifp;
+ }
+ printf(" %.16s%s", ifnet.if_xname,
+ rt->rt_nodes[0].rn_dupedkey ? " =>" : "");
+ }
+ putchar('\n');
+#ifndef SMALL
+ if (vflag)
+ p_rtrmx(&rt->rt_rmx);
+#endif
+}
+
+/*
+ * Print routing statistics
+ */
+void
+rt_stats(u_long off)
+{
+ struct rtstat rtstats;
+
+ if (use_sysctl) {
+ size_t rtsize = sizeof(rtstats);
+
+ if (sysctlbyname("net.route.stats", &rtstats, &rtsize,
+ NULL, 0) == -1)
+ err(1, "rt_stats: sysctl");
+ } else if (off == 0) {
+ printf("rtstat: symbol not in namelist\n");
+ return;
+ } else
+ kread(off, (char *)&rtstats, sizeof(rtstats));
+
+ printf("routing:\n");
+ printf("\t%llu bad routing redirect%s\n",
+ (unsigned long long)rtstats.rts_badredirect,
+ plural(rtstats.rts_badredirect));
+ printf("\t%llu dynamically created route%s\n",
+ (unsigned long long)rtstats.rts_dynamic,
+ plural(rtstats.rts_dynamic));
+ printf("\t%llu new gateway%s due to redirects\n",
+ (unsigned long long)rtstats.rts_newgateway,
+ plural(rtstats.rts_newgateway));
+ printf("\t%llu destination%s found unreachable\n",
+ (unsigned long long)rtstats.rts_unreach,
+ plural(rtstats.rts_unreach));
+ printf("\t%llu use%s of a wildcard route\n",
+ (unsigned long long)rtstats.rts_wildcard,
+ plural(rtstats.rts_wildcard));
+}
--- /dev/null
+/* $NetBSD: unix.c,v 1.34 2012/03/20 20:34:58 matt Exp $ */
+
+/*-
+ * Copyright (c) 1983, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "from: @(#)unix.c 8.1 (Berkeley) 6/6/93";
+#else
+__RCSID("$NetBSD: unix.c,v 1.34 2012/03/20 20:34:58 matt Exp $");
+#endif
+#endif /* not lint */
+
+/*
+ * Display protocol blocks in the unix domain.
+ */
+#define _KERNEL
+#include <sys/types.h>
+#undef _KERNEL
+#include <sys/param.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/mbuf.h>
+#include <sys/sysctl.h>
+#include <sys/un.h>
+#include <sys/unpcb.h>
+#define _KERNEL
+#include <sys/file.h>
+#undef _KERNEL
+
+#include <netinet/in.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <kvm.h>
+#include <err.h>
+#include "netstat.h"
+#include "prog_ops.h"
+
+static void unixdomainprhdr(void);
+static void unixdomainpr0(u_long, u_long, u_long, u_long, u_long, u_long,
+ u_long, u_long, u_long, struct sockaddr_un *, int);
+static void unixdomainpr(struct socket *, void *);
+
+static struct file *file, *fileNFILE;
+static int ns_nfiles;
+
+static void
+unixdomainprhdr(void)
+{
+ printf("Active UNIX domain sockets\n");
+ printf("%-8.8s %-6.6s %-6.6s %-6.6s %8.8s %8.8s %8.8s %8.8s Addr\n",
+ "Address", "Type", "Recv-Q", "Send-Q", "Inode", "Conn", "Refs",
+ "Nextref");
+}
+
+static const char * const socktype[] =
+ { "#0", "stream", "dgram", "raw", "rdm", "seqpacket" };
+
+static void
+unixdomainpr0(u_long so_pcb, u_long so_type, u_long rcvq, u_long sndq,
+ u_long inode, u_long conn, u_long refs, u_long nextref,
+ u_long addr, struct sockaddr_un *sun, int remote)
+{
+ printf("%8lx %-6.6s %6ld %6ld %8lx %8lx %8lx %8lx",
+ so_pcb, socktype[so_type], rcvq, sndq, inode, conn, refs,
+ nextref);
+ if (addr || remote)
+ printf((remote ? " -> %.*s" : " %.*s"),
+ (int)(sun->sun_len - (sizeof(*sun) - sizeof(sun->sun_path))),
+ sun->sun_path);
+ putchar('\n');
+}
+
+static void
+unixdomainpr(struct socket *so, void *soaddr)
+{
+ struct unpcb unp, runp;
+ struct sockaddr_un sun, rsun;
+ static int first = 1;
+ int remote = 0;
+
+ if (kread((u_long)so->so_pcb, (char *)&unp, sizeof (unp)))
+ return;
+ if (unp.unp_addr)
+ if (kread((u_long)unp.unp_addr, (char *)&sun, sizeof (sun)))
+ unp.unp_addr = 0;
+
+ if (!unp.unp_addr) {
+ memset(&rsun, 0, sizeof(rsun));
+ if (unp.unp_conn &&
+ kread((u_long)unp.unp_conn, (char *)&runp, sizeof (runp)) == 0 &&
+ runp.unp_addr &&
+ kread((u_long)runp.unp_addr, (char *)&rsun, sizeof (rsun)) == 0 &&
+ rsun.sun_path[0] != '\0')
+ remote = 1;
+ }
+
+ if (first) {
+ unixdomainprhdr();
+ first = 0;
+ }
+
+ unixdomainpr0((u_long)so->so_pcb, so->so_type, so->so_rcv.sb_cc,
+ so->so_snd.sb_cc, (u_long)unp.unp_vnode,
+ (u_long)unp.unp_conn, (u_long)unp.unp_refs,
+ (u_long)unp.unp_nextref, (u_long)unp.unp_addr,
+ remote ? &rsun : &sun, remote);
+}
+
+void
+unixpr(u_long off)
+{
+ struct file *fp;
+ struct socket sock, *so = &sock;
+ char *filebuf;
+ struct protosw *unixsw = (struct protosw *)off;
+
+ if (use_sysctl) {
+ struct kinfo_pcb *pcblist;
+ int mib[8];
+ size_t namelen = 0, size = 0, i;
+ const char *mibnames[] = {
+ "net.local.stream.pcblist",
+ "net.local.dgram.pcblist",
+ "net.local.seqpacket.pcblist",
+ NULL,
+ };
+ const char **mibname;
+ static int first = 1;
+
+ for (mibname = mibnames; *mibname; mibname++) {
+ memset(mib, 0, sizeof(mib));
+
+ if (sysctlnametomib(*mibname, mib,
+ &namelen) == -1)
+ err(1, "sysctlnametomib: %s", *mibname);
+
+ if (prog_sysctl(mib, sizeof(mib) / sizeof(*mib),
+ NULL, &size, NULL, 0) == -1)
+ err(1, "sysctl (query)");
+
+ if ((pcblist = malloc(size)) == NULL)
+ err(1, "malloc");
+ memset(pcblist, 0, size);
+
+ mib[6] = sizeof(*pcblist);
+ mib[7] = size / sizeof(*pcblist);
+
+ if (prog_sysctl(mib, sizeof(mib) / sizeof(*mib),
+ pcblist, &size, NULL, 0) == -1)
+ err(1, "sysctl (copy)");
+
+ for (i = 0; i < size / sizeof(*pcblist); i++) {
+ struct kinfo_pcb *ki = &pcblist[i];
+ struct sockaddr_un *sun;
+ int remote = 0;
+
+ if (first) {
+ unixdomainprhdr();
+ first = 0;
+ }
+
+ sun = (struct sockaddr_un *)&ki->ki_dst;
+ if (sun->sun_path[0] != '\0') {
+ remote = 1;
+ } else {
+ sun = (struct sockaddr_un *)&ki->ki_src;
+ }
+
+ unixdomainpr0(ki->ki_pcbaddr, ki->ki_type,
+ ki->ki_rcvq, ki->ki_sndq,
+ ki->ki_vnode, ki->ki_conn,
+ ki->ki_refs, ki->ki_nextref,
+ ki->ki_sockaddr, sun, remote);
+ }
+
+ free(pcblist);
+ }
+
+ } else {
+ filebuf = (char *)kvm_getfiles(get_kvmd(), KERN_FILE,
+ 0, &ns_nfiles);
+ if (filebuf == 0) {
+ printf("file table read error: %s",
+ kvm_geterr(get_kvmd()));
+ return;
+ }
+ file = (struct file *)(filebuf + sizeof(fp));
+ fileNFILE = file + ns_nfiles;
+ for (fp = file; fp < fileNFILE; fp++) {
+ if (fp->f_count == 0 || fp->f_type != DTYPE_SOCKET)
+ continue;
+ if (kread((u_long)fp->f_data, (char *)so, sizeof (*so)))
+ continue;
+ /* kludge */
+ if (so->so_proto >= unixsw && so->so_proto <= unixsw + 2)
+ if (so->so_pcb)
+ unixdomainpr(so, fp->f_data);
+ }
+ }
+}
--- /dev/null
+/* $NetBSD: vtw.c,v 1.8 2015/06/16 22:54:10 christos Exp $ */
+
+/*
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Coyote Point Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 1983, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "from: @(#)inet.c 8.4 (Berkeley) 4/20/94";
+#else
+__RCSID("$NetBSD: vtw.c,v 1.8 2015/06/16 22:54:10 christos Exp $");
+#endif
+#endif /* not lint */
+
+#define _CALLOUT_PRIVATE /* for defs in sys/callout.h */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/mbuf.h>
+#include <sys/protosw.h>
+#include <sys/sysctl.h>
+
+#include <net/if_arp.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/in_pcb.h>
+#include <netinet/ip_icmp.h>
+
+#ifdef INET6
+#include <netinet/ip6.h>
+#endif
+
+#include <netinet/icmp_var.h>
+#include <netinet/igmp_var.h>
+#include <netinet/ip_var.h>
+#include <netinet/pim_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+#include <netinet/tcp_seq.h>
+#include <netinet/tcp_fsm.h>
+#include <netinet/tcp_timer.h>
+#include <netinet/tcp_var.h>
+#include <netinet/tcp_debug.h>
+#include <netinet/udp.h>
+#include <netinet/ip_carp.h>
+#include <netinet/udp_var.h>
+#include <netinet/tcp_vtw.h>
+
+#include <arpa/inet.h>
+#include <kvm.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <err.h>
+#include "netstat.h"
+#include "vtw.h"
+#include "prog_ops.h"
+
+static void snarf(const void *, void *, size_t);
+static void *lookup(const char *);
+static void process_vtw(const vtw_ctl_t *, void (*)(const vtw_t *));
+
+static void
+snarf(const void *addr, void *buf, size_t len)
+{
+ size_t cc;
+
+ memset(buf, 0, len);
+
+ cc = kvm_read(get_kvmd(), (unsigned long) addr, buf, len);
+
+ if (cc != len) {
+ warnx("%s: short read at %p, len %zx cc %zx", __func__, addr,
+ len, cc);
+ }
+}
+
+static void *
+lookup(const char *name)
+{
+ kvm_t *k;
+ struct nlist nl[2];
+
+ nl[0].n_name = name;
+ nl[0].n_value = 0;
+ nl[1].n_name = NULL;
+
+ if ((k = get_kvmd()) == NULL) {
+ if (Vflag)
+ errx(EXIT_FAILURE, "kvm not available");
+ return NULL;
+ }
+ switch (kvm_nlist(k, &nl[0])) {
+ case -1:
+ err(EXIT_FAILURE, "kvm_nlist");
+ break;
+
+ case 0:
+ return (void *)nl[0].n_value;
+
+ default:
+ if (Vflag)
+ errx(EXIT_FAILURE, "%s missing in symbol table", name);
+ break;
+ }
+
+ return NULL;
+}
+
+void
+timebase(struct timeval *tv)
+{
+ void *p;
+ struct bintime timebasebin;
+
+ p = lookup("timebasebin");
+ if (!p)
+ return;
+ snarf(p, &timebasebin, sizeof(timebasebin));
+ bintime2timeval(&timebasebin, tv);
+}
+
+static void
+process_vtw(const vtw_ctl_t * ctl, void (*print)(const vtw_t *))
+{
+ vtw_t *vp;
+
+ for (vp = ctl->base.v; vp && vp <= ctl->lim.v;) {
+
+ (*print)(vp);
+
+ if (ctl->is_v4) {
+ vtw_v4_t *v4 = (vtw_v4_t *)vp;
+
+ vp = &(++v4)->common;
+ } else if (ctl->is_v6) {
+ vtw_v6_t *v6 = (vtw_v6_t *)vp;
+
+ vp = &(++v6)->common;
+ }
+ }
+}
+
+void
+show_vtw_stats(void)
+{
+ vtw_stats_t stats;
+ void *p;
+
+ if (!Vflag)
+ return;
+
+ if ((p = lookup("vtw_stats")) == NULL)
+ return;
+ snarf(p, &stats, sizeof(stats));
+
+ printf("\t\t%" PRIu64 " inserts\n", stats.ins);
+ printf("\t\t%" PRIu64 " deletes\n", stats.del);
+ printf("\t\t%" PRIu64 " assassinations\n", stats.kill);
+ printf("\tvestigial time-wait lookup_connect\n");
+ printf("\t\t%" PRIu64 " look\n", stats.look[0]);
+ printf("\t\t%" PRIu64 " hit\n", stats.hit[0]);
+ printf("\t\t%" PRIu64 " miss\n", stats.miss[0]);
+ printf("\t\t%" PRIu64 " probe\n", stats.probe[0]);
+ printf("\t\t%" PRIu64 " losing\n", stats.losing[0]);
+ printf("\t\t%" PRIu64 " max_chain\n", stats.max_chain[0]);
+ printf("\t\t%" PRIu64 " max_probe\n", stats.max_probe[0]);
+ printf("\t\t%" PRIu64 " max_loss\n", stats.max_loss[0]);
+ printf("\tvestigial time-wait lookup_port\n");
+ printf("\t\t%" PRIu64 " look\n", stats.look[1]);
+ printf("\t\t%" PRIu64 " hit\n", stats.hit[1]);
+ printf("\t\t%" PRIu64 " miss\n", stats.miss[1]);
+ printf("\t\t%" PRIu64 " probe\n", stats.probe[1]);
+ printf("\t\t%" PRIu64 " losing\n", stats.losing[1]);
+ printf("\t\t%" PRIu64 " max_chain\n", stats.max_chain[1]);
+ printf("\t\t%" PRIu64 " max_probe\n", stats.max_probe[1]);
+ printf("\t\t%" PRIu64 " max_loss\n", stats.max_loss[1]);
+}
+
+void
+show_vtw_v4(void (*print)(const vtw_t *))
+{
+ fatp_t *base, *lim;
+ fatp_t **hash, **port;
+ size_t n;
+ fatp_ctl_t fat_tcpv4;
+ vtw_ctl_t vtw_tcpv4[VTW_NCLASS];
+ int i;
+ int mem = 0;
+ void *p;
+
+ if ((p = lookup("fat_tcpv4")) == NULL)
+ return;
+ snarf(p, &fat_tcpv4, sizeof(fat_tcpv4));
+
+ if ((p = lookup("vtw_tcpv4")) == NULL)
+ return;
+ snarf(p, &vtw_tcpv4[0], sizeof(vtw_tcpv4));
+
+ mem += sizeof(fat_tcpv4);
+ mem += sizeof(vtw_tcpv4);
+
+ /* snarf/adjust vtw_ctl */
+ for (i = 0; i < VTW_NCLASS; ++i) {
+ vtw_v4_t *kbase, *klim;
+ vtw_v4_t *ubase;
+ ptrdiff_t delta;
+
+ kbase = vtw_tcpv4[i].base.v4;
+ klim = vtw_tcpv4[i].lim.v4;
+
+ if (!kbase | !klim)
+ continue;
+
+ n = (klim - kbase + 1);
+
+ if (!i) {
+ if ((ubase = malloc(n * sizeof(*kbase))) == NULL)
+ err(EXIT_FAILURE, NULL);
+ snarf(kbase, ubase, n * sizeof(*ubase));
+
+ mem += n * sizeof(*ubase);
+ } else {
+ ubase = vtw_tcpv4[0].base.v4;
+ }
+
+ delta = ubase - kbase;
+
+ vtw_tcpv4[i].base.v4 += delta;
+ vtw_tcpv4[i].lim.v4 += delta;
+ vtw_tcpv4[i].alloc.v4 += delta;
+ vtw_tcpv4[i].fat = &fat_tcpv4;
+
+ if (vtw_tcpv4[i].oldest.v4)
+ vtw_tcpv4[i].oldest.v4 += delta;
+ }
+
+ /* snarf/adjust fat_ctl */
+
+ base = fat_tcpv4.base;
+ lim = fat_tcpv4.lim;
+
+ if (!base | !lim)
+ goto end;
+
+ mem += (lim - base + 1) * sizeof(*base);
+
+ fat_tcpv4.base = malloc((lim - base + 1) * sizeof(*base));
+ if (fat_tcpv4.base == NULL)
+ err(EXIT_FAILURE, NULL);
+ fat_tcpv4.lim = fat_tcpv4.base + (lim - base);
+
+ snarf(base, fat_tcpv4.base, sizeof(*base) * (lim - base + 1));
+
+ fat_tcpv4.vtw = &vtw_tcpv4[0];
+ fat_tcpv4.free = fat_tcpv4.base + (fat_tcpv4.free - base);
+
+ n = fat_tcpv4.mask + 1;
+ hash = fat_tcpv4.hash;
+ port = fat_tcpv4.port;
+
+ fat_tcpv4.hash = malloc(n * sizeof(*hash));
+ fat_tcpv4.port = malloc(n * sizeof(*port));
+ if (fat_tcpv4.hash == NULL || fat_tcpv4.port == NULL)
+ err(EXIT_FAILURE, NULL);
+
+ snarf(hash, fat_tcpv4.hash, n * sizeof(*hash));
+ snarf(port, fat_tcpv4.port, n * sizeof(*port));
+
+end:
+ process_vtw(&vtw_tcpv4[0], print);
+
+#if 0
+ if (Vflag && vflag) {
+ printf("total memory for VTW in current config: %d bytes %f MB\n"
+ ,mem
+ ,mem / (1024.0 * 1024));
+ }
+#endif
+}
+
+void
+show_vtw_v6(void (*print)(const vtw_t *))
+{
+ fatp_t *base, *lim;
+ fatp_t **hash, **port;
+ size_t n;
+ fatp_ctl_t fat_tcpv6;
+ vtw_ctl_t vtw_tcpv6[VTW_NCLASS];
+ int i;
+ int mem = 0;
+ void *p;
+
+ if ((p = lookup("fat_tcpv6")) == NULL)
+ return;
+ snarf(p, &fat_tcpv6, sizeof(fat_tcpv6));
+ if ((p = lookup("vtw_tcpv6")) == NULL)
+ return;
+ snarf(p, &vtw_tcpv6[0], sizeof(vtw_tcpv6));
+
+ mem += sizeof(fat_tcpv6);
+ mem += sizeof(vtw_tcpv6);
+
+ for (i = 0; i < VTW_NCLASS; ++i) {
+ vtw_v6_t *kbase, *klim;
+ vtw_v6_t *ubase;
+ ptrdiff_t delta;
+
+ kbase = vtw_tcpv6[i].base.v6;
+ klim = vtw_tcpv6[i].lim.v6;
+
+ if (!kbase | !klim)
+ continue;
+
+ n = (klim - kbase + 1);
+
+ if (!i) {
+ if ((ubase = malloc(n * sizeof(*kbase))) == NULL)
+ err(EXIT_FAILURE, NULL);
+
+ snarf(kbase, ubase, n * sizeof(*ubase));
+
+ mem += n * sizeof(*ubase);
+ } else {
+ ubase = vtw_tcpv6[0].base.v6;
+ }
+
+ delta = ubase - kbase;
+
+ vtw_tcpv6[i].base.v6 += delta;
+ vtw_tcpv6[i].lim.v6 += delta;
+ vtw_tcpv6[i].alloc.v6 += delta;
+ vtw_tcpv6[i].fat = &fat_tcpv6;
+
+ if (vtw_tcpv6[i].oldest.v6)
+ vtw_tcpv6[i].oldest.v6 += delta;
+ }
+
+ base = fat_tcpv6.base;
+ lim = fat_tcpv6.lim;
+
+ if (!base | !lim)
+ goto end;
+
+ mem += (lim - base + 1) * sizeof(*base);
+
+ fat_tcpv6.base = malloc((lim - base + 1) * sizeof(*base));
+ if (fat_tcpv6.base == NULL)
+ err(EXIT_FAILURE, NULL);
+ fat_tcpv6.lim = fat_tcpv6.base + (lim - base);
+
+ snarf(base, fat_tcpv6.base, sizeof(*base) * (lim - base + 1));
+
+ fat_tcpv6.vtw = &vtw_tcpv6[0];
+ fat_tcpv6.free = fat_tcpv6.base + (fat_tcpv6.free - base);
+
+ n = fat_tcpv6.mask + 1;
+ hash = fat_tcpv6.hash;
+ port = fat_tcpv6.port;
+
+ fat_tcpv6.hash = malloc(n * sizeof(*hash));
+ fat_tcpv6.port = malloc(n * sizeof(*port));
+ if (fat_tcpv6.hash == NULL || fat_tcpv6.port == NULL)
+ err(EXIT_FAILURE, NULL);
+
+ snarf(hash, fat_tcpv6.hash, n * sizeof(*hash));
+ snarf(port, fat_tcpv6.port, n * sizeof(*port));
+
+end:
+
+ process_vtw(&vtw_tcpv6[0], print);
+#if 0
+ if (Vflag && vflag) {
+ printf("total memory for VTW in current config: %d bytes %f MB\n"
+ ,mem
+ ,mem / (1024.0 * 1024));
+ }
+#endif
+}
--- /dev/null
+#ifndef _NETSTAT_VTW_H
+#define _NETSTAT_VTW_H
+
+void show_vtw_stats(void);
+void show_vtw_v4(void (*)(const vtw_t *));
+void show_vtw_v6(void (*)(const vtw_t *));
+void timebase(struct timeval *);
+
+#endif /* _NETSTAT_VTW_H */