xref: /openbsd-src/usr.sbin/tcpdump/print-ike.c (revision 91f110e064cd7c194e59e019b83bb7496c1c84d4)
1 /*	$OpenBSD: print-ike.c,v 1.36 2012/01/28 13:47:55 sthen Exp $	*/
2 
3 /*
4  * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999
5  *	The Regents of the University of California.  All rights reserved.
6  * Copyright (c) 2001 H�kan Olsson.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that: (1) source code distributions
10  * retain the above copyright notice and this paragraph in its entirety, (2)
11  * distributions including binary code include the above copyright notice and
12  * this paragraph in its entirety in the documentation or other materials
13  * provided with the distribution, and (3) all advertising materials mentioning
14  * features or use of this software display the following acknowledgement:
15  * ``This product includes software developed by the University of California,
16  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
17  * the University nor the names of its contributors may be used to endorse
18  * or promote products derived from this software without specific prior
19  * written permission.
20  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
21  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
22  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
23  *
24  * Format and print ike (isakmp) packets.
25  *	By Tero Kivinen <kivinen@ssh.fi>, Tero Mononen <tmo@ssh.fi>,
26  *         Tatu Ylonen <ylo@ssh.fi> and Timo J. Rinne <tri@ssh.fi>
27  *         in co-operation with SSH Communications Security, Espoo, Finland
28  */
29 
30 #include <sys/param.h>
31 #include <sys/time.h>
32 #include <sys/socket.h>
33 
34 struct mbuf;
35 struct rtentry;
36 #include <net/if.h>
37 #include <netinet/in.h>
38 #include <arpa/inet.h>
39 
40 #include <ctype.h>
41 #include <stdio.h>
42 #include <string.h>
43 
44 #include "interface.h"
45 #include "addrtoname.h"
46 #include "ike.h"
47 
48 struct isakmp_header {
49 	u_int8_t	init_cookie[8];
50 	u_int8_t	resp_cookie[8];
51 	u_int8_t	next_payload;
52 	u_int8_t	version;
53 	u_int8_t	exgtype;
54 	u_int8_t	flags;
55 	u_int8_t	msgid[4];
56 	u_int32_t	length;
57 	u_int8_t	payloads[0];
58 };
59 
60 struct sa_payload {
61 	u_int8_t	next_payload;
62 	u_int8_t	reserved;
63 	u_int16_t	payload_length;
64 	u_int32_t	doi;
65 	u_int8_t	situation[0];
66 };
67 
68 struct proposal_payload {
69 	u_int8_t	next_payload;
70 	u_int8_t	reserved;
71 	u_int16_t	payload_length;
72 	u_int8_t	nprop;
73 	u_int8_t	proto;
74 	u_int8_t	spi_size;
75 	u_int8_t	nspis;
76 	u_int8_t	spi[0];
77 };
78 
79 struct transform_payload {
80 	u_int8_t	next_payload;
81 	u_int8_t	reserved;
82 	u_int16_t	payload_length;
83 	u_int8_t	ntrans;
84 	u_int8_t	transform;
85 	u_int16_t	reserved2;
86 	u_int8_t	attribute[0];
87 };
88 
89 struct ke_payload {
90 	u_int8_t	next_payload;
91 	u_int8_t	reserved;
92 	u_int16_t	payload_length;
93 	u_int8_t	data[0];
94 };
95 
96 struct id_payload {
97 	u_int8_t	next_payload;
98 	u_int8_t	reserved;
99 	u_int16_t	payload_length;
100 	u_int8_t	type;
101 	u_int8_t	id_data[3];
102 	u_int8_t	data[0];
103 };
104 
105 struct notification_payload {
106 	u_int8_t	next_payload;
107 	u_int8_t	reserved;
108 	u_int16_t	payload_length;
109 	u_int32_t	doi;
110 	u_int8_t	protocol_id;
111   	u_int8_t	spi_size;
112   	u_int16_t	type;
113 	u_int8_t	data[0];
114 };
115 
116 struct delete_payload {
117 	u_int8_t	next_payload;
118 	u_int8_t	reserved;
119 	u_int16_t	payload_length;
120 	u_int32_t	doi;
121 	u_int8_t	proto;
122 	u_int8_t	spi_size;
123 	u_int16_t	nspis;
124 	u_int8_t	spi[0];
125 };
126 
127 struct vendor_payload {
128 	u_int8_t	next_payload;
129 	u_int8_t	reserved;
130 	u_int16_t	payload_length;
131 	u_int8_t	vid[0];
132 };
133 
134 struct attribute_payload {
135 	u_int8_t	next_payload;
136 	u_int8_t	reserved;
137 	u_int16_t	payload_length;
138 	u_int8_t	type;
139 	u_int8_t	reserved2;
140 	u_int16_t	id;
141 };
142 
143 static void ike_pl_print(u_int8_t, u_int8_t *, u_int8_t);
144 
145 int ike_tab_level = 0;
146 u_int8_t xform_proto;
147 
148 static const char *ike[] = IKE_PROTO_INITIALIZER;
149 
150 #define SMALL_TABS 4
151 #define SPACES "                                                   "
152 const char *
153 ike_tab_offset(void)
154 {
155 	const char *p, *endline;
156 	static const char line[] = SPACES;
157 
158 	endline = line + sizeof line - 1;
159 	p = endline - SMALL_TABS * (ike_tab_level);
160 
161 	return (p > line ? p : line);
162 }
163 
164 static char *
165 ike_get_cookie (u_int8_t *ic, u_int8_t *rc)
166 {
167 	static char cookie_jar[35];
168 	int i;
169 
170 	for (i = 0; i < 8; i++)
171 		snprintf(cookie_jar + i*2, sizeof(cookie_jar) - i*2,
172 		    "%02x", *(ic + i));
173 	strlcat(cookie_jar, "->", sizeof(cookie_jar));
174 	for (i = 0; i < 8; i++)
175 		snprintf(cookie_jar + 18 + i*2, sizeof(cookie_jar) - 18 - i*2,
176 		    "%02x", *(rc + i));
177 	return cookie_jar;
178 }
179 
180 /*
181  * Print isakmp requests
182  */
183 void
184 ike_print (const u_int8_t *cp, u_int length)
185 {
186 	struct isakmp_header *ih;
187 	const u_int8_t *ep;
188 	u_int8_t *payload, next_payload;
189 	int encrypted;
190 	static const char *exgtypes[] = IKE_EXCHANGE_TYPES_INITIALIZER;
191 
192 	encrypted = 0;
193 
194 #ifdef TCHECK
195 #undef TCHECK
196 #endif
197 #define TCHECK(var, l) if ((u_int8_t *)&(var) > ep - l) goto trunc
198 
199 	ih = (struct isakmp_header *)cp;
200 
201 	if (length < sizeof (struct isakmp_header))
202 		goto trunc;
203 
204 	/* 'ep' points to the end of avaible data. */
205 	ep = snapend;
206 
207 	printf(" isakmp");
208 
209 	printf(" v%d.%d", ih->version >> 4, ih->version & 0xf);
210 
211 	printf(" exchange ");
212 	if (ih->exgtype < (sizeof exgtypes/sizeof exgtypes[0]))
213 		printf("%s", exgtypes[ih->exgtype]);
214 	else
215 		printf("%d (unknown)", ih->exgtype);
216 
217 	if (ih->flags & FLAGS_ENCRYPTION) {
218 		printf(" encrypted");
219 		encrypted = 1;
220 	}
221 
222 	if (ih->flags & FLAGS_COMMIT) {
223 		printf(" commit");
224 	}
225 
226 	printf("\n\tcookie: %s", ike_get_cookie (ih->init_cookie,
227 						 ih->resp_cookie));
228 
229 	TCHECK(ih->msgid, sizeof(ih->msgid));
230 	printf(" msgid: %02x%02x%02x%02x", ih->msgid[0], ih->msgid[1],
231 	    ih->msgid[2], ih->msgid[3]);
232 
233 	TCHECK(ih->length, sizeof(ih->length));
234 	printf(" len: %d", ntohl(ih->length));
235 
236 	if (ih->version > IKE_VERSION_2) {
237 		printf(" new version");
238 		return;
239 	}
240 
241 	payload = ih->payloads;
242 	next_payload = ih->next_payload;
243 
244 	/* if encrypted, then open special file for encryption keys */
245 	if (encrypted) {
246 		/* decrypt XXX */
247 		return;
248 	}
249 
250 	/* if verbose, print payload data */
251 	if (vflag)
252 		ike_pl_print(next_payload, payload, ISAKMP_DOI);
253 
254 	return;
255 
256 trunc:
257 	fputs(" [|isakmp]", stdout);
258 }
259 
260 void
261 ike_pl_sa_print (u_int8_t *buf, int len)
262 {
263 	struct sa_payload *sp = (struct sa_payload *)buf;
264 	u_int32_t sit_ipsec, doi;
265 
266 	if (len < sizeof(struct sa_payload)) {
267 		printf(" [|payload]");
268 		return;
269 	}
270 
271 	doi = ntohl(sp->doi);
272 	printf(" DOI: %d", doi);
273 
274 	if (doi == IPSEC_DOI) {
275 		if ((sp->situation + sizeof(u_int32_t)) > (buf + len)) {
276 			printf(" [|payload]");
277 			return;
278 		}
279 		printf("(IPSEC) situation: ");
280 		sit_ipsec = ntohl(*(u_int32_t *)sp->situation);
281 		if (sit_ipsec & IKE_SITUATION_IDENTITY_ONLY)
282 			printf("IDENTITY_ONLY ");
283 		if (sit_ipsec & IKE_SITUATION_SECRECY)
284 			printf("SECRECY ");
285 		if (sit_ipsec & IKE_SITUATION_INTEGRITY)
286 			printf("INTEGRITY ");
287 		if ((sit_ipsec & IKE_SITUATION_MASK) == 0)
288 			printf("0x%x (unknown)", sit_ipsec);
289 		ike_pl_print (PAYLOAD_PROPOSAL, buf +
290 		    sizeof(struct sa_payload) + sizeof(u_int32_t), IPSEC_DOI);
291 	} else
292 		printf(" situation: (unknown)");
293 }
294 
295 int
296 ike_attribute_print (u_int8_t *buf, u_int8_t doi, int maxlen)
297 {
298 	static char *attrs[] = IKE_ATTR_INITIALIZER;
299 	static char *attr_enc[] = IKE_ATTR_ENCRYPT_INITIALIZER;
300 	static char *attr_hash[] = IKE_ATTR_HASH_INITIALIZER;
301 	static char *attr_auth[] = IKE_ATTR_AUTH_INITIALIZER;
302 	static char *attr_gdesc[] = IKE_ATTR_GROUP_DESC_INITIALIZER;
303 	static char *attr_gtype[] = IKE_ATTR_GROUP_INITIALIZER;
304 	static char *attr_ltype[] = IKE_ATTR_SA_DURATION_INITIALIZER;
305 	static char *ipsec_attrs[] = IPSEC_ATTR_INITIALIZER;
306 	static char *ipsec_attr_auth[] = IPSEC_ATTR_AUTH_INITIALIZER;
307 	static char *ipsec_attr_ltype[] = IPSEC_ATTR_DURATION_INITIALIZER;
308 
309 	u_int8_t af   = buf[0] >> 7;
310 	u_int16_t type = (buf[0] & 0x7f) << 8 | buf[1];
311 	u_int16_t len  = buf[2] << 8 | buf[3], val;
312 
313 	if (doi == ISAKMP_DOI)
314 		printf("\n\t%sattribute %s = ", ike_tab_offset(),
315 		    (type < sizeof attrs / sizeof attrs[0] ?
316 		    attrs[type] : "<unknown>"));
317 	else
318 		printf("\n\t%sattribute %s = ", ike_tab_offset(),
319 		    (type < (sizeof ipsec_attrs / sizeof ipsec_attrs[0]) ?
320 		    ipsec_attrs[type] : "<unknown>"));
321 
322 	if ((af == 1 && maxlen < 4) || (af == 0 && maxlen < (len + 4))) {
323 		printf("\n\t%s[|attr]", ike_tab_offset());
324 		return maxlen;
325 	}
326 
327 	if (af == 0) {
328 		/* AF=0; print the variable length attribute value */
329 		for (val = 0; val < len; val++)
330 			printf("%02x", *(buf + 4 + val));
331 		return len + 4;
332 	}
333 
334 	val = len;	/* For AF=1, this field is the "VALUE" */
335 	len = 4; 	/* and with AF=1, length is always 4 */
336 
337 #define CASE_PRINT(TYPE, var) \
338 	case TYPE : \
339 		if (val < sizeof var / sizeof var [0]) \
340 			printf("%s", var [val]); \
341 		else \
342 			printf("%d (unknown)", val); \
343 		break;
344 
345 	if (doi == ISAKMP_DOI)
346 		switch(type) {
347 			CASE_PRINT(IKE_ATTR_ENCRYPTION_ALGORITHM, attr_enc);
348 			CASE_PRINT(IKE_ATTR_HASH_ALGORITHM, attr_hash);
349 			CASE_PRINT(IKE_ATTR_AUTHENTICATION_METHOD, attr_auth);
350 			CASE_PRINT(IKE_ATTR_GROUP_DESC, attr_gdesc);
351 			CASE_PRINT(IKE_ATTR_GROUP_TYPE, attr_gtype);
352 			CASE_PRINT(IKE_ATTR_LIFE_TYPE, attr_ltype);
353 		default:
354 			printf("%d", val);
355 		}
356 	else
357 		switch(type) {
358 			CASE_PRINT(IPSEC_ATTR_SA_LIFE_TYPE, ipsec_attr_ltype);
359 			CASE_PRINT(IPSEC_ATTR_AUTHENTICATION_ALGORITHM,
360 			    ipsec_attr_auth);
361 			case IPSEC_ATTR_ENCAPSULATION_MODE:
362 				printf("%s", tok2str(ipsec_attr_encap,
363 				    "%d", val));
364 				break;
365 		default:
366 			printf("%d", val);
367 		}
368 
369 #undef CASE_PRINT
370 	return len;
371 }
372 
373 void
374 ike_pl_transform_print (u_int8_t *buf, int len, u_int8_t doi)
375 {
376 	struct transform_payload *tp = (struct transform_payload *)buf;
377 	const char *ah[] = IPSEC_AH_INITIALIZER;
378 	const char *esp[] = IPSEC_ESP_INITIALIZER;
379 	const char *ipcomp[] = IPCOMP_INITIALIZER;
380 	u_int8_t *attr = tp->attribute;
381 
382 	if (len < sizeof(struct transform_payload)) {
383 		printf(" [|payload]");
384 		return;
385 	}
386 
387 	printf("\n\t%stransform: %u ID: ", ike_tab_offset(), tp->ntrans);
388 
389 	switch (doi) {
390 	case ISAKMP_DOI:
391 		if (tp->transform < (sizeof ike / sizeof ike[0]))
392 			printf("%s", ike[tp->transform]);
393 		else
394 			printf("%d(unknown)", tp->transform);
395 		break;
396 
397 	default: /* IPSEC_DOI */
398 		switch (xform_proto) { /* from ike_proposal_print */
399 		case PROTO_IPSEC_AH:
400 			if (tp->transform < (sizeof ah / sizeof ah[0]))
401 				printf("%s", ah[tp->transform]);
402 			else
403 				printf("%d(unknown)", tp->transform);
404 			break;
405 		case PROTO_IPSEC_ESP:
406 			if (tp->transform < (sizeof esp / sizeof esp[0]))
407 				printf("%s", esp[tp->transform]);
408 			else
409 				printf("%d(unknown)", tp->transform);
410 			break;
411 		case PROTO_IPCOMP:
412 			if (tp->transform < (sizeof ipcomp / sizeof ipcomp[0]))
413 				printf("%s", ipcomp[tp->transform]);
414 			else
415 				printf("%d(unknown)", tp->transform);
416 			break;
417 		default:
418 			printf("%d(unknown)", tp->transform);
419 		}
420 		break;
421 	}
422 
423 	ike_tab_level++;
424 	while ((int)(attr - buf) < len) /* Skip last 'NONE' attr */
425 		attr += ike_attribute_print(attr, doi, len - (attr - buf));
426 	ike_tab_level--;
427 }
428 
429 void
430 ike_pl_proposal_print (u_int8_t *buf, int len, u_int8_t doi)
431 {
432 	struct proposal_payload *pp = (struct proposal_payload *)buf;
433 	int i;
434 
435 	if (len < sizeof(struct proposal_payload)) {
436 		printf(" [|payload]");
437 		return;
438 	}
439 
440 	printf(" proposal: %d proto: %s spisz: %d xforms: %d",
441 	    pp->nprop, (pp->proto < (sizeof ike / sizeof ike[0]) ?
442 	    ike[pp->proto] : "(unknown)"), pp->spi_size, pp->nspis);
443 
444 	xform_proto = pp->proto;
445 
446 	if (pp->spi_size) {
447 		if ((pp->spi + pp->spi_size) > (buf + len)) {
448 			printf(" [|payload]");
449 			return;
450 		}
451 		if (pp->proto == PROTO_IPCOMP)
452 			printf(" CPI: 0x");
453 		else
454 			printf(" SPI: 0x");
455 		for (i = 0; i < pp->spi_size; i++)
456 			printf("%02x", pp->spi[i]);
457 	}
458 
459 	/* Reset to sane value. */
460 	if (pp->proto == PROTO_ISAKMP)
461 		doi = ISAKMP_DOI;
462 	else
463 		doi = IPSEC_DOI;
464 
465 	if (pp->nspis > 0)
466 		ike_pl_print(PAYLOAD_TRANSFORM, pp->spi + pp->spi_size, doi);
467 }
468 
469 void
470 ike_pl_ke_print (u_int8_t *buf, int len, u_int8_t doi)
471 {
472 	if (len < sizeof(struct ke_payload)) {
473 		printf(" [|payload]");
474 		return;
475 	}
476 
477 	if (doi != IPSEC_DOI)
478 		return;
479 
480 	/* XXX ... */
481 }
482 
483 void
484 ipsec_id_print (u_int8_t *buf, int len, u_int8_t doi)
485 {
486 	struct id_payload *ip = (struct id_payload *)buf;
487 	static const char *idtypes[] = IPSEC_ID_TYPE_INITIALIZER;
488 	char ntop_buf[INET6_ADDRSTRLEN];
489 	struct in_addr in;
490 	u_int8_t *p;
491 
492 	if (len < sizeof (struct id_payload)) {
493 		printf(" [|payload]");
494 		return;
495 	}
496 
497 	if (doi != ISAKMP_DOI)
498 		return;
499 
500 	/* Don't print proto+port unless actually used */
501 	if (ip->id_data[0] | ip->id_data[1] | ip->id_data[2])
502 		printf(" proto: %d port: %d", ip->id_data[0],
503 		    (ip->id_data[1] << 8) + ip->id_data[2]);
504 
505 	printf(" type: %s = ", ip->type < (sizeof idtypes/sizeof idtypes[0]) ?
506 	    idtypes[ip->type] : "<unknown>");
507 
508 	switch (ip->type) {
509 	case IPSEC_ID_IPV4_ADDR:
510 		if ((ip->data + sizeof in) > (buf + len)) {
511 			printf(" [|payload]");
512 			return;
513 		}
514 		memcpy (&in.s_addr, ip->data, sizeof in);
515 		printf("%s", inet_ntoa (in));
516 		break;
517 
518 	case IPSEC_ID_IPV4_ADDR_SUBNET:
519 	case IPSEC_ID_IPV4_ADDR_RANGE:
520 		if ((ip->data + 2 * (sizeof in)) > (buf + len)) {
521 			printf(" [|payload]");
522 			return;
523 		}
524 		memcpy (&in.s_addr, ip->data, sizeof in);
525 		printf("%s%s", inet_ntoa (in),
526 		    ip->type == IPSEC_ID_IPV4_ADDR_SUBNET ? "/" : "-");
527 		memcpy (&in.s_addr, ip->data + sizeof in, sizeof in);
528 		printf("%s", inet_ntoa (in));
529 		break;
530 
531 	case IPSEC_ID_IPV6_ADDR:
532 		if ((ip->data + sizeof ntop_buf) > (buf + len)) {
533 			printf(" [|payload]");
534 			return;
535 		}
536 		printf("%s", inet_ntop (AF_INET6, ip->data, ntop_buf,
537 		    sizeof ntop_buf));
538 		break;
539 
540 	case IPSEC_ID_IPV6_ADDR_SUBNET:
541 	case IPSEC_ID_IPV6_ADDR_RANGE:
542 		if ((ip->data + 2 * sizeof ntop_buf) > (buf + len)) {
543 			printf(" [|payload]");
544 			return;
545 		}
546 		printf("%s%s", inet_ntop (AF_INET6, ip->data, ntop_buf,
547 		    sizeof ntop_buf),
548 		    ip->type == IPSEC_ID_IPV6_ADDR_SUBNET ? "/" : "-");
549 		printf("%s", inet_ntop (AF_INET6, ip->data + sizeof ntop_buf,
550 		    ntop_buf, sizeof ntop_buf));
551 		break;
552 
553 	case IPSEC_ID_FQDN:
554 	case IPSEC_ID_USER_FQDN:
555 		printf("\"");
556 		for (p = ip->data; (int)(p - buf) < len; p++)
557 			printf("%c",(isprint(*p) ? *p : '.'));
558 		printf("\"");
559 		break;
560 
561 	case IPSEC_ID_DER_ASN1_DN:
562 	case IPSEC_ID_DER_ASN1_GN:
563 	case IPSEC_ID_KEY_ID:
564 	default:
565 		printf("\"(not shown)\"");
566 		break;
567 	}
568 }
569 
570 void
571 ike_pl_delete_print (u_int8_t *buf, int len)
572 {
573   	struct delete_payload *dp = (struct delete_payload *)buf;
574 	u_int32_t doi;
575 	u_int16_t s, nspis;
576 	u_int8_t *data;
577 
578 	if (len < sizeof (struct delete_payload)) {
579 		printf(" [|payload]");
580 		return;
581 	}
582 
583 	doi   = ntohl(dp->doi);
584 	nspis = ntohs(dp->nspis);
585 
586 	if (doi != ISAKMP_DOI && doi != IPSEC_DOI) {
587 		printf(" (unknown DOI)");
588 		return;
589 	}
590 
591 	printf(" DOI: %u(%s) proto: %s nspis: %u", doi,
592 	    doi == ISAKMP_DOI ? "ISAKMP" : "IPSEC",
593 	    dp->proto < (sizeof ike / sizeof ike[0]) ? ike[dp->proto] :
594 	    "(unknown)", nspis);
595 
596 	if ((dp->spi + nspis * dp->spi_size) > (buf + len)) {
597 		printf(" [|payload]");
598 		return;
599 	}
600 
601 	for (s = 0; s < nspis; s++) {
602 		data = dp->spi + s * dp->spi_size;
603 		if (dp->spi_size == 16)
604 			printf("\n\t%scookie: %s", ike_tab_offset(),
605 			    ike_get_cookie(&data[0], &data[8]));
606 		else
607 			printf("\n\t%sSPI: 0x%08x", ike_tab_offset(),
608 			    data[0]<<24 | data[1]<<16 | data[2]<<8 | data[3]);
609 	}
610 }
611 
612 void
613 ike_pl_notification_print (u_int8_t *buf, int len)
614 {
615   	static const char *nftypes[] = IKE_NOTIFY_TYPES_INITIALIZER;
616   	struct notification_payload *np = (struct notification_payload *)buf;
617 	u_int32_t *replay, *seq;
618 	u_int32_t doi;
619 	u_int16_t type;
620 	u_int8_t *attr;
621 
622 	if (len < sizeof (struct notification_payload)) {
623 		printf(" [|payload]");
624 		return;
625 	}
626 
627 	doi  = ntohl (np->doi);
628 	type = ntohs (np->type);
629 
630 	if (doi != ISAKMP_DOI && doi != IPSEC_DOI) {
631 		printf(" (unknown DOI)");
632 		return;
633 	}
634 
635 	printf("\n\t%snotification: ", ike_tab_offset());
636 
637 	if (type > 0 && type < (sizeof nftypes / sizeof nftypes[0])) {
638 		printf("%s", nftypes[type]);
639 		return;
640 	}
641 	switch (type) {
642 
643 	case NOTIFY_IPSEC_RESPONDER_LIFETIME:
644 		printf("RESPONDER LIFETIME ");
645 		if (np->spi_size == 16)
646 			printf("(%s)", ike_get_cookie (&np->data[0],
647 			    &np->data[8]));
648 		else
649 			printf("SPI: 0x%08x", np->data[0]<<24 |
650 			    np->data[1]<<16 | np->data[2]<<8 | np->data[3]);
651 		attr = &np->data[np->spi_size];
652 		ike_tab_level++;
653 		while ((int)(attr - buf) < len - 4)  /* Skip last 'NONE' attr */
654 			attr += ike_attribute_print(attr, IPSEC_DOI,
655 			    len - (attr-buf));
656 		ike_tab_level--;
657 		break;
658 
659 	case NOTIFY_IPSEC_REPLAY_STATUS:
660 		replay = (u_int32_t *)&np->data[np->spi_size];
661 		printf("REPLAY STATUS [%sabled] ", *replay ? "en" : "dis");
662 		if (np->spi_size == 16)
663 			printf("(%s)", ike_get_cookie (&np->data[0],
664 			    &np->data[8]));
665 		else
666 			printf("SPI: 0x%08x", np->data[0]<<24 |
667 			    np->data[1]<<16 | np->data[2]<<8 | np->data[3]);
668 		break;
669 
670 	case NOTIFY_IPSEC_INITIAL_CONTACT:
671 		printf("INITIAL CONTACT (%s)", ike_get_cookie (&np->data[0],
672 		    &np->data[8]));
673 		break;
674 
675 	case NOTIFY_STATUS_DPD_R_U_THERE:
676 	case NOTIFY_STATUS_DPD_R_U_THERE_ACK:
677 		printf("STATUS_DPD_R_U_THERE%s ",
678 		    type == NOTIFY_STATUS_DPD_R_U_THERE ? "" : "_ACK");
679 		if (np->spi_size != 16 ||
680 		    len < sizeof(struct notification_payload) +
681 		    sizeof(u_int32_t))
682 			printf("[bad notify]");
683 		else {
684 			seq = (u_int32_t *)&np->data[np->spi_size];
685 			printf("seq %u", ntohl(*seq));
686 		}
687 		break;
688 
689 
690 	default:
691 	  	printf("%d (unknown)", type);
692 		break;
693 	}
694 }
695 
696 void
697 ike_pl_vendor_print (u_int8_t *buf, int len, u_int8_t doi)
698 {
699 	struct vendor_payload *vp = (struct vendor_payload *)buf;
700 	u_int8_t *p;
701 	int i;
702 
703 	if (len < sizeof(struct vendor_payload)) {
704 		printf(" [|payload]");
705 		return;
706 	}
707 
708 	for (i = 0; i < sizeof vendor_ids / sizeof vendor_ids[0]; i ++)
709 		if (memcmp(vp->vid, vendor_ids[i].vid,
710 		    vendor_ids[i].len) == 0) {
711 			printf (" (supports %s)", vendor_ids[i].name);
712 			return;
713 		}
714 
715 	if (doi != IPSEC_DOI)
716 		return;
717 
718 	printf(" \"");
719 	for (p = vp->vid; (int)(p - buf) < len; p++)
720 		printf("%c", (isprint(*p) ? *p : '.'));
721 	printf("\"");
722 }
723 
724 /* IKE mode-config. */
725 int
726 ike_cfg_attribute_print (u_int8_t *buf, int attr_type, int maxlen)
727 {
728 	static char *attrs[] = IKE_CFG_ATTRIBUTE_INITIALIZER;
729 	char ntop_buf[INET6_ADDRSTRLEN];
730 	struct in_addr in;
731 
732 	u_int8_t af = buf[0] >> 7;
733 	u_int16_t type = (buf[0] & 0x7f) << 8 | buf[1];
734 	u_int16_t len = af ? 2 : buf[2] << 8 | buf[3], p;
735 	u_int8_t *val = af ? buf + 2 : buf + 4;
736 
737 	printf("\n\t%sattribute %s = ", ike_tab_offset(),
738 	    type < (sizeof attrs / sizeof attrs[0]) ? attrs[type] :
739 	    "<unknown>");
740 
741 	if ((af == 1 && maxlen < 4) ||
742 	    (af == 0 && maxlen < (len + 4))) {
743 		printf("\n\t%s[|attr]", ike_tab_offset());
744 		return maxlen;
745 	}
746 
747 	/* XXX The 2nd term is for bug compatibility with PGPnet.  */
748 	if (len == 0 || (af && !val[0] && !val[1])) {
749 		printf("<none>");
750 		return 4;
751 	}
752 
753 	/* XXX Generally lengths are not checked well below.  */
754 	switch (type) {
755 	case IKE_CFG_ATTR_INTERNAL_IP4_ADDRESS:
756 	case IKE_CFG_ATTR_INTERNAL_IP4_NETMASK:
757 	case IKE_CFG_ATTR_INTERNAL_IP4_DNS:
758 	case IKE_CFG_ATTR_INTERNAL_IP4_NBNS:
759 	case IKE_CFG_ATTR_INTERNAL_IP4_DHCP:
760 		memcpy (&in.s_addr, val, sizeof in);
761 		printf("%s", inet_ntoa (in));
762 		break;
763 
764 	case IKE_CFG_ATTR_INTERNAL_IP6_ADDRESS:
765 	case IKE_CFG_ATTR_INTERNAL_IP6_NETMASK:
766 	case IKE_CFG_ATTR_INTERNAL_IP6_DNS:
767 	case IKE_CFG_ATTR_INTERNAL_IP6_NBNS:
768 	case IKE_CFG_ATTR_INTERNAL_IP6_DHCP:
769 		printf("%s", inet_ntop (AF_INET6, val, ntop_buf,
770 		    sizeof ntop_buf));
771 		break;
772 
773 	case IKE_CFG_ATTR_INTERNAL_IP4_SUBNET:
774 		memcpy(&in.s_addr, val, sizeof in);
775 		printf("%s/", inet_ntoa (in));
776 		memcpy(&in.s_addr, val + sizeof in, sizeof in);
777 		printf("%s", inet_ntoa (in));
778 		break;
779 
780 	case IKE_CFG_ATTR_INTERNAL_IP6_SUBNET:
781 		printf("%s/%u", inet_ntop (AF_INET6, val, ntop_buf,
782 		    sizeof ntop_buf), val[16]);
783 		break;
784 
785 	case IKE_CFG_ATTR_INTERNAL_ADDRESS_EXPIRY:
786 		printf("%u seconds",
787 		    val[0] << 24 | val[1] << 16 | val[2] << 8 | val[3]);
788 		break;
789 
790 	case IKE_CFG_ATTR_APPLICATION_VERSION:
791 		for (p = 0; p < len; p++)
792 			printf("%c", isprint(val[p]) ? val[p] : '.');
793 		break;
794 
795 	case IKE_CFG_ATTR_SUPPORTED_ATTRIBUTES:
796 		printf("<%d attributes>", len / 2);
797 		ike_tab_level++;
798 		for (p = 0; p < len; p += 2) {
799 			type = (val[p] << 8 | val[p + 1]) & 0x7fff;
800 			printf("\n\t%s%s", ike_tab_offset(),
801 			    type < (sizeof attrs/sizeof attrs[0]) ?
802 			    attrs[type] : "<unknown>");
803 		}
804 		ike_tab_level--;
805 		break;
806 
807 	default:
808 		break;
809 	}
810 	return af ? 4 : len + 4;
811 }
812 
813 void
814 ike_pl_attribute_print (u_int8_t *buf, int len)
815 {
816 	struct attribute_payload *ap = (struct attribute_payload *)buf;
817 	static const char *pl_attr[] = IKE_CFG_ATTRIBUTE_TYPE_INITIALIZER;
818 	u_int8_t *attr = buf + sizeof(struct attribute_payload);
819 
820 	if (len < sizeof(struct attribute_payload)) {
821 		printf(" [|payload]");
822 		return;
823 	}
824 
825 	printf(" type: %s Id: %d",
826 	    ap->type < (sizeof pl_attr/sizeof pl_attr[0]) ? pl_attr[ap->type] :
827 	    "<unknown>", ap->id);
828 
829 	while ((int)(attr - buf) < len)
830 		attr += ike_cfg_attribute_print(attr, ap->type,
831 		    len - (attr - buf));
832 }
833 
834 void
835 ike_pl_print (u_int8_t type, u_int8_t *buf, u_int8_t doi)
836 {
837 	static const char *pltypes[] = IKE_PAYLOAD_TYPES_INITIALIZER;
838 	static const char *plprivtypes[] =
839 	    IKE_PRIVATE_PAYLOAD_TYPES_INITIALIZER;
840 	static const char *plv2types[] = IKEV2_PAYLOAD_TYPES_INITIALIZER;
841 	u_int8_t next_type;
842 	u_int16_t this_len;
843 
844 	if (&buf[4] > snapend) {
845 		goto pltrunc;
846 	}
847 
848 	next_type = buf[0];
849 	this_len = buf[2]<<8 | buf[3];
850 
851 	if (type < PAYLOAD_PRIVATE_MIN && type >= PAYLOAD_IKEV2_SA)
852 		printf("\n\t%spayload: %s len: %hu", ike_tab_offset(),
853 		    plv2types[type - PAYLOAD_IKEV2_SA], this_len);
854 	else if (type < PAYLOAD_PRIVATE_MIN || type >= PAYLOAD_PRIVATE_MAX)
855 		printf("\n\t%spayload: %s len: %hu", ike_tab_offset(),
856 		    (type < (sizeof pltypes/sizeof pltypes[0]) ?
857 			pltypes[type] : "<unknown>"), this_len);
858 	else
859 		printf("\n\t%spayload: %s len: %hu", ike_tab_offset(),
860 		    plprivtypes[type - PAYLOAD_PRIVATE_MIN], this_len);
861 
862 	if ((type < PAYLOAD_RESERVED_MIN &&
863 	    (type < sizeof(min_payload_lengths)/sizeof(min_payload_lengths[0]) &&
864 	    this_len < min_payload_lengths[type])) ||
865 	    this_len == 0)
866 		goto pltrunc;
867 
868 	if ((type > PAYLOAD_PRIVATE_MIN && type < PAYLOAD_PRIVATE_MAX &&
869 	    this_len < min_priv_payload_lengths[type - PAYLOAD_PRIVATE_MIN]) ||
870 	    this_len == 0)
871 		goto pltrunc;
872 
873 	if (buf + this_len > snapend)
874 		goto pltrunc;
875 
876 	ike_tab_level++;
877 	switch (type) {
878 	case PAYLOAD_NONE:
879 		return;
880 
881 	case PAYLOAD_SA:
882 		ike_pl_sa_print(buf, this_len);
883 		break;
884 
885 	case PAYLOAD_PROPOSAL:
886 		ike_pl_proposal_print(buf, this_len, doi);
887 		break;
888 
889 	case PAYLOAD_TRANSFORM:
890 		ike_pl_transform_print(buf, this_len, doi);
891 		break;
892 
893 	case PAYLOAD_KE:
894 		ike_pl_ke_print(buf, this_len, doi);
895 		break;
896 
897 	case PAYLOAD_ID:
898 		/* Should only happen with IPsec DOI */
899 		ipsec_id_print(buf, this_len, doi);
900 		break;
901 
902 	case PAYLOAD_CERT:
903 	case PAYLOAD_CERTREQUEST:
904 	case PAYLOAD_HASH:
905 	case PAYLOAD_SIG:
906 	case PAYLOAD_NONCE:
907 		break;
908 
909 	case PAYLOAD_DELETE:
910 		ike_pl_delete_print(buf, this_len);
911 		break;
912 
913 	case PAYLOAD_NOTIFICATION:
914 	  	ike_pl_notification_print(buf, this_len);
915 		break;
916 
917 	case PAYLOAD_VENDOR:
918 		ike_pl_vendor_print(buf, this_len, doi);
919 		break;
920 
921 	case PAYLOAD_ATTRIBUTE:
922 		ike_pl_attribute_print(buf, this_len);
923 		break;
924 
925 	case PAYLOAD_SAK:
926 	case PAYLOAD_SAT:
927 	case PAYLOAD_KD:
928 	case PAYLOAD_SEQ:
929 	case PAYLOAD_POP:
930 	case PAYLOAD_NAT_D:
931 		break;
932 
933 	case PAYLOAD_NAT_OA:
934 		/* RFC3947 NAT-OA uses a subset of the ID payload */
935 		ipsec_id_print(buf, this_len, doi);
936 		break;
937 
938 	case PAYLOAD_NAT_D_DRAFT:
939 		break;
940 
941 	case PAYLOAD_NAT_OA_DRAFT:
942 		ipsec_id_print(buf, this_len, doi);
943 		break;
944 
945 	default:
946 		break;
947 	}
948 	ike_tab_level--;
949 
950 	if (next_type)  /* Recurse over next payload */
951 		ike_pl_print(next_type, buf + this_len, doi);
952 
953 	return;
954 
955 pltrunc:
956 	if (doi == ISAKMP_DOI)
957 		fputs(" [|isakmp]", stdout);
958 	else
959 		fputs(" [|ipsec]", stdout);
960 }
961