[Midnightbsd-cvs] src: usr.bin/telnet: Merge changes

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Fri Nov 14 09:47:44 EST 2008


Log Message:
-----------
Merge changes

Modified Files:
--------------
    src/usr.bin/telnet:
        Makefile (r1.1.1.1 -> r1.2)
    src/usr.bin/netstat:
        Makefile (r1.6 -> r1.7)
        atalk.c (r1.3 -> r1.4)
        bpf.c (r1.2 -> r1.3)
        if.c (r1.4 -> r1.5)
        inet.c (r1.5 -> r1.6)
        inet6.c (r1.4 -> r1.5)
        ipsec.c (r1.4 -> r1.5)
        ipx.c (r1.2 -> r1.3)
        main.c (r1.3 -> r1.4)
        mbuf.c (r1.4 -> r1.5)
        mcast.c (r1.2 -> r1.3)
        mroute.c (r1.3 -> r1.4)
        mroute6.c (r1.2 -> r1.3)
        netgraph.c (r1.2 -> r1.3)
        netstat.1 (r1.3 -> r1.4)
        netstat.h (r1.3 -> r1.4)
        pfkey.c (r1.2 -> r1.3)
        route.c (r1.3 -> r1.4)
        unix.c (r1.2 -> r1.3)

Added Files:
-----------
    src/usr.bin/netstat:
        sctp.c (r1.1)

-------------- next part --------------
Index: Makefile
===================================================================
RCS file: /home/cvs/src/usr.bin/telnet/Makefile,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L usr.bin/telnet/Makefile -L usr.bin/telnet/Makefile -u -r1.1.1.1 -r1.2
--- usr.bin/telnet/Makefile
+++ usr.bin/telnet/Makefile
@@ -1,4 +1,6 @@
-# $FreeBSD: src/usr.bin/telnet/Makefile,v 1.28 2005/06/10 06:12:51 des Exp $
+# $FreeBSD: src/usr.bin/telnet/Makefile,v 1.33 2007/07/05 08:56:45 bz Exp $
+
+.include <bsd.own.mk>
 
 TELNETDIR=	${.CURDIR}/../../contrib/telnet
 .PATH:		${TELNETDIR}/telnet
@@ -11,13 +13,17 @@
 CFLAGS+=	-DKLUDGELINEMODE -DUSE_TERMIO -DENV_HACK -DOPIE \
 		-I${TELNETDIR} -I${TELNETDIR}/libtelnet/
 
+.if ${MK_INET6_SUPPORT} != "no"
+CFLAGS+=	-DINET6
+.endif
+
 LIBTELNET=	${.OBJDIR}/../../lib/libtelnet/libtelnet.a
 
 DPADD=		${LIBTERMCAP} ${LIBTELNET}
 LDADD=		-ltermcap ${LIBTELNET}
 
 .if !defined(RELEASE_CRUNCH)
-CFLAGS+=	-DINET6 -DIPSEC
+CFLAGS+=	-DIPSEC
 DPADD+=		${LIBIPSEC}
 LDADD+=		-lipsec
 .else
@@ -27,17 +33,18 @@
 .endif
 
 .if !defined(RELEASE_CRUNCH)
-.if !defined(NO_CRYPT) && !defined(NO_OPENSSL)
+.if ${MK_OPENSSL} != "no"
 SRCS+=		authenc.c 
 CFLAGS+=	-DENCRYPTION -DAUTHENTICATION -DIPSEC
 DPADD+=		${LIBMP} ${LIBCRYPTO} ${LIBCRYPT} ${LIBIPSEC} ${LIBPAM}
 LDADD+=		-lmp -lcrypto -lcrypt -lipsec ${MINUSLPAM}
-.if !defined(NO_KERBEROS)
+.endif
+
+.if ${MK_KERBEROS_SUPPORT} != "no"
 CFLAGS+=	-DKRB5 -DFORWARD -Dnet_write=telnet_net_write
 DPADD+=		${LIBKRB5} ${LIBASN1} ${LIBCOM_ERR} ${LIBROKEN}
 LDADD+=		-lkrb5 -lasn1 -lcom_err -lroken
 .endif
 .endif
-.endif
 
 .include <bsd.prog.mk>
Index: mcast.c
===================================================================
RCS file: /home/cvs/src/usr.bin/netstat/mcast.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L usr.bin/netstat/mcast.c -L usr.bin/netstat/mcast.c -u -r1.2 -r1.3
--- usr.bin/netstat/mcast.c
+++ usr.bin/netstat/mcast.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004 Bruce M Simpson <bms at spc.org>
+ * Copyright (c) 2007 Bruce M. Simpson <bms at FreeBSD.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,15 +26,16 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/usr.bin/netstat/mcast.c,v 1.2 2004/07/26 20:18:11 charnier Exp $");
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: src/usr.bin/netstat/mcast.c,v 1.9 2007/07/16 17:15:55 jhb Exp $");
 
 /*
- * Print the system's current multicast group memberships.
+ * Print the running system's current multicast group memberships.
+ * As this relies on getifmaddrs(), it may not be used with a core file.
  */
 
 #include <sys/types.h>
 #include <sys/socket.h>
+#include <sys/socketvar.h>
 
 #include <net/if.h>
 #include <net/if_var.h>
@@ -61,6 +62,10 @@
 
 #include "netstat.h"
 
+#define __NETSTAT_BURN_BRIDGES
+
+#ifdef __NETSTAT_BURN_BRIDGES
+
 union sockunion {
 	struct sockaddr_storage	ss;
 	struct sockaddr		sa;
@@ -70,24 +75,42 @@
 };
 typedef union sockunion sockunion_t;
 
-#define MYIFNAME_SIZE 128
+void ifmalist_dump_af(const struct ifmaddrs * const ifmap, int const af);
 
 void
