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