]> The Tcpdump Group git mirrors - tcpdump/blob - print-isoclns.c
code cleanup:
[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 & CLNP support.
25 */
26
27 #ifndef lint
28 static const char rcsid[] _U_ =
29 "@(#) $Header: /tcpdump/master/tcpdump/print-isoclns.c,v 1.128 2005-03-08 08:52:39 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 "nlpid.h"
46 #include "extract.h"
47 #include "gmpls.h"
48 #include "oui.h"
49
50 #define IPV4 1 /* AFI value */
51 #define IPV6 2 /* AFI value */
52
53 /*
54 * IS-IS is defined in ISO 10589. Look there for protocol definitions.
55 */
56
57 #define SYSTEM_ID_LEN ETHER_ADDR_LEN
58 #define NODE_ID_LEN SYSTEM_ID_LEN+1
59 #define LSP_ID_LEN SYSTEM_ID_LEN+2
60
61 #define ISIS_VERSION 1
62 #define ESIS_VERSION 1
63 #define CLNP_VERSION 1
64
65 #define ISIS_PDU_TYPE_MASK 0x1F
66 #define ESIS_PDU_TYPE_MASK 0x1F
67 #define CLNP_PDU_TYPE_MASK 0x1F
68 #define CLNP_FLAG_MASK 0xE0
69 #define ISIS_LAN_PRIORITY_MASK 0x7F
70
71 #define ISIS_PDU_L1_LAN_IIH 15
72 #define ISIS_PDU_L2_LAN_IIH 16
73 #define ISIS_PDU_PTP_IIH 17
74 #define ISIS_PDU_L1_LSP 18
75 #define ISIS_PDU_L2_LSP 20
76 #define ISIS_PDU_L1_CSNP 24
77 #define ISIS_PDU_L2_CSNP 25
78 #define ISIS_PDU_L1_PSNP 26
79 #define ISIS_PDU_L2_PSNP 27
80
81 static struct tok isis_pdu_values[] = {
82 { ISIS_PDU_L1_LAN_IIH, "L1 Lan IIH"},
83 { ISIS_PDU_L2_LAN_IIH, "L2 Lan IIH"},
84 { ISIS_PDU_PTP_IIH, "p2p IIH"},
85 { ISIS_PDU_L1_LSP, "L1 LSP"},
86 { ISIS_PDU_L2_LSP, "L2 LSP"},
87 { ISIS_PDU_L1_CSNP, "L1 CSNP"},
88 { ISIS_PDU_L2_CSNP, "L2 CSNP"},
89 { ISIS_PDU_L1_PSNP, "L1 PSNP"},
90 { ISIS_PDU_L2_PSNP, "L2 PSNP"},
91 { 0, NULL}
92 };
93
94 /*
95 * A TLV is a tuple of a type, length and a value and is normally used for
96 * encoding information in all sorts of places. This is an enumeration of
97 * the well known types.
98 *
99 * list taken from rfc3359 plus some memory from veterans ;-)
100 */
101
102 #define ISIS_TLV_AREA_ADDR 1 /* iso10589 */
103 #define ISIS_TLV_IS_REACH 2 /* iso10589 */
104 #define ISIS_TLV_ESNEIGH 3 /* iso10589 */
105 #define ISIS_TLV_PART_DIS 4 /* iso10589 */
106 #define ISIS_TLV_PREFIX_NEIGH 5 /* iso10589 */
107 #define ISIS_TLV_ISNEIGH 6 /* iso10589 */
108 #define ISIS_TLV_ISNEIGH_VARLEN 7 /* iso10589 */
109 #define ISIS_TLV_PADDING 8 /* iso10589 */
110 #define ISIS_TLV_LSP 9 /* iso10589 */
111 #define ISIS_TLV_AUTH 10 /* iso10589, rfc3567 */
112 #define ISIS_TLV_CHECKSUM 12 /* rfc3358 */
113 #define ISIS_TLV_LSP_BUFFERSIZE 14 /* iso10589 rev2 */
114 #define ISIS_TLV_EXT_IS_REACH 22 /* draft-ietf-isis-traffic-05 */
115 #define ISIS_TLV_IS_ALIAS_ID 24 /* draft-ietf-isis-ext-lsp-frags-02 */
116 #define ISIS_TLV_DECNET_PHASE4 42
117 #define ISIS_TLV_LUCENT_PRIVATE 66
118 #define ISIS_TLV_INT_IP_REACH 128 /* rfc1195, rfc2966 */
119 #define ISIS_TLV_PROTOCOLS 129 /* rfc1195 */
120 #define ISIS_TLV_EXT_IP_REACH 130 /* rfc1195, rfc2966 */
121 #define ISIS_TLV_IDRP_INFO 131 /* rfc1195 */
122 #define ISIS_TLV_IPADDR 132 /* rfc1195 */
123 #define ISIS_TLV_IPAUTH 133 /* rfc1195 */
124 #define ISIS_TLV_TE_ROUTER_ID 134 /* draft-ietf-isis-traffic-05 */
125 #define ISIS_TLV_EXTD_IP_REACH 135 /* draft-ietf-isis-traffic-05 */
126 #define ISIS_TLV_HOSTNAME 137 /* rfc2763 */
127 #define ISIS_TLV_SHARED_RISK_GROUP 138 /* draft-ietf-isis-gmpls-extensions */
128 #define ISIS_TLV_NORTEL_PRIVATE1 176
129 #define ISIS_TLV_NORTEL_PRIVATE2 177
130 #define ISIS_TLV_RESTART_SIGNALING 211 /* draft-ietf-isis-restart-01 */
131 #define ISIS_TLV_MT_IS_REACH 222 /* draft-ietf-isis-wg-multi-topology-05 */
132 #define ISIS_TLV_MT_SUPPORTED 229 /* draft-ietf-isis-wg-multi-topology-05 */
133 #define ISIS_TLV_IP6ADDR 232 /* draft-ietf-isis-ipv6-02 */
134 #define ISIS_TLV_MT_IP_REACH 235 /* draft-ietf-isis-wg-multi-topology-05 */
135 #define ISIS_TLV_IP6_REACH 236 /* draft-ietf-isis-ipv6-02 */
136 #define ISIS_TLV_MT_IP6_REACH 237 /* draft-ietf-isis-wg-multi-topology-05 */
137 #define ISIS_TLV_PTP_ADJ 240 /* rfc3373 */
138 #define ISIS_TLV_IIH_SEQNR 241 /* draft-shen-isis-iih-sequence-00 */
139 #define ISIS_TLV_VENDOR_PRIVATE 250 /* draft-ietf-isis-experimental-tlv-01 */
140
141 static struct tok isis_tlv_values[] = {
142 { ISIS_TLV_AREA_ADDR, "Area address(es)"},
143 { ISIS_TLV_IS_REACH, "IS Reachability"},
144 { ISIS_TLV_ESNEIGH, "ES Neighbor(s)"},
145 { ISIS_TLV_PART_DIS, "Partition DIS"},
146 { ISIS_TLV_PREFIX_NEIGH, "Prefix Neighbors"},
147 { ISIS_TLV_ISNEIGH, "IS Neighbor(s)"},
148 { ISIS_TLV_ISNEIGH_VARLEN, "IS Neighbor(s) (variable length)"},
149 { ISIS_TLV_PADDING, "Padding"},
150 { ISIS_TLV_LSP, "LSP entries"},
151 { ISIS_TLV_AUTH, "Authentication"},
152 { ISIS_TLV_CHECKSUM, "Checksum"},
153 { ISIS_TLV_LSP_BUFFERSIZE, "LSP Buffersize"},
154 { ISIS_TLV_EXT_IS_REACH, "Extended IS Reachability"},
155 { ISIS_TLV_IS_ALIAS_ID, "IS Alias ID"},
156 { ISIS_TLV_DECNET_PHASE4, "DECnet Phase IV"},
157 { ISIS_TLV_LUCENT_PRIVATE, "Lucent Proprietary"},
158 { ISIS_TLV_INT_IP_REACH, "IPv4 Internal Reachability"},
159 { ISIS_TLV_PROTOCOLS, "Protocols supported"},
160 { ISIS_TLV_EXT_IP_REACH, "IPv4 External Reachability"},
161 { ISIS_TLV_IDRP_INFO, "Inter-Domain Information Type"},
162 { ISIS_TLV_IPADDR, "IPv4 Interface address(es)"},
163 { ISIS_TLV_IPAUTH, "IPv4 authentication (deprecated)"},
164 { ISIS_TLV_TE_ROUTER_ID, "Traffic Engineering Router ID"},
165 { ISIS_TLV_EXTD_IP_REACH, "Extended IPv4 Reachability"},
166 { ISIS_TLV_SHARED_RISK_GROUP, "Shared Risk Link Group"},
167 { ISIS_TLV_NORTEL_PRIVATE1, "Nortel Proprietary"},
168 { ISIS_TLV_NORTEL_PRIVATE2, "Nortel Proprietary"},
169 { ISIS_TLV_HOSTNAME, "Hostname"},
170 { ISIS_TLV_RESTART_SIGNALING, "Restart Signaling"},
171 { ISIS_TLV_MT_IS_REACH, "Multi Topology IS Reachability"},
172 { ISIS_TLV_MT_SUPPORTED, "Multi Topology"},
173 { ISIS_TLV_IP6ADDR, "IPv6 Interface address(es)"},
174 { ISIS_TLV_MT_IP_REACH, "Multi-Topology IPv4 Reachability"},
175 { ISIS_TLV_IP6_REACH, "IPv6 reachability"},
176 { ISIS_TLV_MT_IP6_REACH, "Multi-Topology IP6 Reachability"},
177 { ISIS_TLV_PTP_ADJ, "Point-to-point Adjacency State"},
178 { ISIS_TLV_IIH_SEQNR, "Hello PDU Sequence Number"},
179 { ISIS_TLV_VENDOR_PRIVATE, "Vendor Private"},
180 { 0, NULL }
181 };
182
183 #define ESIS_OPTION_PROTOCOLS 129
184 #define ESIS_OPTION_QOS_MAINTENANCE 195 /* iso9542 */
185 #define ESIS_OPTION_SECURITY 197 /* iso9542 */
186 #define ESIS_OPTION_ES_CONF_TIME 198 /* iso9542 */
187 #define ESIS_OPTION_PRIORITY 205 /* iso9542 */
188 #define ESIS_OPTION_ADDRESS_MASK 225 /* iso9542 */
189 #define ESIS_OPTION_SNPA_MASK 226 /* iso9542 */
190
191 static struct tok esis_option_values[] = {
192 { ESIS_OPTION_PROTOCOLS, "Protocols supported"},
193 { ESIS_OPTION_QOS_MAINTENANCE, "QoS Maintenance" },
194 { ESIS_OPTION_SECURITY, "Security" },
195 { ESIS_OPTION_ES_CONF_TIME, "ES Configuration Time" },
196 { ESIS_OPTION_PRIORITY, "Priority" },
197 { ESIS_OPTION_ADDRESS_MASK, "Addressk Mask" },
198 { ESIS_OPTION_SNPA_MASK, "SNPA Mask" },
199 { 0, NULL }
200 };
201
202 #define CLNP_OPTION_DISCARD_REASON 193
203 #define CLNP_OPTION_QOS_MAINTENANCE 195 /* iso8473 */
204 #define CLNP_OPTION_PRIORITY 205 /* iso8473 */
205
206 static struct tok clnp_option_values[] = {
207 { CLNP_OPTION_DISCARD_REASON, "Discard Reason"},
208 { CLNP_OPTION_PRIORITY, "Priority"},
209 { CLNP_OPTION_QOS_MAINTENANCE, "QoS Maintenance"},
210 { 0, NULL }
211 };
212
213 #define ISIS_SUBTLV_EXT_IS_REACH_ADMIN_GROUP 3 /* draft-ietf-isis-traffic-05 */
214 #define ISIS_SUBTLV_EXT_IS_REACH_LINK_LOCAL_REMOTE_ID 4 /* draft-ietf-isis-gmpls-extensions */
215 #define ISIS_SUBTLV_EXT_IS_REACH_LINK_REMOTE_ID 5 /* draft-ietf-isis-traffic-05 */
216 #define ISIS_SUBTLV_EXT_IS_REACH_IPV4_INTF_ADDR 6 /* draft-ietf-isis-traffic-05 */
217 #define ISIS_SUBTLV_EXT_IS_REACH_IPV4_NEIGHBOR_ADDR 8 /* draft-ietf-isis-traffic-05 */
218 #define ISIS_SUBTLV_EXT_IS_REACH_MAX_LINK_BW 9 /* draft-ietf-isis-traffic-05 */
219 #define ISIS_SUBTLV_EXT_IS_REACH_RESERVABLE_BW 10 /* draft-ietf-isis-traffic-05 */
220 #define ISIS_SUBTLV_EXT_IS_REACH_UNRESERVED_BW 11 /* draft-ietf-isis-traffic-05 */
221 #define ISIS_SUBTLV_EXT_IS_REACH_DIFFSERV_TE 12 /* draft-ietf-tewg-diff-te-proto-06 */
222 #define ISIS_SUBTLV_EXT_IS_REACH_TE_METRIC 18 /* draft-ietf-isis-traffic-05 */
223 #define ISIS_SUBTLV_EXT_IS_REACH_LINK_PROTECTION_TYPE 20 /* draft-ietf-isis-gmpls-extensions */
224 #define ISIS_SUBTLV_EXT_IS_REACH_INTF_SW_CAP_DESCR 21 /* draft-ietf-isis-gmpls-extensions */
225
226 static struct tok isis_ext_is_reach_subtlv_values[] = {
227 { ISIS_SUBTLV_EXT_IS_REACH_ADMIN_GROUP, "Administrative groups" },
228 { ISIS_SUBTLV_EXT_IS_REACH_LINK_LOCAL_REMOTE_ID, "Link Local/Remote Identifier" },
229 { ISIS_SUBTLV_EXT_IS_REACH_LINK_REMOTE_ID, "Link Remote Identifier" },
230 { ISIS_SUBTLV_EXT_IS_REACH_IPV4_INTF_ADDR, "IPv4 interface address" },
231 { ISIS_SUBTLV_EXT_IS_REACH_IPV4_NEIGHBOR_ADDR, "IPv4 neighbor address" },
232 { ISIS_SUBTLV_EXT_IS_REACH_MAX_LINK_BW, "Maximum link bandwidth" },
233 { ISIS_SUBTLV_EXT_IS_REACH_RESERVABLE_BW, "Reservable link bandwidth" },
234 { ISIS_SUBTLV_EXT_IS_REACH_UNRESERVED_BW, "Unreserved bandwidth" },
235 { ISIS_SUBTLV_EXT_IS_REACH_DIFFSERV_TE, "Diffserv TE" },
236 { ISIS_SUBTLV_EXT_IS_REACH_TE_METRIC, "Traffic Engineering Metric" },
237 { ISIS_SUBTLV_EXT_IS_REACH_LINK_PROTECTION_TYPE, "Link Protection Type" },
238 { ISIS_SUBTLV_EXT_IS_REACH_INTF_SW_CAP_DESCR, "Interface Switching Capability" },
239 { 250, "Reserved for cisco specific extensions" },
240 { 251, "Reserved for cisco specific extensions" },
241 { 252, "Reserved for cisco specific extensions" },
242 { 253, "Reserved for cisco specific extensions" },
243 { 254, "Reserved for cisco specific extensions" },
244 { 255, "Reserved for future expansion" },
245 { 0, NULL }
246 };
247
248 #define ISIS_SUBTLV_EXTD_IP_REACH_ADMIN_TAG32 1 /* draft-ietf-isis-admin-tags-01 */
249 #define ISIS_SUBTLV_EXTD_IP_REACH_ADMIN_TAG64 2 /* draft-ietf-isis-admin-tags-01 */
250 #define ISIS_SUBTLV_EXTD_IP_REACH_MGMT_PREFIX_COLOR 117 /* draft-ietf-isis-wg-multi-topology-05 */
251
252 static struct tok isis_ext_ip_reach_subtlv_values[] = {
253 { ISIS_SUBTLV_EXTD_IP_REACH_ADMIN_TAG32, "32-Bit Administrative tag" },
254 { ISIS_SUBTLV_EXTD_IP_REACH_ADMIN_TAG64, "64-Bit Administrative tag" },
255 { ISIS_SUBTLV_EXTD_IP_REACH_MGMT_PREFIX_COLOR, "Management Prefix Color" },
256 { 0, NULL }
257 };
258
259 #define ISIS_SUBTLV_AUTH_SIMPLE 1
260 #define ISIS_SUBTLV_AUTH_MD5 54
261 #define ISIS_SUBTLV_AUTH_MD5_LEN 16
262 #define ISIS_SUBTLV_AUTH_PRIVATE 255
263
264 static struct tok isis_subtlv_auth_values[] = {
265 { ISIS_SUBTLV_AUTH_SIMPLE, "simple text password"},
266 { ISIS_SUBTLV_AUTH_MD5, "HMAC-MD5 password"},
267 { ISIS_SUBTLV_AUTH_PRIVATE, "Routing Domain private password"},
268 { 0, NULL }
269 };
270
271 #define ISIS_SUBTLV_IDRP_RES 0
272 #define ISIS_SUBTLV_IDRP_LOCAL 1
273 #define ISIS_SUBTLV_IDRP_ASN 2
274
275 static struct tok isis_subtlv_idrp_values[] = {
276 { ISIS_SUBTLV_IDRP_RES, "Reserved"},
277 { ISIS_SUBTLV_IDRP_LOCAL, "Routing-Domain Specific"},
278 { ISIS_SUBTLV_IDRP_ASN, "AS Number Tag"},
279 { 0, NULL}
280 };
281
282 #define CLNP_SEGMENT_PART 0x80
283 #define CLNP_MORE_SEGMENTS 0x40
284 #define CLNP_REQUEST_ER 0x20
285
286 static struct tok clnp_flag_values[] = {
287 { CLNP_SEGMENT_PART, "Segmentation permitted"},
288 { CLNP_MORE_SEGMENTS, "more Segments"},
289 { CLNP_REQUEST_ER, "request Error Report"},
290 { 0, NULL}
291 };
292
293 #define ISIS_MASK_LSP_OL_BIT(x) ((x)&0x4)
294 #define ISIS_MASK_LSP_ISTYPE_BITS(x) ((x)&0x3)
295 #define ISIS_MASK_LSP_PARTITION_BIT(x) ((x)&0x80)
296 #define ISIS_MASK_LSP_ATT_BITS(x) ((x)&0x78)
297 #define ISIS_MASK_LSP_ATT_ERROR_BIT(x) ((x)&0x40)
298 #define ISIS_MASK_LSP_ATT_EXPENSE_BIT(x) ((x)&0x20)
299 #define ISIS_MASK_LSP_ATT_DELAY_BIT(x) ((x)&0x10)
300 #define ISIS_MASK_LSP_ATT_DEFAULT_BIT(x) ((x)&0x8)
301
302 #define ISIS_MASK_MTID(x) ((x)&0x0fff)
303 #define ISIS_MASK_MTFLAGS(x) ((x)&0xf000)
304
305 static struct tok isis_mt_flag_values[] = {
306 { 0x4000, "sub-TLVs present"},
307 { 0x8000, "ATT bit set"},
308 { 0, NULL}
309 };
310
311 #define ISIS_MASK_TLV_EXTD_IP_UPDOWN(x) ((x)&0x80)
312 #define ISIS_MASK_TLV_EXTD_IP_SUBTLV(x) ((x)&0x40)
313
314 #define ISIS_MASK_TLV_EXTD_IP6_IE(x) ((x)&0x40)
315 #define ISIS_MASK_TLV_EXTD_IP6_SUBTLV(x) ((x)&0x20)
316
317 #define ISIS_LSP_TLV_METRIC_SUPPORTED(x) ((x)&0x80)
318 #define ISIS_LSP_TLV_METRIC_IE(x) ((x)&0x40)
319 #define ISIS_LSP_TLV_METRIC_UPDOWN(x) ((x)&0x80)
320 #define ISIS_LSP_TLV_METRIC_VALUE(x) ((x)&0x3f)
321
322 #define ISIS_MASK_TLV_SHARED_RISK_GROUP(x) ((x)&0x1)
323
324 static struct tok isis_mt_values[] = {
325 { 0, "IPv4 unicast"},
326 { 1, "In-Band Management"},
327 { 2, "IPv6 unicast"},
328 { 3, "Multicast"},
329 { 4095, "Development, Experimental or Proprietary"},
330 { 0, NULL }
331 };
332
333 static struct tok isis_iih_circuit_type_values[] = {
334 { 1, "Level 1 only"},
335 { 2, "Level 2 only"},
336 { 3, "Level 1, Level 2"},
337 { 0, NULL}
338 };
339
340 #define ISIS_LSP_TYPE_UNUSED0 0
341 #define ISIS_LSP_TYPE_LEVEL_1 1
342 #define ISIS_LSP_TYPE_UNUSED2 2
343 #define ISIS_LSP_TYPE_LEVEL_2 3
344
345 static struct tok isis_lsp_istype_values[] = {
346 { ISIS_LSP_TYPE_UNUSED0, "Unused 0x0 (invalid)"},
347 { ISIS_LSP_TYPE_LEVEL_1, "L1 IS"},
348 { ISIS_LSP_TYPE_UNUSED2, "Unused 0x2 (invalid)"},
349 { ISIS_LSP_TYPE_LEVEL_2, "L1L2 IS"},
350 { 0, NULL }
351 };
352
353 /*
354 * Katz's point to point adjacency TLV uses codes to tell us the state of
355 * the remote adjacency. Enumerate them.
356 */
357
358 #define ISIS_PTP_ADJ_UP 0
359 #define ISIS_PTP_ADJ_INIT 1
360 #define ISIS_PTP_ADJ_DOWN 2
361
362 static struct tok isis_ptp_adjancey_values[] = {
363 { ISIS_PTP_ADJ_UP, "Up" },
364 { ISIS_PTP_ADJ_INIT, "Initializing" },
365 { ISIS_PTP_ADJ_DOWN, "Down" },
366 { 0, NULL}
367 };
368
369 struct isis_tlv_ptp_adj {
370 u_int8_t adjacency_state;
371 u_int8_t extd_local_circuit_id[4];
372 u_int8_t neighbor_sysid[SYSTEM_ID_LEN];
373 u_int8_t neighbor_extd_local_circuit_id[4];
374 };
375
376 static int osi_cksum(const u_int8_t *, u_int);
377 static int clnp_print(const u_int8_t *, u_int);
378 static void esis_print(const u_int8_t *, u_int);
379 static int isis_print(const u_int8_t *, u_int);
380
381 struct isis_metric_block {
382 u_int8_t metric_default;
383 u_int8_t metric_delay;
384 u_int8_t metric_expense;
385 u_int8_t metric_error;
386 };
387
388 struct isis_tlv_is_reach {
389 struct isis_metric_block isis_metric_block;
390 u_int8_t neighbor_nodeid[NODE_ID_LEN];
391 };
392
393 struct isis_tlv_es_reach {
394 struct isis_metric_block isis_metric_block;
395 u_int8_t neighbor_sysid[SYSTEM_ID_LEN];
396 };
397
398 struct isis_tlv_ip_reach {
399 struct isis_metric_block isis_metric_block;
400 u_int8_t prefix[4];
401 u_int8_t mask[4];
402 };
403
404 static struct tok isis_is_reach_virtual_values[] = {
405 { 0, "IsNotVirtual"},
406 { 1, "IsVirtual"},
407 { 0, NULL }
408 };
409
410 static struct tok isis_restart_flag_values[] = {
411 { 0x1, "Restart Request"},
412 { 0x2, "Restart Acknowledgement"},
413 { 0, NULL }
414 };
415
416 struct isis_common_header {
417 u_int8_t nlpid;
418 u_int8_t fixed_len;
419 u_int8_t version; /* Protocol version */
420 u_int8_t id_length;
421 u_int8_t pdu_type; /* 3 MSbits are reserved */
422 u_int8_t pdu_version; /* Packet format version */
423 u_int8_t reserved;
424 u_int8_t max_area;
425 };
426
427 struct isis_iih_lan_header {
428 u_int8_t circuit_type;
429 u_int8_t source_id[SYSTEM_ID_LEN];
430 u_int8_t holding_time[2];
431 u_int8_t pdu_len[2];
432 u_int8_t priority;
433 u_int8_t lan_id[NODE_ID_LEN];
434 };
435
436 struct isis_iih_ptp_header {
437 u_int8_t circuit_type;
438 u_int8_t source_id[SYSTEM_ID_LEN];
439 u_int8_t holding_time[2];
440 u_int8_t pdu_len[2];
441 u_int8_t circuit_id;
442 };
443
444 struct isis_lsp_header {
445 u_int8_t pdu_len[2];
446 u_int8_t remaining_lifetime[2];
447 u_int8_t lsp_id[LSP_ID_LEN];
448 u_int8_t sequence_number[4];
449 u_int8_t checksum[2];
450 u_int8_t typeblock;
451 };
452
453 struct isis_csnp_header {
454 u_int8_t pdu_len[2];
455 u_int8_t source_id[NODE_ID_LEN];
456 u_int8_t start_lsp_id[LSP_ID_LEN];
457 u_int8_t end_lsp_id[LSP_ID_LEN];
458 };
459
460 struct isis_psnp_header {
461 u_int8_t pdu_len[2];
462 u_int8_t source_id[NODE_ID_LEN];
463 };
464
465 struct isis_tlv_lsp {
466 u_int8_t remaining_lifetime[2];
467 u_int8_t lsp_id[LSP_ID_LEN];
468 u_int8_t sequence_number[4];
469 u_int8_t checksum[2];
470 };
471
472 #define ISIS_COMMON_HEADER_SIZE (sizeof(struct isis_common_header))
473 #define ISIS_IIH_LAN_HEADER_SIZE (sizeof(struct isis_iih_lan_header))
474 #define ISIS_IIH_PTP_HEADER_SIZE (sizeof(struct isis_iih_ptp_header))
475 #define ISIS_LSP_HEADER_SIZE (sizeof(struct isis_lsp_header))
476 #define ISIS_CSNP_HEADER_SIZE (sizeof(struct isis_csnp_header))
477 #define ISIS_PSNP_HEADER_SIZE (sizeof(struct isis_psnp_header))
478
479 void isoclns_print(const u_int8_t *p, u_int length, u_int caplen)
480 {
481 const struct isis_common_header *header;
482
483 header = (const struct isis_common_header *)p;
484
485 if (caplen <= 1) { /* enough bytes on the wire ? */
486 printf("|OSI");
487 return;
488 }
489
490 if (eflag)
491 printf("OSI NLPID %s (0x%02x): ",
492 tok2str(nlpid_values,"Unknown",*p),
493 *p);
494
495 switch (*p) {
496
497 case NLPID_CLNP:
498 if (!clnp_print(p, length))
499 print_unknown_data(p,"\n\t",caplen);
500 break;
501
502 case NLPID_ESIS:
503 esis_print(p, length);
504 return;
505
506 case NLPID_ISIS:
507 if (!isis_print(p, length))
508 print_unknown_data(p,"\n\t",caplen);
509 break;
510
511 case NLPID_NULLNS:
512 (void)printf(", length: %u", length);
513 break;
514
515 case NLPID_Q933:
516 q933_print(p+1, length-1);
517 break;
518
519 case NLPID_IP:
520 ip_print(p+1, length-1);
521 break;
522
523 #ifdef INET6
524 case NLPID_IP6:
525 ip6_print(p+1, length-1);
526 break;
527 #endif
528
529 case NLPID_PPP:
530 ppp_print(p+1, length-1);
531 break;
532
533 default:
534 if (!eflag)
535 printf("OSI NLPID 0x%02x unknown",*p);
536 (void)printf(", length: %u", length);
537 if (caplen > 1)
538 print_unknown_data(p,"\n\t",caplen);
539 break;
540 }
541 }
542
543 #define CLNP_PDU_ER 1
544 #define CLNP_PDU_DT 28
545 #define CLNP_PDU_MD 29
546 #define CLNP_PDU_ERQ 30
547 #define CLNP_PDU_ERP 31
548
549 static struct tok clnp_pdu_values[] = {
550 { CLNP_PDU_ER, "Error Report"},
551 { CLNP_PDU_MD, "MD"},
552 { CLNP_PDU_DT, "Data"},
553 { CLNP_PDU_ERQ, "Echo Request"},
554 { CLNP_PDU_ERP, "Echo Response"},
555 { 0, NULL }
556 };
557
558 struct clnp_header_t {
559 u_int8_t nlpid;
560 u_int8_t length_indicator;
561 u_int8_t version;
562 u_int8_t lifetime; /* units of 500ms */
563 u_int8_t type;
564 u_int8_t segment_length[2];
565 u_int8_t cksum[2];
566 };
567
568 struct clnp_segment_header_t {
569 u_int8_t data_unit_id[2];
570 u_int8_t segment_offset[2];
571 u_int8_t total_length[2];
572 };
573
574 /*
575 * clnp_print
576 * Decode CLNP packets. Return 0 on error.
577 */
578
579 static int clnp_print (const u_int8_t *pptr, u_int length)
580 {
581 const u_int8_t *optr,*source_address,*dest_address;
582 u_int li,source_address_length,dest_address_length, clnp_pdu_type, clnp_flags;
583 const struct clnp_header_t *clnp_header;
584 const struct clnp_segment_header_t *clnp_segment_header;
585
586 clnp_header = (const struct clnp_header_t *) pptr;
587 TCHECK(*clnp_header);
588
589 li = clnp_header->length_indicator;
590 optr = pptr;
591
592 if (!eflag)
593 printf("CLNP");
594
595 /*
596 * Sanity checking of the header.
597 */
598
599 if (clnp_header->version != CLNP_VERSION) {
600 printf("version %d packet not supported", clnp_header->version);
601 return (0);
602 }
603
604 /* FIXME further header sanity checking */
605
606 clnp_pdu_type = clnp_header->type & CLNP_PDU_TYPE_MASK;
607 clnp_flags = clnp_header->type & CLNP_FLAG_MASK;
608
609 pptr += sizeof(struct clnp_header_t);
610 li -= sizeof(struct clnp_header_t);
611 dest_address_length = *pptr;
612 dest_address = pptr + 1;
613
614 pptr += (1 + dest_address_length);
615 li -= (1 + dest_address_length);
616 source_address_length = *pptr;
617 source_address = pptr +1;
618
619 pptr += (1 + source_address_length);
620 li -= (1 + source_address_length);
621
622 if (vflag < 1) {
623 printf("%s%s > %s, %s, length %u",
624 eflag ? "" : ", ",
625 isonsap_string(source_address, source_address_length),
626 isonsap_string(dest_address, dest_address_length),
627 tok2str(clnp_pdu_values,"unknown (%u)",clnp_pdu_type),
628 length);
629 return (1);
630 }
631 printf("%slength %u",eflag ? "" : ", ",length);
632
633 printf("\n\t%s PDU, hlen: %u, v: %u, lifetime: %u.%us, Segment PDU length: %u, checksum: 0x%04x ",
634 tok2str(clnp_pdu_values, "unknown (%u)",clnp_pdu_type),
635 clnp_header->length_indicator,
636 clnp_header->version,
637 clnp_header->lifetime/2,
638 (clnp_header->lifetime%2)*5,
639 EXTRACT_16BITS(clnp_header->segment_length),
640 EXTRACT_16BITS(clnp_header->cksum));
641
642 /* do not attempt to verify the checksum if it is zero */
643 if (EXTRACT_16BITS(clnp_header->cksum) == 0)
644 printf("(unverified)");
645 else printf("(%s)", osi_cksum(optr, li) ? "incorrect" : "correct");
646
647 printf("\n\tFlags [%s]",
648 bittok2str(clnp_flag_values,"none",clnp_flags));
649
650 printf("\n\tsource address (length %u): %s\n\tdest address (length %u): %s",
651 source_address_length,
652 isonsap_string(source_address, source_address_length),
653 dest_address_length,
654 isonsap_string(dest_address,dest_address_length));
655
656 if (clnp_flags & CLNP_SEGMENT_PART) {
657 clnp_segment_header = (const struct clnp_segment_header_t *) pptr;
658 printf("\n\tData Unit ID: 0x%04x, Segment Offset: %u, Total PDU Length: %u",
659 EXTRACT_16BITS(clnp_segment_header->data_unit_id),
660 EXTRACT_16BITS(clnp_segment_header->segment_offset),
661 EXTRACT_16BITS(clnp_segment_header->total_length));
662 pptr+=sizeof(const struct clnp_segment_header_t);
663 li-=sizeof(const struct clnp_segment_header_t);
664 }
665
666 /* now walk the options */
667 while (li >= 2) {
668 u_int op, opli;
669 const u_int8_t *tptr;
670
671 if (snapend - pptr < 2)
672 return (0);
673 if (li < 2) {
674 printf(", bad opts/li");
675 return (0);
676 }
677 op = *pptr++;
678 opli = *pptr++;
679 li -= 2;
680 if (opli > li) {
681 printf(", opt (%d) too long", op);
682 return (0);
683 }
684 li -= opli;
685 tptr = pptr;
686
687 if (snapend < pptr)
688 return(0);
689
690 printf("\n\t %s Option #%u, length %u, value: ",
691 tok2str(clnp_option_values,"Unknown",op),
692 op,
693 opli);
694
695 switch (op) {
696
697 case CLNP_OPTION_PRIORITY:
698 printf("%u", *tptr);
699 break;
700
701 /*
702 * FIXME those are the defined Options that lack a decoder
703 * you are welcome to contribute code ;-)
704 */
705
706 case CLNP_OPTION_DISCARD_REASON:
707
708 default:
709 print_unknown_data(tptr,"\n\t ",opli);
710 break;
711 }
712 if (vflag > 1)
713 print_unknown_data(pptr,"\n\t ",opli);
714 pptr += opli;
715 }
716
717 switch (clnp_pdu_type) {
718
719 case CLNP_PDU_ER:
720 case CLNP_PDU_DT:
721 case CLNP_PDU_MD:
722 case CLNP_PDU_ERQ:
723 case CLNP_PDU_ERP:
724
725 default:
726 /* dump the PDU specific data */
727 printf("\n\t undecoded non-header data");
728 print_unknown_data(optr+clnp_header->length_indicator,"\n\t ",length-clnp_header->length_indicator);
729
730 }
731
732 return (1);
733
734 trunc:
735 fputs("[|clnp]", stdout);
736 return (1);
737
738 }
739
740
741 #define ESIS_PDU_REDIRECT 6
742 #define ESIS_PDU_ESH 2
743 #define ESIS_PDU_ISH 4
744
745 static struct tok esis_pdu_values[] = {
746 { ESIS_PDU_REDIRECT, "redirect"},
747 { ESIS_PDU_ESH, "ESH"},
748 { ESIS_PDU_ISH, "ISH"},
749 { 0, NULL }
750 };
751
752 struct esis_header_t {
753 u_int8_t nlpid;
754 u_int8_t length_indicator;
755 u_int8_t version;
756 u_int8_t reserved;
757 u_int8_t type;
758 u_int8_t holdtime[2];
759 u_int8_t cksum[2];
760 };
761
762 static void
763 esis_print(const u_int8_t *pptr, u_int length)
764 {
765 const u_int8_t *optr;
766 u_int li,esis_pdu_type,source_address_length, source_address_number;
767 const struct esis_header_t *esis_header;
768
769 if (!eflag)
770 printf("ES-IS");
771
772 if (length <= 2) {
773 if (qflag)
774 printf("bad pkt!");
775 else
776 printf("no header at all!");
777 return;
778 }
779
780 esis_header = (const struct esis_header_t *) pptr;
781 li = esis_header->length_indicator;
782 optr = pptr;
783
784 /*
785 * Sanity checking of the header.
786 */
787
788 if (esis_header->nlpid != NLPID_ESIS) {
789 printf(" nlpid 0x%02x packet not supported", esis_header->nlpid);
790 return;
791 }
792
793 if (esis_header->version != ESIS_VERSION) {
794 printf(" version %d packet not supported", esis_header->version);
795 return;
796 }
797
798 if (li > length) {
799 printf(" length indicator(%d) > PDU size (%d)!", li, length);
800 return;
801 }
802
803 if (li < sizeof(struct esis_header_t) + 2) {
804 printf(" length indicator < min PDU size %d:", li);
805 while (--length != 0)
806 printf("%02X", *pptr++);
807 return;
808 }
809
810 esis_pdu_type = esis_header->type & ESIS_PDU_TYPE_MASK;
811
812 if (vflag < 1) {
813 printf("%s%s, length %u",
814 eflag ? "" : ", ",
815 tok2str(esis_pdu_values,"unknown type (%u)",esis_pdu_type),
816 length);
817 return;
818 } else
819 printf("%slength %u\n\t%s (%u)",
820 eflag ? "" : ", ",
821 length,
822 tok2str(esis_pdu_values,"unknown type: %u", esis_pdu_type),
823 esis_pdu_type);
824
825 printf(", v: %u%s", esis_header->version, esis_header->version == ESIS_VERSION ? "" : "unsupported" );
826 printf(", checksum: 0x%04x ", EXTRACT_16BITS(esis_header->cksum));
827 /* do not attempt to verify the checksum if it is zero */
828 if (EXTRACT_16BITS(esis_header->cksum) == 0)
829 printf("(unverified)");
830 else printf("(%s)", osi_cksum(pptr, li) ? "incorrect" : "correct");
831
832 printf(", holding time: %us, length indicator: %u",EXTRACT_16BITS(esis_header->holdtime),li);
833
834 if (vflag > 1)
835 print_unknown_data(optr,"\n\t",sizeof(struct esis_header_t));
836
837 pptr += sizeof(struct esis_header_t);
838 li -= sizeof(struct esis_header_t);
839
840 switch (esis_pdu_type) {
841 case ESIS_PDU_REDIRECT: {
842 const u_int8_t *dst, *snpa, *tptr;
843
844 dst = pptr; pptr += *pptr + 1;
845 if (pptr > snapend)
846 return;
847 printf("\n\t %s", isonsap_string(dst+1,*dst));
848 snpa = pptr; pptr += *pptr + 1;
849 tptr = pptr; pptr += *pptr + 1;
850 if (pptr > snapend)
851 return;
852
853 if (tptr[0] == 0)
854 printf("\n\t %s", etheraddr_string(&snpa[1]));
855 else
856 printf("\n\t %s", isonsap_string(tptr+1,*tptr));
857 break;
858 }
859
860 case ESIS_PDU_ESH:
861 source_address_number = *pptr;
862 pptr++;
863 li--;
864
865 printf("\n\t Number of Source Addresses: %u", source_address_number);
866
867 while (source_address_number > 0) {
868 source_address_length = *pptr;
869 printf("\n\t NET (length: %u): %s",
870 source_address_length,
871 isonsap_string(pptr+1,source_address_length));
872
873 pptr += source_address_length+1;
874 li -= source_address_length+1;
875 source_address_number--;
876 }
877
878 break;
879
880 case ESIS_PDU_ISH: {
881 source_address_length = *pptr;
882 printf("\n\t NET (length: %u): %s", source_address_length, isonsap_string(pptr+1, source_address_length));
883 pptr += source_address_length+1;
884 li -= source_address_length +1;
885 break;
886 }
887
888 default:
889 if (vflag <= 1) {
890 if (pptr < snapend)
891 print_unknown_data(pptr,"\n\t ",snapend-pptr);
892 }
893 return;
894 }
895
896 /* now walk the options */
897 while (li >= 2) {
898 u_int op, opli;
899 const u_int8_t *tptr;
900
901 if (snapend - pptr < 2)
902 return;
903 if (li < 2) {
904 printf(", bad opts/li");
905 return;
906 }
907 op = *pptr++;
908 opli = *pptr++;
909 li -= 2;
910 if (opli > li) {
911 printf(", opt (%d) too long", op);
912 return;
913 }
914 li -= opli;
915 tptr = pptr;
916
917 if (snapend < pptr)
918 return;
919
920 printf("\n\t %s Option #%u, length %u, value: ",
921 tok2str(esis_option_values,"Unknown",op),
922 op,
923 opli);
924
925 switch (op) {
926
927 case ESIS_OPTION_ES_CONF_TIME:
928 printf("%us", EXTRACT_16BITS(tptr));
929 break;
930
931
932 case ESIS_OPTION_PROTOCOLS:
933 while (opli>0) {
934 printf("%s (0x%02x)",
935 tok2str(nlpid_values,
936 "unknown",
937 *tptr),
938 *tptr);
939 if (opli>1) /* further NPLIDs ? - put comma */
940 printf(", ");
941 tptr++;
942 opli--;
943 }
944 break;
945
946 /*
947 * FIXME those are the defined Options that lack a decoder
948 * you are welcome to contribute code ;-)
949 */
950
951 case ESIS_OPTION_QOS_MAINTENANCE:
952 case ESIS_OPTION_SECURITY:
953 case ESIS_OPTION_PRIORITY:
954 case ESIS_OPTION_ADDRESS_MASK:
955 case ESIS_OPTION_SNPA_MASK:
956
957 default:
958 print_unknown_data(tptr,"\n\t ",opli);
959 break;
960 }
961 if (vflag > 1)
962 print_unknown_data(pptr,"\n\t ",opli);
963 pptr += opli;
964 }
965 }
966
967 /* shared routine for printing system, node and lsp-ids */
968 static char *
969 isis_print_id(const u_int8_t *cp, int id_len)
970 {
971 int i;
972 static char id[sizeof("xxxx.xxxx.xxxx.yy-zz")];
973 char *pos = id;
974
975 for (i = 1; i <= SYSTEM_ID_LEN; i++) {
976 snprintf(pos, sizeof(id) - (pos - id), "%02x", *cp++);
977 pos += strlen(pos);
978 if (i == 2 || i == 4)
979 *pos++ = '.';
980 }
981 if (id_len >= NODE_ID_LEN) {
982 snprintf(pos, sizeof(id) - (pos - id), ".%02x", *cp++);
983 pos += strlen(pos);
984 }
985 if (id_len == LSP_ID_LEN)
986 snprintf(pos, sizeof(id) - (pos - id), "-%02x", *cp);
987 return (id);
988 }
989
990 /* print the 4-byte metric block which is common found in the old-style TLVs */
991 static int
992 isis_print_metric_block (const struct isis_metric_block *isis_metric_block)
993 {
994 printf(", Default Metric: %d, %s",
995 ISIS_LSP_TLV_METRIC_VALUE(isis_metric_block->metric_default),
996 ISIS_LSP_TLV_METRIC_IE(isis_metric_block->metric_default) ? "External" : "Internal");
997 if (!ISIS_LSP_TLV_METRIC_SUPPORTED(isis_metric_block->metric_delay))
998 printf("\n\t\t Delay Metric: %d, %s",
999 ISIS_LSP_TLV_METRIC_VALUE(isis_metric_block->metric_delay),
1000 ISIS_LSP_TLV_METRIC_IE(isis_metric_block->metric_delay) ? "External" : "Internal");
1001 if (!ISIS_LSP_TLV_METRIC_SUPPORTED(isis_metric_block->metric_expense))
1002 printf("\n\t\t Expense Metric: %d, %s",
1003 ISIS_LSP_TLV_METRIC_VALUE(isis_metric_block->metric_expense),
1004 ISIS_LSP_TLV_METRIC_IE(isis_metric_block->metric_expense) ? "External" : "Internal");
1005 if (!ISIS_LSP_TLV_METRIC_SUPPORTED(isis_metric_block->metric_error))
1006 printf("\n\t\t Error Metric: %d, %s",
1007 ISIS_LSP_TLV_METRIC_VALUE(isis_metric_block->metric_error),
1008 ISIS_LSP_TLV_METRIC_IE(isis_metric_block->metric_error) ? "External" : "Internal");
1009
1010 return(1); /* everything is ok */
1011 }
1012
1013 static int
1014 isis_print_tlv_ip_reach (const u_int8_t *cp, const char *ident, int length)
1015 {
1016 int prefix_len;
1017 const struct isis_tlv_ip_reach *tlv_ip_reach;
1018
1019 tlv_ip_reach = (const struct isis_tlv_ip_reach *)cp;
1020
1021 while (length > 0) {
1022 if ((size_t)length < sizeof(*tlv_ip_reach)) {
1023 printf("short IPv4 Reachability (%d vs %lu)",
1024 length,
1025 (unsigned long)sizeof(*tlv_ip_reach));
1026 return (0);
1027 }
1028
1029 if (!TTEST(*tlv_ip_reach))
1030 return (0);
1031
1032 prefix_len = mask2plen(EXTRACT_32BITS(tlv_ip_reach->mask));
1033
1034 if (prefix_len == -1)
1035 printf("%sIPv4 prefix: %s mask %s",
1036 ident,
1037 ipaddr_string((tlv_ip_reach->prefix)),
1038 ipaddr_string((tlv_ip_reach->mask)));
1039 else
1040 printf("%sIPv4 prefix: %15s/%u",
1041 ident,
1042 ipaddr_string((tlv_ip_reach->prefix)),
1043 prefix_len);
1044
1045 printf(", Distribution: %s, Metric: %u, %s",
1046 ISIS_LSP_TLV_METRIC_UPDOWN(tlv_ip_reach->isis_metric_block.metric_default) ? "down" : "up",
1047 ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->isis_metric_block.metric_default),
1048 ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->isis_metric_block.metric_default) ? "External" : "Internal");
1049
1050 if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_ip_reach->isis_metric_block.metric_delay))
1051 printf("%s Delay Metric: %u, %s",
1052 ident,
1053 ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->isis_metric_block.metric_delay),
1054 ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->isis_metric_block.metric_delay) ? "External" : "Internal");
1055
1056 if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_ip_reach->isis_metric_block.metric_expense))
1057 printf("%s Expense Metric: %u, %s",
1058 ident,
1059 ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->isis_metric_block.metric_expense),
1060 ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->isis_metric_block.metric_expense) ? "External" : "Internal");
1061
1062 if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_ip_reach->isis_metric_block.metric_error))
1063 printf("%s Error Metric: %u, %s",
1064 ident,
1065 ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->isis_metric_block.metric_error),
1066 ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->isis_metric_block.metric_error) ? "External" : "Internal");
1067
1068 length -= sizeof(struct isis_tlv_ip_reach);
1069 tlv_ip_reach++;
1070 }
1071 return (1);
1072 }
1073
1074 /*
1075 * this is the common IP-REACH subTLV decoder it is called
1076 * from various EXTD-IP REACH TLVs (135,235,236,237)
1077 */
1078
1079 static int
1080 isis_print_ip_reach_subtlv (const u_int8_t *tptr,int subt,int subl,const char *ident) {
1081
1082 /* first lets see if we know the subTLVs name*/
1083 printf("%s%s subTLV #%u, length: %u",
1084 ident,
1085 tok2str(isis_ext_ip_reach_subtlv_values,
1086 "unknown",
1087 subt),
1088 subt,
1089 subl);
1090
1091 if (!TTEST2(*tptr,subl))
1092 goto trunctlv;
1093
1094 switch(subt) {
1095 case ISIS_SUBTLV_EXTD_IP_REACH_MGMT_PREFIX_COLOR: /* fall through */
1096 case ISIS_SUBTLV_EXTD_IP_REACH_ADMIN_TAG32:
1097 while (subl >= 4) {
1098 printf(", 0x%08x (=%u)",
1099 EXTRACT_32BITS(tptr),
1100 EXTRACT_32BITS(tptr));
1101 tptr+=4;
1102 subl-=4;
1103 }
1104 break;
1105 case ISIS_SUBTLV_EXTD_IP_REACH_ADMIN_TAG64:
1106 while (subl >= 8) {
1107 printf(", 0x%08x%08x",
1108 EXTRACT_32BITS(tptr),
1109 EXTRACT_32BITS(tptr+4));
1110 tptr+=8;
1111 subl-=8;
1112 }
1113 break;
1114 default:
1115 if(!print_unknown_data(tptr,"\n\t\t ",
1116 subl))
1117 return(0);
1118 break;
1119 }
1120 return(1);
1121
1122 trunctlv:
1123 printf("%spacket exceeded snapshot",ident);
1124 return(0);
1125 }
1126
1127 /*
1128 * this is the common IS-REACH subTLV decoder it is called
1129 * from isis_print_ext_is_reach()
1130 */
1131
1132 static int
1133 isis_print_is_reach_subtlv (const u_int8_t *tptr,int subt,int subl,const char *ident) {
1134
1135 int priority_level,bandwidth_constraint;
1136 union { /* int to float conversion buffer for several subTLVs */
1137 float f;
1138 u_int32_t i;
1139 } bw;
1140
1141 /* first lets see if we know the subTLVs name*/
1142 printf("%s%s subTLV #%u, length: %u",
1143 ident,
1144 tok2str(isis_ext_is_reach_subtlv_values,
1145 "unknown",
1146 subt),
1147 subt,
1148 subl);
1149
1150 if (!TTEST2(*tptr,subl))
1151 goto trunctlv;
1152
1153 switch(subt) {
1154 case ISIS_SUBTLV_EXT_IS_REACH_ADMIN_GROUP:
1155 case ISIS_SUBTLV_EXT_IS_REACH_LINK_LOCAL_REMOTE_ID:
1156 case ISIS_SUBTLV_EXT_IS_REACH_LINK_REMOTE_ID:
1157 if (subl >= 4) {
1158 printf(", 0x%08x", EXTRACT_32BITS(tptr));
1159 if (subl == 8) /* draft-ietf-isis-gmpls-extensions */
1160 printf(", 0x%08x", EXTRACT_32BITS(tptr+4));
1161 }
1162 break;
1163 case ISIS_SUBTLV_EXT_IS_REACH_IPV4_INTF_ADDR:
1164 case ISIS_SUBTLV_EXT_IS_REACH_IPV4_NEIGHBOR_ADDR:
1165 if (subl >= 4)
1166 printf(", %s", ipaddr_string(tptr));
1167 break;
1168 case ISIS_SUBTLV_EXT_IS_REACH_MAX_LINK_BW :
1169 case ISIS_SUBTLV_EXT_IS_REACH_RESERVABLE_BW:
1170 if (subl >= 4) {
1171 bw.i = EXTRACT_32BITS(tptr);
1172 printf(", %.3f Mbps", bw.f*8/1000000 );
1173 }
1174 break;
1175 case ISIS_SUBTLV_EXT_IS_REACH_UNRESERVED_BW :
1176 if (subl >= 32) {
1177 for (priority_level = 0; priority_level < 8; priority_level++) {
1178 bw.i = EXTRACT_32BITS(tptr);
1179 printf("%s priority level %d: %.3f Mbps",
1180 ident,
1181 priority_level,
1182 bw.f*8/1000000 );
1183 tptr+=4;
1184 }
1185 }
1186 break;
1187 case ISIS_SUBTLV_EXT_IS_REACH_DIFFSERV_TE:
1188 printf("%sBandwidth Constraints Model ID: %s (%u)",
1189 ident,
1190 tok2str(diffserv_te_bc_values, "unknown", *tptr),
1191 *tptr);
1192 tptr++;
1193 /* decode BCs until the subTLV ends */
1194 for (bandwidth_constraint = 0; bandwidth_constraint < (subl-1)/4; bandwidth_constraint++) {
1195 bw.i = EXTRACT_32BITS(tptr);
1196 printf("%s Bandwidth constraint %d: %.3f Mbps",
1197 ident,
1198 bandwidth_constraint,
1199 bw.f*8/1000000 );
1200 tptr+=4;
1201 }
1202 break;
1203 case ISIS_SUBTLV_EXT_IS_REACH_TE_METRIC:
1204 if (subl >= 3)
1205 printf(", %u", EXTRACT_24BITS(tptr));
1206 break;
1207 case ISIS_SUBTLV_EXT_IS_REACH_LINK_PROTECTION_TYPE:
1208 if (subl >= 2) {
1209 printf(", %s, Priority %u",
1210 bittok2str(gmpls_link_prot_values, "none", *tptr),
1211 *(tptr+1));
1212 }
1213 break;
1214 case ISIS_SUBTLV_EXT_IS_REACH_INTF_SW_CAP_DESCR:
1215 if (subl >= 36) {
1216 printf("%s Interface Switching Capability:%s",
1217 ident,
1218 tok2str(gmpls_switch_cap_values, "Unknown", *(tptr)));
1219 printf(", LSP Encoding: %s",
1220 tok2str(gmpls_encoding_values, "Unknown", *(tptr+1)));
1221 tptr+=4;
1222 printf("%s Max LSP Bandwidth:",ident);
1223 for (priority_level = 0; priority_level < 8; priority_level++) {
1224 bw.i = EXTRACT_32BITS(tptr);
1225 printf("%s priority level %d: %.3f Mbps",
1226 ident,
1227 priority_level,
1228 bw.f*8/1000000 );
1229 tptr+=4;
1230 }
1231 subl-=36;
1232 /* there is some optional stuff left to decode but this is as of yet
1233 not specified so just lets hexdump what is left */
1234 if(subl>0){
1235 if(!print_unknown_data(tptr,"\n\t\t ",
1236 subl-36))
1237 return(0);
1238 }
1239 }
1240 break;
1241 default:
1242 if(!print_unknown_data(tptr,"\n\t\t ",
1243 subl))
1244 return(0);
1245 break;
1246 }
1247 return(1);
1248
1249 trunctlv:
1250 printf("%spacket exceeded snapshot",ident);
1251 return(0);
1252 }
1253
1254
1255 /*
1256 * this is the common IS-REACH decoder it is called
1257 * from various EXTD-IS REACH style TLVs (22,24,222)
1258 */
1259
1260 static int
1261 isis_print_ext_is_reach (const u_int8_t *tptr,const char *ident, int tlv_type) {
1262
1263 char ident_buffer[20];
1264 int subtlv_type,subtlv_len,subtlv_sum_len;
1265 int proc_bytes = 0; /* how many bytes did we process ? */
1266
1267 if (!TTEST2(*tptr, NODE_ID_LEN))
1268 return(0);
1269
1270 printf("%sIS Neighbor: %s", ident, isis_print_id(tptr, NODE_ID_LEN));
1271 tptr+=(NODE_ID_LEN);
1272
1273 if (tlv_type != ISIS_TLV_IS_ALIAS_ID) { /* the Alias TLV Metric field is implicit 0 */
1274 if (!TTEST2(*tptr, 3)) /* and is therefore skipped */
1275 return(0);
1276 printf(", Metric: %d",EXTRACT_24BITS(tptr));
1277 tptr+=3;
1278 }
1279
1280 if (!TTEST2(*tptr, 1))
1281 return(0);
1282 subtlv_sum_len=*(tptr++); /* read out subTLV length */
1283 proc_bytes=NODE_ID_LEN+3+1;
1284 printf(", %ssub-TLVs present",subtlv_sum_len ? "" : "no ");
1285 if (subtlv_sum_len) {
1286 printf(" (%u)",subtlv_sum_len);
1287 while (subtlv_sum_len>0) {
1288 if (!TTEST2(*tptr,2))
1289 return(0);
1290 subtlv_type=*(tptr++);
1291 subtlv_len=*(tptr++);
1292 /* prepend the ident string */
1293 snprintf(ident_buffer, sizeof(ident_buffer), "%s ",ident);
1294 if(!isis_print_is_reach_subtlv(tptr,subtlv_type,subtlv_len,ident_buffer))
1295 return(0);
1296 tptr+=subtlv_len;
1297 subtlv_sum_len-=(subtlv_len+2);
1298 proc_bytes+=(subtlv_len+2);
1299 }
1300 }
1301 return(proc_bytes);
1302 }
1303
1304 /*
1305 * this is the common Multi Topology ID decoder
1306 * it is called from various MT-TLVs (222,229,235,237)
1307 */
1308
1309 static int
1310 isis_print_mtid (const u_int8_t *tptr,const char *ident) {
1311
1312 if (!TTEST2(*tptr, 2))
1313 return(0);
1314
1315 printf("%s%s",
1316 ident,
1317 tok2str(isis_mt_values,
1318 "Reserved for IETF Consensus",
1319 ISIS_MASK_MTID(EXTRACT_16BITS(tptr))));
1320
1321 printf(" Topology (0x%03x), Flags: [%s]",
1322 ISIS_MASK_MTID(EXTRACT_16BITS(tptr)),
1323 bittok2str(isis_mt_flag_values, "none",ISIS_MASK_MTFLAGS(EXTRACT_16BITS(tptr))));
1324
1325 return(2);
1326 }
1327
1328 /*
1329 * this is the common extended IP reach decoder
1330 * it is called from TLVs (135,235,236,237)
1331 * we process the TLV and optional subTLVs and return
1332 * the amount of processed bytes
1333 */
1334
1335 static int
1336 isis_print_extd_ip_reach (const u_int8_t *tptr, const char *ident, u_int16_t afi) {
1337
1338 char ident_buffer[20];
1339 u_int8_t prefix[16]; /* shared copy buffer for IPv4 and IPv6 prefixes */
1340 u_int metric, status_byte, bit_length, byte_length, sublen, processed, subtlvtype, subtlvlen;
1341
1342 if (!TTEST2(*tptr, 4))
1343 return (0);
1344 metric = EXTRACT_32BITS(tptr);
1345 processed=4;
1346 tptr+=4;
1347
1348 if (afi == IPV4) {
1349 if (!TTEST2(*tptr, 1)) /* fetch status byte */
1350 return (0);
1351 status_byte=*(tptr++);
1352 bit_length = status_byte&0x3f;
1353 processed++;
1354 #ifdef INET6
1355 } else if (afi == IPV6) {
1356 if (!TTEST2(*tptr, 1)) /* fetch status & prefix_len byte */
1357 return (0);
1358 status_byte=*(tptr++);
1359 bit_length=*(tptr++);
1360 processed+=2;
1361 #endif
1362 } else
1363 return (0); /* somebody is fooling us */
1364
1365 byte_length = (bit_length + 7) / 8; /* prefix has variable length encoding */
1366
1367 if (!TTEST2(*tptr, byte_length))
1368 return (0);
1369 memset(prefix, 0, 16); /* clear the copy buffer */
1370 memcpy(prefix,tptr,byte_length); /* copy as much as is stored in the TLV */
1371 tptr+=byte_length;
1372 processed+=byte_length;
1373
1374 if (afi == IPV4)
1375 printf("%sIPv4 prefix: %15s/%u",
1376 ident,
1377 ipaddr_string(prefix),
1378 bit_length);
1379 #ifdef INET6
1380 if (afi == IPV6)
1381 printf("%sIPv6 prefix: %s/%u",
1382 ident,
1383 ip6addr_string(prefix),
1384 bit_length);
1385 #endif
1386
1387 printf(", Distribution: %s, Metric: %u",
1388 ISIS_MASK_TLV_EXTD_IP_UPDOWN(status_byte) ? "down" : "up",
1389 metric);
1390
1391 if (afi == IPV4 && ISIS_MASK_TLV_EXTD_IP_SUBTLV(status_byte))
1392 printf(", sub-TLVs present");
1393 #ifdef INET6
1394 if (afi == IPV6)
1395 printf(", %s%s",
1396 ISIS_MASK_TLV_EXTD_IP6_IE(status_byte) ? "External" : "Internal",
1397 ISIS_MASK_TLV_EXTD_IP6_SUBTLV(status_byte) ? ", sub-TLVs present" : "");
1398 #endif
1399
1400 if ((ISIS_MASK_TLV_EXTD_IP_SUBTLV(status_byte) && afi == IPV4) ||
1401 (ISIS_MASK_TLV_EXTD_IP6_SUBTLV(status_byte) && afi == IPV6)) {
1402 /* assume that one prefix can hold more
1403 than one subTLV - therefore the first byte must reflect
1404 the aggregate bytecount of the subTLVs for this prefix
1405 */
1406 if (!TTEST2(*tptr, 1))
1407 return (0);
1408 sublen=*(tptr++);
1409 processed+=sublen+1;
1410 printf(" (%u)",sublen); /* print out subTLV length */
1411
1412 while (sublen>0) {
1413 if (!TTEST2(*tptr,2))
1414 return (0);
1415 subtlvtype=*(tptr++);
1416 subtlvlen=*(tptr++);
1417 /* prepend the ident string */
1418 snprintf(ident_buffer, sizeof(ident_buffer), "%s ",ident);
1419 if(!isis_print_ip_reach_subtlv(tptr,subtlvtype,subtlvlen,ident_buffer))
1420 return(0);
1421 tptr+=subtlvlen;
1422 sublen-=(subtlvlen+2);
1423 }
1424 }
1425 return (processed);
1426 }
1427
1428 /*
1429 * isis_print
1430 * Decode IS-IS packets. Return 0 on error.
1431 */
1432
1433 static int isis_print (const u_int8_t *p, u_int length)
1434 {
1435 const struct isis_common_header *isis_header;
1436
1437 const struct isis_iih_lan_header *header_iih_lan;
1438 const struct isis_iih_ptp_header *header_iih_ptp;
1439 const struct isis_lsp_header *header_lsp;
1440 const struct isis_csnp_header *header_csnp;
1441 const struct isis_psnp_header *header_psnp;
1442
1443 const struct isis_tlv_lsp *tlv_lsp;
1444 const struct isis_tlv_ptp_adj *tlv_ptp_adj;
1445 const struct isis_tlv_is_reach *tlv_is_reach;
1446 const struct isis_tlv_es_reach *tlv_es_reach;
1447
1448 u_int8_t pdu_type, max_area, id_length, tlv_type, tlv_len, tmp, alen, lan_alen, prefix_len;
1449 u_int8_t ext_is_len, ext_ip_len, mt_len;
1450 const u_int8_t *optr, *pptr, *tptr;
1451 u_short packet_len,pdu_len;
1452 u_int i,vendor_id;
1453
1454 packet_len=length;
1455 optr = p; /* initialize the _o_riginal pointer to the packet start -
1456 need it for parsing the checksum TLV */
1457 isis_header = (const struct isis_common_header *)p;
1458 TCHECK(*isis_header);
1459 pptr = p+(ISIS_COMMON_HEADER_SIZE);
1460 header_iih_lan = (const struct isis_iih_lan_header *)pptr;
1461 header_iih_ptp = (const struct isis_iih_ptp_header *)pptr;
1462 header_lsp = (const struct isis_lsp_header *)pptr;
1463 header_csnp = (const struct isis_csnp_header *)pptr;
1464 header_psnp = (const struct isis_psnp_header *)pptr;
1465
1466 if (!eflag)
1467 printf("IS-IS");
1468
1469 /*
1470 * Sanity checking of the header.
1471 */
1472
1473 if (isis_header->version != ISIS_VERSION) {
1474 printf("version %d packet not supported", isis_header->version);
1475 return (0);
1476 }
1477
1478 if ((isis_header->id_length != SYSTEM_ID_LEN) && (isis_header->id_length != 0)) {
1479 printf("system ID length of %d is not supported",
1480 isis_header->id_length);
1481 return (0);
1482 }
1483
1484 if (isis_header->pdu_version != ISIS_VERSION) {
1485 printf("version %d packet not supported", isis_header->pdu_version);
1486 return (0);
1487 }
1488
1489 max_area = isis_header->max_area;
1490 switch(max_area) {
1491 case 0:
1492 max_area = 3; /* silly shit */
1493 break;
1494 case 255:
1495 printf("bad packet -- 255 areas");
1496 return (0);
1497 default:
1498 break;
1499 }
1500
1501 id_length = isis_header->id_length;
1502 switch(id_length) {
1503 case 0:
1504 id_length = 6; /* silly shit again */
1505 break;
1506 case 1: /* 1-8 are valid sys-ID lenghts */
1507 case 2:
1508 case 3:
1509 case 4:
1510 case 5:
1511 case 6:
1512 case 7:
1513 case 8:
1514 break;
1515 case 255:
1516 id_length = 0; /* entirely useless */
1517 break;
1518 default:
1519 break;
1520 }
1521
1522 /* toss any non 6-byte sys-ID len PDUs */
1523 if (id_length != 6 ) {
1524 printf("bad packet -- illegal sys-ID length (%u)", id_length);
1525 return (0);
1526 }
1527
1528 pdu_type=isis_header->pdu_type;
1529
1530 /* in non-verbose mode print the basic PDU Type plus PDU specific brief information*/
1531 if (vflag < 1) {
1532 printf("%s%s",
1533 eflag ? "" : ", ",
1534 tok2str(isis_pdu_values,"unknown PDU-Type %u",pdu_type));
1535
1536 switch (pdu_type) {
1537
1538 case ISIS_PDU_L1_LAN_IIH:
1539 case ISIS_PDU_L2_LAN_IIH:
1540 printf(", src-id %s",
1541 isis_print_id(header_iih_lan->source_id,SYSTEM_ID_LEN));
1542 printf(", lan-id %s, prio %u",
1543 isis_print_id(header_iih_lan->lan_id,NODE_ID_LEN),
1544 header_iih_lan->priority);
1545 break;
1546 case ISIS_PDU_PTP_IIH:
1547 printf(", src-id %s", isis_print_id(header_iih_ptp->source_id,SYSTEM_ID_LEN));
1548 break;
1549 case ISIS_PDU_L1_LSP:
1550 case ISIS_PDU_L2_LSP:
1551 printf(", lsp-id %s, seq 0x%08x, lifetime %5us",
1552 isis_print_id(header_lsp->lsp_id, LSP_ID_LEN),
1553 EXTRACT_32BITS(header_lsp->sequence_number),
1554 EXTRACT_16BITS(header_lsp->remaining_lifetime));
1555 break;
1556 case ISIS_PDU_L1_CSNP:
1557 case ISIS_PDU_L2_CSNP:
1558 printf(", src-id %s", isis_print_id(header_csnp->source_id,NODE_ID_LEN));
1559 break;
1560 case ISIS_PDU_L1_PSNP:
1561 case ISIS_PDU_L2_PSNP:
1562 printf(", src-id %s", isis_print_id(header_psnp->source_id,NODE_ID_LEN));
1563 break;
1564
1565 }
1566 printf(", length %u", length);
1567
1568 return(1);
1569 }
1570
1571 /* ok they seem to want to know everything - lets fully decode it */
1572 printf("%slength %u", eflag ? "" : ", ",length);
1573
1574 printf("\n\t%s, hlen: %u, v: %u, pdu-v: %u, sys-id-len: %u (%u), max-area: %u (%u)",
1575 tok2str(isis_pdu_values,
1576 "unknown, type %u",
1577 pdu_type),
1578 isis_header->fixed_len,
1579 isis_header->version,
1580 isis_header->pdu_version,
1581 id_length,
1582 isis_header->id_length,
1583 max_area,
1584 isis_header->max_area);
1585
1586 if (vflag > 1) {
1587 if(!print_unknown_data(optr,"\n\t",8)) /* provide the _o_riginal pointer */
1588 return(0); /* for optionally debugging the common header */
1589 }
1590
1591 switch (pdu_type) {
1592
1593 case ISIS_PDU_L1_LAN_IIH:
1594 case ISIS_PDU_L2_LAN_IIH:
1595 if (isis_header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE)) {
1596 printf(", bogus fixed header length %u should be %lu",
1597 isis_header->fixed_len, (unsigned long)ISIS_IIH_LAN_HEADER_SIZE);
1598 return (0);
1599 }
1600
1601 pdu_len=EXTRACT_16BITS(header_iih_lan->pdu_len);
1602 if (packet_len>pdu_len) {
1603 packet_len=pdu_len; /* do TLV decoding as long as it makes sense */
1604 length=pdu_len;
1605 }
1606
1607 TCHECK(*header_iih_lan);
1608 printf("\n\t source-id: %s, holding time: %us, Flags: [%s]",
1609 isis_print_id(header_iih_lan->source_id,SYSTEM_ID_LEN),
1610 EXTRACT_16BITS(header_iih_lan->holding_time),
1611 tok2str(isis_iih_circuit_type_values,
1612 "unknown circuit type 0x%02x",
1613 header_iih_lan->circuit_type));
1614
1615 printf("\n\t lan-id: %s, Priority: %u, PDU length: %u",
1616 isis_print_id(header_iih_lan->lan_id, NODE_ID_LEN),
1617 (header_iih_lan->priority) & ISIS_LAN_PRIORITY_MASK,
1618 pdu_len);
1619
1620 if (vflag > 1) {
1621 if(!print_unknown_data(pptr,"\n\t ",ISIS_IIH_LAN_HEADER_SIZE))
1622 return(0);
1623 }
1624
1625 packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE);
1626 pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE);
1627 break;
1628
1629 case ISIS_PDU_PTP_IIH:
1630 if (isis_header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE)) {
1631 printf(", bogus fixed header length %u should be %lu",
1632 isis_header->fixed_len, (unsigned long)ISIS_IIH_PTP_HEADER_SIZE);
1633 return (0);
1634 }
1635
1636 pdu_len=EXTRACT_16BITS(header_iih_ptp->pdu_len);
1637 if (packet_len>pdu_len) {
1638 packet_len=pdu_len; /* do TLV decoding as long as it makes sense */
1639 length=pdu_len;
1640 }
1641
1642 TCHECK(*header_iih_ptp);
1643 printf("\n\t source-id: %s, holding time: %us, Flags: [%s]",
1644 isis_print_id(header_iih_ptp->source_id,SYSTEM_ID_LEN),
1645 EXTRACT_16BITS(header_iih_ptp->holding_time),
1646 tok2str(isis_iih_circuit_type_values,
1647 "unknown circuit type 0x%02x",
1648 header_iih_ptp->circuit_type));
1649
1650 printf("\n\t circuit-id: 0x%02x, PDU length: %u",
1651 header_iih_ptp->circuit_id,
1652 pdu_len);
1653
1654 if (vflag > 1) {
1655 if(!print_unknown_data(pptr,"\n\t ",ISIS_IIH_PTP_HEADER_SIZE))
1656 return(0);
1657 }
1658
1659 packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE);
1660 pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE);
1661 break;
1662
1663 case ISIS_PDU_L1_LSP:
1664 case ISIS_PDU_L2_LSP:
1665 if (isis_header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE)) {
1666 printf(", bogus fixed header length %u should be %lu",
1667 isis_header->fixed_len, (unsigned long)ISIS_LSP_HEADER_SIZE);
1668 return (0);
1669 }
1670
1671 pdu_len=EXTRACT_16BITS(header_lsp->pdu_len);
1672 if (packet_len>pdu_len) {
1673 packet_len=pdu_len; /* do TLV decoding as long as it makes sense */
1674 length=pdu_len;
1675 }
1676
1677 TCHECK(*header_lsp);
1678 printf("\n\t lsp-id: %s, seq: 0x%08x, lifetime: %5us\n\t chksum: 0x%04x",
1679 isis_print_id(header_lsp->lsp_id, LSP_ID_LEN),
1680 EXTRACT_32BITS(header_lsp->sequence_number),
1681 EXTRACT_16BITS(header_lsp->remaining_lifetime),
1682 EXTRACT_16BITS(header_lsp->checksum));
1683
1684 /* if this is a purge do not attempt to verify the checksum */
1685 if ( EXTRACT_16BITS(header_lsp->remaining_lifetime) == 0 &&
1686 EXTRACT_16BITS(header_lsp->checksum) == 0)
1687 printf(" (purged)");
1688 else
1689 /* verify the checksum -
1690 * checking starts at the lsp-id field at byte position [12]
1691 * hence the length needs to be reduced by 12 bytes */
1692 printf(" (%s)", (osi_cksum((u_int8_t *)header_lsp->lsp_id, length-12)) ? "incorrect" : "correct");
1693
1694 printf(", PDU length: %u, Flags: [ %s",
1695 pdu_len,
1696 ISIS_MASK_LSP_OL_BIT(header_lsp->typeblock) ? "Overload bit set, " : "");
1697
1698 if (ISIS_MASK_LSP_ATT_BITS(header_lsp->typeblock)) {
1699 printf("%s", ISIS_MASK_LSP_ATT_DEFAULT_BIT(header_lsp->typeblock) ? "default " : "");
1700 printf("%s", ISIS_MASK_LSP_ATT_DELAY_BIT(header_lsp->typeblock) ? "delay " : "");
1701 printf("%s", ISIS_MASK_LSP_ATT_EXPENSE_BIT(header_lsp->typeblock) ? "expense " : "");
1702 printf("%s", ISIS_MASK_LSP_ATT_ERROR_BIT(header_lsp->typeblock) ? "error " : "");
1703 printf("ATT bit set, ");
1704 }
1705 printf("%s", ISIS_MASK_LSP_PARTITION_BIT(header_lsp->typeblock) ? "P bit set, " : "");
1706 printf("%s ]", tok2str(isis_lsp_istype_values,"Unknown(0x%x)",ISIS_MASK_LSP_ISTYPE_BITS(header_lsp->typeblock)));
1707
1708 if (vflag > 1) {
1709 if(!print_unknown_data(pptr,"\n\t ",ISIS_LSP_HEADER_SIZE))
1710 return(0);
1711 }
1712
1713 packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE);
1714 pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE);
1715 break;
1716
1717 case ISIS_PDU_L1_CSNP:
1718 case ISIS_PDU_L2_CSNP:
1719 if (isis_header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE)) {
1720 printf(", bogus fixed header length %u should be %lu",
1721 isis_header->fixed_len, (unsigned long)ISIS_CSNP_HEADER_SIZE);
1722 return (0);
1723 }
1724
1725 pdu_len=EXTRACT_16BITS(header_csnp->pdu_len);
1726 if (packet_len>pdu_len) {
1727 packet_len=pdu_len; /* do TLV decoding as long as it makes sense */
1728 length=pdu_len;
1729 }
1730
1731 TCHECK(*header_csnp);
1732 printf("\n\t source-id: %s, PDU length: %u",
1733 isis_print_id(header_csnp->source_id, NODE_ID_LEN),
1734 pdu_len);
1735 printf("\n\t start lsp-id: %s",
1736 isis_print_id(header_csnp->start_lsp_id, LSP_ID_LEN));
1737 printf("\n\t end lsp-id: %s",
1738 isis_print_id(header_csnp->end_lsp_id, LSP_ID_LEN));
1739
1740 if (vflag > 1) {
1741 if(!print_unknown_data(pptr,"\n\t ",ISIS_CSNP_HEADER_SIZE))
1742 return(0);
1743 }
1744
1745 packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE);
1746 pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE);
1747 break;
1748
1749 case ISIS_PDU_L1_PSNP:
1750 case ISIS_PDU_L2_PSNP:
1751 if (isis_header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE)) {
1752 printf("- bogus fixed header length %u should be %lu",
1753 isis_header->fixed_len, (unsigned long)ISIS_PSNP_HEADER_SIZE);
1754 return (0);
1755 }
1756
1757 pdu_len=EXTRACT_16BITS(header_psnp->pdu_len);
1758 if (packet_len>pdu_len) {
1759 packet_len=pdu_len; /* do TLV decoding as long as it makes sense */
1760 length=pdu_len;
1761 }
1762
1763 TCHECK(*header_psnp);
1764 printf("\n\t source-id: %s, PDU length: %u",
1765 isis_print_id(header_psnp->source_id, NODE_ID_LEN),
1766 pdu_len);
1767
1768 if (vflag > 1) {
1769 if(!print_unknown_data(pptr,"\n\t ",ISIS_PSNP_HEADER_SIZE))
1770 return(0);
1771 }
1772
1773 packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE);
1774 pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE);
1775 break;
1776
1777 default:
1778 if(!print_unknown_data(pptr,"\n\t ",length))
1779 return(0);
1780 return (0);
1781 }
1782
1783 /*
1784 * Now print the TLV's.
1785 */
1786
1787 while (packet_len >= 2) {
1788 if (pptr == snapend) {
1789 return (1);
1790 }
1791
1792 if (!TTEST2(*pptr, 2)) {
1793 printf("\n\t\t packet exceeded snapshot (%ld) bytes",
1794 (long)(pptr-snapend));
1795 return (1);
1796 }
1797 tlv_type = *pptr++;
1798 tlv_len = *pptr++;
1799 tmp =tlv_len; /* copy temporary len & pointer to packet data */
1800 tptr = pptr;
1801 packet_len -= 2;
1802 if (tlv_len > packet_len) {
1803 break;
1804 }
1805
1806 /* first lets see if we know the TLVs name*/
1807 printf("\n\t %s TLV #%u, length: %u",
1808 tok2str(isis_tlv_values,
1809 "unknown",
1810 tlv_type),
1811 tlv_type,
1812 tlv_len);
1813
1814 /* now check if we have a decoder otherwise do a hexdump at the end*/
1815 switch (tlv_type) {
1816 case ISIS_TLV_AREA_ADDR:
1817 if (!TTEST2(*tptr, 1))
1818 goto trunctlv;
1819 alen = *tptr++;
1820 while (tmp && alen < tmp) {
1821 printf("\n\t Area address (length: %u): %s",
1822 alen,
1823 isonsap_string(tptr,alen));
1824 tptr += alen;
1825 tmp -= alen + 1;
1826 if (tmp==0) /* if this is the last area address do not attemt a boundary check */
1827 break;
1828 if (!TTEST2(*tptr, 1))
1829 goto trunctlv;
1830 alen = *tptr++;
1831 }
1832 break;
1833 case ISIS_TLV_ISNEIGH:
1834 while (tmp >= ETHER_ADDR_LEN) {
1835 if (!TTEST2(*tptr, ETHER_ADDR_LEN))
1836 goto trunctlv;
1837 printf("\n\t SNPA: %s",isis_print_id(tptr,ETHER_ADDR_LEN));
1838 tmp -= ETHER_ADDR_LEN;
1839 tptr += ETHER_ADDR_LEN;
1840 }
1841 break;
1842
1843 case ISIS_TLV_ISNEIGH_VARLEN:
1844 if (!TTEST2(*tptr, 1))
1845 goto trunctlv;
1846 lan_alen = *tptr++; /* LAN adress length */
1847 tmp --;
1848 printf("\n\t LAN address length %u bytes ",lan_alen);
1849 while (tmp >= lan_alen) {
1850 if (!TTEST2(*tptr, lan_alen))
1851 goto trunctlv;
1852 printf("\n\t\tIS Neighbor: %s",isis_print_id(tptr,lan_alen));
1853 tmp -= lan_alen;
1854 tptr +=lan_alen;
1855 }
1856 break;
1857
1858 case ISIS_TLV_PADDING:
1859 break;
1860
1861 case ISIS_TLV_MT_IS_REACH:
1862 while (tmp >= 2+NODE_ID_LEN+3+1) {
1863 mt_len = isis_print_mtid(tptr, "\n\t ");
1864 if (mt_len == 0) /* did something go wrong ? */
1865 goto trunctlv;
1866 tptr+=mt_len;
1867 tmp-=mt_len;
1868
1869 ext_is_len = isis_print_ext_is_reach(tptr,"\n\t ",tlv_type);
1870 if (ext_is_len == 0) /* did something go wrong ? */
1871 goto trunctlv;
1872
1873 tmp-=ext_is_len;
1874 tptr+=ext_is_len;
1875 }
1876 break;
1877
1878 case ISIS_TLV_IS_ALIAS_ID:
1879 while (tmp >= NODE_ID_LEN+1) { /* is it worth attempting a decode ? */
1880 ext_is_len = isis_print_ext_is_reach(tptr,"\n\t ",tlv_type);
1881 if (ext_is_len == 0) /* did something go wrong ? */
1882 goto trunctlv;
1883 tmp-=ext_is_len;
1884 tptr+=ext_is_len;
1885 }
1886 break;
1887
1888 case ISIS_TLV_EXT_IS_REACH:
1889 while (tmp >= NODE_ID_LEN+3+1) { /* is it worth attempting a decode ? */
1890 ext_is_len = isis_print_ext_is_reach(tptr,"\n\t ",tlv_type);
1891 if (ext_is_len == 0) /* did something go wrong ? */
1892 goto trunctlv;
1893 tmp-=ext_is_len;
1894 tptr+=ext_is_len;
1895 }
1896 break;
1897 case ISIS_TLV_IS_REACH:
1898 if (!TTEST2(*tptr,1)) /* check if there is one byte left to read out the virtual flag */
1899 goto trunctlv;
1900 printf("\n\t %s",
1901 tok2str(isis_is_reach_virtual_values,
1902 "bogus virtual flag 0x%02x",
1903 *tptr++));
1904 tlv_is_reach = (const struct isis_tlv_is_reach *)tptr;
1905 while (tmp >= sizeof(struct isis_tlv_is_reach)) {
1906 if (!TTEST(*tlv_is_reach))
1907 goto trunctlv;
1908 printf("\n\t IS Neighbor: %s",
1909 isis_print_id(tlv_is_reach->neighbor_nodeid, NODE_ID_LEN));
1910 isis_print_metric_block(&tlv_is_reach->isis_metric_block);
1911 tmp -= sizeof(struct isis_tlv_is_reach);
1912 tlv_is_reach++;
1913 }
1914 break;
1915
1916 case ISIS_TLV_ESNEIGH:
1917 tlv_es_reach = (const struct isis_tlv_es_reach *)tptr;
1918 while (tmp >= sizeof(struct isis_tlv_es_reach)) {
1919 if (!TTEST(*tlv_es_reach))
1920 goto trunctlv;
1921 printf("\n\t ES Neighbor: %s",
1922 isis_print_id(tlv_es_reach->neighbor_sysid,SYSTEM_ID_LEN));
1923 isis_print_metric_block(&tlv_es_reach->isis_metric_block);
1924 tmp -= sizeof(struct isis_tlv_es_reach);
1925 tlv_es_reach++;
1926 }
1927 break;
1928
1929 /* those two TLVs share the same format */
1930 case ISIS_TLV_INT_IP_REACH:
1931 case ISIS_TLV_EXT_IP_REACH:
1932 if (!isis_print_tlv_ip_reach(pptr, "\n\t ", tlv_len))
1933 return (1);
1934 break;
1935
1936 case ISIS_TLV_EXTD_IP_REACH:
1937 while (tmp>0) {
1938 ext_ip_len = isis_print_extd_ip_reach(tptr, "\n\t ", IPV4);
1939 if (ext_ip_len == 0) /* did something go wrong ? */
1940 goto trunctlv;
1941 tptr+=ext_ip_len;
1942 tmp-=ext_ip_len;
1943 }
1944 break;
1945
1946 case ISIS_TLV_MT_IP_REACH:
1947 while (tmp>0) {
1948 mt_len = isis_print_mtid(tptr, "\n\t ");
1949 if (mt_len == 0) /* did something go wrong ? */
1950 goto trunctlv;
1951 tptr+=mt_len;
1952 tmp-=mt_len;
1953
1954 ext_ip_len = isis_print_extd_ip_reach(tptr, "\n\t ", IPV4);
1955 if (ext_ip_len == 0) /* did something go wrong ? */
1956 goto trunctlv;
1957 tptr+=ext_ip_len;
1958 tmp-=ext_ip_len;
1959 }
1960 break;
1961
1962 #ifdef INET6
1963 case ISIS_TLV_IP6_REACH:
1964 while (tmp>0) {
1965 ext_ip_len = isis_print_extd_ip_reach(tptr, "\n\t ", IPV6);
1966 if (ext_ip_len == 0) /* did something go wrong ? */
1967 goto trunctlv;
1968 tptr+=ext_ip_len;
1969 tmp-=ext_ip_len;
1970 }
1971 break;
1972
1973 case ISIS_TLV_MT_IP6_REACH:
1974 while (tmp>0) {
1975 mt_len = isis_print_mtid(tptr, "\n\t ");
1976 if (mt_len == 0) /* did something go wrong ? */
1977 goto trunctlv;
1978 tptr+=mt_len;
1979 tmp-=mt_len;
1980
1981 ext_ip_len = isis_print_extd_ip_reach(tptr, "\n\t ", IPV6);
1982 if (ext_ip_len == 0) /* did something go wrong ? */
1983 goto trunctlv;
1984 tptr+=ext_ip_len;
1985 tmp-=ext_ip_len;
1986 }
1987 break;
1988
1989 case ISIS_TLV_IP6ADDR:
1990 while (tmp>0) {
1991 if (!TTEST2(*tptr, 16))
1992 goto trunctlv;
1993
1994 printf("\n\t IPv6 interface address: %s",
1995 ip6addr_string(tptr));
1996
1997 tptr += 16;
1998 tmp -= 16;
1999 }
2000 break;
2001 #endif
2002 case ISIS_TLV_AUTH:
2003 if (!TTEST2(*tptr, 1))
2004 goto trunctlv;
2005
2006 printf("\n\t %s: ",
2007 tok2str(isis_subtlv_auth_values,
2008 "unknown Authentication type 0x%02x",
2009 *tptr));
2010
2011 switch (*tptr) {
2012 case ISIS_SUBTLV_AUTH_SIMPLE:
2013 for(i=1;i<tlv_len;i++) {
2014 if (!TTEST2(*(tptr+i), 1))
2015 goto trunctlv;
2016 printf("%c",*(tptr+i));
2017 }
2018 break;
2019 case ISIS_SUBTLV_AUTH_MD5:
2020 for(i=1;i<tlv_len;i++) {
2021 if (!TTEST2(*(tptr+i), 1))
2022 goto trunctlv;
2023 printf("%02x",*(tptr+i));
2024 }
2025 if (tlv_len != ISIS_SUBTLV_AUTH_MD5_LEN+1)
2026 printf(", (malformed subTLV) ");
2027 break;
2028 case ISIS_SUBTLV_AUTH_PRIVATE:
2029 default:
2030 if(!print_unknown_data(tptr+1,"\n\t\t ",tlv_len-1))
2031 return(0);
2032 break;
2033 }
2034 break;
2035
2036 case ISIS_TLV_PTP_ADJ:
2037 tlv_ptp_adj = (const struct isis_tlv_ptp_adj *)tptr;
2038 if(tmp>=1) {
2039 if (!TTEST2(*tptr, 1))
2040 goto trunctlv;
2041 printf("\n\t Adjacency State: %s (%u)",
2042 tok2str(isis_ptp_adjancey_values, "unknown", *tptr),
2043 *tptr);
2044 tmp--;
2045 }
2046 if(tmp>sizeof(tlv_ptp_adj->extd_local_circuit_id)) {
2047 if (!TTEST2(tlv_ptp_adj->extd_local_circuit_id,
2048 sizeof(tlv_ptp_adj->extd_local_circuit_id)))
2049 goto trunctlv;
2050 printf("\n\t Extended Local circuit-ID: 0x%08x",
2051 EXTRACT_32BITS(tlv_ptp_adj->extd_local_circuit_id));
2052 tmp-=sizeof(tlv_ptp_adj->extd_local_circuit_id);
2053 }
2054 if(tmp>=SYSTEM_ID_LEN) {
2055 if (!TTEST2(tlv_ptp_adj->neighbor_sysid, SYSTEM_ID_LEN))
2056 goto trunctlv;
2057 printf("\n\t Neighbor System-ID: %s",
2058 isis_print_id(tlv_ptp_adj->neighbor_sysid,SYSTEM_ID_LEN));
2059 tmp-=SYSTEM_ID_LEN;
2060 }
2061 if(tmp>=sizeof(tlv_ptp_adj->neighbor_extd_local_circuit_id)) {
2062 if (!TTEST2(tlv_ptp_adj->neighbor_extd_local_circuit_id,
2063 sizeof(tlv_ptp_adj->neighbor_extd_local_circuit_id)))
2064 goto trunctlv;
2065 printf("\n\t Neighbor Extended Local circuit-ID: 0x%08x",
2066 EXTRACT_32BITS(tlv_ptp_adj->neighbor_extd_local_circuit_id));
2067 }
2068 break;
2069
2070 case ISIS_TLV_PROTOCOLS:
2071 printf("\n\t NLPID(s): ");
2072 while (tmp>0) {
2073 if (!TTEST2(*(tptr), 1))
2074 goto trunctlv;
2075 printf("%s (0x%02x)",
2076 tok2str(nlpid_values,
2077 "unknown",
2078 *tptr),
2079 *tptr);
2080 if (tmp>1) /* further NPLIDs ? - put comma */
2081 printf(", ");
2082 tptr++;
2083 tmp--;
2084 }
2085 break;
2086
2087 case ISIS_TLV_TE_ROUTER_ID:
2088 if (!TTEST2(*pptr, 4))
2089 goto trunctlv;
2090 printf("\n\t Traffic Engineering Router ID: %s", ipaddr_string(pptr));
2091 break;
2092
2093 case ISIS_TLV_IPADDR:
2094 while (tmp>0) {
2095 if (!TTEST2(*tptr, 4))
2096 goto trunctlv;
2097 printf("\n\t IPv4 interface address: %s", ipaddr_string(tptr));
2098 tptr += 4;
2099 tmp -= 4;
2100 }
2101 break;
2102
2103 case ISIS_TLV_HOSTNAME:
2104 printf("\n\t Hostname: ");
2105 while (tmp>0) {
2106 if (!TTEST2(*tptr, 1))
2107 goto trunctlv;
2108 printf("%c",*tptr++);
2109 tmp--;
2110 }
2111 break;
2112
2113 case ISIS_TLV_SHARED_RISK_GROUP:
2114 if (!TTEST2(*tptr, NODE_ID_LEN))
2115 goto trunctlv;
2116 printf("\n\t IS Neighbor: %s", isis_print_id(tptr, NODE_ID_LEN));
2117 tptr+=(NODE_ID_LEN);
2118 tmp-=(NODE_ID_LEN);
2119
2120 if (!TTEST2(*tptr, 1))
2121 goto trunctlv;
2122 printf(", Flags: [%s]", ISIS_MASK_TLV_SHARED_RISK_GROUP(*tptr++) ? "numbered" : "unnumbered");
2123 tmp--;
2124
2125 if (!TTEST2(*tptr,4))
2126 goto trunctlv;
2127 printf("\n\t IPv4 interface address: %s", ipaddr_string(tptr));
2128 tptr+=4;
2129 tmp-=4;
2130
2131 if (!TTEST2(*tptr,4))
2132 goto trunctlv;
2133 printf("\n\t IPv4 neighbor address: %s", ipaddr_string(tptr));
2134 tptr+=4;
2135 tmp-=4;
2136
2137 while (tmp>0) {
2138 if (!TTEST2(*tptr, 4))
2139 goto trunctlv;
2140 printf("\n\t Link-ID: 0x%08x", EXTRACT_32BITS(tptr));
2141 tptr+=4;
2142 tmp-=4;
2143 }
2144 break;
2145
2146 case ISIS_TLV_LSP:
2147 tlv_lsp = (const struct isis_tlv_lsp *)tptr;
2148 while(tmp>0) {
2149 if (!TTEST((tlv_lsp->lsp_id)[LSP_ID_LEN-1]))
2150 goto trunctlv;
2151 printf("\n\t lsp-id: %s",
2152 isis_print_id(tlv_lsp->lsp_id, LSP_ID_LEN));
2153 if (!TTEST2(tlv_lsp->sequence_number, 4))
2154 goto trunctlv;
2155 printf(", seq: 0x%08x",EXTRACT_32BITS(tlv_lsp->sequence_number));
2156 if (!TTEST2(tlv_lsp->remaining_lifetime, 2))
2157 goto trunctlv;
2158 printf(", lifetime: %5ds",EXTRACT_16BITS(tlv_lsp->remaining_lifetime));
2159 if (!TTEST2(tlv_lsp->checksum, 2))
2160 goto trunctlv;
2161 printf(", chksum: 0x%04x",EXTRACT_16BITS(tlv_lsp->checksum));
2162 tmp-=sizeof(struct isis_tlv_lsp);
2163 tlv_lsp++;
2164 }
2165 break;
2166
2167 case ISIS_TLV_CHECKSUM:
2168 if (!TTEST2(*tptr, 2))
2169 goto trunctlv;
2170 printf("\n\t checksum: 0x%04x ", EXTRACT_16BITS(tptr));
2171 /* do not attempt to verify the checksum if it is zero
2172 * most likely a HMAC-MD5 TLV is also present and
2173 * to avoid conflicts the checksum TLV is zeroed.
2174 * see rfc3358 for details
2175 */
2176 if (EXTRACT_16BITS(tptr) == 0)
2177 printf("(unverified)");
2178 else printf("(%s)", osi_cksum(optr, length) ? "incorrect" : "correct");
2179 break;
2180
2181 case ISIS_TLV_MT_SUPPORTED:
2182 while (tmp>1) {
2183 /* length can only be a multiple of 2, otherwise there is
2184 something broken -> so decode down until length is 1 */
2185 if (tmp!=1) {
2186 mt_len = isis_print_mtid(tptr, "\n\t ");
2187 if (mt_len == 0) /* did something go wrong ? */
2188 goto trunctlv;
2189 tptr+=mt_len;
2190 tmp-=mt_len;
2191 } else {
2192 printf("\n\t malformed MT-ID");
2193 break;
2194 }
2195 }
2196 break;
2197
2198 case ISIS_TLV_RESTART_SIGNALING:
2199 if (!TTEST2(*tptr, 3))
2200 goto trunctlv;
2201 printf("\n\t Flags [%s], Remaining holding time %us",
2202 bittok2str(isis_restart_flag_values, "none", *tptr),
2203 EXTRACT_16BITS(tptr+1));
2204 tptr+=3;
2205 break;
2206
2207 case ISIS_TLV_IDRP_INFO:
2208 if (!TTEST2(*tptr, 1))
2209 goto trunctlv;
2210 printf("\n\t Inter-Domain Information Type: %s",
2211 tok2str(isis_subtlv_idrp_values,
2212 "Unknown (0x%02x)",
2213 *tptr));
2214 switch (*tptr++) {
2215 case ISIS_SUBTLV_IDRP_ASN:
2216 if (!TTEST2(*tptr, 2)) /* fetch AS number */
2217 goto trunctlv;
2218 printf("AS Number: %u",EXTRACT_16BITS(tptr));
2219 break;
2220 case ISIS_SUBTLV_IDRP_LOCAL:
2221 case ISIS_SUBTLV_IDRP_RES:
2222 default:
2223 if(!print_unknown_data(tptr,"\n\t ",tlv_len-1))
2224 return(0);
2225 break;
2226 }
2227 break;
2228
2229 case ISIS_TLV_LSP_BUFFERSIZE:
2230 if (!TTEST2(*tptr, 2))
2231 goto trunctlv;
2232 printf("\n\t LSP Buffersize: %u",EXTRACT_16BITS(tptr));
2233 break;
2234
2235 case ISIS_TLV_PART_DIS:
2236 while (tmp >= SYSTEM_ID_LEN) {
2237 if (!TTEST2(*tptr, SYSTEM_ID_LEN))
2238 goto trunctlv;
2239 printf("\n\t %s",isis_print_id(tptr,SYSTEM_ID_LEN));
2240 tptr+=SYSTEM_ID_LEN;
2241 tmp-=SYSTEM_ID_LEN;
2242 }
2243 break;
2244
2245 case ISIS_TLV_PREFIX_NEIGH:
2246 if (!TTEST2(*tptr, sizeof(struct isis_metric_block)))
2247 goto trunctlv;
2248 printf("\n\t Metric Block");
2249 isis_print_metric_block((const struct isis_metric_block *)tptr);
2250 tptr+=sizeof(struct isis_metric_block);
2251 tmp-=sizeof(struct isis_metric_block);
2252
2253 while(tmp>0) {
2254 if (!TTEST2(*tptr, 1))
2255 goto trunctlv;
2256 prefix_len=*tptr++; /* read out prefix length in semioctets*/
2257 tmp--;
2258 if (!TTEST2(*tptr, prefix_len/2))
2259 goto trunctlv;
2260 printf("\n\t\tAddress: %s/%u",
2261 isonsap_string(tptr,prefix_len/2),
2262 prefix_len*4);
2263 tptr+=prefix_len/2;
2264 tmp-=prefix_len/2;
2265 }
2266 break;
2267
2268 case ISIS_TLV_IIH_SEQNR:
2269 if (!TTEST2(*tptr, 4)) /* check if four bytes are on the wire */
2270 goto trunctlv;
2271 printf("\n\t Sequence number: %u", EXTRACT_32BITS(tptr) );
2272 break;
2273
2274 case ISIS_TLV_VENDOR_PRIVATE:
2275 if (!TTEST2(*tptr, 3)) /* check if enough byte for a full oui */
2276 goto trunctlv;
2277 vendor_id = EXTRACT_24BITS(tptr);
2278 printf("\n\t Vendor: %s (%u)",
2279 tok2str(oui_values,"Unknown",vendor_id),
2280 vendor_id);
2281 tptr+=3;
2282 tmp-=3;
2283 if (tmp > 0) /* hexdump the rest */
2284 if(!print_unknown_data(tptr,"\n\t\t",tmp))
2285 return(0);
2286 break;
2287 /*
2288 * FIXME those are the defined TLVs that lack a decoder
2289 * you are welcome to contribute code ;-)
2290 */
2291
2292 case ISIS_TLV_DECNET_PHASE4:
2293 case ISIS_TLV_LUCENT_PRIVATE:
2294 case ISIS_TLV_IPAUTH:
2295 case ISIS_TLV_NORTEL_PRIVATE1:
2296 case ISIS_TLV_NORTEL_PRIVATE2:
2297
2298 default:
2299 if (vflag <= 1) {
2300 if(!print_unknown_data(pptr,"\n\t\t",tlv_len))
2301 return(0);
2302 }
2303 break;
2304 }
2305 /* do we want to see an additionally hexdump ? */
2306 if (vflag> 1) {
2307 if(!print_unknown_data(pptr,"\n\t ",tlv_len))
2308 return(0);
2309 }
2310
2311 pptr += tlv_len;
2312 packet_len -= tlv_len;
2313 }
2314
2315 if (packet_len != 0) {
2316 printf("\n\t %u straggler bytes", packet_len);
2317 }
2318 return (1);
2319
2320 trunc:
2321 fputs("[|isis]", stdout);
2322 return (1);
2323
2324 trunctlv:
2325 printf("\n\t\t packet exceeded snapshot");
2326 return(1);
2327 }
2328
2329 /*
2330 * Verify the checksum. See 8473-1, Appendix C, section C.4.
2331 */
2332
2333 static int
2334 osi_cksum(const u_int8_t *tptr, u_int len)
2335 {
2336 int32_t c0 = 0, c1 = 0;
2337
2338 while ((int)--len >= 0) {
2339 c0 += *tptr++;
2340 c0 %= 255;
2341 c1 += c0;
2342 c1 %= 255;
2343 }
2344 return (c0 | c1);
2345 }