xref: /freebsd/contrib/tcpdump/print-isakmp.c (revision 4f29da19bd44f0e99f021510460a81bf754c21d2)
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 			setprotoent(1);
720 #endif /* WIN32 */
721 			pe = getprotobynumber(id.proto_id);
722 			if (pe)
723 				printf(" protoid=%s", pe->p_name);
724 #ifndef WIN32
725 			endprotoent();
726 #endif /* WIN32 */
727 		} else {
728 			/* it DOES NOT mean IPPROTO_IP! */
729 			printf(" protoid=%s", "0");
730 		}
731 		printf(" port=%d", ntohs(id.port));
732 		if (!len)
733 			break;
734 		if (data == NULL)
735 			goto trunc;
736 		TCHECK2(*data, len);
737 		switch (id.type) {
738 		case IPSECDOI_ID_IPV4_ADDR:
739 			if (len < 4)
740 				printf(" len=%d [bad: < 4]", len);
741 			else
742 				printf(" len=%d %s", len, ipaddr_string(data));
743 			len = 0;
744 			break;
745 		case IPSECDOI_ID_FQDN:
746 		case IPSECDOI_ID_USER_FQDN:
747 		    {
748 			int i;
749 			printf(" len=%d ", len);
750 			for (i = 0; i < len; i++)
751 				safeputchar(data[i]);
752 			len = 0;
753 			break;
754 		    }
755 		case IPSECDOI_ID_IPV4_ADDR_SUBNET:
756 		    {
757 			const u_char *mask;
758 			if (len < 8)
759 				printf(" len=%d [bad: < 8]", len);
760 			else {
761 				mask = data + sizeof(struct in_addr);
762 				printf(" len=%d %s/%u.%u.%u.%u", len,
763 					ipaddr_string(data),
764 					mask[0], mask[1], mask[2], mask[3]);
765 			}
766 			len = 0;
767 			break;
768 		    }
769 #ifdef INET6
770 		case IPSECDOI_ID_IPV6_ADDR:
771 			if (len < 16)
772 				printf(" len=%d [bad: < 16]", len);
773 			else
774 				printf(" len=%d %s", len, ip6addr_string(data));
775 			len = 0;
776 			break;
777 		case IPSECDOI_ID_IPV6_ADDR_SUBNET:
778 		    {
779 			const u_int32_t *mask;
780 			if (len < 20)
781 				printf(" len=%d [bad: < 20]", len);
782 			else {
783 				mask = (u_int32_t *)(data + sizeof(struct in6_addr));
784 				/*XXX*/
785 				printf(" len=%d %s/0x%08x%08x%08x%08x", len,
786 					ip6addr_string(data),
787 					mask[0], mask[1], mask[2], mask[3]);
788 			}
789 			len = 0;
790 			break;
791 		    }
792 #endif /*INET6*/
793 		case IPSECDOI_ID_IPV4_ADDR_RANGE:
794 			if (len < 8)
795 				printf(" len=%d [bad: < 8]", len);
796 			else {
797 				printf(" len=%d %s-%s", len,
798 					ipaddr_string(data),
799 					ipaddr_string(data + sizeof(struct in_addr)));
800 			}
801 			len = 0;
802 			break;
803 #ifdef INET6
804 		case IPSECDOI_ID_IPV6_ADDR_RANGE:
805 			if (len < 32)
806 				printf(" len=%d [bad: < 32]", len);
807 			else {
808 				printf(" len=%d %s-%s", len,
809 					ip6addr_string(data),
810 					ip6addr_string(data + sizeof(struct in6_addr)));
811 			}
812 			len = 0;
813 			break;
814 #endif /*INET6*/
815 		case IPSECDOI_ID_DER_ASN1_DN:
816 		case IPSECDOI_ID_DER_ASN1_GN:
817 		case IPSECDOI_ID_KEY_ID:
818 			break;
819 		}
820 		break;
821 	    }
822 	}
823 	if (data && len) {
824 		printf(" len=%d", len);
825 		if (2 < vflag) {
826 			printf(" ");
827 			if (!rawprint((caddr_t)data, len))
828 				goto trunc;
829 		}
830 	}
831 	return (u_char *)ext + item_len;
832 trunc:
833 	printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_ID));
834 	return NULL;
835 }
836 
837 static const u_char *
838 isakmp_cert_print(const struct isakmp_gen *ext, u_int item_len _U_,
839 		  const u_char *ep _U_, u_int32_t phase _U_,
840 		  u_int32_t doi0 _U_,
841 		  u_int32_t proto0 _U_, int depth _U_)
842 {
843 	const struct isakmp_pl_cert *p;
844 	struct isakmp_pl_cert cert;
845 	static const char *certstr[] = {
846 		"none",	"pkcs7", "pgp", "dns",
847 		"x509sign", "x509ke", "kerberos", "crl",
848 		"arl", "spki", "x509attr",
849 	};
850 
851 	printf("%s:", NPSTR(ISAKMP_NPTYPE_CERT));
852 
853 	p = (struct isakmp_pl_cert *)ext;
854 	TCHECK(*p);
855 	safememcpy(&cert, ext, sizeof(cert));
856 	printf(" len=%d", item_len - 4);
857 	printf(" type=%s", STR_OR_ID((cert.encode), certstr));
858 	if (2 < vflag && 4 < item_len) {
859 		printf(" ");
860 		if (!rawprint((caddr_t)(ext + 1), item_len - 4))
861 			goto trunc;
862 	}
863 	return (u_char *)ext + item_len;
864 trunc:
865 	printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_CERT));
866 	return NULL;
867 }
868 
869 static const u_char *
870 isakmp_cr_print(const struct isakmp_gen *ext, u_int item_len _U_,
871 		const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi0 _U_,
872 		u_int32_t proto0 _U_, int depth _U_)
873 {
874 	const struct isakmp_pl_cert *p;
875 	struct isakmp_pl_cert cert;
876 	static const char *certstr[] = {
877 		"none",	"pkcs7", "pgp", "dns",
878 		"x509sign", "x509ke", "kerberos", "crl",
879 		"arl", "spki", "x509attr",
880 	};
881 
882 	printf("%s:", NPSTR(ISAKMP_NPTYPE_CR));
883 
884 	p = (struct isakmp_pl_cert *)ext;
885 	TCHECK(*p);
886 	safememcpy(&cert, ext, sizeof(cert));
887 	printf(" len=%d", item_len - 4);
888 	printf(" type=%s", STR_OR_ID((cert.encode), certstr));
889 	if (2 < vflag && 4 < item_len) {
890 		printf(" ");
891 		if (!rawprint((caddr_t)(ext + 1), item_len - 4))
892 			goto trunc;
893 	}
894 	return (u_char *)ext + item_len;
895 trunc:
896 	printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_CR));
897 	return NULL;
898 }
899 
900 static const u_char *
901 isakmp_hash_print(const struct isakmp_gen *ext, u_int item_len _U_,
902 		  const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi _U_,
903 		  u_int32_t proto _U_, int depth _U_)
904 {
905 	struct isakmp_gen e;
906 
907 	printf("%s:", NPSTR(ISAKMP_NPTYPE_HASH));
908 
909 	TCHECK(*ext);
910 	safememcpy(&e, ext, sizeof(e));
911 	printf(" len=%d", ntohs(e.len) - 4);
912 	if (2 < vflag && 4 < ntohs(e.len)) {
913 		printf(" ");
914 		if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
915 			goto trunc;
916 	}
917 	return (u_char *)ext + ntohs(e.len);
918 trunc:
919 	printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_HASH));
920 	return NULL;
921 }
922 
923 static const u_char *
924 isakmp_sig_print(const struct isakmp_gen *ext, u_int item_len _U_,
925 		 const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi _U_,
926 		 u_int32_t proto _U_, int depth _U_)
927 {
928 	struct isakmp_gen e;
929 
930 	printf("%s:", NPSTR(ISAKMP_NPTYPE_SIG));
931 
932 	TCHECK(*ext);
933 	safememcpy(&e, ext, sizeof(e));
934 	printf(" len=%d", ntohs(e.len) - 4);
935 	if (2 < vflag && 4 < ntohs(e.len)) {
936 		printf(" ");
937 		if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
938 			goto trunc;
939 	}
940 	return (u_char *)ext + ntohs(e.len);
941 trunc:
942 	printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_SIG));
943 	return NULL;
944 }
945 
946 static const u_char *
947 isakmp_nonce_print(const struct isakmp_gen *ext,
948 		   u_int item_len _U_,
949 		   const u_char *ep _U_,
950 		   u_int32_t phase _U_, u_int32_t doi _U_,
951 		   u_int32_t proto _U_, int depth _U_)
952 {
953 	struct isakmp_gen e;
954 
955 	printf("%s:", NPSTR(ISAKMP_NPTYPE_NONCE));
956 
957 	TCHECK(*ext);
958 	safememcpy(&e, ext, sizeof(e));
959 	printf(" n len=%d", ntohs(e.len) - 4);
960 	if (2 < vflag && 4 < ntohs(e.len)) {
961 		printf(" ");
962 		if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
963 			goto trunc;
964 	}
965 	return (u_char *)ext + ntohs(e.len);
966 trunc:
967 	printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_NONCE));
968 	return NULL;
969 }
970 
971 static const u_char *
972 isakmp_n_print(const struct isakmp_gen *ext, u_int item_len,
973 	const u_char *ep, u_int32_t phase, u_int32_t doi0 _U_,
974 	u_int32_t proto0 _U_, int depth)
975 {
976 	struct isakmp_pl_n *p, n;
977 	const u_char *cp;
978 	u_char *ep2;
979 	u_int32_t doi;
980 	u_int32_t proto;
981 	static const char *notify_error_str[] = {
982 		NULL,				"INVALID-PAYLOAD-TYPE",
983 		"DOI-NOT-SUPPORTED",		"SITUATION-NOT-SUPPORTED",
984 		"INVALID-COOKIE",		"INVALID-MAJOR-VERSION",
985 		"INVALID-MINOR-VERSION",	"INVALID-EXCHANGE-TYPE",
986 		"INVALID-FLAGS",		"INVALID-MESSAGE-ID",
987 		"INVALID-PROTOCOL-ID",		"INVALID-SPI",
988 		"INVALID-TRANSFORM-ID",		"ATTRIBUTES-NOT-SUPPORTED",
989 		"NO-PROPOSAL-CHOSEN",		"BAD-PROPOSAL-SYNTAX",
990 		"PAYLOAD-MALFORMED",		"INVALID-KEY-INFORMATION",
991 		"INVALID-ID-INFORMATION",	"INVALID-CERT-ENCODING",
992 		"INVALID-CERTIFICATE",		"CERT-TYPE-UNSUPPORTED",
993 		"INVALID-CERT-AUTHORITY",	"INVALID-HASH-INFORMATION",
994 		"AUTHENTICATION-FAILED",	"INVALID-SIGNATURE",
995 		"ADDRESS-NOTIFICATION",		"NOTIFY-SA-LIFETIME",
996 		"CERTIFICATE-UNAVAILABLE",	"UNSUPPORTED-EXCHANGE-TYPE",
997 		"UNEQUAL-PAYLOAD-LENGTHS",
998 	};
999 	static const char *ipsec_notify_error_str[] = {
1000 		"RESERVED",
1001 	};
1002 	static const char *notify_status_str[] = {
1003 		"CONNECTED",
1004 	};
1005 	static const char *ipsec_notify_status_str[] = {
1006 		"RESPONDER-LIFETIME",		"REPLAY-STATUS",
1007 		"INITIAL-CONTACT",
1008 	};
1009 /* NOTE: these macro must be called with x in proper range */
1010 
1011 /* 0 - 8191 */
1012 #define NOTIFY_ERROR_STR(x) \
1013 	STR_OR_ID((x), notify_error_str)
1014 
1015 /* 8192 - 16383 */
1016 #define IPSEC_NOTIFY_ERROR_STR(x) \
1017 	STR_OR_ID((u_int)((x) - 8192), ipsec_notify_error_str)
1018 
1019 /* 16384 - 24575 */
1020 #define NOTIFY_STATUS_STR(x) \
1021 	STR_OR_ID((u_int)((x) - 16384), notify_status_str)
1022 
1023 /* 24576 - 32767 */
1024 #define IPSEC_NOTIFY_STATUS_STR(x) \
1025 	STR_OR_ID((u_int)((x) - 24576), ipsec_notify_status_str)
1026 
1027 	printf("%s:", NPSTR(ISAKMP_NPTYPE_N));
1028 
1029 	p = (struct isakmp_pl_n *)ext;
1030 	TCHECK(*p);
1031 	safememcpy(&n, ext, sizeof(n));
1032 	doi = ntohl(n.doi);
1033 	proto = n.prot_id;
1034 	if (doi != 1) {
1035 		printf(" doi=%d", doi);
1036 		printf(" proto=%d", proto);
1037 		if (ntohs(n.type) < 8192)
1038 			printf(" type=%s", NOTIFY_ERROR_STR(ntohs(n.type)));
1039 		else if (ntohs(n.type) < 16384)
1040 			printf(" type=%s", numstr(ntohs(n.type)));
1041 		else if (ntohs(n.type) < 24576)
1042 			printf(" type=%s", NOTIFY_STATUS_STR(ntohs(n.type)));
1043 		else
1044 			printf(" type=%s", numstr(ntohs(n.type)));
1045 		if (n.spi_size) {
1046 			printf(" spi=");
1047 			if (!rawprint((caddr_t)(p + 1), n.spi_size))
1048 				goto trunc;
1049 		}
1050 		return (u_char *)(p + 1) + n.spi_size;
1051 	}
1052 
1053 	printf(" doi=ipsec");
1054 	printf(" proto=%s", PROTOIDSTR(proto));
1055 	if (ntohs(n.type) < 8192)
1056 		printf(" type=%s", NOTIFY_ERROR_STR(ntohs(n.type)));
1057 	else if (ntohs(n.type) < 16384)
1058 		printf(" type=%s", IPSEC_NOTIFY_ERROR_STR(ntohs(n.type)));
1059 	else if (ntohs(n.type) < 24576)
1060 		printf(" type=%s", NOTIFY_STATUS_STR(ntohs(n.type)));
1061 	else if (ntohs(n.type) < 32768)
1062 		printf(" type=%s", IPSEC_NOTIFY_STATUS_STR(ntohs(n.type)));
1063 	else
1064 		printf(" type=%s", numstr(ntohs(n.type)));
1065 	if (n.spi_size) {
1066 		printf(" spi=");
1067 		if (!rawprint((caddr_t)(p + 1), n.spi_size))
1068 			goto trunc;
1069 	}
1070 
1071 	cp = (u_char *)(p + 1) + n.spi_size;
1072 	ep2 = (u_char *)p + item_len;
1073 
1074 	if (cp < ep) {
1075 		printf(" orig=(");
1076 		switch (ntohs(n.type)) {
1077 		case IPSECDOI_NTYPE_RESPONDER_LIFETIME:
1078 		    {
1079 			const struct attrmap *map = oakley_t_map;
1080 			size_t nmap = sizeof(oakley_t_map)/sizeof(oakley_t_map[0]);
1081 			while (cp < ep && cp < ep2) {
1082 				cp = isakmp_attrmap_print(cp,
1083 					(ep < ep2) ? ep : ep2, map, nmap);
1084 			}
1085 			break;
1086 		    }
1087 		case IPSECDOI_NTYPE_REPLAY_STATUS:
1088 			printf("replay detection %sabled",
1089 				(*(u_int32_t *)cp) ? "en" : "dis");
1090 			break;
1091 		case ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN:
1092 			if (isakmp_sub_print(ISAKMP_NPTYPE_SA,
1093 			    (struct isakmp_gen *)cp, ep, phase, doi, proto,
1094 			    depth) == NULL)
1095 				return NULL;
1096 			break;
1097 		default:
1098 			/* NULL is dummy */
1099 			isakmp_print(gndo, cp,
1100 				     item_len - sizeof(*p) - n.spi_size,
1101 				     NULL);
1102 		}
1103 		printf(")");
1104 	}
1105 	return (u_char *)ext + item_len;
1106 trunc:
1107 	printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_N));
1108 	return NULL;
1109 }
1110 
1111 static const u_char *
1112 isakmp_d_print(const struct isakmp_gen *ext, u_int item_len _U_,
1113 	       const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi0 _U_,
1114 	       u_int32_t proto0 _U_, int depth _U_)
1115 {
1116 	const struct isakmp_pl_d *p;
1117 	struct isakmp_pl_d d;
1118 	const u_int8_t *q;
1119 	u_int32_t doi;
1120 	u_int32_t proto;
1121 	int i;
1122 
1123 	printf("%s:", NPSTR(ISAKMP_NPTYPE_D));
1124 
1125 	p = (struct isakmp_pl_d *)ext;
1126 	TCHECK(*p);
1127 	safememcpy(&d, ext, sizeof(d));
1128 	doi = ntohl(d.doi);
1129 	proto = d.prot_id;
1130 	if (doi != 1) {
1131 		printf(" doi=%u", doi);
1132 		printf(" proto=%u", proto);
1133 	} else {
1134 		printf(" doi=ipsec");
1135 		printf(" proto=%s", PROTOIDSTR(proto));
1136 	}
1137 	printf(" spilen=%u", d.spi_size);
1138 	printf(" nspi=%u", ntohs(d.num_spi));
1139 	printf(" spi=");
1140 	q = (u_int8_t *)(p + 1);
1141 	for (i = 0; i < ntohs(d.num_spi); i++) {
1142 		if (i != 0)
1143 			printf(",");
1144 		if (!rawprint((caddr_t)q, d.spi_size))
1145 			goto trunc;
1146 		q += d.spi_size;
1147 	}
1148 	return q;
1149 trunc:
1150 	printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_D));
1151 	return NULL;
1152 }
1153 
1154 static const u_char *
1155 isakmp_vid_print(const struct isakmp_gen *ext,
1156 		 u_int item_len _U_, const u_char *ep _U_,
1157 		 u_int32_t phase _U_, u_int32_t doi _U_,
1158 		 u_int32_t proto _U_, int depth _U_)
1159 {
1160 	struct isakmp_gen e;
1161 
1162 	printf("%s:", NPSTR(ISAKMP_NPTYPE_VID));
1163 
1164 	TCHECK(*ext);
1165 	safememcpy(&e, ext, sizeof(e));
1166 	printf(" len=%d", ntohs(e.len) - 4);
1167 	if (2 < vflag && 4 < ntohs(e.len)) {
1168 		printf(" ");
1169 		if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
1170 			goto trunc;
1171 	}
1172 	return (u_char *)ext + ntohs(e.len);
1173 trunc:
1174 	printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_VID));
1175 	return NULL;
1176 }
1177 
1178 static const u_char *
1179 isakmp_sub0_print(u_char np, const struct isakmp_gen *ext, const u_char *ep,
1180 	u_int32_t phase, u_int32_t doi, u_int32_t proto, int depth)
1181 {
1182 	const u_char *cp;
1183 	struct isakmp_gen e;
1184 	u_int item_len;
1185 
1186 	cp = (u_char *)ext;
1187 	TCHECK(*ext);
1188 	safememcpy(&e, ext, sizeof(e));
1189 
1190 	/*
1191 	 * Since we can't have a payload length of less than 4 bytes,
1192 	 * we need to bail out here if the generic header is nonsensical
1193 	 * or truncated, otherwise we could loop forever processing
1194 	 * zero-length items or otherwise misdissect the packet.
1195 	 */
1196 	item_len = ntohs(e.len);
1197 	if (item_len <= 4)
1198 		return NULL;
1199 
1200 	if (NPFUNC(np)) {
1201 		/*
1202 		 * XXX - what if item_len is too short, or too long,
1203 		 * for this payload type?
1204 		 */
1205 		cp = (*npfunc[np])(ext, item_len, ep, phase, doi, proto, depth);
1206 	} else {
1207 		printf("%s", NPSTR(np));
1208 		cp += item_len;
1209 	}
1210 
1211 	return cp;
1212 trunc:
1213 	printf(" [|isakmp]");
1214 	return NULL;
1215 }
1216 
1217 static const u_char *
1218 isakmp_sub_print(u_char np, const struct isakmp_gen *ext, const u_char *ep,
1219 	u_int32_t phase, u_int32_t doi, u_int32_t proto, int depth)
1220 {
1221 	const u_char *cp;
1222 	int i;
1223 	struct isakmp_gen e;
1224 
1225 	cp = (const u_char *)ext;
1226 
1227 	while (np) {
1228 		TCHECK(*ext);
1229 
1230 		safememcpy(&e, ext, sizeof(e));
1231 
1232 		TCHECK2(*ext, ntohs(e.len));
1233 
1234 		depth++;
1235 		printf("\n");
1236 		for (i = 0; i < depth; i++)
1237 			printf("    ");
1238 		printf("(");
1239 		cp = isakmp_sub0_print(np, ext, ep, phase, doi, proto, depth);
1240 		printf(")");
1241 		depth--;
1242 
1243 		if (cp == NULL) {
1244 			/* Zero-length subitem */
1245 			return NULL;
1246 		}
1247 
1248 		np = e.np;
1249 		ext = (struct isakmp_gen *)cp;
1250 	}
1251 	return cp;
1252 trunc:
1253 	printf(" [|%s]", NPSTR(np));
1254 	return NULL;
1255 }
1256 
1257 static char *
1258 numstr(int x)
1259 {
1260 	static char buf[20];
1261 	snprintf(buf, sizeof(buf), "#%d", x);
1262 	return buf;
1263 }
1264 
1265 /*
1266  * some compiler tries to optimize memcpy(), using the alignment constraint
1267  * on the argument pointer type.  by using this function, we try to avoid the
1268  * optimization.
1269  */
1270 static void
1271 safememcpy(void *p, const void *q, size_t l)
1272 {
1273 	memcpy(p, q, l);
1274 }
1275 
1276 void
1277 isakmp_print(netdissect_options *ndo,
1278 	     const u_char *bp, u_int length,
1279 	     const u_char *bp2)
1280 {
1281 	const struct isakmp *p;
1282 	struct isakmp base;
1283 	const u_char *ep;
1284 	u_char np;
1285 	int i;
1286 	int phase;
1287 	int major, minor;
1288 
1289 	p = (const struct isakmp *)bp;
1290 	ep = ndo->ndo_snapend;
1291 
1292 	if ((struct isakmp *)ep < p + 1) {
1293 		printf("[|isakmp]");
1294 		return;
1295 	}
1296 
1297 	safememcpy(&base, p, sizeof(base));
1298 
1299 	printf("isakmp");
1300 	if (vflag) {
1301 		major = (base.vers & ISAKMP_VERS_MAJOR)
1302 				>> ISAKMP_VERS_MAJOR_SHIFT;
1303 		minor = (base.vers & ISAKMP_VERS_MINOR)
1304 				>> ISAKMP_VERS_MINOR_SHIFT;
1305 		printf(" %d.%d", major, minor);
1306 	}
1307 
1308 	if (vflag) {
1309 		printf(" msgid ");
1310 		rawprint((caddr_t)&base.msgid, sizeof(base.msgid));
1311 	}
1312 
1313 	if (1 < vflag) {
1314 		printf(" cookie ");
1315 		rawprint((caddr_t)&base.i_ck, sizeof(base.i_ck));
1316 		printf("->");
1317 		rawprint((caddr_t)&base.r_ck, sizeof(base.r_ck));
1318 	}
1319 	printf(":");
1320 
1321 	phase = (*(u_int32_t *)base.msgid == 0) ? 1 : 2;
1322 	if (phase == 1)
1323 		printf(" phase %d", phase);
1324 	else
1325 		printf(" phase %d/others", phase);
1326 
1327 	i = cookie_find(&base.i_ck);
1328 	if (i < 0) {
1329 		if (iszero((u_char *)&base.r_ck, sizeof(base.r_ck))) {
1330 			/* the first packet */
1331 			printf(" I");
1332 			if (bp2)
1333 				cookie_record(&base.i_ck, bp2);
1334 		} else
1335 			printf(" ?");
1336 	} else {
1337 		if (bp2 && cookie_isinitiator(i, bp2))
1338 			printf(" I");
1339 		else if (bp2 && cookie_isresponder(i, bp2))
1340 			printf(" R");
1341 		else
1342 			printf(" ?");
1343 	}
1344 
1345 	printf(" %s", ETYPESTR(base.etype));
1346 	if (base.flags) {
1347 		printf("[%s%s]", base.flags & ISAKMP_FLAG_E ? "E" : "",
1348 			base.flags & ISAKMP_FLAG_C ? "C" : "");
1349 	}
1350 
1351 	if (vflag) {
1352 		const struct isakmp_gen *ext;
1353 		int nparen;
1354 
1355 #define CHECKLEN(p, np) \
1356 		if (ep < (u_char *)(p)) {				\
1357 			printf(" [|%s]", NPSTR(np));			\
1358 			goto done;					\
1359 		}
1360 
1361 		printf(":");
1362 
1363 		/* regardless of phase... */
1364 		if (base.flags & ISAKMP_FLAG_E) {
1365 			/*
1366 			 * encrypted, nothing we can do right now.
1367 			 * we hope to decrypt the packet in the future...
1368 			 */
1369 			printf(" [encrypted %s]", NPSTR(base.np));
1370 			goto done;
1371 		}
1372 
1373 		nparen = 0;
1374 		CHECKLEN(p + 1, base.np)
1375 
1376 		np = base.np;
1377 		ext = (struct isakmp_gen *)(p + 1);
1378 		isakmp_sub_print(np, ext, ep, phase, 0, 0, 0);
1379 	}
1380 
1381 done:
1382 	if (vflag) {
1383 		if (ntohl(base.len) != length) {
1384 			printf(" (len mismatch: isakmp %u/ip %u)",
1385 				(u_int32_t)ntohl(base.len), length);
1386 		}
1387 	}
1388 }
1389 
1390 void
1391 isakmp_rfc3948_print(netdissect_options *ndo,
1392 		     const u_char *bp, u_int length,
1393 		     const u_char *bp2)
1394 {
1395 	const u_char *ep;
1396 	ep = ndo->ndo_snapend;
1397 
1398 	if(length == 1 && bp[0]==0xff) {
1399 		ND_PRINT((ndo, "isakmp-nat-keep-alive"));
1400 		return;
1401 	}
1402 
1403 	if(length < 4) {
1404 		goto trunc;
1405 	}
1406 
1407 	/*
1408 	 * see if this is an IKE packet
1409 	 */
1410 	if(bp[0]==0 && bp[1]==0 && bp[2]==0 && bp[3]==0) {
1411 		ND_PRINT((ndo, "NONESP-encap: "));
1412 		isakmp_print(ndo, bp+4, length-4, bp2);
1413 		return;
1414 	}
1415 
1416 	/* must be an ESP packet */
1417 	{
1418 		int nh, enh, padlen;
1419 		int advance;
1420 
1421 		ND_PRINT((ndo, "UDP-encap: "));
1422 
1423 		advance = esp_print(ndo, bp, length, bp2, &enh, &padlen);
1424 		if(advance <= 0)
1425 			return;
1426 
1427 		bp += advance;
1428 		length -= advance + padlen;
1429 		nh = enh & 0xff;
1430 
1431 		ip_print_inner(ndo, bp, length, nh, bp2);
1432 		return;
1433 	}
1434 
1435 trunc:
1436 	printf("[|isakmp]");
1437 	return;
1438 }
1439 
1440 /*
1441  * Local Variables:
1442  * c-style: whitesmith
1443  * c-basic-offset: 8
1444  * End:
1445  */
1446 
1447 
1448 
1449 
1450