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