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