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