Index: stable/10/usr.bin/netstat/ipsec.c =================================================================== --- stable/10/usr.bin/netstat/ipsec.c (revision 293343) +++ stable/10/usr.bin/netstat/ipsec.c (revision 293344) @@ -1,388 +1,395 @@ /* $KAME: ipsec.c,v 1.33 2003/07/25 09:54:32 itojun Exp $ */ /*- * Copyright (c) 2005 NTT Multimedia Communications Laboratories, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /*- * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /*- * Copyright (c) 1983, 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char sccsid[] = "@(#)inet.c 8.5 (Berkeley) 5/24/95"; #endif /* not lint */ #endif #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #ifdef IPSEC #include #include #include #include #endif #include #include #include #include #include "netstat.h" #ifdef IPSEC struct val2str { int val; const char *str; }; static struct val2str ipsec_ahnames[] = { { SADB_AALG_NONE, "none", }, { SADB_AALG_MD5HMAC, "hmac-md5", }, { SADB_AALG_SHA1HMAC, "hmac-sha1", }, { SADB_X_AALG_MD5, "md5", }, { SADB_X_AALG_SHA, "sha", }, { SADB_X_AALG_NULL, "null", }, #ifdef SADB_X_AALG_SHA2_256 { SADB_X_AALG_SHA2_256, "hmac-sha2-256", }, #endif #ifdef SADB_X_AALG_SHA2_384 { SADB_X_AALG_SHA2_384, "hmac-sha2-384", }, #endif #ifdef SADB_X_AALG_SHA2_512 { SADB_X_AALG_SHA2_512, "hmac-sha2-512", }, #endif #ifdef SADB_X_AALG_RIPEMD160HMAC { SADB_X_AALG_RIPEMD160HMAC, "hmac-ripemd160", }, #endif #ifdef SADB_X_AALG_AES_XCBC_MAC { SADB_X_AALG_AES_XCBC_MAC, "aes-xcbc-mac", }, #endif { -1, NULL }, }; static struct val2str ipsec_espnames[] = { { SADB_EALG_NONE, "none", }, { SADB_EALG_DESCBC, "des-cbc", }, { SADB_EALG_3DESCBC, "3des-cbc", }, { SADB_EALG_NULL, "null", }, { SADB_X_EALG_CAST128CBC, "cast128-cbc", }, { SADB_X_EALG_BLOWFISHCBC, "blowfish-cbc", }, #ifdef SADB_X_EALG_RIJNDAELCBC { SADB_X_EALG_RIJNDAELCBC, "rijndael-cbc", }, #endif #ifdef SADB_X_EALG_AESCTR { SADB_X_EALG_AESCTR, "aes-ctr", }, #endif { -1, NULL }, }; static struct val2str ipsec_compnames[] = { { SADB_X_CALG_NONE, "none", }, { SADB_X_CALG_OUI, "oui", }, { SADB_X_CALG_DEFLATE, "deflate", }, { SADB_X_CALG_LZS, "lzs", }, { -1, NULL }, }; static void print_ipsecstats(const struct ipsecstat *ipsecstat); static void print_ipsecstats(const struct ipsecstat *ipsecstat) { #define p(f, m) if (ipsecstat->f || sflag <= 1) \ printf(m, (uintmax_t)ipsecstat->f, plural(ipsecstat->f)) p(ips_in_polvio, "\t%ju inbound packet%s violated process " "security policy\n"); p(ips_in_nomem, "\t%ju inbound packet%s failed due to " "insufficient memory\n"); p(ips_in_inval, "\t%ju invalid inbound packet%s\n"); p(ips_out_polvio, "\t%ju outbound packet%s violated process " "security policy\n"); p(ips_out_nosa, "\t%ju outbound packet%s with no SA available\n"); p(ips_out_nomem, "\t%ju outbound packet%s failed due to " "insufficient memory\n"); p(ips_out_noroute, "\t%ju outbound packet%s with no route " "available\n"); p(ips_out_inval, "\t%ju invalid outbound packet%s\n"); p(ips_out_bundlesa, "\t%ju outbound packet%s with bundled SAs\n"); p(ips_mbcoalesced, "\t%ju mbuf%s coalesced during clone\n"); p(ips_clcoalesced, "\t%ju cluster%s coalesced during clone\n"); p(ips_clcopied, "\t%ju cluster%s copied during clone\n"); p(ips_mbinserted, "\t%ju mbuf%s inserted during makespace\n"); #undef p } void ipsec_stats(u_long off, const char *name, int af1 __unused, int proto __unused) { struct ipsecstat ipsecstat; - if (off == 0) - return; + if (strcmp(name, "ipsec6") == 0) { + if (fetch_stats("net.inet6.ipsec6.ipsecstats", off,&ipsecstat, + sizeof(ipsecstat), kread_counters) != 0) + return; + } else { + if (fetch_stats("net.inet.ipsec.ipsecstats", off, &ipsecstat, + sizeof(ipsecstat), kread_counters) != 0) + return; + } + printf ("%s:\n", name); - kread_counters(off, (char *)&ipsecstat, sizeof(ipsecstat)); print_ipsecstats(&ipsecstat); } static void ipsec_hist_new(const uint64_t *hist, size_t histmax, const struct val2str *name, const char *title); static void print_ahstats(const struct ahstat *ahstat); static void print_espstats(const struct espstat *espstat); static void print_ipcompstats(const struct ipcompstat *ipcompstat); /* * Dump IPSEC statistics structure. */ static void ipsec_hist_new(const uint64_t *hist, size_t histmax, const struct val2str *name, const char *title) { int first; size_t proto; const struct val2str *p; first = 1; for (proto = 0; proto < histmax; proto++) { if (hist[proto] <= 0) continue; if (first) { printf("\t%s histogram:\n", title); first = 0; } for (p = name; p && p->str; p++) { if (p->val == (int)proto) break; } if (p && p->str) { printf("\t\t%s: %ju\n", p->str, (uintmax_t)hist[proto]); } else { printf("\t\t#%lu: %ju\n", (unsigned long)proto, (uintmax_t)hist[proto]); } } } static void print_ahstats(const struct ahstat *ahstat) { #define p(f, m) if (ahstat->f || sflag <= 1) \ printf("\t%ju" m, (uintmax_t)ahstat->f, plural(ahstat->f)) #define hist(f, n, t) \ ipsec_hist_new((f), sizeof(f)/sizeof(f[0]), (n), (t)); p(ahs_hdrops, " packet%s shorter than header shows\n"); p(ahs_nopf, " packet%s dropped; protocol family not supported\n"); p(ahs_notdb, " packet%s dropped; no TDB\n"); p(ahs_badkcr, " packet%s dropped; bad KCR\n"); p(ahs_qfull, " packet%s dropped; queue full\n"); p(ahs_noxform, " packet%s dropped; no transform\n"); p(ahs_wrap, " replay counter wrap%s\n"); p(ahs_badauth, " packet%s dropped; bad authentication detected\n"); p(ahs_badauthl, " packet%s dropped; bad authentication length\n"); p(ahs_replay, " possible replay packet%s detected\n"); p(ahs_input, " packet%s in\n"); p(ahs_output, " packet%s out\n"); p(ahs_invalid, " packet%s dropped; invalid TDB\n"); p(ahs_ibytes, " byte%s in\n"); p(ahs_obytes, " byte%s out\n"); p(ahs_toobig, " packet%s dropped; larger than IP_MAXPACKET\n"); p(ahs_pdrops, " packet%s blocked due to policy\n"); p(ahs_crypto, " crypto processing failure%s\n"); p(ahs_tunnel, " tunnel sanity check failure%s\n"); hist(ahstat->ahs_hist, ipsec_ahnames, "AH output"); #undef p #undef hist } void ah_stats(u_long off, const char *name, int family __unused, int proto __unused) { struct ahstat ahstat; - if (off == 0) + if (fetch_stats("net.inet.ah.stats", off, &ahstat, + sizeof(ahstat), kread_counters) != 0) return; printf ("%s:\n", name); - kread_counters(off, (char *)&ahstat, sizeof(ahstat)); print_ahstats(&ahstat); } static void print_espstats(const struct espstat *espstat) { #define p(f, m) if (espstat->f || sflag <= 1) \ printf("\t%ju" m, (uintmax_t)espstat->f, plural(espstat->f)) #define hist(f, n, t) \ ipsec_hist_new((f), sizeof(f)/sizeof(f[0]), (n), (t)); p(esps_hdrops, " packet%s shorter than header shows\n"); p(esps_nopf, " packet%s dropped; protocol family not supported\n"); p(esps_notdb, " packet%s dropped; no TDB\n"); p(esps_badkcr, " packet%s dropped; bad KCR\n"); p(esps_qfull, " packet%s dropped; queue full\n"); p(esps_noxform, " packet%s dropped; no transform\n"); p(esps_badilen, " packet%s dropped; bad ilen\n"); p(esps_wrap, " replay counter wrap%s\n"); p(esps_badenc, " packet%s dropped; bad encryption detected\n"); p(esps_badauth, " packet%s dropped; bad authentication detected\n"); p(esps_replay, " possible replay packet%s detected\n"); p(esps_input, " packet%s in\n"); p(esps_output, " packet%s out\n"); p(esps_invalid, " packet%s dropped; invalid TDB\n"); p(esps_ibytes, " byte%s in\n"); p(esps_obytes, " byte%s out\n"); p(esps_toobig, " packet%s dropped; larger than IP_MAXPACKET\n"); p(esps_pdrops, " packet%s blocked due to policy\n"); p(esps_crypto, " crypto processing failure%s\n"); p(esps_tunnel, " tunnel sanity check failure%s\n"); hist(espstat->esps_hist, ipsec_espnames, "ESP output"); #undef p #undef hist } void esp_stats(u_long off, const char *name, int family __unused, int proto __unused) { struct espstat espstat; - if (off == 0) + if (fetch_stats("net.inet.esp.stats", off, &espstat, + sizeof(espstat), kread_counters) != 0) return; printf ("%s:\n", name); - kread_counters(off, (char *)&espstat, sizeof(espstat)); print_espstats(&espstat); } static void print_ipcompstats(const struct ipcompstat *ipcompstat) { #define p(f, m) if (ipcompstat->f || sflag <= 1) \ printf("\t%ju" m, (uintmax_t)ipcompstat->f, plural(ipcompstat->f)) #define hist(f, n, t) \ ipsec_hist_new((f), sizeof(f)/sizeof(f[0]), (n), (t)); p(ipcomps_hdrops, " packet%s shorter than header shows\n"); p(ipcomps_nopf, " packet%s dropped; protocol family not supported\n"); p(ipcomps_notdb, " packet%s dropped; no TDB\n"); p(ipcomps_badkcr, " packet%s dropped; bad KCR\n"); p(ipcomps_qfull, " packet%s dropped; queue full\n"); p(ipcomps_noxform, " packet%s dropped; no transform\n"); p(ipcomps_wrap, " replay counter wrap%s\n"); p(ipcomps_input, " packet%s in\n"); p(ipcomps_output, " packet%s out\n"); p(ipcomps_invalid, " packet%s dropped; invalid TDB\n"); p(ipcomps_ibytes, " byte%s in\n"); p(ipcomps_obytes, " byte%s out\n"); p(ipcomps_toobig, " packet%s dropped; larger than IP_MAXPACKET\n"); p(ipcomps_pdrops, " packet%s blocked due to policy\n"); p(ipcomps_crypto, " crypto processing failure%s\n"); hist(ipcompstat->ipcomps_hist, ipsec_compnames, "COMP output"); p(ipcomps_threshold, " packet%s sent uncompressed; size < compr. algo. threshold\n"); p(ipcomps_uncompr, " packet%s sent uncompressed; compression was useless\n"); #undef p #undef hist } void ipcomp_stats(u_long off, const char *name, int family __unused, int proto __unused) { struct ipcompstat ipcompstat; - if (off == 0) + if (fetch_stats("net.inet.ipcomp.stats", off, &ipcompstat, + sizeof(ipcompstat), kread_counters) != 0) return; printf ("%s:\n", name); - kread_counters(off, (char *)&ipcompstat, sizeof(ipcompstat)); print_ipcompstats(&ipcompstat); } #endif /*IPSEC*/ Index: stable/10/usr.bin/netstat/main.c =================================================================== --- stable/10/usr.bin/netstat/main.c (revision 293343) +++ stable/10/usr.bin/netstat/main.c (revision 293344) @@ -1,924 +1,924 @@ /*- * Copyright (c) 1983, 1988, 1993 * Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint char const copyright[] = "@(#) Copyright (c) 1983, 1988, 1993\n\ Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #if 0 #ifndef lint static char sccsid[] = "@(#)main.c 8.4 (Berkeley) 3/1/94"; #endif /* not lint */ #endif #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #ifdef NETGRAPH #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include "netstat.h" static struct nlist nl[] = { #define N_IFNET 0 { .n_name = "_ifnet" }, /* XXXGL: can be deleted */ #define N_RTSTAT 1 { .n_name = "_rtstat" }, #define N_RTREE 2 { .n_name = "_rt_tables"}, #define N_MRTSTAT 3 { .n_name = "_mrtstat" }, #define N_MFCHASHTBL 4 { .n_name = "_mfchashtbl" }, #define N_VIFTABLE 5 { .n_name = "_viftable" }, #define N_IPX 6 { .n_name = "_ipxpcb_list"}, #define N_IPXSTAT 7 { .n_name = "_ipxstat"}, #define N_SPXSTAT 8 { .n_name = "_spx_istat"}, #define N_DDPSTAT 9 { .n_name = "_ddpstat"}, #define N_DDPCB 10 { .n_name = "_ddpcb"}, #define N_NGSOCKS 11 { .n_name = "_ngsocklist"}, #define N_IP6STAT 12 { .n_name = "_ip6stat" }, #define N_ICMP6STAT 13 { .n_name = "_icmp6stat" }, #define N_IPSECSTAT 14 { .n_name = "_ipsec4stat" }, #define N_IPSEC6STAT 15 { .n_name = "_ipsec6stat" }, #define N_PIM6STAT 16 { .n_name = "_pim6stat" }, #define N_MRT6STAT 17 { .n_name = "_mrt6stat" }, #define N_MF6CTABLE 18 { .n_name = "_mf6ctable" }, #define N_MIF6TABLE 19 { .n_name = "_mif6table" }, #define N_PFKEYSTAT 20 { .n_name = "_pfkeystat" }, #define N_RTTRASH 21 { .n_name = "_rttrash" }, #define N_CARPSTAT 22 { .n_name = "_carpstats" }, #define N_PFSYNCSTAT 23 { .n_name = "_pfsyncstats" }, #define N_AHSTAT 24 { .n_name = "_ahstat" }, #define N_ESPSTAT 25 { .n_name = "_espstat" }, #define N_IPCOMPSTAT 26 { .n_name = "_ipcompstat" }, #define N_TCPSTAT 27 { .n_name = "_tcpstat" }, #define N_UDPSTAT 28 { .n_name = "_udpstat" }, #define N_IPSTAT 29 { .n_name = "_ipstat" }, #define N_ICMPSTAT 30 { .n_name = "_icmpstat" }, #define N_IGMPSTAT 31 { .n_name = "_igmpstat" }, #define N_PIMSTAT 32 { .n_name = "_pimstat" }, #define N_TCBINFO 33 { .n_name = "_tcbinfo" }, #define N_UDBINFO 34 { .n_name = "_udbinfo" }, #define N_DIVCBINFO 35 { .n_name = "_divcbinfo" }, #define N_RIPCBINFO 36 { .n_name = "_ripcbinfo" }, #define N_UNP_COUNT 37 { .n_name = "_unp_count" }, #define N_UNP_GENCNT 38 { .n_name = "_unp_gencnt" }, #define N_UNP_DHEAD 39 { .n_name = "_unp_dhead" }, #define N_UNP_SHEAD 40 { .n_name = "_unp_shead" }, #define N_RIP6STAT 41 { .n_name = "_rip6stat" }, #define N_SCTPSTAT 42 { .n_name = "_sctpstat" }, #define N_MFCTABLESIZE 43 { .n_name = "_mfctablesize" }, #define N_ARPSTAT 44 { .n_name = "_arpstat" }, #define N_UNP_SPHEAD 45 { .n_name = "unp_sphead" }, #define N_SFSTAT 46 { .n_name = "_sfstat"}, { .n_name = NULL }, }; struct protox { int pr_index; /* index into nlist of cb head */ int pr_sindex; /* index into nlist of stat block */ u_char pr_wanted; /* 1 if wanted, 0 otherwise */ void (*pr_cblocks)(u_long, const char *, int, int); /* control blocks printing routine */ void (*pr_stats)(u_long, const char *, int, int); /* statistics printing routine */ void (*pr_istats)(char *); /* per/if statistics printing routine */ const char *pr_name; /* well-known name */ int pr_usesysctl; /* non-zero if we use sysctl, not kvm */ int pr_protocol; } protox[] = { { N_TCBINFO, N_TCPSTAT, 1, protopr, tcp_stats, NULL, "tcp", 1, IPPROTO_TCP }, { N_UDBINFO, N_UDPSTAT, 1, protopr, udp_stats, NULL, "udp", 1, IPPROTO_UDP }, #ifdef SCTP { -1, N_SCTPSTAT, 1, sctp_protopr, sctp_stats, NULL, "sctp", 1, IPPROTO_SCTP }, #endif #ifdef SDP { -1, -1, 1, protopr, NULL, NULL, "sdp", 1, IPPROTO_TCP }, #endif { N_DIVCBINFO, -1, 1, protopr, NULL, NULL, "divert", 1, IPPROTO_DIVERT }, { N_RIPCBINFO, N_IPSTAT, 1, protopr, ip_stats, NULL, "ip", 1, IPPROTO_RAW }, { N_RIPCBINFO, N_ICMPSTAT, 1, protopr, icmp_stats, NULL, "icmp", 1, IPPROTO_ICMP }, { N_RIPCBINFO, N_IGMPSTAT, 1, protopr, igmp_stats, NULL, "igmp", 1, IPPROTO_IGMP }, #ifdef IPSEC { -1, N_IPSECSTAT, 1, NULL, /* keep as compat */ - ipsec_stats, NULL, "ipsec", 0, 0}, + ipsec_stats, NULL, "ipsec", 1, 0}, { -1, N_AHSTAT, 1, NULL, - ah_stats, NULL, "ah", 0, 0}, + ah_stats, NULL, "ah", 1, 0}, { -1, N_ESPSTAT, 1, NULL, - esp_stats, NULL, "esp", 0, 0}, + esp_stats, NULL, "esp", 1, 0}, { -1, N_IPCOMPSTAT, 1, NULL, - ipcomp_stats, NULL, "ipcomp", 0, 0}, + ipcomp_stats, NULL, "ipcomp", 1, 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 }, #ifdef PF { -1, N_PFSYNCSTAT, 1, NULL, pfsync_stats, NULL, "pfsync", 1, 0 }, #endif { -1, N_ARPSTAT, 1, NULL, arp_stats, NULL, "arp", 1, 0 }, { -1, -1, 0, NULL, NULL, NULL, NULL, 0, 0 } }; #ifdef INET6 struct protox ip6protox[] = { { N_TCBINFO, N_TCPSTAT, 1, protopr, tcp_stats, NULL, "tcp", 1, IPPROTO_TCP }, { N_UDBINFO, N_UDPSTAT, 1, protopr, udp_stats, NULL, "udp", 1, IPPROTO_UDP }, { N_RIPCBINFO, N_IP6STAT, 1, protopr, ip6_stats, ip6_ifstats, "ip6", 1, IPPROTO_RAW }, { N_RIPCBINFO, N_ICMP6STAT, 1, protopr, icmp6_stats, icmp6_ifstats, "icmp6", 1, IPPROTO_ICMPV6 }, #ifdef SDP { -1, -1, 1, protopr, NULL, NULL, "sdp", 1, IPPROTO_TCP }, #endif #ifdef IPSEC { -1, N_IPSEC6STAT, 1, NULL, - ipsec_stats, NULL, "ipsec6", 0, 0 }, + ipsec_stats, NULL, "ipsec6", 1, 0 }, #endif #ifdef notyet { -1, N_PIM6STAT, 1, NULL, pim6_stats, NULL, "pim6", 1, 0 }, #endif { -1, N_RIP6STAT, 1, NULL, rip6_stats, NULL, "rip6", 1, 0 }, { -1, -1, 0, NULL, NULL, NULL, NULL, 0, 0 } }; #endif /*INET6*/ #ifdef IPSEC struct protox pfkeyprotox[] = { { -1, N_PFKEYSTAT, 1, NULL, pfkey_stats, NULL, "pfkey", 0, 0 }, { -1, -1, 0, NULL, NULL, NULL, NULL, 0, 0 } }; #endif struct protox atalkprotox[] = { { N_DDPCB, N_DDPSTAT, 1, atalkprotopr, ddp_stats, NULL, "ddp", 0, 0 }, { -1, -1, 0, NULL, NULL, NULL, NULL, 0, 0 } }; #ifdef NETGRAPH struct protox netgraphprotox[] = { { N_NGSOCKS, -1, 1, netgraphprotopr, NULL, NULL, "ctrl", 0, 0 }, { N_NGSOCKS, -1, 1, netgraphprotopr, NULL, NULL, "data", 0, 0 }, { -1, -1, 0, NULL, NULL, NULL, NULL, 0, 0 } }; #endif #ifdef IPX struct protox ipxprotox[] = { { N_IPX, N_IPXSTAT, 1, ipxprotopr, ipx_stats, NULL, "ipx", 0, 0 }, { N_IPX, N_SPXSTAT, 1, ipxprotopr, spx_stats, NULL, "spx", 0, 0 }, { -1, -1, 0, NULL, NULL, NULL, 0, 0, 0 } }; #endif struct protox *protoprotox[] = { protox, #ifdef INET6 ip6protox, #endif #ifdef IPSEC pfkeyprotox, #endif #ifdef IPX ipxprotox, #endif atalkprotox, NULL }; static void printproto(struct protox *, const char *); static void usage(void); static struct protox *name2protox(const char *); static struct protox *knownname(const char *); static kvm_t *kvmd; static char *nlistf = NULL, *memf = NULL; int Aflag; /* show addresses of protocol control block */ int aflag; /* show all sockets (including servers) */ int Bflag; /* show information about bpf consumers */ int bflag; /* show i/f total bytes in/out */ int dflag; /* show i/f dropped packets */ int gflag; /* show group (multicast) routing or stats */ int hflag; /* show counters in human readable format */ int iflag; /* show interfaces */ int Lflag; /* show size of listen queues */ int mflag; /* show memory stats */ int noutputs = 0; /* how much outputs before we exit */ int numeric_addr; /* show addresses numerically */ int numeric_port; /* show ports numerically */ static int pflag; /* show given protocol */ int Qflag; /* show netisr information */ int rflag; /* show routing tables (or routing stats) */ int Rflag; /* show flow / RSS statistics */ int sflag; /* show protocol statistics */ int Wflag; /* wide display */ int Tflag; /* TCP Information */ int xflag; /* extra information, includes all socket buffer info */ int zflag; /* zero stats */ int interval; /* repeat interval for i/f stats */ char *interface; /* desired i/f for stats, or NULL for all i/fs */ int unit; /* unit number for above */ int af; /* address family */ int live; /* true if we are examining a live system */ int main(int argc, char *argv[]) { struct protox *tp = NULL; /* for printing cblocks & stats */ int ch; int fib = -1; char *endptr; af = AF_UNSPEC; while ((ch = getopt(argc, argv, "46AaBbdF:f:ghI:iLlM:mN:np:Qq:RrSTsuWw:xz")) != -1) switch(ch) { case '4': #ifdef INET af = AF_INET; #else errx(1, "IPv4 support is not compiled in"); #endif break; case '6': #ifdef INET6 af = AF_INET6; #else errx(1, "IPv6 support is not compiled in"); #endif break; case 'A': Aflag = 1; break; case 'a': aflag = 1; break; case 'B': Bflag = 1; break; case 'b': bflag = 1; break; case 'd': dflag = 1; break; case 'F': fib = strtol(optarg, &endptr, 0); if (*endptr != '\0' || (fib == 0 && (errno == EINVAL || errno == ERANGE))) errx(1, "%s: invalid fib", optarg); break; case 'f': if (strcmp(optarg, "ipx") == 0) af = AF_IPX; else if (strcmp(optarg, "inet") == 0) af = AF_INET; #ifdef INET6 else if (strcmp(optarg, "inet6") == 0) af = AF_INET6; #endif #ifdef IPSEC else if (strcmp(optarg, "pfkey") == 0) af = PF_KEY; #endif else if (strcmp(optarg, "unix") == 0) af = AF_UNIX; else if (strcmp(optarg, "atalk") == 0) af = AF_APPLETALK; #ifdef NETGRAPH else if (strcmp(optarg, "ng") == 0 || strcmp(optarg, "netgraph") == 0) af = AF_NETGRAPH; #endif else if (strcmp(optarg, "link") == 0) af = AF_LINK; else { errx(1, "%s: unknown address family", optarg); } break; case 'g': gflag = 1; break; case 'h': hflag = 1; break; case 'I': { char *cp; iflag = 1; for (cp = interface = optarg; isalpha(*cp); cp++) continue; unit = atoi(cp); break; } case 'i': iflag = 1; break; case 'L': Lflag = 1; break; case 'M': memf = optarg; break; case 'm': mflag = 1; break; case 'N': nlistf = optarg; break; case 'n': numeric_addr = numeric_port = 1; break; case 'p': if ((tp = name2protox(optarg)) == NULL) { errx(1, "%s: unknown or uninstrumented protocol", optarg); } pflag = 1; break; case 'Q': Qflag = 1; break; case 'q': noutputs = atoi(optarg); if (noutputs != 0) noutputs++; break; case 'r': rflag = 1; break; case 'R': Rflag = 1; break; case 's': ++sflag; break; case 'S': numeric_addr = 1; break; case 'u': af = AF_UNIX; break; case 'W': case 'l': Wflag = 1; break; case 'w': interval = atoi(optarg); iflag = 1; break; case 'T': Tflag = 1; break; case 'x': xflag = 1; break; case 'z': zflag = 1; break; case '?': default: usage(); } argv += optind; argc -= optind; #define BACKWARD_COMPATIBILITY #ifdef BACKWARD_COMPATIBILITY if (*argv) { if (isdigit(**argv)) { interval = atoi(*argv); if (interval <= 0) usage(); ++argv; iflag = 1; } if (*argv) { nlistf = *argv; if (*++argv) memf = *argv; } } #endif /* * Discard setgid privileges if not the running kernel so that bad * guys can't print interesting stuff from kernel memory. */ live = (nlistf == NULL && memf == NULL); if (!live) setgid(getgid()); if (xflag && Tflag) errx(1, "-x and -T are incompatible, pick one."); if (Bflag) { if (!live) usage(); bpf_stats(interface); exit(0); } if (mflag) { if (!live) { if (kread(0, NULL, 0) == 0) mbpr(kvmd, nl[N_SFSTAT].n_value); } else mbpr(NULL, 0); exit(0); } if (Qflag) { if (!live) { if (kread(0, NULL, 0) == 0) netisr_stats(kvmd); } else netisr_stats(NULL); exit(0); } #if 0 /* * Keep file descriptors open to avoid overhead * of open/close on each call to get* routines. */ sethostent(1); setnetent(1); #else /* * This does not make sense any more with DNS being default over * the files. Doing a setXXXXent(1) causes a tcp connection to be * used for the queries, which is slower. */ #endif if (iflag && !sflag) { intpr(interval, NULL, af); exit(0); } if (rflag) { if (sflag) { rt_stats(); flowtable_stats(); } else routepr(fib, af); exit(0); } if (gflag) { if (sflag) { if (af == AF_INET || af == AF_UNSPEC) mrt_stats(); #ifdef INET6 if (af == AF_INET6 || af == AF_UNSPEC) mrt6_stats(); #endif } else { if (af == AF_INET || af == AF_UNSPEC) mroutepr(); #ifdef INET6 if (af == AF_INET6 || af == AF_UNSPEC) mroute6pr(); #endif } exit(0); } /* Load all necessary kvm symbols */ kresolve_list(nl); if (tp) { printproto(tp, tp->pr_name); exit(0); } if (af == AF_INET || af == AF_UNSPEC) for (tp = protox; tp->pr_name; tp++) printproto(tp, tp->pr_name); #ifdef INET6 if (af == AF_INET6 || af == AF_UNSPEC) for (tp = ip6protox; tp->pr_name; tp++) printproto(tp, tp->pr_name); #endif /*INET6*/ #ifdef IPSEC if (af == PF_KEY || af == AF_UNSPEC) for (tp = pfkeyprotox; tp->pr_name; tp++) printproto(tp, tp->pr_name); #endif /*IPSEC*/ #ifdef IPX if (af == AF_IPX || af == AF_UNSPEC) { for (tp = ipxprotox; tp->pr_name; tp++) printproto(tp, tp->pr_name); } #endif /* IPX */ if (af == AF_APPLETALK || af == AF_UNSPEC) for (tp = atalkprotox; tp->pr_name; tp++) printproto(tp, tp->pr_name); #ifdef NETGRAPH if (af == AF_NETGRAPH || af == AF_UNSPEC) for (tp = netgraphprotox; tp->pr_name; tp++) printproto(tp, tp->pr_name); #endif /* NETGRAPH */ if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag) unixpr(nl[N_UNP_COUNT].n_value, nl[N_UNP_GENCNT].n_value, nl[N_UNP_DHEAD].n_value, nl[N_UNP_SHEAD].n_value, nl[N_UNP_SPHEAD].n_value); exit(0); } int fetch_stats(const char *sysctlname, u_long off, void *stats, size_t len, int (*kreadfn)(u_long, void *, size_t)) { int error; if (live) { memset(stats, 0, len); if (zflag) error = sysctlbyname(sysctlname, NULL, NULL, stats, len); else error = sysctlbyname(sysctlname, stats, &len, NULL, 0); if (error == -1 && errno != ENOENT) warn("sysctl %s", sysctlname); } else { if (off == 0) return (1); error = kreadfn(off, stats, len); } return (error); } /* * Print out protocol statistics or control blocks (per sflag). * If the interface was not specifically requested, and the symbol * is not in the namelist, ignore this one. */ static void printproto(struct protox *tp, const char *name) { void (*pr)(u_long, const char *, int, int); u_long off; if (sflag) { if (iflag) { if (tp->pr_istats) intpr(interval, tp->pr_istats, af); else if (pflag) printf("%s: no per-interface stats routine\n", tp->pr_name); return; } else { pr = tp->pr_stats; if (!pr) { if (pflag) printf("%s: no stats routine\n", tp->pr_name); return; } if (tp->pr_usesysctl && live) off = 0; else if (tp->pr_sindex < 0) { if (pflag) printf( "%s: stats routine doesn't work on cores\n", tp->pr_name); return; } else off = nl[tp->pr_sindex].n_value; } } else { pr = tp->pr_cblocks; if (!pr) { if (pflag) printf("%s: no PCB routine\n", tp->pr_name); return; } if (tp->pr_usesysctl && live) off = 0; else if (tp->pr_index < 0) { if (pflag) printf( "%s: PCB routine doesn't work on cores\n", tp->pr_name); return; } else off = nl[tp->pr_index].n_value; } if (pr != NULL && (off || (live && tp->pr_usesysctl) || af != AF_UNSPEC)) (*pr)(off, name, af, tp->pr_protocol); } static int kvmd_init(void) { char errbuf[_POSIX2_LINE_MAX]; if (kvmd != NULL) return (0); kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf); setgid(getgid()); if (kvmd == NULL) { warnx("kvm not available: %s", errbuf); return (-1); } return (0); } /* * Resolve symbol list, return 0 on success. */ int kresolve_list(struct nlist *_nl) { if ((kvmd == NULL) && (kvmd_init() != 0)) return (-1); if (_nl[0].n_type != 0) return (0); if (kvm_nlist(kvmd, _nl) < 0) { if (nlistf) errx(1, "%s: kvm_nlist: %s", nlistf, kvm_geterr(kvmd)); else errx(1, "kvm_nlist: %s", kvm_geterr(kvmd)); } return (0); } /* * Read kernel memory, return 0 on success. */ int kread(u_long addr, void *buf, size_t size) { if (kvmd_init() < 0) return (-1); if (!buf) return (0); if (kvm_read(kvmd, addr, buf, size) != (ssize_t)size) { warnx("%s", kvm_geterr(kvmd)); return (-1); } return (0); } /* * Read single counter(9). */ uint64_t kread_counter(u_long addr) { if (kvmd_init() < 0) return (-1); return (kvm_counter_u64_fetch(kvmd, addr)); } /* * Read an array of N counters in kernel memory into array of N uint64_t's. */ int kread_counters(u_long addr, void *buf, size_t size) { uint64_t *c; u_long *counters; size_t i, n; if (kvmd_init() < 0) return (-1); if (size % sizeof(uint64_t) != 0) { warnx("kread_counters: invalid counter set size"); return (-1); } n = size / sizeof(uint64_t); if ((counters = malloc(n * sizeof(u_long))) == NULL) err(-1, "malloc"); if (kread(addr, counters, n * sizeof(u_long)) < 0) { free(counters); return (-1); } c = buf; for (i = 0; i < n; i++) c[i] = kvm_counter_u64_fetch(kvmd, counters[i]); free(counters); return (0); } const char * plural(uintmax_t n) { return (n != 1 ? "s" : ""); } const char * plurales(uintmax_t n) { return (n != 1 ? "es" : ""); } const char * pluralies(uintmax_t n) { return (n != 1 ? "ies" : "y"); } /* * Find the protox for the given "well-known" name. */ static struct protox * knownname(const char *name) { struct protox **tpp, *tp; for (tpp = protoprotox; *tpp; tpp++) for (tp = *tpp; tp->pr_name; tp++) if (strcmp(tp->pr_name, name) == 0) return (tp); return (NULL); } /* * Find the protox corresponding to name. */ static struct protox * name2protox(const char *name) { struct protox *tp; char **alias; /* alias from p->aliases */ struct protoent *p; /* * Try to find the name in the list of "well-known" names. If that * fails, check if name is an alias for an Internet protocol. */ if ((tp = knownname(name)) != NULL) return (tp); setprotoent(1); /* make protocol lookup cheaper */ while ((p = getprotoent()) != NULL) { /* assert: name not same as p->name */ for (alias = p->p_aliases; *alias; alias++) if (strcmp(name, *alias) == 0) { endprotoent(); return (knownname(p->p_name)); } } endprotoent(); return (NULL); } static void usage(void) { (void)fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n", "usage: netstat [-46AaLnRSTWx] [-f protocol_family | -p protocol]\n" " [-M core] [-N system]", " netstat -i | -I interface [-46abdhnW] [-f address_family]\n" " [-M core] [-N system]", " netstat -w wait [-I interface] [-46d] [-M core] [-N system] [-q howmany]", " netstat -s [-s] [-46z] [-f protocol_family | -p protocol]\n" " [-M core] [-N system]", " netstat -i | -I interface [-46s] [-f protocol_family | -p protocol]\n" " [-M core] [-N system]", " netstat -m [-M core] [-N system]", " netstat -B [-I interface]", " netstat -r [-46AanW] [-f address_family] [-M core] [-N system]", " netstat -rs [-s] [-M core] [-N system]", " netstat -g [-46W] [-f address_family] [-M core] [-N system]", " netstat -gs [-46s] [-f address_family] [-M core] [-N system]", " netstat -Q"); exit(1); } Index: stable/10 =================================================================== --- stable/10 (revision 293343) +++ stable/10 (revision 293344) Property changes on: stable/10 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r292394