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