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