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