xref: /freebsd/contrib/tcpdump/print-isoclns.c (revision f9218d3d4fd34f082473b3a021c6d4d109fb47cf)
1 /*
2  * Copyright (c) 1992, 1993, 1994, 1995, 1996
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that: (1) source code distributions
7  * retain the above copyright notice and this paragraph in its entirety, (2)
8  * distributions including binary code include the above copyright notice and
9  * this paragraph in its entirety in the documentation or other materials
10  * provided with the distribution, and (3) all advertising materials mentioning
11  * features or use of this software display the following acknowledgement:
12  * ``This product includes software developed by the University of California,
13  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14  * the University nor the names of its contributors may be used to endorse
15  * or promote products derived from this software without specific prior
16  * written permission.
17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20  *
21  * Original code by Matt Thomas, Digital Equipment Corporation
22  *
23  * Extensively modified by Hannes Gredler (hannes@juniper.net) for more
24  * complete IS-IS support.
25  *
26  * $FreeBSD$
27  */
28 
29 #ifndef lint
30 static const char rcsid[] =
31     "@(#) $Header: /tcpdump/master/tcpdump/print-isoclns.c,v 1.36.2.2 2002/06/29 04:28:44 guy Exp $ (LBL)";
32 #endif
33 
34 #ifdef HAVE_CONFIG_H
35 #include "config.h"
36 #endif
37 
38 #include <sys/types.h>
39 #include <sys/time.h>
40 #include <sys/socket.h>
41 
42 #include <netinet/in.h>
43 
44 #include <stdio.h>
45 #include <string.h>
46 
47 #include "interface.h"
48 #include "addrtoname.h"
49 #include "ethertype.h"
50 #include "ether.h"
51 #include "extract.h"
52 
53 #define	NLPID_CLNS	129	/* 0x81 */
54 #define	NLPID_ESIS	130	/* 0x82 */
55 #define	NLPID_ISIS	131	/* 0x83 */
56 #define NLPID_IP6       0x8e
57 #define NLPID_IP        0xcc
58 #define	NLPID_NULLNS	0
59 
60 /*
61  * IS-IS is defined in ISO 10589.  Look there for protocol definitions.
62  */
63 
64 #define SYSTEM_ID_LEN	ETHER_ADDR_LEN
65 #define ISIS_VERSION	1
66 #define PDU_TYPE_MASK	0x1F
67 #define PRIORITY_MASK	0x7F
68 
69 #define L1_LAN_IIH	15
70 #define L2_LAN_IIH	16
71 #define PTP_IIH		17
72 #define L1_LSP       	18
73 #define L2_LSP       	20
74 #define L1_CSNP  	24
75 #define L2_CSNP  	25
76 #define L1_PSNP		26
77 #define L2_PSNP		27
78 
79 
80 /*
81  * A TLV is a tuple of a type, length and a value and is normally used for
82  * encoding information in all sorts of places.  This is an enumeration of
83  * the well known types.
84  */
85 
86 #define TLV_AREA_ADDR           1
87 #define TLV_IS_REACH            2
88 #define TLV_ES_REACH            3
89 #define TLV_SUMMARY             5
90 #define TLV_ISNEIGH     	6
91 #define TLV_PADDING             8
92 #define TLV_LSP                 9
93 #define TLV_AUTH                10
94 #define TLV_CHECKSUM		12
95 #define TLV_EXT_IS_REACH	22
96 #define TLV_IP_REACH		128
97 #define TLV_PROTOCOLS		129
98 #define TLV_IP_REACH_EXT	130
99 #define TLV_IDRP_INFO		131
100 #define TLV_IPADDR              132
101 #define TLV_IPAUTH              133
102 #define TLV_TE_ROUTER_ID	134
103 #define TLV_EXT_IP_REACH	135
104 #define	TLV_HOSTNAME		137
105 #define TLV_RESTART_SIGNALING   211
106 #define	TLV_MT_IS_REACH		222
107 #define	TLV_MT_SUPPORTED	229
108 #define TLV_IP6ADDR             232
109 #define	TLV_MT_REACH		235
110 #define	TLV_IP6_REACH		236
111 #define TLV_PTP_ADJ		240
112 
113 #define SUBTLV_EXT_IS_REACH_ADMIN_GROUP        3
114 #define SUBTLV_EXT_IS_REACH_IPV4_INTF_ADDR     6
115 #define SUBTLV_EXT_IS_REACH_IPV4_NEIGHBOR_ADDR 8
116 #define SUBTLV_EXT_IS_REACH_MAX_LINK_BW        9
117 #define SUBTLV_EXT_IS_REACH_RESERVABLE_BW      10
118 #define SUBTLV_EXT_IS_REACH_UNRESERVED_BW      11
119 #define SUBTLV_EXT_IS_REACH_TE_METRIC          18
120 
121 #define SUBTLV_AUTH_SIMPLE      1
122 #define SUBTLV_AUTH_MD5         54
123 
124 #define ISIS_MASK_LEVEL_BITS(x)            ((x)&0x1)
125 
126 #define ISIS_MASK_LSP_OL_BIT(x)            ((x)&0x4)
127 #define ISIS_MASK_LSP_ISTYPE_BITS(x)       ((x)&0x3)
128 #define ISIS_MASK_LSP_PARTITION_BIT(x)     ((x)&0x80)
129 #define ISIS_MASK_LSP_ATT_BITS(x)          ((x)&0x78)
130 #define ISIS_MASK_LSP_ATT_ERROR_BIT(x)     ((x)&0x40)
131 #define ISIS_MASK_LSP_ATT_EXPENSE_BIT(x)   ((x)&0x20)
132 #define ISIS_MASK_LSP_ATT_DELAY_BIT(x)     ((x)&0x10)
133 #define ISIS_MASK_LSP_ATT_DEFAULT_BIT(x)   ((x)&0x8)
134 
135 #define ISIS_MASK_TLV_EXT_IP_UPDOWN(x)     ((x)&0x80)
136 #define ISIS_MASK_TLV_EXT_IP_SUBTLV(x)     ((x)&0x40)
137 
138 #define ISIS_MASK_TLV_IP6_UPDOWN(x)        ((x)&0x80)
139 #define ISIS_MASK_TLV_IP6_IE(x)            ((x)&0x40)
140 #define ISIS_MASK_TLV_IP6_SUBTLV(x)        ((x)&0x20)
141 
142 #define ISIS_MASK_RESTART_RR(x)            ((x)&0x1)
143 #define ISIS_MASK_RESTART_RA(x)            ((x)&0x2)
144 
145 #define ISIS_LSP_TLV_METRIC_SUPPORTED(x)   ((x)&0x80)
146 #define ISIS_LSP_TLV_METRIC_IE(x)          ((x)&0x40)
147 #define ISIS_LSP_TLV_METRIC_UPDOWN(x)      ((x)&0x80)
148 #define ISIS_LSP_TLV_METRIC_VALUE(x)	   ((x)&0x3f)
149 
150 #define ISIS_LSP_TYPE_UNUSED0   0
151 #define ISIS_LSP_TYPE_LEVEL_1   1
152 #define ISIS_LSP_TYPE_UNUSED2   2
153 #define ISIS_LSP_TYPE_LEVEL_2   3
154 
155 static struct tok isis_lsp_istype_values[] = {
156 	{ ISIS_LSP_TYPE_UNUSED0,	"Unused 0x0 (invalid)"},
157 	{ ISIS_LSP_TYPE_LEVEL_1,	"L1 IS"},
158 	{ ISIS_LSP_TYPE_UNUSED2,	"Unused 0x2 (invalid)"},
159 	{ ISIS_LSP_TYPE_LEVEL_2,	"L1L2 IS"},
160 	{ 0, NULL }
161 };
162 
163 static struct tok isis_nlpid_values[] = {
164 	{ NLPID_CLNS,	"CLNS"},
165 	{ NLPID_IP,     "IPv4"},
166 	{ NLPID_IP6,	"IPv6"},
167 	{ 0,            "unknown" }
168 };
169 
170 /*
171  * Katz's point to point adjacency TLV uses codes to tell us the state of
172  * the remote adjacency.  Enumerate them.
173  */
174 
175 #define ISIS_PTP_ADJ_UP   0
176 #define ISIS_PTP_ADJ_INIT 1
177 #define ISIS_PTP_ADJ_DOWN 2
178 
179 static int osi_cksum(const u_char *, u_int, u_char *);
180 static void esis_print(const u_char *, u_int);
181 static int isis_print(const u_char *, u_int);
182 
183 
184 static struct tok isis_ptp_adjancey_values[] = {
185 	{ ISIS_PTP_ADJ_UP,    "Up" },
186 	{ ISIS_PTP_ADJ_INIT,  "Initializing" },
187 	{ ISIS_PTP_ADJ_DOWN,  "Down" }
188 };
189 
190 struct isis_tlv_ptp_adj {
191     u_char adjacency_state;
192     u_char ext_local_circuit_id[4];
193     u_char neighbor_sysid[SYSTEM_ID_LEN];
194     u_char neighbor_ext_local_circuit_id[4];
195 };
196 
197 struct isis_tlv_ip_reach {
198     u_char metric_default;
199     u_char metric_delay;
200     u_char metric_expense;
201     u_char metric_error;
202     u_char prefix[4];
203     u_char mask[4];
204 };
205 
206 struct isis_tlv_is_reach {
207     u_char metric_default;
208     u_char metric_delay;
209     u_char metric_expense;
210     u_char metric_error;
211     u_char neighbor_nodeid[SYSTEM_ID_LEN+1];
212 };
213 
214 
215 struct isis_common_header {
216     u_char nlpid;
217     u_char fixed_len;
218     u_char version;			/* Protocol version? */
219     u_char id_length;
220     u_char pdu_type;		        /* 3 MSbs are reserved */
221     u_char pkt_version;			/* Packet format version? */
222     u_char reserved;
223     u_char max_area;
224 };
225 
226 struct isis_iih_lan_header {
227     u_char circuit_type;
228     u_char source_id[SYSTEM_ID_LEN];
229     u_char holding_time[2];
230     u_char pdu_len[2];
231     u_char priority;
232     u_char lan_id[SYSTEM_ID_LEN+1];
233 };
234 
235 struct isis_iih_ptp_header {
236     u_char circuit_type;
237     u_char source_id[SYSTEM_ID_LEN];
238     u_char holding_time[2];
239     u_char pdu_len[2];
240     u_char circuit_id;
241 };
242 
243 struct isis_lsp_header {
244     u_char pdu_len[2];
245     u_char remaining_lifetime[2];
246     u_char lsp_id[SYSTEM_ID_LEN+2];
247     u_char sequence_number[4];
248     u_char checksum[2];
249     u_char typeblock;
250 };
251 
252 struct isis_csnp_header {
253     u_char pdu_len[2];
254     u_char source_id[SYSTEM_ID_LEN+1];
255     u_char start_lsp_id[SYSTEM_ID_LEN+2];
256     u_char end_lsp_id[SYSTEM_ID_LEN+2];
257 };
258 
259 struct isis_psnp_header {
260     u_char pdu_len[2];
261     u_char source_id[SYSTEM_ID_LEN+1];
262 };
263 
264 struct isis_tlv_lsp {
265     u_char remaining_lifetime[2];
266     u_char lsp_id[SYSTEM_ID_LEN+2];
267     u_char sequence_number[4];
268     u_char checksum[2];
269 };
270 
271 #define ISIS_COMMON_HEADER_SIZE (sizeof(struct isis_common_header))
272 #define ISIS_IIH_LAN_HEADER_SIZE (sizeof(struct isis_iih_lan_header))
273 #define ISIS_IIH_PTP_HEADER_SIZE (sizeof(struct isis_iih_ptp_header))
274 #define ISIS_LSP_HEADER_SIZE (sizeof(struct isis_lsp_header))
275 #define ISIS_CSNP_HEADER_SIZE (sizeof(struct isis_csnp_header))
276 #define ISIS_PSNP_HEADER_SIZE (sizeof(struct isis_psnp_header))
277 
278 void isoclns_print(const u_char *p, u_int length, u_int caplen,
279 	      const u_char *esrc, const u_char *edst)
280 {
281 	u_char pdu_type;
282 	const struct isis_common_header *header;
283 
284 	header = (const struct isis_common_header *)p;
285 	pdu_type = header->pdu_type & PDU_TYPE_MASK;
286 
287 	if (caplen < 1) {
288 		printf("[|iso-clns] ");
289 		if (!eflag && esrc != NULL && edst != NULL)
290 			printf("%s > %s",
291 			       etheraddr_string(esrc),
292 			       etheraddr_string(edst));
293 		return;
294 	}
295 
296 	switch (*p) {
297 
298 	case NLPID_CLNS:
299 		(void)printf("CLNS(%d)", length);
300 		if (!eflag && esrc != NULL && edst != NULL)
301 			(void)printf(", %s > %s",
302 				     etheraddr_string(esrc),
303 				     etheraddr_string(edst));
304 		break;
305 
306 	case NLPID_ESIS:
307 		(void)printf("ESIS");
308 		if (!eflag && esrc != NULL && edst != NULL)
309 			(void)printf(", %s > %s",
310 				     etheraddr_string(esrc),
311 				     etheraddr_string(edst));
312 		esis_print(p, length);
313 		return;
314 
315 	case NLPID_ISIS:
316 		(void)printf("ISIS(%d)", length);
317 		if (!eflag && esrc != NULL && edst != NULL)
318 			(void)printf(", %s > %s",
319 			     etheraddr_string(esrc),
320 			     etheraddr_string(edst));
321 		if (!isis_print(p, length))
322 			default_print_unaligned(p, caplen);
323 		break;
324 
325 	case NLPID_NULLNS:
326 		(void)printf("ISO NULLNS(%d)", length);
327 		if (!eflag && esrc != NULL && edst != NULL)
328 			(void)printf(", %s > %s",
329 				     etheraddr_string(esrc),
330 				     etheraddr_string(edst));
331 		break;
332 
333 	default:
334 		(void)printf("CLNS %02x(%d)", p[0], length);
335 		if (!eflag && esrc != NULL && edst != NULL)
336 			(void)printf(", %s > %s",
337 				     etheraddr_string(esrc),
338 				     etheraddr_string(edst));
339 		if (caplen > 1)
340 			default_print_unaligned(p, caplen);
341 		break;
342 	}
343 }
344 
345 #define	ESIS_REDIRECT	6
346 #define	ESIS_ESH	2
347 #define	ESIS_ISH	4
348 
349 struct esis_hdr {
350 	u_char version;
351 	u_char reserved;
352 	u_char type;
353 	u_char tmo[2];
354 	u_char cksum[2];
355 };
356 
357 static void
358 esis_print(const u_char *p, u_int length)
359 {
360 	const u_char *ep;
361 	u_int li;
362 	const struct esis_hdr *eh;
363 	u_char off[2];
364 
365 	if (length <= 2) {
366 		if (qflag)
367 			printf(" bad pkt!");
368 		else
369 			printf(" no header at all!");
370 		return;
371 	}
372 	li = p[1];
373 	eh = (const struct esis_hdr *) &p[2];
374 	ep = p + li;
375 	if (li > length) {
376 		if (qflag)
377 			printf(" bad pkt!");
378 		else
379 			printf(" LI(%d) > PDU size (%d)!", li, length);
380 		return;
381 	}
382 	if (li < sizeof(struct esis_hdr) + 2) {
383 		if (qflag)
384 			printf(" bad pkt!");
385 		else {
386 			printf(" too short for esis header %d:", li);
387 			while (--length != 0)
388 				printf("%02X", *p++);
389 		}
390 		return;
391 	}
392 	switch (eh->type & 0x1f) {
393 
394 	case ESIS_REDIRECT:
395 		printf(" redirect");
396 		break;
397 
398 	case ESIS_ESH:
399 		printf(" esh");
400 		break;
401 
402 	case ESIS_ISH:
403 		printf(" ish");
404 		break;
405 
406 	default:
407 		printf(" type %d", eh->type & 0x1f);
408 		break;
409 	}
410 	off[0] = eh->cksum[0];
411 	off[1] = eh->cksum[1];
412 	if (vflag && osi_cksum(p, li, off)) {
413 		printf(" bad cksum (got %02x%02x)",
414 		       eh->cksum[1], eh->cksum[0]);
415 		default_print(p, length);
416 		return;
417 	}
418 	if (eh->version != 1) {
419 		printf(" unsupported version %d", eh->version);
420 		return;
421 	}
422 	p += sizeof(*eh) + 2;
423 	li -= sizeof(*eh) + 2;	/* protoid * li */
424 
425 	switch (eh->type & 0x1f) {
426 	case ESIS_REDIRECT: {
427 		const u_char *dst, *snpa, *is;
428 
429 		dst = p; p += *p + 1;
430 		if (p > snapend)
431 			return;
432 		printf("\n\t\t\t %s", isonsap_string(dst));
433 		snpa = p; p += *p + 1;
434 		is = p;   p += *p + 1;
435 		if (p > snapend)
436 			return;
437 		if (p > ep) {
438 			printf(" [bad li]");
439 			return;
440 		}
441 		if (is[0] == 0)
442 			printf(" > %s", etheraddr_string(&snpa[1]));
443 		else
444 			printf(" > %s", isonsap_string(is));
445 		li = ep - p;
446 		break;
447 	}
448 #if 0
449 	case ESIS_ESH:
450 		printf(" esh");
451 		break;
452 #endif
453 	case ESIS_ISH: {
454 		const u_char *is;
455 
456 		is = p; p += *p + 1;
457 		if (p > ep) {
458 			printf(" [bad li]");
459 			return;
460 		}
461 		if (p > snapend)
462 			return;
463 		if (!qflag)
464 			printf("\n\t\t\t %s", isonsap_string(is));
465 		li = ep - p;
466 		break;
467 	}
468 
469 	default:
470 		(void)printf(" len=%d", length);
471 		if (length && p < snapend) {
472 			length = snapend - p;
473 			default_print(p, length);
474 		}
475 		return;
476 	}
477 	if (vflag)
478 		while (p < ep && li) {
479 			u_int op, opli;
480 			const u_char *q;
481 
482 			if (snapend - p < 2)
483 				return;
484 			if (li < 2) {
485 				printf(" bad opts/li");
486 				return;
487 			}
488 			op = *p++;
489 			opli = *p++;
490 			li -= 2;
491 			if (opli > li) {
492 				printf(" opt (%d) too long", op);
493 				return;
494 			}
495 			li -= opli;
496 			q = p;
497 			p += opli;
498 			if (snapend < p)
499 				return;
500 			if (op == 198 && opli == 2) {
501 				printf(" tmo=%d", q[0] * 256 + q[1]);
502 				continue;
503 			}
504 			printf (" %d:<", op);
505 			while (opli-- > 0)
506 				printf("%02x", *q++);
507 			printf (">");
508 		}
509 }
510 
511 /*
512  * print_nsap
513  * Print out an NSAP.
514  */
515 static int
516 print_nsap(register const u_char *cp, register int length)
517 {
518 	int i;
519 
520 	for (i = 0; i < length; i++) {
521 		if (!TTEST2(*cp, 1))
522 			return (0);
523 		printf("%02x", *cp++);
524 		if (((i & 1) == 0) && (i + 1 < length)) {
525 			printf(".");
526 		}
527 	}
528 	return (1);
529 }
530 
531 static int
532 isis_print_sysid(const u_char *cp)
533 {
534 	int i;
535 
536 	for (i = 1; i <= 6; i++) {
537 		if (!TTEST2(*cp, 1))
538 			return (0);
539 		printf("%02x", *cp++);
540 		if ((i==2)^(i==4)) {
541 			printf(".");
542 		}
543 	}
544 	return (1);
545 }
546 
547 static int
548 isis_print_nodeid(const u_char *cp)
549 {
550 	int i;
551 
552 	for (i = 1; i <= 7; i++) {
553 		if (!TTEST2(*cp, 1))
554 			return (0);
555 		printf("%02x", *cp++);
556 		if ((i & 1) == 0) {
557 			printf(".");
558 		}
559 	}
560 	return (1);
561 }
562 
563 static void
564 isis_print_lspid(const u_char *cp)
565 {
566 	int i;
567 
568 	for (i = 1; i <= 7; i++) {
569 		printf("%02x", *cp++);
570 		if ((i & 1) == 0)
571 			printf(".");
572 	}
573 	printf("-%02x", *cp);
574 }
575 
576 static int
577 isis_print_tlv_ip_reach (const u_char *cp, int length)
578 {
579 	u_int bitmasks[33] = {
580 		0x00000000,
581 		0x80000000, 0xc0000000, 0xe0000000, 0xf0000000,
582 		0xf8000000, 0xfc000000, 0xfe000000, 0xff000000,
583 		0xff800000, 0xffc00000, 0xffe00000, 0xfff00000,
584 		0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000,
585 		0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000,
586 		0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00,
587 		0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0,
588 		0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff
589 	};
590 	u_int mask;
591 	int prefix_len;
592 	const struct isis_tlv_ip_reach *tlv_ip_reach;
593 
594 	tlv_ip_reach = (const struct isis_tlv_ip_reach *)cp;
595 
596 	while (length > 0) {
597 		if (length < sizeof(*tlv_ip_reach)) {
598 			printf("short IP reachability (%d vs %lu)", length,
599 			    (unsigned long)sizeof(*tlv_ip_reach));
600 			return (0);
601 		}
602 
603 		if (!TTEST(*tlv_ip_reach))
604 		    return (0);
605 
606 		mask = EXTRACT_32BITS(tlv_ip_reach->mask);
607 		prefix_len = 0;
608 
609 		while (prefix_len <= 33) {
610 			if (bitmasks[prefix_len++] == mask) {
611 				prefix_len--;
612 				break;
613 			}
614 		}
615 
616 		/*
617 		 * 34 indicates no match -> must be a discontiguous netmask
618 		 * lets dump the mask, otherwise print the prefix_len
619 		 */
620 		if (prefix_len == 34)
621 			printf("\n\t\t\tIPv4 prefix: %u.%u.%u.%u mask %u.%u.%u.%u",
622 			    (tlv_ip_reach->prefix)[0],
623 			    (tlv_ip_reach->prefix)[1],
624 			    (tlv_ip_reach->prefix)[2],
625 			    (tlv_ip_reach->prefix)[3],
626 			    (tlv_ip_reach->mask)[0], (tlv_ip_reach->mask)[1],
627 			    (tlv_ip_reach->mask)[2], (tlv_ip_reach->mask)[3]);
628 		else
629 			printf("\n\t\t\tIPv4 prefix: %u.%u.%u.%u/%u",
630 			    (tlv_ip_reach->prefix)[0],
631 			    (tlv_ip_reach->prefix)[1],
632 			    (tlv_ip_reach->prefix)[2],
633 			    (tlv_ip_reach->prefix)[3], prefix_len);
634 
635 		printf("\n\t\t\t  Default Metric: %02d, %s, Distribution: %s",
636 		    ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->metric_default),
637 		    ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->metric_default) ? "External" : "Internal",
638 		    ISIS_LSP_TLV_METRIC_UPDOWN(tlv_ip_reach->metric_default) ? "down" : "up");
639 
640 		if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_ip_reach->metric_delay))
641 			printf("\n\t\t\t  Delay Metric: %02d, %s",
642 			    ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->metric_delay),
643 			    ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->metric_delay) ? "External" : "Internal");
644 
645 		if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_ip_reach->metric_expense))
646 			printf("\n\t\t\t  Expense Metric: %02d, %s",
647 			    ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->metric_expense),
648 			    ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->metric_expense) ? "External" : "Internal");
649 
650 		if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_ip_reach->metric_error))
651 			printf("\n\t\t\t  Error Metric: %02d, %s",
652 			    ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->metric_error),
653 			    ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->metric_error) ? "External" : "Internal");
654 
655 		length -= sizeof(struct isis_tlv_ip_reach);
656 		tlv_ip_reach++;
657 	}
658 	return (1);
659 }
660 
661 /*
662  * isis_print
663  * Decode IS-IS packets.  Return 0 on error.
664  */
665 
666 static int isis_print (const u_char *p, u_int length)
667 {
668     const struct isis_common_header *header;
669 
670     const struct isis_iih_lan_header *header_iih_lan;
671     const struct isis_iih_ptp_header *header_iih_ptp;
672     const struct isis_lsp_header *header_lsp;
673     const struct isis_csnp_header *header_csnp;
674     const struct isis_psnp_header *header_psnp;
675 
676     const struct isis_tlv_lsp *tlv_lsp;
677     const struct isis_tlv_ptp_adj *tlv_ptp_adj;
678     const struct isis_tlv_is_reach *tlv_is_reach;
679 
680     u_char pdu_type, max_area, type, len, tmp, alen, subl, subt, tslen, ttslen;
681     const u_char *optr, *pptr, *tptr;
682     u_char subtlv_len;
683     u_short packet_len,pdu_len;
684     u_int i,j,bit_length,byte_length,metric;
685     u_char prefix[4]; /* copy buffer for ipv4 prefixes */
686 #ifdef INET6
687     u_char prefix6[16]; /* copy buffer for ipv6 prefixes */
688 #endif
689     u_char off[2];
690     float bw; /* copy buffer for several subTLVs of the extended IS reachability TLV */
691 
692     packet_len=length;
693     optr = p; /* initialize the _o_riginal pointer - need it for parsing the checksum TLV */
694     header = (const struct isis_common_header *)p;
695     TCHECK(*header);
696     pptr = p+(ISIS_COMMON_HEADER_SIZE);
697     header_iih_lan = (const struct isis_iih_lan_header *)pptr;
698     header_iih_ptp = (const struct isis_iih_ptp_header *)pptr;
699     header_lsp = (const struct isis_lsp_header *)pptr;
700     header_csnp = (const struct isis_csnp_header *)pptr;
701     header_psnp = (const struct isis_psnp_header *)pptr;
702 
703     /*
704      * Sanity checking of the header.
705      */
706     if (header->nlpid != NLPID_ISIS) {
707 	printf(", coding error!");
708 	return (0);
709     }
710 
711     if (header->version != ISIS_VERSION) {
712 	printf(", version %d packet not supported", header->version);
713 	return (0);
714     }
715 
716     if ((header->id_length != SYSTEM_ID_LEN) && (header->id_length != 0)) {
717 	printf(", system ID length of %d is not supported",
718 	       header->id_length);
719 	return (0);
720     }
721 
722     if (header->pkt_version != ISIS_VERSION) {
723 	printf(", version %d packet not supported", header->pkt_version);
724 	return (0);
725     }
726 
727     max_area = header->max_area;
728     switch(max_area) {
729     case 0:
730 	max_area = 3;			/* silly shit */
731 	break;
732     case 255:
733 	printf(", bad packet -- 255 areas");
734 	return (0);
735     default:
736 	break;
737     }
738 
739     printf(", hlen: %u, v: %u, sys-id-len: 6 (0), max-area: %u (%u)",
740            header->fixed_len,
741            header->pkt_version,
742            max_area,
743            header->max_area);
744 
745     pdu_type=header->pdu_type;
746 
747     switch (pdu_type) {
748 
749     case L1_LAN_IIH:
750     case L2_LAN_IIH:
751 	if (header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE)) {
752 	    printf(", bogus fixed header length %u should be %lu",
753 		   header->fixed_len, (unsigned long)ISIS_IIH_LAN_HEADER_SIZE);
754 	    return (0);
755 	}
756 
757 	pdu_len=EXTRACT_16BITS(header_iih_lan->pdu_len);
758 	if (packet_len>pdu_len) {
759 	  packet_len=pdu_len; /* do TLV decoding as long as it makes sense */
760 	  length=pdu_len;
761 	}
762 
763 	printf(", L%s Lan IIH (%u)",
764 	       ISIS_MASK_LEVEL_BITS(pdu_type) ? "1" : "2",
765 	       pdu_len);
766 
767 	TCHECK(*header_iih_lan);
768 	printf("\n\t\t  source-id: ");
769 	isis_print_sysid(header_iih_lan->source_id);
770 	printf(", holding time: %us",EXTRACT_16BITS(header_iih_lan->holding_time));
771 	switch(header_iih_lan->circuit_type) {
772 
773 	case 1:
774 	    printf(", Level 1 only");
775 	    break;
776 
777 	case 2:
778 	    printf(", Level 2 only");
779 	    break;
780 
781 	case 3:
782 	    printf(", Level 1, Level 2");
783 	    break;
784 
785 	default:
786 	    printf(", unknown 0x%02x", header_iih_lan->circuit_type);
787 	    break;
788 	}
789 	printf("\n\t\t  lan-id:    ");
790 	isis_print_nodeid(header_iih_lan->lan_id);
791 	printf(", Priority: %u",(header_iih_lan->priority) & PRIORITY_MASK);
792 
793 	packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE);
794 	pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE);
795 	break;
796 
797     case PTP_IIH:
798 	if (header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE)) {
799 	    printf(", bogus fixed header length %u should be %lu",
800 		   header->fixed_len, (unsigned long)ISIS_IIH_PTP_HEADER_SIZE);
801 	    return (0);
802 	}
803 
804 	pdu_len=EXTRACT_16BITS(header_iih_ptp->pdu_len);
805 	if (packet_len>pdu_len) {
806 	  packet_len=pdu_len; /* do TLV decoding as long as it makes sense */
807 	  length=pdu_len;
808 	}
809 
810 	printf(", PTP IIH (%u)",pdu_len);
811 	TCHECK(*header_iih_ptp);
812 	printf("\n\t\t  source-id: ");
813 	isis_print_sysid(header_iih_ptp->source_id);
814 	printf(", holding time: %us",EXTRACT_16BITS(header_iih_ptp->holding_time));
815 	printf(", circuit-id: 0x%02x", header_iih_ptp->circuit_id);
816 	switch(header_iih_ptp->circuit_type) {
817 
818 	case 1:
819 	    printf(", Level 1 only");
820 	    break;
821 
822 	case 2:
823 	    printf(", Level 2 only");
824 	    break;
825 
826 	case 3:
827 	    printf(", Level 1, Level 2");
828 	    break;
829 
830 	default:
831 	    printf(", unknown 0x%02x", header_iih_ptp->circuit_type);
832 	    break;
833 	}
834 
835 	packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE);
836 	pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE);
837 	break;
838 
839     case L1_LSP:
840     case L2_LSP:
841 	if (header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE)) {
842 	    printf(", bogus fixed header length %u should be %lu",
843 		   header->fixed_len, (unsigned long)ISIS_LSP_HEADER_SIZE);
844 	    return (0);
845 	}
846 
847 	pdu_len=EXTRACT_16BITS(header_lsp->pdu_len);
848 	if (packet_len>pdu_len) {
849 	  packet_len=pdu_len; /* do TLV decoding as long as it makes sense */
850 	  length=pdu_len;
851 	}
852 
853 	if (pdu_type == L1_LSP)
854 	    printf(", L1 LSP (%u)",pdu_len);
855 	else if (pdu_type == L2_LSP)
856 	    printf(", L2 LSP (%u)",pdu_len);
857 
858 	TCHECK(*header_lsp);
859 	printf("\n\t\t  lsp-id: ");
860 	isis_print_lspid(header_lsp->lsp_id);
861 	printf(", sequence number: 0x%08x",EXTRACT_32BITS(header_lsp->sequence_number));
862 	printf(", lifetime: %5us",EXTRACT_16BITS(header_lsp->remaining_lifetime));
863 	printf("\n\t\t  checksum: 0x%04x",EXTRACT_16BITS(header_lsp->checksum));
864 
865 	printf(", %s", ISIS_MASK_LSP_OL_BIT(header_lsp->typeblock) ? "Overload bit set, " : "");
866 
867 	if (ISIS_MASK_LSP_ATT_BITS(header_lsp->typeblock)) {
868 	    printf("%s", ISIS_MASK_LSP_ATT_DEFAULT_BIT(header_lsp->typeblock) ? "default " : "");
869 	    printf("%s", ISIS_MASK_LSP_ATT_DELAY_BIT(header_lsp->typeblock) ? "delay " : "");
870 	    printf("%s", ISIS_MASK_LSP_ATT_EXPENSE_BIT(header_lsp->typeblock) ? "expense " : "");
871 	    printf("%s", ISIS_MASK_LSP_ATT_ERROR_BIT(header_lsp->typeblock) ? "error " : "");
872 	    printf("ATT bit set, ");
873 	}
874 	printf("%s", ISIS_MASK_LSP_PARTITION_BIT(header_lsp->typeblock) ? "P bit set, " : "");
875 	printf("%s", tok2str(isis_lsp_istype_values,"Unknown(0x%x)",ISIS_MASK_LSP_ISTYPE_BITS(header_lsp->typeblock)));
876 
877 	packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE);
878 	pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE);
879 	break;
880 
881     case L1_CSNP:
882     case L2_CSNP:
883 	if (header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE)) {
884 	    printf(", bogus fixed header length %u should be %lu",
885 		   header->fixed_len, (unsigned long)ISIS_CSNP_HEADER_SIZE);
886 	    return (0);
887 	}
888 
889 	pdu_len=EXTRACT_16BITS(header_csnp->pdu_len);
890 	if (packet_len>pdu_len) {
891 	  packet_len=pdu_len; /* do TLV decoding as long as it makes sense */
892 	  length=pdu_len;
893 	}
894 
895 	printf(", L%s CSNP (%u)", ISIS_MASK_LEVEL_BITS(pdu_type) ? "2" : "1", pdu_len);
896 	TCHECK(*header_csnp);
897 	printf("\n\t\t  source-id:    ");
898 	isis_print_nodeid(header_csnp->source_id);
899 	printf("\n\t\t  start lsp-id: ");
900 	isis_print_lspid(header_csnp->start_lsp_id);
901 	printf("\n\t\t  end lsp-id:   ");
902 	isis_print_lspid(header_csnp->end_lsp_id);
903 
904 	packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE);
905 	pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE);
906         break;
907 
908     case L1_PSNP:
909     case L2_PSNP:
910 	if (header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE)) {
911 	    printf("- bogus fixed header length %u should be %lu",
912 		   header->fixed_len, (unsigned long)ISIS_PSNP_HEADER_SIZE);
913 	    return (0);
914 	}
915 
916 	pdu_len=EXTRACT_16BITS(header_psnp->pdu_len);
917 	if (packet_len>pdu_len) {
918 	  packet_len=pdu_len; /* do TLV decoding as long as it makes sense */
919 	  length=pdu_len;
920 	}
921 
922 	printf(", L%s PSNP (%u)", ISIS_MASK_LEVEL_BITS(pdu_type) ? "2" : "1", pdu_len);
923 	TCHECK(*header_psnp);
924 	printf("\n\t\t  source-id:    ");
925 	isis_print_nodeid(header_psnp->source_id);
926 
927 	packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE);
928 	pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE);
929 	break;
930 
931     default:
932 	printf(", PDU type (0x%02x) not supported", pdu_type);
933 	return (1);
934     }
935 
936     /*
937      * Now print the TLV's.
938      */
939 
940     while (packet_len >= 2) {
941         if (pptr == snapend) {
942 	    return (1);
943         }
944 
945 	if (!TTEST2(*pptr, 2)) {
946 	    printf("\n\t\t\t packet exceeded snapshot (%ld) bytes",
947 		  (long)(pptr-snapend));
948 	    return (1);
949 	}
950 	type = *pptr++;
951 	len = *pptr++;
952 	packet_len -= 2;
953 	if (len > packet_len) {
954 	    break;
955 	}
956 	printf("\n\t\t    ");
957 
958 	switch (type) {
959 	case TLV_AREA_ADDR:
960 	    printf("Area address(es) (%u)",len);
961 	    tmp = len;
962 	    tptr = pptr;
963 	    if (!TTEST2(*tptr, 1))
964 		goto trunctlv;
965 	    alen = *tptr++;
966 	    while (tmp && alen < tmp) {
967 		printf("\n\t\t\tArea address (%u): ",alen);
968 		if (!print_nsap(tptr, alen))
969 		    return (1);
970 		tptr += alen;
971 		tmp -= alen + 1;
972 		if (tmp==0) /* if this is the last area address do not attemt a boundary check */
973 		  break;
974 		if (!TTEST2(*tptr, 1))
975 		    goto trunctlv;
976 		alen = *tptr++;
977 	    }
978 	    break;
979 	case TLV_ISNEIGH:
980 	    printf("IS Neighbor(s) (%u)",len);
981 	    tmp = len;
982 	    tptr = pptr;
983 	    while (tmp >= ETHER_ADDR_LEN) {
984 		printf("\n\t\t\tIS Neighbor: ");
985 		if (!isis_print_sysid(tptr))
986 		    return (1);
987 		tmp -= ETHER_ADDR_LEN;
988 		tptr += ETHER_ADDR_LEN;
989 	    }
990 	    break;
991 
992 	case TLV_PADDING:
993 	    printf("Padding (%u)", len);
994 	    break;
995 
996         case TLV_MT_IS_REACH:
997             printf("Multi Topology IS Reachability (%u)",len);
998             tptr=pptr;
999             tmp=len;
1000             while (tmp>0) {
1001                 printf("\n\t\t\t");
1002                 if (!TTEST2(*tptr, 2))
1003 		    goto trunctlv;
1004 		switch(EXTRACT_16BITS(tptr)&0x0fff) {
1005 
1006 		case 0:
1007 			printf("IPv4 unicast");
1008 			break;
1009 
1010 	        case 1:
1011 			printf("In-Band Management");
1012 			break;
1013 
1014 	        case 2:
1015 			printf("IPv6 unicast");
1016 			break;
1017 
1018 	        case 3:
1019 			printf("Multicast");
1020 			break;
1021 
1022 	        case 4095:
1023 			printf("Development, Experimental or Proprietary");
1024 		        break;
1025 
1026 	        default:
1027 		        printf("Reserved for IETF Consensus");
1028 		        break;
1029 	        }
1030 		printf(" Topology (0x%03x)",EXTRACT_16BITS(tptr)&0x0fff);
1031                 tptr+=2;
1032             	printf("\n\t\t\t  IS Neighbor: ");
1033                 if (!isis_print_nodeid(tptr))
1034                     return (1);
1035                 tptr+=(SYSTEM_ID_LEN+1);
1036                 if (!TTEST2(*tptr, 3))
1037                     goto trunctlv;
1038                 printf(", Metric: %d",EXTRACT_24BITS(tptr));
1039                 tptr+=3;
1040                 if (!TTEST2(*tptr, 1))
1041                     goto trunctlv;
1042                 tslen=*(tptr++);
1043                 printf(", %ssub-TLVs present",tslen ? "" : "no ");
1044 
1045                 tptr+=tslen;
1046                 tmp-=(13+tslen);
1047             }
1048             break;
1049 
1050         case TLV_EXT_IS_REACH:
1051             printf("Extended IS Reachability (%u)",len);
1052             tptr=pptr;
1053             tmp=len;
1054             while (tmp>0) {
1055             	printf("\n\t\t\tIS Neighbor: ");
1056                 if (!isis_print_nodeid(tptr))
1057                     return (1);
1058                 tptr+=(SYSTEM_ID_LEN+1);
1059                 if (!TTEST2(*tptr, 3))
1060                     goto trunctlv;
1061                 printf(", Metric: %d",EXTRACT_24BITS(tptr));
1062                 tptr+=3;
1063                 if (!TTEST2(*tptr, 1))
1064                     goto trunctlv;
1065                 tslen=*(tptr++);
1066                 printf(", %ssub-TLVs present",tslen ? "" : "no ");
1067                 if (tslen) {
1068                     printf(" (%u)",tslen);
1069                     ttslen=tslen;
1070                     while (ttslen>0) {
1071                         if (!TTEST2(*tptr,2))
1072                             goto trunctlv;
1073                         printf("\n\t\t\t  ");
1074                     	subt=*(tptr++);
1075                     	subl=*(tptr++);
1076                         switch(subt) {
1077                         case SUBTLV_EXT_IS_REACH_ADMIN_GROUP:
1078                             printf("Administrative groups: 0x%08x", EXTRACT_32BITS(tptr));
1079                             break;
1080                         case SUBTLV_EXT_IS_REACH_MAX_LINK_BW :
1081                             if (!TTEST2(*tptr,4))
1082                                 goto trunctlv;
1083                             j = EXTRACT_32BITS(tptr);
1084                             memcpy (&bw, &j, 4);
1085                             printf("Maximum link bandwidth : %.3f Mbps",
1086                                    bw*8/1000000 );
1087                             break;
1088                         case SUBTLV_EXT_IS_REACH_RESERVABLE_BW :
1089                             if (!TTEST2(*tptr,4))
1090                                 goto trunctlv;
1091                             j = EXTRACT_32BITS(tptr);
1092                             memcpy (&bw, &j, 4);
1093                             printf("Reservable link bandwidth: %.3f Mbps",
1094                                    bw*8/1000000  );
1095                             break;
1096                         case SUBTLV_EXT_IS_REACH_UNRESERVED_BW :
1097                             printf("Unreserved bandwidth:");
1098                             for (i = 0; i < 8; i++) {
1099                                 if (!TTEST2(*tptr,4))
1100                                     goto trunctlv;
1101                                 j = EXTRACT_32BITS(tptr);
1102                                 memcpy (&bw, &j, 4);
1103                                 printf("\n\t\t\t    priority level %d: %.3f Mbps",
1104                                        i, bw*8/1000000 );
1105                                 tptr+=4;
1106                             }
1107                             tptr-=32;
1108                             break;
1109                         case SUBTLV_EXT_IS_REACH_TE_METRIC:
1110                             if (!TTEST2(*tptr,3))
1111                                 goto trunctlv;
1112                             printf("Traffic Engineering Metric: %d", EXTRACT_24BITS(tptr));
1113                             break;
1114                         case SUBTLV_EXT_IS_REACH_IPV4_INTF_ADDR:
1115                             if (!TTEST2(*tptr,4))
1116                                 goto trunctlv;
1117                             printf("IPv4 interface address: %s", ipaddr_string(tptr));
1118                             break;
1119                         case SUBTLV_EXT_IS_REACH_IPV4_NEIGHBOR_ADDR:
1120                             if (!TTEST2(*tptr,4))
1121                                 goto trunctlv;
1122                             printf("IPv4 neighbor address: %s", ipaddr_string(tptr));
1123                             break;
1124                         case 250:
1125                         case 251:
1126                         case 252:
1127                         case 253:
1128                         case 254:
1129                              printf("Reserved for cisco specific extensions, type %d, length %d", subt, subl);
1130                              break;
1131                         case 255:
1132                              printf("Reserved for future expansion, type %d, length %d", subt, subl);
1133                              break;
1134                         default:
1135                             printf("unknown subTLV, type %d, length %d", subt, subl);
1136                         }
1137 		    tptr+=subl;
1138 	            ttslen-=(subl+2);
1139                     }
1140                 }
1141                 tptr+=tslen;
1142                 tmp-=(11+tslen);
1143             }
1144             break;
1145         case TLV_IS_REACH:
1146             printf("IS Reachability (%u)",len);
1147 
1148 	    tptr=pptr;
1149 
1150 	    if (!TTEST2(*tptr,1))  /* check if there is one byte left to read out the virtual flag */
1151 		 goto trunctlv;
1152 
1153 	    switch (*tptr) {
1154 	    case 0:
1155 	      printf("\n\t\t\tIsNotVirtual");
1156 	      break;
1157 	    case 1:
1158 	      printf("\n\t\t\tIsVirtual");
1159 	      break;
1160 	    default:
1161 	      printf("\n\t\t\tbogus virtual flag 0x%02x",(*tptr));
1162 	      break;
1163 	    }
1164 
1165 	    tptr++;
1166 
1167 	    tlv_is_reach = (const struct isis_tlv_is_reach *)tptr;
1168 
1169 	    tmp = len;
1170             while (tmp >= sizeof(struct isis_tlv_is_reach)) {
1171 		if (!TTEST(*tlv_is_reach))
1172 		    goto trunctlv;
1173 
1174 		printf("\n\t\t\tIS Neighbor: ");
1175 		isis_print_nodeid(tlv_is_reach->neighbor_nodeid);
1176 
1177 		printf(", Default Metric: %d, %s",
1178 			   ISIS_LSP_TLV_METRIC_VALUE(tlv_is_reach->metric_default),
1179 			   ISIS_LSP_TLV_METRIC_IE(tlv_is_reach->metric_default) ? "External" : "Internal");
1180 
1181 		if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_is_reach->metric_delay))
1182 		    printf("\n\t\t\t  Delay Metric: %d, %s",
1183 				   ISIS_LSP_TLV_METRIC_VALUE(tlv_is_reach->metric_delay),
1184 				   ISIS_LSP_TLV_METRIC_IE(tlv_is_reach->metric_delay) ? "External" : "Internal");
1185 
1186 		if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_is_reach->metric_expense))
1187 		    printf("\n\t\t\t  Expense Metric: %d, %s",
1188 				   ISIS_LSP_TLV_METRIC_VALUE(tlv_is_reach->metric_expense),
1189 				   ISIS_LSP_TLV_METRIC_IE(tlv_is_reach->metric_expense) ? "External" : "Internal");
1190 
1191 		if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_is_reach->metric_error))
1192 		    printf("\n\t\t\t  Error Metric: %d, %s",
1193 				   ISIS_LSP_TLV_METRIC_VALUE(tlv_is_reach->metric_error),
1194 				   ISIS_LSP_TLV_METRIC_IE(tlv_is_reach->metric_error) ? "External" : "Internal");
1195 
1196 		tmp -= sizeof(struct isis_tlv_is_reach);
1197 		tlv_is_reach++;
1198 	    }
1199             break;
1200 
1201 	case TLV_IP_REACH:
1202 	    printf("IP Internal reachability (%u)",len);
1203 	    if (!isis_print_tlv_ip_reach(pptr, len))
1204 		return (1);
1205 	    break;
1206 
1207 	case TLV_IP_REACH_EXT:
1208 	    printf("IP External reachability (%u)",len);
1209 	    if (!isis_print_tlv_ip_reach(pptr, len))
1210 		return (1);
1211 	    break;
1212 
1213 	case TLV_EXT_IP_REACH:
1214 	    printf("Extended IP reachability (%u)",len);
1215 	    i=len;
1216 	    tptr=pptr;
1217 
1218 	    while (i>0) {
1219 		memset (prefix, 0, 4);
1220 		if (!TTEST2(*tptr, 4))
1221 		    return (1);
1222 	        metric = EXTRACT_32BITS(tptr);
1223 		tptr+=4;
1224 
1225 		if (!TTEST2(*tptr, 1))
1226 		    return (1);
1227 		j=*(tptr);
1228 		bit_length = (*(tptr)++&0x3f);
1229 		byte_length = (bit_length + 7) / 8;
1230 		if (!TTEST2(*tptr, byte_length))
1231 		    return (1);
1232 
1233 		memcpy(prefix,tptr,byte_length);
1234 
1235 		printf("\n\t\t\tIPv4 prefix: %u.%u.%u.%u/%d",
1236 		       prefix[0],
1237 		       prefix[1],
1238 		       prefix[2],
1239 		       prefix[3],
1240 		       bit_length);
1241 
1242 		printf("\n\t\t\t  Metric: %u, Distribution: %s",
1243 		       metric,
1244 		       ISIS_MASK_TLV_EXT_IP_UPDOWN(j) ? "down" : "up");
1245 
1246 		printf(", %ssub-TLVs present",
1247 		       ISIS_MASK_TLV_EXT_IP_SUBTLV(j) ? "" : "no ");
1248 
1249 		if (ISIS_MASK_TLV_EXT_IP_SUBTLV(j)) {
1250 		    if (!TTEST2(*tptr, 1))
1251 		      return (1);
1252 		    subtlv_len = *tptr;
1253 		    printf(" (%u)",subtlv_len);  /* no subTLV decoder supported - just print out subTLV length */
1254 		    i -= subtlv_len;
1255 		    tptr += subtlv_len + 1;
1256 		}
1257 
1258 		i-=(5+byte_length);
1259 		tptr+=byte_length;
1260 	    }
1261 	    break;
1262 
1263 #ifdef INET6
1264 
1265 	case TLV_IP6_REACH:
1266 	    printf("IP6 reachability (%u)",len);
1267 	    i=len;
1268 	    tptr=pptr;
1269 
1270 	    while (i>0) {
1271 		if (!TTEST2(*tptr, 4))
1272 		    return (1);
1273 	        metric = EXTRACT_32BITS(tptr);
1274 		tptr+=4;
1275 
1276 		if (!TTEST2(*tptr, 2))
1277 		    return (1);
1278 		j=*(tptr++);
1279 		bit_length = (*(tptr)++);
1280 		byte_length = (bit_length + 7) / 8;
1281 		if (!TTEST2(*tptr, byte_length))
1282 		    return (1);
1283 
1284 		memset(prefix6, 0, 16);
1285 		memcpy(prefix6,tptr,byte_length);
1286 
1287 		printf("\n\t\t\tIPv6 prefix: %s/%u",
1288 		       ip6addr_string(prefix6),
1289 		       bit_length);
1290 
1291 		printf("\n\t\t\t  Metric: %u, %s, Distribution: %s, %ssub-TLVs present",
1292 		    metric,
1293 		    ISIS_MASK_TLV_IP6_IE(j) ? "External" : "Internal",
1294 		    ISIS_MASK_TLV_IP6_UPDOWN(j) ? "down" : "up",
1295 		    ISIS_MASK_TLV_IP6_SUBTLV(j) ? "" : "no ");
1296 
1297 		if (ISIS_MASK_TLV_IP6_SUBTLV(j)) {
1298 		    if (!TTEST2(*tptr, 1))
1299 		      return (1);
1300 		    printf(" (%u)",*tptr); /* no subTLV decoder supported - just print out subTLV length */
1301 		    i-=*tptr;
1302 		    tptr+=*tptr++;
1303 		}
1304 
1305 		i-=(6+byte_length);
1306                 tptr+=byte_length;
1307 	    }
1308 
1309 	    break;
1310 #endif
1311 
1312 #ifdef INET6
1313 	case TLV_IP6ADDR:
1314 	    printf("IPv6 Interface address(es) (%u)",len);
1315 	    i=len;
1316 	    tptr=pptr;
1317 	    while (i>0) {
1318 		if (!TTEST2(*tptr, 16))
1319 		    goto trunctlv;
1320 
1321                 printf("\n\t\t\tIPv6 interface address: %s",
1322 		       ip6addr_string(tptr));
1323 
1324 		tptr += 16;
1325 		i -= 16;
1326 	    }
1327 	    break;
1328 #endif
1329 	case TLV_AUTH:
1330 	    if (!TTEST2(*pptr, 1))
1331 		goto trunctlv;
1332 	    printf("Authentication (%u)",len);
1333 	    if (*pptr==SUBTLV_AUTH_SIMPLE) {
1334 		printf("\n\t\t\tsimple text password: ");
1335 		for(i=1;i<len;i++) {
1336 		    if (!TTEST2(*(pptr+i), 1))
1337 			goto trunctlv;
1338 		    printf("%c",*(pptr+i));
1339 		}
1340 	    }
1341 	    if (!TTEST2(*pptr, 1))
1342 		goto trunctlv;
1343 	    if (*pptr==SUBTLV_AUTH_MD5) {
1344 		printf("\n\t\t\tMD5 password: ");
1345 		for(i=1;i<len;i++) {
1346 		    if (!TTEST2(*(pptr+i), 1))
1347 			goto trunctlv;
1348 		    printf("%02x",*(pptr+i));
1349 		}
1350 	    }
1351 	    break;
1352 
1353 	case TLV_PTP_ADJ:
1354 	    printf("Point-to-point Adjacency State (%u)",len);
1355 	    tlv_ptp_adj = (const struct isis_tlv_ptp_adj *)pptr;
1356 	    i=len;
1357 	    if(i>=1) {
1358 		if (!TTEST2(*pptr, 1))
1359 		    goto trunctlv;
1360 		printf("\n\t\t\tAdjacency State: %s",
1361 		       tok2str(isis_ptp_adjancey_values, "#0x%x", *pptr));
1362 		i--;
1363 	    }
1364 	    if(i>=4) {
1365 		if (!TTEST2(tlv_ptp_adj->ext_local_circuit_id, 4))
1366 		    goto trunctlv;
1367 		printf("\n\t\t\tExtended Local circuit ID: 0x%08x",
1368 		       EXTRACT_32BITS(tlv_ptp_adj->ext_local_circuit_id));
1369 		i-=4;
1370 	    }
1371 	    if(i>=6) {
1372 		if (!TTEST2(tlv_ptp_adj->neighbor_sysid, 6))
1373 		    goto trunctlv;
1374 		printf("\n\t\t\tNeighbor SystemID: ");
1375 		       isis_print_sysid(tlv_ptp_adj->neighbor_sysid);
1376 		i-=6;
1377 	    }
1378 	    if(i>=4) {
1379 		if (!TTEST2(tlv_ptp_adj->neighbor_ext_local_circuit_id, 4))
1380 		    goto trunctlv;
1381 		printf("\n\t\t\tNeighbor Extended Local circuit ID: 0x%08x",
1382 		       EXTRACT_32BITS(tlv_ptp_adj->neighbor_ext_local_circuit_id));
1383 	    }
1384 	    break;
1385 
1386 	case TLV_PROTOCOLS:
1387 	    printf("Protocols supported (%u)", len);
1388 	    printf("\n\t\t\tNLPID(s): ");
1389 	    for (i = 0; i < len; i++) {
1390 		if (!TTEST2(*(pptr+i), 1))
1391 		    goto trunctlv;
1392 		printf("%s (0x%02x)",tok2str(isis_nlpid_values, "Unknown", *(pptr+i)),*(pptr+i));
1393 		if (i<len-1)
1394 		    printf(", ");
1395 	    }
1396 	    break;
1397 
1398 	case TLV_TE_ROUTER_ID:
1399 	    printf("Traffic Engineering Router ID (%u)",len);
1400 	    if (!TTEST2(*pptr, 4))
1401 		goto trunctlv;
1402 	    printf("\n\t\t\tTraffic Engineering Router ID: %s", ipaddr_string(pptr));
1403 	    break;
1404 
1405 	case TLV_IPADDR:
1406 	    printf("IPv4 Interface address(es) (%u)",len);
1407 	    i=len;
1408 	    tptr=pptr;
1409 	    while (i>0) {
1410 		if (!TTEST2(*tptr, 4))
1411 		    goto trunctlv;
1412 		printf("\n\t\t\tIPv4 interface address: %s", ipaddr_string(tptr));
1413 		tptr += 4;
1414 		i -= 4;
1415 	    }
1416 	    break;
1417 
1418 	case TLV_HOSTNAME:
1419 	    printf("Hostname (%u)", len);
1420 	    printf("\n\t\t\tHostname: ");
1421 	    for(i = 0; i < len; i++) {
1422 		if (!TTEST2(*(pptr+i), 1))
1423 		    goto trunctlv;
1424 		printf("%c",*(pptr+i));
1425 	    }
1426 	    break;
1427 
1428 	case TLV_LSP:
1429 	    tlv_lsp = (const struct isis_tlv_lsp *)pptr;
1430 	    printf("LSP entries (%u)", len);
1431 	    i=0;
1432 	    while(i<len) {
1433 		printf("\n\t\t\tlsp-id: ");
1434 		if (!isis_print_nodeid(tlv_lsp->lsp_id))
1435 		    return (1);
1436 		if (!TTEST((tlv_lsp->lsp_id)[SYSTEM_ID_LEN+1]))
1437 		    goto trunctlv;
1438 		printf("-%02x",(tlv_lsp->lsp_id)[SYSTEM_ID_LEN+1]);
1439 		if (!TTEST2(tlv_lsp->sequence_number, 4))
1440 		    goto trunctlv;
1441 		printf("\n\t\t\t  sequence number: 0x%08x",EXTRACT_32BITS(tlv_lsp->sequence_number));
1442 		if (!TTEST2(tlv_lsp->remaining_lifetime, 2))
1443 		    goto trunctlv;
1444 		printf("\n\t\t\t  Remaining lifetime: %5ds",EXTRACT_16BITS(tlv_lsp->remaining_lifetime));
1445 		if (!TTEST2(tlv_lsp->checksum, 2))
1446 		    goto trunctlv;
1447 		printf("\n\t\t\t  checksum: 0x%04x",EXTRACT_16BITS(tlv_lsp->checksum));
1448 		i+=sizeof(struct isis_tlv_lsp);
1449 		tlv_lsp++;
1450 	    }
1451 	    break;
1452 
1453 	case TLV_CHECKSUM:
1454 	    if (!TTEST2(*pptr, 2))
1455 		goto trunctlv;
1456 	    printf("Checksum (%u)", len);
1457 	    printf("\n\t\t\tchecksum: 0x%04x",
1458 		   EXTRACT_16BITS(pptr));
1459 
1460 	    if (osi_cksum(optr, length, off))
1461 		printf(" (incorrect)");
1462 	    else
1463 		printf(" (correct)");
1464 	    break;
1465 
1466 	case TLV_MT_SUPPORTED:
1467 	    printf("Multi Topology (%u)",len);
1468 	    i=len;
1469 	    tptr=pptr;
1470 	    while (i>1) {
1471 		/* length can only be a multiple of 2, otherwise there is
1472 		   something broken -> so decode down until length is 1 */
1473 		if (i!=1) {
1474 		    if (!TTEST2(*tptr, 2))
1475 			goto trunctlv;
1476 		    printf("\n\t\t\t");
1477 		    switch(EXTRACT_16BITS(tptr)&0x0fff) {
1478 
1479 		    case 0:
1480 			printf("IPv4 unicast");
1481 			break;
1482 
1483 		    case 1:
1484 			printf("In-Band Management");
1485 			break;
1486 
1487 		    case 2:
1488 			printf("IPv6 unicast");
1489 			break;
1490 
1491 		    case 3:
1492 			printf("Multicast");
1493 			break;
1494 
1495 		    case 4095:
1496 			printf("Development, Experimental or Proprietary");
1497 		        break;
1498 
1499 		    default:
1500 			printf("Reserved for IETF Consensus");
1501 			break;
1502 		    }
1503 		    printf(" Topology (0x%03x)%s%s",
1504 			   EXTRACT_16BITS(tptr)&0xfff,
1505 			   (EXTRACT_16BITS(tptr)&0x8000) ? "" : ", no sub-TLVs present",
1506 			   (EXTRACT_16BITS(tptr)&0x4000) ? ", ATT bit set" : "" );
1507 		} else {
1508 		    printf("\n\t\t\tmalformed MT-ID");
1509 		    break;
1510 		}
1511 		i-=2;
1512 		tptr+=2;
1513 	    }
1514 	    break;
1515 
1516 	case TLV_RESTART_SIGNALING:
1517 	    tptr=pptr;
1518 	    printf("Restart Signaling (%u)",len);
1519 		    if (!TTEST2(*tptr, 3))
1520 			goto trunctlv;
1521 
1522 	    printf("\n\t\t\tRestart Request bit %s, Restart Acknowledgement bit %s\n\t\t\tRemaining holding time: %us",
1523                    ISIS_MASK_RESTART_RR(*tptr) ? "set" : "clear",
1524 		   ISIS_MASK_RESTART_RA(*tptr) ? "set" : "clear",
1525 		   EXTRACT_16BITS(tptr+1));
1526 	    tptr += 3;
1527 
1528 	    break;
1529 
1530 	default:
1531 	    printf("unknown TLV, type %d, length %d\n\t\t\t", type, len);
1532 	    tptr=pptr;
1533 
1534 	    for(i=0;i<len;i++) {
1535 		if (!TTEST2(*(tptr+i), 1))
1536 		    goto trunctlv;
1537 		printf("%02x",*(tptr+i)); /* formatted hex output of unknown TLV data */
1538 		if (i%2)
1539 		    printf(" ");
1540 		if (i/16!=(i+1)/16) {
1541 		  if (i<(len-1))
1542 		    printf("\n\t\t\t");
1543 		}
1544 	    }
1545 	    break;
1546 	}
1547 
1548 	pptr += len;
1549 	packet_len -= len;
1550     }
1551 
1552     if (packet_len != 0) {
1553 	printf("\n\t\t\t %d straggler bytes", packet_len);
1554     }
1555     return (1);
1556 
1557 trunc:
1558     fputs("[|isis]", stdout);
1559     return (1);
1560 
1561 trunctlv:
1562     printf("\n\t\t\t packet exceeded snapshot");
1563     return(1);
1564 }
1565 
1566 /*
1567  * Verify the checksum.  See 8473-1, Appendix C, section C.4.
1568  */
1569 
1570 static int
1571 osi_cksum(register const u_char *p, register u_int len, u_char *off)
1572 {
1573 	int32_t c0 = 0, c1 = 0;
1574 
1575 	if ((off[0] == 0) && (off[1] == 0))
1576 		return 0;
1577 
1578 	off[0] = off[1] = 0;
1579 	while ((int)--len >= 0) {
1580 		c0 += *p++;
1581 		c0 %= 255;
1582 		c1 += c0;
1583 		c1 %= 255;
1584 	}
1585 	return (c0 | c1);
1586 }
1587 
1588