-ifmalist_dump(void)
+ifmalist_dump_af(const struct ifmaddrs * const ifmap, int const af)
 {
-	struct ifmaddrs *ifmap, *ifma;
+	const struct ifmaddrs *ifma;
 	sockunion_t *psa;
-	char myifname[MYIFNAME_SIZE];
+	char myifname[IFNAMSIZ];
+#ifdef INET6
 	char addrbuf[INET6_ADDRSTRLEN];
+#endif
 	char *pcolon;
-	void *addr;
-	char *pifname, *plladdr, *pgroup;
-
-	if (getifmaddrs(&ifmap))
-		err(EX_OSERR, "getifmaddrs");
+	char *pafname, *pifname, *plladdr, *pgroup;
+#ifdef INET6
+	void *in6addr;
+#endif
+
+	switch (af) {
+	case AF_INET:
+		pafname = "IPv4";
+		break;
+#ifdef INET6
+	case AF_INET6:
+		pafname = "IPv6";
+		break;
+#endif
+	case AF_LINK:
+		pafname = "Link-layer";
+		break;
+	default:
+		return;		/* XXX */
+	}
 
-	fputs("IPv4/IPv6 Multicast Group Memberships\n", stdout);
-	fprintf(stdout, "%-20s\t%-16s\t%s\n", "Group", "Gateway", "Netif");
+	fprintf(stdout, "%s Multicast Group Memberships\n", pafname);
+	fprintf(stdout, "%-20s\t%-16s\t%s\n", "Group", "Link-layer Address",
+	    "Netif");
 
 	for (ifma = ifmap; ifma; ifma = ifma->ifma_next) {
 
@@ -96,16 +119,35 @@
 
 		/* Group address */
 		psa = (sockunion_t *)ifma->ifma_addr;
+		if (psa->sa.sa_family != af)
+			continue;
+
 		switch (psa->sa.sa_family) {
 		case AF_INET:
 			pgroup = inet_ntoa(psa->sin.sin_addr);
 			break;
+#ifdef INET6
 		case AF_INET6:
-			addr = &psa->sin6.sin6_addr;
-			inet_ntop(psa->sa.sa_family, addr, addrbuf,
+			in6addr = &psa->sin6.sin6_addr;
+			inet_ntop(psa->sa.sa_family, in6addr, addrbuf,
 			    sizeof(addrbuf));
 			pgroup = addrbuf;
 			break;
+#endif
+		case AF_LINK:
+			if ((psa->sdl.sdl_alen == ETHER_ADDR_LEN) ||
+			    (psa->sdl.sdl_type == IFT_ETHER)) {
+				pgroup =
+ether_ntoa((struct ether_addr *)&psa->sdl.sdl_data);
+#ifdef notyet
+			} else {
+				pgroup = addr2ascii(AF_LINK,
+				    &psa->sdl,
+				    sizeof(struct sockaddr_dl),
+				    addrbuf);
+#endif
+			}
+			break;
 		default:
 			continue;	/* XXX */
 		}
@@ -113,38 +155,65 @@
 		/* Link-layer mapping, if any */
 		psa = (sockunion_t *)ifma->ifma_lladdr;
 		if (psa != NULL) {
-			switch (psa->sa.sa_family) {
-			case AF_INET:
-				plladdr = inet_ntoa(psa->sin.sin_addr);
-				break;
-			case AF_LINK:
-				if (psa->sdl.sdl_type == IFT_ETHER)
-					plladdr = ether_ntoa((struct ether_addr *)&psa->sdl.sdl_data);
-				else
-					plladdr = link_ntoa(&psa->sdl);
-				break;
+			if (psa->sa.sa_family == AF_LINK) {
+				if ((psa->sdl.sdl_alen == ETHER_ADDR_LEN) ||
+				    (psa->sdl.sdl_type == IFT_ETHER)) {
+					/* IEEE 802 */
+					plladdr =
+ether_ntoa((struct ether_addr *)&psa->sdl.sdl_data);
+#ifdef notyet
+				} else {
+					/* something more exotic */
+					plladdr = addr2ascii(AF_LINK,
+					    &psa->sdl,
+					    sizeof(struct sockaddr_dl),
+					    addrbuf);
+#endif
+				}
+			} else {
+				/* not a link-layer address */
+				plladdr = "<invalid>";
 			}
-		} else
+		} else {
 			plladdr = "<none>";
+		}
 
 		/* Interface upon which the membership exists */
 		psa = (sockunion_t *)ifma->ifma_name;
-		switch (psa->sa.sa_family) {
-		case AF_LINK:
-			strlcpy(myifname, link_ntoa(&psa->sdl),
-			    MYIFNAME_SIZE);
+		if (psa != NULL && psa->sa.sa_family == AF_LINK) {
+			strlcpy(myifname, link_ntoa(&psa->sdl), IFNAMSIZ);
 			pcolon = strchr(myifname, ':');
 			if (pcolon)
 				*pcolon = '\0';
 			pifname = myifname;
-			break;
-		default:
+		} else {
 			pifname = "";
-			break;
 		}
 
 		fprintf(stdout, "%-20s\t%-16s\t%s\n", pgroup, plladdr, pifname);
 	}
+}
+
+void
+ifmalist_dump(void)
+{
+	struct ifmaddrs *ifmap;
+
+	fprintf(stderr,
+	     "WARNING: This functionality is deprecated, and will be removed\n"
+	     "in FreeBSD 7.0. Please consider using ifmcstat(8) instead.\n");
+
+	if (getifmaddrs(&ifmap))
+		err(EX_OSERR, "getifmaddrs");
+
+	ifmalist_dump_af(ifmap, AF_LINK);
+	fputs("\n", stdout);
+	ifmalist_dump_af(ifmap, AF_INET);
+#ifdef INET6
+	fputs("\n", stdout);
+	ifmalist_dump_af(ifmap, AF_INET6);
+#endif
 
 	freeifmaddrs(ifmap);
 }
+#endif /* __NETSTAT_BURN_BRIDGES */
Index: ipsec.c
===================================================================
RCS file: /home/cvs/src/usr.bin/netstat/ipsec.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -L usr.bin/netstat/ipsec.c -L usr.bin/netstat/ipsec.c -u -r1.4 -r1.5
--- usr.bin/netstat/ipsec.c
+++ usr.bin/netstat/ipsec.c
@@ -1,4 +1,4 @@
-/*	$FreeBSD: src/usr.bin/netstat/ipsec.c,v 1.12.8.1 2006/01/05 03:47:24 kbyanc Exp $	*/
+/*	$FreeBSD: src/usr.bin/netstat/ipsec.c,v 1.17 2007/07/16 17:15:54 jhb Exp $	*/
 /*	$KAME: ipsec.c,v 1.33 2003/07/25 09:54:32 itojun Exp $	*/
 
 /*
@@ -96,20 +96,16 @@
 #endif
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/usr.bin/netstat/ipsec.c,v 1.12.8.1 2006/01/05 03:47:24 kbyanc Exp $");
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: src/usr.bin/netstat/ipsec.c,v 1.17 2007/07/16 17:15:54 jhb Exp $");
 
 #include <sys/param.h>
 #include <sys/queue.h>
 #include <sys/socket.h>
+#include <sys/socketvar.h>
 
 #include <netinet/in.h>
 
-#if defined(IPSEC) && !defined(FAST_IPSEC)
-#include <netinet6/ipsec.h>
-#endif
-
-#ifdef FAST_IPSEC
+#ifdef IPSEC
 #include <netipsec/ipsec.h>
 #include <netipsec/ah_var.h>
 #include <netipsec/esp_var.h>
@@ -251,13 +247,28 @@
 	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 p
 #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)
+ipsec_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
 {
 	struct ipsecstat ipsecstat;
 
@@ -270,11 +281,8 @@
 }
 
 
-#ifdef FAST_IPSEC
-
 static void ipsec_hist_new(const u_int32_t *hist, size_t histmax,
 			   const struct val2str *name, const char *title);
-static void print_newipsecstats(const struct newipsecstat *newipsecstat);
 static void print_ahstats(const struct ahstat *ahstat);
 static void print_espstats(const struct espstat *espstat);
 static void print_ipcompstats(const struct ipcompstat *ipcompstat);
@@ -312,43 +320,6 @@
 }
   
 static void
-print_newipsecstats(const struct newipsecstat *newipsecstat)
-{
-#define	p(f, m) if (newipsecstat->f || sflag <= 1) \
-    printf(m, newipsecstat->f, plural(newipsecstat->f))
-
-	p(ips_in_polvio, "\t%u inbound packet%s violated process "
-		"security policy\n");
-	p(ips_out_polvio, "\t%u outbound packet%s violated process "
-		"security policy\n");
-	p(ips_out_nosa, "\t%u outbound packet%s with no SA available\n");
-	p(ips_out_nomem, "\t%u outbound packet%s failed due to "
-		"insufficient memory\n");
-	p(ips_out_noroute, "\t%u outbound packet%s with no route "
-		"available\n");
-	p(ips_out_inval, "\t%u invalid outbound packet%s\n");
-	p(ips_out_bundlesa, "\t%u outbound packet%s with bundled SAs\n");
-	p(ips_mbcoalesced, "\t%u mbuf%s coalesced during clone\n");
-	p(ips_clcoalesced, "\t%u cluster%s coalesced during clone\n");
-	p(ips_clcopied, "\t%u cluster%s copied during clone\n");
-	p(ips_mbinserted, "\t%u mbuf%s inserted during makespace\n");
-#undef p
-}
-  
-void
-ipsec_stats_new(u_long off, const char *name, int af __unused)
-{
-	struct newipsecstat newipsecstat;
-
-	if (off == 0)
-		return;
-  	printf ("%s:\n", name);
-	kread(off, (char *)&newipsecstat, sizeof(newipsecstat));
-
-	print_newipsecstats(&newipsecstat);
-}
-
-static void
 print_ahstats(const struct ahstat *ahstat)
 {
 #define	p32(f, m) if (ahstat->f || sflag <= 1) \
@@ -385,7 +356,7 @@
 }
 
 void
-ah_stats(u_long off, const char *name, int af __unused)
+ah_stats(u_long off, const char *name, int family __unused, int proto __unused)
 {
 	struct ahstat ahstat;
 
@@ -435,7 +406,7 @@
 }
 
 void
-esp_stats(u_long off, const char *name, int af __unused)
+esp_stats(u_long off, const char *name, int family __unused, int proto __unused)
 {
 	struct espstat espstat;
 
@@ -480,7 +451,8 @@
 }
 
 void
-ipcomp_stats(u_long off, const char *name, int af __unused)
+ipcomp_stats(u_long off, const char *name, int family __unused,
+    int proto __unused)
 {
 	struct ipcompstat ipcompstat;
 
@@ -492,5 +464,4 @@
 	print_ipcompstats(&ipcompstat);
 }
 
-#endif /* FAST_IPSEC */
 #endif /*IPSEC*/
Index: main.c
===================================================================
RCS file: /home/cvs/src/usr.bin/netstat/main.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -L usr.bin/netstat/main.c -L usr.bin/netstat/main.c -u -r1.3 -r1.4
--- usr.bin/netstat/main.c
+++ usr.bin/netstat/main.c
@@ -1,4 +1,4 @@
-/*-
+/*
  * Copyright (c) 1983, 1988, 1993
  *	Regents of the University of California.  All rights reserved.
  *
@@ -10,7 +10,11 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
+ * 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.
  *
@@ -40,13 +44,13 @@
 #endif
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/usr.bin/netstat/main.c,v 1.72.2.6 2006/01/05 03:47:24 kbyanc Exp $");
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: src/usr.bin/netstat/main.c,v 1.87 2007/07/16 18:13:12 jhb Exp $");
 
 #include <sys/param.h>
 #include <sys/file.h>
 #include <sys/protosw.h>
 #include <sys/socket.h>
+#include <sys/socketvar.h>
 
 #include <netinet/in.h>
 
@@ -65,7 +69,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
-
 #include "netstat.h"
 
 static struct nlist nl[] = {
@@ -98,7 +101,7 @@
 #define N_ICMP6STAT	13
 	{ .n_name = "_icmp6stat" },
 #define N_IPSECSTAT	14
-	{ .n_name = "_ipsecstat" },
+	{ .n_name = "_ipsec4stat" },
 #define N_IPSEC6STAT	15
 	{ .n_name = "_ipsec6stat" },
 #define N_PIM6STAT	16
@@ -139,127 +142,156 @@
 	{ .n_name = "_carpstats" },
 #define N_PFSYNCSTAT	34
 	{ .n_name = "_pfsyncstats" },
-#define	N_FAST_IPSECSTAT 35
-	{ .n_name = "_newipsecstat" },
-#define	N_AHSTAT	36
+#define	N_AHSTAT	35
 	{ .n_name = "_ahstat" },
-#define	N_ESPSTAT	37
+#define	N_ESPSTAT	36
 	{ .n_name = "_espstat" },
-#define	N_IPCOMPSTAT	38
+#define	N_IPCOMPSTAT	37
 	{ .n_name = "_ipcompstat" },
+#define	N_TCPSTAT	38
+	{ .n_name = "_tcpstat" },
+#define	N_UDPSTAT	39
+	{ .n_name = "_udpstat" },
+#define	N_IPSTAT	40
+	{ .n_name = "_ipstat" },
+#define	N_ICMPSTAT	41
+	{ .n_name = "_icmpstat" },
+#define	N_IGMPSTAT	42
+	{ .n_name = "_igmpstat" },
+#define	N_PIMSTAT	43
+	{ .n_name = "_pimstat" },
+#define	N_TCBINFO	44
+	{ .n_name = "_tcbinfo" },
+#define	N_UDBINFO	45
+	{ .n_name = "_udbinfo" },
+#define	N_DIVCBINFO	46
+	{ .n_name = "_divcbinfo" },
+#define	N_RIPCBINFO	47
+	{ .n_name = "_ripcbinfo" },
+#define	N_UNP_COUNT	48
+	{ .n_name = "_unp_count" },
+#define	N_UNP_GENCNT	49
+	{ .n_name = "_unp_gencnt" },
+#define	N_UNP_DHEAD	50
+	{ .n_name = "_unp_dhead" },
+#define	N_UNP_SHEAD	51
+	{ .n_name = "_unp_shead" },
+#define	N_RIP6STAT	52
+	{ .n_name = "_rip6stat" },
+#define	N_SCTPSTAT	53
+	{ .n_name = "_sctpstat" },
 	{ .n_name = NULL },
 };
 
 struct protox {
-	u_char	pr_index;		/* index into nlist of cb head */
-	u_char	pr_sindex;		/* index into nlist of stat block */
+	int	pr_index;		/* index into nlist of cb head */
+	int	pr_sindex;		/* index into nlist of stat block */
 	u_char	pr_wanted;		/* 1 if wanted, 0 otherwise */
-	void	(*pr_cblocks)(u_long, const char *, int);
+	void	(*pr_cblocks)(u_long, const char *, int, int);
 					/* control blocks printing routine */
-	void	(*pr_stats)(u_long, const char *, int);
+	void	(*pr_stats)(u_long, const char *, int, int);
 					/* statistics printing routine */
 	void	(*pr_istats)(char *);	/* per/if statistics printing routine */
 	const char	*pr_name;		/* well-known name */
-	u_long	pr_usesysctl;		/* non-zero if we use sysctl, not kvm */
+	int	pr_usesysctl;		/* non-zero if we use sysctl, not kvm */
+	int	pr_protocol;
 } protox[] = {
-	{ -1,		-1,		1,	protopr,
-	  tcp_stats,	NULL,		"tcp",	IPPROTO_TCP },
-	{ -1,		-1,		1,	protopr,
-	  udp_stats,	NULL,		"udp",	IPPROTO_UDP },
-	{ -1,		-1,		1,	protopr,
-	  NULL,		NULL,		"divert",IPPROTO_DIVERT },
-	{ -1,		-1,		1,	protopr,
-	  ip_stats,	NULL,		"ip",	IPPROTO_RAW },
-	{ -1,		-1,		1,	protopr,
-	  icmp_stats,	NULL,		"icmp",	IPPROTO_ICMP },
-	{ -1,		-1,		1,	protopr,
-	  igmp_stats,	NULL,		"igmp",	IPPROTO_IGMP },
+	{ N_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,
-	  ipsec_stats,	NULL,		"ipsec",	0},
-#ifdef FAST_IPSEC
-	{ -1,		N_FAST_IPSECSTAT, 1,	0,
-	  ipsec_stats_new, NULL,	"fastipsec",	0},
-	{ -1,		N_AHSTAT,	1,	0,
-	  ah_stats,	NULL,		"ah",		0},
-	{ -1,		N_ESPSTAT,	1,	0,
-	  esp_stats,	NULL,		"esp",		0},
-	{ -1,		N_IPCOMPSTAT,	1,	0,
-	  ipcomp_stats,	NULL,		"ipcomp",	0},
-#endif
-#endif
-	{ -1,		-1,		1,	NULL,
-	  bdg_stats,	NULL,		"bdg",	1 /* bridging... */ },
-	{ -1,		-1,		1,	protopr,
-	  pim_stats,	NULL,		"pim",	IPPROTO_PIM },
-	{ -1,		N_CARPSTAT,	1,	0,
-	  carp_stats,	NULL,		"carp",		0},
-	{ -1,		-1,		1,	NULL,
-	  pfsync_stats,	NULL,		"pfsync",	1},
+	{ -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,		-1,		0,	NULL,
-	  NULL,		NULL,		NULL,	0 }
+	  NULL,		NULL,		NULL,	0,	0 }
 };
 
 #ifdef INET6
 struct protox ip6protox[] = {
-	{ -1,		-1,		1,	protopr,
-	  tcp_stats,	NULL,		"tcp",	IPPROTO_TCP },
-	{ -1,		-1,		1,	protopr,
-	  udp_stats,	NULL,		"udp",	IPPROTO_UDP },
-	{ -1,		N_IP6STAT,	1,	protopr,
-	  ip6_stats,	ip6_ifstats,	"ip6",	IPPROTO_RAW },
-	{ -1,		N_ICMP6STAT,	1,	protopr,
-	  icmp6_stats,	icmp6_ifstats,	"icmp6",IPPROTO_ICMPV6 },
+	{ N_TCBINFO,	N_TCPSTAT,	1,	protopr,
+	  tcp_stats,	NULL,		"tcp",	1,	IPPROTO_TCP },
+	{ N_UDBINFO,	N_UDPSTAT,	1,	protopr,
+	  udp_stats,	NULL,		"udp",	1,	IPPROTO_UDP },
+	{ N_RIPCBINFO,	N_IP6STAT,	1,	protopr,
+	  ip6_stats,	ip6_ifstats,	"ip6",	1,	IPPROTO_RAW },
+	{ N_RIPCBINFO,	N_ICMP6STAT,	1,	protopr,
+	  icmp6_stats,	icmp6_ifstats,	"icmp6", 1,	IPPROTO_ICMPV6 },
 #ifdef IPSEC
 	{ -1,		N_IPSEC6STAT,	1,	NULL,
-	  ipsec_stats,	NULL,		"ipsec6",0 },
+	  ipsec_stats,	NULL,		"ipsec6", 0,	0 },
 #endif
 #ifdef notyet
 	{ -1,		N_PIM6STAT,	1,	NULL,
-	  pim6_stats,	NULL,		"pim6",	0 },
+	  pim6_stats,	NULL,		"pim6",	1,	0 },
 #endif
-	{ -1,		-1,		1,	NULL,
-	  rip6_stats,	NULL,		"rip6",	0 },
-	{ -1,		-1,		1,	NULL,
-	  bdg_stats,	NULL,		"bdg",	1 /* bridging... */ },
+	{ -1,		N_RIP6STAT,	1,	NULL,
+	  rip6_stats,	NULL,		"rip6",	1,	0 },
 	{ -1,		-1,		0,	NULL,
-	  NULL,		NULL,		NULL,	0 }
+	  NULL,		NULL,		NULL,	0,	0 }
 };
 #endif /*INET6*/
 
 #ifdef IPSEC
 struct protox pfkeyprotox[] = {
 	{ -1,		N_PFKEYSTAT,	1,	NULL,
-	  pfkey_stats,	NULL,		"pfkey", 0 },
+	  pfkey_stats,	NULL,		"pfkey", 0,	0 },
 	{ -1,		-1,		0,	NULL,
-	  NULL,		NULL,		NULL,	0 }
+	  NULL,		NULL,		NULL,	0,	0 }
 };
 #endif
 
 struct protox atalkprotox[] = {
 	{ N_DDPCB,	N_DDPSTAT,	1,	atalkprotopr,
-	  ddp_stats,	NULL,		"ddp",	0 },
+	  ddp_stats,	NULL,		"ddp",	0,	0 },
 	{ -1,		-1,		0,	NULL,
-	  NULL,		NULL,		NULL,	0 }
+	  NULL,		NULL,		NULL,	0,	0 }
 };
 
 struct protox netgraphprotox[] = {
 	{ N_NGSOCKS,	-1,		1,	netgraphprotopr,
-	  NULL,		NULL,		"ctrl",	0 },
+	  NULL,		NULL,		"ctrl",	0,	0 },
 	{ N_NGSOCKS,	-1,		1,	netgraphprotopr,
-	  NULL,		NULL,		"data",	0 },
+	  NULL,		NULL,		"data",	0,	0 },
 	{ -1,		-1,		0,	NULL,
-	  NULL,		NULL,		NULL,	0 }
+	  NULL,		NULL,		NULL,	0,	0 }
 };
 
