xref: /dragonfly/contrib/tcpdump/print-isakmp.c (revision dcd37f7d)
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.56 2007-08-29 12:31:00 mcr Exp $ (LBL)";
34 #endif
35 
36 #define NETDISSECT_REWORKED
37 #ifdef HAVE_CONFIG_H
38 #include "config.h"
39 #endif
40 
41 #include <tcpdump-stdinc.h>
42 
43 #include <string.h>
44 
45 #include <stdio.h>
46 
47 #include "isakmp.h"
48 #include "ipsec_doi.h"
49 #include "oakley.h"
50 #include "interface.h"
51 #include "addrtoname.h"
52 #include "extract.h"                    /* must come after interface.h */
53 
54 #include "ip.h"
55 #ifdef INET6
56 #include "ip6.h"
57 #endif
58 
59 #ifndef HAVE_SOCKADDR_STORAGE
60 #define sockaddr_storage sockaddr
61 #endif
62 
63 #define DECLARE_PRINTER(func) static const u_char *ike##func##_print( \
64 		netdissect_options *ndo, u_char tpay,	              \
65 		const struct isakmp_gen *ext,			      \
66 		u_int item_len, \
67 		const u_char *end_pointer, \
68 		u_int32_t phase,\
69 		u_int32_t doi0, \
70 		u_int32_t proto0, int depth)
71 
72 DECLARE_PRINTER(v1_sa);
73 DECLARE_PRINTER(v1_p);
74 DECLARE_PRINTER(v1_t);
75 DECLARE_PRINTER(v1_ke);
76 DECLARE_PRINTER(v1_id);
77 DECLARE_PRINTER(v1_cert);
78 DECLARE_PRINTER(v1_cr);
79 DECLARE_PRINTER(v1_sig);
80 DECLARE_PRINTER(v1_hash);
81 DECLARE_PRINTER(v1_nonce);
82 DECLARE_PRINTER(v1_n);
83 DECLARE_PRINTER(v1_d);
84 DECLARE_PRINTER(v1_vid);
85 
86 DECLARE_PRINTER(v2_sa);
87 DECLARE_PRINTER(v2_ke);
88 DECLARE_PRINTER(v2_ID);
89 DECLARE_PRINTER(v2_cert);
90 DECLARE_PRINTER(v2_cr);
91 DECLARE_PRINTER(v2_auth);
92 DECLARE_PRINTER(v2_nonce);
93 DECLARE_PRINTER(v2_n);
94 DECLARE_PRINTER(v2_d);
95 DECLARE_PRINTER(v2_vid);
96 DECLARE_PRINTER(v2_TS);
97 DECLARE_PRINTER(v2_e);
98 DECLARE_PRINTER(v2_cp);
99 DECLARE_PRINTER(v2_eap);
100 
101 static const u_char *ike_sub0_print(netdissect_options *ndo,u_char, const struct isakmp_gen *,
102 	const u_char *,	u_int32_t, u_int32_t, u_int32_t, int);
103 static const u_char *ikev1_sub_print(netdissect_options *ndo,u_char, const struct isakmp_gen *,
104 	const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
105 
106 static const u_char *ikev2_sub_print(netdissect_options *ndo,
107 				     u_char np, const struct isakmp_gen *ext,
108 				     const u_char *ep, u_int32_t phase,
109 				     u_int32_t doi, u_int32_t proto,
110 				     int depth);
111 
112 
113 static char *numstr(int);
114 static void safememcpy(void *, const void *, size_t);
115 
116 static void
117 ikev1_print(netdissect_options *ndo,
118 	    const u_char *bp,  u_int length,
119 	    const u_char *bp2, struct isakmp *base);
120 
121 #define MAXINITIATORS	20
122 int ninitiator = 0;
123 struct {
124 	cookie_t initiator;
125 	struct sockaddr_storage iaddr;
126 	struct sockaddr_storage raddr;
127 } cookiecache[MAXINITIATORS];
128 
129 /* protocol id */
130 static const char *protoidstr[] = {
131 	NULL, "isakmp", "ipsec-ah", "ipsec-esp", "ipcomp",
132 };
133 
134 /* isakmp->np */
135 static const char *npstr[] = {
136 	"none", "sa", "p", "t", "ke", "id", "cert", "cr", "hash", /* 0 - 8 */
137 	"sig", "nonce", "n", "d", "vid",      /* 9 - 13 */
138 	"pay14", "pay15", "pay16", "pay17", "pay18", /* 14- 18 */
139 	"pay19", "pay20", "pay21", "pay22", "pay23", /* 19- 23 */
140 	"pay24", "pay25", "pay26", "pay27", "pay28", /* 24- 28 */
141 	"pay29", "pay30", "pay31", "pay32",          /* 29- 32 */
142 	"v2sa",  "v2ke",  "v2IDi", "v2IDr", "v2cert",/* 33- 37 */
143 	"v2cr",  "v2auth","v2nonce", "v2n",   "v2d",   /* 38- 42 */
144 	"v2vid", "v2TSi", "v2TSr", "v2e",   "v2cp",  /* 43- 47 */
145 	"v2eap",                                     /* 48 */
146 
147 };
148 
149 /* isakmp->np */
150 static const u_char *(*npfunc[])(netdissect_options *ndo, u_char tpay,
151 				 const struct isakmp_gen *ext,
152 				 u_int item_len,
153 				 const u_char *end_pointer,
154 				 u_int32_t phase,
155 				 u_int32_t doi0,
156 				 u_int32_t proto0, int depth) = {
157 	NULL,
158 	ikev1_sa_print,
159 	ikev1_p_print,
160 	ikev1_t_print,
161 	ikev1_ke_print,
162 	ikev1_id_print,
163 	ikev1_cert_print,
164 	ikev1_cr_print,
165 	ikev1_hash_print,
166 	ikev1_sig_print,
167 	ikev1_nonce_print,
168 	ikev1_n_print,
169 	ikev1_d_print,
170 	ikev1_vid_print,                  /* 13 */
171 	NULL, NULL, NULL, NULL, NULL,     /* 14- 18 */
172 	NULL, NULL, NULL, NULL, NULL,     /* 19- 23 */
173 	NULL, NULL, NULL, NULL, NULL,     /* 24- 28 */
174 	NULL, NULL, NULL, NULL,           /* 29- 32 */
175 	ikev2_sa_print,                 /* 33 */
176 	ikev2_ke_print,                 /* 34 */
177 	ikev2_ID_print,                 /* 35 */
178 	ikev2_ID_print,                 /* 36 */
179 	ikev2_cert_print,               /* 37 */
180 	ikev2_cr_print,                 /* 38 */
181 	ikev2_auth_print,               /* 39 */
182 	ikev2_nonce_print,              /* 40 */
183 	ikev2_n_print,                  /* 41 */
184 	ikev2_d_print,                  /* 42 */
185 	ikev2_vid_print,                /* 43 */
186 	ikev2_TS_print,                 /* 44 */
187 	ikev2_TS_print,                 /* 45 */
188 	ikev2_e_print,                  /* 46 */
189 	ikev2_cp_print,                 /* 47 */
190 	ikev2_eap_print,                /* 48 */
191 };
192 
193 /* isakmp->etype */
194 static const char *etypestr[] = {
195 /* IKEv1 exchange types */
196 	"none", "base", "ident", "auth", "agg", "inf", NULL, NULL,  /* 0-7 */
197 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,  /*  8-15 */
198 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,  /* 16-23 */
199 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,  /* 24-31 */
200 	"oakley-quick", "oakley-newgroup",               /* 32-33 */
201 /* IKEv2 exchange types */
202 	"ikev2_init", "ikev2_auth", "child_sa", "inf2"   /* 34-37 */
203 };
204 
205 #define STR_OR_ID(x, tab) \
206 	(((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)])	? tab[(x)] : numstr(x))
207 #define PROTOIDSTR(x)	STR_OR_ID(x, protoidstr)
208 #define NPSTR(x)	STR_OR_ID(x, npstr)
209 #define ETYPESTR(x)	STR_OR_ID(x, etypestr)
210 
211 #define CHECKLEN(p, np)							\
212 		if (ep < (u_char *)(p)) {				\
213 			ND_PRINT((ndo," [|%s]", NPSTR(np)));		\
214 			goto done;					\
215 		}
216 
217 
218 #define NPFUNC(x) \
219 	(((x) < sizeof(npfunc)/sizeof(npfunc[0]) && npfunc[(x)]) \
220 		? npfunc[(x)] : NULL)
221 
222 static int
223 iszero(u_char *p, size_t l)
224 {
225 	while (l--) {
226 		if (*p++)
227 			return 0;
228 	}
229 	return 1;
230 }
231 
232 /* find cookie from initiator cache */
233 static int
234 cookie_find(cookie_t *in)
235 {
236 	int i;
237 
238 	for (i = 0; i < MAXINITIATORS; i++) {
239 		if (memcmp(in, &cookiecache[i].initiator, sizeof(*in)) == 0)
240 			return i;
241 	}
242 
243 	return -1;
244 }
245 
246 /* record initiator */
247 static void
248 cookie_record(cookie_t *in, const u_char *bp2)
249 {
250 	int i;
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 
258 	i = cookie_find(in);
259 	if (0 <= i) {
260 		ninitiator = (i + 1) % MAXINITIATORS;
261 		return;
262 	}
263 
264 	ip = (struct ip *)bp2;
265 	switch (IP_V(ip)) {
266 	case 4:
267 		memset(&cookiecache[ninitiator].iaddr, 0,
268 			sizeof(cookiecache[ninitiator].iaddr));
269 		memset(&cookiecache[ninitiator].raddr, 0,
270 			sizeof(cookiecache[ninitiator].raddr));
271 
272 		sin = (struct sockaddr_in *)&cookiecache[ninitiator].iaddr;
273 #ifdef HAVE_SOCKADDR_SA_LEN
274 		sin->sin_len = sizeof(struct sockaddr_in);
275 #endif
276 		sin->sin_family = AF_INET;
277 		memcpy(&sin->sin_addr, &ip->ip_src, sizeof(ip->ip_src));
278 		sin = (struct sockaddr_in *)&cookiecache[ninitiator].raddr;
279 #ifdef HAVE_SOCKADDR_SA_LEN
280 		sin->sin_len = sizeof(struct sockaddr_in);
281 #endif
282 		sin->sin_family = AF_INET;
283 		memcpy(&sin->sin_addr, &ip->ip_dst, sizeof(ip->ip_dst));
284 		break;
285 #ifdef INET6
286 	case 6:
287 		memset(&cookiecache[ninitiator].iaddr, 0,
288 			sizeof(cookiecache[ninitiator].iaddr));
289 		memset(&cookiecache[ninitiator].raddr, 0,
290 			sizeof(cookiecache[ninitiator].raddr));
291 
292 		ip6 = (struct ip6_hdr *)bp2;
293 		sin6 = (struct sockaddr_in6 *)&cookiecache[ninitiator].iaddr;
294 #ifdef HAVE_SOCKADDR_SA_LEN
295 		sin6->sin6_len = sizeof(struct sockaddr_in6);
296 #endif
297 		sin6->sin6_family = AF_INET6;
298 		memcpy(&sin6->sin6_addr, &ip6->ip6_src, sizeof(ip6->ip6_src));
299 		sin6 = (struct sockaddr_in6 *)&cookiecache[ninitiator].raddr;
300 #ifdef HAVE_SOCKADDR_SA_LEN
301 		sin6->sin6_len = sizeof(struct sockaddr_in6);
302 #endif
303 		sin6->sin6_family = AF_INET6;
304 		memcpy(&sin6->sin6_addr, &ip6->ip6_dst, sizeof(ip6->ip6_dst));
305 		break;
306 #endif
307 	default:
308 		return;
309 	}
310 	memcpy(&cookiecache[ninitiator].initiator, in, sizeof(*in));
311 	ninitiator = (ninitiator + 1) % MAXINITIATORS;
312 }
313 
314 #define cookie_isinitiator(x, y)	cookie_sidecheck((x), (y), 1)
315 #define cookie_isresponder(x, y)	cookie_sidecheck((x), (y), 0)
316 static int
317 cookie_sidecheck(int i, const u_char *bp2, int initiator)
318 {
319 	struct sockaddr_storage ss;
320 	struct sockaddr *sa;
321 	struct ip *ip;
322 	struct sockaddr_in *sin;
323 #ifdef INET6
324 	struct ip6_hdr *ip6;
325 	struct sockaddr_in6 *sin6;
326 #endif
327 	int salen;
328 
329 	memset(&ss, 0, sizeof(ss));
330 	ip = (struct ip *)bp2;
331 	switch (IP_V(ip)) {
332 	case 4:
333 		sin = (struct sockaddr_in *)&ss;
334 #ifdef HAVE_SOCKADDR_SA_LEN
335 		sin->sin_len = sizeof(struct sockaddr_in);
336 #endif
337 		sin->sin_family = AF_INET;
338 		memcpy(&sin->sin_addr, &ip->ip_src, sizeof(ip->ip_src));
339 		break;
340 #ifdef INET6
341 	case 6:
342 		ip6 = (struct ip6_hdr *)bp2;
343 		sin6 = (struct sockaddr_in6 *)&ss;
344 #ifdef HAVE_SOCKADDR_SA_LEN
345 		sin6->sin6_len = sizeof(struct sockaddr_in6);
346 #endif
347 		sin6->sin6_family = AF_INET6;
348 		memcpy(&sin6->sin6_addr, &ip6->ip6_src, sizeof(ip6->ip6_src));
349 		break;
350 #endif
351 	default:
352 		return 0;
353 	}
354 
355 	sa = (struct sockaddr *)&ss;
356 	if (initiator) {
357 		if (sa->sa_family != ((struct sockaddr *)&cookiecache[i].iaddr)->sa_family)
358 			return 0;
359 #ifdef HAVE_SOCKADDR_SA_LEN
360 		salen = sa->sa_len;
361 #else
362 #ifdef INET6
363 		if (sa->sa_family == AF_INET6)
364 			salen = sizeof(struct sockaddr_in6);
365 		else
366 			salen = sizeof(struct sockaddr);
367 #else
368 		salen = sizeof(struct sockaddr);
369 #endif
370 #endif
371 		if (memcmp(&ss, &cookiecache[i].iaddr, salen) == 0)
372 			return 1;
373 	} else {
374 		if (sa->sa_family != ((struct sockaddr *)&cookiecache[i].raddr)->sa_family)
375 			return 0;
376 #ifdef HAVE_SOCKADDR_SA_LEN
377 		salen = sa->sa_len;
378 #else
379 #ifdef INET6
380 		if (sa->sa_family == AF_INET6)
381 			salen = sizeof(struct sockaddr_in6);
382 		else
383 			salen = sizeof(struct sockaddr);
384 #else
385 		salen = sizeof(struct sockaddr);
386 #endif
387 #endif
388 		if (memcmp(&ss, &cookiecache[i].raddr, salen) == 0)
389 			return 1;
390 	}
391 	return 0;
392 }
393 
394 static int
395 rawprint(netdissect_options *ndo, caddr_t loc, size_t len)
396 {
397 	static u_char *p;
398 	size_t i;
399 
400 	ND_TCHECK2(*loc, len);
401 
402 	p = (u_char *)loc;
403 	for (i = 0; i < len; i++)
404 		ND_PRINT((ndo,"%02x", p[i] & 0xff));
405 	return 1;
406 trunc:
407 	return 0;
408 }
409 
410 /*
411  * returns false if we run out of data buffer
412  */
413 static int ike_show_somedata(struct netdissect_options *ndo,
414 			     const u_char *cp, const u_char *ep)
415 {
416 	/* there is too much data, just show some of it */
417 	const u_char *end = ep - 20;
418 	int  elen = 20;
419 	int   len = ep - cp;
420 	if(len > 10) {
421 		len = 10;
422 	}
423 
424 	/* really shouldn't happen because of above */
425 	if(end < cp + len) {
426 		end = cp+len;
427 		elen = ep - end;
428 	}
429 
430 	ND_PRINT((ndo," data=("));
431 	if(!rawprint(ndo, (caddr_t)(cp), len)) goto trunc;
432 	ND_PRINT((ndo, "..."));
433 	if(elen) {
434 		if(!rawprint(ndo, (caddr_t)(end), elen)) goto trunc;
435 	}
436 	ND_PRINT((ndo,")"));
437 	return 1;
438 
439 trunc:
440 	return 0;
441 }
442 
443 struct attrmap {
444 	const char *type;
445 	u_int nvalue;
446 	const char *value[30];	/*XXX*/
447 };
448 
449 static const u_char *
450 ikev1_attrmap_print(netdissect_options *ndo,
451 		    const u_char *p, const u_char *ep,
452 		    const struct attrmap *map, size_t nmap)
453 {
454 	u_int16_t *q;
455 	int totlen;
456 	u_int32_t t, v;
457 
458 	q = (u_int16_t *)p;
459 	if (p[0] & 0x80)
460 		totlen = 4;
461 	else
462 		totlen = 4 + EXTRACT_16BITS(&q[1]);
463 	if (ep < p + totlen) {
464 		ND_PRINT((ndo,"[|attr]"));
465 		return ep + 1;
466 	}
467 
468 	ND_PRINT((ndo,"("));
469 	t = EXTRACT_16BITS(&q[0]) & 0x7fff;
470 	if (map && t < nmap && map[t].type)
471 		ND_PRINT((ndo,"type=%s ", map[t].type));
472 	else
473 		ND_PRINT((ndo,"type=#%d ", t));
474 	if (p[0] & 0x80) {
475 		ND_PRINT((ndo,"value="));
476 		v = EXTRACT_16BITS(&q[1]);
477 		if (map && t < nmap && v < map[t].nvalue && map[t].value[v])
478 			ND_PRINT((ndo,"%s", map[t].value[v]));
479 		else
480 			rawprint(ndo, (caddr_t)&q[1], 2);
481 	} else {
482 		ND_PRINT((ndo,"len=%d value=", EXTRACT_16BITS(&q[1])));
483 		rawprint(ndo, (caddr_t)&p[4], EXTRACT_16BITS(&q[1]));
484 	}
485 	ND_PRINT((ndo,")"));
486 	return p + totlen;
487 }
488 
489 static const u_char *
490 ikev1_attr_print(netdissect_options *ndo, const u_char *p, const u_char *ep)
491 {
492 	u_int16_t *q;
493 	int totlen;
494 	u_int32_t t;
495 
496 	q = (u_int16_t *)p;
497 	if (p[0] & 0x80)
498 		totlen = 4;
499 	else
500 		totlen = 4 + EXTRACT_16BITS(&q[1]);
501 	if (ep < p + totlen) {
502 		ND_PRINT((ndo,"[|attr]"));
503 		return ep + 1;
504 	}
505 
506 	ND_PRINT((ndo,"("));
507 	t = EXTRACT_16BITS(&q[0]) & 0x7fff;
508 	ND_PRINT((ndo,"type=#%d ", t));
509 	if (p[0] & 0x80) {
510 		ND_PRINT((ndo,"value="));
511 		t = q[1];
512 		rawprint(ndo, (caddr_t)&q[1], 2);
513 	} else {
514 		ND_PRINT((ndo,"len=%d value=", EXTRACT_16BITS(&q[1])));
515 		rawprint(ndo, (caddr_t)&p[2], EXTRACT_16BITS(&q[1]));
516 	}
517 	ND_PRINT((ndo,")"));
518 	return p + totlen;
519 }
520 
521 static const u_char *
522 ikev1_sa_print(netdissect_options *ndo, u_char tpay _U_,
523 	       const struct isakmp_gen *ext,
524 		u_int item_len _U_,
525 		const u_char *ep, u_int32_t phase, u_int32_t doi0 _U_,
526 		u_int32_t proto0, int depth)
527 {
528 	const struct ikev1_pl_sa *p;
529 	struct ikev1_pl_sa sa;
530 	const u_int32_t *q;
531 	u_int32_t doi, sit, ident;
532 	const u_char *cp, *np;
533 	int t;
534 
535 	ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_SA)));
536 
537 	p = (struct ikev1_pl_sa *)ext;
538 	ND_TCHECK(*p);
539 	safememcpy(&sa, ext, sizeof(sa));
540 	doi = ntohl(sa.doi);
541 	sit = ntohl(sa.sit);
542 	if (doi != 1) {
543 		ND_PRINT((ndo," doi=%d", doi));
544 		ND_PRINT((ndo," situation=%u", (u_int32_t)ntohl(sa.sit)));
545 		return (u_char *)(p + 1);
546 	}
547 
548 	ND_PRINT((ndo," doi=ipsec"));
549 	q = (u_int32_t *)&sa.sit;
550 	ND_PRINT((ndo," situation="));
551 	t = 0;
552 	if (sit & 0x01) {
553 		ND_PRINT((ndo,"identity"));
554 		t++;
555 	}
556 	if (sit & 0x02) {
557 		ND_PRINT((ndo,"%ssecrecy", t ? "+" : ""));
558 		t++;
559 	}
560 	if (sit & 0x04)
561 		ND_PRINT((ndo,"%sintegrity", t ? "+" : ""));
562 
563 	np = (u_char *)ext + sizeof(sa);
564 	if (sit != 0x01) {
565 		ND_TCHECK2(*(ext + 1), sizeof(ident));
566 		safememcpy(&ident, ext + 1, sizeof(ident));
567 		ND_PRINT((ndo," ident=%u", (u_int32_t)ntohl(ident)));
568 		np += sizeof(ident);
569 	}
570 
571 	ext = (struct isakmp_gen *)np;
572 	ND_TCHECK(*ext);
573 
574 	cp = ikev1_sub_print(ndo, ISAKMP_NPTYPE_P, ext, ep, phase, doi, proto0,
575 		depth);
576 
577 	return cp;
578 trunc:
579 	ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_SA)));
580 	return NULL;
581 }
582 
583 static const u_char *
584 ikev1_p_print(netdissect_options *ndo, u_char tpay _U_,
585 	      const struct isakmp_gen *ext, u_int item_len _U_,
586 	       const u_char *ep, u_int32_t phase, u_int32_t doi0,
587 	       u_int32_t proto0 _U_, int depth)
588 {
589 	const struct ikev1_pl_p *p;
590 	struct ikev1_pl_p prop;
591 	const u_char *cp;
592 
593 	ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_P)));
594 
595 	p = (struct ikev1_pl_p *)ext;
596 	ND_TCHECK(*p);
597 	safememcpy(&prop, ext, sizeof(prop));
598 	ND_PRINT((ndo," #%d protoid=%s transform=%d",
599 		  prop.p_no, PROTOIDSTR(prop.prot_id), prop.num_t));
600 	if (prop.spi_size) {
601 		ND_PRINT((ndo," spi="));
602 		if (!rawprint(ndo, (caddr_t)(p + 1), prop.spi_size))
603 			goto trunc;
604 	}
605 
606 	ext = (struct isakmp_gen *)((u_char *)(p + 1) + prop.spi_size);
607 	ND_TCHECK(*ext);
608 
609 	cp = ikev1_sub_print(ndo, ISAKMP_NPTYPE_T, ext, ep, phase, doi0,
610 			     prop.prot_id, depth);
611 
612 	return cp;
613 trunc:
614 	ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_P)));
615 	return NULL;
616 }
617 
618 static const char *ikev1_p_map[] = {
619 	NULL, "ike",
620 };
621 
622 static const char *ikev2_t_type_map[]={
623 	NULL, "encr", "prf", "integ", "dh", "esn"
624 };
625 
626 static const char *ah_p_map[] = {
627 	NULL, "(reserved)", "md5", "sha", "1des",
628 	"sha2-256", "sha2-384", "sha2-512",
629 };
630 
631 static const char *prf_p_map[] = {
632 	NULL, "hmac-md5", "hmac-sha", "hmac-tiger",
633 	"aes128_xcbc"
634 };
635 
636 static const char *integ_p_map[] = {
637 	NULL, "hmac-md5", "hmac-sha", "dec-mac",
638 	"kpdk-md5", "aes-xcbc"
639 };
640 
641 static const char *esn_p_map[] = {
642 	"no-esn", "esn"
643 };
644 
645 static const char *dh_p_map[] = {
646 	NULL, "modp768",
647 	"modp1024",    /* group 2 */
648 	"EC2N 2^155",  /* group 3 */
649 	"EC2N 2^185",  /* group 4 */
650 	"modp1536",    /* group 5 */
651 	"iana-grp06", "iana-grp07", /* reserved */
652 	"iana-grp08", "iana-grp09",
653 	"iana-grp10", "iana-grp11",
654 	"iana-grp12", "iana-grp13",
655 	"modp2048",    /* group 14 */
656 	"modp3072",    /* group 15 */
657 	"modp4096",    /* group 16 */
658 	"modp6144",    /* group 17 */
659 	"modp8192",    /* group 18 */
660 };
661 
662 static const char *esp_p_map[] = {
663 	NULL, "1des-iv64", "1des", "3des", "rc5", "idea", "cast",
664 	"blowfish", "3idea", "1des-iv32", "rc4", "null", "aes"
665 };
666 
667 static const char *ipcomp_p_map[] = {
668 	NULL, "oui", "deflate", "lzs",
669 };
670 
671 const struct attrmap ipsec_t_map[] = {
672 	{ NULL,	0, { NULL } },
673 	{ "lifetype", 3, { NULL, "sec", "kb", }, },
674 	{ "life", 0, { NULL } },
675 	{ "group desc", 18,	{ NULL, "modp768",
676 				  "modp1024",    /* group 2 */
677 				  "EC2N 2^155",  /* group 3 */
678 				  "EC2N 2^185",  /* group 4 */
679 				  "modp1536",    /* group 5 */
680 				  "iana-grp06", "iana-grp07", /* reserved */
681 				  "iana-grp08", "iana-grp09",
682 				  "iana-grp10", "iana-grp11",
683 				  "iana-grp12", "iana-grp13",
684 				  "modp2048",    /* group 14 */
685 				  "modp3072",    /* group 15 */
686 				  "modp4096",    /* group 16 */
687 				  "modp6144",    /* group 17 */
688 				  "modp8192",    /* group 18 */
689 		}, },
690 	{ "enc mode", 3, { NULL, "tunnel", "transport", }, },
691 	{ "auth", 5, { NULL, "hmac-md5", "hmac-sha1", "1des-mac", "keyed", }, },
692 	{ "keylen", 0, { NULL } },
693 	{ "rounds", 0, { NULL } },
694 	{ "dictsize", 0, { NULL } },
695 	{ "privalg", 0, { NULL } },
696 };
697 
698 const struct attrmap encr_t_map[] = {
699 	{ NULL,	0, { NULL } }, 	{ NULL,	0, { NULL } },  /* 0, 1 */
700 	{ NULL,	0, { NULL } },	{ NULL,	0, { NULL } },  /* 2, 3 */
701 	{ NULL,	0, { NULL } },	{ NULL,	0, { NULL } },  /* 4, 5 */
702 	{ NULL,	0, { NULL } },	{ NULL,	0, { NULL } },  /* 6, 7 */
703 	{ NULL,	0, { NULL } },	{ NULL,	0, { NULL } },  /* 8, 9 */
704 	{ NULL,	0, { NULL } },	{ NULL,	0, { NULL } },  /* 10,11*/
705 	{ NULL,	0, { NULL } },	{ NULL,	0, { NULL } },  /* 12,13*/
706 	{ "keylen", 14, { NULL }},
707 };
708 
709 const struct attrmap oakley_t_map[] = {
710 	{ NULL,	0, { NULL } },
711 	{ "enc", 8,	{ NULL, "1des", "idea", "blowfish", "rc5",
712 		 	  "3des", "cast", "aes", }, },
713 	{ "hash", 7,	{ NULL, "md5", "sha1", "tiger",
714 			  "sha2-256", "sha2-384", "sha2-512", }, },
715 	{ "auth", 6,	{ NULL, "preshared", "dss", "rsa sig", "rsa enc",
716 			  "rsa enc revised", }, },
717 	{ "group desc", 18,	{ NULL, "modp768",
718 				  "modp1024",    /* group 2 */
719 				  "EC2N 2^155",  /* group 3 */
720 				  "EC2N 2^185",  /* group 4 */
721 				  "modp1536",    /* group 5 */
722 				  "iana-grp06", "iana-grp07", /* reserved */
723 				  "iana-grp08", "iana-grp09",
724 				  "iana-grp10", "iana-grp11",
725 				  "iana-grp12", "iana-grp13",
726 				  "modp2048",    /* group 14 */
727 				  "modp3072",    /* group 15 */
728 				  "modp4096",    /* group 16 */
729 				  "modp6144",    /* group 17 */
730 				  "modp8192",    /* group 18 */
731 		}, },
732 	{ "group type", 4,	{ NULL, "MODP", "ECP", "EC2N", }, },
733 	{ "group prime", 0, { NULL } },
734 	{ "group gen1", 0, { NULL } },
735 	{ "group gen2", 0, { NULL } },
736 	{ "group curve A", 0, { NULL } },
737 	{ "group curve B", 0, { NULL } },
738 	{ "lifetype", 3,	{ NULL, "sec", "kb", }, },
739 	{ "lifeduration", 0, { NULL } },
740 	{ "prf", 0, { NULL } },
741 	{ "keylen", 0, { NULL } },
742 	{ "field", 0, { NULL } },
743 	{ "order", 0, { NULL } },
744 };
745 
746 static const u_char *
747 ikev1_t_print(netdissect_options *ndo, u_char tpay _U_,
748 	      const struct isakmp_gen *ext, u_int item_len,
749 	      const u_char *ep, u_int32_t phase _U_, u_int32_t doi _U_,
750 	      u_int32_t proto, int depth _U_)
751 {
752 	const struct ikev1_pl_t *p;
753 	struct ikev1_pl_t t;
754 	const u_char *cp;
755 	const char *idstr;
756 	const struct attrmap *map;
757 	size_t nmap;
758 	const u_char *ep2;
759 
760 	ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_T)));
761 
762 	p = (struct ikev1_pl_t *)ext;
763 	ND_TCHECK(*p);
764 	safememcpy(&t, ext, sizeof(t));
765 
766 	switch (proto) {
767 	case 1:
768 		idstr = STR_OR_ID(t.t_id, ikev1_p_map);
769 		map = oakley_t_map;
770 		nmap = sizeof(oakley_t_map)/sizeof(oakley_t_map[0]);
771 		break;
772 	case 2:
773 		idstr = STR_OR_ID(t.t_id, ah_p_map);
774 		map = ipsec_t_map;
775 		nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
776 		break;
777 	case 3:
778 		idstr = STR_OR_ID(t.t_id, esp_p_map);
779 		map = ipsec_t_map;
780 		nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
781 		break;
782 	case 4:
783 		idstr = STR_OR_ID(t.t_id, ipcomp_p_map);
784 		map = ipsec_t_map;
785 		nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
786 		break;
787 	default:
788 		idstr = NULL;
789 		map = NULL;
790 		nmap = 0;
791 		break;
792 	}
793 
794 	if (idstr)
795 		ND_PRINT((ndo," #%d id=%s ", t.t_no, idstr));
796 	else
797 		ND_PRINT((ndo," #%d id=%d ", t.t_no, t.t_id));
798 	cp = (u_char *)(p + 1);
799 	ep2 = (u_char *)p + item_len;
800 	while (cp < ep && cp < ep2) {
801 		if (map && nmap) {
802 			cp = ikev1_attrmap_print(ndo, cp, (ep < ep2) ? ep : ep2,
803 				map, nmap);
804 		} else
805 			cp = ikev1_attr_print(ndo, cp, (ep < ep2) ? ep : ep2);
806 	}
807 	if (ep < ep2)
808 		ND_PRINT((ndo,"..."));
809 	return cp;
810 trunc:
811 	ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_T)));
812 	return NULL;
813 }
814 
815 static const u_char *
816 ikev1_ke_print(netdissect_options *ndo, u_char tpay _U_,
817 	       const struct isakmp_gen *ext, u_int item_len _U_,
818 	       const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi _U_,
819 	       u_int32_t proto _U_, int depth _U_)
820 {
821 	struct isakmp_gen e;
822 
823 	ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_KE)));
824 
825 	ND_TCHECK(*ext);
826 	safememcpy(&e, ext, sizeof(e));
827 	ND_PRINT((ndo," key len=%d", ntohs(e.len) - 4));
828 	if (2 < ndo->ndo_vflag && 4 < ntohs(e.len)) {
829 		ND_PRINT((ndo," "));
830 		if (!rawprint(ndo, (caddr_t)(ext + 1), ntohs(e.len) - 4))
831 			goto trunc;
832 	}
833 	return (u_char *)ext + ntohs(e.len);
834 trunc:
835 	ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_KE)));
836 	return NULL;
837 }
838 
839 static const u_char *
840 ikev1_id_print(netdissect_options *ndo, u_char tpay _U_,
841 	       const struct isakmp_gen *ext, u_int item_len _U_,
842 	       const u_char *ep _U_, u_int32_t phase, u_int32_t doi _U_,
843 	       u_int32_t proto _U_, int depth _U_)
844 {
845 #define USE_IPSECDOI_IN_PHASE1	1
846 	const struct ikev1_pl_id *p;
847 	struct ikev1_pl_id id;
848 	static const char *idtypestr[] = {
849 		"IPv4", "IPv4net", "IPv6", "IPv6net",
850 	};
851 	static const char *ipsecidtypestr[] = {
852 		NULL, "IPv4", "FQDN", "user FQDN", "IPv4net", "IPv6",
853 		"IPv6net", "IPv4range", "IPv6range", "ASN1 DN", "ASN1 GN",
854 		"keyid",
855 	};
856 	int len;
857 	const u_char *data;
858 
859 	ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_ID)));
860 
861 	p = (struct ikev1_pl_id *)ext;
862 	ND_TCHECK(*p);
863 	safememcpy(&id, ext, sizeof(id));
864 	if (sizeof(*p) < item_len) {
865 		data = (u_char *)(p + 1);
866 		len = item_len - sizeof(*p);
867 	} else {
868 		data = NULL;
869 		len = 0;
870 	}
871 
872 #if 0 /*debug*/
873 	ND_PRINT((ndo," [phase=%d doi=%d proto=%d]", phase, doi, proto));
874 #endif
875 	switch (phase) {
876 #ifndef USE_IPSECDOI_IN_PHASE1
877 	case 1:
878 #endif
879 	default:
880 		ND_PRINT((ndo," idtype=%s", STR_OR_ID(id.d.id_type, idtypestr)));
881 		ND_PRINT((ndo," doi_data=%u",
882 			  (u_int32_t)(ntohl(id.d.doi_data) & 0xffffff)));
883 		break;
884 
885 #ifdef USE_IPSECDOI_IN_PHASE1
886 	case 1:
887 #endif
888 	case 2:
889 	    {
890 		const struct ipsecdoi_id *p;
891 		struct ipsecdoi_id id;
892 		struct protoent *pe;
893 
894 		p = (struct ipsecdoi_id *)ext;
895 		ND_TCHECK(*p);
896 		safememcpy(&id, ext, sizeof(id));
897 		ND_PRINT((ndo," idtype=%s", STR_OR_ID(id.type, ipsecidtypestr)));
898 		if (id.proto_id) {
899 #ifndef WIN32
900 			setprotoent(1);
901 #endif /* WIN32 */
902 			pe = getprotobynumber(id.proto_id);
903 			if (pe)
904 				ND_PRINT((ndo," protoid=%s", pe->p_name));
905 #ifndef WIN32
906 			endprotoent();
907 #endif /* WIN32 */
908 		} else {
909 			/* it DOES NOT mean IPPROTO_IP! */
910 			ND_PRINT((ndo," protoid=%s", "0"));
911 		}
912 		ND_PRINT((ndo," port=%d", ntohs(id.port)));
913 		if (!len)
914 			break;
915 		if (data == NULL)
916 			goto trunc;
917 		ND_TCHECK2(*data, len);
918 		switch (id.type) {
919 		case IPSECDOI_ID_IPV4_ADDR:
920 			if (len < 4)
921 				ND_PRINT((ndo," len=%d [bad: < 4]", len));
922 			else
923 				ND_PRINT((ndo," len=%d %s", len, ipaddr_string(data)));
924 			len = 0;
925 			break;
926 		case IPSECDOI_ID_FQDN:
927 		case IPSECDOI_ID_USER_FQDN:
928 		    {
929 			int i;
930 			ND_PRINT((ndo," len=%d ", len));
931 			for (i = 0; i < len; i++)
932 				safeputchar(data[i]);
933 			len = 0;
934 			break;
935 		    }
936 		case IPSECDOI_ID_IPV4_ADDR_SUBNET:
937 		    {
938 			const u_char *mask;
939 			if (len < 8)
940 				ND_PRINT((ndo," len=%d [bad: < 8]", len));
941 			else {
942 				mask = data + sizeof(struct in_addr);
943 				ND_PRINT((ndo," len=%d %s/%u.%u.%u.%u", len,
944 					  ipaddr_string(data),
945 					  mask[0], mask[1], mask[2], mask[3]));
946 			}
947 			len = 0;
948 			break;
949 		    }
950 #ifdef INET6
951 		case IPSECDOI_ID_IPV6_ADDR:
952 			if (len < 16)
953 				ND_PRINT((ndo," len=%d [bad: < 16]", len));
954 			else
955 				ND_PRINT((ndo," len=%d %s", len, ip6addr_string(data)));
956 			len = 0;
957 			break;
958 		case IPSECDOI_ID_IPV6_ADDR_SUBNET:
959 		    {
960 			const u_int32_t *mask;
961 			if (len < 20)
962 				ND_PRINT((ndo," len=%d [bad: < 20]", len));
963 			else {
964 				mask = (u_int32_t *)(data + sizeof(struct in6_addr));
965 				/*XXX*/
966 				ND_PRINT((ndo," len=%d %s/0x%08x%08x%08x%08x", len,
967 					  ip6addr_string(data),
968 					  mask[0], mask[1], mask[2], mask[3]));
969 			}
970 			len = 0;
971 			break;
972 		    }
973 #endif /*INET6*/
974 		case IPSECDOI_ID_IPV4_ADDR_RANGE:
975 			if (len < 8)
976 				ND_PRINT((ndo," len=%d [bad: < 8]", len));
977 			else {
978 				ND_PRINT((ndo," len=%d %s-%s", len,
979 					  ipaddr_string(data),
980 					  ipaddr_string(data + sizeof(struct in_addr))));
981 			}
982 			len = 0;
983 			break;
984 #ifdef INET6
985 		case IPSECDOI_ID_IPV6_ADDR_RANGE:
986 			if (len < 32)
987 				ND_PRINT((ndo," len=%d [bad: < 32]", len));
988 			else {
989 				ND_PRINT((ndo," len=%d %s-%s", len,
990 					  ip6addr_string(data),
991 					  ip6addr_string(data + sizeof(struct in6_addr))));
992 			}
993 			len = 0;
994 			break;
995 #endif /*INET6*/
996 		case IPSECDOI_ID_DER_ASN1_DN:
997 		case IPSECDOI_ID_DER_ASN1_GN:
998 		case IPSECDOI_ID_KEY_ID:
999 			break;
1000 		}
1001 		break;
1002 	    }
1003 	}
1004 	if (data && len) {
1005 		ND_PRINT((ndo," len=%d", len));
1006 		if (2 < ndo->ndo_vflag) {
1007 			ND_PRINT((ndo," "));
1008 			if (!rawprint(ndo, (caddr_t)data, len))
1009 				goto trunc;
1010 		}
1011 	}
1012 	return (u_char *)ext + item_len;
1013 trunc:
1014 	ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_ID)));
1015 	return NULL;
1016 }
1017 
1018 static const u_char *
1019 ikev1_cert_print(netdissect_options *ndo, u_char tpay _U_,
1020 		 const struct isakmp_gen *ext, u_int item_len _U_,
1021 		 const u_char *ep _U_, u_int32_t phase _U_,
1022 		 u_int32_t doi0 _U_,
1023 		 u_int32_t proto0 _U_, int depth _U_)
1024 {
1025 	const struct ikev1_pl_cert *p;
1026 	struct ikev1_pl_cert cert;
1027 	static const char *certstr[] = {
1028 		"none",	"pkcs7", "pgp", "dns",
1029 		"x509sign", "x509ke", "kerberos", "crl",
1030 		"arl", "spki", "x509attr",
1031 	};
1032 
1033 	ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_CERT)));
1034 
1035 	p = (struct ikev1_pl_cert *)ext;
1036 	ND_TCHECK(*p);
1037 	safememcpy(&cert, ext, sizeof(cert));
1038 	ND_PRINT((ndo," len=%d", item_len - 4));
1039 	ND_PRINT((ndo," type=%s", STR_OR_ID((cert.encode), certstr)));
1040 	if (2 < ndo->ndo_vflag && 4 < item_len) {
1041 		ND_PRINT((ndo," "));
1042 		if (!rawprint(ndo, (caddr_t)(ext + 1), item_len - 4))
1043 			goto trunc;
1044 	}
1045 	return (u_char *)ext + item_len;
1046 trunc:
1047 	ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_CERT)));
1048 	return NULL;
1049 }
1050 
1051 static const u_char *
1052 ikev1_cr_print(netdissect_options *ndo, u_char tpay _U_,
1053 	       const struct isakmp_gen *ext, u_int item_len _U_,
1054 	       const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi0 _U_,
1055 	       u_int32_t proto0 _U_, int depth _U_)
1056 {
1057 	const struct ikev1_pl_cert *p;
1058 	struct ikev1_pl_cert cert;
1059 	static const char *certstr[] = {
1060 		"none",	"pkcs7", "pgp", "dns",
1061 		"x509sign", "x509ke", "kerberos", "crl",
1062 		"arl", "spki", "x509attr",
1063 	};
1064 
1065 	ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_CR)));
1066 
1067 	p = (struct ikev1_pl_cert *)ext;
1068 	ND_TCHECK(*p);
1069 	safememcpy(&cert, ext, sizeof(cert));
1070 	ND_PRINT((ndo," len=%d", item_len - 4));
1071 	ND_PRINT((ndo," type=%s", STR_OR_ID((cert.encode), certstr)));
1072 	if (2 < ndo->ndo_vflag && 4 < item_len) {
1073 		ND_PRINT((ndo," "));
1074 		if (!rawprint(ndo, (caddr_t)(ext + 1), item_len - 4))
1075 			goto trunc;
1076 	}
1077 	return (u_char *)ext + item_len;
1078 trunc:
1079 	ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_CR)));
1080 	return NULL;
1081 }
1082 
1083 static const u_char *
1084 ikev1_hash_print(netdissect_options *ndo, u_char tpay _U_,
1085 		 const struct isakmp_gen *ext, u_int item_len _U_,
1086 		 const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi _U_,
1087 		 u_int32_t proto _U_, int depth _U_)
1088 {
1089 	struct isakmp_gen e;
1090 
1091 	ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_HASH)));
1092 
1093 	ND_TCHECK(*ext);
1094 	safememcpy(&e, ext, sizeof(e));
1095 	ND_PRINT((ndo," len=%d", ntohs(e.len) - 4));
1096 	if (2 < ndo->ndo_vflag && 4 < ntohs(e.len)) {
1097 		ND_PRINT((ndo," "));
1098 		if (!rawprint(ndo, (caddr_t)(ext + 1), ntohs(e.len) - 4))
1099 			goto trunc;
1100 	}
1101 	return (u_char *)ext + ntohs(e.len);
1102 trunc:
1103 	ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_HASH)));
1104 	return NULL;
1105 }
1106 
1107 static const u_char *
1108 ikev1_sig_print(netdissect_options *ndo, u_char tpay _U_,
1109 		const struct isakmp_gen *ext, u_int item_len _U_,
1110 		const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi _U_,
1111 		u_int32_t proto _U_, int depth _U_)
1112 {
1113 	struct isakmp_gen e;
1114 
1115 	ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_SIG)));
1116 
1117 	ND_TCHECK(*ext);
1118 	safememcpy(&e, ext, sizeof(e));
1119 	ND_PRINT((ndo," len=%d", ntohs(e.len) - 4));
1120 	if (2 < ndo->ndo_vflag && 4 < ntohs(e.len)) {
1121 		ND_PRINT((ndo," "));
1122 		if (!rawprint(ndo, (caddr_t)(ext + 1), ntohs(e.len) - 4))
1123 			goto trunc;
1124 	}
1125 	return (u_char *)ext + ntohs(e.len);
1126 trunc:
1127 	ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_SIG)));
1128 	return NULL;
1129 }
1130 
1131 static const u_char *
1132 ikev1_nonce_print(netdissect_options *ndo, u_char tpay _U_,
1133 		  const struct isakmp_gen *ext,
1134 		  u_int item_len _U_,
1135 		  const u_char *ep _U_,
1136 		  u_int32_t phase _U_, u_int32_t doi _U_,
1137 		  u_int32_t proto _U_, int depth _U_)
1138 {
1139 	struct isakmp_gen e;
1140 
1141 	ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_NONCE)));
1142 
1143 	ND_TCHECK(*ext);
1144 	safememcpy(&e, ext, sizeof(e));
1145 	ND_PRINT((ndo," n len=%d", ntohs(e.len) - 4));
1146 	if (2 < ndo->ndo_vflag && 4 < ntohs(e.len)) {
1147 		ND_PRINT((ndo," "));
1148 		if (!rawprint(ndo, (caddr_t)(ext + 1), ntohs(e.len) - 4))
1149 			goto trunc;
1150 	} else if (1 < ndo->ndo_vflag && 4 < ntohs(e.len)) {
1151 		ND_PRINT((ndo," "));
1152 		if (!ike_show_somedata(ndo, (u_char *)(caddr_t)(ext + 1), ep))
1153 			goto trunc;
1154 	}
1155 	return (u_char *)ext + ntohs(e.len);
1156 trunc:
1157 	ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_NONCE)));
1158 	return NULL;
1159 }
1160 
1161 static const u_char *
1162 ikev1_n_print(netdissect_options *ndo, u_char tpay _U_,
1163 	      const struct isakmp_gen *ext, u_int item_len,
1164 	      const u_char *ep, u_int32_t phase, u_int32_t doi0 _U_,
1165 	      u_int32_t proto0 _U_, int depth)
1166 {
1167 	struct ikev1_pl_n *p, n;
1168 	const u_char *cp;
1169 	u_char *ep2;
1170 	u_int32_t doi;
1171 	u_int32_t proto;
1172 	static const char *notify_error_str[] = {
1173 		NULL,				"INVALID-PAYLOAD-TYPE",
1174 		"DOI-NOT-SUPPORTED",		"SITUATION-NOT-SUPPORTED",
1175 		"INVALID-COOKIE",		"INVALID-MAJOR-VERSION",
1176 		"INVALID-MINOR-VERSION",	"INVALID-EXCHANGE-TYPE",
1177 		"INVALID-FLAGS",		"INVALID-MESSAGE-ID",
1178 		"INVALID-PROTOCOL-ID",		"INVALID-SPI",
1179 		"INVALID-TRANSFORM-ID",		"ATTRIBUTES-NOT-SUPPORTED",
1180 		"NO-PROPOSAL-CHOSEN",		"BAD-PROPOSAL-SYNTAX",
1181 		"PAYLOAD-MALFORMED",		"INVALID-KEY-INFORMATION",
1182 		"INVALID-ID-INFORMATION",	"INVALID-CERT-ENCODING",
1183 		"INVALID-CERTIFICATE",		"CERT-TYPE-UNSUPPORTED",
1184 		"INVALID-CERT-AUTHORITY",	"INVALID-HASH-INFORMATION",
1185 		"AUTHENTICATION-FAILED",	"INVALID-SIGNATURE",
1186 		"ADDRESS-NOTIFICATION",		"NOTIFY-SA-LIFETIME",
1187 		"CERTIFICATE-UNAVAILABLE",	"UNSUPPORTED-EXCHANGE-TYPE",
1188 		"UNEQUAL-PAYLOAD-LENGTHS",
1189 	};
1190 	static const char *ipsec_notify_error_str[] = {
1191 		"RESERVED",
1192 	};
1193 	static const char *notify_status_str[] = {
1194 		"CONNECTED",
1195 	};
1196 	static const char *ipsec_notify_status_str[] = {
1197 		"RESPONDER-LIFETIME",		"REPLAY-STATUS",
1198 		"INITIAL-CONTACT",
1199 	};
1200 /* NOTE: these macro must be called with x in proper range */
1201 
1202 /* 0 - 8191 */
1203 #define NOTIFY_ERROR_STR(x) \
1204 	STR_OR_ID((x), notify_error_str)
1205 
1206 /* 8192 - 16383 */
1207 #define IPSEC_NOTIFY_ERROR_STR(x) \
1208 	STR_OR_ID((u_int)((x) - 8192), ipsec_notify_error_str)
1209 
1210 /* 16384 - 24575 */
1211 #define NOTIFY_STATUS_STR(x) \
1212 	STR_OR_ID((u_int)((x) - 16384), notify_status_str)
1213 
1214 /* 24576 - 32767 */
1215 #define IPSEC_NOTIFY_STATUS_STR(x) \
1216 	STR_OR_ID((u_int)((x) - 24576), ipsec_notify_status_str)
1217 
1218 	ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_N)));
1219 
1220 	p = (struct ikev1_pl_n *)ext;
1221 	ND_TCHECK(*p);
1222 	safememcpy(&n, ext, sizeof(n));
1223 	doi = ntohl(n.doi);
1224 	proto = n.prot_id;
1225 	if (doi != 1) {
1226 		ND_PRINT((ndo," doi=%d", doi));
1227 		ND_PRINT((ndo," proto=%d", proto));
1228 		if (ntohs(n.type) < 8192)
1229 			ND_PRINT((ndo," type=%s", NOTIFY_ERROR_STR(ntohs(n.type))));
1230 		else if (ntohs(n.type) < 16384)
1231 			ND_PRINT((ndo," type=%s", numstr(ntohs(n.type))));
1232 		else if (ntohs(n.type) < 24576)
1233 			ND_PRINT((ndo," type=%s", NOTIFY_STATUS_STR(ntohs(n.type))));
1234 		else
1235 			ND_PRINT((ndo," type=%s", numstr(ntohs(n.type))));
1236 		if (n.spi_size) {
1237 			ND_PRINT((ndo," spi="));
1238 			if (!rawprint(ndo, (caddr_t)(p + 1), n.spi_size))
1239 				goto trunc;
1240 		}
1241 		return (u_char *)(p + 1) + n.spi_size;
1242 	}
1243 
1244 	ND_PRINT((ndo," doi=ipsec"));
1245 	ND_PRINT((ndo," proto=%s", PROTOIDSTR(proto)));
1246 	if (ntohs(n.type) < 8192)
1247 		ND_PRINT((ndo," type=%s", NOTIFY_ERROR_STR(ntohs(n.type))));
1248 	else if (ntohs(n.type) < 16384)
1249 		ND_PRINT((ndo," type=%s", IPSEC_NOTIFY_ERROR_STR(ntohs(n.type))));
1250 	else if (ntohs(n.type) < 24576)
1251 		ND_PRINT((ndo," type=%s", NOTIFY_STATUS_STR(ntohs(n.type))));
1252 	else if (ntohs(n.type) < 32768)
1253 		ND_PRINT((ndo," type=%s", IPSEC_NOTIFY_STATUS_STR(ntohs(n.type))));
1254 	else
1255 		ND_PRINT((ndo," type=%s", numstr(ntohs(n.type))));
1256 	if (n.spi_size) {
1257 		ND_PRINT((ndo," spi="));
1258 		if (!rawprint(ndo, (caddr_t)(p + 1), n.spi_size))
1259 			goto trunc;
1260 	}
1261 
1262 	cp = (u_char *)(p + 1) + n.spi_size;
1263 	ep2 = (u_char *)p + item_len;
1264 
1265 	if (cp < ep) {
1266 		ND_PRINT((ndo," orig=("));
1267 		switch (ntohs(n.type)) {
1268 		case IPSECDOI_NTYPE_RESPONDER_LIFETIME:
1269 		    {
1270 			const struct attrmap *map = oakley_t_map;
1271 			size_t nmap = sizeof(oakley_t_map)/sizeof(oakley_t_map[0]);
1272 			while (cp < ep && cp < ep2) {
1273 				cp = ikev1_attrmap_print(ndo, cp,
1274 					(ep < ep2) ? ep : ep2, map, nmap);
1275 			}
1276 			break;
1277 		    }
1278 		case IPSECDOI_NTYPE_REPLAY_STATUS:
1279 			ND_PRINT((ndo,"replay detection %sabled",
1280 				  (*(u_int32_t *)cp) ? "en" : "dis"));
1281 			break;
1282 		case ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN:
1283 			if (ikev1_sub_print(ndo, ISAKMP_NPTYPE_SA,
1284 					    (struct isakmp_gen *)cp, ep, phase, doi, proto,
1285 					    depth) == NULL)
1286 				return NULL;
1287 			break;
1288 		default:
1289 			/* NULL is dummy */
1290 			isakmp_print(ndo, cp,
1291 				     item_len - sizeof(*p) - n.spi_size,
1292 				     NULL);
1293 		}
1294 		ND_PRINT((ndo,")"));
1295 	}
1296 	return (u_char *)ext + item_len;
1297 trunc:
1298 	ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_N)));
1299 	return NULL;
1300 }
1301 
1302 static const u_char *
1303 ikev1_d_print(netdissect_options *ndo, u_char tpay _U_,
1304 	      const struct isakmp_gen *ext, u_int item_len _U_,
1305 	      const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi0 _U_,
1306 	      u_int32_t proto0 _U_, int depth _U_)
1307 {
1308 	const struct ikev1_pl_d *p;
1309 	struct ikev1_pl_d d;
1310 	const u_int8_t *q;
1311 	u_int32_t doi;
1312 	u_int32_t proto;
1313 	int i;
1314 
1315 	ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_D)));
1316 
1317 	p = (struct ikev1_pl_d *)ext;
1318 	ND_TCHECK(*p);
1319 	safememcpy(&d, ext, sizeof(d));
1320 	doi = ntohl(d.doi);
1321 	proto = d.prot_id;
1322 	if (doi != 1) {
1323 		ND_PRINT((ndo," doi=%u", doi));
1324 		ND_PRINT((ndo," proto=%u", proto));
1325 	} else {
1326 		ND_PRINT((ndo," doi=ipsec"));
1327 		ND_PRINT((ndo," proto=%s", PROTOIDSTR(proto)));
1328 	}
1329 	ND_PRINT((ndo," spilen=%u", d.spi_size));
1330 	ND_PRINT((ndo," nspi=%u", ntohs(d.num_spi)));
1331 	ND_PRINT((ndo," spi="));
1332 	q = (u_int8_t *)(p + 1);
1333 	for (i = 0; i < ntohs(d.num_spi); i++) {
1334 		if (i != 0)
1335 			ND_PRINT((ndo,","));
1336 		if (!rawprint(ndo, (caddr_t)q, d.spi_size))
1337 			goto trunc;
1338 		q += d.spi_size;
1339 	}
1340 	return q;
1341 trunc:
1342 	ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_D)));
1343 	return NULL;
1344 }
1345 
1346 static const u_char *
1347 ikev1_vid_print(netdissect_options *ndo, u_char tpay _U_,
1348 		const struct isakmp_gen *ext,
1349 		u_int item_len _U_, const u_char *ep _U_,
1350 		u_int32_t phase _U_, u_int32_t doi _U_,
1351 		u_int32_t proto _U_, int depth _U_)
1352 {
1353 	struct isakmp_gen e;
1354 
1355 	ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_VID)));
1356 
1357 	ND_TCHECK(*ext);
1358 	safememcpy(&e, ext, sizeof(e));
1359 	ND_PRINT((ndo," len=%d", ntohs(e.len) - 4));
1360 	if (2 < ndo->ndo_vflag && 4 < ntohs(e.len)) {
1361 		ND_PRINT((ndo," "));
1362 		if (!rawprint(ndo, (caddr_t)(ext + 1), ntohs(e.len) - 4))
1363 			goto trunc;
1364 	}
1365 	return (u_char *)ext + ntohs(e.len);
1366 trunc:
1367 	ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_VID)));
1368 	return NULL;
1369 }
1370 
1371 /************************************************************/
1372 /*                                                          */
1373 /*              IKE v2 - rfc4306 - dissector                */
1374 /*                                                          */
1375 /************************************************************/
1376 
1377 static void
1378 ikev2_pay_print(netdissect_options *ndo, const char *payname, int critical)
1379 {
1380 	ND_PRINT((ndo,"%s%s:", payname, critical&0x80 ? "[C]" : ""));
1381 }
1382 
1383 static const u_char *
1384 ikev2_gen_print(netdissect_options *ndo, u_char tpay,
1385 		const struct isakmp_gen *ext)
1386 {
1387 	struct isakmp_gen e;
1388 
1389 	ND_TCHECK(*ext);
1390 	safememcpy(&e, ext, sizeof(e));
1391 	ikev2_pay_print(ndo, NPSTR(tpay), e.critical);
1392 
1393 	ND_PRINT((ndo," len=%d", ntohs(e.len) - 4));
1394 	if (2 < ndo->ndo_vflag && 4 < ntohs(e.len)) {
1395 		ND_PRINT((ndo," "));
1396 		if (!rawprint(ndo, (caddr_t)(ext + 1), ntohs(e.len) - 4))
1397 			goto trunc;
1398 	}
1399 	return (u_char *)ext + ntohs(e.len);
1400 trunc:
1401 	ND_PRINT((ndo," [|%s]", NPSTR(tpay)));
1402 	return NULL;
1403 }
1404 
1405 static const u_char *
1406 ikev2_t_print(netdissect_options *ndo, u_char tpay _U_, int pcount,
1407 	      const struct isakmp_gen *ext, u_int item_len,
1408 	      const u_char *ep, u_int32_t phase _U_, u_int32_t doi _U_,
1409 	      u_int32_t proto _U_, int depth _U_)
1410 {
1411 	const struct ikev2_t *p;
1412 	struct ikev2_t t;
1413 	u_int16_t  t_id;
1414 	const u_char *cp;
1415 	const char *idstr;
1416 	const struct attrmap *map;
1417 	size_t nmap;
1418 	const u_char *ep2;
1419 
1420 	p = (struct ikev2_t *)ext;
1421 	ND_TCHECK(*p);
1422 	safememcpy(&t, ext, sizeof(t));
1423 	ikev2_pay_print(ndo, NPSTR(ISAKMP_NPTYPE_T), t.h.critical);
1424 
1425 	t_id = ntohs(t.t_id);
1426 
1427 	map = NULL;
1428 	nmap = 0;
1429 
1430 	switch (t.t_type) {
1431 	case IV2_T_ENCR:
1432 		idstr = STR_OR_ID(t_id, esp_p_map);
1433 		map = encr_t_map;
1434 		nmap = sizeof(encr_t_map)/sizeof(encr_t_map[0]);
1435 		break;
1436 
1437 	case IV2_T_PRF:
1438 		idstr = STR_OR_ID(t_id, prf_p_map);
1439 		break;
1440 
1441 	case IV2_T_INTEG:
1442 		idstr = STR_OR_ID(t_id, integ_p_map);
1443 		break;
1444 
1445 	case IV2_T_DH:
1446 		idstr = STR_OR_ID(t_id, dh_p_map);
1447 		break;
1448 
1449 	case IV2_T_ESN:
1450 		idstr = STR_OR_ID(t_id, esn_p_map);
1451 		break;
1452 
1453 	default:
1454 		idstr = NULL;
1455 		break;
1456 	}
1457 
1458 	if (idstr)
1459 		ND_PRINT((ndo," #%u type=%s id=%s ", pcount,
1460 			  STR_OR_ID(t.t_type, ikev2_t_type_map),
1461 			  idstr));
1462 	else
1463 		ND_PRINT((ndo," #%u type=%s id=%u ", pcount,
1464 			  STR_OR_ID(t.t_type, ikev2_t_type_map),
1465 			  t.t_id));
1466 	cp = (u_char *)(p + 1);
1467 	ep2 = (u_char *)p + item_len;
1468 	while (cp < ep && cp < ep2) {
1469 		if (map && nmap) {
1470 			cp = ikev1_attrmap_print(ndo, cp, (ep < ep2) ? ep : ep2,
1471 				map, nmap);
1472 		} else
1473 			cp = ikev1_attr_print(ndo, cp, (ep < ep2) ? ep : ep2);
1474 	}
1475 	if (ep < ep2)
1476 		ND_PRINT((ndo,"..."));
1477 	return cp;
1478 trunc:
1479 	ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_T)));
1480 	return NULL;
1481 }
1482 
1483 static const u_char *
1484 ikev2_p_print(netdissect_options *ndo, u_char tpay _U_, int pcount _U_,
1485 	      const struct isakmp_gen *ext, u_int item_len _U_,
1486 	       const u_char *ep, u_int32_t phase, u_int32_t doi0,
1487 	       u_int32_t proto0 _U_, int depth)
1488 {
1489 	const struct ikev2_p *p;
1490 	struct ikev2_p prop;
1491 	const u_char *cp;
1492 
1493 	p = (struct ikev2_p *)ext;
1494 	ND_TCHECK(*p);
1495 	safememcpy(&prop, ext, sizeof(prop));
1496 	ikev2_pay_print(ndo, NPSTR(ISAKMP_NPTYPE_P), prop.h.critical);
1497 
1498 	ND_PRINT((ndo," #%u protoid=%s transform=%d",
1499 		  prop.p_no, PROTOIDSTR(prop.prot_id), prop.num_t));
1500 	if (prop.spi_size) {
1501 		ND_PRINT((ndo," spi="));
1502 		if (!rawprint(ndo, (caddr_t)(p + 1), prop.spi_size))
1503 			goto trunc;
1504 	}
1505 
1506 	ext = (struct isakmp_gen *)((u_char *)(p + 1) + prop.spi_size);
1507 	ND_TCHECK(*ext);
1508 
1509 	cp = ikev2_sub_print(ndo, ISAKMP_NPTYPE_T, ext, ep, phase, doi0,
1510 			     prop.prot_id, depth);
1511 
1512 	return cp;
1513 trunc:
1514 	ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_P)));
1515 	return NULL;
1516 }
1517 
1518 static const u_char *
1519 ikev2_sa_print(netdissect_options *ndo, u_char tpay,
1520 		const struct isakmp_gen *ext1,
1521 		u_int item_len _U_, const u_char *ep _U_,
1522 		u_int32_t phase _U_, u_int32_t doi _U_,
1523 		u_int32_t proto _U_, int depth _U_)
1524 {
1525 	struct isakmp_gen e;
1526 	int    osa_len, sa_len;
1527 
1528 	ND_TCHECK(*ext1);
1529 	safememcpy(&e, ext1, sizeof(e));
1530 	ikev2_pay_print(ndo, "sa", e.critical);
1531 
1532 	osa_len= ntohs(e.len);
1533 	sa_len = osa_len - 4;
1534 	ND_PRINT((ndo," len=%d", sa_len));
1535 
1536 	ikev2_sub_print(ndo, ISAKMP_NPTYPE_P,
1537 			ext1+1, ep,
1538 			0, 0, 0, depth);
1539 
1540 	return (u_char *)ext1 + osa_len;
1541 trunc:
1542 	ND_PRINT((ndo," [|%s]", NPSTR(tpay)));
1543 	return NULL;
1544 }
1545 
1546 static const u_char *
1547 ikev2_ke_print(netdissect_options *ndo, u_char tpay,
1548 		const struct isakmp_gen *ext,
1549 		u_int item_len _U_, const u_char *ep _U_,
1550 		u_int32_t phase _U_, u_int32_t doi _U_,
1551 		u_int32_t proto _U_, int depth _U_)
1552 {
1553 	struct ikev2_ke ke;
1554 	struct ikev2_ke *k;
1555 
1556 	k = (struct ikev2_ke *)ext;
1557 	ND_TCHECK(*ext);
1558 	safememcpy(&ke, ext, sizeof(ke));
1559 	ikev2_pay_print(ndo, NPSTR(tpay), ke.h.critical);
1560 
1561 	ND_PRINT((ndo," len=%u group=%s", ntohs(ke.h.len) - 8,
1562 		  STR_OR_ID(ntohs(ke.ke_group), dh_p_map)));
1563 
1564 	if (2 < ndo->ndo_vflag && 8 < ntohs(ke.h.len)) {
1565 		ND_PRINT((ndo," "));
1566 		if (!rawprint(ndo, (caddr_t)(k + 1), ntohs(ke.h.len) - 8))
1567 			goto trunc;
1568 	}
1569 	return (u_char *)ext + ntohs(ke.h.len);
1570 trunc:
1571 	ND_PRINT((ndo," [|%s]", NPSTR(tpay)));
1572 	return NULL;
1573 }
1574 
1575 static const u_char *
1576 ikev2_ID_print(netdissect_options *ndo, u_char tpay,
1577 		const struct isakmp_gen *ext,
1578 		u_int item_len _U_, const u_char *ep _U_,
1579 		u_int32_t phase _U_, u_int32_t doi _U_,
1580 		u_int32_t proto _U_, int depth _U_)
1581 {
1582 	return ikev2_gen_print(ndo, tpay, ext);
1583 }
1584 
1585 static const u_char *
1586 ikev2_cert_print(netdissect_options *ndo, u_char tpay,
1587 		const struct isakmp_gen *ext,
1588 		u_int item_len _U_, const u_char *ep _U_,
1589 		u_int32_t phase _U_, u_int32_t doi _U_,
1590 		u_int32_t proto _U_, int depth _U_)
1591 {
1592 	return ikev2_gen_print(ndo, tpay, ext);
1593 }
1594 
1595 static const u_char *
1596 ikev2_cr_print(netdissect_options *ndo, u_char tpay,
1597 		const struct isakmp_gen *ext,
1598 		u_int item_len _U_, const u_char *ep _U_,
1599 		u_int32_t phase _U_, u_int32_t doi _U_,
1600 		u_int32_t proto _U_, int depth _U_)
1601 {
1602 	return ikev2_gen_print(ndo, tpay, ext);
1603 }
1604 
1605 static const u_char *
1606 ikev2_auth_print(netdissect_options *ndo, u_char tpay,
1607 		const struct isakmp_gen *ext,
1608 		u_int item_len _U_, const u_char *ep _U_,
1609 		u_int32_t phase _U_, u_int32_t doi _U_,
1610 		u_int32_t proto _U_, int depth _U_)
1611 {
1612 	struct ikev2_auth e;
1613 	const char *v2_auth[]={ "invalid", "rsasig",
1614 				"shared-secret", "dsssig" };
1615 
1616 	ND_TCHECK(*ext);
1617 	safememcpy(&e, ext, sizeof(e));
1618 	ikev2_pay_print(ndo, NPSTR(tpay), e.h.critical);
1619 
1620 	ND_PRINT((ndo," len=%d method=%s", ntohs(e.h.len) - 4,
1621 		  STR_OR_ID(e.auth_method, v2_auth)));
1622 
1623 	if (1 < ndo->ndo_vflag && 4 < ntohs(e.h.len)) {
1624 		ND_PRINT((ndo," authdata=("));
1625 		if (!rawprint(ndo, (caddr_t)(ext + 1), ntohs(e.h.len) - 4))
1626 			goto trunc;
1627 		ND_PRINT((ndo,") "));
1628 	} else if(ndo->ndo_vflag && 4 < ntohs(e.h.len)) {
1629 		if(!ike_show_somedata(ndo, (const u_char *)(ext+1), ep)) goto trunc;
1630 	}
1631 
1632 	return (u_char *)ext + ntohs(e.h.len);
1633 trunc:
1634 	ND_PRINT((ndo," [|%s]", NPSTR(tpay)));
1635 	return NULL;
1636 }
1637 
1638 static const u_char *
1639 ikev2_nonce_print(netdissect_options *ndo, u_char tpay,
1640 		const struct isakmp_gen *ext,
1641 		u_int item_len _U_, const u_char *ep _U_,
1642 		u_int32_t phase _U_, u_int32_t doi _U_,
1643 		u_int32_t proto _U_, int depth _U_)
1644 {
1645 	struct isakmp_gen e;
1646 
1647 	ND_TCHECK(*ext);
1648 	safememcpy(&e, ext, sizeof(e));
1649 	ikev2_pay_print(ndo, "nonce", e.critical);
1650 
1651 	ND_PRINT((ndo," len=%d", ntohs(e.len) - 4));
1652 	if (1 < ndo->ndo_vflag && 4 < ntohs(e.len)) {
1653 		ND_PRINT((ndo," nonce=("));
1654 		if (!rawprint(ndo, (caddr_t)(ext + 1), ntohs(e.len) - 4))
1655 			goto trunc;
1656 		ND_PRINT((ndo,") "));
1657 	} else if(ndo->ndo_vflag && 4 < ntohs(e.len)) {
1658 		if(!ike_show_somedata(ndo, (const u_char *)(ext+1), ep)) goto trunc;
1659 	}
1660 
1661 	return (u_char *)ext + ntohs(e.len);
1662 trunc:
1663 	ND_PRINT((ndo," [|%s]", NPSTR(tpay)));
1664 	return NULL;
1665 }
1666 
1667 /* notify payloads */
1668 static const u_char *
1669 ikev2_n_print(netdissect_options *ndo, u_char tpay _U_,
1670 		const struct isakmp_gen *ext,
1671 		u_int item_len _U_, const u_char *ep _U_,
1672 		u_int32_t phase _U_, u_int32_t doi _U_,
1673 		u_int32_t proto _U_, int depth _U_)
1674 {
1675 	struct ikev2_n *p, n;
1676 	const u_char *cp;
1677 	u_char *ep2;
1678 	u_char showspi, showdata, showsomedata;
1679 	const char *notify_name;
1680 	u_int32_t type;
1681 
1682 	p = (struct ikev2_n *)ext;
1683 	ND_TCHECK(*p);
1684 	safememcpy(&n, ext, sizeof(n));
1685 	ikev2_pay_print(ndo, NPSTR(ISAKMP_NPTYPE_N), n.h.critical);
1686 
1687 	showspi = 1;
1688 	showdata = 0;
1689 	showsomedata=0;
1690 	notify_name=NULL;
1691 
1692 	ND_PRINT((ndo," prot_id=%s", PROTOIDSTR(n.prot_id)));
1693 
1694 	type = ntohs(n.type);
1695 
1696 	/* notify space is annoying sparse */
1697 	switch(type) {
1698 	case IV2_NOTIFY_UNSUPPORTED_CRITICAL_PAYLOAD:
1699 		notify_name = "unsupported_critical_payload";
1700 		showspi = 0;
1701 		break;
1702 
1703 	case IV2_NOTIFY_INVALID_IKE_SPI:
1704 		notify_name = "invalid_ike_spi";
1705 		showspi = 1;
1706 		break;
1707 
1708 	case IV2_NOTIFY_INVALID_MAJOR_VERSION:
1709 		notify_name = "invalid_major_version";
1710 		showspi = 0;
1711 		break;
1712 
1713 	case IV2_NOTIFY_INVALID_SYNTAX:
1714 		notify_name = "invalid_syntax";
1715 		showspi = 1;
1716 		break;
1717 
1718 	case IV2_NOTIFY_INVALID_MESSAGE_ID:
1719 		notify_name = "invalid_message_id";
1720 		showspi = 1;
1721 		break;
1722 
1723 	case IV2_NOTIFY_INVALID_SPI:
1724 		notify_name = "invalid_spi";
1725 		showspi = 1;
1726 		break;
1727 
1728 	case IV2_NOTIFY_NO_PROPOSAL_CHOSEN:
1729 		notify_name = "no_protocol_chosen";
1730 		showspi = 1;
1731 		break;
1732 
1733 	case IV2_NOTIFY_INVALID_KE_PAYLOAD:
1734 		notify_name = "invalid_ke_payload";
1735 		showspi = 1;
1736 		break;
1737 
1738 	case IV2_NOTIFY_AUTHENTICATION_FAILED:
1739 		notify_name = "authentication_failed";
1740 		showspi = 1;
1741 		break;
1742 
1743 	case IV2_NOTIFY_SINGLE_PAIR_REQUIRED:
1744 		notify_name = "single_pair_required";
1745 		showspi = 1;
1746 		break;
1747 
1748 	case IV2_NOTIFY_NO_ADDITIONAL_SAS:
1749 		notify_name = "no_additional_sas";
1750 		showspi = 0;
1751 		break;
1752 
1753 	case IV2_NOTIFY_INTERNAL_ADDRESS_FAILURE:
1754 		notify_name = "internal_address_failure";
1755 		showspi = 0;
1756 		break;
1757 
1758 	case IV2_NOTIFY_FAILED_CP_REQUIRED:
1759 		notify_name = "failed:cp_required";
1760 		showspi = 0;
1761 		break;
1762 
1763 	case IV2_NOTIFY_INVALID_SELECTORS:
1764 		notify_name = "invalid_selectors";
1765 		showspi = 0;
1766 		break;
1767 
1768 	case IV2_NOTIFY_INITIAL_CONTACT:
1769 		notify_name = "initial_contact";
1770 		showspi = 0;
1771 		break;
1772 
1773 	case IV2_NOTIFY_SET_WINDOW_SIZE:
1774 		notify_name = "set_window_size";
1775 		showspi = 0;
1776 		break;
1777 
1778 	case IV2_NOTIFY_ADDITIONAL_TS_POSSIBLE:
1779 		notify_name = "additional_ts_possible";
1780 		showspi = 0;
1781 		break;
1782 
1783 	case IV2_NOTIFY_IPCOMP_SUPPORTED:
1784 		notify_name = "ipcomp_supported";
1785 		showspi = 0;
1786 		break;
1787 
1788 	case IV2_NOTIFY_NAT_DETECTION_SOURCE_IP:
1789 		notify_name = "nat_detection_source_ip";
1790 		showspi = 1;
1791 		break;
1792 
1793 	case IV2_NOTIFY_NAT_DETECTION_DESTINATION_IP:
1794 		notify_name = "nat_detection_destination_ip";
1795 		showspi = 1;
1796 		break;
1797 
1798 	case IV2_NOTIFY_COOKIE:
1799 		notify_name = "cookie";
1800 		showspi = 1;
1801 		showsomedata= 1;
1802 		showdata= 0;
1803 		break;
1804 
1805 	case IV2_NOTIFY_USE_TRANSPORT_MODE:
1806 		notify_name = "use_transport_mode";
1807 		showspi = 0;
1808 		break;
1809 
1810 	case IV2_NOTIFY_HTTP_CERT_LOOKUP_SUPPORTED:
1811 		notify_name = "http_cert_lookup_supported";
1812 		showspi = 0;
1813 		break;
1814 
1815 	case IV2_NOTIFY_REKEY_SA:
1816 		notify_name = "rekey_sa";
1817 		showspi = 1;
1818 		break;
1819 
1820 	case IV2_NOTIFY_ESP_TFC_PADDING_NOT_SUPPORTED:
1821 		notify_name = "tfc_padding_not_supported";
1822 		showspi = 0;
1823 		break;
1824 
1825 	case IV2_NOTIFY_NON_FIRST_FRAGMENTS_ALSO:
1826 		notify_name = "non_first_fragment_also";
1827 		showspi = 0;
1828 		break;
1829 
1830 	default:
1831 		if (type < 8192) {
1832 			notify_name="error";
1833 		} else if(type < 16384) {
1834 			notify_name="private-error";
1835 		} else if(type < 40960) {
1836 			notify_name="status";
1837 		} else {
1838 			notify_name="private-status";
1839 		}
1840 	}
1841 
1842 	if(notify_name) {
1843 		ND_PRINT((ndo," type=%u(%s)", type, notify_name));
1844 	}
1845 
1846 
1847 	if (showspi && n.spi_size) {
1848 		ND_PRINT((ndo," spi="));
1849 		if (!rawprint(ndo, (caddr_t)(p + 1), n.spi_size))
1850 			goto trunc;
1851 	}
1852 
1853 	cp = (u_char *)(p + 1) + n.spi_size;
1854 	ep2 = (u_char *)p + item_len;
1855 
1856 	if(3 < ndo->ndo_vflag) {
1857 		showdata = 1;
1858 	}
1859 
1860 	if ((showdata || (showsomedata && ep-cp < 30)) && cp < ep) {
1861 		ND_PRINT((ndo," data=("));
1862 		if (!rawprint(ndo, (caddr_t)(cp), ep - cp))
1863 			goto trunc;
1864 
1865 		ND_PRINT((ndo,")"));
1866 
1867 	} else if(showsomedata && cp < ep) {
1868 		if(!ike_show_somedata(ndo, cp, ep)) goto trunc;
1869 	}
1870 
1871 	return (u_char *)ext + item_len;
1872 trunc:
1873 	ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_N)));
1874 	return NULL;
1875 }
1876 
1877 static const u_char *
1878 ikev2_d_print(netdissect_options *ndo, u_char tpay,
1879 		const struct isakmp_gen *ext,
1880 		u_int item_len _U_, const u_char *ep _U_,
1881 		u_int32_t phase _U_, u_int32_t doi _U_,
1882 		u_int32_t proto _U_, int depth _U_)
1883 {
1884 	return ikev2_gen_print(ndo, tpay, ext);
1885 }
1886 
1887 static const u_char *
1888 ikev2_vid_print(netdissect_options *ndo, u_char tpay,
1889 		const struct isakmp_gen *ext,
1890 		u_int item_len _U_, const u_char *ep _U_,
1891 		u_int32_t phase _U_, u_int32_t doi _U_,
1892 		u_int32_t proto _U_, int depth _U_)
1893 {
1894 	struct isakmp_gen e;
1895 	const u_char *vid;
1896 	int i, len;
1897 
1898 	ND_TCHECK(*ext);
1899 	safememcpy(&e, ext, sizeof(e));
1900 	ikev2_pay_print(ndo, NPSTR(tpay), e.critical);
1901 	ND_PRINT((ndo," len=%d vid=", ntohs(e.len) - 4));
1902 
1903 	vid = (const u_char *)(ext+1);
1904 	len = ntohs(e.len) - 4;
1905 	ND_TCHECK2(*vid, len);
1906 	for(i=0; i<len; i++) {
1907 		if(isprint(vid[i])) ND_PRINT((ndo, "%c", vid[i]));
1908 		else ND_PRINT((ndo, ".", vid[i]));
1909 	}
1910 	if (2 < ndo->ndo_vflag && 4 < len) {
1911 		ND_PRINT((ndo," "));
1912 		if (!rawprint(ndo, (caddr_t)(ext + 1), ntohs(e.len) - 4))
1913 			goto trunc;
1914 	}
1915 	return (u_char *)ext + ntohs(e.len);
1916 trunc:
1917 	ND_PRINT((ndo," [|%s]", NPSTR(tpay)));
1918 	return NULL;
1919 }
1920 
1921 static const u_char *
1922 ikev2_TS_print(netdissect_options *ndo, u_char tpay,
1923 		const struct isakmp_gen *ext,
1924 		u_int item_len _U_, const u_char *ep _U_,
1925 		u_int32_t phase _U_, u_int32_t doi _U_,
1926 		u_int32_t proto _U_, int depth _U_)
1927 {
1928 	return ikev2_gen_print(ndo, tpay, ext);
1929 }
1930 
1931 static const u_char *
1932 ikev2_e_print(netdissect_options *ndo, u_char tpay,
1933 		const struct isakmp_gen *ext,
1934 		u_int item_len _U_, const u_char *ep _U_,
1935 		u_int32_t phase _U_, u_int32_t doi _U_,
1936 		u_int32_t proto _U_, int depth _U_)
1937 {
1938 	return ikev2_gen_print(ndo, tpay, ext);
1939 }
1940 
1941 static const u_char *
1942 ikev2_cp_print(netdissect_options *ndo, u_char tpay,
1943 		const struct isakmp_gen *ext,
1944 		u_int item_len _U_, const u_char *ep _U_,
1945 		u_int32_t phase _U_, u_int32_t doi _U_,
1946 		u_int32_t proto _U_, int depth _U_)
1947 {
1948 	return ikev2_gen_print(ndo, tpay, ext);
1949 }
1950 
1951 static const u_char *
1952 ikev2_eap_print(netdissect_options *ndo, u_char tpay,
1953 		const struct isakmp_gen *ext,
1954 		u_int item_len _U_, const u_char *ep _U_,
1955 		u_int32_t phase _U_, u_int32_t doi _U_,
1956 		u_int32_t proto _U_, int depth _U_)
1957 {
1958 	return ikev2_gen_print(ndo, tpay, ext);
1959 }
1960 
1961 static const u_char *
1962 ike_sub0_print(netdissect_options *ndo,
1963 		 u_char np, const struct isakmp_gen *ext, const u_char *ep,
1964 		 u_int32_t phase, u_int32_t doi, u_int32_t proto, int depth)
1965 {
1966 	const u_char *cp;
1967 	struct isakmp_gen e;
1968 	u_int item_len;
1969 
1970 	cp = (u_char *)ext;
1971 	ND_TCHECK(*ext);
1972 	safememcpy(&e, ext, sizeof(e));
1973 
1974 	/*
1975 	 * Since we can't have a payload length of less than 4 bytes,
1976 	 * we need to bail out here if the generic header is nonsensical
1977 	 * or truncated, otherwise we could loop forever processing
1978 	 * zero-length items or otherwise misdissect the packet.
1979 	 */
1980 	item_len = ntohs(e.len);
1981 	if (item_len <= 4)
1982 		return NULL;
1983 
1984 	if (NPFUNC(np)) {
1985 		/*
1986 		 * XXX - what if item_len is too short, or too long,
1987 		 * for this payload type?
1988 		 */
1989 		cp = (*npfunc[np])(ndo, np, ext, item_len, ep, phase, doi, proto, depth);
1990 	} else {
1991 		ND_PRINT((ndo,"%s", NPSTR(np)));
1992 		cp += item_len;
1993 	}
1994 
1995 	return cp;
1996 trunc:
1997 	ND_PRINT((ndo," [|isakmp]"));
1998 	return NULL;
1999 }
2000 
2001 static const u_char *
2002 ikev1_sub_print(netdissect_options *ndo,
2003 		u_char np, const struct isakmp_gen *ext, const u_char *ep,
2004 		u_int32_t phase, u_int32_t doi, u_int32_t proto, int depth)
2005 {
2006 	const u_char *cp;
2007 	int i;
2008 	struct isakmp_gen e;
2009 
2010 	cp = (const u_char *)ext;
2011 
2012 	while (np) {
2013 		ND_TCHECK(*ext);
2014 
2015 		safememcpy(&e, ext, sizeof(e));
2016 
2017 		ND_TCHECK2(*ext, ntohs(e.len));
2018 
2019 		depth++;
2020 		ND_PRINT((ndo,"\n"));
2021 		for (i = 0; i < depth; i++)
2022 			ND_PRINT((ndo,"    "));
2023 		ND_PRINT((ndo,"("));
2024 		cp = ike_sub0_print(ndo, np, ext, ep, phase, doi, proto, depth);
2025 		ND_PRINT((ndo,")"));
2026 		depth--;
2027 
2028 		if (cp == NULL) {
2029 			/* Zero-length subitem */
2030 			return NULL;
2031 		}
2032 
2033 		np = e.np;
2034 		ext = (struct isakmp_gen *)cp;
2035 	}
2036 	return cp;
2037 trunc:
2038 	ND_PRINT((ndo," [|%s]", NPSTR(np)));
2039 	return NULL;
2040 }
2041 
2042 static char *
2043 numstr(int x)
2044 {
2045 	static char buf[20];
2046 	snprintf(buf, sizeof(buf), "#%d", x);
2047 	return buf;
2048 }
2049 
2050 /*
2051  * some compiler tries to optimize memcpy(), using the alignment constraint
2052  * on the argument pointer type.  by using this function, we try to avoid the
2053  * optimization.
2054  */
2055 static void
2056 safememcpy(void *p, const void *q, size_t l)
2057 {
2058 	memcpy(p, q, l);
2059 }
2060 
2061 void
2062 ikev1_print(netdissect_options *ndo,
2063 	    const u_char *bp,  u_int length,
2064 	    const u_char *bp2, struct isakmp *base)
2065 {
2066 	const struct isakmp *p;
2067 	const u_char *ep;
2068 	u_char np;
2069 	int i;
2070 	int phase;
2071 
2072 	p = (const struct isakmp *)bp;
2073 	ep = ndo->ndo_snapend;
2074 
2075 	phase = (*(u_int32_t *)base->msgid == 0) ? 1 : 2;
2076 	if (phase == 1)
2077 		ND_PRINT((ndo," phase %d", phase));
2078 	else
2079 		ND_PRINT((ndo," phase %d/others", phase));
2080 
2081 	i = cookie_find(&base->i_ck);
2082 	if (i < 0) {
2083 		if (iszero((u_char *)&base->r_ck, sizeof(base->r_ck))) {
2084 			/* the first packet */
2085 			ND_PRINT((ndo," I"));
2086 			if (bp2)
2087 				cookie_record(&base->i_ck, bp2);
2088 		} else
2089 			ND_PRINT((ndo," ?"));
2090 	} else {
2091 		if (bp2 && cookie_isinitiator(i, bp2))
2092 			ND_PRINT((ndo," I"));
2093 		else if (bp2 && cookie_isresponder(i, bp2))
2094 			ND_PRINT((ndo," R"));
2095 		else
2096 			ND_PRINT((ndo," ?"));
2097 	}
2098 
2099 	ND_PRINT((ndo," %s", ETYPESTR(base->etype)));
2100 	if (base->flags) {
2101 		ND_PRINT((ndo,"[%s%s]", base->flags & ISAKMP_FLAG_E ? "E" : "",
2102 			  base->flags & ISAKMP_FLAG_C ? "C" : ""));
2103 	}
2104 
2105 	if (ndo->ndo_vflag) {
2106 		const struct isakmp_gen *ext;
2107 		int nparen;
2108 
2109 		ND_PRINT((ndo,":"));
2110 
2111 		/* regardless of phase... */
2112 		if (base->flags & ISAKMP_FLAG_E) {
2113 			/*
2114 			 * encrypted, nothing we can do right now.
2115 			 * we hope to decrypt the packet in the future...
2116 			 */
2117 			ND_PRINT((ndo," [encrypted %s]", NPSTR(base->np)));
2118 			goto done;
2119 		}
2120 
2121 		nparen = 0;
2122 		CHECKLEN(p + 1, base->np);
2123 		np = base->np;
2124 		ext = (struct isakmp_gen *)(p + 1);
2125 		ikev1_sub_print(ndo, np, ext, ep, phase, 0, 0, 0);
2126 	}
2127 
2128 done:
2129 	if (ndo->ndo_vflag) {
2130 		if (ntohl(base->len) != length) {
2131 			ND_PRINT((ndo," (len mismatch: isakmp %u/ip %u)",
2132 				  (u_int32_t)ntohl(base->len), length));
2133 		}
2134 	}
2135 }
2136 
2137 static const u_char *
2138 ikev2_sub0_print(netdissect_options *ndo, u_char np, int pcount,
2139 		 const struct isakmp_gen *ext, const u_char *ep,
2140 		 u_int32_t phase, u_int32_t doi, u_int32_t proto, int depth)
2141 {
2142 	const u_char *cp;
2143 	struct isakmp_gen e;
2144 	u_int item_len;
2145 
2146 	cp = (u_char *)ext;
2147 	ND_TCHECK(*ext);
2148 	safememcpy(&e, ext, sizeof(e));
2149 
2150 	/*
2151 	 * Since we can't have a payload length of less than 4 bytes,
2152 	 * we need to bail out here if the generic header is nonsensical
2153 	 * or truncated, otherwise we could loop forever processing
2154 	 * zero-length items or otherwise misdissect the packet.
2155 	 */
2156 	item_len = ntohs(e.len);
2157 	if (item_len <= 4)
2158 		return NULL;
2159 
2160 	if(np == ISAKMP_NPTYPE_P) {
2161 		cp = ikev2_p_print(ndo, np, pcount, ext, item_len,
2162 				   ep, phase, doi, proto, depth);
2163 	} else if(np == ISAKMP_NPTYPE_T) {
2164 		cp = ikev2_t_print(ndo, np, pcount, ext, item_len,
2165 				   ep, phase, doi, proto, depth);
2166 	} else if (NPFUNC(np)) {
2167 		/*
2168 		 * XXX - what if item_len is too short, or too long,
2169 		 * for this payload type?
2170 		 */
2171 		cp = (*npfunc[np])(ndo, np, /*pcount,*/ ext, item_len,
2172 				   ep, phase, doi, proto, depth);
2173 	} else {
2174 		ND_PRINT((ndo,"%s", NPSTR(np)));
2175 		cp += item_len;
2176 	}
2177 
2178 	return cp;
2179 trunc:
2180 	ND_PRINT((ndo," [|isakmp]"));
2181 	return NULL;
2182 }
2183 
2184 static const u_char *
2185 ikev2_sub_print(netdissect_options *ndo,
2186 		u_char np, const struct isakmp_gen *ext, const u_char *ep,
2187 		u_int32_t phase, u_int32_t doi, u_int32_t proto, int depth)
2188 {
2189 	const u_char *cp;
2190 	int i;
2191 	int pcount;
2192 	struct isakmp_gen e;
2193 
2194 	cp = (const u_char *)ext;
2195 	pcount = 0;
2196 	while (np) {
2197 		pcount++;
2198 		ND_TCHECK(*ext);
2199 
2200 		safememcpy(&e, ext, sizeof(e));
2201 
2202 		ND_TCHECK2(*ext, ntohs(e.len));
2203 
2204 		depth++;
2205 		ND_PRINT((ndo,"\n"));
2206 		for (i = 0; i < depth; i++)
2207 			ND_PRINT((ndo,"    "));
2208 		ND_PRINT((ndo,"("));
2209 		cp = ikev2_sub0_print(ndo, np, pcount,
2210 				      ext, ep, phase, doi, proto, depth);
2211 		ND_PRINT((ndo,")"));
2212 		depth--;
2213 
2214 		if (cp == NULL) {
2215 			/* Zero-length subitem */
2216 			return NULL;
2217 		}
2218 
2219 		np = e.np;
2220 		ext = (struct isakmp_gen *)cp;
2221 	}
2222 	return cp;
2223 trunc:
2224 	ND_PRINT((ndo," [|%s]", NPSTR(np)));
2225 	return NULL;
2226 }
2227 
2228 static void
2229 ikev2_print(netdissect_options *ndo,
2230 	    const u_char *bp,  u_int length,
2231 	    const u_char *bp2 _U_, struct isakmp *base)
2232 {
2233 	const struct isakmp *p;
2234 	const u_char *ep;
2235 	u_char np;
2236 	int phase;
2237 
2238 	p = (const struct isakmp *)bp;
2239 	ep = ndo->ndo_snapend;
2240 
2241 	phase = (*(u_int32_t *)base->msgid == 0) ? 1 : 2;
2242 	if (phase == 1)
2243 		ND_PRINT((ndo, " parent_sa"));
2244 	else
2245 		ND_PRINT((ndo, " child_sa "));
2246 
2247 	ND_PRINT((ndo, " %s", ETYPESTR(base->etype)));
2248 	if (base->flags) {
2249 		ND_PRINT((ndo, "[%s%s]",
2250 			  base->flags & ISAKMP_FLAG_I ? "I" : "",
2251 			  base->flags & ISAKMP_FLAG_V ? "V" : "",
2252 			  base->flags & ISAKMP_FLAG_R ? "R" : ""));
2253 	}
2254 
2255 	if (ndo->ndo_vflag) {
2256 		const struct isakmp_gen *ext;
2257 		int nparen;
2258 
2259 		ND_PRINT((ndo, ":"));
2260 
2261 		/* regardless of phase... */
2262 		if (base->flags & ISAKMP_FLAG_E) {
2263 			/*
2264 			 * encrypted, nothing we can do right now.
2265 			 * we hope to decrypt the packet in the future...
2266 			 */
2267 			ND_PRINT((ndo, " [encrypted %s]", NPSTR(base->np)));
2268 			goto done;
2269 		}
2270 
2271 		nparen = 0;
2272 		CHECKLEN(p + 1, base->np)
2273 
2274 		np = base->np;
2275 		ext = (struct isakmp_gen *)(p + 1);
2276 		ikev2_sub_print(ndo, np, ext, ep, phase, 0, 0, 0);
2277 	}
2278 
2279 done:
2280 	if (ndo->ndo_vflag) {
2281 		if (ntohl(base->len) != length) {
2282 			ND_PRINT((ndo, " (len mismatch: isakmp %u/ip %u)",
2283 				  (u_int32_t)ntohl(base->len), length));
2284 		}
2285 	}
2286 }
2287 
2288 void
2289 isakmp_print(netdissect_options *ndo,
2290 	     const u_char *bp, u_int length,
2291 	     const u_char *bp2)
2292 {
2293 	const struct isakmp *p;
2294 	struct isakmp base;
2295 	const u_char *ep;
2296 	int major, minor;
2297 
2298 	p = (const struct isakmp *)bp;
2299 	ep = ndo->ndo_snapend;
2300 
2301 	if ((struct isakmp *)ep < p + 1) {
2302 		ND_PRINT((ndo,"[|isakmp]"));
2303 		return;
2304 	}
2305 
2306 	safememcpy(&base, p, sizeof(base));
2307 
2308 	ND_PRINT((ndo,"isakmp"));
2309 	major = (base.vers & ISAKMP_VERS_MAJOR)
2310 		>> ISAKMP_VERS_MAJOR_SHIFT;
2311 	minor = (base.vers & ISAKMP_VERS_MINOR)
2312 		>> ISAKMP_VERS_MINOR_SHIFT;
2313 
2314 	if (ndo->ndo_vflag) {
2315 		ND_PRINT((ndo," %d.%d", major, minor));
2316 	}
2317 
2318 	if (ndo->ndo_vflag) {
2319 		ND_PRINT((ndo," msgid "));
2320 		rawprint(ndo, (caddr_t)&base.msgid, sizeof(base.msgid));
2321 	}
2322 
2323 	if (1 < ndo->ndo_vflag) {
2324 		ND_PRINT((ndo," cookie "));
2325 		rawprint(ndo, (caddr_t)&base.i_ck, sizeof(base.i_ck));
2326 		ND_PRINT((ndo,"->"));
2327 		rawprint(ndo, (caddr_t)&base.r_ck, sizeof(base.r_ck));
2328 	}
2329 	ND_PRINT((ndo,":"));
2330 
2331 	switch(major) {
2332 	case IKEv1_MAJOR_VERSION:
2333 		ikev1_print(ndo, bp, length, bp2, &base);
2334 		break;
2335 
2336 	case IKEv2_MAJOR_VERSION:
2337 		ikev2_print(ndo, bp, length, bp2, &base);
2338 		break;
2339 	}
2340 }
2341 
2342 void
2343 isakmp_rfc3948_print(netdissect_options *ndo,
2344 		     const u_char *bp, u_int length,
2345 		     const u_char *bp2)
2346 {
2347 	const u_char *ep;
2348 	ep = ndo->ndo_snapend;
2349 
2350 	if(length == 1 && bp[0]==0xff) {
2351 		ND_PRINT((ndo, "isakmp-nat-keep-alive"));
2352 		return;
2353 	}
2354 
2355 	if(length < 4) {
2356 		goto trunc;
2357 	}
2358 
2359 	/*
2360 	 * see if this is an IKE packet
2361 	 */
2362 	if(bp[0]==0 && bp[1]==0 && bp[2]==0 && bp[3]==0) {
2363 		ND_PRINT((ndo, "NONESP-encap: "));
2364 		isakmp_print(ndo, bp+4, length-4, bp2);
2365 		return;
2366 	}
2367 
2368 	/* must be an ESP packet */
2369 	{
2370 		int nh, enh, padlen;
2371 		int advance;
2372 
2373 		ND_PRINT((ndo, "UDP-encap: "));
2374 
2375 		advance = esp_print(ndo, bp, length, bp2, &enh, &padlen);
2376 		if(advance <= 0)
2377 			return;
2378 
2379 		bp += advance;
2380 		length -= advance + padlen;
2381 		nh = enh & 0xff;
2382 
2383 		ip_print_inner(ndo, bp, length, nh, bp2);
2384 		return;
2385 	}
2386 
2387 trunc:
2388 	ND_PRINT((ndo,"[|isakmp]"));
2389 	return;
2390 }
2391 
2392 /*
2393  * Local Variables:
2394  * c-style: whitesmith
2395  * c-basic-offset: 8
2396  * End:
2397  */
2398 
2399 
2400 
2401 
2402