Home | History | Annotate | Download | only in tcpdump
      1 /*
      2  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  * 3. Neither the name of the project nor the names of its contributors
     14  *    may be used to endorse or promote products derived from this software
     15  *    without specific prior written permission.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
     18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
     21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     27  * SUCH DAMAGE.
     28  *
     29  */
     30 
     31 #ifndef lint
     32 static const char rcsid[] _U_ =
     33     "@(#) $Header: /tcpdump/master/tcpdump/print-isakmp.c,v 1.51 2005/04/07 00:28:17 mcr Exp $ (LBL)";
     34 #endif
     35 
     36 #ifdef HAVE_CONFIG_H
     37 #include "config.h"
     38 #endif
     39 
     40 #include <tcpdump-stdinc.h>
     41 
     42 #include <string.h>
     43 
     44 #include <stdio.h>
     45 
     46 #include "isakmp.h"
     47 #include "ipsec_doi.h"
     48 #include "oakley.h"
     49 #include "interface.h"
     50 #include "addrtoname.h"
     51 #include "extract.h"                    /* must come after interface.h */
     52 
     53 #include "ip.h"
     54 #ifdef INET6
     55 #include "ip6.h"
     56 #endif
     57 
     58 #ifndef HAVE_SOCKADDR_STORAGE
     59 #define sockaddr_storage sockaddr
     60 #endif
     61 
     62 static const u_char *isakmp_sa_print(const struct isakmp_gen *,
     63 	u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
     64 static const u_char *isakmp_p_print(const struct isakmp_gen *,
     65 	u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
     66 static const u_char *isakmp_t_print(const struct isakmp_gen *,
     67 	u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
     68 static const u_char *isakmp_ke_print(const struct isakmp_gen *,
     69 	u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
     70 static const u_char *isakmp_id_print(const struct isakmp_gen *,
     71 	u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
     72 static const u_char *isakmp_cert_print(const struct isakmp_gen *,
     73 	u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
     74 static const u_char *isakmp_cr_print(const struct isakmp_gen *,
     75 	u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
     76 static const u_char *isakmp_sig_print(const struct isakmp_gen *,
     77 	u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
     78 static const u_char *isakmp_hash_print(const struct isakmp_gen *,
     79 	u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
     80 static const u_char *isakmp_nonce_print(const struct isakmp_gen *,
     81 	u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
     82 static const u_char *isakmp_n_print(const struct isakmp_gen *,
     83 	u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
     84 static const u_char *isakmp_d_print(const struct isakmp_gen *,
     85 	u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
     86 static const u_char *isakmp_vid_print(const struct isakmp_gen *,
     87 	u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
     88 static const u_char *isakmp_sub0_print(u_char, const struct isakmp_gen *,
     89 	const u_char *,	u_int32_t, u_int32_t, u_int32_t, int);
     90 static const u_char *isakmp_sub_print(u_char, const struct isakmp_gen *,
     91 	const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
     92 static char *numstr(int);
     93 static void safememcpy(void *, const void *, size_t);
     94 
     95 #define MAXINITIATORS	20
     96 int ninitiator = 0;
     97 struct {
     98 	cookie_t initiator;
     99 	struct sockaddr_storage iaddr;
    100 	struct sockaddr_storage raddr;
    101 } cookiecache[MAXINITIATORS];
    102 
    103 /* protocol id */
    104 static const char *protoidstr[] = {
    105 	NULL, "isakmp", "ipsec-ah", "ipsec-esp", "ipcomp",
    106 };
    107 
    108 /* isakmp->np */
    109 static const char *npstr[] = {
    110 	"none", "sa", "p", "t", "ke", "id", "cert", "cr", "hash",
    111 	"sig", "nonce", "n", "d", "vid"
    112 };
    113 
    114 /* isakmp->np */
    115 static const u_char *(*npfunc[])(const struct isakmp_gen *, u_int,
    116 		const u_char *, u_int32_t, u_int32_t, u_int32_t, int) = {
    117 	NULL,
    118 	isakmp_sa_print,
    119 	isakmp_p_print,
    120 	isakmp_t_print,
    121 	isakmp_ke_print,
    122 	isakmp_id_print,
    123 	isakmp_cert_print,
    124 	isakmp_cr_print,
    125 	isakmp_hash_print,
    126 	isakmp_sig_print,
    127 	isakmp_nonce_print,
    128 	isakmp_n_print,
    129 	isakmp_d_print,
    130 	isakmp_vid_print,
    131 };
    132 
    133 /* isakmp->etype */
    134 static const char *etypestr[] = {
    135 	"none", "base", "ident", "auth", "agg", "inf", NULL, NULL,
    136 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    137 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    138 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    139 	"oakley-quick", "oakley-newgroup",
    140 };
    141 
    142 #define STR_OR_ID(x, tab) \
    143 	(((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)])	? tab[(x)] : numstr(x))
    144 #define PROTOIDSTR(x)	STR_OR_ID(x, protoidstr)
    145 #define NPSTR(x)	STR_OR_ID(x, npstr)
    146 #define ETYPESTR(x)	STR_OR_ID(x, etypestr)
    147 
    148 #define NPFUNC(x) \
    149 	(((x) < sizeof(npfunc)/sizeof(npfunc[0]) && npfunc[(x)]) \
    150 		? npfunc[(x)] : NULL)
    151 
    152 static int
    153 iszero(u_char *p, size_t l)
    154 {
    155 	while (l--) {
    156 		if (*p++)
    157 			return 0;
    158 	}
    159 	return 1;
    160 }
    161 
    162 /* find cookie from initiator cache */
    163 static int
    164 cookie_find(cookie_t *in)
    165 {
    166 	int i;
    167 
    168 	for (i = 0; i < MAXINITIATORS; i++) {
    169 		if (memcmp(in, &cookiecache[i].initiator, sizeof(*in)) == 0)
    170 			return i;
    171 	}
    172 
    173 	return -1;
    174 }
    175 
    176 /* record initiator */
    177 static void
    178 cookie_record(cookie_t *in, const u_char *bp2)
    179 {
    180 	int i;
    181 	struct ip *ip;
    182 	struct sockaddr_in *sin;
    183 #ifdef INET6
    184 	struct ip6_hdr *ip6;
    185 	struct sockaddr_in6 *sin6;
    186 #endif
    187 
    188 	i = cookie_find(in);
    189 	if (0 <= i) {
    190 		ninitiator = (i + 1) % MAXINITIATORS;
    191 		return;
    192 	}
    193 
    194 	ip = (struct ip *)bp2;
    195 	switch (IP_V(ip)) {
    196 	case 4:
    197 		memset(&cookiecache[ninitiator].iaddr, 0,
    198 			sizeof(cookiecache[ninitiator].iaddr));
    199 		memset(&cookiecache[ninitiator].raddr, 0,
    200 			sizeof(cookiecache[ninitiator].raddr));
    201 
    202 		sin = (struct sockaddr_in *)&cookiecache[ninitiator].iaddr;
    203 #ifdef HAVE_SOCKADDR_SA_LEN
    204 		sin->sin_len = sizeof(struct sockaddr_in);
    205 #endif
    206 		sin->sin_family = AF_INET;
    207 		memcpy(&sin->sin_addr, &ip->ip_src, sizeof(ip->ip_src));
    208 		sin = (struct sockaddr_in *)&cookiecache[ninitiator].raddr;
    209 #ifdef HAVE_SOCKADDR_SA_LEN
    210 		sin->sin_len = sizeof(struct sockaddr_in);
    211 #endif
    212 		sin->sin_family = AF_INET;
    213 		memcpy(&sin->sin_addr, &ip->ip_dst, sizeof(ip->ip_dst));
    214 		break;
    215 #ifdef INET6
    216 	case 6:
    217 		memset(&cookiecache[ninitiator].iaddr, 0,
    218 			sizeof(cookiecache[ninitiator].iaddr));
    219 		memset(&cookiecache[ninitiator].raddr, 0,
    220 			sizeof(cookiecache[ninitiator].raddr));
    221 
    222 		ip6 = (struct ip6_hdr *)bp2;
    223 		sin6 = (struct sockaddr_in6 *)&cookiecache[ninitiator].iaddr;
    224 #ifdef HAVE_SOCKADDR_SA_LEN
    225 		sin6->sin6_len = sizeof(struct sockaddr_in6);
    226 #endif
    227 		sin6->sin6_family = AF_INET6;
    228 		memcpy(&sin6->sin6_addr, &ip6->ip6_src, sizeof(ip6->ip6_src));
    229 		sin6 = (struct sockaddr_in6 *)&cookiecache[ninitiator].raddr;
    230 #ifdef HAVE_SOCKADDR_SA_LEN
    231 		sin6->sin6_len = sizeof(struct sockaddr_in6);
    232 #endif
    233 		sin6->sin6_family = AF_INET6;
    234 		memcpy(&sin6->sin6_addr, &ip6->ip6_dst, sizeof(ip6->ip6_dst));
    235 		break;
    236 #endif
    237 	default:
    238 		return;
    239 	}
    240 	memcpy(&cookiecache[ninitiator].initiator, in, sizeof(*in));
    241 	ninitiator = (ninitiator + 1) % MAXINITIATORS;
    242 }
    243 
    244 #define cookie_isinitiator(x, y)	cookie_sidecheck((x), (y), 1)
    245 #define cookie_isresponder(x, y)	cookie_sidecheck((x), (y), 0)
    246 static int
    247 cookie_sidecheck(int i, const u_char *bp2, int initiator)
    248 {
    249 	struct sockaddr_storage ss;
    250 	struct sockaddr *sa;
    251 	struct ip *ip;
    252 	struct sockaddr_in *sin;
    253 #ifdef INET6
    254 	struct ip6_hdr *ip6;
    255 	struct sockaddr_in6 *sin6;
    256 #endif
    257 	int salen;
    258 
    259 	memset(&ss, 0, sizeof(ss));
    260 	ip = (struct ip *)bp2;
    261 	switch (IP_V(ip)) {
    262 	case 4:
    263 		sin = (struct sockaddr_in *)&ss;
    264 #ifdef HAVE_SOCKADDR_SA_LEN
    265 		sin->sin_len = sizeof(struct sockaddr_in);
    266 #endif
    267 		sin->sin_family = AF_INET;
    268 		memcpy(&sin->sin_addr, &ip->ip_src, sizeof(ip->ip_src));
    269 		break;
    270 #ifdef INET6
    271 	case 6:
    272 		ip6 = (struct ip6_hdr *)bp2;
    273 		sin6 = (struct sockaddr_in6 *)&ss;
    274 #ifdef HAVE_SOCKADDR_SA_LEN
    275 		sin6->sin6_len = sizeof(struct sockaddr_in6);
    276 #endif
    277 		sin6->sin6_family = AF_INET6;
    278 		memcpy(&sin6->sin6_addr, &ip6->ip6_src, sizeof(ip6->ip6_src));
    279 		break;
    280 #endif
    281 	default:
    282 		return 0;
    283 	}
    284 
    285 	sa = (struct sockaddr *)&ss;
    286 	if (initiator) {
    287 		if (sa->sa_family != ((struct sockaddr *)&cookiecache[i].iaddr)->sa_family)
    288 			return 0;
    289 #ifdef HAVE_SOCKADDR_SA_LEN
    290 		salen = sa->sa_len;
    291 #else
    292 #ifdef INET6
    293 		if (sa->sa_family == AF_INET6)
    294 			salen = sizeof(struct sockaddr_in6);
    295 		else
    296 			salen = sizeof(struct sockaddr);
    297 #else
    298 		salen = sizeof(struct sockaddr);
    299 #endif
    300 #endif
    301 		if (memcmp(&ss, &cookiecache[i].iaddr, salen) == 0)
    302 			return 1;
    303 	} else {
    304 		if (sa->sa_family != ((struct sockaddr *)&cookiecache[i].raddr)->sa_family)
    305 			return 0;
    306 #ifdef HAVE_SOCKADDR_SA_LEN
    307 		salen = sa->sa_len;
    308 #else
    309 #ifdef INET6
    310 		if (sa->sa_family == AF_INET6)
    311 			salen = sizeof(struct sockaddr_in6);
    312 		else
    313 			salen = sizeof(struct sockaddr);
    314 #else
    315 		salen = sizeof(struct sockaddr);
    316 #endif
    317 #endif
    318 		if (memcmp(&ss, &cookiecache[i].raddr, salen) == 0)
    319 			return 1;
    320 	}
    321 	return 0;
    322 }
    323 
    324 static int
    325 rawprint(caddr_t loc, size_t len)
    326 {
    327 	static u_char *p;
    328 	size_t i;
    329 
    330 	TCHECK2(*loc, len);
    331 
    332 	p = (u_char *)loc;
    333 	for (i = 0; i < len; i++)
    334 		printf("%02x", p[i] & 0xff);
    335 	return 1;
    336 trunc:
    337 	return 0;
    338 }
    339 
    340 struct attrmap {
    341 	const char *type;
    342 	u_int nvalue;
    343 	const char *value[30];	/*XXX*/
    344 };
    345 
    346 static const u_char *
    347 isakmp_attrmap_print(const u_char *p, const u_char *ep,
    348 	const struct attrmap *map, size_t nmap)
    349 {
    350 	u_int16_t *q;
    351 	int totlen;
    352 	u_int32_t t, v;
    353 
    354 	q = (u_int16_t *)p;
    355 	if (p[0] & 0x80)
    356 		totlen = 4;
    357 	else
    358 		totlen = 4 + EXTRACT_16BITS(&q[1]);
    359 	if (ep < p + totlen) {
    360 		printf("[|attr]");
    361 		return ep + 1;
    362 	}
    363 
    364 	printf("(");
    365 	t = EXTRACT_16BITS(&q[0]) & 0x7fff;
    366 	if (map && t < nmap && map[t].type)
    367 		printf("type=%s ", map[t].type);
    368 	else
    369 		printf("type=#%d ", t);
    370 	if (p[0] & 0x80) {
    371 		printf("value=");
    372 		v = EXTRACT_16BITS(&q[1]);
    373 		if (map && t < nmap && v < map[t].nvalue && map[t].value[v])
    374 			printf("%s", map[t].value[v]);
    375 		else
    376 			rawprint((caddr_t)&q[1], 2);
    377 	} else {
    378 		printf("len=%d value=", EXTRACT_16BITS(&q[1]));
    379 		rawprint((caddr_t)&p[4], EXTRACT_16BITS(&q[1]));
    380 	}
    381 	printf(")");
    382 	return p + totlen;
    383 }
    384 
    385 static const u_char *
    386 isakmp_attr_print(const u_char *p, const u_char *ep)
    387 {
    388 	u_int16_t *q;
    389 	int totlen;
    390 	u_int32_t t;
    391 
    392 	q = (u_int16_t *)p;
    393 	if (p[0] & 0x80)
    394 		totlen = 4;
    395 	else
    396 		totlen = 4 + EXTRACT_16BITS(&q[1]);
    397 	if (ep < p + totlen) {
    398 		printf("[|attr]");
    399 		return ep + 1;
    400 	}
    401 
    402 	printf("(");
    403 	t = EXTRACT_16BITS(&q[0]) & 0x7fff;
    404 	printf("type=#%d ", t);
    405 	if (p[0] & 0x80) {
    406 		printf("value=");
    407 		t = q[1];
    408 		rawprint((caddr_t)&q[1], 2);
    409 	} else {
    410 		printf("len=%d value=", EXTRACT_16BITS(&q[1]));
    411 		rawprint((caddr_t)&p[2], EXTRACT_16BITS(&q[1]));
    412 	}
    413 	printf(")");
    414 	return p + totlen;
    415 }
    416 
    417 static const u_char *
    418 isakmp_sa_print(const struct isakmp_gen *ext,
    419 		u_int item_len _U_,
    420 		const u_char *ep, u_int32_t phase, u_int32_t doi0 _U_,
    421 		u_int32_t proto0, int depth)
    422 {
    423 	const struct isakmp_pl_sa *p;
    424 	struct isakmp_pl_sa sa;
    425 	const u_int32_t *q;
    426 	u_int32_t doi, sit, ident;
    427 	const u_char *cp, *np;
    428 	int t;
    429 
    430 	printf("%s:", NPSTR(ISAKMP_NPTYPE_SA));
    431 
    432 	p = (struct isakmp_pl_sa *)ext;
    433 	TCHECK(*p);
    434 	safememcpy(&sa, ext, sizeof(sa));
    435 	doi = ntohl(sa.doi);
    436 	sit = ntohl(sa.sit);
    437 	if (doi != 1) {
    438 		printf(" doi=%d", doi);
    439 		printf(" situation=%u", (u_int32_t)ntohl(sa.sit));
    440 		return (u_char *)(p + 1);
    441 	}
    442 
    443 	printf(" doi=ipsec");
    444 	q = (u_int32_t *)&sa.sit;
    445 	printf(" situation=");
    446 	t = 0;
    447 	if (sit & 0x01) {
    448 		printf("identity");
    449 		t++;
    450 	}
    451 	if (sit & 0x02) {
    452 		printf("%ssecrecy", t ? "+" : "");
    453 		t++;
    454 	}
    455 	if (sit & 0x04)
    456 		printf("%sintegrity", t ? "+" : "");
    457 
    458 	np = (u_char *)ext + sizeof(sa);
    459 	if (sit != 0x01) {
    460 		TCHECK2(*(ext + 1), sizeof(ident));
    461 		safememcpy(&ident, ext + 1, sizeof(ident));
    462 		printf(" ident=%u", (u_int32_t)ntohl(ident));
    463 		np += sizeof(ident);
    464 	}
    465 
    466 	ext = (struct isakmp_gen *)np;
    467 	TCHECK(*ext);
    468 
    469 	cp = isakmp_sub_print(ISAKMP_NPTYPE_P, ext, ep, phase, doi, proto0,
    470 		depth);
    471 
    472 	return cp;
    473 trunc:
    474 	printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_SA));
    475 	return NULL;
    476 }
    477 
    478 static const u_char *
    479 isakmp_p_print(const struct isakmp_gen *ext, u_int item_len _U_,
    480 	       const u_char *ep, u_int32_t phase, u_int32_t doi0,
    481 	       u_int32_t proto0 _U_, int depth)
    482 {
    483 	const struct isakmp_pl_p *p;
    484 	struct isakmp_pl_p prop;
    485 	const u_char *cp;
    486 
    487 	printf("%s:", NPSTR(ISAKMP_NPTYPE_P));
    488 
    489 	p = (struct isakmp_pl_p *)ext;
    490 	TCHECK(*p);
    491 	safememcpy(&prop, ext, sizeof(prop));
    492 	printf(" #%d protoid=%s transform=%d",
    493 		prop.p_no, PROTOIDSTR(prop.prot_id), prop.num_t);
    494 	if (prop.spi_size) {
    495 		printf(" spi=");
    496 		if (!rawprint((caddr_t)(p + 1), prop.spi_size))
    497 			goto trunc;
    498 	}
    499 
    500 	ext = (struct isakmp_gen *)((u_char *)(p + 1) + prop.spi_size);
    501 	TCHECK(*ext);
    502 
    503 	cp = isakmp_sub_print(ISAKMP_NPTYPE_T, ext, ep, phase, doi0,
    504 		prop.prot_id, depth);
    505 
    506 	return cp;
    507 trunc:
    508 	printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_P));
    509 	return NULL;
    510 }
    511 
    512 static const char *isakmp_p_map[] = {
    513 	NULL, "ike",
    514 };
    515 
    516 static const char *ah_p_map[] = {
    517 	NULL, "(reserved)", "md5", "sha", "1des",
    518 	"sha2-256", "sha2-384", "sha2-512",
    519 };
    520 
    521 static const char *esp_p_map[] = {
    522 	NULL, "1des-iv64", "1des", "3des", "rc5", "idea", "cast",
    523 	"blowfish", "3idea", "1des-iv32", "rc4", "null", "aes"
    524 };
    525 
    526 static const char *ipcomp_p_map[] = {
    527 	NULL, "oui", "deflate", "lzs",
    528 };
    529 
    530 const struct attrmap ipsec_t_map[] = {
    531 	{ NULL,	0, { NULL } },
    532 	{ "lifetype", 3, { NULL, "sec", "kb", }, },
    533 	{ "life", 0, { NULL } },
    534 	{ "group desc", 5,	{ NULL, "modp768", "modp1024", "EC2N 2^155",
    535 				  "EC2N 2^185", }, },
    536 	{ "enc mode", 3, { NULL, "tunnel", "transport", }, },
    537 	{ "auth", 5, { NULL, "hmac-md5", "hmac-sha1", "1des-mac", "keyed", }, },
    538 	{ "keylen", 0, { NULL } },
    539 	{ "rounds", 0, { NULL } },
    540 	{ "dictsize", 0, { NULL } },
    541 	{ "privalg", 0, { NULL } },
    542 };
    543 
    544 const struct attrmap oakley_t_map[] = {
    545 	{ NULL,	0, { NULL } },
    546 	{ "enc", 8,	{ NULL, "1des", "idea", "blowfish", "rc5",
    547 		 	  "3des", "cast", "aes", }, },
    548 	{ "hash", 7,	{ NULL, "md5", "sha1", "tiger",
    549 			  "sha2-256", "sha2-384", "sha2-512", }, },
    550 	{ "auth", 6,	{ NULL, "preshared", "dss", "rsa sig", "rsa enc",
    551 			  "rsa enc revised", }, },
    552 	{ "group desc", 5,	{ NULL, "modp768", "modp1024", "EC2N 2^155",
    553 				  "EC2N 2^185", }, },
    554 	{ "group type", 4,	{ NULL, "MODP", "ECP", "EC2N", }, },
    555 	{ "group prime", 0, { NULL } },
    556 	{ "group gen1", 0, { NULL } },
    557 	{ "group gen2", 0, { NULL } },
    558 	{ "group curve A", 0, { NULL } },
    559 	{ "group curve B", 0, { NULL } },
    560 	{ "lifetype", 3,	{ NULL, "sec", "kb", }, },
    561 	{ "lifeduration", 0, { NULL } },
    562 	{ "prf", 0, { NULL } },
    563 	{ "keylen", 0, { NULL } },
    564 	{ "field", 0, { NULL } },
    565 	{ "order", 0, { NULL } },
    566 };
    567 
    568 static const u_char *
    569 isakmp_t_print(const struct isakmp_gen *ext, u_int item_len,
    570 	const u_char *ep, u_int32_t phase _U_, u_int32_t doi _U_,
    571 	u_int32_t proto, int depth _U_)
    572 {
    573 	const struct isakmp_pl_t *p;
    574 	struct isakmp_pl_t t;
    575 	const u_char *cp;
    576 	const char *idstr;
    577 	const struct attrmap *map;
    578 	size_t nmap;
    579 	const u_char *ep2;
    580 
    581 	printf("%s:", NPSTR(ISAKMP_NPTYPE_T));
    582 
    583 	p = (struct isakmp_pl_t *)ext;
    584 	TCHECK(*p);
    585 	safememcpy(&t, ext, sizeof(t));
    586 
    587 	switch (proto) {
    588 	case 1:
    589 		idstr = STR_OR_ID(t.t_id, isakmp_p_map);
    590 		map = oakley_t_map;
    591 		nmap = sizeof(oakley_t_map)/sizeof(oakley_t_map[0]);
    592 		break;
    593 	case 2:
    594 		idstr = STR_OR_ID(t.t_id, ah_p_map);
    595 		map = ipsec_t_map;
    596 		nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
    597 		break;
    598 	case 3:
    599 		idstr = STR_OR_ID(t.t_id, esp_p_map);
    600 		map = ipsec_t_map;
    601 		nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
    602 		break;
    603 	case 4:
    604 		idstr = STR_OR_ID(t.t_id, ipcomp_p_map);
    605 		map = ipsec_t_map;
    606 		nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
    607 		break;
    608 	default:
    609 		idstr = NULL;
    610 		map = NULL;
    611 		nmap = 0;
    612 		break;
    613 	}
    614 
    615 	if (idstr)
    616 		printf(" #%d id=%s ", t.t_no, idstr);
    617 	else
    618 		printf(" #%d id=%d ", t.t_no, t.t_id);
    619 	cp = (u_char *)(p + 1);
    620 	ep2 = (u_char *)p + item_len;
    621 	while (cp < ep && cp < ep2) {
    622 		if (map && nmap) {
    623 			cp = isakmp_attrmap_print(cp, (ep < ep2) ? ep : ep2,
    624 				map, nmap);
    625 		} else
    626 			cp = isakmp_attr_print(cp, (ep < ep2) ? ep : ep2);
    627 	}
    628 	if (ep < ep2)
    629 		printf("...");
    630 	return cp;
    631 trunc:
    632 	printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_T));
    633 	return NULL;
    634 }
    635 
    636 static const u_char *
    637 isakmp_ke_print(const struct isakmp_gen *ext, u_int item_len _U_,
    638 		const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi _U_,
    639 		u_int32_t proto _U_, int depth _U_)
    640 {
    641 	struct isakmp_gen e;
    642 
    643 	printf("%s:", NPSTR(ISAKMP_NPTYPE_KE));
    644 
    645 	TCHECK(*ext);
    646 	safememcpy(&e, ext, sizeof(e));
    647 	printf(" key len=%d", ntohs(e.len) - 4);
    648 	if (2 < vflag && 4 < ntohs(e.len)) {
    649 		printf(" ");
    650 		if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
    651 			goto trunc;
    652 	}
    653 	return (u_char *)ext + ntohs(e.len);
    654 trunc:
    655 	printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_KE));
    656 	return NULL;
    657 }
    658 
    659 static const u_char *
    660 isakmp_id_print(const struct isakmp_gen *ext, u_int item_len _U_,
    661 		const u_char *ep _U_, u_int32_t phase, u_int32_t doi _U_,
    662 		u_int32_t proto _U_, int depth _U_)
    663 {
    664 #define USE_IPSECDOI_IN_PHASE1	1
    665 	const struct isakmp_pl_id *p;
    666 	struct isakmp_pl_id id;
    667 	static const char *idtypestr[] = {
    668 		"IPv4", "IPv4net", "IPv6", "IPv6net",
    669 	};
    670 	static const char *ipsecidtypestr[] = {
    671 		NULL, "IPv4", "FQDN", "user FQDN", "IPv4net", "IPv6",
    672 		"IPv6net", "IPv4range", "IPv6range", "ASN1 DN", "ASN1 GN",
    673 		"keyid",
    674 	};
    675 	int len;
    676 	const u_char *data;
    677 
    678 	printf("%s:", NPSTR(ISAKMP_NPTYPE_ID));
    679 
    680 	p = (struct isakmp_pl_id *)ext;
    681 	TCHECK(*p);
    682 	safememcpy(&id, ext, sizeof(id));
    683 	if (sizeof(*p) < item_len) {
    684 		data = (u_char *)(p + 1);
    685 		len = item_len - sizeof(*p);
    686 	} else {
    687 		data = NULL;
    688 		len = 0;
    689 	}
    690 
    691 #if 0 /*debug*/
    692 	printf(" [phase=%d doi=%d proto=%d]", phase, doi, proto);
    693 #endif
    694 	switch (phase) {
    695 #ifndef USE_IPSECDOI_IN_PHASE1
    696 	case 1:
    697 #endif
    698 	default:
    699 		printf(" idtype=%s", STR_OR_ID(id.d.id_type, idtypestr));
    700 		printf(" doi_data=%u",
    701 			(u_int32_t)(ntohl(id.d.doi_data) & 0xffffff));
    702 		break;
    703 
    704 #ifdef USE_IPSECDOI_IN_PHASE1
    705 	case 1:
    706 #endif
    707 	case 2:
    708 	    {
    709 		const struct ipsecdoi_id *p;
    710 		struct ipsecdoi_id id;
    711 		struct protoent *pe;
    712 
    713 		p = (struct ipsecdoi_id *)ext;
    714 		TCHECK(*p);
    715 		safememcpy(&id, ext, sizeof(id));
    716 		printf(" idtype=%s", STR_OR_ID(id.type, ipsecidtypestr));
    717 		if (id.proto_id) {
    718 #ifndef WIN32
    719                         // not supported on android
    720 			//setprotoent(1);
    721 #endif /* WIN32 */
    722 			pe = getprotobynumber(id.proto_id);
    723 			if (pe)
    724 				printf(" protoid=%s", pe->p_name);
    725 #ifndef WIN32
    726                         // not supported on android
    727 			//endprotoent();
    728 #endif /* WIN32 */
    729 		} else {
    730 			/* it DOES NOT mean IPPROTO_IP! */
    731 			printf(" protoid=%s", "0");
    732 		}
    733 		printf(" port=%d", ntohs(id.port));
    734 		if (!len)
    735 			break;
    736 		if (data == NULL)
    737 			goto trunc;
    738 		TCHECK2(*data, len);
    739 		switch (id.type) {
    740 		case IPSECDOI_ID_IPV4_ADDR:
    741 			if (len < 4)
    742 				printf(" len=%d [bad: < 4]", len);
    743 			else
    744 				printf(" len=%d %s", len, ipaddr_string(data));
    745 			len = 0;
    746 			break;
    747 		case IPSECDOI_ID_FQDN:
    748 		case IPSECDOI_ID_USER_FQDN:
    749 		    {
    750 			int i;
    751 			printf(" len=%d ", len);
    752 			for (i = 0; i < len; i++)
    753 				safeputchar(data[i]);
    754 			len = 0;
    755 			break;
    756 		    }
    757 		case IPSECDOI_ID_IPV4_ADDR_SUBNET:
    758 		    {
    759 			const u_char *mask;
    760 			if (len < 8)
    761 				printf(" len=%d [bad: < 8]", len);
    762 			else {
    763 				mask = data + sizeof(struct in_addr);
    764 				printf(" len=%d %s/%u.%u.%u.%u", len,
    765 					ipaddr_string(data),
    766 					mask[0], mask[1], mask[2], mask[3]);
    767 			}
    768 			len = 0;
    769 			break;
    770 		    }
    771 #ifdef INET6
    772 		case IPSECDOI_ID_IPV6_ADDR:
    773 			if (len < 16)
    774 				printf(" len=%d [bad: < 16]", len);
    775 			else
    776 				printf(" len=%d %s", len, ip6addr_string(data));
    777 			len = 0;
    778 			break;
    779 		case IPSECDOI_ID_IPV6_ADDR_SUBNET:
    780 		    {
    781 			const u_int32_t *mask;
    782 			if (len < 20)
    783 				printf(" len=%d [bad: < 20]", len);
    784 			else {
    785 				mask = (u_int32_t *)(data + sizeof(struct in6_addr));
    786 				/*XXX*/
    787 				printf(" len=%d %s/0x%08x%08x%08x%08x", len,
    788 					ip6addr_string(data),
    789 					mask[0], mask[1], mask[2], mask[3]);
    790 			}
    791 			len = 0;
    792 			break;
    793 		    }
    794 #endif /*INET6*/
    795 		case IPSECDOI_ID_IPV4_ADDR_RANGE:
    796 			if (len < 8)
    797 				printf(" len=%d [bad: < 8]", len);
    798 			else {
    799 				printf(" len=%d %s-%s", len,
    800 					ipaddr_string(data),
    801 					ipaddr_string(data + sizeof(struct in_addr)));
    802 			}
    803 			len = 0;
    804 			break;
    805 #ifdef INET6
    806 		case IPSECDOI_ID_IPV6_ADDR_RANGE:
    807 			if (len < 32)
    808 				printf(" len=%d [bad: < 32]", len);
    809 			else {
    810 				printf(" len=%d %s-%s", len,
    811 					ip6addr_string(data),
    812 					ip6addr_string(data + sizeof(struct in6_addr)));
    813 			}
    814 			len = 0;
    815 			break;
    816 #endif /*INET6*/
    817 		case IPSECDOI_ID_DER_ASN1_DN:
    818 		case IPSECDOI_ID_DER_ASN1_GN:
    819 		case IPSECDOI_ID_KEY_ID:
    820 			break;
    821 		}
    822 		break;
    823 	    }
    824 	}
    825 	if (data && len) {
    826 		printf(" len=%d", len);
    827 		if (2 < vflag) {
    828 			printf(" ");
    829 			if (!rawprint((caddr_t)data, len))
    830 				goto trunc;
    831 		}
    832 	}
    833 	return (u_char *)ext + item_len;
    834 trunc:
    835 	printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_ID));
    836 	return NULL;
    837 }
    838 
    839 static const u_char *
    840 isakmp_cert_print(const struct isakmp_gen *ext, u_int item_len _U_,
    841 		  const u_char *ep _U_, u_int32_t phase _U_,
    842 		  u_int32_t doi0 _U_,
    843 		  u_int32_t proto0 _U_, int depth _U_)
    844 {
    845 	const struct isakmp_pl_cert *p;
    846 	struct isakmp_pl_cert cert;
    847 	static const char *certstr[] = {
    848 		"none",	"pkcs7", "pgp", "dns",
    849 		"x509sign", "x509ke", "kerberos", "crl",
    850 		"arl", "spki", "x509attr",
    851 	};
    852 
    853 	printf("%s:", NPSTR(ISAKMP_NPTYPE_CERT));
    854 
    855 	p = (struct isakmp_pl_cert *)ext;
    856 	TCHECK(*p);
    857 	safememcpy(&cert, ext, sizeof(cert));
    858 	printf(" len=%d", item_len - 4);
    859 	printf(" type=%s", STR_OR_ID((cert.encode), certstr));
    860 	if (2 < vflag && 4 < item_len) {
    861 		printf(" ");
    862 		if (!rawprint((caddr_t)(ext + 1), item_len - 4))
    863 			goto trunc;
    864 	}
    865 	return (u_char *)ext + item_len;
    866 trunc:
    867 	printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_CERT));
    868 	return NULL;
    869 }
    870 
    871 static const u_char *
    872 isakmp_cr_print(const struct isakmp_gen *ext, u_int item_len _U_,
    873 		const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi0 _U_,
    874 		u_int32_t proto0 _U_, int depth _U_)
    875 {
    876 	const struct isakmp_pl_cert *p;
    877 	struct isakmp_pl_cert cert;
    878 	static const char *certstr[] = {
    879 		"none",	"pkcs7", "pgp", "dns",
    880 		"x509sign", "x509ke", "kerberos", "crl",
    881 		"arl", "spki", "x509attr",
    882 	};
    883 
    884 	printf("%s:", NPSTR(ISAKMP_NPTYPE_CR));
    885 
    886 	p = (struct isakmp_pl_cert *)ext;
    887 	TCHECK(*p);
    888 	safememcpy(&cert, ext, sizeof(cert));
    889 	printf(" len=%d", item_len - 4);
    890 	printf(" type=%s", STR_OR_ID((cert.encode), certstr));
    891 	if (2 < vflag && 4 < item_len) {
    892 		printf(" ");
    893 		if (!rawprint((caddr_t)(ext + 1), item_len - 4))
    894 			goto trunc;
    895 	}
    896 	return (u_char *)ext + item_len;
    897 trunc:
    898 	printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_CR));
    899 	return NULL;
    900 }
    901 
    902 static const u_char *
    903 isakmp_hash_print(const struct isakmp_gen *ext, u_int item_len _U_,
    904 		  const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi _U_,
    905 		  u_int32_t proto _U_, int depth _U_)
    906 {
    907 	struct isakmp_gen e;
    908 
    909 	printf("%s:", NPSTR(ISAKMP_NPTYPE_HASH));
    910 
    911 	TCHECK(*ext);
    912 	safememcpy(&e, ext, sizeof(e));
    913 	printf(" len=%d", ntohs(e.len) - 4);
    914 	if (2 < vflag && 4 < ntohs(e.len)) {
    915 		printf(" ");
    916 		if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
    917 			goto trunc;
    918 	}
    919 	return (u_char *)ext + ntohs(e.len);
    920 trunc:
    921 	printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_HASH));
    922 	return NULL;
    923 }
    924 
    925 static const u_char *
    926 isakmp_sig_print(const struct isakmp_gen *ext, u_int item_len _U_,
    927 		 const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi _U_,
    928 		 u_int32_t proto _U_, int depth _U_)
    929 {
    930 	struct isakmp_gen e;
    931 
    932 	printf("%s:", NPSTR(ISAKMP_NPTYPE_SIG));
    933 
    934 	TCHECK(*ext);
    935 	safememcpy(&e, ext, sizeof(e));
    936 	printf(" len=%d", ntohs(e.len) - 4);
    937 	if (2 < vflag && 4 < ntohs(e.len)) {
    938 		printf(" ");
    939 		if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
    940 			goto trunc;
    941 	}
    942 	return (u_char *)ext + ntohs(e.len);
    943 trunc:
    944 	printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_SIG));
    945 	return NULL;
    946 }
    947 
    948 static const u_char *
    949 isakmp_nonce_print(const struct isakmp_gen *ext,
    950 		   u_int item_len _U_,
    951 		   const u_char *ep _U_,
    952 		   u_int32_t phase _U_, u_int32_t doi _U_,
    953 		   u_int32_t proto _U_, int depth _U_)
    954 {
    955 	struct isakmp_gen e;
    956 
    957 	printf("%s:", NPSTR(ISAKMP_NPTYPE_NONCE));
    958 
    959 	TCHECK(*ext);
    960 	safememcpy(&e, ext, sizeof(e));
    961 	printf(" n len=%d", ntohs(e.len) - 4);
    962 	if (2 < vflag && 4 < ntohs(e.len)) {
    963 		printf(" ");
    964 		if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
    965 			goto trunc;
    966 	}
    967 	return (u_char *)ext + ntohs(e.len);
    968 trunc:
    969 	printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_NONCE));
    970 	return NULL;
    971 }
    972 
    973 static const u_char *
    974 isakmp_n_print(const struct isakmp_gen *ext, u_int item_len,
    975 	const u_char *ep, u_int32_t phase, u_int32_t doi0 _U_,
    976 	u_int32_t proto0 _U_, int depth)
    977 {
    978 	struct isakmp_pl_n *p, n;
    979 	const u_char *cp;
    980 	u_char *ep2;
    981 	u_int32_t doi;
    982 	u_int32_t proto;
    983 	static const char *notify_error_str[] = {
    984 		NULL,				"INVALID-PAYLOAD-TYPE",
    985 		"DOI-NOT-SUPPORTED",		"SITUATION-NOT-SUPPORTED",
    986 		"INVALID-COOKIE",		"INVALID-MAJOR-VERSION",
    987 		"INVALID-MINOR-VERSION",	"INVALID-EXCHANGE-TYPE",
    988 		"INVALID-FLAGS",		"INVALID-MESSAGE-ID",
    989 		"INVALID-PROTOCOL-ID",		"INVALID-SPI",
    990 		"INVALID-TRANSFORM-ID",		"ATTRIBUTES-NOT-SUPPORTED",
    991 		"NO-PROPOSAL-CHOSEN",		"BAD-PROPOSAL-SYNTAX",
    992 		"PAYLOAD-MALFORMED",		"INVALID-KEY-INFORMATION",
    993 		"INVALID-ID-INFORMATION",	"INVALID-CERT-ENCODING",
    994 		"INVALID-CERTIFICATE",		"CERT-TYPE-UNSUPPORTED",
    995 		"INVALID-CERT-AUTHORITY",	"INVALID-HASH-INFORMATION",
    996 		"AUTHENTICATION-FAILED",	"INVALID-SIGNATURE",
    997 		"ADDRESS-NOTIFICATION",		"NOTIFY-SA-LIFETIME",
    998 		"CERTIFICATE-UNAVAILABLE",	"UNSUPPORTED-EXCHANGE-TYPE",
    999 		"UNEQUAL-PAYLOAD-LENGTHS",
   1000 	};
   1001 	static const char *ipsec_notify_error_str[] = {
   1002 		"RESERVED",
   1003 	};
   1004 	static const char *notify_status_str[] = {
   1005 		"CONNECTED",
   1006 	};
   1007 	static const char *ipsec_notify_status_str[] = {
   1008 		"RESPONDER-LIFETIME",		"REPLAY-STATUS",
   1009 		"INITIAL-CONTACT",
   1010 	};
   1011 /* NOTE: these macro must be called with x in proper range */
   1012 
   1013 /* 0 - 8191 */
   1014 #define NOTIFY_ERROR_STR(x) \
   1015 	STR_OR_ID((x), notify_error_str)
   1016 
   1017 /* 8192 - 16383 */
   1018 #define IPSEC_NOTIFY_ERROR_STR(x) \
   1019 	STR_OR_ID((u_int)((x) - 8192), ipsec_notify_error_str)
   1020 
   1021 /* 16384 - 24575 */
   1022 #define NOTIFY_STATUS_STR(x) \
   1023 	STR_OR_ID((u_int)((x) - 16384), notify_status_str)
   1024 
   1025 /* 24576 - 32767 */
   1026 #define IPSEC_NOTIFY_STATUS_STR(x) \
   1027 	STR_OR_ID((u_int)((x) - 24576), ipsec_notify_status_str)
   1028 
   1029 	printf("%s:", NPSTR(ISAKMP_NPTYPE_N));
   1030 
   1031 	p = (struct isakmp_pl_n *)ext;
   1032 	TCHECK(*p);
   1033 	safememcpy(&n, ext, sizeof(n));
   1034 	doi = ntohl(n.doi);
   1035 	proto = n.prot_id;
   1036 	if (doi != 1) {
   1037 		printf(" doi=%d", doi);
   1038 		printf(" proto=%d", proto);
   1039 		if (ntohs(n.type) < 8192)
   1040 			printf(" type=%s", NOTIFY_ERROR_STR(ntohs(n.type)));
   1041 		else if (ntohs(n.type) < 16384)
   1042 			printf(" type=%s", numstr(ntohs(n.type)));
   1043 		else if (ntohs(n.type) < 24576)
   1044 			printf(" type=%s", NOTIFY_STATUS_STR(ntohs(n.type)));
   1045 		else
   1046 			printf(" type=%s", numstr(ntohs(n.type)));
   1047 		if (n.spi_size) {
   1048 			printf(" spi=");
   1049 			if (!rawprint((caddr_t)(p + 1), n.spi_size))
   1050 				goto trunc;
   1051 		}
   1052 		return (u_char *)(p + 1) + n.spi_size;
   1053 	}
   1054 
   1055 	printf(" doi=ipsec");
   1056 	printf(" proto=%s", PROTOIDSTR(proto));
   1057 	if (ntohs(n.type) < 8192)
   1058 		printf(" type=%s", NOTIFY_ERROR_STR(ntohs(n.type)));
   1059 	else if (ntohs(n.type) < 16384)
   1060 		printf(" type=%s", IPSEC_NOTIFY_ERROR_STR(ntohs(n.type)));
   1061 	else if (ntohs(n.type) < 24576)
   1062 		printf(" type=%s", NOTIFY_STATUS_STR(ntohs(n.type)));
   1063 	else if (ntohs(n.type) < 32768)
   1064 		printf(" type=%s", IPSEC_NOTIFY_STATUS_STR(ntohs(n.type)));
   1065 	else
   1066 		printf(" type=%s", numstr(ntohs(n.type)));
   1067 	if (n.spi_size) {
   1068 		printf(" spi=");
   1069 		if (!rawprint((caddr_t)(p + 1), n.spi_size))
   1070 			goto trunc;
   1071 	}
   1072 
   1073 	cp = (u_char *)(p + 1) + n.spi_size;
   1074 	ep2 = (u_char *)p + item_len;
   1075 
   1076 	if (cp < ep) {
   1077 		printf(" orig=(");
   1078 		switch (ntohs(n.type)) {
   1079 		case IPSECDOI_NTYPE_RESPONDER_LIFETIME:
   1080 		    {
   1081 			const struct attrmap *map = oakley_t_map;
   1082 			size_t nmap = sizeof(oakley_t_map)/sizeof(oakley_t_map[0]);
   1083 			while (cp < ep && cp < ep2) {
   1084 				cp = isakmp_attrmap_print(cp,
   1085 					(ep < ep2) ? ep : ep2, map, nmap);
   1086 			}
   1087 			break;
   1088 		    }
   1089 		case IPSECDOI_NTYPE_REPLAY_STATUS:
   1090 			printf("replay detection %sabled",
   1091 				(*(u_int32_t *)cp) ? "en" : "dis");
   1092 			break;
   1093 		case ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN:
   1094 			if (isakmp_sub_print(ISAKMP_NPTYPE_SA,
   1095 			    (struct isakmp_gen *)cp, ep, phase, doi, proto,
   1096 			    depth) == NULL)
   1097 				return NULL;
   1098 			break;
   1099 		default:
   1100 			/* NULL is dummy */
   1101 			isakmp_print(gndo, cp,
   1102 				     item_len - sizeof(*p) - n.spi_size,
   1103 				     NULL);
   1104 		}
   1105 		printf(")");
   1106 	}
   1107 	return (u_char *)ext + item_len;
   1108 trunc:
   1109 	printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_N));
   1110 	return NULL;
   1111 }
   1112 
   1113 static const u_char *
   1114 isakmp_d_print(const struct isakmp_gen *ext, u_int item_len _U_,
   1115 	       const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi0 _U_,
   1116 	       u_int32_t proto0 _U_, int depth _U_)
   1117 {
   1118 	const struct isakmp_pl_d *p;
   1119 	struct isakmp_pl_d d;
   1120 	const u_int8_t *q;
   1121 	u_int32_t doi;
   1122 	u_int32_t proto;
   1123 	int i;
   1124 
   1125 	printf("%s:", NPSTR(ISAKMP_NPTYPE_D));
   1126 
   1127 	p = (struct isakmp_pl_d *)ext;
   1128 	TCHECK(*p);
   1129 	safememcpy(&d, ext, sizeof(d));
   1130 	doi = ntohl(d.doi);
   1131 	proto = d.prot_id;
   1132 	if (doi != 1) {
   1133 		printf(" doi=%u", doi);
   1134 		printf(" proto=%u", proto);
   1135 	} else {
   1136 		printf(" doi=ipsec");
   1137 		printf(" proto=%s", PROTOIDSTR(proto));
   1138 	}
   1139 	printf(" spilen=%u", d.spi_size);
   1140 	printf(" nspi=%u", ntohs(d.num_spi));
   1141 	printf(" spi=");
   1142 	q = (u_int8_t *)(p + 1);
   1143 	for (i = 0; i < ntohs(d.num_spi); i++) {
   1144 		if (i != 0)
   1145 			printf(",");
   1146 		if (!rawprint((caddr_t)q, d.spi_size))
   1147 			goto trunc;
   1148 		q += d.spi_size;
   1149 	}
   1150 	return q;
   1151 trunc:
   1152 	printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_D));
   1153 	return NULL;
   1154 }
   1155 
   1156 static const u_char *
   1157 isakmp_vid_print(const struct isakmp_gen *ext,
   1158 		 u_int item_len _U_, const u_char *ep _U_,
   1159 		 u_int32_t phase _U_, u_int32_t doi _U_,
   1160 		 u_int32_t proto _U_, int depth _U_)
   1161 {
   1162 	struct isakmp_gen e;
   1163 
   1164 	printf("%s:", NPSTR(ISAKMP_NPTYPE_VID));
   1165 
   1166 	TCHECK(*ext);
   1167 	safememcpy(&e, ext, sizeof(e));
   1168 	printf(" len=%d", ntohs(e.len) - 4);
   1169 	if (2 < vflag && 4 < ntohs(e.len)) {
   1170 		printf(" ");
   1171 		if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
   1172 			goto trunc;
   1173 	}
   1174 	return (u_char *)ext + ntohs(e.len);
   1175 trunc:
   1176 	printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_VID));
   1177 	return NULL;
   1178 }
   1179 
   1180 static const u_char *
   1181 isakmp_sub0_print(u_char np, const struct isakmp_gen *ext, const u_char *ep,
   1182 	u_int32_t phase, u_int32_t doi, u_int32_t proto, int depth)
   1183 {
   1184 	const u_char *cp;
   1185 	struct isakmp_gen e;
   1186 	u_int item_len;
   1187 
   1188 	cp = (u_char *)ext;
   1189 	TCHECK(*ext);
   1190 	safememcpy(&e, ext, sizeof(e));
   1191 
   1192 	/*
   1193 	 * Since we can't have a payload length of less than 4 bytes,
   1194 	 * we need to bail out here if the generic header is nonsensical
   1195 	 * or truncated, otherwise we could loop forever processing
   1196 	 * zero-length items or otherwise misdissect the packet.
   1197 	 */
   1198 	item_len = ntohs(e.len);
   1199 	if (item_len <= 4)
   1200 		return NULL;
   1201 
   1202 	if (NPFUNC(np)) {
   1203 		/*
   1204 		 * XXX - what if item_len is too short, or too long,
   1205 		 * for this payload type?
   1206 		 */
   1207 		cp = (*npfunc[np])(ext, item_len, ep, phase, doi, proto, depth);
   1208 	} else {
   1209 		printf("%s", NPSTR(np));
   1210 		cp += item_len;
   1211 	}
   1212 
   1213 	return cp;
   1214 trunc:
   1215 	printf(" [|isakmp]");
   1216 	return NULL;
   1217 }
   1218 
   1219 static const u_char *
   1220 isakmp_sub_print(u_char np, const struct isakmp_gen *ext, const u_char *ep,
   1221 	u_int32_t phase, u_int32_t doi, u_int32_t proto, int depth)
   1222 {
   1223 	const u_char *cp;
   1224 	int i;
   1225 	struct isakmp_gen e;
   1226 
   1227 	cp = (const u_char *)ext;
   1228 
   1229 	while (np) {
   1230 		TCHECK(*ext);
   1231 
   1232 		safememcpy(&e, ext, sizeof(e));
   1233 
   1234 		TCHECK2(*ext, ntohs(e.len));
   1235 
   1236 		depth++;
   1237 		printf("\n");
   1238 		for (i = 0; i < depth; i++)
   1239 			printf("    ");
   1240 		printf("(");
   1241 		cp = isakmp_sub0_print(np, ext, ep, phase, doi, proto, depth);
   1242 		printf(")");
   1243 		depth--;
   1244 
   1245 		if (cp == NULL) {
   1246 			/* Zero-length subitem */
   1247 			return NULL;
   1248 		}
   1249 
   1250 		np = e.np;
   1251 		ext = (struct isakmp_gen *)cp;
   1252 	}
   1253 	return cp;
   1254 trunc:
   1255 	printf(" [|%s]", NPSTR(np));
   1256 	return NULL;
   1257 }
   1258 
   1259 static char *
   1260 numstr(int x)
   1261 {
   1262 	static char buf[20];
   1263 	snprintf(buf, sizeof(buf), "#%d", x);
   1264 	return buf;
   1265 }
   1266 
   1267 /*
   1268  * some compiler tries to optimize memcpy(), using the alignment constraint
   1269  * on the argument pointer type.  by using this function, we try to avoid the
   1270  * optimization.
   1271  */
   1272 static void
   1273 safememcpy(void *p, const void *q, size_t l)
   1274 {
   1275 	memcpy(p, q, l);
   1276 }
   1277 
   1278 void
   1279 isakmp_print(netdissect_options *ndo,
   1280 	     const u_char *bp, u_int length,
   1281 	     const u_char *bp2)
   1282 {
   1283 	const struct isakmp *p;
   1284 	struct isakmp base;
   1285 	const u_char *ep;
   1286 	u_char np;
   1287 	int i;
   1288 	int phase;
   1289 	int major, minor;
   1290 
   1291 	p = (const struct isakmp *)bp;
   1292 	ep = ndo->ndo_snapend;
   1293 
   1294 	if ((struct isakmp *)ep < p + 1) {
   1295 		printf("[|isakmp]");
   1296 		return;
   1297 	}
   1298 
   1299 	safememcpy(&base, p, sizeof(base));
   1300 
   1301 	printf("isakmp");
   1302 	if (vflag) {
   1303 		major = (base.vers & ISAKMP_VERS_MAJOR)
   1304 				>> ISAKMP_VERS_MAJOR_SHIFT;
   1305 		minor = (base.vers & ISAKMP_VERS_MINOR)
   1306 				>> ISAKMP_VERS_MINOR_SHIFT;
   1307 		printf(" %d.%d", major, minor);
   1308 	}
   1309 
   1310 	if (vflag) {
   1311 		printf(" msgid ");
   1312 		rawprint((caddr_t)&base.msgid, sizeof(base.msgid));
   1313 	}
   1314 
   1315 	if (1 < vflag) {
   1316 		printf(" cookie ");
   1317 		rawprint((caddr_t)&base.i_ck, sizeof(base.i_ck));
   1318 		printf("->");
   1319 		rawprint((caddr_t)&base.r_ck, sizeof(base.r_ck));
   1320 	}
   1321 	printf(":");
   1322 
   1323 	phase = (*(u_int32_t *)base.msgid == 0) ? 1 : 2;
   1324 	if (phase == 1)
   1325 		printf(" phase %d", phase);
   1326 	else
   1327 		printf(" phase %d/others", phase);
   1328 
   1329 	i = cookie_find(&base.i_ck);
   1330 	if (i < 0) {
   1331 		if (iszero((u_char *)&base.r_ck, sizeof(base.r_ck))) {
   1332 			/* the first packet */
   1333 			printf(" I");
   1334 			if (bp2)
   1335 				cookie_record(&base.i_ck, bp2);
   1336 		} else
   1337 			printf(" ?");
   1338 	} else {
   1339 		if (bp2 && cookie_isinitiator(i, bp2))
   1340 			printf(" I");
   1341 		else if (bp2 && cookie_isresponder(i, bp2))
   1342 			printf(" R");
   1343 		else
   1344 			printf(" ?");
   1345 	}
   1346 
   1347 	printf(" %s", ETYPESTR(base.etype));
   1348 	if (base.flags) {
   1349 		printf("[%s%s]", base.flags & ISAKMP_FLAG_E ? "E" : "",
   1350 			base.flags & ISAKMP_FLAG_C ? "C" : "");
   1351 	}
   1352 
   1353 	if (vflag) {
   1354 		const struct isakmp_gen *ext;
   1355 		int nparen;
   1356 
   1357 #define CHECKLEN(p, np) \
   1358 		if (ep < (u_char *)(p)) {				\
   1359 			printf(" [|%s]", NPSTR(np));			\
   1360 			goto done;					\
   1361 		}
   1362 
   1363 		printf(":");
   1364 
   1365 		/* regardless of phase... */
   1366 		if (base.flags & ISAKMP_FLAG_E) {
   1367 			/*
   1368 			 * encrypted, nothing we can do right now.
   1369 			 * we hope to decrypt the packet in the future...
   1370 			 */
   1371 			printf(" [encrypted %s]", NPSTR(base.np));
   1372 			goto done;
   1373 		}
   1374 
   1375 		nparen = 0;
   1376 		CHECKLEN(p + 1, base.np)
   1377 
   1378 		np = base.np;
   1379 		ext = (struct isakmp_gen *)(p + 1);
   1380 		isakmp_sub_print(np, ext, ep, phase, 0, 0, 0);
   1381 	}
   1382 
   1383 done:
   1384 	if (vflag) {
   1385 		if (ntohl(base.len) != length) {
   1386 			printf(" (len mismatch: isakmp %u/ip %u)",
   1387 				(u_int32_t)ntohl(base.len), length);
   1388 		}
   1389 	}
   1390 }
   1391 
   1392 void
   1393 isakmp_rfc3948_print(netdissect_options *ndo,
   1394 		     const u_char *bp, u_int length,
   1395 		     const u_char *bp2)
   1396 {
   1397 	const u_char *ep;
   1398 	ep = ndo->ndo_snapend;
   1399 
   1400 	if(length == 1 && bp[0]==0xff) {
   1401 		ND_PRINT((ndo, "isakmp-nat-keep-alive"));
   1402 		return;
   1403 	}
   1404 
   1405 	if(length < 4) {
   1406 		goto trunc;
   1407 	}
   1408 
   1409 	/*
   1410 	 * see if this is an IKE packet
   1411 	 */
   1412 	if(bp[0]==0 && bp[1]==0 && bp[2]==0 && bp[3]==0) {
   1413 		ND_PRINT((ndo, "NONESP-encap: "));
   1414 		isakmp_print(ndo, bp+4, length-4, bp2);
   1415 		return;
   1416 	}
   1417 
   1418 	/* must be an ESP packet */
   1419 	{
   1420 		int nh, enh, padlen;
   1421 		int advance;
   1422 
   1423 		ND_PRINT((ndo, "UDP-encap: "));
   1424 
   1425 		advance = esp_print(ndo, bp, length, bp2, &enh, &padlen);
   1426 		if(advance <= 0)
   1427 			return;
   1428 
   1429 		bp += advance;
   1430 		length -= advance + padlen;
   1431 		nh = enh & 0xff;
   1432 
   1433 		ip_print_inner(ndo, bp, length, nh, bp2);
   1434 		return;
   1435 	}
   1436 
   1437 trunc:
   1438 	printf("[|isakmp]");
   1439 	return;
   1440 }
   1441 
   1442 /*
   1443  * Local Variables:
   1444  * c-style: whitesmith
   1445  * c-basic-offset: 8
   1446  * End:
   1447  */
   1448