Home | History | Annotate | Download | only in libipsec
      1 /*	$NetBSD: pfkey_dump.c,v 1.18 2010/12/03 14:32:52 tteras Exp $	*/
      2 
      3 /*	$KAME: pfkey_dump.c,v 1.45 2003/09/08 10:14:56 itojun Exp $	*/
      4 
      5 /*
      6  * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
      7  * All rights reserved.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  * 3. Neither the name of the project nor the names of its contributors
     18  *    may be used to endorse or promote products derived from this software
     19  *    without specific prior written permission.
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
     22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
     25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     31  * SUCH DAMAGE.
     32  */
     33 
     34 #ifdef HAVE_CONFIG_H
     35 #include "config.h"
     36 #endif
     37 
     38 #include <sys/types.h>
     39 #include <sys/param.h>
     40 #include <sys/socket.h>
     41 #include PATH_IPSEC_H
     42 #include <net/pfkeyv2.h>
     43 
     44 #include <netinet/in.h>
     45 #include <arpa/inet.h>
     46 
     47 #include <stdlib.h>
     48 #include <unistd.h>
     49 #include <stdio.h>
     50 #include <string.h>
     51 #include <time.h>
     52 #include <netdb.h>
     53 
     54 #include "ipsec_strerror.h"
     55 #include "libpfkey.h"
     56 
     57 /* cope with old kame headers - ugly */
     58 #ifndef SADB_X_AALG_MD5
     59 #define SADB_X_AALG_MD5		SADB_AALG_MD5
     60 #endif
     61 #ifndef SADB_X_AALG_SHA
     62 #define SADB_X_AALG_SHA		SADB_AALG_SHA
     63 #endif
     64 #ifndef SADB_X_AALG_NULL
     65 #define SADB_X_AALG_NULL	SADB_AALG_NULL
     66 #endif
     67 
     68 #ifndef SADB_X_EALG_BLOWFISHCBC
     69 #define SADB_X_EALG_BLOWFISHCBC	SADB_EALG_BLOWFISHCBC
     70 #endif
     71 #ifndef SADB_X_EALG_CAST128CBC
     72 #define SADB_X_EALG_CAST128CBC	SADB_EALG_CAST128CBC
     73 #endif
     74 #ifndef SADB_X_EALG_RC5CBC
     75 #ifdef SADB_EALG_RC5CBC
     76 #define SADB_X_EALG_RC5CBC	SADB_EALG_RC5CBC
     77 #endif
     78 #endif
     79 #if defined(SADB_X_EALG_AES) && ! defined(SADB_X_EALG_AESCBC)
     80 #define SADB_X_EALG_AESCBC  SADB_X_EALG_AES
     81 #endif
     82 
     83 #define GETMSGSTR(str, num) \
     84 do { \
     85 	/*CONSTCOND*/ \
     86 	if (sizeof((str)[0]) == 0 \
     87 	 || num >= sizeof(str)/sizeof((str)[0])) \
     88 		printf("%u ", (num)); \
     89 	else if (strlen((str)[(num)]) == 0) \
     90 		printf("%u ", (num)); \
     91 	else \
     92 		printf("%s ", (str)[(num)]); \
     93 } while (/*CONSTCOND*/0)
     94 
     95 #define GETMSGV2S(v2s, num) \
     96 do { \
     97 	struct val2str *p;  \
     98 	for (p = (v2s); p && p->str; p++) { \
     99 		if (p->val == (num)) \
    100 			break; \
    101 	} \
    102 	if (p && p->str) \
    103 		printf("%s ", p->str); \
    104 	else \
    105 		printf("%u ", (num)); \
    106 } while (/*CONSTCOND*/0)
    107 
    108 static char *str_ipaddr __P((struct sockaddr *));
    109 static char *str_ipport __P((struct sockaddr *));
    110 static char *str_prefport __P((u_int, u_int, u_int, u_int));
    111 static void str_upperspec __P((u_int, u_int, u_int));
    112 static char *str_time __P((time_t));
    113 static void str_lifetime_byte __P((struct sadb_lifetime *, char *));
    114 static void pfkey_sadump1(struct sadb_msg *, int);
    115 static void pfkey_spdump1(struct sadb_msg *, int);
    116 
    117 struct val2str {
    118 	int val;
    119 	const char *str;
    120 };
    121 
    122 /*
    123  * Must to be re-written about following strings.
    124  */
    125 static char *str_satype[] = {
    126 	"unspec",
    127 	"unknown",
    128 	"ah",
    129 	"esp",
    130 	"unknown",
    131 	"rsvp",
    132 	"ospfv2",
    133 	"ripv2",
    134 	"mip",
    135 	"ipcomp",
    136 	"policy",
    137 	"tcp",
    138 };
    139 
    140 static char *str_mode[] = {
    141 	"any",
    142 	"transport",
    143 	"tunnel",
    144 };
    145 
    146 static char *str_state[] = {
    147 	"larval",
    148 	"mature",
    149 	"dying",
    150 	"dead",
    151 };
    152 
    153 static struct val2str str_alg_auth[] = {
    154 	{ SADB_AALG_NONE, "none", },
    155 	{ SADB_AALG_MD5HMAC, "hmac-md5", },
    156 	{ SADB_AALG_SHA1HMAC, "hmac-sha1", },
    157 	{ SADB_X_AALG_MD5, "md5", },
    158 	{ SADB_X_AALG_SHA, "sha", },
    159 	{ SADB_X_AALG_NULL, "null", },
    160 #ifdef SADB_X_AALG_TCP_MD5
    161 	{ SADB_X_AALG_TCP_MD5, "tcp-md5", },
    162 #endif
    163 #ifdef SADB_X_AALG_SHA2_256
    164 	{ SADB_X_AALG_SHA2_256, "hmac-sha256", },
    165 #endif
    166 #ifdef SADB_X_AALG_SHA2_384
    167 	{ SADB_X_AALG_SHA2_384, "hmac-sha384", },
    168 #endif
    169 #ifdef SADB_X_AALG_SHA2_512
    170 	{ SADB_X_AALG_SHA2_512, "hmac-sha512", },
    171 #endif
    172 #ifdef SADB_X_AALG_RIPEMD160HMAC
    173 	{ SADB_X_AALG_RIPEMD160HMAC, "hmac-ripemd160", },
    174 #endif
    175 #ifdef SADB_X_AALG_AES_XCBC_MAC
    176 	{ SADB_X_AALG_AES_XCBC_MAC, "aes-xcbc-mac", },
    177 #endif
    178 	{ -1, NULL, },
    179 };
    180 
    181 static struct val2str str_alg_enc[] = {
    182 	{ SADB_EALG_NONE, "none", },
    183 	{ SADB_EALG_DESCBC, "des-cbc", },
    184 	{ SADB_EALG_3DESCBC, "3des-cbc", },
    185 	{ SADB_EALG_NULL, "null", },
    186 #ifdef SADB_X_EALG_RC5CBC
    187 	{ SADB_X_EALG_RC5CBC, "rc5-cbc", },
    188 #endif
    189 	{ SADB_X_EALG_CAST128CBC, "cast128-cbc", },
    190 	{ SADB_X_EALG_BLOWFISHCBC, "blowfish-cbc", },
    191 #ifdef SADB_X_EALG_AESCBC
    192 	{ SADB_X_EALG_AESCBC, "aes-cbc", },
    193 #endif
    194 #ifdef SADB_X_EALG_TWOFISHCBC
    195 	{ SADB_X_EALG_TWOFISHCBC, "twofish-cbc", },
    196 #endif
    197 #ifdef SADB_X_EALG_AESCTR
    198 	{ SADB_X_EALG_AESCTR, "aes-ctr", },
    199 #endif
    200 #ifdef SADB_X_EALG_CAMELLIACBC
    201 	{ SADB_X_EALG_CAMELLIACBC, "camellia-cbc", },
    202 #endif
    203 	{ -1, NULL, },
    204 };
    205 
    206 static struct val2str str_alg_comp[] = {
    207 	{ SADB_X_CALG_NONE, "none", },
    208 	{ SADB_X_CALG_OUI, "oui", },
    209 	{ SADB_X_CALG_DEFLATE, "deflate", },
    210 	{ SADB_X_CALG_LZS, "lzs", },
    211 	{ -1, NULL, },
    212 };
    213 
    214 /*
    215  * dump SADB_MSG formated.  For debugging, you should use kdebug_sadb().
    216  */
    217 
    218 void
    219 pfkey_sadump(m)
    220 	struct sadb_msg *m;
    221 {
    222 	pfkey_sadump1(m, 0);
    223 }
    224 
    225 void
    226 pfkey_sadump_withports(m)
    227 	struct sadb_msg *m;
    228 {
    229 	pfkey_sadump1(m, 1);
    230 }
    231 
    232 void
    233 pfkey_sadump1(m, withports)
    234 	struct sadb_msg *m;
    235 	int withports;
    236 {
    237 	caddr_t mhp[SADB_EXT_MAX + 1];
    238 	struct sadb_sa *m_sa;
    239 	struct sadb_x_sa2 *m_sa2;
    240 	struct sadb_lifetime *m_lftc, *m_lfth, *m_lfts;
    241 	struct sadb_address *m_saddr, *m_daddr;
    242 #ifdef notdef
    243 	struct sadb_address *m_paddr;
    244 #endif
    245 	struct sadb_key *m_auth, *m_enc;
    246 #ifdef notdef
    247 	struct sadb_ident *m_sid, *m_did;
    248 	struct sadb_sens *m_sens;
    249 #endif
    250 #ifdef SADB_X_EXT_SEC_CTX
    251 	struct sadb_x_sec_ctx *m_sec_ctx;
    252 #endif
    253 #ifdef SADB_X_EXT_NAT_T_TYPE
    254 	struct sadb_x_nat_t_type *natt_type;
    255 	struct sadb_x_nat_t_port *natt_sport, *natt_dport;
    256 	struct sadb_address *natt_oa;
    257 
    258 	int use_natt = 0;
    259 #endif
    260 	struct sockaddr *sa;
    261 
    262 	/* check pfkey message. */
    263 	if (pfkey_align(m, mhp)) {
    264 		printf("%s\n", ipsec_strerror());
    265 		return;
    266 	}
    267 	if (pfkey_check(mhp)) {
    268 		printf("%s\n", ipsec_strerror());
    269 		return;
    270 	}
    271 
    272 	m_sa = (void *)mhp[SADB_EXT_SA];
    273 	m_sa2 = (void *)mhp[SADB_X_EXT_SA2];
    274 	m_lftc = (void *)mhp[SADB_EXT_LIFETIME_CURRENT];
    275 	m_lfth = (void *)mhp[SADB_EXT_LIFETIME_HARD];
    276 	m_lfts = (void *)mhp[SADB_EXT_LIFETIME_SOFT];
    277 	m_saddr = (void *)mhp[SADB_EXT_ADDRESS_SRC];
    278 	m_daddr = (void *)mhp[SADB_EXT_ADDRESS_DST];
    279 #ifdef notdef
    280 	m_paddr = (void *)mhp[SADB_EXT_ADDRESS_PROXY];
    281 #endif
    282 	m_auth = (void *)mhp[SADB_EXT_KEY_AUTH];
    283 	m_enc = (void *)mhp[SADB_EXT_KEY_ENCRYPT];
    284 #ifdef notdef
    285 	m_sid = (void *)mhp[SADB_EXT_IDENTITY_SRC];
    286 	m_did = (void *)mhp[SADB_EXT_IDENTITY_DST];
    287 	m_sens = (void *)mhp[SADB_EXT_SENSITIVITY];
    288 #endif
    289 #ifdef SADB_X_EXT_SEC_CTX
    290 	m_sec_ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX];
    291 #endif
    292 #ifdef SADB_X_EXT_NAT_T_TYPE
    293 	natt_type = (void *)mhp[SADB_X_EXT_NAT_T_TYPE];
    294 	natt_sport = (void *)mhp[SADB_X_EXT_NAT_T_SPORT];
    295 	natt_dport = (void *)mhp[SADB_X_EXT_NAT_T_DPORT];
    296 	natt_oa = (void *)mhp[SADB_X_EXT_NAT_T_OA];
    297 
    298 	if (natt_type && natt_type->sadb_x_nat_t_type_type)
    299 		use_natt = 1;
    300 #endif
    301 	/* source address */
    302 	if (m_saddr == NULL) {
    303 		printf("no ADDRESS_SRC extension.\n");
    304 		return;
    305 	}
    306 	sa = (void *)(m_saddr + 1);
    307 	if (withports)
    308 		printf("%s[%s]", str_ipaddr(sa), str_ipport(sa));
    309 	else
    310 		printf("%s", str_ipaddr(sa));
    311 #ifdef SADB_X_EXT_NAT_T_TYPE
    312 	if (use_natt && natt_sport)
    313 		printf("[%u]", ntohs(natt_sport->sadb_x_nat_t_port_port));
    314 #endif
    315 	printf(" ");
    316 
    317 	/* destination address */
    318 	if (m_daddr == NULL) {
    319 		printf(" no ADDRESS_DST extension.\n");
    320 		return;
    321 	}
    322 	sa = (void *)(m_daddr + 1);
    323 	if (withports)
    324 		printf("%s[%s]", str_ipaddr(sa), str_ipport(sa));
    325 	else
    326 		printf("%s", str_ipaddr(sa));
    327 #ifdef SADB_X_EXT_NAT_T_TYPE
    328 	if (use_natt && natt_dport)
    329 		printf("[%u]", ntohs(natt_dport->sadb_x_nat_t_port_port));
    330 #endif
    331 	printf(" ");
    332 
    333 	/* SA type */
    334 	if (m_sa == NULL) {
    335 		printf("no SA extension.\n");
    336 		return;
    337 	}
    338 	if (m_sa2 == NULL) {
    339 		printf("no SA2 extension.\n");
    340 		return;
    341 	}
    342 	printf("\n\t");
    343 
    344 #ifdef SADB_X_EXT_NAT_T_TYPE
    345 	if (use_natt && m->sadb_msg_satype == SADB_SATYPE_ESP)
    346 		printf("esp-udp ");
    347 	else if (use_natt)
    348 		printf("natt+");
    349 
    350 	if (!use_natt || m->sadb_msg_satype != SADB_SATYPE_ESP)
    351 #endif
    352 	GETMSGSTR(str_satype, m->sadb_msg_satype);
    353 
    354 	printf("mode=");
    355 	GETMSGSTR(str_mode, m_sa2->sadb_x_sa2_mode);
    356 
    357 	printf("spi=%u(0x%08x) reqid=%u(0x%08x)\n",
    358 		(u_int32_t)ntohl(m_sa->sadb_sa_spi),
    359 		(u_int32_t)ntohl(m_sa->sadb_sa_spi),
    360 		(u_int32_t)m_sa2->sadb_x_sa2_reqid,
    361 		(u_int32_t)m_sa2->sadb_x_sa2_reqid);
    362 
    363 #ifdef SADB_X_EXT_NAT_T_TYPE
    364 	/* other NAT-T information */
    365 	if (use_natt && natt_oa)
    366 		printf("\tNAT OA=%s\n",
    367 		       str_ipaddr((void *)(natt_oa + 1)));
    368 #endif
    369 
    370 	/* encryption key */
    371 	if (m->sadb_msg_satype == SADB_X_SATYPE_IPCOMP) {
    372 		printf("\tC: ");
    373 		GETMSGV2S(str_alg_comp, m_sa->sadb_sa_encrypt);
    374 	} else if (m->sadb_msg_satype == SADB_SATYPE_ESP) {
    375 		if (m_enc != NULL) {
    376 			printf("\tE: ");
    377 			GETMSGV2S(str_alg_enc, m_sa->sadb_sa_encrypt);
    378 			ipsec_hexdump((caddr_t)(void *)m_enc + sizeof(*m_enc),
    379 				      m_enc->sadb_key_bits / 8);
    380 			printf("\n");
    381 		}
    382 	}
    383 
    384 	/* authentication key */
    385 	if (m_auth != NULL) {
    386 		printf("\tA: ");
    387 		GETMSGV2S(str_alg_auth, m_sa->sadb_sa_auth);
    388 		ipsec_hexdump((caddr_t)(void *)m_auth + sizeof(*m_auth),
    389 		              m_auth->sadb_key_bits / 8);
    390 		printf("\n");
    391 	}
    392 
    393 	/* replay windoe size & flags */
    394 	printf("\tseq=0x%08x replay=%u flags=0x%08x ",
    395 		m_sa2->sadb_x_sa2_sequence,
    396 		m_sa->sadb_sa_replay,
    397 		m_sa->sadb_sa_flags);
    398 
    399 	/* state */
    400 	printf("state=");
    401 	GETMSGSTR(str_state, m_sa->sadb_sa_state);
    402 	printf("\n");
    403 
    404 	/* lifetime */
    405 	if (m_lftc != NULL) {
    406 		time_t tmp_time = time(0);
    407 
    408 		printf("\tcreated: %s",
    409 			str_time((long)m_lftc->sadb_lifetime_addtime));
    410 		printf("\tcurrent: %s\n", str_time(tmp_time));
    411 		printf("\tdiff: %lu(s)",
    412 			(u_long)(m_lftc->sadb_lifetime_addtime == 0 ?
    413 			0 : (tmp_time - m_lftc->sadb_lifetime_addtime)));
    414 
    415 		printf("\thard: %lu(s)",
    416 			(u_long)(m_lfth == NULL ?
    417 			0 : m_lfth->sadb_lifetime_addtime));
    418 		printf("\tsoft: %lu(s)\n",
    419 			(u_long)(m_lfts == NULL ?
    420 			0 : m_lfts->sadb_lifetime_addtime));
    421 
    422 		printf("\tlast: %s",
    423 			str_time((long)m_lftc->sadb_lifetime_usetime));
    424 		printf("\thard: %lu(s)",
    425 			(u_long)(m_lfth == NULL ?
    426 			0 : m_lfth->sadb_lifetime_usetime));
    427 		printf("\tsoft: %lu(s)\n",
    428 			(u_long)(m_lfts == NULL ?
    429 			0 : m_lfts->sadb_lifetime_usetime));
    430 
    431 		str_lifetime_byte(m_lftc, "current");
    432 		str_lifetime_byte(m_lfth, "hard");
    433 		str_lifetime_byte(m_lfts, "soft");
    434 		printf("\n");
    435 
    436 		printf("\tallocated: %lu",
    437 			(unsigned long)m_lftc->sadb_lifetime_allocations);
    438 		printf("\thard: %lu",
    439 			(u_long)(m_lfth == NULL ?
    440 			0 : m_lfth->sadb_lifetime_allocations));
    441 		printf("\tsoft: %lu\n",
    442 			(u_long)(m_lfts == NULL ?
    443 			0 : m_lfts->sadb_lifetime_allocations));
    444 	}
    445 
    446 #ifdef SADB_X_EXT_SEC_CTX
    447 	if (m_sec_ctx != NULL) {
    448 		printf("\tsecurity context doi: %u\n",
    449 					m_sec_ctx->sadb_x_ctx_doi);
    450 		printf("\tsecurity context algorithm: %u\n",
    451 					m_sec_ctx->sadb_x_ctx_alg);
    452 		printf("\tsecurity context length: %u\n",
    453 					m_sec_ctx->sadb_x_ctx_len);
    454 		printf("\tsecurity context: %s\n",
    455 			(char *)m_sec_ctx + sizeof(struct sadb_x_sec_ctx));
    456 	}
    457 #endif
    458 
    459 	printf("\tsadb_seq=%lu pid=%lu ",
    460 		(u_long)m->sadb_msg_seq,
    461 		(u_long)m->sadb_msg_pid);
    462 
    463 	/* XXX DEBUG */
    464 	printf("refcnt=%u\n", m->sadb_msg_reserved);
    465 
    466 	return;
    467 }
    468 
    469 void
    470 pfkey_spdump(m)
    471 	struct sadb_msg *m;
    472 {
    473 	pfkey_spdump1(m, 0);
    474 }
    475 
    476 void
    477 pfkey_spdump_withports(m)
    478 	struct sadb_msg *m;
    479 {
    480 	pfkey_spdump1(m, 1);
    481 }
    482 
    483 static void
    484 pfkey_spdump1(m, withports)
    485 	struct sadb_msg *m;
    486 	int withports;
    487 {
    488 	char pbuf[NI_MAXSERV];
    489 	caddr_t mhp[SADB_EXT_MAX + 1];
    490 	struct sadb_address *m_saddr, *m_daddr;
    491 #ifdef SADB_X_EXT_TAG
    492 	struct sadb_x_tag *m_tag;
    493 #endif
    494 	struct sadb_x_policy *m_xpl;
    495 	struct sadb_lifetime *m_lftc = NULL, *m_lfth = NULL;
    496 #ifdef SADB_X_EXT_SEC_CTX
    497 	struct sadb_x_sec_ctx *m_sec_ctx;
    498 #endif
    499 	struct sockaddr *sa;
    500 	u_int16_t sport = 0, dport = 0;
    501 
    502 	/* check pfkey message. */
    503 	if (pfkey_align(m, mhp)) {
    504 		printf("%s\n", ipsec_strerror());
    505 		return;
    506 	}
    507 	if (pfkey_check(mhp)) {
    508 		printf("%s\n", ipsec_strerror());
    509 		return;
    510 	}
    511 
    512 	m_saddr = (void *)mhp[SADB_EXT_ADDRESS_SRC];
    513 	m_daddr = (void *)mhp[SADB_EXT_ADDRESS_DST];
    514 #ifdef SADB_X_EXT_TAG
    515 	m_tag = (void *)mhp[SADB_X_EXT_TAG];
    516 #endif
    517 	m_xpl = (void *)mhp[SADB_X_EXT_POLICY];
    518 	m_lftc = (void *)mhp[SADB_EXT_LIFETIME_CURRENT];
    519 	m_lfth = (void *)mhp[SADB_EXT_LIFETIME_HARD];
    520 
    521 #ifdef SADB_X_EXT_SEC_CTX
    522 	m_sec_ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX];
    523 #endif
    524 #ifdef __linux__
    525 	/* *bsd indicates per-socket policies by omiting src and dst
    526 	 * extensions. Linux always includes them, but we can catch it
    527 	 * by checkin for policy id.
    528 	 */
    529 	if (m_xpl->sadb_x_policy_id % 8 >= 3) {
    530 		printf("(per-socket policy) ");
    531 	} else
    532 #endif
    533 	if (m_saddr && m_daddr) {
    534 		/* source address */
    535 		sa = (void *)(m_saddr + 1);
    536 		switch (sa->sa_family) {
    537 		case AF_INET:
    538 		case AF_INET6:
    539 			if (getnameinfo(sa, (socklen_t)sysdep_sa_len(sa), NULL,
    540 			    0, pbuf, sizeof(pbuf), NI_NUMERICSERV) != 0)
    541 				sport = 0;	/*XXX*/
    542 			else
    543 				sport = atoi(pbuf);
    544 			printf("%s%s ", str_ipaddr(sa),
    545 				str_prefport((u_int)sa->sa_family,
    546 				    (u_int)m_saddr->sadb_address_prefixlen,
    547 				    (u_int)sport,
    548 				    (u_int)m_saddr->sadb_address_proto));
    549 			break;
    550 		default:
    551 			printf("unknown-af ");
    552 			break;
    553 		}
    554 
    555 		/* destination address */
    556 		sa = (void *)(m_daddr + 1);
    557 		switch (sa->sa_family) {
    558 		case AF_INET:
    559 		case AF_INET6:
    560 			if (getnameinfo(sa, (socklen_t)sysdep_sa_len(sa), NULL,
    561 			    0, pbuf, sizeof(pbuf), NI_NUMERICSERV) != 0)
    562 				dport = 0;	/*XXX*/
    563 			else
    564 				dport = atoi(pbuf);
    565 			printf("%s%s ", str_ipaddr(sa),
    566 				str_prefport((u_int)sa->sa_family,
    567 				    (u_int)m_daddr->sadb_address_prefixlen,
    568 				    (u_int)dport,
    569 				    (u_int)m_saddr->sadb_address_proto));
    570 			break;
    571 		default:
    572 			printf("unknown-af ");
    573 			break;
    574 		}
    575 
    576 		/* upper layer protocol */
    577 		if (m_saddr->sadb_address_proto !=
    578 		    m_daddr->sadb_address_proto) {
    579 			printf("upper layer protocol mismatched.\n");
    580 			return;
    581 		}
    582 		str_upperspec((u_int)m_saddr->sadb_address_proto, (u_int)sport,
    583 		    (u_int)dport);
    584 	}
    585 #ifdef SADB_X_EXT_TAG
    586 	else if (m_tag)
    587 		printf("tagged \"%s\" ", m_tag->sadb_x_tag_name);
    588 #endif
    589 	else
    590 		printf("(no selector, probably per-socket policy) ");
    591 
    592 	/* policy */
    593     {
    594 	char *d_xpl;
    595 
    596 	if (m_xpl == NULL) {
    597 		printf("no X_POLICY extension.\n");
    598 		return;
    599 	}
    600 	if (withports)
    601 		d_xpl = ipsec_dump_policy_withports(m_xpl, "\n\t");
    602 	else
    603 		d_xpl = ipsec_dump_policy((ipsec_policy_t)m_xpl, "\n\t");
    604 
    605 	if (!d_xpl)
    606 		printf("\n\tPolicy:[%s]\n", ipsec_strerror());
    607 	else {
    608 		/* dump SPD */
    609 		printf("\n\t%s\n", d_xpl);
    610 		free(d_xpl);
    611 	}
    612     }
    613 
    614 	/* lifetime */
    615 	if (m_lftc) {
    616 		printf("\tcreated: %s  ",
    617 			str_time((long)m_lftc->sadb_lifetime_addtime));
    618 		printf("lastused: %s\n",
    619 			str_time((long)m_lftc->sadb_lifetime_usetime));
    620 	}
    621 	if (m_lfth) {
    622 		printf("\tlifetime: %lu(s) ",
    623 			(u_long)m_lfth->sadb_lifetime_addtime);
    624 		printf("validtime: %lu(s)\n",
    625 			(u_long)m_lfth->sadb_lifetime_usetime);
    626 	}
    627 
    628 #ifdef SADB_X_EXT_SEC_CTX
    629 	if (m_sec_ctx != NULL) {
    630 		printf("\tsecurity context doi: %u\n",
    631 					m_sec_ctx->sadb_x_ctx_doi);
    632 		printf("\tsecurity context algorithm: %u\n",
    633 					m_sec_ctx->sadb_x_ctx_alg);
    634 		printf("\tsecurity context length: %u\n",
    635 					m_sec_ctx->sadb_x_ctx_len);
    636 		printf("\tsecurity context: %s\n",
    637 			(char *)m_sec_ctx + sizeof(struct sadb_x_sec_ctx));
    638 	}
    639 #endif
    640 
    641 	printf("\tspid=%ld seq=%ld pid=%ld\n",
    642 		(u_long)m_xpl->sadb_x_policy_id,
    643 		(u_long)m->sadb_msg_seq,
    644 		(u_long)m->sadb_msg_pid);
    645 
    646 	/* XXX TEST */
    647 	printf("\trefcnt=%u\n", m->sadb_msg_reserved);
    648 
    649 	return;
    650 }
    651 
    652 /*
    653  * set "ipaddress" to buffer.
    654  */
    655 static char *
    656 str_ipaddr(sa)
    657 	struct sockaddr *sa;
    658 {
    659 	static char buf[NI_MAXHOST];
    660 	const int niflag = NI_NUMERICHOST;
    661 
    662 	if (sa == NULL)
    663 		return "";
    664 
    665 	if (getnameinfo(sa, (socklen_t)sysdep_sa_len(sa), buf, sizeof(buf),
    666 	    NULL, 0, niflag) == 0)
    667 		return buf;
    668 	return NULL;
    669 }
    670 
    671 /*
    672  * set "port" to buffer.
    673  */
    674 static char *
    675 str_ipport(sa)
    676 	struct sockaddr *sa;
    677 {
    678 	static char buf[NI_MAXHOST];
    679 	const int niflag = NI_NUMERICSERV;
    680 
    681 	if (sa == NULL)
    682 		return "";
    683 
    684 	if (getnameinfo(sa, (socklen_t)sysdep_sa_len(sa), NULL, 0,
    685 	    buf, sizeof(buf), niflag) == 0)
    686 		return buf;
    687 	return NULL;
    688 }
    689 
    690 
    691 /*
    692  * set "/prefix[port number]" to buffer.
    693  */
    694 static char *
    695 str_prefport(family, pref, port, ulp)
    696 	u_int family, pref, port, ulp;
    697 {
    698 	static char buf[128];
    699 	char prefbuf[128];
    700 	char portbuf[128];
    701 	int plen;
    702 
    703 	switch (family) {
    704 	case AF_INET:
    705 		plen = sizeof(struct in_addr) << 3;
    706 		break;
    707 	case AF_INET6:
    708 		plen = sizeof(struct in6_addr) << 3;
    709 		break;
    710 	default:
    711 		return "?";
    712 	}
    713 
    714 	if (pref == plen)
    715 		prefbuf[0] = '\0';
    716 	else
    717 		snprintf(prefbuf, sizeof(prefbuf), "/%u", pref);
    718 
    719 	switch (ulp) {
    720 	case IPPROTO_ICMP:
    721 	case IPPROTO_ICMPV6:
    722 	case IPPROTO_MH:
    723 	case IPPROTO_GRE:
    724 		memset(portbuf, 0, sizeof(portbuf));
    725 		break;
    726 	default:
    727 		if (port == IPSEC_PORT_ANY)
    728 			strcpy(portbuf, "[any]");
    729 		else
    730 			snprintf(portbuf, sizeof(portbuf), "[%u]", port);
    731 		break;
    732 	}
    733 
    734 	snprintf(buf, sizeof(buf), "%s%s", prefbuf, portbuf);
    735 
    736 	return buf;
    737 }
    738 
    739 static void
    740 str_upperspec(ulp, p1, p2)
    741 	u_int ulp, p1, p2;
    742 {
    743 	struct protoent *ent;
    744 
    745 	ent = getprotobynumber((int)ulp);
    746 	if (ent)
    747 		printf("%s", ent->p_name);
    748 	else
    749 		printf("%u", ulp);
    750 
    751 	if (p1 == IPSEC_PORT_ANY && p2 == IPSEC_PORT_ANY)
    752 		return;
    753 
    754 	switch (ulp) {
    755 	case IPPROTO_ICMP:
    756 	case IPPROTO_ICMPV6:
    757 	case IPPROTO_MH:
    758 		printf(" %u,%u", p1, p2);
    759 		break;
    760 	case IPPROTO_GRE:
    761 		printf(" %u", (p1 << 16) + p2);
    762 		break;
    763 	}
    764 }
    765 
    766 /*
    767  * set "Mon Day Time Year" to buffer
    768  */
    769 static char *
    770 str_time(t)
    771 	time_t t;
    772 {
    773 	static char buf[128];
    774 
    775 	if (t == 0) {
    776 		int i = 0;
    777 		for (;i < 20;) buf[i++] = ' ';
    778 	} else {
    779 		char *t0;
    780 		if ((t0 = ctime(&t)) == NULL)
    781 			memset(buf, '?', 20);
    782 		else
    783 			memcpy(buf, t0 + 4, 20);
    784 	}
    785 
    786 	buf[20] = '\0';
    787 
    788 	return(buf);
    789 }
    790 
    791 static void
    792 str_lifetime_byte(x, str)
    793 	struct sadb_lifetime *x;
    794 	char *str;
    795 {
    796 	double y;
    797 	char *unit;
    798 	int w;
    799 
    800 	if (x == NULL) {
    801 		printf("\t%s: 0(bytes)", str);
    802 		return;
    803 	}
    804 
    805 #if 0
    806 	if ((x->sadb_lifetime_bytes) / 1024 / 1024) {
    807 		y = (x->sadb_lifetime_bytes) * 1.0 / 1024 / 1024;
    808 		unit = "M";
    809 		w = 1;
    810 	} else if ((x->sadb_lifetime_bytes) / 1024) {
    811 		y = (x->sadb_lifetime_bytes) * 1.0 / 1024;
    812 		unit = "K";
    813 		w = 1;
    814 	} else {
    815 		y = (x->sadb_lifetime_bytes) * 1.0;
    816 		unit = "";
    817 		w = 0;
    818 	}
    819 #else
    820 	y = (x->sadb_lifetime_bytes) * 1.0;
    821 	unit = "";
    822 	w = 0;
    823 #endif
    824 	printf("\t%s: %.*f(%sbytes)", str, w, y, unit);
    825 }
    826