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