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