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