[rtems-libbsd commit] netstat: New command - Almost completely compiles

Joel Sherrill joel at rtems.org
Fri Sep 7 17:46:52 UTC 2012


Module:    rtems-libbsd
Branch:    master
Commit:    f1710b69d4ea496c3af76b46d7bec67b20dab1be
Changeset: http://git.rtems.org/rtems-libbsd/commit/?id=f1710b69d4ea496c3af76b46d7bec67b20dab1be

Author:    Joel Sherrill <joel.sherrill at oarcorp.com>
Date:      Fri Sep  7 12:50:18 2012 -0500

netstat: New command - Almost completely compiles

Currently disable in Makefile until all builds. Adding it so
others can assist in debugging issues.

---

 freebsd-userspace/commands/usr.bin/netstat/atalk.c |  293 +++++
 freebsd-userspace/commands/usr.bin/netstat/bpf.c   |  158 +++
 freebsd-userspace/commands/usr.bin/netstat/if.c    |  735 +++++++++++
 freebsd-userspace/commands/usr.bin/netstat/inet.c  | 1291 ++++++++++++++++++++
 freebsd-userspace/commands/usr.bin/netstat/inet6.c | 1159 ++++++++++++++++++
 freebsd-userspace/commands/usr.bin/netstat/ipsec.c |  481 ++++++++
 freebsd-userspace/commands/usr.bin/netstat/ipx.c   |  354 ++++++
 freebsd-userspace/commands/usr.bin/netstat/main.c  |  805 ++++++++++++
 freebsd-userspace/commands/usr.bin/netstat/mbuf.c  |  323 +++++
 .../commands/usr.bin/netstat/mroute.c              |  391 ++++++
 .../commands/usr.bin/netstat/mroute6.c             |  268 ++++
 .../commands/usr.bin/netstat/netgraph.c            |  196 +++
 .../commands/usr.bin/netstat/netstat.1             |  523 ++++++++
 .../commands/usr.bin/netstat/netstat.h             |  167 +++
 freebsd-userspace/commands/usr.bin/netstat/pfkey.c |  184 +++
 freebsd-userspace/commands/usr.bin/netstat/route.c | 1167 ++++++++++++++++++
 freebsd-userspace/commands/usr.bin/netstat/sctp.c  |  703 +++++++++++
 freebsd-userspace/commands/usr.bin/netstat/unix.c  |  294 +++++
 18 files changed, 9492 insertions(+), 0 deletions(-)

