1 /* $FreeBSD$ */ 2 /* $NetBSD: inet.c,v 1.35.2.1 1999/04/29 14:57:08 perry Exp $ */ 3 4 /* 5 * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the project nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 /* 34 * Copyright (c) 1983, 1988, 1993 35 * The Regents of the University of California. All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 3. All advertising materials mentioning features or use of this software 46 * must display the following acknowledgement: 47 * This product includes software developed by the University of 48 * California, Berkeley and its contributors. 49 * 4. Neither the name of the University nor the names of its contributors 50 * may be used to endorse or promote products derived from this software 51 * without specific prior written permission. 52 * 53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 63 * SUCH DAMAGE. 64 */ 65 66 #ifndef lint 67 /* 68 static char sccsid[] = "@(#)inet.c 8.5 (Berkeley) 5/24/95"; 69 */ 70 static const char rcsid[] = 71 "$FreeBSD$"; 72 #endif /* not lint */ 73 74 #include <sys/param.h> 75 #include <sys/queue.h> 76 #include <sys/socket.h> 77 78 #include <netinet/in.h> 79 80 #ifdef IPSEC 81 #include <netinet6/ipsec.h> 82 #include <netkey/keysock.h> 83 #endif 84 85 #include <stdio.h> 86 #include <string.h> 87 #include <unistd.h> 88 #include "netstat.h" 89 90 /* 91 * portability issues: 92 * - bsdi[34] uses PLURAL(), not plural(). 93 * - freebsd2 can't print "unsigned long long" properly. 94 */ 95 /* 96 * XXX see PORTABILITY for the twist 97 */ 98 #define LLU "%llu" 99 #define CAST unsigned long long 100 101 #ifdef IPSEC 102 static const char *ipsec_ahnames[] = { 103 "none", 104 "hmac MD5", 105 "hmac SHA1", 106 "keyed MD5", 107 "keyed SHA1", 108 "null", 109 }; 110 111 static const char *ipsec_espnames[] = { 112 "none", 113 "DES CBC", 114 "3DES CBC", 115 "simple", 116 "blowfish CBC", 117 "CAST128 CBC", 118 "DES derived IV", 119 }; 120 121 static const char *ipsec_compnames[] = { 122 "none", 123 "OUI", 124 "deflate", 125 "LZS", 126 }; 127 128 static const char *pfkey_msgtypenames[] = { 129 "reserved", "getspi", "update", "add", "delete", 130 "get", "acquire", "register", "expire", "flush", 131 "dump", "x_promisc", "x_pchange", "x_spdupdate", "x_spdadd", 132 "x_spddelete", "x_spdget", "x_spdacquire", "x_spddump", "x_spdflush", 133 "x_spdsetidx", "x_spdexpire", "x_spddelete2" 134 }; 135 136 static struct ipsecstat ipsecstat; 137 138 static void print_ipsecstats __P((void)); 139 static const char *pfkey_msgtype_names __P((int)); 140 static void ipsec_hist __P((const u_quad_t *, size_t, const char **, size_t, 141 const char *)); 142 143 /* 144 * Dump IPSEC statistics structure. 145 */ 146 static void 147 ipsec_hist(hist, histmax, name, namemax, title) 148 const u_quad_t *hist; 149 size_t histmax; 150 const char **name; 151 size_t namemax; 152 const char *title; 153 { 154 int first; 155 size_t proto; 156 157 for (first = 1, proto = 0; proto < histmax; proto++) { 158 if (hist[proto] <= 0) 159 continue; 160 if (first) { 161 printf("\t%s histogram:\n", title); 162 first = 0; 163 } 164 if (proto < namemax && name[proto]) { 165 printf("\t\t%s: " LLU "\n", name[proto], 166 (CAST)hist[proto]); 167 } else { 168 printf("\t\t#%ld: " LLU "\n", (long)proto, 169 (CAST)hist[proto]); 170 } 171 } 172 } 173 174 static void 175 print_ipsecstats() 176 { 177 #define p(f, m) if (ipsecstat.f || sflag <= 1) \ 178 printf(m, (CAST)ipsecstat.f, plural(ipsecstat.f)) 179 #define hist(f, n, t) \ 180 ipsec_hist((f), sizeof(f)/sizeof(f[0]), (n), sizeof(n)/sizeof(n[0]), (t)); 181 182 p(in_success, "\t" LLU " inbound packet%s processed successfully\n"); 183 p(in_polvio, "\t" LLU " inbound packet%s violated process security " 184 "policy\n"); 185 p(in_nosa, "\t" LLU " inbound packet%s with no SA available\n"); 186 p(in_inval, "\t" LLU " invalid inbound packet%s\n"); 187 p(in_nomem, "\t" LLU " inbound packet%s failed due to insufficient memory\n"); 188 p(in_badspi, "\t" LLU " inbound packet%s failed getting SPI\n"); 189 p(in_ahreplay, "\t" LLU " inbound packet%s failed on AH replay check\n"); 190 p(in_espreplay, "\t" LLU " inbound packet%s failed on ESP replay check\n"); 191 p(in_ahauthsucc, "\t" LLU " inbound packet%s considered authentic\n"); 192 p(in_ahauthfail, "\t" LLU " inbound packet%s failed on authentication\n"); 193 hist(ipsecstat.in_ahhist, ipsec_ahnames, "AH input"); 194 hist(ipsecstat.in_esphist, ipsec_espnames, "ESP input"); 195 hist(ipsecstat.in_comphist, ipsec_compnames, "IPComp input"); 196 197 p(out_success, "\t" LLU " outbound packet%s processed successfully\n"); 198 p(out_polvio, "\t" LLU " outbound packet%s violated process security " 199 "policy\n"); 200 p(out_nosa, "\t" LLU " outbound packet%s with no SA available\n"); 201 p(out_inval, "\t" LLU " invalid outbound packet%s\n"); 202 p(out_nomem, "\t" LLU " outbound packet%s failed due to insufficient memory\n"); 203 p(out_noroute, "\t" LLU " outbound packet%s with no route\n"); 204 hist(ipsecstat.out_ahhist, ipsec_ahnames, "AH output"); 205 hist(ipsecstat.out_esphist, ipsec_espnames, "ESP output"); 206 hist(ipsecstat.out_comphist, ipsec_compnames, "IPComp output"); 207 #undef p 208 #undef hist 209 } 210 211 void 212 ipsec_stats(off, name) 213 u_long off; 214 char *name; 215 { 216 if (off == 0) 217 return; 218 printf ("%s:\n", name); 219 kread(off, (char *)&ipsecstat, sizeof (ipsecstat)); 220 221 print_ipsecstats(); 222 } 223 224 #if defined(__bsdi__) && _BSDI_VERSION >= 199802 /* bsdi4 only */ 225 void 226 ipsec_stats0(name) 227 char *name; 228 { 229 printf("%s:\n", name); 230 231 skread(name, &ipsecstat_info); 232 233 print_ipsecstats(); 234 } 235 #endif 236 237 static const char * 238 pfkey_msgtype_names(x) 239 int x; 240 { 241 const int max = 242 sizeof(pfkey_msgtypenames)/sizeof(pfkey_msgtypenames[0]); 243 static char buf[10]; 244 245 if (x < max && pfkey_msgtypenames[x]) 246 return pfkey_msgtypenames[x]; 247 snprintf(buf, sizeof(buf), "#%d", x); 248 return buf; 249 } 250 251 void 252 pfkey_stats(off, name) 253 u_long off; 254 char *name; 255 { 256 struct pfkeystat pfkeystat; 257 int first, type; 258 259 if (off == 0) 260 return; 261 printf ("%s:\n", name); 262 kread(off, (char *)&pfkeystat, sizeof(pfkeystat)); 263 264 #define p(f, m) if (pfkeystat.f || sflag <= 1) \ 265 printf(m, (CAST)pfkeystat.f, plural(pfkeystat.f)) 266 267 /* kernel -> userland */ 268 p(out_total, "\t" LLU " request%s sent to userland\n"); 269 p(out_bytes, "\t" LLU " byte%s sent to userland\n"); 270 for (first = 1, type = 0; 271 type < sizeof(pfkeystat.out_msgtype)/sizeof(pfkeystat.out_msgtype[0]); 272 type++) { 273 if (pfkeystat.out_msgtype[type] <= 0) 274 continue; 275 if (first) { 276 printf("\thistogram by message type:\n"); 277 first = 0; 278 } 279 printf("\t\t%s: " LLU "\n", pfkey_msgtype_names(type), 280 (CAST)pfkeystat.out_msgtype[type]); 281 } 282 p(out_invlen, "\t" LLU " message%s with invalid length field\n"); 283 p(out_invver, "\t" LLU " message%s with invalid version field\n"); 284 p(out_invmsgtype, "\t" LLU " message%s with invalid message type field\n"); 285 p(out_tooshort, "\t" LLU " message%s too short\n"); 286 p(out_nomem, "\t" LLU " message%s with memory allocation failure\n"); 287 p(out_dupext, "\t" LLU " message%s with duplicate extension\n"); 288 p(out_invexttype, "\t" LLU " message%s with invalid extension type\n"); 289 p(out_invsatype, "\t" LLU " message%s with invalid sa type\n"); 290 p(out_invaddr, "\t" LLU " message%s with invalid address extension\n"); 291 292 /* userland -> kernel */ 293 p(in_total, "\t" LLU " request%s sent from userland\n"); 294 p(in_bytes, "\t" LLU " byte%s sent from userland\n"); 295 for (first = 1, type = 0; 296 type < sizeof(pfkeystat.in_msgtype)/sizeof(pfkeystat.in_msgtype[0]); 297 type++) { 298 if (pfkeystat.in_msgtype[type] <= 0) 299 continue; 300 if (first) { 301 printf("\thistogram by message type:\n"); 302 first = 0; 303 } 304 printf("\t\t%s: " LLU "\n", pfkey_msgtype_names(type), 305 (CAST)pfkeystat.in_msgtype[type]); 306 } 307 p(in_msgtarget[KEY_SENDUP_ONE], 308 "\t" LLU " message%s toward single socket\n"); 309 p(in_msgtarget[KEY_SENDUP_ALL], 310 "\t" LLU " message%s toward all sockets\n"); 311 p(in_msgtarget[KEY_SENDUP_REGISTERED], 312 "\t" LLU " message%s toward registered sockets\n"); 313 p(in_nomem, "\t" LLU " message%s with memory allocation failure\n"); 314 #undef p 315 } 316 #endif /*IPSEC*/ 317