1 /* $KAME: ipsec.c,v 1.33 2003/07/25 09:54:32 itojun Exp $ */ 2 3 /*- 4 * Copyright (c) 2005 NTT Multimedia Communications Laboratories, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 /*- 29 * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. 30 * All rights reserved. 31 * 32 * Redistribution and use in source and binary forms, with or without 33 * modification, are permitted provided that the following conditions 34 * are met: 35 * 1. Redistributions of source code must retain the above copyright 36 * notice, this list of conditions and the following disclaimer. 37 * 2. Redistributions in binary form must reproduce the above copyright 38 * notice, this list of conditions and the following disclaimer in the 39 * documentation and/or other materials provided with the distribution. 40 * 3. Neither the name of the project nor the names of its contributors 41 * may be used to endorse or promote products derived from this software 42 * without specific prior written permission. 43 * 44 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 47 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 54 * SUCH DAMAGE. 55 */ 56 /*- 57 * Copyright (c) 1983, 1988, 1993 58 * The Regents of the University of California. All rights reserved. 59 * 60 * Redistribution and use in source and binary forms, with or without 61 * modification, are permitted provided that the following conditions 62 * are met: 63 * 1. Redistributions of source code must retain the above copyright 64 * notice, this list of conditions and the following disclaimer. 65 * 2. Redistributions in binary form must reproduce the above copyright 66 * notice, this list of conditions and the following disclaimer in the 67 * documentation and/or other materials provided with the distribution. 68 * 4. Neither the name of the University nor the names of its contributors 69 * may be used to endorse or promote products derived from this software 70 * without specific prior written permission. 71 * 72 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 73 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 74 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 75 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 76 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 77 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 78 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 79 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 80 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 81 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 82 * SUCH DAMAGE. 83 */ 84 85 #if 0 86 #ifndef lint 87 static char sccsid[] = "@(#)inet.c 8.5 (Berkeley) 5/24/95"; 88 #endif /* not lint */ 89 #endif 90 91 #include <sys/cdefs.h> 92 __FBSDID("$FreeBSD$"); 93 94 #include <sys/param.h> 95 #include <sys/queue.h> 96 #include <sys/socket.h> 97 #include <sys/socketvar.h> 98 99 #include <netinet/in.h> 100 101 #ifdef IPSEC 102 #include <netipsec/ipsec.h> 103 #include <netipsec/ah_var.h> 104 #include <netipsec/esp_var.h> 105 #include <netipsec/ipcomp_var.h> 106 #endif 107 108 #include <stdint.h> 109 #include <stdio.h> 110 #include <string.h> 111 #include <unistd.h> 112 #include "netstat.h" 113 114 #ifdef IPSEC 115 struct val2str { 116 int val; 117 const char *str; 118 }; 119 120 static struct val2str ipsec_ahnames[] = { 121 { SADB_AALG_NONE, "none", }, 122 { SADB_AALG_MD5HMAC, "hmac-md5", }, 123 { SADB_AALG_SHA1HMAC, "hmac-sha1", }, 124 { SADB_X_AALG_MD5, "md5", }, 125 { SADB_X_AALG_SHA, "sha", }, 126 { SADB_X_AALG_NULL, "null", }, 127 #ifdef SADB_X_AALG_SHA2_256 128 { SADB_X_AALG_SHA2_256, "hmac-sha2-256", }, 129 #endif 130 #ifdef SADB_X_AALG_SHA2_384 131 { SADB_X_AALG_SHA2_384, "hmac-sha2-384", }, 132 #endif 133 #ifdef SADB_X_AALG_SHA2_512 134 { SADB_X_AALG_SHA2_512, "hmac-sha2-512", }, 135 #endif 136 #ifdef SADB_X_AALG_RIPEMD160HMAC 137 { SADB_X_AALG_RIPEMD160HMAC, "hmac-ripemd160", }, 138 #endif 139 #ifdef SADB_X_AALG_AES_XCBC_MAC 140 { SADB_X_AALG_AES_XCBC_MAC, "aes-xcbc-mac", }, 141 #endif 142 { -1, NULL }, 143 }; 144 145 static struct val2str ipsec_espnames[] = { 146 { SADB_EALG_NONE, "none", }, 147 { SADB_EALG_DESCBC, "des-cbc", }, 148 { SADB_EALG_3DESCBC, "3des-cbc", }, 149 { SADB_EALG_NULL, "null", }, 150 { SADB_X_EALG_CAST128CBC, "cast128-cbc", }, 151 { SADB_X_EALG_BLOWFISHCBC, "blowfish-cbc", }, 152 #ifdef SADB_X_EALG_RIJNDAELCBC 153 { SADB_X_EALG_RIJNDAELCBC, "rijndael-cbc", }, 154 #endif 155 #ifdef SADB_X_EALG_AESCTR 156 { SADB_X_EALG_AESCTR, "aes-ctr", }, 157 #endif 158 { -1, NULL }, 159 }; 160 161 static struct val2str ipsec_compnames[] = { 162 { SADB_X_CALG_NONE, "none", }, 163 { SADB_X_CALG_OUI, "oui", }, 164 { SADB_X_CALG_DEFLATE, "deflate", }, 165 { SADB_X_CALG_LZS, "lzs", }, 166 { -1, NULL }, 167 }; 168 169 static void ipsec_hist(const u_quad_t *hist, size_t histmax, 170 const struct val2str *name, const char *title); 171 static void print_ipsecstats(const struct ipsecstat *ipsecstat); 172 173 174 /* 175 * Dump IPSEC statistics structure. 176 */ 177 static void 178 ipsec_hist(const u_quad_t *hist, size_t histmax, const struct val2str *name, 179 const char *title) 180 { 181 int first; 182 size_t proto; 183 const struct val2str *p; 184 185 first = 1; 186 for (proto = 0; proto < histmax; proto++) { 187 if (hist[proto] <= 0) 188 continue; 189 if (first) { 190 printf("\t%s histogram:\n", title); 191 first = 0; 192 } 193 for (p = name; p && p->str; p++) { 194 if (p->val == (int)proto) 195 break; 196 } 197 if (p && p->str) { 198 printf("\t\t%s: %ju\n", p->str, (uintmax_t)hist[proto]); 199 } else { 200 printf("\t\t#%ld: %ju\n", (long)proto, 201 (uintmax_t)hist[proto]); 202 } 203 } 204 } 205 206 static void 207 print_ipsecstats(const struct ipsecstat *ipsecstat) 208 { 209 #define p(f, m) if (ipsecstat->f || sflag <= 1) \ 210 printf(m, (uintmax_t)ipsecstat->f, plural(ipsecstat->f)) 211 #define pes(f, m) if (ipsecstat->f || sflag <= 1) \ 212 printf(m, (uintmax_t)ipsecstat->f, plurales(ipsecstat->f)) 213 #define hist(f, n, t) \ 214 ipsec_hist((f), sizeof(f)/sizeof(f[0]), (n), (t)); 215 216 p(in_success, "\t%ju inbound packet%s processed successfully\n"); 217 p(in_polvio, "\t%ju inbound packet%s violated process security " 218 "policy\n"); 219 p(in_nosa, "\t%ju inbound packet%s with no SA available\n"); 220 p(in_inval, "\t%ju invalid inbound packet%s\n"); 221 p(in_nomem, "\t%ju inbound packet%s failed due to insufficient memory\n"); 222 p(in_badspi, "\t%ju inbound packet%s failed getting SPI\n"); 223 p(in_ahreplay, "\t%ju inbound packet%s failed on AH replay check\n"); 224 p(in_espreplay, "\t%ju inbound packet%s failed on ESP replay check\n"); 225 p(in_ahauthsucc, "\t%ju inbound packet%s considered authentic\n"); 226 p(in_ahauthfail, "\t%ju inbound packet%s failed on authentication\n"); 227 hist(ipsecstat->in_ahhist, ipsec_ahnames, "AH input"); 228 hist(ipsecstat->in_esphist, ipsec_espnames, "ESP input"); 229 hist(ipsecstat->in_comphist, ipsec_compnames, "IPComp input"); 230 231 p(out_success, "\t%ju outbound packet%s processed successfully\n"); 232 p(out_polvio, "\t%ju outbound packet%s violated process security " 233 "policy\n"); 234 p(out_nosa, "\t%ju outbound packet%s with no SA available\n"); 235 p(out_inval, "\t%ju invalid outbound packet%s\n"); 236 p(out_nomem, "\t%ju outbound packet%s failed due to insufficient memory\n"); 237 p(out_noroute, "\t%ju outbound packet%s with no route\n"); 238 hist(ipsecstat->out_ahhist, ipsec_ahnames, "AH output"); 239 hist(ipsecstat->out_esphist, ipsec_espnames, "ESP output"); 240 hist(ipsecstat->out_comphist, ipsec_compnames, "IPComp output"); 241 p(spdcachelookup, "\t%ju SPD cache lookup%s\n"); 242 pes(spdcachemiss, "\t%ju SPD cache miss%s\n"); 243 #undef pes 244 #undef hist 245 p(ips_in_polvio, "\t%ju inbound packet%s violated process " 246 "security policy\n"); 247 p(ips_out_polvio, "\t%ju outbound packet%s violated process " 248 "security policy\n"); 249 p(ips_out_nosa, "\t%ju outbound packet%s with no SA available\n"); 250 p(ips_out_nomem, "\t%ju outbound packet%s failed due to " 251 "insufficient memory\n"); 252 p(ips_out_noroute, "\t%ju outbound packet%s with no route " 253 "available\n"); 254 p(ips_out_inval, "\t%ju invalid outbound packet%s\n"); 255 p(ips_out_bundlesa, "\t%ju outbound packet%s with bundled SAs\n"); 256 p(ips_mbcoalesced, "\t%ju mbuf%s coalesced during clone\n"); 257 p(ips_clcoalesced, "\t%ju cluster%s coalesced during clone\n"); 258 p(ips_clcopied, "\t%ju cluster%s copied during clone\n"); 259 p(ips_mbinserted, "\t%ju mbuf%s inserted during makespace\n"); 260 #undef p 261 } 262 263 void 264 ipsec_stats(u_long off, const char *name, int af1 __unused, int proto __unused) 265 { 266 struct ipsecstat ipsecstat; 267 268 if (off == 0) 269 return; 270 printf ("%s:\n", name); 271 kread(off, (char *)&ipsecstat, sizeof(ipsecstat)); 272 273 print_ipsecstats(&ipsecstat); 274 } 275 276 277 static void ipsec_hist_new(const u_int32_t *hist, size_t histmax, 278 const struct val2str *name, const char *title); 279 static void print_ahstats(const struct ahstat *ahstat); 280 static void print_espstats(const struct espstat *espstat); 281 static void print_ipcompstats(const struct ipcompstat *ipcompstat); 282 283 /* 284 * Dump IPSEC statistics structure. 285 */ 286 static void 287 ipsec_hist_new(const u_int32_t *hist, size_t histmax, 288 const struct val2str *name, const char *title) 289 { 290 int first; 291 size_t proto; 292 const struct val2str *p; 293 294 first = 1; 295 for (proto = 0; proto < histmax; proto++) { 296 if (hist[proto] <= 0) 297 continue; 298 if (first) { 299 printf("\t%s histogram:\n", title); 300 first = 0; 301 } 302 for (p = name; p && p->str; p++) { 303 if (p->val == (int)proto) 304 break; 305 } 306 if (p && p->str) { 307 printf("\t\t%s: %u\n", p->str, hist[proto]); 308 } else { 309 printf("\t\t#%lu: %u\n", (unsigned long)proto, 310 hist[proto]); 311 } 312 } 313 } 314 315 static void 316 print_ahstats(const struct ahstat *ahstat) 317 { 318 #define p32(f, m) if (ahstat->f || sflag <= 1) \ 319 printf("\t%u" m, (unsigned int)ahstat->f, plural(ahstat->f)) 320 #define p64(f, m) if (ahstat->f || sflag <= 1) \ 321 printf("\t%ju" m, (uintmax_t)ahstat->f, plural(ahstat->f)) 322 #define hist(f, n, t) \ 323 ipsec_hist_new((f), sizeof(f)/sizeof(f[0]), (n), (t)); 324 325 p32(ahs_hdrops, " packet%s shorter than header shows\n"); 326 p32(ahs_nopf, " packet%s dropped; protocol family not supported\n"); 327 p32(ahs_notdb, " packet%s dropped; no TDB\n"); 328 p32(ahs_badkcr, " packet%s dropped; bad KCR\n"); 329 p32(ahs_qfull, " packet%s dropped; queue full\n"); 330 p32(ahs_noxform, " packet%s dropped; no transform\n"); 331 p32(ahs_wrap, " replay counter wrap%s\n"); 332 p32(ahs_badauth, " packet%s dropped; bad authentication detected\n"); 333 p32(ahs_badauthl, " packet%s dropped; bad authentication length\n"); 334 p32(ahs_replay, " possible replay packet%s detected\n"); 335 p32(ahs_input, " packet%s in\n"); 336 p32(ahs_output, " packet%s out\n"); 337 p32(ahs_invalid, " packet%s dropped; invalid TDB\n"); 338 p64(ahs_ibytes, " byte%s in\n"); 339 p64(ahs_obytes, " byte%s out\n"); 340 p32(ahs_toobig, " packet%s dropped; larger than IP_MAXPACKET\n"); 341 p32(ahs_pdrops, " packet%s blocked due to policy\n"); 342 p32(ahs_crypto, " crypto processing failure%s\n"); 343 p32(ahs_tunnel, " tunnel sanity check failure%s\n"); 344 hist(ahstat->ahs_hist, ipsec_ahnames, "AH output"); 345 346 #undef p32 347 #undef p64 348 #undef hist 349 } 350 351 void 352 ah_stats(u_long off, const char *name, int family __unused, int proto __unused) 353 { 354 struct ahstat ahstat; 355 356 if (off == 0) 357 return; 358 printf ("%s:\n", name); 359 kread(off, (char *)&ahstat, sizeof(ahstat)); 360 361 print_ahstats(&ahstat); 362 } 363 364 static void 365 print_espstats(const struct espstat *espstat) 366 { 367 #define p32(f, m) if (espstat->f || sflag <= 1) \ 368 printf("\t%u" m, (unsigned int)espstat->f, plural(espstat->f)) 369 #define p64(f, m) if (espstat->f || sflag <= 1) \ 370 printf("\t%ju" m, (uintmax_t)espstat->f, plural(espstat->f)) 371 #define hist(f, n, t) \ 372 ipsec_hist_new((f), sizeof(f)/sizeof(f[0]), (n), (t)); 373 374 p32(esps_hdrops, " packet%s shorter than header shows\n"); 375 p32(esps_nopf, " packet%s dropped; protocol family not supported\n"); 376 p32(esps_notdb, " packet%s dropped; no TDB\n"); 377 p32(esps_badkcr, " packet%s dropped; bad KCR\n"); 378 p32(esps_qfull, " packet%s dropped; queue full\n"); 379 p32(esps_noxform, " packet%s dropped; no transform\n"); 380 p32(esps_badilen, " packet%s dropped; bad ilen\n"); 381 p32(esps_wrap, " replay counter wrap%s\n"); 382 p32(esps_badenc, " packet%s dropped; bad encryption detected\n"); 383 p32(esps_badauth, " packet%s dropped; bad authentication detected\n"); 384 p32(esps_replay, " possible replay packet%s detected\n"); 385 p32(esps_input, " packet%s in\n"); 386 p32(esps_output, " packet%s out\n"); 387 p32(esps_invalid, " packet%s dropped; invalid TDB\n"); 388 p64(esps_ibytes, " byte%s in\n"); 389 p64(esps_obytes, " byte%s out\n"); 390 p32(esps_toobig, " packet%s dropped; larger than IP_MAXPACKET\n"); 391 p32(esps_pdrops, " packet%s blocked due to policy\n"); 392 p32(esps_crypto, " crypto processing failure%s\n"); 393 p32(esps_tunnel, " tunnel sanity check failure%s\n"); 394 hist(espstat->esps_hist, ipsec_espnames, "ESP output"); 395 396 #undef p32 397 #undef p64 398 #undef hist 399 } 400 401 void 402 esp_stats(u_long off, const char *name, int family __unused, int proto __unused) 403 { 404 struct espstat espstat; 405 406 if (off == 0) 407 return; 408 printf ("%s:\n", name); 409 kread(off, (char *)&espstat, sizeof(espstat)); 410 411 print_espstats(&espstat); 412 } 413 414 static void 415 print_ipcompstats(const struct ipcompstat *ipcompstat) 416 { 417 uint32_t version; 418 #define p32(f, m) if (ipcompstat->f || sflag <= 1) \ 419 printf("\t%u" m, (unsigned int)ipcompstat->f, plural(ipcompstat->f)) 420 #define p64(f, m) if (ipcompstat->f || sflag <= 1) \ 421 printf("\t%ju" m, (uintmax_t)ipcompstat->f, plural(ipcompstat->f)) 422 #define hist(f, n, t) \ 423 ipsec_hist_new((f), sizeof(f)/sizeof(f[0]), (n), (t)); 424 425 #ifndef IPCOMPSTAT_VERSION 426 version = 0; 427 #else 428 version = ipcompstat->version; 429 #endif 430 p32(ipcomps_hdrops, " packet%s shorter than header shows\n"); 431 p32(ipcomps_nopf, " packet%s dropped; protocol family not supported\n"); 432 p32(ipcomps_notdb, " packet%s dropped; no TDB\n"); 433 p32(ipcomps_badkcr, " packet%s dropped; bad KCR\n"); 434 p32(ipcomps_qfull, " packet%s dropped; queue full\n"); 435 p32(ipcomps_noxform, " packet%s dropped; no transform\n"); 436 p32(ipcomps_wrap, " replay counter wrap%s\n"); 437 p32(ipcomps_input, " packet%s in\n"); 438 p32(ipcomps_output, " packet%s out\n"); 439 p32(ipcomps_invalid, " packet%s dropped; invalid TDB\n"); 440 p64(ipcomps_ibytes, " byte%s in\n"); 441 p64(ipcomps_obytes, " byte%s out\n"); 442 p32(ipcomps_toobig, " packet%s dropped; larger than IP_MAXPACKET\n"); 443 p32(ipcomps_pdrops, " packet%s blocked due to policy\n"); 444 p32(ipcomps_crypto, " crypto processing failure%s\n"); 445 hist(ipcompstat->ipcomps_hist, ipsec_compnames, "COMP output"); 446 if (version >= 1) { 447 p32(ipcomps_threshold, " packet%s sent uncompressed; size < compr. algo. threshold\n"); 448 p32(ipcomps_uncompr, " packet%s sent uncompressed; compression was useless\n"); 449 } 450 451 #undef p32 452 #undef p64 453 #undef hist 454 } 455 456 void 457 ipcomp_stats(u_long off, const char *name, int family __unused, 458 int proto __unused) 459 { 460 struct ipcompstat ipcompstat; 461 462 if (off == 0) 463 return; 464 printf ("%s:\n", name); 465 kread(off, (char *)&ipcompstat, sizeof(ipcompstat)); 466 467 print_ipcompstats(&ipcompstat); 468 } 469 470 #endif /*IPSEC*/ 471