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