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