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