+#ifdef IPX
 struct protox ipxprotox[] = {
 	{ N_IPX,	N_IPXSTAT,	1,	ipxprotopr,
-	  ipx_stats,	NULL,		"ipx",	0 },
+	  ipx_stats,	NULL,		"ipx",	0,	0 },
 	{ N_IPX,	N_SPXSTAT,	1,	ipxprotopr,
-	  spx_stats,	NULL,		"spx",	0 },
+	  spx_stats,	NULL,		"spx",	0,	0 },
 	{ -1,		-1,		0,	NULL,
-	  NULL,		NULL,		0,	0 }
+	  NULL,		NULL,		0,	0,	0 }
 };
+#endif
 
 struct protox *protoprotox[] = {
 					 protox,
@@ -269,7 +301,10 @@
 #ifdef IPSEC
 					 pfkeyprotox,
 #endif
-					 ipxprotox, atalkprotox, NULL };
+#ifdef IPX
+					 ipxprotox,
+#endif
+					 atalkprotox, NULL };
 
 static void printproto(struct protox *, const char *);
 static void usage(void);
@@ -304,6 +339,7 @@
 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[])
@@ -452,16 +488,19 @@
 	 * Discard setgid privileges if not the running kernel so that bad
 	 * guys can't print interesting stuff from kernel memory.
 	 */
-	if (nlistf != NULL || memf != NULL)
-		(void)setgid(getgid());
+	live = (nlistf == NULL && memf == NULL);
+	if (!live)
+		setgid(getgid());
 
 	if (Bflag) {
+		if (!live)
+			usage();
 		bpf_stats(interface);
 		exit(0);
 	}
 	if (mflag) {
 		if (memf != NULL) {
-			if (kread(0, 0, 0) == 0)
+			if (kread(0, NULL, 0) == 0)
 				mbpr(kvmd, nl[N_MBSTAT].n_value);
 		} else
 			mbpr(NULL, 0);
@@ -481,13 +520,12 @@
 	 * used for the queries, which is slower.
 	 */
 #endif
+	kread(0, NULL, 0);
 	if (iflag && !sflag) {
-		kread(0, 0, 0);
 		intpr(interval, nl[N_IFNET].n_value, NULL);
 		exit(0);
 	}
 	if (rflag) {
-		kread(0, 0, 0);
 		if (sflag)
 			rt_stats(nl[N_RTSTAT].n_value, nl[N_RTTRASH].n_value);
 		else
@@ -495,7 +533,6 @@
 		exit(0);
 	}
 	if (gflag) {
-		kread(0, 0, 0);
 		if (sflag) {
 			if (af == AF_INET || af == AF_UNSPEC)
 				mrt_stats(nl[N_MRTSTAT].n_value);
@@ -517,19 +554,7 @@
 		exit(0);
 	}
 
-	kread(0, 0, 0);
 	if (tp) {
-#ifdef FAST_IPSEC
-		/*
-		 * HACK: fallback to printing the new FAST IPSEC stats
-		 *	 if the kernel was built with FAST_IPSEC rather
-		 *	 than the KAME IPSEC stack (the two are mutually
-		 *	 exclusive).
-		 */
-		if (nl[tp->pr_sindex].n_value == 0 &&
-		    strcmp(tp->pr_name, "ipsec") == 0)
-			tp = name2protox("fastipsec");
-#endif
 		printproto(tp, tp->pr_name);
 		exit(0);
 	}
@@ -546,11 +571,12 @@
 		for (tp = pfkeyprotox; tp->pr_name; tp++)
 			printproto(tp, tp->pr_name);
 #endif /*IPSEC*/
+#ifdef IPX
 	if (af == AF_IPX || af == AF_UNSPEC) {
-		kread(0, 0, 0);
 		for (tp = ipxprotox; tp->pr_name; tp++)
 			printproto(tp, tp->pr_name);
 	}
+#endif /* IPX */
 	if (af == AF_APPLETALK || af == AF_UNSPEC)
 		for (tp = atalkprotox; tp->pr_name; tp++)
 			printproto(tp, tp->pr_name);
@@ -558,7 +584,8 @@
 		for (tp = netgraphprotox; tp->pr_name; tp++)
 			printproto(tp, tp->pr_name);
 	if ((af == AF_UNIX || af == AF_UNSPEC) && !Lflag && !sflag)
-		unixpr();
+		unixpr(nl[N_UNP_COUNT].n_value, nl[N_UNP_GENCNT].n_value,
+		    nl[N_UNP_DHEAD].n_value, nl[N_UNP_SHEAD].n_value);
 	exit(0);
 }
 
@@ -572,7 +599,7 @@
 	struct protox *tp;
 	const char *name;
 {
-	void (*pr)(u_long, const char *, int);
+	void (*pr)(u_long, const char *, int, int);
 	u_long off;
 
 	if (sflag) {
@@ -584,17 +611,24 @@
 				printf("%s: no per-interface stats routine\n",
 				    tp->pr_name);
 			return;
-		}
-		else {
+		} else {
 			pr = tp->pr_stats;
 			if (!pr) {
 				if (pflag)
 					printf("%s: no stats routine\n",
 					    tp->pr_name);
 				return;
-			}
-			off = tp->pr_usesysctl ? tp->pr_usesysctl 
-				: nl[tp->pr_sindex].n_value;
+			}			
+			if (tp->pr_usesysctl && live)
+				off = 0;
+			else if (tp->pr_sindex < 0) {
+				if (pflag)
+					printf(
+				    "%s: stats routine doesn't work on cores\n",
+					    tp->pr_name);
+				return;
+			} else
+				off = nl[tp->pr_sindex].n_value;
 		}
 	} else {
 		pr = tp->pr_cblocks;
@@ -603,28 +637,36 @@
 				printf("%s: no PCB routine\n", tp->pr_name);
 			return;
 		}
-		off = tp->pr_usesysctl ? tp->pr_usesysctl
-			: nl[tp->pr_index].n_value;
+		if (tp->pr_usesysctl && live)
+			off = 0;
+		else if (tp->pr_index < 0) {
+			if (pflag)
+				printf(
+				    "%s: PCB routine doesn't work on cores\n",
+				    tp->pr_name);
+			return;
+		} else
+			off = nl[tp->pr_index].n_value;
 	}
-	if (pr != NULL && (off || af != AF_UNSPEC))
-		(*pr)(off, name, af);
+	if (pr != NULL && (off || (live && tp->pr_usesysctl) ||
+	    af != AF_UNSPEC))
+		(*pr)(off, name, af, tp->pr_protocol);
 }
 
 /*
  * Read kernel memory, return 0 on success.
  */
 int
