xref: /openbsd/usr.sbin/tcpdump/print-ike.c (revision 891d7ab6)
1 /*	$OpenBSD: print-ike.c,v 1.35 2010/06/07 16:20:58 jsg 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_encap[] = IPSEC_ATTR_ENCAP_INITIALIZER;
307 	static char *ipsec_attr_auth[] = IPSEC_ATTR_AUTH_INITIALIZER;
308 	static char *ipsec_attr_ltype[] = IPSEC_ATTR_DURATION_INITIALIZER;
309 
310 	u_int8_t af   = buf[0] >> 7;
311 	u_int16_t type = (buf[0] & 0x7f) << 8 | buf[1];
312 	u_int16_t len  = buf[2] << 8 | buf[3], val;
313 
314 	if (doi == ISAKMP_DOI)
315 		printf("\n\t%sattribute %s = ", ike_tab_offset(),
316 		    (type < sizeof attrs / sizeof attrs[0] ?
317 		    attrs[type] : "<unknown>"));
318 	else
319 		printf("\n\t%sattribute %s = ", ike_tab_offset(),
320 		    (type < (sizeof ipsec_attrs / sizeof ipsec_attrs[0]) ?
321 		    ipsec_attrs[type] : "<unknown>"));
322 
323 	if ((af == 1 && maxlen < 4) || (af == 0 && maxlen < (len + 4))) {
324 		printf("\n\t%s[|attr]", ike_tab_offset());
325 		return maxlen;
326 	}
327 
328 	if (af == 0) {
329 		/* AF=0; print the variable length attribute value */
330 		for (val = 0; val < len; val++)
331 			printf("%02x", *(buf + 4 + val));
332 		return len + 4;
333 	}
334 
335 	val = len;	/* For AF=1, this field is the "VALUE" */
336 	len = 4; 	/* and with AF=1, length is always 4 */
337 
338 #define CASE_PRINT(TYPE, var) \
339 	case TYPE : \
340 		if (val < sizeof var / sizeof var [0]) \
341 			printf("%s", var [val]); \
342 		else \
343 			printf("%d (unknown)", val); \
344 		break;
345 
346 	if (doi == ISAKMP_DOI)
347 		switch(type) {
348 			CASE_PRINT(IKE_ATTR_ENCRYPTION_ALGORITHM, attr_enc);
349 			CASE_PRINT(IKE_ATTR_HASH_ALGORITHM, attr_hash);
350 			CASE_PRINT(IKE_ATTR_AUTHENTICATION_METHOD, attr_auth);
351 			CASE_PRINT(IKE_ATTR_GROUP_DESC, attr_gdesc);
352 			CASE_PRINT(IKE_ATTR_GROUP_TYPE, attr_gtype);
353 			CASE_PRINT(IKE_ATTR_LIFE_TYPE, attr_ltype);
354 		default:
355 			printf("%d", val);
356 		}
357 	else
358 		switch(type) {
359 			CASE_PRINT(IPSEC_ATTR_SA_LIFE_TYPE, ipsec_attr_ltype);
360 			CASE_PRINT(IPSEC_ATTR_ENCAPSULATION_MODE,
361 			    ipsec_attr_encap);
362 			CASE_PRINT(IPSEC_ATTR_AUTHENTICATION_ALGORITHM,
363 			    ipsec_attr_auth);
364 		default:
365 			printf("%d", val);
366 		}
367 
368 #undef CASE_PRINT
369 	return len;
370 }
371 
372 void
373 ike_pl_transform_print (u_int8_t *buf, int len, u_int8_t doi)
374 {
375 	struct transform_payload *tp = (struct transform_payload *)buf;
376 	const char *ah[] = IPSEC_AH_INITIALIZER;
377 	const char *esp[] = IPSEC_ESP_INITIALIZER;
378 	const char *ipcomp[] = IPCOMP_INITIALIZER;
379 	u_int8_t *attr = tp->attribute;
380 
381 	if (len < sizeof(struct transform_payload)) {
382 		printf(" [|payload]");
383 		return;
384 	}
385 
386 	printf("\n\t%stransform: %u ID: ", ike_tab_offset(), tp->ntrans);
387 
388 	switch (doi) {
389 	case ISAKMP_DOI:
390 		if (tp->transform < (sizeof ike / sizeof ike[0]))
391 			printf("%s", ike[tp->transform]);
392 		else
393 			printf("%d(unknown)", tp->transform);
394 		break;
395 
396 	default: /* IPSEC_DOI */
397 		switch (xform_proto) { /* from ike_proposal_print */
398 		case PROTO_IPSEC_AH:
399 			if (tp->transform < (sizeof ah / sizeof ah[0]))
400 				printf("%s", ah[tp->transform]);
401 			else
402 				printf("%d(unknown)", tp->transform);
403 			break;
404 		case PROTO_IPSEC_ESP:
405 			if (tp->transform < (sizeof esp / sizeof esp[0]))
406 				printf("%s", esp[tp->transform]);
407 			else
408 				printf("%d(unknown)", tp->transform);
409 			break;
410 		case PROTO_IPCOMP:
411 			if (tp->transform < (sizeof ipcomp / sizeof ipcomp[0]))
412 				printf("%s", ipcomp[tp->transform]);
413 			else
414 				printf("%d(unknown)", tp->transform);
415 			break;
416 		default:
417 			printf("%d(unknown)", tp->transform);
418 		}
419 		break;
420 	}
421 
422 	ike_tab_level++;
423 	while ((int)(attr - buf) < len) /* Skip last 'NONE' attr */
424 		attr += ike_attribute_print(attr, doi, len - (attr - buf));
425 	ike_tab_level--;
426 }
427 
428 void
429 ike_pl_proposal_print (u_int8_t *buf, int len, u_int8_t doi)
430 {
431 	struct proposal_payload *pp = (struct proposal_payload *)buf;
432 	int i;
433 
434 	if (len < sizeof(struct proposal_payload)) {
435 		printf(" [|payload]");
436 		return;
437 	}
438 
439 	printf(" proposal: %d proto: %s spisz: %d xforms: %d",
440 	    pp->nprop, (pp->proto < (sizeof ike / sizeof ike[0]) ?
441 	    ike[pp->proto] : "(unknown)"), pp->spi_size, pp->nspis);
442 
443 	xform_proto = pp->proto;
444 
445 	if (pp->spi_size) {
446 		if ((pp->spi + pp->spi_size) > (buf + len)) {
447 			printf(" [|payload]");
448 			return;
449 		}
450 		if (pp->proto == PROTO_IPCOMP)
451 			printf(" CPI: 0x");
452 		else
453 			printf(" SPI: 0x");
454 		for (i = 0; i < pp->spi_size; i++)
455 			printf("%02x", pp->spi[i]);
456 	}
457 
458 	/* Reset to sane value. */
459 	if (pp->proto == PROTO_ISAKMP)
460 		doi = ISAKMP_DOI;
461 	else
462 		doi = IPSEC_DOI;
463 
464 	if (pp->nspis > 0)
465 		ike_pl_print(PAYLOAD_TRANSFORM, pp->spi + pp->spi_size, doi);
466 }
467 
468 void
469 ike_pl_ke_print (u_int8_t *buf, int len, u_int8_t doi)
470 {
471 	if (len < sizeof(struct ke_payload)) {
472 		printf(" [|payload]");
473 		return;
474 	}
475 
476 	if (doi != IPSEC_DOI)
477 		return;
478 
479 	/* XXX ... */
480 }
481 
482 void
483 ipsec_id_print (u_int8_t *buf, int len, u_int8_t doi)
484 {
485 	struct id_payload *ip = (struct id_payload *)buf;
486 	static const char *idtypes[] = IPSEC_ID_TYPE_INITIALIZER;
487 	char ntop_buf[INET6_ADDRSTRLEN];
488 	struct in_addr in;
489 	u_int8_t *p;
490 
491 	if (len < sizeof (struct id_payload)) {
492 		printf(" [|payload]");
493 		return;
494 	}
495 
496 	if (doi != ISAKMP_DOI)
497 		return;
498 
499 	/* Don't print proto+port unless actually used */
500 	if (ip->id_data[0] | ip->id_data[1] | ip->id_data[2])
501 		printf(" proto: %d port: %d", ip->id_data[0],
502 		    (ip->id_data[1] << 8) + ip->id_data[2]);
503 
504 	printf(" type: %s = ", ip->type < (sizeof idtypes/sizeof idtypes[0]) ?
505 	    idtypes[ip->type] : "<unknown>");
506 
507 	switch (ip->type) {
508 	case IPSEC_ID_IPV4_ADDR:
509 		if ((ip->data + sizeof in) > (buf + len)) {
510 			printf(" [|payload]");
511 			return;
512 		}
513 		memcpy (&in.s_addr, ip->data, sizeof in);
514 		printf("%s", inet_ntoa (in));
515 		break;
516 
517 	case IPSEC_ID_IPV4_ADDR_SUBNET:
518 	case IPSEC_ID_IPV4_ADDR_RANGE:
519 		if ((ip->data + 2 * (sizeof in)) > (buf + len)) {
520 			printf(" [|payload]");
521 			return;
522 		}
523 		memcpy (&in.s_addr, ip->data, sizeof in);
524 		printf("%s%s", inet_ntoa (in),
525 		    ip->type == IPSEC_ID_IPV4_ADDR_SUBNET ? "/" : "-");
526 		memcpy (&in.s_addr, ip->data + sizeof in, sizeof in);
527 		printf("%s", inet_ntoa (in));
528 		break;
529 
530 	case IPSEC_ID_IPV6_ADDR:
531 		if ((ip->data + sizeof ntop_buf) > (buf + len)) {
532 			printf(" [|payload]");
533 			return;
534 		}
535 		printf("%s", inet_ntop (AF_INET6, ip->data, ntop_buf,
536 		    sizeof ntop_buf));
537 		break;
538 
539 	case IPSEC_ID_IPV6_ADDR_SUBNET:
540 	case IPSEC_ID_IPV6_ADDR_RANGE:
541 		if ((ip->data + 2 * sizeof ntop_buf) > (buf + len)) {
542 			printf(" [|payload]");
543 			return;
544 		}
545 		printf("%s%s", inet_ntop (AF_INET6, ip->data, ntop_buf,
546 		    sizeof ntop_buf),
547 		    ip->type == IPSEC_ID_IPV6_ADDR_SUBNET ? "/" : "-");
548 		printf("%s", inet_ntop (AF_INET6, ip->data + sizeof ntop_buf,
549 		    ntop_buf, sizeof ntop_buf));
550 		break;
551 
552 	case IPSEC_ID_FQDN:
553 	case IPSEC_ID_USER_FQDN:
554 		printf("\"");
555 		for (p = ip->data; (int)(p - buf) < len; p++)
556 			printf("%c",(isprint(*p) ? *p : '.'));
557 		printf("\"");
558 		break;
559 
560 	case IPSEC_ID_DER_ASN1_DN:
561 	case IPSEC_ID_DER_ASN1_GN:
562 	case IPSEC_ID_KEY_ID:
563 	default:
564 		printf("\"(not shown)\"");
565 		break;
566 	}
567 }
568 
569 void
570 ike_pl_delete_print (u_int8_t *buf, int len)
571 {
572   	struct delete_payload *dp = (struct delete_payload *)buf;
573 	u_int32_t doi;
574 	u_int16_t s, nspis;
575 	u_int8_t *data;
576 
577 	if (len < sizeof (struct delete_payload)) {
578 		printf(" [|payload]");
579 		return;
580 	}
581 
582 	doi   = ntohl(dp->doi);
583 	nspis = ntohs(dp->nspis);
584 
585 	if (doi != ISAKMP_DOI && doi != IPSEC_DOI) {
586 		printf(" (unknown DOI)");
587 		return;
588 	}
589 
590 	printf(" DOI: %u(%s) proto: %s nspis: %u", doi,
591 	    doi == ISAKMP_DOI ? "ISAKMP" : "IPSEC",
592 	    dp->proto < (sizeof ike / sizeof ike[0]) ? ike[dp->proto] :
593 	    "(unknown)", nspis);
594 
595 	if ((dp->spi + nspis * dp->spi_size) > (buf + len)) {
596 		printf(" [|payload]");
597 		return;
598 	}
599 
600 	for (s = 0; s < nspis; s++) {
601 		data = dp->spi + s * dp->spi_size;
602 		if (dp->spi_size == 16)
603 			printf("\n\t%scookie: %s", ike_tab_offset(),
604 			    ike_get_cookie(&data[0], &data[8]));
605 		else
606 			printf("\n\t%sSPI: 0x%08x", ike_tab_offset(),
607 			    data[0]<<24 | data[1]<<16 | data[2]<<8 | data[3]);
608 	}
609 }
610 
611 void
612 ike_pl_notification_print (u_int8_t *buf, int len)
613 {
614   	static const char *nftypes[] = IKE_NOTIFY_TYPES_INITIALIZER;
615   	struct notification_payload *np = (struct notification_payload *)buf;
616 	u_int32_t *replay, *seq;
617 	u_int32_t doi;
618 	u_int16_t type;
619 	u_int8_t *attr;
620 
621 	if (len < sizeof (struct notification_payload)) {
622 		printf(" [|payload]");
623 		return;
624 	}
625 
626 	doi  = ntohl (np->doi);
627 	type = ntohs (np->type);
628 
629 	if (doi != ISAKMP_DOI && doi != IPSEC_DOI) {
630 		printf(" (unknown DOI)");
631 		return;
632 	}
633 
634 	printf("\n\t%snotification: ", ike_tab_offset());
635 
636 	if (type > 0 && type < (sizeof nftypes / sizeof nftypes[0])) {
637 		printf("%s", nftypes[type]);
638 		return;
639 	}
640 	switch (type) {
641 
642 	case NOTIFY_IPSEC_RESPONDER_LIFETIME:
643 		printf("RESPONDER LIFETIME ");
644 		if (np->spi_size == 16)
645 			printf("(%s)", ike_get_cookie (&np->data[0],
646 			    &np->data[8]));
647 		else
648 			printf("SPI: 0x%08x", np->data[0]<<24 |
649 			    np->data[1]<<16 | np->data[2]<<8 | np->data[3]);
650 		attr = &np->data[np->spi_size];
651 		ike_tab_level++;
652 		while ((int)(attr - buf) < len - 4)  /* Skip last 'NONE' attr */
653 			attr += ike_attribute_print(attr, IPSEC_DOI,
654 			    len - (attr-buf));
655 		ike_tab_level--;
656 		break;
657 
658 	case NOTIFY_IPSEC_REPLAY_STATUS:
659 		replay = (u_int32_t *)&np->data[np->spi_size];
660 		printf("REPLAY STATUS [%sabled] ", *replay ? "en" : "dis");
661 		if (np->spi_size == 16)
662 			printf("(%s)", ike_get_cookie (&np->data[0],
663 			    &np->data[8]));
664 		else
665 			printf("SPI: 0x%08x", np->data[0]<<24 |
666 			    np->data[1]<<16 | np->data[2]<<8 | np->data[3]);
667 		break;
668 
669 	case NOTIFY_IPSEC_INITIAL_CONTACT:
670 		printf("INITIAL CONTACT (%s)", ike_get_cookie (&np->data[0],
671 		    &np->data[8]));
672 		break;
673 
674 	case NOTIFY_STATUS_DPD_R_U_THERE:
675 	case NOTIFY_STATUS_DPD_R_U_THERE_ACK:
676 		printf("STATUS_DPD_R_U_THERE%s ",
677 		    type == NOTIFY_STATUS_DPD_R_U_THERE ? "" : "_ACK");
678 		if (np->spi_size != 16 ||
679 		    len < sizeof(struct notification_payload) +
680 		    sizeof(u_int32_t))
681 			printf("[bad notify]");
682 		else {
683 			seq = (u_int32_t *)&np->data[np->spi_size];
684 			printf("seq %u", ntohl(*seq));
685 		}
686 		break;
687 
688 
689 	default:
690 	  	printf("%d (unknown)", type);
691 		break;
692 	}
693 }
694 
695 void
696 ike_pl_vendor_print (u_int8_t *buf, int len, u_int8_t doi)
697 {
698 	struct vendor_payload *vp = (struct vendor_payload *)buf;
699 	u_int8_t *p;
700 	int i;
701 
702 	if (len < sizeof(struct vendor_payload)) {
703 		printf(" [|payload]");
704 		return;
705 	}
706 
707 	for (i = 0; i < sizeof vendor_ids / sizeof vendor_ids[0]; i ++)
708 		if (memcmp(vp->vid, vendor_ids[i].vid,
709 		    vendor_ids[i].len) == 0) {
710 			printf (" (supports %s)", vendor_ids[i].name);
711 			return;
712 		}
713 
714 	if (doi != IPSEC_DOI)
715 		return;
716 
717 	printf(" \"");
718 	for (p = vp->vid; (int)(p - buf) < len; p++)
719 		printf("%c", (isprint(*p) ? *p : '.'));
720 	printf("\"");
721 }
722 
723 /* IKE mode-config. */
724 int
725 ike_cfg_attribute_print (u_int8_t *buf, int attr_type, int maxlen)
726 {
727 	static char *attrs[] = IKE_CFG_ATTRIBUTE_INITIALIZER;
728 	char ntop_buf[INET6_ADDRSTRLEN];
729 	struct in_addr in;
730 
731 	u_int8_t af = buf[0] >> 7;
732 	u_int16_t type = (buf[0] & 0x7f) << 8 | buf[1];
733 	u_int16_t len = af ? 2 : buf[2] << 8 | buf[3], p;
734 	u_int8_t *val = af ? buf + 2 : buf + 4;
735 
736 	printf("\n\t%sattribute %s = ", ike_tab_offset(),
737 	    type < (sizeof attrs / sizeof attrs[0]) ? attrs[type] :
738 	    "<unknown>");
739 
740 	if ((af == 1 && maxlen < 4) ||
741 	    (af == 0 && maxlen < (len + 4))) {
742 		printf("\n\t%s[|attr]", ike_tab_offset());
743 		return maxlen;
744 	}
745 
746 	/* XXX The 2nd term is for bug compatibility with PGPnet.  */
747 	if (len == 0 || (af && !val[0] && !val[1])) {
748 		printf("<none>");
749 		return 4;
750 	}
751 
752 	/* XXX Generally lengths are not checked well below.  */
753 	switch (type) {
754 	case IKE_CFG_ATTR_INTERNAL_IP4_ADDRESS:
755 	case IKE_CFG_ATTR_INTERNAL_IP4_NETMASK:
756 	case IKE_CFG_ATTR_INTERNAL_IP4_DNS:
757 	case IKE_CFG_ATTR_INTERNAL_IP4_NBNS:
758 	case IKE_CFG_ATTR_INTERNAL_IP4_DHCP:
759 		memcpy (&in.s_addr, val, sizeof in);
760 		printf("%s", inet_ntoa (in));
761 		break;
762 
763 	case IKE_CFG_ATTR_INTERNAL_IP6_ADDRESS:
764 	case IKE_CFG_ATTR_INTERNAL_IP6_NETMASK:
765 	case IKE_CFG_ATTR_INTERNAL_IP6_DNS:
766 	case IKE_CFG_ATTR_INTERNAL_IP6_NBNS:
767 	case IKE_CFG_ATTR_INTERNAL_IP6_DHCP:
768 		printf("%s", inet_ntop (AF_INET6, val, ntop_buf,
769 		    sizeof ntop_buf));
770 		break;
771 
772 	case IKE_CFG_ATTR_INTERNAL_IP4_SUBNET:
773 		memcpy(&in.s_addr, val, sizeof in);
774 		printf("%s/", inet_ntoa (in));
775 		memcpy(&in.s_addr, val + sizeof in, sizeof in);
776 		printf("%s", inet_ntoa (in));
777 		break;
778 
779 	case IKE_CFG_ATTR_INTERNAL_IP6_SUBNET:
780 		printf("%s/%u", inet_ntop (AF_INET6, val, ntop_buf,
781 		    sizeof ntop_buf), val[16]);
782 		break;
783 
784 	case IKE_CFG_ATTR_INTERNAL_ADDRESS_EXPIRY:
785 		printf("%u seconds",
786 		    val[0] << 24 | val[1] << 16 | val[2] << 8 | val[3]);
787 		break;
788 
789 	case IKE_CFG_ATTR_APPLICATION_VERSION:
790 		for (p = 0; p < len; p++)
791 			printf("%c", isprint(val[p]) ? val[p] : '.');
792 		break;
793 
794 	case IKE_CFG_ATTR_SUPPORTED_ATTRIBUTES:
795 		printf("<%d attributes>", len / 2);
796 		ike_tab_level++;
797 		for (p = 0; p < len; p += 2) {
798 			type = (val[p] << 8 | val[p + 1]) & 0x7fff;
799 			printf("\n\t%s%s", ike_tab_offset(),
800 			    type < (sizeof attrs/sizeof attrs[0]) ?
801 			    attrs[type] : "<unknown>");
802 		}
803 		ike_tab_level--;
804 		break;
805 
806 	default:
807 		break;
808 	}
809 	return af ? 4 : len + 4;
810 }
811 
812 void
813 ike_pl_attribute_print (u_int8_t *buf, int len)
814 {
815 	struct attribute_payload *ap = (struct attribute_payload *)buf;
816 	static const char *pl_attr[] = IKE_CFG_ATTRIBUTE_TYPE_INITIALIZER;
817 	u_int8_t *attr = buf + sizeof(struct attribute_payload);
818 
819 	if (len < sizeof(struct attribute_payload)) {
820 		printf(" [|payload]");
821 		return;
822 	}
823 
824 	printf(" type: %s Id: %d",
825 	    ap->type < (sizeof pl_attr/sizeof pl_attr[0]) ? pl_attr[ap->type] :
826 	    "<unknown>", ap->id);
827 
828 	while ((int)(attr - buf) < len)
829 		attr += ike_cfg_attribute_print(attr, ap->type,
830 		    len - (attr - buf));
831 }
832 
833 void
834 ike_pl_print (u_int8_t type, u_int8_t *buf, u_int8_t doi)
835 {
836 	static const char *pltypes[] = IKE_PAYLOAD_TYPES_INITIALIZER;
837 	static const char *plprivtypes[] =
838 	    IKE_PRIVATE_PAYLOAD_TYPES_INITIALIZER;
839 	static const char *plv2types[] = IKEV2_PAYLOAD_TYPES_INITIALIZER;
840 	u_int8_t next_type;
841 	u_int16_t this_len;
842 
843 	if (&buf[4] > snapend) {
844 		goto pltrunc;
845 	}
846 
847 	next_type = buf[0];
848 	this_len = buf[2]<<8 | buf[3];
849 
850 	if (type < PAYLOAD_PRIVATE_MIN && type >= PAYLOAD_IKEV2_SA)
851 		printf("\n\t%spayload: %s len: %hu", ike_tab_offset(),
852 		    plv2types[type - PAYLOAD_IKEV2_SA], this_len);
853 	else if (type < PAYLOAD_PRIVATE_MIN || type >= PAYLOAD_PRIVATE_MAX)
854 		printf("\n\t%spayload: %s len: %hu", ike_tab_offset(),
855 		    (type < (sizeof pltypes/sizeof pltypes[0]) ?
856 			pltypes[type] : "<unknown>"), this_len);
857 	else
858 		printf("\n\t%spayload: %s len: %hu", ike_tab_offset(),
859 		    plprivtypes[type - PAYLOAD_PRIVATE_MIN], this_len);
860 
861 	if ((type < PAYLOAD_RESERVED_MIN &&
862 	    (type < sizeof(min_payload_lengths)/sizeof(min_payload_lengths[0]) &&
863 	    this_len < min_payload_lengths[type])) ||
864 	    this_len == 0)
865 		goto pltrunc;
866 
867 	if ((type > PAYLOAD_PRIVATE_MIN && type < PAYLOAD_PRIVATE_MAX &&
868 	    this_len < min_priv_payload_lengths[type - PAYLOAD_PRIVATE_MIN]) ||
869 	    this_len == 0)
870 		goto pltrunc;
871 
872 	if (buf + this_len > snapend)
873 		goto pltrunc;
874 
875 	ike_tab_level++;
876 	switch (type) {
877 	case PAYLOAD_NONE:
878 		return;
879 
880 	case PAYLOAD_SA:
881 		ike_pl_sa_print(buf, this_len);
882 		break;
883 
884 	case PAYLOAD_PROPOSAL:
885 		ike_pl_proposal_print(buf, this_len, doi);
886 		break;
887 
888 	case PAYLOAD_TRANSFORM:
889 		ike_pl_transform_print(buf, this_len, doi);
890 		break;
891 
892 	case PAYLOAD_KE:
893 		ike_pl_ke_print(buf, this_len, doi);
894 		break;
895 
896 	case PAYLOAD_ID:
897 		/* Should only happen with IPsec DOI */
898 		ipsec_id_print(buf, this_len, doi);
899 		break;
900 
901 	case PAYLOAD_CERT:
902 	case PAYLOAD_CERTREQUEST:
903 	case PAYLOAD_HASH:
904 	case PAYLOAD_SIG:
905 	case PAYLOAD_NONCE:
906 		break;
907 
908 	case PAYLOAD_DELETE:
909 		ike_pl_delete_print(buf, this_len);
910 		break;
911 
912 	case PAYLOAD_NOTIFICATION:
913 	  	ike_pl_notification_print(buf, this_len);
914 		break;
915 
916 	case PAYLOAD_VENDOR:
917 		ike_pl_vendor_print(buf, this_len, doi);
918 		break;
919 
920 	case PAYLOAD_ATTRIBUTE:
921 		ike_pl_attribute_print(buf, this_len);
922 		break;
923 
924 	case PAYLOAD_SAK:
925 	case PAYLOAD_SAT:
926 	case PAYLOAD_KD:
927 	case PAYLOAD_SEQ:
928 	case PAYLOAD_POP:
929 	case PAYLOAD_NAT_D:
930 		break;
931 
932 	case PAYLOAD_NAT_OA:
933 		/* RFC3947 NAT-OA uses a subset of the ID payload */
934 		ipsec_id_print(buf, this_len, doi);
935 		break;
936 
937 	case PAYLOAD_NAT_D_DRAFT:
938 		break;
939 
940 	case PAYLOAD_NAT_OA_DRAFT:
941 		ipsec_id_print(buf, this_len, doi);
942 		break;
943 
944 	default:
945 		break;
946 	}
947 	ike_tab_level--;
948 
949 	if (next_type)  /* Recurse over next payload */
950 		ike_pl_print(next_type, buf + this_len, doi);
951 
952 	return;
953 
954 pltrunc:
955 	if (doi == ISAKMP_DOI)
956 		fputs(" [|isakmp]", stdout);
957 	else
958 		fputs(" [|ipsec]", stdout);
959 }
960