print-isakmp.c revision 124488
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[] =
33    "@(#) $Header: /tcpdump/master/tcpdump/print-isakmp.c,v 1.29.2.2 2003/02/26 05:58:39 fenner Exp $ (LBL)";
34#endif
35
36#ifdef HAVE_CONFIG_H
37#include "config.h"
38#endif
39
40#include <string.h>
41#include <ctype.h>
42#include <sys/param.h>
43#include <sys/time.h>
44#include <sys/socket.h>
45
46#include <netinet/in.h>
47
48#include <stdio.h>
49#include <netdb.h>
50
51#include "isakmp.h"
52#include "ipsec_doi.h"
53#include "oakley.h"
54#include "interface.h"
55#include "addrtoname.h"
56#include "extract.h"                    /* must come after interface.h */
57
58#include "ip.h"
59#ifdef INET6
60#include "ip6.h"
61#endif
62
63#ifndef HAVE_SOCKADDR_STORAGE
64#define sockaddr_storage sockaddr
65#endif
66
67static u_char *isakmp_sa_print(struct isakmp_gen *, u_char *, u_int32_t,
68	u_int32_t, u_int32_t);
69static u_char *isakmp_p_print(struct isakmp_gen *, u_char *, u_int32_t,
70	u_int32_t, u_int32_t);
71static u_char *isakmp_t_print(struct isakmp_gen *, u_char *, u_int32_t,
72	u_int32_t, u_int32_t);
73static u_char *isakmp_ke_print(struct isakmp_gen *, u_char *, u_int32_t,
74	u_int32_t, u_int32_t);
75static u_char *isakmp_id_print(struct isakmp_gen *, u_char *, u_int32_t,
76	u_int32_t, u_int32_t);
77static u_char *isakmp_cert_print(struct isakmp_gen *, u_char *, u_int32_t,
78	u_int32_t, u_int32_t);
79static u_char *isakmp_cr_print(struct isakmp_gen *, u_char *, u_int32_t,
80	u_int32_t, u_int32_t);
81static u_char *isakmp_sig_print(struct isakmp_gen *, u_char *, u_int32_t,
82	u_int32_t, u_int32_t);
83static u_char *isakmp_hash_print(struct isakmp_gen *, u_char *,
84	u_int32_t, u_int32_t, u_int32_t);
85static u_char *isakmp_nonce_print(struct isakmp_gen *, u_char *,
86	u_int32_t, u_int32_t, u_int32_t);
87static u_char *isakmp_n_print(struct isakmp_gen *, u_char *, u_int32_t,
88	u_int32_t, u_int32_t);
89static u_char *isakmp_d_print(struct isakmp_gen *, u_char *, u_int32_t,
90	u_int32_t, u_int32_t);
91static u_char *isakmp_vid_print(struct isakmp_gen *, u_char *, u_int32_t,
92	u_int32_t, u_int32_t);
93static u_char *isakmp_sub0_print(u_char, struct isakmp_gen *, u_char *,
94	u_int32_t, u_int32_t, u_int32_t);
95static u_char *isakmp_sub_print(u_char, struct isakmp_gen *, u_char *,
96	u_int32_t, u_int32_t, u_int32_t);
97static char *numstr(int);
98static void safememcpy(void *, void *, size_t);
99
100#define MAXINITIATORS	20
101int ninitiator = 0;
102struct {
103	cookie_t initiator;
104	struct sockaddr_storage iaddr;
105	struct sockaddr_storage raddr;
106} cookiecache[MAXINITIATORS];
107
108/* protocol id */
109static char *protoidstr[] = {
110	NULL, "isakmp", "ipsec-ah", "ipsec-esp", "ipcomp",
111};
112
113/* isakmp->np */
114static char *npstr[] = {
115	"none", "sa", "p", "t", "ke", "id", "cert", "cr", "hash",
116	"sig", "nonce", "n", "d", "vid"
117};
118
119/* isakmp->np */
120static u_char *(*npfunc[])(struct isakmp_gen *, u_char *, u_int32_t,
121		u_int32_t, u_int32_t) = {
122	NULL,
123	isakmp_sa_print,
124	isakmp_p_print,
125	isakmp_t_print,
126	isakmp_ke_print,
127	isakmp_id_print,
128	isakmp_cert_print,
129	isakmp_cr_print,
130	isakmp_hash_print,
131	isakmp_sig_print,
132	isakmp_nonce_print,
133	isakmp_n_print,
134	isakmp_d_print,
135	isakmp_vid_print,
136};
137
138/* isakmp->etype */
139static char *etypestr[] = {
140	"none", "base", "ident", "auth", "agg", "inf", NULL, NULL,
141	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
142	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
143	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
144	"oakley-quick", "oakley-newgroup",
145};
146
147#define STR_OR_ID(x, tab) \
148	(((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)])	? tab[(x)] : numstr(x))
149#define PROTOIDSTR(x)	STR_OR_ID(x, protoidstr)
150#define NPSTR(x)	STR_OR_ID(x, npstr)
151#define ETYPESTR(x)	STR_OR_ID(x, etypestr)
152
153#define NPFUNC(x) \
154	(((x) < sizeof(npfunc)/sizeof(npfunc[0]) && npfunc[(x)]) \
155		? npfunc[(x)] : NULL)
156
157static int
158iszero(u_char *p, size_t l)
159{
160	while (l--) {
161		if (*p++)
162			return 0;
163	}
164	return 1;
165}
166
167/* find cookie from initiator cache */
168static int
169cookie_find(cookie_t *in)
170{
171	int i;
172
173	for (i = 0; i < MAXINITIATORS; i++) {
174		if (memcmp(in, &cookiecache[i].initiator, sizeof(*in)) == 0)
175			return i;
176	}
177
178	return -1;
179}
180
181/* record initiator */
182static void
183cookie_record(cookie_t *in, const u_char *bp2)
184{
185	int i;
186	struct ip *ip;
187	struct sockaddr_in *sin;
188#ifdef INET6
189	struct ip6_hdr *ip6;
190	struct sockaddr_in6 *sin6;
191#endif
192
193	i = cookie_find(in);
194	if (0 <= i) {
195		ninitiator = (i + 1) % MAXINITIATORS;
196		return;
197	}
198
199	ip = (struct ip *)bp2;
200	switch (IP_V(ip)) {
201	case 4:
202		memset(&cookiecache[ninitiator].iaddr, 0,
203			sizeof(cookiecache[ninitiator].iaddr));
204		memset(&cookiecache[ninitiator].raddr, 0,
205			sizeof(cookiecache[ninitiator].raddr));
206
207		sin = (struct sockaddr_in *)&cookiecache[ninitiator].iaddr;
208#ifdef HAVE_SOCKADDR_SA_LEN
209		sin->sin_len = sizeof(struct sockaddr_in);
210#endif
211		sin->sin_family = AF_INET;
212		memcpy(&sin->sin_addr, &ip->ip_src, sizeof(ip->ip_src));
213		sin = (struct sockaddr_in *)&cookiecache[ninitiator].raddr;
214#ifdef HAVE_SOCKADDR_SA_LEN
215		sin->sin_len = sizeof(struct sockaddr_in);
216#endif
217		sin->sin_family = AF_INET;
218		memcpy(&sin->sin_addr, &ip->ip_dst, sizeof(ip->ip_dst));
219		break;
220#ifdef INET6
221	case 6:
222		memset(&cookiecache[ninitiator].iaddr, 0,
223			sizeof(cookiecache[ninitiator].iaddr));
224		memset(&cookiecache[ninitiator].raddr, 0,
225			sizeof(cookiecache[ninitiator].raddr));
226
227		ip6 = (struct ip6_hdr *)bp2;
228		sin6 = (struct sockaddr_in6 *)&cookiecache[ninitiator].iaddr;
229#ifdef HAVE_SOCKADDR_SA_LEN
230		sin6->sin6_len = sizeof(struct sockaddr_in6);
231#endif
232		sin6->sin6_family = AF_INET6;
233		memcpy(&sin6->sin6_addr, &ip6->ip6_src, sizeof(ip6->ip6_src));
234		sin6 = (struct sockaddr_in6 *)&cookiecache[ninitiator].raddr;
235#ifdef HAVE_SOCKADDR_SA_LEN
236		sin6->sin6_len = sizeof(struct sockaddr_in6);
237#endif
238		sin6->sin6_family = AF_INET6;
239		memcpy(&sin6->sin6_addr, &ip6->ip6_dst, sizeof(ip6->ip6_dst));
240		break;
241#endif
242	default:
243		return;
244	}
245	memcpy(&cookiecache[ninitiator].initiator, in, sizeof(*in));
246	ninitiator = (ninitiator + 1) % MAXINITIATORS;
247}
248
249#define cookie_isinitiator(x, y)	cookie_sidecheck((x), (y), 1)
250#define cookie_isresponder(x, y)	cookie_sidecheck((x), (y), 0)
251static int
252cookie_sidecheck(int i, const u_char *bp2, int initiator)
253{
254	struct sockaddr_storage ss;
255	struct sockaddr *sa;
256	struct ip *ip;
257	struct sockaddr_in *sin;
258#ifdef INET6
259	struct ip6_hdr *ip6;
260	struct sockaddr_in6 *sin6;
261#endif
262	int salen;
263
264	memset(&ss, 0, sizeof(ss));
265	ip = (struct ip *)bp2;
266	switch (IP_V(ip)) {
267	case 4:
268		sin = (struct sockaddr_in *)&ss;
269#ifdef HAVE_SOCKADDR_SA_LEN
270		sin->sin_len = sizeof(struct sockaddr_in);
271#endif
272		sin->sin_family = AF_INET;
273		memcpy(&sin->sin_addr, &ip->ip_src, sizeof(ip->ip_src));
274		break;
275#ifdef INET6
276	case 6:
277		ip6 = (struct ip6_hdr *)bp2;
278		sin6 = (struct sockaddr_in6 *)&ss;
279#ifdef HAVE_SOCKADDR_SA_LEN
280		sin6->sin6_len = sizeof(struct sockaddr_in6);
281#endif
282		sin6->sin6_family = AF_INET6;
283		memcpy(&sin6->sin6_addr, &ip6->ip6_src, sizeof(ip6->ip6_src));
284		break;
285#endif
286	default:
287		return 0;
288	}
289
290	sa = (struct sockaddr *)&ss;
291	if (initiator) {
292		if (sa->sa_family != ((struct sockaddr *)&cookiecache[i].iaddr)->sa_family)
293			return 0;
294#ifdef HAVE_SOCKADDR_SA_LEN
295		salen = sa->sa_len;
296#else
297#ifdef INET6
298		if (sa->sa_family == AF_INET6)
299			salen = sizeof(struct sockaddr_in6);
300		else
301			salen = sizeof(struct sockaddr);
302#else
303		salen = sizeof(struct sockaddr);
304#endif
305#endif
306		if (memcmp(&ss, &cookiecache[i].iaddr, salen) == 0)
307			return 1;
308	} else {
309		if (sa->sa_family != ((struct sockaddr *)&cookiecache[i].raddr)->sa_family)
310			return 0;
311#ifdef HAVE_SOCKADDR_SA_LEN
312		salen = sa->sa_len;
313#else
314#ifdef INET6
315		if (sa->sa_family == AF_INET6)
316			salen = sizeof(struct sockaddr_in6);
317		else
318			salen = sizeof(struct sockaddr);
319#else
320		salen = sizeof(struct sockaddr);
321#endif
322#endif
323		if (memcmp(&ss, &cookiecache[i].raddr, salen) == 0)
324			return 1;
325	}
326	return 0;
327}
328
329static void
330rawprint(caddr_t loc, size_t len)
331{
332	static u_char *p;
333	int i;
334
335	TCHECK2(*loc, len);
336
337	p = (u_char *)loc;
338	for (i = 0; i < len; i++)
339		printf("%02x", p[i] & 0xff);
340trunc:
341
342}
343
344struct attrmap {
345	char *type;
346	int nvalue;
347	char *value[30];	/*XXX*/
348};
349
350static u_char *
351isakmp_attrmap_print(u_char *p, u_char *ep, struct attrmap *map, size_t nmap)
352{
353	u_int16_t *q;
354	int totlen;
355	u_int32_t t, v;
356
357	q = (u_int16_t *)p;
358	if (p[0] & 0x80)
359		totlen = 4;
360	else
361		totlen = 4 + ntohs(q[1]);
362	if (ep < p + totlen) {
363		printf("[|attr]");
364		return ep + 1;
365	}
366
367	printf("(");
368	t = ntohs(q[0]) & 0x7fff;
369	if (map && t < nmap && map[t].type)
370		printf("type=%s ", map[t].type);
371	else
372		printf("type=#%d ", t);
373	if (p[0] & 0x80) {
374		printf("value=");
375		v = ntohs(q[1]);
376		if (map && t < nmap && v < map[t].nvalue && map[t].value[v])
377			printf("%s", map[t].value[v]);
378		else
379			rawprint((caddr_t)&q[1], 2);
380	} else {
381		printf("len=%d value=", ntohs(q[1]));
382		rawprint((caddr_t)&p[4], ntohs(q[1]));
383	}
384	printf(")");
385	return p + totlen;
386}
387
388static u_char *
389isakmp_attr_print(u_char *p, u_char *ep)
390{
391	u_int16_t *q;
392	int totlen;
393	u_int32_t t;
394
395	q = (u_int16_t *)p;
396	if (p[0] & 0x80)
397		totlen = 4;
398	else
399		totlen = 4 + ntohs(q[1]);
400	if (ep < p + totlen) {
401		printf("[|attr]");
402		return ep + 1;
403	}
404
405	printf("(");
406	t = ntohs(q[0]) & 0x7fff;
407	printf("type=#%d ", t);
408	if (p[0] & 0x80) {
409		printf("value=");
410		t = q[1];
411		rawprint((caddr_t)&q[1], 2);
412	} else {
413		printf("len=%d value=", ntohs(q[1]));
414		rawprint((caddr_t)&p[2], ntohs(q[1]));
415	}
416	printf(")");
417	return p + totlen;
418}
419
420static u_char *
421isakmp_sa_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
422	u_int32_t doi0, u_int32_t proto0)
423{
424	struct isakmp_pl_sa *p, sa;
425	u_int32_t *q;
426	u_int32_t doi, sit, ident;
427	u_char *cp, *np;
428	int t;
429
430	printf("%s:", NPSTR(ISAKMP_NPTYPE_SA));
431
432	p = (struct isakmp_pl_sa *)ext;
433	safememcpy(&sa, ext, sizeof(sa));
434	doi = ntohl(sa.doi);
435	sit = ntohl(sa.sit);
436	if (doi != 1) {
437		printf(" doi=%d", doi);
438		printf(" situation=%u", (u_int32_t)ntohl(sa.sit));
439		return (u_char *)(p + 1);
440	}
441
442	printf(" doi=ipsec");
443	q = (u_int32_t *)&sa.sit;
444	printf(" situation=");
445	t = 0;
446	if (sit & 0x01) {
447		printf("identity");
448		t++;
449	}
450	if (sit & 0x02) {
451		printf("%ssecrecy", t ? "+" : "");
452		t++;
453	}
454	if (sit & 0x04)
455		printf("%sintegrity", t ? "+" : "");
456
457	np = (u_char *)ext + sizeof(sa);
458	if (sit != 0x01) {
459		safememcpy(&ident, ext + 1, sizeof(ident));
460		printf(" ident=%u", (u_int32_t)ntohl(ident));
461		np += sizeof(ident);
462	}
463
464	ext = (struct isakmp_gen *)np;
465
466	cp = isakmp_sub_print(ISAKMP_NPTYPE_P, ext, ep, phase, doi, proto0);
467
468	return cp;
469}
470
471static u_char *
472isakmp_p_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
473	u_int32_t doi0, u_int32_t proto0)
474{
475	struct isakmp_pl_p *p, prop;
476	u_char *cp;
477
478	printf("%s:", NPSTR(ISAKMP_NPTYPE_P));
479
480	p = (struct isakmp_pl_p *)ext;
481	safememcpy(&prop, ext, sizeof(prop));
482	printf(" #%d protoid=%s transform=%d",
483		prop.p_no, PROTOIDSTR(prop.prot_id), prop.num_t);
484	if (prop.spi_size) {
485		printf(" spi=");
486		rawprint((caddr_t)(p + 1), prop.spi_size);
487	}
488
489	ext = (struct isakmp_gen *)((u_char *)(p + 1) + prop.spi_size);
490
491	cp = isakmp_sub_print(ISAKMP_NPTYPE_T, ext, ep, phase, doi0,
492		prop.prot_id);
493
494	return cp;
495}
496
497static char *isakmp_p_map[] = {
498	NULL, "ike",
499};
500
501static char *ah_p_map[] = {
502	NULL, "(reserved)", "md5", "sha", "1des",
503	"sha2-256", "sha2-384", "sha2-512",
504};
505
506static char *esp_p_map[] = {
507	NULL, "1des-iv64", "1des", "3des", "rc5", "idea", "cast",
508	"blowfish", "3idea", "1des-iv32", "rc4", "null", "aes"
509};
510
511static char *ipcomp_p_map[] = {
512	NULL, "oui", "deflate", "lzs",
513};
514
515struct attrmap ipsec_t_map[] = {
516	{ NULL,	0, },
517	{ "lifetype", 3, { NULL, "sec", "kb", }, },
518	{ "life", 0, },
519	{ "group desc", 5,	{ NULL, "modp768", "modp1024", "EC2N 2^155",
520				  "EC2N 2^185", }, },
521	{ "enc mode", 3, { NULL, "tunnel", "transport", }, },
522	{ "auth", 5, { NULL, "hmac-md5", "hmac-sha1", "1des-mac", "keyed", }, },
523	{ "keylen", 0, },
524	{ "rounds", 0, },
525	{ "dictsize", 0, },
526	{ "privalg", 0, },
527};
528
529struct attrmap oakley_t_map[] = {
530	{ NULL,	0 },
531	{ "enc", 8,	{ NULL, "1des", "idea", "blowfish", "rc5",
532		 	  "3des", "cast", "aes", }, },
533	{ "hash", 7,	{ NULL, "md5", "sha1", "tiger",
534			  "sha2-256", "sha2-384", "sha2-512", }, },
535	{ "auth", 6,	{ NULL, "preshared", "dss", "rsa sig", "rsa enc",
536			  "rsa enc revised", }, },
537	{ "group desc", 5,	{ NULL, "modp768", "modp1024", "EC2N 2^155",
538				  "EC2N 2^185", }, },
539	{ "group type", 4,	{ NULL, "MODP", "ECP", "EC2N", }, },
540	{ "group prime", 0, },
541	{ "group gen1", 0, },
542	{ "group gen2", 0, },
543	{ "group curve A", 0, },
544	{ "group curve B", 0, },
545	{ "lifetype", 3,	{ NULL, "sec", "kb", }, },
546	{ "lifeduration", 0, },
547	{ "prf", 0, },
548	{ "keylen", 0, },
549	{ "field", 0, },
550	{ "order", 0, },
551};
552
553static u_char *
554isakmp_t_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
555	u_int32_t doi, u_int32_t proto)
556{
557	struct isakmp_pl_t *p, t;
558	u_char *cp;
559	char *idstr;
560	struct attrmap *map;
561	size_t nmap;
562	u_char *ep2;
563
564	printf("%s:", NPSTR(ISAKMP_NPTYPE_T));
565
566	p = (struct isakmp_pl_t *)ext;
567	safememcpy(&t, ext, sizeof(t));
568
569	switch (proto) {
570	case 1:
571		idstr = STR_OR_ID(t.t_id, isakmp_p_map);
572		map = oakley_t_map;
573		nmap = sizeof(oakley_t_map)/sizeof(oakley_t_map[0]);
574		break;
575	case 2:
576		idstr = STR_OR_ID(t.t_id, ah_p_map);
577		map = ipsec_t_map;
578		nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
579		break;
580	case 3:
581		idstr = STR_OR_ID(t.t_id, esp_p_map);
582		map = ipsec_t_map;
583		nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
584		break;
585	case 4:
586		idstr = STR_OR_ID(t.t_id, ipcomp_p_map);
587		map = ipsec_t_map;
588		nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
589		break;
590	default:
591		idstr = NULL;
592		map = NULL;
593		nmap = 0;
594		break;
595	}
596
597	if (idstr)
598		printf(" #%d id=%s ", t.t_no, idstr);
599	else
600		printf(" #%d id=%d ", t.t_no, t.t_id);
601	cp = (u_char *)(p + 1);
602	ep2 = (u_char *)p + ntohs(t.h.len);
603	while (cp < ep && cp < ep2) {
604		if (map && nmap) {
605			cp = isakmp_attrmap_print(cp, (ep < ep2) ? ep : ep2,
606				map, nmap);
607		} else
608			cp = isakmp_attr_print(cp, (ep < ep2) ? ep : ep2);
609	}
610	if (ep < ep2)
611		printf("...");
612	return cp;
613}
614
615static u_char *
616isakmp_ke_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
617	u_int32_t doi, u_int32_t proto)
618{
619	struct isakmp_gen e;
620
621	printf("%s:", NPSTR(ISAKMP_NPTYPE_KE));
622
623	safememcpy(&e, ext, sizeof(e));
624	printf(" key len=%d", ntohs(e.len) - 4);
625	if (2 < vflag && 4 < ntohs(e.len)) {
626		printf(" ");
627		rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4);
628	}
629	return (u_char *)ext + ntohs(e.len);
630}
631
632static u_char *
633isakmp_id_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
634	u_int32_t doi, u_int32_t proto)
635{
636#define USE_IPSECDOI_IN_PHASE1	1
637	struct isakmp_pl_id *p, id;
638	static char *idtypestr[] = {
639		"IPv4", "IPv4net", "IPv6", "IPv6net",
640	};
641	static char *ipsecidtypestr[] = {
642		NULL, "IPv4", "FQDN", "user FQDN", "IPv4net", "IPv6",
643		"IPv6net", "IPv4range", "IPv6range", "ASN1 DN", "ASN1 GN",
644		"keyid",
645	};
646	int len;
647	u_char *data;
648
649	printf("%s:", NPSTR(ISAKMP_NPTYPE_ID));
650
651	p = (struct isakmp_pl_id *)ext;
652	safememcpy(&id, ext, sizeof(id));
653	if (sizeof(*p) < id.h.len)
654		data = (u_char *)(p + 1);
655	else
656		data = NULL;
657	len = ntohs(id.h.len) - sizeof(*p);
658
659#if 0 /*debug*/
660	printf(" [phase=%d doi=%d proto=%d]", phase, doi, proto);
661#endif
662	switch (phase) {
663#ifndef USE_IPSECDOI_IN_PHASE1
664	case 1:
665#endif
666	default:
667		printf(" idtype=%s", STR_OR_ID(id.d.id_type, idtypestr));
668		printf(" doi_data=%u",
669			(u_int32_t)(ntohl(id.d.doi_data) & 0xffffff));
670		break;
671
672#ifdef USE_IPSECDOI_IN_PHASE1
673	case 1:
674#endif
675	case 2:
676	    {
677		struct ipsecdoi_id *p, id;
678		struct protoent *pe;
679
680		p = (struct ipsecdoi_id *)ext;
681		safememcpy(&id, ext, sizeof(id));
682		printf(" idtype=%s", STR_OR_ID(id.type, ipsecidtypestr));
683		if (id.proto_id) {
684			setprotoent(1);
685			pe = getprotobynumber(id.proto_id);
686			if (pe)
687				printf(" protoid=%s", pe->p_name);
688			endprotoent();
689		} else {
690			/* it DOES NOT mean IPPROTO_IP! */
691			printf(" protoid=%s", "0");
692		}
693		printf(" port=%d", ntohs(id.port));
694		if (!len)
695			break;
696		switch (id.type) {
697		case IPSECDOI_ID_IPV4_ADDR:
698			printf(" len=%d %s", len, ipaddr_string(data));
699			len = 0;
700			break;
701		case IPSECDOI_ID_FQDN:
702		case IPSECDOI_ID_USER_FQDN:
703		    {
704			int i;
705			printf(" len=%d ", len);
706			for (i = 0; i < len; i++)
707				safeputchar(data[i]);
708			len = 0;
709			break;
710		    }
711		case IPSECDOI_ID_IPV4_ADDR_SUBNET:
712		    {
713			u_char *mask;
714			mask = data + sizeof(struct in_addr);
715			printf(" len=%d %s/%u.%u.%u.%u", len,
716				ipaddr_string(data),
717				mask[0], mask[1], mask[2], mask[3]);
718			len = 0;
719			break;
720		    }
721#ifdef INET6
722		case IPSECDOI_ID_IPV6_ADDR:
723			printf(" len=%d %s", len, ip6addr_string(data));
724			len = 0;
725			break;
726		case IPSECDOI_ID_IPV6_ADDR_SUBNET:
727		    {
728			u_int32_t *mask;
729			mask = (u_int32_t *)(data + sizeof(struct in6_addr));
730			/*XXX*/
731			printf(" len=%d %s/0x%08x%08x%08x%08x", len,
732				ip6addr_string(data),
733				mask[0], mask[1], mask[2], mask[3]);
734			len = 0;
735			break;
736		    }
737#endif /*INET6*/
738		case IPSECDOI_ID_IPV4_ADDR_RANGE:
739			printf(" len=%d %s-%s", len, ipaddr_string(data),
740				ipaddr_string(data + sizeof(struct in_addr)));
741			len = 0;
742			break;
743#ifdef INET6
744		case IPSECDOI_ID_IPV6_ADDR_RANGE:
745			printf(" len=%d %s-%s", len, ip6addr_string(data),
746				ip6addr_string(data + sizeof(struct in6_addr)));
747			len = 0;
748			break;
749#endif /*INET6*/
750		case IPSECDOI_ID_DER_ASN1_DN:
751		case IPSECDOI_ID_DER_ASN1_GN:
752		case IPSECDOI_ID_KEY_ID:
753			break;
754		}
755		break;
756	    }
757	}
758	if (data && len) {
759		printf(" len=%d", len);
760		if (2 < vflag) {
761			printf(" ");
762			rawprint((caddr_t)data, len);
763		}
764	}
765	return (u_char *)ext + ntohs(id.h.len);
766}
767
768static u_char *
769isakmp_cert_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
770	u_int32_t doi0, u_int32_t proto0)
771{
772	struct isakmp_pl_cert *p, cert;
773	static char *certstr[] = {
774		"none",	"pkcs7", "pgp", "dns",
775		"x509sign", "x509ke", "kerberos", "crl",
776		"arl", "spki", "x509attr",
777	};
778
779	printf("%s:", NPSTR(ISAKMP_NPTYPE_CERT));
780
781	p = (struct isakmp_pl_cert *)ext;
782	safememcpy(&cert, ext, sizeof(cert));
783	printf(" len=%d", ntohs(cert.h.len) - 4);
784	printf(" type=%s", STR_OR_ID((cert.encode), certstr));
785	if (2 < vflag && 4 < ntohs(cert.h.len)) {
786		printf(" ");
787		rawprint((caddr_t)(ext + 1), ntohs(cert.h.len) - 4);
788	}
789	return (u_char *)ext + ntohs(cert.h.len);
790}
791
792static u_char *
793isakmp_cr_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
794	u_int32_t doi0, u_int32_t proto0)
795{
796	struct isakmp_pl_cert *p, cert;
797	static char *certstr[] = {
798		"none",	"pkcs7", "pgp", "dns",
799		"x509sign", "x509ke", "kerberos", "crl",
800		"arl", "spki", "x509attr",
801	};
802
803	printf("%s:", NPSTR(ISAKMP_NPTYPE_CR));
804
805	p = (struct isakmp_pl_cert *)ext;
806	safememcpy(&cert, ext, sizeof(cert));
807	printf(" len=%d", ntohs(cert.h.len) - 4);
808	printf(" type=%s", STR_OR_ID((cert.encode), certstr));
809	if (2 < vflag && 4 < ntohs(cert.h.len)) {
810		printf(" ");
811		rawprint((caddr_t)(ext + 1), ntohs(cert.h.len) - 4);
812	}
813	return (u_char *)ext + ntohs(cert.h.len);
814}
815
816static u_char *
817isakmp_hash_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
818	u_int32_t doi, u_int32_t proto)
819{
820	struct isakmp_gen e;
821
822	printf("%s:", NPSTR(ISAKMP_NPTYPE_HASH));
823
824	safememcpy(&e, ext, sizeof(e));
825	printf(" len=%d", ntohs(e.len) - 4);
826	if (2 < vflag && 4 < ntohs(e.len)) {
827		printf(" ");
828		rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4);
829	}
830	return (u_char *)ext + ntohs(e.len);
831}
832
833static u_char *
834isakmp_sig_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
835	u_int32_t doi, u_int32_t proto)
836{
837	struct isakmp_gen e;
838
839	printf("%s:", NPSTR(ISAKMP_NPTYPE_SIG));
840
841	safememcpy(&e, ext, sizeof(e));
842	printf(" len=%d", ntohs(e.len) - 4);
843	if (2 < vflag && 4 < ntohs(e.len)) {
844		printf(" ");
845		rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4);
846	}
847	return (u_char *)ext + ntohs(e.len);
848}
849
850static u_char *
851isakmp_nonce_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
852	u_int32_t doi, u_int32_t proto)
853{
854	struct isakmp_gen e;
855
856	printf("%s:", NPSTR(ISAKMP_NPTYPE_NONCE));
857
858	safememcpy(&e, ext, sizeof(e));
859	printf(" n len=%d", ntohs(e.len) - 4);
860	if (2 < vflag && 4 < ntohs(e.len)) {
861		printf(" ");
862		rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4);
863	}
864	return (u_char *)ext + ntohs(e.len);
865}
866
867static u_char *
868isakmp_n_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
869	u_int32_t doi0, u_int32_t proto0)
870{
871	struct isakmp_pl_n *p, n;
872	u_char *cp;
873	u_char *ep2;
874	u_int32_t doi;
875	u_int32_t proto;
876	static char *notifystr[] = {
877		NULL,				"INVALID-PAYLOAD-TYPE",
878		"DOI-NOT-SUPPORTED",		"SITUATION-NOT-SUPPORTED",
879		"INVALID-COOKIE",		"INVALID-MAJOR-VERSION",
880		"INVALID-MINOR-VERSION",	"INVALID-EXCHANGE-TYPE",
881		"INVALID-FLAGS",		"INVALID-MESSAGE-ID",
882		"INVALID-PROTOCOL-ID",		"INVALID-SPI",
883		"INVALID-TRANSFORM-ID",		"ATTRIBUTES-NOT-SUPPORTED",
884		"NO-PROPOSAL-CHOSEN",		"BAD-PROPOSAL-SYNTAX",
885		"PAYLOAD-MALFORMED",		"INVALID-KEY-INFORMATION",
886		"INVALID-ID-INFORMATION",	"INVALID-CERT-ENCODING",
887		"INVALID-CERTIFICATE",		"CERT-TYPE-UNSUPPORTED",
888		"INVALID-CERT-AUTHORITY",	"INVALID-HASH-INFORMATION",
889		"AUTHENTICATION-FAILED",	"INVALID-SIGNATURE",
890		"ADDRESS-NOTIFICATION",		"NOTIFY-SA-LIFETIME",
891		"CERTIFICATE-UNAVAILABLE",	"UNSUPPORTED-EXCHANGE-TYPE",
892		"UNEQUAL-PAYLOAD-LENGTHS",
893	};
894	static char *ipsecnotifystr[] = {
895		"RESPONDER-LIFETIME",		"REPLAY-STATUS",
896		"INITIAL-CONTACT",
897	};
898/* NOTE: these macro must be called with x in proper range */
899#define NOTIFYSTR(x) \
900	(((x) == 16384) ? "CONNECTED" : STR_OR_ID((x), notifystr))
901#define IPSECNOTIFYSTR(x) \
902	(((x) == 8192) ? "RESERVED" : STR_OR_ID(((x) - 24576), ipsecnotifystr))
903
904	printf("%s:", NPSTR(ISAKMP_NPTYPE_N));
905
906	p = (struct isakmp_pl_n *)ext;
907	safememcpy(&n, ext, sizeof(n));
908	doi = ntohl(n.doi);
909	proto = n.prot_id;
910	if (doi != 1) {
911		printf(" doi=%d", doi);
912		printf(" proto=%d", proto);
913		printf(" type=%s", NOTIFYSTR(ntohs(n.type)));
914		if (n.spi_size) {
915			printf(" spi=");
916			rawprint((caddr_t)(p + 1), n.spi_size);
917		}
918		return (u_char *)(p + 1) + n.spi_size;
919	}
920
921	printf(" doi=ipsec");
922	printf(" proto=%s", PROTOIDSTR(proto));
923	if (ntohs(n.type) < 8192)
924		printf(" type=%s", NOTIFYSTR(ntohs(n.type)));
925	else if (ntohs(n.type) < 16384)
926		printf(" type=%s", IPSECNOTIFYSTR(ntohs(n.type)));
927	else if (ntohs(n.type) < 24576)
928		printf(" type=%s", NOTIFYSTR(ntohs(n.type)));
929	else if (ntohs(n.type) < 40960)
930		printf(" type=%s", IPSECNOTIFYSTR(ntohs(n.type)));
931	else
932		printf(" type=%s", NOTIFYSTR(ntohs(n.type)));
933	if (n.spi_size) {
934		printf(" spi=");
935		rawprint((caddr_t)(p + 1), n.spi_size);
936	}
937
938	cp = (u_char *)(p + 1) + n.spi_size;
939	ep2 = (u_char *)p + ntohs(n.h.len);
940
941	if (cp < ep) {
942		printf(" orig=(");
943		switch (ntohs(n.type)) {
944		case IPSECDOI_NTYPE_RESPONDER_LIFETIME:
945		    {
946			struct attrmap *map = oakley_t_map;
947			size_t nmap = sizeof(oakley_t_map)/sizeof(oakley_t_map[0]);
948			while (cp < ep && cp < ep2) {
949				cp = isakmp_attrmap_print(cp,
950					(ep < ep2) ? ep : ep2, map, nmap);
951			}
952			break;
953		    }
954		case IPSECDOI_NTYPE_REPLAY_STATUS:
955			printf("replay detection %sabled",
956				(*(u_int32_t *)cp) ? "en" : "dis");
957			break;
958		case ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN:
959			isakmp_sub_print(ISAKMP_NPTYPE_SA,
960				(struct isakmp_gen *)cp, ep, phase, doi, proto);
961			break;
962		default:
963			/* NULL is dummy */
964			isakmp_print(cp,
965				ntohs(n.h.len) - sizeof(*p) - n.spi_size,
966				NULL);
967		}
968		printf(")");
969	}
970	return (u_char *)ext + ntohs(n.h.len);
971}
972
973static u_char *
974isakmp_d_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
975	u_int32_t doi0, u_int32_t proto0)
976{
977	struct isakmp_pl_d *p, d;
978	u_int8_t *q;
979	u_int32_t doi;
980	u_int32_t proto;
981	int i;
982
983	printf("%s:", NPSTR(ISAKMP_NPTYPE_D));
984
985	p = (struct isakmp_pl_d *)ext;
986	safememcpy(&d, ext, sizeof(d));
987	doi = ntohl(d.doi);
988	proto = d.prot_id;
989	if (doi != 1) {
990		printf(" doi=%u", doi);
991		printf(" proto=%u", proto);
992	} else {
993		printf(" doi=ipsec");
994		printf(" proto=%s", PROTOIDSTR(proto));
995	}
996	printf(" spilen=%u", d.spi_size);
997	printf(" nspi=%u", ntohs(d.num_spi));
998	printf(" spi=");
999	q = (u_int8_t *)(p + 1);
1000	for (i = 0; i < ntohs(d.num_spi); i++) {
1001		if (i != 0)
1002			printf(",");
1003		rawprint((caddr_t)q, d.spi_size);
1004		q += d.spi_size;
1005	}
1006	return q;
1007}
1008
1009static u_char *
1010isakmp_vid_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
1011	u_int32_t doi, u_int32_t proto)
1012{
1013	struct isakmp_gen e;
1014
1015	printf("%s:", NPSTR(ISAKMP_NPTYPE_VID));
1016
1017	safememcpy(&e, ext, sizeof(e));
1018	printf(" len=%d", ntohs(e.len) - 4);
1019	if (2 < vflag && 4 < ntohs(e.len)) {
1020		printf(" ");
1021		rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4);
1022	}
1023	return (u_char *)ext + ntohs(e.len);
1024}
1025
1026static u_char *
1027isakmp_sub0_print(u_char np, struct isakmp_gen *ext, u_char *ep,
1028	u_int32_t phase, u_int32_t doi, u_int32_t proto)
1029{
1030	u_char *cp;
1031	struct isakmp_gen e;
1032	u_int item_len;
1033
1034	cp = (u_char *)ext;
1035	safememcpy(&e, ext, sizeof(e));
1036
1037	if (NPFUNC(np))
1038		cp = (*NPFUNC(np))(ext, ep, phase, doi, proto);
1039	else {
1040		printf("%s", NPSTR(np));
1041		item_len = ntohs(e.len);
1042		if (item_len == 0) {
1043			/*
1044			 * We don't want to loop forever processing this
1045			 * bogus (zero-length) item; return NULL so that
1046			 * we stop dissecting.
1047			 */
1048			cp = NULL;
1049		} else
1050			cp += item_len;
1051	}
1052	return cp;
1053}
1054
1055static u_char *
1056isakmp_sub_print(u_char np, struct isakmp_gen *ext, u_char *ep,
1057	u_int32_t phase, u_int32_t doi, u_int32_t proto)
1058{
1059	u_char *cp;
1060	static int depth = 0;
1061	int i;
1062	struct isakmp_gen e;
1063
1064	cp = (u_char *)ext;
1065
1066	while (np) {
1067		TCHECK2(*ext, sizeof(e));
1068
1069		safememcpy(&e, ext, sizeof(e));
1070
1071		if (ep < (u_char *)ext + ntohs(e.len)) {
1072			printf(" [|%s]", NPSTR(np));
1073			cp = ep + 1;
1074			break;
1075		}
1076		depth++;
1077		printf("\n");
1078		for (i = 0; i < depth; i++)
1079			printf("    ");
1080		printf("(");
1081		cp = isakmp_sub0_print(np, ext, ep, phase, doi, proto);
1082		printf(")");
1083		depth--;
1084
1085		if (cp == NULL) {
1086			/* Zero-length subitem */
1087			return NULL;
1088		}
1089
1090		np = e.np;
1091		ext = (struct isakmp_gen *)cp;
1092	}
1093	return cp;
1094trunc:
1095	return NULL;
1096}
1097
1098static char *
1099numstr(int x)
1100{
1101	static char buf[20];
1102	snprintf(buf, sizeof(buf), "#%d", x);
1103	return buf;
1104}
1105
1106/*
1107 * some compiler tries to optimize memcpy(), using the alignment constraint
1108 * on the argument pointer type.  by using this function, we try to avoid the
1109 * optimization.
1110 */
1111static void
1112safememcpy(void *p, void *q, size_t l)
1113{
1114	memcpy(p, q, l);
1115}
1116
1117void
1118isakmp_print(const u_char *bp, u_int length, const u_char *bp2)
1119{
1120	struct isakmp *p, base;
1121	u_char *ep;
1122	u_char np;
1123	int i;
1124	int phase;
1125	int major, minor;
1126
1127	p = (struct isakmp *)bp;
1128	ep = (u_char *)snapend;
1129
1130	if ((struct isakmp *)ep < p + 1) {
1131		printf("[|isakmp]");
1132		return;
1133	}
1134
1135	safememcpy(&base, p, sizeof(base));
1136
1137	printf("isakmp");
1138	if (vflag) {
1139		major = (base.vers & ISAKMP_VERS_MAJOR)
1140				>> ISAKMP_VERS_MAJOR_SHIFT;
1141		minor = (base.vers & ISAKMP_VERS_MINOR)
1142				>> ISAKMP_VERS_MINOR_SHIFT;
1143		printf(" %d.%d", major, minor);
1144	}
1145
1146	if (vflag) {
1147		printf(" msgid ");
1148		rawprint((caddr_t)&base.msgid, sizeof(base.msgid));
1149	}
1150
1151	if (1 < vflag) {
1152		printf(" cookie ");
1153		rawprint((caddr_t)&base.i_ck, sizeof(base.i_ck));
1154		printf("->");
1155		rawprint((caddr_t)&base.r_ck, sizeof(base.r_ck));
1156	}
1157	printf(":");
1158
1159	phase = (*(u_int32_t *)base.msgid == 0) ? 1 : 2;
1160	if (phase == 1)
1161		printf(" phase %d", phase);
1162	else
1163		printf(" phase %d/others", phase);
1164
1165	i = cookie_find(&base.i_ck);
1166	if (i < 0) {
1167		if (iszero((u_char *)&base.r_ck, sizeof(base.r_ck))) {
1168			/* the first packet */
1169			printf(" I");
1170			if (bp2)
1171				cookie_record(&base.i_ck, bp2);
1172		} else
1173			printf(" ?");
1174	} else {
1175		if (bp2 && cookie_isinitiator(i, bp2))
1176			printf(" I");
1177		else if (bp2 && cookie_isresponder(i, bp2))
1178			printf(" R");
1179		else
1180			printf(" ?");
1181	}
1182
1183	printf(" %s", ETYPESTR(base.etype));
1184	if (base.flags) {
1185		printf("[%s%s]", base.flags & ISAKMP_FLAG_E ? "E" : "",
1186			base.flags & ISAKMP_FLAG_C ? "C" : "");
1187	}
1188	printf(":");
1189
1190    {
1191	struct isakmp_gen *ext;
1192	int nparen;
1193
1194#define CHECKLEN(p, np) \
1195	if (ep < (u_char *)(p)) {				\
1196		printf(" [|%s]", NPSTR(np));			\
1197		goto done;					\
1198	}
1199
1200	/* regardless of phase... */
1201	if (base.flags & ISAKMP_FLAG_E) {
1202		/*
1203		 * encrypted, nothing we can do right now.
1204		 * we hope to decrypt the packet in the future...
1205		 */
1206		printf(" [encrypted %s]", NPSTR(base.np));
1207		goto done;
1208	}
1209
1210	nparen = 0;
1211	CHECKLEN(p + 1, base.np)
1212
1213	np = base.np;
1214	ext = (struct isakmp_gen *)(p + 1);
1215	isakmp_sub_print(np, ext, ep, phase, 0, 0);
1216    }
1217
1218done:
1219	if (vflag) {
1220		if (ntohl(base.len) != length) {
1221			printf(" (len mismatch: isakmp %u/ip %d)",
1222				(u_int32_t)ntohl(base.len), length);
1223		}
1224	}
1225}
1226