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