1/* 2 * Copyright (c) 2008-2012 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* $FreeBSD: src/usr.bin/netstat/ipsec.c,v 1.1.2.3 2001/08/10 09:07:09 ru Exp $ */ 29/* $NetBSD: inet.c,v 1.35.2.1 1999/04/29 14:57:08 perry Exp $ */ 30/* $KAME: ipsec.c,v 1.25 2001/03/12 09:04:39 itojun Exp $ */ 31 32/* 33 * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. 34 * All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 3. Neither the name of the project nor the names of its contributors 45 * may be used to endorse or promote products derived from this software 46 * without specific prior written permission. 47 * 48 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 * SUCH DAMAGE. 59 */ 60 61/* 62 * Copyright (c) 1983, 1988, 1993 63 * The Regents of the University of California. All rights reserved. 64 * 65 * Redistribution and use in source and binary forms, with or without 66 * modification, are permitted provided that the following conditions 67 * are met: 68 * 1. Redistributions of source code must retain the above copyright 69 * notice, this list of conditions and the following disclaimer. 70 * 2. Redistributions in binary form must reproduce the above copyright 71 * notice, this list of conditions and the following disclaimer in the 72 * documentation and/or other materials provided with the distribution. 73 * 3. All advertising materials mentioning features or use of this software 74 * must display the following acknowledgement: 75 * This product includes software developed by the University of 76 * California, Berkeley and its contributors. 77 * 4. Neither the name of the University nor the names of its contributors 78 * may be used to endorse or promote products derived from this software 79 * without specific prior written permission. 80 * 81 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 82 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 83 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 84 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 85 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 86 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 87 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 88 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 89 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 90 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 91 * SUCH DAMAGE. 92 */ 93 94#include <sys/cdefs.h> 95#ifndef lint 96/* 97static char sccsid[] = "@(#)inet.c 8.5 (Berkeley) 5/24/95"; 98*/ 99static const char rcsid[] = 100 "$FreeBSD: src/usr.bin/netstat/ipsec.c,v 1.1.2.3 2001/08/10 09:07:09 ru Exp $"; 101#endif /* not lint */ 102 103#include <sys/param.h> 104#include <sys/queue.h> 105#include <sys/socket.h> 106#include <sys/sysctl.h> 107 108#include <netinet/in.h> 109 110#ifdef IPSEC 111#include <netinet6/ipsec.h> 112#include <netkey/keysock.h> 113#endif 114 115#include <stdio.h> 116#include <string.h> 117#include <unistd.h> 118#include "netstat.h" 119 120#if defined(__APPLE__) && !defined(__unused) 121#define __unused 122#endif 123/* 124 * portability issues: 125 * - bsdi[34] uses PLURAL(), not plural(). 126 * - freebsd2 can't print "unsigned long long" properly. 127 */ 128/* 129 * XXX see PORTABILITY for the twist 130 */ 131#define LLU "%llu" 132#define CAST unsigned long long 133 134#ifdef IPSEC 135struct val2str { 136 int val; 137 const char *str; 138}; 139 140static struct val2str ipsec_ahnames[] = { 141 { SADB_AALG_NONE, "none", }, 142 { SADB_AALG_MD5HMAC, "hmac-md5", }, 143 { SADB_AALG_SHA1HMAC, "hmac-sha1", }, 144 { SADB_X_AALG_MD5, "md5", }, 145 { SADB_X_AALG_SHA, "sha", }, 146 { SADB_X_AALG_NULL, "null", }, 147#ifdef SADB_X_AALG_SHA2_256 148 { SADB_X_AALG_SHA2_256, "hmac-sha2-256", }, 149#endif 150#ifdef SADB_X_AALG_SHA2_384 151 { SADB_X_AALG_SHA2_384, "hmac-sha2-384", }, 152#endif 153#ifdef SADB_X_AALG_SHA2_512 154 { SADB_X_AALG_SHA2_512, "hmac-sha2-512", }, 155#endif 156 { -1, NULL }, 157}; 158 159static struct val2str ipsec_espnames[] = { 160 { SADB_EALG_NONE, "none", }, 161 { SADB_EALG_DESCBC, "des-cbc", }, 162 { SADB_EALG_3DESCBC, "3des-cbc", }, 163 { SADB_EALG_NULL, "null", }, 164#ifdef SADB_X_EALG_RC5CBC 165 { SADB_X_EALG_RC5CBC, "rc5-cbc", }, 166#endif 167 { SADB_X_EALG_CAST128CBC, "cast128-cbc", }, 168 { SADB_X_EALG_BLOWFISHCBC, "blowfish-cbc", }, 169#ifdef SADB_X_EALG_RIJNDAELCBC 170 { SADB_X_EALG_RIJNDAELCBC, "rijndael-cbc", }, 171#endif 172 { -1, NULL }, 173}; 174 175static struct val2str ipsec_compnames[] = { 176 { SADB_X_CALG_NONE, "none", }, 177 { SADB_X_CALG_OUI, "oui", }, 178 { SADB_X_CALG_DEFLATE, "deflate", }, 179 { SADB_X_CALG_LZS, "lzs", }, 180 { -1, NULL }, 181}; 182 183static const char *pfkey_msgtypenames[] = { 184 "reserved", "getspi", "update", "add", "delete", 185 "get", "acquire", "register", "expire", "flush", 186 "dump", "x_promisc", "x_pchange", "x_spdupdate", "x_spdadd", 187 "x_spddelete", "x_spdget", "x_spdacquire", "x_spddump", "x_spdflush", 188 "x_spdsetidx", "x_spdexpire", "x_spddelete2" 189}; 190 191static struct ipsecstat pipsecstat; 192static struct ipsecstat ipsecstat; 193 194static void print_ipsecstats (void); 195static const char *pfkey_msgtype_names (int); 196static void ipsec_hist (const u_quad_t *, const u_quad_t *, size_t, 197 const struct val2str *, const char *); 198 199/* 200 * Dump IPSEC statistics structure. 201 */ 202static void 203ipsec_hist(const u_quad_t *hist, 204 const u_quad_t *phist, 205 size_t histmax, 206 const struct val2str *name, 207 const char *title) 208{ 209 int first; 210 size_t proto; 211 const struct val2str *p; 212 213 first = 1; 214 for (proto = 0; proto < histmax; proto++) { 215 if ((hist[proto] - phist[proto]) <= 0) 216 continue; 217 if (first) { 218 printf("\t%s histogram:\n", title); 219 first = 0; 220 } 221 for (p = name; p && p->str; p++) { 222 if (p->val == (int)proto) 223 break; 224 } 225 if (p && p->str) { 226 printf("\t\t%s: " LLU "\n", p->str, 227 (CAST)hist[proto] - (CAST)phist[proto]); 228 } else { 229 printf("\t\t#%ld: " LLU "\n", (long)proto, 230 (CAST)hist[proto] - (CAST)phist[proto]); 231 } 232 } 233} 234 235static void 236print_ipsecstats(void) 237{ 238#define IPSECDIFF(f) (ipsecstat.f - pipsecstat.f) 239#define p(f, m) if (IPSECDIFF(f) || sflag <= 1) \ 240 printf(m, (CAST)IPSECDIFF(f), plural(IPSECDIFF(f))) 241#define hist(f, n, t) \ 242 ipsec_hist(ipsecstat.f, pipsecstat.f, \ 243 sizeof(ipsecstat.f)/sizeof(ipsecstat.f[0]), (n), (t)); 244 245 if (interval && vflag > 0) 246 print_time(); 247 248 p(in_success, "\t" LLU " inbound packet%s processed successfully\n"); 249 p(in_polvio, "\t" LLU " inbound packet%s violated process security " 250 "policy\n"); 251 p(in_nosa, "\t" LLU " inbound packet%s with no SA available\n"); 252 p(in_inval, "\t" LLU " invalid inbound packet%s\n"); 253 p(in_nomem, "\t" LLU " inbound packet%s failed due to insufficient memory\n"); 254 p(in_badspi, "\t" LLU " inbound packet%s failed getting SPI\n"); 255 p(in_ahreplay, "\t" LLU " inbound packet%s failed on AH replay check\n"); 256 p(in_espreplay, "\t" LLU " inbound packet%s failed on ESP replay check\n"); 257 p(in_ahauthsucc, "\t" LLU " inbound packet%s considered authentic\n"); 258 p(in_ahauthfail, "\t" LLU " inbound packet%s failed on authentication\n"); 259 hist(in_ahhist, ipsec_ahnames, "AH input"); 260 hist(in_esphist, ipsec_espnames, "ESP input"); 261 hist(in_comphist, ipsec_compnames, "IPComp input"); 262 263 p(out_success, "\t" LLU " outbound packet%s processed successfully\n"); 264 p(out_polvio, "\t" LLU " outbound packet%s violated process security " 265 "policy\n"); 266 p(out_nosa, "\t" LLU " outbound packet%s with no SA available\n"); 267 p(out_inval, "\t" LLU " invalid outbound packet%s\n"); 268 p(out_nomem, "\t" LLU " outbound packet%s failed due to insufficient memory\n"); 269 p(out_noroute, "\t" LLU " outbound packet%s with no route\n"); 270 hist(out_ahhist, ipsec_ahnames, "AH output"); 271 hist(out_esphist, ipsec_espnames, "ESP output"); 272 hist(out_comphist, ipsec_compnames, "IPComp output"); 273#undef IPSECDIFF 274#undef p 275#undef hist 276} 277 278void 279ipsec_stats(uint32_t off __unused, char *name, int af __unused) 280{ 281 size_t len; 282 283 len = sizeof(struct ipsecstat); 284 if (strcmp(name, "ipsec") == 0) { 285 if (sysctlbyname("net.inet.ipsec.stats", &ipsecstat, &len, 0, 0) == -1) 286 return; 287 } else if (strcmp(name, "ipsec6") == 0) { 288 if (sysctlbyname("net.inet6.ipsec6.stats", &ipsecstat, &len, 0, 0) == -1) 289 return; 290 } else 291 return; 292 printf ("%s:\n", name); 293 294 print_ipsecstats(); 295 296 if (interval > 0) 297 bcopy(&ipsecstat, &pipsecstat, len); 298} 299 300static const char * 301pfkey_msgtype_names(int x) 302{ 303 const int max = 304 sizeof(pfkey_msgtypenames)/sizeof(pfkey_msgtypenames[0]); 305 static char buf[10]; 306 307 if (x < max && pfkey_msgtypenames[x]) 308 return pfkey_msgtypenames[x]; 309 snprintf(buf, sizeof(buf), "#%d", x); 310 return buf; 311} 312 313void 314pfkey_stats(uint32_t off __unused, char *name, int af __unused) 315{ 316 static struct pfkeystat ppfkeystat; 317 struct pfkeystat pfkeystat; 318 unsigned first, type; 319 size_t len; 320 321 len = sizeof(struct pfkeystat); 322 if (sysctlbyname("net.key.pfkeystat", &pfkeystat, &len, 0, 0) == -1) 323 return; 324 if (interval && vflag > 0) 325 print_time(); 326 printf ("%s:\n", name); 327 328#define PFKEYDIFF(f) (pfkeystat.f - ppfkeystat.f) 329#define p(f, m) if (PFKEYDIFF(f) || sflag <= 1) \ 330 printf(m, (CAST)PFKEYDIFF(f), plural(PFKEYDIFF(f))) 331 332 /* kernel -> userland */ 333 p(out_total, "\t" LLU " request%s sent to userland\n"); 334 p(out_bytes, "\t" LLU " byte%s sent to userland\n"); 335 for (first = 1, type = 0; 336 type < sizeof(pfkeystat.out_msgtype)/sizeof(pfkeystat.out_msgtype[0]); 337 type++) { 338 if (PFKEYDIFF(out_msgtype[type]) <= 0) 339 continue; 340 if (first) { 341 printf("\thistogram by message type:\n"); 342 first = 0; 343 } 344 printf("\t\t%s: " LLU "\n", pfkey_msgtype_names(type), 345 (CAST)PFKEYDIFF(out_msgtype[type])); 346 } 347 p(out_invlen, "\t" LLU " message%s with invalid length field\n"); 348 p(out_invver, "\t" LLU " message%s with invalid version field\n"); 349 p(out_invmsgtype, "\t" LLU " message%s with invalid message type field\n"); 350 p(out_tooshort, "\t" LLU " message%s too short\n"); 351 p(out_nomem, "\t" LLU " message%s with memory allocation failure\n"); 352 p(out_dupext, "\t" LLU " message%s with duplicate extension\n"); 353 p(out_invexttype, "\t" LLU " message%s with invalid extension type\n"); 354 p(out_invsatype, "\t" LLU " message%s with invalid sa type\n"); 355 p(out_invaddr, "\t" LLU " message%s with invalid address extension\n"); 356 357 /* userland -> kernel */ 358 p(in_total, "\t" LLU " request%s sent from userland\n"); 359 p(in_bytes, "\t" LLU " byte%s sent from userland\n"); 360 for (first = 1, type = 0; 361 type < sizeof(pfkeystat.in_msgtype)/sizeof(pfkeystat.in_msgtype[0]); 362 type++) { 363 if (PFKEYDIFF(in_msgtype[type]) <= 0) 364 continue; 365 if (first) { 366 printf("\thistogram by message type:\n"); 367 first = 0; 368 } 369 printf("\t\t%s: " LLU "\n", pfkey_msgtype_names(type), 370 (CAST)PFKEYDIFF(in_msgtype[type])); 371 } 372 p(in_msgtarget[KEY_SENDUP_ONE], 373 "\t" LLU " message%s toward single socket\n"); 374 p(in_msgtarget[KEY_SENDUP_ALL], 375 "\t" LLU " message%s toward all sockets\n"); 376 p(in_msgtarget[KEY_SENDUP_REGISTERED], 377 "\t" LLU " message%s toward registered sockets\n"); 378 p(in_nomem, "\t" LLU " message%s with memory allocation failure\n"); 379 380 if (interval > 0) 381 bcopy(&pfkeystat, &ppfkeystat, len); 382#undef PFKEYDIFF 383#undef p 384} 385#endif /*IPSEC*/ 386