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