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