xref: /openbsd-src/sbin/ipsecctl/pfkdump.c (revision c4f11a127652779ac3804b8bfaeb83b0f4b24955)
1*c4f11a12Stobhe /*	$OpenBSD: pfkdump.c,v 1.58 2023/10/10 16:16:16 tobhe Exp $	*/
23dd59ad2Shshoexer 
33dd59ad2Shshoexer /*
43dd59ad2Shshoexer  * Copyright (c) 2003 Markus Friedl.  All rights reserved.
53dd59ad2Shshoexer  *
63dd59ad2Shshoexer  * Redistribution and use in source and binary forms, with or without
73dd59ad2Shshoexer  * modification, are permitted provided that the following conditions
83dd59ad2Shshoexer  * are met:
93dd59ad2Shshoexer  * 1. Redistributions of source code must retain the above copyright
103dd59ad2Shshoexer  *    notice, this list of conditions and the following disclaimer.
113dd59ad2Shshoexer  * 2. Redistributions in binary form must reproduce the above copyright
123dd59ad2Shshoexer  *    notice, this list of conditions and the following disclaimer in the
133dd59ad2Shshoexer  *    documentation and/or other materials provided with the distribution.
143dd59ad2Shshoexer  *
153dd59ad2Shshoexer  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
163dd59ad2Shshoexer  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
173dd59ad2Shshoexer  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
183dd59ad2Shshoexer  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
193dd59ad2Shshoexer  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
203dd59ad2Shshoexer  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
213dd59ad2Shshoexer  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
223dd59ad2Shshoexer  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
233dd59ad2Shshoexer  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
243dd59ad2Shshoexer  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
253dd59ad2Shshoexer  */
26b9fc9a72Sderaadt 
273dd59ad2Shshoexer #include <sys/socket.h>
283dd59ad2Shshoexer #include <sys/time.h>
293dd59ad2Shshoexer #include <sys/sysctl.h>
300bfe572bSmpi #include <sys/queue.h>
317fc6e3f0Smpi 
323dd59ad2Shshoexer #include <net/pfkeyv2.h>
333dd59ad2Shshoexer #include <netinet/ip_ipsp.h>
343dd59ad2Shshoexer #include <netdb.h>
353dd59ad2Shshoexer #include <string.h>
363dd59ad2Shshoexer #include <unistd.h>
373dd59ad2Shshoexer #include <stdlib.h>
383dd59ad2Shshoexer #include <stdio.h>
393dd59ad2Shshoexer #include <err.h>
40ae5feee3Smillert #include <errno.h>
413dd59ad2Shshoexer 
423dd59ad2Shshoexer #include "ipsecctl.h"
433dd59ad2Shshoexer #include "pfkey.h"
443dd59ad2Shshoexer 
457fc6e3f0Smpi static void	print_proto(struct sadb_ext *, struct sadb_msg *, int);
467fc6e3f0Smpi static void	print_flow(struct sadb_ext *, struct sadb_msg *, int);
477fc6e3f0Smpi static void	print_supp(struct sadb_ext *, struct sadb_msg *, int);
487fc6e3f0Smpi static void	print_prop(struct sadb_ext *, struct sadb_msg *, int);
497fc6e3f0Smpi static void	print_sens(struct sadb_ext *, struct sadb_msg *, int);
507fc6e3f0Smpi static void	print_spir(struct sadb_ext *, struct sadb_msg *, int);
517fc6e3f0Smpi static void	print_policy(struct sadb_ext *, struct sadb_msg *, int);
527fc6e3f0Smpi static void	print_sa(struct sadb_ext *, struct sadb_msg *, int);
537fc6e3f0Smpi static void	print_addr(struct sadb_ext *, struct sadb_msg *, int);
547fc6e3f0Smpi static void	print_key(struct sadb_ext *, struct sadb_msg *, int);
557fc6e3f0Smpi static void	print_life(struct sadb_ext *, struct sadb_msg *, int);
567fc6e3f0Smpi static void	print_ident(struct sadb_ext *, struct sadb_msg *, int);
577fc6e3f0Smpi static void	print_udpenc(struct sadb_ext *, struct sadb_msg *, int);
587fc6e3f0Smpi static void	print_tag(struct sadb_ext *, struct sadb_msg *, int);
59f5924638Stobhe static void	print_rdomain(struct sadb_ext *, struct sadb_msg *, int);
60094e3f7dStobhe static void	print_replay(struct sadb_ext *, struct sadb_msg *, int);
6149c3446eStobhe static void	print_mtu(struct sadb_ext *, struct sadb_msg *, int);
627fc6e3f0Smpi static void	print_tap(struct sadb_ext *, struct sadb_msg *, int);
637fc6e3f0Smpi static void	print_satype(struct sadb_ext *, struct sadb_msg *, int);
647fc6e3f0Smpi static void	print_counter(struct sadb_ext *, struct sadb_msg *, int);
658fd570bdSdlg static void	print_iface(struct sadb_ext *, struct sadb_msg *, int);
663dd59ad2Shshoexer 
67fd81a95bSmikeb static struct idname *lookup(struct idname *, u_int32_t);
68fd81a95bSmikeb static char    *lookup_name(struct idname *, u_int32_t);
697fc6e3f0Smpi static void	print_ext(struct sadb_ext *, struct sadb_msg *, int);
703dd59ad2Shshoexer 
718a87fca6Smsf void		pfkey_print_raw(u_int8_t *, ssize_t);
72fd81a95bSmikeb static char	*print_flags(uint32_t);
733dd59ad2Shshoexer 
7494de6926Smarkus struct sadb_ext *extensions[SADB_EXT_MAX + 1];
7595f27d1eShshoexer 
763dd59ad2Shshoexer struct idname {
77fd81a95bSmikeb 	u_int32_t id;
783dd59ad2Shshoexer 	char *name;
797fc6e3f0Smpi 	void (*func)(struct sadb_ext *, struct sadb_msg *, int);
803dd59ad2Shshoexer };
813dd59ad2Shshoexer 
823dd59ad2Shshoexer struct idname ext_types[] = {
833dd59ad2Shshoexer 	{ SADB_EXT_RESERVED,		"reserved",		NULL },
843dd59ad2Shshoexer 	{ SADB_EXT_SA,			"sa",			print_sa },
853dd59ad2Shshoexer 	{ SADB_EXT_LIFETIME_CURRENT,	"lifetime_cur",		print_life },
863dd59ad2Shshoexer 	{ SADB_EXT_LIFETIME_HARD,	"lifetime_hard",	print_life },
873dd59ad2Shshoexer 	{ SADB_EXT_LIFETIME_SOFT,	"lifetime_soft",	print_life },
883dd59ad2Shshoexer 	{ SADB_EXT_ADDRESS_SRC,		"address_src",		print_addr },
893dd59ad2Shshoexer 	{ SADB_EXT_ADDRESS_DST,		"address_dst",		print_addr },
908a87fca6Smsf 	{ SADB_EXT_ADDRESS_PROXY,	"address_proxy",	print_addr },
913dd59ad2Shshoexer 	{ SADB_EXT_KEY_AUTH,		"key_auth",		print_key },
923dd59ad2Shshoexer 	{ SADB_EXT_KEY_ENCRYPT,		"key_encrypt",		print_key },
933dd59ad2Shshoexer 	{ SADB_EXT_IDENTITY_SRC,	"identity_src",		print_ident },
943dd59ad2Shshoexer 	{ SADB_EXT_IDENTITY_DST,	"identity_dst",		print_ident },
958a87fca6Smsf 	{ SADB_EXT_SENSITIVITY,		"sensitivity",		print_sens },
968a87fca6Smsf 	{ SADB_EXT_PROPOSAL,		"proposal",		print_prop },
978a87fca6Smsf 	{ SADB_EXT_SUPPORTED_AUTH,	"supported_auth",	print_supp },
988a87fca6Smsf 	{ SADB_EXT_SUPPORTED_ENCRYPT,	"supported_encrypt",	print_supp },
998a87fca6Smsf 	{ SADB_EXT_SPIRANGE,		"spirange",		print_spir },
1008a87fca6Smsf 	{ SADB_X_EXT_SRC_MASK,		"src_mask",		print_addr },
1018a87fca6Smsf 	{ SADB_X_EXT_DST_MASK,		"dst_mask",		print_addr },
1028a87fca6Smsf 	{ SADB_X_EXT_PROTOCOL,		"protocol",		print_proto },
1038a87fca6Smsf 	{ SADB_X_EXT_FLOW_TYPE,		"flow_type",		print_flow },
1048a87fca6Smsf 	{ SADB_X_EXT_SRC_FLOW,		"src_flow",		print_addr },
1058a87fca6Smsf 	{ SADB_X_EXT_DST_FLOW,		"dst_flow",		print_addr },
1068a87fca6Smsf 	{ SADB_X_EXT_SA2,		"sa2",			print_sa },
1078a87fca6Smsf 	{ SADB_X_EXT_DST2,		"dst2",			print_addr },
1088a87fca6Smsf 	{ SADB_X_EXT_POLICY,		"policy",		print_policy },
1098a87fca6Smsf 	{ SADB_X_EXT_SUPPORTED_COMP,	"supported_comp",	print_supp },
1103dd59ad2Shshoexer 	{ SADB_X_EXT_UDPENCAP,		"udpencap",		print_udpenc },
1113dd59ad2Shshoexer 	{ SADB_X_EXT_LIFETIME_LASTUSE,	"lifetime_lastuse",	print_life },
112aa920ac7Sreyk 	{ SADB_X_EXT_TAG,		"tag",			print_tag },
113f5924638Stobhe 	{ SADB_X_EXT_RDOMAIN,		"rdomain",		print_rdomain },
114094e3f7dStobhe 	{ SADB_X_EXT_REPLAY,		"replay",		print_replay },
11549c3446eStobhe 	{ SADB_X_EXT_MTU,		"mtu",			print_mtu },
1160d5acc6aSreyk 	{ SADB_X_EXT_TAP,		"tap",			print_tap },
117d44c51a1Sbluhm 	{ SADB_X_EXT_SATYPE2,		"satype2",		print_satype },
1187fc6e3f0Smpi 	{ SADB_X_EXT_COUNTER,		"counter",		print_counter },
1198fd570bdSdlg 	{ SADB_X_EXT_IFACE,		"interface",		print_iface },
1203dd59ad2Shshoexer 	{ 0,				NULL,			NULL }
1213dd59ad2Shshoexer };
1223dd59ad2Shshoexer 
1238a87fca6Smsf struct idname msg_types[] = {
1248a87fca6Smsf 	{ SADB_ACQUIRE,			"sadb_acquire",		NULL },
1258a87fca6Smsf 	{ SADB_ADD,			"sadb_add",		NULL },
1268a87fca6Smsf 	{ SADB_DELETE,			"sadb_delete",		NULL },
1278a87fca6Smsf 	{ SADB_DUMP,			"sadb_dump",		NULL },
1288a87fca6Smsf 	{ SADB_EXPIRE,			"sadb_expire",		NULL },
1298a87fca6Smsf 	{ SADB_FLUSH,			"sadb_flush",		NULL },
1308a87fca6Smsf 	{ SADB_GET,			"sadb_get",		NULL },
1318a87fca6Smsf 	{ SADB_GETSPI,			"sadb_getspi",		NULL },
1328a87fca6Smsf 	{ SADB_REGISTER,		"sadb_register",	NULL },
1338a87fca6Smsf 	{ SADB_UPDATE,			"sadb_update",		NULL },
1348a87fca6Smsf 	{ SADB_X_ADDFLOW,		"sadb_addflow",		NULL },
1358a87fca6Smsf 	{ SADB_X_ASKPOLICY,		"sadb_askpolicy",	NULL },
1368a87fca6Smsf 	{ SADB_X_DELFLOW,		"sadb_delflow",		NULL },
1378a87fca6Smsf 	{ SADB_X_GRPSPIS,		"sadb_grpspis",		NULL },
1388a87fca6Smsf 	{ SADB_X_PROMISC,		"sadb_promisc",		NULL },
1398a87fca6Smsf 	{ 0,				NULL,			NULL },
1408a87fca6Smsf };
1418a87fca6Smsf 
1423dd59ad2Shshoexer struct idname sa_types[] = {
1433dd59ad2Shshoexer 	{ SADB_SATYPE_UNSPEC,		"unspec",		NULL },
1443dd59ad2Shshoexer 	{ SADB_SATYPE_AH,		"ah",			NULL },
1453dd59ad2Shshoexer 	{ SADB_SATYPE_ESP,		"esp",			NULL },
1463dd59ad2Shshoexer 	{ SADB_SATYPE_RSVP,		"rsvp",			NULL },
1473dd59ad2Shshoexer 	{ SADB_SATYPE_OSPFV2,		"ospfv2",		NULL },
1483dd59ad2Shshoexer 	{ SADB_SATYPE_RIPV2,		"ripv2",		NULL },
1493dd59ad2Shshoexer 	{ SADB_SATYPE_MIP,		"mip",			NULL },
1503dd59ad2Shshoexer 	{ SADB_X_SATYPE_IPIP,		"ipip",			NULL },
1513dd59ad2Shshoexer 	{ SADB_X_SATYPE_TCPSIGNATURE,	"tcpmd5",		NULL },
1523dd59ad2Shshoexer 	{ SADB_X_SATYPE_IPCOMP,		"ipcomp",		NULL },
1533dd59ad2Shshoexer 	{ 0,				NULL,			NULL }
1543dd59ad2Shshoexer };
1553dd59ad2Shshoexer 
1563dd59ad2Shshoexer struct idname auth_types[] = {
1573dd59ad2Shshoexer 	{ SADB_AALG_NONE,		"none",			NULL },
1583dd59ad2Shshoexer 	{ SADB_AALG_MD5HMAC,		"hmac-md5",		NULL },
1593dd59ad2Shshoexer 	{ SADB_X_AALG_RIPEMD160HMAC,	"hmac-ripemd160",	NULL },
1603dd59ad2Shshoexer 	{ SADB_AALG_SHA1HMAC,		"hmac-sha1",		NULL },
1613dd59ad2Shshoexer 	{ SADB_X_AALG_SHA2_256,		"hmac-sha2-256",	NULL },
1623dd59ad2Shshoexer 	{ SADB_X_AALG_SHA2_384,		"hmac-sha2-384",	NULL },
1633dd59ad2Shshoexer 	{ SADB_X_AALG_SHA2_512,		"hmac-sha2-512",	NULL },
164783454c1Smikeb 	{ SADB_X_AALG_AES128GMAC,	"gmac-aes-128",		NULL },
165783454c1Smikeb 	{ SADB_X_AALG_AES192GMAC,	"gmac-aes-192",		NULL },
166783454c1Smikeb 	{ SADB_X_AALG_AES256GMAC,	"gmac-aes-256",		NULL },
167f705960cSmikeb 	{ SADB_X_AALG_CHACHA20POLY1305,	"chacha20-poly1305",	NULL },
1683dd59ad2Shshoexer 	{ 0,				NULL,			NULL }
1693dd59ad2Shshoexer };
1703dd59ad2Shshoexer 
1713dd59ad2Shshoexer struct idname enc_types[] = {
1723dd59ad2Shshoexer 	{ SADB_EALG_NONE,		"none",			NULL },
1733dd59ad2Shshoexer 	{ SADB_EALG_3DESCBC,		"3des-cbc",		NULL },
1743dd59ad2Shshoexer 	{ SADB_X_EALG_AES,		"aes",			NULL },
1753dd59ad2Shshoexer 	{ SADB_X_EALG_AESCTR,		"aesctr",		NULL },
176783454c1Smikeb 	{ SADB_X_EALG_AESGCM16,		"aes-gcm",		NULL },
177783454c1Smikeb 	{ SADB_X_EALG_AESGMAC,		"aes-gmac",		NULL },
1783dd59ad2Shshoexer 	{ SADB_X_EALG_BLF,		"blowfish",		NULL },
1793dd59ad2Shshoexer 	{ SADB_X_EALG_CAST,		"cast128",		NULL },
1803dd59ad2Shshoexer 	{ SADB_EALG_NULL,		"null",			NULL },
181f705960cSmikeb 	{ SADB_X_EALG_CHACHA20POLY1305,	"chacha20-poly1305",	NULL },
1823dd59ad2Shshoexer 	{ 0,				NULL,			NULL }
1833dd59ad2Shshoexer };
1843dd59ad2Shshoexer 
1853dd59ad2Shshoexer struct idname comp_types[] = {
1863dd59ad2Shshoexer 	{ SADB_X_CALG_NONE,		"none",			NULL },
1873dd59ad2Shshoexer 	{ SADB_X_CALG_OUI,		"oui",			NULL },
1883dd59ad2Shshoexer 	{ SADB_X_CALG_DEFLATE,		"deflate",		NULL },
1893dd59ad2Shshoexer 	{ 0,				NULL,			NULL }
1903dd59ad2Shshoexer };
1913dd59ad2Shshoexer 
192fd81a95bSmikeb struct idname flag_types[] = {
193fd81a95bSmikeb 	{ SADB_SAFLAGS_PFS,		"pfs",			NULL },
194fd81a95bSmikeb 	{ SADB_X_SAFLAGS_TUNNEL,	"tunnel",		NULL },
195fd81a95bSmikeb 	{ SADB_X_SAFLAGS_CHAINDEL,	"chaindel",		NULL },
196fd81a95bSmikeb 	{ SADB_X_SAFLAGS_UDPENCAP,	"udpencap",		NULL },
197fd81a95bSmikeb 	{ SADB_X_SAFLAGS_ESN,		"esn",			NULL },
198fd81a95bSmikeb 	{ 0,				NULL,			NULL }
199fd81a95bSmikeb };
200fd81a95bSmikeb 
2013dd59ad2Shshoexer struct idname identity_types[] = {
2023dd59ad2Shshoexer 	{ SADB_IDENTTYPE_RESERVED,	"reserved",		NULL },
2033dd59ad2Shshoexer 	{ SADB_IDENTTYPE_PREFIX,	"prefix",		NULL },
2043dd59ad2Shshoexer 	{ SADB_IDENTTYPE_FQDN,		"fqdn",			NULL },
2053dd59ad2Shshoexer 	{ SADB_IDENTTYPE_USERFQDN,	"ufqdn",		NULL },
206d8131d03Sphessler 	{ SADB_IDENTTYPE_ASN1_DN,	"asn1_dn",		NULL },
2073dd59ad2Shshoexer 	{ 0,				NULL,			NULL }
2083dd59ad2Shshoexer };
2093dd59ad2Shshoexer 
2108a87fca6Smsf struct idname flow_types[] = {
2118a87fca6Smsf 	{ SADB_X_FLOW_TYPE_USE,		"use",			NULL },
2128a87fca6Smsf 	{ SADB_X_FLOW_TYPE_ACQUIRE,	"acquire",		NULL },
2138a87fca6Smsf 	{ SADB_X_FLOW_TYPE_REQUIRE,	"require",		NULL },
2148a87fca6Smsf 	{ SADB_X_FLOW_TYPE_BYPASS,	"bypass",		NULL },
2158a87fca6Smsf 	{ SADB_X_FLOW_TYPE_DENY,	"deny",			NULL },
2168a87fca6Smsf 	{ SADB_X_FLOW_TYPE_DONTACQ,	"dontacq",		NULL },
2178a87fca6Smsf 	{ 0,				NULL,			NULL }
2188a87fca6Smsf };
2198a87fca6Smsf 
2208a87fca6Smsf struct idname states[] = {
2218a87fca6Smsf 	{ SADB_SASTATE_LARVAL,		"larval",		NULL },
2228a87fca6Smsf 	{ SADB_SASTATE_MATURE,		"mature",		NULL },
2238a87fca6Smsf 	{ SADB_SASTATE_DYING,		"dying",		NULL },
2248a87fca6Smsf 	{ SADB_SASTATE_DEAD,		"dead",			NULL },
2258a87fca6Smsf 	{ 0,				NULL,			NULL }
2268a87fca6Smsf };
2278a87fca6Smsf 
2283dd59ad2Shshoexer static struct idname *
lookup(struct idname * tab,u_int32_t id)229fd81a95bSmikeb lookup(struct idname *tab, u_int32_t id)
2303dd59ad2Shshoexer {
2313dd59ad2Shshoexer 	struct idname *entry;
2323dd59ad2Shshoexer 
2333dd59ad2Shshoexer 	for (entry = tab; entry->name; entry++)
2343dd59ad2Shshoexer 		if (entry->id == id)
2353dd59ad2Shshoexer 			return (entry);
2363dd59ad2Shshoexer 	return (NULL);
2373dd59ad2Shshoexer }
2383dd59ad2Shshoexer 
2393dd59ad2Shshoexer static char *
lookup_name(struct idname * tab,u_int32_t id)240fd81a95bSmikeb lookup_name(struct idname *tab, u_int32_t id)
2413dd59ad2Shshoexer {
2423dd59ad2Shshoexer 	struct idname *entry;
2433dd59ad2Shshoexer 
2443dd59ad2Shshoexer 	entry = lookup(tab, id);
2453dd59ad2Shshoexer 	return (entry ? entry->name : "unknown");
2463dd59ad2Shshoexer }
2473dd59ad2Shshoexer 
2483dd59ad2Shshoexer static void
print_ext(struct sadb_ext * ext,struct sadb_msg * msg,int opts)2497fc6e3f0Smpi print_ext(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
2503dd59ad2Shshoexer {
2513dd59ad2Shshoexer 	struct idname *entry;
2523dd59ad2Shshoexer 
2533dd59ad2Shshoexer 	if ((entry = lookup(ext_types, ext->sadb_ext_type)) == NULL) {
2543dd59ad2Shshoexer 		printf("unknown ext: type %u len %u\n",
2553dd59ad2Shshoexer 		    ext->sadb_ext_type, ext->sadb_ext_len);
2563dd59ad2Shshoexer 		return;
2573dd59ad2Shshoexer 	}
2583dd59ad2Shshoexer 	printf("\t%s: ", entry->name);
2593dd59ad2Shshoexer 	if (entry->func != NULL)
2607fc6e3f0Smpi 		(*entry->func)(ext, msg, opts);
2613dd59ad2Shshoexer 	else
2628685c612Smsf 		printf("type %u len %u",
2633dd59ad2Shshoexer 		    ext->sadb_ext_type, ext->sadb_ext_len);
2648685c612Smsf 	printf("\n");
2653dd59ad2Shshoexer }
2663dd59ad2Shshoexer 
267fd81a95bSmikeb static char *
print_flags(uint32_t flags)268fd81a95bSmikeb print_flags(uint32_t flags)
269fd81a95bSmikeb {
270fd81a95bSmikeb 	static char fstr[80];
271fd81a95bSmikeb 	struct idname *entry;
272515e489cSderaadt 	int len;
27379d7816aSderaadt 	int i, comma = 0, n;
274fd81a95bSmikeb 
275fd81a95bSmikeb 	len = snprintf(fstr, sizeof(fstr), "%#x<", flags);
27614c62822Stobhe 	if (len < 0 || (size_t)len >= sizeof(fstr))
27779d7816aSderaadt 		return (NULL);
278fd81a95bSmikeb 	for (i = 0; i < 32; i++) {
279fd81a95bSmikeb 		if ((flags & (1 << i)) == 0 ||
280fd81a95bSmikeb 		    (entry = lookup(flag_types, 1 << i)) == NULL)
281fd81a95bSmikeb 			continue;
28279d7816aSderaadt 		n = snprintf(fstr + len, sizeof(fstr) - len - 1,
283fd81a95bSmikeb 		    comma ? ",%s" : "%s", entry->name);
28414c62822Stobhe 		if (n < 0 || (size_t)n >= sizeof(fstr) - len - 1)
28579d7816aSderaadt 			return (NULL);
28679d7816aSderaadt 		len += n;
287fd81a95bSmikeb 		comma = 1;
288fd81a95bSmikeb 	}
289fd81a95bSmikeb 	strlcat(fstr, ">", sizeof(fstr));
290fd81a95bSmikeb 
291fd81a95bSmikeb 	return (fstr);
292fd81a95bSmikeb }
293fd81a95bSmikeb 
2943dd59ad2Shshoexer static void
print_sa(struct sadb_ext * ext,struct sadb_msg * msg,int opts)2957fc6e3f0Smpi print_sa(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
2963dd59ad2Shshoexer {
2973dd59ad2Shshoexer 	struct sadb_sa *sa = (struct sadb_sa *)ext;
2983dd59ad2Shshoexer 
29905f7f063Shshoexer 	if (msg->sadb_msg_satype == SADB_X_SATYPE_IPCOMP)
3000c77d9beSmarkus 		printf("cpi 0x%8.8x comp %s\n",
3010c77d9beSmarkus 		    ntohl(sa->sadb_sa_spi),
3020c77d9beSmarkus 		    lookup_name(comp_types, sa->sadb_sa_encrypt));
3030c77d9beSmarkus 	else
3040c77d9beSmarkus 		printf("spi 0x%8.8x auth %s enc %s\n",
3050c77d9beSmarkus 		    ntohl(sa->sadb_sa_spi),
3060c77d9beSmarkus 		    lookup_name(auth_types, sa->sadb_sa_auth),
3070c77d9beSmarkus 		    lookup_name(enc_types, sa->sadb_sa_encrypt));
308fd81a95bSmikeb 	printf("\t\tstate %s replay %u flags %s",
3090c77d9beSmarkus 	    lookup_name(states, sa->sadb_sa_state),
310fd81a95bSmikeb 	    sa->sadb_sa_replay, print_flags(sa->sadb_sa_flags));
3113dd59ad2Shshoexer }
3123dd59ad2Shshoexer 
3133dd59ad2Shshoexer static void
print_addr(struct sadb_ext * ext,struct sadb_msg * msg,int opts)3147fc6e3f0Smpi print_addr(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
3153dd59ad2Shshoexer {
3163dd59ad2Shshoexer 	struct sadb_address *addr = (struct sadb_address *)ext;
3173dd59ad2Shshoexer 	struct sockaddr *sa;
3183dd59ad2Shshoexer 	struct sockaddr_in *sin4;
3193dd59ad2Shshoexer 	struct sockaddr_in6 *sin6;
3203dd59ad2Shshoexer 	char hbuf[NI_MAXHOST];
3213dd59ad2Shshoexer 
3223dd59ad2Shshoexer 	sa = (struct sockaddr *)(addr + 1);
3233dd59ad2Shshoexer 	if (sa->sa_family == 0)
3243dd59ad2Shshoexer 		printf("<any>");
3253dd59ad2Shshoexer 	else if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0,
3263dd59ad2Shshoexer 	    NI_NUMERICHOST))
3273dd59ad2Shshoexer 		printf("<could not get numeric hostname>");
3283dd59ad2Shshoexer 	else
3293dd59ad2Shshoexer 		printf("%s", hbuf);
3303dd59ad2Shshoexer 	switch (sa->sa_family) {
3313dd59ad2Shshoexer 	case AF_INET:
3323dd59ad2Shshoexer 		sin4 = (struct sockaddr_in *)sa;
3333dd59ad2Shshoexer 		if (sin4->sin_port)
3343dd59ad2Shshoexer 			printf(" port %u", ntohs(sin4->sin_port));
3353dd59ad2Shshoexer 		break;
3363dd59ad2Shshoexer 	case AF_INET6:
3373dd59ad2Shshoexer 		sin6 = (struct sockaddr_in6 *)sa;
3383dd59ad2Shshoexer 		if (sin6->sin6_port)
3393dd59ad2Shshoexer 			printf(" port %u", ntohs(sin6->sin6_port));
3403dd59ad2Shshoexer 		break;
3413dd59ad2Shshoexer 	}
3423dd59ad2Shshoexer }
3433dd59ad2Shshoexer 
3443dd59ad2Shshoexer static void
print_key(struct sadb_ext * ext,struct sadb_msg * msg,int opts)3457fc6e3f0Smpi print_key(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
3463dd59ad2Shshoexer {
3473dd59ad2Shshoexer 	struct sadb_key *key = (struct sadb_key *)ext;
3483dd59ad2Shshoexer 	u_int8_t *data;
3493dd59ad2Shshoexer 	int i;
3503dd59ad2Shshoexer 
3513dd59ad2Shshoexer 	printf("bits %u: ", key->sadb_key_bits);
3523dd59ad2Shshoexer 	data = (u_int8_t *)(key + 1);
3533dd59ad2Shshoexer 	for (i = 0; i < key->sadb_key_bits / 8; i++) {
3543dd59ad2Shshoexer 		printf("%2.2x", data[i]);
3553dd59ad2Shshoexer 		data[i] = 0x00;		/* clear sensitive data */
3563dd59ad2Shshoexer 	}
3573dd59ad2Shshoexer }
3583dd59ad2Shshoexer 
3593dd59ad2Shshoexer static void
print_life(struct sadb_ext * ext,struct sadb_msg * msg,int opts)3607fc6e3f0Smpi print_life(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
3613dd59ad2Shshoexer {
3623dd59ad2Shshoexer 	struct sadb_lifetime *life = (struct sadb_lifetime *)ext;
3633dd59ad2Shshoexer 
3648685c612Smsf 	printf("alloc %u bytes %llu add %llu first %llu",
3653dd59ad2Shshoexer 	    life->sadb_lifetime_allocations,
3663dd59ad2Shshoexer 	    life->sadb_lifetime_bytes,
3673dd59ad2Shshoexer 	    life->sadb_lifetime_addtime,
3683dd59ad2Shshoexer 	    life->sadb_lifetime_usetime);
3693dd59ad2Shshoexer }
3703dd59ad2Shshoexer 
3718a87fca6Smsf static void
print_proto(struct sadb_ext * ext,struct sadb_msg * msg,int opts)3727fc6e3f0Smpi print_proto(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
3738a87fca6Smsf {
3748a87fca6Smsf 	struct sadb_protocol *proto = (struct sadb_protocol *)ext;
3758a87fca6Smsf 
3768a87fca6Smsf 	/* overloaded */
3778a87fca6Smsf 	if (msg->sadb_msg_type == SADB_X_GRPSPIS)
3786507611dSmarkus 		printf("satype %s flags %x",
3798a87fca6Smsf 		    lookup_name(sa_types, proto->sadb_protocol_proto),
3808a87fca6Smsf 		    proto->sadb_protocol_flags);
3818a87fca6Smsf 	else
3826507611dSmarkus 		printf("proto %u flags %x",
3838a87fca6Smsf 		    proto->sadb_protocol_proto, proto->sadb_protocol_flags);
3848a87fca6Smsf }
3858a87fca6Smsf 
3868a87fca6Smsf static void
print_flow(struct sadb_ext * ext,struct sadb_msg * msg,int opts)3877fc6e3f0Smpi print_flow(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
3888a87fca6Smsf {
3898a87fca6Smsf 	struct sadb_protocol *proto = (struct sadb_protocol *)ext;
3908a87fca6Smsf 	char *dir = "unknown";
3918a87fca6Smsf 
3928a87fca6Smsf 	switch (proto->sadb_protocol_direction) {
3938a87fca6Smsf 	case IPSP_DIRECTION_IN:
3948a87fca6Smsf 		dir = "in";
3958a87fca6Smsf 		break;
3968a87fca6Smsf 	case IPSP_DIRECTION_OUT:
3978a87fca6Smsf 		dir = "out";
3988a87fca6Smsf 		break;
3998a87fca6Smsf 	}
4008a87fca6Smsf 	printf("type %s direction %s",
4018a87fca6Smsf 	    lookup_name(flow_types, proto->sadb_protocol_proto), dir);
4028a87fca6Smsf }
4038a87fca6Smsf 
404aa920ac7Sreyk static void
print_tag(struct sadb_ext * ext,struct sadb_msg * msg,int opts)4057fc6e3f0Smpi print_tag(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
406aa920ac7Sreyk {
407aa920ac7Sreyk 	struct sadb_x_tag *stag = (struct sadb_x_tag *)ext;
408aa920ac7Sreyk 	char *p;
409*c4f11a12Stobhe 	int plen;
410aa920ac7Sreyk 
411aa920ac7Sreyk 	p = (char *)(stag + 1);
412*c4f11a12Stobhe 	plen = stag->sadb_x_tag_len * 8 - sizeof(*stag);
413*c4f11a12Stobhe 	printf("%.*s", plen, p);
414aa920ac7Sreyk }
415aa920ac7Sreyk 
4160d5acc6aSreyk static void
print_replay(struct sadb_ext * ext,struct sadb_msg * msg,int opts)417094e3f7dStobhe print_replay(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
418094e3f7dStobhe {
419094e3f7dStobhe 	struct sadb_x_replay *sreplay = (struct sadb_x_replay *)ext;
420094e3f7dStobhe 
421094e3f7dStobhe 	printf("rpl %llu", sreplay->sadb_x_replay_count);
422094e3f7dStobhe }
423094e3f7dStobhe 
424094e3f7dStobhe static void
print_mtu(struct sadb_ext * ext,struct sadb_msg * msg,int opts)42549c3446eStobhe print_mtu(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
42649c3446eStobhe {
42749c3446eStobhe 	struct sadb_x_mtu *smtu = (struct sadb_x_mtu *)ext;
42849c3446eStobhe 
42949c3446eStobhe 	printf("mtu %u", smtu->sadb_x_mtu_mtu);
43049c3446eStobhe }
43149c3446eStobhe 
43249c3446eStobhe static void
print_tap(struct sadb_ext * ext,struct sadb_msg * msg,int opts)4337fc6e3f0Smpi print_tap(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
4340d5acc6aSreyk {
4350d5acc6aSreyk 	struct sadb_x_tap *stap = (struct sadb_x_tap *)ext;
4360d5acc6aSreyk 
4370d5acc6aSreyk 	printf("enc%u", stap->sadb_x_tap_unit);
4380d5acc6aSreyk }
4390d5acc6aSreyk 
440d44c51a1Sbluhm static void
print_satype(struct sadb_ext * ext,struct sadb_msg * msg,int opts)4417fc6e3f0Smpi print_satype(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
442d44c51a1Sbluhm {
443d44c51a1Sbluhm 	struct sadb_protocol *proto = (struct sadb_protocol *)ext;
444d44c51a1Sbluhm 
445d44c51a1Sbluhm 	printf("type %s", lookup_name(sa_types, proto->sadb_protocol_proto));
446d44c51a1Sbluhm }
447d44c51a1Sbluhm 
4487fc6e3f0Smpi static void
print_counter(struct sadb_ext * ext,struct sadb_msg * msg,int opts)4497fc6e3f0Smpi print_counter(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
4507fc6e3f0Smpi {
4517fc6e3f0Smpi 	struct sadb_x_counter *scnt = (struct sadb_x_counter *)ext;
4527fc6e3f0Smpi 
4537fc6e3f0Smpi 	printf("\n");
4547fc6e3f0Smpi 
4557fc6e3f0Smpi #define plural(n) ((n) != 1 ? "s" : "")
4567fc6e3f0Smpi #define p(f, m) if (scnt->f || opts & IPSECCTL_OPT_VERBOSE2) \
4577fc6e3f0Smpi 	printf(m, scnt->f, plural(scnt->f))
4587fc6e3f0Smpi 	p(sadb_x_counter_ipackets, "\t\t%llu input packet%s\n");
4597fc6e3f0Smpi 	p(sadb_x_counter_opackets, "\t\t%llu output packet%s\n");
4607fc6e3f0Smpi 	p(sadb_x_counter_ibytes, "\t\t%llu input byte%s\n");
4617fc6e3f0Smpi 	p(sadb_x_counter_obytes, "\t\t%llu output byte%s\n");
4627fc6e3f0Smpi 	p(sadb_x_counter_idecompbytes, "\t\t%llu input byte%s, decompressed\n");
4637fc6e3f0Smpi 	p(sadb_x_counter_ouncompbytes,"\t\t%llu output byte%s, uncompressed\n");
4647fc6e3f0Smpi 	p(sadb_x_counter_idrops, "\t\t%llu packet%s dropped on input\n");
4657fc6e3f0Smpi 	p(sadb_x_counter_odrops, "\t\t%llu packet%s dropped on output\n");
4667fc6e3f0Smpi #undef p
4677fc6e3f0Smpi #undef plural
4687fc6e3f0Smpi }
4697fc6e3f0Smpi 
4708fd570bdSdlg static void
print_iface(struct sadb_ext * ext,struct sadb_msg * msg,int opts)4718fd570bdSdlg print_iface(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
4728fd570bdSdlg {
4738fd570bdSdlg 	struct sadb_x_iface *siface = (struct sadb_x_iface *)ext;
4748fd570bdSdlg 	const char *dir = "unknown";
4758fd570bdSdlg 
4768fd570bdSdlg 	switch (siface->sadb_x_iface_direction) {
4778fd570bdSdlg 	case IPSP_DIRECTION_IN:
4788fd570bdSdlg 		dir = "in";
4798fd570bdSdlg 		break;
4808fd570bdSdlg 	case IPSP_DIRECTION_OUT:
4818fd570bdSdlg 		dir = "out";
4828fd570bdSdlg 		break;
4838fd570bdSdlg 	}
4848fd570bdSdlg 
4858fd570bdSdlg 	printf("sec%u direction %s", siface->sadb_x_iface_unit, dir);
4868fd570bdSdlg }
4878fd570bdSdlg 
4888a87fca6Smsf static char *
alg_by_ext(u_int8_t ext_type,u_int8_t id)4898a87fca6Smsf alg_by_ext(u_int8_t ext_type, u_int8_t id)
4908a87fca6Smsf {
4918a87fca6Smsf 	switch (ext_type) {
4928a87fca6Smsf 	case SADB_EXT_SUPPORTED_ENCRYPT:
4938a87fca6Smsf 		return lookup_name(enc_types, id);
4948a87fca6Smsf 	case SADB_EXT_SUPPORTED_AUTH:
4958a87fca6Smsf 		return lookup_name(auth_types, id);
4968a87fca6Smsf 	case SADB_X_EXT_SUPPORTED_COMP:
4978a87fca6Smsf 		return lookup_name(comp_types, id);
4988a87fca6Smsf 	default:
4998a87fca6Smsf 		return "unknown";
5008a87fca6Smsf 	}
5018a87fca6Smsf }
5028a87fca6Smsf 
5038a87fca6Smsf static void
print_alg(struct sadb_alg * alg,u_int8_t ext_type)5048a87fca6Smsf print_alg(struct sadb_alg *alg, u_int8_t ext_type)
5058a87fca6Smsf {
5068685c612Smsf 	printf("\t\t%s iv %u min %u max %u",
5078a87fca6Smsf 	    alg_by_ext(ext_type, alg->sadb_alg_id), alg->sadb_alg_ivlen,
5088a87fca6Smsf 	    alg->sadb_alg_minbits, alg->sadb_alg_maxbits);
5098a87fca6Smsf }
5108a87fca6Smsf 
5118a87fca6Smsf static void
print_supp(struct sadb_ext * ext,struct sadb_msg * msg,int opts)5127fc6e3f0Smpi print_supp(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
5138a87fca6Smsf {
5148a87fca6Smsf 	struct sadb_supported *supported = (struct sadb_supported *)ext;
5158a87fca6Smsf 	struct sadb_alg *alg;
5168a87fca6Smsf 
5178a87fca6Smsf 	printf("\n");
5188a87fca6Smsf 	for (alg = (struct sadb_alg *)(supported + 1);
5198a87fca6Smsf 	    (size_t)((u_int8_t *)alg - (u_int8_t *)ext) <
5208a87fca6Smsf 	    ext->sadb_ext_len * PFKEYV2_CHUNK;
521863d7323Smsf 	    alg++) {
522863d7323Smsf 		struct sadb_alg *next = alg + 1;
5238a87fca6Smsf 		print_alg(alg, ext->sadb_ext_type);
524863d7323Smsf 		if ((size_t)((u_int8_t *)next - (u_int8_t *)ext) <
525863d7323Smsf 		    ext->sadb_ext_len * PFKEYV2_CHUNK)
526863d7323Smsf 			printf("\n");
527863d7323Smsf 	}
5288a87fca6Smsf }
5298a87fca6Smsf 
5308a87fca6Smsf static void
print_comb(struct sadb_comb * comb,struct sadb_msg * msg,int opts)5317fc6e3f0Smpi print_comb(struct sadb_comb *comb, struct sadb_msg *msg, int opts)
5328a87fca6Smsf {
5338a87fca6Smsf 	printf("\t\tauth %s min %u max %u\n"
5348a87fca6Smsf 	    "\t\tenc %s min %u max %u\n"
5358a87fca6Smsf 	    "\t\taddtime hard %llu soft %llu\n"
5368685c612Smsf 	    "\t\tusetime hard %llu soft %llu",
5378a87fca6Smsf 	    lookup_name(auth_types, comb->sadb_comb_auth),
5388a87fca6Smsf 	    comb->sadb_comb_auth_minbits,
5398a87fca6Smsf 	    comb->sadb_comb_auth_maxbits,
5408a87fca6Smsf 	    lookup_name(enc_types, comb->sadb_comb_encrypt),
5418a87fca6Smsf 	    comb->sadb_comb_encrypt_minbits,
5428a87fca6Smsf 	    comb->sadb_comb_encrypt_maxbits,
5438a87fca6Smsf 	    comb->sadb_comb_soft_addtime,
5448a87fca6Smsf 	    comb->sadb_comb_hard_addtime,
5458a87fca6Smsf 	    comb->sadb_comb_soft_usetime,
5468a87fca6Smsf 	    comb->sadb_comb_hard_usetime);
5478a87fca6Smsf #if 0
5488a87fca6Smsf 	    comb->sadb_comb_flags,
5498a87fca6Smsf 	    comb->sadb_comb_reserved,
5508a87fca6Smsf 	    comb->sadb_comb_soft_allocations,
5518a87fca6Smsf 	    comb->sadb_comb_hard_allocations,
5528a87fca6Smsf 	    comb->sadb_comb_soft_bytes,
5538a87fca6Smsf 	    comb->sadb_comb_hard_bytes,
5548a87fca6Smsf #endif
5558a87fca6Smsf }
5568a87fca6Smsf 
5578a87fca6Smsf static void
print_prop(struct sadb_ext * ext,struct sadb_msg * msg,int opts)5587fc6e3f0Smpi print_prop(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
5598a87fca6Smsf {
5608a87fca6Smsf 	struct sadb_prop *prop = (struct sadb_prop *)ext;
5618a87fca6Smsf 	struct sadb_comb *comb;
5628a87fca6Smsf 
563863d7323Smsf 	printf("replay %u\n", prop->sadb_prop_replay);
5648a87fca6Smsf 	for (comb = (struct sadb_comb *)(prop + 1);
5658a87fca6Smsf 	    (size_t)((u_int8_t *)comb - (u_int8_t *)ext) <
5668a87fca6Smsf 	    ext->sadb_ext_len * PFKEYV2_CHUNK;
5678a87fca6Smsf 	    comb++)
5687fc6e3f0Smpi 		print_comb(comb, msg, opts);
5698a87fca6Smsf }
5708a87fca6Smsf 
5718a87fca6Smsf static void
print_sens(struct sadb_ext * ext,struct sadb_msg * msg,int opts)5727fc6e3f0Smpi print_sens(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
5738a87fca6Smsf {
5748a87fca6Smsf 	struct sadb_sens *sens = (struct sadb_sens *)ext;
5758a87fca6Smsf 
5768685c612Smsf 	printf("dpd %u sens_level %u integ_level %u",
5778a87fca6Smsf 	    sens->sadb_sens_dpd,
5788a87fca6Smsf 	    sens->sadb_sens_sens_level,
5798a87fca6Smsf 	    sens->sadb_sens_integ_level);
5808a87fca6Smsf }
5818a87fca6Smsf 
5828a87fca6Smsf static void
print_spir(struct sadb_ext * ext,struct sadb_msg * msg,int opts)5837fc6e3f0Smpi print_spir(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
5848a87fca6Smsf {
5858a87fca6Smsf 	struct sadb_spirange *spirange = (struct sadb_spirange *)ext;
5868a87fca6Smsf 
5878685c612Smsf 	printf("min 0x%8.8x max 0x%8.8x",
5888a87fca6Smsf 	    spirange->sadb_spirange_min, spirange->sadb_spirange_max);
5898a87fca6Smsf }
5908a87fca6Smsf 
5913dd59ad2Shshoexer static void
print_ident(struct sadb_ext * ext,struct sadb_msg * msg,int opts)5927fc6e3f0Smpi print_ident(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
5933dd59ad2Shshoexer {
5943dd59ad2Shshoexer 	struct sadb_ident *ident = (struct sadb_ident *)ext;
595*c4f11a12Stobhe 	int ilen;
5963dd59ad2Shshoexer 
597*c4f11a12Stobhe 	ilen = ident->sadb_ident_len * 8 - sizeof(*ident);
598*c4f11a12Stobhe 	printf("type %s id %llu: %.*s",
5993dd59ad2Shshoexer 	    lookup_name(identity_types, ident->sadb_ident_type),
600*c4f11a12Stobhe 	    ident->sadb_ident_id, ilen, (char *)(ident + 1));
6013dd59ad2Shshoexer }
6023dd59ad2Shshoexer 
6033dd59ad2Shshoexer static void
print_policy(struct sadb_ext * ext,struct sadb_msg * msg,int opts)6047fc6e3f0Smpi print_policy(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
6058a87fca6Smsf {
6068a87fca6Smsf 	struct sadb_x_policy *x_policy = (struct sadb_x_policy *)ext;
6078a87fca6Smsf 
6088685c612Smsf 	printf("seq %u", x_policy->sadb_x_policy_seq);
6098a87fca6Smsf }
6108a87fca6Smsf 
6118a87fca6Smsf static void
print_udpenc(struct sadb_ext * ext,struct sadb_msg * msg,int opts)6127fc6e3f0Smpi print_udpenc(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
6133dd59ad2Shshoexer {
6143dd59ad2Shshoexer 	struct sadb_x_udpencap *x_udpencap = (struct sadb_x_udpencap *)ext;
6153dd59ad2Shshoexer 
6168685c612Smsf 	printf("udpencap port %u", ntohs(x_udpencap->sadb_x_udpencap_port));
6173dd59ad2Shshoexer }
6183dd59ad2Shshoexer 
619f5924638Stobhe static void
print_rdomain(struct sadb_ext * ext,struct sadb_msg * msg,int opts)620f5924638Stobhe print_rdomain(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
621f5924638Stobhe {
622f5924638Stobhe 	struct sadb_x_rdomain *srdomain = (struct sadb_x_rdomain *)ext;
623f5924638Stobhe 
624f5924638Stobhe 	printf("%d/%d", srdomain->sadb_x_rdomain_dom1,
625f5924638Stobhe 	    srdomain->sadb_x_rdomain_dom2);
626f5924638Stobhe }
627f5924638Stobhe 
6288a87fca6Smsf static void
setup_extensions(struct sadb_msg * msg)6298a87fca6Smsf setup_extensions(struct sadb_msg *msg)
6303dd59ad2Shshoexer {
6313dd59ad2Shshoexer 	struct sadb_ext *ext;
63295f27d1eShshoexer 
63395f27d1eShshoexer 	bzero(extensions, sizeof(extensions));
6348a87fca6Smsf 	if (msg->sadb_msg_len == 0)
6358a87fca6Smsf 		return;
6363dd59ad2Shshoexer 	for (ext = (struct sadb_ext *)(msg + 1);
6373dd59ad2Shshoexer 	    (size_t)((u_int8_t *)ext - (u_int8_t *)msg) <
6383dd59ad2Shshoexer 	    msg->sadb_msg_len * PFKEYV2_CHUNK && ext->sadb_ext_len > 0;
6393dd59ad2Shshoexer 	    ext = (struct sadb_ext *)((u_int8_t *)ext +
6403dd59ad2Shshoexer 	    ext->sadb_ext_len * PFKEYV2_CHUNK))
64195f27d1eShshoexer 		extensions[ext->sadb_ext_type] = ext;
6428a87fca6Smsf }
64395f27d1eShshoexer 
6440c77d9beSmarkus static void
parse_addr(struct sadb_ext * ext,struct ipsec_addr_wrap * ipa)6450c77d9beSmarkus parse_addr(struct sadb_ext *ext, struct ipsec_addr_wrap *ipa)
6460c77d9beSmarkus {
6470c77d9beSmarkus 	struct sadb_address *addr = (struct sadb_address *)ext;
6480c77d9beSmarkus 	struct sockaddr *sa;
6490c77d9beSmarkus 
6500c77d9beSmarkus 	if (addr == NULL)
6510c77d9beSmarkus 		return;
6520c77d9beSmarkus 	sa = (struct sockaddr *)(addr + 1);
6530c77d9beSmarkus 	switch (sa->sa_family) {
6540c77d9beSmarkus 	case AF_INET:
6550c77d9beSmarkus 		ipa->address.v4 = ((struct sockaddr_in *)sa)->sin_addr;
6560c77d9beSmarkus 		set_ipmask(ipa, 32);
6570c77d9beSmarkus 		break;
6580c77d9beSmarkus 	case AF_INET6:
6590c77d9beSmarkus 		ipa->address.v6 = ((struct sockaddr_in6 *)sa)->sin6_addr;
6600c77d9beSmarkus 		set_ipmask(ipa, 128);
6610c77d9beSmarkus 		break;
6620c77d9beSmarkus 	}
6630c77d9beSmarkus 	ipa->af = sa->sa_family;
6640c77d9beSmarkus 	ipa->next = NULL;
6650c77d9beSmarkus 	ipa->tail = ipa;
6660c77d9beSmarkus }
6670c77d9beSmarkus 
6680c77d9beSmarkus static void
parse_key(struct sadb_ext * ext,struct ipsec_key * ikey)6690c77d9beSmarkus parse_key(struct sadb_ext *ext, struct ipsec_key *ikey)
6700c77d9beSmarkus {
6710c77d9beSmarkus 	struct sadb_key *key = (struct sadb_key *)ext;
6720c77d9beSmarkus 	u_int8_t *data;
6730c77d9beSmarkus 
6740c77d9beSmarkus 	if (key == NULL)
6750c77d9beSmarkus 		return;
6760c77d9beSmarkus 	data = (u_int8_t *)(key + 1);
6770c77d9beSmarkus 	ikey->data = data;
6780c77d9beSmarkus 	ikey->len = key->sadb_key_bits / 8;
6790c77d9beSmarkus }
6800c77d9beSmarkus 
681fbd50af5Sbluhm static void
parse_satype(struct sadb_ext * ext,u_int8_t * satype)682fbd50af5Sbluhm parse_satype(struct sadb_ext *ext, u_int8_t *satype)
683fbd50af5Sbluhm {
684fbd50af5Sbluhm 	struct sadb_protocol *proto = (struct sadb_protocol *)ext;
685fbd50af5Sbluhm 
686fbd50af5Sbluhm 	if (proto == NULL)
687fbd50af5Sbluhm 		return;
688fbd50af5Sbluhm 	switch (proto->sadb_protocol_proto) {
689fbd50af5Sbluhm 	case SADB_SATYPE_ESP:
690fbd50af5Sbluhm 		*satype = IPSEC_ESP;
691fbd50af5Sbluhm 		break;
692fbd50af5Sbluhm 	case SADB_SATYPE_AH:
693fbd50af5Sbluhm 		*satype = IPSEC_AH;
694fbd50af5Sbluhm 		break;
695fbd50af5Sbluhm 	case SADB_X_SATYPE_IPCOMP:
696fbd50af5Sbluhm 		*satype = IPSEC_IPCOMP;
697fbd50af5Sbluhm 		break;
698fbd50af5Sbluhm 	case SADB_X_SATYPE_IPIP:
699fbd50af5Sbluhm 		*satype = IPSEC_IPIP;
700fbd50af5Sbluhm 		break;
701fbd50af5Sbluhm 	default:
702fbd50af5Sbluhm 		return;
703fbd50af5Sbluhm 	}
704fbd50af5Sbluhm }
705fbd50af5Sbluhm 
706895bd039Smarkus u_int32_t
pfkey_get_spi(struct sadb_msg * msg)707895bd039Smarkus pfkey_get_spi(struct sadb_msg *msg)
708895bd039Smarkus {
709895bd039Smarkus 	struct sadb_sa *sa;
710895bd039Smarkus 
711895bd039Smarkus 	setup_extensions(msg);
712895bd039Smarkus 	sa = (struct sadb_sa *)extensions[SADB_EXT_SA];
713895bd039Smarkus 	return (ntohl(sa->sadb_sa_spi));
714895bd039Smarkus }
715895bd039Smarkus 
7160c77d9beSmarkus /* opposite of pfkey_sa() */
7178a87fca6Smsf void
pfkey_print_sa(struct sadb_msg * msg,int opts)7188a87fca6Smsf pfkey_print_sa(struct sadb_msg *msg, int opts)
7198a87fca6Smsf {
7208a87fca6Smsf 	int i;
7210c77d9beSmarkus 	struct ipsec_rule r;
7220c77d9beSmarkus 	struct ipsec_key enckey, authkey;
7230c77d9beSmarkus 	struct ipsec_transforms xfs;
724fbd50af5Sbluhm 	struct ipsec_addr_wrap src, dst, dst2;
725fbd50af5Sbluhm 	struct sadb_sa *sa, *sa2;
7268a87fca6Smsf 
7278a87fca6Smsf 	setup_extensions(msg);
7280c77d9beSmarkus 	sa = (struct sadb_sa *)extensions[SADB_EXT_SA];
7290c77d9beSmarkus 	bzero(&r, sizeof r);
7300c77d9beSmarkus 	r.type |= RULE_SA;
7310c77d9beSmarkus 	r.tmode = (msg->sadb_msg_satype != SADB_X_SATYPE_TCPSIGNATURE) &&
7320c77d9beSmarkus 	    (sa->sadb_sa_flags & SADB_X_SAFLAGS_TUNNEL) ?
7330c77d9beSmarkus 	    IPSEC_TUNNEL : IPSEC_TRANSPORT;
7340c77d9beSmarkus 	r.spi = ntohl(sa->sadb_sa_spi);
7358685c612Smsf 
7360c77d9beSmarkus 	switch (msg->sadb_msg_satype) {
7370c77d9beSmarkus 	case SADB_SATYPE_AH:
7380c77d9beSmarkus 		r.satype = IPSEC_AH;
7390c77d9beSmarkus 		break;
7400c77d9beSmarkus 	case SADB_SATYPE_ESP:
7410c77d9beSmarkus 		r.satype = IPSEC_ESP;
7420c77d9beSmarkus 		break;
7430c77d9beSmarkus 	case SADB_X_SATYPE_IPCOMP:
7440c77d9beSmarkus 		r.satype = IPSEC_IPCOMP;
7450c77d9beSmarkus 		break;
7460c77d9beSmarkus 	case SADB_X_SATYPE_TCPSIGNATURE:
7470c77d9beSmarkus 		r.satype = IPSEC_TCPMD5;
7480c77d9beSmarkus 		break;
7490c77d9beSmarkus 	case SADB_X_SATYPE_IPIP:
7500c77d9beSmarkus 		r.satype = IPSEC_IPIP;
7510c77d9beSmarkus 		break;
7520c77d9beSmarkus 	default:
7538a87fca6Smsf 		return;
7548a87fca6Smsf 	}
7550c77d9beSmarkus 	bzero(&dst, sizeof dst);
7560c77d9beSmarkus 	bzero(&src, sizeof src);
7570c77d9beSmarkus 	parse_addr(extensions[SADB_EXT_ADDRESS_SRC], &src);
7580c77d9beSmarkus 	parse_addr(extensions[SADB_EXT_ADDRESS_DST], &dst);
7590c77d9beSmarkus 	r.src = &src;
7600c77d9beSmarkus 	r.dst = &dst;
76145ad2739Smarkus 	if (r.satype == IPSEC_IPCOMP) {
76245ad2739Smarkus 		if (sa->sadb_sa_encrypt) {
76345ad2739Smarkus 			bzero(&xfs, sizeof xfs);
76445ad2739Smarkus 			r.xfs = &xfs;
76545ad2739Smarkus 			switch (sa->sadb_sa_encrypt) {
76645ad2739Smarkus 			case SADB_X_CALG_DEFLATE:
767b6ffab99Smarkus 				xfs.compxf = &compxfs[COMPXF_DEFLATE];
76845ad2739Smarkus 				break;
76945ad2739Smarkus 			}
77045ad2739Smarkus 		}
77145ad2739Smarkus 	} else if (r.satype == IPSEC_TCPMD5) {
77245ad2739Smarkus 		bzero(&authkey, sizeof authkey);
77345ad2739Smarkus 		parse_key(extensions[SADB_EXT_KEY_AUTH], &authkey);
77445ad2739Smarkus 		r.authkey = &authkey;
7754b7bcba6Snaddy 	} else if (sa->sadb_sa_encrypt || sa->sadb_sa_auth) {
7760c77d9beSmarkus 		bzero(&xfs, sizeof xfs);
7770c77d9beSmarkus 		r.xfs = &xfs;
7780c77d9beSmarkus 		if (sa->sadb_sa_encrypt) {
779a18fcb51Smarkus 			bzero(&enckey, sizeof enckey);
780a18fcb51Smarkus 			parse_key(extensions[SADB_EXT_KEY_ENCRYPT], &enckey);
781a18fcb51Smarkus 			r.enckey = &enckey;
782a18fcb51Smarkus 
7830c77d9beSmarkus 			switch (sa->sadb_sa_encrypt) {
7840c77d9beSmarkus 			case SADB_EALG_3DESCBC:
7850c77d9beSmarkus 				xfs.encxf = &encxfs[ENCXF_3DES_CBC];
7860c77d9beSmarkus 				break;
7870c77d9beSmarkus 			case SADB_X_EALG_AES:
788a18fcb51Smarkus 				switch (r.enckey->len) {
789a18fcb51Smarkus 				case 192/8:
790a18fcb51Smarkus 					xfs.encxf = &encxfs[ENCXF_AES_192];
791a18fcb51Smarkus 					break;
792a18fcb51Smarkus 				case 256/8:
793a18fcb51Smarkus 					xfs.encxf = &encxfs[ENCXF_AES_256];
794a18fcb51Smarkus 					break;
795a18fcb51Smarkus 				default:
7960c77d9beSmarkus 					xfs.encxf = &encxfs[ENCXF_AES];
7970c77d9beSmarkus 					break;
798a18fcb51Smarkus 				}
799a18fcb51Smarkus 				break;
8000c77d9beSmarkus 			case SADB_X_EALG_AESCTR:
8015f649d51Snaddy 				switch (r.enckey->len) {
8025f649d51Snaddy 				case 28:
8035f649d51Snaddy 					xfs.encxf = &encxfs[ENCXF_AES_192_CTR];
8045f649d51Snaddy 					break;
8055f649d51Snaddy 				case 36:
8065f649d51Snaddy 					xfs.encxf = &encxfs[ENCXF_AES_256_CTR];
8075f649d51Snaddy 					break;
8085f649d51Snaddy 				default:
8090c77d9beSmarkus 					xfs.encxf = &encxfs[ENCXF_AESCTR];
8100c77d9beSmarkus 					break;
8115f649d51Snaddy 				}
8125f649d51Snaddy 				break;
813783454c1Smikeb 			case SADB_X_EALG_AESGCM16:
814783454c1Smikeb 				switch (r.enckey->len) {
815783454c1Smikeb 				case 28:
816783454c1Smikeb 					xfs.encxf = &encxfs[ENCXF_AES_192_GCM];
817783454c1Smikeb 					break;
818783454c1Smikeb 				case 36:
819783454c1Smikeb 					xfs.encxf = &encxfs[ENCXF_AES_256_GCM];
820783454c1Smikeb 					break;
821783454c1Smikeb 				default:
822783454c1Smikeb 					xfs.encxf = &encxfs[ENCXF_AES_128_GCM];
823783454c1Smikeb 					break;
824783454c1Smikeb 				}
825783454c1Smikeb 				break;
826783454c1Smikeb 			case SADB_X_EALG_AESGMAC:
827783454c1Smikeb 				switch (r.enckey->len) {
828783454c1Smikeb 				case 28:
829783454c1Smikeb 					xfs.encxf = &encxfs[ENCXF_AES_192_GMAC];
830783454c1Smikeb 					break;
831783454c1Smikeb 				case 36:
832783454c1Smikeb 					xfs.encxf = &encxfs[ENCXF_AES_256_GMAC];
833783454c1Smikeb 					break;
834783454c1Smikeb 				default:
835783454c1Smikeb 					xfs.encxf = &encxfs[ENCXF_AES_128_GMAC];
836783454c1Smikeb 					break;
837783454c1Smikeb 				}
838783454c1Smikeb 				break;
8390c77d9beSmarkus 			case SADB_X_EALG_BLF:
8400c77d9beSmarkus 				xfs.encxf = &encxfs[ENCXF_BLOWFISH];
8410c77d9beSmarkus 				break;
8420c77d9beSmarkus 			case SADB_X_EALG_CAST:
8430c77d9beSmarkus 				xfs.encxf = &encxfs[ENCXF_CAST128];
8440c77d9beSmarkus 				break;
845f705960cSmikeb 			case SADB_X_EALG_CHACHA20POLY1305:
846f705960cSmikeb 				xfs.encxf = &encxfs[ENCXF_CHACHA20_POLY1305];
847f705960cSmikeb 				break;
8480c77d9beSmarkus 			case SADB_EALG_NULL:
8490c77d9beSmarkus 				xfs.encxf = &encxfs[ENCXF_NULL];
8500c77d9beSmarkus 				break;
8510c77d9beSmarkus 			}
8520c77d9beSmarkus 		}
8530c77d9beSmarkus 		if (sa->sadb_sa_auth) {
854a18fcb51Smarkus 			bzero(&authkey, sizeof authkey);
855a18fcb51Smarkus 			parse_key(extensions[SADB_EXT_KEY_AUTH], &authkey);
856a18fcb51Smarkus 			r.authkey = &authkey;
857a18fcb51Smarkus 
8580c77d9beSmarkus 			switch (sa->sadb_sa_auth) {
8590c77d9beSmarkus 			case SADB_AALG_MD5HMAC:
8600c77d9beSmarkus 				xfs.authxf = &authxfs[AUTHXF_HMAC_MD5];
8610c77d9beSmarkus 				break;
8620c77d9beSmarkus 			case SADB_X_AALG_RIPEMD160HMAC:
8630c77d9beSmarkus 				xfs.authxf = &authxfs[AUTHXF_HMAC_RIPEMD160];
8640c77d9beSmarkus 				break;
8650c77d9beSmarkus 			case SADB_AALG_SHA1HMAC:
8660c77d9beSmarkus 				xfs.authxf = &authxfs[AUTHXF_HMAC_SHA1];
8670c77d9beSmarkus 				break;
8680c77d9beSmarkus 			case SADB_X_AALG_SHA2_256:
8690c77d9beSmarkus 				xfs.authxf = &authxfs[AUTHXF_HMAC_SHA2_256];
8700c77d9beSmarkus 				break;
8710c77d9beSmarkus 			case SADB_X_AALG_SHA2_384:
8720c77d9beSmarkus 				xfs.authxf = &authxfs[AUTHXF_HMAC_SHA2_384];
8730c77d9beSmarkus 				break;
8740c77d9beSmarkus 			case SADB_X_AALG_SHA2_512:
8750c77d9beSmarkus 				xfs.authxf = &authxfs[AUTHXF_HMAC_SHA2_512];
8760c77d9beSmarkus 				break;
8770c77d9beSmarkus 			}
8780c77d9beSmarkus 		}
8790c77d9beSmarkus 	}
880a18fcb51Smarkus 	if (!(opts & IPSECCTL_OPT_SHOWKEY)) {
881a18fcb51Smarkus 		bzero(&enckey, sizeof enckey);
882a18fcb51Smarkus 		bzero(&authkey, sizeof authkey);
883a18fcb51Smarkus 		extensions[SADB_EXT_KEY_AUTH] = NULL;
884a18fcb51Smarkus 		extensions[SADB_EXT_KEY_ENCRYPT] = NULL;
885a18fcb51Smarkus 	}
886fbd50af5Sbluhm 	if (extensions[SADB_X_EXT_SA2]) {
887a6bcba92Sbluhm 		r.type |= RULE_BUNDLE;
888fbd50af5Sbluhm 		sa2 = (struct sadb_sa *)extensions[SADB_X_EXT_SA2];
889fbd50af5Sbluhm 		r.spi2 = ntohl(sa2->sadb_sa_spi);
890fbd50af5Sbluhm 		parse_addr(extensions[SADB_X_EXT_DST2], &dst2);
891fbd50af5Sbluhm 		r.dst2 = &dst2;
892fbd50af5Sbluhm 		parse_satype(extensions[SADB_X_EXT_SATYPE2], &r.proto2);
893fbd50af5Sbluhm 		r.proto = r.satype;
894fbd50af5Sbluhm 	}
8950c77d9beSmarkus 	ipsecctl_print_rule(&r, opts);
8960c77d9beSmarkus 
8970c77d9beSmarkus 	if (opts & IPSECCTL_OPT_VERBOSE) {
89894de6926Smarkus 		for (i = 0; i <= SADB_EXT_MAX; i++)
8990c77d9beSmarkus 			if (extensions[i])
9007fc6e3f0Smpi 				print_ext(extensions[i], msg, opts);
9010c77d9beSmarkus 	}
9020c77d9beSmarkus 	fflush(stdout);
9038a87fca6Smsf }
9048a87fca6Smsf 
9058a87fca6Smsf void
pfkey_monitor_sa(struct sadb_msg * msg,int opts)9068a87fca6Smsf pfkey_monitor_sa(struct sadb_msg *msg, int opts)
9078a87fca6Smsf {
9088a87fca6Smsf 	int		 i;
9098a87fca6Smsf 
9108a87fca6Smsf 	setup_extensions(msg);
9118a87fca6Smsf 
9128a87fca6Smsf 	printf("%s: satype %s vers %u len %u seq %u pid %u\n",
9138a87fca6Smsf 	    lookup_name(msg_types, msg->sadb_msg_type),
9148a87fca6Smsf 	    lookup_name(sa_types, msg->sadb_msg_satype),
9158a87fca6Smsf 	    msg->sadb_msg_version, msg->sadb_msg_len,
9168a87fca6Smsf 	    msg->sadb_msg_seq,
9178a87fca6Smsf 	    msg->sadb_msg_pid);
9188a87fca6Smsf 	if (msg->sadb_msg_errno)
9198a87fca6Smsf 		printf("\terrno %u: %s\n", msg->sadb_msg_errno,
9208a87fca6Smsf 		    strerror(msg->sadb_msg_errno));
92194de6926Smarkus 	for (i = 0; i <= SADB_EXT_MAX; i++)
9228a87fca6Smsf 		if (extensions[i])
9237fc6e3f0Smpi 			print_ext(extensions[i], msg, opts);
9248a87fca6Smsf 	fflush(stdout);
9258a87fca6Smsf }
9268a87fca6Smsf 
9278a87fca6Smsf void
pfkey_print_raw(u_int8_t * data,ssize_t len)9288a87fca6Smsf pfkey_print_raw(u_int8_t *data, ssize_t len)
9298a87fca6Smsf {
9308a87fca6Smsf 	int i;
9318a87fca6Smsf 	const u_int8_t *sp = (const u_int8_t *)data;
9328a87fca6Smsf 
9338a87fca6Smsf 	printf("RAW PFKEYV2 MESSAGE:\n");
9348a87fca6Smsf 	for (i = 0; i < len; i++) {
9358a87fca6Smsf 		if ((i % 8 == 0) && (i != 0))
9368a87fca6Smsf 			printf("\n");
9378a87fca6Smsf 		printf("%02x ", *sp);
9388a87fca6Smsf 		sp++;
9398a87fca6Smsf 	}
9408a87fca6Smsf 	printf("\n");
9418a87fca6Smsf }
942