1*d7198e62Smsaitoh /* $NetBSD: fast_ipsec.c,v 1.24 2022/09/01 10:10:20 msaitoh Exp $ */
285b3ba5bSjonathan /* $FreeBSD: src/tools/tools/crypto/ipsecstats.c,v 1.1.4.1 2003/06/03 00:13:13 sam Exp $ */
385b3ba5bSjonathan
485b3ba5bSjonathan /*-
585b3ba5bSjonathan * Copyright (c) 2003, 2004 Jonathan Stone
685b3ba5bSjonathan * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
785b3ba5bSjonathan * All rights reserved.
885b3ba5bSjonathan *
985b3ba5bSjonathan * Redistribution and use in source and binary forms, with or without
1085b3ba5bSjonathan * modification, are permitted provided that the following conditions
1185b3ba5bSjonathan * are met:
1285b3ba5bSjonathan * 1. Redistributions of source code must retain the above copyright
1385b3ba5bSjonathan * notice, this list of conditions and the following disclaimer.
1485b3ba5bSjonathan * 2. Redistributions in binary form must reproduce the above copyright
1585b3ba5bSjonathan * notice, this list of conditions and the following disclaimer in the
1685b3ba5bSjonathan * documentation and/or other materials provided with the distribution.
1785b3ba5bSjonathan *
1885b3ba5bSjonathan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1985b3ba5bSjonathan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2085b3ba5bSjonathan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2185b3ba5bSjonathan * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2285b3ba5bSjonathan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2385b3ba5bSjonathan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2485b3ba5bSjonathan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2585b3ba5bSjonathan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2685b3ba5bSjonathan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2785b3ba5bSjonathan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2885b3ba5bSjonathan * SUCH DAMAGE.
2985b3ba5bSjonathan *
3085b3ba5bSjonathan * $FreeBSD: src/tools/tools/crypto/ipsecstats.c,v 1.1.4.1 2003/06/03 00:13:13 sam Exp $
3185b3ba5bSjonathan */
3285b3ba5bSjonathan
3385b3ba5bSjonathan #include <sys/cdefs.h>
3485b3ba5bSjonathan #ifndef lint
3585b3ba5bSjonathan #ifdef __NetBSD__
36*d7198e62Smsaitoh __RCSID("$NetBSD: fast_ipsec.c,v 1.24 2022/09/01 10:10:20 msaitoh Exp $");
3785b3ba5bSjonathan #endif
3885b3ba5bSjonathan #endif /* not lint*/
3985b3ba5bSjonathan
4085b3ba5bSjonathan /* Kernel headers required, but not included, by netstat.h */
4185b3ba5bSjonathan #include <sys/types.h>
4285b3ba5bSjonathan #include <sys/socket.h>
4385b3ba5bSjonathan
4485b3ba5bSjonathan /* Kernel headers for sysctl(3). */
4585b3ba5bSjonathan #include <sys/param.h>
4685b3ba5bSjonathan #include <sys/sysctl.h>
4785b3ba5bSjonathan
4885b3ba5bSjonathan /* Kernel headers for FAST_IPSEC statistics */
4985b3ba5bSjonathan #include <net/pfkeyv2.h>
5085b3ba5bSjonathan #include <netipsec/esp_var.h>
5185b3ba5bSjonathan #include <netipsec/ah_var.h>
5285b3ba5bSjonathan #include <netipsec/ipip_var.h>
5385b3ba5bSjonathan #include <netipsec/ipcomp_var.h>
5485b3ba5bSjonathan #include <netipsec/ipsec_var.h>
5585b3ba5bSjonathan
566e4bb32aSpetrov #include <machine/int_fmtio.h>
576e4bb32aSpetrov
589ce7ce6bSrpaulo #include <kvm.h>
5985b3ba5bSjonathan #include <err.h>
6014eee8f4Satatat #include <errno.h>
6185b3ba5bSjonathan #include <stdio.h>
6285b3ba5bSjonathan #include <string.h>
6385b3ba5bSjonathan
6485b3ba5bSjonathan #include "netstat.h"
65fc2fae23Skamil #include "prog_ops.h"
6685b3ba5bSjonathan
6785b3ba5bSjonathan /*
6885b3ba5bSjonathan * Table-driven mapping from SADB algorithm codes to string names.
6985b3ba5bSjonathan */
7085b3ba5bSjonathan struct alg {
7185b3ba5bSjonathan int a;
7285b3ba5bSjonathan const char *name;
7385b3ba5bSjonathan };
7462446aa1Schristos
7562446aa1Schristos static const char *ahalgs[] = { AH_ALG_STR };
7662446aa1Schristos static const char *espalgs[] = { ESP_ALG_STR };
7762446aa1Schristos static const char *ipcompalgs[] = { IPCOMP_ALG_STR };
7885b3ba5bSjonathan
7985b3ba5bSjonathan static const char *
algname(size_t a,const char * algs[],size_t nalgs)8062446aa1Schristos algname(size_t a, const char *algs[], size_t nalgs)
8185b3ba5bSjonathan {
8285b3ba5bSjonathan static char buf[80];
8385b3ba5bSjonathan
8462446aa1Schristos if (a < nalgs)
8562446aa1Schristos return algs[a];
8662446aa1Schristos snprintf(buf, sizeof(buf), "alg#%zu", a);
8785b3ba5bSjonathan return buf;
8885b3ba5bSjonathan }
8985b3ba5bSjonathan
9085b3ba5bSjonathan /*
9185b3ba5bSjonathan * Print the fast_ipsec statistics.
9285b3ba5bSjonathan * Since NetBSD's netstat(1) seems not to find us for "netstat -s",
9385b3ba5bSjonathan * but does(?) find KAME, be prepared to be called explicitly from
9485b3ba5bSjonathan * netstat's main program for "netstat -s"; but silently do nothing
9585b3ba5bSjonathan * if that happens when we are running on KAME IPsec.
9685b3ba5bSjonathan */
9785b3ba5bSjonathan void
fast_ipsec_stats(u_long off,const char * name)98d5a0caadSlukem fast_ipsec_stats(u_long off, const char *name)
9985b3ba5bSjonathan {
100caf49ea5Sthorpej uint64_t ipsecstats[IPSEC_NSTATS];
101caf49ea5Sthorpej uint64_t ahstats[AH_NSTATS];
102caf49ea5Sthorpej uint64_t espstats[ESP_NSTATS];
103caf49ea5Sthorpej uint64_t ipcs[IPCOMP_NSTATS];
104caf49ea5Sthorpej uint64_t ipips[IPIP_NSTATS];
1056e4bb32aSpetrov int status;
10662446aa1Schristos size_t slen, i;
10785b3ba5bSjonathan
10840edcfedSthorpej if (! use_sysctl) {
10940edcfedSthorpej warnx("IPsec stats not available via KVM.");
11040edcfedSthorpej return;
11140edcfedSthorpej }
11240edcfedSthorpej
113caf49ea5Sthorpej memset(ipsecstats, 0, sizeof(ipsecstats));
114caf49ea5Sthorpej memset(ahstats, 0, sizeof(ahstats));
115caf49ea5Sthorpej memset(espstats, 0, sizeof(espstats));
116caf49ea5Sthorpej memset(ipcs, 0, sizeof(ipcs));
117caf49ea5Sthorpej memset(ipips, 0, sizeof(ipips));
11885b3ba5bSjonathan
11985b3ba5bSjonathan slen = sizeof(ipsecstats);
120*d7198e62Smsaitoh status = prog_sysctlbyname("net.inet.ipsec.ipsecstats",
121*d7198e62Smsaitoh ipsecstats, &slen, NULL, 0);
1227ed35ab9Schristos if (status < 0) {
1237ed35ab9Schristos if (errno == ENOENT)
1247ed35ab9Schristos return;
1257ed35ab9Schristos if (errno != ENOMEM)
12614eee8f4Satatat err(1, "net.inet.ipsec.ipsecstats");
1277ed35ab9Schristos }
12885b3ba5bSjonathan
12985b3ba5bSjonathan slen = sizeof (ahstats);
130*d7198e62Smsaitoh status = prog_sysctlbyname("net.inet.ah.ah_stats",
131*d7198e62Smsaitoh ahstats, &slen, NULL, 0);
13214eee8f4Satatat if (status < 0 && errno != ENOMEM)
13314eee8f4Satatat err(1, "net.inet.ah.ah_stats");
13414eee8f4Satatat
13585b3ba5bSjonathan slen = sizeof (espstats);
136*d7198e62Smsaitoh status = prog_sysctlbyname("net.inet.esp.esp_stats",
137*d7198e62Smsaitoh espstats, &slen, NULL, 0);
13814eee8f4Satatat if (status < 0 && errno != ENOMEM)
13914eee8f4Satatat err(1, "net.inet.esp.esp_stats");
14014eee8f4Satatat
14114eee8f4Satatat slen = sizeof(ipcs);
142*d7198e62Smsaitoh status = prog_sysctlbyname("net.inet.ipcomp.ipcomp_stats",
143*d7198e62Smsaitoh ipcs, &slen, NULL, 0);
14414eee8f4Satatat if (status < 0 && errno != ENOMEM)
14514eee8f4Satatat err(1, "net.inet.ipcomp.ipcomp_stats");
14614eee8f4Satatat
14714eee8f4Satatat slen = sizeof(ipips);
148*d7198e62Smsaitoh status = prog_sysctlbyname("net.inet.ipip.ipip_stats",
149*d7198e62Smsaitoh ipips, &slen, NULL, 0);
15014eee8f4Satatat if (status < 0 && errno != ENOMEM)
15114eee8f4Satatat err(1, "net.inet.ipip.ipip_stats");
15285b3ba5bSjonathan
1535bd67db9Sozaki-r printf("%s:\n", name);
15485b3ba5bSjonathan
155*d7198e62Smsaitoh #define STAT(x, fmt) \
156*d7198e62Smsaitoh if (ipsecstats[x] || sflag <= 1) \
157*d7198e62Smsaitoh printf("\t%"PRIu64" " fmt "\n", ipsecstats[x])
158*d7198e62Smsaitoh
159caf49ea5Sthorpej if (ipsecstats[IPSEC_STAT_IN_POLVIO]+ipsecstats[IPSEC_STAT_OUT_POLVIO])
160*d7198e62Smsaitoh printf("\t%"PRIu64" policy violations: %"PRIu64" input %"
161*d7198e62Smsaitoh PRIu64" output\n",
162caf49ea5Sthorpej ipsecstats[IPSEC_STAT_IN_POLVIO] + ipsecstats[IPSEC_STAT_OUT_POLVIO],
163caf49ea5Sthorpej ipsecstats[IPSEC_STAT_IN_POLVIO], ipsecstats[IPSEC_STAT_OUT_POLVIO]);
164*d7198e62Smsaitoh STAT(IPSEC_STAT_OUT_NOSA, "no SA found (output)");
165*d7198e62Smsaitoh STAT(IPSEC_STAT_OUT_NOMEM, "no memory available (output)");
166*d7198e62Smsaitoh STAT(IPSEC_STAT_OUT_NOROUTE, "no route available (output)");
167*d7198e62Smsaitoh STAT(IPSEC_STAT_OUT_INVAL, "generic errors (output)");
168*d7198e62Smsaitoh STAT(IPSEC_STAT_OUT_BUNDLESA, "bundled SA processed (output)");
169*d7198e62Smsaitoh STAT(IPSEC_STAT_SPDCACHELOOKUP, "SPD cache lookups");
170*d7198e62Smsaitoh STAT(IPSEC_STAT_SPDCACHEMISS, "SPD cache misses");
17185b3ba5bSjonathan #undef STAT
17285b3ba5bSjonathan
1735bd67db9Sozaki-r printf("\tah:\n");
174*d7198e62Smsaitoh #define AHSTAT(x, fmt) \
175*d7198e62Smsaitoh if (ahstats[x] || sflag <= 1) \
176*d7198e62Smsaitoh printf("\t\t%"PRIu64" ah " fmt "\n", ahstats[x])
177*d7198e62Smsaitoh
178*d7198e62Smsaitoh AHSTAT(AH_STAT_INPUT, "input packets processed");
179*d7198e62Smsaitoh AHSTAT(AH_STAT_OUTPUT, "output packets processed");
180*d7198e62Smsaitoh AHSTAT(AH_STAT_HDROPS, "headers too short");
181*d7198e62Smsaitoh AHSTAT(AH_STAT_NOPF, "headers for unsupported address family");
182*d7198e62Smsaitoh AHSTAT(AH_STAT_NOTDB, "packets with no SA");
183*d7198e62Smsaitoh AHSTAT(AH_STAT_BADKCR,
184*d7198e62Smsaitoh "packets dropped by crypto returning NULL mbuf");
185*d7198e62Smsaitoh AHSTAT(AH_STAT_BADAUTH, "packets with bad authentication");
186*d7198e62Smsaitoh AHSTAT(AH_STAT_NOXFORM, "packets with no xform");
187*d7198e62Smsaitoh AHSTAT(AH_STAT_QFULL, "packets dropped due to queue full");
188*d7198e62Smsaitoh AHSTAT(AH_STAT_WRAP, "packets dropped for replay counter wrap");
189*d7198e62Smsaitoh AHSTAT(AH_STAT_REPLAY, "packets dropped for possible replay");
190*d7198e62Smsaitoh AHSTAT(AH_STAT_BADAUTHL,
191*d7198e62Smsaitoh "packets dropped for bad authenticator length");
192*d7198e62Smsaitoh AHSTAT(AH_STAT_INVALID, "packets with an invalid SA");
193*d7198e62Smsaitoh AHSTAT(AH_STAT_TOOBIG, "packets too big");
194*d7198e62Smsaitoh AHSTAT(AH_STAT_PDROPS, "packets blocked due to policy");
195*d7198e62Smsaitoh AHSTAT(AH_STAT_CRYPTO, "failed crypto requests");
196*d7198e62Smsaitoh AHSTAT(AH_STAT_TUNNEL, "tunnel sanity check failures");
19785b3ba5bSjonathan
19885b3ba5bSjonathan printf("\tah histogram:\n");
19985b3ba5bSjonathan for (i = 0; i < AH_ALG_MAX; i++)
200caf49ea5Sthorpej if (ahstats[AH_STAT_HIST + i])
201*d7198e62Smsaitoh printf("\t\tah packets with %s: %"PRIu64"\n",
202*d7198e62Smsaitoh algname(i, ahalgs, __arraycount(ahalgs)),
203*d7198e62Smsaitoh ahstats[AH_STAT_HIST + i]);
204*d7198e62Smsaitoh AHSTAT(AH_STAT_IBYTES, "bytes received");
205*d7198e62Smsaitoh AHSTAT(AH_STAT_OBYTES, "bytes transmitted");
20685b3ba5bSjonathan #undef AHSTAT
20785b3ba5bSjonathan
2085bd67db9Sozaki-r printf("\tesp:\n");
209*d7198e62Smsaitoh #define ESPSTAT(x, fmt) \
210*d7198e62Smsaitoh if (espstats[x] || sflag <= 1) \
211*d7198e62Smsaitoh printf("\t\t%"PRIu64" esp " fmt "\n", espstats[x])
212*d7198e62Smsaitoh
213*d7198e62Smsaitoh ESPSTAT(ESP_STAT_INPUT, "input packets processed");
214*d7198e62Smsaitoh ESPSTAT(ESP_STAT_OUTPUT, "output packets processed");
215*d7198e62Smsaitoh ESPSTAT(ESP_STAT_HDROPS, "headers too short");
216*d7198e62Smsaitoh ESPSTAT(ESP_STAT_NOPF, "headers for unsupported address family");
217*d7198e62Smsaitoh ESPSTAT(ESP_STAT_NOTDB, "packets with no SA");
218*d7198e62Smsaitoh ESPSTAT(ESP_STAT_BADKCR,
219*d7198e62Smsaitoh "packets dropped by crypto returning NULL mbuf");
220*d7198e62Smsaitoh ESPSTAT(ESP_STAT_QFULL, "packets dropped due to queue full");
221*d7198e62Smsaitoh ESPSTAT(ESP_STAT_NOXFORM, "packets with no xform");
222*d7198e62Smsaitoh ESPSTAT(ESP_STAT_BADILEN, "packets with bad ilen");
223*d7198e62Smsaitoh ESPSTAT(ESP_STAT_BADENC, "packets with bad encryption");
224*d7198e62Smsaitoh ESPSTAT(ESP_STAT_BADAUTH, "packets with bad authentication");
225*d7198e62Smsaitoh ESPSTAT(ESP_STAT_WRAP, "packets dropped for replay counter wrap");
226*d7198e62Smsaitoh ESPSTAT(ESP_STAT_REPLAY, "packets dropped for possible replay");
227*d7198e62Smsaitoh ESPSTAT(ESP_STAT_INVALID, "packets with an invalid SA");
228*d7198e62Smsaitoh ESPSTAT(ESP_STAT_TOOBIG, "packets too big");
229*d7198e62Smsaitoh ESPSTAT(ESP_STAT_PDROPS, "packets blocked due to policy");
230*d7198e62Smsaitoh ESPSTAT(ESP_STAT_CRYPTO, "failed crypto requests");
231*d7198e62Smsaitoh ESPSTAT(ESP_STAT_TUNNEL, "tunnel sanity check failures");
23285b3ba5bSjonathan printf("\tesp histogram:\n");
23385b3ba5bSjonathan for (i = 0; i < ESP_ALG_MAX; i++)
234caf49ea5Sthorpej if (espstats[ESP_STAT_HIST + i])
235*d7198e62Smsaitoh printf("\t\tesp packets with %s: %"PRIu64"\n",
236*d7198e62Smsaitoh algname(i, espalgs, __arraycount(espalgs)),
237*d7198e62Smsaitoh espstats[ESP_STAT_HIST + i]);
238*d7198e62Smsaitoh ESPSTAT(ESP_STAT_IBYTES, "bytes received");
239*d7198e62Smsaitoh ESPSTAT(ESP_STAT_OBYTES, "bytes transmitted");
24085b3ba5bSjonathan #undef ESPSTAT
2415bd67db9Sozaki-r printf("\tipip:\n");
24285b3ba5bSjonathan
24385b3ba5bSjonathan #define IPIPSTAT(x, fmt) \
244*d7198e62Smsaitoh if (ipips[x] || sflag <= 1) \
245*d7198e62Smsaitoh printf("\t\t%"PRIu64" ipip " fmt "\n", ipips[x])
246*d7198e62Smsaitoh
247*d7198e62Smsaitoh IPIPSTAT(IPIP_STAT_IPACKETS, "total input packets");
248*d7198e62Smsaitoh IPIPSTAT(IPIP_STAT_OPACKETS, "total output packets");
249*d7198e62Smsaitoh IPIPSTAT(IPIP_STAT_HDROPS, "packets too short for header length");
250*d7198e62Smsaitoh IPIPSTAT(IPIP_STAT_QFULL, "packets dropped due to queue full");
251*d7198e62Smsaitoh IPIPSTAT(IPIP_STAT_PDROPS, "packets blocked due to policy");
252*d7198e62Smsaitoh IPIPSTAT(IPIP_STAT_SPOOF, "IP spoofing attempts");
253*d7198e62Smsaitoh IPIPSTAT(IPIP_STAT_FAMILY, "protocol family mismatched");
254*d7198e62Smsaitoh IPIPSTAT(IPIP_STAT_UNSPEC, "missing tunnel-endpoint address");
255*d7198e62Smsaitoh IPIPSTAT(IPIP_STAT_IBYTES, "input bytes received");
256*d7198e62Smsaitoh IPIPSTAT(IPIP_STAT_OBYTES, "output bytes processed");
25785b3ba5bSjonathan #undef IPIPSTAT
25885b3ba5bSjonathan
2595bd67db9Sozaki-r printf("\tipcomp:\n");
26085b3ba5bSjonathan #define IPCOMP(x, fmt) \
261*d7198e62Smsaitoh if (ipcs[x] || sflag <= 1) \
262*d7198e62Smsaitoh printf("\t\t%"PRIu64" ipcomp " fmt "\n", ipcs[x])
26385b3ba5bSjonathan
264*d7198e62Smsaitoh IPCOMP(IPCOMP_STAT_HDROPS, "packets too short for header length");
265*d7198e62Smsaitoh IPCOMP(IPCOMP_STAT_NOPF, "protocol family not supported");
266*d7198e62Smsaitoh IPCOMP(IPCOMP_STAT_NOTDB, "packets with no SA");
267*d7198e62Smsaitoh IPCOMP(IPCOMP_STAT_BADKCR,
268*d7198e62Smsaitoh "packets dropped by crypto returning NULL mbuf");
269*d7198e62Smsaitoh IPCOMP(IPCOMP_STAT_QFULL, "queue full");
270*d7198e62Smsaitoh IPCOMP(IPCOMP_STAT_NOXFORM, "no support for transform");
271*d7198e62Smsaitoh IPCOMP(IPCOMP_STAT_WRAP, "packets dropped for replay counter wrap");
272*d7198e62Smsaitoh IPCOMP(IPCOMP_STAT_INPUT, "input IPcomp packets");
273*d7198e62Smsaitoh IPCOMP(IPCOMP_STAT_OUTPUT, "output IPcomp packets");
274*d7198e62Smsaitoh IPCOMP(IPCOMP_STAT_INVALID, "packets with an invalid SA");
275*d7198e62Smsaitoh IPCOMP(IPCOMP_STAT_TOOBIG, "packets decompressed as too big");
276*d7198e62Smsaitoh IPCOMP(IPCOMP_STAT_MINLEN, "packets too short to be compressed");
277*d7198e62Smsaitoh IPCOMP(IPCOMP_STAT_USELESS,"packet for which compression was useless");
278*d7198e62Smsaitoh IPCOMP(IPCOMP_STAT_PDROPS, "packets blocked due to policy");
279*d7198e62Smsaitoh IPCOMP(IPCOMP_STAT_CRYPTO, "failed crypto requests");
28085b3ba5bSjonathan
2815bd67db9Sozaki-r printf("\tipcomp histogram:\n");
28285b3ba5bSjonathan for (i = 0; i < IPCOMP_ALG_MAX; i++)
283caf49ea5Sthorpej if (ipcs[IPCOMP_STAT_HIST + i])
284*d7198e62Smsaitoh printf("\t\tIPcomp packets with %s: %"PRIu64"\n",
285*d7198e62Smsaitoh algname(i, ipcompalgs, __arraycount(ipcompalgs)),
286*d7198e62Smsaitoh ipcs[IPCOMP_STAT_HIST + i]);
287*d7198e62Smsaitoh IPCOMP(IPCOMP_STAT_IBYTES, "input bytes");
288*d7198e62Smsaitoh IPCOMP(IPCOMP_STAT_OBYTES, "output bytes");
28985b3ba5bSjonathan #undef IPCOMP
29085b3ba5bSjonathan }
291