summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@oarcorp.com>2012-09-07 12:50:18 -0500
committerJoel Sherrill <joel.sherrill@oarcorp.com>2012-09-07 12:50:18 -0500
commitf1710b69d4ea496c3af76b46d7bec67b20dab1be (patch)
tree72fe7bf58d78eaf508bb0758104817c2a48d6221
parentnetshell01: Link against ping command (diff)
downloadrtems-libbsd-f1710b69d4ea496c3af76b46d7bec67b20dab1be.tar.bz2
netstat: New command - Almost completely compiles
Currently disable in Makefile until all builds. Adding it so others can assist in debugging issues.
-rw-r--r--freebsd-userspace/commands/usr.bin/netstat/atalk.c293
-rw-r--r--freebsd-userspace/commands/usr.bin/netstat/bpf.c158
-rw-r--r--freebsd-userspace/commands/usr.bin/netstat/if.c735
-rw-r--r--freebsd-userspace/commands/usr.bin/netstat/inet.c1291
-rw-r--r--freebsd-userspace/commands/usr.bin/netstat/inet6.c1159
-rw-r--r--freebsd-userspace/commands/usr.bin/netstat/ipsec.c481
-rw-r--r--freebsd-userspace/commands/usr.bin/netstat/ipx.c354
-rw-r--r--freebsd-userspace/commands/usr.bin/netstat/main.c805
-rw-r--r--freebsd-userspace/commands/usr.bin/netstat/mbuf.c323
-rw-r--r--freebsd-userspace/commands/usr.bin/netstat/mroute.c391
-rw-r--r--freebsd-userspace/commands/usr.bin/netstat/mroute6.c268
-rw-r--r--freebsd-userspace/commands/usr.bin/netstat/netgraph.c196
-rw-r--r--freebsd-userspace/commands/usr.bin/netstat/netstat.1523
-rw-r--r--freebsd-userspace/commands/usr.bin/netstat/netstat.h167
-rw-r--r--freebsd-userspace/commands/usr.bin/netstat/pfkey.c184
-rw-r--r--freebsd-userspace/commands/usr.bin/netstat/route.c1167
-rw-r--r--freebsd-userspace/commands/usr.bin/netstat/sctp.c703
-rw-r--r--freebsd-userspace/commands/usr.bin/netstat/unix.c294
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 00000000..2c7e7a18
--- /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 00000000..3e3053d7
--- /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 00000000..d91db8c1
--- /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 00000000..37b650c5
--- /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 00000000..254868d5
--- /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 00000000..a6ef510c
--- /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 00000000..b78b1514
--- /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 00000000..09b26a26
--- /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 00000000..dd105259
--- /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 00000000..7669ff07
--- /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 00000000..cd7d8d25
--- /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 00000000..06a244ff
--- /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 00000000..872ff954
--- /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 00000000..75944645
--- /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 00000000..7c5af07b
--- /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 00000000..af60527d
--- /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 00000000..0c02db9f
--- /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 00000000..17d52031
--- /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');
+}