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