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