1/*	$OpenBSD: pfkdump.c,v 1.58 2023/10/10 16:16:16 tobhe Exp $	*/
2
3/*
4 * Copyright (c) 2003 Markus Friedl.  All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include <sys/socket.h>
28#include <sys/time.h>
29#include <sys/sysctl.h>
30#include <sys/queue.h>
31
32#include <net/pfkeyv2.h>
33#include <netinet/ip_ipsp.h>
34#include <netdb.h>
35#include <string.h>
36#include <unistd.h>
37#include <stdlib.h>
38#include <stdio.h>
39#include <err.h>
40#include <errno.h>
41
42#include "ipsecctl.h"
43#include "pfkey.h"
44
45static void	print_proto(struct sadb_ext *, struct sadb_msg *, int);
46static void	print_flow(struct sadb_ext *, struct sadb_msg *, int);
47static void	print_supp(struct sadb_ext *, struct sadb_msg *, int);
48static void	print_prop(struct sadb_ext *, struct sadb_msg *, int);
49static void	print_sens(struct sadb_ext *, struct sadb_msg *, int);
50static void	print_spir(struct sadb_ext *, struct sadb_msg *, int);
51static void	print_policy(struct sadb_ext *, struct sadb_msg *, int);
52static void	print_sa(struct sadb_ext *, struct sadb_msg *, int);
53static void	print_addr(struct sadb_ext *, struct sadb_msg *, int);
54static void	print_key(struct sadb_ext *, struct sadb_msg *, int);
55static void	print_life(struct sadb_ext *, struct sadb_msg *, int);
56static void	print_ident(struct sadb_ext *, struct sadb_msg *, int);
57static void	print_udpenc(struct sadb_ext *, struct sadb_msg *, int);
58static void	print_tag(struct sadb_ext *, struct sadb_msg *, int);
59static void	print_rdomain(struct sadb_ext *, struct sadb_msg *, int);
60static void	print_replay(struct sadb_ext *, struct sadb_msg *, int);
61static void	print_mtu(struct sadb_ext *, struct sadb_msg *, int);
62static void	print_tap(struct sadb_ext *, struct sadb_msg *, int);
63static void	print_satype(struct sadb_ext *, struct sadb_msg *, int);
64static void	print_counter(struct sadb_ext *, struct sadb_msg *, int);
65static void	print_iface(struct sadb_ext *, struct sadb_msg *, int);
66
67static struct idname *lookup(struct idname *, u_int32_t);
68static char    *lookup_name(struct idname *, u_int32_t);
69static void	print_ext(struct sadb_ext *, struct sadb_msg *, int);
70
71void		pfkey_print_raw(u_int8_t *, ssize_t);
72static char	*print_flags(uint32_t);
73
74struct sadb_ext *extensions[SADB_EXT_MAX + 1];
75
76struct idname {
77	u_int32_t id;
78	char *name;
79	void (*func)(struct sadb_ext *, struct sadb_msg *, int);
80};
81
82struct idname ext_types[] = {
83	{ SADB_EXT_RESERVED,		"reserved",		NULL },
84	{ SADB_EXT_SA,			"sa",			print_sa },
85	{ SADB_EXT_LIFETIME_CURRENT,	"lifetime_cur",		print_life },
86	{ SADB_EXT_LIFETIME_HARD,	"lifetime_hard",	print_life },
87	{ SADB_EXT_LIFETIME_SOFT,	"lifetime_soft",	print_life },
88	{ SADB_EXT_ADDRESS_SRC,		"address_src",		print_addr },
89	{ SADB_EXT_ADDRESS_DST,		"address_dst",		print_addr },
90	{ SADB_EXT_ADDRESS_PROXY,	"address_proxy",	print_addr },
91	{ SADB_EXT_KEY_AUTH,		"key_auth",		print_key },
92	{ SADB_EXT_KEY_ENCRYPT,		"key_encrypt",		print_key },
93	{ SADB_EXT_IDENTITY_SRC,	"identity_src",		print_ident },
94	{ SADB_EXT_IDENTITY_DST,	"identity_dst",		print_ident },
95	{ SADB_EXT_SENSITIVITY,		"sensitivity",		print_sens },
96	{ SADB_EXT_PROPOSAL,		"proposal",		print_prop },
97	{ SADB_EXT_SUPPORTED_AUTH,	"supported_auth",	print_supp },
98	{ SADB_EXT_SUPPORTED_ENCRYPT,	"supported_encrypt",	print_supp },
99	{ SADB_EXT_SPIRANGE,		"spirange",		print_spir },
100	{ SADB_X_EXT_SRC_MASK,		"src_mask",		print_addr },
101	{ SADB_X_EXT_DST_MASK,		"dst_mask",		print_addr },
102	{ SADB_X_EXT_PROTOCOL,		"protocol",		print_proto },
103	{ SADB_X_EXT_FLOW_TYPE,		"flow_type",		print_flow },
104	{ SADB_X_EXT_SRC_FLOW,		"src_flow",		print_addr },
105	{ SADB_X_EXT_DST_FLOW,		"dst_flow",		print_addr },
106	{ SADB_X_EXT_SA2,		"sa2",			print_sa },
107	{ SADB_X_EXT_DST2,		"dst2",			print_addr },
108	{ SADB_X_EXT_POLICY,		"policy",		print_policy },
109	{ SADB_X_EXT_SUPPORTED_COMP,	"supported_comp",	print_supp },
110	{ SADB_X_EXT_UDPENCAP,		"udpencap",		print_udpenc },
111	{ SADB_X_EXT_LIFETIME_LASTUSE,	"lifetime_lastuse",	print_life },
112	{ SADB_X_EXT_TAG,		"tag",			print_tag },
113	{ SADB_X_EXT_RDOMAIN,		"rdomain",		print_rdomain },
114	{ SADB_X_EXT_REPLAY,		"replay",		print_replay },
115	{ SADB_X_EXT_MTU,		"mtu",			print_mtu },
116	{ SADB_X_EXT_TAP,		"tap",			print_tap },
117	{ SADB_X_EXT_SATYPE2,		"satype2",		print_satype },
118	{ SADB_X_EXT_COUNTER,		"counter",		print_counter },
119	{ SADB_X_EXT_IFACE,		"interface",		print_iface },
120	{ 0,				NULL,			NULL }
121};
122
123struct idname msg_types[] = {
124	{ SADB_ACQUIRE,			"sadb_acquire",		NULL },
125	{ SADB_ADD,			"sadb_add",		NULL },
126	{ SADB_DELETE,			"sadb_delete",		NULL },
127	{ SADB_DUMP,			"sadb_dump",		NULL },
128	{ SADB_EXPIRE,			"sadb_expire",		NULL },
129	{ SADB_FLUSH,			"sadb_flush",		NULL },
130	{ SADB_GET,			"sadb_get",		NULL },
131	{ SADB_GETSPI,			"sadb_getspi",		NULL },
132	{ SADB_REGISTER,		"sadb_register",	NULL },
133	{ SADB_UPDATE,			"sadb_update",		NULL },
134	{ SADB_X_ADDFLOW,		"sadb_addflow",		NULL },
135	{ SADB_X_ASKPOLICY,		"sadb_askpolicy",	NULL },
136	{ SADB_X_DELFLOW,		"sadb_delflow",		NULL },
137	{ SADB_X_GRPSPIS,		"sadb_grpspis",		NULL },
138	{ SADB_X_PROMISC,		"sadb_promisc",		NULL },
139	{ 0,				NULL,			NULL },
140};
141
142struct idname sa_types[] = {
143	{ SADB_SATYPE_UNSPEC,		"unspec",		NULL },
144	{ SADB_SATYPE_AH,		"ah",			NULL },
145	{ SADB_SATYPE_ESP,		"esp",			NULL },
146	{ SADB_SATYPE_RSVP,		"rsvp",			NULL },
147	{ SADB_SATYPE_OSPFV2,		"ospfv2",		NULL },
148	{ SADB_SATYPE_RIPV2,		"ripv2",		NULL },
149	{ SADB_SATYPE_MIP,		"mip",			NULL },
150	{ SADB_X_SATYPE_IPIP,		"ipip",			NULL },
151	{ SADB_X_SATYPE_TCPSIGNATURE,	"tcpmd5",		NULL },
152	{ SADB_X_SATYPE_IPCOMP,		"ipcomp",		NULL },
153	{ 0,				NULL,			NULL }
154};
155
156struct idname auth_types[] = {
157	{ SADB_AALG_NONE,		"none",			NULL },
158	{ SADB_AALG_MD5HMAC,		"hmac-md5",		NULL },
159	{ SADB_X_AALG_RIPEMD160HMAC,	"hmac-ripemd160",	NULL },
160	{ SADB_AALG_SHA1HMAC,		"hmac-sha1",		NULL },
161	{ SADB_X_AALG_SHA2_256,		"hmac-sha2-256",	NULL },
162	{ SADB_X_AALG_SHA2_384,		"hmac-sha2-384",	NULL },
163	{ SADB_X_AALG_SHA2_512,		"hmac-sha2-512",	NULL },
164	{ SADB_X_AALG_AES128GMAC,	"gmac-aes-128",		NULL },
165	{ SADB_X_AALG_AES192GMAC,	"gmac-aes-192",		NULL },
166	{ SADB_X_AALG_AES256GMAC,	"gmac-aes-256",		NULL },
167	{ SADB_X_AALG_CHACHA20POLY1305,	"chacha20-poly1305",	NULL },
168	{ 0,				NULL,			NULL }
169};
170
171struct idname enc_types[] = {
172	{ SADB_EALG_NONE,		"none",			NULL },
173	{ SADB_EALG_3DESCBC,		"3des-cbc",		NULL },
174	{ SADB_X_EALG_AES,		"aes",			NULL },
175	{ SADB_X_EALG_AESCTR,		"aesctr",		NULL },
176	{ SADB_X_EALG_AESGCM16,		"aes-gcm",		NULL },
177	{ SADB_X_EALG_AESGMAC,		"aes-gmac",		NULL },
178	{ SADB_X_EALG_BLF,		"blowfish",		NULL },
179	{ SADB_X_EALG_CAST,		"cast128",		NULL },
180	{ SADB_EALG_NULL,		"null",			NULL },
181	{ SADB_X_EALG_CHACHA20POLY1305,	"chacha20-poly1305",	NULL },
182	{ 0,				NULL,			NULL }
183};
184
185struct idname comp_types[] = {
186	{ SADB_X_CALG_NONE,		"none",			NULL },
187	{ SADB_X_CALG_OUI,		"oui",			NULL },
188	{ SADB_X_CALG_DEFLATE,		"deflate",		NULL },
189	{ 0,				NULL,			NULL }
190};
191
192struct idname flag_types[] = {
193	{ SADB_SAFLAGS_PFS,		"pfs",			NULL },
194	{ SADB_X_SAFLAGS_TUNNEL,	"tunnel",		NULL },
195	{ SADB_X_SAFLAGS_CHAINDEL,	"chaindel",		NULL },
196	{ SADB_X_SAFLAGS_UDPENCAP,	"udpencap",		NULL },
197	{ SADB_X_SAFLAGS_ESN,		"esn",			NULL },
198	{ 0,				NULL,			NULL }
199};
200
201struct idname identity_types[] = {
202	{ SADB_IDENTTYPE_RESERVED,	"reserved",		NULL },
203	{ SADB_IDENTTYPE_PREFIX,	"prefix",		NULL },
204	{ SADB_IDENTTYPE_FQDN,		"fqdn",			NULL },
205	{ SADB_IDENTTYPE_USERFQDN,	"ufqdn",		NULL },
206	{ SADB_IDENTTYPE_ASN1_DN,	"asn1_dn",		NULL },
207	{ 0,				NULL,			NULL }
208};
209
210struct idname flow_types[] = {
211	{ SADB_X_FLOW_TYPE_USE,		"use",			NULL },
212	{ SADB_X_FLOW_TYPE_ACQUIRE,	"acquire",		NULL },
213	{ SADB_X_FLOW_TYPE_REQUIRE,	"require",		NULL },
214	{ SADB_X_FLOW_TYPE_BYPASS,	"bypass",		NULL },
215	{ SADB_X_FLOW_TYPE_DENY,	"deny",			NULL },
216	{ SADB_X_FLOW_TYPE_DONTACQ,	"dontacq",		NULL },
217	{ 0,				NULL,			NULL }
218};
219
220struct idname states[] = {
221	{ SADB_SASTATE_LARVAL,		"larval",		NULL },
222	{ SADB_SASTATE_MATURE,		"mature",		NULL },
223	{ SADB_SASTATE_DYING,		"dying",		NULL },
224	{ SADB_SASTATE_DEAD,		"dead",			NULL },
225	{ 0,				NULL,			NULL }
226};
227
228static struct idname *
229lookup(struct idname *tab, u_int32_t id)
230{
231	struct idname *entry;
232
233	for (entry = tab; entry->name; entry++)
234		if (entry->id == id)
235			return (entry);
236	return (NULL);
237}
238
239static char *
240lookup_name(struct idname *tab, u_int32_t id)
241{
242	struct idname *entry;
243
244	entry = lookup(tab, id);
245	return (entry ? entry->name : "unknown");
246}
247
248static void
249print_ext(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
250{
251	struct idname *entry;
252
253	if ((entry = lookup(ext_types, ext->sadb_ext_type)) == NULL) {
254		printf("unknown ext: type %u len %u\n",
255		    ext->sadb_ext_type, ext->sadb_ext_len);
256		return;
257	}
258	printf("\t%s: ", entry->name);
259	if (entry->func != NULL)
260		(*entry->func)(ext, msg, opts);
261	else
262		printf("type %u len %u",
263		    ext->sadb_ext_type, ext->sadb_ext_len);
264	printf("\n");
265}
266
267static char *
268print_flags(uint32_t flags)
269{
270	static char fstr[80];
271	struct idname *entry;
272	int len;
273	int i, comma = 0, n;
274
275	len = snprintf(fstr, sizeof(fstr), "%#x<", flags);
276	if (len < 0 || (size_t)len >= sizeof(fstr))
277		return (NULL);
278	for (i = 0; i < 32; i++) {
279		if ((flags & (1 << i)) == 0 ||
280		    (entry = lookup(flag_types, 1 << i)) == NULL)
281			continue;
282		n = snprintf(fstr + len, sizeof(fstr) - len - 1,
283		    comma ? ",%s" : "%s", entry->name);
284		if (n < 0 || (size_t)n >= sizeof(fstr) - len - 1)
285			return (NULL);
286		len += n;
287		comma = 1;
288	}
289	strlcat(fstr, ">", sizeof(fstr));
290
291	return (fstr);
292}
293
294static void
295print_sa(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
296{
297	struct sadb_sa *sa = (struct sadb_sa *)ext;
298
299	if (msg->sadb_msg_satype == SADB_X_SATYPE_IPCOMP)
300		printf("cpi 0x%8.8x comp %s\n",
301		    ntohl(sa->sadb_sa_spi),
302		    lookup_name(comp_types, sa->sadb_sa_encrypt));
303	else
304		printf("spi 0x%8.8x auth %s enc %s\n",
305		    ntohl(sa->sadb_sa_spi),
306		    lookup_name(auth_types, sa->sadb_sa_auth),
307		    lookup_name(enc_types, sa->sadb_sa_encrypt));
308	printf("\t\tstate %s replay %u flags %s",
309	    lookup_name(states, sa->sadb_sa_state),
310	    sa->sadb_sa_replay, print_flags(sa->sadb_sa_flags));
311}
312
313static void
314print_addr(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
315{
316	struct sadb_address *addr = (struct sadb_address *)ext;
317	struct sockaddr *sa;
318	struct sockaddr_in *sin4;
319	struct sockaddr_in6 *sin6;
320	char hbuf[NI_MAXHOST];
321
322	sa = (struct sockaddr *)(addr + 1);
323	if (sa->sa_family == 0)
324		printf("<any>");
325	else if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0,
326	    NI_NUMERICHOST))
327		printf("<could not get numeric hostname>");
328	else
329		printf("%s", hbuf);
330	switch (sa->sa_family) {
331	case AF_INET:
332		sin4 = (struct sockaddr_in *)sa;
333		if (sin4->sin_port)
334			printf(" port %u", ntohs(sin4->sin_port));
335		break;
336	case AF_INET6:
337		sin6 = (struct sockaddr_in6 *)sa;
338		if (sin6->sin6_port)
339			printf(" port %u", ntohs(sin6->sin6_port));
340		break;
341	}
342}
343
344static void
345print_key(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
346{
347	struct sadb_key *key = (struct sadb_key *)ext;
348	u_int8_t *data;
349	int i;
350
351	printf("bits %u: ", key->sadb_key_bits);
352	data = (u_int8_t *)(key + 1);
353	for (i = 0; i < key->sadb_key_bits / 8; i++) {
354		printf("%2.2x", data[i]);
355		data[i] = 0x00;		/* clear sensitive data */
356	}
357}
358
359static void
360print_life(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
361{
362	struct sadb_lifetime *life = (struct sadb_lifetime *)ext;
363
364	printf("alloc %u bytes %llu add %llu first %llu",
365	    life->sadb_lifetime_allocations,
366	    life->sadb_lifetime_bytes,
367	    life->sadb_lifetime_addtime,
368	    life->sadb_lifetime_usetime);
369}
370
371static void
372print_proto(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
373{
374	struct sadb_protocol *proto = (struct sadb_protocol *)ext;
375
376	/* overloaded */
377	if (msg->sadb_msg_type == SADB_X_GRPSPIS)
378		printf("satype %s flags %x",
379		    lookup_name(sa_types, proto->sadb_protocol_proto),
380		    proto->sadb_protocol_flags);
381	else
382		printf("proto %u flags %x",
383		    proto->sadb_protocol_proto, proto->sadb_protocol_flags);
384}
385
386static void
387print_flow(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
388{
389	struct sadb_protocol *proto = (struct sadb_protocol *)ext;
390	char *dir = "unknown";
391
392	switch (proto->sadb_protocol_direction) {
393	case IPSP_DIRECTION_IN:
394		dir = "in";
395		break;
396	case IPSP_DIRECTION_OUT:
397		dir = "out";
398		break;
399	}
400	printf("type %s direction %s",
401	    lookup_name(flow_types, proto->sadb_protocol_proto), dir);
402}
403
404static void
405print_tag(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
406{
407	struct sadb_x_tag *stag = (struct sadb_x_tag *)ext;
408	char *p;
409	int plen;
410
411	p = (char *)(stag + 1);
412	plen = stag->sadb_x_tag_len * 8 - sizeof(*stag);
413	printf("%.*s", plen, p);
414}
415
416static void
417print_replay(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
418{
419	struct sadb_x_replay *sreplay = (struct sadb_x_replay *)ext;
420
421	printf("rpl %llu", sreplay->sadb_x_replay_count);
422}
423
424static void
425print_mtu(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
426{
427	struct sadb_x_mtu *smtu = (struct sadb_x_mtu *)ext;
428
429	printf("mtu %u", smtu->sadb_x_mtu_mtu);
430}
431
432static void
433print_tap(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
434{
435	struct sadb_x_tap *stap = (struct sadb_x_tap *)ext;
436
437	printf("enc%u", stap->sadb_x_tap_unit);
438}
439
440static void
441print_satype(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
442{
443	struct sadb_protocol *proto = (struct sadb_protocol *)ext;
444
445	printf("type %s", lookup_name(sa_types, proto->sadb_protocol_proto));
446}
447
448static void
449print_counter(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
450{
451	struct sadb_x_counter *scnt = (struct sadb_x_counter *)ext;
452
453	printf("\n");
454
455#define plural(n) ((n) != 1 ? "s" : "")
456#define p(f, m) if (scnt->f || opts & IPSECCTL_OPT_VERBOSE2) \
457	printf(m, scnt->f, plural(scnt->f))
458	p(sadb_x_counter_ipackets, "\t\t%llu input packet%s\n");
459	p(sadb_x_counter_opackets, "\t\t%llu output packet%s\n");
460	p(sadb_x_counter_ibytes, "\t\t%llu input byte%s\n");
461	p(sadb_x_counter_obytes, "\t\t%llu output byte%s\n");
462	p(sadb_x_counter_idecompbytes, "\t\t%llu input byte%s, decompressed\n");
463	p(sadb_x_counter_ouncompbytes,"\t\t%llu output byte%s, uncompressed\n");
464	p(sadb_x_counter_idrops, "\t\t%llu packet%s dropped on input\n");
465	p(sadb_x_counter_odrops, "\t\t%llu packet%s dropped on output\n");
466#undef p
467#undef plural
468}
469
470static void
471print_iface(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
472{
473	struct sadb_x_iface *siface = (struct sadb_x_iface *)ext;
474	const char *dir = "unknown";
475
476	switch (siface->sadb_x_iface_direction) {
477	case IPSP_DIRECTION_IN:
478		dir = "in";
479		break;
480	case IPSP_DIRECTION_OUT:
481		dir = "out";
482		break;
483	}
484
485	printf("sec%u direction %s", siface->sadb_x_iface_unit, dir);
486}
487
488static char *
489alg_by_ext(u_int8_t ext_type, u_int8_t id)
490{
491	switch (ext_type) {
492	case SADB_EXT_SUPPORTED_ENCRYPT:
493		return lookup_name(enc_types, id);
494	case SADB_EXT_SUPPORTED_AUTH:
495		return lookup_name(auth_types, id);
496	case SADB_X_EXT_SUPPORTED_COMP:
497		return lookup_name(comp_types, id);
498	default:
499		return "unknown";
500	}
501}
502
503static void
504print_alg(struct sadb_alg *alg, u_int8_t ext_type)
505{
506	printf("\t\t%s iv %u min %u max %u",
507	    alg_by_ext(ext_type, alg->sadb_alg_id), alg->sadb_alg_ivlen,
508	    alg->sadb_alg_minbits, alg->sadb_alg_maxbits);
509}
510
511static void
512print_supp(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
513{
514	struct sadb_supported *supported = (struct sadb_supported *)ext;
515	struct sadb_alg *alg;
516
517	printf("\n");
518	for (alg = (struct sadb_alg *)(supported + 1);
519	    (size_t)((u_int8_t *)alg - (u_int8_t *)ext) <
520	    ext->sadb_ext_len * PFKEYV2_CHUNK;
521	    alg++) {
522		struct sadb_alg *next = alg + 1;
523		print_alg(alg, ext->sadb_ext_type);
524		if ((size_t)((u_int8_t *)next - (u_int8_t *)ext) <
525		    ext->sadb_ext_len * PFKEYV2_CHUNK)
526			printf("\n");
527	}
528}
529
530static void
531print_comb(struct sadb_comb *comb, struct sadb_msg *msg, int opts)
532{
533	printf("\t\tauth %s min %u max %u\n"
534	    "\t\tenc %s min %u max %u\n"
535	    "\t\taddtime hard %llu soft %llu\n"
536	    "\t\tusetime hard %llu soft %llu",
537	    lookup_name(auth_types, comb->sadb_comb_auth),
538	    comb->sadb_comb_auth_minbits,
539	    comb->sadb_comb_auth_maxbits,
540	    lookup_name(enc_types, comb->sadb_comb_encrypt),
541	    comb->sadb_comb_encrypt_minbits,
542	    comb->sadb_comb_encrypt_maxbits,
543	    comb->sadb_comb_soft_addtime,
544	    comb->sadb_comb_hard_addtime,
545	    comb->sadb_comb_soft_usetime,
546	    comb->sadb_comb_hard_usetime);
547#if 0
548	    comb->sadb_comb_flags,
549	    comb->sadb_comb_reserved,
550	    comb->sadb_comb_soft_allocations,
551	    comb->sadb_comb_hard_allocations,
552	    comb->sadb_comb_soft_bytes,
553	    comb->sadb_comb_hard_bytes,
554#endif
555}
556
557static void
558print_prop(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
559{
560	struct sadb_prop *prop = (struct sadb_prop *)ext;
561	struct sadb_comb *comb;
562
563	printf("replay %u\n", prop->sadb_prop_replay);
564	for (comb = (struct sadb_comb *)(prop + 1);
565	    (size_t)((u_int8_t *)comb - (u_int8_t *)ext) <
566	    ext->sadb_ext_len * PFKEYV2_CHUNK;
567	    comb++)
568		print_comb(comb, msg, opts);
569}
570
571static void
572print_sens(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
573{
574	struct sadb_sens *sens = (struct sadb_sens *)ext;
575
576	printf("dpd %u sens_level %u integ_level %u",
577	    sens->sadb_sens_dpd,
578	    sens->sadb_sens_sens_level,
579	    sens->sadb_sens_integ_level);
580}
581
582static void
583print_spir(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
584{
585	struct sadb_spirange *spirange = (struct sadb_spirange *)ext;
586
587	printf("min 0x%8.8x max 0x%8.8x",
588	    spirange->sadb_spirange_min, spirange->sadb_spirange_max);
589}
590
591static void
592print_ident(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
593{
594	struct sadb_ident *ident = (struct sadb_ident *)ext;
595	int ilen;
596
597	ilen = ident->sadb_ident_len * 8 - sizeof(*ident);
598	printf("type %s id %llu: %.*s",
599	    lookup_name(identity_types, ident->sadb_ident_type),
600	    ident->sadb_ident_id, ilen, (char *)(ident + 1));
601}
602
603static void
604print_policy(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
605{
606	struct sadb_x_policy *x_policy = (struct sadb_x_policy *)ext;
607
608	printf("seq %u", x_policy->sadb_x_policy_seq);
609}
610
611static void
612print_udpenc(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
613{
614	struct sadb_x_udpencap *x_udpencap = (struct sadb_x_udpencap *)ext;
615
616	printf("udpencap port %u", ntohs(x_udpencap->sadb_x_udpencap_port));
617}
618
619static void
620print_rdomain(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
621{
622	struct sadb_x_rdomain *srdomain = (struct sadb_x_rdomain *)ext;
623
624	printf("%d/%d", srdomain->sadb_x_rdomain_dom1,
625	    srdomain->sadb_x_rdomain_dom2);
626}
627
628static void
629setup_extensions(struct sadb_msg *msg)
630{
631	struct sadb_ext *ext;
632
633	bzero(extensions, sizeof(extensions));
634	if (msg->sadb_msg_len == 0)
635		return;
636	for (ext = (struct sadb_ext *)(msg + 1);
637	    (size_t)((u_int8_t *)ext - (u_int8_t *)msg) <
638	    msg->sadb_msg_len * PFKEYV2_CHUNK && ext->sadb_ext_len > 0;
639	    ext = (struct sadb_ext *)((u_int8_t *)ext +
640	    ext->sadb_ext_len * PFKEYV2_CHUNK))
641		extensions[ext->sadb_ext_type] = ext;
642}
643
644static void
645parse_addr(struct sadb_ext *ext, struct ipsec_addr_wrap *ipa)
646{
647	struct sadb_address *addr = (struct sadb_address *)ext;
648	struct sockaddr *sa;
649
650	if (addr == NULL)
651		return;
652	sa = (struct sockaddr *)(addr + 1);
653	switch (sa->sa_family) {
654	case AF_INET:
655		ipa->address.v4 = ((struct sockaddr_in *)sa)->sin_addr;
656		set_ipmask(ipa, 32);
657		break;
658	case AF_INET6:
659		ipa->address.v6 = ((struct sockaddr_in6 *)sa)->sin6_addr;
660		set_ipmask(ipa, 128);
661		break;
662	}
663	ipa->af = sa->sa_family;
664	ipa->next = NULL;
665	ipa->tail = ipa;
666}
667
668static void
669parse_key(struct sadb_ext *ext, struct ipsec_key *ikey)
670{
671	struct sadb_key *key = (struct sadb_key *)ext;
672	u_int8_t *data;
673
674	if (key == NULL)
675		return;
676	data = (u_int8_t *)(key + 1);
677	ikey->data = data;
678	ikey->len = key->sadb_key_bits / 8;
679}
680
681static void
682parse_satype(struct sadb_ext *ext, u_int8_t *satype)
683{
684	struct sadb_protocol *proto = (struct sadb_protocol *)ext;
685
686	if (proto == NULL)
687		return;
688	switch (proto->sadb_protocol_proto) {
689	case SADB_SATYPE_ESP:
690		*satype = IPSEC_ESP;
691		break;
692	case SADB_SATYPE_AH:
693		*satype = IPSEC_AH;
694		break;
695	case SADB_X_SATYPE_IPCOMP:
696		*satype = IPSEC_IPCOMP;
697		break;
698	case SADB_X_SATYPE_IPIP:
699		*satype = IPSEC_IPIP;
700		break;
701	default:
702		return;
703	}
704}
705
706u_int32_t
707pfkey_get_spi(struct sadb_msg *msg)
708{
709	struct sadb_sa *sa;
710
711	setup_extensions(msg);
712	sa = (struct sadb_sa *)extensions[SADB_EXT_SA];
713	return (ntohl(sa->sadb_sa_spi));
714}
715
716/* opposite of pfkey_sa() */
717void
718pfkey_print_sa(struct sadb_msg *msg, int opts)
719{
720	int i;
721	struct ipsec_rule r;
722	struct ipsec_key enckey, authkey;
723	struct ipsec_transforms xfs;
724	struct ipsec_addr_wrap src, dst, dst2;
725	struct sadb_sa *sa, *sa2;
726
727	setup_extensions(msg);
728	sa = (struct sadb_sa *)extensions[SADB_EXT_SA];
729	bzero(&r, sizeof r);
730	r.type |= RULE_SA;
731	r.tmode = (msg->sadb_msg_satype != SADB_X_SATYPE_TCPSIGNATURE) &&
732	    (sa->sadb_sa_flags & SADB_X_SAFLAGS_TUNNEL) ?
733	    IPSEC_TUNNEL : IPSEC_TRANSPORT;
734	r.spi = ntohl(sa->sadb_sa_spi);
735
736	switch (msg->sadb_msg_satype) {
737	case SADB_SATYPE_AH:
738		r.satype = IPSEC_AH;
739		break;
740	case SADB_SATYPE_ESP:
741		r.satype = IPSEC_ESP;
742		break;
743	case SADB_X_SATYPE_IPCOMP:
744		r.satype = IPSEC_IPCOMP;
745		break;
746	case SADB_X_SATYPE_TCPSIGNATURE:
747		r.satype = IPSEC_TCPMD5;
748		break;
749	case SADB_X_SATYPE_IPIP:
750		r.satype = IPSEC_IPIP;
751		break;
752	default:
753		return;
754	}
755	bzero(&dst, sizeof dst);
756	bzero(&src, sizeof src);
757	parse_addr(extensions[SADB_EXT_ADDRESS_SRC], &src);
758	parse_addr(extensions[SADB_EXT_ADDRESS_DST], &dst);
759	r.src = &src;
760	r.dst = &dst;
761	if (r.satype == IPSEC_IPCOMP) {
762		if (sa->sadb_sa_encrypt) {
763			bzero(&xfs, sizeof xfs);
764			r.xfs = &xfs;
765			switch (sa->sadb_sa_encrypt) {
766			case SADB_X_CALG_DEFLATE:
767				xfs.compxf = &compxfs[COMPXF_DEFLATE];
768				break;
769			}
770		}
771	} else if (r.satype == IPSEC_TCPMD5) {
772		bzero(&authkey, sizeof authkey);
773		parse_key(extensions[SADB_EXT_KEY_AUTH], &authkey);
774		r.authkey = &authkey;
775	} else if (sa->sadb_sa_encrypt || sa->sadb_sa_auth) {
776		bzero(&xfs, sizeof xfs);
777		r.xfs = &xfs;
778		if (sa->sadb_sa_encrypt) {
779			bzero(&enckey, sizeof enckey);
780			parse_key(extensions[SADB_EXT_KEY_ENCRYPT], &enckey);
781			r.enckey = &enckey;
782
783			switch (sa->sadb_sa_encrypt) {
784			case SADB_EALG_3DESCBC:
785				xfs.encxf = &encxfs[ENCXF_3DES_CBC];
786				break;
787			case SADB_X_EALG_AES:
788				switch (r.enckey->len) {
789				case 192/8:
790					xfs.encxf = &encxfs[ENCXF_AES_192];
791					break;
792				case 256/8:
793					xfs.encxf = &encxfs[ENCXF_AES_256];
794					break;
795				default:
796					xfs.encxf = &encxfs[ENCXF_AES];
797					break;
798				}
799				break;
800			case SADB_X_EALG_AESCTR:
801				switch (r.enckey->len) {
802				case 28:
803					xfs.encxf = &encxfs[ENCXF_AES_192_CTR];
804					break;
805				case 36:
806					xfs.encxf = &encxfs[ENCXF_AES_256_CTR];
807					break;
808				default:
809					xfs.encxf = &encxfs[ENCXF_AESCTR];
810					break;
811				}
812				break;
813			case SADB_X_EALG_AESGCM16:
814				switch (r.enckey->len) {
815				case 28:
816					xfs.encxf = &encxfs[ENCXF_AES_192_GCM];
817					break;
818				case 36:
819					xfs.encxf = &encxfs[ENCXF_AES_256_GCM];
820					break;
821				default:
822					xfs.encxf = &encxfs[ENCXF_AES_128_GCM];
823					break;
824				}
825				break;
826			case SADB_X_EALG_AESGMAC:
827				switch (r.enckey->len) {
828				case 28:
829					xfs.encxf = &encxfs[ENCXF_AES_192_GMAC];
830					break;
831				case 36:
832					xfs.encxf = &encxfs[ENCXF_AES_256_GMAC];
833					break;
834				default:
835					xfs.encxf = &encxfs[ENCXF_AES_128_GMAC];
836					break;
837				}
838				break;
839			case SADB_X_EALG_BLF:
840				xfs.encxf = &encxfs[ENCXF_BLOWFISH];
841				break;
842			case SADB_X_EALG_CAST:
843				xfs.encxf = &encxfs[ENCXF_CAST128];
844				break;
845			case SADB_X_EALG_CHACHA20POLY1305:
846				xfs.encxf = &encxfs[ENCXF_CHACHA20_POLY1305];
847				break;
848			case SADB_EALG_NULL:
849				xfs.encxf = &encxfs[ENCXF_NULL];
850				break;
851			}
852		}
853		if (sa->sadb_sa_auth) {
854			bzero(&authkey, sizeof authkey);
855			parse_key(extensions[SADB_EXT_KEY_AUTH], &authkey);
856			r.authkey = &authkey;
857
858			switch (sa->sadb_sa_auth) {
859			case SADB_AALG_MD5HMAC:
860				xfs.authxf = &authxfs[AUTHXF_HMAC_MD5];
861				break;
862			case SADB_X_AALG_RIPEMD160HMAC:
863				xfs.authxf = &authxfs[AUTHXF_HMAC_RIPEMD160];
864				break;
865			case SADB_AALG_SHA1HMAC:
866				xfs.authxf = &authxfs[AUTHXF_HMAC_SHA1];
867				break;
868			case SADB_X_AALG_SHA2_256:
869				xfs.authxf = &authxfs[AUTHXF_HMAC_SHA2_256];
870				break;
871			case SADB_X_AALG_SHA2_384:
872				xfs.authxf = &authxfs[AUTHXF_HMAC_SHA2_384];
873				break;
874			case SADB_X_AALG_SHA2_512:
875				xfs.authxf = &authxfs[AUTHXF_HMAC_SHA2_512];
876				break;
877			}
878		}
879	}
880	if (!(opts & IPSECCTL_OPT_SHOWKEY)) {
881		bzero(&enckey, sizeof enckey);
882		bzero(&authkey, sizeof authkey);
883		extensions[SADB_EXT_KEY_AUTH] = NULL;
884		extensions[SADB_EXT_KEY_ENCRYPT] = NULL;
885	}
886	if (extensions[SADB_X_EXT_SA2]) {
887		r.type |= RULE_BUNDLE;
888		sa2 = (struct sadb_sa *)extensions[SADB_X_EXT_SA2];
889		r.spi2 = ntohl(sa2->sadb_sa_spi);
890		parse_addr(extensions[SADB_X_EXT_DST2], &dst2);
891		r.dst2 = &dst2;
892		parse_satype(extensions[SADB_X_EXT_SATYPE2], &r.proto2);
893		r.proto = r.satype;
894	}
895	ipsecctl_print_rule(&r, opts);
896
897	if (opts & IPSECCTL_OPT_VERBOSE) {
898		for (i = 0; i <= SADB_EXT_MAX; i++)
899			if (extensions[i])
900				print_ext(extensions[i], msg, opts);
901	}
902	fflush(stdout);
903}
904
905void
906pfkey_monitor_sa(struct sadb_msg *msg, int opts)
907{
908	int		 i;
909
910	setup_extensions(msg);
911
912	printf("%s: satype %s vers %u len %u seq %u pid %u\n",
913	    lookup_name(msg_types, msg->sadb_msg_type),
914	    lookup_name(sa_types, msg->sadb_msg_satype),
915	    msg->sadb_msg_version, msg->sadb_msg_len,
916	    msg->sadb_msg_seq,
917	    msg->sadb_msg_pid);
918	if (msg->sadb_msg_errno)
919		printf("\terrno %u: %s\n", msg->sadb_msg_errno,
920		    strerror(msg->sadb_msg_errno));
921	for (i = 0; i <= SADB_EXT_MAX; i++)
922		if (extensions[i])
923			print_ext(extensions[i], msg, opts);
924	fflush(stdout);
925}
926
927void
928pfkey_print_raw(u_int8_t *data, ssize_t len)
929{
930	int i;
931	const u_int8_t *sp = (const u_int8_t *)data;
932
933	printf("RAW PFKEYV2 MESSAGE:\n");
934	for (i = 0; i < len; i++) {
935		if ((i % 8 == 0) && (i != 0))
936			printf("\n");
937		printf("%02x ", *sp);
938		sp++;
939	}
940	printf("\n");
941}
942