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