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