1169695Skan/*	$KAME: pfkey_dump.c,v 1.45 2003/09/08 10:14:56 itojun Exp $	*/
2169695Skan
3259890Spfg/*-
4259890Spfg * SPDX-License-Identifier: BSD-3-Clause
5169695Skan *
6169695Skan * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
7169695Skan * All rights reserved.
8169695Skan *
9169695Skan * Redistribution and use in source and binary forms, with or without
10169695Skan * modification, are permitted provided that the following conditions
11169695Skan * are met:
12169695Skan * 1. Redistributions of source code must retain the above copyright
13169695Skan *    notice, this list of conditions and the following disclaimer.
14169695Skan * 2. Redistributions in binary form must reproduce the above copyright
15169695Skan *    notice, this list of conditions and the following disclaimer in the
16169695Skan *    documentation and/or other materials provided with the distribution.
17169695Skan * 3. Neither the name of the project nor the names of its contributors
18169695Skan *    may be used to endorse or promote products derived from this software
19169695Skan *    without specific prior written permission.
20169695Skan *
21169695Skan * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22169695Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23169695Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24169695Skan * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25169695Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26169695Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27169695Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28169695Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29169695Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30169695Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31169695Skan * SUCH DAMAGE.
32169695Skan */
33169695Skan
34169695Skan#include <sys/types.h>
35169695Skan#include <sys/param.h>
36169695Skan#include <sys/socket.h>
37169695Skan#include <net/if.h>
38169695Skan#include <net/pfkeyv2.h>
39169695Skan#include <netipsec/ipsec.h>
40169695Skan#include <netipsec/key_var.h>
41169695Skan#include <netipsec/key_debug.h>
42169695Skan
43169695Skan#include <netinet/in.h>
44169695Skan#include <arpa/inet.h>
45169695Skan
46169695Skan#include <stdlib.h>
47169695Skan#include <unistd.h>
48169695Skan#include <stdio.h>
49169695Skan#include <string.h>
50169695Skan#include <time.h>
51169695Skan#include <netdb.h>
52169695Skan
53169695Skan#include "ipsec_strerror.h"
54169695Skan#include "libpfkey.h"
55169695Skan
56169695Skan/* cope with old kame headers - ugly */
57169695Skan#ifndef SADB_X_AALG_NULL
58169695Skan#define SADB_X_AALG_NULL	SADB_AALG_NULL
59169695Skan#endif
60169695Skan
61169695Skan#ifndef SADB_X_EALG_RC5CBC
62169695Skan#ifdef SADB_EALG_RC5CBC
63169695Skan#define SADB_X_EALG_RC5CBC	SADB_EALG_RC5CBC
64169695Skan#endif
65169695Skan#endif
66169695Skan
67169695Skan#define GETMSGSTR(str, num) \
68169695Skando { \
69169695Skan	if (sizeof((str)[0]) == 0 \
70169695Skan	 || num >= sizeof(str)/sizeof((str)[0])) \
71169695Skan		printf("%u ", (num)); \
72169695Skan	else if (strlen((str)[(num)]) == 0) \
73169695Skan		printf("%u ", (num)); \
74169695Skan	else \
75169695Skan		printf("%s ", (str)[(num)]); \
76169695Skan} while (0)
77169695Skan
78169695Skan#define GETMSGV2S(v2s, num) \
79169695Skando { \
80169695Skan	struct val2str *p;  \
81169695Skan	for (p = (v2s); p && p->str; p++) { \
82169695Skan		if (p->val == (num)) \
83169695Skan			break; \
84169695Skan	} \
85169695Skan	if (p && p->str) \
86169695Skan		printf("%s ", p->str); \
87169695Skan	else \
88169695Skan		printf("%u ", (num)); \
89169695Skan} while (0)
90169695Skan
91169695Skanstatic char *str_ipaddr(struct sockaddr *);
92169695Skanstatic char *str_prefport(u_int, u_int, u_int, u_int);
93169695Skanstatic void str_upperspec(u_int, u_int, u_int);
94169695Skanstatic char *str_time(time_t);
95169695Skanstatic void str_lifetime_byte(struct sadb_lifetime *, char *);
96169695Skan
97169695Skanstruct val2str {
98169695Skan	int val;
99169695Skan	const char *str;
100169695Skan};
101169695Skan
102169695Skan/*
103169695Skan * Must to be re-written about following strings.
104169695Skan */
105169695Skanstatic char *str_satype[] = {
106169695Skan	"unspec",
107169695Skan	"unknown",
108169695Skan	"ah",
109169695Skan	"esp",
110169695Skan	"unknown",
111169695Skan	"rsvp",
112169695Skan	"ospfv2",
113169695Skan	"ripv2",
114169695Skan	"mip",
115169695Skan	"ipcomp",
116169695Skan	"policy",
117169695Skan	"tcp"
118169695Skan};
119169695Skan
120169695Skanstatic char *str_mode[] = {
121169695Skan	"any",
122169695Skan	"transport",
123169695Skan	"tunnel",
124169695Skan};
125169695Skan
126169695Skanstatic char *str_state[] = {
127169695Skan	"larval",
128169695Skan	"mature",
129169695Skan	"dying",
130169695Skan	"dead",
131169695Skan};
132169695Skan
133169695Skanstatic struct val2str str_alg_auth[] = {
134169695Skan	{ SADB_AALG_NONE, "none", },
135169695Skan	{ SADB_AALG_SHA1HMAC, "hmac-sha1", },
136169695Skan	{ SADB_X_AALG_NULL, "null", },
137169695Skan	{ SADB_X_AALG_TCP_MD5, "tcp-md5", },
138169695Skan#ifdef SADB_X_AALG_SHA2_256
139169695Skan	{ SADB_X_AALG_SHA2_256, "hmac-sha2-256", },
140169695Skan#endif
141169695Skan#ifdef SADB_X_AALG_SHA2_384
142169695Skan	{ SADB_X_AALG_SHA2_384, "hmac-sha2-384", },
143169695Skan#endif
144169695Skan#ifdef SADB_X_AALG_SHA2_512
145169695Skan	{ SADB_X_AALG_SHA2_512, "hmac-sha2-512", },
146169695Skan#endif
147169695Skan#ifdef SADB_X_AALG_AES_XCBC_MAC
148169695Skan	{ SADB_X_AALG_AES_XCBC_MAC, "aes-xcbc-mac", },
149169695Skan#endif
150169695Skan#ifdef SADB_X_AALG_CHACHA20POLY1305
151169695Skan	{ SADB_X_AALG_CHACHA20POLY1305, "chacha20-poly1305", },
152169695Skan#endif
153169695Skan	{ -1, NULL, },
154169695Skan};
155169695Skan
156169695Skanstatic struct val2str str_alg_enc[] = {
157169695Skan	{ SADB_EALG_NONE, "none", },
158169695Skan	{ SADB_EALG_NULL, "null", },
159169695Skan#ifdef SADB_X_EALG_RC5CBC
160169695Skan	{ SADB_X_EALG_RC5CBC, "rc5-cbc", },
161169695Skan#endif
162169695Skan#ifdef SADB_X_EALG_AESCBC
163169695Skan	{ SADB_X_EALG_AESCBC, "aes-cbc", },
164169695Skan#endif
165169695Skan#ifdef SADB_X_EALG_TWOFISHCBC
166169695Skan	{ SADB_X_EALG_TWOFISHCBC, "twofish-cbc", },
167169695Skan#endif
168169695Skan#ifdef SADB_X_EALG_AESCTR
169169695Skan	{ SADB_X_EALG_AESCTR, "aes-ctr", },
170169695Skan#endif
171169695Skan#ifdef SADB_X_EALG_AESGCM16
172169695Skan	{ SADB_X_EALG_AESGCM16, "aes-gcm-16", },
173169695Skan#endif
174169695Skan#ifdef SADB_X_EALG_CHACHA20POLY1305
175169695Skan	{ SADB_X_EALG_CHACHA20POLY1305, "chacha20-poly1305", },
176169695Skan#endif
177169695Skan	{ -1, NULL, },
178169695Skan};
179169695Skan
180169695Skanstatic struct val2str str_alg_comp[] = {
181169695Skan	{ SADB_X_CALG_NONE, "none", },
182169695Skan	{ SADB_X_CALG_OUI, "oui", },
183169695Skan	{ SADB_X_CALG_DEFLATE, "deflate", },
184169695Skan	{ SADB_X_CALG_LZS, "lzs", },
185169695Skan	{ -1, NULL, },
186169695Skan};
187169695Skan
188169695Skanstatic struct val2str str_sp_scope[] = {
189169695Skan	{ IPSEC_POLICYSCOPE_GLOBAL, "global" },
190169695Skan	{ IPSEC_POLICYSCOPE_IFNET, "ifnet" },
191169695Skan	{ IPSEC_POLICYSCOPE_PCB, "pcb"},
192169695Skan	{ -1, NULL },
193169695Skan};
194169695Skan
195169695Skan/*
196169695Skan * dump SADB_MSG formatted.  For debugging, you should use kdebug_sadb().
197169695Skan */
198169695Skanvoid
199169695Skanpfkey_sadump(struct sadb_msg *m)
200169695Skan{
201169695Skan	caddr_t mhp[SADB_EXT_MAX + 1];
202169695Skan	struct sadb_sa *m_sa;
203169695Skan	struct sadb_x_sa2 *m_sa2;
204169695Skan	struct sadb_lifetime *m_lftc, *m_lfth, *m_lfts;
205169695Skan	struct sadb_address *m_saddr, *m_daddr, *m_paddr;
206169695Skan	struct sadb_key *m_auth, *m_enc;
207169695Skan	struct sadb_ident *m_sid, *m_did;
208169695Skan	struct sadb_sens *m_sens;
209169695Skan	struct sadb_x_sa_replay *m_sa_replay;
210169695Skan	struct sadb_x_nat_t_type *natt_type;
211169695Skan	struct sadb_x_nat_t_port *natt_sport, *natt_dport;
212169695Skan	struct sadb_address *natt_oai, *natt_oar;
213169695Skan
214169695Skan	/* check pfkey message. */
215169695Skan	if (pfkey_align(m, mhp)) {
216169695Skan		printf("%s\n", ipsec_strerror());
217169695Skan		return;
218169695Skan	}
219169695Skan	if (pfkey_check(mhp)) {
220169695Skan		printf("%s\n", ipsec_strerror());
221169695Skan		return;
222169695Skan	}
223169695Skan
224169695Skan	m_sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
225169695Skan	m_sa2 = (struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2];
226169695Skan	m_lftc = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_CURRENT];
227169695Skan	m_lfth = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_HARD];
228169695Skan	m_lfts = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_SOFT];
229169695Skan	m_saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
230169695Skan	m_daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
231169695Skan	m_paddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_PROXY];
232169695Skan	m_auth = (struct sadb_key *)mhp[SADB_EXT_KEY_AUTH];
233169695Skan	m_enc = (struct sadb_key *)mhp[SADB_EXT_KEY_ENCRYPT];
234169695Skan	m_sid = (struct sadb_ident *)mhp[SADB_EXT_IDENTITY_SRC];
235169695Skan	m_did = (struct sadb_ident *)mhp[SADB_EXT_IDENTITY_DST];
236169695Skan	m_sens = (struct sadb_sens *)mhp[SADB_EXT_SENSITIVITY];
237169695Skan	m_sa_replay = (struct sadb_x_sa_replay *)mhp[SADB_X_EXT_SA_REPLAY];
238169695Skan	natt_type = (struct sadb_x_nat_t_type *)mhp[SADB_X_EXT_NAT_T_TYPE];
239169695Skan	natt_sport = (struct sadb_x_nat_t_port *)mhp[SADB_X_EXT_NAT_T_SPORT];
240169695Skan	natt_dport = (struct sadb_x_nat_t_port *)mhp[SADB_X_EXT_NAT_T_DPORT];
241169695Skan	natt_oai = (struct sadb_address *)mhp[SADB_X_EXT_NAT_T_OAI];
242169695Skan	natt_oar = (struct sadb_address *)mhp[SADB_X_EXT_NAT_T_OAR];
243169695Skan
244169695Skan
245169695Skan	/* source address */
246169695Skan	if (m_saddr == NULL) {
247169695Skan		printf("no ADDRESS_SRC extension.\n");
248169695Skan		return;
249169695Skan	}
250169695Skan	printf("%s", str_ipaddr((struct sockaddr *)(m_saddr + 1)));
251169695Skan	if (natt_type != NULL && natt_sport != NULL)
252169695Skan		printf("[%u]", ntohs(natt_sport->sadb_x_nat_t_port_port));
253169695Skan
254169695Skan	/* destination address */
255169695Skan	if (m_daddr == NULL) {
256169695Skan		printf("\nno ADDRESS_DST extension.\n");
257169695Skan		return;
258169695Skan	}
259169695Skan	printf(" %s", str_ipaddr((struct sockaddr *)(m_daddr + 1)));
260169695Skan	if (natt_type != NULL && natt_dport != NULL)
261169695Skan		printf("[%u]", ntohs(natt_dport->sadb_x_nat_t_port_port));
262169695Skan
263169695Skan	/* SA type */
264169695Skan	if (m_sa == NULL) {
265169695Skan		printf("\nno SA extension.\n");
266228474Sed		return;
267228474Sed	}
268259405Spfg	if (m_sa2 == NULL) {
269259405Spfg		printf("\nno SA2 extension.\n");
270259405Spfg		return;
271228474Sed	}
272228474Sed	printf("\n\t");
273169695Skan
274169695Skan	if (m->sadb_msg_satype == SADB_SATYPE_ESP && natt_type != NULL)
275169695Skan		printf("esp-udp ");
276169695Skan	else
277169695Skan		GETMSGSTR(str_satype, m->sadb_msg_satype);
278169695Skan
279169695Skan	printf("mode=");
280169695Skan	GETMSGSTR(str_mode, m_sa2->sadb_x_sa2_mode);
281169695Skan
282169695Skan	printf("spi=%u(0x%08x) reqid=%u(0x%08x)\n",
283169695Skan		(u_int32_t)ntohl(m_sa->sadb_sa_spi),
284169695Skan		(u_int32_t)ntohl(m_sa->sadb_sa_spi),
285169695Skan		(u_int32_t)m_sa2->sadb_x_sa2_reqid,
286169695Skan		(u_int32_t)m_sa2->sadb_x_sa2_reqid);
287169695Skan
288169695Skan	/* other NAT-T information */
289169695Skan	if (natt_type != NULL && (natt_oai != NULL || natt_oar != NULL)) {
290169695Skan		printf("\tNAT:");
291169695Skan		if (natt_oai != NULL)
292169695Skan			printf(" OAI=%s",
293169695Skan			    str_ipaddr((struct sockaddr *)(natt_oai + 1)));
294169695Skan		if (natt_oar != NULL)
295169695Skan			printf(" OAR=%s",
296169695Skan			    str_ipaddr((struct sockaddr *)(natt_oar + 1)));
297169695Skan		printf("\n");
298169695Skan	}
299169695Skan
300169695Skan	/* encryption key */
301169695Skan	if (m->sadb_msg_satype == SADB_X_SATYPE_IPCOMP) {
302169695Skan		printf("\tC: ");
303169695Skan		GETMSGV2S(str_alg_comp, m_sa->sadb_sa_encrypt);
304169695Skan	} else if (m->sadb_msg_satype == SADB_SATYPE_ESP) {
305169695Skan		if (m_enc != NULL) {
306169695Skan			printf("\tE: ");
307169695Skan			GETMSGV2S(str_alg_enc, m_sa->sadb_sa_encrypt);
308169695Skan			ipsec_hexdump((caddr_t)m_enc + sizeof(*m_enc),
309169695Skan				      m_enc->sadb_key_bits / 8);
310169695Skan			printf("\n");
311169695Skan		}
312169695Skan	}
313169695Skan
314169695Skan	/* authentication key */
315169695Skan	if (m_auth != NULL) {
316169695Skan		printf("\tA: ");
317169695Skan		GETMSGV2S(str_alg_auth, m_sa->sadb_sa_auth);
318169695Skan		ipsec_hexdump((caddr_t)m_auth + sizeof(*m_auth),
319169695Skan		              m_auth->sadb_key_bits / 8);
320169695Skan		printf("\n");
321169695Skan	}
322169695Skan
323169695Skan	/* replay windoe size & flags */
324169695Skan	printf("\tseq=0x%08x replay=%u flags=0x%08x ",
325169695Skan		m_sa2->sadb_x_sa2_sequence,
326169695Skan		m_sa_replay ? (m_sa_replay->sadb_x_sa_replay_replay >> 3) :
327169695Skan			m_sa->sadb_sa_replay,
328169695Skan		m_sa->sadb_sa_flags);
329169695Skan
330169695Skan	/* state */
331169695Skan	printf("state=");
332169695Skan	GETMSGSTR(str_state, m_sa->sadb_sa_state);
333169695Skan	printf("\n");
334169695Skan
335169695Skan	/* lifetime */
336169695Skan	if (m_lftc != NULL) {
337169695Skan		time_t tmp_time = time(0);
338169695Skan
339169695Skan		printf("\tcreated: %s",
340169695Skan			str_time(m_lftc->sadb_lifetime_addtime));
341169695Skan		printf("\tcurrent: %s\n", str_time(tmp_time));
342169695Skan		printf("\tdiff: %lu(s)",
343169695Skan			(u_long)(m_lftc->sadb_lifetime_addtime == 0 ?
344169695Skan			0 : (tmp_time - m_lftc->sadb_lifetime_addtime)));
345169695Skan
346169695Skan		printf("\thard: %lu(s)",
347169695Skan			(u_long)(m_lfth == NULL ?
348169695Skan			0 : m_lfth->sadb_lifetime_addtime));
349169695Skan		printf("\tsoft: %lu(s)\n",
350169695Skan			(u_long)(m_lfts == NULL ?
351169695Skan			0 : m_lfts->sadb_lifetime_addtime));
352169695Skan
353169695Skan		printf("\tlast: %s",
354169695Skan			str_time(m_lftc->sadb_lifetime_usetime));
355169695Skan		printf("\thard: %lu(s)",
356169695Skan			(u_long)(m_lfth == NULL ?
357169695Skan			0 : m_lfth->sadb_lifetime_usetime));
358169695Skan		printf("\tsoft: %lu(s)\n",
359169695Skan			(u_long)(m_lfts == NULL ?
360169695Skan			0 : m_lfts->sadb_lifetime_usetime));
361169695Skan
362169695Skan		str_lifetime_byte(m_lftc, "current");
363169695Skan		str_lifetime_byte(m_lfth, "hard");
364169695Skan		str_lifetime_byte(m_lfts, "soft");
365169695Skan		printf("\n");
366169695Skan
367169695Skan		printf("\tallocated: %lu",
368169695Skan			(unsigned long)m_lftc->sadb_lifetime_allocations);
369169695Skan		printf("\thard: %lu",
370169695Skan			(u_long)(m_lfth == NULL ?
371169695Skan			0 : m_lfth->sadb_lifetime_allocations));
372169695Skan		printf("\tsoft: %lu\n",
373169695Skan			(u_long)(m_lfts == NULL ?
374169695Skan			0 : m_lfts->sadb_lifetime_allocations));
375169695Skan	}
376169695Skan
377169695Skan	printf("\tsadb_seq=%lu pid=%lu ",
378169695Skan		(u_long)m->sadb_msg_seq,
379169695Skan		(u_long)m->sadb_msg_pid);
380169695Skan
381169695Skan	/* XXX DEBUG */
382169695Skan	printf("refcnt=%u\n", m->sadb_msg_reserved);
383169695Skan
384169695Skan	return;
385169695Skan}
386169695Skan
387169695Skanvoid
388169695Skanpfkey_spdump(struct sadb_msg *m)
389169695Skan{
390169695Skan	char pbuf[NI_MAXSERV];
391169695Skan	caddr_t mhp[SADB_EXT_MAX + 1];
392169695Skan	struct sadb_address *m_saddr, *m_daddr;
393169695Skan	struct sadb_x_policy *m_xpl;
394169695Skan	struct sadb_lifetime *m_lftc = NULL, *m_lfth = NULL;
395169695Skan	struct sockaddr *sa;
396169695Skan	u_int16_t sport = 0, dport = 0;
397169695Skan
398169695Skan	/* check pfkey message. */
399169695Skan	if (pfkey_align(m, mhp)) {
400169695Skan		printf("%s\n", ipsec_strerror());
401169695Skan		return;
402169695Skan	}
403169695Skan	if (pfkey_check(mhp)) {
404169695Skan		printf("%s\n", ipsec_strerror());
405169695Skan		return;
406169695Skan	}
407169695Skan
408169695Skan	m_saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
409169695Skan	m_daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
410169695Skan	m_xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
411169695Skan	m_lftc = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_CURRENT];
412169695Skan	m_lfth = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_HARD];
413169695Skan
414169695Skan	if (m_saddr && m_daddr) {
415169695Skan		/* source address */
416169695Skan		sa = (struct sockaddr *)(m_saddr + 1);
417169695Skan		switch (sa->sa_family) {
418169695Skan		case AF_INET:
419169695Skan		case AF_INET6:
420169695Skan			if (getnameinfo(sa, sa->sa_len, NULL, 0,
421169695Skan			    pbuf, sizeof(pbuf), NI_NUMERICSERV) != 0)
422169695Skan				sport = 0;	/*XXX*/
423169695Skan			else
424169695Skan				sport = atoi(pbuf);
425169695Skan			printf("%s%s ", str_ipaddr(sa),
426169695Skan				str_prefport(sa->sa_family,
427169695Skan				    m_saddr->sadb_address_prefixlen, sport,
428169695Skan				    m_saddr->sadb_address_proto));
429169695Skan			break;
430169695Skan		default:
431169695Skan			printf("unknown-af ");
432169695Skan			break;
433169695Skan		}
434169695Skan
435169695Skan		/* destination address */
436169695Skan		sa = (struct sockaddr *)(m_daddr + 1);
437169695Skan		switch (sa->sa_family) {
438169695Skan		case AF_INET:
439169695Skan		case AF_INET6:
440169695Skan			if (getnameinfo(sa, sa->sa_len, NULL, 0,
441169695Skan			    pbuf, sizeof(pbuf), NI_NUMERICSERV) != 0)
442259890Spfg				dport = 0;	/*XXX*/
443169695Skan			else
444169695Skan				dport = atoi(pbuf);
445259890Spfg			printf("%s%s ", str_ipaddr(sa),
446169695Skan				str_prefport(sa->sa_family,
447259890Spfg				    m_daddr->sadb_address_prefixlen, dport,
448169695Skan				    m_saddr->sadb_address_proto));
449169695Skan			break;
450169695Skan		default:
451169695Skan			printf("unknown-af ");
452169695Skan			break;
453259890Spfg		}
454169695Skan
455169695Skan		/* upper layer protocol */
456169695Skan		if (m_saddr->sadb_address_proto !=
457169695Skan		    m_daddr->sadb_address_proto) {
458169695Skan			printf("upper layer protocol mismatched.\n");
459169695Skan			return;
460169695Skan		}
461169695Skan		str_upperspec(m_saddr->sadb_address_proto, sport, dport);
462169695Skan	}
463259890Spfg	else
464169695Skan		printf("(no selector, probably per-socket policy) ");
465169695Skan
466259890Spfg	/* policy */
467259890Spfg    {
468169695Skan	char *d_xpl;
469169695Skan
470169695Skan	if (m_xpl == NULL) {
471169695Skan		printf("no X_POLICY extension.\n");
472259890Spfg		return;
473259890Spfg	}
474259890Spfg	d_xpl = ipsec_dump_policy((char *)m_xpl, "\n\t");
475259890Spfg
476259890Spfg	/* dump SPD */
477259890Spfg	printf("\n\t%s\n", d_xpl);
478259890Spfg	free(d_xpl);
479169695Skan    }
480169695Skan
481169695Skan	/* lifetime */
482169695Skan	if (m_lftc) {
483169695Skan		printf("\tcreated: %s  ",
484169695Skan			str_time(m_lftc->sadb_lifetime_addtime));
485169695Skan		printf("lastused: %s\n",
486169695Skan			str_time(m_lftc->sadb_lifetime_usetime));
487259890Spfg	}
488169695Skan	if (m_lfth) {
489169695Skan		printf("\tlifetime: %lu(s) ",
490169695Skan			(u_long)m_lfth->sadb_lifetime_addtime);
491169695Skan		printf("validtime: %lu(s)\n",
492169695Skan			(u_long)m_lfth->sadb_lifetime_usetime);
493169695Skan	}
494169695Skan
495169695Skan
496169695Skan	printf("\tspid=%ld seq=%ld pid=%ld scope=",
497169695Skan		(u_long)m_xpl->sadb_x_policy_id,
498169695Skan		(u_long)m->sadb_msg_seq,
499169695Skan		(u_long)m->sadb_msg_pid);
500169695Skan	GETMSGV2S(str_sp_scope, m_xpl->sadb_x_policy_scope);
501169695Skan	if (m_xpl->sadb_x_policy_scope == IPSEC_POLICYSCOPE_IFNET &&
502169695Skan	    if_indextoname(m_xpl->sadb_x_policy_ifindex, pbuf) != NULL)
503169695Skan		printf("ifname=%s", pbuf);
504169695Skan	printf("\n");
505169695Skan
506169695Skan	/* XXX TEST */
507169695Skan	printf("\trefcnt=%u\n", m->sadb_msg_reserved);
508169695Skan
509169695Skan	return;
510169695Skan}
511169695Skan
512169695Skan/*
513169695Skan * set "ipaddress" to buffer.
514169695Skan */
515169695Skanstatic char *
516169695Skanstr_ipaddr(struct sockaddr *sa)
517169695Skan{
518169695Skan	static char buf[NI_MAXHOST];
519169695Skan	const int niflag = NI_NUMERICHOST;
520169695Skan
521169695Skan	if (sa == NULL)
522169695Skan		return "";
523169695Skan
524169695Skan	if (getnameinfo(sa, sa->sa_len, buf, sizeof(buf), NULL, 0, niflag) == 0)
525169695Skan		return buf;
526169695Skan	return NULL;
527169695Skan}
528169695Skan
529169695Skan/*
530169695Skan * set "/prefix[port number]" to buffer.
531169695Skan */
532169695Skanstatic char *
533169695Skanstr_prefport(u_int family, u_int pref, u_int port, u_int ulp)
534169695Skan{
535169695Skan	static char buf[128];
536169695Skan	char prefbuf[128];
537169695Skan	char portbuf[128];
538169695Skan	int plen;
539169695Skan
540169695Skan	switch (family) {
541169695Skan	case AF_INET:
542169695Skan		plen = sizeof(struct in_addr) << 3;
543169695Skan		break;
544169695Skan	case AF_INET6:
545169695Skan		plen = sizeof(struct in6_addr) << 3;
546169695Skan		break;
547169695Skan	default:
548169695Skan		return "?";
549169695Skan	}
550169695Skan
551169695Skan	if (pref == plen)
552169695Skan		prefbuf[0] = '\0';
553169695Skan	else
554169695Skan		snprintf(prefbuf, sizeof(prefbuf), "/%u", pref);
555169695Skan
556169695Skan	if (ulp == IPPROTO_ICMPV6)
557169695Skan		memset(portbuf, 0, sizeof(portbuf));
558169695Skan	else {
559169695Skan		if (port == IPSEC_PORT_ANY)
560169695Skan			snprintf(portbuf, sizeof(portbuf), "[%s]", "any");
561169695Skan		else
562169695Skan			snprintf(portbuf, sizeof(portbuf), "[%u]", port);
563169695Skan	}
564169695Skan
565169695Skan	snprintf(buf, sizeof(buf), "%s%s", prefbuf, portbuf);
566169695Skan
567169695Skan	return buf;
568169695Skan}
569169695Skan
570169695Skanstatic void
571169695Skanstr_upperspec(u_int ulp, u_int p1, u_int p2)
572169695Skan{
573169695Skan	if (ulp == IPSEC_ULPROTO_ANY)
574169695Skan		printf("any");
575169695Skan	else if (ulp == IPPROTO_ICMPV6) {
576169695Skan		printf("icmp6");
577169695Skan		if (!(p1 == IPSEC_PORT_ANY && p2 == IPSEC_PORT_ANY))
578169695Skan			printf(" %u,%u", p1, p2);
579169695Skan	} else {
580169695Skan		struct protoent *ent;
581169695Skan
582169695Skan		switch (ulp) {
583169695Skan		case IPPROTO_IPV4:
584169695Skan			printf("ip4");
585169695Skan			break;
586169695Skan		default:
587169695Skan			ent = getprotobynumber(ulp);
588169695Skan			if (ent)
589169695Skan				printf("%s", ent->p_name);
590169695Skan			else
591169695Skan				printf("%u", ulp);
592169695Skan
593169695Skan			endprotoent();
594169695Skan			break;
595169695Skan		}
596169695Skan	}
597169695Skan}
598169695Skan
599169695Skan/*
600169695Skan * set "Mon Day Time Year" to buffer
601169695Skan */
602169695Skanstatic char *
603169695Skanstr_time(time_t t)
604169695Skan{
605169695Skan	static char buf[128];
606169695Skan
607169695Skan	if (t == 0) {
608169695Skan		int i = 0;
609169695Skan		for (;i < 20;) buf[i++] = ' ';
610169695Skan	} else {
611169695Skan		char *t0;
612169695Skan		t0 = ctime(&t);
613169695Skan		memcpy(buf, t0 + 4, 20);
614169695Skan	}
615169695Skan
616169695Skan	buf[20] = '\0';
617169695Skan
618169695Skan	return(buf);
619169695Skan}
620169695Skan
621169695Skanstatic void
622169695Skanstr_lifetime_byte(struct sadb_lifetime *x, char *str)
623169695Skan{
624169695Skan	double y;
625169695Skan	char *unit;
626169695Skan	int w;
627169695Skan
628169695Skan	if (x == NULL) {
629169695Skan		printf("\t%s: 0(bytes)", str);
630169695Skan		return;
631169695Skan	}
632169695Skan
633169695Skan#if 0
634169695Skan	if ((x->sadb_lifetime_bytes) / 1024 / 1024) {
635169695Skan		y = (x->sadb_lifetime_bytes) * 1.0 / 1024 / 1024;
636169695Skan		unit = "M";
637169695Skan		w = 1;
638169695Skan	} else if ((x->sadb_lifetime_bytes) / 1024) {
639169695Skan		y = (x->sadb_lifetime_bytes) * 1.0 / 1024;
640169695Skan		unit = "K";
641169695Skan		w = 1;
642169695Skan	} else {
643169695Skan		y = (x->sadb_lifetime_bytes) * 1.0;
644169695Skan		unit = "";
645169695Skan		w = 0;
646169695Skan	}
647169695Skan#else
648169695Skan	y = (x->sadb_lifetime_bytes) * 1.0;
649169695Skan	unit = "";
650169695Skan	w = 0;
651169695Skan#endif
652169695Skan	printf("\t%s: %.*f(%sbytes)", str, w, y, unit);
653169695Skan}
654169695Skan