summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKelly Yancey <kbyanc@FreeBSD.org>2005-12-28 20:36:55 +0000
committerKelly Yancey <kbyanc@FreeBSD.org>2005-12-28 20:36:55 +0000
commit100b98db7576b0ca1bbc465795480b0202014f4b (patch)
tree2ab5b6014aab6dcec0f6fad9abd7981ca2b4acb9
parent5108cc565a0265d2c6fb4c5425bfead411546955 (diff)
Notes
-rw-r--r--usr.bin/netstat/Makefile3
-rw-r--r--usr.bin/netstat/ipsec.c364
-rw-r--r--usr.bin/netstat/main.c29
-rw-r--r--usr.bin/netstat/netstat.h6
-rw-r--r--usr.bin/netstat/pfkey.c184
5 files changed, 489 insertions, 97 deletions
diff --git a/usr.bin/netstat/Makefile b/usr.bin/netstat/Makefile
index 322872d2651b..b2c32dc90d5b 100644
--- a/usr.bin/netstat/Makefile
+++ b/usr.bin/netstat/Makefile
@@ -3,12 +3,13 @@
PROG= netstat
SRCS= if.c inet.c inet6.c main.c mbuf.c mcast.c mroute.c route.c \
- unix.c atalk.c netgraph.c mroute6.c ipsec.c bpf.c
+ unix.c atalk.c netgraph.c mroute6.c ipsec.c bpf.c pfkey.c
WARNS?= 2
NO_WERROR=
CFLAGS+=-DIPSEC
+CFLAGS+=-DFAST_IPSEC
.if !defined(NO_INET6)
CFLAGS+=-DINET6
.endif
diff --git a/usr.bin/netstat/ipsec.c b/usr.bin/netstat/ipsec.c
index c99d27a2e988..c7135c4192c7 100644
--- a/usr.bin/netstat/ipsec.c
+++ b/usr.bin/netstat/ipsec.c
@@ -1,7 +1,33 @@
-/* $NetBSD: inet.c,v 1.35.2.1 1999/04/29 14:57:08 perry Exp $ */
+/* $FreeBSD$ */
/* $KAME: ipsec.c,v 1.33 2003/07/25 09:54:32 itojun Exp $ */
/*
+ * Copyright (c) 2005 NTT Multimedia Communications Laboratories, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
* Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
* All rights reserved.
*
@@ -78,9 +104,15 @@ __FBSDID("$FreeBSD$");
#include <netinet/in.h>
-#ifdef IPSEC
+#if defined(IPSEC) && !defined(FAST_IPSEC)
#include <netinet6/ipsec.h>
-#include <netkey/keysock.h>
+#endif
+
+#ifdef FAST_IPSEC
+#include <netipsec/ipsec.h>
+#include <netipsec/ah_var.h>
+#include <netipsec/esp_var.h>
+#include <netipsec/ipcomp_var.h>
#endif
#include <stdio.h>
@@ -88,7 +120,7 @@ __FBSDID("$FreeBSD$");
#include <unistd.h>
#include "netstat.h"
-#ifdef IPSEC
+#ifdef IPSEC
struct val2str {
int val;
const char *str;
@@ -143,20 +175,10 @@ static struct val2str ipsec_compnames[] = {
{ -1, NULL },
};
-static const char *pfkey_msgtypenames[] = {
- "reserved", "getspi", "update", "add", "delete",
- "get", "acquire", "register", "expire", "flush",
- "dump", "x_promisc", "x_pchange", "x_spdupdate", "x_spdadd",
- "x_spddelete", "x_spdget", "x_spdacquire", "x_spddump", "x_spdflush",
- "x_spdsetidx", "x_spdexpire", "x_spddelete2"
-};
+static void ipsec_hist(const u_quad_t *hist, size_t histmax,
+ const struct val2str *name, const char *title);
+static void print_ipsecstats(const struct ipsecstat *ipsecstat);
-static struct ipsecstat ipsecstat;
-
-static void print_ipsecstats (void);
-static const char *pfkey_msgtype_names (int);
-static void ipsec_hist (const u_quad_t *, size_t, const struct val2str *,
- const char *);
/*
* Dump IPSEC statistics structure.
@@ -191,12 +213,12 @@ ipsec_hist(const u_quad_t *hist, size_t histmax, const struct val2str *name,
}
static void
-print_ipsecstats(void)
+print_ipsecstats(const struct ipsecstat *ipsecstat)
{
-#define p(f, m) if (ipsecstat.f || sflag <= 1) \
- printf(m, (unsigned long long)ipsecstat.f, plural(ipsecstat.f))
-#define pes(f, m) if (ipsecstat.f || sflag <= 1) \
- printf(m, (unsigned long long)ipsecstat.f, plurales(ipsecstat.f))
+#define p(f, m) if (ipsecstat->f || sflag <= 1) \
+ printf(m, (unsigned long long)ipsecstat->f, plural(ipsecstat->f))
+#define pes(f, m) if (ipsecstat->f || sflag <= 1) \
+ printf(m, (unsigned long long)ipsecstat->f, plurales(ipsecstat->f))
#define hist(f, n, t) \
ipsec_hist((f), sizeof(f)/sizeof(f[0]), (n), (t));
@@ -211,9 +233,9 @@ print_ipsecstats(void)
p(in_espreplay, "\t%llu inbound packet%s failed on ESP replay check\n");
p(in_ahauthsucc, "\t%llu inbound packet%s considered authentic\n");
p(in_ahauthfail, "\t%llu inbound packet%s failed on authentication\n");
- hist(ipsecstat.in_ahhist, ipsec_ahnames, "AH input");
- hist(ipsecstat.in_esphist, ipsec_espnames, "ESP input");
- hist(ipsecstat.in_comphist, ipsec_compnames, "IPComp input");
+ hist(ipsecstat->in_ahhist, ipsec_ahnames, "AH input");
+ hist(ipsecstat->in_esphist, ipsec_espnames, "ESP input");
+ hist(ipsecstat->in_comphist, ipsec_compnames, "IPComp input");
p(out_success, "\t%llu outbound packet%s processed successfully\n");
p(out_polvio, "\t%llu outbound packet%s violated process security "
@@ -222,9 +244,9 @@ print_ipsecstats(void)
p(out_inval, "\t%llu invalid outbound packet%s\n");
p(out_nomem, "\t%llu outbound packet%s failed due to insufficient memory\n");
p(out_noroute, "\t%llu outbound packet%s with no route\n");
- hist(ipsecstat.out_ahhist, ipsec_ahnames, "AH output");
- hist(ipsecstat.out_esphist, ipsec_espnames, "ESP output");
- hist(ipsecstat.out_comphist, ipsec_compnames, "IPComp output");
+ hist(ipsecstat->out_ahhist, ipsec_ahnames, "AH output");
+ hist(ipsecstat->out_esphist, ipsec_espnames, "ESP output");
+ hist(ipsecstat->out_comphist, ipsec_compnames, "IPComp output");
p(spdcachelookup, "\t%llu SPD cache lookup%s\n");
pes(spdcachemiss, "\t%llu SPD cache miss%s\n");
#undef p
@@ -233,90 +255,240 @@ print_ipsecstats(void)
}
void
-ipsec_stats(u_long off __unused, const char *name, int af1 __unused)
+ipsec_stats(u_long off, const char *name, int af1 __unused)
{
+ struct ipsecstat ipsecstat;
+
if (off == 0)
return;
printf ("%s:\n", name);
- kread(off, (char *)&ipsecstat, sizeof (ipsecstat));
+ kread(off, (char *)&ipsecstat, sizeof(ipsecstat));
- print_ipsecstats();
+ print_ipsecstats(&ipsecstat);
}
-static const char *
-pfkey_msgtype_names(int x)
-{
- const int max =
- sizeof(pfkey_msgtypenames)/sizeof(pfkey_msgtypenames[0]);
- static char buf[20];
-
- if (x < max && pfkey_msgtypenames[x])
- return pfkey_msgtypenames[x];
- snprintf(buf, sizeof(buf), "#%d", x);
- return buf;
-}
-void
-pfkey_stats(u_long off __unused, const char *name, int af1 __unused)
+#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);
+
+/*
+ * Dump IPSEC statistics structure.
+ */
+static void
+ipsec_hist_new(const u_int32_t *hist, size_t histmax,
+ const struct val2str *name, const char *title)
{
- struct pfkeystat pfkeystat;
- unsigned first, type;
+ int first;
+ size_t proto;
+ const struct val2str *p;
- if (off == 0)
- return;
- printf ("%s:\n", name);
- kread(off, (char *)&pfkeystat, sizeof(pfkeystat));
-
-#define p(f, m) if (pfkeystat.f || sflag <= 1) \
- printf(m, (unsigned long long)pfkeystat.f, plural(pfkeystat.f))
-
- /* userland -> kernel */
- p(out_total, "\t%llu request%s sent from userland\n");
- p(out_bytes, "\t%llu byte%s sent from userland\n");
- for (first = 1, type = 0;
- type < sizeof(pfkeystat.out_msgtype)/sizeof(pfkeystat.out_msgtype[0]);
- type++) {
- if (pfkeystat.out_msgtype[type] <= 0)
+ first = 1;
+ for (proto = 0; proto < histmax; proto++) {
+ if (hist[proto] <= 0)
continue;
if (first) {
- printf("\thistogram by message type:\n");
+ printf("\t%s histogram:\n", title);
first = 0;
}
- printf("\t\t%s: %llu\n", pfkey_msgtype_names(type),
- (unsigned long long)pfkeystat.out_msgtype[type]);
- }
- p(out_invlen, "\t%llu message%s with invalid length field\n");
- p(out_invver, "\t%llu message%s with invalid version field\n");
- p(out_invmsgtype, "\t%llu message%s with invalid message type field\n");
- p(out_tooshort, "\t%llu message%s too short\n");
- p(out_nomem, "\t%llu message%s with memory allocation failure\n");
- p(out_dupext, "\t%llu message%s with duplicate extension\n");
- p(out_invexttype, "\t%llu message%s with invalid extension type\n");
- p(out_invsatype, "\t%llu message%s with invalid sa type\n");
- p(out_invaddr, "\t%llu message%s with invalid address extension\n");
-
- /* kernel -> userland */
- p(in_total, "\t%llu request%s sent to userland\n");
- p(in_bytes, "\t%llu byte%s sent to userland\n");
- for (first = 1, type = 0;
- type < sizeof(pfkeystat.in_msgtype)/sizeof(pfkeystat.in_msgtype[0]);
- type++) {
- if (pfkeystat.in_msgtype[type] <= 0)
- continue;
- if (first) {
- printf("\thistogram by message type:\n");
- first = 0;
+ for (p = name; p && p->str; p++) {
+ if (p->val == (int)proto)
+ break;
+ }
+ if (p && p->str) {
+ printf("\t\t%s: %u\n", p->str, hist[proto]);
+ } else {
+ printf("\t\t#%lu: %u\n", (unsigned long)proto,
+ hist[proto]);
}
- printf("\t\t%s: %llu\n", pfkey_msgtype_names(type),
- (unsigned long long)pfkeystat.in_msgtype[type]);
}
- p(in_msgtarget[KEY_SENDUP_ONE],
- "\t%llu message%s toward single socket\n");
- p(in_msgtarget[KEY_SENDUP_ALL],
- "\t%llu message%s toward all sockets\n");
- p(in_msgtarget[KEY_SENDUP_REGISTERED],
- "\t%llu message%s toward registered sockets\n");
- p(in_nomem, "\t%llu message%s with memory allocation failure\n");
+}
+
+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) \
+ printf("\t%u" m, (unsigned int)ahstat->f, plural(ahstat->f))
+#define p64(f, m) if (ahstat->f || sflag <= 1) \
+ printf("\t%llu" m, (unsigned long long)ahstat->f, plural(ahstat->f))
+#define hist(f, n, t) \
+ ipsec_hist_new((f), sizeof(f)/sizeof(f[0]), (n), (t));
+
+ p32(ahs_hdrops, " packet%s shorter than header shows\n");
+ p32(ahs_nopf, " packet%s dropped; protocol family not supported\n");
+ p32(ahs_notdb, " packet%s dropped; no TDB\n");
+ p32(ahs_badkcr, " packet%s dropped; bad KCR\n");
+ p32(ahs_qfull, " packet%s dropped; queue full\n");
+ p32(ahs_noxform, " packet%s dropped; no transform\n");
+ p32(ahs_wrap, " replay counter wrap%s\n");
+ p32(ahs_badauth, " packet%s dropped; bad authentication detected\n");
+ p32(ahs_badauthl, " packet%s dropped; bad authentication length\n");
+ p32(ahs_replay, " possible replay packet%s detected\n");
+ p32(ahs_input, " packet%s in\n");
+ p32(ahs_output, " packet%s out\n");
+ p32(ahs_invalid, " packet%s dropped; invalid TDB\n");
+ p64(ahs_ibytes, " byte%s in\n");
+ p64(ahs_obytes, " byte%s out\n");
+ p32(ahs_toobig, " packet%s dropped; larger than IP_MAXPACKET\n");
+ p32(ahs_pdrops, " packet%s blocked due to policy\n");
+ p32(ahs_crypto, " crypto processing failure%s\n");
+ p32(ahs_tunnel, " tunnel sanity check failure%s\n");
+ hist(ahstat->ahs_hist, ipsec_ahnames, "AH output");
+
+#undef p32
+#undef p64
+#undef hist
+}
+
+void
+ah_stats(u_long off, const char *name, int af __unused)
+{
+ struct ahstat ahstat;
+
+ if (off == 0)
+ return;
+ printf ("%s:\n", name);
+ kread(off, (char *)&ahstat, sizeof(ahstat));
+
+ print_ahstats(&ahstat);
+}
+
+static void
+print_espstats(const struct espstat *espstat)
+{
+#define p32(f, m) if (espstat->f || sflag <= 1) \
+ printf("\t%u" m, (unsigned int)espstat->f, plural(espstat->f))
+#define p64(f, m) if (espstat->f || sflag <= 1) \
+ printf("\t%llu" m, (unsigned long long)espstat->f, plural(espstat->f))
+#define hist(f, n, t) \
+ ipsec_hist_new((f), sizeof(f)/sizeof(f[0]), (n), (t));
+
+ p32(esps_hdrops, " packet%s shorter than header shows\n");
+ p32(esps_nopf, " packet%s dropped; protocol family not supported\n");
+ p32(esps_notdb, " packet%s dropped; no TDB\n");
+ p32(esps_badkcr, " packet%s dropped; bad KCR\n");
+ p32(esps_qfull, " packet%s dropped; queue full\n");
+ p32(esps_noxform, " packet%s dropped; no transform\n");
+ p32(esps_badilen, " packet%s dropped; bad ilen\n");
+ p32(esps_wrap, " replay counter wrap%s\n");
+ p32(esps_badenc, " packet%s dropped; bad encryption detected\n");
+ p32(esps_badauth, " packet%s dropped; bad authentication detected\n");
+ p32(esps_replay, " possible replay packet%s detected\n");
+ p32(esps_input, " packet%s in\n");
+ p32(esps_output, " packet%s out\n");
+ p32(esps_invalid, " packet%s dropped; invalid TDB\n");
+ p64(esps_ibytes, " byte%s in\n");
+ p64(esps_obytes, " byte%s out\n");
+ p32(esps_toobig, " packet%s dropped; larger than IP_MAXPACKET\n");
+ p32(esps_pdrops, " packet%s blocked due to policy\n");
+ p32(esps_crypto, " crypto processing failure%s\n");
+ p32(esps_tunnel, " tunnel sanity check failure%s\n");
+ hist(espstat->esps_hist, ipsec_espnames, "ESP output");
+
+#undef p32
+#undef p64
+#undef hist
+}
+
+void
+esp_stats(u_long off, const char *name, int af __unused)
+{
+ struct espstat espstat;
+
+ if (off == 0)
+ return;
+ printf ("%s:\n", name);
+ kread(off, (char *)&espstat, sizeof(espstat));
+
+ print_espstats(&espstat);
+}
+
+static void
+print_ipcompstats(const struct ipcompstat *ipcompstat)
+{
+#define p32(f, m) if (ipcompstat->f || sflag <= 1) \
+ printf("\t%u" m, (unsigned int)ipcompstat->f, plural(ipcompstat->f))
+#define p64(f, m) if (ipcompstat->f || sflag <= 1) \
+ printf("\t%llu" m, (unsigned long long)ipcompstat->f, plural(ipcompstat->f))
+#define hist(f, n, t) \
+ ipsec_hist_new((f), sizeof(f)/sizeof(f[0]), (n), (t));
+
+ p32(ipcomps_hdrops, " packet%s shorter than header shows\n");
+ p32(ipcomps_nopf, " packet%s dropped; protocol family not supported\n");
+ p32(ipcomps_notdb, " packet%s dropped; no TDB\n");
+ p32(ipcomps_badkcr, " packet%s dropped; bad KCR\n");
+ p32(ipcomps_qfull, " packet%s dropped; queue full\n");
+ p32(ipcomps_noxform, " packet%s dropped; no transform\n");
+ p32(ipcomps_wrap, " replay counter wrap%s\n");
+ p32(ipcomps_input, " packet%s in\n");
+ p32(ipcomps_output, " packet%s out\n");
+ p32(ipcomps_invalid, " packet%s dropped; invalid TDB\n");
+ p64(ipcomps_ibytes, " byte%s in\n");
+ p64(ipcomps_obytes, " byte%s out\n");
+ p32(ipcomps_toobig, " packet%s dropped; larger than IP_MAXPACKET\n");
+ p32(ipcomps_pdrops, " packet%s blocked due to policy\n");
+ p32(ipcomps_crypto, " crypto processing failure%s\n");
+ hist(ipcompstat->ipcomps_hist, ipsec_compnames, "COMP output");
+
+#undef p32
+#undef p64
+#undef hist
+}
+
+void
+ipcomp_stats(u_long off, const char *name, int af __unused)
+{
+ struct ipcompstat ipcompstat;
+
+ if (off == 0)
+ return;
+ printf ("%s:\n", name);
+ kread(off, (char *)&ipcompstat, sizeof(ipcompstat));
+
+ print_ipcompstats(&ipcompstat);
+}
+
+#endif /* FAST_IPSEC */
#endif /*IPSEC*/
diff --git a/usr.bin/netstat/main.c b/usr.bin/netstat/main.c
index 4c89a941ace6..9861d6e6a92c 100644
--- a/usr.bin/netstat/main.c
+++ b/usr.bin/netstat/main.c
@@ -140,6 +140,14 @@ static struct nlist nl[] = {
{ "_carpstats" },
#define N_PFSYNCSTAT 34
{ "_pfsyncstats" },
+#define N_FAST_IPSECSTAT 35
+ { "_newipsecstat" },
+#define N_AHSTAT 36
+ { "_ahstat" },
+#define N_ESPSTAT 37
+ { "_espstat" },
+#define N_IPCOMPSTAT 38
+ { "_ipcompstat" },
{ "" },
};
@@ -170,6 +178,16 @@ struct protox {
#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, protopr,
pim_stats, NULL, "pim", IPPROTO_PIM },
@@ -504,6 +522,17 @@ main(int argc, char *argv[])
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);
}
diff --git a/usr.bin/netstat/netstat.h b/usr.bin/netstat/netstat.h
index 3d3e745c52d1..1eb6288be8fc 100644
--- a/usr.bin/netstat/netstat.h
+++ b/usr.bin/netstat/netstat.h
@@ -76,6 +76,12 @@ 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);
+#endif
#endif
#ifdef INET6
diff --git a/usr.bin/netstat/pfkey.c b/usr.bin/netstat/pfkey.c
new file mode 100644
index 000000000000..014e3019db29
--- /dev/null
+++ b/usr.bin/netstat/pfkey.c
@@ -0,0 +1,184 @@
+/* $FreeBSD$ */
+/* $NetBSD: inet.c,v 1.35.2.1 1999/04/29 14:57:08 perry Exp $ */
+/* $KAME: ipsec.c,v 1.25 2001/03/12 09:04:39 itojun Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1983, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+/*
+static char sccsid[] = "@(#)inet.c 8.5 (Berkeley) 5/24/95";
+*/
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+
+#if defined(IPSEC) && !defined(FAST_IPSEC)
+#include <netkey/keysock.h>
+#endif
+
+#ifdef FAST_IPSEC
+#include <netipsec/keysock.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include "netstat.h"
+
+#ifdef IPSEC
+
+static const char *pfkey_msgtypenames[] = {
+ "reserved", "getspi", "update", "add", "delete",
+ "get", "acquire", "register", "expire", "flush",
+ "dump", "x_promisc", "x_pchange", "x_spdupdate", "x_spdadd",
+ "x_spddelete", "x_spdget", "x_spdacquire", "x_spddump", "x_spdflush",
+ "x_spdsetidx", "x_spdexpire", "x_spddelete2"
+};
+
+static const char *pfkey_msgtype_names (int);
+
+
+static const char *
+pfkey_msgtype_names(int x)
+{
+ const int max =
+ sizeof(pfkey_msgtypenames)/sizeof(pfkey_msgtypenames[0]);
+ static char buf[20];
+
+ if (x < max && pfkey_msgtypenames[x])
+ return pfkey_msgtypenames[x];
+ snprintf(buf, sizeof(buf), "#%d", x);
+ return buf;
+}
+
+void
+pfkey_stats(u_long off, const char *name, int af __unused)
+{
+ struct pfkeystat pfkeystat;
+ unsigned first, type;
+
+ if (off == 0)
+ return;
+ printf ("%s:\n", name);
+ kread(off, (char *)&pfkeystat, sizeof(pfkeystat));
+
+#define p(f, m) if (pfkeystat.f || sflag <= 1) \
+ printf(m, (unsigned long long)pfkeystat.f, plural(pfkeystat.f))
+
+ /* userland -> kernel */
+ p(out_total, "\t%llu request%s sent from userland\n");
+ p(out_bytes, "\t%llu byte%s sent from userland\n");
+ for (first = 1, type = 0;
+ type < sizeof(pfkeystat.out_msgtype)/sizeof(pfkeystat.out_msgtype[0]);
+ type++) {
+ if (pfkeystat.out_msgtype[type] <= 0)
+ continue;
+ if (first) {
+ printf("\thistogram by message type:\n");
+ first = 0;
+ }
+ printf("\t\t%s: %llu\n", pfkey_msgtype_names(type),
+ (unsigned long long)pfkeystat.out_msgtype[type]);
+ }
+ p(out_invlen, "\t%llu message%s with invalid length field\n");
+ p(out_invver, "\t%llu message%s with invalid version field\n");
+ p(out_invmsgtype, "\t%llu message%s with invalid message type field\n");
+ p(out_tooshort, "\t%llu message%s too short\n");
+ p(out_nomem, "\t%llu message%s with memory allocation failure\n");
+ p(out_dupext, "\t%llu message%s with duplicate extension\n");
+ p(out_invexttype, "\t%llu message%s with invalid extension type\n");
+ p(out_invsatype, "\t%llu message%s with invalid sa type\n");
+ p(out_invaddr, "\t%llu message%s with invalid address extension\n");
+
+ /* kernel -> userland */
+ p(in_total, "\t%llu request%s sent to userland\n");
+ p(in_bytes, "\t%llu byte%s sent to userland\n");
+ for (first = 1, type = 0;
+ type < sizeof(pfkeystat.in_msgtype)/sizeof(pfkeystat.in_msgtype[0]);
+ type++) {
+ if (pfkeystat.in_msgtype[type] <= 0)
+ continue;
+ if (first) {
+ printf("\thistogram by message type:\n");
+ first = 0;
+ }
+ printf("\t\t%s: %llu\n", pfkey_msgtype_names(type),
+ (unsigned long long)pfkeystat.in_msgtype[type]);
+ }
+ p(in_msgtarget[KEY_SENDUP_ONE],
+ "\t%llu message%s toward single socket\n");
+ p(in_msgtarget[KEY_SENDUP_ALL],
+ "\t%llu message%s toward all sockets\n");
+ p(in_msgtarget[KEY_SENDUP_REGISTERED],
+ "\t%llu message%s toward registered sockets\n");
+ p(in_nomem, "\t%llu message%s with memory allocation failure\n");
+#undef p
+}
+#endif /* IPSEC */