]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcpdump/print-isoclns.c
Catch up with "base" telnet.
[FreeBSD/FreeBSD.git] / contrib / tcpdump / print-isoclns.c
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