xref: /freebsd/contrib/tcpdump/print-isoclns.c (revision 09e8dea79366f1e5b3a73e8a271b26e4b6bf2e6a)
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 2002/01/10 09:33:23 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 	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 	int mask, prefix_len;
591 	const struct isis_tlv_ip_reach *tlv_ip_reach;
592 
593 	tlv_ip_reach = (const struct isis_tlv_ip_reach *)cp;
594 
595 	while (length > 0) {
596 		if (length < sizeof(*tlv_ip_reach)) {
597 			printf("short IP reachability (%d vs %lu)", length,
598 			    (unsigned long)sizeof(*tlv_ip_reach));
599 			return (0);
600 		}
601 
602 		if (!TTEST(*tlv_ip_reach))
603 		    return (0);
604 
605 		mask = EXTRACT_32BITS(tlv_ip_reach->mask);
606 		prefix_len = 0;
607 
608 		while (prefix_len <= 33) {
609 			if (bitmasks[prefix_len++] == mask) {
610 				prefix_len--;
611 				break;
612 			}
613 		}
614 
615 		/*
616 		 * 34 indicates no match -> must be a discontiguous netmask
617 		 * lets dump the mask, otherwise print the prefix_len
618 		 */
619 		if (prefix_len == 34)
620 			printf("\n\t\t\tIPv4 prefix: %u.%u.%u.%u mask %u.%u.%u.%u",
621 			    (tlv_ip_reach->prefix)[0],
622 			    (tlv_ip_reach->prefix)[1],
623 			    (tlv_ip_reach->prefix)[2],
624 			    (tlv_ip_reach->prefix)[3],
625 			    (tlv_ip_reach->mask)[0], (tlv_ip_reach->mask)[1],
626 			    (tlv_ip_reach->mask)[2], (tlv_ip_reach->mask)[3]);
627 		else
628 			printf("\n\t\t\tIPv4 prefix: %u.%u.%u.%u/%u",
629 			    (tlv_ip_reach->prefix)[0],
630 			    (tlv_ip_reach->prefix)[1],
631 			    (tlv_ip_reach->prefix)[2],
632 			    (tlv_ip_reach->prefix)[3], prefix_len);
633 
634 		printf("\n\t\t\t  Default Metric: %02d, %s, Distribution: %s",
635 		    ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->metric_default),
636 		    ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->metric_default) ? "External" : "Internal",
637 		    ISIS_LSP_TLV_METRIC_UPDOWN(tlv_ip_reach->metric_default) ? "down" : "up");
638 
639 		if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_ip_reach->metric_delay))
640 			printf("\n\t\t\t  Delay Metric: %02d, %s",
641 			    ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->metric_delay),
642 			    ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->metric_delay) ? "External" : "Internal");
643 
644 		if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_ip_reach->metric_expense))
645 			printf("\n\t\t\t  Expense Metric: %02d, %s",
646 			    ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->metric_expense),
647 			    ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->metric_expense) ? "External" : "Internal");
648 
649 		if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_ip_reach->metric_error))
650 			printf("\n\t\t\t  Error Metric: %02d, %s",
651 			    ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->metric_error),
652 			    ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->metric_error) ? "External" : "Internal");
653 
654 		length -= sizeof(struct isis_tlv_ip_reach);
655 		tlv_ip_reach++;
656 	}
657 	return (1);
658 }
659 
660 /*
661  * isis_print
662  * Decode IS-IS packets.  Return 0 on error.
663  */
664 
665 static int isis_print (const u_char *p, u_int length)
666 {
667     const struct isis_common_header *header;
668 
669     const struct isis_iih_lan_header *header_iih_lan;
670     const struct isis_iih_ptp_header *header_iih_ptp;
671     const struct isis_lsp_header *header_lsp;
672     const struct isis_csnp_header *header_csnp;
673     const struct isis_psnp_header *header_psnp;
674 
675     const struct isis_tlv_lsp *tlv_lsp;
676     const struct isis_tlv_ptp_adj *tlv_ptp_adj;
677     const struct isis_tlv_is_reach *tlv_is_reach;
678 
679     u_char pdu_type, max_area, type, len, tmp, alen, subl, subt, tslen, ttslen;
680     const u_char *optr, *pptr, *tptr;
681     u_short packet_len,pdu_len;
682     u_int i,j,bit_length,byte_length,metric;
683     u_char prefix[4]; /* copy buffer for ipv4 prefixes */
684 #ifdef INET6
685     u_char prefix6[16]; /* copy buffer for ipv6 prefixes */
686 #endif
687     u_char off[2];
688     float bw; /* copy buffer for several subTLVs of the extended IS reachability TLV */
689 
690     packet_len=length;
691     optr = p; /* initialize the _o_riginal pointer - need it for parsing the checksum TLV */
692     header = (const struct isis_common_header *)p;
693     TCHECK(*header);
694     pptr = p+(ISIS_COMMON_HEADER_SIZE);
695     header_iih_lan = (const struct isis_iih_lan_header *)pptr;
696     header_iih_ptp = (const struct isis_iih_ptp_header *)pptr;
697     header_lsp = (const struct isis_lsp_header *)pptr;
698     header_csnp = (const struct isis_csnp_header *)pptr;
699     header_psnp = (const struct isis_psnp_header *)pptr;
700 
701     /*
702      * Sanity checking of the header.
703      */
704     if (header->nlpid != NLPID_ISIS) {
705 	printf(", coding error!");
706 	return (0);
707     }
708 
709     if (header->version != ISIS_VERSION) {
710 	printf(", version %d packet not supported", header->version);
711 	return (0);
712     }
713 
714     if ((header->id_length != SYSTEM_ID_LEN) && (header->id_length != 0)) {
715 	printf(", system ID length of %d is not supported",
716 	       header->id_length);
717 	return (0);
718     }
719 
720     if (header->pkt_version != ISIS_VERSION) {
721 	printf(", version %d packet not supported", header->pkt_version);
722 	return (0);
723     }
724 
725     max_area = header->max_area;
726     switch(max_area) {
727     case 0:
728 	max_area = 3;			/* silly shit */
729 	break;
730     case 255:
731 	printf(", bad packet -- 255 areas");
732 	return (0);
733     default:
734 	break;
735     }
736 
737     printf(", hlen: %u, v: %u, sys-id-len: 6 (0), max-area: %u (%u)",
738            header->fixed_len,
739            header->pkt_version,
740            max_area,
741            header->max_area);
742 
743     pdu_type=header->pdu_type;
744 
745     switch (pdu_type) {
746 
747     case L1_LAN_IIH:
748     case L2_LAN_IIH:
749 	if (header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE)) {
750 	    printf(", bogus fixed header length %u should be %lu",
751 		   header->fixed_len, (unsigned long)ISIS_IIH_LAN_HEADER_SIZE);
752 	    return (0);
753 	}
754 
755 	pdu_len=EXTRACT_16BITS(header_iih_lan->pdu_len);
756 	if (packet_len>pdu_len) {
757 	  packet_len=pdu_len; /* do TLV decoding as long as it makes sense */
758 	  length=pdu_len;
759 	}
760 
761 	printf(", L%s Lan IIH (%u)",
762 	       ISIS_MASK_LEVEL_BITS(pdu_type) ? "1" : "2",
763 	       pdu_len);
764 
765 	TCHECK(*header_iih_lan);
766 	printf("\n\t\t  source-id: ");
767 	isis_print_sysid(header_iih_lan->source_id);
768 	printf(", holding time: %us",EXTRACT_16BITS(header_iih_lan->holding_time));
769 	switch(header_iih_lan->circuit_type) {
770 
771 	case 1:
772 	    printf(", Level 1 only");
773 	    break;
774 
775 	case 2:
776 	    printf(", Level 2 only");
777 	    break;
778 
779 	case 3:
780 	    printf(", Level 1, Level 2");
781 	    break;
782 
783 	default:
784 	    printf(", unknown 0x%02x", header_iih_lan->circuit_type);
785 	    break;
786 	}
787 	printf("\n\t\t  lan-id:    ");
788 	isis_print_nodeid(header_iih_lan->lan_id);
789 	printf(", Priority: %u",(header_iih_lan->priority) & PRIORITY_MASK);
790 
791 	packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE);
792 	pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE);
793 	break;
794 
795     case PTP_IIH:
796 	if (header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE)) {
797 	    printf(", bogus fixed header length %u should be %lu",
798 		   header->fixed_len, (unsigned long)ISIS_IIH_PTP_HEADER_SIZE);
799 	    return (0);
800 	}
801 
802 	pdu_len=EXTRACT_16BITS(header_iih_ptp->pdu_len);
803 	if (packet_len>pdu_len) {
804 	  packet_len=pdu_len; /* do TLV decoding as long as it makes sense */
805 	  length=pdu_len;
806 	}
807 
808 	printf(", PTP IIH (%u)",pdu_len);
809 	TCHECK(*header_iih_ptp);
810 	printf("\n\t\t  source-id: ");
811 	isis_print_sysid(header_iih_ptp->source_id);
812 	printf(", holding time: %us",EXTRACT_16BITS(header_iih_ptp->holding_time));
813 	printf(", circuit-id: 0x%02x", header_iih_ptp->circuit_id);
814 	switch(header_iih_ptp->circuit_type) {
815 
816 	case 1:
817 	    printf(", Level 1 only");
818 	    break;
819 
820 	case 2:
821 	    printf(", Level 2 only");
822 	    break;
823 
824 	case 3:
825 	    printf(", Level 1, Level 2");
826 	    break;
827 
828 	default:
829 	    printf(", unknown 0x%02x", header_iih_ptp->circuit_type);
830 	    break;
831 	}
832 
833 	packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE);
834 	pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE);
835 	break;
836 
837     case L1_LSP:
838     case L2_LSP:
839 	if (header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE)) {
840 	    printf(", bogus fixed header length %u should be %lu",
841 		   header->fixed_len, (unsigned long)ISIS_LSP_HEADER_SIZE);
842 	    return (0);
843 	}
844 
845 	pdu_len=EXTRACT_16BITS(header_lsp->pdu_len);
846 	if (packet_len>pdu_len) {
847 	  packet_len=pdu_len; /* do TLV decoding as long as it makes sense */
848 	  length=pdu_len;
849 	}
850 
851 	if (pdu_type == L1_LSP)
852 	    printf(", L1 LSP (%u)",pdu_len);
853 	else if (pdu_type == L2_LSP)
854 	    printf(", L2 LSP (%u)",pdu_len);
855 
856 	TCHECK(*header_lsp);
857 	printf("\n\t\t  lsp-id: ");
858 	isis_print_lspid(header_lsp->lsp_id);
859 	printf(", sequence number: 0x%08x",EXTRACT_32BITS(header_lsp->sequence_number));
860 	printf(", lifetime: %5us",EXTRACT_16BITS(header_lsp->remaining_lifetime));
861 	printf("\n\t\t  checksum: 0x%04x",EXTRACT_16BITS(header_lsp->checksum));
862 
863 	printf(", %s", ISIS_MASK_LSP_OL_BIT(header_lsp->typeblock) ? "Overload bit set, " : "");
864 
865 	if (ISIS_MASK_LSP_ATT_BITS(header_lsp->typeblock)) {
866 	    printf("%s", ISIS_MASK_LSP_ATT_DEFAULT_BIT(header_lsp->typeblock) ? "default " : "");
867 	    printf("%s", ISIS_MASK_LSP_ATT_DELAY_BIT(header_lsp->typeblock) ? "delay " : "");
868 	    printf("%s", ISIS_MASK_LSP_ATT_EXPENSE_BIT(header_lsp->typeblock) ? "expense " : "");
869 	    printf("%s", ISIS_MASK_LSP_ATT_ERROR_BIT(header_lsp->typeblock) ? "error " : "");
870 	    printf("ATT bit set, ");
871 	}
872 	printf("%s", ISIS_MASK_LSP_PARTITION_BIT(header_lsp->typeblock) ? "P bit set, " : "");
873 	printf("%s", tok2str(isis_lsp_istype_values,"Unknown(0x%x)",ISIS_MASK_LSP_ISTYPE_BITS(header_lsp->typeblock)));
874 
875 	packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE);
876 	pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE);
877 	break;
878 
879     case L1_CSNP:
880     case L2_CSNP:
881 	if (header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE)) {
882 	    printf(", bogus fixed header length %u should be %lu",
883 		   header->fixed_len, (unsigned long)ISIS_CSNP_HEADER_SIZE);
884 	    return (0);
885 	}
886 
887 	pdu_len=EXTRACT_16BITS(header_csnp->pdu_len);
888 	if (packet_len>pdu_len) {
889 	  packet_len=pdu_len; /* do TLV decoding as long as it makes sense */
890 	  length=pdu_len;
891 	}
892 
893 	printf(", L%s CSNP (%u)", ISIS_MASK_LEVEL_BITS(pdu_type) ? "2" : "1", pdu_len);
894 	TCHECK(*header_csnp);
895 	printf("\n\t\t  source-id:    ");
896 	isis_print_nodeid(header_csnp->source_id);
897 	printf("\n\t\t  start lsp-id: ");
898 	isis_print_lspid(header_csnp->start_lsp_id);
899 	printf("\n\t\t  end lsp-id:   ");
900 	isis_print_lspid(header_csnp->end_lsp_id);
901 
902 	packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE);
903 	pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE);
904         break;
905 
906     case L1_PSNP:
907     case L2_PSNP:
908 	if (header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE)) {
909 	    printf("- bogus fixed header length %u should be %lu",
910 		   header->fixed_len, (unsigned long)ISIS_PSNP_HEADER_SIZE);
911 	    return (0);
912 	}
913 
914 	pdu_len=EXTRACT_16BITS(header_psnp->pdu_len);
915 	if (packet_len>pdu_len) {
916 	  packet_len=pdu_len; /* do TLV decoding as long as it makes sense */
917 	  length=pdu_len;
918 	}
919 
920 	printf(", L%s PSNP (%u)", ISIS_MASK_LEVEL_BITS(pdu_type) ? "2" : "1", pdu_len);
921 	TCHECK(*header_psnp);
922 	printf("\n\t\t  source-id:    ");
923 	isis_print_nodeid(header_psnp->source_id);
924 
925 	packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE);
926 	pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE);
927 	break;
928 
929     default:
930 	printf(", PDU type (0x%02x) not supported", pdu_type);
931 	return (1);
932     }
933 
934     /*
935      * Now print the TLV's.
936      */
937 
938     while (packet_len >= 2) {
939         if (pptr == snapend) {
940 	    return (1);
941         }
942 
943 	if (!TTEST2(*pptr, 2)) {
944 	    printf("\n\t\t\t packet exceeded snapshot (%ld) bytes",
945 		  (long)(pptr-snapend));
946 	    return (1);
947 	}
948 	type = *pptr++;
949 	len = *pptr++;
950 	packet_len -= 2;
951 	if (len > packet_len) {
952 	    break;
953 	}
954 	printf("\n\t\t    ");
955 
956 	switch (type) {
957 	case TLV_AREA_ADDR:
958 	    printf("Area address(es) (%u)",len);
959 	    tmp = len;
960 	    tptr = pptr;
961 	    if (!TTEST2(*tptr, 1))
962 		goto trunctlv;
963 	    alen = *tptr++;
964 	    while (tmp && alen < tmp) {
965 		printf("\n\t\t\tArea address (%u): ",alen);
966 		if (!print_nsap(tptr, alen))
967 		    return (1);
968 		tptr += alen;
969 		tmp -= alen + 1;
970 		if (tmp==0) /* if this is the last area address do not attemt a boundary check */
971 		  break;
972 		if (!TTEST2(*tptr, 1))
973 		    goto trunctlv;
974 		alen = *tptr++;
975 	    }
976 	    break;
977 	case TLV_ISNEIGH:
978 	    printf("IS Neighbor(s) (%u)",len);
979 	    tmp = len;
980 	    tptr = pptr;
981 	    while (tmp >= ETHER_ADDR_LEN) {
982 		printf("\n\t\t\tIS Neighbor: ");
983 		if (!isis_print_sysid(tptr))
984 		    return (1);
985 		tmp -= ETHER_ADDR_LEN;
986 		tptr += ETHER_ADDR_LEN;
987 	    }
988 	    break;
989 
990 	case TLV_PADDING:
991 	    printf("Padding (%u)", len);
992 	    break;
993 
994         case TLV_MT_IS_REACH:
995             printf("Multi Topology IS Reachability (%u)",len);
996             tptr=pptr;
997             tmp=len;
998             while (tmp>0) {
999                 printf("\n\t\t\t");
1000                 if (!TTEST2(*tptr, 2))
1001 		    goto trunctlv;
1002 		switch(EXTRACT_16BITS(tptr)&0x0fff) {
1003 
1004 		case 0:
1005 			printf("IPv4 unicast");
1006 			break;
1007 
1008 	        case 1:
1009 			printf("In-Band Management");
1010 			break;
1011 
1012 	        case 2:
1013 			printf("IPv6 unicast");
1014 			break;
1015 
1016 	        case 3:
1017 			printf("Multicast");
1018 			break;
1019 
1020 	        case 4095:
1021 			printf("Development, Experimental or Proprietary");
1022 		        break;
1023 
1024 	        default:
1025 		        printf("Reserved for IETF Consensus");
1026 		        break;
1027 	        }
1028 		printf(" Topology (0x%03x)",EXTRACT_16BITS(tptr)&0x0fff);
1029                 tptr+=2;
1030             	printf("\n\t\t\t  IS Neighbor: ");
1031                 if (!isis_print_nodeid(tptr))
1032                     return (1);
1033                 tptr+=(SYSTEM_ID_LEN+1);
1034                 if (!TTEST2(*tptr, 3))
1035                     goto trunctlv;
1036                 printf(", Metric: %d",EXTRACT_24BITS(tptr));
1037                 tptr+=3;
1038                 if (!TTEST2(*tptr, 1))
1039                     goto trunctlv;
1040                 tslen=*(tptr++);
1041                 printf(", %ssub-TLVs present",tslen ? "" : "no ");
1042 
1043                 tptr+=tslen;
1044                 tmp-=(13+tslen);
1045             }
1046             break;
1047 
1048         case TLV_EXT_IS_REACH:
1049             printf("Extended IS Reachability (%u)",len);
1050             tptr=pptr;
1051             tmp=len;
1052             while (tmp>0) {
1053             	printf("\n\t\t\tIS Neighbor: ");
1054                 if (!isis_print_nodeid(tptr))
1055                     return (1);
1056                 tptr+=(SYSTEM_ID_LEN+1);
1057                 if (!TTEST2(*tptr, 3))
1058                     goto trunctlv;
1059                 printf(", Metric: %d",EXTRACT_24BITS(tptr));
1060                 tptr+=3;
1061                 if (!TTEST2(*tptr, 1))
1062                     goto trunctlv;
1063                 tslen=*(tptr++);
1064                 printf(", %ssub-TLVs present",tslen ? "" : "no ");
1065                 if (tslen) {
1066                     printf(" (%u)",tslen);
1067                     ttslen=tslen;
1068                     while (ttslen>0) {
1069                         if (!TTEST2(*tptr,2))
1070                             goto trunctlv;
1071                         printf("\n\t\t\t  ");
1072                     	subt=*(tptr++);
1073                     	subl=*(tptr++);
1074                         switch(subt) {
1075                         case SUBTLV_EXT_IS_REACH_ADMIN_GROUP:
1076                             printf("Administrative groups: 0x%08x", EXTRACT_32BITS(tptr));
1077                             break;
1078                         case SUBTLV_EXT_IS_REACH_MAX_LINK_BW :
1079                             if (!TTEST2(*tptr,4))
1080                                 goto trunctlv;
1081                             j = EXTRACT_32BITS(tptr);
1082                             memcpy (&bw, &j, 4);
1083                             printf("Maximum link bandwidth : %.3f Mbps",
1084                                    bw*8/1000000 );
1085                             break;
1086                         case SUBTLV_EXT_IS_REACH_RESERVABLE_BW :
1087                             if (!TTEST2(*tptr,4))
1088                                 goto trunctlv;
1089                             j = EXTRACT_32BITS(tptr);
1090                             memcpy (&bw, &j, 4);
1091                             printf("Reservable link bandwidth: %.3f Mbps",
1092                                    bw*8/1000000  );
1093                             break;
1094                         case SUBTLV_EXT_IS_REACH_UNRESERVED_BW :
1095                             printf("Unreserved bandwidth:");
1096                             for (i = 0; i < 8; i++) {
1097                                 if (!TTEST2(*tptr,4))
1098                                     goto trunctlv;
1099                                 j = EXTRACT_32BITS(tptr);
1100                                 memcpy (&bw, &j, 4);
1101                                 printf("\n\t\t\t    priority level %d: %.3f Mbps",
1102                                        i, bw*8/1000000 );
1103                                 tptr+=4;
1104                             }
1105                             tptr-=32;
1106                             break;
1107                         case SUBTLV_EXT_IS_REACH_TE_METRIC:
1108                             if (!TTEST2(*tptr,3))
1109                                 goto trunctlv;
1110                             printf("Traffic Engineering Metric: %d", EXTRACT_24BITS(tptr));
1111                             break;
1112                         case SUBTLV_EXT_IS_REACH_IPV4_INTF_ADDR:
1113                             if (!TTEST2(*tptr,4))
1114                                 goto trunctlv;
1115                             printf("IPv4 interface address: %s", ipaddr_string(tptr));
1116                             break;
1117                         case SUBTLV_EXT_IS_REACH_IPV4_NEIGHBOR_ADDR:
1118                             if (!TTEST2(*tptr,4))
1119                                 goto trunctlv;
1120                             printf("IPv4 neighbor address: %s", ipaddr_string(tptr));
1121                             break;
1122                         case 250:
1123                         case 251:
1124                         case 252:
1125                         case 253:
1126                         case 254:
1127                              printf("Reserved for cisco specific extensions, type %d, length %d", subt, subl);
1128                              break;
1129                         case 255:
1130                              printf("Reserved for future expansion, type %d, length %d", subt, subl);
1131                              break;
1132                         default:
1133                             printf("unknown subTLV, type %d, length %d", subt, subl);
1134                         }
1135 		    tptr+=subl;
1136 	            ttslen-=(subl+2);
1137                     }
1138                 }
1139                 tptr+=tslen;
1140                 tmp-=(11+tslen);
1141             }
1142             break;
1143         case TLV_IS_REACH:
1144             printf("IS Reachability (%u)",len);
1145 
1146 	    tptr=pptr;
1147 
1148 	    if (!TTEST2(*tptr,1))  /* check if there is one byte left to read out the virtual flag */
1149 		 goto trunctlv;
1150 
1151 	    switch (*tptr) {
1152 	    case 0:
1153 	      printf("\n\t\t\tIsNotVirtual");
1154 	      break;
1155 	    case 1:
1156 	      printf("\n\t\t\tIsVirtual");
1157 	      break;
1158 	    default:
1159 	      printf("\n\t\t\tbogus virtual flag 0x%02x",(*tptr));
1160 	      break;
1161 	    }
1162 
1163 	    tptr++;
1164 
1165 	    tlv_is_reach = (const struct isis_tlv_is_reach *)tptr;
1166 
1167 	    tmp = len;
1168             while (tmp >= sizeof(struct isis_tlv_is_reach)) {
1169 		if (!TTEST(*tlv_is_reach))
1170 		    goto trunctlv;
1171 
1172 		printf("\n\t\t\tIS Neighbor: ");
1173 		isis_print_nodeid(tlv_is_reach->neighbor_nodeid);
1174 
1175 		printf(", Default Metric: %d, %s",
1176 			   ISIS_LSP_TLV_METRIC_VALUE(tlv_is_reach->metric_default),
1177 			   ISIS_LSP_TLV_METRIC_IE(tlv_is_reach->metric_default) ? "External" : "Internal");
1178 
1179 		if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_is_reach->metric_delay))
1180 		    printf("\n\t\t\t  Delay Metric: %d, %s",
1181 				   ISIS_LSP_TLV_METRIC_VALUE(tlv_is_reach->metric_delay),
1182 				   ISIS_LSP_TLV_METRIC_IE(tlv_is_reach->metric_delay) ? "External" : "Internal");
1183 
1184 		if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_is_reach->metric_expense))
1185 		    printf("\n\t\t\t  Expense Metric: %d, %s",
1186 				   ISIS_LSP_TLV_METRIC_VALUE(tlv_is_reach->metric_expense),
1187 				   ISIS_LSP_TLV_METRIC_IE(tlv_is_reach->metric_expense) ? "External" : "Internal");
1188 
1189 		if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_is_reach->metric_error))
1190 		    printf("\n\t\t\t  Error Metric: %d, %s",
1191 				   ISIS_LSP_TLV_METRIC_VALUE(tlv_is_reach->metric_error),
1192 				   ISIS_LSP_TLV_METRIC_IE(tlv_is_reach->metric_error) ? "External" : "Internal");
1193 
1194 		tmp -= sizeof(struct isis_tlv_is_reach);
1195 		tlv_is_reach++;
1196 	    }
1197             break;
1198 
1199 	case TLV_IP_REACH:
1200 	    printf("IP Internal reachability (%u)",len);
1201 	    if (!isis_print_tlv_ip_reach(pptr, len))
1202 		return (1);
1203 	    break;
1204 
1205 	case TLV_IP_REACH_EXT:
1206 	    printf("IP External reachability (%u)",len);
1207 	    if (!isis_print_tlv_ip_reach(pptr, len))
1208 		return (1);
1209 	    break;
1210 
1211 	case TLV_EXT_IP_REACH:
1212 	    printf("Extended IP reachability (%u)",len);
1213 	    i=len;
1214 	    tptr=pptr;
1215 
1216 	    while (i>0) {
1217 		memset (prefix, 0, 4);
1218 		if (!TTEST2(*tptr, 4))
1219 		    return (1);
1220 	        metric = EXTRACT_32BITS(tptr);
1221 		tptr+=4;
1222 
1223 		if (!TTEST2(*tptr, 1))
1224 		    return (1);
1225 		j=*(tptr);
1226 		bit_length = (*(tptr)++&0x3f);
1227 		byte_length = (bit_length + 7) / 8;
1228 		if (!TTEST2(*tptr, byte_length))
1229 		    return (1);
1230 
1231 		memcpy(prefix,tptr,byte_length);
1232 
1233 		printf("\n\t\t\tIPv4 prefix: %u.%u.%u.%u/%d",
1234 		       prefix[0],
1235 		       prefix[1],
1236 		       prefix[2],
1237 		       prefix[3],
1238 		       bit_length);
1239 
1240 		printf("\n\t\t\t  Metric: %u, Distribution: %s",
1241 		       metric,
1242 		       ISIS_MASK_TLV_EXT_IP_UPDOWN(j) ? "down" : "up");
1243 
1244 		printf(", %ssub-TLVs present",
1245 		       ISIS_MASK_TLV_EXT_IP_SUBTLV(j) ? "" : "no ");
1246 
1247 		if (ISIS_MASK_TLV_EXT_IP_SUBTLV(j)) {
1248 		    if (!TTEST2(*tptr, 1))
1249 		      return (1);
1250 		    printf(" (%u)",*tptr);  /* no subTLV decoder supported - just print out subTLV length */
1251 		    i-=*tptr;
1252 		    tptr+=*tptr++;
1253 		}
1254 
1255 		i-=(5+byte_length);
1256 		tptr+=byte_length;
1257 	    }
1258 	    break;
1259 
1260 #ifdef INET6
1261 
1262 	case TLV_IP6_REACH:
1263 	    printf("IP6 reachability (%u)",len);
1264 	    i=len;
1265 	    tptr=pptr;
1266 
1267 	    while (i>0) {
1268 		if (!TTEST2(*tptr, 4))
1269 		    return (1);
1270 	        metric = EXTRACT_32BITS(tptr);
1271 		tptr+=4;
1272 
1273 		if (!TTEST2(*tptr, 2))
1274 		    return (1);
1275 		j=*(tptr++);
1276 		bit_length = (*(tptr)++);
1277 		byte_length = (bit_length + 7) / 8;
1278 		if (!TTEST2(*tptr, byte_length))
1279 		    return (1);
1280 
1281 		memset(prefix6, 0, 16);
1282 		memcpy(prefix6,tptr,byte_length);
1283 
1284 		printf("\n\t\t\tIPv6 prefix: %s/%u",
1285 		       ip6addr_string(prefix6),
1286 		       bit_length);
1287 
1288 		printf("\n\t\t\t  Metric: %u, %s, Distribution: %s, %ssub-TLVs present",
1289 		    metric,
1290 		    ISIS_MASK_TLV_IP6_IE(j) ? "External" : "Internal",
1291 		    ISIS_MASK_TLV_IP6_UPDOWN(j) ? "down" : "up",
1292 		    ISIS_MASK_TLV_IP6_SUBTLV(j) ? "" : "no ");
1293 
1294 		if (ISIS_MASK_TLV_IP6_SUBTLV(j)) {
1295 		    if (!TTEST2(*tptr, 1))
1296 		      return (1);
1297 		    printf(" (%u)",*tptr); /* no subTLV decoder supported - just print out subTLV length */
1298 		    i-=*tptr;
1299 		    tptr+=*tptr++;
1300 		}
1301 
1302 		i-=(6+byte_length);
1303                 tptr+=byte_length;
1304 	    }
1305 
1306 	    break;
1307 #endif
1308 
1309 #ifdef INET6
1310 	case TLV_IP6ADDR:
1311 	    printf("IPv6 Interface address(es) (%u)",len);
1312 	    i=len;
1313 	    tptr=pptr;
1314 	    while (i>0) {
1315 		if (!TTEST2(*tptr, 16))
1316 		    goto trunctlv;
1317 
1318                 printf("\n\t\t\tIPv6 interface address: %s",
1319 		       ip6addr_string(tptr));
1320 
1321 		tptr += 16;
1322 		i -= 16;
1323 	    }
1324 	    break;
1325 #endif
1326 	case TLV_AUTH:
1327 	    if (!TTEST2(*pptr, 1))
1328 		goto trunctlv;
1329 	    printf("Authentication (%u)",len);
1330 	    if (*pptr==SUBTLV_AUTH_SIMPLE) {
1331 		printf("\n\t\t\tsimple text password: ");
1332 		for(i=1;i<len;i++) {
1333 		    if (!TTEST2(*(pptr+i), 1))
1334 			goto trunctlv;
1335 		    printf("%c",*(pptr+i));
1336 		}
1337 	    }
1338 	    if (!TTEST2(*pptr, 1))
1339 		goto trunctlv;
1340 	    if (*pptr==SUBTLV_AUTH_MD5) {
1341 		printf("\n\t\t\tMD5 password: ");
1342 		for(i=1;i<len;i++) {
1343 		    if (!TTEST2(*(pptr+i), 1))
1344 			goto trunctlv;
1345 		    printf("%02x",*(pptr+i));
1346 		}
1347 	    }
1348 	    break;
1349 
1350 	case TLV_PTP_ADJ:
1351 	    printf("Point-to-point Adjacency State (%u)",len);
1352 	    tlv_ptp_adj = (const struct isis_tlv_ptp_adj *)pptr;
1353 	    i=len;
1354 	    if(i>=1) {
1355 		if (!TTEST2(*pptr, 1))
1356 		    goto trunctlv;
1357 		printf("\n\t\t\tAdjacency State: %s",
1358 		       tok2str(isis_ptp_adjancey_values, "#0x%x", *pptr));
1359 		i--;
1360 	    }
1361 	    if(i>=4) {
1362 		if (!TTEST2(tlv_ptp_adj->ext_local_circuit_id, 4))
1363 		    goto trunctlv;
1364 		printf("\n\t\t\tExtended Local circuit ID: 0x%08x",
1365 		       EXTRACT_32BITS(tlv_ptp_adj->ext_local_circuit_id));
1366 		i-=4;
1367 	    }
1368 	    if(i>=6) {
1369 		if (!TTEST2(tlv_ptp_adj->neighbor_sysid, 6))
1370 		    goto trunctlv;
1371 		printf("\n\t\t\tNeighbor SystemID: ");
1372 		       isis_print_sysid(tlv_ptp_adj->neighbor_sysid);
1373 		i-=6;
1374 	    }
1375 	    if(i>=4) {
1376 		if (!TTEST2(tlv_ptp_adj->neighbor_ext_local_circuit_id, 4))
1377 		    goto trunctlv;
1378 		printf("\n\t\t\tNeighbor Extended Local circuit ID: 0x%08x",
1379 		       EXTRACT_32BITS(tlv_ptp_adj->neighbor_ext_local_circuit_id));
1380 	    }
1381 	    break;
1382 
1383 	case TLV_PROTOCOLS:
1384 	    printf("Protocols supported (%u)", len);
1385 	    printf("\n\t\t\tNLPID(s): ");
1386 	    for (i = 0; i < len; i++) {
1387 		if (!TTEST2(*(pptr+i), 1))
1388 		    goto trunctlv;
1389 		printf("%s (0x%02x)",tok2str(isis_nlpid_values, "Unknown", *(pptr+i)),*(pptr+i));
1390 		if (i<len-1)
1391 		    printf(", ");
1392 	    }
1393 	    break;
1394 
1395 	case TLV_TE_ROUTER_ID:
1396 	    printf("Traffic Engineering Router ID (%u)",len);
1397 	    if (!TTEST2(*pptr, 4))
1398 		goto trunctlv;
1399 	    printf("\n\t\t\tTraffic Engineering Router ID: %s", ipaddr_string(pptr));
1400 	    break;
1401 
1402 	case TLV_IPADDR:
1403 	    printf("IPv4 Interface address(es) (%u)",len);
1404 	    i=len;
1405 	    tptr=pptr;
1406 	    while (i>0) {
1407 		if (!TTEST2(*tptr, 4))
1408 		    goto trunctlv;
1409 		printf("\n\t\t\tIPv4 interface address: %s", ipaddr_string(tptr));
1410 		tptr += 4;
1411 		i -= 4;
1412 	    }
1413 	    break;
1414 
1415 	case TLV_HOSTNAME:
1416 	    printf("Hostname (%u)", len);
1417 	    printf("\n\t\t\tHostname: ");
1418 	    for(i = 0; i < len; i++) {
1419 		if (!TTEST2(*(pptr+i), 1))
1420 		    goto trunctlv;
1421 		printf("%c",*(pptr+i));
1422 	    }
1423 	    break;
1424 
1425 	case TLV_LSP:
1426 	    tlv_lsp = (const struct isis_tlv_lsp *)pptr;
1427 	    printf("LSP entries (%u)", len);
1428 	    i=0;
1429 	    while(i<len) {
1430 		printf("\n\t\t\tlsp-id: ");
1431 		if (!isis_print_nodeid(tlv_lsp->lsp_id))
1432 		    return (1);
1433 		if (!TTEST((tlv_lsp->lsp_id)[SYSTEM_ID_LEN+1]))
1434 		    goto trunctlv;
1435 		printf("-%02x",(tlv_lsp->lsp_id)[SYSTEM_ID_LEN+1]);
1436 		if (!TTEST2(tlv_lsp->sequence_number, 4))
1437 		    goto trunctlv;
1438 		printf("\n\t\t\t  sequence number: 0x%08x",EXTRACT_32BITS(tlv_lsp->sequence_number));
1439 		if (!TTEST2(tlv_lsp->remaining_lifetime, 2))
1440 		    goto trunctlv;
1441 		printf("\n\t\t\t  Remaining lifetime: %5ds",EXTRACT_16BITS(tlv_lsp->remaining_lifetime));
1442 		if (!TTEST2(tlv_lsp->checksum, 2))
1443 		    goto trunctlv;
1444 		printf("\n\t\t\t  checksum: 0x%04x",EXTRACT_16BITS(tlv_lsp->checksum));
1445 		i+=sizeof(struct isis_tlv_lsp);
1446 		tlv_lsp++;
1447 	    }
1448 	    break;
1449 
1450 	case TLV_CHECKSUM:
1451 	    if (!TTEST2(*pptr, 2))
1452 		goto trunctlv;
1453 	    printf("Checksum (%u)", len);
1454 	    printf("\n\t\t\tchecksum: 0x%04x",
1455 		   EXTRACT_16BITS(pptr));
1456 
1457 	    if (osi_cksum(optr, length, off))
1458 		printf(" (incorrect)");
1459 	    else
1460 		printf(" (correct)");
1461 	    break;
1462 
1463 	case TLV_MT_SUPPORTED:
1464 	    printf("Multi Topology (%u)",len);
1465 	    i=len;
1466 	    tptr=pptr;
1467 	    while (i>1) {
1468 		/* length can only be a multiple of 2, otherwise there is
1469 		   something broken -> so decode down until length is 1 */
1470 		if (i!=1) {
1471 		    if (!TTEST2(*tptr, 2))
1472 			goto trunctlv;
1473 		    printf("\n\t\t\t");
1474 		    switch(EXTRACT_16BITS(tptr)&0x0fff) {
1475 
1476 		    case 0:
1477 			printf("IPv4 unicast");
1478 			break;
1479 
1480 		    case 1:
1481 			printf("In-Band Management");
1482 			break;
1483 
1484 		    case 2:
1485 			printf("IPv6 unicast");
1486 			break;
1487 
1488 		    case 3:
1489 			printf("Multicast");
1490 			break;
1491 
1492 		    case 4095:
1493 			printf("Development, Experimental or Proprietary");
1494 		        break;
1495 
1496 		    default:
1497 			printf("Reserved for IETF Consensus");
1498 			break;
1499 		    }
1500 		    printf(" Topology (0x%03x)%s%s",
1501 			   EXTRACT_16BITS(tptr)&0xfff,
1502 			   (EXTRACT_16BITS(tptr)&0x8000) ? "" : ", no sub-TLVs present",
1503 			   (EXTRACT_16BITS(tptr)&0x4000) ? ", ATT bit set" : "" );
1504 		} else {
1505 		    printf("\n\t\t\tmalformed MT-ID");
1506 		    break;
1507 		}
1508 		i-=2;
1509 		tptr+=2;
1510 	    }
1511 	    break;
1512 
1513 	case TLV_RESTART_SIGNALING:
1514 	    tptr=pptr;
1515 	    printf("Restart Signaling (%u)",len);
1516 		    if (!TTEST2(*tptr, 3))
1517 			goto trunctlv;
1518 
1519 	    printf("\n\t\t\tRestart Request bit %s, Restart Acknowledgement bit %s\n\t\t\tRemaining holding time: %us",
1520                    ISIS_MASK_RESTART_RR(*tptr) ? "set" : "clear",
1521 		   ISIS_MASK_RESTART_RA(*tptr++) ? "set" : "clear",
1522 		   EXTRACT_16BITS(tptr));
1523 
1524 	    break;
1525 
1526 	default:
1527 	    printf("unknown TLV, type %d, length %d\n\t\t\t", type, len);
1528 	    tptr=pptr;
1529 
1530 	    for(i=0;i<len;i++) {
1531 		if (!TTEST2(*(tptr+i), 1))
1532 		    goto trunctlv;
1533 		printf("%02x",*(tptr+i)); /* formatted hex output of unknown TLV data */
1534 		if (i%2)
1535 		    printf(" ");
1536 		if (i/16!=(i+1)/16) {
1537 		  if (i<(len-1))
1538 		    printf("\n\t\t\t");
1539 		}
1540 	    }
1541 	    break;
1542 	}
1543 
1544 	pptr += len;
1545 	packet_len -= len;
1546     }
1547 
1548     if (packet_len != 0) {
1549 	printf("\n\t\t\t %d straggler bytes", packet_len);
1550     }
1551     return (1);
1552 
1553 trunc:
1554     fputs("[|isis]", stdout);
1555     return (1);
1556 
1557 trunctlv:
1558     printf("\n\t\t\t packet exceeded snapshot");
1559     return(1);
1560 }
1561 
1562 /*
1563  * Verify the checksum.  See 8473-1, Appendix C, section C.4.
1564  */
1565 
1566 static int
1567 osi_cksum(register const u_char *p, register u_int len, u_char *off)
1568 {
1569 	int32_t c0 = 0, c1 = 0;
1570 
1571 	if ((off[0] == 0) && (off[1] == 0))
1572 		return 0;
1573 
1574 	off[0] = off[1] = 0;
1575 	while ((int)--len >= 0) {
1576 		c0 += *p++;
1577 		c0 %= 255;
1578 		c1 += c0;
1579 		c1 %= 255;
1580 	}
1581 	return (c0 | c1);
1582 }
1583 
1584