diff --git a/freebsd-userspace/commands/usr.bin/netstat/atalk.c b/freebsd-userspace/commands/usr.bin/netstat/atalk.c
new file mode 100644
index 0000000..2c7e7a1
--- /dev/null
+++ b/freebsd-userspace/commands/usr.bin/netstat/atalk.c
@@ -0,0 +1,293 @@
+/*-
+ * 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. 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.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)atalk.c	1.1 (Whistle) 6/6/96";
+#endif /* not lint */
+#endif
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#ifdef __rtems__
+#include <freebsd/sys/protosw.h>
+#else
+#include <sys/protosw.h>
+#endif
+
+#include <arpa/inet.h>
+#include <net/route.h>
+
+#include <netatalk/at.h>
+#include <netatalk/ddp_var.h>
+
+#include <errno.h>
+#include <nlist.h>
+#include <netdb.h>
+#include <stdint.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(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("*");
+		}
+	}
+	sprintf(mybuf,"%hu",ntohs(sat->sat_addr.s_net));
+	return mybuf;
+}
+
+static const char *
+at_pr_host(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("*");
+		}
+	}
+	sprintf(mybuf,"%d",(unsigned int)sat->sat_addr.s_node);
+	return mybuf;
+}
+
+static const char *
+at_pr_port(struct sockaddr_at *sat)
+{
+static	char mybuf[50];
+	struct servent *serv;
+
+	switch(sat->sat_port) {
+	case ATADDR_ANYPORT:
+		return("*");
+	case 0xff:
+		return "????";
+	default:
+		if (numeric_port) {
+			(void)snprintf(mybuf, sizeof(mybuf), "%d",
+			    (unsigned int)sat->sat_port);
+		} else {
+			serv = getservbyport(sat->sat_port, "ddp");
+			if (serv == NULL)
+				(void)snprintf(mybuf, sizeof(mybuf), "%d",
+				    (unsigned int) sat->sat_port);
+			else
+				(void) snprintf(mybuf, sizeof(mybuf), "%s",
+				    serv->s_name);
+		}
+	}
+	return mybuf;
+}
+
+static char *
+at_pr_range(struct sockaddr_at *sat)
+{
+static	char mybuf[50];
+
+	if(sat->sat_range.r_netrange.nr_firstnet
+           != sat->sat_range.r_netrange.nr_lastnet) {
+		sprintf(mybuf,"%d-%d",
+			ntohs(sat->sat_range.r_netrange.nr_firstnet),
+			ntohs(sat->sat_range.r_netrange.nr_lastnet));
+	} else {
+		sprintf(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 */
+char *
+atalk_print(struct sockaddr *sa, int what)
+{
+	struct sockaddr_at *sat = (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:
+		sprintf(mybuf,"%s",at_pr_net(sat, numeric));
+		break;
+	case 2:
+		sprintf(mybuf,"%s",at_pr_host(sat, numeric));
+		break;
+	case 3:
+		sprintf(mybuf,"%s.%s",
+				at_pr_net(sat, numeric),
+				at_pr_host(sat, numeric));
+		break;
+	case 0x10:
+		sprintf(mybuf,"%s", at_pr_range(sat));
+	}
+	if (what & 4) {
+		sprintf(mybuf+strlen(mybuf),".%s",at_pr_port(sat));
+	}
+	return mybuf;
+}
+
+char *
+atalk_print2(struct sockaddr *sa, struct sockaddr *mask, int what)
+{
+  int n;
+  static char buf[100];
+  struct sockaddr_at *sat1, *sat2;
+  struct sockaddr_at thesockaddr;
+  struct sockaddr *sa2;
+
+  sat1 = (struct sockaddr_at *)sa;
+  sat2 = (struct sockaddr_at *)mask;
+  sa2 = (struct sockaddr *)&thesockaddr;
+
+  thesockaddr.sat_addr.s_net = sat1->sat_addr.s_net & sat2->sat_addr.s_net;
+  snprintf(buf, sizeof(buf), "%s", atalk_print(sa2, 1 |(what & 8)));
+  if(sat2->sat_addr.s_net != 0xFFFF) {
+    thesockaddr.sat_addr.s_net = sat1->sat_addr.s_net | ~sat2->sat_addr.s_net;
+    n = strlen(buf);
+    snprintf(buf + n, sizeof(buf) - n, "-%s", atalk_print(sa2, 1 |(what & 8)));
+  }
+  if(what & 2) {
+    n = strlen(buf);
+    snprintf(buf + n, sizeof(buf) - n, ".%s", atalk_print(sa, what & (~1)));
+  }
+  return(buf);
+}
+
+void
+atalkprotopr(u_long off __unused, const char *name, int af1 __unused,
+    int proto __unused)
+{
+	struct ddpcb *this, *next;
+
+	if (off == 0)
+		return;
+	kread(off, (char *)&this, sizeof (struct ddpcb *));
+	for ( ; this != NULL; this = next) {
+		kread((u_long)this, (char *)&ddpcb, sizeof (ddpcb));
+		next = ddpcb.ddp_next;
+#if 0
+		if (!aflag && atalk_nullhost(ddpcb.ddp_lsat) ) {
+			continue;
+		}
+#endif
+		kread((u_long)ddpcb.ddp_socket, (char *)&sockb, sizeof (sockb));
+		if (first) {
+			printf("Active ATALK connections");
+			if (aflag)
+				printf(" (including servers)");
+			putchar('\n');
+			if (Aflag)
+				printf("%-8.8s ", "PCB");
+			printf(Aflag ?
+				"%-5.5s %-6.6s %-6.6s  %-18.18s %-18.18s %s\n" :
+				"%-5.5s %-6.6s %-6.6s  %-22.22s %-22.22s %s\n",
+				"Proto", "Recv-Q", "Send-Q",
+				"Local Address", "Foreign Address", "(state)");
+			first = 0;
+		}
+		if (Aflag)
+			printf("%8lx ", (u_long) this);
+		printf("%-5.5s %6u %6u ", name, sockb.so_rcv.sb_cc,
+			sockb.so_snd.sb_cc);
+		printf(Aflag?" %-18.18s":" %-22.22s", atalk_print(
+					(struct sockaddr *)&ddpcb.ddp_lsat,7));
+		printf(Aflag?" %-18.18s":" %-22.22s", atalk_print(
+					(struct sockaddr *)&ddpcb.ddp_fsat,7));
+		putchar('\n');
+	}
+}
+
+#define	ANY(x,y,z) if (x || sflag <= 1) \
+	printf("\t%lu %s%s%s\n",x,y,plural(x),z)
+
+/*
+ * Dump DDP statistics structure.
+ */
+void
+ddp_stats(u_long off __unused, const char *name, int af1 __unused,
+    int proto __unused)
+{
+	struct ddpstat ddpstat;
+
+	if (off == 0)
+		return;
+	kread(off, (char *)&ddpstat, sizeof (ddpstat));
+	printf("%s:\n", name);
+	ANY(ddpstat.ddps_short, "packet", " with short headers ");
+	ANY(ddpstat.ddps_long, "packet", " with long headers ");
+	ANY(ddpstat.ddps_nosum, "packet", " with no checksum ");
+	ANY(ddpstat.ddps_tooshort, "packet", " too short ");
+	ANY(ddpstat.ddps_badsum, "packet", " with bad checksum ");
+	ANY(ddpstat.ddps_toosmall, "packet", " with not enough data ");
+	ANY(ddpstat.ddps_forward, "packet", " forwarded ");
+	ANY(ddpstat.ddps_encap, "packet", " encapsulated ");
+	ANY(ddpstat.ddps_cantforward, "packet", " rcvd for unreachable dest ");
+	ANY(ddpstat.ddps_nosockspace, "packet", " dropped due to no socket space ");
+}
diff --git a/freebsd-userspace/commands/usr.bin/netstat/bpf.c b/freebsd-userspace/commands/usr.bin/netstat/bpf.c
new file mode 100644
index 0000000..3e3053d
--- /dev/null
+++ b/freebsd-userspace/commands/usr.bin/netstat/bpf.c
@@ -0,0 +1,158 @@
+/*-
+ * Copyright (c) 2005 Christian S.J. Peron
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#ifdef __rtems__
+#include <freebsd/sys/protosw.h>
+#else
+#include <sys/protosw.h>
+#endif
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/sysctl.h>
+#include <sys/param.h>
+#ifndef __rtems__
+#include <sys/user.h>
+#endif
+
+#include <net/if.h>
+#ifdef __rtems__
+#include <freebsd/net/if_var.h>
+#include <freebsd/net/bpf.h>
+#include <freebsd/net/bpfdesc.h>
+#else
+#include <net/if_var.h>
+#include <net/bpf.h>
+#include <net/bpfdesc.h>
+#endif
+#include <arpa/inet.h>
+
+#include <err.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "netstat.h"
+
+/* print bpf stats */
+
+static char *
+bpf_pidname(pid_t pid)
+{
+#ifdef __rtems__
+	return "rtems";
+#else
+	struct kinfo_proc newkp;
+	int error, mib[4];
+	size_t size;
+
+	mib[0] = CTL_KERN;
+	mib[1] = KERN_PROC;
+	mib[2] = KERN_PROC_PID;
+	mib[3] = pid;
+	size = sizeof(newkp);
+	error = sysctl(mib, 4, &newkp, &size, NULL, 0);
+	if (error < 0) {
+		warn("kern.proc.pid failed");
+		return (strdup("??????"));
+	}
+	return (strdup(newkp.ki_comm));
+#endif
+}
+
+static void
+bpf_flags(struct xbpf_d *bd, char *flagbuf)
+{
+
+	*flagbuf++ = bd->bd_promisc ? 'p' : '-';
+	*flagbuf++ = bd->bd_immediate ? 'i' : '-';
+	*flagbuf++ = bd->bd_hdrcmplt ? '-' : 'f';
+	*flagbuf++ = (bd->bd_direction == BPF_D_IN) ? '-' :
+	    ((bd->bd_direction == BPF_D_OUT) ? 'o' : 's');
+	*flagbuf++ = bd->bd_feedback ? 'b' : '-';
+	*flagbuf++ = bd->bd_async ? 'a' : '-';
+	*flagbuf++ = bd->bd_locked ? 'l' : '-';
+	*flagbuf++ = '\0';
+}
+
+void
+bpf_stats(char *ifname)
+{
+	struct xbpf_d *d, *bd, zerostat;
+	char *pname, flagbuf[12];
+	size_t size;
+
+	if (zflag) {
+		bzero(&zerostat, sizeof(zerostat));
+		if (sysctlbyname("net.bpf.stats", NULL, NULL,
+		    &zerostat, sizeof(zerostat)) < 0)
+			warn("failed to zero bpf counters");
+		return;
+	}
+	if (sysctlbyname("net.bpf.stats", NULL, &size,
+	    NULL, 0) < 0) {
+		warn("net.bpf.stats");
+		return;
+	}
+	if (size == 0)
+		return;
+	bd = malloc(size);
+	if (bd == NULL) {
+		warn("malloc failed");
+		return;
+	}
+	if (sysctlbyname("net.bpf.stats", bd, &size,
+	    NULL, 0) < 0) {
+		warn("net.bpf.stats");
+		free(bd);
+		return;
+	}
+	(void) printf("%5s %6s %7s %9s %9s %9s %5s %5s %s\n",
+	    "Pid", "Netif", "Flags", "Recv", "Drop", "Match", "Sblen",
+	    "Hblen", "Command");
+	for (d = &bd[0]; d < &bd[size / sizeof(*d)]; d++) {
+		if (d->bd_structsize != sizeof(*d)) {
+			warnx("bpf_stats_extended: version mismatch");
+			return;
+		}
+		if (ifname && strcmp(ifname, d->bd_ifname) != 0)
+			continue;
+		bpf_flags(d, flagbuf);
+		pname = bpf_pidname(d->bd_pid);
+		(void) printf("%5d %6s %7s %9ju %9ju %9ju %5d %5d %s\n",
+		    d->bd_pid, d->bd_ifname, flagbuf,
+		    d->bd_rcount, d->bd_dcount, d->bd_fcount,
+		    d->bd_slen, d->bd_hlen, pname);
+		free(pname);
+	}
+	free(bd);
+}
diff --git a/freebsd-userspace/commands/usr.bin/netstat/if.c b/freebsd-userspace/commands/usr.bin/netstat/if.c
new file mode 100644
index 0000000..d91db8c
--- /dev/null
+++ b/freebsd-userspace/commands/usr.bin/netstat/if.c
@@ -0,0 +1,735 @@
+/*-
+ * 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. 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.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)if.c	8.3 (Berkeley) 4/28/95";
+#endif /* not lint */
+#endif
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#ifdef __rtems__
+#include <freebsd/sys/protosw.h>
+#else
+#include <sys/protosw.h>
+#endif
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+
+#include <net/if.h>
+#ifdef __rtems__
+#include <freebsd/net/if_var.h>
+#else
+#include <net/if_var.h>
+#endif
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <net/ethernet.h>
+#ifdef __rtems__
+#include <freebsd/net/pfvar.h>
+#include <freebsd/net/if_pfsync.h>
+#include <netinet/in.h>
+#include <freebsd/netinet/in_var.h>
+/* IPX not on RTEMS */
+/* #include <netipx/ipx.h> */
+/* #include <netipx/ipx_if.h> */
+#else
+#include <net/pfvar.h>
+#include <net/if_pfsync.h>
+#include <netinet/in.h>
+#include <netinet/in_var.h>
+#include <netipx/ipx.h>
+#include <netipx/ipx_if.h>
+#endif
+#include <arpa/inet.h>
+
+#include <err.h>
+#include <errno.h>
+#ifdef __rtems__
+/* apparently libutil.h is not needed */
+#else
+#include <libutil.h>
+#endif
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "netstat.h"
+
+#define	YES	1
+#define	NO	0
+
+static void sidewaysintpr(int, u_long);
+static void catchalarm(int);
+
+#ifdef INET6
+static char ntop_buf[INET6_ADDRSTRLEN];		/* for inet_ntop() */
+#endif
+
+/*
+ * Dump pfsync statistics structure.
+ */
+void
+pfsync_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+	struct pfsyncstats pfsyncstat, zerostat;
+	size_t len = sizeof(struct pfsyncstats);
+
+	if (live) {
+		if (zflag)
+			memset(&zerostat, 0, len);
+		if (sysctlbyname("net.inet.pfsync.stats", &pfsyncstat, &len,
+		    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+			if (errno != ENOENT)
+				warn("sysctl: net.inet.pfsync.stats");
+			return;
+		}
+	} else
+		kread(off, &pfsyncstat, len);
+
+	printf("%s:\n", name);
+
+#define	p(f, m) if (pfsyncstat.f || sflag <= 1) \
+	printf(m, (uintmax_t)pfsyncstat.f, plural(pfsyncstat.f))
+#define	p2(f, m) if (pfsyncstat.f || sflag <= 1) \
+	printf(m, (uintmax_t)pfsyncstat.f)
+
+	p(pfsyncs_ipackets, "\t%ju packet%s received (IPv4)\n");
+	p(pfsyncs_ipackets6, "\t%ju packet%s received (IPv6)\n");
+	p(pfsyncs_badif, "\t\t%ju packet%s discarded for bad interface\n");
+	p(pfsyncs_badttl, "\t\t%ju packet%s discarded for bad ttl\n");
+	p(pfsyncs_hdrops, "\t\t%ju packet%s shorter than header\n");
+	p(pfsyncs_badver, "\t\t%ju packet%s discarded for bad version\n");
+	p(pfsyncs_badauth, "\t\t%ju packet%s discarded for bad HMAC\n");
+	p(pfsyncs_badact,"\t\t%ju packet%s discarded for bad action\n");
+	p(pfsyncs_badlen, "\t\t%ju packet%s discarded for short packet\n");
+	p(pfsyncs_badval, "\t\t%ju state%s discarded for bad values\n");
+	p(pfsyncs_stale, "\t\t%ju stale state%s\n");
+	p(pfsyncs_badstate, "\t\t%ju failed state lookup/insert%s\n");
+	p(pfsyncs_opackets, "\t%ju packet%s sent (IPv4)\n");
+	p(pfsyncs_opackets6, "\t%ju packet%s sent (IPv6)\n");
+	p2(pfsyncs_onomem, "\t\t%ju send failed due to mbuf memory error\n");
+	p2(pfsyncs_oerrors, "\t\t%ju send error\n");
+#undef p
+#undef p2
+}
+
+/*
+ * Display a formatted value, or a '-' in the same space.
+ */
+static void
+show_stat(const char *fmt, int width, u_long value, short showvalue)
+{
+	const char *lsep, *rsep;
+	char newfmt[32];
+
+	lsep = "";
+	if (strncmp(fmt, "LS", 2) == 0) {
+		lsep = " ";
+		fmt += 2;
+	}
+	rsep = " ";
+	if (strncmp(fmt, "NRS", 3) == 0) {
+		rsep = "";
+		fmt += 3;
+	}
+	if (showvalue == 0) {
+		/* Print just dash. */
+		sprintf(newfmt, "%s%%%ds%s", lsep, width, rsep);
+		printf(newfmt, "-");
+		return;
+	}
+
+	if (hflag) {
+		char buf[5];
+
+		/* Format in human readable form. */
+		humanize_number(buf, sizeof(buf), (int64_t)value, "",
+		    HN_AUTOSCALE, HN_NOSPACE | HN_DECIMAL);
+		sprintf(newfmt, "%s%%%ds%s", lsep, width, rsep);
+		printf(newfmt, buf);
+	} else {
+		/* Construct the format string. */
+		sprintf(newfmt, "%s%%%d%s%s", lsep, width, fmt, rsep);
+		printf(newfmt, value);
+	}
+}
+
+/*
+ * Print a description of the network interfaces.
+ */
+void
+intpr(int interval1, u_long ifnetaddr, void (*pfunc)(char *))
+{
+	struct ifnet ifnet;
+	struct ifnethead ifnethead;
+	union {
+		struct ifaddr ifa;
+		struct in_ifaddr in;
+#ifdef INET6
+		struct in6_ifaddr in6;
+#endif
+		struct ipx_ifaddr ipx;
+	} ifaddr;
+	u_long ifaddraddr;
+	u_long ifaddrfound;
+	u_long ifnetfound;
+	u_long opackets;
+	u_long ipackets;
+	u_long obytes;
+	u_long ibytes;
+	u_long omcasts;
+	u_long imcasts;
+	u_long oerrors;
+	u_long ierrors;
+	u_long idrops;
+	u_long collisions;
+	short timer;
+	int drops;
+	struct sockaddr *sa = NULL;
+	char name[IFNAMSIZ];
+	short network_layer;
+	short link_layer;
+
+	if (ifnetaddr == 0) {
+		printf("ifnet: symbol not defined\n");
+		return;
+	}
+	if (interval1) {
+		sidewaysintpr(interval1, ifnetaddr);
+		return;
+	}
+	if (kread(ifnetaddr, (char *)&ifnethead, sizeof ifnethead) != 0)
+		return;
+	ifnetaddr = (u_long)TAILQ_FIRST(&ifnethead);
+	if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet) != 0)
+		return;
+
+	if (!pfunc) {
+		if (Wflag)
+			printf("%-7.7s", "Name");
+		else
+			printf("%-5.5s", "Name");
+		printf(" %5.5s %-13.13s %-17.17s %8.8s %5.5s %5.5s",
+		    "Mtu", "Network", "Address", "Ipkts", "Ierrs", "Idrop");
+		if (bflag)
+			printf(" %10.10s","Ibytes");
+		printf(" %8.8s %5.5s", "Opkts", "Oerrs");
+		if (bflag)
+			printf(" %10.10s","Obytes");
+		printf(" %5s", "Coll");
+		if (tflag)
+			printf(" %s", "Time");
+		if (dflag)
+			printf(" %s", "Drop");
+		putchar('\n');
+	}
+	ifaddraddr = 0;
+	while (ifnetaddr || ifaddraddr) {
+		struct sockaddr_in *sockin;
+#ifdef INET6
+		struct sockaddr_in6 *sockin6;
+#endif
+		char *cp;
+		int n, m;
+
+		network_layer = 0;
+		link_layer = 0;
+
+		if (ifaddraddr == 0) {
+			ifnetfound = ifnetaddr;
+			if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet) != 0)
+				return;
+			strlcpy(name, ifnet.if_xname, sizeof(name));
+			ifnetaddr = (u_long)TAILQ_NEXT(&ifnet, if_link);
+			if (interface != 0 && strcmp(name, interface) != 0)
+				continue;
+			cp = index(name, '\0');
+
+			if (pfunc) {
+				(*pfunc)(name);
+				continue;
+			}
+
+			if ((ifnet.if_flags&IFF_UP) == 0)
+				*cp++ = '*';
+			*cp = '\0';
+			ifaddraddr = (u_long)TAILQ_FIRST(&ifnet.if_addrhead);
+		}
+		ifaddrfound = ifaddraddr;
+
+		/*
+		 * Get the interface stats.  These may get
+		 * overriden below on a per-interface basis.
+		 */
+		opackets = ifnet.if_opackets;
+		ipackets = ifnet.if_ipackets;
+		obytes = ifnet.if_obytes;
+		ibytes = ifnet.if_ibytes;
+		omcasts = ifnet.if_omcasts;
+		imcasts = ifnet.if_imcasts;
+		oerrors = ifnet.if_oerrors;
+		ierrors = ifnet.if_ierrors;
+		idrops = ifnet.if_iqdrops;
+		collisions = ifnet.if_collisions;
+		timer = ifnet.if_timer;
+		drops = ifnet.if_snd.ifq_drops;
+
+		if (ifaddraddr == 0) {
+			if (Wflag)
+				printf("%-7.7s", name);
+			else
+				printf("%-5.5s", name);
+			printf(" %5lu ", ifnet.if_mtu);
+			printf("%-13.13s ", "none");
+			printf("%-17.17s ", "none");
+		} else {
+			if (kread(ifaddraddr, (char *)&ifaddr, sizeof ifaddr)
+			    != 0) {
+				ifaddraddr = 0;
+				continue;
+			}
+#define	CP(x) ((char *)(x))
+			cp = (CP(ifaddr.ifa.ifa_addr) - CP(ifaddraddr)) +
+				CP(&ifaddr);
+			sa = (struct sockaddr *)cp;
+			if (af != AF_UNSPEC && sa->sa_family != af) {
+				ifaddraddr =
+				    (u_long)TAILQ_NEXT(&ifaddr.ifa, ifa_link);
+				continue;
+			}
+			if (Wflag)
+				printf("%-7.7s", name);
+			else
+				printf("%-5.5s", name);
+			printf(" %5lu ", ifnet.if_mtu);
+			switch (sa->sa_family) {
+			case AF_UNSPEC:
+				printf("%-13.13s ", "none");
+				printf("%-15.15s ", "none");
+				break;
+			case AF_INET:
+				sockin = (struct sockaddr_in *)sa;
+#ifdef notdef
+				/* can't use inet_makeaddr because kernel
+				 * keeps nets unshifted.
+				 */
+				in = inet_makeaddr(ifaddr.in.ia_subnet,
+					INADDR_ANY);
+				printf("%-13.13s ", netname(in.s_addr,
+				    ifaddr.in.ia_subnetmask));
+#else
+				printf("%-13.13s ",
+				    netname(htonl(ifaddr.in.ia_subnet),
+				    ifaddr.in.ia_subnetmask));
+#endif
+				printf("%-17.17s ",
+				    routename(sockin->sin_addr.s_addr));
+
+				network_layer = 1;
+				break;
+#ifdef INET6
+			case AF_INET6:
+				sockin6 = (struct sockaddr_in6 *)sa;
+				printf("%-13.13s ",
+				       netname6(&ifaddr.in6.ia_addr,
+						&ifaddr.in6.ia_prefixmask.sin6_addr));
+				printf("%-17.17s ",
+				    inet_ntop(AF_INET6,
+					&sockin6->sin6_addr,
+					ntop_buf, sizeof(ntop_buf)));
+
+				network_layer = 1;
+				break;
+#endif /*INET6*/
+			case AF_IPX:
+				{
+				struct sockaddr_ipx *sipx =
+					(struct sockaddr_ipx *)sa;
+				u_long net;
+				char netnum[10];
+
+				*(union ipx_net *) &net = sipx->sipx_addr.x_net;
+				sprintf(netnum, "%lx", (u_long)ntohl(net));
+				printf("ipx:%-8s  ", netnum);
+/*				printf("ipx:%-8s ", netname(net, 0L)); */
+				printf("%-17s ",
+				    ipx_phost((struct sockaddr *)sipx));
+				}
+
+				network_layer = 1;
+				break;
+
+			case AF_APPLETALK:
+				printf("atalk:%-12.12s ",atalk_print(sa,0x10) );
+				printf("%-11.11s  ",atalk_print(sa,0x0b) );
+				break;
+			case AF_LINK:
+				{
+				struct sockaddr_dl *sdl =
+					(struct sockaddr_dl *)sa;
+				char linknum[10];
+				cp = (char *)LLADDR(sdl);
+				n = sdl->sdl_alen;
+				sprintf(linknum, "<Link#%d>", sdl->sdl_index);
+				m = printf("%-13.13s ", linknum);
+				}
+				goto hexprint;
+			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;
+			hexprint:
+				while (--n >= 0)
+					m += printf("%02x%c", *cp++ & 0xff,
+						    n > 0 ? ':' : ' ');
+				m = 32 - m;
+				while (m-- > 0)
+					putchar(' ');
+
+				link_layer = 1;
+				break;
+			}
+
+			/*
+			 * Fixup the statistics for interfaces that
+			 * update stats for their network addresses
+			 */
+			if (network_layer) {
+				opackets = ifaddr.in.ia_ifa.if_opackets;
+				ipackets = ifaddr.in.ia_ifa.if_ipackets;
+				obytes = ifaddr.in.ia_ifa.if_obytes;
+				ibytes = ifaddr.in.ia_ifa.if_ibytes;
+			}
+
+			ifaddraddr = (u_long)TAILQ_NEXT(&ifaddr.ifa, ifa_link);
+		}
+
+		show_stat("lu", 8, ipackets, link_layer|network_layer);
+		show_stat("lu", 5, ierrors, link_layer);
+		show_stat("lu", 5, idrops, link_layer);
+		if (bflag)
+			show_stat("lu", 10, ibytes, link_layer|network_layer);
+
+		show_stat("lu", 8, opackets, link_layer|network_layer);
+		show_stat("lu", 5, oerrors, link_layer);
+		if (bflag)
+			show_stat("lu", 10, obytes, link_layer|network_layer);
+
+		show_stat("NRSlu", 5, collisions, link_layer);
+		if (tflag)
+			show_stat("LSd", 4, timer, link_layer);
+		if (dflag)
+			show_stat("LSd", 4, drops, link_layer);
+		putchar('\n');
+
+		if (aflag && ifaddrfound) {
+			/*
+			 * Print family's multicast addresses
+			 */
+			struct ifmultiaddr *multiaddr;
+			struct ifmultiaddr ifma;
+			union {
+				struct sockaddr sa;
+				struct sockaddr_in in;
+#ifdef INET6
+				struct sockaddr_in6 in6;
+#endif /* INET6 */
+				struct sockaddr_dl dl;
+			} msa;
+			const char *fmt;
+
+			TAILQ_FOREACH(multiaddr, &ifnet.if_multiaddrs, ifma_link) {
+				if (kread((u_long)multiaddr, (char *)&ifma,
+					  sizeof ifma) != 0)
+					break;
+				multiaddr = &ifma;
+				if (kread((u_long)ifma.ifma_addr, (char *)&msa,
+					  sizeof msa) != 0)
+					break;
+				if (msa.sa.sa_family != sa->sa_family)
+					continue;
+
+				fmt = 0;
+				switch (msa.sa.sa_family) {
+				case AF_INET:
+					fmt = routename(msa.in.sin_addr.s_addr);
+					break;
+#ifdef INET6
+				case AF_INET6:
+					printf("%*s %-19.19s(refs: %d)\n",
+					       Wflag ? 27 : 25, "",
+					       inet_ntop(AF_INET6,
+							 &msa.in6.sin6_addr,
+							 ntop_buf,
+							 sizeof(ntop_buf)),
+					       ifma.ifma_refcount);
+					break;
+#endif /* INET6 */
+				case AF_LINK:
+					switch (msa.dl.sdl_type) {
+					case IFT_ETHER:
+					case IFT_FDDI:
+						fmt = ether_ntoa(
+							(struct ether_addr *)
+							LLADDR(&msa.dl));
+						break;
+					}
+					break;
+				}
+				if (fmt) {
+					printf("%*s %-17.17s",
+					    Wflag ? 27 : 25, "", fmt);
+					if (msa.sa.sa_family == AF_LINK) {
+						printf(" %8lu", imcasts);
+						printf("%*s",
+						    bflag ? 17 : 6, "");
+						printf(" %8lu", omcasts);
+					}
+					putchar('\n');
+				}
+			}
+		}
+	}
+}
+
+struct	iftot {
+	SLIST_ENTRY(iftot) chain;
+	char	ift_name[IFNAMSIZ];	/* interface name */
+	u_long	ift_ip;			/* input packets */
+	u_long	ift_ie;			/* input errors */
+	u_long	ift_id;			/* input drops */
+	u_long	ift_op;			/* output packets */
+	u_long	ift_oe;			/* output errors */
+	u_long	ift_co;			/* collisions */
+	u_int	ift_dr;			/* drops */
+	u_long	ift_ib;			/* input bytes */
+	u_long	ift_ob;			/* output bytes */
+};
+
+u_char	signalled;			/* set if alarm goes off "early" */
+
+/*
+ * Print a running summary of interface statistics.
+ * Repeat display every interval1 seconds, showing statistics
+ * collected over that interval.  Assumes that interval1 is non-zero.
+ * First line printed at top of screen is always cumulative.
+ * XXX - should be rewritten to use ifmib(4).
+ */
+static void
+sidewaysintpr(int interval1, u_long off)
+{
+	struct ifnet ifnet;
+	u_long firstifnet;
+	struct ifnethead ifnethead;
+	struct itimerval interval_it;
+	struct iftot *iftot, *ip, *ipn, *total, *sum, *interesting;
+	int line;
+	int oldmask, first;
+	u_long interesting_off;
+
+	if (kread(off, (char *)&ifnethead, sizeof ifnethead) != 0)
+		return;
+	firstifnet = (u_long)TAILQ_FIRST(&ifnethead);
+
+	if ((iftot = malloc(sizeof(struct iftot))) == NULL) {
+		printf("malloc failed\n");
+		exit(1);
+	}
+	memset(iftot, 0, sizeof(struct iftot));
+
+	interesting = NULL;
+	interesting_off = 0;
+	for (off = firstifnet, ip = iftot; off;) {
+		char name[IFNAMSIZ];
+
+		if (kread(off, (char *)&ifnet, sizeof ifnet) != 0)
+			break;
+		strlcpy(name, ifnet.if_xname, sizeof(name));
+		if (interface && strcmp(name, interface) == 0) {
+			interesting = ip;
+			interesting_off = off;
+		}
+		snprintf(ip->ift_name, sizeof(ip->ift_name), "(%s)", name);;
+		if ((ipn = malloc(sizeof(struct iftot))) == NULL) {
+			printf("malloc failed\n");
+			exit(1);
+		}
+		memset(ipn, 0, sizeof(struct iftot));
+		SLIST_NEXT(ip, chain) = ipn;
+		ip = ipn;
+		off = (u_long)TAILQ_NEXT(&ifnet, if_link);
+	}
+	if (interface && interesting == NULL)
+		errx(1, "%s: unknown interface", interface);
+	if ((total = malloc(sizeof(struct iftot))) == NULL) {
+		printf("malloc failed\n");
+		exit(1);
+	}
+	memset(total, 0, sizeof(struct iftot));
+	if ((sum = malloc(sizeof(struct iftot))) == NULL) {
+		printf("malloc failed\n");
+		exit(1);
+	}
+	memset(sum, 0, sizeof(struct iftot));
+
+	(void)signal(SIGALRM, catchalarm);
+	signalled = NO;
+	interval_it.it_interval.tv_sec = interval1;
+	interval_it.it_interval.tv_usec = 0;
+	interval_it.it_value = interval_it.it_interval;
+	setitimer(ITIMER_REAL, &interval_it, NULL);
+	first = 1;
+banner:
+	printf("%17s %14s %16s", "input",
+	    interesting ? interesting->ift_name : "(Total)", "output");
+	putchar('\n');
+	printf("%10s %5s %5s %10s %10s %5s %10s %5s",
+	    "packets", "errs", "idrops", "bytes", "packets", "errs", "bytes",
+	    "colls");
+	if (dflag)
+		printf(" %5.5s", "drops");
+	putchar('\n');
+	fflush(stdout);
+	line = 0;
+loop:
+	if (interesting != NULL) {
+		ip = interesting;
+		if (kread(interesting_off, (char *)&ifnet, sizeof ifnet) != 0) {
+			printf("???\n");
+			exit(1);
+		};
+		if (!first) {
+			show_stat("lu", 10, ifnet.if_ipackets - ip->ift_ip, 1);
+			show_stat("lu", 5, ifnet.if_ierrors - ip->ift_ie, 1);
+			show_stat("lu", 5, ifnet.if_iqdrops - ip->ift_id, 1);
+			show_stat("lu", 10, ifnet.if_ibytes - ip->ift_ib, 1);
+			show_stat("lu", 10, ifnet.if_opackets - ip->ift_op, 1);
+			show_stat("lu", 5, ifnet.if_oerrors - ip->ift_oe, 1);
+			show_stat("lu", 10, ifnet.if_obytes - ip->ift_ob, 1);
+			show_stat("NRSlu", 5,
+			    ifnet.if_collisions - ip->ift_co, 1);
+			if (dflag)
+				show_stat("LSu", 5,
+				    ifnet.if_snd.ifq_drops - ip->ift_dr, 1);
+		}
+		ip->ift_ip = ifnet.if_ipackets;
+		ip->ift_ie = ifnet.if_ierrors;
+		ip->ift_id = ifnet.if_iqdrops;
+		ip->ift_ib = ifnet.if_ibytes;
+		ip->ift_op = ifnet.if_opackets;
+		ip->ift_oe = ifnet.if_oerrors;
+		ip->ift_ob = ifnet.if_obytes;
+		ip->ift_co = ifnet.if_collisions;
+		ip->ift_dr = ifnet.if_snd.ifq_drops;
+	} else {
+		sum->ift_ip = 0;
+		sum->ift_ie = 0;
+		sum->ift_id = 0;
+		sum->ift_ib = 0;
+		sum->ift_op = 0;
+		sum->ift_oe = 0;
+		sum->ift_ob = 0;
+		sum->ift_co = 0;
+		sum->ift_dr = 0;
+		for (off = firstifnet, ip = iftot;
+		     off && SLIST_NEXT(ip, chain) != NULL;
+		     ip = SLIST_NEXT(ip, chain)) {
+			if (kread(off, (char *)&ifnet, sizeof ifnet) != 0) {
+				off = 0;
+				continue;
+			}
+			sum->ift_ip += ifnet.if_ipackets;
+			sum->ift_ie += ifnet.if_ierrors;
+			sum->ift_id += ifnet.if_iqdrops;
+			sum->ift_ib += ifnet.if_ibytes;
+			sum->ift_op += ifnet.if_opackets;
+			sum->ift_oe += ifnet.if_oerrors;
+			sum->ift_ob += ifnet.if_obytes;
+			sum->ift_co += ifnet.if_collisions;
+			sum->ift_dr += ifnet.if_snd.ifq_drops;
+			off = (u_long)TAILQ_NEXT(&ifnet, if_link);
+		}
+		if (!first) {
+			show_stat("lu", 10, sum->ift_ip - total->ift_ip, 1);
+			show_stat("lu", 5, sum->ift_ie - total->ift_ie, 1);
+			show_stat("lu", 5, sum->ift_id - total->ift_id, 1);
+			show_stat("lu", 10, sum->ift_ib - total->ift_ib, 1);
+			show_stat("lu", 10, sum->ift_op - total->ift_op, 1);
+			show_stat("lu", 5, sum->ift_oe - total->ift_oe, 1);
+			show_stat("lu", 10, sum->ift_ob - total->ift_ob, 1);
+			show_stat("NRSlu", 5, sum->ift_co - total->ift_co, 1);
+			if (dflag)
+				show_stat("LSu", 5,
+				    sum->ift_dr - total->ift_dr, 1);
+		}
+		*total = *sum;
+	}
+	if (!first)
+		putchar('\n');
+	fflush(stdout);
+	if ((noutputs != 0) && (--noutputs == 0))
+		exit(0);
+	oldmask = sigblock(sigmask(SIGALRM));
+	while (!signalled)
+		sigpause(0);
+	signalled = NO;
+	sigsetmask(oldmask);
+	line++;
+	first = 0;
+	if (line == 21)
+		goto banner;
+	else
+		goto loop;
+	/*NOTREACHED*/
+}
+
+/*
+ * Set a flag to indicate that a signal from the periodic itimer has been
+ * caught.
+ */
+static void
+catchalarm(int signo __unused)
+{
+	signalled = YES;
+}
diff --git a/freebsd-userspace/commands/usr.bin/netstat/inet.c b/freebsd-userspace/commands/usr.bin/netstat/inet.c
new file mode 100644
index 0000000..37b650c
--- /dev/null
+++ b/freebsd-userspace/commands/usr.bin/netstat/inet.c
@@ -0,0 +1,1291 @@
+/*-
+ * Copyright (c) 1983, 1988, 1993, 1995
+ *	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. 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.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)inet.c	8.5 (Berkeley) 5/24/95";
+#endif /* not lint */
+#endif
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#ifdef __rtems__
+#include <freebsd/sys/domain.h>
+#include <freebsd/sys/protosw.h>
+#else
+#include <sys/domain.h>
+#include <sys/protosw.h>
+#endif
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/sysctl.h>
+
+#include <net/route.h>
+#include <net/if_arp.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#ifdef __rtems__
+#include <freebsd/netinet/ip_carp.h>
+#else
+#include <netinet/ip_carp.h>
+#endif
+#ifdef INET6
+#include <netinet/ip6.h>
+#endif /* INET6 */
+#include <netinet/in_pcb.h>
+#include <netinet/ip_icmp.h>
+#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>
+#include <netinet/tcp_timer.h>
+#include <netinet/tcp_var.h>
+#include <netinet/tcp_debug.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+
+#include <arpa/inet.h>
+#include <err.h>
+#include <errno.h>
+#include <libutil.h>
+#include <netdb.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "netstat.h"
+
+char	*inetname(struct in_addr *);
+void	inetprint(struct in_addr *, int, const char *, int);
+#ifdef INET6
+static int udp_done, tcp_done;
+#endif /* INET6 */
+
+static int
+pcblist_sysctl(int proto, char **bufp, int istcp)
+{
+	const char *mibvar;
+	char *buf;
+	size_t len;
+
+	switch (proto) {
+	case IPPROTO_TCP:
+		mibvar = "net.inet.tcp.pcblist";
+		break;
+	case IPPROTO_UDP:
+		mibvar = "net.inet.udp.pcblist";
+		break;
+	case IPPROTO_DIVERT:
+		mibvar = "net.inet.divert.pcblist";
+		break;
+	default:
+		mibvar = "net.inet.raw.pcblist";
+		break;
+	}
+
+	len = 0;
+	if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
+		if (errno != ENOENT)
+			warn("sysctl: %s", mibvar);
+		return (0);
+	}
+	if ((buf = malloc(len)) == 0) {
+		warnx("malloc %lu bytes", (u_long)len);
+		return (0);
+	}
+	if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
+		warn("sysctl: %s", mibvar);
+		free(buf);
+		return (0);
+	}
+	*bufp = buf;
+	return (1);
+}
+
+/*
+ * Copied directly from uipc_socket2.c.  We leave out some fields that are in
+ * nested structures that aren't used to avoid extra work.
+ */
+static void
+sbtoxsockbuf(struct sockbuf *sb, struct xsockbuf *xsb)
+{
+	xsb->sb_cc = sb->sb_cc;
+	xsb->sb_hiwat = sb->sb_hiwat;
+	xsb->sb_mbcnt = sb->sb_mbcnt;
+	xsb->sb_mcnt = sb->sb_mcnt;
+	xsb->sb_ccnt = sb->sb_ccnt;
+	xsb->sb_mbmax = sb->sb_mbmax;
+	xsb->sb_lowat = sb->sb_lowat;
+	xsb->sb_flags = sb->sb_flags;
+	xsb->sb_timeo = sb->sb_timeo;
+}
+
+int
+sotoxsocket(struct socket *so, struct xsocket *xso)
+{
+	struct protosw proto;
+	struct domain domain;
+
+	bzero(xso, sizeof *xso);
+	xso->xso_len = sizeof *xso;
+	xso->xso_so = so;
+	xso->so_type = so->so_type;
+	xso->so_options = so->so_options;
+	xso->so_linger = so->so_linger;
+	xso->so_state = so->so_state;
+	xso->so_pcb = so->so_pcb;
+	if (kread((uintptr_t)so->so_proto, &proto, sizeof(proto)) != 0)
+		return (-1);
+	xso->xso_protocol = proto.pr_protocol;
+	if (kread((uintptr_t)proto.pr_domain, &domain, sizeof(domain)) != 0)
+		return (-1);
+	xso->xso_family = domain.dom_family;
+	xso->so_qlen = so->so_qlen;
+	xso->so_incqlen = so->so_incqlen;
+	xso->so_qlimit = so->so_qlimit;
+	xso->so_timeo = so->so_timeo;
+	xso->so_error = so->so_error;
+	xso->so_oobmark = so->so_oobmark;
+	sbtoxsockbuf(&so->so_snd, &xso->so_snd);
+	sbtoxsockbuf(&so->so_rcv, &xso->so_rcv);
+	return (0);
+}
+
+static int
+pcblist_kvm(u_long off, char **bufp, int istcp)
+{
+	struct inpcbinfo pcbinfo;
+	struct inpcbhead listhead;
+	struct inpcb *inp;
+	struct xinpcb xi;
+	struct xinpgen xig;
+	struct xtcpcb xt;
+	struct socket so;
+	struct xsocket *xso;
+	char *buf, *p;
+	size_t len;
+
+	if (off == 0)
+		return (0);
+	kread(off, &pcbinfo, sizeof(pcbinfo));
+	if (istcp)
+		len = 2 * sizeof(xig) +
+		    (pcbinfo.ipi_count + pcbinfo.ipi_count / 8) *
+		    sizeof(struct xtcpcb);
+	else
+		len = 2 * sizeof(xig) +
+		    (pcbinfo.ipi_count + pcbinfo.ipi_count / 8) *
+		    sizeof(struct xinpcb);
+	if ((buf = malloc(len)) == 0) {
+		warnx("malloc %lu bytes", (u_long)len);
+		return (0);
+	}
+	p = buf;
+
+#define	COPYOUT(obj, size) do {						\
+	if (len < (size)) {						\
+		warnx("buffer size exceeded");				\
+		goto fail;						\
+	}								\
+	bcopy((obj), p, (size));					\
+	len -= (size);							\
+	p += (size);							\
+} while (0)
+
+#define	KREAD(off, buf, len) do {					\
+	if (kread((uintptr_t)(off), (buf), (len)) != 0)			\
+		goto fail;						\
+} while (0)
+
+	/* Write out header. */
+	xig.xig_len = sizeof xig;
+	xig.xig_count = pcbinfo.ipi_count;
+	xig.xig_gen = pcbinfo.ipi_gencnt;
+	xig.xig_sogen = 0;
+	COPYOUT(&xig, sizeof xig);
+
+	/* Walk the PCB list. */
+	xt.xt_len = sizeof xt;
+	xi.xi_len = sizeof xi;
+	if (istcp)
+		xso = &xt.xt_socket;
+	else
+		xso = &xi.xi_socket;
+	KREAD(pcbinfo.ipi_listhead, &listhead, sizeof(listhead));
+	LIST_FOREACH(inp, &listhead, inp_list) {
+		if (istcp) {
+			KREAD(inp, &xt.xt_inp, sizeof(*inp));
+			inp = &xt.xt_inp;
+		} else {
+			KREAD(inp, &xi.xi_inp, sizeof(*inp));
+			inp = &xi.xi_inp;
+		}
+
+		if (inp->inp_gencnt > pcbinfo.ipi_gencnt)
+			continue;
+
+		if (istcp) {
+			if (inp->inp_ppcb == NULL)
+				bzero(&xt.xt_tp, sizeof xt.xt_tp);
+			else if (inp->inp_flags & INP_TIMEWAIT) {
+				bzero(&xt.xt_tp, sizeof xt.xt_tp);
+				xt.xt_tp.t_state = TCPS_TIME_WAIT;
+			} else
+				KREAD(inp->inp_ppcb, &xt.xt_tp,
+				    sizeof xt.xt_tp);
+		}
+		if (inp->inp_socket) {
+			KREAD(inp->inp_socket, &so, sizeof(so));
+			if (sotoxsocket(&so, xso) != 0)
+				goto fail;
+		} else {
+			bzero(xso, sizeof(*xso));
+			if (istcp)
+				xso->xso_protocol = IPPROTO_TCP;
+		}
+		if (istcp)
+			COPYOUT(&xt, sizeof xt);
+		else
+			COPYOUT(&xi, sizeof xi);
+	}
+
+	/* Reread the pcbinfo and write out the footer. */
+	kread(off, &pcbinfo, sizeof(pcbinfo));
+	xig.xig_count = pcbinfo.ipi_count;
+	xig.xig_gen = pcbinfo.ipi_gencnt;
+	COPYOUT(&xig, sizeof xig);
+
+	*bufp = buf;
+	return (1);
+
+fail:
+	free(buf);
+	return (0);
+#undef COPYOUT
+#undef KREAD
+}
+
+/*
+ * Print a summary of connections related to an Internet
+ * protocol.  For TCP, also give state of connection.
+ * Listening processes (aflag) are suppressed unless the
+ * -a (all) flag is specified.
+ */
+void
+protopr(u_long off, const char *name, int af1, int proto)
+{
+	int istcp;
+	static int first = 1;
+	char *buf;
+	const char *vchar;
+	struct tcpcb *tp = NULL;
+	struct inpcb *inp;
+	struct xinpgen *xig, *oxig;
+	struct xsocket *so;
+
+	istcp = 0;
+	switch (proto) {
+	case IPPROTO_TCP:
+#ifdef INET6
+		if (tcp_done != 0)
+			return;
+		else
+			tcp_done = 1;
+#endif
+		istcp = 1;
+		break;
+	case IPPROTO_UDP:
+#ifdef INET6
+		if (udp_done != 0)
+			return;
+		else
+			udp_done = 1;
+#endif
+		break;
+	}
+	if (live) {
+		if (!pcblist_sysctl(proto, &buf, istcp))
+			return;
+	} else {
+		if (!pcblist_kvm(off, &buf, istcp))
+			return;
+	}
+
+	oxig = xig = (struct xinpgen *)buf;
+	for (xig = (struct xinpgen *)((char *)xig + xig->xig_len);
+	     xig->xig_len > sizeof(struct xinpgen);
+	     xig = (struct xinpgen *)((char *)xig + xig->xig_len)) {
+		if (istcp) {
+			tp = &((struct xtcpcb *)xig)->xt_tp;
+			inp = &((struct xtcpcb *)xig)->xt_inp;
+			so = &((struct xtcpcb *)xig)->xt_socket;
+		} else {
+			inp = &((struct xinpcb *)xig)->xi_inp;
+			so = &((struct xinpcb *)xig)->xi_socket;
+		}
+
+		/* Ignore sockets for protocols other than the desired one. */
+		if (so->xso_protocol != proto)
+			continue;
+
+		/* Ignore PCBs which were freed during copyout. */
+		if (inp->inp_gencnt > oxig->xig_gen)
+			continue;
+
+		if ((af1 == AF_INET && (inp->inp_vflag & INP_IPV4) == 0)
+#ifdef INET6
+		    || (af1 == AF_INET6 && (inp->inp_vflag & INP_IPV6) == 0)
+#endif /* INET6 */
+		    || (af1 == AF_UNSPEC && ((inp->inp_vflag & INP_IPV4) == 0
+#ifdef INET6
+					  && (inp->inp_vflag & INP_IPV6) == 0
+#endif /* INET6 */
+			))
+		    )
+			continue;
+		if (!aflag &&
+		    (
+		     (istcp && tp->t_state == TCPS_LISTEN)
+		     || (af1 == AF_INET &&
+		      inet_lnaof(inp->inp_laddr) == INADDR_ANY)
+#ifdef INET6
+		     || (af1 == AF_INET6 &&
+			 IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
+#endif /* INET6 */
+		     || (af1 == AF_UNSPEC &&
+			 (((inp->inp_vflag & INP_IPV4) != 0 &&
+			   inet_lnaof(inp->inp_laddr) == INADDR_ANY)
+#ifdef INET6
+			  || ((inp->inp_vflag & INP_IPV6) != 0 &&
+			      IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
+#endif
+			  ))
+		     ))
+			continue;
+
+		if (first) {
+			if (!Lflag) {
+				printf("Active Internet connections");
+				if (aflag)
+					printf(" (including servers)");
+			} else
+				printf(
+	"Current listen queue sizes (qlen/incqlen/maxqlen)");
+			putchar('\n');
+			if (Aflag)
+				printf("%-8.8s ", "Tcpcb");
+			if (Lflag)
+				printf("%-5.5s %-14.14s %-22.22s\n",
+				    "Proto", "Listen", "Local Address");
+			else {
+				printf((Aflag && !Wflag) ? 
+				       "%-5.5s %-6.6s %-6.6s  %-18.18s %-18.18s" :
+				       "%-5.5s %-6.6s %-6.6s  %-22.22s %-22.22s",
+				       "Proto", "Recv-Q", "Send-Q",
+				       "Local Address", "Foreign Address");
+				if (xflag)
+					printf("%-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %s\n",
+					       	"R-MBUF", "S-MBUF", "R-CLUS", 
+						"S-CLUS", "R-HIWA", "S-HIWA", 
+						"R-LOWA", "S-LOWA", "R-BCNT", 
+						"S-BCNT", "R-BMAX", "S-BMAX",
+					       "(state)");
+				else
+					printf("(state)\n");
+			}
+			first = 0;
+		}
+		if (Lflag && so->so_qlimit == 0)
+			continue;
+		if (Aflag) {
+			if (istcp)
+				printf("%8lx ", (u_long)inp->inp_ppcb);
+			else
+				printf("%8lx ", (u_long)so->so_pcb);
+		}
+#ifdef INET6
+		if ((inp->inp_vflag & INP_IPV6) != 0)
+			vchar = ((inp->inp_vflag & INP_IPV4) != 0) ?
+			    "46" : "6 ";
+		else
+#endif
+		vchar = ((inp->inp_vflag & INP_IPV4) != 0) ?
+		    "4 " : "  ";
+		printf("%-3.3s%-2.2s ", name, vchar);
+		if (Lflag) {
+			char buf1[15];
+
+			snprintf(buf1, 15, "%d/%d/%d", so->so_qlen,
+			    so->so_incqlen, so->so_qlimit);
+			printf("%-14.14s ", buf1);
+		} else {
+			printf("%6u %6u ", so->so_rcv.sb_cc, so->so_snd.sb_cc);
+		}
+		if (numeric_port) {
+			if (inp->inp_vflag & INP_IPV4) {
+				inetprint(&inp->inp_laddr, (int)inp->inp_lport,
+				    name, 1);
+				if (!Lflag)
+					inetprint(&inp->inp_faddr,
+					    (int)inp->inp_fport, name, 1);
+			}
+#ifdef INET6
+			else if (inp->inp_vflag & INP_IPV6) {
+				inet6print(&inp->in6p_laddr,
+				    (int)inp->inp_lport, name, 1);
+				if (!Lflag)
+					inet6print(&inp->in6p_faddr,
+					    (int)inp->inp_fport, name, 1);
+			} /* else nothing printed now */
+#endif /* INET6 */
+		} else if (inp->inp_flags & INP_ANONPORT) {
+			if (inp->inp_vflag & INP_IPV4) {
+				inetprint(&inp->inp_laddr, (int)inp->inp_lport,
+				    name, 1);
+				if (!Lflag)
+					inetprint(&inp->inp_faddr,
+					    (int)inp->inp_fport, name, 0);
+			}
+#ifdef INET6
+			else if (inp->inp_vflag & INP_IPV6) {
+				inet6print(&inp->in6p_laddr,
+				    (int)inp->inp_lport, name, 1);
+				if (!Lflag)
+					inet6print(&inp->in6p_faddr,
+					    (int)inp->inp_fport, name, 0);
+			} /* else nothing printed now */
+#endif /* INET6 */
+		} else {
+			if (inp->inp_vflag & INP_IPV4) {
+				inetprint(&inp->inp_laddr, (int)inp->inp_lport,
+				    name, 0);
+				if (!Lflag)
+					inetprint(&inp->inp_faddr,
+					    (int)inp->inp_fport, name,
+					    inp->inp_lport != inp->inp_fport);
+			}
+#ifdef INET6
+			else if (inp->inp_vflag & INP_IPV6) {
+				inet6print(&inp->in6p_laddr,
+				    (int)inp->inp_lport, name, 0);
+				if (!Lflag)
+					inet6print(&inp->in6p_faddr,
+					    (int)inp->inp_fport, name,
+					    inp->inp_lport != inp->inp_fport);
+			} /* else nothing printed now */
+#endif /* INET6 */
+		}
+		if (xflag) {
+			if (Lflag)
+				printf("%21s %6u %6u %6u %6u %6u %6u %6u %6u %6u %6u %6u %6u ",
+				       " ",
+				       so->so_rcv.sb_mcnt, so->so_snd.sb_mcnt,
+				       so->so_rcv.sb_ccnt, so->so_snd.sb_ccnt,
+				       so->so_rcv.sb_hiwat, so->so_snd.sb_hiwat,
+				       so->so_rcv.sb_lowat, so->so_snd.sb_lowat,
+				       so->so_rcv.sb_mbcnt, so->so_snd.sb_mbcnt,
+				       so->so_rcv.sb_mbmax, so->so_snd.sb_mbmax);
+			else
+				printf("%6u %6u %6u %6u %6u %6u %6u %6u %6u %6u %6u %6u ",
+				       so->so_rcv.sb_mcnt, so->so_snd.sb_mcnt,
+				       so->so_rcv.sb_ccnt, so->so_snd.sb_ccnt,
+				       so->so_rcv.sb_hiwat, so->so_snd.sb_hiwat,
+				       so->so_rcv.sb_lowat, so->so_snd.sb_lowat,
+				       so->so_rcv.sb_mbcnt, so->so_snd.sb_mbcnt,
+				       so->so_rcv.sb_mbmax, so->so_snd.sb_mbmax);
+		}
+		if (istcp && !Lflag) {
+			if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES)
+				printf("%d", tp->t_state);
+			else {
+				printf("%s", tcpstates[tp->t_state]);
+#if defined(TF_NEEDSYN) && defined(TF_NEEDFIN)
+				/* Show T/TCP `hidden state' */
+				if (tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN))
+					putchar('*');
+#endif /* defined(TF_NEEDSYN) && defined(TF_NEEDFIN) */
+			}
+		} 		
+		putchar('\n');
+	}
+	if (xig != oxig && xig->xig_gen != oxig->xig_gen) {
+		if (oxig->xig_count > xig->xig_count) {
+			printf("Some %s sockets may have been deleted.\n",
+			    name);
+		} else if (oxig->xig_count < xig->xig_count) {
+			printf("Some %s sockets may have been created.\n",
+			    name);
+		} else {
+			printf(
+	"Some %s sockets may have been created or deleted.\n",
+			    name);
+		}
+	}
+	free(buf);
+}
+
+/*
+ * Dump TCP statistics structure.
+ */
+void
+tcp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+	struct tcpstat tcpstat, zerostat;
+	size_t len = sizeof tcpstat;
+
+#ifdef INET6
+	if (tcp_done != 0)
+		return;
+	else
+		tcp_done = 1;
+#endif
+
+	if (live) {
+		if (zflag)
+			memset(&zerostat, 0, len);
+		if (sysctlbyname("net.inet.tcp.stats", &tcpstat, &len,
+		    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+			warn("sysctl: net.inet.tcp.stats");
+			return;
+		}
+	} else
+		kread(off, &tcpstat, len);
+
+	printf ("%s:\n", name);
+
+#define	p(f, m) if (tcpstat.f || sflag <= 1) \
+    printf(m, tcpstat.f, plural(tcpstat.f))
+#define	p1a(f, m) if (tcpstat.f || sflag <= 1) \
+    printf(m, 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	p2a(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, pluralies(tcpstat.f))
+
+	p(tcps_sndtotal, "\t%lu packet%s sent\n");
+	p2(tcps_sndpack,tcps_sndbyte, "\t\t%lu data packet%s (%lu byte%s)\n");
+	p2(tcps_sndrexmitpack, tcps_sndrexmitbyte,
+	    "\t\t%lu data packet%s (%lu byte%s) retransmitted\n");
+	p(tcps_sndrexmitbad,
+	    "\t\t%lu data packet%s unnecessarily retransmitted\n");
+	p(tcps_mturesent, "\t\t%lu resend%s initiated by MTU discovery\n");
+	p2a(tcps_sndacks, tcps_delack,
+	    "\t\t%lu ack-only packet%s (%lu delayed)\n");
+	p(tcps_sndurg, "\t\t%lu URG only packet%s\n");
+	p(tcps_sndprobe, "\t\t%lu window probe packet%s\n");
+	p(tcps_sndwinup, "\t\t%lu window update packet%s\n");
+	p(tcps_sndctrl, "\t\t%lu control packet%s\n");
+	p(tcps_rcvtotal, "\t%lu packet%s received\n");
+	p2(tcps_rcvackpack, tcps_rcvackbyte,
+	    "\t\t%lu ack%s (for %lu byte%s)\n");
+	p(tcps_rcvdupack, "\t\t%lu duplicate ack%s\n");
+	p(tcps_rcvacktoomuch, "\t\t%lu ack%s for unsent data\n");
+	p2(tcps_rcvpack, tcps_rcvbyte,
+	    "\t\t%lu packet%s (%lu byte%s) received in-sequence\n");
+	p2(tcps_rcvduppack, tcps_rcvdupbyte,
+	    "\t\t%lu completely duplicate packet%s (%lu byte%s)\n");
+	p(tcps_pawsdrop, "\t\t%lu old duplicate packet%s\n");
+	p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte,
+	    "\t\t%lu packet%s with some dup. data (%lu byte%s duped)\n");
+	p2(tcps_rcvoopack, tcps_rcvoobyte,
+	    "\t\t%lu out-of-order packet%s (%lu byte%s)\n");
+	p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin,
+	    "\t\t%lu packet%s (%lu byte%s) of data after window\n");
+	p(tcps_rcvwinprobe, "\t\t%lu window probe%s\n");
+	p(tcps_rcvwinupd, "\t\t%lu window update packet%s\n");
+	p(tcps_rcvafterclose, "\t\t%lu packet%s received after close\n");
+	p(tcps_rcvbadsum, "\t\t%lu discarded for bad checksum%s\n");
+	p(tcps_rcvbadoff, "\t\t%lu discarded for bad header offset field%s\n");
+	p1a(tcps_rcvshort, "\t\t%lu discarded because packet too short\n");
+	p1a(tcps_rcvmemdrop, "\t\t%lu discarded due to memory problems\n");
+	p(tcps_connattempt, "\t%lu connection request%s\n");
+	p(tcps_accepts, "\t%lu connection accept%s\n");
+	p(tcps_badsyn, "\t%lu bad connection attempt%s\n");
+	p(tcps_listendrop, "\t%lu listen queue overflow%s\n");
+	p(tcps_badrst, "\t%lu ignored RSTs in the window%s\n");
+	p(tcps_connects, "\t%lu connection%s established (including accepts)\n");
+	p2(tcps_closed, tcps_drops,
+	    "\t%lu connection%s closed (including %lu drop%s)\n");
+	p(tcps_cachedrtt, "\t\t%lu connection%s updated cached RTT on close\n");
+	p(tcps_cachedrttvar,
+	    "\t\t%lu connection%s updated cached RTT variance on close\n");
+	p(tcps_cachedssthresh,
+	    "\t\t%lu connection%s updated cached ssthresh on close\n");
+	p(tcps_conndrops, "\t%lu embryonic connection%s dropped\n");
+	p2(tcps_rttupdated, tcps_segstimed,
+	    "\t%lu segment%s updated rtt (of %lu attempt%s)\n");
+	p(tcps_rexmttimeo, "\t%lu retransmit timeout%s\n");
+	p(tcps_timeoutdrop, "\t\t%lu connection%s dropped by rexmit timeout\n");
+	p(tcps_persisttimeo, "\t%lu persist timeout%s\n");
+	p(tcps_persistdrop, "\t\t%lu connection%s dropped by persist timeout\n");
+	p(tcps_finwait2_drops,
+	    "\t%lu Connection%s (fin_wait_2) dropped because of timeout\n");
+	p(tcps_keeptimeo, "\t%lu keepalive timeout%s\n");
+	p(tcps_keepprobe, "\t\t%lu keepalive probe%s sent\n");
+	p(tcps_keepdrops, "\t\t%lu connection%s dropped by keepalive\n");
+	p(tcps_predack, "\t%lu correct ACK header prediction%s\n");
+	p(tcps_preddat, "\t%lu correct data packet header prediction%s\n");
+
+	p3(tcps_sc_added, "\t%lu syncache entr%s added\n");
+	p1a(tcps_sc_retransmitted, "\t\t%lu retransmitted\n");
+	p1a(tcps_sc_dupsyn, "\t\t%lu dupsyn\n");
+	p1a(tcps_sc_dropped, "\t\t%lu dropped\n");
+	p1a(tcps_sc_completed, "\t\t%lu completed\n");
+	p1a(tcps_sc_bucketoverflow, "\t\t%lu bucket overflow\n");
+	p1a(tcps_sc_cacheoverflow, "\t\t%lu cache overflow\n");
+	p1a(tcps_sc_reset, "\t\t%lu reset\n");
+	p1a(tcps_sc_stale, "\t\t%lu stale\n");
+	p1a(tcps_sc_aborted, "\t\t%lu aborted\n");
+	p1a(tcps_sc_badack, "\t\t%lu badack\n");
+	p1a(tcps_sc_unreach, "\t\t%lu unreach\n");
+	p(tcps_sc_zonefail, "\t\t%lu zone failure%s\n");
+	p(tcps_sc_sendcookie, "\t%lu cookie%s sent\n");
+	p(tcps_sc_recvcookie, "\t%lu cookie%s received\n");
+
+	p(tcps_sack_recovery_episode, "\t%lu SACK recovery episode%s\n");
+	p(tcps_sack_rexmits,
+	    "\t%lu segment rexmit%s in SACK recovery episodes\n");
+	p(tcps_sack_rexmit_bytes,
+	    "\t%lu byte rexmit%s in SACK recovery episodes\n");
+	p(tcps_sack_rcv_blocks,
+	    "\t%lu SACK option%s (SACK blocks) received\n");
+	p(tcps_sack_send_blocks, "\t%lu SACK option%s (SACK blocks) sent\n");
+	p1a(tcps_sack_sboverflow, "\t%lu SACK scoreboard overflow\n");
+
+	p(tcps_ecn_ce, "\t%lu packet%s with ECN CE bit set\n");
+	p(tcps_ecn_ect0, "\t%lu packet%s with ECN ECT(0) bit set\n");
+	p(tcps_ecn_ect1, "\t%lu packet%s with ECN ECT(1) bit set\n");
+	p(tcps_ecn_shs, "\t%lu successful ECN handshake%s\n");
+	p(tcps_ecn_rcwnd, "\t%lu time%s ECN reduced the congestion window\n");
+#undef p
+#undef p1a
+#undef p2
+#undef p2a
+#undef p3
+}
+
+/*
+ * Dump UDP statistics structure.
+ */
+void
+udp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+	struct udpstat udpstat, zerostat;
+	size_t len = sizeof udpstat;
+	u_long delivered;
+
+#ifdef INET6
+	if (udp_done != 0)
+		return;
+	else
+		udp_done = 1;
+#endif
+
+	if (live) {
+		if (zflag)
+			memset(&zerostat, 0, len);
+		if (sysctlbyname("net.inet.udp.stats", &udpstat, &len,
+		    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+			warn("sysctl: net.inet.udp.stats");
+			return;
+		}
+	} else
+		kread(off, &udpstat, len);
+
+	printf("%s:\n", name);
+#define	p(f, m) if (udpstat.f || sflag <= 1) \
+    printf(m, udpstat.f, plural(udpstat.f))
+#define	p1a(f, m) if (udpstat.f || sflag <= 1) \
+    printf(m, udpstat.f)
+	p(udps_ipackets, "\t%lu datagram%s received\n");
+	p1a(udps_hdrops, "\t%lu with incomplete header\n");
+	p1a(udps_badlen, "\t%lu with bad data length field\n");
+	p1a(udps_badsum, "\t%lu with bad checksum\n");
+	p1a(udps_nosum, "\t%lu with no checksum\n");
+	p1a(udps_noport, "\t%lu dropped due to no socket\n");
+	p(udps_noportbcast,
+	    "\t%lu broadcast/multicast datagram%s undelivered\n");
+	p1a(udps_fullsock, "\t%lu dropped due to full socket buffers\n");
+	p1a(udpps_pcbhashmiss, "\t%lu not for hashed pcb\n");
+	delivered = udpstat.udps_ipackets -
+		    udpstat.udps_hdrops -
+		    udpstat.udps_badlen -
+		    udpstat.udps_badsum -
+		    udpstat.udps_noport -
+		    udpstat.udps_noportbcast -
+		    udpstat.udps_fullsock;
+	if (delivered || sflag <= 1)
+		printf("\t%lu delivered\n", delivered);
+	p(udps_opackets, "\t%lu datagram%s output\n");
+	/* the next statistic is cumulative in udps_noportbcast */
+	p(udps_filtermcast,
+	    "\t%lu time%s multicast source filter matched\n");
+#undef p
+#undef p1a
+}
+
+/*
+ * Dump CARP statistics structure.
+ */
+void
+carp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+	struct carpstats carpstat, zerostat;
+	size_t len = sizeof(struct carpstats);
+
+	if (live) {
+		if (zflag)
+			memset(&zerostat, 0, len);
+		if (sysctlbyname("net.inet.carp.stats", &carpstat, &len,
+		    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+			if (errno != ENOENT)
+				warn("sysctl: net.inet.carp.stats");
+			return;
+		}
+	} else {
+		if (off == 0)
+			return;
+		kread(off, &carpstat, len);
+	}
+
+	printf("%s:\n", name);
+
+#define	p(f, m) if (carpstat.f || sflag <= 1) \
+	printf(m, (uintmax_t)carpstat.f, plural(carpstat.f))
+#define	p2(f, m) if (carpstat.f || sflag <= 1) \
+	printf(m, (uintmax_t)carpstat.f)
+
+	p(carps_ipackets, "\t%ju packet%s received (IPv4)\n");
+	p(carps_ipackets6, "\t%ju packet%s received (IPv6)\n");
+	p(carps_badttl, "\t\t%ju packet%s discarded for wrong TTL\n");
+	p(carps_hdrops, "\t\t%ju packet%s shorter than header\n");
+	p(carps_badsum, "\t\t%ju discarded for bad checksum%s\n");
+	p(carps_badver,	"\t\t%ju discarded packet%s with a bad version\n");
+	p2(carps_badlen, "\t\t%ju discarded because packet too short\n");
+	p2(carps_badauth, "\t\t%ju discarded for bad authentication\n");
+	p2(carps_badvhid, "\t\t%ju discarded for bad vhid\n");
+	p2(carps_badaddrs, "\t\t%ju discarded because of a bad address list\n");
+	p(carps_opackets, "\t%ju packet%s sent (IPv4)\n");
+	p(carps_opackets6, "\t%ju packet%s sent (IPv6)\n");
+	p2(carps_onomem, "\t\t%ju send failed due to mbuf memory error\n");
+#if notyet
+	p(carps_ostates, "\t\t%s state update%s sent\n");
+#endif
+#undef p
+#undef p2
+}
+
+/*
+ * Dump IP statistics structure.
+ */
+void
+ip_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+	struct ipstat ipstat, zerostat;
+	size_t len = sizeof ipstat;
+
+	if (live) {
+		if (zflag)
+			memset(&zerostat, 0, len);
+		if (sysctlbyname("net.inet.ip.stats", &ipstat, &len,
+		    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+			warn("sysctl: net.inet.ip.stats");
+			return;
+		}
+	} else
+		kread(off, &ipstat, len);
+
+	printf("%s:\n", name);
+
+#define	p(f, m) if (ipstat.f || sflag <= 1) \
+    printf(m, ipstat.f, plural(ipstat.f))
+#define	p1a(f, m) if (ipstat.f || sflag <= 1) \
+    printf(m, ipstat.f)
+
+	p(ips_total, "\t%lu total packet%s received\n");
+	p(ips_badsum, "\t%lu bad header checksum%s\n");
+	p1a(ips_toosmall, "\t%lu with size smaller than minimum\n");
+	p1a(ips_tooshort, "\t%lu with data size < data length\n");
+	p1a(ips_toolong, "\t%lu with ip length > max ip packet size\n");
+	p1a(ips_badhlen, "\t%lu with header length < data size\n");
+	p1a(ips_badlen, "\t%lu with data length < header length\n");
+	p1a(ips_badoptions, "\t%lu with bad options\n");
+	p1a(ips_badvers, "\t%lu with incorrect version number\n");
+	p(ips_fragments, "\t%lu fragment%s received\n");
+	p(ips_fragdropped, "\t%lu fragment%s dropped (dup or out of space)\n");
+	p(ips_fragtimeout, "\t%lu fragment%s dropped after timeout\n");
+	p(ips_reassembled, "\t%lu packet%s reassembled ok\n");
+	p(ips_delivered, "\t%lu packet%s for this host\n");
+	p(ips_noproto, "\t%lu packet%s for unknown/unsupported protocol\n");
+	p(ips_forward, "\t%lu packet%s forwarded");
+	p(ips_fastforward, " (%lu packet%s fast forwarded)");
+	if (ipstat.ips_forward || sflag <= 1)
+		putchar('\n');
+	p(ips_cantforward, "\t%lu packet%s not forwardable\n");
+	p(ips_notmember,
+	    "\t%lu packet%s received for unknown multicast group\n");
+	p(ips_redirectsent, "\t%lu redirect%s sent\n");
+	p(ips_localout, "\t%lu packet%s sent from this host\n");
+	p(ips_rawout, "\t%lu packet%s sent with fabricated ip header\n");
+	p(ips_odropped,
+	    "\t%lu output packet%s dropped due to no bufs, etc.\n");
+	p(ips_noroute, "\t%lu output packet%s discarded due to no route\n");
+	p(ips_fragmented, "\t%lu output datagram%s fragmented\n");
+	p(ips_ofragments, "\t%lu fragment%s created\n");
+	p(ips_cantfrag, "\t%lu datagram%s that can't be fragmented\n");
+	p(ips_nogif, "\t%lu tunneling packet%s that can't find gif\n");
+	p(ips_badaddr, "\t%lu datagram%s with bad address in header\n");
+#undef p
+#undef p1a
+}
+
+/*
+ * Dump ARP statistics structure.
+ */
+void
+arp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+	struct arpstat arpstat, zerostat;
+	size_t len = sizeof(arpstat);
+
+	if (live) {
+		if (zflag)
+			memset(&zerostat, 0, len);
+		if (sysctlbyname("net.link.ether.arp.stats", &arpstat, &len,
+		    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+			warn("sysctl: net.link.ether.arp.stats");
+			return;
+		}
+	} else
+		kread(off, &arpstat, len);
+
+	printf("%s:\n", name);
+
+#define	p(f, m) if (arpstat.f || sflag <= 1) \
+    printf(m, arpstat.f, plural(arpstat.f))
+#define	p2(f, m) if (arpstat.f || sflag <= 1) \
+    printf(m, arpstat.f, pluralies(arpstat.f))
+
+	p(txrequests, "\t%lu ARP request%s sent\n");
+	p2(txreplies, "\t%lu ARP repl%s sent\n");
+	p(rxrequests, "\t%lu ARP request%s received\n");
+	p2(rxreplies, "\t%lu ARP repl%s received\n");
+	p(received, "\t%lu ARP packet%s received\n");
+	p(dropped, "\t%lu total packet%s dropped due to no ARP entry\n");
+	p(timeouts, "\t%lu ARP entry%s timed out\n");
+	p(dupips, "\t%lu Duplicate IP%s seen\n");
+#undef p
+#undef p2
+}
+
+
+
+static	const char *icmpnames[ICMP_MAXTYPE + 1] = {
+	"echo reply",			/* RFC 792 */
+	"#1",
+	"#2",
+	"destination unreachable",	/* RFC 792 */
+	"source quench",		/* RFC 792 */
+	"routing redirect",		/* RFC 792 */
+	"#6",
+	"#7",
+	"echo",				/* RFC 792 */
+	"router advertisement",		/* RFC 1256 */
+	"router solicitation",		/* RFC 1256 */
+	"time exceeded",		/* RFC 792 */
+	"parameter problem",		/* RFC 792 */
+	"time stamp",			/* RFC 792 */
+	"time stamp reply",		/* RFC 792 */
+	"information request",		/* RFC 792 */
+	"information request reply",	/* RFC 792 */
+	"address mask request",		/* RFC 950 */
+	"address mask reply",		/* RFC 950 */
+	"#19",
+	"#20",
+	"#21",
+	"#22",
+	"#23",
+	"#24",
+	"#25",
+	"#26",
+	"#27",
+	"#28",
+	"#29",
+	"icmp traceroute",		/* RFC 1393 */
+	"datagram conversion error",	/* RFC 1475 */
+	"mobile host redirect",
+	"IPv6 where-are-you",
+	"IPv6 i-am-here",
+	"mobile registration req",
+	"mobile registration reply",
+	"domain name request",		/* RFC 1788 */
+	"domain name reply",		/* RFC 1788 */
+	"icmp SKIP",
+	"icmp photuris",		/* RFC 2521 */
+};
+
+/*
+ * Dump ICMP statistics.
+ */
+void
+icmp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+	struct icmpstat icmpstat, zerostat;
+	int i, first;
+	size_t len;
+
+	len = sizeof icmpstat;
+	if (live) {
+		if (zflag)
+			memset(&zerostat, 0, len);
+		if (sysctlbyname("net.inet.icmp.stats", &icmpstat, &len,
+		    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+			warn("sysctl: net.inet.icmp.stats");
+			return;
+		}
+	} else
+		kread(off, &icmpstat, len);
+
+	printf("%s:\n", name);
+
+#define	p(f, m) if (icmpstat.f || sflag <= 1) \
+    printf(m, icmpstat.f, plural(icmpstat.f))
+#define	p1a(f, m) if (icmpstat.f || sflag <= 1) \
+    printf(m, icmpstat.f)
+#define	p2(f, m) if (icmpstat.f || sflag <= 1) \
+    printf(m, icmpstat.f, plurales(icmpstat.f))
+
+	p(icps_error, "\t%lu call%s to icmp_error\n");
+	p(icps_oldicmp,
+	    "\t%lu error%s not generated in response to an icmp message\n");
+	for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
+		if (icmpstat.icps_outhist[i] != 0) {
+			if (first) {
+				printf("\tOutput histogram:\n");
+				first = 0;
+			}
+			if (icmpnames[i] != NULL)
+				printf("\t\t%s: %lu\n", icmpnames[i],
+					icmpstat.icps_outhist[i]);
+			else
+				printf("\t\tunknown ICMP #%d: %lu\n", i,
+					icmpstat.icps_outhist[i]);
+		}
+	p(icps_badcode, "\t%lu message%s with bad code fields\n");
+	p(icps_tooshort, "\t%lu message%s less than the minimum length\n");
+	p(icps_checksum, "\t%lu message%s with bad checksum\n");
+	p(icps_badlen, "\t%lu message%s with bad length\n");
+	p1a(icps_bmcastecho, "\t%lu multicast echo requests ignored\n");
+	p1a(icps_bmcasttstamp, "\t%lu multicast timestamp requests ignored\n");
+	for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
+		if (icmpstat.icps_inhist[i] != 0) {
+			if (first) {
+				printf("\tInput histogram:\n");
+				first = 0;
+			}
+			if (icmpnames[i] != NULL)
+				printf("\t\t%s: %lu\n", icmpnames[i],
+				    icmpstat.icps_inhist[i]);
+			else
+				printf("\t\tunknown ICMP #%d: %lu\n", i,
+				    icmpstat.icps_inhist[i]);
+		}
+	p(icps_reflect, "\t%lu message response%s generated\n");
+	p2(icps_badaddr, "\t%lu invalid return address%s\n");
+	p(icps_noroute, "\t%lu no return route%s\n");
+#undef p
+#undef p1a
+#undef p2
+	if (live) {
+		len = sizeof i;
+		if (sysctlbyname("net.inet.icmp.maskrepl", &i, &len, NULL, 0) <
+		    0)
+			return;
+		printf("\tICMP address mask responses are %sabled\n",
+		    i ? "en" : "dis");
+	}
+}
+
+#ifndef BURN_BRIDGES
+/*
+ * Dump IGMP statistics structure (pre 8.x kernel).
+ */
+static void
+igmp_stats_live_old(u_long off, const char *name)
+{
+	struct oigmpstat oigmpstat, zerostat;
+	size_t len = sizeof(oigmpstat);
+
+	if (zflag)
+		memset(&zerostat, 0, len);
+	if (sysctlbyname("net.inet.igmp.stats", &oigmpstat, &len,
+	    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+		warn("sysctl: net.inet.igmp.stats");
+		return;
+	}
+
+	printf("%s:\n", name);
+
+#define	p(f, m) if (oigmpstat.f || sflag <= 1) \
+    printf(m, oigmpstat.f, plural(oigmpstat.f))
+#define	py(f, m) if (oigmpstat.f || sflag <= 1) \
+    printf(m, oigmpstat.f, oigmpstat.f != 1 ? "ies" : "y")
+	p(igps_rcv_total, "\t%u message%s received\n");
+	p(igps_rcv_tooshort, "\t%u message%s received with too few bytes\n");
+	p(igps_rcv_badsum, "\t%u message%s received with bad checksum\n");
+	py(igps_rcv_queries, "\t%u membership quer%s received\n");
+	py(igps_rcv_badqueries,
+	    "\t%u membership quer%s received with invalid field(s)\n");
+	p(igps_rcv_reports, "\t%u membership report%s received\n");
+	p(igps_rcv_badreports,
+	    "\t%u membership report%s received with invalid field(s)\n");
+	p(igps_rcv_ourreports,
+"\t%u membership report%s received for groups to which we belong\n");
+        p(igps_snd_reports, "\t%u membership report%s sent\n");
+#undef p
+#undef py
+}
+#endif /* !BURN_BRIDGES */
+
+/*
+ * Dump IGMP statistics structure.
+ */
+void
+igmp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+	struct igmpstat igmpstat, zerostat;
+	size_t len;
+
+#ifndef BURN_BRIDGES
+	if (live) {
+		/*
+		 * Detect if we are being run against a pre-IGMPv3 kernel.
+		 * We cannot do this for a core file as the legacy
+		 * struct igmpstat has no size field, nor does it
+		 * export it in any readily-available symbols.
+		 */
+		len = 0;
+		if (sysctlbyname("net.inet.igmp.stats", NULL, &len, NULL,
+		    0) < 0) {
+			warn("sysctl: net.inet.igmp.stats");
+			return;
+		}
+		if (len < sizeof(igmpstat)) {
+			igmp_stats_live_old(off, name);
+			return;
+		}
+	}
+#endif /* !BURN_BRIDGES */
+
+	len = sizeof(igmpstat);
+	if (live) {
+		if (zflag)
+			memset(&zerostat, 0, len);
+		if (sysctlbyname("net.inet.igmp.stats", &igmpstat, &len,
+		    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+			warn("sysctl: net.inet.igmp.stats");
+			return;
+		}
+	} else {
+		len = sizeof(igmpstat);
+		kread(off, &igmpstat, len);
+	}
+
+	if (igmpstat.igps_version != IGPS_VERSION_3) {
+		warnx("%s: version mismatch (%d != %d)", __func__,
+		    igmpstat.igps_version, IGPS_VERSION_3);
+	}
+	if (igmpstat.igps_len != IGPS_VERSION3_LEN) {
+		warnx("%s: size mismatch (%d != %d)", __func__,
+		    igmpstat.igps_len, IGPS_VERSION3_LEN);
+	}
+
+	printf("%s:\n", name);
+
+#define	p64(f, m) if (igmpstat.f || sflag <= 1) \
+    printf(m, (uintmax_t) igmpstat.f, plural(igmpstat.f))
+#define	py64(f, m) if (igmpstat.f || sflag <= 1) \
+    printf(m, (uintmax_t) igmpstat.f, pluralies(igmpstat.f))
+	p64(igps_rcv_total, "\t%ju message%s received\n");
+	p64(igps_rcv_tooshort, "\t%ju message%s received with too few bytes\n");
+	p64(igps_rcv_badttl, "\t%ju message%s received with wrong TTL\n");
+	p64(igps_rcv_badsum, "\t%ju message%s received with bad checksum\n");
+	py64(igps_rcv_v1v2_queries, "\t%ju V1/V2 membership quer%s received\n");
+	py64(igps_rcv_v3_queries, "\t%ju V3 membership quer%s received\n");
+	py64(igps_rcv_badqueries,
+	    "\t%ju membership quer%s received with invalid field(s)\n");
+	py64(igps_rcv_gen_queries, "\t%ju general quer%s received\n");
+	py64(igps_rcv_group_queries, "\t%ju group quer%s received\n");
+	py64(igps_rcv_gsr_queries, "\t%ju group-source quer%s received\n");
+	py64(igps_drop_gsr_queries, "\t%ju group-source quer%s dropped\n");
+	p64(igps_rcv_reports, "\t%ju membership report%s received\n");
+	p64(igps_rcv_badreports,
+	    "\t%ju membership report%s received with invalid field(s)\n");
+	p64(igps_rcv_ourreports,
+"\t%ju membership report%s received for groups to which we belong\n");
+        p64(igps_rcv_nora, "\t%ju V3 report%s received without Router Alert\n");
+        p64(igps_snd_reports, "\t%ju membership report%s sent\n");
+#undef p64
+#undef py64
+}
+
+/*
+ * Dump PIM statistics structure.
+ */
+void
+pim_stats(u_long off __unused, const char *name, int af1 __unused,
+    int proto __unused)
+{
+	struct pimstat pimstat, zerostat;
+	size_t len = sizeof pimstat;
+
+	if (live) {
+		if (zflag)
+			memset(&zerostat, 0, len);
+		if (sysctlbyname("net.inet.pim.stats", &pimstat, &len,
+		    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+			if (errno != ENOENT)
+				warn("sysctl: net.inet.pim.stats");
+			return;
+		}
+	} else {
+		if (off == 0)
+			return;
+		kread(off, &pimstat, len);
+	}
+
+	printf("%s:\n", name);
+
+#define	p(f, m) if (pimstat.f || sflag <= 1) \
+    printf(m, (uintmax_t)pimstat.f, plural(pimstat.f))
+#define	py(f, m) if (pimstat.f || sflag <= 1) \
+    printf(m, (uintmax_t)pimstat.f, pimstat.f != 1 ? "ies" : "y")
+	p(pims_rcv_total_msgs, "\t%ju message%s received\n");
+	p(pims_rcv_total_bytes, "\t%ju byte%s received\n");
+	p(pims_rcv_tooshort, "\t%ju message%s received with too few bytes\n");
+        p(pims_rcv_badsum, "\t%ju message%s received with bad checksum\n");
+	p(pims_rcv_badversion, "\t%ju message%s received with bad version\n");
+	p(pims_rcv_registers_msgs, "\t%ju data register message%s received\n");
+	p(pims_rcv_registers_bytes, "\t%ju data register byte%s received\n");
+	p(pims_rcv_registers_wrongiif,
+	    "\t%ju data register message%s received on wrong iif\n");
+	p(pims_rcv_badregisters, "\t%ju bad register%s received\n");
+	p(pims_snd_registers_msgs, "\t%ju data register message%s sent\n");
+	p(pims_snd_registers_bytes, "\t%ju data register byte%s sent\n");
+#undef p
+#undef py
+}
+
+/*
+ * Pretty print an Internet address (net address + port).
+ */
+void
+inetprint(struct in_addr *in, int port, const char *proto, int num_port)
+{
+	struct servent *sp = 0;
+	char line[80], *cp;
+	int width;
+
+	if (Wflag)
+	    sprintf(line, "%s.", inetname(in));
+	else
+	    sprintf(line, "%.*s.", (Aflag && !num_port) ? 12 : 16, inetname(in));
+	cp = index(line, '\0');
+	if (!num_port && port)
+		sp = getservbyport((int)port, proto);
+	if (sp || port == 0)
+		sprintf(cp, "%.15s ", sp ? sp->s_name : "*");
+	else
+		sprintf(cp, "%d ", ntohs((u_short)port));
+	width = (Aflag && !Wflag) ? 18 : 22;
+	if (Wflag)
+	    printf("%-*s ", width, line);
+	else
+	    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[MAXHOSTNAMELEN];
+	struct hostent *hp;
+	struct netent *np;
+
+	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) {
+				cp = hp->h_name;
+				trimdomain(cp, strlen(cp));
+			}
+		}
+	}
+	if (inp->s_addr == INADDR_ANY)
+		strcpy(line, "*");
+	else if (cp) {
+		strlcpy(line, cp, sizeof(line));
+	} else {
+		inp->s_addr = ntohl(inp->s_addr);
+#define	C(x)	((u_int)((x) & 0xff))
+		sprintf(line, "%u.%u.%u.%u", C(inp->s_addr >> 24),
+		    C(inp->s_addr >> 16), C(inp->s_addr >> 8), C(inp->s_addr));
+	}
+	return (line);
+}
diff --git a/freebsd-userspace/commands/usr.bin/netstat/inet6.c b/freebsd-userspace/commands/usr.bin/netstat/inet6.c
new file mode 100644
index 0000000..254868d
--- /dev/null
+++ b/freebsd-userspace/commands/usr.bin/netstat/inet6.c
@@ -0,0 +1,1159 @@
+/*	BSDI inet.c,v 2.3 1995/10/24 02:19:29 prb 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. 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.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)inet6.c	8.4 (Berkeley) 4/20/94";
+#endif /* not lint */
+#endif
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifdef INET6
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/ioctl.h>
+#include <sys/mbuf.h>
+#ifdef __rtems__
+#include <freebsd/sys/protosw.h>
+#else
+#include <sys/protosw.h>
+#endif
+#include <sys/sysctl.h>
+
+#include <net/route.h>
+#include <net/if.h>
+#include <net/if_var.h>
+#include <netinet/in.h>
+#include <netinet/ip6.h>
+#include <netinet/icmp6.h>
+#include <netinet/in_systm.h>
+#include <netinet6/in6_pcb.h>
+#include <netinet6/in6_var.h>
+#include <netinet6/ip6_var.h>
+#include <netinet6/pim6_var.h>
+#include <netinet6/raw_ip6.h>
+
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include <err.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include "netstat.h"
+
+struct	socket sockb;
+
+char	*inet6name(struct in6_addr *);
+
+static char ntop_buf[INET6_ADDRSTRLEN];
+
+static	const char *ip6nh[] = {
+	"hop by hop",
+	"ICMP",
+	"IGMP",
+	"#3",
+	"IP",
+	"#5",
+	"TCP",
+	"#7",
+	"#8",
+	"#9",
+	"#10",
+	"#11",
+	"#12",
+	"#13",
+	"#14",
+	"#15",
+	"#16",
+	"UDP",
+	"#18",
+	"#19",
+	"#20",
+	"#21",
+	"IDP",
+	"#23",
+	"#24",
+	"#25",
+	"#26",
+	"#27",
+	"#28",
+	"TP",
+	"#30",
+	"#31",
+	"#32",
+	"#33",
+	"#34",
+	"#35",
+	"#36",
+	"#37",
+	"#38",
+	"#39",
+	"#40",
+	"IP6",
+	"#42",
+	"routing",
+	"fragment",
+	"#45",
+	"#46",
+	"#47",
+	"#48",
+	"#49",
+	"ESP",
+	"AH",
+	"#52",
+	"#53",
+	"#54",
+	"#55",
+	"#56",
+	"#57",
+	"ICMP6",
+	"no next header",
+	"destination option",
+	"#61",
+	"mobility",
+	"#63",
+	"#64",
+	"#65",
+	"#66",
+	"#67",
+	"#68",
+	"#69",
+	"#70",
+	"#71",
+	"#72",
+	"#73",
+	"#74",
+	"#75",
+	"#76",
+	"#77",
+	"#78",
+	"#79",
+	"ISOIP",
+	"#81",
+	"#82",
+	"#83",
+	"#84",
+	"#85",
+	"#86",
+	"#87",
+	"#88",
+	"OSPF",
+	"#80",
+	"#91",
+	"#92",
+	"#93",
+	"#94",
+	"#95",
+	"#96",
+	"Ethernet",
+	"#98",
+	"#99",
+	"#100",
+	"#101",
+	"#102",
+	"PIM",
+	"#104",
+	"#105",
+	"#106",
+	"#107",
+	"#108",
+	"#109",
+	"#110",
+	"#111",
+	"#112",
+	"#113",
+	"#114",
+	"#115",
+	"#116",
+	"#117",
+	"#118",
+	"#119",
+	"#120",
+	"#121",
+	"#122",
+	"#123",
+	"#124",
+	"#125",
+	"#126",
+	"#127",
+	"#128",
+	"#129",
+	"#130",
+	"#131",
+	"#132",
+	"#133",
+	"#134",
+	"#135",
+	"#136",
+	"#137",
+	"#138",
+	"#139",
+	"#140",
+	"#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",
+};
+
+static char *srcrule_str[] = {
+	"first candidate",
+	"same address",
+	"appropriate scope",
+	"deprecated address",
+	"home address",
+	"outgoing interface",
+	"matching label",
+	"public/temporary address",
+	"alive interface",
+	"preferred interface",
+	"rule #10",
+	"rule #11",
+	"rule #12",
+	"rule #13",
+	"longest match",
+	"rule #15",
+};
+
+/*
+ * Dump IP6 statistics structure.
+ */
+void
+ip6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+	struct ip6stat ip6stat;
+	int first, i;
+	size_t len;
+
+	len = sizeof ip6stat;
+	if (live) {
+		memset(&ip6stat, 0, len);
+		if (sysctlbyname("net.inet6.ip6.stats", &ip6stat, &len, NULL,
+		    0) < 0) {
+			if (errno != ENOENT)
+				warn("sysctl: net.inet6.ip6.stats");
+			return;
+		}
+	} else
+		kread(off, &ip6stat, len);
+
+	printf("%s:\n", name);
+
+#define	p(f, m) if (ip6stat.f || sflag <= 1) \
+    printf(m, (uintmax_t)ip6stat.f, plural(ip6stat.f))
+#define	p1a(f, m) if (ip6stat.f || sflag <= 1) \
+    printf(m, (uintmax_t)ip6stat.f)
+
+	p(ip6s_total, "\t%ju total packet%s received\n");
+	p1a(ip6s_toosmall, "\t%ju with size smaller than minimum\n");
+	p1a(ip6s_tooshort, "\t%ju with data size < data length\n");
+	p1a(ip6s_badoptions, "\t%ju with bad options\n");
+	p1a(ip6s_badvers, "\t%ju with incorrect version number\n");
+	p(ip6s_fragments, "\t%ju fragment%s received\n");
+	p(ip6s_fragdropped, "\t%ju fragment%s dropped (dup or out of space)\n");
+	p(ip6s_fragtimeout, "\t%ju fragment%s dropped after timeout\n");
+	p(ip6s_fragoverflow, "\t%ju fragment%s that exceeded limit\n");
+	p(ip6s_reassembled, "\t%ju packet%s reassembled ok\n");
+	p(ip6s_delivered, "\t%ju packet%s for this host\n");
+	p(ip6s_forward, "\t%ju packet%s forwarded\n");
+	p(ip6s_cantforward, "\t%ju packet%s not forwardable\n");
+	p(ip6s_redirectsent, "\t%ju redirect%s sent\n");
+	p(ip6s_localout, "\t%ju packet%s sent from this host\n");
+	p(ip6s_rawout, "\t%ju packet%s sent with fabricated ip header\n");
+	p(ip6s_odropped, "\t%ju output packet%s dropped due to no bufs, etc.\n");
+	p(ip6s_noroute, "\t%ju output packet%s discarded due to no route\n");
+	p(ip6s_fragmented, "\t%ju output datagram%s fragmented\n");
+	p(ip6s_ofragments, "\t%ju fragment%s created\n");
+	p(ip6s_cantfrag, "\t%ju datagram%s that can't be fragmented\n");
+	p(ip6s_badscope, "\t%ju packet%s that violated scope rules\n");
+	p(ip6s_notmember, "\t%ju multicast packet%s which we don't join\n");
+	for (first = 1, i = 0; i < 256; i++)
+		if (ip6stat.ip6s_nxthist[i] != 0) {
+			if (first) {
+				printf("\tInput histogram:\n");
+				first = 0;
+			}
+			printf("\t\t%s: %ju\n", ip6nh[i],
+			    (uintmax_t)ip6stat.ip6s_nxthist[i]);
+		}
+	printf("\tMbuf statistics:\n");
+	printf("\t\t%ju one mbuf\n", (uintmax_t)ip6stat.ip6s_m1);
+	for (first = 1, i = 0; i < 32; i++) {
+		char ifbuf[IFNAMSIZ];
+		if (ip6stat.ip6s_m2m[i] != 0) {
+			if (first) {
+				printf("\t\ttwo or more mbuf:\n");
+				first = 0;
+			}
+			printf("\t\t\t%s= %ju\n",
+			    if_indextoname(i, ifbuf),
+			    (uintmax_t)ip6stat.ip6s_m2m[i]);
+		}
+	}
+	printf("\t\t%ju one ext mbuf\n",
+	    (uintmax_t)ip6stat.ip6s_mext1);
+	printf("\t\t%ju two or more ext mbuf\n",
+	    (uintmax_t)ip6stat.ip6s_mext2m);
+	p(ip6s_exthdrtoolong,
+	    "\t%ju packet%s whose headers are not continuous\n");
+	p(ip6s_nogif, "\t%ju tunneling packet%s that can't find gif\n");
+	p(ip6s_toomanyhdr,
+	    "\t%ju packet%s discarded because of 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%ju node-local%s\n");\
+			break;\
+		case 2:\
+			p(s,"\t\t%ju link-local%s\n");\
+			break;\
+		case 5:\
+			p(s,"\t\t%ju site-local%s\n");\
+			break;\
+		case 14:\
+			p(s,"\t\t%ju global%s\n");\
+			break;\
+		default:\
+			printf("\t\t%ju addresses scope=%x\n",\
+			    (uintmax_t)ip6stat.s, i);\
+		}\
+	} while (0);
+
+	p(ip6s_sources_none,
+	  "\t%ju failure%s of source address selection\n");
+	for (first = 1, i = 0; i < 16; i++) {
+		if (ip6stat.ip6s_sources_sameif[i]) {
+			if (first) {
+				printf("\tsource addresses on an outgoing I/F\n");
+				first = 0;
+			}
+			PRINT_SCOPESTAT(ip6s_sources_sameif[i], i);
+		}
+	}
+	for (first = 1, i = 0; i < 16; i++) {
+		if (ip6stat.ip6s_sources_otherif[i]) {
+			if (first) {
+				printf("\tsource addresses on a non-outgoing I/F\n");
+				first = 0;
+			}
+			PRINT_SCOPESTAT(ip6s_sources_otherif[i], i);
+		}
+	}
+	for (first = 1, i = 0; i < 16; i++) {
+		if (ip6stat.ip6s_sources_samescope[i]) {
+			if (first) {
+				printf("\tsource addresses of same scope\n");
+				first = 0;
+			}
+			PRINT_SCOPESTAT(ip6s_sources_samescope[i], i);
+		}
+	}
+	for (first = 1, i = 0; i < 16; i++) {
+		if (ip6stat.ip6s_sources_otherscope[i]) {
+			if (first) {
+				printf("\tsource addresses of a different scope\n");
+				first = 0;
+			}
+			PRINT_SCOPESTAT(ip6s_sources_otherscope[i], i);
+		}
+	}
+	for (first = 1, i = 0; i < 16; i++) {
+		if (ip6stat.ip6s_sources_deprecated[i]) {
+			if (first) {
+				printf("\tdeprecated source addresses\n");
+				first = 0;
+			}
+			PRINT_SCOPESTAT(ip6s_sources_deprecated[i], i);
+		}
+	}
+
+	printf("\tSource addresses selection rule applied:\n");
+	for (i = 0; i < 16; i++) {
+		if (ip6stat.ip6s_sources_rule[i])
+			printf("\t\t%ju %s\n",
+			       (uintmax_t)ip6stat.ip6s_sources_rule[i],
+			       srcrule_str[i]);
+	}
+#undef p
+#undef p1a
+}
+
+/*
+ * Dump IPv6 per-interface statistics based on RFC 2465.
+ */
+void
+ip6_ifstats(char *ifname)
+{
+	struct in6_ifreq ifr;
+	int s;
+#define	p(f, m) if (ifr.ifr_ifru.ifru_stat.f || sflag <= 1) \
+    printf(m, (uintmax_t)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, (uintmax_t)ip6stat.f)
+
+	if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+		perror("Warning: socket(AF_INET6)");
+		return;
+	}
+
+	strcpy(ifr.ifr_name, ifname);
+	printf("ip6 on %s:\n", ifr.ifr_name);
+
+	if (ioctl(s, SIOCGIFSTAT_IN6, (char *)&ifr) < 0) {
+		perror("Warning: ioctl(SIOCGIFSTAT_IN6)");
+		goto end;
+	}
+
+	p(ifs6_in_receive, "\t%ju total input datagram%s\n");
+	p(ifs6_in_hdrerr, "\t%ju datagram%s with invalid header received\n");
+	p(ifs6_in_toobig, "\t%ju datagram%s exceeded MTU received\n");
+	p(ifs6_in_noroute, "\t%ju datagram%s with no route received\n");
+	p(ifs6_in_addrerr, "\t%ju datagram%s with invalid dst received\n");
+	p(ifs6_in_protounknown, "\t%ju datagram%s with unknown proto received\n");
+	p(ifs6_in_truncated, "\t%ju truncated datagram%s received\n");
+	p(ifs6_in_discard, "\t%ju input datagram%s discarded\n");
+	p(ifs6_in_deliver,
+	  "\t%ju datagram%s delivered to an upper layer protocol\n");
+	p(ifs6_out_forward, "\t%ju datagram%s forwarded to this interface\n");
+	p(ifs6_out_request,
+	  "\t%ju datagram%s sent from an upper layer protocol\n");
+	p(ifs6_out_discard, "\t%ju total discarded output datagram%s\n");
+	p(ifs6_out_fragok, "\t%ju output datagram%s fragmented\n");
+	p(ifs6_out_fragfail, "\t%ju output datagram%s failed on fragment\n");
+	p(ifs6_out_fragcreat, "\t%ju output datagram%s succeeded on fragment\n");
+	p(ifs6_reass_reqd, "\t%ju incoming datagram%s fragmented\n");
+	p(ifs6_reass_ok, "\t%ju datagram%s reassembled\n");
+	p(ifs6_reass_fail, "\t%ju datagram%s failed on reassembly\n");
+	p(ifs6_in_mcast, "\t%ju multicast datagram%s received\n");
+	p(ifs6_out_mcast, "\t%ju 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",
+	"MLDv1 listener report",
+	"MLDv1 listener done",
+	"router solicitation",
+	"router advertisement",
+	"neighbor solicitation",
+	"neighbor advertisement",
+	"redirect",
+	"router renumbering",
+	"node information request",
+	"node information reply",
+	"inverse neighbor solicitation",
+	"inverse neighbor advertisement",
+	"MLDv2 listener report",
+	"#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 ICMP6 statistics.
+ */
+void
+icmp6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+	struct icmp6stat icmp6stat;
+	int i, first;
+	size_t len;
+
+	len = sizeof icmp6stat;
+	if (live) {
+		memset(&icmp6stat, 0, len);
+		if (sysctlbyname("net.inet6.icmp6.stats", &icmp6stat, &len,
+		    NULL, 0) < 0) {
+			if (errno != ENOENT)
+				warn("sysctl: net.inet6.icmp6.stats");
+			return;
+		}
+	} else
+		kread(off, &icmp6stat, len);
+
+	printf("%s:\n", name);
+
+#define	p(f, m) if (icmp6stat.f || sflag <= 1) \
+    printf(m, (uintmax_t)icmp6stat.f, plural(icmp6stat.f))
+#define	p_5(f, m) if (icmp6stat.f || sflag <= 1) \
+    printf(m, (uintmax_t)icmp6stat.f)
+
+	p(icp6s_error, "\t%ju call%s to icmp6_error\n");
+	p(icp6s_canterror,
+	    "\t%ju error%s not generated in response to an icmp6 message\n");
+	p(icp6s_toofreq,
+	  "\t%ju error%s not generated because of rate limitation\n");
+#define	NELEM (int)(sizeof(icmp6stat.icp6s_outhist)/sizeof(icmp6stat.icp6s_outhist[0]))
+	for (first = 1, i = 0; i < NELEM; i++)
+		if (icmp6stat.icp6s_outhist[i] != 0) {
+			if (first) {
+				printf("\tOutput histogram:\n");
+				first = 0;
+			}
+			printf("\t\t%s: %ju\n", icmp6names[i],
+			    (uintmax_t)icmp6stat.icp6s_outhist[i]);
+		}
+#undef NELEM
+	p(icp6s_badcode, "\t%ju message%s with bad code fields\n");
+	p(icp6s_tooshort, "\t%ju message%s < minimum length\n");
+	p(icp6s_checksum, "\t%ju bad checksum%s\n");
+	p(icp6s_badlen, "\t%ju message%s with bad length\n");
+#define	NELEM (int)(sizeof(icmp6stat.icp6s_inhist)/sizeof(icmp6stat.icp6s_inhist[0]))
+	for (first = 1, i = 0; i < NELEM; i++)
+		if (icmp6stat.icp6s_inhist[i] != 0) {
+			if (first) {
+				printf("\tInput histogram:\n");
+				first = 0;
+			}
+			printf("\t\t%s: %ju\n", icmp6names[i],
+			    (uintmax_t)icmp6stat.icp6s_inhist[i]);
+		}
+#undef NELEM
+	printf("\tHistogram of error messages to be generated:\n");
+	p_5(icp6s_odst_unreach_noroute, "\t\t%ju no route\n");
+	p_5(icp6s_odst_unreach_admin, "\t\t%ju administratively prohibited\n");
+	p_5(icp6s_odst_unreach_beyondscope, "\t\t%ju beyond scope\n");
+	p_5(icp6s_odst_unreach_addr, "\t\t%ju address unreachable\n");
+	p_5(icp6s_odst_unreach_noport, "\t\t%ju port unreachable\n");
+	p_5(icp6s_opacket_too_big, "\t\t%ju packet too big\n");
+	p_5(icp6s_otime_exceed_transit, "\t\t%ju time exceed transit\n");
+	p_5(icp6s_otime_exceed_reassembly, "\t\t%ju time exceed reassembly\n");
+	p_5(icp6s_oparamprob_header, "\t\t%ju erroneous header field\n");
+	p_5(icp6s_oparamprob_nextheader, "\t\t%ju unrecognized next header\n");
+	p_5(icp6s_oparamprob_option, "\t\t%ju unrecognized option\n");
+	p_5(icp6s_oredirect, "\t\t%ju redirect\n");
+	p_5(icp6s_ounknown, "\t\t%ju unknown\n");
+
+	p(icp6s_reflect, "\t%ju message response%s generated\n");
+	p(icp6s_nd_toomanyopt, "\t%ju message%s with too many ND options\n");
+	p(icp6s_nd_badopt, "\t%ju message%s with bad ND options\n");
+	p(icp6s_badns, "\t%ju bad neighbor solicitation message%s\n");
+	p(icp6s_badna, "\t%ju bad neighbor advertisement message%s\n");
+	p(icp6s_badrs, "\t%ju bad router solicitation message%s\n");
+	p(icp6s_badra, "\t%ju bad router advertisement message%s\n");
+	p(icp6s_badredirect, "\t%ju bad redirect message%s\n");
+	p(icp6s_pmtuchg, "\t%ju path MTU change%s\n");
+#undef p
+#undef p_5
+}
+
+/*
+ * Dump ICMPv6 per-interface statistics based on RFC 2466.
+ */
+void
+icmp6_ifstats(char *ifname)
+{
+	struct in6_ifreq ifr;
+	int s;
+#define	p(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1) \
+    printf(m, (uintmax_t)ifr.ifr_ifru.ifru_icmp6stat.f, plural(ifr.ifr_ifru.ifru_icmp6stat.f))
+#define	p2(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1) \
+    printf(m, (uintmax_t)ifr.ifr_ifru.ifru_icmp6stat.f, pluralies(ifr.ifr_ifru.ifru_icmp6stat.f))
+
+	if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+		perror("Warning: socket(AF_INET6)");
+		return;
+	}
+
+	strcpy(ifr.ifr_name, ifname);
+	printf("icmp6 on %s:\n", ifr.ifr_name);
+
+	if (ioctl(s, SIOCGIFSTAT_ICMP6, (char *)&ifr) < 0) {
+		perror("Warning: ioctl(SIOCGIFSTAT_ICMP6)");
+		goto end;
+	}
+
+	p(ifs6_in_msg, "\t%ju total input message%s\n");
+	p(ifs6_in_error, "\t%ju total input error message%s\n");
+	p(ifs6_in_dstunreach, "\t%ju input destination unreachable error%s\n");
+	p(ifs6_in_adminprohib, "\t%ju input administratively prohibited error%s\n");
+	p(ifs6_in_timeexceed, "\t%ju input time exceeded error%s\n");
+	p(ifs6_in_paramprob, "\t%ju input parameter problem error%s\n");
+	p(ifs6_in_pkttoobig, "\t%ju input packet too big error%s\n");
+	p(ifs6_in_echo, "\t%ju input echo request%s\n");
+	p2(ifs6_in_echoreply, "\t%ju input echo repl%s\n");
+	p(ifs6_in_routersolicit, "\t%ju input router solicitation%s\n");
+	p(ifs6_in_routeradvert, "\t%ju input router advertisement%s\n");
+	p(ifs6_in_neighborsolicit, "\t%ju input neighbor solicitation%s\n");
+	p(ifs6_in_neighboradvert, "\t%ju input neighbor advertisement%s\n");
+	p(ifs6_in_redirect, "\t%ju input redirect%s\n");
+	p2(ifs6_in_mldquery, "\t%ju input MLD quer%s\n");
+	p(ifs6_in_mldreport, "\t%ju input MLD report%s\n");
+	p(ifs6_in_mlddone, "\t%ju input MLD done%s\n");
+
+	p(ifs6_out_msg, "\t%ju total output message%s\n");
+	p(ifs6_out_error, "\t%ju total output error message%s\n");
+	p(ifs6_out_dstunreach, "\t%ju output destination unreachable error%s\n");
+	p(ifs6_out_adminprohib, "\t%ju output administratively prohibited error%s\n");
+	p(ifs6_out_timeexceed, "\t%ju output time exceeded error%s\n");
+	p(ifs6_out_paramprob, "\t%ju output parameter problem error%s\n");
+	p(ifs6_out_pkttoobig, "\t%ju output packet too big error%s\n");
+	p(ifs6_out_echo, "\t%ju output echo request%s\n");
+	p2(ifs6_out_echoreply, "\t%ju output echo repl%s\n");
+	p(ifs6_out_routersolicit, "\t%ju output router solicitation%s\n");
+	p(ifs6_out_routeradvert, "\t%ju output router advertisement%s\n");
+	p(ifs6_out_neighborsolicit, "\t%ju output neighbor solicitation%s\n");
+	p(ifs6_out_neighboradvert, "\t%ju output neighbor advertisement%s\n");
+	p(ifs6_out_redirect, "\t%ju output redirect%s\n");
+	p2(ifs6_out_mldquery, "\t%ju output MLD quer%s\n");
+	p(ifs6_out_mldreport, "\t%ju output MLD report%s\n");
+	p(ifs6_out_mlddone, "\t%ju output MLD done%s\n");
+
+  end:
+	close(s);
+#undef p
+}
+
+/*
+ * Dump PIM statistics structure.
+ */
+void
+pim6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+	struct pim6stat pim6stat, zerostat;
+	size_t len = sizeof pim6stat;
+
+	if (live) {
+		if (zflag)
+			memset(&zerostat, 0, len);
+		if (sysctlbyname("net.inet6.pim.stats", &pim6stat, &len,
+		    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+			if (errno != ENOENT)
+				warn("sysctl: net.inet6.pim.stats");
+			return;
+		}
+	} else {
+		if (off == 0)
+			return;
+		kread(off, &pim6stat, len);
+	}
+
+	printf("%s:\n", name);
+
+#define	p(f, m) if (pim6stat.f || sflag <= 1) \
+    printf(m, (uintmax_t)pim6stat.f, plural(pim6stat.f))
+	p(pim6s_rcv_total, "\t%ju message%s received\n");
+	p(pim6s_rcv_tooshort, "\t%ju message%s received with too few bytes\n");
+	p(pim6s_rcv_badsum, "\t%ju message%s received with bad checksum\n");
+	p(pim6s_rcv_badversion, "\t%ju message%s received with bad version\n");
+	p(pim6s_rcv_registers, "\t%ju register%s received\n");
+	p(pim6s_rcv_badregisters, "\t%ju bad register%s received\n");
+	p(pim6s_snd_registers, "\t%ju register%s sent\n");
+#undef p
+}
+
+/*
+ * Dump raw ip6 statistics structure.
+ */
+void
+rip6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+	struct rip6stat rip6stat;
+	u_quad_t delivered;
+	size_t len;
+
+	len = sizeof(rip6stat);
+	if (live) {
+		if (sysctlbyname("net.inet6.ip6.rip6stats", &rip6stat, &len,
+		    NULL, 0) < 0) {
+			if (errno != ENOENT)
+				warn("sysctl: net.inet6.ip6.rip6stats");
+			return;
+		}
+	} else
+		kread(off, &rip6stat, len);
+
+	printf("%s:\n", name);
+
+#define	p(f, m) if (rip6stat.f || sflag <= 1) \
+    printf(m, (uintmax_t)rip6stat.f, plural(rip6stat.f))
+	p(rip6s_ipackets, "\t%ju message%s received\n");
+	p(rip6s_isum, "\t%ju checksum calculation%s on inbound\n");
+	p(rip6s_badsum, "\t%ju message%s with bad checksum\n");
+	p(rip6s_nosock, "\t%ju message%s dropped due to no socket\n");
+	p(rip6s_nosockmcast,
+	    "\t%ju multicast message%s dropped due to no socket\n");
+	p(rip6s_fullsock,
+	    "\t%ju message%s dropped due to full socket buffers\n");
+	delivered = rip6stat.rip6s_ipackets -
+		    rip6stat.rip6s_badsum -
+		    rip6stat.rip6s_nosock -
+		    rip6stat.rip6s_nosockmcast -
+		    rip6stat.rip6s_fullsock;
+	if (delivered || sflag <= 1)
+		printf("\t%ju delivered\n", (uintmax_t)delivered);
+	p(rip6s_opackets, "\t%ju datagram%s output\n");
+#undef p
+}
+
+/*
+ * Pretty print an Internet address (net address + port).
+ * Take numeric_addr and numeric_port into consideration.
+ */
+#define	GETSERVBYPORT6(port, proto, ret)\
+{\
+	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));\
+};
+
+void
+inet6print(struct in6_addr *in6, int port, const char *proto, int numeric)
+{
+	struct servent *sp = 0;
+	char line[80], *cp;
+	int width;
+
+	sprintf(line, "%.*s.", Wflag ? 39 :
+		(Aflag && !numeric) ? 12 : 16, inet6name(in6));
+	cp = index(line, '\0');
+	if (!numeric && port)
+		GETSERVBYPORT6(port, proto, sp);
+	if (sp || port == 0)
+		sprintf(cp, "%.15s", sp ? sp->s_name : "*");
+	else
+		sprintf(cp, "%d", ntohs((u_short)port));
+	width = Wflag ? 45 : Aflag ? 18 : 22;
+	printf("%-*.*s ", width, width, line);
+}
+
+/*
+ * Construct an Internet address representation.
+ * If the numeric_addr has been supplied, give
+ * numeric value, otherwise try for symbolic name.
+ */
+
+char *
+inet6name(struct in6_addr *in6p)
+{
+	char *cp;
+	static char line[50];
+	struct hostent *hp;
+	static char domain[MAXHOSTNAMELEN];
+	static int first = 1;
+
+	if (first && !numeric_addr) {
+		first = 0;
+		if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
+		    (cp = index(domain, '.')))
+			(void) strcpy(domain, cp + 1);
+		else
+			domain[0] = 0;
+	}
+	cp = 0;
+	if (!numeric_addr && !IN6_IS_ADDR_UNSPECIFIED(in6p)) {
+		hp = gethostbyaddr((char *)in6p, sizeof(*in6p), AF_INET6);
+		if (hp) {
+			if ((cp = index(hp->h_name, '.')) &&
+			    !strcmp(cp + 1, domain))
+				*cp = 0;
+			cp = hp->h_name;
+		}
+	}
+	if (IN6_IS_ADDR_UNSPECIFIED(in6p))
+		strcpy(line, "*");
+	else if (cp)
+		strcpy(line, cp);
+	else
+		sprintf(line, "%s",
+			inet_ntop(AF_INET6, (void *)in6p, ntop_buf,
+				sizeof(ntop_buf)));
+	return (line);
+}
+#endif /*INET6*/
diff --git a/freebsd-userspace/commands/usr.bin/netstat/ipsec.c b/freebsd-userspace/commands/usr.bin/netstat/ipsec.c
new file mode 100644
index 0000000..a6ef510
--- /dev/null
+++ b/freebsd-userspace/commands/usr.bin/netstat/ipsec.c
@@ -0,0 +1,481 @@
+/*	$KAME: ipsec.c,v 1.33 2003/07/25 09:54:32 itojun Exp $	*/
+
+/*-
+ * Copyright (c) 2005 NTT Multimedia Communications Laboratories, 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 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.
+ */
+/*-
+ * 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. 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.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)inet.c	8.5 (Berkeley) 5/24/95";
+#endif /* not lint */
+#endif
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+
+#include <netinet/in.h>
+
+#ifdef IPSEC
+#ifdef __rtems__
+#include <freebsd/netipsec/ipsec.h>
+#include <freebsd/netipsec/ah_var.h>
+#include <freebsd/netipsec/esp_var.h>
+#include <freebsd/netipsec/ipcomp_var.h>
+#else
+#include <netipsec/ipsec.h>
+#include <netipsec/ah_var.h>
+#include <netipsec/esp_var.h>
+#include <netipsec/ipcomp_var.h>
+#endif
+#endif
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include "netstat.h"
+
+#ifdef IPSEC
+struct val2str {
+	int val;
+	const char *str;
+};
+
+static struct val2str ipsec_ahnames[] = {
+	{ 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", },
+#ifdef SADB_X_AALG_SHA2_256
+	{ SADB_X_AALG_SHA2_256, "hmac-sha2-256", },
+#endif
+#ifdef SADB_X_AALG_SHA2_384
+	{ SADB_X_AALG_SHA2_384, "hmac-sha2-384", },
+#endif
+#ifdef SADB_X_AALG_SHA2_512
+	{ SADB_X_AALG_SHA2_512, "hmac-sha2-512", },
+#endif
+#ifdef SADB_X_AALG_RIPEMD160HMAC
+	{ SADB_X_AALG_RIPEMD160HMAC, "hmac-ripemd160", },
+#endif
+#ifdef SADB_X_AALG_AES_XCBC_MAC
+	{ SADB_X_AALG_AES_XCBC_MAC, "aes-xcbc-mac", },
+#endif
+	{ -1, NULL },
+};
+
+static struct val2str ipsec_espnames[] = {
+	{ 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", },
+#ifdef SADB_X_EALG_RIJNDAELCBC
+	{ SADB_X_EALG_RIJNDAELCBC, "rijndael-cbc", },
+#endif
+#ifdef SADB_X_EALG_AESCTR
+	{ SADB_X_EALG_AESCTR, "aes-ctr", },
+#endif
+	{ -1, NULL },
+};
+
+static struct val2str ipsec_compnames[] = {
+	{ SADB_X_CALG_NONE, "none", },
+	{ SADB_X_CALG_OUI, "oui", },
+	{ SADB_X_CALG_DEFLATE, "deflate", },
+	{ SADB_X_CALG_LZS, "lzs", },
+	{ -1, NULL },
+};
+
+static void ipsec_hist(const u_quad_t *hist, size_t histmax,
+		       const struct val2str *name, const char *title);
+static void print_ipsecstats(const struct ipsecstat *ipsecstat);
+
+
+/*
+ * Dump IPSEC statistics structure.
+ */
+static void
+ipsec_hist(const u_quad_t *hist, size_t histmax, const struct val2str *name,
+	   const char *title)
+{
+	int first;
+	size_t proto;
+	const struct val2str *p;
+
+	first = 1;
+	for (proto = 0; proto < histmax; proto++) {
+		if (hist[proto] <= 0)
+			continue;
+		if (first) {
+			printf("\t%s histogram:\n", title);
+			first = 0;
+		}
+		for (p = name; p && p->str; p++) {
+			if (p->val == (int)proto)
+				break;
+		}
+		if (p && p->str) {
+			printf("\t\t%s: %ju\n", p->str, (uintmax_t)hist[proto]);
+		} else {
+			printf("\t\t#%ld: %ju\n", (long)proto,
+			    (uintmax_t)hist[proto]);
+		}
+	}
+}
+
+static void
+print_ipsecstats(const struct ipsecstat *ipsecstat)
+{
+#define	p(f, m) if (ipsecstat->f || sflag <= 1) \
+    printf(m, (uintmax_t)ipsecstat->f, plural(ipsecstat->f))
+#define	pes(f, m) if (ipsecstat->f || sflag <= 1) \
+    printf(m, (uintmax_t)ipsecstat->f, plurales(ipsecstat->f))
+#define	hist(f, n, t) \
+    ipsec_hist((f), sizeof(f)/sizeof(f[0]), (n), (t));
+
+	p(in_success, "\t%ju inbound packet%s processed successfully\n");
+	p(in_polvio, "\t%ju inbound packet%s violated process security "
+	    "policy\n");
+	p(in_nosa, "\t%ju inbound packet%s with no SA available\n");
+	p(in_inval, "\t%ju invalid inbound packet%s\n");
+	p(in_nomem, "\t%ju inbound packet%s failed due to insufficient memory\n");
+	p(in_badspi, "\t%ju inbound packet%s failed getting SPI\n");
+	p(in_ahreplay, "\t%ju inbound packet%s failed on AH replay check\n");
+	p(in_espreplay, "\t%ju inbound packet%s failed on ESP replay check\n");
+	p(in_ahauthsucc, "\t%ju inbound packet%s considered authentic\n");
+	p(in_ahauthfail, "\t%ju inbound packet%s failed on authentication\n");
+	hist(ipsecstat->in_ahhist, ipsec_ahnames, "AH input");
+	hist(ipsecstat->in_esphist, ipsec_espnames, "ESP input");
+	hist(ipsecstat->in_comphist, ipsec_compnames, "IPComp input");
+
+	p(out_success, "\t%ju outbound packet%s processed successfully\n");
+	p(out_polvio, "\t%ju outbound packet%s violated process security "
+	    "policy\n");
+	p(out_nosa, "\t%ju outbound packet%s with no SA available\n");
+	p(out_inval, "\t%ju invalid outbound packet%s\n");
+	p(out_nomem, "\t%ju outbound packet%s failed due to insufficient memory\n");
+	p(out_noroute, "\t%ju outbound packet%s with no route\n");
+	hist(ipsecstat->out_ahhist, ipsec_ahnames, "AH output");
+	hist(ipsecstat->out_esphist, ipsec_espnames, "ESP output");
+	hist(ipsecstat->out_comphist, ipsec_compnames, "IPComp output");
+	p(spdcachelookup, "\t%ju SPD cache lookup%s\n");
+	pes(spdcachemiss, "\t%ju SPD cache miss%s\n");
+#undef pes
+#undef hist
+	p(ips_in_polvio, "\t%ju inbound packet%s violated process "
+		"security policy\n");
+	p(ips_out_polvio, "\t%ju outbound packet%s violated process "
+		"security policy\n");
+	p(ips_out_nosa, "\t%ju outbound packet%s with no SA available\n");
+	p(ips_out_nomem, "\t%ju outbound packet%s failed due to "
+		"insufficient memory\n");
+	p(ips_out_noroute, "\t%ju outbound packet%s with no route "
+		"available\n");
+	p(ips_out_inval, "\t%ju invalid outbound packet%s\n");
+	p(ips_out_bundlesa, "\t%ju outbound packet%s with bundled SAs\n");
+	p(ips_mbcoalesced, "\t%ju mbuf%s coalesced during clone\n");
+	p(ips_clcoalesced, "\t%ju cluster%s coalesced during clone\n");
+	p(ips_clcopied, "\t%ju cluster%s copied during clone\n");
+	p(ips_mbinserted, "\t%ju mbuf%s inserted during makespace\n");
+#undef p
+}
+
+void
+ipsec_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+	struct ipsecstat ipsecstat;
+
+	if (off == 0)
+		return;
+	printf ("%s:\n", name);
+	kread(off, (char *)&ipsecstat, sizeof(ipsecstat));
+
+	print_ipsecstats(&ipsecstat);
+}
+
+
+static void ipsec_hist_new(const u_int32_t *hist, size_t histmax,
+			   const struct val2str *name, const char *title);
+static void print_ahstats(const struct ahstat *ahstat);
+static void print_espstats(const struct espstat *espstat);
+static void print_ipcompstats(const struct ipcompstat *ipcompstat);
+
+/*
+ * Dump IPSEC statistics structure.
+ */
+static void
+ipsec_hist_new(const u_int32_t *hist, size_t histmax,
+	       const struct val2str *name, const char *title)
+{
+	int first;
+	size_t proto;
+	const struct val2str *p;
+
+	first = 1;
+	for (proto = 0; proto < histmax; proto++) {
+		if (hist[proto] <= 0)
+			continue;
+		if (first) {
+			printf("\t%s histogram:\n", title);
+			first = 0;
+		}
+		for (p = name; p && p->str; p++) {
+			if (p->val == (int)proto)
+				break;
+		}
+		if (p && p->str) {
+			printf("\t\t%s: %u\n", p->str, hist[proto]);
+		} else {
+			printf("\t\t#%lu: %u\n", (unsigned long)proto,
+			       hist[proto]);
+		}
+	}
+}
+
+static void
+print_ahstats(const struct ahstat *ahstat)
+{
+#define	p32(f, m) if (ahstat->f || sflag <= 1) \
+    printf("\t%u" m, (unsigned int)ahstat->f, plural(ahstat->f))
+#define	p64(f, m) if (ahstat->f || sflag <= 1) \
+    printf("\t%ju" m, (uintmax_t)ahstat->f, plural(ahstat->f))
+#define	hist(f, n, t) \
+    ipsec_hist_new((f), sizeof(f)/sizeof(f[0]), (n), (t));
+
+	p32(ahs_hdrops, " packet%s shorter than header shows\n");
+	p32(ahs_nopf, " packet%s dropped; protocol family not supported\n");
+	p32(ahs_notdb, " packet%s dropped; no TDB\n");
+	p32(ahs_badkcr, " packet%s dropped; bad KCR\n");
+	p32(ahs_qfull, " packet%s dropped; queue full\n");
+	p32(ahs_noxform, " packet%s dropped; no transform\n");
+	p32(ahs_wrap, " replay counter wrap%s\n");
+	p32(ahs_badauth, " packet%s dropped; bad authentication detected\n");
+	p32(ahs_badauthl, " packet%s dropped; bad authentication length\n");
+	p32(ahs_replay, " possible replay packet%s detected\n");
+	p32(ahs_input, " packet%s in\n");
+	p32(ahs_output, " packet%s out\n");
+	p32(ahs_invalid, " packet%s dropped; invalid TDB\n");
+	p64(ahs_ibytes, " byte%s in\n");
+	p64(ahs_obytes, " byte%s out\n");
+	p32(ahs_toobig, " packet%s dropped; larger than IP_MAXPACKET\n");
+	p32(ahs_pdrops, " packet%s blocked due to policy\n");
+	p32(ahs_crypto, " crypto processing failure%s\n");
+	p32(ahs_tunnel, " tunnel sanity check failure%s\n");
+	hist(ahstat->ahs_hist, ipsec_ahnames, "AH output");
+
+#undef p32
+#undef p64
+#undef hist
+}
+
+void
+ah_stats(u_long off, const char *name, int family __unused, int proto __unused)
+{
+	struct ahstat ahstat;
+
+	if (off == 0)
+		return;
+	printf ("%s:\n", name);
+	kread(off, (char *)&ahstat, sizeof(ahstat));
+
+	print_ahstats(&ahstat);
+}
+
+static void
+print_espstats(const struct espstat *espstat)
+{
+#define	p32(f, m) if (espstat->f || sflag <= 1) \
+    printf("\t%u" m, (unsigned int)espstat->f, plural(espstat->f))
+#define	p64(f, m) if (espstat->f || sflag <= 1) \
+    printf("\t%ju" m, (uintmax_t)espstat->f, plural(espstat->f))
+#define	hist(f, n, t) \
+    ipsec_hist_new((f), sizeof(f)/sizeof(f[0]), (n), (t));
+
+	p32(esps_hdrops, " packet%s shorter than header shows\n");
+	p32(esps_nopf, " packet%s dropped; protocol family not supported\n");
+	p32(esps_notdb, " packet%s dropped; no TDB\n");
+	p32(esps_badkcr, " packet%s dropped; bad KCR\n");
+	p32(esps_qfull, " packet%s dropped; queue full\n");
+	p32(esps_noxform, " packet%s dropped; no transform\n");
+	p32(esps_badilen, " packet%s dropped; bad ilen\n");
+	p32(esps_wrap, " replay counter wrap%s\n");
+	p32(esps_badenc, " packet%s dropped; bad encryption detected\n");
+	p32(esps_badauth, " packet%s dropped; bad authentication detected\n");
+	p32(esps_replay, " possible replay packet%s detected\n");
+	p32(esps_input, " packet%s in\n");
+	p32(esps_output, " packet%s out\n");
+	p32(esps_invalid, " packet%s dropped; invalid TDB\n");
+	p64(esps_ibytes, " byte%s in\n");
+	p64(esps_obytes, " byte%s out\n");
+	p32(esps_toobig, " packet%s dropped; larger than IP_MAXPACKET\n");
+	p32(esps_pdrops, " packet%s blocked due to policy\n");
+	p32(esps_crypto, " crypto processing failure%s\n");
+	p32(esps_tunnel, " tunnel sanity check failure%s\n");
+	hist(espstat->esps_hist, ipsec_espnames, "ESP output");
+
+#undef p32
+#undef p64
+#undef hist
+}
+
+void
+esp_stats(u_long off, const char *name, int family __unused, int proto __unused)
+{
+	struct espstat espstat;
+
+	if (off == 0)
+		return;
+	printf ("%s:\n", name);
+	kread(off, (char *)&espstat, sizeof(espstat));
+
+	print_espstats(&espstat);
+}
+
+static void
+print_ipcompstats(const struct ipcompstat *ipcompstat)
+{
+	uint32_t version;
+#define	p32(f, m) if (ipcompstat->f || sflag <= 1) \
+    printf("\t%u" m, (unsigned int)ipcompstat->f, plural(ipcompstat->f))
+#define	p64(f, m) if (ipcompstat->f || sflag <= 1) \
+    printf("\t%ju" m, (uintmax_t)ipcompstat->f, plural(ipcompstat->f))
+#define	hist(f, n, t) \
+    ipsec_hist_new((f), sizeof(f)/sizeof(f[0]), (n), (t));
+
+#ifndef IPCOMPSTAT_VERSION
+	version = 0;
+#else
+	version = ipcompstat->version;
+#endif
+	p32(ipcomps_hdrops, " packet%s shorter than header shows\n");
+	p32(ipcomps_nopf, " packet%s dropped; protocol family not supported\n");
+	p32(ipcomps_notdb, " packet%s dropped; no TDB\n");
+	p32(ipcomps_badkcr, " packet%s dropped; bad KCR\n");
+	p32(ipcomps_qfull, " packet%s dropped; queue full\n");
+	p32(ipcomps_noxform, " packet%s dropped; no transform\n");
+	p32(ipcomps_wrap, " replay counter wrap%s\n");
+	p32(ipcomps_input, " packet%s in\n");
+	p32(ipcomps_output, " packet%s out\n");
+	p32(ipcomps_invalid, " packet%s dropped; invalid TDB\n");
+	p64(ipcomps_ibytes, " byte%s in\n");
+	p64(ipcomps_obytes, " byte%s out\n");
+	p32(ipcomps_toobig, " packet%s dropped; larger than IP_MAXPACKET\n");
+	p32(ipcomps_pdrops, " packet%s blocked due to policy\n");
+	p32(ipcomps_crypto, " crypto processing failure%s\n");
+	hist(ipcompstat->ipcomps_hist, ipsec_compnames, "COMP output");
+	if (version >= 1) {
+	p32(ipcomps_threshold, " packet%s sent uncompressed; size < compr. algo. threshold\n");
+	p32(ipcomps_uncompr, " packet%s sent uncompressed; compression was useless\n");
+	}
+
+#undef p32
+#undef p64
+#undef hist
+}
+
+void
+ipcomp_stats(u_long off, const char *name, int family __unused,
+    int proto __unused)
+{
+	struct ipcompstat ipcompstat;
+
+	if (off == 0)
+		return;
+	printf ("%s:\n", name);
+	kread(off, (char *)&ipcompstat, sizeof(ipcompstat));
+
+	print_ipcompstats(&ipcompstat);
+}
+
+#endif /*IPSEC*/
diff --git a/freebsd-userspace/commands/usr.bin/netstat/ipx.c b/freebsd-userspace/commands/usr.bin/netstat/ipx.c
new file mode 100644
index 0000000..b78b151
--- /dev/null
+++ b/freebsd-userspace/commands/usr.bin/netstat/ipx.c
@@ -0,0 +1,354 @@
+/*-
+ * Copyright (c) 2004, Robert N. M. Watson
+ * 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. 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.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)ns.c	8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+#endif
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#ifdef __rtems__
+#include <freebsd/sys/protosw.h>
+#else
+#include <sys/protosw.h>
+#endif
+
+#include <net/route.h>
+
+#define	TCPSTATES
+#include <netinet/tcp_fsm.h>
+
+#include <netipx/ipx.h>
+#include <netipx/ipx_pcb.h>
+#include <netipx/ipx_var.h>
+#ifdef IPXERRORMSGS
+#include <netipx/ipx_error.h>
+#endif
+#include <netipx/spx.h>
+#include <netipx/spx_timer.h>
+#include <netipx/spx_var.h>
+#define	SANAMES
+#include <netipx/spx_debug.h>
+
+#include <nlist.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include "netstat.h"
+
+static char *ipx_prpr(struct ipx_addr *);
+
+/*
+ * Print a summary of connections related to a Network Systems
+ * protocol.  For SPX, also give state of connection.
+ * Listening processes (aflag) are suppressed unless the
+ * -a (all) flag is specified.
+ */
+
+void
+ipxprotopr(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+	struct ipxpcbhead cb;
+	struct ipxpcb *ipxp;
+	struct ipxpcb ipxpcb;
+	struct spxpcb spxpcb;
+	struct socket sockb;
+	static int first = 1;
+	int isspx;
+
+	if (off == 0)
+		return;
+
+	isspx = strcmp(name, "spx") == 0;
+	kread(off, (char *)&cb, sizeof (struct ipxpcbhead));
+	ipxp = LIST_FIRST(&cb);
+	while (ipxp != NULL) {
+		u_long ppcb;
+
+		kread((u_long)ipxp, (char *)&ipxpcb, sizeof (ipxpcb));
+		ipxp = LIST_NEXT(&ipxpcb, ipxp_list);
+
+		if (!aflag && ipx_nullhost(ipxpcb.ipxp_faddr) ) {
+			continue;
+		}
+		kread((u_long)ipxpcb.ipxp_socket,
+				(char *)&sockb, sizeof (sockb));
+		ppcb = (u_long) ipxpcb.ipxp_pcb;
+		if (ppcb) {
+			if (isspx) {
+				kread(ppcb, (char *)&spxpcb, sizeof (spxpcb));
+			} else continue;
+		} else
+			if (isspx) continue;
+		if (first) {
+			printf("Active IPX connections");
+			if (aflag)
+				printf(" (including servers)");
+			putchar('\n');
+			if (Aflag)
+				printf("%-8.8s ", "PCB");
+			printf(Aflag ?
+				"%-5.5s %-6.6s %-6.6s  %-18.18s %-18.18s %s\n" :
+				"%-5.5s %-6.6s %-6.6s  %-22.22s %-22.22s %s\n",
+				"Proto", "Recv-Q", "Send-Q",
+				"Local Address", "Foreign Address", "(state)");
+			first = 0;
+		}
+		if (Aflag)
+			printf("%8lx ", ppcb);
+		printf("%-5.5s %6u %6u ", name, sockb.so_rcv.sb_cc,
+			sockb.so_snd.sb_cc);
+		printf(Aflag?" %-18.18s":" %-22.22s", ipx_prpr(&ipxpcb.ipxp_laddr));
+		printf(Aflag?" %-18.18s":" %-22.22s", ipx_prpr(&ipxpcb.ipxp_faddr));
+		if (isspx) {
+			if (spxpcb.s_state >= TCP_NSTATES)
+				printf(" %d", spxpcb.s_state);
+			else
+				printf(" %s", tcpstates[spxpcb.s_state]);
+		}
+		putchar('\n');
+	}
+}
+
+#define	ANY(x,y,z) \
+	    if (x || sflag <= 1) printf("\t%u %s%s%s\n", x, y, plural(x), z)
+#define	ANYl(x,y,z) \
+	    if (x || sflag <= 1) printf("\t%lu %s%s%s\n", x, y, plural(x), z)
+
+/*
+ * Dump SPX statistics structure.
+ */
+void
+spx_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+	struct spx_istat spx_istat;
+#define	spxstat spx_istat.newstats
+
+	if (off == 0)
+		return;
+	kread(off, (char *)&spx_istat, sizeof (spx_istat));
+	printf("%s:\n", name);
+	ANY(spx_istat.nonucn, "connection", " dropped due to no new sockets ");
+	ANY(spx_istat.gonawy, "connection", " terminated due to our end dying");
+	ANY(spx_istat.nonucn, "connection",
+	    " dropped due to inability to connect");
+	ANY(spx_istat.noconn, "connection",
+	    " dropped due to inability to connect");
+	ANY(spx_istat.notme, "connection",
+	    " incompleted due to mismatched id's");
+	ANY(spx_istat.wrncon, "connection", " dropped due to mismatched id's");
+	ANY(spx_istat.bdreas, "packet", " dropped out of sequence");
+	ANY(spx_istat.lstdup, "packet", " duplicating the highest packet");
+	ANY(spx_istat.notyet, "packet", " refused as exceeding allocation");
+	ANYl(spxstat.spxs_connattempt, "connection", " initiated");
+	ANYl(spxstat.spxs_accepts, "connection", " accepted");
+	ANYl(spxstat.spxs_connects, "connection", " established");
+	ANYl(spxstat.spxs_drops, "connection", " dropped");
+	ANYl(spxstat.spxs_conndrops, "embryonic connection", " dropped");
+	ANYl(spxstat.spxs_closed, "connection", " closed (includes drops)");
+	ANYl(spxstat.spxs_segstimed, "packet", " where we tried to get rtt");
+	ANYl(spxstat.spxs_rttupdated, "time", " we got rtt");
+	ANYl(spxstat.spxs_delack, "delayed ack", " sent");
+	ANYl(spxstat.spxs_timeoutdrop, "connection",
+	    " dropped in rxmt timeout");
+	ANYl(spxstat.spxs_rexmttimeo, "retransmit timeout", "");
+	ANYl(spxstat.spxs_persisttimeo, "persist timeout", "");
+	ANYl(spxstat.spxs_keeptimeo, "keepalive timeout", "");
+	ANYl(spxstat.spxs_keepprobe, "keepalive probe", " sent");
+	ANYl(spxstat.spxs_keepdrops, "connection", " dropped in keepalive");
+	ANYl(spxstat.spxs_sndtotal, "total packet", " sent");
+	ANYl(spxstat.spxs_sndpack, "data packet", " sent");
+	ANYl(spxstat.spxs_sndbyte, "data byte", " sent");
+	ANYl(spxstat.spxs_sndrexmitpack, "data packet", " retransmitted");
+	ANYl(spxstat.spxs_sndrexmitbyte, "data byte", " retransmitted");
+	ANYl(spxstat.spxs_sndacks, "ack-only packet", " sent");
+	ANYl(spxstat.spxs_sndprobe, "window probe", " sent");
+	ANYl(spxstat.spxs_sndurg, "packet", " sent with URG only");
+	ANYl(spxstat.spxs_sndwinup, "window update-only packet", " sent");
+	ANYl(spxstat.spxs_sndctrl, "control (SYN|FIN|RST) packet", " sent");
+	ANYl(spxstat.spxs_sndvoid, "request", " to send a non-existant packet");
+	ANYl(spxstat.spxs_rcvtotal, "total packet", " received");
+	ANYl(spxstat.spxs_rcvpack, "packet", " received in sequence");
+	ANYl(spxstat.spxs_rcvbyte, "byte", " received in sequence");
+	ANYl(spxstat.spxs_rcvbadsum, "packet", " received with ccksum errs");
+	ANYl(spxstat.spxs_rcvbadoff, "packet", " received with bad offset");
+	ANYl(spxstat.spxs_rcvshort, "packet", " received too short");
+	ANYl(spxstat.spxs_rcvduppack, "duplicate-only packet", " received");
+	ANYl(spxstat.spxs_rcvdupbyte, "duplicate-only byte", " received");
+	ANYl(spxstat.spxs_rcvpartduppack, "packet",
+	    " with some duplicate data");
+	ANYl(spxstat.spxs_rcvpartdupbyte, "dup. byte", " in part-dup. packet");
+	ANYl(spxstat.spxs_rcvoopack, "out-of-order packet", " received");
+	ANYl(spxstat.spxs_rcvoobyte, "out-of-order byte", " received");
+	ANYl(spxstat.spxs_rcvpackafterwin, "packet", " with data after window");
+	ANYl(spxstat.spxs_rcvbyteafterwin, "byte", " rcvd after window");
+	ANYl(spxstat.spxs_rcvafterclose, "packet", " rcvd after 'close'");
+	ANYl(spxstat.spxs_rcvwinprobe, "rcvd window probe packet", "");
+	ANYl(spxstat.spxs_rcvdupack, "rcvd duplicate ack", "");
+	ANYl(spxstat.spxs_rcvacktoomuch, "rcvd ack", " for unsent data");
+	ANYl(spxstat.spxs_rcvackpack, "rcvd ack packet", "");
+	ANYl(spxstat.spxs_rcvackbyte, "byte", " acked by rcvd acks");
+	ANYl(spxstat.spxs_rcvwinupd, "rcvd window update packet", "");
+}
+
+/*
+ * Dump IPX statistics structure.
+ */
+void
+ipx_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+	struct ipxstat ipxstat;
+
+	if (off == 0)
+		return;
+	kread(off, (char *)&ipxstat, sizeof (ipxstat));
+	printf("%s:\n", name);
+	ANYl(ipxstat.ipxs_total, "total packet", " received");
+	ANYl(ipxstat.ipxs_badsum, "packet", " with bad checksums");
+	ANYl(ipxstat.ipxs_tooshort, "packet", " smaller than advertised");
+	ANYl(ipxstat.ipxs_toosmall, "packet", " smaller than a header");
+	ANYl(ipxstat.ipxs_forward, "packet", " forwarded");
+	ANYl(ipxstat.ipxs_cantforward, "packet", " not forwardable");
+	ANYl(ipxstat.ipxs_delivered, "packet", " for this host");
+	ANYl(ipxstat.ipxs_localout, "packet", " sent from this host");
+	ANYl(ipxstat.ipxs_odropped, "packet", " dropped due to no bufs, etc.");
+	ANYl(ipxstat.ipxs_noroute, "packet", " discarded due to no route");
+	ANYl(ipxstat.ipxs_mtutoosmall, "packet", " too big");
+}
+
+#ifdef IPXERRORMSGS
+static	struct {
+	u_short code;
+	char *name;
+	char *where;
+} ipx_errnames[] = {
+	{0, "Unspecified Error", " at Destination"},
+	{1, "Bad Checksum", " at Destination"},
+	{2, "No Listener", " at Socket"},
+	{3, "Packet", " Refused due to lack of space at Destination"},
+	{01000, "Unspecified Error", " while gatewayed"},
+	{01001, "Bad Checksum", " while gatewayed"},
+	{01002, "Packet", " forwarded too many times"},
+	{01003, "Packet", " too large to be forwarded"},
+	{-1, 0, 0},
+};
+
+/*
+ * Dump IPX Error statistics structure.
+ */
+/*ARGSUSED*/
+void
+ipxerr_stats(u_long off, const char *name, int af __unused, int proto __unused)
+{
+	struct ipx_errstat ipx_errstat;
+	int j;
+	int histoprint = 1;
+	int z;
+
+	if (off == 0)
+		return;
+	kread(off, (char *)&ipx_errstat, sizeof (ipx_errstat));
+	printf("IPX error statistics:\n");
+	ANY(ipx_errstat.ipx_es_error, "call", " to ipx_error");
+	ANY(ipx_errstat.ipx_es_oldshort, "error",
+		" ignored due to insufficient addressing");
+	ANY(ipx_errstat.ipx_es_oldipx_err, "error request",
+		" in response to error packets");
+	ANY(ipx_errstat.ipx_es_tooshort, "error packet",
+		" received incomplete");
+	ANY(ipx_errstat.ipx_es_badcode, "error packet",
+		" received of unknown type");
+	for(j = 0; j < IPX_ERR_MAX; j ++) {
+		z = ipx_errstat.ipx_es_outhist[j];
+		if (z && histoprint) {
+			printf("Output Error Histogram:\n");
+			histoprint = 0;
+		}
+		ipx_erputil(z, ipx_errstat.ipx_es_codes[j]);
+	}
+	histoprint = 1;
+	for(j = 0; j < IPX_ERR_MAX; j ++) {
+		z = ipx_errstat.ipx_es_inhist[j];
+		if (z && histoprint) {
+			printf("Input Error Histogram:\n");
+			histoprint = 0;
+		}
+		ipx_erputil(z, ipx_errstat.ipx_es_codes[j]);
+	}
+}
+
+static void
+ipx_erputil(int z, int c)
+{
+	int j;
+	char codebuf[30];
+	char *name, *where;
+
+	for(j = 0;; j ++) {
+		if ((name = ipx_errnames[j].name) == 0)
+			break;
+		if (ipx_errnames[j].code == c)
+			break;
+	}
+	if (name == 0)  {
+		if (c > 01000)
+			where = "in transit";
+		else
+			where = "at destination";
+		sprintf(codebuf, "Unknown IPX error code 0%o", c);
+		name = codebuf;
+	} else
+		where =  ipx_errnames[j].where;
+	ANY(z, name, where);
+}
+#endif /* IPXERRORMSGS */
+
+static struct sockaddr_ipx ssipx = { .sipx_family = AF_IPX };
+
+static
+char *ipx_prpr(struct ipx_addr *x)
+{
+	struct sockaddr_ipx *sipx = &ssipx;
+
+	sipx->sipx_addr = *x;
+	return(ipx_print((struct sockaddr *)sipx));
+}
diff --git a/freebsd-userspace/commands/usr.bin/netstat/main.c b/freebsd-userspace/commands/usr.bin/netstat/main.c
new file mode 100644
index 0000000..09b26a2
--- /dev/null
+++ b/freebsd-userspace/commands/usr.bin/netstat/main.c
@@ -0,0 +1,805 @@
+/*-
+ * 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. 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.
+ */
+
+#ifndef lint
+char const copyright[] =
+"@(#) Copyright (c) 1983, 1988, 1993\n\
+	Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)main.c	8.4 (Berkeley) 3/1/94";
+#endif /* not lint */
+#endif
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/file.h>
+#ifdef __rtems__
+#include <freebsd/sys/protosw.h>
+#else
+#include <sys/protosw.h>
+#endif
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+
+#include <netinet/in.h>
+
+#ifdef NETGRAPH
+#include <netgraph/ng_socket.h>
+#endif
+
+#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 <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "netstat.h"
+
+static struct nlist nl[] = {
+#define	N_IFNET		0
+	{ .n_name = "_ifnet" },
+#define	N_RTSTAT	1
+	{ .n_name = "_rtstat" },
+#define	N_RTREE		2
+	{ .n_name = "_rt_tables"},
+#define	N_MRTSTAT	3
+	{ .n_name = "_mrtstat" },
+#define	N_MFCHASHTBL	4
+	{ .n_name = "_mfchashtbl" },
+#define	N_VIFTABLE	5
+	{ .n_name = "_viftable" },
+#define	N_IPX		6
+	{ .n_name = "_ipxpcb_list"},
+#define	N_IPXSTAT	7
+	{ .n_name = "_ipxstat"},
+#define	N_SPXSTAT	8
+	{ .n_name = "_spx_istat"},
+#define	N_DDPSTAT	9
+	{ .n_name = "_ddpstat"},
+#define	N_DDPCB		10
+	{ .n_name = "_ddpcb"},
+#define	N_NGSOCKS	11
+	{ .n_name = "_ngsocklist"},
+#define	N_IP6STAT	12
+	{ .n_name = "_ip6stat" },
+#define	N_ICMP6STAT	13
+	{ .n_name = "_icmp6stat" },
+#define	N_IPSECSTAT	14
+	{ .n_name = "_ipsec4stat" },
+#define	N_IPSEC6STAT	15
+	{ .n_name = "_ipsec6stat" },
+#define	N_PIM6STAT	16
+	{ .n_name = "_pim6stat" },
+#define	N_MRT6STAT	17
+	{ .n_name = "_mrt6stat" },
+#define	N_MF6CTABLE	18
+	{ .n_name = "_mf6ctable" },
+#define	N_MIF6TABLE	19
+	{ .n_name = "_mif6table" },
+#define	N_PFKEYSTAT	20
+	{ .n_name = "_pfkeystat" },
+#define	N_MBSTAT	21
+	{ .n_name = "_mbstat" },
+#define	N_MBTYPES	22
+	{ .n_name = "_mbtypes" },
+#define	N_NMBCLUSTERS	23
+	{ .n_name = "_nmbclusters" },
+#define	N_NMBUFS	24
+	{ .n_name = "_nmbufs" },
+#define	N_MBHI		25
+	{ .n_name = "_mbuf_hiwm" },
+#define	N_CLHI		26
+	{ .n_name = "_clust_hiwm" },
+#define	N_NCPUS		27
+	{ .n_name = "_smp_cpus" },
+#define	N_PAGESZ	28
+	{ .n_name = "_pagesize" },
+#define	N_MBPSTAT	29
+	{ .n_name = "_mb_statpcpu" },
+#define	N_RTTRASH	30
+	{ .n_name = "_rttrash" },
+#define	N_MBLO		31
+	{ .n_name = "_mbuf_lowm" },
+#define	N_CLLO		32
+	{ .n_name = "_clust_lowm" },
+#define	N_CARPSTAT	33
+	{ .n_name = "_carpstats" },
+#define	N_PFSYNCSTAT	34
+	{ .n_name = "_pfsyncstats" },
+#define	N_AHSTAT	35
+	{ .n_name = "_ahstat" },
+#define	N_ESPSTAT	36
+	{ .n_name = "_espstat" },
+#define	N_IPCOMPSTAT	37
+	{ .n_name = "_ipcompstat" },
+#define	N_TCPSTAT	38
+	{ .n_name = "_tcpstat" },
+#define	N_UDPSTAT	39
+	{ .n_name = "_udpstat" },
+#define	N_IPSTAT	40
+	{ .n_name = "_ipstat" },
+#define	N_ICMPSTAT	41
+	{ .n_name = "_icmpstat" },
+#define	N_IGMPSTAT	42
+	{ .n_name = "_igmpstat" },
+#define	N_PIMSTAT	43
+	{ .n_name = "_pimstat" },
+#define	N_TCBINFO	44
+	{ .n_name = "_tcbinfo" },
+#define	N_UDBINFO	45
+	{ .n_name = "_udbinfo" },
+#define	N_DIVCBINFO	46
+	{ .n_name = "_divcbinfo" },
+#define	N_RIPCBINFO	47
+	{ .n_name = "_ripcbinfo" },
+#define	N_UNP_COUNT	48
+	{ .n_name = "_unp_count" },
+#define	N_UNP_GENCNT	49
+	{ .n_name = "_unp_gencnt" },
+#define	N_UNP_DHEAD	50
+	{ .n_name = "_unp_dhead" },
+#define	N_UNP_SHEAD	51
+	{ .n_name = "_unp_shead" },
+#define	N_RIP6STAT	52
+	{ .n_name = "_rip6stat" },
+#define	N_SCTPSTAT	53
+	{ .n_name = "_sctpstat" },
+#define	N_MFCTABLESIZE	54
+	{ .n_name = "_mfctablesize" },
+#define N_ARPSTAT       55
+	{ .n_name = "_arpstat" },
+	{ .n_name = NULL },
+};
+
+struct protox {
+	int	pr_index;		/* index into nlist of cb head */
+	int	pr_sindex;		/* index into nlist of stat block */
+	u_char	pr_wanted;		/* 1 if wanted, 0 otherwise */
+	void	(*pr_cblocks)(u_long, const char *, int, int);
+					/* control blocks printing routine */
+	void	(*pr_stats)(u_long, const char *, int, int);
+					/* statistics printing routine */
+	void	(*pr_istats)(char *);	/* per/if statistics printing routine */
+	const char	*pr_name;		/* well-known name */
+	int	pr_usesysctl;		/* non-zero if we use sysctl, not kvm */
+	int	pr_protocol;
+} protox[] = {
+	{ N_TCBINFO,	N_TCPSTAT,	1,	protopr,
+	  tcp_stats,	NULL,		"tcp",	1,	IPPROTO_TCP },
+	{ N_UDBINFO,	N_UDPSTAT,	1,	protopr,
+	  udp_stats,	NULL,		"udp",	1,	IPPROTO_UDP },
+#ifdef SCTP
+	{ -1,		N_SCTPSTAT,	1,	sctp_protopr,
+	  sctp_stats,	NULL,		"sctp",	1,	IPPROTO_SCTP },
+#endif
+	{ N_DIVCBINFO,	-1,		1,	protopr,
+	  NULL,		NULL,		"divert", 1,	IPPROTO_DIVERT },
+	{ N_RIPCBINFO,	N_IPSTAT,	1,	protopr,
+	  ip_stats,	NULL,		"ip",	1,	IPPROTO_RAW },
+	{ N_RIPCBINFO,	N_ICMPSTAT,	1,	protopr,
+	  icmp_stats,	NULL,		"icmp",	1,	IPPROTO_ICMP },
+	{ N_RIPCBINFO,	N_IGMPSTAT,	1,	protopr,
+	  igmp_stats,	NULL,		"igmp",	1,	IPPROTO_IGMP },
+#ifdef IPSEC
+	{ -1,		N_IPSECSTAT,	1,	NULL,	/* keep as compat */
+	  ipsec_stats,	NULL,		"ipsec", 0,	0},
+	{ -1,		N_AHSTAT,	1,	NULL,
+	  ah_stats,	NULL,		"ah",	0,	0},
+	{ -1,		N_ESPSTAT,	1,	NULL,
+	  esp_stats,	NULL,		"esp",	0,	0},
+	{ -1,		N_IPCOMPSTAT,	1,	NULL,
+	  ipcomp_stats,	NULL,		"ipcomp", 0,	0},
+#endif
+	{ N_RIPCBINFO,	N_PIMSTAT,	1,	protopr,
+	  pim_stats,	NULL,		"pim",	1,	IPPROTO_PIM },
+	{ -1,		N_CARPSTAT,	1,	NULL,
+	  carp_stats,	NULL,		"carp",	1,	0 },
+	{ -1,		N_PFSYNCSTAT,	1,	NULL,
+	  pfsync_stats,	NULL,		"pfsync", 1,	0 },
+	{ -1,		N_ARPSTAT,	1,	NULL,
+	  arp_stats,	NULL,		"arp", 1,	0 },
+	{ -1,		-1,		0,	NULL,
+	  NULL,		NULL,		NULL,	0,	0 }
+};
+
+#ifdef INET6
+struct protox ip6protox[] = {
+	{ N_TCBINFO,	N_TCPSTAT,	1,	protopr,
+	  tcp_stats,	NULL,		"tcp",	1,	IPPROTO_TCP },
+	{ N_UDBINFO,	N_UDPSTAT,	1,	protopr,
+	  udp_stats,	NULL,		"udp",	1,	IPPROTO_UDP },
+	{ N_RIPCBINFO,	N_IP6STAT,	1,	protopr,
+	  ip6_stats,	ip6_ifstats,	"ip6",	1,	IPPROTO_RAW },
+	{ N_RIPCBINFO,	N_ICMP6STAT,	1,	protopr,
+	  icmp6_stats,	icmp6_ifstats,	"icmp6", 1,	IPPROTO_ICMPV6 },
+#ifdef IPSEC
+	{ -1,		N_IPSEC6STAT,	1,	NULL,
+	  ipsec_stats,	NULL,		"ipsec6", 0,	0 },
+#endif
+#ifdef notyet
+	{ -1,		N_PIM6STAT,	1,	NULL,
+	  pim6_stats,	NULL,		"pim6",	1,	0 },
+#endif
+	{ -1,		N_RIP6STAT,	1,	NULL,
+	  rip6_stats,	NULL,		"rip6",	1,	0 },
+	{ -1,		-1,		0,	NULL,
+	  NULL,		NULL,		NULL,	0,	0 }
+};
+#endif /*INET6*/
+
+#ifdef IPSEC
+struct protox pfkeyprotox[] = {
+	{ -1,		N_PFKEYSTAT,	1,	NULL,
+	  pfkey_stats,	NULL,		"pfkey", 0,	0 },
+	{ -1,		-1,		0,	NULL,
+	  NULL,		NULL,		NULL,	0,	0 }
+};
+#endif
+
+struct protox atalkprotox[] = {
+	{ N_DDPCB,	N_DDPSTAT,	1,	atalkprotopr,
+	  ddp_stats,	NULL,		"ddp",	0,	0 },
+	{ -1,		-1,		0,	NULL,
+	  NULL,		NULL,		NULL,	0,	0 }
+};
+#ifdef NETGRAPH
+struct protox netgraphprotox[] = {
+	{ N_NGSOCKS,	-1,		1,	netgraphprotopr,
+	  NULL,		NULL,		"ctrl",	0,	0 },
+	{ N_NGSOCKS,	-1,		1,	netgraphprotopr,
+	  NULL,		NULL,		"data",	0,	0 },
+	{ -1,		-1,		0,	NULL,
+	  NULL,		NULL,		NULL,	0,	0 }
+};
+#endif
+#ifdef IPX
+struct protox ipxprotox[] = {
+	{ N_IPX,	N_IPXSTAT,	1,	ipxprotopr,
+	  ipx_stats,	NULL,		"ipx",	0,	0 },
+	{ N_IPX,	N_SPXSTAT,	1,	ipxprotopr,
+	  spx_stats,	NULL,		"spx",	0,	0 },
+	{ -1,		-1,		0,	NULL,
+	  NULL,		NULL,		0,	0,	0 }
+};
+#endif
+
+struct protox *protoprotox[] = {
+					 protox,
+#ifdef INET6
+					 ip6protox,
+#endif
+#ifdef IPSEC
+					 pfkeyprotox,
+#endif
+#ifdef IPX
+					 ipxprotox,
+#endif
+					 atalkprotox, NULL };
+
+static void printproto(struct protox *, const char *);
+static void usage(void);
+static struct protox *name2protox(const char *);
+static struct protox *knownname(const char *);
+
+static kvm_t *kvmd;
+static char *nlistf = NULL, *memf = NULL;
+
+int	Aflag;		/* show addresses of protocol control block */
+int	aflag;		/* show all sockets (including servers) */
+int	Bflag;		/* show information about bpf consumers */
+int	bflag;		/* show i/f total bytes in/out */
+int	dflag;		/* show i/f dropped packets */
+int	gflag;		/* show group (multicast) routing or stats */
+int	hflag;		/* show counters in human readable format */
+int	iflag;		/* show interfaces */
+int	Lflag;		/* show size of listen queues */
+int	mflag;		/* show memory stats */
+int	noutputs = 0;	/* how much outputs before we exit */
+int	numeric_addr;	/* show addresses numerically */
+int	numeric_port;	/* show ports numerically */
+static int pflag;	/* show given protocol */
+int	rflag;		/* show routing tables (or routing stats) */
+int	sflag;		/* show protocol statistics */
+int	tflag;		/* show i/f watchdog timers */
+int	Wflag;		/* wide display */
+int	xflag;		/* extra information, includes all socket buffer info */
+int	zflag;		/* zero stats */
+
+int	interval;	/* repeat interval for i/f stats */
+
+char	*interface;	/* desired i/f for stats, or NULL for all i/fs */
+int	unit;		/* unit number for above */
+
+int	af;		/* address family */
+int	live;		/* true if we are examining a live system */
+
+int
+main(int argc, char *argv[])
+{
+	struct protox *tp = NULL;  /* for printing cblocks & stats */
+	int ch;
+
+	af = AF_UNSPEC;
+
+	while ((ch = getopt(argc, argv, "AaBbdf:ghI:iLlM:mN:np:q:rSstuWw:xz")) != -1)
+		switch(ch) {
+		case 'A':
+			Aflag = 1;
+			break;
+		case 'a':
+			aflag = 1;
+			break;
+		case 'B':
+			Bflag = 1;
+			break;
+		case 'b':
+			bflag = 1;
+			break;
+		case 'd':
+			dflag = 1;
+			break;
+		case 'f':
+			if (strcmp(optarg, "ipx") == 0)
+				af = AF_IPX;
+			else if (strcmp(optarg, "inet") == 0)
+				af = AF_INET;
+#ifdef INET6
+			else if (strcmp(optarg, "inet6") == 0)
+				af = AF_INET6;
+#endif
+#ifdef IPSEC
+			else if (strcmp(optarg, "pfkey") == 0)
+				af = PF_KEY;
+#endif
+			else if (strcmp(optarg, "unix") == 0)
+				af = AF_UNIX;
+			else if (strcmp(optarg, "atalk") == 0)
+				af = AF_APPLETALK;
+#ifdef NETGRAPH
+			else if (strcmp(optarg, "ng") == 0
+			    || strcmp(optarg, "netgraph") == 0)
+				af = AF_NETGRAPH;
+#endif
+			else if (strcmp(optarg, "link") == 0)
+				af = AF_LINK;
+			else {
+				errx(1, "%s: unknown address family", optarg);
+			}
+			break;
+		case 'g':
+			gflag = 1;
+			break;
+		case 'h':
+			hflag = 1;
+			break;
+		case 'I': {
+			char *cp;
+
+			iflag = 1;
+			for (cp = interface = optarg; isalpha(*cp); cp++)
+				continue;
+			unit = atoi(cp);
+			break;
+		}
+		case 'i':
+			iflag = 1;
+			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 = 1;
+			break;
+		case 'p':
+			if ((tp = name2protox(optarg)) == NULL) {
+				errx(1,
+				     "%s: unknown or uninstrumented protocol",
+				     optarg);
+			}
+			pflag = 1;
+			break;
+		case 'q':
+			noutputs = atoi(optarg);
+			if (noutputs != 0)
+				noutputs++;
+			break;
+		case 'r':
+			rflag = 1;
+			break;
+		case 's':
+			++sflag;
+			break;
+		case 'S':
+			numeric_addr = 1;
+			break;
+		case 't':
+			tflag = 1;
+			break;
+		case 'u':
+			af = AF_UNIX;
+			break;
+		case 'W':
+		case 'l':
+			Wflag = 1;
+			break;
+		case 'w':
+			interval = atoi(optarg);
+			iflag = 1;
+			break;
+		case 'x':
+			xflag = 1;
+			break;
+		case 'z':
+			zflag = 1;
+			break;
+		case '?':
+		default:
+			usage();
+		}
+	argv += optind;
+	argc -= optind;
+
+#define	BACKWARD_COMPATIBILITY
+#ifdef	BACKWARD_COMPATIBILITY
+	if (*argv) {
+		if (isdigit(**argv)) {
+			interval = atoi(*argv);
+			if (interval <= 0)
+				usage();
+			++argv;
+			iflag = 1;
+		}
+		if (*argv) {
+			nlistf = *argv;
+			if (*++argv)
+				memf = *argv;
+		}
+	}
+#endif
+
+	/*
+	 * Discard setgid privileges if not the running kernel so that bad
+	 * guys can't print interesting stuff from kernel memory.
+	 */
+	live = (nlistf == NULL && memf == NULL);
+	if (!live)
+		setgid(getgid());
+
+	if (Bflag) {
+		if (!live)
+			usage();
+		bpf_stats(interface);
+		exit(0);
+	}
+	if (mflag) {
+		if (!live) {
+			if (kread(0, NULL, 0) == 0)
+				mbpr(kvmd, nl[N_MBSTAT].n_value);
+		} else
+			mbpr(NULL, 0);
+		exit(0);
+	}
+#if 0
+	/*
+	 * Keep file descriptors open to avoid overhead
+	 * of open/close on each call to get* routines.
+	 */
+	sethostent(1);
+	setnetent(1);
+#else
+	/*
+	 * This does not make sense any more with DNS being default over
+	 * the files.  Doing a setXXXXent(1) causes a tcp connection to be
+	 * used for the queries, which is slower.
+	 */
+#endif
+	kread(0, NULL, 0);
+	if (iflag && !sflag) {
+		intpr(interval, nl[N_IFNET].n_value, NULL);
+		exit(0);
+	}
+	if (rflag) {
+		if (sflag)
+			rt_stats(nl[N_RTSTAT].n_value, nl[N_RTTRASH].n_value);
+		else
+			routepr(nl[N_RTREE].n_value);
+		exit(0);
+	}
+	if (gflag) {
+		if (sflag) {
+			if (af == AF_INET || af == AF_UNSPEC)
+				mrt_stats(nl[N_MRTSTAT].n_value);
+#ifdef INET6
+			if (af == AF_INET6 || af == AF_UNSPEC)
+				mrt6_stats(nl[N_MRT6STAT].n_value);
+#endif
+		} else {
+			if (af == AF_INET || af == AF_UNSPEC)
+				mroutepr(nl[N_MFCHASHTBL].n_value,
+					 nl[N_MFCTABLESIZE].n_value,
+					 nl[N_VIFTABLE].n_value);
+#ifdef INET6
+			if (af == AF_INET6 || af == AF_UNSPEC)
+				mroute6pr(nl[N_MF6CTABLE].n_value,
+					  nl[N_MIF6TABLE].n_value);
+#endif
+		}
+		exit(0);
+	}
+
+	if (tp) {
+		printproto(tp, tp->pr_name);
+		exit(0);
+	}
+	if (af == AF_INET || af == AF_UNSPEC)
+		for (tp = protox; tp->pr_name; tp++)
+			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 /*INET6*/
+#ifdef IPSEC
+	if (af == PF_KEY || af == AF_UNSPEC)
+		for (tp = pfkeyprotox; tp->pr_name; tp++)
+			printproto(tp, tp->pr_name);
+#endif /*IPSEC*/
+#ifdef IPX
+	if (af == AF_IPX || af == AF_UNSPEC) {
+		for (tp = ipxprotox; tp->pr_name; tp++)
+			printproto(tp, tp->pr_name);
+	}
+#endif /* IPX */
+	if (af == AF_APPLETALK || af == AF_UNSPEC)
+		for (tp = atalkprotox; tp->pr_name; tp++)
+			printproto(tp, tp->pr_name);
+#ifdef NETGRAPH
+	if (af == AF_NETGRAPH || af == AF_UNSPEC)
+		for (tp = netgraphprotox; tp->pr_name; tp++)
+			printproto(tp, tp->pr_name);
+#endif /* NETGRAPH */
+	if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag)
+		unixpr(nl[N_UNP_COUNT].n_value, nl[N_UNP_GENCNT].n_value,
+		    nl[N_UNP_DHEAD].n_value, nl[N_UNP_SHEAD].n_value);
+	exit(0);
+}
+
+/*
+ * 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(tp, name)
+	struct protox *tp;
+	const char *name;
+{
+	void (*pr)(u_long, const char *, int, int);
+	u_long off;
+
+	if (sflag) {
+		if (iflag) {
+			if (tp->pr_istats)
+				intpr(interval, nl[N_IFNET].n_value,
+				      tp->pr_istats);
+			else if (pflag)
+				printf("%s: no per-interface stats routine\n",
+				    tp->pr_name);
+			return;
+		} else {
+			pr = tp->pr_stats;
+			if (!pr) {
+				if (pflag)
+					printf("%s: no stats routine\n",
+					    tp->pr_name);
+				return;
+			}
+			if (tp->pr_usesysctl && live)
+				off = 0;
+			else if (tp->pr_sindex < 0) {
+				if (pflag)
+					printf(
+				    "%s: stats routine doesn't work on cores\n",
+					    tp->pr_name);
+				return;
+			} else
+				off = nl[tp->pr_sindex].n_value;
+		}
+	} else {
+		pr = tp->pr_cblocks;
+		if (!pr) {
+			if (pflag)
+				printf("%s: no PCB routine\n", tp->pr_name);
+			return;
+		}
+		if (tp->pr_usesysctl && live)
+			off = 0;
+		else if (tp->pr_index < 0) {
+			if (pflag)
+				printf(
+				    "%s: PCB routine doesn't work on cores\n",
+				    tp->pr_name);
+			return;
+		} else
+			off = nl[tp->pr_index].n_value;
+	}
+	if (pr != NULL && (off || (live && tp->pr_usesysctl) ||
+	    af != AF_UNSPEC))
+		(*pr)(off, name, af, tp->pr_protocol);
+}
+
+/*
+ * Read kernel memory, return 0 on success.
+ */
+int
+kread(u_long addr, void *buf, size_t size)
+{
+	char errbuf[_POSIX2_LINE_MAX];
+
+	if (kvmd == NULL) {
+		kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
+		setgid(getgid());
+		if (kvmd != NULL) {
+			if (kvm_nlist(kvmd, nl) < 0) {
+				if (nlistf)
+					errx(1, "%s: kvm_nlist: %s", nlistf,
+					     kvm_geterr(kvmd));
+				else
+					errx(1, "kvm_nlist: %s", kvm_geterr(kvmd));
+			}
+
+			if (nl[0].n_type == 0) {
+				if (nlistf)
+					errx(1, "%s: no namelist", nlistf);
+				else
+					errx(1, "no namelist");
+			}
+		} else {
+			warnx("kvm not available: %s", errbuf);
+			return(-1);
+		}
+	}
+	if (!buf)
+		return (0);
+	if (kvm_read(kvmd, addr, buf, size) != (ssize_t)size) {
+		warnx("%s", kvm_geterr(kvmd));
+		return (-1);
+	}
+	return (0);
+}
+
+const char *
+plural(uintmax_t n)
+{
+	return (n != 1 ? "s" : "");
+}
+
+const char *
+plurales(uintmax_t n)
+{
+	return (n != 1 ? "es" : "");
+}
+
+const char *
+pluralies(uintmax_t n)
+{
+	return (n != 1 ? "ies" : "y");
+}
+
+/*
+ * 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)
+{
+	(void)fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
+"usage: netstat [-AaLnSWx] [-f protocol_family | -p protocol]\n"
+"               [-M core] [-N system]",
+"       netstat -i | -I interface [-abdhntW] [-f address_family]\n"
+"               [-M core] [-N system]",
+"       netstat -w wait [-I interface] [-d] [-M core] [-N system] [-q howmany]",
+"       netstat -s [-s] [-z] [-f protocol_family | -p protocol]\n"
+"               [-M core] [-N system]",
+"       netstat -i | -I interface -s [-f protocol_family | -p protocol]\n"
+"               [-M core] [-N system]",
+"       netstat -m [-M core] [-N system]",
+"       netstat -B [-I interface]",
+"       netstat -r [-AanW] [-f address_family] [-M core] [-N system]",
+"       netstat -rs [-s] [-M core] [-N system]",
+"       netstat -g [-W] [-f address_family] [-M core] [-N system]",
+"       netstat -gs [-s] [-f address_family] [-M core] [-N system]");
+	exit(1);
+}
diff --git a/freebsd-userspace/commands/usr.bin/netstat/mbuf.c b/freebsd-userspace/commands/usr.bin/netstat/mbuf.c
new file mode 100644
index 0000000..dd10525
--- /dev/null
+++ b/freebsd-userspace/commands/usr.bin/netstat/mbuf.c
@@ -0,0 +1,323 @@
+/*-
+ * Copyright (c) 1983, 1988, 1993
+ *	The Regents of the University of California.
+ * Copyright (c) 2005 Robert N. M. Watson
+ * 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. 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.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)mbuf.c	8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+#endif
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#ifdef __rtems__
+#include <stdint.h>
+#include <freebsd/sys/mbuf.h>
+#include <freebsd/sys/protosw.h>
+#else
+#include <sys/mbuf.h>
+#include <sys/protosw.h>
+#endif
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/sysctl.h>
+
+#include <err.h>
+#ifdef __rtems__
+/* XXX what to do? */
+#else
+#include <kvm.h>
+#include <memstat.h>
+#endif
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "netstat.h"
+
+/*
+ * Print mbuf statistics.
+ */
+void
+mbpr(void *kvmd, u_long mbaddr)
+{
+	struct memory_type_list *mtlp;
+	struct memory_type *mtp;
+	uintmax_t mbuf_count, mbuf_bytes, mbuf_free, mbuf_failures, mbuf_size;
+	uintmax_t cluster_count, cluster_bytes, cluster_limit, cluster_free;
+	uintmax_t cluster_failures, cluster_size;
+	uintmax_t packet_count, packet_bytes, packet_free, packet_failures;
+	uintmax_t tag_count, tag_bytes;
+	uintmax_t jumbop_count, jumbop_bytes, jumbop_limit, jumbop_free;
+	uintmax_t jumbop_failures, jumbop_size;
+	uintmax_t jumbo9_count, jumbo9_bytes, jumbo9_limit, jumbo9_free;
+	uintmax_t jumbo9_failures, jumbo9_size;
+	uintmax_t jumbo16_count, jumbo16_bytes, jumbo16_limit, jumbo16_free;
+	uintmax_t jumbo16_failures, jumbo16_size;
+	uintmax_t bytes_inuse, bytes_incache, bytes_total;
+	int nsfbufs, nsfbufspeak, nsfbufsused;
+	struct mbstat mbstat;
+	size_t mlen;
+	int error;
+
+	mtlp = memstat_mtl_alloc();
+	if (mtlp == NULL) {
+		warn("memstat_mtl_alloc");
+		return;
+	}
+
+	/*
+	 * Use memstat_*_all() because some mbuf-related memory is in uma(9),
+	 * and some malloc(9).
+	 */
+	if (live) {
+		if (memstat_sysctl_all(mtlp, 0) < 0) {
+			warnx("memstat_sysctl_all: %s",
+			    memstat_strerror(memstat_mtl_geterror(mtlp)));
+			goto out;
+		}
+	} else {
+		if (memstat_kvm_all(mtlp, kvmd) < 0) {
+			error = memstat_mtl_geterror(mtlp);
+			if (error == MEMSTAT_ERROR_KVM)
+				warnx("memstat_kvm_all: %s",
+				    kvm_geterr(kvmd));
+			else
+				warnx("memstat_kvm_all: %s",
+				    memstat_strerror(error));
+			goto out;
+		}
+	}
+
+	mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_MEM_NAME);
+	if (mtp == NULL) {
+		warnx("memstat_mtl_find: zone %s not found", MBUF_MEM_NAME);
+		goto out;
+	}
+	mbuf_count = memstat_get_count(mtp);
+	mbuf_bytes = memstat_get_bytes(mtp);
+	mbuf_free = memstat_get_free(mtp);
+	mbuf_failures = memstat_get_failures(mtp);
+	mbuf_size = memstat_get_size(mtp);
+
+	mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_PACKET_MEM_NAME);
+	if (mtp == NULL) {
+		warnx("memstat_mtl_find: zone %s not found",
+		    MBUF_PACKET_MEM_NAME);
+		goto out;
+	}
+	packet_count = memstat_get_count(mtp);
+	packet_bytes = memstat_get_bytes(mtp);
+	packet_free = memstat_get_free(mtp);
+	packet_failures = memstat_get_failures(mtp);
+
+	mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_CLUSTER_MEM_NAME);
+	if (mtp == NULL) {
+		warnx("memstat_mtl_find: zone %s not found",
+		    MBUF_CLUSTER_MEM_NAME);
+		goto out;
+	}
+	cluster_count = memstat_get_count(mtp);
+	cluster_bytes = memstat_get_bytes(mtp);
+	cluster_limit = memstat_get_countlimit(mtp);
+	cluster_free = memstat_get_free(mtp);
+	cluster_failures = memstat_get_failures(mtp);
+	cluster_size = memstat_get_size(mtp);
+
+	mtp = memstat_mtl_find(mtlp, ALLOCATOR_MALLOC, MBUF_TAG_MEM_NAME);
+	if (mtp == NULL) {
+		warnx("memstat_mtl_find: malloc type %s not found",
+		    MBUF_TAG_MEM_NAME);
+		goto out;
+	}
+	tag_count = memstat_get_count(mtp);
+	tag_bytes = memstat_get_bytes(mtp);
+
+	mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_JUMBOP_MEM_NAME);
+	if (mtp == NULL) {
+		warnx("memstat_mtl_find: zone %s not found",
+		    MBUF_JUMBOP_MEM_NAME);
+		goto out;
+	}
+	jumbop_count = memstat_get_count(mtp);
+	jumbop_bytes = memstat_get_bytes(mtp);
+	jumbop_limit = memstat_get_countlimit(mtp);
+	jumbop_free = memstat_get_free(mtp);
+	jumbop_failures = memstat_get_failures(mtp);
+	jumbop_size = memstat_get_size(mtp);
+
+	mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_JUMBO9_MEM_NAME);
+	if (mtp == NULL) {
+		warnx("memstat_mtl_find: zone %s not found",
+		    MBUF_JUMBO9_MEM_NAME);
+		goto out;
+	}
+	jumbo9_count = memstat_get_count(mtp);
+	jumbo9_bytes = memstat_get_bytes(mtp);
+	jumbo9_limit = memstat_get_countlimit(mtp);
+	jumbo9_free = memstat_get_free(mtp);
+	jumbo9_failures = memstat_get_failures(mtp);
+	jumbo9_size = memstat_get_size(mtp);
+
+	mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_JUMBO16_MEM_NAME);
+	if (mtp == NULL) {
+		warnx("memstat_mtl_find: zone %s not found",
+		    MBUF_JUMBO16_MEM_NAME);
+		goto out;
+	}
+	jumbo16_count = memstat_get_count(mtp);
+	jumbo16_bytes = memstat_get_bytes(mtp);
+	jumbo16_limit = memstat_get_countlimit(mtp);
+	jumbo16_free = memstat_get_free(mtp);
+	jumbo16_failures = memstat_get_failures(mtp);
+	jumbo16_size = memstat_get_size(mtp);
+
+	printf("%ju/%ju/%ju mbufs in use (current/cache/total)\n",
+	    mbuf_count + packet_count, mbuf_free + packet_free,
+	    mbuf_count + packet_count + mbuf_free + packet_free);
+
+	printf("%ju/%ju/%ju/%ju mbuf clusters in use "
+	    "(current/cache/total/max)\n",
+	    cluster_count - packet_free, cluster_free + packet_free,
+	    cluster_count + cluster_free, cluster_limit);
+
+	printf("%ju/%ju mbuf+clusters out of packet secondary zone in use "
+	    "(current/cache)\n",
+	    packet_count, packet_free);
+
+	printf("%ju/%ju/%ju/%ju %juk (page size) jumbo clusters in use "
+	    "(current/cache/total/max)\n",
+	    jumbop_count, jumbop_free, jumbop_count + jumbop_free,
+	    jumbop_limit, jumbop_size / 1024);
+
+	printf("%ju/%ju/%ju/%ju 9k jumbo clusters in use "
+	    "(current/cache/total/max)\n",
+	    jumbo9_count, jumbo9_free, jumbo9_count + jumbo9_free,
+	    jumbo9_limit);
+
+	printf("%ju/%ju/%ju/%ju 16k jumbo clusters in use "
+	    "(current/cache/total/max)\n",
+	    jumbo16_count, jumbo16_free, jumbo16_count + jumbo16_free,
+	    jumbo16_limit);
+
+#if 0
+	printf("%ju mbuf tags in use\n", tag_count);
+#endif
+
+	/*-
+	 * Calculate in-use bytes as:
+	 * - straight mbuf memory
+	 * - mbuf memory in packets
+	 * - the clusters attached to packets
+	 * - and the rest of the non-packet-attached clusters.
+	 * - m_tag memory
+	 * This avoids counting the clusters attached to packets in the cache.
+	 * This currently excludes sf_buf space.
+	 */
+	bytes_inuse =
+	    mbuf_bytes +			/* straight mbuf memory */
+	    packet_bytes +			/* mbufs in packets */
+	    (packet_count * cluster_size) +	/* clusters in packets */
+	    /* other clusters */
+	    ((cluster_count - packet_count - packet_free) * cluster_size) +
+	    tag_bytes +
+	    (jumbop_count * jumbop_size) +	/* jumbo clusters */
+	    (jumbo9_count * jumbo9_size) +
+	    (jumbo16_count * jumbo16_size);
+
+	/*
+	 * Calculate in-cache bytes as:
+	 * - cached straught mbufs
+	 * - cached packet mbufs
+	 * - cached packet clusters
+	 * - cached straight clusters
+	 * This currently excludes sf_buf space.
+	 */
+	bytes_incache =
+	    (mbuf_free * mbuf_size) +		/* straight free mbufs */
+	    (packet_free * mbuf_size) +		/* mbufs in free packets */
+	    (packet_free * cluster_size) +	/* clusters in free packets */
+	    (cluster_free * cluster_size) +	/* free clusters */
+	    (jumbop_free * jumbop_size) +	/* jumbo clusters */
+	    (jumbo9_free * jumbo9_size) +
+	    (jumbo16_free * jumbo16_size);
+
+	/*
+	 * Total is bytes in use + bytes in cache.  This doesn't take into
+	 * account various other misc data structures, overhead, etc, but
+	 * gives the user something useful despite that.
+	 */
+	bytes_total = bytes_inuse + bytes_incache;
+
+	printf("%juK/%juK/%juK bytes allocated to network "
+	    "(current/cache/total)\n", bytes_inuse / 1024,
+	    bytes_incache / 1024, bytes_total / 1024);
+
+	printf("%ju/%ju/%ju requests for mbufs denied (mbufs/clusters/"
+	    "mbuf+clusters)\n", mbuf_failures, cluster_failures,
+	    packet_failures);
+
+	printf("%ju/%ju/%ju requests for jumbo clusters denied "
+	    "(%juk/9k/16k)\n", jumbop_failures, jumbo9_failures,
+	    jumbo16_failures, jumbop_size / 1024);
+
+	if (live) {
+		mlen = sizeof(nsfbufs);
+		if (!sysctlbyname("kern.ipc.nsfbufs", &nsfbufs, &mlen, NULL,
+		    0) &&
+		    !sysctlbyname("kern.ipc.nsfbufsused", &nsfbufsused,
+		    &mlen, NULL, 0) &&
+		    !sysctlbyname("kern.ipc.nsfbufspeak", &nsfbufspeak,
+		    &mlen, NULL, 0))
+			printf("%d/%d/%d sfbufs in use (current/peak/max)\n",
+			    nsfbufsused, nsfbufspeak, nsfbufs);
+		mlen = sizeof(mbstat);
+		if (sysctlbyname("kern.ipc.mbstat", &mbstat, &mlen, NULL, 0)) {
+			warn("kern.ipc.mbstat");
+			goto out;
+		}
+	} else {
+		if (kread(mbaddr, (char *)&mbstat, sizeof mbstat) != 0)
+			goto out;
+	}
+	printf("%lu requests for sfbufs denied\n", mbstat.sf_allocfail);
+	printf("%lu requests for sfbufs delayed\n", mbstat.sf_allocwait);
+	printf("%lu requests for I/O initiated by sendfile\n",
+	    mbstat.sf_iocnt);
+	printf("%lu calls to protocol drain routines\n", mbstat.m_drain);
+out:
+	memstat_mtl_free(mtlp);
+}
diff --git a/freebsd-userspace/commands/usr.bin/netstat/mroute.c b/freebsd-userspace/commands/usr.bin/netstat/mroute.c
new file mode 100644
index 0000000..7669ff0
--- /dev/null
+++ b/freebsd-userspace/commands/usr.bin/netstat/mroute.c
@@ -0,0 +1,391 @@
+/*-
+ * Copyright (c) 1989 Stephen Deering
+ * 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. 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/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Print multicast routing structures and statistics.
+ *
+ * MROUTING 1.0
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/sysctl.h>
+#ifdef __rtems__
+#include <freebsd/sys/protosw.h>
+#else
+#include <sys/protosw.h>
+#endif
+#ifdef __rtems__
+#include <freebsd/sys/mbuf.h>
+#else
+#include <sys/mbuf.h>
+#endif
+#include <sys/time.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/igmp.h>
+#include <net/route.h>
+
+#define _KERNEL 1
+#ifdef __rtems__
+#include <freebsd/netinet/ip_mroute.h>
+#else
+#include <netinet/ip_mroute.h>
+#endif
+#undef _KERNEL
+
+#include <err.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "netstat.h"
+
+
+static void	print_bw_meter(struct bw_meter *, int *);
+static void	print_mfc(struct mfc *, int, int *);
+
+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, "%ju", (uintmax_t)bw_meter->bm_measured.b_packets);
+	else
+		sprintf(s1, "?");
+	if (bw_meter->bm_flags & BW_METER_UNIT_BYTES)
+		sprintf(s2, "%ju", (uintmax_t)bw_meter->bm_measured.b_bytes);
+	else
+		sprintf(s2, "?");
+	sprintf(s0, "%lu.%lu|%s|%s",
+		(u_long)bw_meter->bm_start_time.tv_sec,
+		(u_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, "%ju", (uintmax_t)bw_meter->bm_threshold.b_packets);
+	else
+		sprintf(s1, "?");
+	if (bw_meter->bm_flags & BW_METER_UNIT_BYTES)
+		sprintf(s2, "%ju", (uintmax_t)bw_meter->bm_threshold.b_bytes);
+	else
+		sprintf(s2, "?");
+	sprintf(s0, "%lu.%lu|%s|%s",
+		(u_long)bw_meter->bm_threshold.b_time.tv_sec,
+		(u_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, "%lu.%lu",
+			(u_long)delta.tv_sec,
+			(u_long)delta.tv_usec);
+	} else {
+		/* Negative time */
+		timersub(&now, &end, &delta);
+		sprintf(s3, "-%lu.%lu",
+			(u_long)delta.tv_sec,
+			(u_long)delta.tv_usec);
+	}
+	printf(" %s", s3);
+
+	printf("\n");
+}
+
+static void
+print_mfc(struct mfc *m, int maxvif, int *banner_printed)
+{
+	struct bw_meter bw_meter, *bwm;
+	int bw_banner_printed;
+	int error;
+	vifi_t vifi;
+
+	bw_banner_printed = 0;
+
+	if (! *banner_printed) {
+		printf("\nIPv4 Multicast Forwarding Table\n"
+		       " Origin          Group            "
+		       " Packets In-Vif  Out-Vifs:Ttls\n");
+		*banner_printed = 1;
+	}
+
+	printf(" %-15.15s", routename(m->mfc_origin.s_addr));
+	printf(" %-15.15s", routename(m->mfc_mcastgrp.s_addr));
+	printf(" %9lu", m->mfc_pkt_cnt);
+	printf("  %3d   ", m->mfc_parent);
+	for (vifi = 0; vifi <= maxvif; vifi++) {
+		if (m->mfc_ttls[vifi] > 0)
+			printf(" %u:%u", vifi, m->mfc_ttls[vifi]);
+	}
+	printf("\n");
+
+	/*
+	 * XXX We break the rules and try to use KVM to read the
+	 * bandwidth meters, they are not retrievable via sysctl yet.
+	 */
+	bwm = m->mfc_bw_meter;
+	while (bwm != NULL) {
+		error = kread((u_long)bwm, (char *)&bw_meter,
+		    sizeof(bw_meter));
+		if (error)
+			break;
+		print_bw_meter(&bw_meter, &bw_banner_printed);
+		bwm = bw_meter.bm_mfc_next;
+	}
+}
+
+void
+mroutepr(u_long pmfchashtbl, u_long pmfctablesize, u_long pviftbl)
+{
+	struct vif viftable[MAXVIFS];
+	struct vif *v;
+	struct mfc *m;
+	int banner_printed;
+	int saved_numeric_addr;
+	size_t len;
+	vifi_t vifi, maxvif;
+
+	saved_numeric_addr = numeric_addr;
+	numeric_addr = 1;
+
+	/*
+	 * TODO:
+	 * The VIF table will move to hanging off the struct if_info for
+	 * each IPv4 configured interface. Currently it is statically
+	 * allocated, and retrieved either using KVM or an opaque SYSCTL.
+	 *
+	 * This can't happen until the API documented in multicast(4)
+	 * is itself refactored. The historical reason why VIFs use
+	 * a separate ifindex space is entirely due to the legacy
+	 * capability of the MROUTING code to create IPIP tunnels on
+	 * the fly to support DVMRP. When gif(4) became available, this
+	 * functionality was deprecated, as PIM does not use it.
+	 */
+	maxvif = 0;
+
+	len = sizeof(viftable);
+	if (live) {
+		if (sysctlbyname("net.inet.ip.viftable", viftable, &len, NULL,
+		    0) < 0) {
+			warn("sysctl: net.inet.ip.viftable");
+			return;
+		}
+	} else
+		kread(pviftbl, (char *)viftable, sizeof(viftable));
+
+	banner_printed = 0;
+	for (vifi = 0, v = viftable; vifi < MAXVIFS; ++vifi, ++v) {
+		if (v->v_lcl_addr.s_addr == 0)
+			continue;
+
+		maxvif = vifi;
+		if (!banner_printed) {
+			printf("\nIPv4 Virtual Interface Table\n"
+			       " Vif   Thresh   Local-Address   "
+			       "Remote-Address    Pkts-In   Pkts-Out\n");
+			banner_printed = 1;
+		}
+
+		printf(" %2u    %6u   %-15.15s",
+					/* opposite math of add_vif() */
+		    vifi, v->v_threshold,
+		    routename(v->v_lcl_addr.s_addr));
+		printf(" %-15.15s", (v->v_flags & VIFF_TUNNEL) ?
+		    routename(v->v_rmt_addr.s_addr) : "");
+
+		printf(" %9lu  %9lu\n", v->v_pkt_in, v->v_pkt_out);
+	}
+	if (!banner_printed)
+		printf("\nIPv4 Virtual Interface Table is empty\n");
+
+	banner_printed = 0;
+
+	/*
+	 * TODO:
+	 * The MFC table will move into the AF_INET radix trie in future.
+	 * In 8.x, it becomes a dynamically allocated structure referenced
+	 * by a hashed LIST, allowing more than 256 entries w/o kernel tuning.
+	 *
+	 * If retrieved via opaque SYSCTL, the kernel will coalesce it into
+	 * a static table for us.
+	 * If retrieved via KVM, the hash list pointers must be followed.
+	 */
+	if (live) {
+		struct mfc *mfctable;
+
+		len = 0;
+		if (sysctlbyname("net.inet.ip.mfctable", NULL, &len, NULL,
+		    0) < 0) {
+			warn("sysctl: net.inet.ip.mfctable");
+			return;
+		}
+
+		mfctable = malloc(len);
+		if (mfctable == NULL) {
+			warnx("malloc %lu bytes", (u_long)len);
+			return;
+		}
+		if (sysctlbyname("net.inet.ip.mfctable", mfctable, &len, NULL,
+		    0) < 0) {
+			free(mfctable);
+			warn("sysctl: net.inet.ip.mfctable");
+			return;
+		}
+
+		m = mfctable;
+		while (len >= sizeof(*m)) {
+			print_mfc(m++, maxvif, &banner_printed);
+			len -= sizeof(*m);
+		}
+		if (len != 0)
+			warnx("print_mfc: %lu trailing bytes", (u_long)len);
+
+		free(mfctable);
+	} else {
+		LIST_HEAD(, mfc) *mfchashtbl;
+		u_long i, mfctablesize;
+		struct mfc mfc;
+		int error;
+
+		error = kread(pmfctablesize, (char *)&mfctablesize,
+		    sizeof(u_long));
+		if (error) {
+			warn("kread: mfctablesize");
+			return;
+		}
+
+		len = sizeof(*mfchashtbl) * mfctablesize;
+		mfchashtbl = malloc(len);
+		if (mfchashtbl == NULL) {
+			warnx("malloc %lu bytes", (u_long)len);
+			return;
+		}
+		kread(pmfchashtbl, (char *)&mfchashtbl, len);
+
+		for (i = 0; i < mfctablesize; i++) {
+			LIST_FOREACH(m, &mfchashtbl[i], mfc_hash) {
+				kread((u_long)m, (char *)&mfc, sizeof(mfc));
+				print_mfc(m, maxvif, &banner_printed);
+			}
+		}
+
+		free(mfchashtbl);
+	}
+
+	if (!banner_printed)
+		printf("\nIPv4 Multicast Forwarding Table is empty\n");
+
+	printf("\n");
+	numeric_addr = saved_numeric_addr;
+}
+
+void
+mrt_stats(u_long mstaddr)
+{
+	struct mrtstat mrtstat;
+	size_t len = sizeof mrtstat;
+
+	if (live) {
+		if (sysctlbyname("net.inet.ip.mrtstat", &mrtstat, &len, NULL,
+		    0) < 0) {
+			warn("sysctl: net.inet.ip.mrtstat");
+			return;
+		}
+	} else
+		kread(mstaddr, (char *)&mrtstat, sizeof(mrtstat));
+
+	printf("IPv4 multicast forwarding:\n");
+
+#define	p(f, m) if (mrtstat.f || sflag <= 1) \
+	printf(m, mrtstat.f, plural(mrtstat.f))
+#define	p2(f, m) if (mrtstat.f || sflag <= 1) \
+	printf(m, mrtstat.f, plurales(mrtstat.f))
+
+	p(mrts_mfc_lookups, "\t%lu multicast forwarding cache lookup%s\n");
+	p2(mrts_mfc_misses, "\t%lu multicast forwarding cache miss%s\n");
+	p(mrts_upcalls, "\t%lu upcall%s to multicast routing daemon\n");
+	p(mrts_upq_ovflw, "\t%lu upcall queue overflow%s\n");
+	p(mrts_upq_sockfull,
+	    "\t%lu upcall%s dropped due to full socket buffer\n");
+	p(mrts_cache_cleanups, "\t%lu cache cleanup%s\n");
+	p(mrts_no_route, "\t%lu datagram%s with no route for origin\n");
+	p(mrts_bad_tunnel, "\t%lu datagram%s arrived with bad tunneling\n");
+	p(mrts_cant_tunnel, "\t%lu datagram%s could not be tunneled\n");
+	p(mrts_wrong_if, "\t%lu datagram%s arrived on wrong interface\n");
+	p(mrts_drop_sel, "\t%lu datagram%s selectively dropped\n");
+	p(mrts_q_overflow, "\t%lu datagram%s dropped due to queue overflow\n");
+	p(mrts_pkt2large, "\t%lu datagram%s dropped for being too large\n");
+
+#undef	p2
+#undef	p
+}
diff --git a/freebsd-userspace/commands/usr.bin/netstat/mroute6.c b/freebsd-userspace/commands/usr.bin/netstat/mroute6.c
new file mode 100644
index 0000000..cd7d8d2
--- /dev/null
+++ b/freebsd-userspace/commands/usr.bin/netstat/mroute6.c
@@ -0,0 +1,268 @@
+/*-
+ * 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) 1989 Stephen Deering
+ * 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. 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/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifdef INET6
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/sysctl.h>
+#ifdef __rtems__
+#include <freebsd/sys/protosw.h>
+#else
+#include <sys/protosw.h>
+#endif
+#ifdef __rtems__
+#include <freebsd/sys/mbuf.h>
+#else
+#include <sys/mbuf.h>
+#endif
+#include <sys/time.h>
+
+#include <net/if.h>
+#include <net/if_var.h>
+#include <net/route.h>
+
+#include <netinet/in.h>
+
+#include <err.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define	KERNEL 1
+#include <netinet6/ip6_mroute.h>
+#undef KERNEL
+
+#include "netstat.h"
+
+#define	WID_ORG	(Wflag ? 39 : (numeric_addr ? 29 : 18)) /* width of origin column */
+#define	WID_GRP	(Wflag ? 18 : (numeric_addr ? 16 : 18)) /* width of group column */
+
+void
+mroute6pr(u_long mfcaddr, u_long mifaddr)
+{
+	struct mf6c *mf6ctable[MF6CTBLSIZ], *mfcp;
+	struct mif6 mif6table[MAXMIFS];
+	struct mf6c mfc;
+	struct rtdetq rte, *rtep;
+	struct mif6 *mifp;
+	mifi_t mifi;
+	int i;
+	int banner_printed;
+	int saved_numeric_addr;
+	mifi_t maxmif = 0;
+	long int waitings;
+	size_t len;
+
+	len = sizeof(mif6table);
+	if (live) {
+		if (sysctlbyname("net.inet6.ip6.mif6table", mif6table, &len,
+		    NULL, 0) < 0) {
+			warn("sysctl: net.inet6.ip6.mif6table");
+			return;
+		}
+	} else
+		kread(mifaddr, (char *)mif6table, sizeof(mif6table));
+
+	saved_numeric_addr = numeric_addr;
+	numeric_addr = 1;
+	banner_printed = 0;
+
+	for (mifi = 0, mifp = mif6table; mifi < MAXMIFS; ++mifi, ++mifp) {
+		struct ifnet ifnet;
+		char ifname[IFNAMSIZ];
+
+		if (mifp->m6_ifp == NULL)
+			continue;
+
+		/* XXX KVM */
+		kread((u_long)mifp->m6_ifp, (char *)&ifnet, sizeof(ifnet));
+
+		maxmif = mifi;
+		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(" %9ju  %9ju\n", (uintmax_t)mifp->m6_pkt_in,
+		    (uintmax_t)mifp->m6_pkt_out);
+	}
+	if (!banner_printed)
+		printf("\nIPv6 Multicast Interface Table is empty\n");
+
+	len = sizeof(mf6ctable);
+	if (live) {
+		if (sysctlbyname("net.inet6.ip6.mf6ctable", mf6ctable, &len,
+		    NULL, 0) < 0) {
+			warn("sysctl: net.inet6.ip6.mf6ctable");
+			return;
+		}
+	} else
+		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));
+			printf(" %-*.*s", WID_GRP, WID_GRP,
+			       routename6(&mfc.mf6c_mcastgrp));
+			printf(" %9ju", (uintmax_t)mfc.mf6c_pkt_cnt);
+
+			for (waitings = 0, rtep = mfc.mf6c_stall; rtep; ) {
+				waitings++;
+				/* XXX KVM */
+				kread((u_long)rtep, (char *)&rte, sizeof(rte));
+				rtep = rte.next;
+			}
+			printf("   %3ld", waitings);
+
+			if (mfc.mf6c_parent == MF6C_INCOMPLETE_PARENT)
+				printf(" ---   ");
+			else
+				printf("  %3d   ", mfc.mf6c_parent);
+			for (mifi = 0; mifi <= maxmif; mifi++) {
+				if (IF_ISSET(mifi, &mfc.mf6c_ifset))
+					printf(" %u", mifi);
+			}
+			printf("\n");
+
+			mfcp = mfc.mf6c_next;
+		}
+	}
+	if (!banner_printed)
+		printf("\nIPv6 Multicast Forwarding Table is empty\n");
+
+	printf("\n");
+	numeric_addr = saved_numeric_addr;
+}
+
+void
+mrt6_stats(u_long mstaddr)
+{
+	struct mrt6stat mrtstat;
+	size_t len = sizeof mrtstat;
+
+	if (live) {
+		if (sysctlbyname("net.inet6.ip6.mrt6stat", &mrtstat, &len,
+		    NULL, 0) < 0) {
+			warn("sysctl: net.inet6.ip6.mrt6stat");
+			return;
+		}
+	} else
+		kread(mstaddr, (char *)&mrtstat, sizeof(mrtstat));
+
+	printf("IPv6 multicast forwarding:\n");
+
+#define	p(f, m) if (mrtstat.f || sflag <= 1) \
+	printf(m, (uintmax_t)mrtstat.f, plural(mrtstat.f))
+#define	p2(f, m) if (mrtstat.f || sflag <= 1) \
+	printf(m, (uintmax_t)mrtstat.f, plurales(mrtstat.f))
+
+	p(mrt6s_mfc_lookups, "\t%ju multicast forwarding cache lookup%s\n");
+	p2(mrt6s_mfc_misses, "\t%ju multicast forwarding cache miss%s\n");
+	p(mrt6s_upcalls, "\t%ju upcall%s to multicast routing daemon\n");
+	p(mrt6s_upq_ovflw, "\t%ju upcall queue overflow%s\n");
+	p(mrt6s_upq_sockfull,
+	    "\t%ju upcall%s dropped due to full socket buffer\n");
+	p(mrt6s_cache_cleanups, "\t%ju cache cleanup%s\n");
+	p(mrt6s_no_route, "\t%ju datagram%s with no route for origin\n");
+	p(mrt6s_bad_tunnel, "\t%ju datagram%s arrived with bad tunneling\n");
+	p(mrt6s_cant_tunnel, "\t%ju datagram%s could not be tunneled\n");
+	p(mrt6s_wrong_if, "\t%ju datagram%s arrived on wrong interface\n");
+	p(mrt6s_drop_sel, "\t%ju datagram%s selectively dropped\n");
+	p(mrt6s_q_overflow,
+	    "\t%ju datagram%s dropped due to queue overflow\n");
+	p(mrt6s_pkt2large, "\t%ju datagram%s dropped for being too large\n");
+
+#undef	p2
+#undef	p
+}
+#endif /*INET6*/
diff --git a/freebsd-userspace/commands/usr.bin/netstat/netgraph.c b/freebsd-userspace/commands/usr.bin/netstat/netgraph.c
new file mode 100644
index 0000000..06a244f
--- /dev/null
+++ b/freebsd-userspace/commands/usr.bin/netstat/netgraph.c
@@ -0,0 +1,196 @@
+/*-
+ * Copyright (c) 1996-1999 Whistle Communications, Inc.
+ * All rights reserved.
+ *
+ * Subject to the following obligations and disclaimer of warranty, use and
+ * redistribution of this software, in source or object code forms, with or
+ * without modifications are expressly permitted by Whistle Communications;
+ * provided, however, that:
+ * 1. Any and all reproductions of the source or object code must include the
+ *    copyright notice above and the following disclaimer of warranties; and
+ * 2. No rights are granted, in any manner or form, to use Whistle
+ *    Communications, Inc. trademarks, including the mark "WHISTLE
+ *    COMMUNICATIONS" on advertising, endorsements, or otherwise except as
+ *    such appears in the above copyright notice or in the software.
+ *
+ * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
+ * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
+ * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
+ * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
+ * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
+ * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
+ * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
+ * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
+ * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
+ * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER 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 WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#ifdef __rtems__
+#include <freebsd/sys/protosw.h>
+#include <freebsd/sys/linker.h>
+#else
+#include <sys/protosw.h>
+#include <sys/linker.h>
+#endif
+
+#include <net/route.h>
+
+#include <netgraph.h>
+#include <netgraph/ng_message.h>
+#include <netgraph/ng_socket.h>
+#include <netgraph/ng_socketvar.h>
+
+#include <nlist.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <err.h>
+#include "netstat.h"
+
+static	int first = 1;
+static	int csock = -1;
+
+void
+netgraphprotopr(u_long off, const char *name, int af1 __unused,
+    int proto __unused)
+{
+	struct ngpcb *this, *next;
+	struct ngpcb ngpcb;
+	struct ngsock info;
+	struct socket sockb;
+	int debug = 1;
+
+	/* If symbol not found, try looking in the KLD module */
+	if (off == 0) {
+		const char *const modname = "ng_socket.ko";
+/* XXX We should get "mpath" from "sysctl kern.module_path" */
+		const char *mpath[] = { "/", "/boot/", "/modules/", NULL };
+		struct nlist sym[] = { { .n_name = "_ngsocklist" },
+				       { .n_name = NULL } };
+		const char **pre;
+		struct kld_file_stat ks;
+		int fileid;
+
+		/* Can't do this for core dumps. */
+		if (!live)
+			return;
+
+		/* See if module is loaded */
+		if ((fileid = kldfind(modname)) < 0) {
+			if (debug)
+				warn("kldfind(%s)", modname);
+			return;
+		}
+
+		/* Get module info */
+		memset(&ks, 0, sizeof(ks));
+		ks.version = sizeof(struct kld_file_stat);
+		if (kldstat(fileid, &ks) < 0) {
+			if (debug)
+				warn("kldstat(%d)", fileid);
+			return;
+		}
+
+		/* Get symbol table from module file */
+		for (pre = mpath; *pre; pre++) {
+			char path[MAXPATHLEN];
+
+			snprintf(path, sizeof(path), "%s%s", *pre, modname);
+			if (nlist(path, sym) == 0)
+				break;
+		}
+
+		/* Did we find it? */
+		if (sym[0].n_value == 0) {
+			if (debug)
+				warnx("%s not found", modname);
+			return;
+		}
+
+		/* Symbol found at load address plus symbol offset */
+		off = (u_long) ks.address + sym[0].n_value;
+	}
+
+	/* Get pointer to first socket */
+	kread(off, (char *)&this, sizeof(this));
+
+	/* Get my own socket node */
+	if (csock == -1)
+		NgMkSockNode(NULL, &csock, NULL);
+
+	for (; this != NULL; this = next) {
+		u_char rbuf[sizeof(struct ng_mesg) + sizeof(struct nodeinfo)];
+		struct ng_mesg *resp = (struct ng_mesg *) rbuf;
+		struct nodeinfo *ni = (struct nodeinfo *) resp->data;
+		char path[64];
+
+		/* Read in ngpcb structure */
+		kread((u_long)this, (char *)&ngpcb, sizeof(ngpcb));
+		next = LIST_NEXT(&ngpcb, socks);
+
+		/* Read in socket structure */
+		kread((u_long)ngpcb.ng_socket, (char *)&sockb, sizeof(sockb));
+
+		/* Check type of socket */
+		if (strcmp(name, "ctrl") == 0 && ngpcb.type != NG_CONTROL)
+			continue;
+		if (strcmp(name, "data") == 0 && ngpcb.type != NG_DATA)
+			continue;
+
+		/* Do headline */
+		if (first) {
+			printf("Netgraph sockets\n");
+			if (Aflag)
+				printf("%-8.8s ", "PCB");
+			printf("%-5.5s %-6.6s %-6.6s %-14.14s %s\n",
+			    "Type", "Recv-Q", "Send-Q",
+			    "Node Address", "#Hooks");
+			first = 0;
+		}
+
+		/* Show socket */
+		if (Aflag)
+			printf("%8lx ", (u_long) this);
+		printf("%-5.5s %6u %6u ",
+		    name, sockb.so_rcv.sb_cc, sockb.so_snd.sb_cc);
+
+		/* Get ngsock structure */
+		if (ngpcb.sockdata == NULL)	/* unconnected data socket */
+			goto finish;
+		kread((u_long)ngpcb.sockdata, (char *)&info, sizeof(info));
+
+		/* Get info on associated node */
+		if (info.node_id == 0 || csock == -1)
+			goto finish;
+		snprintf(path, sizeof(path), "[%x]:", info.node_id);
+		if (NgSendMsg(csock, path,
+		    NGM_GENERIC_COOKIE, NGM_NODEINFO, NULL, 0) < 0)
+			goto finish;
+		if (NgRecvMsg(csock, resp, sizeof(rbuf), NULL) < 0)
+			goto finish;
+
+		/* Display associated node info */
+		if (*ni->name != '\0')
+			snprintf(path, sizeof(path), "%s:", ni->name);
+		printf("%-14.14s %4d", path, ni->hooks);
+finish:
+		putchar('\n');
+	}
+}
+
diff --git a/freebsd-userspace/commands/usr.bin/netstat/netstat.1 b/freebsd-userspace/commands/usr.bin/netstat/netstat.1
new file mode 100644
index 0000000..872ff95
--- /dev/null
+++ b/freebsd-userspace/commands/usr.bin/netstat/netstat.1
@@ -0,0 +1,523 @@
+.\" 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. 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.
+.\"
+.\"	@(#)netstat.1	8.8 (Berkeley) 4/18/94
+.\" $FreeBSD$
+.\"
+.Dd January 10, 2010
+.Dt NETSTAT 1
+.Os
+.Sh NAME
+.Nm netstat
+.Nd show network status
+.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.
+.Bl -tag -width indent
+.It Xo
+.Bk -words
+.Nm
+.Op Fl AaLnSWx
+.Op Fl f Ar protocol_family | Fl p Ar protocol
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Ek
+.Xc
+Display a list of active sockets
+(protocol control blocks)
+for each network protocol,
+for a particular
+.Ar protocol_family ,
+or for a single
+.Ar protocol .
+If
+.Fl A
+is also present,
+show the address of a protocol control block (PCB)
+associated with a socket; used for debugging.
+If
+.Fl a
+is also present,
+show the state of all sockets;
+normally sockets used by server processes are not shown.
+If
+.Fl L
+is also present,
+show the size of the various listen queues.
+The first count shows the number of unaccepted connections,
+the second count shows the amount of unaccepted incomplete connections,
+and the third count is the maximum number of queued connections.
+If
+.Fl S
+is also present,
+show network addresses as numbers (as with
+.Fl n )
+but show ports symbolically.
+If
+.Fl x
+is present display full socket buffer statistics for each internet socket.
+.It Xo
+.Bk -words
+.Nm
+.Fl i | I Ar interface
+.Op Fl abdhntW
+.Op Fl f Ar address_family
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Ek
+.Xc
+Show the state of all network interfaces or a single
+.Ar interface
+which have been auto-configured
+(interfaces statically configured into a system, but not
+located at boot time are not shown).
+An asterisk
+.Pq Dq Li *
+after an interface name indicates that the interface is
+.Dq down .
+If
+.Fl a
+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
+.Fl b
+is also present, show the number of bytes in and out.
+If
+.Fl d
+is also present, show the number of dropped packets.
+If
+.Fl h
+is also present, print all counters in human readable form.
+If
+.Fl t
+is also present, show the contents of watchdog timers.
+If
+.Fl W
+is also present, print interface names using a wider field size.
+.It Xo
+.Bk -words
+.Nm
+.Fl w Ar wait
+.Op Fl I Ar interface
+.Op Fl d
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Op Fl q Ar howmany
+.Ek
+.Xc
+At intervals of
+.Ar wait
+seconds,
+display the information regarding packet
+traffic on all configured network interfaces
+or a single
+.Ar interface .
+If
+.Fl q
+is also present, exit after
+.Ar howmany
+outputs.
+If
+.Fl d
+is also present, show the number of dropped packets.
+.It Xo
+.Bk -words
+.Nm
+.Fl s Op Fl s
+.Op Fl z
+.Op Fl f Ar protocol_family | Fl p Ar protocol
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Ek
+.Xc
+Display system-wide statistics for each network protocol,
+for a particular
+.Ar protocol_family ,
+or for a single
+.Ar protocol .
+If
+.Fl s
+is repeated, counters with a value of zero are suppressed.
+If
+.Fl z
+is also present, reset statistic counters after displaying them.
+.It Xo
+.Bk -words
+.Nm
+.Fl i | I Ar interface Fl s
+.Op Fl f Ar protocol_family | Fl p Ar protocol
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Ek
+.Xc
+Display per-interface statistics for each network protocol,
+for a particular
+.Ar protocol_family ,
+or for a single
+.Ar protocol .
+.It Xo
+.Bk -words
+.Nm
+.Fl m
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Ek
+.Xc
+Show statistics recorded by the memory management routines
+.Pq Xr mbuf 9 .
+The network manages a private pool of memory buffers.
+.It Xo
+.Bk -words
+.Nm
+.Fl B
+.Op Fl z
+.Op Fl I Ar interface
+.Ek
+.Xc
+Show statistics about
+.Xr bpf 4
+peers.
+This includes information like
+how many packets have been matched, dropped and received by the
+bpf device, also information about current buffer sizes and device
+states.
+.It Xo
+.Bk -words
+.Nm
+.Fl r
+.Op Fl AanW
+.Op Fl f Ar address_family
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Ek
+.Xc
+Display the contents of all routing tables,
+or a routing table for a particular
+.Ar address_family .
+If
+.Fl A
+is also present,
+show the contents of the internal Patricia tree
+structures; used for debugging.
+If
+.Fl a
+is also present,
+show protocol-cloned routes
+(routes generated by an
+.Dv RTF_PRCLONING
+parent route);
+normally these routes are not shown.
+When
+.Fl W
+is also present,
+show the path MTU
+for each route,
+and print interface
+names with a wider
+field size.
+.It Xo
+.Bk -words
+.Nm
+.Fl rs
+.Op Fl s
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Ek
+.Xc
+Display routing statistics.
+If
+.Fl s
+is repeated, counters with a value of zero are suppressed.
+.It Xo
+.Bk -words
+.Nm
+.Fl g
+.Op Fl W
+.Op Fl f Ar address_family
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Ek
+.Xc
+Display the contents of the multicast virtual interface tables,
+and multicast forwarding caches.
+Entries in these tables will appear only when the kernel is
+actively forwarding multicast sessions.
+This option is applicable only to the
+.Cm inet
+and
+.Cm inet6
+address families.
+.It Xo
+.Bk -words
+.Nm
+.Fl gs
+.Op Fl s
+.Op Fl f Ar address_family
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Ek
+.Xc
+Show multicast routing statistics.
+If
+.Fl s
+is repeated, counters with a value of zero are suppressed.
+.El
+.Pp
+Some options have the general meaning:
+.Bl -tag -width flag
+.It Fl f Ar address_family , Fl p Ar protocol
+Limit display to those records
+of the specified
+.Ar address_family
+or a single
+.Ar protocol .
+The following address families and protocols are recognized:
+.Pp
+.Bl -tag -width ".Cm netgraph , ng Pq Dv AF_NETGRAPH" -compact
+.It Em Family
+.Em Protocols
+.It Cm inet Pq Dv AF_INET
+.Cm divert , icmp , igmp , ip , ipsec , pim, sctp , tcp , udp
+.It Cm inet6 Pq Dv AF_INET6
+.Cm icmp6 , ip6 , ipsec6 , rip6 , tcp , udp
+.It Cm pfkey Pq Dv PF_KEY
+.Cm pfkey
+.It Cm atalk Pq Dv AF_APPLETALK
+.Cm ddp
+.It Cm netgraph , ng Pq Dv AF_NETGRAPH
+.Cm ctrl , data
+.It Cm ipx Pq Dv AF_IPX
+.Cm ipx , spx
+.\".It Cm ns Pq Dv AF_NS
+.\".Cm idp , ns_err , spp
+.\".It Cm iso Pq Dv AF_ISO
+.\".Cm clnp , cltp , esis , tp
+.It Cm unix Pq Dv AF_UNIX
+.It Cm link Pq Dv AF_LINK
+.El
+.Pp
+The program will complain if
+.Ar protocol
+is unknown or if there is no statistics routine for it.
+.It Fl M
+Extract values associated with the name list from the specified core
+instead of the default
+.Pa /dev/kmem .
+.It Fl N
+Extract the name list from the specified system instead of the default,
+which is the kernel image the system has booted from.
+.It Fl n
+Show network addresses and ports as numbers.
+Normally
+.Nm
+attempts to resolve addresses and ports,
+and display them symbolically.
+.It Fl W
+In certain displays, avoid truncating addresses even if this causes
+some fields to overflow.
+.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
+.Dq host.port
+or
+.Dq 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 databases
+.Xr hosts 5
+and
+.Xr networks 5 ,
+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 IPv4
+.Dq dot format ,
+refer to
+.Xr inet 3 .
+Unspecified,
+or
+.Dq wildcard ,
+addresses and ports appear as
+.Dq Li * .
+.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
+.Pq Dq 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 ".Li W" ".Dv RTF_WASCLONED"
+.It Li 1 Ta Dv RTF_PROTO1 Ta "Protocol specific routing flag #1"
+.It Li 2 Ta Dv RTF_PROTO2 Ta "Protocol specific routing flag #2"
+.It Li 3 Ta Dv RTF_PROTO3 Ta "Protocol specific routing flag #3"
+.It Li B Ta Dv RTF_BLACKHOLE Ta "Just discard pkts (during updates)"
+.It Li b Ta Dv RTF_BROADCAST Ta "The route represents a broadcast address"
+.It Li C Ta Dv RTF_CLONING Ta "Generate new routes on use"
+.It Li c Ta Dv RTF_PRCLONING Ta "Protocol-specified generate new routes on use"
+.It Li D Ta Dv RTF_DYNAMIC Ta "Created dynamically (by redirect)"
+.It Li G Ta Dv RTF_GATEWAY Ta "Destination requires forwarding by intermediary"
+.It Li H Ta Dv RTF_HOST Ta "Host entry (net otherwise)"
+.It Li L Ta Dv RTF_LLINFO Ta "Valid protocol to link address translation"
+.It Li M Ta Dv RTF_MODIFIED Ta "Modified dynamically (by redirect)"
+.It Li R Ta Dv RTF_REJECT Ta "Host or net unreachable"
+.It Li S Ta Dv RTF_STATIC Ta "Manually added"
+.It Li U Ta Dv RTF_UP Ta "Route usable"
+.It Li W Ta Dv RTF_WASCLONED Ta "Route was generated as a result of cloning"
+.It Li X Ta Dv RTF_XRESOLVE Ta "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 interface entry indicates the network interface utilized 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.
+By default, this display summarizes information for all interfaces.
+Information for a specific interface may be displayed with the
+.Fl I
+option.
+.Pp
+The
+.Xr bpf 4
+flags displayed when
+.Nm
+is invoked with the
+.Fl B
+option represent the underlying parameters of the bpf peer.
+Each flag is
+represented as a single lower case letter.
+The mapping between the letters and flags in order of appearance are:
+.Bl -column ".Li i"
+.It Li p Ta Set if listening promiscuously
+.It Li i Ta Dv BIOCIMMEDIATE No has been set on the device
+.It Li f Ta Dv BIOCGHDRCMPLT No status: source link addresses are being
+filled automatically
+.It Li s Ta Dv BIOCGSEESENT No status: see packets originating locally and
+remotely on the interface.
+.It Li a Ta Packet reception generates a signal
+.It Li l Ta Dv BIOCLOCK No status: descriptor has been locked
+.El
+.Pp
+For more information about these flags, please refer to
+.Xr bpf 4 .
+.Pp
+The
+.Fl x
+flag causes
+.Nm
+to output all the information recorded about data
+stored in the socket buffers.
+The fields are:
+.Bl -column ".Li R-MBUF"
+.It Li R-MBUF Ta Number of mbufs in the receive queue.
+.It Li S-MBUF Ta Number of mbufs in the send queue.
+.It Li R-CLUS Ta Number of clusters, of any type, in the receive
+queue.
+.It Li S-CLUS Ta Number of clusters, of any type, in the send queue.
+.It Li R-HIWA Ta Receive buffer high water mark, in bytes.
+.It Li S-HIWA Ta Send buffer high water mark, in bytes.
+.It Li R-LOWA Ta Receive buffer low water mark, in bytes.
+.It Li S-LOWA Ta Send buffer low water mark, in bytes.
+.It Li R-BCNT Ta Receive buffer byte count.
+.It Li S-BCNT Ta Send buffer byte count.
+.It Li R-BMAX Ta Maximum bytes that can be used in the receive buffer.
+.It Li S-BMAX Ta Maximum bytes that can be used in the send buffer.
+.El
+.Sh SEE ALSO
+.Xr fstat 1 ,
+.Xr nfsstat 1 ,
+.Xr procstat 1 ,
+.Xr ps 1 ,
+.Xr sockstat 1 ,
+.Xr bpf 4 ,
+.Xr inet 4 ,
+.Xr route 4 ,
+.Xr unix 4 ,
+.Xr hosts 5 ,
+.Xr networks 5 ,
+.Xr protocols 5 ,
+.Xr services 5 ,
+.Xr iostat 8 ,
+.Xr route 8 ,
+.Xr trpt 8 ,
+.Xr vmstat 8 ,
+.Xr mbuf 9
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
+.Pp
+IPv6 support was added by WIDE/KAME project.
+.Sh BUGS
+The notion of errors is ill-defined.
diff --git a/freebsd-userspace/commands/usr.bin/netstat/netstat.h b/freebsd-userspace/commands/usr.bin/netstat/netstat.h
new file mode 100644
index 0000000..7594464
--- /dev/null
+++ b/freebsd-userspace/commands/usr.bin/netstat/netstat.h
@@ -0,0 +1,167 @@
+/*-
+ * 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. 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.
+ *
+ *	@(#)netstat.h	8.2 (Berkeley) 1/4/94
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+
+extern int	Aflag;	/* show addresses of protocol control block */
+extern int	aflag;	/* show all sockets (including servers) */
+extern int	bflag;	/* show i/f total bytes in/out */
+extern int	dflag;	/* show i/f dropped packets */
+extern int	gflag;	/* show group (multicast) routing or stats */
+extern int	hflag;	/* show counters in human readable format */
+extern int	iflag;	/* show interfaces */
+extern int	Lflag;	/* show size of listen queues */
+extern int	mflag;	/* show memory stats */
+extern int	noutputs;	/* how much outputs before we exit */
+extern int	numeric_addr;	/* show addresses numerically */
+extern int	numeric_port;	/* show ports numerically */
+extern int	rflag;	/* show routing tables (or routing stats) */
+extern int	sflag;	/* show protocol statistics */
+extern int	tflag;	/* show i/f watchdog timers */
+extern int	Wflag;	/* wide display */
+extern int	xflag;	/* extended display, includes all socket buffer info */
+extern int	zflag;	/* zero stats */
+
+extern int	interval; /* repeat interval for i/f stats */
+
+extern char	*interface; /* desired i/f for stats, or NULL for all i/fs */
+extern int	unit;	/* unit number for above */
+
+extern int	af;	/* address family */
+extern int	live;	/* true if we are examining a live system */
+
+int	kread(u_long addr, void *buf, size_t size);
+const char *plural(uintmax_t);
+const char *plurales(uintmax_t);
+const char *pluralies(uintmax_t);
+
+int	sotoxsocket(struct socket *, struct xsocket *);
+void	protopr(u_long, const char *, int, int);
+void	tcp_stats(u_long, const char *, int, int);
+void	udp_stats(u_long, const char *, int, int);
+#ifdef SCTP
+void	sctp_protopr(u_long, const char *, int, int);
+void	sctp_stats(u_long, const char *, int, int);
+#endif
+void	arp_stats(u_long, const char *, int, int);
+void	ip_stats(u_long, const char *, int, int);
+void	icmp_stats(u_long, const char *, int, int);
+void	igmp_stats(u_long, const char *, int, int);
+void	pim_stats(u_long, const char *, int, int);
+void	carp_stats(u_long, const char *, int, int);
+void	pfsync_stats(u_long, const char *, int, int);
+#ifdef IPSEC
+void	ipsec_stats(u_long, const char *, int, int);
+void	esp_stats(u_long, const char *, int, int);
+void	ah_stats(u_long, const char *, int, int);
+void	ipcomp_stats(u_long, const char *, int, int);
+#endif
+
+#ifdef INET6
+void	ip6_stats(u_long, const char *, int, int);
+void	ip6_ifstats(char *);
+void	icmp6_stats(u_long, const char *, int, int);
+void	icmp6_ifstats(char *);
+void	pim6_stats(u_long, const char *, int, int);
+void	rip6_stats(u_long, const char *, int, int);
+void	mroute6pr(u_long, u_long);
+void	mrt6_stats(u_long);
+
+struct sockaddr_in6;
+struct in6_addr;
+char *routename6(struct sockaddr_in6 *);
+const char *netname6(struct sockaddr_in6 *, struct in6_addr *);
+void	inet6print(struct in6_addr *, int, const char *, int);
+#endif /*INET6*/
+
+#ifdef IPSEC
+void	pfkey_stats(u_long, const char *, int, int);
+#endif
+
+void	mbpr(void *, u_long);
+
+void	hostpr(u_long, u_long);
+void	impstats(u_long, u_long);
+
+void	intpr(int, u_long, void (*)(char *));
+
+void	pr_rthdr(int);
+void	pr_family(int);
+void	rt_stats(u_long, u_long);
+char	*ipx_pnet(struct sockaddr *);
+char	*ipx_phost(struct sockaddr *);
+char	*ns_phost(struct sockaddr *);
+void	upHex(char *);
+
+char	*routename(in_addr_t);
+char	*netname(in_addr_t, u_long);
+char	*atalk_print(struct sockaddr *, int);
+char	*atalk_print2(struct sockaddr *, struct sockaddr *, int);
+char	*ipx_print(struct sockaddr *);
+char	*ns_print(struct sockaddr *);
+void	routepr(u_long);
+
+void	ipxprotopr(u_long, const char *, int, int);
+void	spx_stats(u_long, const char *, int, int);
+void	ipx_stats(u_long, const char *, int, int);
+void	ipxerr_stats(u_long, const char *, int, int);
+
+void	nsprotopr(u_long, const char *, int, int);
+void	spp_stats(u_long, const char *, int, int);
+void	idp_stats(u_long, const char *, int, int);
+void	nserr_stats(u_long, const char *, int, int);
+
+void	atalkprotopr(u_long, const char *, int, int);
+void	ddp_stats(u_long, const char *, int, int);
+
+#ifdef NETGRAPH
+void	netgraphprotopr(u_long, const char *, int, int);
+#endif
+
+void	unixpr(u_long, u_long, u_long, u_long);
+
+void	esis_stats(u_long, const char *, int, int);
+void	clnp_stats(u_long, const char *, int, int);
+void	cltp_stats(u_long, const char *, int, int);
+void	iso_protopr(u_long, const char *, int, int);
+void	iso_protopr1(u_long, int);
+void	tp_protopr(u_long, const char *, int, int);
+void	tp_inproto(u_long);
+void	tp_stats(caddr_t, caddr_t);
+
+void	mroutepr(u_long, u_long, u_long);
+void	mrt_stats(u_long);
+void	bpf_stats(char *);
diff --git a/freebsd-userspace/commands/usr.bin/netstat/pfkey.c b/freebsd-userspace/commands/usr.bin/netstat/pfkey.c
new file mode 100644
index 0000000..7c5af07
--- /dev/null
+++ b/freebsd-userspace/commands/usr.bin/netstat/pfkey.c
@@ -0,0 +1,184 @@
+/*	$NetBSD: inet.c,v 1.35.2.1 1999/04/29 14:57:08 perry Exp $	*/
+/*	$KAME: ipsec.c,v 1.25 2001/03/12 09:04:39 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. 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.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)inet.c	8.5 (Berkeley) 5/24/95";
+#endif /* not lint */
+#endif
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+
+#include <netinet/in.h>
+
+#ifdef IPSEC
+#ifdef __rtems__
+#include <freebsd/netipsec/keysock.h>
+#else
+#include <netipsec/keysock.h>
+#endif
+#endif
+
+#include <stdint.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, int family __unused,
+    int proto __unused)
+{
+	struct pfkeystat pfkeystat;
+	unsigned first, type;
+
+	if (off == 0)
+		return;
+	printf ("%s:\n", name);
+	kread(off, (char *)&pfkeystat, sizeof(pfkeystat));
+
+#define	p(f, m) if (pfkeystat.f || sflag <= 1) \
+    printf(m, (uintmax_t)pfkeystat.f, plural(pfkeystat.f))
+
+	/* userland -> kernel */
+	p(out_total, "\t%ju request%s sent from userland\n");
+	p(out_bytes, "\t%ju byte%s sent from userland\n");
+	for (first = 1, type = 0;
+	     type < sizeof(pfkeystat.out_msgtype)/sizeof(pfkeystat.out_msgtype[0]);
+	     type++) {
+		if (pfkeystat.out_msgtype[type] <= 0)
+			continue;
+		if (first) {
+			printf("\thistogram by message type:\n");
+			first = 0;
+		}
+		printf("\t\t%s: %ju\n", pfkey_msgtype_names(type),
+			(uintmax_t)pfkeystat.out_msgtype[type]);
+	}
+	p(out_invlen, "\t%ju message%s with invalid length field\n");
+	p(out_invver, "\t%ju message%s with invalid version field\n");
+	p(out_invmsgtype, "\t%ju message%s with invalid message type field\n");
+	p(out_tooshort, "\t%ju message%s too short\n");
+	p(out_nomem, "\t%ju message%s with memory allocation failure\n");
+	p(out_dupext, "\t%ju message%s with duplicate extension\n");
+	p(out_invexttype, "\t%ju message%s with invalid extension type\n");
+	p(out_invsatype, "\t%ju message%s with invalid sa type\n");
+	p(out_invaddr, "\t%ju message%s with invalid address extension\n");
+
+	/* kernel -> userland */
+	p(in_total, "\t%ju request%s sent to userland\n");
+	p(in_bytes, "\t%ju byte%s sent to userland\n");
+	for (first = 1, type = 0;
+	     type < sizeof(pfkeystat.in_msgtype)/sizeof(pfkeystat.in_msgtype[0]);
+	     type++) {
+		if (pfkeystat.in_msgtype[type] <= 0)
+			continue;
+		if (first) {
+			printf("\thistogram by message type:\n");
+			first = 0;
+		}
+		printf("\t\t%s: %ju\n", pfkey_msgtype_names(type),
+			(uintmax_t)pfkeystat.in_msgtype[type]);
+	}
+	p(in_msgtarget[KEY_SENDUP_ONE],
+	    "\t%ju message%s toward single socket\n");
+	p(in_msgtarget[KEY_SENDUP_ALL],
+	    "\t%ju message%s toward all sockets\n");
+	p(in_msgtarget[KEY_SENDUP_REGISTERED],
+	    "\t%ju message%s toward registered sockets\n");
+	p(in_nomem, "\t%ju message%s with memory allocation failure\n");
+#undef p
+}
+#endif /* IPSEC */
diff --git a/freebsd-userspace/commands/usr.bin/netstat/route.c b/freebsd-userspace/commands/usr.bin/netstat/route.c
new file mode 100644
index 0000000..af60527
--- /dev/null
+++ b/freebsd-userspace/commands/usr.bin/netstat/route.c
@@ -0,0 +1,1167 @@
+/*-
+ * 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. 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.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "From: @(#)route.c	8.6 (Berkeley) 4/28/95";
+#endif /* not lint */
+#endif
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#ifdef __rtems__
+#include <freebsd/sys/protosw.h>
+#else
+#include <sys/protosw.h>
+#endif
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/time.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#ifdef __rtems__
+#include <freebsd/net/if_var.h>
+#else
+#include <net/if_var.h>
+#endif
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#ifdef __rtems__
+#include <freebsd/net/radix.h>
+#else
+#include <net/radix.h>
+#endif
+#include <net/route.h>
+
+#include <netinet/in.h>
+#ifdef __rtems__
+/* no IPX on RTEMS */
+/* no AppleTalk on RTEMS */
+#else
+#include <netipx/ipx.h>
+#include <netatalk/at.h>
+#endif
+#ifdef __rtems__
+/* why isn't this protected by a NETGRAPH define */
+#else
+#include <netgraph/ng_socket.h>
+#endif
+
+#include <sys/sysctl.h>
+
+#include <arpa/inet.h>
+#ifdef __rtems__
+/* apparently libutil.h is not needed */
+#else
+#include <libutil.h>
+#endif
+#include <netdb.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <err.h>
+#include "netstat.h"
+
+#define	kget(p, d) (kread((u_long)(p), (char *)&(d), sizeof (d)))
+
+/*
+ * Definitions for showing gateway flags.
+ */
+struct bits {
+	u_long	b_mask;
+	char	b_val;
+} bits[] = {
+	{ RTF_UP,	'U' },
+	{ RTF_GATEWAY,	'G' },
+	{ RTF_HOST,	'H' },
+	{ RTF_REJECT,	'R' },
+	{ RTF_DYNAMIC,	'D' },
+	{ RTF_MODIFIED,	'M' },
+	{ RTF_DONE,	'd' }, /* Completed -- for routing messages only */
+	{ RTF_XRESOLVE,	'X' },
+	{ RTF_STATIC,	'S' },
+	{ RTF_PROTO1,	'1' },
+	{ RTF_PROTO2,	'2' },
+	{ RTF_PRCLONING,'c' },
+	{ RTF_PROTO3,	'3' },
+	{ RTF_BLACKHOLE,'B' },
+	{ RTF_BROADCAST,'b' },
+#ifdef RTF_LLINFO
+	{ RTF_LLINFO,	'L' },
+#endif
+#ifdef RTF_WASCLONED
+	{ RTF_WASCLONED,'W' },
+#endif
+#ifdef RTF_CLONING
+	{ RTF_CLONING,	'C' },
+#endif
+	{ 0 , 0 }
+};
+
+typedef union {
+	long	dummy;		/* Helps align structure. */
+	struct	sockaddr u_sa;
+	u_short	u_data[128];
+} sa_u;
+
+static sa_u pt_u;
+
+int	fibnum;
+int	do_rtent = 0;
+struct	rtentry rtentry;
+struct	radix_node rnode;
+struct	radix_mask rmask;
+struct	radix_node_head **rt_tables;
+
+int	NewTree = 0;
+
+struct	timespec uptime;
+
+static struct sockaddr *kgetsa(struct sockaddr *);
+static void size_cols(int ef, struct radix_node *rn);
+static void size_cols_tree(struct radix_node *rn);
+static void size_cols_rtentry(struct rtentry *rt);
+static void p_tree(struct radix_node *);
+static void p_rtnode(void);
+static void ntreestuff(void);
+static void np_rtentry(struct rt_msghdr *);
+static void p_sockaddr(struct sockaddr *, struct sockaddr *, int, int);
+static const char *fmt_sockaddr(struct sockaddr *sa, struct sockaddr *mask,
+    int flags);
+static void p_flags(int, const char *);
+static const char *fmt_flags(int f);
+static void p_rtentry(struct rtentry *);
+static void domask(char *, in_addr_t, u_long);
+
+/*
+ * Print routing tables.
+ */
+void
+routepr(u_long rtree)
+{
+	struct radix_node_head **rnhp, *rnh, head;
+	size_t intsize;
+	int i;
+	int numfibs;
+
+	intsize = sizeof(int);
+	if (sysctlbyname("net.my_fibnum", &fibnum, &intsize, NULL, 0) == -1)
+		fibnum = 0;
+	if (sysctlbyname("net.fibs", &numfibs, &intsize, NULL, 0) == -1)
+		numfibs = 1;
+	rt_tables = calloc(numfibs * (AF_MAX+1),
+	    sizeof(struct radix_node_head *));
+	if (rt_tables == NULL)
+		err(EX_OSERR, "memory allocation failed");
+	/*
+	 * Since kernel & userland use different timebase
+	 * (time_uptime vs time_second) and we are reading kernel memory
+	 * directly we should do rt_rmx.rmx_expire --> expire_time conversion.
+	 */
+#ifdef __rtems__
+#warning "fix clock_gettime(CLOCK_UPTIME)"
+#else
+	if (clock_gettime(CLOCK_UPTIME, &uptime) < 0)
+		err(EX_OSERR, "clock_gettime() failed");
+#endif
+
+	printf("Routing tables\n");
+
+	if (Aflag == 0 && NewTree)
+		ntreestuff();
+	else {
+		if (rtree == 0) {
+			printf("rt_tables: symbol not in namelist\n");
+			return;
+		}
+
+		if (kread((u_long)(rtree), (char *)(rt_tables), (numfibs *
+		    (AF_MAX+1) * sizeof(struct radix_node_head *))) != 0)
+			return;
+		for (i = 0; i <= AF_MAX; i++) {
+			int tmpfib;
+			if (i != AF_INET)
+				tmpfib = 0;
+			else
+				tmpfib = fibnum;
+			rnhp = (struct radix_node_head **)*rt_tables;
+			/* Calculate the in-kernel address. */
+			rnhp += tmpfib * (AF_MAX+1) + i;
+			/* Read the in kernel rhn pointer. */
+			if (kget(rnhp, rnh) != 0)
+				continue;
+			if (rnh == NULL)
+				continue;
+			/* Read the rnh data. */
+			if (kget(rnh, head) != 0)
+				continue;
+			if (i == AF_UNSPEC) {
+				if (Aflag && af == 0) {
+					printf("Netmasks:\n");
+					p_tree(head.rnh_treetop);
+				}
+			} else if (af == AF_UNSPEC || af == i) {
+				size_cols(i, head.rnh_treetop);
+				pr_family(i);
+				do_rtent = 1;
+				pr_rthdr(i);
+				p_tree(head.rnh_treetop);
+			}
+		}
+	}
+}
+
+/*
+ * Print address family header before a section of the routing table.
+ */
+void
+pr_family(int af1)
+{
+	const char *afname;
+
+	switch (af1) {
+	case AF_INET:
+		afname = "Internet";
+		break;
+#ifdef INET6
+	case AF_INET6:
+		afname = "Internet6";
+		break;
+#endif /*INET6*/
+	case AF_IPX:
+		afname = "IPX";
+		break;
+	case AF_ISO:
+		afname = "ISO";
+		break;
+	case AF_APPLETALK:
+		afname = "AppleTalk";
+		break;
+	case AF_CCITT:
+		afname = "X.25";
+		break;
+	case AF_NETGRAPH:
+		afname = "Netgraph";
+		break;
+	default:
+		afname = NULL;
+		break;
+	}
+	if (afname)
+		printf("\n%s:\n", afname);
+	else
+		printf("\nProtocol Family %d:\n", af1);
+}
+
+/* column widths; each followed by one space */
+#ifndef INET6
+#define	WID_DST_DEFAULT(af) 	18	/* width of destination column */
+#define	WID_GW_DEFAULT(af)	18	/* width of gateway column */
+#define	WID_IF_DEFAULT(af)	(Wflag ? 8 : 6)	/* width of netif column */
+#else
+#define	WID_DST_DEFAULT(af) \
+	((af) == AF_INET6 ? (numeric_addr ? 33: 18) : 18)
+#define	WID_GW_DEFAULT(af) \
+	((af) == AF_INET6 ? (numeric_addr ? 29 : 18) : 18)
+#define	WID_IF_DEFAULT(af)	((af) == AF_INET6 ? 8 : (Wflag ? 8 : 6))
+#endif /*INET6*/
+
+static int wid_dst;
+static int wid_gw;
+static int wid_flags;
+static int wid_refs;
+static int wid_use;
+static int wid_mtu;
+static int wid_if;
+static int wid_expire;
+
+static void
+size_cols(int ef __unused, struct radix_node *rn)
+{
+	wid_dst = WID_DST_DEFAULT(ef);
+	wid_gw = WID_GW_DEFAULT(ef);
+	wid_flags = 6;
+	wid_refs = 6;
+	wid_use = 8;
+	wid_mtu = 6;
+	wid_if = WID_IF_DEFAULT(ef);
+	wid_expire = 6;
+
+	if (Wflag)
+		size_cols_tree(rn);
+}
+
+static void
+size_cols_tree(struct radix_node *rn)
+{
+again:
+	if (kget(rn, rnode) != 0)
+		return;
+	if (!(rnode.rn_flags & RNF_ACTIVE))
+		return;
+	if (rnode.rn_bit < 0) {
+		if ((rnode.rn_flags & RNF_ROOT) == 0) {
+			if (kget(rn, rtentry) != 0)
+				return;
+			size_cols_rtentry(&rtentry);
+		}
+		if ((rn = rnode.rn_dupedkey))
+			goto again;
+	} else {
+		rn = rnode.rn_right;
+		size_cols_tree(rnode.rn_left);
+		size_cols_tree(rn);
+	}
+}
+
+static void
+size_cols_rtentry(struct rtentry *rt)
+{
+	static struct ifnet ifnet, *lastif;
+	static char buffer[100];
+	const char *bp;
+	struct sockaddr *sa;
+	sa_u addr, mask;
+	int len;
+
+	bzero(&addr, sizeof(addr));
+	if ((sa = kgetsa(rt_key(rt))))
+		bcopy(sa, &addr, sa->sa_len);
+	bzero(&mask, sizeof(mask));
+	if (rt_mask(rt) && (sa = kgetsa(rt_mask(rt))))
+		bcopy(sa, &mask, sa->sa_len);
+	bp = fmt_sockaddr(&addr.u_sa, &mask.u_sa, rt->rt_flags);
+	len = strlen(bp);
+	wid_dst = MAX(len, wid_dst);
+
+	bp = fmt_sockaddr(kgetsa(rt->rt_gateway), NULL, RTF_HOST);
+	len = strlen(bp);
+	wid_gw = MAX(len, wid_gw);
+
+	bp = fmt_flags(rt->rt_flags);
+	len = strlen(bp);
+	wid_flags = MAX(len, wid_flags);
+
+	if (addr.u_sa.sa_family == AF_INET || Wflag) {
+		len = snprintf(buffer, sizeof(buffer), "%d", rt->rt_refcnt);
+		wid_refs = MAX(len, wid_refs);
+		len = snprintf(buffer, sizeof(buffer), "%lu", rt->rt_use);
+		wid_use = MAX(len, wid_use);
+		if (Wflag && rt->rt_rmx.rmx_mtu != 0) {
+			len = snprintf(buffer, sizeof(buffer),
+				       "%lu", rt->rt_rmx.rmx_mtu);
+			wid_mtu = MAX(len, wid_mtu);
+		}
+	}
+	if (rt->rt_ifp) {
+		if (rt->rt_ifp != lastif) {
+			if (kget(rt->rt_ifp, ifnet) == 0) 
+				len = strlen(ifnet.if_xname);
+			else
+				len = strlen("---");
+			lastif = rt->rt_ifp;
+			wid_if = MAX(len, wid_if);
+		}
+		if (rt->rt_rmx.rmx_expire) {
+			time_t expire_time;
+
+			if ((expire_time =
+			    rt->rt_rmx.rmx_expire - uptime.tv_sec) > 0) {
+				len = snprintf(buffer, sizeof(buffer), "%d",
+					       (int)expire_time);
+				wid_expire = MAX(len, wid_expire);
+			}
+		}
+	}
+}
+
+
+/*
+ * Print header for routing table columns.
+ */
+void
+pr_rthdr(int af1)
+{
+
+	if (Aflag)
+		printf("%-8.8s ","Address");
+	if (af1 == AF_INET || Wflag) {
+		if (Wflag) {
+			printf("%-*.*s %-*.*s %-*.*s %*.*s %*.*s %*.*s %*.*s %*s\n",
+				wid_dst,	wid_dst,	"Destination",
+				wid_gw,		wid_gw,		"Gateway",
+				wid_flags,	wid_flags,	"Flags",
+				wid_refs,	wid_refs,	"Refs",
+				wid_use,	wid_use,	"Use",
+				wid_mtu,	wid_mtu,	"Mtu",
+				wid_if,		wid_if,		"Netif",
+				wid_expire,			"Expire");
+		} else {
+			printf("%-*.*s %-*.*s %-*.*s %*.*s %*.*s %*.*s %*s\n",
+				wid_dst,	wid_dst,	"Destination",
+				wid_gw,		wid_gw,		"Gateway",
+				wid_flags,	wid_flags,	"Flags",
+				wid_refs,	wid_refs,	"Refs",
+				wid_use,	wid_use,	"Use",
+				wid_if,		wid_if,		"Netif",
+				wid_expire,			"Expire");
+		}
+	} else {
+		printf("%-*.*s %-*.*s %-*.*s  %*.*s %*s\n",
+			wid_dst,	wid_dst,	"Destination",
+			wid_gw,		wid_gw,		"Gateway",
+			wid_flags,	wid_flags,	"Flags",
+			wid_if,		wid_if,		"Netif",
+			wid_expire,			"Expire");
+	}
+}
+
+static struct sockaddr *
+kgetsa(struct sockaddr *dst)
+{
+
+	if (kget(dst, pt_u.u_sa) != 0)
+		return (NULL);
+	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:
+	if (kget(rn, rnode) != 0)
+		return;
+	if (!(rnode.rn_flags & RNF_ACTIVE))
+		return;
+	if (rnode.rn_bit < 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) {
+			if (kget(rn, rtentry) == 0) {
+				p_rtentry(&rtentry);
+				if (Aflag)
+					p_rtnode();
+			}
+		} else {
+			p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_key),
+				   NULL, 0, 44);
+			putchar('\n');
+		}
+		if ((rn = rnode.rn_dupedkey))
+			goto again;
+	} else {
+		if (Aflag && do_rtent) {
+			printf("%-8.8lx ", (u_long)rn);
+			p_rtnode();
+		}
+		rn = rnode.rn_right;
+		p_tree(rnode.rn_left);
+		p_tree(rn);
+	}
+}
+
+char	nbuf[20];
+
+static void
+p_rtnode(void)
+{
+	struct radix_mask *rm = rnode.rn_mklist;
+
+	if (rnode.rn_bit < 0) {
+		if (rnode.rn_mask) {
+			printf("\t  mask ");
+			p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_mask),
+				   NULL, 0, -1);
+		} else if (rm == 0)
+			return;
+	} else {
+		sprintf(nbuf, "(%d)", rnode.rn_bit);
+		printf("%6.6s %8.8lx : %8.8lx", nbuf, (u_long)rnode.rn_left, (u_long)rnode.rn_right);
+	}
+	while (rm) {
+		if (kget(rm, rmask) != 0)
+			break;
+		sprintf(nbuf, " %d refs, ", rmask.rm_refs);
+		printf(" mk = %8.8lx {(%d),%s",
+			(u_long)rm, -1 - rmask.rm_bit, rmask.rm_refs ? nbuf : " ");
+		if (rmask.rm_flags & RNF_NORMAL) {
+			struct radix_node rnode_aux;
+			printf(" <normal>, ");
+			if (kget(rmask.rm_leaf, rnode_aux) == 0)
+				p_sockaddr(kgetsa((struct sockaddr *)rnode_aux.rn_mask),
+				    NULL, 0, -1);
+			else
+				p_sockaddr(NULL, NULL, 0, -1);
+		} else
+		    p_sockaddr(kgetsa((struct sockaddr *)rmask.rm_mask),
+				NULL, 0, -1);
+		putchar('}');
+		if ((rm = rmask.rm_mklist))
+			printf(" ->");
+	}
+	putchar('\n');
+}
+
+static void
+ntreestuff(void)
+{
+	size_t needed;
+	int mib[6];
+	char *buf, *next, *lim;
+	struct rt_msghdr *rtm;
+
+	mib[0] = CTL_NET;
+	mib[1] = PF_ROUTE;
+	mib[2] = 0;
+	mib[3] = 0;
+	mib[4] = NET_RT_DUMP;
+	mib[5] = 0;
+	if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
+		err(1, "sysctl: net.route.0.0.dump estimate");
+	}
+
+	if ((buf = malloc(needed)) == 0) {
+		errx(2, "malloc(%lu)", (unsigned long)needed);
+	}
+	if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
+		err(1, "sysctl: net.route.0.0.dump");
+	}
+	lim  = buf + needed;
+	for (next = buf; next < lim; next += rtm->rtm_msglen) {
+		rtm = (struct rt_msghdr *)next;
+		np_rtentry(rtm);
+	}
+}
+
+static void
+np_rtentry(struct rt_msghdr *rtm)
+{
+	struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
+#ifdef notdef
+	static int masks_done, banner_printed;
+#endif
+	static int old_af;
+	int af1 = 0, interesting = RTF_UP | RTF_GATEWAY | RTF_HOST;
+
+#ifdef notdef
+	/* for the moment, netmasks are skipped over */
+	if (!banner_printed) {
+		printf("Netmasks:\n");
+		banner_printed = 1;
+	}
+	if (masks_done == 0) {
+		if (rtm->rtm_addrs != RTA_DST ) {
+			masks_done = 1;
+			af1 = sa->sa_family;
+		}
+	} else
+#endif
+		af1 = sa->sa_family;
+	if (af1 != old_af) {
+		pr_family(af1);
+		old_af = af1;
+	}
+	if (rtm->rtm_addrs == RTA_DST)
+		p_sockaddr(sa, NULL, 0, 36);
+	else {
+		p_sockaddr(sa, NULL, rtm->rtm_flags, 16);
+		sa = (struct sockaddr *)(SA_SIZE(sa) + (char *)sa);
+		p_sockaddr(sa, NULL, 0, 18);
+	}
+	p_flags(rtm->rtm_flags & interesting, "%-6.6s ");
+	putchar('\n');
+}
+
+static void
+p_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags, int width)
+{
+	const char *cp;
+
+	cp = fmt_sockaddr(sa, mask, flags);
+
+	if (width < 0 )
+		printf("%s ", cp);
+	else {
+		if (numeric_addr)
+			printf("%-*s ", width, cp);
+		else
+			printf("%-*.*s ", width, width, cp);
+	}
+}
+
+static const char *
+fmt_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags)
+{
+	static char workbuf[128];
+	const char *cp;
+
+	if (sa == NULL)
+		return ("null");
+
+	switch(sa->sa_family) {
+	case AF_INET:
+	    {
+		struct sockaddr_in *sockin = (struct sockaddr_in *)sa;
+
+		if ((sockin->sin_addr.s_addr == INADDR_ANY) &&
+			mask &&
+			ntohl(((struct sockaddr_in *)mask)->sin_addr.s_addr)
+				==0L)
+				cp = "default" ;
+		else if (flags & RTF_HOST)
+			cp = routename(sockin->sin_addr.s_addr);
+		else if (mask)
+			cp = netname(sockin->sin_addr.s_addr,
+				     ntohl(((struct sockaddr_in *)mask)
+					   ->sin_addr.s_addr));
+		else
+			cp = netname(sockin->sin_addr.s_addr, 0L);
+		break;
+	    }
+
+#ifdef INET6
+	case AF_INET6:
+	    {
+		struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
+		struct in6_addr *in6 = &sa6->sin6_addr;
+
+		/*
+		 * XXX: This is a special workaround for KAME kernels.
+		 * sin6_scope_id field of SA should be set in the future.
+		 */
+		if (IN6_IS_ADDR_LINKLOCAL(in6) ||
+		    IN6_IS_ADDR_MC_LINKLOCAL(in6)) {
+		    /* XXX: override is ok? */
+		    sa6->sin6_scope_id = (u_int32_t)ntohs(*(u_short *)&in6->s6_addr[2]);
+		    *(u_short *)&in6->s6_addr[2] = 0;
+		}
+
+		if (flags & RTF_HOST)
+		    cp = routename6(sa6);
+		else if (mask)
+		    cp = netname6(sa6,
+				  &((struct sockaddr_in6 *)mask)->sin6_addr);
+		else {
+		    cp = netname6(sa6, NULL);
+		}
+		break;
+	    }
+#endif /*INET6*/
+
+#ifndef __rtems__
+	case AF_IPX:
+	    {
+		struct ipx_addr work = ((struct sockaddr_ipx *)sa)->sipx_addr;
+		if (ipx_nullnet(satoipx_addr(work)))
+			cp = "default";
+		else
+			cp = ipx_print(sa);
+		break;
+	    }
+	case AF_APPLETALK:
+	    {
+		if (!(flags & RTF_HOST) && mask)
+			cp = atalk_print2(sa,mask,9);
+		else
+			cp = atalk_print(sa,11);
+		break;
+	    }
+#endif
+	case AF_NETGRAPH:
+	    {
+#ifdef __rtems__
+		/* netgraph not supported yet */
+		err(EX_OSERR, "memory allocation failed");
+#else
+		strlcpy(workbuf, ((struct sockaddr_ng *)sa)->sg_data,
+		        sizeof(workbuf));
+		cp = workbuf;
+#endif
+		break;
+	    }
+
+	case AF_LINK:
+	    {
+		struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
+
+		if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 &&
+		    sdl->sdl_slen == 0) {
+			(void) sprintf(workbuf, "link#%d", sdl->sdl_index);
+			cp = workbuf;
+		} else
+			switch (sdl->sdl_type) {
+
+			case IFT_ETHER:
+			case IFT_L2VLAN:
+			case IFT_BRIDGE:
+				if (sdl->sdl_alen == ETHER_ADDR_LEN) {
+					cp = ether_ntoa((struct ether_addr *)
+					    (sdl->sdl_data + sdl->sdl_nlen));
+					break;
+				}
+				/* FALLTHROUGH */
+			default:
+				cp = link_ntoa(sdl);
+				break;
+			}
+		break;
+	    }
+
+	default:
+	    {
+		u_char *s = (u_char *)sa->sa_data, *slim;
+		char *cq, *cqlim;
+
+		cq = workbuf;
+		slim =  sa->sa_len + (u_char *) sa;
+		cqlim = cq + sizeof(workbuf) - 6;
+		cq += sprintf(cq, "(%d)", sa->sa_family);
+		while (s < slim && cq < cqlim) {
+			cq += sprintf(cq, " %02x", *s++);
+			if (s < slim)
+			    cq += sprintf(cq, "%02x", *s++);
+		}
+		cp = workbuf;
+	    }
+	}
+
+	return (cp);
+}
+
+static void
+p_flags(int f, const char *format)
+{
+	printf(format, fmt_flags(f));
+}
+
+static const char *
+fmt_flags(int f)
+{
+	static char name[33];
+	char *flags;
+	struct bits *p = bits;
+
+	for (flags = name; p->b_mask; p++)
+		if (p->b_mask & f)
+			*flags++ = p->b_val;
+	*flags = '\0';
+	return (name);
+}
+
+static void
+p_rtentry(struct rtentry *rt)
+{
+	static struct ifnet ifnet, *lastif;
+	static char buffer[128];
+	static char prettyname[128];
+	struct sockaddr *sa;
+	sa_u addr, mask;
+
+	bzero(&addr, sizeof(addr));
+	if ((sa = kgetsa(rt_key(rt))))
+		bcopy(sa, &addr, sa->sa_len);
+	bzero(&mask, sizeof(mask));
+	if (rt_mask(rt) && (sa = kgetsa(rt_mask(rt))))
+		bcopy(sa, &mask, sa->sa_len);
+	p_sockaddr(&addr.u_sa, &mask.u_sa, rt->rt_flags, wid_dst);
+	p_sockaddr(kgetsa(rt->rt_gateway), NULL, RTF_HOST, wid_gw);
+	snprintf(buffer, sizeof(buffer), "%%-%d.%ds ", wid_flags, wid_flags);
+	p_flags(rt->rt_flags, buffer);
+	if (addr.u_sa.sa_family == AF_INET || Wflag) {
+		printf("%*d %*lu ", wid_refs, rt->rt_refcnt,
+				     wid_use, rt->rt_use);
+		if (Wflag) {
+			if (rt->rt_rmx.rmx_mtu != 0)
+				printf("%*lu ", wid_mtu, rt->rt_rmx.rmx_mtu);
+			else
+				printf("%*s ", wid_mtu, "");
+		}
+	}
+	if (rt->rt_ifp) {
+		if (rt->rt_ifp != lastif) {
+			if (kget(rt->rt_ifp, ifnet) == 0)
+				strlcpy(prettyname, ifnet.if_xname,
+				    sizeof(prettyname));
+			else
+				strlcpy(prettyname, "---", sizeof(prettyname));
+			lastif = rt->rt_ifp;
+		}
+		printf("%*.*s", wid_if, wid_if, prettyname);
+		if (rt->rt_rmx.rmx_expire) {
+			time_t expire_time;
+
+			if ((expire_time =
+			    rt->rt_rmx.rmx_expire - uptime.tv_sec) > 0)
+				printf(" %*d", wid_expire, (int)expire_time);
+		}
+		if (rt->rt_nodes[0].rn_dupedkey)
+			printf(" =>");
+	}
+	putchar('\n');
+}
+
+char *
+routename(in_addr_t in)
+{
+	char *cp;
+	static char line[MAXHOSTNAMELEN];
+	struct hostent *hp;
+
+	cp = 0;
+	if (!numeric_addr) {
+		hp = gethostbyaddr(&in, sizeof (struct in_addr), AF_INET);
+		if (hp) {
+			cp = hp->h_name;
+			trimdomain(cp, strlen(cp));
+		}
+	}
+	if (cp) {
+		strlcpy(line, cp, sizeof(line));
+	} else {
+#define	C(x)	((x) & 0xff)
+		in = ntohl(in);
+		sprintf(line, "%u.%u.%u.%u",
+		    C(in >> 24), C(in >> 16), C(in >> 8), C(in));
+	}
+	return (line);
+}
+
+#define	NSHIFT(m) (							\
+	(m) == IN_CLASSA_NET ? IN_CLASSA_NSHIFT :			\
+	(m) == IN_CLASSB_NET ? IN_CLASSB_NSHIFT :			\
+	(m) == IN_CLASSC_NET ? IN_CLASSC_NSHIFT :			\
+	0)
+
+static void
+domask(char *dst, in_addr_t addr __unused, u_long mask)
+{
+	int b, i;
+
+	if (mask == 0 || (!numeric_addr && NSHIFT(mask) != 0)) {
+		*dst = '\0';
+		return;
+	}
+	i = 0;
+	for (b = 0; b < 32; b++)
+		if (mask & (1 << b)) {
+			int bb;
+
+			i = b;
+			for (bb = b+1; bb < 32; bb++)
+				if (!(mask & (1 << bb))) {
+					i = -1;	/* noncontig */
+					break;
+				}
+			break;
+		}
+	if (i == -1)
+		sprintf(dst, "&0x%lx", mask);
+	else
+		sprintf(dst, "/%d", 32-i);
+}
+
+/*
+ * Return the name of the network whose address is given.
+ * The address is assumed to be that of a net or subnet, not a host.
+ */
+char *
+netname(in_addr_t in, u_long mask)
+{
+	char *cp = 0;
+	static char line[MAXHOSTNAMELEN];
+	struct netent *np = 0;
+	in_addr_t i;
+
+	i = ntohl(in);
+	if (!numeric_addr && i) {
+		np = getnetbyaddr(i >> NSHIFT(mask), AF_INET);
+		if (np != NULL) {
+			cp = np->n_name;
+			trimdomain(cp, strlen(cp));
+		}
+	}
+	if (cp != NULL) {
+		strlcpy(line, cp, sizeof(line));
+	} else {
+		inet_ntop(AF_INET, &in, line, sizeof(line) - 1);
+	}
+	domask(line + strlen(line), i, mask);
+	return (line);
+}
+
+#undef NSHIFT
+
+#ifdef INET6
+const char *
+netname6(struct sockaddr_in6 *sa6, struct in6_addr *mask)
+{
+	static char line[MAXHOSTNAMELEN];
+	u_char *p = (u_char *)mask;
+	u_char *lim;
+	int masklen, illegal = 0, flag = 0;
+
+	if (mask) {
+		for (masklen = 0, lim = p + 16; p < lim; p++) {
+			switch (*p) {
+			 case 0xff:
+				 masklen += 8;
+				 break;
+			 case 0xfe:
+				 masklen += 7;
+				 break;
+			 case 0xfc:
+				 masklen += 6;
+				 break;
+			 case 0xf8:
+				 masklen += 5;
+				 break;
+			 case 0xf0:
+				 masklen += 4;
+				 break;
+			 case 0xe0:
+				 masklen += 3;
+				 break;
+			 case 0xc0:
+				 masklen += 2;
+				 break;
+			 case 0x80:
+				 masklen += 1;
+				 break;
+			 case 0x00:
+				 break;
+			 default:
+				 illegal ++;
+				 break;
+			}
+		}
+		if (illegal)
+			fprintf(stderr, "illegal prefixlen\n");
+	}
+	else
+		masklen = 128;
+
+	if (masklen == 0 && IN6_IS_ADDR_UNSPECIFIED(&sa6->sin6_addr))
+		return("default");
+
+	if (numeric_addr)
+		flag |= NI_NUMERICHOST;
+	getnameinfo((struct sockaddr *)sa6, sa6->sin6_len, line, sizeof(line),
+		    NULL, 0, flag);
+
+	if (numeric_addr)
+		sprintf(&line[strlen(line)], "/%d", masklen);
+
+	return line;
+}
+
+char *
+routename6(struct sockaddr_in6 *sa6)
+{
+	static char line[MAXHOSTNAMELEN];
+	int flag = 0;
+	/* use local variable for safety */
+	struct sockaddr_in6 sa6_local;
+
+	sa6_local.sin6_family = AF_INET6;
+	sa6_local.sin6_len = sizeof(sa6_local);
+	sa6_local.sin6_addr = sa6->sin6_addr;
+	sa6_local.sin6_scope_id = sa6->sin6_scope_id;
+
+	if (numeric_addr)
+		flag |= NI_NUMERICHOST;
+
+	getnameinfo((struct sockaddr *)&sa6_local, sa6_local.sin6_len,
+		    line, sizeof(line), NULL, 0, flag);
+
+	return line;
+}
+#endif /*INET6*/
+
+/*
+ * Print routing statistics
+ */
+void
+rt_stats(u_long rtsaddr, u_long rttaddr)
+{
+	struct rtstat rtstat;
+	int rttrash;
+
+	if (rtsaddr == 0) {
+		printf("rtstat: symbol not in namelist\n");
+		return;
+	}
+	if (rttaddr == 0) {
+		printf("rttrash: symbol not in namelist\n");
+		return;
+	}
+	kread(rtsaddr, (char *)&rtstat, sizeof (rtstat));
+	kread(rttaddr, (char *)&rttrash, sizeof (rttrash));
+	printf("routing:\n");
+
+#define	p(f, m) if (rtstat.f || sflag <= 1) \
+	printf(m, rtstat.f, plural(rtstat.f))
+
+	p(rts_badredirect, "\t%hu bad routing redirect%s\n");
+	p(rts_dynamic, "\t%hu dynamically created route%s\n");
+	p(rts_newgateway, "\t%hu new gateway%s due to redirects\n");
+	p(rts_unreach, "\t%hu destination%s found unreachable\n");
+	p(rts_wildcard, "\t%hu use%s of a wildcard route\n");
+#undef p
+
+	if (rttrash || sflag <= 1)
+		printf("\t%u route%s not in table but not freed\n",
+		    rttrash, plural(rttrash));
+}
+
+#ifndef __rtems__
+char *
+ipx_print(struct sockaddr *sa)
+{
+	u_short port;
+	struct servent *sp = 0;
+	const char *net = "", *host = "";
+	char *p;
+	u_char *q;
+	struct ipx_addr work = ((struct sockaddr_ipx *)sa)->sipx_addr;
+	static char mybuf[50];
+	char cport[10], chost[15], cnet[15];
+
+	port = ntohs(work.x_port);
+
+	if (ipx_nullnet(work) && ipx_nullhost(work)) {
+
+		if (port) {
+			if (sp)
+				sprintf(mybuf, "*.%s", sp->s_name);
+			else
+				sprintf(mybuf, "*.%x", port);
+		} else
+			sprintf(mybuf, "*.*");
+
+		return (mybuf);
+	}
+
+	if (ipx_wildnet(work))
+		net = "any";
+	else if (ipx_nullnet(work))
+		net = "*";
+	else {
+		q = work.x_net.c_net;
+		sprintf(cnet, "%02x%02x%02x%02x",
+			q[0], q[1], q[2], q[3]);
+		for (p = cnet; *p == '0' && p < cnet + 8; p++)
+			continue;
+		net = p;
+	}
+
+	if (ipx_wildhost(work))
+		host = "any";
+	else if (ipx_nullhost(work))
+		host = "*";
+	else {
+		q = work.x_host.c_host;
+		sprintf(chost, "%02x%02x%02x%02x%02x%02x",
+			q[0], q[1], q[2], q[3], q[4], q[5]);
+		for (p = chost; *p == '0' && p < chost + 12; p++)
+			continue;
+		host = p;
+	}
+
+	if (port) {
+		if (strcmp(host, "*") == 0)
+			host = "";
+		if (sp)
+			snprintf(cport, sizeof(cport),
+				"%s%s", *host ? "." : "", sp->s_name);
+		else
+			snprintf(cport, sizeof(cport),
+				"%s%x", *host ? "." : "", port);
+	} else
+		*cport = 0;
+
+	snprintf(mybuf, sizeof(mybuf), "%s.%s%s", net, host, cport);
+	return(mybuf);
+}
+
+char *
+ipx_phost(struct sockaddr *sa)
+{
+	struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)sa;
+	struct sockaddr_ipx work;
+	static union ipx_net ipx_zeronet;
+	char *p;
+	struct ipx_addr in;
+
+	work = *sipx;
+	in = work.sipx_addr;
+
+	work.sipx_addr.x_port = 0;
+	work.sipx_addr.x_net = ipx_zeronet;
+	p = ipx_print((struct sockaddr *)&work);
+	if (strncmp("*.", p, 2) == 0) p += 2;
+
+	return(p);
+}
+#endif
+
+void
+upHex(char *p0)
+{
+	char *p = p0;
+
+	for (; *p; p++)
+		switch (*p) {
+
+		case 'a':
+		case 'b':
+		case 'c':
+		case 'd':
+		case 'e':
+		case 'f':
+			*p += ('A' - 'a');
+			break;
+		}
+}
diff --git a/freebsd-userspace/commands/usr.bin/netstat/sctp.c b/freebsd-userspace/commands/usr.bin/netstat/sctp.c
new file mode 100644
index 0000000..0c02db9
--- /dev/null
+++ b/freebsd-userspace/commands/usr.bin/netstat/sctp.c
@@ -0,0 +1,703 @@
+/*-
+ * Copyright (c) 2001-2007, by Weongyo Jeong. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * a) Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ *
+ * b) 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.
+ *
+ * c) Neither the name of Cisco Systems, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)sctp.c	0.1 (Berkeley) 4/18/2007";
+#endif /* not lint */
+#endif
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/sysctl.h>
+#ifdef __rtems__
+#include <freebsd/sys/protosw.h>
+#else
+#include <sys/protosw.h>
+#endif
+
+#include <netinet/in.h>
+#ifdef __rtems__
+#include <freebsd/netinet/sctp.h>
+#include <freebsd/netinet/sctp_constants.h>
+#else
+#include <netinet/sctp.h>
+#include <netinet/sctp_constants.h>
+#endif
+#include <arpa/inet.h>
+
+#include <err.h>
+#include <errno.h>
+#ifdef __rtems__
+/* apparently libutil.h is not needed */
+#else
+#include <libutil.h>
+#endif
+#include <netdb.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "netstat.h"
+
+#ifdef SCTP
+
+void	inetprint(struct in_addr *, int, const char *, int);
+static void sctp_statesprint(uint32_t state);
+
+#define	NETSTAT_SCTP_STATES_CLOSED		0x0
+#define	NETSTAT_SCTP_STATES_BOUND		0x1
+#define	NETSTAT_SCTP_STATES_LISTEN		0x2
+#define	NETSTAT_SCTP_STATES_COOKIE_WAIT		0x3
+#define	NETSTAT_SCTP_STATES_COOKIE_ECHOED	0x4
+#define	NETSTAT_SCTP_STATES_ESTABLISHED		0x5
+#define	NETSTAT_SCTP_STATES_SHUTDOWN_SENT	0x6
+#define	NETSTAT_SCTP_STATES_SHUTDOWN_RECEIVED	0x7
+#define	NETSTAT_SCTP_STATES_SHUTDOWN_ACK_SENT	0x8
+#define	NETSTAT_SCTP_STATES_SHUTDOWN_PENDING	0x9
+
+char *sctpstates[] = {
+	"CLOSED",
+	"BOUND",
+	"LISTEN",
+	"COOKIE_WAIT",
+	"COOKIE_ECHOED",
+	"ESTABLISHED",
+	"SHUTDOWN_SENT",
+	"SHUTDOWN_RECEIVED",
+	"SHUTDOWN_ACK_SENT",
+	"SHUTDOWN_PENDING"
+};
+
+LIST_HEAD(xladdr_list, xladdr_entry) xladdr_head;
+struct xladdr_entry {
+	struct xsctp_laddr *xladdr;
+	LIST_ENTRY(xladdr_entry) xladdr_entries;
+};
+
+LIST_HEAD(xraddr_list, xraddr_entry) xraddr_head;
+struct xraddr_entry {
+        struct xsctp_raddr *xraddr;
+        LIST_ENTRY(xraddr_entry) xraddr_entries;
+};
+
+static int
+sctp_skip_xinpcb_ifneed(char *buf, const size_t buflen, size_t *offset)
+{
+	int exist_tcb = 0;
+	struct xsctp_tcb *xstcb;
+	struct xsctp_raddr *xraddr;
+	struct xsctp_laddr *xladdr;
+
+	while (*offset < buflen) {
+		xladdr = (struct xsctp_laddr *)(buf + *offset);
+		*offset += sizeof(struct xsctp_laddr);
+		if (xladdr->last == 1)
+			break;
+	}
+
+	while (*offset < buflen) {
+		xstcb = (struct xsctp_tcb *)(buf + *offset);
+		*offset += sizeof(struct xsctp_tcb);
+		if (xstcb->last == 1)
+			break;
+
+		exist_tcb = 1;
+
+		while (*offset < buflen) {
+			xladdr = (struct xsctp_laddr *)(buf + *offset);
+			*offset += sizeof(struct xsctp_laddr);
+			if (xladdr->last == 1)
+				break;
+		}
+
+		while (*offset < buflen) {
+			xraddr = (struct xsctp_raddr *)(buf + *offset);
+			*offset += sizeof(struct xsctp_raddr);
+			if (xraddr->last == 1)
+				break;
+		}
+	}
+
+	/*
+	 * If Lflag is set, we don't care about the return value.
+	 */
+	if (Lflag)
+		return 0;
+
+	return exist_tcb;
+}
+
+static void
+sctp_process_tcb(struct xsctp_tcb *xstcb, const char *name,
+    char *buf, const size_t buflen, size_t *offset, int *indent)
+{
+	int i, xl_total = 0, xr_total = 0, x_max;
+	struct sockaddr *sa;
+	struct xsctp_raddr *xraddr;
+	struct xsctp_laddr *xladdr;
+	struct xladdr_entry *prev_xl = NULL, *xl = NULL, *xl_tmp;
+	struct xraddr_entry *prev_xr = NULL, *xr = NULL, *xr_tmp;
+#ifdef INET6
+	struct sockaddr_in6 *in6;
+#endif
+
+	LIST_INIT(&xladdr_head);
+	LIST_INIT(&xraddr_head);
+
+	/*
+	 * Make `struct xladdr_list' list and `struct xraddr_list' list
+	 * to handle the address flexibly.
+	 */
+	while (*offset < buflen) {
+		xladdr = (struct xsctp_laddr *)(buf + *offset);
+		*offset += sizeof(struct xsctp_laddr);
+		if (xladdr->last == 1)
+			break;
+
+		prev_xl = xl;
+		xl = malloc(sizeof(struct xladdr_entry));
+		if (xl == NULL) {
+			warnx("malloc %lu bytes",
+			    (u_long)sizeof(struct xladdr_entry));
+			goto out;
+		}
+		xl->xladdr = xladdr;
+		if (prev_xl == NULL)
+			LIST_INSERT_HEAD(&xladdr_head, xl, xladdr_entries);
+		else
+			LIST_INSERT_AFTER(prev_xl, xl, xladdr_entries);
+		xl_total++;
+	}
+
+	while (*offset < buflen) {
+		xraddr = (struct xsctp_raddr *)(buf + *offset);
+		*offset += sizeof(struct xsctp_raddr);
+		if (xraddr->last == 1)
+			break;
+
+		prev_xr = xr;
+		xr = malloc(sizeof(struct xraddr_entry));
+		if (xr == NULL) {
+			warnx("malloc %lu bytes",
+			    (u_long)sizeof(struct xraddr_entry));
+			goto out;
+		}
+		xr->xraddr = xraddr;
+		if (prev_xr == NULL)
+			LIST_INSERT_HEAD(&xraddr_head, xr, xraddr_entries);
+		else
+			LIST_INSERT_AFTER(prev_xr, xr, xraddr_entries);
+		xr_total++;
+	}
+
+	/*
+	 * Let's print the address infos.
+	 */
+	xl = LIST_FIRST(&xladdr_head);
+	xr = LIST_FIRST(&xraddr_head);
+	x_max = (xl_total > xr_total) ? xl_total : xr_total;
+	for (i = 0; i < x_max; i++) {
+		if (((*indent == 0) && i > 0) || *indent > 0)
+			printf("%-11s ", " ");
+
+		if (xl != NULL) {
+			sa = &(xl->xladdr->address.sa);
+			if ((sa->sa_family) == AF_INET)
+				inetprint(&((struct sockaddr_in *)sa)->sin_addr,
+				    htons(xstcb->local_port),
+				    name, numeric_port);
+#ifdef INET6
+			else {
+				in6 = (struct sockaddr_in6 *)sa;
+				inet6print(&in6->sin6_addr,
+				    htons(xstcb->local_port),
+				    name, numeric_port);
+			}
+#endif
+		}
+
+		if (xr != NULL && !Lflag) {
+			sa = &(xr->xraddr->address.sa);
+			if ((sa->sa_family) == AF_INET)
+				inetprint(&((struct sockaddr_in *)sa)->sin_addr,
+				    htons(xstcb->remote_port),
+				    name, numeric_port);
+#ifdef INET6
+			else {
+				in6 = (struct sockaddr_in6 *)sa;
+				inet6print(&in6->sin6_addr,
+				    htons(xstcb->remote_port),
+				    name, numeric_port);
+			}
+#endif
+		}
+
+		if (xl != NULL)
+			xl = LIST_NEXT(xl, xladdr_entries);
+		if (xr != NULL)
+			xr = LIST_NEXT(xr, xraddr_entries);
+
+		if (i == 0 && !Lflag)
+			sctp_statesprint(xstcb->state);
+
+		if (i < x_max)
+			putchar('\n');
+	}
+
+out:
+	/*
+	 * Free the list which be used to handle the address.
+	 */
+	xl = LIST_FIRST(&xladdr_head);
+	while (xl != NULL) {
+		xl_tmp = LIST_NEXT(xl, xladdr_entries);
+		free(xl);
+		xl = xl_tmp;
+	}
+
+	xr = LIST_FIRST(&xraddr_head);
+	while (xr != NULL) {
+		xr_tmp = LIST_NEXT(xr, xraddr_entries);
+		free(xr);
+		xr = xr_tmp;
+	}
+}
+
+#ifdef SCTP_DEBUG
+uint32_t sctp_pdup[64];
+int sctp_pcnt = 0;
+#endif
+
+static void
+sctp_process_inpcb(struct xsctp_inpcb *xinpcb, const char *name,
+    char *buf, const size_t buflen, size_t *offset)
+{
+	int offset_backup, indent = 0, xladdr_total = 0, is_listening = 0;
+	static int first = 1;
+	char *tname;
+	struct xsctp_tcb *xstcb;
+	struct xsctp_laddr *xladdr;
+	struct sockaddr *sa;
+#ifdef INET6
+	struct sockaddr_in6 *in6;
+#endif
+
+	if ((xinpcb->flags & SCTP_PCB_FLAGS_TCPTYPE) ==
+	    SCTP_PCB_FLAGS_TCPTYPE && xinpcb->maxqlen > 0)
+		is_listening = 1;
+
+	if (!Lflag && !is_listening &&
+	    !(xinpcb->flags & SCTP_PCB_FLAGS_CONNECTED)) {
+#ifdef SCTP_DEBUG
+		int i, found = 0;
+
+		for (i = 0; i < sctp_pcnt; i++) {
+			if (sctp_pdup[i] == xinpcb->flags) {
+				found = 1;
+				break;
+			}
+		}
+		if (!found) {
+			sctp_pdup[sctp_pcnt++] = xinpcb->flags;
+			if (sctp_pcnt >= 64)
+				sctp_pcnt = 0;
+			printf("[0x%08x]", xinpcb->flags);
+		}
+#endif
+		offset_backup = *offset;
+		if (!sctp_skip_xinpcb_ifneed(buf, buflen, offset))
+			return;
+		*offset = offset_backup;
+	}
+
+	if (first) {
+		if (!Lflag) {
+			printf("Active SCTP associations");
+			if (aflag)
+				printf(" (including servers)");
+		} else
+			printf("Current listen queue sizes (qlen/maxqlen)");
+		putchar('\n');
+		if (Aflag)
+			printf("%-8.8s ", "Socket");
+		if (Lflag)
+			printf("%-5.5s %-5.5s %-8.8s %-22.22s\n",
+			    "Proto", "Type", "Listen", "Local Address");
+		else
+			printf((Aflag && !Wflag) ?
+			    "%-5.5s %-5.5s %-18.18s %-18.18s %s\n" :
+			    "%-5.5s %-5.5s %-22.22s %-22.22s %s\n",
+			    "Proto", "Type",
+			    "Local Address", "Foreign Address",
+			    "(state)");
+		first = 0;
+	}
+	if (Lflag && xinpcb->maxqlen == 0) {
+		(int)sctp_skip_xinpcb_ifneed(buf, buflen, offset);
+		return;
+	}
+	if (Aflag)
+		printf("%8lx ", (u_long)xinpcb);
+
+	printf("%-5.5s ", name);
+
+	if (xinpcb->flags & SCTP_PCB_FLAGS_TCPTYPE)
+		tname = "1to1";
+	else if (xinpcb->flags & SCTP_PCB_FLAGS_UDPTYPE)
+		tname = "1toN";
+	else
+		return;
+
+	printf("%-5.5s ", tname);
+
+	if (Lflag) {
+		char buf1[9];
+
+		snprintf(buf1, 9, "%hu/%hu", xinpcb->qlen, xinpcb->maxqlen);
+		printf("%-8.8s ", buf1);
+	}
+	/*
+	 * process the local address.  This routine are used for Lflag.
+	 */
+	while (*offset < buflen) {
+		xladdr = (struct xsctp_laddr *)(buf + *offset);
+		*offset += sizeof(struct xsctp_laddr);
+		if (xladdr->last == 1)
+			break;
+
+		if (!Lflag && !is_listening)
+			continue;
+
+		if (xladdr_total != 0)
+			putchar('\n');
+		if (xladdr_total > 0)
+			printf((Lflag) ?
+			    "%-20.20s " : "%-11.11s ", " ");
+
+		sa = &(xladdr->address.sa);
+		if ((sa->sa_family) == AF_INET)
+			inetprint(&((struct sockaddr_in *)sa)->sin_addr,
+			    htons(xinpcb->local_port), name, numeric_port);
+#ifdef INET6
+		else {
+			in6 = (struct sockaddr_in6 *)sa;
+			inet6print(&in6->sin6_addr,
+			    htons(xinpcb->local_port), name, numeric_port);
+		}
+#endif
+
+		if (!Lflag && xladdr_total == 0 && is_listening == 1)
+			printf("%-22.22s LISTEN", " ");
+
+		xladdr_total++;
+	}
+
+	xstcb = (struct xsctp_tcb *)(buf + *offset);
+	*offset += sizeof(struct xsctp_tcb);
+	while (xstcb->last == 0 && *offset < buflen) {
+		sctp_process_tcb(xstcb, name, buf, buflen, offset, &indent);
+		indent++;
+		xstcb = (struct xsctp_tcb *)(buf + *offset);
+		*offset += sizeof(struct xsctp_tcb);
+	}
+
+	putchar('\n');
+}
+
+/*
+ * Print a summary of SCTP connections related to an Internet
+ * protocol.
+ */
+void
+sctp_protopr(u_long off __unused,
+    const char *name, int af1, int proto)
+{
+	char *buf;
+	const char *mibvar = "net.inet.sctp.assoclist";
+	size_t offset = 0;
+	size_t len = 0;
+	struct xsctp_inpcb *xinpcb;
+
+	if (proto != IPPROTO_SCTP)
+		return;
+
+	if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
+		if (errno != ENOENT)
+			warn("sysctl: %s", mibvar);
+		return;
+	}
+	if ((buf = malloc(len)) == 0) {
+		warnx("malloc %lu bytes", (u_long)len);
+		return;
+	}
+	if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
+		warn("sysctl: %s", mibvar);
+		free(buf);
+		return;
+	}
+
+	xinpcb = (struct xsctp_inpcb *)(buf + offset);
+	offset += sizeof(struct xsctp_inpcb);
+	while (xinpcb->last == 0 && offset < len) {
+		sctp_process_inpcb(xinpcb, name, buf, (const size_t)len,
+		    &offset);
+
+		xinpcb = (struct xsctp_inpcb *)(buf + offset);
+		offset += sizeof(struct xsctp_inpcb);
+	}
+
+	free(buf);
+}
+
+static void
+sctp_statesprint(uint32_t state)
+{
+	int idx;
+
+	switch (state) {
+	case SCTP_STATE_COOKIE_WAIT:
+		idx = NETSTAT_SCTP_STATES_COOKIE_WAIT;
+		break;
+	case SCTP_STATE_COOKIE_ECHOED:
+		idx = NETSTAT_SCTP_STATES_COOKIE_ECHOED;
+		break;
+	case SCTP_STATE_OPEN:
+		idx = NETSTAT_SCTP_STATES_ESTABLISHED;
+		break;
+	case SCTP_STATE_SHUTDOWN_SENT:
+		idx = NETSTAT_SCTP_STATES_SHUTDOWN_SENT;
+		break;
+	case SCTP_STATE_SHUTDOWN_RECEIVED:
+		idx = NETSTAT_SCTP_STATES_SHUTDOWN_RECEIVED;
+		break;
+	case SCTP_STATE_SHUTDOWN_ACK_SENT:
+		idx = NETSTAT_SCTP_STATES_SHUTDOWN_ACK_SENT;
+		break;
+	case SCTP_STATE_SHUTDOWN_PENDING:
+		idx = NETSTAT_SCTP_STATES_SHUTDOWN_PENDING;
+		break;
+	default:
+		printf("UNKNOWN 0x%08x", state);
+		return;
+	}
+
+	printf("%s", sctpstates[idx]);
+}
+
+/*
+ * Dump SCTP statistics structure.
+ */
+void
+sctp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+	struct sctpstat sctpstat, zerostat;
+	size_t len = sizeof(sctpstat);
+
+	if (live) {
+		if (zflag)
+			memset(&zerostat, 0, len);
+		if (sysctlbyname("net.inet.sctp.stats", &sctpstat, &len,
+		    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+			warn("sysctl: net.inet.sctp.stats");
+			return;
+		}
+	} else
+		kread(off, &sctpstat, len);
+
+	printf ("%s:\n", name);
+
+#define	p(f, m) if (sctpstat.f || sflag <= 1) \
+    printf(m, (uintmax_t)sctpstat.f, plural(sctpstat.f))
+#define	p1a(f, m) if (sctpstat.f || sflag <= 1) \
+    printf(m, (uintmax_t)sctpstat.f)
+
+	/*
+	 * input statistics
+	 */
+	p(sctps_recvpackets, "\t%ju input packet%s\n");
+	p(sctps_recvdatagrams, "\t\t%ju datagram%s\n");
+	p(sctps_recvpktwithdata, "\t\t%ju packet%s that had data\n");
+	p(sctps_recvsacks, "\t\t%ju input SACK chunk%s\n");
+	p(sctps_recvdata, "\t\t%ju input DATA chunk%s\n");
+	p(sctps_recvdupdata, "\t\t%ju duplicate DATA chunk%s\n");
+	p(sctps_recvheartbeat, "\t\t%ju input HB chunk%s\n");
+	p(sctps_recvheartbeatack, "\t\t%ju HB-ACK chunk%s\n");
+	p(sctps_recvecne, "\t\t%ju input ECNE chunk%s\n");
+	p(sctps_recvauth, "\t\t%ju input AUTH chunk%s\n");
+	p(sctps_recvauthmissing, "\t\t%ju chunk%s missing AUTH\n");
+	p(sctps_recvivalhmacid, "\t\t%ju invalid HMAC id%s received\n");
+	p(sctps_recvivalkeyid, "\t\t%ju invalid secret id%s received\n");
+	p1a(sctps_recvauthfailed, "\t\t%ju auth failed\n");
+	p1a(sctps_recvexpress, "\t\t%ju fast path receives all one chunk\n");
+	p1a(sctps_recvexpressm, "\t\t%ju fast path multi-part data\n");
+
+	/*
+	 * output statistics
+	 */
+	p(sctps_sendpackets, "\t%ju output packet%s\n");
+	p(sctps_sendsacks, "\t\t%ju output SACK%s\n");
+	p(sctps_senddata, "\t\t%ju output DATA chunk%s\n");
+	p(sctps_sendretransdata, "\t\t%ju retransmitted DATA chunk%s\n");
+	p(sctps_sendfastretrans, "\t\t%ju fast retransmitted DATA chunk%s\n");
+	p(sctps_sendmultfastretrans, "\t\t%ju FR'%s that happened more "
+	    "than once to same chunk\n");
+	p(sctps_sendheartbeat, "\t\t%ju intput HB chunk%s\n");
+	p(sctps_sendecne, "\t\t%ju output ECNE chunk%s\n");
+	p(sctps_sendauth, "\t\t%ju output AUTH chunk%s\n");
+	p1a(sctps_senderrors, "\t\t%ju ip_output error counter\n");
+
+	/*
+	 * PCKDROPREP statistics
+	 */
+	printf("\tPacket drop statistics:\n");
+	p1a(sctps_pdrpfmbox, "\t\t%ju from middle box\n");
+	p1a(sctps_pdrpfehos, "\t\t%ju from end host\n");
+	p1a(sctps_pdrpmbda, "\t\t%ju with data\n");
+	p1a(sctps_pdrpmbct, "\t\t%ju non-data, non-endhost\n");
+	p1a(sctps_pdrpbwrpt, "\t\t%ju non-endhost, bandwidth rep only\n");
+	p1a(sctps_pdrpcrupt, "\t\t%ju not enough for chunk header\n");
+	p1a(sctps_pdrpnedat, "\t\t%ju not enough data to confirm\n");
+	p1a(sctps_pdrppdbrk, "\t\t%ju where process_chunk_drop said break\n");
+	p1a(sctps_pdrptsnnf, "\t\t%ju failed to find TSN\n");
+	p1a(sctps_pdrpdnfnd, "\t\t%ju attempt reverse TSN lookup\n");
+	p1a(sctps_pdrpdiwnp, "\t\t%ju e-host confirms zero-rwnd\n");
+	p1a(sctps_pdrpdizrw, "\t\t%ju midbox confirms no space\n");
+	p1a(sctps_pdrpbadd, "\t\t%ju data did not match TSN\n");
+	p(sctps_pdrpmark, "\t\t%ju TSN'%s marked for Fast Retran\n");
+
+	/*
+	 * Timeouts
+	 */
+	printf("\tTimeouts:\n");
+	p(sctps_timoiterator, "\t\t%ju iterator timer%s fired\n");
+	p(sctps_timodata, "\t\t%ju T3 data time out%s\n");
+	p(sctps_timowindowprobe, "\t\t%ju window probe (T3) timer%s fired\n");
+	p(sctps_timoinit, "\t\t%ju INIT timer%s fired\n");
+	p(sctps_timosack, "\t\t%ju sack timer%s fired\n");
+	p(sctps_timoshutdown, "\t\t%ju shutdown timer%s fired\n");
+	p(sctps_timoheartbeat, "\t\t%ju heartbeat timer%s fired\n");
+	p1a(sctps_timocookie, "\t\t%ju a cookie timeout fired\n");
+	p1a(sctps_timosecret, "\t\t%ju an endpoint changed its cookie"
+	    "secret\n");
+	p(sctps_timopathmtu, "\t\t%ju PMTU timer%s fired\n");
+	p(sctps_timoshutdownack, "\t\t%ju shutdown ack timer%s fired\n");
+	p(sctps_timoshutdownguard, "\t\t%ju shutdown guard timer%s fired\n");
+	p(sctps_timostrmrst, "\t\t%ju stream reset timer%s fired\n");
+	p(sctps_timoearlyfr, "\t\t%ju early FR timer%s fired\n");
+	p1a(sctps_timoasconf, "\t\t%ju an asconf timer fired\n");
+	p1a(sctps_timoautoclose, "\t\t%ju auto close timer fired\n");
+	p(sctps_timoassockill, "\t\t%ju asoc free timer%s expired\n");
+	p(sctps_timoinpkill, "\t\t%ju inp free timer%s expired\n");
+
+#if 0
+	/*
+	 * Early fast retransmission counters
+	 */
+	p(sctps_earlyfrstart, "\t%ju TODO:sctps_earlyfrstart\n");
+	p(sctps_earlyfrstop, "\t%ju TODO:sctps_earlyfrstop\n");
+	p(sctps_earlyfrmrkretrans, "\t%ju TODO:sctps_earlyfrmrkretrans\n");
+	p(sctps_earlyfrstpout, "\t%ju TODO:sctps_earlyfrstpout\n");
+	p(sctps_earlyfrstpidsck1, "\t%ju TODO:sctps_earlyfrstpidsck1\n");
+	p(sctps_earlyfrstpidsck2, "\t%ju TODO:sctps_earlyfrstpidsck2\n");
+	p(sctps_earlyfrstpidsck3, "\t%ju TODO:sctps_earlyfrstpidsck3\n");
+	p(sctps_earlyfrstpidsck4, "\t%ju TODO:sctps_earlyfrstpidsck4\n");
+	p(sctps_earlyfrstrid, "\t%ju TODO:sctps_earlyfrstrid\n");
+	p(sctps_earlyfrstrout, "\t%ju TODO:sctps_earlyfrstrout\n");
+	p(sctps_earlyfrstrtmr, "\t%ju TODO:sctps_earlyfrstrtmr\n");
+#endif
+
+	/*
+	 * Others
+	 */
+	p1a(sctps_hdrops, "\t%ju packet shorter than header\n");
+	p1a(sctps_badsum, "\t%ju checksum error\n");
+	p1a(sctps_noport, "\t%ju no endpoint for port\n");
+	p1a(sctps_badvtag, "\t%ju bad v-tag\n");
+	p1a(sctps_badsid, "\t%ju bad SID\n");
+	p1a(sctps_nomem, "\t%ju no memory\n");
+	p1a(sctps_fastretransinrtt, "\t%ju number of multiple FR in a RTT "
+	    "window\n");
+#if 0
+	p(sctps_markedretrans, "\t%ju TODO:sctps_markedretrans\n");
+#endif
+	p1a(sctps_naglesent, "\t%ju RFC813 allowed sending\n");
+	p1a(sctps_naglequeued, "\t%ju RFC813 does not allow sending\n");
+	p1a(sctps_maxburstqueued, "\t%ju times max burst prohibited sending\n");
+	p1a(sctps_ifnomemqueued, "\t%ju look ahead tells us no memory in "
+	    "interface\n");
+	p(sctps_windowprobed, "\t%ju number%s of window probes sent\n");
+	p(sctps_lowlevelerr, "\t%ju time%s an output error to clamp "
+	    "down on next user send\n");
+	p(sctps_lowlevelerrusr, "\t%ju time%s sctp_senderrors were "
+	    "caused from a user\n");
+	p(sctps_datadropchklmt, "\t%ju number of in data drop%s due to "
+	    "chunk limit reached\n");
+	p(sctps_datadroprwnd, "\t%ju number of in data drop%s due to rwnd "
+	    "limit reached\n");
+	p(sctps_ecnereducedcwnd, "\t%ju time%s a ECN reduced "
+	    "the cwnd\n");
+	p1a(sctps_vtagexpress, "\t%ju used express lookup via vtag\n");
+	p1a(sctps_vtagbogus, "\t%ju collision in express lookup\n");
+	p(sctps_primary_randry, "\t%ju time%s the sender ran dry "
+	    "of user data on primary\n");
+	p1a(sctps_cmt_randry, "\t%ju same for above\n");
+	p(sctps_slowpath_sack, "\t%ju sack%s the slow way\n");
+	p(sctps_wu_sacks_sent, "\t%ju window update only sack%s sent\n");
+	p(sctps_sends_with_flags, "\t%ju send%s with sinfo_flags !=0\n");
+	p(sctps_sends_with_unord, "\t%ju unordered send%s\n");
+	p(sctps_sends_with_eof, "\t%ju send%s with EOF flag set\n");
+	p(sctps_sends_with_abort, "\t%ju send%s with ABORT flag set\n");
+	p(sctps_protocol_drain_calls, "\t%ju time%s protocol drain called\n");
+	p(sctps_protocol_drains_done, "\t%ju time%s we did a protocol "
+	    "drain\n");
+	p(sctps_read_peeks, "\t%ju time%s recv was called with peek\n");
+	p(sctps_cached_chk, "\t%ju cached chunk%s used\n");
+	p1a(sctps_cached_strmoq, "\t%ju cached stream oq's used\n");
+	p(sctps_left_abandon, "\t%ju unread message%s abandonded by close\n");
+	p1a(sctps_send_burst_avoid, "\t%ju send burst avoidance, already "
+	    "max burst inflight to net\n");
+	p1a(sctps_send_cwnd_avoid, "\t%ju send cwnd full avoidance, already "
+	    "max burst inflight to net\n");
+	p(sctps_fwdtsn_map_over, "\t%ju number of map array over-run%s via "
+	    "fwd-tsn's\n");
+
+#undef p
+#undef p1a
+}
+
+#endif /* SCTP */
diff --git a/freebsd-userspace/commands/usr.bin/netstat/unix.c b/freebsd-userspace/commands/usr.bin/netstat/unix.c
new file mode 100644
index 0000000..17d5203
--- /dev/null
+++ b/freebsd-userspace/commands/usr.bin/netstat/unix.c
@@ -0,0 +1,294 @@
+/*-
+ * 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. 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.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)unix.c	8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+#endif
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Display protocol blocks in the unix domain.
+ */
+#include <sys/param.h>
+#include <sys/queue.h>
+#ifdef __rtems__
+#include <freebsd/sys/protosw.h>
+#else
+#include <sys/protosw.h>
+#endif
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#ifdef __rtems__
+#include <freebsd/sys/mbuf.h>
+#else
+#include <sys/mbuf.h>
+#endif
+#include <sys/sysctl.h>
+#include <sys/un.h>
+#include <sys/unpcb.h>
+
+#include <netinet/in.h>
+
+#include <errno.h>
+#include <err.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <kvm.h>
+#include "netstat.h"
+
+static	void unixdomainpr(struct xunpcb *, struct xsocket *);
+
+static	const char *const socktype[] =
+    { "#0", "stream", "dgram", "raw", "rdm", "seqpacket" };
+
+static int
+pcblist_sysctl(int type, char **bufp)
+{
+	char 	*buf;
+	size_t	len;
+	char mibvar[sizeof "net.local.seqpacket.pcblist"];
+
+	sprintf(mibvar, "net.local.%s.pcblist", socktype[type]);
+
+	len = 0;
+	if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
+		if (errno != ENOENT)
+			warn("sysctl: %s", mibvar);
+		return (-1);
+	}
+	if ((buf = malloc(len)) == 0) {
+		warnx("malloc %lu bytes", (u_long)len);
+		return (-2);
+	}
+	if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
+		warn("sysctl: %s", mibvar);
+		free(buf);
+		return (-2);
+	}
+	*bufp = buf;
+	return (0);
+}
+
+static int
+pcblist_kvm(u_long count_off, u_long gencnt_off, u_long head_off, char **bufp)
+{
+	struct unp_head head;
+	struct unpcb *unp, unp_conn;
+	u_char sun_len;
+	struct socket so;
+	struct xunpgen xug;
+	struct xunpcb xu;
+	unp_gen_t unp_gencnt;
+	u_int	unp_count;
+	char 	*buf, *p;
+	size_t	len;
+
+	if (count_off == 0 || gencnt_off == 0)
+		return (-2);
+	if (head_off == 0)
+		return (-1);
+	kread(count_off, &unp_count, sizeof(unp_count));
+	len = 2 * sizeof(xug) + (unp_count + unp_count / 8) * sizeof(xu);
+	if ((buf = malloc(len)) == 0) {
+		warnx("malloc %lu bytes", (u_long)len);
+		return (-2);
+	}
+	p = buf;
+
+#define	COPYOUT(obj, size) do {						\
+	if (len < (size)) {						\
+		warnx("buffer size exceeded");				\
+		goto fail;						\
+	}								\
+	bcopy((obj), p, (size));					\
+	len -= (size);							\
+	p += (size);							\
+} while (0)
+
+#define	KREAD(off, buf, len) do {					\
+	if (kread((uintptr_t)(off), (buf), (len)) != 0)			\
+		goto fail;						\
+} while (0)
+
+	/* Write out header. */
+	kread(gencnt_off, &unp_gencnt, sizeof(unp_gencnt));
+	xug.xug_len = sizeof xug;
+	xug.xug_count = unp_count;
+	xug.xug_gen = unp_gencnt;
+	xug.xug_sogen = 0;
+	COPYOUT(&xug, sizeof xug);
+
+	/* Walk the PCB list. */
+	xu.xu_len = sizeof xu;
+	KREAD(head_off, &head, sizeof(head));
+	LIST_FOREACH(unp, &head, unp_link) {
+		xu.xu_unpp = unp;
+		KREAD(unp, &xu.xu_unp, sizeof (*unp));
+		unp = &xu.xu_unp;
+
+		if (unp->unp_gencnt > unp_gencnt)
+			continue;
+		if (unp->unp_addr != NULL) {
+			KREAD(unp->unp_addr, &sun_len, sizeof(sun_len));
+			KREAD(unp->unp_addr, &xu.xu_addr, sun_len);
+		}
+		if (unp->unp_conn != NULL) {
+			KREAD(unp->unp_conn, &unp_conn, sizeof(unp_conn));
+			if (unp_conn.unp_addr != NULL) {
+				KREAD(unp_conn.unp_addr, &sun_len,
+				    sizeof(sun_len));
+				KREAD(unp_conn.unp_addr, &xu.xu_caddr, sun_len);
+			}
+		}
+		KREAD(unp->unp_socket, &so, sizeof(so));
+		if (sotoxsocket(&so, &xu.xu_socket) != 0)
+			goto fail;
+		COPYOUT(&xu, sizeof(xu));
+	}
+
+	/* Reread the counts and write the footer. */
+	kread(count_off, &unp_count, sizeof(unp_count));
+	kread(gencnt_off, &unp_gencnt, sizeof(unp_gencnt));
+	xug.xug_count = unp_count;
+	xug.xug_gen = unp_gencnt;
+	COPYOUT(&xug, sizeof xug);
+
+	*bufp = buf;
+	return (0);
+
+fail:
+	free(buf);
+	return (-1);
+#undef COPYOUT
+#undef KREAD
+}
+
+void
+unixpr(u_long count_off, u_long gencnt_off, u_long dhead_off, u_long shead_off)
+{
+	char 	*buf;
+	int	ret, type;
+	struct	xsocket *so;
+	struct	xunpgen *xug, *oxug;
+	struct	xunpcb *xunp;
+
+	for (type = SOCK_STREAM; type <= SOCK_SEQPACKET; type++) {
+		if (live)
+			ret = pcblist_sysctl(type, &buf);
+		else
+			ret = pcblist_kvm(count_off, gencnt_off,
+			    type == SOCK_STREAM ? shead_off :
+			    (type == SOCK_DGRAM ? dhead_off : 0), &buf);
+		if (ret == -1)
+			continue;
+		if (ret < 0)
+			return;
+
+		oxug = xug = (struct xunpgen *)buf;
+		for (xug = (struct xunpgen *)((char *)xug + xug->xug_len);
+		     xug->xug_len > sizeof(struct xunpgen);
+		     xug = (struct xunpgen *)((char *)xug + xug->xug_len)) {
+			xunp = (struct xunpcb *)xug;
+			so = &xunp->xu_socket;
+
+			/* Ignore PCBs which were freed during copyout. */
+			if (xunp->xu_unp.unp_gencnt > oxug->xug_gen)
+				continue;
+			unixdomainpr(xunp, so);
+		}
+		if (xug != oxug && xug->xug_gen != oxug->xug_gen) {
+			if (oxug->xug_count > xug->xug_count) {
+				printf("Some %s sockets may have been deleted.\n",
+				       socktype[type]);
+			} else if (oxug->xug_count < xug->xug_count) {
+				printf("Some %s sockets may have been created.\n",
+			       socktype[type]);
+			} else {
+				printf("Some %s sockets may have been created or deleted",
+			       socktype[type]);
+			}
+		}
+		free(buf);
+	}
+}
+
+static void
+unixdomainpr(struct xunpcb *xunp, struct xsocket *so)
+{
+	struct unpcb *unp;
+	struct sockaddr_un *sa;
+	static int first = 1;
+	char buf1[15];
+
+	unp = &xunp->xu_unp;
+	if (unp->unp_addr)
+		sa = &xunp->xu_addr;
+	else
+		sa = (struct sockaddr_un *)0;
+
+	if (first && !Lflag) {
+		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");
+		first = 0;
+	}
+
+	if (Lflag && so->so_qlimit == 0)
+		return;
+
+	if (Lflag) {
+		snprintf(buf1, 15, "%d/%d/%d", so->so_qlen,
+		    so->so_incqlen, so->so_qlimit);
+		printf("unix  %-14.14s", buf1);
+	} else {
+		printf("%8lx %-6.6s %6u %6u %8lx %8lx %8lx %8lx",
+		    (long)so->so_pcb, socktype[so->so_type], so->so_rcv.sb_cc,
+		    so->so_snd.sb_cc, (long)unp->unp_vnode, (long)unp->unp_conn,
+		    (long)LIST_FIRST(&unp->unp_refs),
+		    (long)LIST_NEXT(unp, unp_reflink));
+	}
+	if (sa)
+		printf(" %.*s",
+		    (int)(sa->sun_len - offsetof(struct sockaddr_un, sun_path)),
+		    sa->sun_path);
+	putchar('\n');
+}




More information about the vc mailing list