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