156893Sfenner/*
256893Sfenner * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
356893Sfenner * All rights reserved.
4127668Sbms *
556893Sfenner * Redistribution and use in source and binary forms, with or without
656893Sfenner * modification, are permitted provided that the following conditions
756893Sfenner * are met:
856893Sfenner * 1. Redistributions of source code must retain the above copyright
956893Sfenner *    notice, this list of conditions and the following disclaimer.
1056893Sfenner * 2. Redistributions in binary form must reproduce the above copyright
1156893Sfenner *    notice, this list of conditions and the following disclaimer in the
1256893Sfenner *    documentation and/or other materials provided with the distribution.
1356893Sfenner * 3. Neither the name of the project nor the names of its contributors
1456893Sfenner *    may be used to endorse or promote products derived from this software
1556893Sfenner *    without specific prior written permission.
16127668Sbms *
1756893Sfenner * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
1856893Sfenner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1956893Sfenner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2056893Sfenner * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
2156893Sfenner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2256893Sfenner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2356893Sfenner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2456893Sfenner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2556893Sfenner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2656893Sfenner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2756893Sfenner * SUCH DAMAGE.
2856893Sfenner *
2956893Sfenner */
3056893Sfenner
3156893Sfenner#ifndef lint
32127668Sbmsstatic const char rcsid[] _U_ =
33214478Srpaulo    "@(#) $Header: /tcpdump/master/tcpdump/print-isakmp.c,v 1.61 2008-02-05 19:34:25 guy Exp $ (LBL)";
3456893Sfenner#endif
3556893Sfenner
36190207Srpaulo#define NETDISSECT_REWORKED
3756893Sfenner#ifdef HAVE_CONFIG_H
3856893Sfenner#include "config.h"
3956893Sfenner#endif
4056893Sfenner
41127668Sbms#include <tcpdump-stdinc.h>
42127668Sbms
4356893Sfenner#include <string.h>
4456893Sfenner
4556893Sfenner#include <stdio.h>
4656893Sfenner
4756893Sfenner#include "isakmp.h"
4856893Sfenner#include "ipsec_doi.h"
4956893Sfenner#include "oakley.h"
5056893Sfenner#include "interface.h"
5156893Sfenner#include "addrtoname.h"
5256893Sfenner#include "extract.h"                    /* must come after interface.h */
5356893Sfenner
5475115Sfenner#include "ip.h"
5575115Sfenner#ifdef INET6
5675115Sfenner#include "ip6.h"
5775115Sfenner#endif
5875115Sfenner
5956893Sfenner#ifndef HAVE_SOCKADDR_STORAGE
6056893Sfenner#define sockaddr_storage sockaddr
6156893Sfenner#endif
6256893Sfenner
63190207Srpaulo#define DECLARE_PRINTER(func) static const u_char *ike##func##_print( \
64190207Srpaulo		netdissect_options *ndo, u_char tpay,	              \
65190207Srpaulo		const struct isakmp_gen *ext,			      \
66190207Srpaulo		u_int item_len, \
67190207Srpaulo		const u_char *end_pointer, \
68190207Srpaulo		u_int32_t phase,\
69190207Srpaulo		u_int32_t doi0, \
70190207Srpaulo		u_int32_t proto0, int depth)
71190207Srpaulo
72190207SrpauloDECLARE_PRINTER(v1_sa);
73190207SrpauloDECLARE_PRINTER(v1_p);
74190207SrpauloDECLARE_PRINTER(v1_t);
75190207SrpauloDECLARE_PRINTER(v1_ke);
76190207SrpauloDECLARE_PRINTER(v1_id);
77190207SrpauloDECLARE_PRINTER(v1_cert);
78190207SrpauloDECLARE_PRINTER(v1_cr);
79190207SrpauloDECLARE_PRINTER(v1_sig);
80190207SrpauloDECLARE_PRINTER(v1_hash);
81190207SrpauloDECLARE_PRINTER(v1_nonce);
82190207SrpauloDECLARE_PRINTER(v1_n);
83190207SrpauloDECLARE_PRINTER(v1_d);
84190207SrpauloDECLARE_PRINTER(v1_vid);
85190207Srpaulo
86190207SrpauloDECLARE_PRINTER(v2_sa);
87190207SrpauloDECLARE_PRINTER(v2_ke);
88190207SrpauloDECLARE_PRINTER(v2_ID);
89190207SrpauloDECLARE_PRINTER(v2_cert);
90190207SrpauloDECLARE_PRINTER(v2_cr);
91190207SrpauloDECLARE_PRINTER(v2_auth);
92190207SrpauloDECLARE_PRINTER(v2_nonce);
93190207SrpauloDECLARE_PRINTER(v2_n);
94190207SrpauloDECLARE_PRINTER(v2_d);
95190207SrpauloDECLARE_PRINTER(v2_vid);
96190207SrpauloDECLARE_PRINTER(v2_TS);
97190207SrpauloDECLARE_PRINTER(v2_cp);
98190207SrpauloDECLARE_PRINTER(v2_eap);
99190207Srpaulo
100214478Srpaulostatic const u_char *ikev2_e_print(netdissect_options *ndo,
101214478Srpaulo				   struct isakmp *base,
102214478Srpaulo				   u_char tpay,
103214478Srpaulo				   const struct isakmp_gen *ext,
104214478Srpaulo				   u_int item_len,
105214478Srpaulo				   const u_char *end_pointer,
106214478Srpaulo				   u_int32_t phase,
107214478Srpaulo				   u_int32_t doi0,
108214478Srpaulo				   u_int32_t proto0, int depth);
109214478Srpaulo
110214478Srpaulo
111190207Srpaulostatic const u_char *ike_sub0_print(netdissect_options *ndo,u_char, const struct isakmp_gen *,
112127668Sbms	const u_char *,	u_int32_t, u_int32_t, u_int32_t, int);
113190207Srpaulostatic const u_char *ikev1_sub_print(netdissect_options *ndo,u_char, const struct isakmp_gen *,
114127668Sbms	const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
115190207Srpaulo
116190207Srpaulostatic const u_char *ikev2_sub_print(netdissect_options *ndo,
117214478Srpaulo				     struct isakmp *base,
118190207Srpaulo				     u_char np, const struct isakmp_gen *ext,
119190207Srpaulo				     const u_char *ep, u_int32_t phase,
120190207Srpaulo				     u_int32_t doi, u_int32_t proto,
121190207Srpaulo				     int depth);
122190207Srpaulo
123190207Srpaulo
12475115Sfennerstatic char *numstr(int);
125127668Sbmsstatic void safememcpy(void *, const void *, size_t);
12656893Sfenner
127190207Srpaulostatic void
128190207Srpauloikev1_print(netdissect_options *ndo,
129190207Srpaulo	    const u_char *bp,  u_int length,
130190207Srpaulo	    const u_char *bp2, struct isakmp *base);
131190207Srpaulo
13256893Sfenner#define MAXINITIATORS	20
13356893Sfennerint ninitiator = 0;
13456893Sfennerstruct {
13556893Sfenner	cookie_t initiator;
13656893Sfenner	struct sockaddr_storage iaddr;
13756893Sfenner	struct sockaddr_storage raddr;
13856893Sfenner} cookiecache[MAXINITIATORS];
13956893Sfenner
14056893Sfenner/* protocol id */
141127668Sbmsstatic const char *protoidstr[] = {
14256893Sfenner	NULL, "isakmp", "ipsec-ah", "ipsec-esp", "ipcomp",
14356893Sfenner};
14456893Sfenner
14556893Sfenner/* isakmp->np */
146127668Sbmsstatic const char *npstr[] = {
147190207Srpaulo	"none", "sa", "p", "t", "ke", "id", "cert", "cr", "hash", /* 0 - 8 */
148190207Srpaulo	"sig", "nonce", "n", "d", "vid",      /* 9 - 13 */
149190207Srpaulo	"pay14", "pay15", "pay16", "pay17", "pay18", /* 14- 18 */
150190207Srpaulo	"pay19", "pay20", "pay21", "pay22", "pay23", /* 19- 23 */
151190207Srpaulo	"pay24", "pay25", "pay26", "pay27", "pay28", /* 24- 28 */
152190207Srpaulo	"pay29", "pay30", "pay31", "pay32",          /* 29- 32 */
153190207Srpaulo	"v2sa",  "v2ke",  "v2IDi", "v2IDr", "v2cert",/* 33- 37 */
154190207Srpaulo	"v2cr",  "v2auth","v2nonce", "v2n",   "v2d",   /* 38- 42 */
155190207Srpaulo	"v2vid", "v2TSi", "v2TSr", "v2e",   "v2cp",  /* 43- 47 */
156190207Srpaulo	"v2eap",                                     /* 48 */
157190207Srpaulo
15856893Sfenner};
15956893Sfenner
16056893Sfenner/* isakmp->np */
161190207Srpaulostatic const u_char *(*npfunc[])(netdissect_options *ndo, u_char tpay,
162190207Srpaulo				 const struct isakmp_gen *ext,
163190207Srpaulo				 u_int item_len,
164190207Srpaulo				 const u_char *end_pointer,
165190207Srpaulo				 u_int32_t phase,
166190207Srpaulo				 u_int32_t doi0,
167190207Srpaulo				 u_int32_t proto0, int depth) = {
16856893Sfenner	NULL,
169190207Srpaulo	ikev1_sa_print,
170190207Srpaulo	ikev1_p_print,
171190207Srpaulo	ikev1_t_print,
172190207Srpaulo	ikev1_ke_print,
173190207Srpaulo	ikev1_id_print,
174190207Srpaulo	ikev1_cert_print,
175190207Srpaulo	ikev1_cr_print,
176190207Srpaulo	ikev1_hash_print,
177190207Srpaulo	ikev1_sig_print,
178190207Srpaulo	ikev1_nonce_print,
179190207Srpaulo	ikev1_n_print,
180190207Srpaulo	ikev1_d_print,
181190207Srpaulo	ikev1_vid_print,                  /* 13 */
182190207Srpaulo	NULL, NULL, NULL, NULL, NULL,     /* 14- 18 */
183190207Srpaulo	NULL, NULL, NULL, NULL, NULL,     /* 19- 23 */
184190207Srpaulo	NULL, NULL, NULL, NULL, NULL,     /* 24- 28 */
185190207Srpaulo	NULL, NULL, NULL, NULL,           /* 29- 32 */
186190207Srpaulo	ikev2_sa_print,                 /* 33 */
187190207Srpaulo	ikev2_ke_print,                 /* 34 */
188190207Srpaulo	ikev2_ID_print,                 /* 35 */
189190207Srpaulo	ikev2_ID_print,                 /* 36 */
190190207Srpaulo	ikev2_cert_print,               /* 37 */
191190207Srpaulo	ikev2_cr_print,                 /* 38 */
192190207Srpaulo	ikev2_auth_print,               /* 39 */
193190207Srpaulo	ikev2_nonce_print,              /* 40 */
194190207Srpaulo	ikev2_n_print,                  /* 41 */
195190207Srpaulo	ikev2_d_print,                  /* 42 */
196190207Srpaulo	ikev2_vid_print,                /* 43 */
197190207Srpaulo	ikev2_TS_print,                 /* 44 */
198190207Srpaulo	ikev2_TS_print,                 /* 45 */
199214478Srpaulo	NULL, /* ikev2_e_print,*/       /* 46 - special */
200190207Srpaulo	ikev2_cp_print,                 /* 47 */
201190207Srpaulo	ikev2_eap_print,                /* 48 */
20256893Sfenner};
20356893Sfenner
20456893Sfenner/* isakmp->etype */
205127668Sbmsstatic const char *etypestr[] = {
206190207Srpaulo/* IKEv1 exchange types */
207190207Srpaulo	"none", "base", "ident", "auth", "agg", "inf", NULL, NULL,  /* 0-7 */
208190207Srpaulo	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,  /*  8-15 */
209190207Srpaulo	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,  /* 16-23 */
210190207Srpaulo	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,  /* 24-31 */
211190207Srpaulo	"oakley-quick", "oakley-newgroup",               /* 32-33 */
212190207Srpaulo/* IKEv2 exchange types */
213190207Srpaulo	"ikev2_init", "ikev2_auth", "child_sa", "inf2"   /* 34-37 */
21456893Sfenner};
21556893Sfenner
21656893Sfenner#define STR_OR_ID(x, tab) \
21756893Sfenner	(((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)])	? tab[(x)] : numstr(x))
21856893Sfenner#define PROTOIDSTR(x)	STR_OR_ID(x, protoidstr)
21956893Sfenner#define NPSTR(x)	STR_OR_ID(x, npstr)
22056893Sfenner#define ETYPESTR(x)	STR_OR_ID(x, etypestr)
22156893Sfenner
222190207Srpaulo#define CHECKLEN(p, np)							\
223190207Srpaulo		if (ep < (u_char *)(p)) {				\
224190207Srpaulo			ND_PRINT((ndo," [|%s]", NPSTR(np)));		\
225190207Srpaulo			goto done;					\
226190207Srpaulo		}
227190207Srpaulo
228190207Srpaulo
22956893Sfenner#define NPFUNC(x) \
23056893Sfenner	(((x) < sizeof(npfunc)/sizeof(npfunc[0]) && npfunc[(x)]) \
23156893Sfenner		? npfunc[(x)] : NULL)
23256893Sfenner
23356893Sfennerstatic int
23456893Sfenneriszero(u_char *p, size_t l)
23556893Sfenner{
23656893Sfenner	while (l--) {
23756893Sfenner		if (*p++)
23856893Sfenner			return 0;
23956893Sfenner	}
24056893Sfenner	return 1;
24156893Sfenner}
24256893Sfenner
24356893Sfenner/* find cookie from initiator cache */
24456893Sfennerstatic int
24556893Sfennercookie_find(cookie_t *in)
24656893Sfenner{
24756893Sfenner	int i;
24856893Sfenner
24956893Sfenner	for (i = 0; i < MAXINITIATORS; i++) {
25056893Sfenner		if (memcmp(in, &cookiecache[i].initiator, sizeof(*in)) == 0)
25156893Sfenner			return i;
25256893Sfenner	}
25356893Sfenner
25456893Sfenner	return -1;
25556893Sfenner}
25656893Sfenner
25756893Sfenner/* record initiator */
25856893Sfennerstatic void
25956893Sfennercookie_record(cookie_t *in, const u_char *bp2)
26056893Sfenner{
26156893Sfenner	int i;
26256893Sfenner	struct ip *ip;
26356893Sfenner	struct sockaddr_in *sin;
26456893Sfenner#ifdef INET6
26556893Sfenner	struct ip6_hdr *ip6;
26656893Sfenner	struct sockaddr_in6 *sin6;
26756893Sfenner#endif
26856893Sfenner
26956893Sfenner	i = cookie_find(in);
27056893Sfenner	if (0 <= i) {
27156893Sfenner		ninitiator = (i + 1) % MAXINITIATORS;
27256893Sfenner		return;
27356893Sfenner	}
27456893Sfenner
27556893Sfenner	ip = (struct ip *)bp2;
27675115Sfenner	switch (IP_V(ip)) {
27756893Sfenner	case 4:
27856893Sfenner		memset(&cookiecache[ninitiator].iaddr, 0,
27956893Sfenner			sizeof(cookiecache[ninitiator].iaddr));
28056893Sfenner		memset(&cookiecache[ninitiator].raddr, 0,
28156893Sfenner			sizeof(cookiecache[ninitiator].raddr));
28256893Sfenner
28356893Sfenner		sin = (struct sockaddr_in *)&cookiecache[ninitiator].iaddr;
28456893Sfenner#ifdef HAVE_SOCKADDR_SA_LEN
28556893Sfenner		sin->sin_len = sizeof(struct sockaddr_in);
28656893Sfenner#endif
28756893Sfenner		sin->sin_family = AF_INET;
28856893Sfenner		memcpy(&sin->sin_addr, &ip->ip_src, sizeof(ip->ip_src));
28956893Sfenner		sin = (struct sockaddr_in *)&cookiecache[ninitiator].raddr;
29056893Sfenner#ifdef HAVE_SOCKADDR_SA_LEN
29156893Sfenner		sin->sin_len = sizeof(struct sockaddr_in);
29256893Sfenner#endif
29356893Sfenner		sin->sin_family = AF_INET;
29456893Sfenner		memcpy(&sin->sin_addr, &ip->ip_dst, sizeof(ip->ip_dst));
29556893Sfenner		break;
29656893Sfenner#ifdef INET6
29756893Sfenner	case 6:
29856893Sfenner		memset(&cookiecache[ninitiator].iaddr, 0,
29956893Sfenner			sizeof(cookiecache[ninitiator].iaddr));
30056893Sfenner		memset(&cookiecache[ninitiator].raddr, 0,
30156893Sfenner			sizeof(cookiecache[ninitiator].raddr));
30256893Sfenner
30356893Sfenner		ip6 = (struct ip6_hdr *)bp2;
30456893Sfenner		sin6 = (struct sockaddr_in6 *)&cookiecache[ninitiator].iaddr;
30556893Sfenner#ifdef HAVE_SOCKADDR_SA_LEN
30656893Sfenner		sin6->sin6_len = sizeof(struct sockaddr_in6);
30756893Sfenner#endif
30856893Sfenner		sin6->sin6_family = AF_INET6;
30956893Sfenner		memcpy(&sin6->sin6_addr, &ip6->ip6_src, sizeof(ip6->ip6_src));
31056893Sfenner		sin6 = (struct sockaddr_in6 *)&cookiecache[ninitiator].raddr;
31156893Sfenner#ifdef HAVE_SOCKADDR_SA_LEN
31256893Sfenner		sin6->sin6_len = sizeof(struct sockaddr_in6);
31356893Sfenner#endif
31456893Sfenner		sin6->sin6_family = AF_INET6;
31556893Sfenner		memcpy(&sin6->sin6_addr, &ip6->ip6_dst, sizeof(ip6->ip6_dst));
31656893Sfenner		break;
31756893Sfenner#endif
31856893Sfenner	default:
31956893Sfenner		return;
32056893Sfenner	}
32156893Sfenner	memcpy(&cookiecache[ninitiator].initiator, in, sizeof(*in));
32256893Sfenner	ninitiator = (ninitiator + 1) % MAXINITIATORS;
32356893Sfenner}
32456893Sfenner
32556893Sfenner#define cookie_isinitiator(x, y)	cookie_sidecheck((x), (y), 1)
32656893Sfenner#define cookie_isresponder(x, y)	cookie_sidecheck((x), (y), 0)
32756893Sfennerstatic int
32856893Sfennercookie_sidecheck(int i, const u_char *bp2, int initiator)
32956893Sfenner{
33056893Sfenner	struct sockaddr_storage ss;
33156893Sfenner	struct sockaddr *sa;
33256893Sfenner	struct ip *ip;
33356893Sfenner	struct sockaddr_in *sin;
33456893Sfenner#ifdef INET6
33556893Sfenner	struct ip6_hdr *ip6;
33656893Sfenner	struct sockaddr_in6 *sin6;
33756893Sfenner#endif
33856893Sfenner	int salen;
33956893Sfenner
34056893Sfenner	memset(&ss, 0, sizeof(ss));
34156893Sfenner	ip = (struct ip *)bp2;
34275115Sfenner	switch (IP_V(ip)) {
34356893Sfenner	case 4:
34456893Sfenner		sin = (struct sockaddr_in *)&ss;
34556893Sfenner#ifdef HAVE_SOCKADDR_SA_LEN
34656893Sfenner		sin->sin_len = sizeof(struct sockaddr_in);
34756893Sfenner#endif
34856893Sfenner		sin->sin_family = AF_INET;
34956893Sfenner		memcpy(&sin->sin_addr, &ip->ip_src, sizeof(ip->ip_src));
35056893Sfenner		break;
35156893Sfenner#ifdef INET6
35256893Sfenner	case 6:
35356893Sfenner		ip6 = (struct ip6_hdr *)bp2;
35456893Sfenner		sin6 = (struct sockaddr_in6 *)&ss;
35556893Sfenner#ifdef HAVE_SOCKADDR_SA_LEN
35656893Sfenner		sin6->sin6_len = sizeof(struct sockaddr_in6);
35756893Sfenner#endif
35856893Sfenner		sin6->sin6_family = AF_INET6;
35956893Sfenner		memcpy(&sin6->sin6_addr, &ip6->ip6_src, sizeof(ip6->ip6_src));
36056893Sfenner		break;
36156893Sfenner#endif
36256893Sfenner	default:
36356893Sfenner		return 0;
36456893Sfenner	}
36556893Sfenner
36656893Sfenner	sa = (struct sockaddr *)&ss;
36756893Sfenner	if (initiator) {
36856893Sfenner		if (sa->sa_family != ((struct sockaddr *)&cookiecache[i].iaddr)->sa_family)
36956893Sfenner			return 0;
37056893Sfenner#ifdef HAVE_SOCKADDR_SA_LEN
37156893Sfenner		salen = sa->sa_len;
37256893Sfenner#else
37356893Sfenner#ifdef INET6
37456893Sfenner		if (sa->sa_family == AF_INET6)
37556893Sfenner			salen = sizeof(struct sockaddr_in6);
37656893Sfenner		else
37756893Sfenner			salen = sizeof(struct sockaddr);
37856893Sfenner#else
37956893Sfenner		salen = sizeof(struct sockaddr);
38056893Sfenner#endif
38156893Sfenner#endif
38256893Sfenner		if (memcmp(&ss, &cookiecache[i].iaddr, salen) == 0)
38356893Sfenner			return 1;
38456893Sfenner	} else {
38556893Sfenner		if (sa->sa_family != ((struct sockaddr *)&cookiecache[i].raddr)->sa_family)
38656893Sfenner			return 0;
38756893Sfenner#ifdef HAVE_SOCKADDR_SA_LEN
38856893Sfenner		salen = sa->sa_len;
38956893Sfenner#else
39056893Sfenner#ifdef INET6
39156893Sfenner		if (sa->sa_family == AF_INET6)
39256893Sfenner			salen = sizeof(struct sockaddr_in6);
39356893Sfenner		else
39456893Sfenner			salen = sizeof(struct sockaddr);
39556893Sfenner#else
39656893Sfenner		salen = sizeof(struct sockaddr);
39756893Sfenner#endif
39856893Sfenner#endif
39956893Sfenner		if (memcmp(&ss, &cookiecache[i].raddr, salen) == 0)
40056893Sfenner			return 1;
40156893Sfenner	}
40256893Sfenner	return 0;
40356893Sfenner}
40456893Sfenner
405214478Srpaulostatic void
406214478Srpaulohexprint(netdissect_options *ndo, caddr_t loc, size_t len)
40756893Sfenner{
408214478Srpaulo	u_char *p;
409127668Sbms	size_t i;
41056893Sfenner
41156893Sfenner	p = (u_char *)loc;
41256893Sfenner	for (i = 0; i < len; i++)
413190207Srpaulo		ND_PRINT((ndo,"%02x", p[i] & 0xff));
414214478Srpaulo}
415214478Srpaulo
416214478Srpaulostatic int
417214478Srpaulorawprint(netdissect_options *ndo, caddr_t loc, size_t len)
418214478Srpaulo{
419214478Srpaulo	ND_TCHECK2(*loc, len);
420214478Srpaulo
421214478Srpaulo	hexprint(ndo, loc, len);
422127668Sbms	return 1;
423124488Sfennertrunc:
424127668Sbms	return 0;
42556893Sfenner}
42656893Sfenner
427214478Srpaulo
428190207Srpaulo/*
429190207Srpaulo * returns false if we run out of data buffer
430190207Srpaulo */
431190207Srpaulostatic int ike_show_somedata(struct netdissect_options *ndo,
432190207Srpaulo			     const u_char *cp, const u_char *ep)
433190207Srpaulo{
434190207Srpaulo	/* there is too much data, just show some of it */
435190207Srpaulo	const u_char *end = ep - 20;
436190207Srpaulo	int  elen = 20;
437190207Srpaulo	int   len = ep - cp;
438190207Srpaulo	if(len > 10) {
439190207Srpaulo		len = 10;
440190207Srpaulo	}
441190207Srpaulo
442190207Srpaulo	/* really shouldn't happen because of above */
443190207Srpaulo	if(end < cp + len) {
444190207Srpaulo		end = cp+len;
445190207Srpaulo		elen = ep - end;
446190207Srpaulo	}
447190207Srpaulo
448190207Srpaulo	ND_PRINT((ndo," data=("));
449190207Srpaulo	if(!rawprint(ndo, (caddr_t)(cp), len)) goto trunc;
450190207Srpaulo	ND_PRINT((ndo, "..."));
451190207Srpaulo	if(elen) {
452190207Srpaulo		if(!rawprint(ndo, (caddr_t)(end), elen)) goto trunc;
453190207Srpaulo	}
454190207Srpaulo	ND_PRINT((ndo,")"));
455190207Srpaulo	return 1;
456190207Srpaulo
457190207Srpaulotrunc:
458190207Srpaulo	return 0;
459190207Srpaulo}
460190207Srpaulo
46156893Sfennerstruct attrmap {
462127668Sbms	const char *type;
463127668Sbms	u_int nvalue;
464127668Sbms	const char *value[30];	/*XXX*/
46556893Sfenner};
46656893Sfenner
467127668Sbmsstatic const u_char *
468190207Srpauloikev1_attrmap_print(netdissect_options *ndo,
469190207Srpaulo		    const u_char *p, const u_char *ep,
470190207Srpaulo		    const struct attrmap *map, size_t nmap)
47156893Sfenner{
47275115Sfenner	u_int16_t *q;
47356893Sfenner	int totlen;
47456893Sfenner	u_int32_t t, v;
47556893Sfenner
47675115Sfenner	q = (u_int16_t *)p;
47756893Sfenner	if (p[0] & 0x80)
47856893Sfenner		totlen = 4;
47956893Sfenner	else
480127668Sbms		totlen = 4 + EXTRACT_16BITS(&q[1]);
48156893Sfenner	if (ep < p + totlen) {
482190207Srpaulo		ND_PRINT((ndo,"[|attr]"));
48356893Sfenner		return ep + 1;
48456893Sfenner	}
48556893Sfenner
486190207Srpaulo	ND_PRINT((ndo,"("));
487127668Sbms	t = EXTRACT_16BITS(&q[0]) & 0x7fff;
48856893Sfenner	if (map && t < nmap && map[t].type)
489190207Srpaulo		ND_PRINT((ndo,"type=%s ", map[t].type));
49056893Sfenner	else
491190207Srpaulo		ND_PRINT((ndo,"type=#%d ", t));
49256893Sfenner	if (p[0] & 0x80) {
493190207Srpaulo		ND_PRINT((ndo,"value="));
494127668Sbms		v = EXTRACT_16BITS(&q[1]);
49556893Sfenner		if (map && t < nmap && v < map[t].nvalue && map[t].value[v])
496190207Srpaulo			ND_PRINT((ndo,"%s", map[t].value[v]));
49756893Sfenner		else
498190207Srpaulo			rawprint(ndo, (caddr_t)&q[1], 2);
49956893Sfenner	} else {
500190207Srpaulo		ND_PRINT((ndo,"len=%d value=", EXTRACT_16BITS(&q[1])));
501190207Srpaulo		rawprint(ndo, (caddr_t)&p[4], EXTRACT_16BITS(&q[1]));
50256893Sfenner	}
503190207Srpaulo	ND_PRINT((ndo,")"));
50456893Sfenner	return p + totlen;
50556893Sfenner}
50656893Sfenner
507127668Sbmsstatic const u_char *
508190207Srpauloikev1_attr_print(netdissect_options *ndo, const u_char *p, const u_char *ep)
50956893Sfenner{
51075115Sfenner	u_int16_t *q;
51156893Sfenner	int totlen;
51256893Sfenner	u_int32_t t;
51356893Sfenner
51475115Sfenner	q = (u_int16_t *)p;
51556893Sfenner	if (p[0] & 0x80)
51656893Sfenner		totlen = 4;
51756893Sfenner	else
518127668Sbms		totlen = 4 + EXTRACT_16BITS(&q[1]);
51956893Sfenner	if (ep < p + totlen) {
520190207Srpaulo		ND_PRINT((ndo,"[|attr]"));
52156893Sfenner		return ep + 1;
52256893Sfenner	}
52356893Sfenner
524190207Srpaulo	ND_PRINT((ndo,"("));
525127668Sbms	t = EXTRACT_16BITS(&q[0]) & 0x7fff;
526190207Srpaulo	ND_PRINT((ndo,"type=#%d ", t));
52756893Sfenner	if (p[0] & 0x80) {
528190207Srpaulo		ND_PRINT((ndo,"value="));
52956893Sfenner		t = q[1];
530190207Srpaulo		rawprint(ndo, (caddr_t)&q[1], 2);
53156893Sfenner	} else {
532190207Srpaulo		ND_PRINT((ndo,"len=%d value=", EXTRACT_16BITS(&q[1])));
533190207Srpaulo		rawprint(ndo, (caddr_t)&p[2], EXTRACT_16BITS(&q[1]));
53456893Sfenner	}
535190207Srpaulo	ND_PRINT((ndo,")"));
53656893Sfenner	return p + totlen;
53756893Sfenner}
53856893Sfenner
539127668Sbmsstatic const u_char *
540190207Srpauloikev1_sa_print(netdissect_options *ndo, u_char tpay _U_,
541190207Srpaulo	       const struct isakmp_gen *ext,
542146773Ssam		u_int item_len _U_,
543146773Ssam		const u_char *ep, u_int32_t phase, u_int32_t doi0 _U_,
544146773Ssam		u_int32_t proto0, int depth)
54556893Sfenner{
546190207Srpaulo	const struct ikev1_pl_sa *p;
547190207Srpaulo	struct ikev1_pl_sa sa;
548127668Sbms	const u_int32_t *q;
54975115Sfenner	u_int32_t doi, sit, ident;
550127668Sbms	const u_char *cp, *np;
55156893Sfenner	int t;
55256893Sfenner
553190207Srpaulo	ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_SA)));
55456893Sfenner
555190207Srpaulo	p = (struct ikev1_pl_sa *)ext;
556190207Srpaulo	ND_TCHECK(*p);
55775115Sfenner	safememcpy(&sa, ext, sizeof(sa));
55875115Sfenner	doi = ntohl(sa.doi);
55975115Sfenner	sit = ntohl(sa.sit);
56056893Sfenner	if (doi != 1) {
561190207Srpaulo		ND_PRINT((ndo," doi=%d", doi));
562190207Srpaulo		ND_PRINT((ndo," situation=%u", (u_int32_t)ntohl(sa.sit)));
56356893Sfenner		return (u_char *)(p + 1);
56456893Sfenner	}
56556893Sfenner
566190207Srpaulo	ND_PRINT((ndo," doi=ipsec"));
56775115Sfenner	q = (u_int32_t *)&sa.sit;
568190207Srpaulo	ND_PRINT((ndo," situation="));
56956893Sfenner	t = 0;
57075115Sfenner	if (sit & 0x01) {
571190207Srpaulo		ND_PRINT((ndo,"identity"));
57256893Sfenner		t++;
57356893Sfenner	}
57475115Sfenner	if (sit & 0x02) {
575190207Srpaulo		ND_PRINT((ndo,"%ssecrecy", t ? "+" : ""));
57656893Sfenner		t++;
57756893Sfenner	}
57875115Sfenner	if (sit & 0x04)
579190207Srpaulo		ND_PRINT((ndo,"%sintegrity", t ? "+" : ""));
58056893Sfenner
58175115Sfenner	np = (u_char *)ext + sizeof(sa);
58275115Sfenner	if (sit != 0x01) {
583190207Srpaulo		ND_TCHECK2(*(ext + 1), sizeof(ident));
58475115Sfenner		safememcpy(&ident, ext + 1, sizeof(ident));
585190207Srpaulo		ND_PRINT((ndo," ident=%u", (u_int32_t)ntohl(ident)));
58675115Sfenner		np += sizeof(ident);
58775115Sfenner	}
58856893Sfenner
58975115Sfenner	ext = (struct isakmp_gen *)np;
590190207Srpaulo	ND_TCHECK(*ext);
59156893Sfenner
592190207Srpaulo	cp = ikev1_sub_print(ndo, ISAKMP_NPTYPE_P, ext, ep, phase, doi, proto0,
593127668Sbms		depth);
59456893Sfenner
59556893Sfenner	return cp;
596127668Sbmstrunc:
597190207Srpaulo	ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_SA)));
598127668Sbms	return NULL;
59956893Sfenner}
60056893Sfenner
601127668Sbmsstatic const u_char *
602190207Srpauloikev1_p_print(netdissect_options *ndo, u_char tpay _U_,
603190207Srpaulo	      const struct isakmp_gen *ext, u_int item_len _U_,
604146773Ssam	       const u_char *ep, u_int32_t phase, u_int32_t doi0,
605146773Ssam	       u_int32_t proto0 _U_, int depth)
60656893Sfenner{
607190207Srpaulo	const struct ikev1_pl_p *p;
608190207Srpaulo	struct ikev1_pl_p prop;
609127668Sbms	const u_char *cp;
61056893Sfenner
611190207Srpaulo	ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_P)));
61256893Sfenner
613190207Srpaulo	p = (struct ikev1_pl_p *)ext;
614190207Srpaulo	ND_TCHECK(*p);
61575115Sfenner	safememcpy(&prop, ext, sizeof(prop));
616190207Srpaulo	ND_PRINT((ndo," #%d protoid=%s transform=%d",
617190207Srpaulo		  prop.p_no, PROTOIDSTR(prop.prot_id), prop.num_t));
61875115Sfenner	if (prop.spi_size) {
619190207Srpaulo		ND_PRINT((ndo," spi="));
620190207Srpaulo		if (!rawprint(ndo, (caddr_t)(p + 1), prop.spi_size))
621127668Sbms			goto trunc;
62256893Sfenner	}
62356893Sfenner
62475115Sfenner	ext = (struct isakmp_gen *)((u_char *)(p + 1) + prop.spi_size);
625190207Srpaulo	ND_TCHECK(*ext);
626190207Srpaulo
627190207Srpaulo	cp = ikev1_sub_print(ndo, ISAKMP_NPTYPE_T, ext, ep, phase, doi0,
628190207Srpaulo			     prop.prot_id, depth);
629190207Srpaulo
63056893Sfenner	return cp;
631127668Sbmstrunc:
632190207Srpaulo	ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_P)));
633127668Sbms	return NULL;
63456893Sfenner}
63556893Sfenner
636190207Srpaulostatic const char *ikev1_p_map[] = {
63756893Sfenner	NULL, "ike",
63856893Sfenner};
63956893Sfenner
640190207Srpaulostatic const char *ikev2_t_type_map[]={
641190207Srpaulo	NULL, "encr", "prf", "integ", "dh", "esn"
642190207Srpaulo};
643190207Srpaulo
644127668Sbmsstatic const char *ah_p_map[] = {
64575115Sfenner	NULL, "(reserved)", "md5", "sha", "1des",
64675115Sfenner	"sha2-256", "sha2-384", "sha2-512",
64756893Sfenner};
64856893Sfenner
649190207Srpaulostatic const char *prf_p_map[] = {
650190207Srpaulo	NULL, "hmac-md5", "hmac-sha", "hmac-tiger",
651190207Srpaulo	"aes128_xcbc"
652190207Srpaulo};
653190207Srpaulo
654190207Srpaulostatic const char *integ_p_map[] = {
655190207Srpaulo	NULL, "hmac-md5", "hmac-sha", "dec-mac",
656190207Srpaulo	"kpdk-md5", "aes-xcbc"
657190207Srpaulo};
658190207Srpaulo
659190207Srpaulostatic const char *esn_p_map[] = {
660190207Srpaulo	"no-esn", "esn"
661190207Srpaulo};
662190207Srpaulo
663190207Srpaulostatic const char *dh_p_map[] = {
664190207Srpaulo	NULL, "modp768",
665190207Srpaulo	"modp1024",    /* group 2 */
666190207Srpaulo	"EC2N 2^155",  /* group 3 */
667190207Srpaulo	"EC2N 2^185",  /* group 4 */
668190207Srpaulo	"modp1536",    /* group 5 */
669190207Srpaulo	"iana-grp06", "iana-grp07", /* reserved */
670190207Srpaulo	"iana-grp08", "iana-grp09",
671190207Srpaulo	"iana-grp10", "iana-grp11",
672190207Srpaulo	"iana-grp12", "iana-grp13",
673190207Srpaulo	"modp2048",    /* group 14 */
674190207Srpaulo	"modp3072",    /* group 15 */
675190207Srpaulo	"modp4096",    /* group 16 */
676190207Srpaulo	"modp6144",    /* group 17 */
677190207Srpaulo	"modp8192",    /* group 18 */
678190207Srpaulo};
679190207Srpaulo
680127668Sbmsstatic const char *esp_p_map[] = {
68156893Sfenner	NULL, "1des-iv64", "1des", "3des", "rc5", "idea", "cast",
68275115Sfenner	"blowfish", "3idea", "1des-iv32", "rc4", "null", "aes"
68356893Sfenner};
68456893Sfenner
685127668Sbmsstatic const char *ipcomp_p_map[] = {
68656893Sfenner	NULL, "oui", "deflate", "lzs",
68756893Sfenner};
68856893Sfenner
689127668Sbmsconst struct attrmap ipsec_t_map[] = {
690127668Sbms	{ NULL,	0, { NULL } },
69156893Sfenner	{ "lifetype", 3, { NULL, "sec", "kb", }, },
692127668Sbms	{ "life", 0, { NULL } },
693190207Srpaulo	{ "group desc", 18,	{ NULL, "modp768",
694190207Srpaulo				  "modp1024",    /* group 2 */
695190207Srpaulo				  "EC2N 2^155",  /* group 3 */
696190207Srpaulo				  "EC2N 2^185",  /* group 4 */
697190207Srpaulo				  "modp1536",    /* group 5 */
698190207Srpaulo				  "iana-grp06", "iana-grp07", /* reserved */
699190207Srpaulo				  "iana-grp08", "iana-grp09",
700190207Srpaulo				  "iana-grp10", "iana-grp11",
701190207Srpaulo				  "iana-grp12", "iana-grp13",
702190207Srpaulo				  "modp2048",    /* group 14 */
703190207Srpaulo				  "modp3072",    /* group 15 */
704190207Srpaulo				  "modp4096",    /* group 16 */
705190207Srpaulo				  "modp6144",    /* group 17 */
706190207Srpaulo				  "modp8192",    /* group 18 */
707190207Srpaulo		}, },
70856893Sfenner	{ "enc mode", 3, { NULL, "tunnel", "transport", }, },
70956893Sfenner	{ "auth", 5, { NULL, "hmac-md5", "hmac-sha1", "1des-mac", "keyed", }, },
710127668Sbms	{ "keylen", 0, { NULL } },
711127668Sbms	{ "rounds", 0, { NULL } },
712127668Sbms	{ "dictsize", 0, { NULL } },
713127668Sbms	{ "privalg", 0, { NULL } },
71456893Sfenner};
71556893Sfenner
716190207Srpauloconst struct attrmap encr_t_map[] = {
717190207Srpaulo	{ NULL,	0, { NULL } }, 	{ NULL,	0, { NULL } },  /* 0, 1 */
718190207Srpaulo	{ NULL,	0, { NULL } },	{ NULL,	0, { NULL } },  /* 2, 3 */
719190207Srpaulo	{ NULL,	0, { NULL } },	{ NULL,	0, { NULL } },  /* 4, 5 */
720190207Srpaulo	{ NULL,	0, { NULL } },	{ NULL,	0, { NULL } },  /* 6, 7 */
721190207Srpaulo	{ NULL,	0, { NULL } },	{ NULL,	0, { NULL } },  /* 8, 9 */
722190207Srpaulo	{ NULL,	0, { NULL } },	{ NULL,	0, { NULL } },  /* 10,11*/
723190207Srpaulo	{ NULL,	0, { NULL } },	{ NULL,	0, { NULL } },  /* 12,13*/
724190207Srpaulo	{ "keylen", 14, { NULL }},
725190207Srpaulo};
726190207Srpaulo
727127668Sbmsconst struct attrmap oakley_t_map[] = {
728127668Sbms	{ NULL,	0, { NULL } },
72975115Sfenner	{ "enc", 8,	{ NULL, "1des", "idea", "blowfish", "rc5",
73075115Sfenner		 	  "3des", "cast", "aes", }, },
73175115Sfenner	{ "hash", 7,	{ NULL, "md5", "sha1", "tiger",
73275115Sfenner			  "sha2-256", "sha2-384", "sha2-512", }, },
73356893Sfenner	{ "auth", 6,	{ NULL, "preshared", "dss", "rsa sig", "rsa enc",
73456893Sfenner			  "rsa enc revised", }, },
735190207Srpaulo	{ "group desc", 18,	{ NULL, "modp768",
736190207Srpaulo				  "modp1024",    /* group 2 */
737190207Srpaulo				  "EC2N 2^155",  /* group 3 */
738190207Srpaulo				  "EC2N 2^185",  /* group 4 */
739190207Srpaulo				  "modp1536",    /* group 5 */
740190207Srpaulo				  "iana-grp06", "iana-grp07", /* reserved */
741190207Srpaulo				  "iana-grp08", "iana-grp09",
742190207Srpaulo				  "iana-grp10", "iana-grp11",
743190207Srpaulo				  "iana-grp12", "iana-grp13",
744190207Srpaulo				  "modp2048",    /* group 14 */
745190207Srpaulo				  "modp3072",    /* group 15 */
746190207Srpaulo				  "modp4096",    /* group 16 */
747190207Srpaulo				  "modp6144",    /* group 17 */
748190207Srpaulo				  "modp8192",    /* group 18 */
749190207Srpaulo		}, },
75056893Sfenner	{ "group type", 4,	{ NULL, "MODP", "ECP", "EC2N", }, },
751127668Sbms	{ "group prime", 0, { NULL } },
752127668Sbms	{ "group gen1", 0, { NULL } },
753127668Sbms	{ "group gen2", 0, { NULL } },
754127668Sbms	{ "group curve A", 0, { NULL } },
755127668Sbms	{ "group curve B", 0, { NULL } },
75656893Sfenner	{ "lifetype", 3,	{ NULL, "sec", "kb", }, },
757127668Sbms	{ "lifeduration", 0, { NULL } },
758127668Sbms	{ "prf", 0, { NULL } },
759127668Sbms	{ "keylen", 0, { NULL } },
760127668Sbms	{ "field", 0, { NULL } },
761127668Sbms	{ "order", 0, { NULL } },
76256893Sfenner};
76356893Sfenner
764127668Sbmsstatic const u_char *
765190207Srpauloikev1_t_print(netdissect_options *ndo, u_char tpay _U_,
766190207Srpaulo	      const struct isakmp_gen *ext, u_int item_len,
767190207Srpaulo	      const u_char *ep, u_int32_t phase _U_, u_int32_t doi _U_,
768190207Srpaulo	      u_int32_t proto, int depth _U_)
76956893Sfenner{
770190207Srpaulo	const struct ikev1_pl_t *p;
771190207Srpaulo	struct ikev1_pl_t t;
772127668Sbms	const u_char *cp;
773127668Sbms	const char *idstr;
774127668Sbms	const struct attrmap *map;
77556893Sfenner	size_t nmap;
776127668Sbms	const u_char *ep2;
77756893Sfenner
778190207Srpaulo	ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_T)));
77956893Sfenner
780190207Srpaulo	p = (struct ikev1_pl_t *)ext;
781190207Srpaulo	ND_TCHECK(*p);
78275115Sfenner	safememcpy(&t, ext, sizeof(t));
78356893Sfenner
78456893Sfenner	switch (proto) {
78556893Sfenner	case 1:
786190207Srpaulo		idstr = STR_OR_ID(t.t_id, ikev1_p_map);
78756893Sfenner		map = oakley_t_map;
78856893Sfenner		nmap = sizeof(oakley_t_map)/sizeof(oakley_t_map[0]);
78956893Sfenner		break;
79056893Sfenner	case 2:
79175115Sfenner		idstr = STR_OR_ID(t.t_id, ah_p_map);
79256893Sfenner		map = ipsec_t_map;
79356893Sfenner		nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
79456893Sfenner		break;
79556893Sfenner	case 3:
79675115Sfenner		idstr = STR_OR_ID(t.t_id, esp_p_map);
79756893Sfenner		map = ipsec_t_map;
79856893Sfenner		nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
79956893Sfenner		break;
80056893Sfenner	case 4:
80175115Sfenner		idstr = STR_OR_ID(t.t_id, ipcomp_p_map);
80256893Sfenner		map = ipsec_t_map;
80356893Sfenner		nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
80456893Sfenner		break;
80556893Sfenner	default:
80656893Sfenner		idstr = NULL;
80756893Sfenner		map = NULL;
80856893Sfenner		nmap = 0;
80956893Sfenner		break;
81056893Sfenner	}
81156893Sfenner
81256893Sfenner	if (idstr)
813190207Srpaulo		ND_PRINT((ndo," #%d id=%s ", t.t_no, idstr));
81456893Sfenner	else
815190207Srpaulo		ND_PRINT((ndo," #%d id=%d ", t.t_no, t.t_id));
81656893Sfenner	cp = (u_char *)(p + 1);
817127668Sbms	ep2 = (u_char *)p + item_len;
81856893Sfenner	while (cp < ep && cp < ep2) {
81956893Sfenner		if (map && nmap) {
820190207Srpaulo			cp = ikev1_attrmap_print(ndo, cp, (ep < ep2) ? ep : ep2,
82156893Sfenner				map, nmap);
82256893Sfenner		} else
823190207Srpaulo			cp = ikev1_attr_print(ndo, cp, (ep < ep2) ? ep : ep2);
82456893Sfenner	}
82556893Sfenner	if (ep < ep2)
826190207Srpaulo		ND_PRINT((ndo,"..."));
82756893Sfenner	return cp;
828127668Sbmstrunc:
829190207Srpaulo	ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_T)));
830127668Sbms	return NULL;
83156893Sfenner}
83256893Sfenner
833127668Sbmsstatic const u_char *
834190207Srpauloikev1_ke_print(netdissect_options *ndo, u_char tpay _U_,
835190207Srpaulo	       const struct isakmp_gen *ext, u_int item_len _U_,
836190207Srpaulo	       const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi _U_,
837190207Srpaulo	       u_int32_t proto _U_, int depth _U_)
83856893Sfenner{
83975115Sfenner	struct isakmp_gen e;
84075115Sfenner
841190207Srpaulo	ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_KE)));
84256893Sfenner
843190207Srpaulo	ND_TCHECK(*ext);
84475115Sfenner	safememcpy(&e, ext, sizeof(e));
845190207Srpaulo	ND_PRINT((ndo," key len=%d", ntohs(e.len) - 4));
846190207Srpaulo	if (2 < ndo->ndo_vflag && 4 < ntohs(e.len)) {
847190207Srpaulo		ND_PRINT((ndo," "));
848190207Srpaulo		if (!rawprint(ndo, (caddr_t)(ext + 1), ntohs(e.len) - 4))
849127668Sbms			goto trunc;
85056893Sfenner	}
85175115Sfenner	return (u_char *)ext + ntohs(e.len);
852127668Sbmstrunc:
853190207Srpaulo	ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_KE)));
854127668Sbms	return NULL;
85556893Sfenner}
85656893Sfenner
857127668Sbmsstatic const u_char *
858190207Srpauloikev1_id_print(netdissect_options *ndo, u_char tpay _U_,
859190207Srpaulo	       const struct isakmp_gen *ext, u_int item_len _U_,
860190207Srpaulo	       const u_char *ep _U_, u_int32_t phase, u_int32_t doi _U_,
861190207Srpaulo	       u_int32_t proto _U_, int depth _U_)
86256893Sfenner{
86356893Sfenner#define USE_IPSECDOI_IN_PHASE1	1
864190207Srpaulo	const struct ikev1_pl_id *p;
865190207Srpaulo	struct ikev1_pl_id id;
866127668Sbms	static const char *idtypestr[] = {
86756893Sfenner		"IPv4", "IPv4net", "IPv6", "IPv6net",
86856893Sfenner	};
869127668Sbms	static const char *ipsecidtypestr[] = {
87056893Sfenner		NULL, "IPv4", "FQDN", "user FQDN", "IPv4net", "IPv6",
87156893Sfenner		"IPv6net", "IPv4range", "IPv6range", "ASN1 DN", "ASN1 GN",
87256893Sfenner		"keyid",
87356893Sfenner	};
87456893Sfenner	int len;
875127668Sbms	const u_char *data;
87656893Sfenner
877190207Srpaulo	ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_ID)));
87856893Sfenner
879190207Srpaulo	p = (struct ikev1_pl_id *)ext;
880190207Srpaulo	ND_TCHECK(*p);
88175115Sfenner	safememcpy(&id, ext, sizeof(id));
882127668Sbms	if (sizeof(*p) < item_len) {
88356893Sfenner		data = (u_char *)(p + 1);
884127668Sbms		len = item_len - sizeof(*p);
885127668Sbms	} else {
88656893Sfenner		data = NULL;
887127668Sbms		len = 0;
888127668Sbms	}
88956893Sfenner
89056893Sfenner#if 0 /*debug*/
891190207Srpaulo	ND_PRINT((ndo," [phase=%d doi=%d proto=%d]", phase, doi, proto));
89256893Sfenner#endif
89356893Sfenner	switch (phase) {
89456893Sfenner#ifndef USE_IPSECDOI_IN_PHASE1
89556893Sfenner	case 1:
89656893Sfenner#endif
89756893Sfenner	default:
898190207Srpaulo		ND_PRINT((ndo," idtype=%s", STR_OR_ID(id.d.id_type, idtypestr)));
899190207Srpaulo		ND_PRINT((ndo," doi_data=%u",
900190207Srpaulo			  (u_int32_t)(ntohl(id.d.doi_data) & 0xffffff)));
90156893Sfenner		break;
90256893Sfenner
90356893Sfenner#ifdef USE_IPSECDOI_IN_PHASE1
90456893Sfenner	case 1:
90556893Sfenner#endif
90656893Sfenner	case 2:
90756893Sfenner	    {
908127668Sbms		const struct ipsecdoi_id *p;
909127668Sbms		struct ipsecdoi_id id;
91056893Sfenner		struct protoent *pe;
91156893Sfenner
91256893Sfenner		p = (struct ipsecdoi_id *)ext;
913190207Srpaulo		ND_TCHECK(*p);
91475115Sfenner		safememcpy(&id, ext, sizeof(id));
915190207Srpaulo		ND_PRINT((ndo," idtype=%s", STR_OR_ID(id.type, ipsecidtypestr)));
91675115Sfenner		if (id.proto_id) {
917127668Sbms#ifndef WIN32
91875115Sfenner			setprotoent(1);
919127668Sbms#endif /* WIN32 */
92075115Sfenner			pe = getprotobynumber(id.proto_id);
92175115Sfenner			if (pe)
922190207Srpaulo				ND_PRINT((ndo," protoid=%s", pe->p_name));
923127668Sbms#ifndef WIN32
92475115Sfenner			endprotoent();
925127668Sbms#endif /* WIN32 */
92675115Sfenner		} else {
92775115Sfenner			/* it DOES NOT mean IPPROTO_IP! */
928190207Srpaulo			ND_PRINT((ndo," protoid=%s", "0"));
92975115Sfenner		}
930190207Srpaulo		ND_PRINT((ndo," port=%d", ntohs(id.port)));
93156893Sfenner		if (!len)
93256893Sfenner			break;
933127668Sbms		if (data == NULL)
934127668Sbms			goto trunc;
935190207Srpaulo		ND_TCHECK2(*data, len);
93675115Sfenner		switch (id.type) {
93756893Sfenner		case IPSECDOI_ID_IPV4_ADDR:
938127668Sbms			if (len < 4)
939190207Srpaulo				ND_PRINT((ndo," len=%d [bad: < 4]", len));
940127668Sbms			else
941190207Srpaulo				ND_PRINT((ndo," len=%d %s", len, ipaddr_string(data)));
94256893Sfenner			len = 0;
94356893Sfenner			break;
94456893Sfenner		case IPSECDOI_ID_FQDN:
94556893Sfenner		case IPSECDOI_ID_USER_FQDN:
94656893Sfenner		    {
94756893Sfenner			int i;
948190207Srpaulo			ND_PRINT((ndo," len=%d ", len));
94998524Sfenner			for (i = 0; i < len; i++)
95098524Sfenner				safeputchar(data[i]);
95156893Sfenner			len = 0;
95256893Sfenner			break;
95356893Sfenner		    }
95456893Sfenner		case IPSECDOI_ID_IPV4_ADDR_SUBNET:
95556893Sfenner		    {
956127668Sbms			const u_char *mask;
957127668Sbms			if (len < 8)
958190207Srpaulo				ND_PRINT((ndo," len=%d [bad: < 8]", len));
959127668Sbms			else {
960127668Sbms				mask = data + sizeof(struct in_addr);
961190207Srpaulo				ND_PRINT((ndo," len=%d %s/%u.%u.%u.%u", len,
962190207Srpaulo					  ipaddr_string(data),
963190207Srpaulo					  mask[0], mask[1], mask[2], mask[3]));
964127668Sbms			}
96556893Sfenner			len = 0;
96656893Sfenner			break;
96756893Sfenner		    }
96856893Sfenner#ifdef INET6
96956893Sfenner		case IPSECDOI_ID_IPV6_ADDR:
970127668Sbms			if (len < 16)
971190207Srpaulo				ND_PRINT((ndo," len=%d [bad: < 16]", len));
972127668Sbms			else
973190207Srpaulo				ND_PRINT((ndo," len=%d %s", len, ip6addr_string(data)));
97456893Sfenner			len = 0;
97556893Sfenner			break;
97656893Sfenner		case IPSECDOI_ID_IPV6_ADDR_SUBNET:
97756893Sfenner		    {
978127668Sbms			const u_int32_t *mask;
979127668Sbms			if (len < 20)
980190207Srpaulo				ND_PRINT((ndo," len=%d [bad: < 20]", len));
981127668Sbms			else {
982127668Sbms				mask = (u_int32_t *)(data + sizeof(struct in6_addr));
983127668Sbms				/*XXX*/
984190207Srpaulo				ND_PRINT((ndo," len=%d %s/0x%08x%08x%08x%08x", len,
985190207Srpaulo					  ip6addr_string(data),
986190207Srpaulo					  mask[0], mask[1], mask[2], mask[3]));
987127668Sbms			}
98856893Sfenner			len = 0;
98956893Sfenner			break;
99056893Sfenner		    }
99156893Sfenner#endif /*INET6*/
99256893Sfenner		case IPSECDOI_ID_IPV4_ADDR_RANGE:
993127668Sbms			if (len < 8)
994190207Srpaulo				ND_PRINT((ndo," len=%d [bad: < 8]", len));
995127668Sbms			else {
996190207Srpaulo				ND_PRINT((ndo," len=%d %s-%s", len,
997190207Srpaulo					  ipaddr_string(data),
998190207Srpaulo					  ipaddr_string(data + sizeof(struct in_addr))));
999127668Sbms			}
100056893Sfenner			len = 0;
100156893Sfenner			break;
100256893Sfenner#ifdef INET6
100356893Sfenner		case IPSECDOI_ID_IPV6_ADDR_RANGE:
1004127668Sbms			if (len < 32)
1005190207Srpaulo				ND_PRINT((ndo," len=%d [bad: < 32]", len));
1006127668Sbms			else {
1007190207Srpaulo				ND_PRINT((ndo," len=%d %s-%s", len,
1008190207Srpaulo					  ip6addr_string(data),
1009190207Srpaulo					  ip6addr_string(data + sizeof(struct in6_addr))));
1010127668Sbms			}
101156893Sfenner			len = 0;
101256893Sfenner			break;
101356893Sfenner#endif /*INET6*/
101456893Sfenner		case IPSECDOI_ID_DER_ASN1_DN:
101556893Sfenner		case IPSECDOI_ID_DER_ASN1_GN:
101656893Sfenner		case IPSECDOI_ID_KEY_ID:
101756893Sfenner			break;
101856893Sfenner		}
101956893Sfenner		break;
102056893Sfenner	    }
102156893Sfenner	}
102256893Sfenner	if (data && len) {
1023190207Srpaulo		ND_PRINT((ndo," len=%d", len));
1024190207Srpaulo		if (2 < ndo->ndo_vflag) {
1025190207Srpaulo			ND_PRINT((ndo," "));
1026190207Srpaulo			if (!rawprint(ndo, (caddr_t)data, len))
1027127668Sbms				goto trunc;
102856893Sfenner		}
102956893Sfenner	}
1030127668Sbms	return (u_char *)ext + item_len;
1031127668Sbmstrunc:
1032190207Srpaulo	ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_ID)));
1033127668Sbms	return NULL;
103456893Sfenner}
103556893Sfenner
1036127668Sbmsstatic const u_char *
1037190207Srpauloikev1_cert_print(netdissect_options *ndo, u_char tpay _U_,
1038190207Srpaulo		 const struct isakmp_gen *ext, u_int item_len _U_,
1039190207Srpaulo		 const u_char *ep _U_, u_int32_t phase _U_,
1040190207Srpaulo		 u_int32_t doi0 _U_,
1041190207Srpaulo		 u_int32_t proto0 _U_, int depth _U_)
104275115Sfenner{
1043190207Srpaulo	const struct ikev1_pl_cert *p;
1044190207Srpaulo	struct ikev1_pl_cert cert;
1045127668Sbms	static const char *certstr[] = {
104675115Sfenner		"none",	"pkcs7", "pgp", "dns",
104775115Sfenner		"x509sign", "x509ke", "kerberos", "crl",
104875115Sfenner		"arl", "spki", "x509attr",
104975115Sfenner	};
105075115Sfenner
1051190207Srpaulo	ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_CERT)));
105275115Sfenner
1053190207Srpaulo	p = (struct ikev1_pl_cert *)ext;
1054190207Srpaulo	ND_TCHECK(*p);
105575115Sfenner	safememcpy(&cert, ext, sizeof(cert));
1056190207Srpaulo	ND_PRINT((ndo," len=%d", item_len - 4));
1057190207Srpaulo	ND_PRINT((ndo," type=%s", STR_OR_ID((cert.encode), certstr)));
1058190207Srpaulo	if (2 < ndo->ndo_vflag && 4 < item_len) {
1059190207Srpaulo		ND_PRINT((ndo," "));
1060190207Srpaulo		if (!rawprint(ndo, (caddr_t)(ext + 1), item_len - 4))
1061127668Sbms			goto trunc;
106275115Sfenner	}
1063127668Sbms	return (u_char *)ext + item_len;
1064127668Sbmstrunc:
1065190207Srpaulo	ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_CERT)));
1066127668Sbms	return NULL;
106775115Sfenner}
106875115Sfenner
1069127668Sbmsstatic const u_char *
1070190207Srpauloikev1_cr_print(netdissect_options *ndo, u_char tpay _U_,
1071190207Srpaulo	       const struct isakmp_gen *ext, u_int item_len _U_,
1072190207Srpaulo	       const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi0 _U_,
1073190207Srpaulo	       u_int32_t proto0 _U_, int depth _U_)
107475115Sfenner{
1075190207Srpaulo	const struct ikev1_pl_cert *p;
1076190207Srpaulo	struct ikev1_pl_cert cert;
1077127668Sbms	static const char *certstr[] = {
107875115Sfenner		"none",	"pkcs7", "pgp", "dns",
107975115Sfenner		"x509sign", "x509ke", "kerberos", "crl",
108075115Sfenner		"arl", "spki", "x509attr",
108175115Sfenner	};
108275115Sfenner
1083190207Srpaulo	ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_CR)));
108475115Sfenner
1085190207Srpaulo	p = (struct ikev1_pl_cert *)ext;
1086190207Srpaulo	ND_TCHECK(*p);
108775115Sfenner	safememcpy(&cert, ext, sizeof(cert));
1088190207Srpaulo	ND_PRINT((ndo," len=%d", item_len - 4));
1089190207Srpaulo	ND_PRINT((ndo," type=%s", STR_OR_ID((cert.encode), certstr)));
1090190207Srpaulo	if (2 < ndo->ndo_vflag && 4 < item_len) {
1091190207Srpaulo		ND_PRINT((ndo," "));
1092190207Srpaulo		if (!rawprint(ndo, (caddr_t)(ext + 1), item_len - 4))
1093127668Sbms			goto trunc;
109475115Sfenner	}
1095127668Sbms	return (u_char *)ext + item_len;
1096127668Sbmstrunc:
1097190207Srpaulo	ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_CR)));
1098127668Sbms	return NULL;
109975115Sfenner}
110075115Sfenner
1101127668Sbmsstatic const u_char *
1102190207Srpauloikev1_hash_print(netdissect_options *ndo, u_char tpay _U_,
1103190207Srpaulo		 const struct isakmp_gen *ext, u_int item_len _U_,
1104190207Srpaulo		 const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi _U_,
1105190207Srpaulo		 u_int32_t proto _U_, int depth _U_)
110656893Sfenner{
110775115Sfenner	struct isakmp_gen e;
110875115Sfenner
1109190207Srpaulo	ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_HASH)));
111056893Sfenner
1111190207Srpaulo	ND_TCHECK(*ext);
111275115Sfenner	safememcpy(&e, ext, sizeof(e));
1113190207Srpaulo	ND_PRINT((ndo," len=%d", ntohs(e.len) - 4));
1114190207Srpaulo	if (2 < ndo->ndo_vflag && 4 < ntohs(e.len)) {
1115190207Srpaulo		ND_PRINT((ndo," "));
1116190207Srpaulo		if (!rawprint(ndo, (caddr_t)(ext + 1), ntohs(e.len) - 4))
1117127668Sbms			goto trunc;
111856893Sfenner	}
111975115Sfenner	return (u_char *)ext + ntohs(e.len);
1120127668Sbmstrunc:
1121190207Srpaulo	ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_HASH)));
1122127668Sbms	return NULL;
112356893Sfenner}
112456893Sfenner
1125127668Sbmsstatic const u_char *
1126190207Srpauloikev1_sig_print(netdissect_options *ndo, u_char tpay _U_,
1127190207Srpaulo		const struct isakmp_gen *ext, u_int item_len _U_,
1128190207Srpaulo		const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi _U_,
1129190207Srpaulo		u_int32_t proto _U_, int depth _U_)
113075115Sfenner{
113175115Sfenner	struct isakmp_gen e;
113275115Sfenner
1133190207Srpaulo	ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_SIG)));
113475115Sfenner
1135190207Srpaulo	ND_TCHECK(*ext);
113675115Sfenner	safememcpy(&e, ext, sizeof(e));
1137190207Srpaulo	ND_PRINT((ndo," len=%d", ntohs(e.len) - 4));
1138190207Srpaulo	if (2 < ndo->ndo_vflag && 4 < ntohs(e.len)) {
1139190207Srpaulo		ND_PRINT((ndo," "));
1140190207Srpaulo		if (!rawprint(ndo, (caddr_t)(ext + 1), ntohs(e.len) - 4))
1141127668Sbms			goto trunc;
114275115Sfenner	}
114375115Sfenner	return (u_char *)ext + ntohs(e.len);
1144127668Sbmstrunc:
1145190207Srpaulo	ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_SIG)));
1146127668Sbms	return NULL;
114775115Sfenner}
114875115Sfenner
1149127668Sbmsstatic const u_char *
1150190207Srpauloikev1_nonce_print(netdissect_options *ndo, u_char tpay _U_,
1151190207Srpaulo		  const struct isakmp_gen *ext,
1152190207Srpaulo		  u_int item_len _U_,
1153190207Srpaulo		  const u_char *ep _U_,
1154190207Srpaulo		  u_int32_t phase _U_, u_int32_t doi _U_,
1155190207Srpaulo		  u_int32_t proto _U_, int depth _U_)
115656893Sfenner{
115775115Sfenner	struct isakmp_gen e;
115875115Sfenner
1159190207Srpaulo	ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_NONCE)));
116056893Sfenner
1161190207Srpaulo	ND_TCHECK(*ext);
116275115Sfenner	safememcpy(&e, ext, sizeof(e));
1163190207Srpaulo	ND_PRINT((ndo," n len=%d", ntohs(e.len) - 4));
1164190207Srpaulo	if (2 < ndo->ndo_vflag && 4 < ntohs(e.len)) {
1165190207Srpaulo		ND_PRINT((ndo," "));
1166190207Srpaulo		if (!rawprint(ndo, (caddr_t)(ext + 1), ntohs(e.len) - 4))
1167127668Sbms			goto trunc;
1168190207Srpaulo	} else if (1 < ndo->ndo_vflag && 4 < ntohs(e.len)) {
1169190207Srpaulo		ND_PRINT((ndo," "));
1170190207Srpaulo		if (!ike_show_somedata(ndo, (u_char *)(caddr_t)(ext + 1), ep))
1171190207Srpaulo			goto trunc;
117256893Sfenner	}
117375115Sfenner	return (u_char *)ext + ntohs(e.len);
1174127668Sbmstrunc:
1175190207Srpaulo	ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_NONCE)));
1176127668Sbms	return NULL;
117756893Sfenner}
117856893Sfenner
1179127668Sbmsstatic const u_char *
1180190207Srpauloikev1_n_print(netdissect_options *ndo, u_char tpay _U_,
1181190207Srpaulo	      const struct isakmp_gen *ext, u_int item_len,
1182190207Srpaulo	      const u_char *ep, u_int32_t phase, u_int32_t doi0 _U_,
1183190207Srpaulo	      u_int32_t proto0 _U_, int depth)
118456893Sfenner{
1185190207Srpaulo	struct ikev1_pl_n *p, n;
1186127668Sbms	const u_char *cp;
118756893Sfenner	u_char *ep2;
118856893Sfenner	u_int32_t doi;
118956893Sfenner	u_int32_t proto;
1190127668Sbms	static const char *notify_error_str[] = {
119156893Sfenner		NULL,				"INVALID-PAYLOAD-TYPE",
119256893Sfenner		"DOI-NOT-SUPPORTED",		"SITUATION-NOT-SUPPORTED",
119356893Sfenner		"INVALID-COOKIE",		"INVALID-MAJOR-VERSION",
119456893Sfenner		"INVALID-MINOR-VERSION",	"INVALID-EXCHANGE-TYPE",
119556893Sfenner		"INVALID-FLAGS",		"INVALID-MESSAGE-ID",
119656893Sfenner		"INVALID-PROTOCOL-ID",		"INVALID-SPI",
119756893Sfenner		"INVALID-TRANSFORM-ID",		"ATTRIBUTES-NOT-SUPPORTED",
119856893Sfenner		"NO-PROPOSAL-CHOSEN",		"BAD-PROPOSAL-SYNTAX",
119956893Sfenner		"PAYLOAD-MALFORMED",		"INVALID-KEY-INFORMATION",
120056893Sfenner		"INVALID-ID-INFORMATION",	"INVALID-CERT-ENCODING",
120156893Sfenner		"INVALID-CERTIFICATE",		"CERT-TYPE-UNSUPPORTED",
120256893Sfenner		"INVALID-CERT-AUTHORITY",	"INVALID-HASH-INFORMATION",
120356893Sfenner		"AUTHENTICATION-FAILED",	"INVALID-SIGNATURE",
120456893Sfenner		"ADDRESS-NOTIFICATION",		"NOTIFY-SA-LIFETIME",
120556893Sfenner		"CERTIFICATE-UNAVAILABLE",	"UNSUPPORTED-EXCHANGE-TYPE",
120656893Sfenner		"UNEQUAL-PAYLOAD-LENGTHS",
120756893Sfenner	};
1208127668Sbms	static const char *ipsec_notify_error_str[] = {
1209127668Sbms		"RESERVED",
1210127668Sbms	};
1211127668Sbms	static const char *notify_status_str[] = {
1212127668Sbms		"CONNECTED",
1213127668Sbms	};
1214127668Sbms	static const char *ipsec_notify_status_str[] = {
121556893Sfenner		"RESPONDER-LIFETIME",		"REPLAY-STATUS",
121656893Sfenner		"INITIAL-CONTACT",
121756893Sfenner	};
121856893Sfenner/* NOTE: these macro must be called with x in proper range */
121956893Sfenner
1220127668Sbms/* 0 - 8191 */
1221127668Sbms#define NOTIFY_ERROR_STR(x) \
1222127668Sbms	STR_OR_ID((x), notify_error_str)
1223127668Sbms
1224127668Sbms/* 8192 - 16383 */
1225127668Sbms#define IPSEC_NOTIFY_ERROR_STR(x) \
1226127668Sbms	STR_OR_ID((u_int)((x) - 8192), ipsec_notify_error_str)
1227127668Sbms
1228127668Sbms/* 16384 - 24575 */
1229127668Sbms#define NOTIFY_STATUS_STR(x) \
1230127668Sbms	STR_OR_ID((u_int)((x) - 16384), notify_status_str)
1231127668Sbms
1232127668Sbms/* 24576 - 32767 */
1233127668Sbms#define IPSEC_NOTIFY_STATUS_STR(x) \
1234127668Sbms	STR_OR_ID((u_int)((x) - 24576), ipsec_notify_status_str)
1235127668Sbms
1236190207Srpaulo	ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_N)));
123756893Sfenner
1238190207Srpaulo	p = (struct ikev1_pl_n *)ext;
1239190207Srpaulo	ND_TCHECK(*p);
124075115Sfenner	safememcpy(&n, ext, sizeof(n));
124175115Sfenner	doi = ntohl(n.doi);
124275115Sfenner	proto = n.prot_id;
124356893Sfenner	if (doi != 1) {
1244190207Srpaulo		ND_PRINT((ndo," doi=%d", doi));
1245190207Srpaulo		ND_PRINT((ndo," proto=%d", proto));
1246127668Sbms		if (ntohs(n.type) < 8192)
1247190207Srpaulo			ND_PRINT((ndo," type=%s", NOTIFY_ERROR_STR(ntohs(n.type))));
1248127668Sbms		else if (ntohs(n.type) < 16384)
1249190207Srpaulo			ND_PRINT((ndo," type=%s", numstr(ntohs(n.type))));
1250127668Sbms		else if (ntohs(n.type) < 24576)
1251190207Srpaulo			ND_PRINT((ndo," type=%s", NOTIFY_STATUS_STR(ntohs(n.type))));
1252127668Sbms		else
1253190207Srpaulo			ND_PRINT((ndo," type=%s", numstr(ntohs(n.type))));
125475115Sfenner		if (n.spi_size) {
1255190207Srpaulo			ND_PRINT((ndo," spi="));
1256190207Srpaulo			if (!rawprint(ndo, (caddr_t)(p + 1), n.spi_size))
1257127668Sbms				goto trunc;
125856893Sfenner		}
125975115Sfenner		return (u_char *)(p + 1) + n.spi_size;
126056893Sfenner	}
126156893Sfenner
1262190207Srpaulo	ND_PRINT((ndo," doi=ipsec"));
1263190207Srpaulo	ND_PRINT((ndo," proto=%s", PROTOIDSTR(proto)));
126475115Sfenner	if (ntohs(n.type) < 8192)
1265190207Srpaulo		ND_PRINT((ndo," type=%s", NOTIFY_ERROR_STR(ntohs(n.type))));
126675115Sfenner	else if (ntohs(n.type) < 16384)
1267190207Srpaulo		ND_PRINT((ndo," type=%s", IPSEC_NOTIFY_ERROR_STR(ntohs(n.type))));
126875115Sfenner	else if (ntohs(n.type) < 24576)
1269190207Srpaulo		ND_PRINT((ndo," type=%s", NOTIFY_STATUS_STR(ntohs(n.type))));
1270127668Sbms	else if (ntohs(n.type) < 32768)
1271190207Srpaulo		ND_PRINT((ndo," type=%s", IPSEC_NOTIFY_STATUS_STR(ntohs(n.type))));
127256893Sfenner	else
1273190207Srpaulo		ND_PRINT((ndo," type=%s", numstr(ntohs(n.type))));
127475115Sfenner	if (n.spi_size) {
1275190207Srpaulo		ND_PRINT((ndo," spi="));
1276190207Srpaulo		if (!rawprint(ndo, (caddr_t)(p + 1), n.spi_size))
1277127668Sbms			goto trunc;
127856893Sfenner	}
127956893Sfenner
128075115Sfenner	cp = (u_char *)(p + 1) + n.spi_size;
1281127668Sbms	ep2 = (u_char *)p + item_len;
128256893Sfenner
128356893Sfenner	if (cp < ep) {
1284190207Srpaulo		ND_PRINT((ndo," orig=("));
128575115Sfenner		switch (ntohs(n.type)) {
128656893Sfenner		case IPSECDOI_NTYPE_RESPONDER_LIFETIME:
128756893Sfenner		    {
1288127668Sbms			const struct attrmap *map = oakley_t_map;
128956893Sfenner			size_t nmap = sizeof(oakley_t_map)/sizeof(oakley_t_map[0]);
129056893Sfenner			while (cp < ep && cp < ep2) {
1291190207Srpaulo				cp = ikev1_attrmap_print(ndo, cp,
129256893Sfenner					(ep < ep2) ? ep : ep2, map, nmap);
129356893Sfenner			}
129456893Sfenner			break;
129556893Sfenner		    }
129656893Sfenner		case IPSECDOI_NTYPE_REPLAY_STATUS:
1297190207Srpaulo			ND_PRINT((ndo,"replay detection %sabled",
1298190207Srpaulo				  (*(u_int32_t *)cp) ? "en" : "dis"));
129956893Sfenner			break;
130056893Sfenner		case ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN:
1301190207Srpaulo			if (ikev1_sub_print(ndo, ISAKMP_NPTYPE_SA,
1302190207Srpaulo					    (struct isakmp_gen *)cp, ep, phase, doi, proto,
1303190207Srpaulo					    depth) == NULL)
1304127668Sbms				return NULL;
130556893Sfenner			break;
130656893Sfenner		default:
130756893Sfenner			/* NULL is dummy */
1308190207Srpaulo			isakmp_print(ndo, cp,
1309146773Ssam				     item_len - sizeof(*p) - n.spi_size,
1310146773Ssam				     NULL);
131156893Sfenner		}
1312190207Srpaulo		ND_PRINT((ndo,")"));
131356893Sfenner	}
1314127668Sbms	return (u_char *)ext + item_len;
1315127668Sbmstrunc:
1316190207Srpaulo	ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_N)));
1317127668Sbms	return NULL;
131856893Sfenner}
131956893Sfenner
1320127668Sbmsstatic const u_char *
1321190207Srpauloikev1_d_print(netdissect_options *ndo, u_char tpay _U_,
1322190207Srpaulo	      const struct isakmp_gen *ext, u_int item_len _U_,
1323190207Srpaulo	      const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi0 _U_,
1324190207Srpaulo	      u_int32_t proto0 _U_, int depth _U_)
132556893Sfenner{
1326190207Srpaulo	const struct ikev1_pl_d *p;
1327190207Srpaulo	struct ikev1_pl_d d;
1328127668Sbms	const u_int8_t *q;
132956893Sfenner	u_int32_t doi;
133056893Sfenner	u_int32_t proto;
133156893Sfenner	int i;
133256893Sfenner
1333190207Srpaulo	ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_D)));
133456893Sfenner
1335190207Srpaulo	p = (struct ikev1_pl_d *)ext;
1336190207Srpaulo	ND_TCHECK(*p);
133775115Sfenner	safememcpy(&d, ext, sizeof(d));
133875115Sfenner	doi = ntohl(d.doi);
133975115Sfenner	proto = d.prot_id;
134056893Sfenner	if (doi != 1) {
1341190207Srpaulo		ND_PRINT((ndo," doi=%u", doi));
1342190207Srpaulo		ND_PRINT((ndo," proto=%u", proto));
134356893Sfenner	} else {
1344190207Srpaulo		ND_PRINT((ndo," doi=ipsec"));
1345190207Srpaulo		ND_PRINT((ndo," proto=%s", PROTOIDSTR(proto)));
134656893Sfenner	}
1347190207Srpaulo	ND_PRINT((ndo," spilen=%u", d.spi_size));
1348190207Srpaulo	ND_PRINT((ndo," nspi=%u", ntohs(d.num_spi)));
1349190207Srpaulo	ND_PRINT((ndo," spi="));
135056893Sfenner	q = (u_int8_t *)(p + 1);
135175115Sfenner	for (i = 0; i < ntohs(d.num_spi); i++) {
135256893Sfenner		if (i != 0)
1353190207Srpaulo			ND_PRINT((ndo,","));
1354190207Srpaulo		if (!rawprint(ndo, (caddr_t)q, d.spi_size))
1355127668Sbms			goto trunc;
135675115Sfenner		q += d.spi_size;
135756893Sfenner	}
135856893Sfenner	return q;
1359127668Sbmstrunc:
1360190207Srpaulo	ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_D)));
1361127668Sbms	return NULL;
136256893Sfenner}
136356893Sfenner
1364127668Sbmsstatic const u_char *
1365190207Srpauloikev1_vid_print(netdissect_options *ndo, u_char tpay _U_,
1366190207Srpaulo		const struct isakmp_gen *ext,
1367190207Srpaulo		u_int item_len _U_, const u_char *ep _U_,
1368190207Srpaulo		u_int32_t phase _U_, u_int32_t doi _U_,
1369190207Srpaulo		u_int32_t proto _U_, int depth _U_)
137056893Sfenner{
137175115Sfenner	struct isakmp_gen e;
137275115Sfenner
1373190207Srpaulo	ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_VID)));
137456893Sfenner
1375190207Srpaulo	ND_TCHECK(*ext);
137675115Sfenner	safememcpy(&e, ext, sizeof(e));
1377190207Srpaulo	ND_PRINT((ndo," len=%d", ntohs(e.len) - 4));
1378190207Srpaulo	if (2 < ndo->ndo_vflag && 4 < ntohs(e.len)) {
1379190207Srpaulo		ND_PRINT((ndo," "));
1380190207Srpaulo		if (!rawprint(ndo, (caddr_t)(ext + 1), ntohs(e.len) - 4))
1381127668Sbms			goto trunc;
138256893Sfenner	}
138375115Sfenner	return (u_char *)ext + ntohs(e.len);
1384127668Sbmstrunc:
1385190207Srpaulo	ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_VID)));
1386127668Sbms	return NULL;
138756893Sfenner}
138856893Sfenner
1389190207Srpaulo/************************************************************/
1390190207Srpaulo/*                                                          */
1391190207Srpaulo/*              IKE v2 - rfc4306 - dissector                */
1392190207Srpaulo/*                                                          */
1393190207Srpaulo/************************************************************/
1394190207Srpaulo
1395190207Srpaulostatic void
1396190207Srpauloikev2_pay_print(netdissect_options *ndo, const char *payname, int critical)
1397190207Srpaulo{
1398190207Srpaulo	ND_PRINT((ndo,"%s%s:", payname, critical&0x80 ? "[C]" : ""));
1399190207Srpaulo}
1400190207Srpaulo
1401127668Sbmsstatic const u_char *
1402190207Srpauloikev2_gen_print(netdissect_options *ndo, u_char tpay,
1403190207Srpaulo		const struct isakmp_gen *ext)
140456893Sfenner{
1405190207Srpaulo	struct isakmp_gen e;
1406190207Srpaulo
1407190207Srpaulo	ND_TCHECK(*ext);
1408190207Srpaulo	safememcpy(&e, ext, sizeof(e));
1409190207Srpaulo	ikev2_pay_print(ndo, NPSTR(tpay), e.critical);
1410190207Srpaulo
1411190207Srpaulo	ND_PRINT((ndo," len=%d", ntohs(e.len) - 4));
1412190207Srpaulo	if (2 < ndo->ndo_vflag && 4 < ntohs(e.len)) {
1413190207Srpaulo		ND_PRINT((ndo," "));
1414190207Srpaulo		if (!rawprint(ndo, (caddr_t)(ext + 1), ntohs(e.len) - 4))
1415190207Srpaulo			goto trunc;
1416190207Srpaulo	}
1417190207Srpaulo	return (u_char *)ext + ntohs(e.len);
1418190207Srpaulotrunc:
1419190207Srpaulo	ND_PRINT((ndo," [|%s]", NPSTR(tpay)));
1420190207Srpaulo	return NULL;
1421190207Srpaulo}
1422190207Srpaulo
1423190207Srpaulostatic const u_char *
1424190207Srpauloikev2_t_print(netdissect_options *ndo, u_char tpay _U_, int pcount,
1425190207Srpaulo	      const struct isakmp_gen *ext, u_int item_len,
1426190207Srpaulo	      const u_char *ep, u_int32_t phase _U_, u_int32_t doi _U_,
1427190207Srpaulo	      u_int32_t proto _U_, int depth _U_)
1428190207Srpaulo{
1429190207Srpaulo	const struct ikev2_t *p;
1430190207Srpaulo	struct ikev2_t t;
1431190207Srpaulo	u_int16_t  t_id;
1432127668Sbms	const u_char *cp;
1433190207Srpaulo	const char *idstr;
1434190207Srpaulo	const struct attrmap *map;
1435190207Srpaulo	size_t nmap;
1436190207Srpaulo	const u_char *ep2;
1437190207Srpaulo
1438190207Srpaulo	p = (struct ikev2_t *)ext;
1439190207Srpaulo	ND_TCHECK(*p);
1440190207Srpaulo	safememcpy(&t, ext, sizeof(t));
1441190207Srpaulo	ikev2_pay_print(ndo, NPSTR(ISAKMP_NPTYPE_T), t.h.critical);
1442190207Srpaulo
1443190207Srpaulo	t_id = ntohs(t.t_id);
1444190207Srpaulo
1445190207Srpaulo	map = NULL;
1446190207Srpaulo	nmap = 0;
1447190207Srpaulo
1448190207Srpaulo	switch (t.t_type) {
1449190207Srpaulo	case IV2_T_ENCR:
1450190207Srpaulo		idstr = STR_OR_ID(t_id, esp_p_map);
1451190207Srpaulo		map = encr_t_map;
1452190207Srpaulo		nmap = sizeof(encr_t_map)/sizeof(encr_t_map[0]);
1453190207Srpaulo		break;
1454190207Srpaulo
1455190207Srpaulo	case IV2_T_PRF:
1456190207Srpaulo		idstr = STR_OR_ID(t_id, prf_p_map);
1457190207Srpaulo		break;
1458190207Srpaulo
1459190207Srpaulo	case IV2_T_INTEG:
1460190207Srpaulo		idstr = STR_OR_ID(t_id, integ_p_map);
1461190207Srpaulo		break;
1462190207Srpaulo
1463190207Srpaulo	case IV2_T_DH:
1464190207Srpaulo		idstr = STR_OR_ID(t_id, dh_p_map);
1465190207Srpaulo		break;
1466190207Srpaulo
1467190207Srpaulo	case IV2_T_ESN:
1468190207Srpaulo		idstr = STR_OR_ID(t_id, esn_p_map);
1469190207Srpaulo		break;
1470190207Srpaulo
1471190207Srpaulo	default:
1472190207Srpaulo		idstr = NULL;
1473190207Srpaulo		break;
1474190207Srpaulo	}
1475190207Srpaulo
1476190207Srpaulo	if (idstr)
1477190207Srpaulo		ND_PRINT((ndo," #%u type=%s id=%s ", pcount,
1478190207Srpaulo			  STR_OR_ID(t.t_type, ikev2_t_type_map),
1479190207Srpaulo			  idstr));
1480190207Srpaulo	else
1481190207Srpaulo		ND_PRINT((ndo," #%u type=%s id=%u ", pcount,
1482190207Srpaulo			  STR_OR_ID(t.t_type, ikev2_t_type_map),
1483190207Srpaulo			  t.t_id));
1484190207Srpaulo	cp = (u_char *)(p + 1);
1485190207Srpaulo	ep2 = (u_char *)p + item_len;
1486190207Srpaulo	while (cp < ep && cp < ep2) {
1487190207Srpaulo		if (map && nmap) {
1488190207Srpaulo			cp = ikev1_attrmap_print(ndo, cp, (ep < ep2) ? ep : ep2,
1489190207Srpaulo				map, nmap);
1490190207Srpaulo		} else
1491190207Srpaulo			cp = ikev1_attr_print(ndo, cp, (ep < ep2) ? ep : ep2);
1492190207Srpaulo	}
1493190207Srpaulo	if (ep < ep2)
1494190207Srpaulo		ND_PRINT((ndo,"..."));
1495190207Srpaulo	return cp;
1496190207Srpaulotrunc:
1497190207Srpaulo	ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_T)));
1498190207Srpaulo	return NULL;
1499190207Srpaulo}
1500190207Srpaulo
1501190207Srpaulostatic const u_char *
1502190207Srpauloikev2_p_print(netdissect_options *ndo, u_char tpay _U_, int pcount _U_,
1503190207Srpaulo	      const struct isakmp_gen *ext, u_int item_len _U_,
1504190207Srpaulo	       const u_char *ep, u_int32_t phase, u_int32_t doi0,
1505190207Srpaulo	       u_int32_t proto0 _U_, int depth)
1506190207Srpaulo{
1507190207Srpaulo	const struct ikev2_p *p;
1508190207Srpaulo	struct ikev2_p prop;
1509190207Srpaulo	const u_char *cp;
1510190207Srpaulo
1511190207Srpaulo	p = (struct ikev2_p *)ext;
1512190207Srpaulo	ND_TCHECK(*p);
1513190207Srpaulo	safememcpy(&prop, ext, sizeof(prop));
1514190207Srpaulo	ikev2_pay_print(ndo, NPSTR(ISAKMP_NPTYPE_P), prop.h.critical);
1515190207Srpaulo
1516214478Srpaulo	ND_PRINT((ndo," #%u protoid=%s transform=%d len=%u",
1517214478Srpaulo		  prop.p_no,  PROTOIDSTR(prop.prot_id),
1518214478Srpaulo		  prop.num_t, ntohs(prop.h.len)));
1519190207Srpaulo	if (prop.spi_size) {
1520190207Srpaulo		ND_PRINT((ndo," spi="));
1521190207Srpaulo		if (!rawprint(ndo, (caddr_t)(p + 1), prop.spi_size))
1522190207Srpaulo			goto trunc;
1523190207Srpaulo	}
1524190207Srpaulo
1525190207Srpaulo	ext = (struct isakmp_gen *)((u_char *)(p + 1) + prop.spi_size);
1526190207Srpaulo	ND_TCHECK(*ext);
1527214478Srpaulo
1528214478Srpaulo	cp = ikev2_sub_print(ndo, NULL, ISAKMP_NPTYPE_T, ext, ep, phase, doi0,
1529190207Srpaulo			     prop.prot_id, depth);
1530190207Srpaulo
1531190207Srpaulo	return cp;
1532190207Srpaulotrunc:
1533190207Srpaulo	ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_P)));
1534190207Srpaulo	return NULL;
1535190207Srpaulo}
1536190207Srpaulo
1537190207Srpaulostatic const u_char *
1538190207Srpauloikev2_sa_print(netdissect_options *ndo, u_char tpay,
1539190207Srpaulo		const struct isakmp_gen *ext1,
1540190207Srpaulo		u_int item_len _U_, const u_char *ep _U_,
1541190207Srpaulo		u_int32_t phase _U_, u_int32_t doi _U_,
1542190207Srpaulo		u_int32_t proto _U_, int depth _U_)
1543190207Srpaulo{
154475115Sfenner	struct isakmp_gen e;
1545214478Srpaulo	int    osa_length, sa_length;
1546190207Srpaulo
1547190207Srpaulo	ND_TCHECK(*ext1);
1548190207Srpaulo	safememcpy(&e, ext1, sizeof(e));
1549190207Srpaulo	ikev2_pay_print(ndo, "sa", e.critical);
1550190207Srpaulo
1551214478Srpaulo	osa_length= ntohs(e.len);
1552214478Srpaulo	sa_length = osa_length - 4;
1553214478Srpaulo	ND_PRINT((ndo," len=%d", sa_length));
1554190207Srpaulo
1555214478Srpaulo	ikev2_sub_print(ndo, NULL, ISAKMP_NPTYPE_P,
1556190207Srpaulo			ext1+1, ep,
1557190207Srpaulo			0, 0, 0, depth);
1558190207Srpaulo
1559214478Srpaulo	return (u_char *)ext1 + osa_length;
1560190207Srpaulotrunc:
1561190207Srpaulo	ND_PRINT((ndo," [|%s]", NPSTR(tpay)));
1562190207Srpaulo	return NULL;
1563190207Srpaulo}
1564190207Srpaulo
1565190207Srpaulostatic const u_char *
1566190207Srpauloikev2_ke_print(netdissect_options *ndo, u_char tpay,
1567190207Srpaulo		const struct isakmp_gen *ext,
1568190207Srpaulo		u_int item_len _U_, const u_char *ep _U_,
1569190207Srpaulo		u_int32_t phase _U_, u_int32_t doi _U_,
1570190207Srpaulo		u_int32_t proto _U_, int depth _U_)
1571190207Srpaulo{
1572190207Srpaulo	struct ikev2_ke ke;
1573190207Srpaulo	struct ikev2_ke *k;
1574190207Srpaulo
1575190207Srpaulo	k = (struct ikev2_ke *)ext;
1576190207Srpaulo	ND_TCHECK(*ext);
1577190207Srpaulo	safememcpy(&ke, ext, sizeof(ke));
1578190207Srpaulo	ikev2_pay_print(ndo, NPSTR(tpay), ke.h.critical);
1579190207Srpaulo
1580190207Srpaulo	ND_PRINT((ndo," len=%u group=%s", ntohs(ke.h.len) - 8,
1581190207Srpaulo		  STR_OR_ID(ntohs(ke.ke_group), dh_p_map)));
1582190207Srpaulo
1583190207Srpaulo	if (2 < ndo->ndo_vflag && 8 < ntohs(ke.h.len)) {
1584190207Srpaulo		ND_PRINT((ndo," "));
1585190207Srpaulo		if (!rawprint(ndo, (caddr_t)(k + 1), ntohs(ke.h.len) - 8))
1586190207Srpaulo			goto trunc;
1587190207Srpaulo	}
1588190207Srpaulo	return (u_char *)ext + ntohs(ke.h.len);
1589190207Srpaulotrunc:
1590190207Srpaulo	ND_PRINT((ndo," [|%s]", NPSTR(tpay)));
1591190207Srpaulo	return NULL;
1592190207Srpaulo}
1593190207Srpaulo
1594190207Srpaulostatic const u_char *
1595190207Srpauloikev2_ID_print(netdissect_options *ndo, u_char tpay,
1596190207Srpaulo		const struct isakmp_gen *ext,
1597190207Srpaulo		u_int item_len _U_, const u_char *ep _U_,
1598190207Srpaulo		u_int32_t phase _U_, u_int32_t doi _U_,
1599190207Srpaulo		u_int32_t proto _U_, int depth _U_)
1600190207Srpaulo{
1601214478Srpaulo	struct ikev2_id id;
1602214478Srpaulo	int id_len, idtype_len, i;
1603214478Srpaulo	unsigned int dumpascii, dumphex;
1604214478Srpaulo	unsigned char *typedata;
1605214478Srpaulo
1606214478Srpaulo	ND_TCHECK(*ext);
1607214478Srpaulo	safememcpy(&id, ext, sizeof(id));
1608214478Srpaulo	ikev2_pay_print(ndo, NPSTR(tpay), id.h.critical);
1609214478Srpaulo
1610214478Srpaulo	id_len = ntohs(id.h.len);
1611214478Srpaulo
1612214478Srpaulo	ND_PRINT((ndo," len=%d", id_len - 4));
1613214478Srpaulo	if (2 < ndo->ndo_vflag && 4 < id_len) {
1614214478Srpaulo		ND_PRINT((ndo," "));
1615214478Srpaulo		if (!rawprint(ndo, (caddr_t)(ext + 1), id_len - 4))
1616214478Srpaulo			goto trunc;
1617214478Srpaulo	}
1618214478Srpaulo
1619214478Srpaulo	idtype_len =id_len - sizeof(struct ikev2_id);
1620214478Srpaulo	dumpascii = 0;
1621214478Srpaulo	dumphex   = 0;
1622214478Srpaulo	typedata  = (unsigned char *)(ext)+sizeof(struct ikev2_id);
1623214478Srpaulo
1624214478Srpaulo	switch(id.type) {
1625214478Srpaulo	case ID_IPV4_ADDR:
1626214478Srpaulo		ND_PRINT((ndo, " ipv4:"));
1627214478Srpaulo		dumphex=1;
1628214478Srpaulo		break;
1629214478Srpaulo	case ID_FQDN:
1630214478Srpaulo		ND_PRINT((ndo, " fqdn:"));
1631214478Srpaulo		dumpascii=1;
1632214478Srpaulo		break;
1633214478Srpaulo	case ID_RFC822_ADDR:
1634214478Srpaulo		ND_PRINT((ndo, " rfc822:"));
1635214478Srpaulo		dumpascii=1;
1636214478Srpaulo		break;
1637214478Srpaulo	case ID_IPV6_ADDR:
1638214478Srpaulo		ND_PRINT((ndo, " ipv6:"));
1639214478Srpaulo		dumphex=1;
1640214478Srpaulo		break;
1641214478Srpaulo	case ID_DER_ASN1_DN:
1642214478Srpaulo		ND_PRINT((ndo, " dn:"));
1643214478Srpaulo		dumphex=1;
1644214478Srpaulo		break;
1645214478Srpaulo	case ID_DER_ASN1_GN:
1646214478Srpaulo		ND_PRINT((ndo, " gn:"));
1647214478Srpaulo		dumphex=1;
1648214478Srpaulo		break;
1649214478Srpaulo	case ID_KEY_ID:
1650214478Srpaulo		ND_PRINT((ndo, " keyid:"));
1651214478Srpaulo		dumphex=1;
1652214478Srpaulo		break;
1653214478Srpaulo	}
1654214478Srpaulo
1655214478Srpaulo	if(dumpascii) {
1656214478Srpaulo		ND_TCHECK2(*typedata, idtype_len);
1657214478Srpaulo		for(i=0; i<idtype_len; i++) {
1658214478Srpaulo			if(isprint(typedata[i])) {
1659214478Srpaulo				ND_PRINT((ndo, "%c", typedata[i]));
1660214478Srpaulo			} else {
1661214478Srpaulo				ND_PRINT((ndo, "."));
1662214478Srpaulo			}
1663214478Srpaulo		}
1664214478Srpaulo	}
1665214478Srpaulo	if(dumphex) {
1666214478Srpaulo		if (!rawprint(ndo, (caddr_t)typedata, idtype_len))
1667214478Srpaulo			goto trunc;
1668214478Srpaulo	}
1669214478Srpaulo
1670214478Srpaulo	return (u_char *)ext + id_len;
1671214478Srpaulotrunc:
1672214478Srpaulo	ND_PRINT((ndo," [|%s]", NPSTR(tpay)));
1673214478Srpaulo	return NULL;
1674190207Srpaulo}
1675190207Srpaulo
1676190207Srpaulostatic const u_char *
1677190207Srpauloikev2_cert_print(netdissect_options *ndo, u_char tpay,
1678190207Srpaulo		const struct isakmp_gen *ext,
1679190207Srpaulo		u_int item_len _U_, const u_char *ep _U_,
1680190207Srpaulo		u_int32_t phase _U_, u_int32_t doi _U_,
1681190207Srpaulo		u_int32_t proto _U_, int depth _U_)
1682190207Srpaulo{
1683190207Srpaulo	return ikev2_gen_print(ndo, tpay, ext);
1684190207Srpaulo}
1685190207Srpaulo
1686190207Srpaulostatic const u_char *
1687190207Srpauloikev2_cr_print(netdissect_options *ndo, u_char tpay,
1688190207Srpaulo		const struct isakmp_gen *ext,
1689190207Srpaulo		u_int item_len _U_, const u_char *ep _U_,
1690190207Srpaulo		u_int32_t phase _U_, u_int32_t doi _U_,
1691190207Srpaulo		u_int32_t proto _U_, int depth _U_)
1692190207Srpaulo{
1693190207Srpaulo	return ikev2_gen_print(ndo, tpay, ext);
1694190207Srpaulo}
1695190207Srpaulo
1696190207Srpaulostatic const u_char *
1697190207Srpauloikev2_auth_print(netdissect_options *ndo, u_char tpay,
1698190207Srpaulo		const struct isakmp_gen *ext,
1699190207Srpaulo		u_int item_len _U_, const u_char *ep _U_,
1700190207Srpaulo		u_int32_t phase _U_, u_int32_t doi _U_,
1701190207Srpaulo		u_int32_t proto _U_, int depth _U_)
1702190207Srpaulo{
1703214478Srpaulo	struct ikev2_auth a;
1704190207Srpaulo	const char *v2_auth[]={ "invalid", "rsasig",
1705190207Srpaulo				"shared-secret", "dsssig" };
1706214478Srpaulo	u_char *authdata = (u_char*)ext + sizeof(a);
1707214478Srpaulo	unsigned int len;
1708190207Srpaulo
1709190207Srpaulo	ND_TCHECK(*ext);
1710214478Srpaulo	safememcpy(&a, ext, sizeof(a));
1711214478Srpaulo	ikev2_pay_print(ndo, NPSTR(tpay), a.h.critical);
1712214478Srpaulo	len = ntohs(a.h.len);
1713190207Srpaulo
1714214478Srpaulo	ND_PRINT((ndo," len=%d method=%s", len-4,
1715214478Srpaulo		  STR_OR_ID(a.auth_method, v2_auth)));
1716190207Srpaulo
1717214478Srpaulo	if (1 < ndo->ndo_vflag && 4 < len) {
1718190207Srpaulo		ND_PRINT((ndo," authdata=("));
1719214478Srpaulo		if (!rawprint(ndo, (caddr_t)authdata, len - sizeof(a)))
1720190207Srpaulo			goto trunc;
1721190207Srpaulo		ND_PRINT((ndo,") "));
1722214478Srpaulo	} else if(ndo->ndo_vflag && 4 < len) {
1723214478Srpaulo		if(!ike_show_somedata(ndo, authdata, ep)) goto trunc;
1724190207Srpaulo	}
1725190207Srpaulo
1726214478Srpaulo	return (u_char *)ext + len;
1727190207Srpaulotrunc:
1728190207Srpaulo	ND_PRINT((ndo," [|%s]", NPSTR(tpay)));
1729190207Srpaulo	return NULL;
1730190207Srpaulo}
1731190207Srpaulo
1732190207Srpaulostatic const u_char *
1733190207Srpauloikev2_nonce_print(netdissect_options *ndo, u_char tpay,
1734190207Srpaulo		const struct isakmp_gen *ext,
1735190207Srpaulo		u_int item_len _U_, const u_char *ep _U_,
1736190207Srpaulo		u_int32_t phase _U_, u_int32_t doi _U_,
1737190207Srpaulo		u_int32_t proto _U_, int depth _U_)
1738190207Srpaulo{
1739190207Srpaulo	struct isakmp_gen e;
1740190207Srpaulo
1741190207Srpaulo	ND_TCHECK(*ext);
1742190207Srpaulo	safememcpy(&e, ext, sizeof(e));
1743190207Srpaulo	ikev2_pay_print(ndo, "nonce", e.critical);
1744190207Srpaulo
1745190207Srpaulo	ND_PRINT((ndo," len=%d", ntohs(e.len) - 4));
1746190207Srpaulo	if (1 < ndo->ndo_vflag && 4 < ntohs(e.len)) {
1747190207Srpaulo		ND_PRINT((ndo," nonce=("));
1748190207Srpaulo		if (!rawprint(ndo, (caddr_t)(ext + 1), ntohs(e.len) - 4))
1749190207Srpaulo			goto trunc;
1750190207Srpaulo		ND_PRINT((ndo,") "));
1751190207Srpaulo	} else if(ndo->ndo_vflag && 4 < ntohs(e.len)) {
1752190207Srpaulo		if(!ike_show_somedata(ndo, (const u_char *)(ext+1), ep)) goto trunc;
1753190207Srpaulo	}
1754190207Srpaulo
1755190207Srpaulo	return (u_char *)ext + ntohs(e.len);
1756190207Srpaulotrunc:
1757190207Srpaulo	ND_PRINT((ndo," [|%s]", NPSTR(tpay)));
1758190207Srpaulo	return NULL;
1759190207Srpaulo}
1760190207Srpaulo
1761190207Srpaulo/* notify payloads */
1762190207Srpaulostatic const u_char *
1763190207Srpauloikev2_n_print(netdissect_options *ndo, u_char tpay _U_,
1764190207Srpaulo		const struct isakmp_gen *ext,
1765190207Srpaulo		u_int item_len _U_, const u_char *ep _U_,
1766190207Srpaulo		u_int32_t phase _U_, u_int32_t doi _U_,
1767190207Srpaulo		u_int32_t proto _U_, int depth _U_)
1768190207Srpaulo{
1769190207Srpaulo	struct ikev2_n *p, n;
1770190207Srpaulo	const u_char *cp;
1771190207Srpaulo	u_char *ep2;
1772190207Srpaulo	u_char showspi, showdata, showsomedata;
1773190207Srpaulo	const char *notify_name;
1774190207Srpaulo	u_int32_t type;
1775190207Srpaulo
1776190207Srpaulo	p = (struct ikev2_n *)ext;
1777190207Srpaulo	ND_TCHECK(*p);
1778190207Srpaulo	safememcpy(&n, ext, sizeof(n));
1779190207Srpaulo	ikev2_pay_print(ndo, NPSTR(ISAKMP_NPTYPE_N), n.h.critical);
1780190207Srpaulo
1781190207Srpaulo	showspi = 1;
1782190207Srpaulo	showdata = 0;
1783190207Srpaulo	showsomedata=0;
1784190207Srpaulo	notify_name=NULL;
1785190207Srpaulo
1786190207Srpaulo	ND_PRINT((ndo," prot_id=%s", PROTOIDSTR(n.prot_id)));
1787190207Srpaulo
1788190207Srpaulo	type = ntohs(n.type);
1789190207Srpaulo
1790190207Srpaulo	/* notify space is annoying sparse */
1791190207Srpaulo	switch(type) {
1792190207Srpaulo	case IV2_NOTIFY_UNSUPPORTED_CRITICAL_PAYLOAD:
1793190207Srpaulo		notify_name = "unsupported_critical_payload";
1794190207Srpaulo		showspi = 0;
1795190207Srpaulo		break;
1796190207Srpaulo
1797190207Srpaulo	case IV2_NOTIFY_INVALID_IKE_SPI:
1798190207Srpaulo		notify_name = "invalid_ike_spi";
1799190207Srpaulo		showspi = 1;
1800190207Srpaulo		break;
1801190207Srpaulo
1802190207Srpaulo	case IV2_NOTIFY_INVALID_MAJOR_VERSION:
1803190207Srpaulo		notify_name = "invalid_major_version";
1804190207Srpaulo		showspi = 0;
1805190207Srpaulo		break;
1806190207Srpaulo
1807190207Srpaulo	case IV2_NOTIFY_INVALID_SYNTAX:
1808190207Srpaulo		notify_name = "invalid_syntax";
1809190207Srpaulo		showspi = 1;
1810190207Srpaulo		break;
1811190207Srpaulo
1812190207Srpaulo	case IV2_NOTIFY_INVALID_MESSAGE_ID:
1813190207Srpaulo		notify_name = "invalid_message_id";
1814190207Srpaulo		showspi = 1;
1815190207Srpaulo		break;
1816190207Srpaulo
1817190207Srpaulo	case IV2_NOTIFY_INVALID_SPI:
1818190207Srpaulo		notify_name = "invalid_spi";
1819190207Srpaulo		showspi = 1;
1820190207Srpaulo		break;
1821190207Srpaulo
1822190207Srpaulo	case IV2_NOTIFY_NO_PROPOSAL_CHOSEN:
1823190207Srpaulo		notify_name = "no_protocol_chosen";
1824190207Srpaulo		showspi = 1;
1825190207Srpaulo		break;
1826190207Srpaulo
1827190207Srpaulo	case IV2_NOTIFY_INVALID_KE_PAYLOAD:
1828190207Srpaulo		notify_name = "invalid_ke_payload";
1829190207Srpaulo		showspi = 1;
1830190207Srpaulo		break;
1831190207Srpaulo
1832190207Srpaulo	case IV2_NOTIFY_AUTHENTICATION_FAILED:
1833190207Srpaulo		notify_name = "authentication_failed";
1834190207Srpaulo		showspi = 1;
1835190207Srpaulo		break;
1836190207Srpaulo
1837190207Srpaulo	case IV2_NOTIFY_SINGLE_PAIR_REQUIRED:
1838190207Srpaulo		notify_name = "single_pair_required";
1839190207Srpaulo		showspi = 1;
1840190207Srpaulo		break;
1841190207Srpaulo
1842190207Srpaulo	case IV2_NOTIFY_NO_ADDITIONAL_SAS:
1843190207Srpaulo		notify_name = "no_additional_sas";
1844190207Srpaulo		showspi = 0;
1845190207Srpaulo		break;
1846190207Srpaulo
1847190207Srpaulo	case IV2_NOTIFY_INTERNAL_ADDRESS_FAILURE:
1848190207Srpaulo		notify_name = "internal_address_failure";
1849190207Srpaulo		showspi = 0;
1850190207Srpaulo		break;
1851190207Srpaulo
1852190207Srpaulo	case IV2_NOTIFY_FAILED_CP_REQUIRED:
1853190207Srpaulo		notify_name = "failed:cp_required";
1854190207Srpaulo		showspi = 0;
1855190207Srpaulo		break;
1856190207Srpaulo
1857190207Srpaulo	case IV2_NOTIFY_INVALID_SELECTORS:
1858190207Srpaulo		notify_name = "invalid_selectors";
1859190207Srpaulo		showspi = 0;
1860190207Srpaulo		break;
1861190207Srpaulo
1862190207Srpaulo	case IV2_NOTIFY_INITIAL_CONTACT:
1863190207Srpaulo		notify_name = "initial_contact";
1864190207Srpaulo		showspi = 0;
1865190207Srpaulo		break;
1866190207Srpaulo
1867190207Srpaulo	case IV2_NOTIFY_SET_WINDOW_SIZE:
1868190207Srpaulo		notify_name = "set_window_size";
1869190207Srpaulo		showspi = 0;
1870190207Srpaulo		break;
1871190207Srpaulo
1872190207Srpaulo	case IV2_NOTIFY_ADDITIONAL_TS_POSSIBLE:
1873190207Srpaulo		notify_name = "additional_ts_possible";
1874190207Srpaulo		showspi = 0;
1875190207Srpaulo		break;
1876190207Srpaulo
1877190207Srpaulo	case IV2_NOTIFY_IPCOMP_SUPPORTED:
1878190207Srpaulo		notify_name = "ipcomp_supported";
1879190207Srpaulo		showspi = 0;
1880190207Srpaulo		break;
1881190207Srpaulo
1882190207Srpaulo	case IV2_NOTIFY_NAT_DETECTION_SOURCE_IP:
1883190207Srpaulo		notify_name = "nat_detection_source_ip";
1884190207Srpaulo		showspi = 1;
1885190207Srpaulo		break;
1886190207Srpaulo
1887190207Srpaulo	case IV2_NOTIFY_NAT_DETECTION_DESTINATION_IP:
1888190207Srpaulo		notify_name = "nat_detection_destination_ip";
1889190207Srpaulo		showspi = 1;
1890190207Srpaulo		break;
1891190207Srpaulo
1892190207Srpaulo	case IV2_NOTIFY_COOKIE:
1893190207Srpaulo		notify_name = "cookie";
1894190207Srpaulo		showspi = 1;
1895190207Srpaulo		showsomedata= 1;
1896190207Srpaulo		showdata= 0;
1897190207Srpaulo		break;
1898190207Srpaulo
1899190207Srpaulo	case IV2_NOTIFY_USE_TRANSPORT_MODE:
1900190207Srpaulo		notify_name = "use_transport_mode";
1901190207Srpaulo		showspi = 0;
1902190207Srpaulo		break;
1903190207Srpaulo
1904190207Srpaulo	case IV2_NOTIFY_HTTP_CERT_LOOKUP_SUPPORTED:
1905190207Srpaulo		notify_name = "http_cert_lookup_supported";
1906190207Srpaulo		showspi = 0;
1907190207Srpaulo		break;
1908190207Srpaulo
1909190207Srpaulo	case IV2_NOTIFY_REKEY_SA:
1910190207Srpaulo		notify_name = "rekey_sa";
1911190207Srpaulo		showspi = 1;
1912190207Srpaulo		break;
1913190207Srpaulo
1914190207Srpaulo	case IV2_NOTIFY_ESP_TFC_PADDING_NOT_SUPPORTED:
1915190207Srpaulo		notify_name = "tfc_padding_not_supported";
1916190207Srpaulo		showspi = 0;
1917190207Srpaulo		break;
1918190207Srpaulo
1919190207Srpaulo	case IV2_NOTIFY_NON_FIRST_FRAGMENTS_ALSO:
1920190207Srpaulo		notify_name = "non_first_fragment_also";
1921190207Srpaulo		showspi = 0;
1922190207Srpaulo		break;
1923190207Srpaulo
1924190207Srpaulo	default:
1925190207Srpaulo		if (type < 8192) {
1926190207Srpaulo			notify_name="error";
1927190207Srpaulo		} else if(type < 16384) {
1928190207Srpaulo			notify_name="private-error";
1929190207Srpaulo		} else if(type < 40960) {
1930190207Srpaulo			notify_name="status";
1931190207Srpaulo		} else {
1932190207Srpaulo			notify_name="private-status";
1933190207Srpaulo		}
1934190207Srpaulo	}
1935190207Srpaulo
1936190207Srpaulo	if(notify_name) {
1937190207Srpaulo		ND_PRINT((ndo," type=%u(%s)", type, notify_name));
1938190207Srpaulo	}
1939190207Srpaulo
1940190207Srpaulo
1941190207Srpaulo	if (showspi && n.spi_size) {
1942190207Srpaulo		ND_PRINT((ndo," spi="));
1943190207Srpaulo		if (!rawprint(ndo, (caddr_t)(p + 1), n.spi_size))
1944190207Srpaulo			goto trunc;
1945190207Srpaulo	}
1946190207Srpaulo
1947190207Srpaulo	cp = (u_char *)(p + 1) + n.spi_size;
1948190207Srpaulo	ep2 = (u_char *)p + item_len;
1949190207Srpaulo
1950190207Srpaulo	if(3 < ndo->ndo_vflag) {
1951190207Srpaulo		showdata = 1;
1952190207Srpaulo	}
1953190207Srpaulo
1954190207Srpaulo	if ((showdata || (showsomedata && ep-cp < 30)) && cp < ep) {
1955190207Srpaulo		ND_PRINT((ndo," data=("));
1956190207Srpaulo		if (!rawprint(ndo, (caddr_t)(cp), ep - cp))
1957190207Srpaulo			goto trunc;
1958190207Srpaulo
1959190207Srpaulo		ND_PRINT((ndo,")"));
1960190207Srpaulo
1961190207Srpaulo	} else if(showsomedata && cp < ep) {
1962190207Srpaulo		if(!ike_show_somedata(ndo, cp, ep)) goto trunc;
1963190207Srpaulo	}
1964190207Srpaulo
1965190207Srpaulo	return (u_char *)ext + item_len;
1966190207Srpaulotrunc:
1967190207Srpaulo	ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_N)));
1968190207Srpaulo	return NULL;
1969190207Srpaulo}
1970190207Srpaulo
1971190207Srpaulostatic const u_char *
1972190207Srpauloikev2_d_print(netdissect_options *ndo, u_char tpay,
1973190207Srpaulo		const struct isakmp_gen *ext,
1974190207Srpaulo		u_int item_len _U_, const u_char *ep _U_,
1975190207Srpaulo		u_int32_t phase _U_, u_int32_t doi _U_,
1976190207Srpaulo		u_int32_t proto _U_, int depth _U_)
1977190207Srpaulo{
1978190207Srpaulo	return ikev2_gen_print(ndo, tpay, ext);
1979190207Srpaulo}
1980190207Srpaulo
1981190207Srpaulostatic const u_char *
1982190207Srpauloikev2_vid_print(netdissect_options *ndo, u_char tpay,
1983190207Srpaulo		const struct isakmp_gen *ext,
1984190207Srpaulo		u_int item_len _U_, const u_char *ep _U_,
1985190207Srpaulo		u_int32_t phase _U_, u_int32_t doi _U_,
1986190207Srpaulo		u_int32_t proto _U_, int depth _U_)
1987190207Srpaulo{
1988190207Srpaulo	struct isakmp_gen e;
1989190207Srpaulo	const u_char *vid;
1990190207Srpaulo	int i, len;
1991190207Srpaulo
1992190207Srpaulo	ND_TCHECK(*ext);
1993190207Srpaulo	safememcpy(&e, ext, sizeof(e));
1994190207Srpaulo	ikev2_pay_print(ndo, NPSTR(tpay), e.critical);
1995190207Srpaulo	ND_PRINT((ndo," len=%d vid=", ntohs(e.len) - 4));
1996190207Srpaulo
1997190207Srpaulo	vid = (const u_char *)(ext+1);
1998190207Srpaulo	len = ntohs(e.len) - 4;
1999190207Srpaulo	ND_TCHECK2(*vid, len);
2000190207Srpaulo	for(i=0; i<len; i++) {
2001190207Srpaulo		if(isprint(vid[i])) ND_PRINT((ndo, "%c", vid[i]));
2002214478Srpaulo		else ND_PRINT((ndo, "."));
2003190207Srpaulo	}
2004190207Srpaulo	if (2 < ndo->ndo_vflag && 4 < len) {
2005190207Srpaulo		ND_PRINT((ndo," "));
2006190207Srpaulo		if (!rawprint(ndo, (caddr_t)(ext + 1), ntohs(e.len) - 4))
2007190207Srpaulo			goto trunc;
2008190207Srpaulo	}
2009190207Srpaulo	return (u_char *)ext + ntohs(e.len);
2010190207Srpaulotrunc:
2011190207Srpaulo	ND_PRINT((ndo," [|%s]", NPSTR(tpay)));
2012190207Srpaulo	return NULL;
2013190207Srpaulo}
2014190207Srpaulo
2015190207Srpaulostatic const u_char *
2016190207Srpauloikev2_TS_print(netdissect_options *ndo, u_char tpay,
2017190207Srpaulo		const struct isakmp_gen *ext,
2018190207Srpaulo		u_int item_len _U_, const u_char *ep _U_,
2019190207Srpaulo		u_int32_t phase _U_, u_int32_t doi _U_,
2020190207Srpaulo		u_int32_t proto _U_, int depth _U_)
2021190207Srpaulo{
2022190207Srpaulo	return ikev2_gen_print(ndo, tpay, ext);
2023190207Srpaulo}
2024190207Srpaulo
2025190207Srpaulostatic const u_char *
2026214478Srpauloikev2_e_print(netdissect_options *ndo,
2027214478Srpaulo#ifndef HAVE_LIBCRYPTO
2028214478Srpaulo	      _U_
2029214478Srpaulo#endif
2030214478Srpaulo	      struct isakmp *base,
2031214478Srpaulo	      u_char tpay,
2032214478Srpaulo	      const struct isakmp_gen *ext,
2033214478Srpaulo	      u_int item_len _U_, const u_char *ep _U_,
2034214478Srpaulo#ifndef HAVE_LIBCRYPTO
2035214478Srpaulo	      _U_
2036214478Srpaulo#endif
2037214478Srpaulo	      u_int32_t phase,
2038214478Srpaulo#ifndef HAVE_LIBCRYPTO
2039214478Srpaulo	      _U_
2040214478Srpaulo#endif
2041214478Srpaulo	      u_int32_t doi,
2042214478Srpaulo#ifndef HAVE_LIBCRYPTO
2043214478Srpaulo	      _U_
2044214478Srpaulo#endif
2045214478Srpaulo	      u_int32_t proto,
2046214478Srpaulo#ifndef HAVE_LIBCRYPTO
2047214478Srpaulo	      _U_
2048214478Srpaulo#endif
2049214478Srpaulo	      int depth)
2050190207Srpaulo{
2051214478Srpaulo	struct isakmp_gen e;
2052214478Srpaulo	u_char *dat;
2053214478Srpaulo	volatile int dlen;
2054214478Srpaulo
2055214478Srpaulo	ND_TCHECK(*ext);
2056214478Srpaulo	safememcpy(&e, ext, sizeof(e));
2057214478Srpaulo	ikev2_pay_print(ndo, NPSTR(tpay), e.critical);
2058214478Srpaulo
2059214478Srpaulo	dlen = ntohs(e.len)-4;
2060214478Srpaulo
2061214478Srpaulo	ND_PRINT((ndo," len=%d", dlen));
2062214478Srpaulo	if (2 < ndo->ndo_vflag && 4 < dlen) {
2063214478Srpaulo		ND_PRINT((ndo," "));
2064214478Srpaulo		if (!rawprint(ndo, (caddr_t)(ext + 1), dlen))
2065214478Srpaulo			goto trunc;
2066214478Srpaulo	}
2067214478Srpaulo
2068214478Srpaulo	dat = (u_char *)(ext+1);
2069214478Srpaulo	ND_TCHECK2(*dat, dlen);
2070214478Srpaulo
2071214478Srpaulo#ifdef HAVE_LIBCRYPTO
2072214478Srpaulo	/* try to decypt it! */
2073214478Srpaulo	if(esp_print_decrypt_buffer_by_ikev2(ndo,
2074214478Srpaulo					     base->flags & ISAKMP_FLAG_I,
2075214478Srpaulo					     base->i_ck, base->r_ck,
2076214478Srpaulo					     dat, dat+dlen)) {
2077214478Srpaulo
2078214478Srpaulo		ext = (const struct isakmp_gen *)ndo->ndo_packetp;
2079214478Srpaulo
2080214478Srpaulo		/* got it decrypted, print stuff inside. */
2081214478Srpaulo		ikev2_sub_print(ndo, base, e.np, ext, ndo->ndo_snapend,
2082214478Srpaulo				phase, doi, proto, depth+1);
2083214478Srpaulo	}
2084214478Srpaulo#endif
2085214478Srpaulo
2086214478Srpaulo
2087214478Srpaulo	/* always return NULL, because E must be at end, and NP refers
2088214478Srpaulo	 * to what was inside.
2089214478Srpaulo	 */
2090214478Srpaulo	return NULL;
2091214478Srpaulotrunc:
2092214478Srpaulo	ND_PRINT((ndo," [|%s]", NPSTR(tpay)));
2093214478Srpaulo	return NULL;
2094190207Srpaulo}
2095190207Srpaulo
2096190207Srpaulostatic const u_char *
2097190207Srpauloikev2_cp_print(netdissect_options *ndo, u_char tpay,
2098190207Srpaulo		const struct isakmp_gen *ext,
2099190207Srpaulo		u_int item_len _U_, const u_char *ep _U_,
2100190207Srpaulo		u_int32_t phase _U_, u_int32_t doi _U_,
2101190207Srpaulo		u_int32_t proto _U_, int depth _U_)
2102190207Srpaulo{
2103190207Srpaulo	return ikev2_gen_print(ndo, tpay, ext);
2104190207Srpaulo}
2105190207Srpaulo
2106190207Srpaulostatic const u_char *
2107190207Srpauloikev2_eap_print(netdissect_options *ndo, u_char tpay,
2108190207Srpaulo		const struct isakmp_gen *ext,
2109190207Srpaulo		u_int item_len _U_, const u_char *ep _U_,
2110190207Srpaulo		u_int32_t phase _U_, u_int32_t doi _U_,
2111190207Srpaulo		u_int32_t proto _U_, int depth _U_)
2112190207Srpaulo{
2113190207Srpaulo	return ikev2_gen_print(ndo, tpay, ext);
2114190207Srpaulo}
2115190207Srpaulo
2116190207Srpaulostatic const u_char *
2117190207Srpauloike_sub0_print(netdissect_options *ndo,
2118190207Srpaulo		 u_char np, const struct isakmp_gen *ext, const u_char *ep,
2119214478Srpaulo
2120214478Srpaulo	       u_int32_t phase, u_int32_t doi, u_int32_t proto, int depth)
2121190207Srpaulo{
2122190207Srpaulo	const u_char *cp;
2123190207Srpaulo	struct isakmp_gen e;
2124111726Sfenner	u_int item_len;
212556893Sfenner
212656893Sfenner	cp = (u_char *)ext;
2127190207Srpaulo	ND_TCHECK(*ext);
212875115Sfenner	safememcpy(&e, ext, sizeof(e));
212956893Sfenner
2130127668Sbms	/*
2131127668Sbms	 * Since we can't have a payload length of less than 4 bytes,
2132127668Sbms	 * we need to bail out here if the generic header is nonsensical
2133127668Sbms	 * or truncated, otherwise we could loop forever processing
2134127668Sbms	 * zero-length items or otherwise misdissect the packet.
2135127668Sbms	 */
2136127668Sbms	item_len = ntohs(e.len);
2137127668Sbms	if (item_len <= 4)
2138127668Sbms		return NULL;
2139127668Sbms
2140127668Sbms	if (NPFUNC(np)) {
2141127668Sbms		/*
2142127668Sbms		 * XXX - what if item_len is too short, or too long,
2143127668Sbms		 * for this payload type?
2144127668Sbms		 */
2145190207Srpaulo		cp = (*npfunc[np])(ndo, np, ext, item_len, ep, phase, doi, proto, depth);
2146127668Sbms	} else {
2147190207Srpaulo		ND_PRINT((ndo,"%s", NPSTR(np)));
2148127668Sbms		cp += item_len;
214956893Sfenner	}
2150127668Sbms
215156893Sfenner	return cp;
2152127668Sbmstrunc:
2153190207Srpaulo	ND_PRINT((ndo," [|isakmp]"));
2154127668Sbms	return NULL;
215556893Sfenner}
215656893Sfenner
2157127668Sbmsstatic const u_char *
2158190207Srpauloikev1_sub_print(netdissect_options *ndo,
2159190207Srpaulo		u_char np, const struct isakmp_gen *ext, const u_char *ep,
2160190207Srpaulo		u_int32_t phase, u_int32_t doi, u_int32_t proto, int depth)
216156893Sfenner{
2162127668Sbms	const u_char *cp;
216356893Sfenner	int i;
216475115Sfenner	struct isakmp_gen e;
216556893Sfenner
2166127668Sbms	cp = (const u_char *)ext;
216756893Sfenner
216856893Sfenner	while (np) {
2169190207Srpaulo		ND_TCHECK(*ext);
2170124488Sfenner
217175115Sfenner		safememcpy(&e, ext, sizeof(e));
217275115Sfenner
2173190207Srpaulo		ND_TCHECK2(*ext, ntohs(e.len));
2174127668Sbms
217556893Sfenner		depth++;
2176190207Srpaulo		ND_PRINT((ndo,"\n"));
217756893Sfenner		for (i = 0; i < depth; i++)
2178190207Srpaulo			ND_PRINT((ndo,"    "));
2179190207Srpaulo		ND_PRINT((ndo,"("));
2180190207Srpaulo		cp = ike_sub0_print(ndo, np, ext, ep, phase, doi, proto, depth);
2181190207Srpaulo		ND_PRINT((ndo,")"));
218256893Sfenner		depth--;
218356893Sfenner
2184111726Sfenner		if (cp == NULL) {
2185111726Sfenner			/* Zero-length subitem */
2186111726Sfenner			return NULL;
2187111726Sfenner		}
2188111726Sfenner
218975115Sfenner		np = e.np;
219056893Sfenner		ext = (struct isakmp_gen *)cp;
219156893Sfenner	}
219256893Sfenner	return cp;
2193124488Sfennertrunc:
2194190207Srpaulo	ND_PRINT((ndo," [|%s]", NPSTR(np)));
2195124488Sfenner	return NULL;
219656893Sfenner}
219756893Sfenner
219856893Sfennerstatic char *
219956893Sfennernumstr(int x)
220056893Sfenner{
220156893Sfenner	static char buf[20];
220275115Sfenner	snprintf(buf, sizeof(buf), "#%d", x);
220356893Sfenner	return buf;
220456893Sfenner}
220556893Sfenner
220675115Sfenner/*
220775115Sfenner * some compiler tries to optimize memcpy(), using the alignment constraint
220875115Sfenner * on the argument pointer type.  by using this function, we try to avoid the
220975115Sfenner * optimization.
221075115Sfenner */
221175115Sfennerstatic void
2212127668Sbmssafememcpy(void *p, const void *q, size_t l)
221375115Sfenner{
221475115Sfenner	memcpy(p, q, l);
221575115Sfenner}
221675115Sfenner
2217214478Srpaulostatic void
2218190207Srpauloikev1_print(netdissect_options *ndo,
2219190207Srpaulo	    const u_char *bp,  u_int length,
2220190207Srpaulo	    const u_char *bp2, struct isakmp *base)
222156893Sfenner{
2222127668Sbms	const struct isakmp *p;
2223127668Sbms	const u_char *ep;
222456893Sfenner	u_char np;
222556893Sfenner	int i;
222656893Sfenner	int phase;
2227190207Srpaulo
2228127668Sbms	p = (const struct isakmp *)bp;
2229146773Ssam	ep = ndo->ndo_snapend;
2230190207Srpaulo
2231190207Srpaulo	phase = (*(u_int32_t *)base->msgid == 0) ? 1 : 2;
223256893Sfenner	if (phase == 1)
2233190207Srpaulo		ND_PRINT((ndo," phase %d", phase));
223456893Sfenner	else
2235190207Srpaulo		ND_PRINT((ndo," phase %d/others", phase));
2236190207Srpaulo
2237190207Srpaulo	i = cookie_find(&base->i_ck);
223856893Sfenner	if (i < 0) {
2239190207Srpaulo		if (iszero((u_char *)&base->r_ck, sizeof(base->r_ck))) {
224056893Sfenner			/* the first packet */
2241190207Srpaulo			ND_PRINT((ndo," I"));
224256893Sfenner			if (bp2)
2243190207Srpaulo				cookie_record(&base->i_ck, bp2);
224456893Sfenner		} else
2245190207Srpaulo			ND_PRINT((ndo," ?"));
224656893Sfenner	} else {
224756893Sfenner		if (bp2 && cookie_isinitiator(i, bp2))
2248190207Srpaulo			ND_PRINT((ndo," I"));
224956893Sfenner		else if (bp2 && cookie_isresponder(i, bp2))
2250190207Srpaulo			ND_PRINT((ndo," R"));
225156893Sfenner		else
2252190207Srpaulo			ND_PRINT((ndo," ?"));
225356893Sfenner	}
2254190207Srpaulo
2255190207Srpaulo	ND_PRINT((ndo," %s", ETYPESTR(base->etype)));
2256190207Srpaulo	if (base->flags) {
2257190207Srpaulo		ND_PRINT((ndo,"[%s%s]", base->flags & ISAKMP_FLAG_E ? "E" : "",
2258190207Srpaulo			  base->flags & ISAKMP_FLAG_C ? "C" : ""));
2259190207Srpaulo	}
2260190207Srpaulo
2261190207Srpaulo	if (ndo->ndo_vflag) {
2262190207Srpaulo		const struct isakmp_gen *ext;
2263190207Srpaulo		int nparen;
2264190207Srpaulo
2265190207Srpaulo		ND_PRINT((ndo,":"));
2266190207Srpaulo
2267190207Srpaulo		/* regardless of phase... */
2268190207Srpaulo		if (base->flags & ISAKMP_FLAG_E) {
2269190207Srpaulo			/*
2270190207Srpaulo			 * encrypted, nothing we can do right now.
2271190207Srpaulo			 * we hope to decrypt the packet in the future...
2272190207Srpaulo			 */
2273190207Srpaulo			ND_PRINT((ndo," [encrypted %s]", NPSTR(base->np)));
2274190207Srpaulo			goto done;
2275190207Srpaulo		}
2276190207Srpaulo
2277190207Srpaulo		nparen = 0;
2278190207Srpaulo		CHECKLEN(p + 1, base->np);
2279190207Srpaulo		np = base->np;
2280190207Srpaulo		ext = (struct isakmp_gen *)(p + 1);
2281190207Srpaulo		ikev1_sub_print(ndo, np, ext, ep, phase, 0, 0, 0);
2282190207Srpaulo	}
2283190207Srpaulo
2284190207Srpaulodone:
2285190207Srpaulo	if (ndo->ndo_vflag) {
2286190207Srpaulo		if (ntohl(base->len) != length) {
2287190207Srpaulo			ND_PRINT((ndo," (len mismatch: isakmp %u/ip %u)",
2288190207Srpaulo				  (u_int32_t)ntohl(base->len), length));
2289190207Srpaulo		}
2290190207Srpaulo	}
2291190207Srpaulo}
229256893Sfenner
2293190207Srpaulostatic const u_char *
2294214478Srpauloikev2_sub0_print(netdissect_options *ndo, struct isakmp *base,
2295214478Srpaulo		 u_char np, int pcount,
2296190207Srpaulo		 const struct isakmp_gen *ext, const u_char *ep,
2297190207Srpaulo		 u_int32_t phase, u_int32_t doi, u_int32_t proto, int depth)
2298190207Srpaulo{
2299190207Srpaulo	const u_char *cp;
2300190207Srpaulo	struct isakmp_gen e;
2301190207Srpaulo	u_int item_len;
2302190207Srpaulo
2303190207Srpaulo	cp = (u_char *)ext;
2304190207Srpaulo	ND_TCHECK(*ext);
2305190207Srpaulo	safememcpy(&e, ext, sizeof(e));
2306190207Srpaulo
2307190207Srpaulo	/*
2308190207Srpaulo	 * Since we can't have a payload length of less than 4 bytes,
2309190207Srpaulo	 * we need to bail out here if the generic header is nonsensical
2310190207Srpaulo	 * or truncated, otherwise we could loop forever processing
2311190207Srpaulo	 * zero-length items or otherwise misdissect the packet.
2312190207Srpaulo	 */
2313190207Srpaulo	item_len = ntohs(e.len);
2314190207Srpaulo	if (item_len <= 4)
2315190207Srpaulo		return NULL;
2316190207Srpaulo
2317190207Srpaulo	if(np == ISAKMP_NPTYPE_P) {
2318190207Srpaulo		cp = ikev2_p_print(ndo, np, pcount, ext, item_len,
2319190207Srpaulo				   ep, phase, doi, proto, depth);
2320190207Srpaulo	} else if(np == ISAKMP_NPTYPE_T) {
2321190207Srpaulo		cp = ikev2_t_print(ndo, np, pcount, ext, item_len,
2322190207Srpaulo				   ep, phase, doi, proto, depth);
2323214478Srpaulo	} else if(np == ISAKMP_NPTYPE_v2E) {
2324214478Srpaulo		cp = ikev2_e_print(ndo, base, np, ext, item_len,
2325214478Srpaulo				   ep, phase, doi, proto, depth);
2326190207Srpaulo	} else if (NPFUNC(np)) {
2327190207Srpaulo		/*
2328190207Srpaulo		 * XXX - what if item_len is too short, or too long,
2329190207Srpaulo		 * for this payload type?
2330190207Srpaulo		 */
2331190207Srpaulo		cp = (*npfunc[np])(ndo, np, /*pcount,*/ ext, item_len,
2332190207Srpaulo				   ep, phase, doi, proto, depth);
2333190207Srpaulo	} else {
2334190207Srpaulo		ND_PRINT((ndo,"%s", NPSTR(np)));
2335190207Srpaulo		cp += item_len;
233656893Sfenner	}
233756893Sfenner
2338190207Srpaulo	return cp;
2339190207Srpaulotrunc:
2340190207Srpaulo	ND_PRINT((ndo," [|isakmp]"));
2341190207Srpaulo	return NULL;
2342190207Srpaulo}
2343190207Srpaulo
2344190207Srpaulostatic const u_char *
2345190207Srpauloikev2_sub_print(netdissect_options *ndo,
2346214478Srpaulo		struct isakmp *base,
2347190207Srpaulo		u_char np, const struct isakmp_gen *ext, const u_char *ep,
2348190207Srpaulo		u_int32_t phase, u_int32_t doi, u_int32_t proto, int depth)
2349190207Srpaulo{
2350190207Srpaulo	const u_char *cp;
2351190207Srpaulo	int i;
2352190207Srpaulo	int pcount;
2353190207Srpaulo	struct isakmp_gen e;
2354190207Srpaulo
2355190207Srpaulo	cp = (const u_char *)ext;
2356190207Srpaulo	pcount = 0;
2357190207Srpaulo	while (np) {
2358190207Srpaulo		pcount++;
2359190207Srpaulo		ND_TCHECK(*ext);
2360190207Srpaulo
2361190207Srpaulo		safememcpy(&e, ext, sizeof(e));
2362190207Srpaulo
2363190207Srpaulo		ND_TCHECK2(*ext, ntohs(e.len));
2364190207Srpaulo
2365190207Srpaulo		depth++;
2366190207Srpaulo		ND_PRINT((ndo,"\n"));
2367190207Srpaulo		for (i = 0; i < depth; i++)
2368190207Srpaulo			ND_PRINT((ndo,"    "));
2369190207Srpaulo		ND_PRINT((ndo,"("));
2370214478Srpaulo		cp = ikev2_sub0_print(ndo, base, np, pcount,
2371190207Srpaulo				      ext, ep, phase, doi, proto, depth);
2372190207Srpaulo		ND_PRINT((ndo,")"));
2373190207Srpaulo		depth--;
2374190207Srpaulo
2375190207Srpaulo		if (cp == NULL) {
2376190207Srpaulo			/* Zero-length subitem */
2377190207Srpaulo			return NULL;
2378190207Srpaulo		}
2379190207Srpaulo
2380190207Srpaulo		np = e.np;
2381190207Srpaulo		ext = (struct isakmp_gen *)cp;
2382190207Srpaulo	}
2383190207Srpaulo	return cp;
2384190207Srpaulotrunc:
2385190207Srpaulo	ND_PRINT((ndo," [|%s]", NPSTR(np)));
2386190207Srpaulo	return NULL;
2387190207Srpaulo}
2388190207Srpaulo
2389190207Srpaulostatic void
2390190207Srpauloikev2_print(netdissect_options *ndo,
2391190207Srpaulo	    const u_char *bp,  u_int length,
2392190207Srpaulo	    const u_char *bp2 _U_, struct isakmp *base)
2393190207Srpaulo{
2394190207Srpaulo	const struct isakmp *p;
2395190207Srpaulo	const u_char *ep;
2396190207Srpaulo	u_char np;
2397190207Srpaulo	int phase;
2398190207Srpaulo
2399190207Srpaulo	p = (const struct isakmp *)bp;
2400190207Srpaulo	ep = ndo->ndo_snapend;
2401190207Srpaulo
2402190207Srpaulo	phase = (*(u_int32_t *)base->msgid == 0) ? 1 : 2;
2403190207Srpaulo	if (phase == 1)
2404190207Srpaulo		ND_PRINT((ndo, " parent_sa"));
2405190207Srpaulo	else
2406190207Srpaulo		ND_PRINT((ndo, " child_sa "));
2407190207Srpaulo
2408190207Srpaulo	ND_PRINT((ndo, " %s", ETYPESTR(base->etype)));
2409190207Srpaulo	if (base->flags) {
2410214478Srpaulo		ND_PRINT((ndo, "[%s%s%s]",
2411190207Srpaulo			  base->flags & ISAKMP_FLAG_I ? "I" : "",
2412190207Srpaulo			  base->flags & ISAKMP_FLAG_V ? "V" : "",
2413190207Srpaulo			  base->flags & ISAKMP_FLAG_R ? "R" : ""));
2414190207Srpaulo	}
2415190207Srpaulo
2416190207Srpaulo	if (ndo->ndo_vflag) {
2417127668Sbms		const struct isakmp_gen *ext;
2418127668Sbms		int nparen;
241956893Sfenner
2420190207Srpaulo		ND_PRINT((ndo, ":"));
242156893Sfenner
2422127668Sbms		/* regardless of phase... */
2423190207Srpaulo		if (base->flags & ISAKMP_FLAG_E) {
2424127668Sbms			/*
2425127668Sbms			 * encrypted, nothing we can do right now.
2426127668Sbms			 * we hope to decrypt the packet in the future...
2427127668Sbms			 */
2428190207Srpaulo			ND_PRINT((ndo, " [encrypted %s]", NPSTR(base->np)));
2429127668Sbms			goto done;
2430127668Sbms		}
243156893Sfenner
2432127668Sbms		nparen = 0;
2433190207Srpaulo		CHECKLEN(p + 1, base->np)
243456893Sfenner
2435190207Srpaulo		np = base->np;
2436127668Sbms		ext = (struct isakmp_gen *)(p + 1);
2437214478Srpaulo		ikev2_sub_print(ndo, base, np, ext, ep, phase, 0, 0, 0);
2438127668Sbms	}
2439127668Sbms
244056893Sfennerdone:
2441190207Srpaulo	if (ndo->ndo_vflag) {
2442190207Srpaulo		if (ntohl(base->len) != length) {
2443190207Srpaulo			ND_PRINT((ndo, " (len mismatch: isakmp %u/ip %u)",
2444190207Srpaulo				  (u_int32_t)ntohl(base->len), length));
244556893Sfenner		}
244656893Sfenner	}
244756893Sfenner}
2448146773Ssam
2449146773Ssamvoid
2450190207Srpauloisakmp_print(netdissect_options *ndo,
2451190207Srpaulo	     const u_char *bp, u_int length,
2452190207Srpaulo	     const u_char *bp2)
2453190207Srpaulo{
2454190207Srpaulo	const struct isakmp *p;
2455190207Srpaulo	struct isakmp base;
2456190207Srpaulo	const u_char *ep;
2457190207Srpaulo	int major, minor;
2458190207Srpaulo
2459214478Srpaulo#ifdef HAVE_LIBCRYPTO
2460214478Srpaulo	/* initialize SAs */
2461214478Srpaulo	if (ndo->ndo_sa_list_head == NULL) {
2462214478Srpaulo		if (ndo->ndo_espsecret)
2463214478Srpaulo			esp_print_decodesecret(ndo);
2464214478Srpaulo	}
2465214478Srpaulo#endif
2466214478Srpaulo
2467190207Srpaulo	p = (const struct isakmp *)bp;
2468190207Srpaulo	ep = ndo->ndo_snapend;
2469190207Srpaulo
2470190207Srpaulo	if ((struct isakmp *)ep < p + 1) {
2471190207Srpaulo		ND_PRINT((ndo,"[|isakmp]"));
2472190207Srpaulo		return;
2473190207Srpaulo	}
2474190207Srpaulo
2475190207Srpaulo	safememcpy(&base, p, sizeof(base));
2476190207Srpaulo
2477190207Srpaulo	ND_PRINT((ndo,"isakmp"));
2478190207Srpaulo	major = (base.vers & ISAKMP_VERS_MAJOR)
2479190207Srpaulo		>> ISAKMP_VERS_MAJOR_SHIFT;
2480190207Srpaulo	minor = (base.vers & ISAKMP_VERS_MINOR)
2481190207Srpaulo		>> ISAKMP_VERS_MINOR_SHIFT;
2482190207Srpaulo
2483190207Srpaulo	if (ndo->ndo_vflag) {
2484190207Srpaulo		ND_PRINT((ndo," %d.%d", major, minor));
2485190207Srpaulo	}
2486190207Srpaulo
2487190207Srpaulo	if (ndo->ndo_vflag) {
2488190207Srpaulo		ND_PRINT((ndo," msgid "));
2489214478Srpaulo		hexprint(ndo, (caddr_t)&base.msgid, sizeof(base.msgid));
2490190207Srpaulo	}
2491190207Srpaulo
2492190207Srpaulo	if (1 < ndo->ndo_vflag) {
2493190207Srpaulo		ND_PRINT((ndo," cookie "));
2494214478Srpaulo		hexprint(ndo, (caddr_t)&base.i_ck, sizeof(base.i_ck));
2495190207Srpaulo		ND_PRINT((ndo,"->"));
2496214478Srpaulo		hexprint(ndo, (caddr_t)&base.r_ck, sizeof(base.r_ck));
2497190207Srpaulo	}
2498190207Srpaulo	ND_PRINT((ndo,":"));
2499190207Srpaulo
2500190207Srpaulo	switch(major) {
2501190207Srpaulo	case IKEv1_MAJOR_VERSION:
2502190207Srpaulo		ikev1_print(ndo, bp, length, bp2, &base);
2503190207Srpaulo		break;
2504190207Srpaulo
2505190207Srpaulo	case IKEv2_MAJOR_VERSION:
2506190207Srpaulo		ikev2_print(ndo, bp, length, bp2, &base);
2507190207Srpaulo		break;
2508190207Srpaulo	}
2509190207Srpaulo}
2510190207Srpaulo
2511190207Srpaulovoid
2512146773Ssamisakmp_rfc3948_print(netdissect_options *ndo,
2513146773Ssam		     const u_char *bp, u_int length,
2514146773Ssam		     const u_char *bp2)
2515146773Ssam{
2516146773Ssam	const u_char *ep;
2517146773Ssam	ep = ndo->ndo_snapend;
2518146773Ssam
2519146773Ssam	if(length == 1 && bp[0]==0xff) {
2520146773Ssam		ND_PRINT((ndo, "isakmp-nat-keep-alive"));
2521146773Ssam		return;
2522146773Ssam	}
2523146773Ssam
2524146773Ssam	if(length < 4) {
2525146773Ssam		goto trunc;
2526146773Ssam	}
2527190207Srpaulo
2528146773Ssam	/*
2529146773Ssam	 * see if this is an IKE packet
2530146773Ssam	 */
2531146773Ssam	if(bp[0]==0 && bp[1]==0 && bp[2]==0 && bp[3]==0) {
2532146773Ssam		ND_PRINT((ndo, "NONESP-encap: "));
2533146773Ssam		isakmp_print(ndo, bp+4, length-4, bp2);
2534146773Ssam		return;
2535146773Ssam	}
2536146773Ssam
2537146773Ssam	/* must be an ESP packet */
2538146773Ssam	{
2539146773Ssam		int nh, enh, padlen;
2540146773Ssam		int advance;
2541146773Ssam
2542146773Ssam		ND_PRINT((ndo, "UDP-encap: "));
2543146773Ssam
2544146773Ssam		advance = esp_print(ndo, bp, length, bp2, &enh, &padlen);
2545146773Ssam		if(advance <= 0)
2546146773Ssam			return;
2547146773Ssam
2548146773Ssam		bp += advance;
2549146773Ssam		length -= advance + padlen;
2550146773Ssam		nh = enh & 0xff;
2551146773Ssam
2552146773Ssam		ip_print_inner(ndo, bp, length, nh, bp2);
2553146773Ssam		return;
2554146773Ssam	}
2555146773Ssam
2556146773Ssamtrunc:
2557190207Srpaulo	ND_PRINT((ndo,"[|isakmp]"));
2558146773Ssam	return;
2559146773Ssam}
2560146773Ssam
2561146773Ssam/*
2562146773Ssam * Local Variables:
2563146773Ssam * c-style: whitesmith
2564146773Ssam * c-basic-offset: 8
2565146773Ssam * End:
2566146773Ssam */
2567146773Ssam
2568146773Ssam
2569146773Ssam
2570146773Ssam
2571