1 /* $NetBSD: fast_ipsec.c,v 1.5 2004/06/27 01:10:53 jonathan Exp $ */ 2 /* $FreeBSD: src/tools/tools/crypto/ipsecstats.c,v 1.1.4.1 2003/06/03 00:13:13 sam Exp $ */ 3 4 /*- 5 * Copyright (c) 2003, 2004 Jonathan Stone 6 * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 * $FreeBSD: src/tools/tools/crypto/ipsecstats.c,v 1.1.4.1 2003/06/03 00:13:13 sam Exp $ 31 */ 32 33 #include <sys/cdefs.h> 34 #ifndef lint 35 #ifdef __NetBSD__ 36 __RCSID("$NetBSD: fast_ipsec.c,v 1.5 2004/06/27 01:10:53 jonathan Exp $"); 37 #endif 38 #endif /* not lint*/ 39 40 /* Kernel headers required, but not included, by netstat.h */ 41 #include <sys/types.h> 42 #include <sys/socket.h> 43 44 /* Kernel headers for sysctl(3). */ 45 #include <sys/param.h> 46 #include <sys/sysctl.h> 47 48 /* Kernel headers for FAST_IPSEC statistics */ 49 #include <net/pfkeyv2.h> 50 #include <netipsec/esp_var.h> 51 #include <netipsec/ah_var.h> 52 #include <netipsec/ipip_var.h> 53 #include <netipsec/ipcomp_var.h> 54 #include <netipsec/ipsec_var.h> 55 #include <netipsec/keydb.h> 56 57 #include <machine/int_fmtio.h> 58 59 #include <err.h> 60 #include <stdio.h> 61 #include <string.h> 62 63 #include "netstat.h" 64 65 /* 66 * Dispatch between fetching and printing (KAME) IPsec statistics, 67 * and FAST_IPSEC statistics, so the rest of netstat need not know 68 * about the vagaries of the two implementations. 69 */ 70 void 71 ipsec_switch(u_long off, char * name) 72 { 73 int status; 74 size_t slen; 75 76 slen = 0; 77 status = sysctlbyname("net.inet.ipsec.stats", NULL, &slen, NULL, 0); 78 if (status == 0 && slen == sizeof(struct newipsecstat)) 79 return fast_ipsec_stats(off, name); 80 81 return ipsec_stats(off, name); 82 } 83 84 85 /* 86 * Table-driven mapping from SADB algorithm codes to string names. 87 */ 88 struct alg { 89 int a; 90 const char *name; 91 }; 92 static const struct alg aalgs[] = { 93 { SADB_AALG_NONE, "none", }, 94 { SADB_AALG_MD5HMAC, "hmac-md5", }, 95 { SADB_AALG_SHA1HMAC, "hmac-sha1", }, 96 { SADB_X_AALG_MD5, "md5", }, 97 { SADB_X_AALG_SHA, "sha", }, 98 { SADB_X_AALG_NULL, "null", }, 99 { SADB_X_AALG_SHA2_256, "hmac-sha2-256", }, 100 { SADB_X_AALG_SHA2_384, "hmac-sha2-384", }, 101 { SADB_X_AALG_SHA2_512, "hmac-sha2-512", }, 102 }; 103 static const struct alg espalgs[] = { 104 { SADB_EALG_NONE, "none", }, 105 { SADB_EALG_DESCBC, "des-cbc", }, 106 { SADB_EALG_3DESCBC, "3des-cbc", }, 107 { SADB_EALG_NULL, "null", }, 108 { SADB_X_EALG_CAST128CBC, "cast128-cbc", }, 109 { SADB_X_EALG_BLOWFISHCBC, "blowfish-cbc", }, 110 { SADB_X_EALG_RIJNDAELCBC, "aes-cbc", }, 111 }; 112 static const struct alg ipcompalgs[] = { 113 { SADB_X_CALG_NONE, "none", }, 114 { SADB_X_CALG_OUI, "oui", }, 115 { SADB_X_CALG_DEFLATE, "deflate", }, 116 { SADB_X_CALG_LZS, "lzs", }, 117 }; 118 #define N(a) (sizeof(a)/sizeof(a[0])) 119 120 static const char* 121 algname(int a, const struct alg algs[], int nalgs) 122 { 123 static char buf[80]; 124 int i; 125 126 for (i = 0; i < nalgs; i++) 127 if (algs[i].a == a) 128 return algs[i].name; 129 snprintf(buf, sizeof(buf), "alg#%u", a); 130 return buf; 131 } 132 133 /* 134 * Print the fast_ipsec statistics. 135 * Since NetBSD's netstat(1) seems not to find us for "netstat -s", 136 * but does(?) find KAME, be prepared to be called explicitly from 137 * netstat's main program for "netstat -s"; but silently do nothing 138 * if that happens when we are running on KAME IPsec. 139 */ 140 void 141 fast_ipsec_stats(u_long off, char *name) 142 { 143 struct newipsecstat ipsecstats; 144 struct ahstat ahstats; 145 struct espstat espstats; 146 struct ipcompstat ipcs; 147 struct ipipstat ipips; 148 int status; 149 size_t slen; 150 int i; 151 152 memset(&ipsecstats, 0, sizeof(ipsecstats)); 153 memset(&ahstats, 0, sizeof(ahstats)); 154 memset(&espstats, 0, sizeof(espstats)); 155 memset(&ipcs, 0, sizeof(ipcs)); 156 memset(&ipips, 0, sizeof(ipips)); 157 158 /* silence check */ 159 status = sysctlbyname("net.inet.ipsec.stats", NULL, &slen, NULL, 0); 160 if (status != 0) 161 return; 162 163 slen = sizeof(ipsecstats); 164 status = sysctlbyname("net.inet.ipsec.stats", &ipsecstats, &slen, 165 NULL, 0); 166 if (status < 0) 167 err(1, "net.inet.ipsec.stats"); 168 169 slen = sizeof (ahstats); 170 if (sysctlbyname("net.inet.ah.stats", &ahstats, &slen, NULL, 0) < 0) 171 err(1, "net.inet.ah.stats"); 172 slen = sizeof (espstats); 173 if (sysctlbyname("net.inet.esp.stats", &espstats, &slen, NULL, 0) < 0) 174 err(1, "net.inet.esp.stats"); 175 if (sysctlbyname("net.inet.ipcomp.stats", &ipcs, &slen, NULL, 0) < 0) 176 err(1, "net.inet.ipcomp.stats"); 177 if (sysctlbyname("net.inet.ipip.stats", &ipips, &slen, NULL, 0) < 0) 178 err(1, "net.inet.ipip.stats"); 179 180 printf("(Fast) IPsec:\n"); 181 182 #define STAT(x,fmt) if ((x) || sflag <= 1) printf("\t%"PRIu64" " fmt "\n", x) 183 if (ipsecstats.ips_in_polvio+ipsecstats.ips_out_polvio) 184 printf("\t%"PRIu64" policy violations: %"PRIu64" input %"PRIu64" output\n", 185 ipsecstats.ips_in_polvio + ipsecstats.ips_out_polvio, 186 ipsecstats.ips_in_polvio, ipsecstats.ips_out_polvio); 187 STAT(ipsecstats.ips_out_nosa, "no SA found (output)"); 188 STAT(ipsecstats.ips_out_nomem, "no memory available (output)"); 189 STAT(ipsecstats.ips_out_noroute, "no route available (output)"); 190 STAT(ipsecstats.ips_out_inval, "generic errors (output)"); 191 STAT(ipsecstats.ips_out_bundlesa, "bundled SA processed (output)"); 192 STAT(ipsecstats.ips_spdcache_lookup, "SPD cache lookups"); 193 STAT(ipsecstats.ips_spdcache_lookup, "SPD cache misses"); 194 #undef STAT 195 printf("\n"); 196 197 printf("IPsec ah:\n"); 198 #define AHSTAT(x,fmt) if ((x) || sflag <= 1) printf("\t%"PRIu64" ah " fmt "\n", x) 199 AHSTAT(ahstats.ahs_input, "input packets processed"); 200 AHSTAT(ahstats.ahs_output, "output packets processed"); 201 AHSTAT(ahstats.ahs_hdrops, "headers too short"); 202 AHSTAT(ahstats.ahs_nopf, "headers for unsupported address family"); 203 AHSTAT(ahstats.ahs_notdb, "packets with no SA"); 204 AHSTAT(ahstats.ahs_badkcr, "packets dropped by crypto returning NULL mbuf"); 205 AHSTAT(ahstats.ahs_badauth, "packets with bad authentication"); 206 AHSTAT(ahstats.ahs_noxform, "packets with no xform"); 207 AHSTAT(ahstats.ahs_qfull, "packets dropped due to queue full"); 208 AHSTAT(ahstats.ahs_wrap, "packets dropped for replay counter wrap"); 209 AHSTAT(ahstats.ahs_replay, "packets dropped for possible replay"); 210 AHSTAT(ahstats.ahs_badauthl,"packets dropped for bad authenticator length"); 211 AHSTAT(ahstats.ahs_invalid, "packets with an invalid SA"); 212 AHSTAT(ahstats.ahs_toobig, "packets too big"); 213 AHSTAT(ahstats.ahs_pdrops, "packets blocked due to policy"); 214 AHSTAT(ahstats.ahs_crypto, "failed crypto requests"); 215 AHSTAT(ahstats.ahs_tunnel, "tunnel sanity check failures"); 216 217 printf("\tah histogram:\n"); 218 for (i = 0; i < AH_ALG_MAX; i++) 219 if (ahstats.ahs_hist[i]) 220 printf("\t\tah packets with %s: %"PRIu64"\n" 221 , algname(i, aalgs, N(aalgs)) 222 , ahstats.ahs_hist[i] 223 ); 224 AHSTAT(ahstats.ahs_ibytes, "bytes received"); 225 AHSTAT(ahstats.ahs_obytes, "bytes transmitted"); 226 #undef AHSTAT 227 printf("\n"); 228 229 printf("IPsec esp:\n"); 230 #define ESPSTAT(x,fmt) if ((x) || sflag <= 1) printf("\t%"PRIu64" esp " fmt "\n", x) 231 ESPSTAT(espstats.esps_input, "input packets processed"); 232 ESPSTAT(espstats.esps_output, "output packets processed"); 233 ESPSTAT(espstats.esps_hdrops, "headers too short"); 234 ESPSTAT(espstats.esps_nopf, "headers for unsupported address family"); 235 ESPSTAT(espstats.esps_notdb, "packets with no SA"); 236 ESPSTAT(espstats.esps_badkcr, "packets dropped by crypto returning NULL mbuf"); 237 ESPSTAT(espstats.esps_qfull, "packets dropped due to queue full"); 238 ESPSTAT(espstats.esps_noxform, "packets with no xform"); 239 ESPSTAT(espstats.esps_badilen, "packets with bad ilen"); 240 ESPSTAT(espstats.esps_badenc, "packets with bad encryption"); 241 ESPSTAT(espstats.esps_badauth, "packets with bad authentication"); 242 ESPSTAT(espstats.esps_wrap, "packets dropped for replay counter wrap"); 243 ESPSTAT(espstats.esps_replay, "packets dropped for possible replay"); 244 ESPSTAT(espstats.esps_invalid, "packets with an invalid SA"); 245 ESPSTAT(espstats.esps_toobig, "packets too big"); 246 ESPSTAT(espstats.esps_pdrops, "packets blocked due to policy"); 247 ESPSTAT(espstats.esps_crypto, "failed crypto requests"); 248 ESPSTAT(espstats.esps_tunnel, "tunnel sanity check failures"); 249 printf("\tesp histogram:\n"); 250 for (i = 0; i < ESP_ALG_MAX; i++) 251 if (espstats.esps_hist[i]) 252 printf("\t\tesp packets with %s: %"PRIu64"\n" 253 , algname(i, espalgs, N(espalgs)) 254 , espstats.esps_hist[i] 255 ); 256 ESPSTAT(espstats.esps_ibytes, "bytes received"); 257 ESPSTAT(espstats.esps_obytes, "bytes transmitted"); 258 #undef ESPSTAT 259 printf("IPsec ipip:\n"); 260 261 #define IPIPSTAT(x,fmt) \ 262 if ((x) || sflag <= 1) printf("\t%"PRIu64" ipip " fmt "\n", x) 263 IPIPSTAT(ipips.ipips_ipackets, "total input packets"); 264 IPIPSTAT(ipips.ipips_opackets, "total output packets"); 265 IPIPSTAT(ipips.ipips_hdrops, "packets too short for header length"); 266 IPIPSTAT(ipips.ipips_qfull, "packets dropped due to queue full"); 267 IPIPSTAT(ipips.ipips_pdrops, "packets blocked due to policy"); 268 IPIPSTAT(ipips.ipips_spoof, "IP spoofing attempts"); 269 IPIPSTAT(ipips.ipips_family, "protocol family mismatched"); 270 IPIPSTAT(ipips.ipips_unspec, "missing tunnel-endpoint address"); 271 IPIPSTAT(ipips.ipips_ibytes, "input bytes received"); 272 IPIPSTAT(ipips.ipips_obytes, "output bytes procesesed"); 273 #undef IPIPSTAT 274 275 printf("IPsec ipcomp:\n"); 276 #define IPCOMP(x,fmt) \ 277 if ((x) || sflag <= 1) printf("\t%"PRIu64" ipcomp " fmt "\n", x) 278 279 IPCOMP(ipcs.ipcomps_hdrops, "packets too short for header length"); 280 IPCOMP(ipcs.ipcomps_nopf, "protocol family not supported"); 281 IPCOMP(ipcs.ipcomps_notdb, "not db"); 282 IPCOMP(ipcs.ipcomps_badkcr, "packets dropped by crypto returning NULL mbuf"); 283 IPCOMP(ipcs.ipcomps_qfull, "queue full"); 284 IPCOMP(ipcs.ipcomps_noxform, "no support for transform"); 285 IPCOMP(ipcs.ipcomps_wrap, "packets dropped for replay counter wrap"); 286 IPCOMP(ipcs.ipcomps_input, "input IPcomp packets"); 287 IPCOMP(ipcs.ipcomps_output, "output IPcomp packets"); 288 IPCOMP(ipcs.ipcomps_invalid, "specified an invalid TDB"); 289 IPCOMP(ipcs.ipcomps_toobig, "packets decompressed as too big"); 290 IPCOMP(ipcs.ipcomps_pdrops, "packets blocked due to policy"); 291 IPCOMP(ipcs.ipcomps_crypto, "failed crypto requests"); 292 293 printf("\tIPcomp histogram:\n"); 294 for (i = 0; i < IPCOMP_ALG_MAX; i++) 295 if (ipcs.ipcomps_hist[i]) 296 printf("\t\tIPcomp packets with %s: %"PRIu64"\n" 297 , algname(i, ipcompalgs, N(ipcompalgs)) 298 , ipcs.ipcomps_hist[i] 299 ); 300 IPCOMP(ipcs.ipcomps_ibytes, "input bytes"); 301 IPCOMP(ipcs.ipcomps_obytes, "output bytes"); 302 #undef IPCOMP 303 } 304