1/*
2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the project nor the names of its contributors
14 *    may be used to endorse or promote products derived from this software
15 *    without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 */
30
31#ifndef lint
32static const char rcsid[] _U_ =
33    "@(#) $Header: /tcpdump/master/tcpdump/print-isakmp.c,v 1.51 2005/04/07 00:28:17 mcr Exp $ (LBL)";
34#endif
35
36#ifdef HAVE_CONFIG_H
37#include "config.h"
38#endif
39
40#include <tcpdump-stdinc.h>
41
42#include <string.h>
43
44#include <stdio.h>
45
46#include "isakmp.h"
47#include "ipsec_doi.h"
48#include "oakley.h"
49#include "interface.h"
50#include "addrtoname.h"
51#include "extract.h"                    /* must come after interface.h */
52
53#include "ip.h"
54#ifdef INET6
55#include "ip6.h"
56#endif
57
58#ifndef HAVE_SOCKADDR_STORAGE
59#define sockaddr_storage sockaddr
60#endif
61
62static const u_char *isakmp_sa_print(const struct isakmp_gen *,
63	u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
64static const u_char *isakmp_p_print(const struct isakmp_gen *,
65	u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
66static const u_char *isakmp_t_print(const struct isakmp_gen *,
67	u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
68static const u_char *isakmp_ke_print(const struct isakmp_gen *,
69	u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
70static const u_char *isakmp_id_print(const struct isakmp_gen *,
71	u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
72static const u_char *isakmp_cert_print(const struct isakmp_gen *,
73	u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
74static const u_char *isakmp_cr_print(const struct isakmp_gen *,
75	u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
76static const u_char *isakmp_sig_print(const struct isakmp_gen *,
77	u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
78static const u_char *isakmp_hash_print(const struct isakmp_gen *,
79	u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
80static const u_char *isakmp_nonce_print(const struct isakmp_gen *,
81	u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
82static const u_char *isakmp_n_print(const struct isakmp_gen *,
83	u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
84static const u_char *isakmp_d_print(const struct isakmp_gen *,
85	u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
86static const u_char *isakmp_vid_print(const struct isakmp_gen *,
87	u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
88static const u_char *isakmp_sub0_print(u_char, const struct isakmp_gen *,
89	const u_char *,	u_int32_t, u_int32_t, u_int32_t, int);
90static const u_char *isakmp_sub_print(u_char, const struct isakmp_gen *,
91	const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
92static char *numstr(int);
93static void safememcpy(void *, const void *, size_t);
94
95#define MAXINITIATORS	20
96int ninitiator = 0;
97struct {
98	cookie_t initiator;
99	struct sockaddr_storage iaddr;
100	struct sockaddr_storage raddr;
101} cookiecache[MAXINITIATORS];
102
103/* protocol id */
104static const char *protoidstr[] = {
105	NULL, "isakmp", "ipsec-ah", "ipsec-esp", "ipcomp",
106};
107
108/* isakmp->np */
109static const char *npstr[] = {
110	"none", "sa", "p", "t", "ke", "id", "cert", "cr", "hash",
111	"sig", "nonce", "n", "d", "vid"
112};
113
114/* isakmp->np */
115static const u_char *(*npfunc[])(const struct isakmp_gen *, u_int,
116		const u_char *, u_int32_t, u_int32_t, u_int32_t, int) = {
117	NULL,
118	isakmp_sa_print,
119	isakmp_p_print,
120	isakmp_t_print,
121	isakmp_ke_print,
122	isakmp_id_print,
123	isakmp_cert_print,
124	isakmp_cr_print,
125	isakmp_hash_print,
126	isakmp_sig_print,
127	isakmp_nonce_print,
128	isakmp_n_print,
129	isakmp_d_print,
130	isakmp_vid_print,
131};
132
133/* isakmp->etype */
134static const char *etypestr[] = {
135	"none", "base", "ident", "auth", "agg", "inf", NULL, NULL,
136	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
137	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
138	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
139	"oakley-quick", "oakley-newgroup",
140};
141
142#define STR_OR_ID(x, tab) \
143	(((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)])	? tab[(x)] : numstr(x))
144#define PROTOIDSTR(x)	STR_OR_ID(x, protoidstr)
145#define NPSTR(x)	STR_OR_ID(x, npstr)
146#define ETYPESTR(x)	STR_OR_ID(x, etypestr)
147
148#define NPFUNC(x) \
149	(((x) < sizeof(npfunc)/sizeof(npfunc[0]) && npfunc[(x)]) \
150		? npfunc[(x)] : NULL)
151
152static int
153iszero(u_char *p, size_t l)
154{
155	while (l--) {
156		if (*p++)
157			return 0;
158	}
159	return 1;
160}
161
162/* find cookie from initiator cache */
163static int
164cookie_find(cookie_t *in)
165{
166	int i;
167
168	for (i = 0; i < MAXINITIATORS; i++) {
169		if (memcmp(in, &cookiecache[i].initiator, sizeof(*in)) == 0)
170			return i;
171	}
172
173	return -1;
174}
175
176/* record initiator */
177static void
178cookie_record(cookie_t *in, const u_char *bp2)
179{
180	int i;
181	struct ip *ip;
182	struct sockaddr_in *sin;
183#ifdef INET6
184	struct ip6_hdr *ip6;
185	struct sockaddr_in6 *sin6;
186#endif
187
188	i = cookie_find(in);
189	if (0 <= i) {
190		ninitiator = (i + 1) % MAXINITIATORS;
191		return;
192	}
193
194	ip = (struct ip *)bp2;
195	switch (IP_V(ip)) {
196	case 4:
197		memset(&cookiecache[ninitiator].iaddr, 0,
198			sizeof(cookiecache[ninitiator].iaddr));
199		memset(&cookiecache[ninitiator].raddr, 0,
200			sizeof(cookiecache[ninitiator].raddr));
201
202		sin = (struct sockaddr_in *)&cookiecache[ninitiator].iaddr;
203#ifdef HAVE_SOCKADDR_SA_LEN
204		sin->sin_len = sizeof(struct sockaddr_in);
205#endif
206		sin->sin_family = AF_INET;
207		memcpy(&sin->sin_addr, &ip->ip_src, sizeof(ip->ip_src));
208		sin = (struct sockaddr_in *)&cookiecache[ninitiator].raddr;
209#ifdef HAVE_SOCKADDR_SA_LEN
210		sin->sin_len = sizeof(struct sockaddr_in);
211#endif
212		sin->sin_family = AF_INET;
213		memcpy(&sin->sin_addr, &ip->ip_dst, sizeof(ip->ip_dst));
214		break;
215#ifdef INET6
216	case 6:
217		memset(&cookiecache[ninitiator].iaddr, 0,
218			sizeof(cookiecache[ninitiator].iaddr));
219		memset(&cookiecache[ninitiator].raddr, 0,
220			sizeof(cookiecache[ninitiator].raddr));
221
222		ip6 = (struct ip6_hdr *)bp2;
223		sin6 = (struct sockaddr_in6 *)&cookiecache[ninitiator].iaddr;
224#ifdef HAVE_SOCKADDR_SA_LEN
225		sin6->sin6_len = sizeof(struct sockaddr_in6);
226#endif
227		sin6->sin6_family = AF_INET6;
228		memcpy(&sin6->sin6_addr, &ip6->ip6_src, sizeof(ip6->ip6_src));
229		sin6 = (struct sockaddr_in6 *)&cookiecache[ninitiator].raddr;
230#ifdef HAVE_SOCKADDR_SA_LEN
231		sin6->sin6_len = sizeof(struct sockaddr_in6);
232#endif
233		sin6->sin6_family = AF_INET6;
234		memcpy(&sin6->sin6_addr, &ip6->ip6_dst, sizeof(ip6->ip6_dst));
235		break;
236#endif
237	default:
238		return;
239	}
240	memcpy(&cookiecache[ninitiator].initiator, in, sizeof(*in));
241	ninitiator = (ninitiator + 1) % MAXINITIATORS;
242}
243
244#define cookie_isinitiator(x, y)	cookie_sidecheck((x), (y), 1)
245#define cookie_isresponder(x, y)	cookie_sidecheck((x), (y), 0)
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                        // not supported on android
720			//setprotoent(1);
721#endif /* WIN32 */
722			pe = getprotobynumber(id.proto_id);
723			if (pe)
724				printf(" protoid=%s", pe->p_name);
725#ifndef WIN32
726                        // not supported on android
727			//endprotoent();
728#endif /* WIN32 */
729		} else {
730			/* it DOES NOT mean IPPROTO_IP! */
731			printf(" protoid=%s", "0");
732		}
733		printf(" port=%d", ntohs(id.port));
734		if (!len)
735			break;
736		if (data == NULL)
737			goto trunc;
738		TCHECK2(*data, len);
739		switch (id.type) {
740		case IPSECDOI_ID_IPV4_ADDR:
741			if (len < 4)
742				printf(" len=%d [bad: < 4]", len);
743			else
744				printf(" len=%d %s", len, ipaddr_string(data));
745			len = 0;
746			break;
747		case IPSECDOI_ID_FQDN:
748		case IPSECDOI_ID_USER_FQDN:
749		    {
750			int i;
751			printf(" len=%d ", len);
752			for (i = 0; i < len; i++)
753				safeputchar(data[i]);
754			len = 0;
755			break;
756		    }
757		case IPSECDOI_ID_IPV4_ADDR_SUBNET:
758		    {
759			const u_char *mask;
760			if (len < 8)
761				printf(" len=%d [bad: < 8]", len);
762			else {
763				mask = data + sizeof(struct in_addr);
764				printf(" len=%d %s/%u.%u.%u.%u", len,
765					ipaddr_string(data),
766					mask[0], mask[1], mask[2], mask[3]);
767			}
768			len = 0;
769			break;
770		    }
771#ifdef INET6
772		case IPSECDOI_ID_IPV6_ADDR:
773			if (len < 16)
774				printf(" len=%d [bad: < 16]", len);
775			else
776				printf(" len=%d %s", len, ip6addr_string(data));
777			len = 0;
778			break;
779		case IPSECDOI_ID_IPV6_ADDR_SUBNET:
780		    {
781			const u_int32_t *mask;
782			if (len < 20)
783				printf(" len=%d [bad: < 20]", len);
784			else {
785				mask = (u_int32_t *)(data + sizeof(struct in6_addr));
786				/*XXX*/
787				printf(" len=%d %s/0x%08x%08x%08x%08x", len,
788					ip6addr_string(data),
789					mask[0], mask[1], mask[2], mask[3]);
790			}
791			len = 0;
792			break;
793		    }
794#endif /*INET6*/
795		case IPSECDOI_ID_IPV4_ADDR_RANGE:
796			if (len < 8)
797				printf(" len=%d [bad: < 8]", len);
798			else {
799				printf(" len=%d %s-%s", len,
800					ipaddr_string(data),
801					ipaddr_string(data + sizeof(struct in_addr)));
802			}
803			len = 0;
804			break;
805#ifdef INET6
806		case IPSECDOI_ID_IPV6_ADDR_RANGE:
807			if (len < 32)
808				printf(" len=%d [bad: < 32]", len);
809			else {
810				printf(" len=%d %s-%s", len,
811					ip6addr_string(data),
812					ip6addr_string(data + sizeof(struct in6_addr)));
813			}
814			len = 0;
815			break;
816#endif /*INET6*/
817		case IPSECDOI_ID_DER_ASN1_DN:
818		case IPSECDOI_ID_DER_ASN1_GN:
819		case IPSECDOI_ID_KEY_ID:
820			break;
821		}
822		break;
823	    }
824	}
825	if (data && len) {
826		printf(" len=%d", len);
827		if (2 < vflag) {
828			printf(" ");
829			if (!rawprint((caddr_t)data, len))
830				goto trunc;
831		}
832	}
833	return (u_char *)ext + item_len;
834trunc:
835	printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_ID));
836	return NULL;
837}
838
839static const u_char *
840isakmp_cert_print(const struct isakmp_gen *ext, u_int item_len _U_,
841		  const u_char *ep _U_, u_int32_t phase _U_,
842		  u_int32_t doi0 _U_,
843		  u_int32_t proto0 _U_, int depth _U_)
844{
845	const struct isakmp_pl_cert *p;
846	struct isakmp_pl_cert cert;
847	static const char *certstr[] = {
848		"none",	"pkcs7", "pgp", "dns",
849		"x509sign", "x509ke", "kerberos", "crl",
850		"arl", "spki", "x509attr",
851	};
852
853	printf("%s:", NPSTR(ISAKMP_NPTYPE_CERT));
854
855	p = (struct isakmp_pl_cert *)ext;
856	TCHECK(*p);
857	safememcpy(&cert, ext, sizeof(cert));
858	printf(" len=%d", item_len - 4);
859	printf(" type=%s", STR_OR_ID((cert.encode), certstr));
860	if (2 < vflag && 4 < item_len) {
861		printf(" ");
862		if (!rawprint((caddr_t)(ext + 1), item_len - 4))
863			goto trunc;
864	}
865	return (u_char *)ext + item_len;
866trunc:
867	printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_CERT));
868	return NULL;
869}
870
871static const u_char *
872isakmp_cr_print(const struct isakmp_gen *ext, u_int item_len _U_,
873		const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi0 _U_,
874		u_int32_t proto0 _U_, int depth _U_)
875{
876	const struct isakmp_pl_cert *p;
877	struct isakmp_pl_cert cert;
878	static const char *certstr[] = {
879		"none",	"pkcs7", "pgp", "dns",
880		"x509sign", "x509ke", "kerberos", "crl",
881		"arl", "spki", "x509attr",
882	};
883
884	printf("%s:", NPSTR(ISAKMP_NPTYPE_CR));
885
886	p = (struct isakmp_pl_cert *)ext;
887	TCHECK(*p);
888	safememcpy(&cert, ext, sizeof(cert));
889	printf(" len=%d", item_len - 4);
890	printf(" type=%s", STR_OR_ID((cert.encode), certstr));
891	if (2 < vflag && 4 < item_len) {
892		printf(" ");
893		if (!rawprint((caddr_t)(ext + 1), item_len - 4))
894			goto trunc;
895	}
896	return (u_char *)ext + item_len;
897trunc:
898	printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_CR));
899	return NULL;
900}
901
902static const u_char *
903isakmp_hash_print(const struct isakmp_gen *ext, u_int item_len _U_,
904		  const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi _U_,
905		  u_int32_t proto _U_, int depth _U_)
906{
907	struct isakmp_gen e;
908
909	printf("%s:", NPSTR(ISAKMP_NPTYPE_HASH));
910
911	TCHECK(*ext);
912	safememcpy(&e, ext, sizeof(e));
913	printf(" len=%d", ntohs(e.len) - 4);
914	if (2 < vflag && 4 < ntohs(e.len)) {
915		printf(" ");
916		if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
917			goto trunc;
918	}
919	return (u_char *)ext + ntohs(e.len);
920trunc:
921	printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_HASH));
922	return NULL;
923}
924
925static const u_char *
926isakmp_sig_print(const struct isakmp_gen *ext, u_int item_len _U_,
927		 const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi _U_,
928		 u_int32_t proto _U_, int depth _U_)
929{
930	struct isakmp_gen e;
931
932	printf("%s:", NPSTR(ISAKMP_NPTYPE_SIG));
933
934	TCHECK(*ext);
935	safememcpy(&e, ext, sizeof(e));
936	printf(" len=%d", ntohs(e.len) - 4);
937	if (2 < vflag && 4 < ntohs(e.len)) {
938		printf(" ");
939		if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
940			goto trunc;
941	}
942	return (u_char *)ext + ntohs(e.len);
943trunc:
944	printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_SIG));
945	return NULL;
946}
947
948static const u_char *
949isakmp_nonce_print(const struct isakmp_gen *ext,
950		   u_int item_len _U_,
951		   const u_char *ep _U_,
952		   u_int32_t phase _U_, u_int32_t doi _U_,
953		   u_int32_t proto _U_, int depth _U_)
954{
955	struct isakmp_gen e;
956
957	printf("%s:", NPSTR(ISAKMP_NPTYPE_NONCE));
958
959	TCHECK(*ext);
960	safememcpy(&e, ext, sizeof(e));
961	printf(" n len=%d", ntohs(e.len) - 4);
962	if (2 < vflag && 4 < ntohs(e.len)) {
963		printf(" ");
964		if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
965			goto trunc;
966	}
967	return (u_char *)ext + ntohs(e.len);
968trunc:
969	printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_NONCE));
970	return NULL;
971}
972
973static const u_char *
974isakmp_n_print(const struct isakmp_gen *ext, u_int item_len,
975	const u_char *ep, u_int32_t phase, u_int32_t doi0 _U_,
976	u_int32_t proto0 _U_, int depth)
977{
978	struct isakmp_pl_n *p, n;
979	const u_char *cp;
980	u_char *ep2;
981	u_int32_t doi;
982	u_int32_t proto;
983	static const char *notify_error_str[] = {
984		NULL,				"INVALID-PAYLOAD-TYPE",
985		"DOI-NOT-SUPPORTED",		"SITUATION-NOT-SUPPORTED",
986		"INVALID-COOKIE",		"INVALID-MAJOR-VERSION",
987		"INVALID-MINOR-VERSION",	"INVALID-EXCHANGE-TYPE",
988		"INVALID-FLAGS",		"INVALID-MESSAGE-ID",
989		"INVALID-PROTOCOL-ID",		"INVALID-SPI",
990		"INVALID-TRANSFORM-ID",		"ATTRIBUTES-NOT-SUPPORTED",
991		"NO-PROPOSAL-CHOSEN",		"BAD-PROPOSAL-SYNTAX",
992		"PAYLOAD-MALFORMED",		"INVALID-KEY-INFORMATION",
993		"INVALID-ID-INFORMATION",	"INVALID-CERT-ENCODING",
994		"INVALID-CERTIFICATE",		"CERT-TYPE-UNSUPPORTED",
995		"INVALID-CERT-AUTHORITY",	"INVALID-HASH-INFORMATION",
996		"AUTHENTICATION-FAILED",	"INVALID-SIGNATURE",
997		"ADDRESS-NOTIFICATION",		"NOTIFY-SA-LIFETIME",
998		"CERTIFICATE-UNAVAILABLE",	"UNSUPPORTED-EXCHANGE-TYPE",
999		"UNEQUAL-PAYLOAD-LENGTHS",
1000	};
1001	static const char *ipsec_notify_error_str[] = {
1002		"RESERVED",
1003	};
1004	static const char *notify_status_str[] = {
1005		"CONNECTED",
1006	};
1007	static const char *ipsec_notify_status_str[] = {
1008		"RESPONDER-LIFETIME",		"REPLAY-STATUS",
1009		"INITIAL-CONTACT",
1010	};
1011/* NOTE: these macro must be called with x in proper range */
1012
1013/* 0 - 8191 */
1014#define NOTIFY_ERROR_STR(x) \
1015	STR_OR_ID((x), notify_error_str)
1016
1017/* 8192 - 16383 */
1018#define IPSEC_NOTIFY_ERROR_STR(x) \
1019	STR_OR_ID((u_int)((x) - 8192), ipsec_notify_error_str)
1020
1021/* 16384 - 24575 */
1022#define NOTIFY_STATUS_STR(x) \
1023	STR_OR_ID((u_int)((x) - 16384), notify_status_str)
1024
1025/* 24576 - 32767 */
1026#define IPSEC_NOTIFY_STATUS_STR(x) \
1027	STR_OR_ID((u_int)((x) - 24576), ipsec_notify_status_str)
1028
1029	printf("%s:", NPSTR(ISAKMP_NPTYPE_N));
1030
1031	p = (struct isakmp_pl_n *)ext;
1032	TCHECK(*p);
1033	safememcpy(&n, ext, sizeof(n));
1034	doi = ntohl(n.doi);
1035	proto = n.prot_id;
1036	if (doi != 1) {
1037		printf(" doi=%d", doi);
1038		printf(" proto=%d", proto);
1039		if (ntohs(n.type) < 8192)
1040			printf(" type=%s", NOTIFY_ERROR_STR(ntohs(n.type)));
1041		else if (ntohs(n.type) < 16384)
1042			printf(" type=%s", numstr(ntohs(n.type)));
1043		else if (ntohs(n.type) < 24576)
1044			printf(" type=%s", NOTIFY_STATUS_STR(ntohs(n.type)));
1045		else
1046			printf(" type=%s", numstr(ntohs(n.type)));
1047		if (n.spi_size) {
1048			printf(" spi=");
1049			if (!rawprint((caddr_t)(p + 1), n.spi_size))
1050				goto trunc;
1051		}
1052		return (u_char *)(p + 1) + n.spi_size;
1053	}
1054
1055	printf(" doi=ipsec");
1056	printf(" proto=%s", PROTOIDSTR(proto));
1057	if (ntohs(n.type) < 8192)
1058		printf(" type=%s", NOTIFY_ERROR_STR(ntohs(n.type)));
1059	else if (ntohs(n.type) < 16384)
1060		printf(" type=%s", IPSEC_NOTIFY_ERROR_STR(ntohs(n.type)));
1061	else if (ntohs(n.type) < 24576)
1062		printf(" type=%s", NOTIFY_STATUS_STR(ntohs(n.type)));
1063	else if (ntohs(n.type) < 32768)
1064		printf(" type=%s", IPSEC_NOTIFY_STATUS_STR(ntohs(n.type)));
1065	else
1066		printf(" type=%s", numstr(ntohs(n.type)));
1067	if (n.spi_size) {
1068		printf(" spi=");
1069		if (!rawprint((caddr_t)(p + 1), n.spi_size))
1070			goto trunc;
1071	}
1072
1073	cp = (u_char *)(p + 1) + n.spi_size;
1074	ep2 = (u_char *)p + item_len;
1075
1076	if (cp < ep) {
1077		printf(" orig=(");
1078		switch (ntohs(n.type)) {
1079		case IPSECDOI_NTYPE_RESPONDER_LIFETIME:
1080		    {
1081			const struct attrmap *map = oakley_t_map;
1082			size_t nmap = sizeof(oakley_t_map)/sizeof(oakley_t_map[0]);
1083			while (cp < ep && cp < ep2) {
1084				cp = isakmp_attrmap_print(cp,
1085					(ep < ep2) ? ep : ep2, map, nmap);
1086			}
1087			break;
1088		    }
1089		case IPSECDOI_NTYPE_REPLAY_STATUS:
1090			printf("replay detection %sabled",
1091				(*(u_int32_t *)cp) ? "en" : "dis");
1092			break;
1093		case ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN:
1094			if (isakmp_sub_print(ISAKMP_NPTYPE_SA,
1095			    (struct isakmp_gen *)cp, ep, phase, doi, proto,
1096			    depth) == NULL)
1097				return NULL;
1098			break;
1099		default:
1100			/* NULL is dummy */
1101			isakmp_print(gndo, cp,
1102				     item_len - sizeof(*p) - n.spi_size,
1103				     NULL);
1104		}
1105		printf(")");
1106	}
1107	return (u_char *)ext + item_len;
1108trunc:
1109	printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_N));
1110	return NULL;
1111}
1112
1113static const u_char *
1114isakmp_d_print(const struct isakmp_gen *ext, u_int item_len _U_,
1115	       const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi0 _U_,
1116	       u_int32_t proto0 _U_, int depth _U_)
1117{
1118	const struct isakmp_pl_d *p;
1119	struct isakmp_pl_d d;
1120	const u_int8_t *q;
1121	u_int32_t doi;
1122	u_int32_t proto;
1123	int i;
1124
1125	printf("%s:", NPSTR(ISAKMP_NPTYPE_D));
1126
1127	p = (struct isakmp_pl_d *)ext;
1128	TCHECK(*p);
1129	safememcpy(&d, ext, sizeof(d));
1130	doi = ntohl(d.doi);
1131	proto = d.prot_id;
1132	if (doi != 1) {
1133		printf(" doi=%u", doi);
1134		printf(" proto=%u", proto);
1135	} else {
1136		printf(" doi=ipsec");
1137		printf(" proto=%s", PROTOIDSTR(proto));
1138	}
1139	printf(" spilen=%u", d.spi_size);
1140	printf(" nspi=%u", ntohs(d.num_spi));
1141	printf(" spi=");
1142	q = (u_int8_t *)(p + 1);
1143	for (i = 0; i < ntohs(d.num_spi); i++) {
1144		if (i != 0)
1145			printf(",");
1146		if (!rawprint((caddr_t)q, d.spi_size))
1147			goto trunc;
1148		q += d.spi_size;
1149	}
1150	return q;
1151trunc:
1152	printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_D));
1153	return NULL;
1154}
1155
1156static const u_char *
1157isakmp_vid_print(const struct isakmp_gen *ext,
1158		 u_int item_len _U_, const u_char *ep _U_,
1159		 u_int32_t phase _U_, u_int32_t doi _U_,
1160		 u_int32_t proto _U_, int depth _U_)
1161{
1162	struct isakmp_gen e;
1163
1164	printf("%s:", NPSTR(ISAKMP_NPTYPE_VID));
1165
1166	TCHECK(*ext);
1167	safememcpy(&e, ext, sizeof(e));
1168	printf(" len=%d", ntohs(e.len) - 4);
1169	if (2 < vflag && 4 < ntohs(e.len)) {
1170		printf(" ");
1171		if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
1172			goto trunc;
1173	}
1174	return (u_char *)ext + ntohs(e.len);
1175trunc:
1176	printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_VID));
1177	return NULL;
1178}
1179
1180static const u_char *
1181isakmp_sub0_print(u_char np, const struct isakmp_gen *ext, const u_char *ep,
1182	u_int32_t phase, u_int32_t doi, u_int32_t proto, int depth)
1183{
1184	const u_char *cp;
1185	struct isakmp_gen e;
1186	u_int item_len;
1187
1188	cp = (u_char *)ext;
1189	TCHECK(*ext);
1190	safememcpy(&e, ext, sizeof(e));
1191
1192	/*
1193	 * Since we can't have a payload length of less than 4 bytes,
1194	 * we need to bail out here if the generic header is nonsensical
1195	 * or truncated, otherwise we could loop forever processing
1196	 * zero-length items or otherwise misdissect the packet.
1197	 */
1198	item_len = ntohs(e.len);
1199	if (item_len <= 4)
1200		return NULL;
1201
1202	if (NPFUNC(np)) {
1203		/*
1204		 * XXX - what if item_len is too short, or too long,
1205		 * for this payload type?
1206		 */
1207		cp = (*npfunc[np])(ext, item_len, ep, phase, doi, proto, depth);
1208	} else {
1209		printf("%s", NPSTR(np));
1210		cp += item_len;
1211	}
1212
1213	return cp;
1214trunc:
1215	printf(" [|isakmp]");
1216	return NULL;
1217}
1218
1219static const u_char *
1220isakmp_sub_print(u_char np, const struct isakmp_gen *ext, const u_char *ep,
1221	u_int32_t phase, u_int32_t doi, u_int32_t proto, int depth)
1222{
1223	const u_char *cp;
1224	int i;
1225	struct isakmp_gen e;
1226
1227	cp = (const u_char *)ext;
1228
1229	while (np) {
1230		TCHECK(*ext);
1231
1232		safememcpy(&e, ext, sizeof(e));
1233
1234		TCHECK2(*ext, ntohs(e.len));
1235
1236		depth++;
1237		printf("\n");
1238		for (i = 0; i < depth; i++)
1239			printf("    ");
1240		printf("(");
1241		cp = isakmp_sub0_print(np, ext, ep, phase, doi, proto, depth);
1242		printf(")");
1243		depth--;
1244
1245		if (cp == NULL) {
1246			/* Zero-length subitem */
1247			return NULL;
1248		}
1249
1250		np = e.np;
1251		ext = (struct isakmp_gen *)cp;
1252	}
1253	return cp;
1254trunc:
1255	printf(" [|%s]", NPSTR(np));
1256	return NULL;
1257}
1258
1259static char *
1260numstr(int x)
1261{
1262	static char buf[20];
1263	snprintf(buf, sizeof(buf), "#%d", x);
1264	return buf;
1265}
1266
1267/*
1268 * some compiler tries to optimize memcpy(), using the alignment constraint
1269 * on the argument pointer type.  by using this function, we try to avoid the
1270 * optimization.
1271 */
1272static void
1273safememcpy(void *p, const void *q, size_t l)
1274{
1275	memcpy(p, q, l);
1276}
1277
1278void
1279isakmp_print(netdissect_options *ndo,
1280	     const u_char *bp, u_int length,
1281	     const u_char *bp2)
1282{
1283	const struct isakmp *p;
1284	struct isakmp base;
1285	const u_char *ep;
1286	u_char np;
1287	int i;
1288	int phase;
1289	int major, minor;
1290
1291	p = (const struct isakmp *)bp;
1292	ep = ndo->ndo_snapend;
1293
1294	if ((struct isakmp *)ep < p + 1) {
1295		printf("[|isakmp]");
1296		return;
1297	}
1298
1299	safememcpy(&base, p, sizeof(base));
1300
1301	printf("isakmp");
1302	if (vflag) {
1303		major = (base.vers & ISAKMP_VERS_MAJOR)
1304				>> ISAKMP_VERS_MAJOR_SHIFT;
1305		minor = (base.vers & ISAKMP_VERS_MINOR)
1306				>> ISAKMP_VERS_MINOR_SHIFT;
1307		printf(" %d.%d", major, minor);
1308	}
1309
1310	if (vflag) {
1311		printf(" msgid ");
1312		rawprint((caddr_t)&base.msgid, sizeof(base.msgid));
1313	}
1314
1315	if (1 < vflag) {
1316		printf(" cookie ");
1317		rawprint((caddr_t)&base.i_ck, sizeof(base.i_ck));
1318		printf("->");
1319		rawprint((caddr_t)&base.r_ck, sizeof(base.r_ck));
1320	}
1321	printf(":");
1322
1323	phase = (*(u_int32_t *)base.msgid == 0) ? 1 : 2;
1324	if (phase == 1)
1325		printf(" phase %d", phase);
1326	else
1327		printf(" phase %d/others", phase);
1328
1329	i = cookie_find(&base.i_ck);
1330	if (i < 0) {
1331		if (iszero((u_char *)&base.r_ck, sizeof(base.r_ck))) {
1332			/* the first packet */
1333			printf(" I");
1334			if (bp2)
1335				cookie_record(&base.i_ck, bp2);
1336		} else
1337			printf(" ?");
1338	} else {
1339		if (bp2 && cookie_isinitiator(i, bp2))
1340			printf(" I");
1341		else if (bp2 && cookie_isresponder(i, bp2))
1342			printf(" R");
1343		else
1344			printf(" ?");
1345	}
1346
1347	printf(" %s", ETYPESTR(base.etype));
1348	if (base.flags) {
1349		printf("[%s%s]", base.flags & ISAKMP_FLAG_E ? "E" : "",
1350			base.flags & ISAKMP_FLAG_C ? "C" : "");
1351	}
1352
1353	if (vflag) {
1354		const struct isakmp_gen *ext;
1355		int nparen;
1356
1357#define CHECKLEN(p, np) \
1358		if (ep < (u_char *)(p)) {				\
1359			printf(" [|%s]", NPSTR(np));			\
1360			goto done;					\
1361		}
1362
1363		printf(":");
1364
1365		/* regardless of phase... */
1366		if (base.flags & ISAKMP_FLAG_E) {
1367			/*
1368			 * encrypted, nothing we can do right now.
1369			 * we hope to decrypt the packet in the future...
1370			 */
1371			printf(" [encrypted %s]", NPSTR(base.np));
1372			goto done;
1373		}
1374
1375		nparen = 0;
1376		CHECKLEN(p + 1, base.np)
1377
1378		np = base.np;
1379		ext = (struct isakmp_gen *)(p + 1);
1380		isakmp_sub_print(np, ext, ep, phase, 0, 0, 0);
1381	}
1382
1383done:
1384	if (vflag) {
1385		if (ntohl(base.len) != length) {
1386			printf(" (len mismatch: isakmp %u/ip %u)",
1387				(u_int32_t)ntohl(base.len), length);
1388		}
1389	}
1390}
1391
1392void
1393isakmp_rfc3948_print(netdissect_options *ndo,
1394		     const u_char *bp, u_int length,
1395		     const u_char *bp2)
1396{
1397	const u_char *ep;
1398	ep = ndo->ndo_snapend;
1399
1400	if(length == 1 && bp[0]==0xff) {
1401		ND_PRINT((ndo, "isakmp-nat-keep-alive"));
1402		return;
1403	}
1404
1405	if(length < 4) {
1406		goto trunc;
1407	}
1408
1409	/*
1410	 * see if this is an IKE packet
1411	 */
1412	if(bp[0]==0 && bp[1]==0 && bp[2]==0 && bp[3]==0) {
1413		ND_PRINT((ndo, "NONESP-encap: "));
1414		isakmp_print(ndo, bp+4, length-4, bp2);
1415		return;
1416	}
1417
1418	/* must be an ESP packet */
1419	{
1420		int nh, enh, padlen;
1421		int advance;
1422
1423		ND_PRINT((ndo, "UDP-encap: "));
1424
1425		advance = esp_print(ndo, bp, length, bp2, &enh, &padlen);
1426		if(advance <= 0)
1427			return;
1428
1429		bp += advance;
1430		length -= advance + padlen;
1431		nh = enh & 0xff;
1432
1433		ip_print_inner(ndo, bp, length, nh, bp2);
1434		return;
1435	}
1436
1437trunc:
1438	printf("[|isakmp]");
1439	return;
1440}
1441
1442/*
1443 * Local Variables:
1444 * c-style: whitesmith
1445 * c-basic-offset: 8
1446 * End:
1447 */
1448