]> The Tcpdump Group git mirrors - tcpdump/blob - print-isoclns.c
0f457f29dcdde6e9e696f6c34cc1b20ec6e370eb
[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.44 2002-04-12 07:56:49 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 static struct tok isis_pdu_values[] = {
78 { L1_LAN_IIH, "L1 Lan IIH"},
79 { L2_LAN_IIH, "L2 Lan IIH"},
80 { PTP_IIH, "p2p IIH"},
81 { L1_LSP, "L1 LSP"},
82 { L2_LSP, "L2 LSP"},
83 { L1_CSNP, "L1 CSNP"},
84 { L2_CSNP, "L2 CSNP"},
85 { L1_PSNP, "L1 PSNP"},
86 { L2_PSNP, "L2 PSNP"},
87 { 0, NULL}
88 };
89
90 /*
91 * A TLV is a tuple of a type, length and a value and is normally used for
92 * encoding information in all sorts of places. This is an enumeration of
93 * the well known types.
94 *
95 * list taken from draft-ietf-isis-wg-tlv-codepoints-01.txt
96 */
97
98 #define TLV_AREA_ADDR 1
99 #define TLV_IS_REACH 2
100 #define TLV_ESNEIGH 3
101 #define TLV_PART_DIS 4
102 #define TLV_SUMMARY 5
103 #define TLV_ISNEIGH 6
104 #define TLV_PADDING 8
105 #define TLV_LSP 9
106 #define TLV_AUTH 10
107 #define TLV_CHECKSUM 12
108 #define TLV_LSP_BUFFERSIZE 14
109 #define TLV_EXT_IS_REACH 22
110 #define TLV_IS_ALIAS_ID 24
111 #define TLV_DECNET_PHASE4 42
112 #define TLV_LUCENT_PRIVATE 66
113 #define TLV_IP_REACH 128
114 #define TLV_PROTOCOLS 129
115 #define TLV_IP_REACH_EXT 130
116 #define TLV_IDRP_INFO 131
117 #define TLV_IPADDR 132
118 #define TLV_IPAUTH 133
119 #define TLV_TE_ROUTER_ID 134
120 #define TLV_EXT_IP_REACH 135
121 #define TLV_HOSTNAME 137
122 #define TLV_SHARED_RISK_GROUP 138
123 #define TLV_NORTEL_PRIVATE1 176
124 #define TLV_NORTEL_PRIVATE2 177
125 #define TLV_RESTART_SIGNALING 211
126 #define TLV_MT_IS_REACH 222
127 #define TLV_MT_SUPPORTED 229
128 #define TLV_IP6ADDR 232
129 #define TLV_MT_IP_REACH 235
130 #define TLV_IP6_REACH 236
131 #define TLV_MT_IP6_REACH 237
132 #define TLV_PTP_ADJ 240
133
134 static struct tok isis_tlv_values[] = {
135 { TLV_AREA_ADDR, "Area address(es)"},
136 { TLV_IS_REACH, "IS Reachability"},
137 { TLV_ESNEIGH, "IS Neighbor(s)"},
138 { TLV_PART_DIS, "Partition DIS"},
139 { TLV_SUMMARY, "Prefix Neighbors"},
140 { TLV_ISNEIGH, "IS Neighbor(s)"},
141 { TLV_PADDING, "Padding"},
142 { TLV_LSP, "LSP entries"},
143 { TLV_AUTH, "Authentication"},
144 { TLV_CHECKSUM, "Checksum"},
145 { TLV_LSP_BUFFERSIZE, "LSP Buffersize"},
146 { TLV_EXT_IS_REACH, "Extended IS Reachability"},
147 { TLV_IS_ALIAS_ID, "IS Alias ID"},
148 { TLV_DECNET_PHASE4, "DECnet Phase IV"},
149 { TLV_LUCENT_PRIVATE, "Lucent Proprietary"},
150 { TLV_IP_REACH, "IP Internal reachability"},
151 { TLV_PROTOCOLS, "Protocols supported"},
152 { TLV_IP_REACH_EXT, "IP External reachability"},
153 { TLV_IDRP_INFO, "Inter-Domain Information Type"},
154 { TLV_IPADDR, "IP Interface address(es)"},
155 { TLV_IPAUTH, "IP authentication (depreciated)"},
156 { TLV_TE_ROUTER_ID, "Traffic Engineering Router ID"},
157 { TLV_EXT_IP_REACH, "Extended IP reachability"},
158 { TLV_HOSTNAME, "Hostname"},
159 { TLV_SHARED_RISK_GROUP, "Shared Risk Link Group"},
160 { TLV_NORTEL_PRIVATE1, "Nortel Proprietary"},
161 { TLV_NORTEL_PRIVATE2, "Nortel Proprietary"},
162 { TLV_RESTART_SIGNALING, "Restart Signaling"},
163 { TLV_MT_IS_REACH, "Multi Topology IS Reachability"},
164 { TLV_MT_SUPPORTED, "Multi Topology"},
165 { TLV_IP6ADDR, "IP6 Interface address(es)"},
166 { TLV_MT_IP_REACH, "Multi-Topology IP reachability"},
167 { TLV_IP6_REACH, "IP6 reachability"},
168 { TLV_MT_IP6_REACH, "Multi-Topology IP6 reachability"},
169 { TLV_PTP_ADJ, "Point-to-point Adjacency State"},
170 { 0, NULL }
171 };
172
173 #define SUBTLV_EXT_IS_REACH_ADMIN_GROUP 3
174 #define SUBTLV_EXT_IS_REACH_LINK_LOCAL_ID 4
175 #define SUBTLV_EXT_IS_REACH_LINK_REMOTE_ID 5
176 #define SUBTLV_EXT_IS_REACH_IPV4_INTF_ADDR 6
177 #define SUBTLV_EXT_IS_REACH_IPV4_NEIGHBOR_ADDR 8
178 #define SUBTLV_EXT_IS_REACH_MAX_LINK_BW 9
179 #define SUBTLV_EXT_IS_REACH_RESERVABLE_BW 10
180 #define SUBTLV_EXT_IS_REACH_UNRESERVED_BW 11
181 #define SUBTLV_EXT_IS_REACH_TE_METRIC 18
182 #define SUBTLV_EXT_IS_REACH_LINK_PROTECTION_TYPE 20
183 #define SUBTLV_EXT_IS_REACH_INTF_SW_CAP_DESCR 21
184
185 #define SUBTLV_EXT_IP_REACH_ADMIN_TAG 1
186
187 #define SUBTLV_AUTH_SIMPLE 1
188 #define SUBTLV_AUTH_MD5 54
189 #define SUBTLV_AUTH_MD5_LEN 16
190 #define SUBTLV_AUTH_PRIVATE 255
191
192 static struct tok isis_subtlv_auth_values[] = {
193 { SUBTLV_AUTH_SIMPLE, "simple text password"},
194 { SUBTLV_AUTH_MD5, "HMAC-MD5 password"},
195 { SUBTLV_AUTH_PRIVATE, "Routing Domain private password"},
196 { 0, NULL }
197 };
198
199
200 #define ISIS_8BIT_MASK(x) ((x)&0xff)
201
202 #define ISIS_MASK_LSP_OL_BIT(x) ((x)&0x4)
203 #define ISIS_MASK_LSP_ISTYPE_BITS(x) ((x)&0x3)
204 #define ISIS_MASK_LSP_PARTITION_BIT(x) ((x)&0x80)
205 #define ISIS_MASK_LSP_ATT_BITS(x) ((x)&0x78)
206 #define ISIS_MASK_LSP_ATT_ERROR_BIT(x) ((x)&0x40)
207 #define ISIS_MASK_LSP_ATT_EXPENSE_BIT(x) ((x)&0x20)
208 #define ISIS_MASK_LSP_ATT_DELAY_BIT(x) ((x)&0x10)
209 #define ISIS_MASK_LSP_ATT_DEFAULT_BIT(x) ((x)&0x8)
210
211 #define ISIS_MASK_MTID(x) ((x)&0xfff)
212 #define ISIS_MASK_MTSUB(x) ((x)&0x8000)
213 #define ISIS_MASK_MTATT(x) ((x)&0x4000)
214
215 #define ISIS_MASK_TLV_EXT_IP_UPDOWN(x) ((x)&0x80)
216 #define ISIS_MASK_TLV_EXT_IP_SUBTLV(x) ((x)&0x40)
217
218 #define ISIS_MASK_TLV_IP6_UPDOWN(x) ((x)&0x80)
219 #define ISIS_MASK_TLV_IP6_IE(x) ((x)&0x40)
220 #define ISIS_MASK_TLV_IP6_SUBTLV(x) ((x)&0x20)
221
222 #define ISIS_MASK_TLV_RESTART_RR(x) ((x)&0x1)
223 #define ISIS_MASK_TLV_RESTART_RA(x) ((x)&0x2)
224
225 #define ISIS_LSP_TLV_METRIC_SUPPORTED(x) ((x)&0x80)
226 #define ISIS_LSP_TLV_METRIC_IE(x) ((x)&0x40)
227 #define ISIS_LSP_TLV_METRIC_UPDOWN(x) ((x)&0x80)
228 #define ISIS_LSP_TLV_METRIC_VALUE(x) ((x)&0x3f)
229
230 #define ISIS_MASK_TLV_SHARED_RISK_GROUP(x) ((x)&0x1)
231
232 static const char *isis_gmpls_link_prot_values[] = {
233 "Extra",
234 "Unprotected",
235 "Shared",
236 "Dedicated 1:1",
237 "Dedicated 1+1",
238 "Enhanced",
239 "Reserved",
240 "Reserved"
241 };
242
243 static struct tok isis_gmpls_sw_cap_values[] = {
244 { 1, "Packet-Switch Capable-1"},
245 { 2, "Packet-Switch Capable-2"},
246 { 3, "Packet-Switch Capable-3"},
247 { 4, "Packet-Switch Capable-4"},
248 { 51, "Layer-2 Switch Capable"},
249 { 100, "Time-Division-Multiplex"},
250 { 150, "Lambda-Switch Capable"},
251 { 200, "Fiber-Switch Capable"},
252 { 0, NULL }
253 };
254
255 static struct tok isis_gmpls_lsp_enc_values[] = {
256 { 1, "Packet"},
257 { 2, "Ethernet V2/DIX"},
258 { 3, "ANSI PDH"},
259 { 4, "ETSI PDH"},
260 { 5, "SDH ITU-T G.707"},
261 { 6, "SONET ANSI T1.105"},
262 { 7, "Digital Wrapper"},
263 { 8, "Lambda (photonic)"},
264 { 9, "Fiber"},
265 { 10, "Ethernet 802.3"},
266 { 11, "FiberChannel"},
267 { 0, NULL }
268 };
269
270 static struct tok isis_mt_values[] = {
271 { 0, "IPv4 unicast"},
272 { 1, "In-Band Management"},
273 { 2, "IPv6 unicast"},
274 { 3, "Multicast"},
275 { 4095, "Development, Experimental or Proprietary"},
276 { 0, NULL }
277 };
278
279 static struct tok isis_iih_circuit_type_values[] = {
280 { 1, "Level 1 only"},
281 { 2, "Level 2 only"},
282 { 3, "Level 1, Level 2"},
283 { 0, NULL}
284 };
285
286 #define ISIS_LSP_TYPE_UNUSED0 0
287 #define ISIS_LSP_TYPE_LEVEL_1 1
288 #define ISIS_LSP_TYPE_UNUSED2 2
289 #define ISIS_LSP_TYPE_LEVEL_2 3
290
291 static struct tok isis_lsp_istype_values[] = {
292 { ISIS_LSP_TYPE_UNUSED0, "Unused 0x0 (invalid)"},
293 { ISIS_LSP_TYPE_LEVEL_1, "L1 IS"},
294 { ISIS_LSP_TYPE_UNUSED2, "Unused 0x2 (invalid)"},
295 { ISIS_LSP_TYPE_LEVEL_2, "L1L2 IS"},
296 { 0, NULL }
297 };
298
299 static struct tok isis_nlpid_values[] = {
300 { NLPID_CLNS, "CLNS"},
301 { NLPID_IP, "IPv4"},
302 { NLPID_IP6, "IPv6"},
303 { 0, NULL }
304 };
305
306 /*
307 * Katz's point to point adjacency TLV uses codes to tell us the state of
308 * the remote adjacency. Enumerate them.
309 */
310
311 #define ISIS_PTP_ADJ_UP 0
312 #define ISIS_PTP_ADJ_INIT 1
313 #define ISIS_PTP_ADJ_DOWN 2
314
315
316 static struct tok isis_ptp_adjancey_values[] = {
317 { ISIS_PTP_ADJ_UP, "Up" },
318 { ISIS_PTP_ADJ_INIT, "Initializing" },
319 { ISIS_PTP_ADJ_DOWN, "Down" },
320 { 0, NULL}
321 };
322
323 struct isis_tlv_ptp_adj {
324 u_char adjacency_state;
325 u_char ext_local_circuit_id[4];
326 u_char neighbor_sysid[SYSTEM_ID_LEN];
327 u_char neighbor_ext_local_circuit_id[4];
328 };
329
330 static int osi_cksum(const u_char *, u_int);
331 static void esis_print(const u_char *, u_int);
332 static int isis_print(const u_char *, u_int);
333
334 struct isis_tlv_ip_reach {
335 u_char metric_default;
336 u_char metric_delay;
337 u_char metric_expense;
338 u_char metric_error;
339 u_char prefix[4];
340 u_char mask[4];
341 };
342
343 struct isis_tlv_is_reach {
344 u_char metric_default;
345 u_char metric_delay;
346 u_char metric_expense;
347 u_char metric_error;
348 u_char neighbor_nodeid[SYSTEM_ID_LEN+1];
349 };
350
351 static struct tok isis_is_reach_virtual_values[] = {
352 { 0, "IsNotVirtual"},
353 { 1, "IsVirtual"},
354 { 0, NULL }
355 };
356
357 struct isis_common_header {
358 u_char nlpid;
359 u_char fixed_len;
360 u_char version; /* Protocol version? */
361 u_char id_length;
362 u_char pdu_type; /* 3 MSbs are reserved */
363 u_char pkt_version; /* Packet format version? */
364 u_char reserved;
365 u_char max_area;
366 };
367
368 struct isis_iih_lan_header {
369 u_char circuit_type;
370 u_char source_id[SYSTEM_ID_LEN];
371 u_char holding_time[2];
372 u_char pdu_len[2];
373 u_char priority;
374 u_char lan_id[SYSTEM_ID_LEN+1];
375 };
376
377 struct isis_iih_ptp_header {
378 u_char circuit_type;
379 u_char source_id[SYSTEM_ID_LEN];
380 u_char holding_time[2];
381 u_char pdu_len[2];
382 u_char circuit_id;
383 };
384
385 struct isis_lsp_header {
386 u_char pdu_len[2];
387 u_char remaining_lifetime[2];
388 u_char lsp_id[SYSTEM_ID_LEN+2];
389 u_char sequence_number[4];
390 u_char checksum[2];
391 u_char typeblock;
392 };
393
394 struct isis_csnp_header {
395 u_char pdu_len[2];
396 u_char source_id[SYSTEM_ID_LEN+1];
397 u_char start_lsp_id[SYSTEM_ID_LEN+2];
398 u_char end_lsp_id[SYSTEM_ID_LEN+2];
399 };
400
401 struct isis_psnp_header {
402 u_char pdu_len[2];
403 u_char source_id[SYSTEM_ID_LEN+1];
404 };
405
406 struct isis_tlv_lsp {
407 u_char remaining_lifetime[2];
408 u_char lsp_id[SYSTEM_ID_LEN+2];
409 u_char sequence_number[4];
410 u_char checksum[2];
411 };
412
413 #define ISIS_COMMON_HEADER_SIZE (sizeof(struct isis_common_header))
414 #define ISIS_IIH_LAN_HEADER_SIZE (sizeof(struct isis_iih_lan_header))
415 #define ISIS_IIH_PTP_HEADER_SIZE (sizeof(struct isis_iih_ptp_header))
416 #define ISIS_LSP_HEADER_SIZE (sizeof(struct isis_lsp_header))
417 #define ISIS_CSNP_HEADER_SIZE (sizeof(struct isis_csnp_header))
418 #define ISIS_PSNP_HEADER_SIZE (sizeof(struct isis_psnp_header))
419
420 void isoclns_print(const u_char *p, u_int length, u_int caplen,
421 const u_char *esrc, const u_char *edst)
422 {
423 u_char pdu_type;
424 const struct isis_common_header *header;
425
426 header = (const struct isis_common_header *)p;
427 pdu_type = header->pdu_type & PDU_TYPE_MASK;
428
429 if (caplen < 1) {
430 printf("[|iso-clns] ");
431 if (!eflag && esrc != NULL && edst != NULL)
432 printf("%s > %s",
433 etheraddr_string(esrc),
434 etheraddr_string(edst));
435 return;
436 }
437
438 switch (*p) {
439
440 case NLPID_CLNS:
441 (void)printf("CLNS(%d)", length);
442 if (!eflag && esrc != NULL && edst != NULL)
443 (void)printf(", %s > %s",
444 etheraddr_string(esrc),
445 etheraddr_string(edst));
446 break;
447
448 case NLPID_ESIS:
449 (void)printf("ESIS");
450 if (!eflag && esrc != NULL && edst != NULL)
451 (void)printf(", %s > %s",
452 etheraddr_string(esrc),
453 etheraddr_string(edst));
454 esis_print(p, length);
455 return;
456
457 case NLPID_ISIS:
458 (void)printf("ISIS(%d)", length);
459 if (!eflag && esrc != NULL && edst != NULL)
460 (void)printf(", %s > %s",
461 etheraddr_string(esrc),
462 etheraddr_string(edst));
463 if (!isis_print(p, length))
464 default_print_unaligned(p, caplen);
465 break;
466
467 case NLPID_NULLNS:
468 (void)printf("ISO NULLNS(%d)", length);
469 if (!eflag && esrc != NULL && edst != NULL)
470 (void)printf(", %s > %s",
471 etheraddr_string(esrc),
472 etheraddr_string(edst));
473 break;
474
475 default:
476 (void)printf("CLNS %02x(%d)", p[0], length);
477 if (!eflag && esrc != NULL && edst != NULL)
478 (void)printf(", %s > %s",
479 etheraddr_string(esrc),
480 etheraddr_string(edst));
481 if (caplen > 1)
482 default_print_unaligned(p, caplen);
483 break;
484 }
485 }
486
487 #define ESIS_REDIRECT 6
488 #define ESIS_ESH 2
489 #define ESIS_ISH 4
490
491 struct esis_hdr {
492 u_char version;
493 u_char reserved;
494 u_char type;
495 u_char tmo[2];
496 u_char cksum[2];
497 };
498
499 static void
500 esis_print(const u_char *p, u_int length)
501 {
502 const u_char *ep;
503 u_int li;
504 const struct esis_hdr *eh;
505
506 if (length <= 2) {
507 if (qflag)
508 printf(" bad pkt!");
509 else
510 printf(" no header at all!");
511 return;
512 }
513 li = p[1];
514 eh = (const struct esis_hdr *) &p[2];
515 ep = p + li;
516 if (li > length) {
517 if (qflag)
518 printf(" bad pkt!");
519 else
520 printf(" LI(%d) > PDU size (%d)!", li, length);
521 return;
522 }
523 if (li < sizeof(struct esis_hdr) + 2) {
524 if (qflag)
525 printf(" bad pkt!");
526 else {
527 printf(" too short for esis header %d:", li);
528 while (--length != 0)
529 printf("%02X", *p++);
530 }
531 return;
532 }
533 switch (eh->type & 0x1f) {
534
535 case ESIS_REDIRECT:
536 printf(" redirect");
537 break;
538
539 case ESIS_ESH:
540 printf(" esh");
541 break;
542
543 case ESIS_ISH:
544 printf(" ish");
545 break;
546
547 default:
548 printf(" type %d", eh->type & 0x1f);
549 break;
550 }
551 if (vflag && osi_cksum(p, li)) {
552 printf(" bad cksum (got 0x%02x%02x)",
553 eh->cksum[1], eh->cksum[0]);
554 default_print(p, length);
555 return;
556 }
557 if (eh->version != 1) {
558 printf(" unsupported version %d", eh->version);
559 return;
560 }
561 p += sizeof(*eh) + 2;
562 li -= sizeof(*eh) + 2; /* protoid * li */
563
564 switch (eh->type & 0x1f) {
565 case ESIS_REDIRECT: {
566 const u_char *dst, *snpa, *is;
567
568 dst = p; p += *p + 1;
569 if (p > snapend)
570 return;
571 printf("\n\t\t\t %s", isonsap_string(dst));
572 snpa = p; p += *p + 1;
573 is = p; p += *p + 1;
574 if (p > snapend)
575 return;
576 if (p > ep) {
577 printf(" [bad li]");
578 return;
579 }
580 if (is[0] == 0)
581 printf(" > %s", etheraddr_string(&snpa[1]));
582 else
583 printf(" > %s", isonsap_string(is));
584 li = ep - p;
585 break;
586 }
587 #if 0
588 case ESIS_ESH:
589 printf(" esh");
590 break;
591 #endif
592 case ESIS_ISH: {
593 const u_char *is;
594
595 is = p; p += *p + 1;
596 if (p > ep) {
597 printf(" [bad li]");
598 return;
599 }
600 if (p > snapend)
601 return;
602 if (!qflag)
603 printf("\n\t\t\t %s", isonsap_string(is));
604 li = ep - p;
605 break;
606 }
607
608 default:
609 (void)printf(" len=%d", length);
610 if (length && p < snapend) {
611 length = snapend - p;
612 default_print(p, length);
613 }
614 return;
615 }
616 if (vflag)
617 while (p < ep && li) {
618 u_int op, opli;
619 const u_char *q;
620
621 if (snapend - p < 2)
622 return;
623 if (li < 2) {
624 printf(" bad opts/li");
625 return;
626 }
627 op = *p++;
628 opli = *p++;
629 li -= 2;
630 if (opli > li) {
631 printf(" opt (%d) too long", op);
632 return;
633 }
634 li -= opli;
635 q = p;
636 p += opli;
637 if (snapend < p)
638 return;
639 if (op == 198 && opli == 2) {
640 printf(" tmo=%d", q[0] * 256 + q[1]);
641 continue;
642 }
643 printf (" %d:<", op);
644 while (opli-- > 0)
645 printf("%02x", *q++);
646 printf (">");
647 }
648 }
649
650 /*
651 * print_nsap
652 * Print out an NSAP.
653 */
654 static int
655 print_nsap(register const u_char *cp, register int length)
656 {
657 int i;
658
659 for (i = 0; i < length; i++) {
660 if (!TTEST2(*cp, 1))
661 return (0);
662 printf("%02x", *cp++);
663 if (((i & 1) == 0) && (i + 1 < length)) {
664 printf(".");
665 }
666 }
667 return (1);
668 }
669
670 char *isis_print_sysid (const u_char *);
671 /* allocate space for the following string
672 * xxxx.xxxx.xxxx
673 * 14 bytes plus one termination byte */
674 char sysid[15];
675 char *
676 isis_print_sysid(const u_char *cp)
677 {
678 int i;
679 char *pos = sysid;
680
681 for (i = 1; i <= 6; i++) {
682 if (!TTEST2(*cp, 1))
683 return (0);
684 pos+=sprintf(pos, "%02x", *cp++);
685 if ((i==2)^(i==4)) {
686 pos+=sprintf(pos, ".");
687 }
688 }
689 *(pos) = '\0';
690 return (sysid);
691 }
692
693
694 char *isis_print_nodeid (const u_char *);
695 /* allocate space for the following string
696 * xxxx.xxxx.xxxx.yy
697 * 17 bytes plus one termination byte */
698 char nodeid[18];
699 char *
700 isis_print_nodeid(const u_char *cp)
701 {
702 int i;
703 char *pos = nodeid;
704
705 for (i = 1; i <= 7; i++) {
706 if (!TTEST2(*cp, 1))
707 return (0);
708 pos+=sprintf(pos, "%02x", *cp++);
709 if ((i & 1) == 0) {
710 pos+=sprintf(pos, ".");
711 }
712 }
713 *(pos) = '\0';
714 return (nodeid);
715 }
716
717 char *isis_print_lspid (const u_char *);
718 /* allocate space for the following string
719 * xxxx.xxxx.xxxx.yy-zz
720 * 20 bytes plus one termination byte */
721 char lspid[21];
722 char *
723 isis_print_lspid(const u_char *cp)
724 {
725 int i;
726 char *pos = lspid;
727
728 for (i = 1; i <= 7; i++) {
729 pos+=sprintf(pos, "%02x", *cp++);
730 if ((i & 1) == 0)
731 pos+=sprintf(pos, ".");
732 }
733 pos+=sprintf(pos, "-%02x", *cp);
734 return (lspid);
735 }
736
737 /*
738 * this is a generic routine for printing unknown data;
739 * as it is called from various places (TLV and subTLV parsing routines)
740 * we pass on the linefeed plus indentation string to
741 * get a proper output - returns 0 on error
742 */
743
744 static int
745 isis_print_unknown_data(const u_char *cp,const u_char *lf,int len)
746 {
747 int i;
748
749 printf("%s0x0000: ",lf);
750 for(i=0;i<len;i++) {
751 if (!TTEST2(*(cp+i), 1))
752 goto trunctlv;
753 printf("%02x",*(cp+i));
754 if (i%2)
755 printf(" ");
756 if (i/16!=(i+1)/16) {
757 if (i<(len-1))
758 printf("%s0x%04x: ",lf,i);
759 }
760 }
761 return(1); /* everything is ok */
762
763 trunctlv:
764 printf("%spacket exceeded snapshot",lf);
765 return(0);
766
767 }
768
769 static int
770 isis_print_tlv_ip_reach (const u_char *cp, int length)
771 {
772 u_int bitmasks[33] = {
773 0x00000000,
774 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000,
775 0xf8000000, 0xfc000000, 0xfe000000, 0xff000000,
776 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000,
777 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000,
778 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000,
779 0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00,
780 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0,
781 0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff
782 };
783 u_int mask;
784 int prefix_len;
785 const struct isis_tlv_ip_reach *tlv_ip_reach;
786
787 tlv_ip_reach = (const struct isis_tlv_ip_reach *)cp;
788
789 while (length > 0) {
790 if (length < sizeof(*tlv_ip_reach)) {
791 printf("short IP reachability (%d vs %lu)", length,
792 (unsigned long)sizeof(*tlv_ip_reach));
793 return (0);
794 }
795
796 if (!TTEST(*tlv_ip_reach))
797 return (0);
798
799 mask = EXTRACT_32BITS(tlv_ip_reach->mask);
800 prefix_len = 0;
801
802 /* lets see if we can transform the mask into a prefixlen */
803 while (prefix_len <= 33) {
804 if (bitmasks[prefix_len++] == mask) {
805 prefix_len--;
806 break;
807 }
808 }
809
810 /*
811 * 34 indicates no match -> must be a discontiguous netmask
812 * lets dump the mask, otherwise print the prefix_len
813 */
814 if (prefix_len == 34)
815 printf("\n\t\t\tIPv4 prefix: %s mask %s",
816 ipaddr_string((tlv_ip_reach->prefix)),
817 ipaddr_string((tlv_ip_reach->mask)));
818 else
819 printf("\n\t\t\tIPv4 prefix: %s/%u",
820 ipaddr_string((tlv_ip_reach->prefix)),
821 prefix_len);
822
823 printf("\n\t\t\t Default Metric: %02d, %s, Distribution: %s",
824 ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->metric_default),
825 ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->metric_default) ? "External" : "Internal",
826 ISIS_LSP_TLV_METRIC_UPDOWN(tlv_ip_reach->metric_default) ? "down" : "up");
827
828 if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_ip_reach->metric_delay))
829 printf("\n\t\t\t Delay Metric: %02d, %s",
830 ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->metric_delay),
831 ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->metric_delay) ? "External" : "Internal");
832
833 if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_ip_reach->metric_expense))
834 printf("\n\t\t\t Expense Metric: %02d, %s",
835 ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->metric_expense),
836 ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->metric_expense) ? "External" : "Internal");
837
838 if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_ip_reach->metric_error))
839 printf("\n\t\t\t Error Metric: %02d, %s",
840 ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->metric_error),
841 ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->metric_error) ? "External" : "Internal");
842
843 length -= sizeof(struct isis_tlv_ip_reach);
844 tlv_ip_reach++;
845 }
846 return (1);
847 }
848
849 /*
850 * this is the common IP-REACH subTLV decoder it is called
851 * from various EXTD-IP REACH TLVs (135,236)
852 */
853
854 static int
855 isis_print_ip_reach_subtlv (const u_char *tptr,int subt,int subl,const u_char *lf) {
856
857 switch(subt) {
858 case SUBTLV_EXT_IP_REACH_ADMIN_TAG:
859 if (!TTEST2(*tptr,4))
860 goto trunctlv;
861 printf("%sAdministrative tag: 0x%08x",
862 lf,
863 EXTRACT_32BITS(tptr));
864 break;
865 default:
866 printf("%sunknown subTLV, type %d, length %d",
867 lf,
868 subt,
869 subl);
870 if(!isis_print_unknown_data(tptr,"\n\t\t\t ",
871 subl))
872 return(0);
873 break;
874 }
875 return(1);
876
877 trunctlv:
878 printf("%spacket exceeded snapshot",lf);
879 return(0);
880 }
881
882 /*
883 * this is the common IS-REACH subTLV decoder it is called
884 * from various EXTD-IS REACH TLVs (22,222)
885 */
886
887 static int
888 isis_print_is_reach_subtlv (const u_char *tptr,int subt,int subl,const u_char *lf) {
889
890 int i,j;
891 float bw; /* copy buffer for several subTLVs */
892
893 switch(subt) {
894 case SUBTLV_EXT_IS_REACH_ADMIN_GROUP:
895 if (!TTEST2(*tptr,4))
896 goto trunctlv;
897 printf("%sAdministrative groups: 0x%08x",
898 lf,
899 EXTRACT_32BITS(tptr));
900 break;
901 case SUBTLV_EXT_IS_REACH_LINK_LOCAL_ID:
902 if (!TTEST2(*tptr,4))
903 goto trunctlv;
904 printf("%sLink Local Identifier: 0x%08x",
905 lf,
906 EXTRACT_32BITS(tptr));
907 break;
908 case SUBTLV_EXT_IS_REACH_LINK_REMOTE_ID:
909 if (!TTEST2(*tptr,4))
910 goto trunctlv;
911 printf("%sLink Remote Identifier: 0x%08x",
912 lf,
913 EXTRACT_32BITS(tptr));
914 break;
915 case SUBTLV_EXT_IS_REACH_MAX_LINK_BW :
916 if (!TTEST2(*tptr,4))
917 goto trunctlv;
918 j = EXTRACT_32BITS(tptr);
919 memcpy (&bw, &j, 4);
920 printf("%sMaximum link bandwidth : %.3f Mbps",
921 lf,
922 bw*8/1000000 );
923 break;
924 case SUBTLV_EXT_IS_REACH_RESERVABLE_BW :
925 if (!TTEST2(*tptr,4))
926 goto trunctlv;
927 j = EXTRACT_32BITS(tptr);
928 memcpy (&bw, &j, 4);
929 printf("%sReservable link bandwidth: %.3f Mbps",
930 lf,
931 bw*8/1000000 );
932 break;
933 case SUBTLV_EXT_IS_REACH_UNRESERVED_BW :
934 printf("%sUnreserved bandwidth:",lf);
935 for (i = 0; i < 8; i++) {
936 if (!TTEST2(*(tptr+i*4),4))
937 goto trunctlv;
938 j = EXTRACT_32BITS(tptr);
939 memcpy (&bw, &j, 4);
940 printf("%s priority level %d: %.3f Mbps",
941 lf,
942 i,
943 bw*8/1000000 );
944 }
945 break;
946 case SUBTLV_EXT_IS_REACH_TE_METRIC:
947 if (!TTEST2(*tptr,3))
948 goto trunctlv;
949 printf("%sTraffic Engineering Metric: %d",
950 lf,
951 EXTRACT_24BITS(tptr));
952 break;
953 case SUBTLV_EXT_IS_REACH_IPV4_INTF_ADDR:
954 if (!TTEST2(*tptr,4))
955 goto trunctlv;
956 printf("%sIPv4 interface address: %s",
957 lf,
958 ipaddr_string(tptr));
959 break;
960 case SUBTLV_EXT_IS_REACH_IPV4_NEIGHBOR_ADDR:
961 if (!TTEST2(*tptr,4))
962 goto trunctlv;
963 printf("%sIPv4 neighbor address: %s",
964 lf,
965 ipaddr_string(tptr));
966 break;
967 case SUBTLV_EXT_IS_REACH_LINK_PROTECTION_TYPE:
968 if (!TTEST2(*tptr,2))
969 goto trunctlv;
970 i = 0;
971 j = (ISIS_8BIT_MASK(*tptr)); /* fetch the typecode and make sure
972 that no high-order LSBs are set */
973 printf("%sLink Protection Type: %s",
974 lf,
975 (j) ? "" : "none" );
976 /* scan through the bits until the typecode is zero */
977 while(!j) {
978 printf("%s", isis_gmpls_link_prot_values[i]);
979 j=j>>1;
980 if (j) /*any other bit set ?*/
981 printf(", ");
982 i++;
983 }
984 printf(", Priority %u", *(tptr+1));
985 break;
986 case SUBTLV_EXT_IS_REACH_INTF_SW_CAP_DESCR:
987 printf("%sInterface Switching Capability",lf);
988
989 if (!TTEST2(*tptr,1))
990 goto trunctlv;
991 printf("%s Interface Switching Capability:%s",
992 lf,
993 tok2str(isis_gmpls_sw_cap_values, "Unknown", *(tptr)));
994
995 if (!TTEST2(*(tptr+1),1))
996 goto trunctlv;
997 printf(", LSP Encoding: %s",
998 tok2str(isis_gmpls_lsp_enc_values, "Unknown", *(tptr+1)));
999
1000 if (!TTEST2(*(tptr+2),2)) /* skip 2 res. bytes */
1001 goto trunctlv;
1002
1003 printf("%s Max LSP Bandwidth:",lf);
1004 for (i = 0; i < 8; i++) {
1005 if (!TTEST2(*(tptr+(i*4)+4),4))
1006 goto trunctlv;
1007 j = EXTRACT_32BITS(tptr);
1008 memcpy (&bw, &j, 4);
1009 printf("%s priority level %d: %.3f Mbps",
1010 lf,
1011 i,
1012 bw*8/1000000 );
1013 }
1014 subl-=36;
1015 /* there is some optional stuff left to decode but this is as of yet
1016 not specified so just lets hexdump what is left */
1017 if(subl>0){
1018 if(!isis_print_unknown_data(tptr,"\n\t\t\t ",
1019 subl-36))
1020 return(0);
1021 }
1022 break;
1023 case 250:
1024 case 251:
1025 case 252:
1026 case 253:
1027 case 254:
1028 printf("%sReserved for cisco specific extensions, type %d, length %d",
1029 lf,
1030 subt,
1031 subl);
1032 break;
1033 case 255:
1034 printf("%sReserved for future expansion, type %d, length %d",
1035 lf,
1036 subt,
1037 subl);
1038 break;
1039 default:
1040 printf("%sunknown subTLV, type %d, length %d",
1041 lf,
1042 subt,
1043 subl);
1044 if(!isis_print_unknown_data(tptr,"\n\t\t\t ",
1045 subl))
1046 return(0);
1047 break;
1048 }
1049 return(1);
1050
1051 trunctlv:
1052 printf("%spacket exceeded snapshot",lf);
1053 return(0);
1054 }
1055
1056
1057 /*
1058 * isis_print
1059 * Decode IS-IS packets. Return 0 on error.
1060 */
1061
1062 static int isis_print (const u_char *p, u_int length)
1063 {
1064 const struct isis_common_header *header;
1065
1066 const struct isis_iih_lan_header *header_iih_lan;
1067 const struct isis_iih_ptp_header *header_iih_ptp;
1068 const struct isis_lsp_header *header_lsp;
1069 const struct isis_csnp_header *header_csnp;
1070 const struct isis_psnp_header *header_psnp;
1071
1072 const struct isis_tlv_lsp *tlv_lsp;
1073 const struct isis_tlv_ptp_adj *tlv_ptp_adj;
1074 const struct isis_tlv_is_reach *tlv_is_reach;
1075
1076 u_char pdu_type, max_area, id_length, type, len, tmp, alen, subl, subt, tslen;
1077 const u_char *optr, *pptr, *tptr;
1078 u_short packet_len,pdu_len,time_remain;
1079 u_int i,j,bit_length,byte_length,metric,ra,rr;
1080 u_char prefix[4]; /* copy buffer for ipv4 prefixes */
1081 #ifdef INET6
1082 u_char prefix6[16]; /* copy buffer for ipv6 prefixes */
1083 #endif
1084 packet_len=length;
1085 optr = p; /* initialize the _o_riginal pointer to the packet start -
1086 need it for parsing the checksum TLV */
1087 header = (const struct isis_common_header *)p;
1088 TCHECK(*header);
1089 pptr = p+(ISIS_COMMON_HEADER_SIZE);
1090 header_iih_lan = (const struct isis_iih_lan_header *)pptr;
1091 header_iih_ptp = (const struct isis_iih_ptp_header *)pptr;
1092 header_lsp = (const struct isis_lsp_header *)pptr;
1093 header_csnp = (const struct isis_csnp_header *)pptr;
1094 header_psnp = (const struct isis_psnp_header *)pptr;
1095
1096 /*
1097 * Sanity checking of the header.
1098 */
1099 if (header->nlpid != NLPID_ISIS) {
1100 printf(", coding error!");
1101 return (0);
1102 }
1103
1104 if (header->version != ISIS_VERSION) {
1105 printf(", version %d packet not supported", header->version);
1106 return (0);
1107 }
1108
1109 if ((header->id_length != SYSTEM_ID_LEN) && (header->id_length != 0)) {
1110 printf(", system ID length of %d is not supported",
1111 header->id_length);
1112 return (0);
1113 }
1114
1115 if (header->pkt_version != ISIS_VERSION) {
1116 printf(", version %d packet not supported", header->pkt_version);
1117 return (0);
1118 }
1119
1120 max_area = header->max_area;
1121 switch(max_area) {
1122 case 0:
1123 max_area = 3; /* silly shit */
1124 break;
1125 case 255:
1126 printf(", bad packet -- 255 areas");
1127 return (0);
1128 default:
1129 break;
1130 }
1131
1132 id_length = header->id_length;
1133 switch(id_length) {
1134 case 0:
1135 id_length = 6; /* silly shit again */
1136 break;
1137 case 1: /* 1-8 are valid sys-ID lenghts */
1138 case 2:
1139 case 3:
1140 case 4:
1141 case 5:
1142 case 6:
1143 case 7:
1144 case 8:
1145 break;
1146 case 255:
1147 id_length = 0; /* entirely useless */
1148 break;
1149 default:
1150 printf(", bad packet -- illegal sys-ID length (%u)", id_length);
1151 return (0);
1152 break;
1153 }
1154
1155 printf(", hlen: %u, v: %u, sys-id-len: %u (%u), max-area: %u (%u)",
1156 header->fixed_len,
1157 header->version,
1158 id_length,
1159 header->id_length,
1160 max_area,
1161 header->max_area);
1162
1163 pdu_type=header->pdu_type;
1164
1165 /* first lets see if we know the PDU name*/
1166 printf(", %s",
1167 tok2str(isis_pdu_values,
1168 "unknown PDU, type %d",
1169 pdu_type));
1170
1171 switch (pdu_type) {
1172
1173 case L1_LAN_IIH:
1174 case L2_LAN_IIH:
1175 if (header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE)) {
1176 printf(", bogus fixed header length %u should be %lu",
1177 header->fixed_len, (unsigned long)ISIS_IIH_LAN_HEADER_SIZE);
1178 return (0);
1179 }
1180
1181 pdu_len=EXTRACT_16BITS(header_iih_lan->pdu_len);
1182 if (packet_len>pdu_len) {
1183 packet_len=pdu_len; /* do TLV decoding as long as it makes sense */
1184 length=pdu_len;
1185 }
1186
1187 TCHECK(*header_iih_lan);
1188 printf("\n\t\t source-id: %s, holding time: %u, %s",
1189 isis_print_sysid(header_iih_lan->source_id),
1190 EXTRACT_16BITS(header_iih_lan->holding_time),
1191 tok2str(isis_iih_circuit_type_values,
1192 "unknown circuit type 0x%02x",
1193 header_iih_lan->circuit_type));
1194
1195 printf("\n\t\t lan-id: %s, Priority: %u, PDU Length: %u",
1196 isis_print_nodeid(header_iih_lan->lan_id),
1197 (header_iih_lan->priority) & PRIORITY_MASK,
1198 pdu_len);
1199
1200 packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE);
1201 pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE);
1202 break;
1203
1204 case PTP_IIH:
1205 if (header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE)) {
1206 printf(", bogus fixed header length %u should be %lu",
1207 header->fixed_len, (unsigned long)ISIS_IIH_PTP_HEADER_SIZE);
1208 return (0);
1209 }
1210
1211 pdu_len=EXTRACT_16BITS(header_iih_ptp->pdu_len);
1212 if (packet_len>pdu_len) {
1213 packet_len=pdu_len; /* do TLV decoding as long as it makes sense */
1214 length=pdu_len;
1215 }
1216
1217 TCHECK(*header_iih_ptp);
1218 printf("\n\t\t source-id: %s, holding time: %us, circuit-id: 0x%02x, %s, PDU Length: %u",
1219 isis_print_sysid(header_iih_ptp->source_id),
1220 EXTRACT_16BITS(header_iih_ptp->holding_time),
1221 header_iih_ptp->circuit_id,
1222 tok2str(isis_iih_circuit_type_values,
1223 "unknown circuit type 0x%02x",
1224 header_iih_ptp->circuit_type),
1225 pdu_len);
1226
1227 packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE);
1228 pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE);
1229 break;
1230
1231 case L1_LSP:
1232 case L2_LSP:
1233 if (header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE)) {
1234 printf(", bogus fixed header length %u should be %lu",
1235 header->fixed_len, (unsigned long)ISIS_LSP_HEADER_SIZE);
1236 return (0);
1237 }
1238
1239 pdu_len=EXTRACT_16BITS(header_lsp->pdu_len);
1240 if (packet_len>pdu_len) {
1241 packet_len=pdu_len; /* do TLV decoding as long as it makes sense */
1242 length=pdu_len;
1243 }
1244
1245 TCHECK(*header_lsp);
1246 printf("\n\t\t lsp-id: %s, seq: 0x%08x, lifetime: %5us",
1247 isis_print_lspid(header_lsp->lsp_id),
1248 EXTRACT_32BITS(header_lsp->sequence_number),
1249 EXTRACT_16BITS(header_lsp->remaining_lifetime));
1250 printf("\n\t\t chksum: 0x%04x, PDU Length: %u",
1251 EXTRACT_16BITS(header_lsp->checksum),
1252 pdu_len);
1253 /* verify the checksum -
1254 * checking starts at the lsp-id field
1255 * which is 12 bytes after the packet start*/
1256 if (osi_cksum(optr+12, length-12))
1257 printf(" (incorrect)");
1258 else
1259 printf(" (correct)");
1260
1261 printf(", %s", ISIS_MASK_LSP_OL_BIT(header_lsp->typeblock) ? "Overload bit set, " : "");
1262
1263 if (ISIS_MASK_LSP_ATT_BITS(header_lsp->typeblock)) {
1264 printf("%s", ISIS_MASK_LSP_ATT_DEFAULT_BIT(header_lsp->typeblock) ? "default " : "");
1265 printf("%s", ISIS_MASK_LSP_ATT_DELAY_BIT(header_lsp->typeblock) ? "delay " : "");
1266 printf("%s", ISIS_MASK_LSP_ATT_EXPENSE_BIT(header_lsp->typeblock) ? "expense " : "");
1267 printf("%s", ISIS_MASK_LSP_ATT_ERROR_BIT(header_lsp->typeblock) ? "error " : "");
1268 printf("ATT bit set, ");
1269 }
1270 printf("%s", ISIS_MASK_LSP_PARTITION_BIT(header_lsp->typeblock) ? "P bit set, " : "");
1271 printf("%s", tok2str(isis_lsp_istype_values,"Unknown(0x%x)",ISIS_MASK_LSP_ISTYPE_BITS(header_lsp->typeblock)));
1272
1273 packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE);
1274 pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE);
1275 break;
1276
1277 case L1_CSNP:
1278 case L2_CSNP:
1279 if (header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE)) {
1280 printf(", bogus fixed header length %u should be %lu",
1281 header->fixed_len, (unsigned long)ISIS_CSNP_HEADER_SIZE);
1282 return (0);
1283 }
1284
1285 pdu_len=EXTRACT_16BITS(header_csnp->pdu_len);
1286 if (packet_len>pdu_len) {
1287 packet_len=pdu_len; /* do TLV decoding as long as it makes sense */
1288 length=pdu_len;
1289 }
1290
1291 TCHECK(*header_csnp);
1292 printf("\n\t\t source-id: %s, PDU Length: %u",
1293 isis_print_nodeid(header_csnp->source_id),
1294 pdu_len);
1295 printf("\n\t\t start lsp-id: %s",
1296 isis_print_lspid(header_csnp->start_lsp_id));
1297 printf("\n\t\t end lsp-id: %s",
1298 isis_print_lspid(header_csnp->end_lsp_id));
1299
1300 packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE);
1301 pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE);
1302 break;
1303
1304 case L1_PSNP:
1305 case L2_PSNP:
1306 if (header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE)) {
1307 printf("- bogus fixed header length %u should be %lu",
1308 header->fixed_len, (unsigned long)ISIS_PSNP_HEADER_SIZE);
1309 return (0);
1310 }
1311
1312 pdu_len=EXTRACT_16BITS(header_psnp->pdu_len);
1313 if (packet_len>pdu_len) {
1314 packet_len=pdu_len; /* do TLV decoding as long as it makes sense */
1315 length=pdu_len;
1316 }
1317
1318 TCHECK(*header_psnp);
1319 printf("\n\t\t source-id: %s",
1320 isis_print_nodeid(header_psnp->source_id));
1321
1322 packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE);
1323 pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE);
1324 break;
1325
1326 default:
1327 if(!isis_print_unknown_data(pptr,"\n\t\t ",length))
1328 return(0);
1329 return (0);
1330 }
1331
1332 /*
1333 * Now print the TLV's.
1334 */
1335
1336 while (packet_len >= 2) {
1337 if (pptr == snapend) {
1338 return (1);
1339 }
1340
1341 if (!TTEST2(*pptr, 2)) {
1342 printf("\n\t\t\t packet exceeded snapshot (%ld) bytes",
1343 (long)(pptr-snapend));
1344 return (1);
1345 }
1346 type = *pptr++;
1347 len = *pptr++;
1348 tmp =len; /* copy temporary len & pointer to packet data */
1349 tptr = pptr;
1350 packet_len -= 2;
1351 if (len > packet_len) {
1352 break;
1353 }
1354
1355 /* first lets see if we know the TLVs name*/
1356 printf("\n\t\t %s (%u)",
1357 tok2str(isis_tlv_values,
1358 "unknown TLV, type %d, length",
1359 type),
1360 len);
1361
1362 /* now check if we have a decoder otherwise do a hexdump at the end*/
1363 switch (type) {
1364 case TLV_AREA_ADDR:
1365 if (!TTEST2(*tptr, 1))
1366 goto trunctlv;
1367 alen = *tptr++;
1368 while (tmp && alen < tmp) {
1369 printf("\n\t\t\tArea address (%u): ",alen);
1370 if (!print_nsap(tptr, alen))
1371 return (1);
1372 tptr += alen;
1373 tmp -= alen + 1;
1374 if (tmp==0) /* if this is the last area address do not attemt a boundary check */
1375 break;
1376 if (!TTEST2(*tptr, 1))
1377 goto trunctlv;
1378 alen = *tptr++;
1379 }
1380 break;
1381 case TLV_ISNEIGH:
1382 while (tmp >= ETHER_ADDR_LEN) {
1383 printf("\n\t\t\tIS Neighbor: %s",isis_print_sysid(tptr));
1384 tmp -= ETHER_ADDR_LEN;
1385 tptr += ETHER_ADDR_LEN;
1386 }
1387 break;
1388
1389 case TLV_PADDING:
1390 break;
1391
1392 case TLV_MT_IS_REACH:
1393 while (tmp>0) {
1394 if (!TTEST2(*tptr, 2))
1395 goto trunctlv;
1396 printf("\n\t\t\t%s",
1397 tok2str(isis_mt_values,
1398 "Reserved for IETF Consensus",
1399 ISIS_MASK_MTID(EXTRACT_16BITS(tptr))));
1400
1401 printf(" Topology (0x%03x)",
1402 ISIS_MASK_MTID(EXTRACT_16BITS(tptr)));
1403 tptr+=2;
1404 printf("\n\t\t\t IS Neighbor: %s", isis_print_nodeid(tptr));
1405 tptr+=(SYSTEM_ID_LEN+1);
1406 if (!TTEST2(*tptr, 3))
1407 goto trunctlv;
1408 printf(", Metric: %d",EXTRACT_24BITS(tptr));
1409 tptr+=3;
1410 if (!TTEST2(*tptr, 1))
1411 goto trunctlv;
1412 tslen=*(tptr++);
1413 printf(", %ssub-TLVs present",tslen ? "" : "no ");
1414 if (tslen) {
1415 printf(" (%u)",tslen);
1416 while (tslen>0) {
1417 if (!TTEST2(*tptr,2))
1418 goto trunctlv;
1419 subt=*(tptr++);
1420 subl=*(tptr++);
1421 if(!isis_print_is_reach_subtlv(tptr,subt,subl,"\n\t\t\t "))
1422 return(0);
1423 tptr+=subl;
1424 tslen-=(subl+2);
1425 tmp-=(subl+2);
1426 }
1427 }
1428 tmp-=(SYSTEM_ID_LEN+7);
1429 }
1430 break;
1431
1432 case TLV_EXT_IS_REACH:
1433 while (tmp>0) {
1434 if (!TTEST2(*tptr, SYSTEM_ID_LEN+1))
1435 goto trunctlv;
1436 printf("\n\t\t\tIS Neighbor: %s", isis_print_nodeid(tptr));
1437 tptr+=(SYSTEM_ID_LEN+1);
1438
1439 if (!TTEST2(*tptr, 3))
1440 goto trunctlv;
1441 printf(", Metric: %d",EXTRACT_24BITS(tptr));
1442 tptr+=3;
1443
1444 if (!TTEST2(*tptr, 1))
1445 goto trunctlv;
1446 tslen=*(tptr++); /* read out subTLV length */
1447 printf(", %ssub-TLVs present",tslen ? "" : "no ");
1448 if (tslen) {
1449 printf(" (%u)",tslen);
1450 while (tslen>0) {
1451 if (!TTEST2(*tptr,2))
1452 goto trunctlv;
1453 subt=*(tptr++);
1454 subl=*(tptr++);
1455 if(!isis_print_is_reach_subtlv(tptr,subt,subl,"\n\t\t\t "))
1456 return(0);
1457 tptr+=subl;
1458 tslen-=(subl+2);
1459 tmp-=(subl+2);
1460 }
1461 }
1462 tmp-=(SYSTEM_ID_LEN+5);
1463 }
1464 break;
1465 case TLV_IS_REACH:
1466 if (!TTEST2(*tptr,1)) /* check if there is one byte left to read out the virtual flag */
1467 goto trunctlv;
1468
1469 printf("\n\t\t\t%s",
1470 tok2str(isis_is_reach_virtual_values,
1471 "bogus virtual flag 0x%02x",
1472 *tptr++));
1473
1474 tlv_is_reach = (const struct isis_tlv_is_reach *)tptr;
1475
1476 while (tmp >= sizeof(struct isis_tlv_is_reach)) {
1477 if (!TTEST(*tlv_is_reach))
1478 goto trunctlv;
1479
1480 printf("\n\t\t\tIS Neighbor: %s", isis_print_nodeid(tlv_is_reach->neighbor_nodeid));
1481 printf(", Default Metric: %d, %s",
1482 ISIS_LSP_TLV_METRIC_VALUE(tlv_is_reach->metric_default),
1483 ISIS_LSP_TLV_METRIC_IE(tlv_is_reach->metric_default) ? "External" : "Internal");
1484
1485 if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_is_reach->metric_delay))
1486 printf("\n\t\t\t Delay Metric: %d, %s",
1487 ISIS_LSP_TLV_METRIC_VALUE(tlv_is_reach->metric_delay),
1488 ISIS_LSP_TLV_METRIC_IE(tlv_is_reach->metric_delay) ? "External" : "Internal");
1489
1490 if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_is_reach->metric_expense))
1491 printf("\n\t\t\t Expense Metric: %d, %s",
1492 ISIS_LSP_TLV_METRIC_VALUE(tlv_is_reach->metric_expense),
1493 ISIS_LSP_TLV_METRIC_IE(tlv_is_reach->metric_expense) ? "External" : "Internal");
1494
1495 if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_is_reach->metric_error))
1496 printf("\n\t\t\t Error Metric: %d, %s",
1497 ISIS_LSP_TLV_METRIC_VALUE(tlv_is_reach->metric_error),
1498 ISIS_LSP_TLV_METRIC_IE(tlv_is_reach->metric_error) ? "External" : "Internal");
1499
1500 tmp -= sizeof(struct isis_tlv_is_reach);
1501 tlv_is_reach++;
1502 }
1503 break;
1504
1505 /* those two TLVs share the same format */
1506 case TLV_IP_REACH:
1507 case TLV_IP_REACH_EXT:
1508 if (!isis_print_tlv_ip_reach(pptr, len))
1509 return (1);
1510 break;
1511
1512 case TLV_MT_IP_REACH:
1513 while (tmp>0) {
1514 if (!TTEST2(*tptr, 2))
1515 goto trunctlv;
1516
1517 printf("\n\t\t\t%s",
1518 tok2str(isis_mt_values,
1519 "Reserved for IETF Consensus",
1520 ISIS_MASK_MTID(EXTRACT_16BITS(tptr))));
1521
1522 printf(" Topology (0x%03x)",
1523 ISIS_MASK_MTID(EXTRACT_16BITS(tptr)));
1524 tptr+=2;
1525
1526 memset (prefix, 0, 4);
1527 if (!TTEST2(*tptr, 4))
1528 return (1);
1529 metric = EXTRACT_32BITS(tptr);
1530 tptr+=4;
1531
1532 if (!TTEST2(*tptr, 1)) /* fetch status byte */
1533 return (1);
1534 j=*(tptr);
1535 bit_length = (*(tptr)++&0x3f);
1536 byte_length = (bit_length + 7) / 8; /* prefix has variable length encoding */
1537
1538 if (!TTEST2(*tptr, byte_length))
1539 return (1);
1540 memcpy(prefix,tptr,byte_length);
1541 tptr+=byte_length;
1542 printf("\n\t\t\tIPv4 prefix: %s/%d",
1543 ipaddr_string(prefix),
1544 bit_length);
1545
1546 printf("\n\t\t\t Metric: %u, Distribution: %s",
1547 metric,
1548 ISIS_MASK_TLV_EXT_IP_UPDOWN(j) ? "down" : "up");
1549
1550 printf(", %ssub-TLVs present",
1551 ISIS_MASK_TLV_EXT_IP_SUBTLV(j) ? "" : "no ");
1552
1553 if (ISIS_MASK_TLV_EXT_IP_SUBTLV(j)) {
1554 /* assume that one prefix can hold more
1555 than one subTLV - therefore the first byte must reflect
1556 the aggregate bytecount of the subTLVs for this prefix
1557 */
1558 if (!TTEST2(*tptr, 1))
1559 return (1);
1560 tslen=*(tptr++);
1561 tmp--;
1562 printf(" (%u)",tslen); /* print out subTLV length */
1563
1564 while (tslen>0) {
1565 if (!TTEST2(*tptr,2))
1566 goto trunctlv;
1567 subt=*(tptr++);
1568 subl=*(tptr++);
1569 if(!isis_print_ip_reach_subtlv(tptr,subt,subl,"\n\t\t\t "))
1570 return(0);
1571 tptr+=subl;
1572 tslen-=(subl+2);
1573 tmp-=(subl+2);
1574 }
1575 }
1576 tmp-=(7+byte_length);
1577 }
1578 break;
1579
1580 case TLV_EXT_IP_REACH:
1581 while (tmp>0) {
1582 memset (prefix, 0, 4);
1583 if (!TTEST2(*tptr, 4))
1584 return (1);
1585 metric = EXTRACT_32BITS(tptr);
1586 tptr+=4;
1587
1588 if (!TTEST2(*tptr, 1)) /* fetch status byte */
1589 return (1);
1590 j=*(tptr);
1591 bit_length = (*(tptr)++&0x3f);
1592 byte_length = (bit_length + 7) / 8; /* prefix has variable length encoding */
1593
1594 if (!TTEST2(*tptr, byte_length))
1595 return (1);
1596 memcpy(prefix,tptr,byte_length);
1597 tptr+=byte_length;
1598 printf("\n\t\t\tIPv4 prefix: %s/%d",
1599 ipaddr_string(prefix),
1600 bit_length);
1601
1602 printf("\n\t\t\t Metric: %u, Distribution: %s",
1603 metric,
1604 ISIS_MASK_TLV_EXT_IP_UPDOWN(j) ? "down" : "up");
1605
1606 printf(", %ssub-TLVs present",
1607 ISIS_MASK_TLV_EXT_IP_SUBTLV(j) ? "" : "no ");
1608
1609 if (ISIS_MASK_TLV_EXT_IP_SUBTLV(j)) {
1610 /* assume that one prefix can hold more
1611 than one subTLV - therefore the first byte must reflect
1612 the aggregate bytecount of the subTLVs for this prefix
1613 */
1614 if (!TTEST2(*tptr, 1))
1615 return (1);
1616 tslen=*(tptr++);
1617 tmp--;
1618 printf(" (%u)",tslen); /* print out subTLV length */
1619
1620 while (tslen>0) {
1621 if (!TTEST2(*tptr,2))
1622 goto trunctlv;
1623 subt=*(tptr++);
1624 subl=*(tptr++);
1625 if(!isis_print_ip_reach_subtlv(tptr,subt,subl,"\n\t\t\t "))
1626 return(0);
1627 tptr+=subl;
1628 tslen-=(subl+2);
1629 tmp-=(subl+2);
1630 }
1631 }
1632 tmp-=(5+byte_length);
1633 }
1634 break;
1635
1636 #ifdef INET6
1637
1638 case TLV_IP6_REACH:
1639 while (tmp>0) {
1640 if (!TTEST2(*tptr, 4))
1641 return (1);
1642 metric = EXTRACT_32BITS(tptr);
1643 tptr+=4;
1644
1645 if (!TTEST2(*tptr, 2))
1646 return (1);
1647 j=*(tptr++);
1648 bit_length = (*(tptr)++);
1649 byte_length = (bit_length + 7) / 8;
1650 if (!TTEST2(*tptr, byte_length))
1651 return (1);
1652
1653 memset(prefix6, 0, 16);
1654 memcpy(prefix6,tptr,byte_length);
1655 tptr+=byte_length;
1656 printf("\n\t\t\tIPv6 prefix: %s/%u",
1657 ip6addr_string(prefix6),
1658 bit_length);
1659
1660 printf("\n\t\t\t Metric: %u, %s, Distribution: %s, %ssub-TLVs present",
1661 metric,
1662 ISIS_MASK_TLV_IP6_IE(j) ? "External" : "Internal",
1663 ISIS_MASK_TLV_IP6_UPDOWN(j) ? "down" : "up",
1664 ISIS_MASK_TLV_IP6_SUBTLV(j) ? "" : "no ");
1665
1666 if (ISIS_MASK_TLV_IP6_SUBTLV(j)) {
1667 /* assume that one prefix can hold more
1668 than one subTLV - therefore the first byte must reflect
1669 the aggregate bytecount of the subTLVs for this prefix
1670 */
1671 if (!TTEST2(*tptr, 1))
1672 return (1);
1673 tslen=*(tptr++);
1674 tmp--;
1675 printf(" (%u)",tslen); /* print out subTLV length */
1676
1677 while (tslen>0) {
1678 if (!TTEST2(*tptr,2))
1679 goto trunctlv;
1680 subt=*(tptr++);
1681 subl=*(tptr++);
1682 if(!isis_print_ip_reach_subtlv(tptr,subt,subl,"\n\t\t\t "))
1683 return(0);
1684 tptr+=subl;
1685 tslen-=(subl+2);
1686 tmp-=(subl+2);
1687 }
1688 }
1689 tmp-=(6+byte_length);
1690 }
1691
1692 break;
1693 #endif
1694
1695 #ifdef INET6
1696 case TLV_IP6ADDR:
1697 while (tmp>0) {
1698 if (!TTEST2(*tptr, 16))
1699 goto trunctlv;
1700
1701 printf("\n\t\t\tIPv6 interface address: %s",
1702 ip6addr_string(tptr));
1703
1704 tptr += 16;
1705 tmp -= 16;
1706 }
1707 break;
1708 #endif
1709 case TLV_AUTH:
1710 if (!TTEST2(*tptr, 1))
1711 goto trunctlv;
1712
1713 printf("\n\t\t\t%s: ",
1714 tok2str(isis_subtlv_auth_values,
1715 "unknown Authentication type 0x%02x",
1716 *tptr));
1717
1718 switch (*tptr) {
1719 case SUBTLV_AUTH_SIMPLE:
1720 for(i=1;i<len;i++) {
1721 if (!TTEST2(*(tptr+i), 1))
1722 goto trunctlv;
1723 printf("%c",*(tptr+i));
1724 }
1725 break;
1726 case SUBTLV_AUTH_MD5:
1727 for(i=1;i<len;i++) {
1728 if (!TTEST2(*(tptr+i), 1))
1729 goto trunctlv;
1730 printf("%02x",*(tptr+i));
1731 }
1732 if (len != SUBTLV_AUTH_MD5_LEN+1)
1733 printf(", (malformed subTLV) ");
1734 break;
1735 case SUBTLV_AUTH_PRIVATE:
1736 default:
1737 if(!isis_print_unknown_data(tptr+1,"\n\t\t\t ",len-1))
1738 return(0);
1739 break;
1740 }
1741 break;
1742
1743 case TLV_PTP_ADJ:
1744 tlv_ptp_adj = (const struct isis_tlv_ptp_adj *)tptr;
1745 if(tmp>=1) {
1746 if (!TTEST2(*tptr, 1))
1747 goto trunctlv;
1748 printf("\n\t\t\tAdjacency State: %s",
1749 tok2str(isis_ptp_adjancey_values, "0x%02x", *tptr));
1750 tmp--;
1751 }
1752 if(tmp>=4) {
1753 if (!TTEST2(tlv_ptp_adj->ext_local_circuit_id, 4))
1754 goto trunctlv;
1755 printf("\n\t\t\tExtended Local circuit ID: 0x%08x",
1756 EXTRACT_32BITS(tlv_ptp_adj->ext_local_circuit_id));
1757 tmp-=4;
1758 }
1759 if(tmp>=6) {
1760 if (!TTEST2(tlv_ptp_adj->neighbor_sysid, 6))
1761 goto trunctlv;
1762 printf("\n\t\t\tNeighbor SystemID: %s",
1763 isis_print_sysid(tlv_ptp_adj->neighbor_sysid));
1764 tmp-=6;
1765 }
1766 if(tmp>=4) {
1767 if (!TTEST2(tlv_ptp_adj->neighbor_ext_local_circuit_id, 4))
1768 goto trunctlv;
1769 printf("\n\t\t\tNeighbor Extended Local circuit ID: 0x%08x",
1770 EXTRACT_32BITS(tlv_ptp_adj->neighbor_ext_local_circuit_id));
1771 }
1772 break;
1773
1774 case TLV_PROTOCOLS:
1775 printf("\n\t\t\tNLPID(s): ");
1776 while (tmp>0) {
1777 if (!TTEST2(*(tptr), 1))
1778 goto trunctlv;
1779 printf("%s",
1780 tok2str(isis_nlpid_values,
1781 "Unknown 0x%02x",
1782 *tptr++));
1783 if (tmp>1) /* further NPLIDs ? - put comma */
1784 printf(", ");
1785 tmp--;
1786 }
1787 break;
1788
1789 case TLV_TE_ROUTER_ID:
1790 if (!TTEST2(*pptr, 4))
1791 goto trunctlv;
1792 printf("\n\t\t\tTraffic Engineering Router ID: %s", ipaddr_string(pptr));
1793 break;
1794
1795 case TLV_IPADDR:
1796 while (tmp>0) {
1797 if (!TTEST2(*tptr, 4))
1798 goto trunctlv;
1799 printf("\n\t\t\tIPv4 interface address: %s", ipaddr_string(tptr));
1800 tptr += 4;
1801 tmp -= 4;
1802 }
1803 break;
1804
1805 case TLV_HOSTNAME:
1806 printf("\n\t\t\tHostname: ");
1807 while (tmp>0) {
1808 if (!TTEST2(*tptr, 1))
1809 goto trunctlv;
1810 printf("%c",*tptr++);
1811 tmp--;
1812 }
1813 break;
1814
1815 case TLV_SHARED_RISK_GROUP:
1816 if (!TTEST2(*tptr, 7))
1817 goto trunctlv;
1818 printf("\n\t\t\tIS Neighbor: %s", isis_print_nodeid(tptr));
1819 tptr+=(SYSTEM_ID_LEN+1);
1820 len-=(SYSTEM_ID_LEN+1);
1821
1822 if (!TTEST2(*tptr, 1))
1823 goto trunctlv;
1824 printf(", %s", ISIS_MASK_TLV_SHARED_RISK_GROUP(*tptr++) ? "numbered" : "unnumbered");
1825 len--;
1826
1827 if (!TTEST2(*tptr,4))
1828 goto trunctlv;
1829 printf("\n\t\t\tIPv4 interface address: %s", ipaddr_string(tptr));
1830 tptr+=4;
1831 len-=4;
1832
1833 if (!TTEST2(*tptr,4))
1834 goto trunctlv;
1835 printf("\n\t\t\tIPv4 neighbor address: %s", ipaddr_string(tptr));
1836 tptr+=4;
1837 len-=4;
1838
1839 while (tmp>0) {
1840 if (!TTEST2(*tptr, 4))
1841 goto trunctlv;
1842 printf("\n\t\t\tLink-ID: 0x%08x", EXTRACT_32BITS(tptr));
1843 tptr+=4;
1844 len-=4;
1845 }
1846 break;
1847
1848 case TLV_LSP:
1849 tlv_lsp = (const struct isis_tlv_lsp *)tptr;
1850 while(tmp>0) {
1851 printf("\n\t\t\tlsp-id: %s",
1852 isis_print_nodeid(tlv_lsp->lsp_id));
1853 if (!TTEST((tlv_lsp->lsp_id)[SYSTEM_ID_LEN+1]))
1854 goto trunctlv;
1855 printf("-%02x",(tlv_lsp->lsp_id)[SYSTEM_ID_LEN+1]);
1856 if (!TTEST2(tlv_lsp->sequence_number, 4))
1857 goto trunctlv;
1858 printf(", seq: 0x%08x",EXTRACT_32BITS(tlv_lsp->sequence_number));
1859 if (!TTEST2(tlv_lsp->remaining_lifetime, 2))
1860 goto trunctlv;
1861 printf(", lifetime: %5ds",EXTRACT_16BITS(tlv_lsp->remaining_lifetime));
1862 if (!TTEST2(tlv_lsp->checksum, 2))
1863 goto trunctlv;
1864 printf(", chksum: 0x%04x",EXTRACT_16BITS(tlv_lsp->checksum));
1865 tmp-=sizeof(struct isis_tlv_lsp);
1866 tlv_lsp++;
1867 }
1868 break;
1869
1870 case TLV_CHECKSUM:
1871 if (!TTEST2(*tptr, 2))
1872 goto trunctlv;
1873 printf("\n\t\t\tchecksum: 0x%04x",
1874 EXTRACT_16BITS(tptr));
1875 if (osi_cksum(optr, length))
1876 printf(" (incorrect)");
1877 else
1878 printf(" (correct)");
1879 break;
1880
1881 case TLV_MT_SUPPORTED:
1882 while (tmp>1) {
1883 /* length can only be a multiple of 2, otherwise there is
1884 something broken -> so decode down until length is 1 */
1885 if (tmp!=1) {
1886 if (!TTEST2(*tptr, 2))
1887 goto trunctlv;
1888 printf("\n\t\t\t%s",
1889 tok2str(isis_mt_values,
1890 "Reserved for IETF Consensus",
1891 ISIS_MASK_MTID(EXTRACT_16BITS(tptr))));
1892
1893 printf(" Topology (0x%03x)%s%s",
1894 ISIS_MASK_MTID(EXTRACT_16BITS(tptr)),
1895 ISIS_MASK_MTSUB(EXTRACT_16BITS(tptr)) ? "" : ", no sub-TLVs present",
1896 ISIS_MASK_MTATT(EXTRACT_16BITS(tptr)) ? ", ATT bit set" : "" );
1897 } else {
1898 printf("\n\t\t\tmalformed MT-ID");
1899 break;
1900 }
1901 tmp-=2;
1902 tptr+=2;
1903 }
1904 break;
1905
1906 case TLV_RESTART_SIGNALING:
1907 if (!TTEST2(*tptr, 3))
1908 goto trunctlv;
1909 rr = ISIS_MASK_TLV_RESTART_RR(*tptr);
1910 ra = ISIS_MASK_TLV_RESTART_RA(*tptr);
1911 tptr++;
1912 time_remain = EXTRACT_16BITS(tptr);
1913 printf("\n\t\t\tRestart Request bit %s, Restart Acknowledgement bit %s\n\t\t\tRemaining holding time: %us",
1914 rr ? "set" : "clear", ra ? "set" : "clear", time_remain);
1915 break;
1916
1917 /*
1918 * FIXME those are the defined TLVs that lack a decoder
1919 * you are welcome to contribute code ;-)
1920 */
1921
1922 case TLV_ESNEIGH:
1923 case TLV_PART_DIS:
1924 case TLV_SUMMARY:
1925 case TLV_LSP_BUFFERSIZE:
1926 case TLV_IS_ALIAS_ID:
1927 case TLV_DECNET_PHASE4:
1928 case TLV_LUCENT_PRIVATE:
1929 case TLV_IDRP_INFO:
1930 case TLV_IPAUTH:
1931 case TLV_NORTEL_PRIVATE1:
1932 case TLV_NORTEL_PRIVATE2:
1933 case TLV_MT_IP6_REACH:
1934
1935 default:
1936 if(!isis_print_unknown_data(pptr,"\n\t\t\t",len))
1937 return(0);
1938 break;
1939 }
1940
1941 pptr += len;
1942 packet_len -= len;
1943 }
1944
1945 if (packet_len != 0) {
1946 printf("\n\t\t\t %d straggler bytes", packet_len);
1947 }
1948 return (1);
1949
1950 trunc:
1951 fputs("[|isis]", stdout);
1952 return (1);
1953
1954 trunctlv:
1955 printf("\n\t\t\t packet exceeded snapshot");
1956 return(1);
1957 }
1958
1959 /*
1960 * Verify the checksum. See 8473-1, Appendix C, section C.4.
1961 */
1962
1963 static int
1964 osi_cksum(const u_char *tptr, u_int len)
1965 {
1966 int32_t c0 = 0, c1 = 0;
1967
1968 while ((int)--len >= 0) {
1969 c0 += *tptr++;
1970 c0 %= 255;
1971 c1 += c0;
1972 c1 %= 255;
1973 }
1974 return (c0 | c1);
1975 }