xref: /freebsd/contrib/tcpdump/print-isakmp.c (revision 23f282aa31e9b6fceacd449020e936e98d6f2298)
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
32 static 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__
47 struct mbuf;
48 struct 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 
79 static u_char *isakmp_sa_print __P((struct isakmp_gen *, u_char *, u_int32_t,
80 	u_int32_t, u_int32_t));
81 static u_char *isakmp_p_print __P((struct isakmp_gen *, u_char *, u_int32_t,
82 	u_int32_t, u_int32_t));
83 static u_char *isakmp_t_print __P((struct isakmp_gen *, u_char *, u_int32_t,
84 	u_int32_t, u_int32_t));
85 static u_char *isakmp_ke_print __P((struct isakmp_gen *, u_char *, u_int32_t,
86 	u_int32_t, u_int32_t));
87 static u_char *isakmp_id_print __P((struct isakmp_gen *, u_char *, u_int32_t,
88 	u_int32_t, u_int32_t));
89 static u_char *isakmp_hash_print __P((struct isakmp_gen *, u_char *,
90 	u_int32_t, u_int32_t, u_int32_t));
91 static u_char *isakmp_nonce_print __P((struct isakmp_gen *, u_char *,
92 	u_int32_t, u_int32_t, u_int32_t));
93 static u_char *isakmp_n_print __P((struct isakmp_gen *, u_char *, u_int32_t,
94 	u_int32_t, u_int32_t));
95 static u_char *isakmp_d_print __P((struct isakmp_gen *, u_char *, u_int32_t,
96 	u_int32_t, u_int32_t));
97 static u_char *isakmp_vid_print __P((struct isakmp_gen *, u_char *, u_int32_t,
98 	u_int32_t, u_int32_t));
99 static u_char *isakmp_sub0_print __P((u_char, struct isakmp_gen *, u_char *,
100 	u_int32_t, u_int32_t, u_int32_t));
101 static u_char *isakmp_sub_print __P((u_char, struct isakmp_gen *, u_char *,
102 	u_int32_t, u_int32_t, u_int32_t));
103 static char *numstr __P((int));
104 
105 #define MAXINITIATORS	20
106 int ninitiator = 0;
107 struct {
108 	cookie_t initiator;
109 	struct sockaddr_storage iaddr;
110 	struct sockaddr_storage raddr;
111 } cookiecache[MAXINITIATORS];
112 
113 /* protocol id */
114 static char *protoidstr[] = {
115 	NULL, "isakmp", "ipsec-ah", "ipsec-esp", "ipcomp",
116 };
117 
118 /* isakmp->np */
119 static char *npstr[] = {
120 	"none", "sa", "p", "t", "ke", "id", "cert", "cr", "hash",
121 	"sig", "nonce", "n", "d", "vid"
122 };
123 
124 /* isakmp->np */
125 static 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 */
144 static 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 
162 static int
163 iszero(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 */
173 static int
174 cookie_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 */
187 static void
188 cookie_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)
256 static int
257 cookie_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 
334 static void
335 rawprint(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 
345 struct attrmap {
346 	char *type;
347 	int nvalue;
348 	char *value[30];	/*XXX*/
349 };
350 
351 static u_char *
352 isakmp_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 
389 static u_char *
390 isakmp_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 
421 static u_char *
422 isakmp_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 
468 static u_char *
469 isakmp_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 
493 static char *isakmp_p_map[] = {
494 	NULL, "ike",
495 };
496 
497 static char *ah_p_map[] = {
498 	NULL, "md5", "sha", "1des",
499 };
500 
501 static char *esp_p_map[] = {
502 	NULL, "1des-iv64", "1des", "3des", "rc5", "idea", "cast",
503 	"blowfish", "3idea", "1des-iv32", "rc4", "null"
504 };
505 
506 static char *ipcomp_p_map[] = {
507 	NULL, "oui", "deflate", "lzs",
508 };
509 
510 struct 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 
524 struct 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 
547 static u_char *
548 isakmp_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 
608 static u_char *
609 isakmp_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 
622 static u_char *
623 isakmp_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 
758 static u_char *
759 isakmp_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 
772 static u_char *
773 isakmp_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 
786 static u_char *
787 isakmp_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 
891 static u_char *
892 isakmp_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 
926 static u_char *
927 isakmp_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 
940 static u_char *
941 isakmp_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 
957 static u_char *
958 isakmp_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 
988 static char *
989 numstr(int x)
990 {
991 	static char buf[20];
992 	sprintf(buf, "#%d", x);
993 	return buf;
994 }
995 
996 void
997 isakmp_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 
1095 done:
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