-kread(u_long addr, char *buf, int size)
+kread(u_long addr, void *buf, size_t size)
 {
-	if (kvmd == 0) {
-		/*
-		 * XXX.
-		 */
-		kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf);
+	char errbuf[_POSIX2_LINE_MAX];
+
+	if (kvmd == NULL) {
+		kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
 		setgid(getgid());
 		if (kvmd != NULL) {
 			if (kvm_nlist(kvmd, nl) < 0) {
-				if(nlistf)
+				if (nlistf)
 					errx(1, "%s: kvm_nlist: %s", nlistf,
 					     kvm_geterr(kvmd));
 				else
@@ -632,19 +674,19 @@
 			}
 
 			if (nl[0].n_type == 0) {
-				if(nlistf)
+				if (nlistf)
 					errx(1, "%s: no namelist", nlistf);
 				else
 					errx(1, "no namelist");
 			}
 		} else {
-			warnx("kvm not available");
+			warnx("kvm not available: %s", errbuf);
 			return(-1);
 		}
 	}
 	if (!buf)
 		return (0);
-	if (kvm_read(kvmd, addr, buf, size) != size) {
+	if (kvm_read(kvmd, addr, buf, size) != (ssize_t)size) {
 		warnx("%s", kvm_geterr(kvmd));
 		return (-1);
 	}
Index: inet6.c
===================================================================
RCS file: /home/cvs/src/usr.bin/netstat/inet6.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -L usr.bin/netstat/inet6.c -L usr.bin/netstat/inet6.c -u -r1.4 -r1.5
--- usr.bin/netstat/inet6.c
+++ usr.bin/netstat/inet6.c
@@ -39,7 +39,7 @@
 #endif
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/usr.bin/netstat/inet6.c,v 1.25 2004/07/28 16:03:12 stefanf Exp $");
+__FBSDID("$FreeBSD: src/usr.bin/netstat/inet6.c,v 1.29 2007/07/16 17:15:54 jhb Exp $");
 
 #ifdef INET6
 #include <sys/param.h>
@@ -66,8 +66,10 @@
 #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"
@@ -75,7 +77,6 @@
 struct	socket sockb;
 
 char	*inet6name(struct in6_addr *);
-const char *pluralies(uintmax_t);
 
 static char ntop_buf[INET6_ADDRSTRLEN];
 
@@ -361,22 +362,24 @@
  * Dump IP6 statistics structure.
  */
 void
-ip6_stats(u_long off __unused, const char *name, int af1 __unused)
+ip6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
 {
 	struct ip6stat ip6stat;
 	int first, i;
-	int mib[4];
 	size_t len;
 
-	mib[0] = CTL_NET;
-	mib[1] = PF_INET6;
-	mib[2] = IPPROTO_IPV6;
-	mib[3] = IPV6CTL_STATS;
-
 	len = sizeof ip6stat;
-	memset(&ip6stat, 0, len);
-	if (sysctl(mib, 4, &ip6stat, &len, (void *)0, 0) < 0)
-		return;
+	if (live) {
+		memset(&ip6stat, 0, len);
+		if (sysctlbyname("net.inet6.ip6.stats", &ip6stat, &len, NULL,
+		    0) < 0) {
+			if (errno != ENOENT)
+				warn("sysctl: net.inet6.ip6.stats");
+			return;
+		}
+	} else
+		kread(off, &ip6stat, len);
+
 	printf("%s:\n", name);
 
 #define	p(f, m) if (ip6stat.f || sflag <= 1) \
@@ -514,7 +517,8 @@
 	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", ip6stat.ip6s_sources_rule[i],
+			printf("\t\t%ju %s\n",
+			       (uintmax_t)ip6stat.ip6s_sources_rule[i],
 			       srcrule_str[i]);
 	}
 #undef p
@@ -840,22 +844,24 @@
  * Dump ICMP6 statistics.
  */
 void
-icmp6_stats(u_long off __unused, const char *name, int af1 __unused)
+icmp6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
 {
 	struct icmp6stat icmp6stat;
 	int i, first;
-	int mib[4];
 	size_t len;
 
-	mib[0] = CTL_NET;
-	mib[1] = PF_INET6;
-	mib[2] = IPPROTO_ICMPV6;
-	mib[3] = ICMPV6CTL_STATS;
-
 	len = sizeof icmp6stat;
-	memset(&icmp6stat, 0, len);
-	if (sysctl(mib, 4, &icmp6stat, &len, (void *)0, 0) < 0)
-		return;
+	if (live) {
+		memset(&icmp6stat, 0, len);
+		if (sysctlbyname("net.inet6.icmp6.stats", &icmp6stat, &len,
+		    NULL, 0) < 0) {
+			if (errno != ENOENT)
+				warn("sysctl: net.inet6.icmp6.stats");
+			return;
+		}
+	} else
+		kread(off, &icmp6stat, len);
+
 	printf("%s:\n", name);
 
 #define	p(f, m) if (icmp6stat.f || sflag <= 1) \
@@ -992,14 +998,26 @@
  * Dump PIM statistics structure.
  */
 void
-pim6_stats(u_long off __unused, const char *name, int af1 __unused)
+pim6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
 {
-	struct pim6stat pim6stat;
+	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);
+	}
 
-	if (off == 0)
-		return;
-	if (kread(off, (char *)&pim6stat, sizeof(pim6stat)))
-		return;
 	printf("%s:\n", name);
 
 #define	p(f, m) if (pim6stat.f || sflag <= 1) \
@@ -1018,22 +1036,22 @@
  * Dump raw ip6 statistics structure.
  */
 void
-rip6_stats(u_long off __unused, const char *name, int af1 __unused)
+rip6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
 {
 	struct rip6stat rip6stat;
 	u_quad_t delivered;
-	int mib[4];
-	size_t l;
+	size_t len;
 
-	mib[0] = CTL_NET;
-	mib[1] = PF_INET6;
-	mib[2] = IPPROTO_IPV6;
-	mib[3] = IPV6CTL_RIP6STATS;
-	l = sizeof(rip6stat);
-	if (sysctl(mib, 4, &rip6stat, &l, NULL, 0) < 0) {
-		perror("Warning: sysctl(net.inet6.ip6.rip6stats)");
-		return;
-	}
+	len = sizeof(rip6stat);
+	if (live) {
+		if (sysctlbyname("net.inet6.ip6.rip6stats", &rip6stat, &len,
+		    NULL, 0) < 0) {
+			if (errno != ENOENT)
+				warn("sysctl: net.inet6.ip6.rip6stats");
+			return;
+		}
+	} else
+		kread(off, &rip6stat, len);
 
 	printf("%s:\n", name);
 
Index: pfkey.c
===================================================================
RCS file: /home/cvs/src/usr.bin/netstat/pfkey.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L usr.bin/netstat/pfkey.c -L usr.bin/netstat/pfkey.c -u -r1.2 -r1.3
--- usr.bin/netstat/pfkey.c
+++ usr.bin/netstat/pfkey.c
@@ -1,4 +1,4 @@
-/*	$FreeBSD: src/usr.bin/netstat/pfkey.c,v 1.1.2.1 2006/01/05 03:47:24 kbyanc Exp $	*/
+/*	$FreeBSD: src/usr.bin/netstat/pfkey.c,v 1.5 2007/07/16 17:15:55 jhb Exp $	*/
 /*	$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 $	*/
 
@@ -70,20 +70,17 @@
 static char sccsid[] = "@(#)inet.c	8.5 (Berkeley) 5/24/95";
 */
 static const char rcsid[] =
-  "$FreeBSD: src/usr.bin/netstat/pfkey.c,v 1.1.2.1 2006/01/05 03:47:24 kbyanc Exp $";
+  "$FreeBSD: src/usr.bin/netstat/pfkey.c,v 1.5 2007/07/16 17:15:55 jhb Exp $";
 #endif /* not lint */
 
 #include <sys/param.h>
 #include <sys/queue.h>
 #include <sys/socket.h>
+#include <sys/socketvar.h>
 
 #include <netinet/in.h>
 
-#if defined(IPSEC) && !defined(FAST_IPSEC)
-#include <netkey/keysock.h>
-#endif
-
-#ifdef FAST_IPSEC
+#ifdef IPSEC
 #include <netipsec/keysock.h>
 #endif
 
@@ -120,7 +117,8 @@
 }
 
 void
-pfkey_stats(u_long off, const char *name, int family __unused)
+pfkey_stats(u_long off, const char *name, int family __unused,
+    int proto __unused)
 {
 	struct pfkeystat pfkeystat;
 	unsigned first, type;
Index: netstat.1
===================================================================
RCS file: /home/cvs/src/usr.bin/netstat/netstat.1,v
retrieving revision 1.3
retrieving revision 1.4
diff -L usr.bin/netstat/netstat.1 -L usr.bin/netstat/netstat.1 -u -r1.3 -r1.4
--- usr.bin/netstat/netstat.1
+++ usr.bin/netstat/netstat.1
@@ -9,7 +9,11 @@
 .\" 2. Redistributions in binary form must reproduce the above copyright
 .\"    notice, this list of conditions and the following disclaimer in the
 .\"    documentation and/or other materials provided with the distribution.
-.\" 3. Neither the name of the University nor the names of its contributors
+.\" 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.
 .\"
@@ -26,10 +30,9 @@
 .\" SUCH DAMAGE.
 .\"
 .\"	@(#)netstat.1	8.8 (Berkeley) 4/18/94
-.\" $FreeBSD: src/usr.bin/netstat/netstat.1,v 1.50.8.3 2005/12/27 23:34:13 csjp Exp $
-.\" $MidnightBSD$
+.\" $FreeBSD: src/usr.bin/netstat/netstat.1,v 1.58 2007/06/10 06:11:03 ceri Exp $
 .\"
-.Dd August 19, 2005
+.Dd June 10, 2007
 .Dt NETSTAT 1
 .Os
 .Sh NAME
@@ -191,6 +194,20 @@
 .It Xo
 .Bk -words
 .Nm
+.Fl B
+.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
@@ -278,9 +295,9 @@
 .It Em Family
 .Em Protocols
 .It Cm inet Pq Dv AF_INET
-.Cm bdg , divert , icmp , igmp , ip , ipsec , pim, tcp , udp
+.Cm divert , icmp , igmp , ip , ipsec , pim, sctp , tcp , udp
 .It Cm inet6 Pq Dv AF_INET6
-.Cm bdg , icmp6 , ip6 , ipsec6 , rip6 , tcp , udp
+.Cm icmp6 , ip6 , ipsec6 , rip6 , tcp , udp
 .It Cm pfkey Pq Dv PF_KEY
 .Cm pfkey
 .It Cm atalk Pq Dv AF_APPLETALK
@@ -420,18 +437,19 @@
 .Nm
 is invoked with the
 .Fl B
-option represents the underlying parameters of the bpf peer. Each flag is
+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 BIOCIMMEDIATE has been set on the device
-.It Li f Ta BIOCGHDRCMPLT status: source link addresses are being
+.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 BIOCGSEESENT status: see packets originating locally and
+.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 BIOCLOCK status: descriptor has been locked
+.It Li l Ta Dv BIOCLOCK No status: descriptor has been locked
 .El
 .Pp
 For more information about these flags, please refer to
Index: atalk.c
===================================================================
RCS file: /home/cvs/src/usr.bin/netstat/atalk.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -L usr.bin/netstat/atalk.c -L usr.bin/netstat/atalk.c -u -r1.3 -r1.4
--- usr.bin/netstat/atalk.c
+++ usr.bin/netstat/atalk.c
@@ -38,7 +38,7 @@
 #endif
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/usr.bin/netstat/atalk.c,v 1.24 2004/07/26 20:18:11 charnier Exp $");
+__FBSDID("$FreeBSD: src/usr.bin/netstat/atalk.c,v 1.26 2007/07/16 17:15:54 jhb Exp $");
 
 #include <sys/param.h>
 #include <sys/queue.h>
@@ -75,12 +75,12 @@
 static const char *
 at_pr_net(struct sockaddr_at *sat, int numeric)
 {
-	static	char mybuf[50];
+static	char mybuf[50];
 
-	if (numeric == 0) {
+	if (!numeric) {
 		switch(sat->sat_addr.s_net) {
 		case 0xffff:
-			return("????");
+			return "????";
 		case ATADDR_ANYNET:
 			return("*");
 		}
@@ -92,7 +92,7 @@
 static const char *
 at_pr_host(struct sockaddr_at *sat, int numeric)
 {
-	static	char mybuf[50];
+static	char mybuf[50];
 
 	if (!numeric) {
 		switch(sat->sat_addr.s_node) {
@@ -217,7 +217,8 @@
 }
 
 void
-atalkprotopr(u_long off __unused, const char *name, int af1 __unused)
+atalkprotopr(u_long off __unused, const char *name, int af1 __unused,
+    int proto __unused)
 {
 	struct ddpcb *this, *next;
 
@@ -266,7 +267,8 @@
  * Dump DDP statistics structure.
  */
 void
-ddp_stats(u_long off __unused, const char *name, int af1 __unused)
+ddp_stats(u_long off __unused, const char *name, int af1 __unused,
+    int proto __unused)
 {
 	struct ddpstat ddpstat;
 
--- /dev/null
+++ usr.bin/netstat/sctp.c
@@ -0,0 +1,691 @@
+/*-
+ * 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: src/usr.bin/netstat/sctp.c,v 1.7.2.1 2007/10/29 12:50:28 rrs Exp $");
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/sysctl.h>
+#include <sys/protosw.h>
+
+#include <netinet/in.h>
+#include <netinet/sctp.h>
+#include <netinet/sctp_constants.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"
+
+#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 max burst dosn't allow 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 */
Index: Makefile
===================================================================
RCS file: /home/cvs/src/usr.bin/netstat/Makefile,v
retrieving revision 1.6
retrieving revision 1.7
diff -L usr.bin/netstat/Makefile -L usr.bin/netstat/Makefile -u -r1.6 -r1.7
--- usr.bin/netstat/Makefile
+++ usr.bin/netstat/Makefile
@@ -1,23 +1,33 @@
 #	@(#)Makefile	8.1 (Berkeley) 6/12/93
-# $FreeBSD: src/usr.bin/netstat/Makefile,v 1.26.2.3 2006/01/05 03:47:24 kbyanc Exp $
+# $FreeBSD: src/usr.bin/netstat/Makefile,v 1.39 2007/07/01 12:08:07 gnn Exp $
 # $MidnightBSD$
 
+.include <bsd.own.mk>
+
 PROG=	netstat
-SRCS=	bpf.c if.c inet.c main.c mbuf.c mcast.c mroute.c ipx.c route.c \
-	unix.c atalk.c netgraph.c mroute6.c ipsec.c pfkey.c
+SRCS=	if.c inet.c main.c mbuf.c mcast.c mroute.c route.c \
+	unix.c atalk.c netgraph.c mroute6.c ipsec.c bpf.c pfkey.c sctp.c
 
 WARNS?=	3
 
 CFLAGS+=-DIPSEC
-.if !defined(NO_INET6)
-CFLAGS+=-DINET6
-CFLAGS+=-DFAST_IPSEC
+CFLAGS+=-DSCTP
+
+.if ${MK_INET6_SUPPORT} != "no"
 SRCS+=	inet6.c
+CFLAGS+=-DINET6
 .endif
 
 BINGRP=	kmem
 BINMODE=2555
-DPADD=	${LIBKVM} ${LIBIPX} ${LIBMEMSTAT} ${LIBNETGRAPH} ${LIBUTIL}
-LDADD=	-lkvm -lipx -lmemstat -lnetgraph -lutil
+DPADD=	${LIBKVM} ${LIBMEMSTAT} ${LIBNETGRAPH} ${LIBUTIL}
+LDADD=	-lkvm -lmemstat -lnetgraph -lutil
+
+.if ${MK_IPX_SUPPORT} != "no"
+SRCS+=	ipx.c
+DPADD+=	${LIBIPX}
+LDADD+=	-lipx
+CFLAGS+=-DIPX
+.endif
 
 .include <bsd.prog.mk>
Index: mbuf.c
===================================================================
RCS file: /home/cvs/src/usr.bin/netstat/mbuf.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -L usr.bin/netstat/mbuf.c -L usr.bin/netstat/mbuf.c -u -r1.4 -r1.5
--- usr.bin/netstat/mbuf.c
+++ usr.bin/netstat/mbuf.c
@@ -40,13 +40,13 @@
 #endif
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/usr.bin/netstat/mbuf.c,v 1.42.8.6 2006/03/01 20:54:21 andre Exp $");
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: src/usr.bin/netstat/mbuf.c,v 1.53 2007/07/16 17:15:55 jhb Exp $");
 
 #include <sys/param.h>
 #include <sys/mbuf.h>
 #include <sys/protosw.h>
 #include <sys/socket.h>
+#include <sys/socketvar.h>
 #include <sys/sysctl.h>
 
 #include <err.h>
@@ -66,24 +66,23 @@
 {
 	struct memory_type_list *mtlp;
 	struct memory_type *mtp;
-	u_int64_t mbuf_count, mbuf_bytes, mbuf_free, mbuf_failures, mbuf_size;
-	u_int64_t cluster_count, cluster_bytes, cluster_limit, cluster_free;
-	u_int64_t cluster_failures, cluster_size;
-	u_int64_t packet_count, packet_bytes, packet_free, packet_failures;
-	u_int64_t tag_count, tag_bytes;
-	u_int64_t jumbop_count, jumbop_bytes, jumbop_limit, jumbop_free;
-	u_int64_t jumbop_failures, jumbop_size;
-	u_int64_t jumbo9_count, jumbo9_bytes, jumbo9_limit, jumbo9_free;
-	u_int64_t jumbo9_failures, jumbo9_size;
-	u_int64_t jumbo16_count, jumbo16_bytes, jumbo16_limit, jumbo16_free;
-	u_int64_t jumbo16_failures, jumbo16_size;
-	u_int64_t bytes_inuse, bytes_incache, bytes_total;
+	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, live;
+	int error;
 
-	live = (kvmd == NULL);
 	mtlp = memstat_mtl_alloc();
 	if (mtlp == NULL) {
 		warn("memstat_mtl_alloc");
Index: unix.c
===================================================================
RCS file: /home/cvs/src/usr.bin/netstat/unix.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L usr.bin/netstat/unix.c -L usr.bin/netstat/unix.c -u -r1.2 -r1.3
--- usr.bin/netstat/unix.c
+++ usr.bin/netstat/unix.c
@@ -38,7 +38,7 @@
 #endif
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/usr.bin/netstat/unix.c,v 1.18 2004/07/26 20:18:11 charnier Exp $");
+__FBSDID("$FreeBSD: src/usr.bin/netstat/unix.c,v 1.20 2007/07/16 17:15:55 jhb Exp $");
 
 /*
  * Display protocol blocks in the unix domain.
@@ -61,6 +61,7 @@
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <strings.h>
 #include <kvm.h>
 #include "netstat.h"
 
@@ -69,35 +70,148 @@
 static	const char *const socktype[] =
     { "#0", "stream", "dgram", "raw", "rdm", "seqpacket" };
 
-void
-unixpr(void)
+static int
+pcblist_sysctl(int type, char **bufp)
 {
 	char 	*buf;
-	int	type;
 	size_t	len;
-	struct	xsocket *so;
-	struct	xunpgen *xug, *oxug;
-	struct	xunpcb *xunp;
 	char mibvar[sizeof "net.local.seqpacket.pcblist"];
 
-	for (type = SOCK_STREAM; type <= SOCK_SEQPACKET; type++) {
-		sprintf(mibvar, "net.local.%s.pcblist", socktype[type]);
+	sprintf(mibvar, "net.local.%s.pcblist", socktype[type]);
+
+	len = 0;
+	if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
+		if (errno != ENOENT)
+			warn("sysctl: %s", mibvar);
+		return (-1);
+	}
+	if ((buf = malloc(len)) == 0) {
+		warnx("malloc %lu bytes", (u_long)len);
+		return (-2);
+	}
+	if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
+		warn("sysctl: %s", mibvar);
+		free(buf);
+		return (-2);
+	}
+	*bufp = buf;
+	return (0);
+}
+
+static int
+pcblist_kvm(u_long count_off, u_long gencnt_off, u_long head_off, char **bufp)
+{
+	struct unp_head head;
+	struct unpcb *unp, unp_conn;
+	u_char sun_len;
+	struct socket so;
+	struct xunpgen xug;
+	struct xunpcb xu;
+	unp_gen_t unp_gencnt;
+	u_int	unp_count;
+	char 	*buf, *p;
+	size_t	len;
+
+	if (count_off == 0 || gencnt_off == 0)
+		return (-2);
+	if (head_off == 0)
+		return (-1);
+	kread(count_off, &unp_count, sizeof(unp_count));
+	len = 2 * sizeof(xug) + (unp_count + unp_count / 8) * sizeof(xu);
+	if ((buf = malloc(len)) == 0) {
+		warnx("malloc %lu bytes", (u_long)len);
+		return (-2);
+	}
+	p = buf;
+
+#define COPYOUT(obj, size) do {						\
+	if (len < (size)) {						\
+		warnx("buffer size exceeded");				\
+		goto fail;						\
+	}								\
+	bcopy((obj), p, (size));					\
+	len -= (size);							\
+	p += (size);							\
+} while (0)
+
+#define KREAD(off, buf, len) do {					\
+	if (kread((uintptr_t)(off), (buf), (len)) != 0)			\
+		goto fail;						\
+} while (0)
+
+	/* Write out header. */
+	kread(gencnt_off, &unp_gencnt, sizeof(unp_gencnt));
+	xug.xug_len = sizeof xug;
+	xug.xug_count = unp_count;
+	xug.xug_gen = unp_gencnt;
+	xug.xug_sogen = 0;
+	COPYOUT(&xug, sizeof xug);
+
+	/* 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;
 
-		len = 0;
-		if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
-			if (errno != ENOENT)
-				warn("sysctl: %s", mibvar);
+		if (unp->unp_gencnt > unp_gencnt)
 			continue;
+		if (unp->unp_addr != NULL) {
+			KREAD(unp->unp_addr, &sun_len, sizeof(sun_len));
+			KREAD(unp->unp_addr, &xu.xu_addr, sun_len);
 		}
-		if ((buf = malloc(len)) == 0) {
-			warnx("malloc %lu bytes", (u_long)len);
-			return;
+		if (unp->unp_conn != NULL) {
+			KREAD(unp->unp_conn, &unp_conn, sizeof(unp_conn));
+			if (unp_conn.unp_addr != NULL) {
+				KREAD(unp_conn.unp_addr, &sun_len,
+				    sizeof(sun_len));
+				KREAD(unp_conn.unp_addr, &xu.xu_caddr, sun_len);
+			}
 		}
-		if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
-			warn("sysctl: %s", mibvar);
-			free(buf);
+		KREAD(unp->unp_socket, &so, sizeof(so));
+		if (sotoxsocket(&so, &xu.xu_socket) != 0)
+			goto fail;
+		COPYOUT(&xu, sizeof(xu));
+	}
+
+	/* Reread the counts and write the footer. */
+	kread(count_off, &unp_count, sizeof(unp_count));
+	kread(gencnt_off, &unp_gencnt, sizeof(unp_gencnt));
+	xug.xug_count = unp_count;
+	xug.xug_gen = unp_gencnt;
+	COPYOUT(&xug, sizeof xug);
+
+	*bufp = buf;
+	return (0);
+
+fail:
+	free(buf);
+	return (-1);
+#undef COPYOUT
+#undef KREAD
+}
+
+void
+unixpr(u_long count_off, u_long gencnt_off, u_long dhead_off, u_long shead_off)
+{
+	char 	*buf;
+	int	ret, type;
+	struct	xsocket *so;
+	struct	xunpgen *xug, *oxug;
+	struct	xunpcb *xunp;
+
+	for (type = SOCK_STREAM; type <= SOCK_SEQPACKET; type++) {
+		if (live)
+			ret = pcblist_sysctl(type, &buf);
+		else
+			ret = pcblist_kvm(count_off, gencnt_off,
+			    type == SOCK_STREAM ? shead_off :
+			    (type == SOCK_DGRAM ? dhead_off : 0), &buf);
+		if (ret == -1)
+			continue;
+		if (ret < 0)
 			return;
-		}
 
 		oxug = xug = (struct xunpgen *)buf;
 		for (xug = (struct xunpgen *)((char *)xug + xug->xug_len);
Index: route.c
===================================================================
RCS file: /home/cvs/src/usr.bin/netstat/route.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -L usr.bin/netstat/route.c -L usr.bin/netstat/route.c -u -r1.3 -r1.4
--- usr.bin/netstat/route.c
+++ usr.bin/netstat/route.c
@@ -38,11 +38,12 @@
 #endif
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/usr.bin/netstat/route.c,v 1.76 2005/05/13 16:31:10 ume Exp $");
+__FBSDID("$FreeBSD: src/usr.bin/netstat/route.c,v 1.82 2007/07/16 17:15:55 jhb Exp $");
 
 #include <sys/param.h>
 #include <sys/protosw.h>
 #include <sys/socket.h>
+#include <sys/socketvar.h>
 #include <sys/time.h>
 
 #include <net/ethernet.h>
@@ -67,9 +68,9 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sysexits.h>
 #include <unistd.h>
 #include <err.h>
-#include <time.h>
 #include "netstat.h"
 
 #define kget(p, d) (kread((u_long)(p), (char *)&(d), sizeof (d)))
@@ -118,6 +119,8 @@
 
 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);
@@ -132,7 +135,6 @@
 static void p_flags (int, const char *);
 static const char *fmt_flags(int f);
 static void p_rtentry (struct rtentry *);
-static u_long forgemask (u_long);
 static void domask (char *, u_long, u_long);
 
 /*
@@ -144,6 +146,14 @@
 	struct radix_node_head *rnh, head;
 	int i;
 
+	/*
+	 * 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.
+	 */
+	if (clock_gettime(CLOCK_UPTIME, &uptime) < 0)
+		err(EX_OSERR, "clock_gettime() failed");
+
 	printf("Routing tables\n");
 
 	if (Aflag == 0 && NewTree)
@@ -334,7 +344,7 @@
 			time_t expire_time;
 
 			if ((expire_time =
-			    rt->rt_rmx.rmx_expire - time(NULL)) > 0) {
+			    rt->rt_rmx.rmx_expire - uptime.tv_sec) > 0) {
 				len = snprintf(buffer, sizeof(buffer), "%d",
 					       (int)expire_time);
 				wid_expire = MAX(len, wid_expire);
@@ -632,7 +642,7 @@
 	case AF_NETGRAPH:
 	    {
 		strlcpy(workbuf, ((struct sockaddr_ng *)sa)->sg_data,
-			sizeof(workbuf));
+		        sizeof(workbuf));
 		cp = workbuf;
 		break;
 	    }
@@ -754,7 +764,7 @@
 			time_t expire_time;
 
 			if ((expire_time =
-			    rt->rt_rmx.rmx_expire - time((time_t *)0)) > 0)
+			    rt->rt_rmx.rmx_expire - uptime.tv_sec) > 0)
 				printf(" %*d", wid_expire, (int)expire_time);
 		}
 		if (rt->rt_nodes[0].rn_dupedkey)
@@ -791,26 +801,18 @@
 	return (line);
 }
 
-static u_long
-forgemask(u_long a)
-{
-	u_long m;
-
-	if (IN_CLASSA(a))
-		m = IN_CLASSA_NET;
-	else if (IN_CLASSB(a))
-		m = IN_CLASSB_NET;
-	else
-		m = IN_CLASSC_NET;
-	return (m);
-}
+#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, u_long addr, u_long mask)
 {
 	int b, i;
 
-	if (!mask || (forgemask(addr) == mask)) {
+	if (mask == 0 || (!numeric_addr && NSHIFT(mask) != 0)) {
 		*dst = '\0';
 		return;
 	}
@@ -843,27 +845,16 @@
 	char *cp = 0;
 	static char line[MAXHOSTNAMELEN];
 	struct netent *np = 0;
-	u_long dmask;
 	u_long i;
 
-#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)
-
 	i = ntohl(in);
-	dmask = forgemask(i);
 	if (!numeric_addr && i) {
 		np = getnetbyaddr(i >> NSHIFT(mask), AF_INET);
-		if (np == NULL && mask == 0)
-			np = getnetbyaddr(i >> NSHIFT(dmask), AF_INET);
 		if (np != NULL) {
 			cp = np->n_name;
 			trimdomain(cp, strlen(cp));
 		}
 	}
-#undef NSHIFT
 	if (cp != NULL) {
 		strncpy(line, cp, sizeof(line) - 1);
 		line[sizeof(line) - 1] = '\0';
@@ -874,6 +865,8 @@
 	return (line);
 }
 
+#undef NSHIFT
+
 #ifdef INET6
 const char *
 netname6(struct sockaddr_in6 *sa6, struct in6_addr *mask)
Index: inet.c
===================================================================
RCS file: /home/cvs/src/usr.bin/netstat/inet.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -L usr.bin/netstat/inet.c -L usr.bin/netstat/inet.c -u -r1.5 -r1.6
--- usr.bin/netstat/inet.c
+++ usr.bin/netstat/inet.c
@@ -38,10 +38,11 @@
 #endif
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/usr.bin/netstat/inet.c,v 1.70 2005/04/12 08:47:04 ru Exp $");
+__FBSDID("$FreeBSD: src/usr.bin/netstat/inet.c,v 1.78 2007/07/16 17:15:54 jhb Exp $");
 
 #include <sys/param.h>
 #include <sys/queue.h>
+#include <sys/domain.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
 #include <sys/sysctl.h>
@@ -90,6 +91,208 @@
 static int udp_done, tcp_done;
 #endif /* INET6 */
 
+static int
+pcblist_sysctl(int proto, char **bufp, int istcp)
+{
+	const char *mibvar;
+	char *buf;
+	size_t len;
+
+	switch (proto) {
+	case IPPROTO_TCP:
+		mibvar = "net.inet.tcp.pcblist";
+		break;
+	case IPPROTO_UDP:
+		mibvar = "net.inet.udp.pcblist";
+		break;
+	case IPPROTO_DIVERT:
+		mibvar = "net.inet.divert.pcblist";
+		break;
+	default:
+		mibvar = "net.inet.raw.pcblist";
+		break;
+	}
+
+	len = 0;
+	if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
+		if (errno != ENOENT)
+			warn("sysctl: %s", mibvar);
+		return (0);
+	}
+	if ((buf = malloc(len)) == 0) {
+		warnx("malloc %lu bytes", (u_long)len);
+		return (0);
+	}
+	if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
+		warn("sysctl: %s", mibvar);
+		free(buf);
+		return (0);
+	}
+	*bufp = buf;
+	return (1);
+}
+
+/*
+ * Copied directly from uipc_socket2.c.  We leave out some fields that are in
+ * nested structures that aren't used to avoid extra work.
+ */
+static void
+sbtoxsockbuf(struct sockbuf *sb, struct xsockbuf *xsb)
+{
+	xsb->sb_cc = sb->sb_cc;
+	xsb->sb_hiwat = sb->sb_hiwat;
+	xsb->sb_mbcnt = sb->sb_mbcnt;
+	xsb->sb_mbmax = sb->sb_mbmax;
+	xsb->sb_lowat = sb->sb_lowat;
+	xsb->sb_flags = sb->sb_flags;
+	xsb->sb_timeo = sb->sb_timeo;
+}
+
+int
+sotoxsocket(struct socket *so, struct xsocket *xso)
+{
+	struct protosw proto;
+	struct domain domain;
+
+	bzero(xso, sizeof *xso);
+	xso->xso_len = sizeof *xso;
+	xso->xso_so = so;
+	xso->so_type = so->so_type;
+	xso->so_options = so->so_options;
+	xso->so_linger = so->so_linger;
+	xso->so_state = so->so_state;
+	xso->so_pcb = so->so_pcb;
+	if (kread((uintptr_t)so->so_proto, &proto, sizeof(proto)) != 0)
+		return (-1);
+	xso->xso_protocol = proto.pr_protocol;
+	if (kread((uintptr_t)proto.pr_domain, &domain, sizeof(domain)) != 0)
+		return (-1);
+	xso->xso_family = domain.dom_family;
+	xso->so_qlen = so->so_qlen;
+	xso->so_incqlen = so->so_incqlen;
+	xso->so_qlimit = so->so_qlimit;
+	xso->so_timeo = so->so_timeo;
+	xso->so_error = so->so_error;
+	xso->so_oobmark = so->so_oobmark;
+	sbtoxsockbuf(&so->so_snd, &xso->so_snd);
+	sbtoxsockbuf(&so->so_rcv, &xso->so_rcv);
+	return (0);
+}
+
+static int
+pcblist_kvm(u_long off, char **bufp, int istcp)
+{
+	struct inpcbinfo pcbinfo;
+	struct inpcbhead listhead;
+	struct inpcb *inp;
+	struct xinpcb xi;
+	struct xinpgen xig;
+	struct xtcpcb xt;
+	struct socket so;
+	struct xsocket *xso;
+	char *buf, *p;
+	size_t len;
+
+	if (off == 0)
+		return (0);
+	kread(off, &pcbinfo, sizeof(pcbinfo));
+	if (istcp)
+		len = 2 * sizeof(xig) +
+		    (pcbinfo.ipi_count + pcbinfo.ipi_count / 8) *
+		    sizeof(struct xtcpcb);
+	else
+		len = 2 * sizeof(xig) +
+		    (pcbinfo.ipi_count + pcbinfo.ipi_count / 8) *
+		    sizeof(struct xinpcb);
+	if ((buf = malloc(len)) == 0) {
+		warnx("malloc %lu bytes", (u_long)len);
+		return (0);
+	}
+	p = buf;
+
+#define COPYOUT(obj, size) do {						\
+	if (len < (size)) {						\
+		warnx("buffer size exceeded");				\
+		goto fail;						\
+	}								\
+	bcopy((obj), p, (size));					\
+	len -= (size);							\
+	p += (size);							\
+} while (0)
+
+#define KREAD(off, buf, len) do {					\
+	if (kread((uintptr_t)(off), (buf), (len)) != 0)			\
+		goto fail;						\
+} while (0)
+
+	/* Write out header. */
+	xig.xig_len = sizeof xig;
+	xig.xig_count = pcbinfo.ipi_count;
+	xig.xig_gen = pcbinfo.ipi_gencnt;
+	xig.xig_sogen = 0;
+	COPYOUT(&xig, sizeof xig);
+
+	/* Walk the PCB list. */
+	xt.xt_len = sizeof xt;
+	xi.xi_len = sizeof xi;
+	if (istcp)
+		xso = &xt.xt_socket;
+	else
+		xso = &xi.xi_socket;
+	KREAD(pcbinfo.ipi_listhead, &listhead, sizeof(listhead));
+	LIST_FOREACH(inp, &listhead, inp_list) {
+		if (istcp) {
+			KREAD(inp, &xt.xt_inp, sizeof(*inp));
+			inp = &xt.xt_inp;
+		} else {
+			KREAD(inp, &xi.xi_inp, sizeof(*inp));
+			inp = &xi.xi_inp;
+		}
+
+		if (inp->inp_gencnt > pcbinfo.ipi_gencnt)
+			continue;
+
+		if (istcp) {
+			if (inp->inp_ppcb == NULL)
+				bzero(&xt.xt_tp, sizeof xt.xt_tp);
+			else if (inp->inp_vflag & INP_TIMEWAIT) {
+				bzero(&xt.xt_tp, sizeof xt.xt_tp);
+				xt.xt_tp.t_state = TCPS_TIME_WAIT;
+			} else
+				KREAD(inp->inp_ppcb, &xt.xt_tp,
+				    sizeof xt.xt_tp);
+		}
+		if (inp->inp_socket) {
+			KREAD(inp->inp_socket, &so, sizeof(so));
+			if (sotoxsocket(&so, xso) != 0)
+				goto fail;
+		} else {
+			bzero(xso, sizeof(*xso));
+			if (istcp)
+				xso->xso_protocol = IPPROTO_TCP;
+		}
+		if (istcp)
+			COPYOUT(&xt, sizeof xt);
+		else
+			COPYOUT(&xi, sizeof xi);		
+	}
+
+	/* Reread the pcbinfo and write out the footer. */
+	kread(off, &pcbinfo, sizeof(pcbinfo));
+	xig.xig_count = pcbinfo.ipi_count;
+	xig.xig_gen = pcbinfo.ipi_gencnt;
+	COPYOUT(&xig, sizeof xig);
+	
+	*bufp = buf;
+	return (1);
+
+fail:
+	free(buf);
+	return (0);
+#undef COPYOUT
+#undef KREAD
+}
+
 /*
  * Print a summary of connections related to an Internet
  * protocol.  For TCP, also give state of connection.
@@ -97,18 +300,16 @@
  * -a (all) flag is specified.
  */
 void
-protopr(u_long proto,		/* for sysctl version we pass proto # */
-	const char *name, int af1)
+protopr(u_long off, const char *name, int af1, int proto)
 {
 	int istcp;
 	static int first = 1;
 	char *buf;
-	const char *mibvar, *vchar;
+	const char *vchar;
 	struct tcpcb *tp = NULL;
 	struct inpcb *inp;
 	struct xinpgen *xig, *oxig;
 	struct xsocket *so;
-	size_t len;
 
 	istcp = 0;
 	switch (proto) {
@@ -120,7 +321,6 @@
 			tcp_done = 1;
 #endif
 		istcp = 1;
-		mibvar = "net.inet.tcp.pcblist";
 		break;
 	case IPPROTO_UDP:
 #ifdef INET6
@@ -129,29 +329,14 @@
 		else
 			udp_done = 1;
 #endif
-		mibvar = "net.inet.udp.pcblist";
-		break;
-	case IPPROTO_DIVERT:
-		mibvar = "net.inet.divert.pcblist";
-		break;
-	default:
-		mibvar = "net.inet.raw.pcblist";
 		break;
 	}
-	len = 0;
-	if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
-		if (errno != ENOENT)
-			warn("sysctl: %s", mibvar);
-		return;
-	}
-	if ((buf = malloc(len)) == 0) {
-		warnx("malloc %lu bytes", (u_long)len);
-		return;
-	}
-	if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
-		warn("sysctl: %s", mibvar);
-		free(buf);
-		return;
+	if (live) {
+		if (!pcblist_sysctl(proto, &buf, istcp))
+			return;
+	} else {
+		if (!pcblist_kvm(off, &buf, istcp))
+			return;
 	}
 
 	oxig = xig = (struct xinpgen *)buf;
@@ -168,7 +353,7 @@
 		}
 
 		/* Ignore sockets for protocols other than the desired one. */
-		if (so->xso_protocol != (int)proto)
+		if (so->xso_protocol != proto)
 			continue;
 
 		/* Ignore PCBs which were freed during copyout. */
@@ -217,7 +402,7 @@
 	"Current listen queue sizes (qlen/incqlen/maxqlen)");
 			putchar('\n');
 			if (Aflag)
-				printf("%-8.8s ", "Socket");
+				printf("%-8.8s ", "Tcpcb");
 			if (Lflag)
 				printf("%-5.5s %-14.14s %-22.22s\n",
 					"Proto", "Listen", "Local Address");
@@ -347,18 +532,10 @@
  * Dump TCP statistics structure.
  */
 void
-tcp_stats(u_long off __unused, const char *name, int af1 __unused)
+tcp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
 {
 	struct tcpstat tcpstat, zerostat;
 	size_t len = sizeof tcpstat;
-	
-	if (zflag)
-		memset(&zerostat, 0, len);
-	if (sysctlbyname("net.inet.tcp.stats", &tcpstat, &len,
-	    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
-		warn("sysctl: net.inet.tcp.stats");
-		return;
-	}
 
 #ifdef INET6
 	if (tcp_done != 0)
@@ -367,6 +544,17 @@
 		tcp_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) \
@@ -436,6 +624,7 @@
 	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");
@@ -479,20 +668,12 @@
  * Dump UDP statistics structure.
  */
 void
-udp_stats(u_long off __unused, const char *name, int af1 __unused)
+udp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
 {
 	struct udpstat udpstat, zerostat;
 	size_t len = sizeof udpstat;
 	u_long delivered;
 
-	if (zflag)
-		memset(&zerostat, 0, len);
-	if (sysctlbyname("net.inet.udp.stats", &udpstat, &len,
-	    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
-		warn("sysctl: net.inet.udp.stats");
-		return;
-	}
-
 #ifdef INET6
 	if (udp_done != 0)
 		return;
@@ -500,6 +681,17 @@
 		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))
@@ -512,7 +704,7 @@
 	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 dropped due to no socket\n");
+	    "\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 -
@@ -525,6 +717,9 @@
 	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
 }
@@ -533,24 +728,30 @@
  * Dump CARP statistics structure.
  */
 void
-carp_stats(u_long off __unused, const char *name, int af1 __unused)
+carp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
 {
 	struct carpstats carpstat, zerostat;
 	size_t len = sizeof(struct carpstats);
 
-	if (zflag)
-		memset(&zerostat, 0, len);
-	if (sysctlbyname("net.inet.carp.stats", &carpstat, &len,
-	    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
-		if (errno != ENOENT)
-			warn("sysctl: net.inet.carp.stats");
-		return;
+	if (live) {
+		if (zflag)
+			memset(&zerostat, 0, len);
+		if (sysctlbyname("net.inet.carp.stats", &carpstat, &len,
+		    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+			if (errno != ENOENT)
+				warn("sysctl: net.inet.carp.stats");
+			return;
+		}
+	} else {
+		if (off == 0)
+			return;
+		kread(off, &carpstat, len);
 	}
 
 	printf("%s:\n", name);
 
 #define p(f, m) if (carpstat.f || sflag <= 1) \
-	printf(m, (uintmax_t)carpstat.f, plural((int)carpstat.f))
+	printf(m, (uintmax_t)carpstat.f, plural(carpstat.f))
 #define p2(f, m) if (carpstat.f || sflag <= 1) \
 	printf(m, (uintmax_t)carpstat.f)
 
@@ -578,18 +779,21 @@
  * Dump IP statistics structure.
  */
 void
-ip_stats(u_long off __unused, const char *name, int af1 __unused)
+ip_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
 {
 	struct ipstat ipstat, zerostat;
 	size_t len = sizeof ipstat;
 
-	if (zflag)
-		memset(&zerostat, 0, len);
-	if (sysctlbyname("net.inet.ip.stats", &ipstat, &len,
-	    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
-		warn("sysctl: net.inet.ip.stats");
-		return;
-	}
+	if (live) {
+		if (zflag)
+			memset(&zerostat, 0, len);
+		if (sysctlbyname("net.inet.ip.stats", &ipstat, &len,
+		    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+			warn("sysctl: net.inet.ip.stats");
+			return;
+		}
+	} else
+		kread(off, &ipstat, len);
 
 	printf("%s:\n", name);
 
@@ -635,52 +839,71 @@
 #undef p1a
 }
 
-static	const char *icmpnames[] = {
-	"echo reply",
+static	const char *icmpnames[ICMP_MAXTYPE + 1] = {
+	"echo reply",			/* RFC 792 */
 	"#1",
 	"#2",
-	"destination unreachable",
-	"source quench",
-	"routing redirect",
+	"destination unreachable",	/* RFC 792 */
+	"source quench",		/* RFC 792 */
+	"routing redirect",		/* RFC 792 */
 	"#6",
 	"#7",
-	"echo",
-	"router advertisement",
-	"router solicitation",
-	"time exceeded",
-	"parameter problem",
-	"time stamp",
-	"time stamp reply",
-	"information request",
-	"information request reply",
-	"address mask request",
-	"address mask reply",
+	"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 __unused, const char *name, int af1 __unused)
+icmp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
 {
 	struct icmpstat icmpstat, zerostat;
 	int i, first;
-	int mib[4];		/* CTL_NET + PF_INET + IPPROTO_ICMP + req */
 	size_t len;
 
-	mib[0] = CTL_NET;
-	mib[1] = PF_INET;
-	mib[2] = IPPROTO_ICMP;
-	mib[3] = ICMPCTL_STATS;
-
 	len = sizeof icmpstat;
-	if (zflag)
-		memset(&zerostat, 0, len);
-	if (sysctl(mib, 4, &icmpstat, &len,
-	    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
-		warn("sysctl: net.inet.icmp.stats");
-		return;
-	}
+	if (live) {
+		if (zflag)
+			memset(&zerostat, 0, len);
+		if (sysctlbyname("net.inet.icmp.stats", &icmpstat, &len,
+		    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+			warn("sysctl: net.inet.icmp.stats");
+			return;
+		}
+	} else
+		kread(off, &icmpstat, len);
 
 	printf("%s:\n", name);
 
@@ -700,8 +923,12 @@
 				printf("\tOutput histogram:\n");
 				first = 0;
 			}
-			printf("\t\t%s: %lu\n", icmpnames[i],
-				icmpstat.icps_outhist[i]);
+			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 < minimum length\n");
@@ -715,8 +942,12 @@
 				printf("\tInput histogram:\n");
 				first = 0;
 			}
-			printf("\t\t%s: %lu\n", icmpnames[i],
-				icmpstat.icps_inhist[i]);
+			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");
@@ -724,30 +955,35 @@
 #undef p
 #undef p1a
 #undef p2
-	mib[3] = ICMPCTL_MASKREPL;
-	len = sizeof i;
-	if (sysctl(mib, 4, &i, &len, (void *)0, 0) < 0)
-		return;
-	printf("\tICMP address mask responses are %sabled\n", 
-	       i ? "en" : "dis");
+	if (live) {
+		len = sizeof i;
+		if (sysctlbyname("net.inet.icmp.maskrepl", &i, &len, NULL, 0) <
+		    0)
+			return;
+		printf("\tICMP address mask responses are %sabled\n", 
+		    i ? "en" : "dis");
+	}
 }
 
 /*
  * Dump IGMP statistics structure.
  */
 void
-igmp_stats(u_long off __unused, const char *name, int af1 __unused)
+igmp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
 {
 	struct igmpstat igmpstat, zerostat;
 	size_t len = sizeof igmpstat;
 
-	if (zflag)
-		memset(&zerostat, 0, len);
-	if (sysctlbyname("net.inet.igmp.stats", &igmpstat, &len,
-	    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
-		warn("sysctl: net.inet.igmp.stats");
-		return;
-	}
+	if (live) {
+		if (zflag)
+			memset(&zerostat, 0, len);
+		if (sysctlbyname("net.inet.igmp.stats", &igmpstat, &len,
+		    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+			warn("sysctl: net.inet.igmp.stats");
+			return;
+		}
+	} else
+		kread(off, &igmpstat, len);
 
 	printf("%s:\n", name);
 
@@ -772,18 +1008,25 @@
  * Dump PIM statistics structure.
  */
 void
-pim_stats(u_long off __unused, const char *name, int af1 __unused)
+pim_stats(u_long off __unused, const char *name, int af1 __unused,
+    int proto __unused)
 {
 	struct pimstat pimstat, zerostat;
 	size_t len = sizeof pimstat;
 
-	if (zflag)
-		memset(&zerostat, 0, len);
-	if (sysctlbyname("net.inet.pim.stats", &pimstat, &len,
-	    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
-		if (errno != ENOENT)
-			warn("sysctl: net.inet.pim.stats");
-		return;
+	if (live) {
+		if (zflag)
+			memset(&zerostat, 0, len);
+		if (sysctlbyname("net.inet.pim.stats", &pimstat, &len,
+		    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+			if (errno != ENOENT)
+				warn("sysctl: net.inet.pim.stats");
+			return;
+		}
+	} else {
+		if (off == 0)
+			return;
+		kread(off, &pimstat, len);
 	}
 
 	printf("%s:\n", name);
Index: netstat.h
===================================================================
RCS file: /home/cvs/src/usr.bin/netstat/netstat.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -L usr.bin/netstat/netstat.h -L usr.bin/netstat/netstat.h -u -r1.3 -r1.4
--- usr.bin/netstat/netstat.h
+++ usr.bin/netstat/netstat.h
@@ -1,4 +1,4 @@
-/*-
+/*
  * Copyright (c) 1992, 1993
  *	Regents of the University of California.  All rights reserved.
  *
@@ -10,7 +10,11 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
+ * 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.
  *
@@ -27,8 +31,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)netstat.h	8.2 (Berkeley) 1/4/94
- * $FreeBSD: src/usr.bin/netstat/netstat.h,v 1.41.2.5 2006/01/05 03:47:24 kbyanc Exp $
- * $MidnightBSD$
+ * $FreeBSD: src/usr.bin/netstat/netstat.h,v 1.51 2007/07/16 17:15:55 jhb Exp $
  */
 
 #include <sys/cdefs.h>
@@ -56,38 +59,41 @@
 extern int	unit;	/* unit number for above */
 
 extern int	af;	/* address family */
+extern int	live;	/* true if we are examining a live system */
 
-int	kread(u_long addr, char *buf, int size);
+int	kread(u_long addr, void *buf, size_t size);
 const char *plural(uintmax_t);
 const char *plurales(uintmax_t);
 const char *pluralies(uintmax_t);
 
-void	protopr(u_long, const char *, int);
-void	tcp_stats(u_long, const char *, int);
-void	udp_stats(u_long, const char *, int);
-void	ip_stats(u_long, const char *, int);
-void	icmp_stats(u_long, const char *, int);
-void	igmp_stats(u_long, const char *, int);
-void	pim_stats(u_long, const char *, int);
-void	carp_stats (u_long, const char *, int);
-void	pfsync_stats (u_long, const char *, int);
-#ifdef IPSEC
-void	ipsec_stats(u_long, const char *, int);
-#ifdef FAST_IPSEC
-void	ipsec_stats_new (u_long, const char *, int);
-void	esp_stats (u_long, const char *, int);
-void	ah_stats (u_long, const char *, int);
-void	ipcomp_stats (u_long, const char *, int);
+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	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);
+void	ip6_stats(u_long, const char *, int, int);
 void	ip6_ifstats(char *);
-void	icmp6_stats(u_long, const char *, int);
+void	icmp6_stats(u_long, const char *, int, int);
 void	icmp6_ifstats(char *);
-void	pim6_stats(u_long, const char *, int);
-void	rip6_stats(u_long, const char *, int);
+void	pim6_stats(u_long, const char *, int, int);
+void	rip6_stats(u_long, const char *, int, int);
 void	mroute6pr(u_long, u_long);
 void	mrt6_stats(u_long);
 
@@ -99,11 +105,9 @@
 #endif /*INET6*/
 
 #ifdef IPSEC
-void	pfkey_stats(u_long, const char *, int);
+void	pfkey_stats(u_long, const char *, int, int);
 #endif
 
-void	bdg_stats(u_long, const char *, int);
-
 void	mbpr(void *, u_long);
 
 void	hostpr(u_long, u_long);
@@ -127,29 +131,29 @@
 char	*ns_print(struct sockaddr *);
 void	routepr(u_long);
 
-void	ipxprotopr(u_long, const char *, int);
-void	spx_stats(u_long, const char *, int);
-void	ipx_stats(u_long, const char *, int);
-void	ipxerr_stats(u_long, const char *, int);
-
-void	nsprotopr(u_long, const char *, int);
-void	spp_stats(u_long, const char *, int);
-void	idp_stats(u_long, const char *, int);
-void	nserr_stats(u_long, const char *, int);
-
-void	atalkprotopr(u_long, const char *, int);
-void	ddp_stats(u_long, const char *, int);
-
-void	netgraphprotopr(u_long, const char *, int);
-
-void	unixpr(void);
-
-void	esis_stats(u_long, const char *, int);
-void	clnp_stats(u_long, const char *, int);
-void	cltp_stats(u_long, const char *, int);
-void	iso_protopr(u_long, const char *, int);
+void	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);
+
+void	netgraphprotopr(u_long, const char *, int, int);
+
+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);
+void	tp_protopr(u_long, const char *, int, int);
 void	tp_inproto(u_long);
 void	tp_stats(caddr_t, caddr_t);
 
Index: netgraph.c
===================================================================
RCS file: /home/cvs/src/usr.bin/netstat/netgraph.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L usr.bin/netstat/netgraph.c -L usr.bin/netstat/netgraph.c -u -r1.2 -r1.3
--- usr.bin/netstat/netgraph.c
+++ usr.bin/netstat/netgraph.c
@@ -33,7 +33,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/usr.bin/netstat/netgraph.c,v 1.10 2004/07/26 20:18:11 charnier Exp $");
+__FBSDID("$FreeBSD: src/usr.bin/netstat/netgraph.c,v 1.13 2007/07/16 17:15:55 jhb Exp $");
 
 #include <sys/param.h>
 #include <sys/queue.h>
@@ -62,7 +62,8 @@
 static	int csock = -1;
 
 void
-netgraphprotopr(u_long off, const char *name, int af1 __unused)
+netgraphprotopr(u_long off, const char *name, int af1 __unused,
+    int proto __unused)
 {
 	struct ngpcb *this, *next;
 	struct ngpcb ngpcb;
@@ -76,11 +77,15 @@
 /* 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 } };
+				       { .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)
Index: ipx.c
===================================================================
RCS file: /home/cvs/src/usr.bin/netstat/ipx.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L usr.bin/netstat/ipx.c -L usr.bin/netstat/ipx.c -u -r1.2 -r1.3
--- usr.bin/netstat/ipx.c
+++ usr.bin/netstat/ipx.c
@@ -39,8 +39,7 @@
 #endif
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/usr.bin/netstat/ipx.c,v 1.23 2005/01/02 19:26:06 rwatson Exp $");
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: src/usr.bin/netstat/ipx.c,v 1.27 2007/07/30 11:06:42 des Exp $");
 
 #include <sys/param.h>
 #include <sys/queue.h>
@@ -50,6 +49,7 @@
 
 #include <net/route.h>
 
+#define TCPSTATES
 #include <netinet/tcp_fsm.h>
 
 #include <netipx/ipx.h>
@@ -73,8 +73,6 @@
 
 static char *ipx_prpr (struct ipx_addr *);
 
-extern char *tcpstates[];
-
 /*
  * Print a summary of connections related to a Network Systems
  * protocol.  For SPX, also give state of connection.
@@ -83,7 +81,7 @@
  */
 
 void
-ipxprotopr(u_long off, const char *name, int af1 __unused)
+ipxprotopr(u_long off, const char *name, int af1 __unused, int proto __unused)
 {
 	struct ipxpcbhead cb;
 	struct ipxpcb *ipxp;
@@ -156,7 +154,7 @@
  * Dump SPX statistics structure.
  */
 void
-spx_stats(u_long off, const char *name, int af1 __unused)
+spx_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
 {
 	struct spx_istat spx_istat;
 #define spxstat spx_istat.newstats
@@ -232,7 +230,7 @@
  * Dump IPX statistics structure.
  */
 void
-ipx_stats(u_long off, const char *name, int af1 __unused)
+ipx_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
 {
 	struct ipxstat ipxstat;
 
@@ -275,7 +273,7 @@
  */
 /*ARGSUSED*/
 void
-ipxerr_stats(u_long off, const char *name, int af __unused)
+ipxerr_stats(u_long off, const char *name, int af __unused, int proto __unused)
 {
 	struct ipx_errstat ipx_errstat;
 	int j;
@@ -340,7 +338,7 @@
 }
 #endif /* IPXERRORMSGS */
 
-static struct sockaddr_ipx ssipx = {.sipx_family = AF_IPX};
+static struct sockaddr_ipx ssipx = { .sipx_family = AF_IPX };
 
 static
 char *ipx_prpr(struct ipx_addr *x)
Index: if.c
===================================================================
RCS file: /home/cvs/src/usr.bin/netstat/if.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -L usr.bin/netstat/if.c -L usr.bin/netstat/if.c -u -r1.4 -r1.5
--- usr.bin/netstat/if.c
+++ usr.bin/netstat/if.c
@@ -10,7 +10,11 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
+ * 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.
  *
@@ -34,12 +38,12 @@
 #endif
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/usr.bin/netstat/if.c,v 1.58.8.5 2005/11/16 08:27:46 ru Exp $");
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: src/usr.bin/netstat/if.c,v 1.69 2007/07/16 17:15:54 jhb Exp $");
 
 #include <sys/types.h>
 #include <sys/protosw.h>
 #include <sys/socket.h>
+#include <sys/socketvar.h>
 #include <sys/sysctl.h>
 #include <sys/time.h>
 
@@ -47,7 +51,6 @@
 #include <net/if_var.h>
 #include <net/if_dl.h>
 #include <net/if_types.h>
-#include <net/bridge.h>
 #include <net/ethernet.h>
 #include <net/pfvar.h>
 #include <net/if_pfsync.h>
@@ -72,72 +75,33 @@
 #define	YES	1
 #define	NO	0
 
-static void sidewaysintpr (u_int, u_long);
-static void catchalarm (int);
+static void sidewaysintpr(int, u_long);
+static void catchalarm(int);
 
 #ifdef INET6
 static char ntop_buf[INET6_ADDRSTRLEN];		/* for inet_ntop() */
-static int bdg_done;
 #endif
 
-/* print bridge statistics */
-void
-bdg_stats(u_long dummy __unused, const char *name, int af1 __unused)
-{
-    int i;
-    size_t slen ;
-    struct bdg_stats s ;
-    int mib[4] ;
-
-    slen = sizeof(s);
-
-    mib[0] = CTL_NET ;
-    mib[1] = PF_LINK ;
-    mib[2] = IFT_ETHER ;
-    mib[3] = PF_BDG ;
-    if (sysctl(mib,4, &s,&slen,NULL,0)==-1)
-	return ; /* no bridging */
-#ifdef INET6
-    if (bdg_done != 0)
-	return;
-    else
-	bdg_done = 1;
-#endif
-    printf("-- Bridging statistics (%s) --\n", name) ;
-    printf(
-"Name          In      Out  Forward     Drop    Bcast    Mcast    Local  Unknown\n");
-    for (i = 0 ; i < 16 ; i++) {
-	if (s.s[i].name[0])
-	printf("%-6s %9ld%9ld%9ld%9ld%9ld%9ld%9ld%9ld\n",
-	  s.s[i].name,
-	  s.s[i].p_in[(int)BDG_IN],
-	  s.s[i].p_in[(int)BDG_OUT],
-	  s.s[i].p_in[(int)BDG_FORWARD],
-	  s.s[i].p_in[(int)BDG_DROP],
-	  s.s[i].p_in[(int)BDG_BCAST],
-	  s.s[i].p_in[(int)BDG_MCAST],
-	  s.s[i].p_in[(int)BDG_LOCAL],
-	  s.s[i].p_in[(int)BDG_UNKNOWN] );
-    }
-}
-
 /* 
  * Dump pfsync statistics structure.
  */
 void
-pfsync_stats(u_long off __unused, const char *name, int af1 __unused)
+pfsync_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
 {
 	struct pfsyncstats pfsyncstat, zerostat;
 	size_t len = sizeof(struct pfsyncstats);
 
-	if (zflag)
-		memset(&zerostat, 0, len);
-	if (sysctlbyname("net.inet.pfsync.stats", &pfsyncstat, &len,
-	    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
-		if (errno != ENOENT)
-			warn("sysctl: net.inet.pfsync.stats");
-		return;
-	}
+	if (live) {
+		if (zflag)
+			memset(&zerostat, 0, len);
+		if (sysctlbyname("net.inet.pfsync.stats", &pfsyncstat, &len,
+		    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+			if (errno != ENOENT)
+				warn("sysctl: net.inet.pfsync.stats");
+			return;
+		}
+	} else
+		kread(off, &pfsyncstat, len);
 
 	printf("%s:\n", name);
 
@@ -172,11 +136,22 @@
 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, "%%%ds ", width);
+		sprintf(newfmt, "%s%%%ds%s", lsep, width, rsep);
 		printf(newfmt, "-");
 		return;
 	}
@@ -187,11 +162,11 @@
 		/* Format in human readable form. */
 		humanize_number(buf, sizeof(buf), (int64_t)value, "",
 		    HN_AUTOSCALE, HN_NOSPACE | HN_DECIMAL);
-		sprintf(newfmt, "%%%ds ", width);
+		sprintf(newfmt, "%s%%%ds%s", lsep, width, rsep);
 		printf(newfmt, buf);
 	} else {
 		/* Construct the format string. */
-		sprintf(newfmt, "%%%d%s ", width, fmt);
+		sprintf(newfmt, "%s%%%d%s%s", lsep, width, fmt, rsep);
 		printf(newfmt, value);
 	}
 }
@@ -200,7 +175,7 @@
  * Print a description of the network interfaces.
  */
 void
-intpr(int _interval, u_long ifnetaddr, void (*pfunc)(char *))
+intpr(int interval1, u_long ifnetaddr, void (*pfunc)(char *))
 {
 	struct ifnet ifnet;
 	struct ifnethead ifnethead;
@@ -235,8 +210,8 @@
 		printf("ifnet: symbol not defined\n");
 		return;
 	}
-	if (_interval) {
-		sidewaysintpr((unsigned)_interval, ifnetaddr);
+	if (interval1) {
+		sidewaysintpr(interval1, ifnetaddr);
 		return;
 	}
 	if (kread(ifnetaddr, (char *)&ifnethead, sizeof ifnethead))
@@ -455,14 +430,13 @@
 		if (bflag)
 			show_stat("lu", 10, obytes, link_layer|network_layer);
 
-		show_stat("lu", 5, collisions, link_layer);
+		show_stat("NRSlu", 5, collisions, link_layer);
 		if (tflag)
-			show_stat("d", 4, timer, link_layer);
-
+			show_stat("LSd", 4, timer, link_layer);
 		if (dflag)
-			show_stat("d", 4, drops, link_layer);
-
+			show_stat("LSd", 4, drops, link_layer);
 		putchar('\n');
+
 		if (aflag && ifaddrfound) {
 			/*
 			 * Print family's multicast addresses
@@ -550,17 +524,18 @@
 
 /*
  * Print a running summary of interface statistics.
- * Repeat display every interval seconds, showing statistics
- * collected over that interval.  Assumes that interval is non-zero.
+ * 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(unsigned interval1, u_long off)
+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;
@@ -613,7 +588,10 @@
 
 	(void)signal(SIGALRM, catchalarm);
 	signalled = NO;
-	(void)alarm(interval1);
+	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",
@@ -640,9 +618,10 @@
 			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("lu", 5, ifnet.if_collisions - ip->ift_co, 1);
+			show_stat("NRSlu", 5, 
+			    ifnet.if_collisions - ip->ift_co, 1);
 			if (dflag)
-				show_stat("u", 5,
+				show_stat("LSu", 5,
 				    ifnet.if_snd.ifq_drops - ip->ift_dr, 1);
 		}
 		ip->ift_ip = ifnet.if_ipackets;
@@ -686,9 +665,9 @@
 			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("lu", 5, sum->ift_co - total->ift_co, 1);
+			show_stat("NRSlu", 5, sum->ift_co - total->ift_co, 1);
 			if (dflag)
-				show_stat("u", 5,
+				show_stat("LSu", 5,
 				    sum->ift_dr - total->ift_dr, 1);
 		}
 		*total = *sum;
@@ -697,12 +676,10 @@
 		putchar('\n');
 	fflush(stdout);
 	oldmask = sigblock(sigmask(SIGALRM));
-	if (! signalled) {
+	while (!signalled)
 		sigpause(0);
-	}
-	sigsetmask(oldmask);
 	signalled = NO;
-	(void)alarm(interval1);
+	sigsetmask(oldmask);
 	line++;
 	first = 0;
 	if (line == 21)
@@ -713,8 +690,8 @@
 }
 
 /*
- * Called if an interval expires before sidewaysintpr has completed a loop.
- * Sets a flag to not wait for the alarm.
+ * Set a flag to indicate that a signal from the periodic itimer has been
+ * caught.
  */
 static void
 catchalarm(int signo __unused)
Index: mroute6.c
===================================================================
RCS file: /home/cvs/src/usr.bin/netstat/mroute6.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L usr.bin/netstat/mroute6.c -L usr.bin/netstat/mroute6.c -u -r1.2 -r1.3
--- usr.bin/netstat/mroute6.c
+++ usr.bin/netstat/mroute6.c
@@ -67,14 +67,17 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/usr.bin/netstat/mroute6.c,v 1.15 2004/07/26 20:18:11 charnier Exp $");
+__FBSDID("$FreeBSD: src/usr.bin/netstat/mroute6.c,v 1.21 2007/07/16 17:15:55 jhb Exp $");
 
 #ifdef INET6
 #include <sys/param.h>
 #include <sys/queue.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
+#include <sys/sysctl.h>
 #include <sys/protosw.h>
+#include <sys/mbuf.h>
+#include <sys/time.h>
 
 #include <net/if.h>
 #include <net/if_var.h>
@@ -82,8 +85,10 @@
 
 #include <netinet/in.h>
 
+#include <err.h>
 #include <stdint.h>
 #include <stdio.h>
+#include <stdlib.h>
 
 #define	KERNEL 1
 #include <netinet6/ip6_mroute.h>
@@ -108,18 +113,22 @@
 	int saved_numeric_addr;
 	mifi_t maxmif = 0;
 	long int waitings;
+	size_t len;
 
-	if (mfcaddr == 0 || mifaddr == 0) {
-		printf("No IPv6 multicast routing compiled into this"
-		       " system.\n");
-		return;
-	}
+	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;
-
-	kread(mifaddr, (char *)&mif6table, sizeof(mif6table));
 	banner_printed = 0;
+
 	for (mifi = 0, mifp = mif6table; mifi < MAXMIFS; ++mifi, ++mifp) {
 		struct ifnet ifnet;
 		char ifname[IFNAMSIZ];
@@ -127,7 +136,9 @@
 		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"
@@ -147,8 +158,18 @@
 	if (!banner_printed)
 		printf("\nIPv6 Multicast Interface Table is empty\n");
 
-	kread(mfcaddr, (char *)&mf6ctable, sizeof(mf6ctable));
+	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) {
@@ -170,6 +191,7 @@
 
 			for (waitings = 0, rtep = mfc.mf6c_stall; rtep; ) {
 				waitings++;
+				/* XXX KVM */
 				kread((u_long)rtep, (char *)&rte, sizeof(rte));
 				rtep = rte.next;
 			}
@@ -189,7 +211,7 @@
 		}
 	}
 	if (!banner_printed)
-		printf("\nIPv6 Multicast Routing Table is empty\n");
+		printf("\nIPv6 Multicast Forwarding Table is empty\n");
 
 	printf("\n");
 	numeric_addr = saved_numeric_addr;
@@ -199,14 +221,17 @@
 mrt6_stats(u_long mstaddr)
 {
 	struct mrt6stat mrtstat;
+	size_t len = sizeof mrtstat;
 
-	if (mstaddr == 0) {
-		printf("No IPv6 multicast routing compiled into this"
-		       " system.\n");
-		return;
-	}
+	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));
 
-	kread(mstaddr, (char *)&mrtstat, sizeof(mrtstat));
 	printf("IPv6 multicast forwarding:\n");
 
 #define	p(f, m) if (mrtstat.f || sflag <= 1) \
@@ -216,7 +241,7 @@
 
 	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 mrouted\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");
Index: bpf.c
===================================================================
RCS file: /home/cvs/src/usr.bin/netstat/bpf.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L usr.bin/netstat/bpf.c -L usr.bin/netstat/bpf.c -u -r1.2 -r1.3
--- usr.bin/netstat/bpf.c
+++ usr.bin/netstat/bpf.c
@@ -23,17 +23,19 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/usr.bin/netstat/bpf.c,v 1.5.2.1 2005/12/27 23:34:13 csjp Exp $
+ * $FreeBSD: src/usr.bin/netstat/bpf.c,v 1.9 2007/07/16 17:15:54 jhb Exp $
  */
 #include <sys/types.h>
 #include <sys/protosw.h>
 #include <sys/socket.h>
+#include <sys/socketvar.h>
 #include <sys/sysctl.h>
 #include <sys/param.h>
 #include <sys/user.h>
 
 #include <net/if.h>
 #include <net/if_var.h>
+#include <net/bpf.h>
 #include <net/bpfdesc.h>
 #include <arpa/inet.h>
 
@@ -76,7 +78,9 @@
 	*flagbuf++ = bd->bd_promisc ? 'p' : '-';
 	*flagbuf++ = bd->bd_immediate ? 'i' : '-';
 	*flagbuf++ = bd->bd_hdrcmplt ? '-' : 'f';
-	*flagbuf++ = bd->bd_seesent ? 's' : '-';
+	*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';
@@ -107,7 +111,7 @@
 		free(bd);
 		return;
 	}
-	printf("%5s %6s %6s %9s %9s %9s %5s %5s %s\n",
+	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++) {
@@ -115,7 +119,7 @@
 			continue;
 		bpf_flags(d, flagbuf);
 		pname = bpf_pidname(d->bd_pid);
-		printf("%5d %6s %6s %9lu %9lu %9lu %5d %5d %s\n",
+		printf("%5d %6s %7s %9lu %9lu %9lu %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);
Index: mroute.c
===================================================================
RCS file: /home/cvs/src/usr.bin/netstat/mroute.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -L usr.bin/netstat/mroute.c -L usr.bin/netstat/mroute.c -u -r1.3 -r1.4
--- usr.bin/netstat/mroute.c
+++ usr.bin/netstat/mroute.c
@@ -38,8 +38,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/usr.bin/netstat/mroute.c,v 1.22 2004/07/26 20:18:11 charnier Exp $");
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: src/usr.bin/netstat/mroute.c,v 1.30 2007/07/16 17:15:55 jhb Exp $");
 
 /*
  * Print multicast routing structures and statistics.
@@ -85,28 +84,24 @@
 	size_t len;
 
 	len = sizeof(mfctable);
-	if (sysctlbyname("net.inet.ip.mfctable", mfctable, &len, NULL, 0) < 0) {
-		warn("sysctl: net.inet.ip.mfctable");
-		/* Compatability with older kernels - candidate for removal */
-		if (mfcaddr == 0) {
-			printf("No IPv4 multicast routing compiled into this system.\n");
+	if (live) {
+		if (sysctlbyname("net.inet.ip.mfctable", mfctable, &len, NULL,
+		    0) < 0) {
+			warn("sysctl: net.inet.ip.mfctable");
 			return;
 		}
-
+	} else
 		kread(mfcaddr, (char *)mfctable, sizeof(mfctable));
-	}
 
 	len = sizeof(viftable);
-	if (sysctlbyname("net.inet.ip.viftable", viftable, &len, NULL, 0) < 0) {
-		warn("sysctl: net.inet.ip.viftable");
-		/* Compatability with older kernels - candidate for removal */
-		if (vifaddr == 0) {
-			printf("No IPv4 multicast routing compiled into this system.\n");
+	if (live) {
+		if (sysctlbyname("net.inet.ip.viftable", viftable, &len, NULL,
+		    0) < 0) {
+			warn("sysctl: net.inet.ip.viftable");
 			return;
 		}
-
+	} else
 		kread(vifaddr, (char *)viftable, sizeof(viftable));
-	}
 
 	saved_numeric_addr = numeric_addr;
 	numeric_addr = 1;
@@ -118,7 +113,7 @@
 
 		maxvif = vifi;
 		if (!banner_printed) {
-			printf("\nVirtual Interface Table\n"
+			printf("\nIPv4 Virtual Interface Table\n"
 			       " Vif   Thresh   Rate   Local-Address   "
 			       "Remote-Address    Pkts-In   Pkts-Out\n");
 			banner_printed = 1;
@@ -134,16 +129,17 @@
 		printf(" %9lu  %9lu\n", v->v_pkt_in, v->v_pkt_out);
 	}
 	if (!banner_printed)
-		printf("\nVirtual Interface Table is empty\n");
+		printf("\nIPv4 Virtual Interface Table is empty\n");
 
 	banner_printed = 0;
 	for (i = 0; i < MFCTBLSIZ; ++i) {
 		m = mfctable[i];
 		while(m) {
+			/* XXX KVM */
 			kread((u_long)m, (char *)&mfc, sizeof mfc);
 
 			if (!banner_printed) {
-				printf("\nIPv4 Multicast Forwarding Cache\n"
+				printf("\nIPv4 Multicast Forwarding Table\n"
 				       " Origin          Group            "
 				       " Packets In-Vif  Out-Vifs:Ttls\n");
 				banner_printed = 1;
@@ -167,6 +163,7 @@
 				
 				bwm = mfc.mfc_bw_meter;
 				while (bwm) {
+				    /* XXX KVM */
 				    kread((u_long)bwm, (char *)&bw_meter,
 						sizeof bw_meter);
 				    print_bw_meter(&bw_meter,
@@ -183,7 +180,7 @@
 		}
 	}
 	if (!banner_printed)
-		printf("\nMulticast Routing Table is empty\n");
+		printf("\nIPv4 Multicast Forwarding Table is empty\n");
 
 	printf("\n");
 	numeric_addr = saved_numeric_addr;
@@ -209,16 +206,16 @@
 
 	/* The measured values */
 	if (bw_meter->bm_flags & BW_METER_UNIT_PACKETS)
-		sprintf(s1, "%ju", bw_meter->bm_measured.b_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", bw_meter->bm_measured.b_bytes);
+		sprintf(s2, "%ju", (uintmax_t)bw_meter->bm_measured.b_bytes);
 	else
 		sprintf(s2, "?");
 	sprintf(s0, "%lu.%lu|%s|%s",
-		bw_meter->bm_start_time.tv_sec,
-		bw_meter->bm_start_time.tv_usec,
+		(u_long)bw_meter->bm_start_time.tv_sec,
+		(u_long)bw_meter->bm_start_time.tv_usec,
 		s1, s2);
 	printf("  %-30s", s0);
 
@@ -232,16 +229,16 @@
 
 	/* The threshold values */
 	if (bw_meter->bm_flags & BW_METER_UNIT_PACKETS)
-		sprintf(s1, "%ju", bw_meter->bm_threshold.b_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", bw_meter->bm_threshold.b_bytes);
+		sprintf(s2, "%ju", (uintmax_t)bw_meter->bm_threshold.b_bytes);
 	else
 		sprintf(s2, "?");
 	sprintf(s0, "%lu.%lu|%s|%s",
-		bw_meter->bm_threshold.b_time.tv_sec,
-		bw_meter->bm_threshold.b_time.tv_usec,
+		(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);
 
@@ -250,11 +247,15 @@
 		 &bw_meter->bm_threshold.b_time, &end);
 	if (timercmp(&now, &end, <=)) {
 		timersub(&end, &now, &delta);
-		sprintf(s3, "%lu.%lu", delta.tv_sec, delta.tv_usec);
+		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", delta.tv_sec, delta.tv_usec);
+		sprintf(s3, "-%lu.%lu",
+			(u_long)delta.tv_sec,
+			(u_long)delta.tv_usec);
 	}
 	printf(" %s", s3);
 
@@ -267,17 +268,15 @@
 	struct mrtstat mrtstat;
 	size_t len = sizeof mrtstat;
 
-	if (sysctlbyname("net.inet.ip.mrtstat", &mrtstat, &len,
-				NULL, 0) < 0) {
-		warn("sysctl: net.inet.ip.mrtstat");
-		/* Compatability with older kernels - candidate for removal */
-		if (mstaddr == 0) {
-			printf("No IPv4 multicast routing compiled into this system.\n");
+	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) \
@@ -287,7 +286,7 @@
 
 	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 mrouted\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");


More information about the Midnightbsd-cvs mailing list