1/* $NetBSD: fast_ipsec.c,v 1.24 2022/09/01 10:10:20 msaitoh 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.24 2022/09/01 10:10:20 msaitoh 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 56#include <machine/int_fmtio.h> 57 58#include <kvm.h> 59#include <err.h> 60#include <errno.h> 61#include <stdio.h> 62#include <string.h> 63 64#include "netstat.h" 65#include "prog_ops.h" 66 67/* 68 * Table-driven mapping from SADB algorithm codes to string names. 69 */ 70struct alg { 71 int a; 72 const char *name; 73}; 74 75static const char *ahalgs[] = { AH_ALG_STR }; 76static const char *espalgs[] = { ESP_ALG_STR }; 77static const char *ipcompalgs[] = { IPCOMP_ALG_STR }; 78 79static const char * 80algname(size_t a, const char *algs[], size_t nalgs) 81{ 82 static char buf[80]; 83 84 if (a < nalgs) 85 return algs[a]; 86 snprintf(buf, sizeof(buf), "alg#%zu", a); 87 return buf; 88} 89 90/* 91 * Print the fast_ipsec statistics. 92 * Since NetBSD's netstat(1) seems not to find us for "netstat -s", 93 * but does(?) find KAME, be prepared to be called explicitly from 94 * netstat's main program for "netstat -s"; but silently do nothing 95 * if that happens when we are running on KAME IPsec. 96 */ 97void 98fast_ipsec_stats(u_long off, const char *name) 99{ 100 uint64_t ipsecstats[IPSEC_NSTATS]; 101 uint64_t ahstats[AH_NSTATS]; 102 uint64_t espstats[ESP_NSTATS]; 103 uint64_t ipcs[IPCOMP_NSTATS]; 104 uint64_t ipips[IPIP_NSTATS]; 105 int status; 106 size_t slen, i; 107 108 if (! use_sysctl) { 109 warnx("IPsec stats not available via KVM."); 110 return; 111 } 112 113 memset(ipsecstats, 0, sizeof(ipsecstats)); 114 memset(ahstats, 0, sizeof(ahstats)); 115 memset(espstats, 0, sizeof(espstats)); 116 memset(ipcs, 0, sizeof(ipcs)); 117 memset(ipips, 0, sizeof(ipips)); 118 119 slen = sizeof(ipsecstats); 120 status = prog_sysctlbyname("net.inet.ipsec.ipsecstats", 121 ipsecstats, &slen, NULL, 0); 122 if (status < 0) { 123 if (errno == ENOENT) 124 return; 125 if (errno != ENOMEM) 126 err(1, "net.inet.ipsec.ipsecstats"); 127 } 128 129 slen = sizeof (ahstats); 130 status = prog_sysctlbyname("net.inet.ah.ah_stats", 131 ahstats, &slen, NULL, 0); 132 if (status < 0 && errno != ENOMEM) 133 err(1, "net.inet.ah.ah_stats"); 134 135 slen = sizeof (espstats); 136 status = prog_sysctlbyname("net.inet.esp.esp_stats", 137 espstats, &slen, NULL, 0); 138 if (status < 0 && errno != ENOMEM) 139 err(1, "net.inet.esp.esp_stats"); 140 141 slen = sizeof(ipcs); 142 status = prog_sysctlbyname("net.inet.ipcomp.ipcomp_stats", 143 ipcs, &slen, NULL, 0); 144 if (status < 0 && errno != ENOMEM) 145 err(1, "net.inet.ipcomp.ipcomp_stats"); 146 147 slen = sizeof(ipips); 148 status = prog_sysctlbyname("net.inet.ipip.ipip_stats", 149 ipips, &slen, NULL, 0); 150 if (status < 0 && errno != ENOMEM) 151 err(1, "net.inet.ipip.ipip_stats"); 152 153 printf("%s:\n", name); 154 155#define STAT(x, fmt) \ 156 if (ipsecstats[x] || sflag <= 1) \ 157 printf("\t%"PRIu64" " fmt "\n", ipsecstats[x]) 158 159 if (ipsecstats[IPSEC_STAT_IN_POLVIO]+ipsecstats[IPSEC_STAT_OUT_POLVIO]) 160 printf("\t%"PRIu64" policy violations: %"PRIu64" input %" 161 PRIu64" output\n", 162 ipsecstats[IPSEC_STAT_IN_POLVIO] + ipsecstats[IPSEC_STAT_OUT_POLVIO], 163 ipsecstats[IPSEC_STAT_IN_POLVIO], ipsecstats[IPSEC_STAT_OUT_POLVIO]); 164 STAT(IPSEC_STAT_OUT_NOSA, "no SA found (output)"); 165 STAT(IPSEC_STAT_OUT_NOMEM, "no memory available (output)"); 166 STAT(IPSEC_STAT_OUT_NOROUTE, "no route available (output)"); 167 STAT(IPSEC_STAT_OUT_INVAL, "generic errors (output)"); 168 STAT(IPSEC_STAT_OUT_BUNDLESA, "bundled SA processed (output)"); 169 STAT(IPSEC_STAT_SPDCACHELOOKUP, "SPD cache lookups"); 170 STAT(IPSEC_STAT_SPDCACHEMISS, "SPD cache misses"); 171#undef STAT 172 173 printf("\tah:\n"); 174#define AHSTAT(x, fmt) \ 175 if (ahstats[x] || sflag <= 1) \ 176 printf("\t\t%"PRIu64" ah " fmt "\n", ahstats[x]) 177 178 AHSTAT(AH_STAT_INPUT, "input packets processed"); 179 AHSTAT(AH_STAT_OUTPUT, "output packets processed"); 180 AHSTAT(AH_STAT_HDROPS, "headers too short"); 181 AHSTAT(AH_STAT_NOPF, "headers for unsupported address family"); 182 AHSTAT(AH_STAT_NOTDB, "packets with no SA"); 183 AHSTAT(AH_STAT_BADKCR, 184 "packets dropped by crypto returning NULL mbuf"); 185 AHSTAT(AH_STAT_BADAUTH, "packets with bad authentication"); 186 AHSTAT(AH_STAT_NOXFORM, "packets with no xform"); 187 AHSTAT(AH_STAT_QFULL, "packets dropped due to queue full"); 188 AHSTAT(AH_STAT_WRAP, "packets dropped for replay counter wrap"); 189 AHSTAT(AH_STAT_REPLAY, "packets dropped for possible replay"); 190 AHSTAT(AH_STAT_BADAUTHL, 191 "packets dropped for bad authenticator length"); 192 AHSTAT(AH_STAT_INVALID, "packets with an invalid SA"); 193 AHSTAT(AH_STAT_TOOBIG, "packets too big"); 194 AHSTAT(AH_STAT_PDROPS, "packets blocked due to policy"); 195 AHSTAT(AH_STAT_CRYPTO, "failed crypto requests"); 196 AHSTAT(AH_STAT_TUNNEL, "tunnel sanity check failures"); 197 198 printf("\tah histogram:\n"); 199 for (i = 0; i < AH_ALG_MAX; i++) 200 if (ahstats[AH_STAT_HIST + i]) 201 printf("\t\tah packets with %s: %"PRIu64"\n", 202 algname(i, ahalgs, __arraycount(ahalgs)), 203 ahstats[AH_STAT_HIST + i]); 204 AHSTAT(AH_STAT_IBYTES, "bytes received"); 205 AHSTAT(AH_STAT_OBYTES, "bytes transmitted"); 206#undef AHSTAT 207 208 printf("\tesp:\n"); 209#define ESPSTAT(x, fmt) \ 210 if (espstats[x] || sflag <= 1) \ 211 printf("\t\t%"PRIu64" esp " fmt "\n", espstats[x]) 212 213 ESPSTAT(ESP_STAT_INPUT, "input packets processed"); 214 ESPSTAT(ESP_STAT_OUTPUT, "output packets processed"); 215 ESPSTAT(ESP_STAT_HDROPS, "headers too short"); 216 ESPSTAT(ESP_STAT_NOPF, "headers for unsupported address family"); 217 ESPSTAT(ESP_STAT_NOTDB, "packets with no SA"); 218 ESPSTAT(ESP_STAT_BADKCR, 219 "packets dropped by crypto returning NULL mbuf"); 220 ESPSTAT(ESP_STAT_QFULL, "packets dropped due to queue full"); 221 ESPSTAT(ESP_STAT_NOXFORM, "packets with no xform"); 222 ESPSTAT(ESP_STAT_BADILEN, "packets with bad ilen"); 223 ESPSTAT(ESP_STAT_BADENC, "packets with bad encryption"); 224 ESPSTAT(ESP_STAT_BADAUTH, "packets with bad authentication"); 225 ESPSTAT(ESP_STAT_WRAP, "packets dropped for replay counter wrap"); 226 ESPSTAT(ESP_STAT_REPLAY, "packets dropped for possible replay"); 227 ESPSTAT(ESP_STAT_INVALID, "packets with an invalid SA"); 228 ESPSTAT(ESP_STAT_TOOBIG, "packets too big"); 229 ESPSTAT(ESP_STAT_PDROPS, "packets blocked due to policy"); 230 ESPSTAT(ESP_STAT_CRYPTO, "failed crypto requests"); 231 ESPSTAT(ESP_STAT_TUNNEL, "tunnel sanity check failures"); 232 printf("\tesp histogram:\n"); 233 for (i = 0; i < ESP_ALG_MAX; i++) 234 if (espstats[ESP_STAT_HIST + i]) 235 printf("\t\tesp packets with %s: %"PRIu64"\n", 236 algname(i, espalgs, __arraycount(espalgs)), 237 espstats[ESP_STAT_HIST + i]); 238 ESPSTAT(ESP_STAT_IBYTES, "bytes received"); 239 ESPSTAT(ESP_STAT_OBYTES, "bytes transmitted"); 240#undef ESPSTAT 241 printf("\tipip:\n"); 242 243#define IPIPSTAT(x, fmt) \ 244 if (ipips[x] || sflag <= 1) \ 245 printf("\t\t%"PRIu64" ipip " fmt "\n", ipips[x]) 246 247 IPIPSTAT(IPIP_STAT_IPACKETS, "total input packets"); 248 IPIPSTAT(IPIP_STAT_OPACKETS, "total output packets"); 249 IPIPSTAT(IPIP_STAT_HDROPS, "packets too short for header length"); 250 IPIPSTAT(IPIP_STAT_QFULL, "packets dropped due to queue full"); 251 IPIPSTAT(IPIP_STAT_PDROPS, "packets blocked due to policy"); 252 IPIPSTAT(IPIP_STAT_SPOOF, "IP spoofing attempts"); 253 IPIPSTAT(IPIP_STAT_FAMILY, "protocol family mismatched"); 254 IPIPSTAT(IPIP_STAT_UNSPEC, "missing tunnel-endpoint address"); 255 IPIPSTAT(IPIP_STAT_IBYTES, "input bytes received"); 256 IPIPSTAT(IPIP_STAT_OBYTES, "output bytes processed"); 257#undef IPIPSTAT 258 259 printf("\tipcomp:\n"); 260#define IPCOMP(x, fmt) \ 261 if (ipcs[x] || sflag <= 1) \ 262 printf("\t\t%"PRIu64" ipcomp " fmt "\n", ipcs[x]) 263 264 IPCOMP(IPCOMP_STAT_HDROPS, "packets too short for header length"); 265 IPCOMP(IPCOMP_STAT_NOPF, "protocol family not supported"); 266 IPCOMP(IPCOMP_STAT_NOTDB, "packets with no SA"); 267 IPCOMP(IPCOMP_STAT_BADKCR, 268 "packets dropped by crypto returning NULL mbuf"); 269 IPCOMP(IPCOMP_STAT_QFULL, "queue full"); 270 IPCOMP(IPCOMP_STAT_NOXFORM, "no support for transform"); 271 IPCOMP(IPCOMP_STAT_WRAP, "packets dropped for replay counter wrap"); 272 IPCOMP(IPCOMP_STAT_INPUT, "input IPcomp packets"); 273 IPCOMP(IPCOMP_STAT_OUTPUT, "output IPcomp packets"); 274 IPCOMP(IPCOMP_STAT_INVALID, "packets with an invalid SA"); 275 IPCOMP(IPCOMP_STAT_TOOBIG, "packets decompressed as too big"); 276 IPCOMP(IPCOMP_STAT_MINLEN, "packets too short to be compressed"); 277 IPCOMP(IPCOMP_STAT_USELESS,"packet for which compression was useless"); 278 IPCOMP(IPCOMP_STAT_PDROPS, "packets blocked due to policy"); 279 IPCOMP(IPCOMP_STAT_CRYPTO, "failed crypto requests"); 280 281 printf("\tipcomp histogram:\n"); 282 for (i = 0; i < IPCOMP_ALG_MAX; i++) 283 if (ipcs[IPCOMP_STAT_HIST + i]) 284 printf("\t\tIPcomp packets with %s: %"PRIu64"\n", 285 algname(i, ipcompalgs, __arraycount(ipcompalgs)), 286 ipcs[IPCOMP_STAT_HIST + i]); 287 IPCOMP(IPCOMP_STAT_IBYTES, "input bytes"); 288 IPCOMP(IPCOMP_STAT_OBYTES, "output bytes"); 289#undef IPCOMP 290} 291