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