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