Home | History | Annotate | Line # | Download | only in libipsec
      1 /*	$NetBSD: pfkey_dump.c,v 1.26 2025/03/10 15:59:04 christos 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 const char *str_ipaddr(struct sockaddr *);
    109 static const char *str_ipport(struct sockaddr *);
    110 static const char *str_prefport(u_int, u_int, u_int, u_int);
    111 static void str_upperspec(u_int, u_int, u_int);
    112 static char *str_time(time_t);
    113 static void str_lifetime_byte(struct sadb_lifetime *, const 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 const 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 const char *str_mode[] = {
    141 	"any",
    142 	"transport",
    143 	"tunnel",
    144 };
    145 
    146 static const 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_AESGCM16
    201 	{ SADB_X_EALG_AESGCM16, "aes-gcm-16", },
    202 #endif
    203 #ifdef SADB_X_EALG_AESGMAC
    204 	{ SADB_X_EALG_AESGMAC, "aes-gmac", },
    205 #endif
    206 #ifdef SADB_X_EALG_CAMELLIACBC
    207 	{ SADB_X_EALG_CAMELLIACBC, "camellia-cbc", },
    208 #endif
    209 	{ -1, NULL, },
    210 };
    211 
    212 static struct val2str str_alg_comp[] = {
    213 	{ SADB_X_CALG_NONE, "none", },
    214 	{ SADB_X_CALG_OUI, "oui", },
    215 	{ SADB_X_CALG_DEFLATE, "deflate", },
    216 	{ SADB_X_CALG_LZS, "lzs", },
    217 	{ -1, NULL, },
    218 };
    219 
    220 /*
    221  * dump SADB_MSG formated.  For debugging, you should use kdebug_sadb().
    222  */
    223 
    224 void
    225 pfkey_sadump(struct sadb_msg *m)
    226 {
    227 	pfkey_sadump1(m, 0);
    228 }
    229 
    230 void
    231 pfkey_sadump_withports(struct sadb_msg *m)
    232 {
    233 	pfkey_sadump1(m, 1);
    234 }
    235 
    236 void
    237 pfkey_sadump1(struct sadb_msg *m, int withports)
    238 {
    239 	caddr_t mhp[SADB_EXT_MAX + 1];
    240 	struct sadb_sa *m_sa;
    241 	struct sadb_x_sa2 *m_sa2;
    242 	struct sadb_lifetime *m_lftc, *m_lfth, *m_lfts;
    243 	struct sadb_address *m_saddr, *m_daddr;
    244 #ifdef notdef
    245 	struct sadb_address *m_paddr;
    246 #endif
    247 	struct sadb_key *m_auth, *m_enc;
    248 #ifdef notdef
    249 	struct sadb_ident *m_sid, *m_did;
    250 	struct sadb_sens *m_sens;
    251 #endif
    252 #ifdef SADB_X_EXT_SEC_CTX
    253 	struct sadb_x_sec_ctx *m_sec_ctx;
    254 #endif
    255 #ifdef SADB_X_EXT_NAT_T_TYPE
    256 	struct sadb_x_nat_t_type *natt_type;
    257 	struct sadb_x_nat_t_port *natt_sport, *natt_dport;
    258 	struct sadb_address *natt_oa;
    259 #ifdef SADB_X_EXT_NAT_T_FRAG
    260 	struct sadb_x_nat_t_frag *esp_frag;
    261 #endif
    262 
    263 	int use_natt = 0;
    264 #endif
    265 	struct sockaddr *sa;
    266 
    267 	/* check pfkey message. */
    268 	if (pfkey_align(m, mhp)) {
    269 		printf("%s\n", ipsec_strerror());
    270 		return;
    271 	}
    272 	if (pfkey_check(mhp)) {
    273 		printf("%s\n", ipsec_strerror());
    274 		return;
    275 	}
    276 
    277 	m_sa = (void *)mhp[SADB_EXT_SA];
    278 	m_sa2 = (void *)mhp[SADB_X_EXT_SA2];
    279 	m_lftc = (void *)mhp[SADB_EXT_LIFETIME_CURRENT];
    280 	m_lfth = (void *)mhp[SADB_EXT_LIFETIME_HARD];
    281 	m_lfts = (void *)mhp[SADB_EXT_LIFETIME_SOFT];
    282 	m_saddr = (void *)mhp[SADB_EXT_ADDRESS_SRC];
    283 	m_daddr = (void *)mhp[SADB_EXT_ADDRESS_DST];
    284 #ifdef notdef
    285 	m_paddr = (void *)mhp[SADB_EXT_ADDRESS_PROXY];
    286 #endif
    287 	m_auth = (void *)mhp[SADB_EXT_KEY_AUTH];
    288 	m_enc = (void *)mhp[SADB_EXT_KEY_ENCRYPT];
    289 #ifdef notdef
    290 	m_sid = (void *)mhp[SADB_EXT_IDENTITY_SRC];
    291 	m_did = (void *)mhp[SADB_EXT_IDENTITY_DST];
    292 	m_sens = (void *)mhp[SADB_EXT_SENSITIVITY];
    293 #endif
    294 #ifdef SADB_X_EXT_SEC_CTX
    295 	m_sec_ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX];
    296 #endif
    297 #ifdef SADB_X_EXT_NAT_T_TYPE
    298 	natt_type = (void *)mhp[SADB_X_EXT_NAT_T_TYPE];
    299 	natt_sport = (void *)mhp[SADB_X_EXT_NAT_T_SPORT];
    300 	natt_dport = (void *)mhp[SADB_X_EXT_NAT_T_DPORT];
    301 	natt_oa = (void *)mhp[SADB_X_EXT_NAT_T_OA];
    302 #ifdef SADB_X_EXT_NAT_T_FRAG
    303 	esp_frag = (void *)mhp[SADB_X_EXT_NAT_T_FRAG];
    304 #endif
    305 
    306 	if (natt_type && natt_type->sadb_x_nat_t_type_type)
    307 		use_natt = 1;
    308 #endif
    309 	/* source address */
    310 	if (m_saddr == NULL) {
    311 		printf("no ADDRESS_SRC extension.\n");
    312 		return;
    313 	}
    314 	sa = (void *)(m_saddr + 1);
    315 	if (withports)
    316 		printf("%s[%s]", str_ipaddr(sa), str_ipport(sa));
    317 	else
    318 		printf("%s", str_ipaddr(sa));
    319 #ifdef SADB_X_EXT_NAT_T_TYPE
    320 	if (use_natt && natt_sport)
    321 		printf("[%u]", ntohs(natt_sport->sadb_x_nat_t_port_port));
    322 #endif
    323 	printf(" ");
    324 
    325 	/* destination address */
    326 	if (m_daddr == NULL) {
    327 		printf(" no ADDRESS_DST extension.\n");
    328 		return;
    329 	}
    330 	sa = (void *)(m_daddr + 1);
    331 	if (withports)
    332 		printf("%s[%s]", str_ipaddr(sa), str_ipport(sa));
    333 	else
    334 		printf("%s", str_ipaddr(sa));
    335 #ifdef SADB_X_EXT_NAT_T_TYPE
    336 	if (use_natt && natt_dport)
    337 		printf("[%u]", ntohs(natt_dport->sadb_x_nat_t_port_port));
    338 #endif
    339 	printf(" ");
    340 
    341 	/* SA type */
    342 	if (m_sa == NULL) {
    343 		printf("no SA extension.\n");
    344 		return;
    345 	}
    346 	if (m_sa2 == NULL) {
    347 		printf("no SA2 extension.\n");
    348 		return;
    349 	}
    350 	printf("\n\t");
    351 
    352 #ifdef SADB_X_EXT_NAT_T_TYPE
    353 	if (use_natt && m->sadb_msg_satype == SADB_SATYPE_ESP)
    354 		printf("esp-udp ");
    355 	else if (use_natt)
    356 		printf("natt+");
    357 
    358 	if (!use_natt || m->sadb_msg_satype != SADB_SATYPE_ESP)
    359 #endif
    360 	GETMSGSTR(str_satype, m->sadb_msg_satype);
    361 
    362 	printf("mode=");
    363 	GETMSGSTR(str_mode, m_sa2->sadb_x_sa2_mode);
    364 
    365 	printf("spi=%u(0x%08x) reqid=%u(0x%08x)\n",
    366 		(u_int32_t)ntohl(m_sa->sadb_sa_spi),
    367 		(u_int32_t)ntohl(m_sa->sadb_sa_spi),
    368 		(u_int32_t)m_sa2->sadb_x_sa2_reqid,
    369 		(u_int32_t)m_sa2->sadb_x_sa2_reqid);
    370 
    371 #ifdef SADB_X_EXT_NAT_T_TYPE
    372 	/* other NAT-T information */
    373 	if (use_natt && natt_oa)
    374 		printf("\tNAT OA=%s\n",
    375 		       str_ipaddr((void *)(natt_oa + 1)));
    376 
    377 #ifdef SADB_X_EXT_NAT_T_FRAG
    378 	if (use_natt && esp_frag && esp_frag->sadb_x_nat_t_frag_fraglen != 0)
    379 		printf("\tNAT-T esp_frag=%u\n", esp_frag->sadb_x_nat_t_frag_fraglen);
    380 #endif
    381 #endif
    382 
    383 	/* encryption key */
    384 	if (m->sadb_msg_satype == SADB_X_SATYPE_IPCOMP) {
    385 		printf("\tC: ");
    386 		GETMSGV2S(str_alg_comp, m_sa->sadb_sa_encrypt);
    387 	} else if (m->sadb_msg_satype == SADB_SATYPE_ESP) {
    388 		if (m_enc != NULL) {
    389 			printf("\tE: ");
    390 			GETMSGV2S(str_alg_enc, m_sa->sadb_sa_encrypt);
    391 			ipsec_hexdump((caddr_t)(void *)m_enc + sizeof(*m_enc),
    392 				      m_enc->sadb_key_bits / 8);
    393 			printf("\n");
    394 		}
    395 	}
    396 
    397 	/* authentication key */
    398 	if (m_auth != NULL) {
    399 		printf("\tA: ");
    400 		GETMSGV2S(str_alg_auth, m_sa->sadb_sa_auth);
    401 		ipsec_hexdump((caddr_t)(void *)m_auth + sizeof(*m_auth),
    402 		              m_auth->sadb_key_bits / 8);
    403 		printf("\n");
    404 	}
    405 
    406 	/* replay windoe size & flags */
    407 	printf("\tseq=0x%08x replay=%u flags=0x%08x ",
    408 		m_sa2->sadb_x_sa2_sequence,
    409 		m_sa->sadb_sa_replay,
    410 		m_sa->sadb_sa_flags);
    411 
    412 	/* state */
    413 	printf("state=");
    414 	GETMSGSTR(str_state, m_sa->sadb_sa_state);
    415 	printf("\n");
    416 
    417 	/* lifetime */
    418 	if (m_lftc != NULL) {
    419 		time_t tmp_time = time(0);
    420 
    421 		printf("\tcreated: %s",
    422 			str_time((long)m_lftc->sadb_lifetime_addtime));
    423 		printf("\tcurrent: %s\n", str_time(tmp_time));
    424 		printf("\tdiff: %lu(s)",
    425 			(u_long)(m_lftc->sadb_lifetime_addtime == 0 ?
    426 			0 : (tmp_time - m_lftc->sadb_lifetime_addtime)));
    427 
    428 		printf("\thard: %lu(s)",
    429 			(u_long)(m_lfth == NULL ?
    430 			0 : m_lfth->sadb_lifetime_addtime));
    431 		printf("\tsoft: %lu(s)\n",
    432 			(u_long)(m_lfts == NULL ?
    433 			0 : m_lfts->sadb_lifetime_addtime));
    434 
    435 		printf("\tlast: %s",
    436 			str_time((long)m_lftc->sadb_lifetime_usetime));
    437 		printf("\thard: %lu(s)",
    438 			(u_long)(m_lfth == NULL ?
    439 			0 : m_lfth->sadb_lifetime_usetime));
    440 		printf("\tsoft: %lu(s)\n",
    441 			(u_long)(m_lfts == NULL ?
    442 			0 : m_lfts->sadb_lifetime_usetime));
    443 
    444 		str_lifetime_byte(m_lftc, "current");
    445 		str_lifetime_byte(m_lfth, "hard");
    446 		str_lifetime_byte(m_lfts, "soft");
    447 		printf("\n");
    448 
    449 		printf("\tallocated: %lu",
    450 			(unsigned long)m_lftc->sadb_lifetime_allocations);
    451 		printf("\thard: %lu",
    452 			(u_long)(m_lfth == NULL ?
    453 			0 : m_lfth->sadb_lifetime_allocations));
    454 		printf("\tsoft: %lu\n",
    455 			(u_long)(m_lfts == NULL ?
    456 			0 : m_lfts->sadb_lifetime_allocations));
    457 	}
    458 
    459 #ifdef SADB_X_EXT_SEC_CTX
    460 	if (m_sec_ctx != NULL) {
    461 		printf("\tsecurity context doi: %u\n",
    462 					m_sec_ctx->sadb_x_ctx_doi);
    463 		printf("\tsecurity context algorithm: %u\n",
    464 					m_sec_ctx->sadb_x_ctx_alg);
    465 		printf("\tsecurity context length: %u\n",
    466 					m_sec_ctx->sadb_x_ctx_len);
    467 		printf("\tsecurity context: %s\n",
    468 			(char *)m_sec_ctx + sizeof(struct sadb_x_sec_ctx));
    469 	}
    470 #endif
    471 
    472 	printf("\tsadb_seq=%lu pid=%lu ",
    473 		(u_long)m->sadb_msg_seq,
    474 		(u_long)m->sadb_msg_pid);
    475 
    476 	/* XXX DEBUG */
    477 	printf("refcnt=%u\n", m->sadb_msg_reserved);
    478 
    479 	return;
    480 }
    481 
    482 void
    483 pfkey_spdump(struct sadb_msg *m)
    484 {
    485 	pfkey_spdump1(m, 0);
    486 }
    487 
    488 void
    489 pfkey_spdump_withports(struct sadb_msg *m)
    490 {
    491 	pfkey_spdump1(m, 1);
    492 }
    493 
    494 static void
    495 pfkey_spdump1(struct sadb_msg *m, int withports)
    496 {
    497 	char pbuf[NI_MAXSERV];
    498 	caddr_t mhp[SADB_EXT_MAX + 1];
    499 	struct sadb_address *m_saddr, *m_daddr;
    500 #ifdef SADB_X_EXT_TAG
    501 	struct sadb_x_tag *m_tag;
    502 #endif
    503 	struct sadb_x_policy *m_xpl;
    504 	struct sadb_lifetime *m_lftc = NULL, *m_lfth = NULL;
    505 #ifdef SADB_X_EXT_SEC_CTX
    506 	struct sadb_x_sec_ctx *m_sec_ctx;
    507 #endif
    508 	struct sockaddr *sa;
    509 	u_int16_t sport = 0, dport = 0;
    510 
    511 	/* check pfkey message. */
    512 	if (pfkey_align(m, mhp)) {
    513 		printf("%s\n", ipsec_strerror());
    514 		return;
    515 	}
    516 	if (pfkey_check(mhp)) {
    517 		printf("%s\n", ipsec_strerror());
    518 		return;
    519 	}
    520 
    521 	m_saddr = (void *)mhp[SADB_EXT_ADDRESS_SRC];
    522 	m_daddr = (void *)mhp[SADB_EXT_ADDRESS_DST];
    523 #ifdef SADB_X_EXT_TAG
    524 	m_tag = (void *)mhp[SADB_X_EXT_TAG];
    525 #endif
    526 	m_xpl = (void *)mhp[SADB_X_EXT_POLICY];
    527 	m_lftc = (void *)mhp[SADB_EXT_LIFETIME_CURRENT];
    528 	m_lfth = (void *)mhp[SADB_EXT_LIFETIME_HARD];
    529 
    530 #ifdef SADB_X_EXT_SEC_CTX
    531 	m_sec_ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX];
    532 #endif
    533 #ifdef __linux__
    534 	/* *bsd indicates per-socket policies by omiting src and dst
    535 	 * extensions. Linux always includes them, but we can catch it
    536 	 * by checkin for policy id.
    537 	 */
    538 	if (m_xpl->sadb_x_policy_id % 8 >= 3) {
    539 		printf("(per-socket policy) ");
    540 	} else
    541 #endif
    542 	if (m_saddr && m_daddr) {
    543 		/* source address */
    544 		sa = (void *)(m_saddr + 1);
    545 		switch (sa->sa_family) {
    546 		case AF_INET:
    547 		case AF_INET6:
    548 			if (getnameinfo(sa, (socklen_t)sysdep_sa_len(sa), NULL,
    549 			    0, pbuf, sizeof(pbuf), NI_NUMERICSERV) != 0)
    550 				sport = 0;	/*XXX*/
    551 			else
    552 				sport = atoi(pbuf);
    553 			printf("%s%s ", str_ipaddr(sa),
    554 				str_prefport((u_int)sa->sa_family,
    555 				    (u_int)m_saddr->sadb_address_prefixlen,
    556 				    (u_int)sport,
    557 				    (u_int)m_saddr->sadb_address_proto));
    558 			break;
    559 		default:
    560 			printf("unknown-af ");
    561 			break;
    562 		}
    563 
    564 		/* destination address */
    565 		sa = (void *)(m_daddr + 1);
    566 		switch (sa->sa_family) {
    567 		case AF_INET:
    568 		case AF_INET6:
    569 			if (getnameinfo(sa, (socklen_t)sysdep_sa_len(sa), NULL,
    570 			    0, pbuf, sizeof(pbuf), NI_NUMERICSERV) != 0)
    571 				dport = 0;	/*XXX*/
    572 			else
    573 				dport = atoi(pbuf);
    574 			printf("%s%s ", str_ipaddr(sa),
    575 				str_prefport((u_int)sa->sa_family,
    576 				    (u_int)m_daddr->sadb_address_prefixlen,
    577 				    (u_int)dport,
    578 				    (u_int)m_saddr->sadb_address_proto));
    579 			break;
    580 		default:
    581 			printf("unknown-af ");
    582 			break;
    583 		}
    584 
    585 		/* upper layer protocol */
    586 		if (m_saddr->sadb_address_proto !=
    587 		    m_daddr->sadb_address_proto) {
    588 			printf("upper layer protocol mismatched.\n");
    589 			return;
    590 		}
    591 		str_upperspec((u_int)m_saddr->sadb_address_proto, (u_int)sport,
    592 		    (u_int)dport);
    593 	}
    594 #ifdef SADB_X_EXT_TAG
    595 	else if (m_tag)
    596 		printf("tagged \"%s\" ", m_tag->sadb_x_tag_name);
    597 #endif
    598 	else
    599 		printf("(no selector, probably per-socket policy) ");
    600 
    601 	/* policy */
    602     {
    603 	char *d_xpl;
    604 
    605 	if (m_xpl == NULL) {
    606 		printf("no X_POLICY extension.\n");
    607 		return;
    608 	}
    609 	if (withports)
    610 		d_xpl = ipsec_dump_policy_withports(m_xpl, "\n\t");
    611 	else
    612 		d_xpl = ipsec_dump_policy((ipsec_policy_t)m_xpl, "\n\t");
    613 
    614 	if (!d_xpl)
    615 		printf("\n\tPolicy:[%s]\n", ipsec_strerror());
    616 	else {
    617 		/* dump SPD */
    618 		printf("\n\t%s\n", d_xpl);
    619 		free(d_xpl);
    620 	}
    621     }
    622 
    623 	/* lifetime */
    624 	if (m_lftc) {
    625 		printf("\tcreated: %s  ",
    626 			str_time((long)m_lftc->sadb_lifetime_addtime));
    627 		printf("lastused: %s\n",
    628 			str_time((long)m_lftc->sadb_lifetime_usetime));
    629 	}
    630 	if (m_lfth) {
    631 		printf("\tlifetime: %lu(s) ",
    632 			(u_long)m_lfth->sadb_lifetime_addtime);
    633 		printf("validtime: %lu(s)\n",
    634 			(u_long)m_lfth->sadb_lifetime_usetime);
    635 	}
    636 
    637 #ifdef SADB_X_EXT_SEC_CTX
    638 	if (m_sec_ctx != NULL) {
    639 		printf("\tsecurity context doi: %u\n",
    640 					m_sec_ctx->sadb_x_ctx_doi);
    641 		printf("\tsecurity context algorithm: %u\n",
    642 					m_sec_ctx->sadb_x_ctx_alg);
    643 		printf("\tsecurity context length: %u\n",
    644 					m_sec_ctx->sadb_x_ctx_len);
    645 		printf("\tsecurity context: %s\n",
    646 			(char *)m_sec_ctx + sizeof(struct sadb_x_sec_ctx));
    647 	}
    648 #endif
    649 
    650 	printf("\tspid=%ld seq=%ld pid=%ld\n",
    651 		(u_long)m_xpl->sadb_x_policy_id,
    652 		(u_long)m->sadb_msg_seq,
    653 		(u_long)m->sadb_msg_pid);
    654 
    655 	/* XXX TEST */
    656 	printf("\trefcnt=%u\n", m->sadb_msg_reserved);
    657 
    658 	return;
    659 }
    660 
    661 /*
    662  * set "ipaddress" to buffer.
    663  */
    664 static const char *
    665 str_ipaddr(struct sockaddr *sa)
    666 {
    667 	static char buf[NI_MAXHOST];
    668 	const int niflag = NI_NUMERICHOST;
    669 
    670 	if (sa == NULL)
    671 		return "";
    672 
    673 	if (getnameinfo(sa, (socklen_t)sysdep_sa_len(sa), buf, sizeof(buf),
    674 	    NULL, 0, niflag) == 0)
    675 		return buf;
    676 	return NULL;
    677 }
    678 
    679 /*
    680  * set "port" to buffer.
    681  */
    682 static const char *
    683 str_ipport(struct sockaddr *sa)
    684 {
    685 	static char buf[NI_MAXHOST];
    686 	const int niflag = NI_NUMERICSERV;
    687 
    688 	if (sa == NULL)
    689 		return "";
    690 
    691 	if (getnameinfo(sa, (socklen_t)sysdep_sa_len(sa), NULL, 0,
    692 	    buf, sizeof(buf), niflag) == 0)
    693 		return buf;
    694 	return NULL;
    695 }
    696 
    697 
    698 /*
    699  * set "/prefix[port number]" to buffer.
    700  */
    701 static const char *
    702 str_prefport(u_int family, u_int pref, u_int port, u_int ulp)
    703 {
    704 	static char buf[256];
    705 	char prefbuf[128];
    706 	char portbuf[128];
    707 	size_t plen;
    708 
    709 	switch (family) {
    710 	case AF_INET:
    711 		plen = sizeof(struct in_addr) << 3;
    712 		break;
    713 	case AF_INET6:
    714 		plen = sizeof(struct in6_addr) << 3;
    715 		break;
    716 	default:
    717 		return "?";
    718 	}
    719 
    720 	if (pref == plen)
    721 		prefbuf[0] = '\0';
    722 	else
    723 		snprintf(prefbuf, sizeof(prefbuf), "/%u", pref);
    724 
    725 	switch (ulp) {
    726 	case IPPROTO_ICMP:
    727 	case IPPROTO_ICMPV6:
    728 	case IPPROTO_MH:
    729 	case IPPROTO_GRE:
    730 		memset(portbuf, 0, sizeof(portbuf));
    731 		break;
    732 	default:
    733 		if (port == IPSEC_PORT_ANY)
    734 			strcpy(portbuf, "[any]");
    735 		else
    736 			snprintf(portbuf, sizeof(portbuf), "[%u]", port);
    737 		break;
    738 	}
    739 
    740 	snprintf(buf, sizeof(buf), "%s%s", prefbuf, portbuf);
    741 
    742 	return buf;
    743 }
    744 
    745 static void
    746 str_upperspec(u_int ulp, u_int p1, u_int p2)
    747 {
    748 	struct protoent *ent;
    749 
    750 	ent = getprotobynumber((int)ulp);
    751 	if (ent)
    752 		printf("%u(%s)", ulp, ent->p_name);
    753 	else
    754 		printf("%u", ulp);
    755 
    756 	if (p1 == IPSEC_PORT_ANY && p2 == IPSEC_PORT_ANY)
    757 		return;
    758 
    759 	switch (ulp) {
    760 	case IPPROTO_ICMP:
    761 	case IPPROTO_ICMPV6:
    762 	case IPPROTO_MH:
    763 		printf(" %u,%u", p1, p2);
    764 		break;
    765 	case IPPROTO_GRE:
    766 		printf(" %u", (p1 << 16) + p2);
    767 		break;
    768 	}
    769 }
    770 
    771 /*
    772  * set "Mon Day Time Year" to buffer
    773  */
    774 static char *
    775 str_time(time_t t)
    776 {
    777 	static char buf[128];
    778 
    779 	if (t == 0) {
    780 		int i = 0;
    781 		for (;i < 20;) buf[i++] = ' ';
    782 	} else {
    783 		char *t0;
    784 		if ((t0 = ctime(&t)) == NULL)
    785 			memset(buf, '?', 20);
    786 		else
    787 			memcpy(buf, t0 + 4, 20);
    788 	}
    789 
    790 	buf[20] = '\0';
    791 
    792 	return(buf);
    793 }
    794 
    795 static void
    796 str_lifetime_byte(struct sadb_lifetime *x, const char *str)
    797 {
    798 	double y;
    799 	const char *unit;
    800 	int w;
    801 
    802 	if (x == NULL) {
    803 		printf("\t%s: 0(bytes)", str);
    804 		return;
    805 	}
    806 
    807 #if 0
    808 	if ((x->sadb_lifetime_bytes) / 1024 / 1024) {
    809 		y = (x->sadb_lifetime_bytes) * 1.0 / 1024 / 1024;
    810 		unit = "M";
    811 		w = 1;
    812 	} else if ((x->sadb_lifetime_bytes) / 1024) {
    813 		y = (x->sadb_lifetime_bytes) * 1.0 / 1024;
    814 		unit = "K";
    815 		w = 1;
    816 	} else {
    817 		y = (x->sadb_lifetime_bytes) * 1.0;
    818 		unit = "";
    819 		w = 0;
    820 	}
    821 #else
    822 	y = (x->sadb_lifetime_bytes) * 1.0;
    823 	unit = "";
    824 	w = 0;
    825 #endif
    826 	printf("\t%s: %.*f(%sbytes)", str, w, y, unit);
    827 }
    828