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