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