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