10f74e101Schristos /* 20f74e101Schristos * Copyright (c) 1992, 1993, 1994, 1995, 1996 30f74e101Schristos * The Regents of the University of California. All rights reserved. 40f74e101Schristos * 50f74e101Schristos * Redistribution and use in source and binary forms, with or without 60f74e101Schristos * modification, are permitted provided that: (1) source code distributions 70f74e101Schristos * retain the above copyright notice and this paragraph in its entirety, (2) 80f74e101Schristos * distributions including binary code include the above copyright notice and 90f74e101Schristos * this paragraph in its entirety in the documentation or other materials 100f74e101Schristos * provided with the distribution, and (3) all advertising materials mentioning 110f74e101Schristos * features or use of this software display the following acknowledgement: 120f74e101Schristos * ``This product includes software developed by the University of California, 130f74e101Schristos * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 140f74e101Schristos * the University nor the names of its contributors may be used to endorse 150f74e101Schristos * or promote products derived from this software without specific prior 160f74e101Schristos * written permission. 170f74e101Schristos * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 180f74e101Schristos * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 190f74e101Schristos * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 200f74e101Schristos * 210f74e101Schristos * Original code by Matt Thomas, Digital Equipment Corporation 220f74e101Schristos * 2372c96ff3Schristos * Extensively modified by Hannes Gredler (hannes@gredler.at) for more 240f74e101Schristos * complete IS-IS & CLNP support. 250f74e101Schristos */ 260f74e101Schristos 2711b3aaa1Schristos #include <sys/cdefs.h> 280f74e101Schristos #ifndef lint 29*26ba0b50Schristos __RCSID("$NetBSD: print-isoclns.c,v 1.11 2024/09/02 16:15:31 christos Exp $"); 300f74e101Schristos #endif 310f74e101Schristos 32dc860a36Sspz /* \summary: ISO CLNS, ESIS, and ISIS printer */ 33dc860a36Sspz 34c74ad251Schristos /* 35c74ad251Schristos * specification: 36c74ad251Schristos * 37c74ad251Schristos * CLNP: ISO 8473 (respective ITU version is at https://www.itu.int/rec/T-REC-X.233/en/) 38c74ad251Schristos * ES-IS: ISO 9542 39c74ad251Schristos * IS-IS: ISO 10589 40c74ad251Schristos */ 41c74ad251Schristos 42c74ad251Schristos #include <config.h> 430f74e101Schristos 44c74ad251Schristos #include "netdissect-stdinc.h" 450f74e101Schristos 460f74e101Schristos #include <string.h> 470f74e101Schristos 48fdccd7e4Schristos #include "netdissect.h" 490f74e101Schristos #include "addrtoname.h" 500f74e101Schristos #include "nlpid.h" 510f74e101Schristos #include "extract.h" 520f74e101Schristos #include "gmpls.h" 530f74e101Schristos #include "oui.h" 540f74e101Schristos #include "signature.h" 550f74e101Schristos 56fdccd7e4Schristos 570f74e101Schristos /* 580f74e101Schristos * IS-IS is defined in ISO 10589. Look there for protocol definitions. 590f74e101Schristos */ 600f74e101Schristos 61c74ad251Schristos #define SYSTEM_ID_LEN MAC_ADDR_LEN 62c74ad251Schristos #define NODE_ID_LEN (SYSTEM_ID_LEN+1) 63c74ad251Schristos #define LSP_ID_LEN (SYSTEM_ID_LEN+2) 640f74e101Schristos 650f74e101Schristos #define ISIS_VERSION 1 660f74e101Schristos #define ESIS_VERSION 1 670f74e101Schristos #define CLNP_VERSION 1 680f74e101Schristos 690f74e101Schristos #define ISIS_PDU_TYPE_MASK 0x1F 700f74e101Schristos #define ESIS_PDU_TYPE_MASK 0x1F 710f74e101Schristos #define CLNP_PDU_TYPE_MASK 0x1F 720f74e101Schristos #define CLNP_FLAG_MASK 0xE0 730f74e101Schristos #define ISIS_LAN_PRIORITY_MASK 0x7F 740f74e101Schristos 750f74e101Schristos #define ISIS_PDU_L1_LAN_IIH 15 760f74e101Schristos #define ISIS_PDU_L2_LAN_IIH 16 770f74e101Schristos #define ISIS_PDU_PTP_IIH 17 780f74e101Schristos #define ISIS_PDU_L1_LSP 18 790f74e101Schristos #define ISIS_PDU_L2_LSP 20 800f74e101Schristos #define ISIS_PDU_L1_CSNP 24 810f74e101Schristos #define ISIS_PDU_L2_CSNP 25 820f74e101Schristos #define ISIS_PDU_L1_PSNP 26 830f74e101Schristos #define ISIS_PDU_L2_PSNP 27 840f74e101Schristos 85870189d2Schristos static const struct tok isis_pdu_values[] = { 860f74e101Schristos { ISIS_PDU_L1_LAN_IIH, "L1 Lan IIH"}, 870f74e101Schristos { ISIS_PDU_L2_LAN_IIH, "L2 Lan IIH"}, 880f74e101Schristos { ISIS_PDU_PTP_IIH, "p2p IIH"}, 890f74e101Schristos { ISIS_PDU_L1_LSP, "L1 LSP"}, 900f74e101Schristos { ISIS_PDU_L2_LSP, "L2 LSP"}, 910f74e101Schristos { ISIS_PDU_L1_CSNP, "L1 CSNP"}, 920f74e101Schristos { ISIS_PDU_L2_CSNP, "L2 CSNP"}, 930f74e101Schristos { ISIS_PDU_L1_PSNP, "L1 PSNP"}, 940f74e101Schristos { ISIS_PDU_L2_PSNP, "L2 PSNP"}, 950f74e101Schristos { 0, NULL} 960f74e101Schristos }; 970f74e101Schristos 980f74e101Schristos /* 990f74e101Schristos * A TLV is a tuple of a type, length and a value and is normally used for 1000f74e101Schristos * encoding information in all sorts of places. This is an enumeration of 1010f74e101Schristos * the well known types. 1020f74e101Schristos * 1030f74e101Schristos * list taken from rfc3359 plus some memory from veterans ;-) 1040f74e101Schristos */ 1050f74e101Schristos 1060f74e101Schristos #define ISIS_TLV_AREA_ADDR 1 /* iso10589 */ 1070f74e101Schristos #define ISIS_TLV_IS_REACH 2 /* iso10589 */ 1080f74e101Schristos #define ISIS_TLV_ESNEIGH 3 /* iso10589 */ 1090f74e101Schristos #define ISIS_TLV_PART_DIS 4 /* iso10589 */ 1100f74e101Schristos #define ISIS_TLV_PREFIX_NEIGH 5 /* iso10589 */ 1110f74e101Schristos #define ISIS_TLV_ISNEIGH 6 /* iso10589 */ 112c74ad251Schristos #define ISIS_TLV_INSTANCE_ID 7 /* rfc8202 */ 1130f74e101Schristos #define ISIS_TLV_PADDING 8 /* iso10589 */ 1140f74e101Schristos #define ISIS_TLV_LSP 9 /* iso10589 */ 1150f74e101Schristos #define ISIS_TLV_AUTH 10 /* iso10589, rfc3567 */ 1160f74e101Schristos #define ISIS_TLV_CHECKSUM 12 /* rfc3358 */ 1170f74e101Schristos #define ISIS_TLV_CHECKSUM_MINLEN 2 118fdccd7e4Schristos #define ISIS_TLV_POI 13 /* rfc6232 */ 1190f74e101Schristos #define ISIS_TLV_LSP_BUFFERSIZE 14 /* iso10589 rev2 */ 120c74ad251Schristos #define ISIS_TLV_EXT_IS_REACH 22 /* rfc5305 */ 121c74ad251Schristos #define ISIS_TLV_IS_ALIAS_ID 24 /* rfc5311 */ 1220f74e101Schristos #define ISIS_TLV_DECNET_PHASE4 42 1230f74e101Schristos #define ISIS_TLV_LUCENT_PRIVATE 66 1240f74e101Schristos #define ISIS_TLV_INT_IP_REACH 128 /* rfc1195, rfc2966 */ 1250f74e101Schristos #define ISIS_TLV_PROTOCOLS 129 /* rfc1195 */ 1260f74e101Schristos #define ISIS_TLV_EXT_IP_REACH 130 /* rfc1195, rfc2966 */ 1270f74e101Schristos #define ISIS_TLV_IDRP_INFO 131 /* rfc1195 */ 1280f74e101Schristos #define ISIS_TLV_IPADDR 132 /* rfc1195 */ 1290f74e101Schristos #define ISIS_TLV_IPAUTH 133 /* rfc1195 */ 130c74ad251Schristos #define ISIS_TLV_TE_ROUTER_ID 134 /* rfc5305 */ 131c74ad251Schristos #define ISIS_TLV_EXTD_IP_REACH 135 /* rfc5305 */ 1320f74e101Schristos #define ISIS_TLV_HOSTNAME 137 /* rfc2763 */ 1330f74e101Schristos #define ISIS_TLV_SHARED_RISK_GROUP 138 /* draft-ietf-isis-gmpls-extensions */ 134870189d2Schristos #define ISIS_TLV_MT_PORT_CAP 143 /* rfc6165 */ 135870189d2Schristos #define ISIS_TLV_MT_CAPABILITY 144 /* rfc6329 */ 1360f74e101Schristos #define ISIS_TLV_NORTEL_PRIVATE1 176 1370f74e101Schristos #define ISIS_TLV_NORTEL_PRIVATE2 177 1380f74e101Schristos #define ISIS_TLV_RESTART_SIGNALING 211 /* rfc3847 */ 1390f74e101Schristos #define ISIS_TLV_RESTART_SIGNALING_FLAGLEN 1 1400f74e101Schristos #define ISIS_TLV_RESTART_SIGNALING_HOLDTIMELEN 2 1410f74e101Schristos #define ISIS_TLV_MT_IS_REACH 222 /* draft-ietf-isis-wg-multi-topology-05 */ 1420f74e101Schristos #define ISIS_TLV_MT_SUPPORTED 229 /* draft-ietf-isis-wg-multi-topology-05 */ 1430f74e101Schristos #define ISIS_TLV_IP6ADDR 232 /* draft-ietf-isis-ipv6-02 */ 1440f74e101Schristos #define ISIS_TLV_MT_IP_REACH 235 /* draft-ietf-isis-wg-multi-topology-05 */ 1450f74e101Schristos #define ISIS_TLV_IP6_REACH 236 /* draft-ietf-isis-ipv6-02 */ 1460f74e101Schristos #define ISIS_TLV_MT_IP6_REACH 237 /* draft-ietf-isis-wg-multi-topology-05 */ 1470f74e101Schristos #define ISIS_TLV_PTP_ADJ 240 /* rfc3373 */ 1480f74e101Schristos #define ISIS_TLV_IIH_SEQNR 241 /* draft-shen-isis-iih-sequence-00 */ 149c74ad251Schristos #define ISIS_TLV_ROUTER_CAPABILITY 242 /* rfc7981 */ 1500f74e101Schristos #define ISIS_TLV_VENDOR_PRIVATE 250 /* draft-ietf-isis-experimental-tlv-01 */ 1510f74e101Schristos #define ISIS_TLV_VENDOR_PRIVATE_MINLEN 3 1520f74e101Schristos 153870189d2Schristos static const struct tok isis_tlv_values[] = { 1540f74e101Schristos { ISIS_TLV_AREA_ADDR, "Area address(es)"}, 1550f74e101Schristos { ISIS_TLV_IS_REACH, "IS Reachability"}, 1560f74e101Schristos { ISIS_TLV_ESNEIGH, "ES Neighbor(s)"}, 1570f74e101Schristos { ISIS_TLV_PART_DIS, "Partition DIS"}, 1580f74e101Schristos { ISIS_TLV_PREFIX_NEIGH, "Prefix Neighbors"}, 1590f74e101Schristos { ISIS_TLV_ISNEIGH, "IS Neighbor(s)"}, 160c74ad251Schristos { ISIS_TLV_INSTANCE_ID, "Instance Identifier"}, 1610f74e101Schristos { ISIS_TLV_PADDING, "Padding"}, 1620f74e101Schristos { ISIS_TLV_LSP, "LSP entries"}, 1630f74e101Schristos { ISIS_TLV_AUTH, "Authentication"}, 1640f74e101Schristos { ISIS_TLV_CHECKSUM, "Checksum"}, 165fdccd7e4Schristos { ISIS_TLV_POI, "Purge Originator Identifier"}, 1660f74e101Schristos { ISIS_TLV_LSP_BUFFERSIZE, "LSP Buffersize"}, 1670f74e101Schristos { ISIS_TLV_EXT_IS_REACH, "Extended IS Reachability"}, 1680f74e101Schristos { ISIS_TLV_IS_ALIAS_ID, "IS Alias ID"}, 1690f74e101Schristos { ISIS_TLV_DECNET_PHASE4, "DECnet Phase IV"}, 1700f74e101Schristos { ISIS_TLV_LUCENT_PRIVATE, "Lucent Proprietary"}, 1710f74e101Schristos { ISIS_TLV_INT_IP_REACH, "IPv4 Internal Reachability"}, 1720f74e101Schristos { ISIS_TLV_PROTOCOLS, "Protocols supported"}, 1730f74e101Schristos { ISIS_TLV_EXT_IP_REACH, "IPv4 External Reachability"}, 1740f74e101Schristos { ISIS_TLV_IDRP_INFO, "Inter-Domain Information Type"}, 1750f74e101Schristos { ISIS_TLV_IPADDR, "IPv4 Interface address(es)"}, 1760f74e101Schristos { ISIS_TLV_IPAUTH, "IPv4 authentication (deprecated)"}, 1770f74e101Schristos { ISIS_TLV_TE_ROUTER_ID, "Traffic Engineering Router ID"}, 1780f74e101Schristos { ISIS_TLV_EXTD_IP_REACH, "Extended IPv4 Reachability"}, 1790f74e101Schristos { ISIS_TLV_SHARED_RISK_GROUP, "Shared Risk Link Group"}, 180870189d2Schristos { ISIS_TLV_MT_PORT_CAP, "Multi-Topology-Aware Port Capability"}, 181870189d2Schristos { ISIS_TLV_MT_CAPABILITY, "Multi-Topology Capability"}, 1820f74e101Schristos { ISIS_TLV_NORTEL_PRIVATE1, "Nortel Proprietary"}, 1830f74e101Schristos { ISIS_TLV_NORTEL_PRIVATE2, "Nortel Proprietary"}, 1840f74e101Schristos { ISIS_TLV_HOSTNAME, "Hostname"}, 1850f74e101Schristos { ISIS_TLV_RESTART_SIGNALING, "Restart Signaling"}, 1860f74e101Schristos { ISIS_TLV_MT_IS_REACH, "Multi Topology IS Reachability"}, 1870f74e101Schristos { ISIS_TLV_MT_SUPPORTED, "Multi Topology"}, 1880f74e101Schristos { ISIS_TLV_IP6ADDR, "IPv6 Interface address(es)"}, 1890f74e101Schristos { ISIS_TLV_MT_IP_REACH, "Multi-Topology IPv4 Reachability"}, 1900f74e101Schristos { ISIS_TLV_IP6_REACH, "IPv6 reachability"}, 1910f74e101Schristos { ISIS_TLV_MT_IP6_REACH, "Multi-Topology IP6 Reachability"}, 1920f74e101Schristos { ISIS_TLV_PTP_ADJ, "Point-to-point Adjacency State"}, 1930f74e101Schristos { ISIS_TLV_IIH_SEQNR, "Hello PDU Sequence Number"}, 194c74ad251Schristos { ISIS_TLV_ROUTER_CAPABILITY, "IS-IS Router Capability"}, 1950f74e101Schristos { ISIS_TLV_VENDOR_PRIVATE, "Vendor Private"}, 1960f74e101Schristos { 0, NULL } 1970f74e101Schristos }; 1980f74e101Schristos 1990f74e101Schristos #define ESIS_OPTION_PROTOCOLS 129 2000f74e101Schristos #define ESIS_OPTION_QOS_MAINTENANCE 195 /* iso9542 */ 2010f74e101Schristos #define ESIS_OPTION_SECURITY 197 /* iso9542 */ 2020f74e101Schristos #define ESIS_OPTION_ES_CONF_TIME 198 /* iso9542 */ 2030f74e101Schristos #define ESIS_OPTION_PRIORITY 205 /* iso9542 */ 2040f74e101Schristos #define ESIS_OPTION_ADDRESS_MASK 225 /* iso9542 */ 2050f74e101Schristos #define ESIS_OPTION_SNPA_MASK 226 /* iso9542 */ 2060f74e101Schristos 207870189d2Schristos static const struct tok esis_option_values[] = { 2080f74e101Schristos { ESIS_OPTION_PROTOCOLS, "Protocols supported"}, 2090f74e101Schristos { ESIS_OPTION_QOS_MAINTENANCE, "QoS Maintenance" }, 2100f74e101Schristos { ESIS_OPTION_SECURITY, "Security" }, 2110f74e101Schristos { ESIS_OPTION_ES_CONF_TIME, "ES Configuration Time" }, 2120f74e101Schristos { ESIS_OPTION_PRIORITY, "Priority" }, 213*26ba0b50Schristos { ESIS_OPTION_ADDRESS_MASK, "Address Mask" }, 2140f74e101Schristos { ESIS_OPTION_SNPA_MASK, "SNPA Mask" }, 2150f74e101Schristos { 0, NULL } 2160f74e101Schristos }; 2170f74e101Schristos 2180f74e101Schristos #define CLNP_OPTION_DISCARD_REASON 193 2190f74e101Schristos #define CLNP_OPTION_QOS_MAINTENANCE 195 /* iso8473 */ 2200f74e101Schristos #define CLNP_OPTION_SECURITY 197 /* iso8473 */ 2210f74e101Schristos #define CLNP_OPTION_SOURCE_ROUTING 200 /* iso8473 */ 2220f74e101Schristos #define CLNP_OPTION_ROUTE_RECORDING 203 /* iso8473 */ 2230f74e101Schristos #define CLNP_OPTION_PADDING 204 /* iso8473 */ 2240f74e101Schristos #define CLNP_OPTION_PRIORITY 205 /* iso8473 */ 2250f74e101Schristos 226870189d2Schristos static const struct tok clnp_option_values[] = { 2270f74e101Schristos { CLNP_OPTION_DISCARD_REASON, "Discard Reason"}, 2280f74e101Schristos { CLNP_OPTION_PRIORITY, "Priority"}, 2290f74e101Schristos { CLNP_OPTION_QOS_MAINTENANCE, "QoS Maintenance"}, 2300f74e101Schristos { CLNP_OPTION_SECURITY, "Security"}, 2310f74e101Schristos { CLNP_OPTION_SOURCE_ROUTING, "Source Routing"}, 2320f74e101Schristos { CLNP_OPTION_ROUTE_RECORDING, "Route Recording"}, 2330f74e101Schristos { CLNP_OPTION_PADDING, "Padding"}, 2340f74e101Schristos { 0, NULL } 2350f74e101Schristos }; 2360f74e101Schristos 237870189d2Schristos static const struct tok clnp_option_rfd_class_values[] = { 2380f74e101Schristos { 0x0, "General"}, 2390f74e101Schristos { 0x8, "Address"}, 2400f74e101Schristos { 0x9, "Source Routeing"}, 2410f74e101Schristos { 0xa, "Lifetime"}, 2420f74e101Schristos { 0xb, "PDU Discarded"}, 2430f74e101Schristos { 0xc, "Reassembly"}, 2440f74e101Schristos { 0, NULL } 2450f74e101Schristos }; 2460f74e101Schristos 247870189d2Schristos static const struct tok clnp_option_rfd_general_values[] = { 2480f74e101Schristos { 0x0, "Reason not specified"}, 2490f74e101Schristos { 0x1, "Protocol procedure error"}, 2500f74e101Schristos { 0x2, "Incorrect checksum"}, 2510f74e101Schristos { 0x3, "PDU discarded due to congestion"}, 2520f74e101Schristos { 0x4, "Header syntax error (cannot be parsed)"}, 2530f74e101Schristos { 0x5, "Segmentation needed but not permitted"}, 2540f74e101Schristos { 0x6, "Incomplete PDU received"}, 2550f74e101Schristos { 0x7, "Duplicate option"}, 2560f74e101Schristos { 0, NULL } 2570f74e101Schristos }; 2580f74e101Schristos 259870189d2Schristos static const struct tok clnp_option_rfd_address_values[] = { 2600f74e101Schristos { 0x0, "Destination address unreachable"}, 2610f74e101Schristos { 0x1, "Destination address unknown"}, 2620f74e101Schristos { 0, NULL } 2630f74e101Schristos }; 2640f74e101Schristos 265870189d2Schristos static const struct tok clnp_option_rfd_source_routeing_values[] = { 2660f74e101Schristos { 0x0, "Unspecified source routeing error"}, 2670f74e101Schristos { 0x1, "Syntax error in source routeing field"}, 2680f74e101Schristos { 0x2, "Unknown address in source routeing field"}, 2690f74e101Schristos { 0x3, "Path not acceptable"}, 2700f74e101Schristos { 0, NULL } 2710f74e101Schristos }; 2720f74e101Schristos 273870189d2Schristos static const struct tok clnp_option_rfd_lifetime_values[] = { 2740f74e101Schristos { 0x0, "Lifetime expired while data unit in transit"}, 2750f74e101Schristos { 0x1, "Lifetime expired during reassembly"}, 2760f74e101Schristos { 0, NULL } 2770f74e101Schristos }; 2780f74e101Schristos 279870189d2Schristos static const struct tok clnp_option_rfd_pdu_discard_values[] = { 2800f74e101Schristos { 0x0, "Unsupported option not specified"}, 2810f74e101Schristos { 0x1, "Unsupported protocol version"}, 2820f74e101Schristos { 0x2, "Unsupported security option"}, 2830f74e101Schristos { 0x3, "Unsupported source routeing option"}, 2840f74e101Schristos { 0x4, "Unsupported recording of route option"}, 2850f74e101Schristos { 0, NULL } 2860f74e101Schristos }; 2870f74e101Schristos 288870189d2Schristos static const struct tok clnp_option_rfd_reassembly_values[] = { 2890f74e101Schristos { 0x0, "Reassembly interference"}, 2900f74e101Schristos { 0, NULL } 2910f74e101Schristos }; 2920f74e101Schristos 2930f74e101Schristos /* array of 16 error-classes */ 294870189d2Schristos static const struct tok *clnp_option_rfd_error_class[] = { 2950f74e101Schristos clnp_option_rfd_general_values, 2960f74e101Schristos NULL, 2970f74e101Schristos NULL, 2980f74e101Schristos NULL, 2990f74e101Schristos NULL, 3000f74e101Schristos NULL, 3010f74e101Schristos NULL, 3020f74e101Schristos NULL, 3030f74e101Schristos clnp_option_rfd_address_values, 3040f74e101Schristos clnp_option_rfd_source_routeing_values, 3050f74e101Schristos clnp_option_rfd_lifetime_values, 3060f74e101Schristos clnp_option_rfd_pdu_discard_values, 3070f74e101Schristos clnp_option_rfd_reassembly_values, 3080f74e101Schristos NULL, 3090f74e101Schristos NULL, 3100f74e101Schristos NULL 3110f74e101Schristos }; 3120f74e101Schristos 3130f74e101Schristos #define CLNP_OPTION_OPTION_QOS_MASK 0x3f 3140f74e101Schristos #define CLNP_OPTION_SCOPE_MASK 0xc0 3150f74e101Schristos #define CLNP_OPTION_SCOPE_SA_SPEC 0x40 3160f74e101Schristos #define CLNP_OPTION_SCOPE_DA_SPEC 0x80 3170f74e101Schristos #define CLNP_OPTION_SCOPE_GLOBAL 0xc0 3180f74e101Schristos 319870189d2Schristos static const struct tok clnp_option_scope_values[] = { 3200f74e101Schristos { CLNP_OPTION_SCOPE_SA_SPEC, "Source Address Specific"}, 3210f74e101Schristos { CLNP_OPTION_SCOPE_DA_SPEC, "Destination Address Specific"}, 3220f74e101Schristos { CLNP_OPTION_SCOPE_GLOBAL, "Globally unique"}, 3230f74e101Schristos { 0, NULL } 3240f74e101Schristos }; 3250f74e101Schristos 326870189d2Schristos static const struct tok clnp_option_sr_rr_values[] = { 3270f74e101Schristos { 0x0, "partial"}, 3280f74e101Schristos { 0x1, "complete"}, 3290f74e101Schristos { 0, NULL } 3300f74e101Schristos }; 3310f74e101Schristos 332870189d2Schristos static const struct tok clnp_option_sr_rr_string_values[] = { 3330f74e101Schristos { CLNP_OPTION_SOURCE_ROUTING, "source routing"}, 3340f74e101Schristos { CLNP_OPTION_ROUTE_RECORDING, "recording of route in progress"}, 3350f74e101Schristos { 0, NULL } 3360f74e101Schristos }; 3370f74e101Schristos 338870189d2Schristos static const struct tok clnp_option_qos_global_values[] = { 3390f74e101Schristos { 0x20, "reserved"}, 3400f74e101Schristos { 0x10, "sequencing vs. delay"}, 3410f74e101Schristos { 0x08, "congested"}, 3420f74e101Schristos { 0x04, "delay vs. cost"}, 3430f74e101Schristos { 0x02, "error vs. delay"}, 3440f74e101Schristos { 0x01, "error vs. cost"}, 3450f74e101Schristos { 0, NULL } 3460f74e101Schristos }; 3470f74e101Schristos 348c74ad251Schristos static const struct tok isis_tlv_router_capability_flags[] = { 349c74ad251Schristos { 0x01, "S bit"}, 350c74ad251Schristos { 0x02, "D bit"}, 351c74ad251Schristos { 0, NULL } 352c74ad251Schristos }; 353c74ad251Schristos 354c74ad251Schristos #define ISIS_SUBTLV_ROUTER_CAP_SR 2 /* rfc 8667 */ 355c74ad251Schristos 356c74ad251Schristos static const struct tok isis_router_capability_subtlv_values[] = { 357c74ad251Schristos { ISIS_SUBTLV_ROUTER_CAP_SR, "SR-Capabilities"}, 358c74ad251Schristos { 0, NULL } 359c74ad251Schristos }; 360c74ad251Schristos 361c74ad251Schristos static const struct tok isis_router_capability_sr_flags[] = { 362c74ad251Schristos { 0x80, "ipv4"}, 363c74ad251Schristos { 0x40, "ipv6"}, 364c74ad251Schristos { 0, NULL } 365c74ad251Schristos }; 366c74ad251Schristos 367c74ad251Schristos #define ISIS_SUBTLV_EXT_IS_REACH_ADMIN_GROUP 3 /* rfc5305 */ 3680f74e101Schristos #define ISIS_SUBTLV_EXT_IS_REACH_LINK_LOCAL_REMOTE_ID 4 /* rfc4205 */ 369c74ad251Schristos #define ISIS_SUBTLV_EXT_IS_REACH_LINK_REMOTE_ID 5 /* rfc5305 */ 370c74ad251Schristos #define ISIS_SUBTLV_EXT_IS_REACH_IPV4_INTF_ADDR 6 /* rfc5305 */ 371c74ad251Schristos #define ISIS_SUBTLV_EXT_IS_REACH_IPV4_NEIGHBOR_ADDR 8 /* rfc5305 */ 372c74ad251Schristos #define ISIS_SUBTLV_EXT_IS_REACH_MAX_LINK_BW 9 /* rfc5305 */ 373c74ad251Schristos #define ISIS_SUBTLV_EXT_IS_REACH_RESERVABLE_BW 10 /* rfc5305 */ 3740f74e101Schristos #define ISIS_SUBTLV_EXT_IS_REACH_UNRESERVED_BW 11 /* rfc4124 */ 3750f74e101Schristos #define ISIS_SUBTLV_EXT_IS_REACH_BW_CONSTRAINTS_OLD 12 /* draft-ietf-tewg-diff-te-proto-06 */ 376c74ad251Schristos #define ISIS_SUBTLV_EXT_IS_REACH_TE_METRIC 18 /* rfc5305 */ 3770f74e101Schristos #define ISIS_SUBTLV_EXT_IS_REACH_LINK_ATTRIBUTE 19 /* draft-ietf-isis-link-attr-01 */ 3780f74e101Schristos #define ISIS_SUBTLV_EXT_IS_REACH_LINK_PROTECTION_TYPE 20 /* rfc4205 */ 3790f74e101Schristos #define ISIS_SUBTLV_EXT_IS_REACH_INTF_SW_CAP_DESCR 21 /* rfc4205 */ 3800f74e101Schristos #define ISIS_SUBTLV_EXT_IS_REACH_BW_CONSTRAINTS 22 /* rfc4124 */ 381c74ad251Schristos #define ISIS_SUBTLV_EXT_IS_REACH_LAN_ADJ_SEGMENT_ID 32 /* rfc8667 */ 3820f74e101Schristos 383870189d2Schristos #define ISIS_SUBTLV_SPB_METRIC 29 /* rfc6329 */ 384870189d2Schristos 385870189d2Schristos static const struct tok isis_ext_is_reach_subtlv_values[] = { 3860f74e101Schristos { ISIS_SUBTLV_EXT_IS_REACH_ADMIN_GROUP, "Administrative groups" }, 3870f74e101Schristos { ISIS_SUBTLV_EXT_IS_REACH_LINK_LOCAL_REMOTE_ID, "Link Local/Remote Identifier" }, 3880f74e101Schristos { ISIS_SUBTLV_EXT_IS_REACH_LINK_REMOTE_ID, "Link Remote Identifier" }, 3890f74e101Schristos { ISIS_SUBTLV_EXT_IS_REACH_IPV4_INTF_ADDR, "IPv4 interface address" }, 3900f74e101Schristos { ISIS_SUBTLV_EXT_IS_REACH_IPV4_NEIGHBOR_ADDR, "IPv4 neighbor address" }, 3910f74e101Schristos { ISIS_SUBTLV_EXT_IS_REACH_MAX_LINK_BW, "Maximum link bandwidth" }, 3920f74e101Schristos { ISIS_SUBTLV_EXT_IS_REACH_RESERVABLE_BW, "Reservable link bandwidth" }, 3930f74e101Schristos { ISIS_SUBTLV_EXT_IS_REACH_UNRESERVED_BW, "Unreserved bandwidth" }, 3940f74e101Schristos { ISIS_SUBTLV_EXT_IS_REACH_TE_METRIC, "Traffic Engineering Metric" }, 3950f74e101Schristos { ISIS_SUBTLV_EXT_IS_REACH_LINK_ATTRIBUTE, "Link Attribute" }, 3960f74e101Schristos { ISIS_SUBTLV_EXT_IS_REACH_LINK_PROTECTION_TYPE, "Link Protection Type" }, 3970f74e101Schristos { ISIS_SUBTLV_EXT_IS_REACH_INTF_SW_CAP_DESCR, "Interface Switching Capability" }, 3980f74e101Schristos { ISIS_SUBTLV_EXT_IS_REACH_BW_CONSTRAINTS_OLD, "Bandwidth Constraints (old)" }, 3990f74e101Schristos { ISIS_SUBTLV_EXT_IS_REACH_BW_CONSTRAINTS, "Bandwidth Constraints" }, 400c74ad251Schristos { ISIS_SUBTLV_EXT_IS_REACH_LAN_ADJ_SEGMENT_ID, "LAN Adjacency Segment Identifier" }, 401870189d2Schristos { ISIS_SUBTLV_SPB_METRIC, "SPB Metric" }, 4020f74e101Schristos { 250, "Reserved for cisco specific extensions" }, 4030f74e101Schristos { 251, "Reserved for cisco specific extensions" }, 4040f74e101Schristos { 252, "Reserved for cisco specific extensions" }, 4050f74e101Schristos { 253, "Reserved for cisco specific extensions" }, 4060f74e101Schristos { 254, "Reserved for cisco specific extensions" }, 4070f74e101Schristos { 255, "Reserved for future expansion" }, 4080f74e101Schristos { 0, NULL } 4090f74e101Schristos }; 4100f74e101Schristos 4110f74e101Schristos #define ISIS_SUBTLV_EXTD_IP_REACH_ADMIN_TAG32 1 /* draft-ietf-isis-admin-tags-01 */ 4120f74e101Schristos #define ISIS_SUBTLV_EXTD_IP_REACH_ADMIN_TAG64 2 /* draft-ietf-isis-admin-tags-01 */ 413c74ad251Schristos #define ISIS_SUBTLV_EXTD_IP_REACH_PREFIX_SID 3 /* rfc8667 */ 4140f74e101Schristos #define ISIS_SUBTLV_EXTD_IP_REACH_MGMT_PREFIX_COLOR 117 /* draft-ietf-isis-wg-multi-topology-05 */ 4150f74e101Schristos 416870189d2Schristos static const struct tok isis_ext_ip_reach_subtlv_values[] = { 4170f74e101Schristos { ISIS_SUBTLV_EXTD_IP_REACH_ADMIN_TAG32, "32-Bit Administrative tag" }, 4180f74e101Schristos { ISIS_SUBTLV_EXTD_IP_REACH_ADMIN_TAG64, "64-Bit Administrative tag" }, 419c74ad251Schristos { ISIS_SUBTLV_EXTD_IP_REACH_PREFIX_SID, "Prefix SID" }, 4200f74e101Schristos { ISIS_SUBTLV_EXTD_IP_REACH_MGMT_PREFIX_COLOR, "Management Prefix Color" }, 4210f74e101Schristos { 0, NULL } 4220f74e101Schristos }; 4230f74e101Schristos 424c74ad251Schristos #define ISIS_PREFIX_SID_FLAG_R 0x80 /* rfc 8667 */ 425c74ad251Schristos #define ISIS_PREFIX_SID_FLAG_N 0x40 /* rfc 8667 */ 426c74ad251Schristos #define ISIS_PREFIX_SID_FLAG_P 0x20 /* rfc 8667 */ 427c74ad251Schristos #define ISIS_PREFIX_SID_FLAG_E 0x10 /* rfc 8667 */ 428c74ad251Schristos #define ISIS_PREFIX_SID_FLAG_V 0x08 /* rfc 8667 */ 429c74ad251Schristos #define ISIS_PREFIX_SID_FLAG_L 0x04 /* rfc 8667 */ 430c74ad251Schristos 431c74ad251Schristos static const struct tok prefix_sid_flag_values[] = { 432c74ad251Schristos { ISIS_PREFIX_SID_FLAG_R, "Readvertisement"}, 433c74ad251Schristos { ISIS_PREFIX_SID_FLAG_N, "Node"}, 434c74ad251Schristos { ISIS_PREFIX_SID_FLAG_P, "No-PHP"}, 435c74ad251Schristos { ISIS_PREFIX_SID_FLAG_E, "Explicit NULL"}, 436c74ad251Schristos { ISIS_PREFIX_SID_FLAG_V, "Value"}, 437c74ad251Schristos { ISIS_PREFIX_SID_FLAG_L, "Local"}, 438c74ad251Schristos { 0, NULL} 439c74ad251Schristos }; 440c74ad251Schristos 441c74ad251Schristos 442c74ad251Schristos /* rfc 8667 */ 443c74ad251Schristos static const struct tok prefix_sid_algo_values[] = { 444c74ad251Schristos { 0, "SPF"}, 445c74ad251Schristos { 1, "strict-SPF"}, 446c74ad251Schristos { 0, NULL} 447c74ad251Schristos }; 448c74ad251Schristos 449870189d2Schristos static const struct tok isis_subtlv_link_attribute_values[] = { 4500f74e101Schristos { 0x01, "Local Protection Available" }, 4510f74e101Schristos { 0x02, "Link excluded from local protection path" }, 4520f74e101Schristos { 0x04, "Local maintenance required"}, 4530f74e101Schristos { 0, NULL } 4540f74e101Schristos }; 4550f74e101Schristos 456c74ad251Schristos static const struct tok isis_lan_adj_sid_flag_values[] = { 457c74ad251Schristos { 0x80, "Address family IPv6" }, 458c74ad251Schristos { 0x40, "Backup" }, 459c74ad251Schristos { 0x20, "Value" }, 460c74ad251Schristos { 0x10, "Local significance" }, 461c74ad251Schristos { 0x08, "Set of adjacencies" }, 462c74ad251Schristos { 0x04, "Persistent" }, 463c74ad251Schristos { 0, NULL } 464c74ad251Schristos }; 465c74ad251Schristos 4660f74e101Schristos #define ISIS_SUBTLV_AUTH_SIMPLE 1 4670e9868baSchristos #define ISIS_SUBTLV_AUTH_GENERIC 3 /* rfc 5310 */ 4680f74e101Schristos #define ISIS_SUBTLV_AUTH_MD5 54 4690f74e101Schristos #define ISIS_SUBTLV_AUTH_MD5_LEN 16 4700f74e101Schristos #define ISIS_SUBTLV_AUTH_PRIVATE 255 4710f74e101Schristos 472870189d2Schristos static const struct tok isis_subtlv_auth_values[] = { 4730f74e101Schristos { ISIS_SUBTLV_AUTH_SIMPLE, "simple text password"}, 4740e9868baSchristos { ISIS_SUBTLV_AUTH_GENERIC, "Generic Crypto key-id"}, 4750f74e101Schristos { ISIS_SUBTLV_AUTH_MD5, "HMAC-MD5 password"}, 4760f74e101Schristos { ISIS_SUBTLV_AUTH_PRIVATE, "Routing Domain private password"}, 4770f74e101Schristos { 0, NULL } 4780f74e101Schristos }; 4790f74e101Schristos 4800f74e101Schristos #define ISIS_SUBTLV_IDRP_RES 0 4810f74e101Schristos #define ISIS_SUBTLV_IDRP_LOCAL 1 4820f74e101Schristos #define ISIS_SUBTLV_IDRP_ASN 2 4830f74e101Schristos 484870189d2Schristos static const struct tok isis_subtlv_idrp_values[] = { 4850f74e101Schristos { ISIS_SUBTLV_IDRP_RES, "Reserved"}, 4860f74e101Schristos { ISIS_SUBTLV_IDRP_LOCAL, "Routing-Domain Specific"}, 4870f74e101Schristos { ISIS_SUBTLV_IDRP_ASN, "AS Number Tag"}, 4880f74e101Schristos { 0, NULL} 4890f74e101Schristos }; 4900f74e101Schristos 491870189d2Schristos #define ISIS_SUBTLV_SPB_MCID 4 492870189d2Schristos #define ISIS_SUBTLV_SPB_DIGEST 5 493870189d2Schristos #define ISIS_SUBTLV_SPB_BVID 6 494870189d2Schristos 495870189d2Schristos #define ISIS_SUBTLV_SPB_INSTANCE 1 496870189d2Schristos #define ISIS_SUBTLV_SPBM_SI 3 497870189d2Schristos 498870189d2Schristos #define ISIS_SPB_MCID_LEN 51 499870189d2Schristos #define ISIS_SUBTLV_SPB_MCID_MIN_LEN 102 500870189d2Schristos #define ISIS_SUBTLV_SPB_DIGEST_MIN_LEN 33 501870189d2Schristos #define ISIS_SUBTLV_SPB_BVID_MIN_LEN 6 502870189d2Schristos #define ISIS_SUBTLV_SPB_INSTANCE_MIN_LEN 19 503870189d2Schristos #define ISIS_SUBTLV_SPB_INSTANCE_VLAN_TUPLE_LEN 8 504870189d2Schristos 505870189d2Schristos static const struct tok isis_mt_port_cap_subtlv_values[] = { 506870189d2Schristos { ISIS_SUBTLV_SPB_MCID, "SPB MCID" }, 507870189d2Schristos { ISIS_SUBTLV_SPB_DIGEST, "SPB Digest" }, 508870189d2Schristos { ISIS_SUBTLV_SPB_BVID, "SPB BVID" }, 509870189d2Schristos { 0, NULL } 510870189d2Schristos }; 511870189d2Schristos 512870189d2Schristos static const struct tok isis_mt_capability_subtlv_values[] = { 513870189d2Schristos { ISIS_SUBTLV_SPB_INSTANCE, "SPB Instance" }, 514870189d2Schristos { ISIS_SUBTLV_SPBM_SI, "SPBM Service Identifier and Unicast Address" }, 515870189d2Schristos { 0, NULL } 516870189d2Schristos }; 517870189d2Schristos 518870189d2Schristos struct isis_spb_mcid { 519c74ad251Schristos nd_uint8_t format_id; 520c74ad251Schristos nd_byte name[32]; 521c74ad251Schristos nd_uint16_t revision_lvl; 522c74ad251Schristos nd_byte digest[16]; 523870189d2Schristos }; 524870189d2Schristos 525870189d2Schristos struct isis_subtlv_spb_mcid { 526870189d2Schristos struct isis_spb_mcid mcid; 527870189d2Schristos struct isis_spb_mcid aux_mcid; 528870189d2Schristos }; 529870189d2Schristos 530870189d2Schristos struct isis_subtlv_spb_instance { 531c74ad251Schristos nd_byte cist_root_id[8]; 532c74ad251Schristos nd_uint32_t cist_external_root_path_cost; 533c74ad251Schristos nd_uint16_t bridge_priority; 534c74ad251Schristos nd_uint32_t spsourceid; 535c74ad251Schristos nd_uint8_t no_of_trees; 536870189d2Schristos }; 537870189d2Schristos 5380f74e101Schristos #define CLNP_SEGMENT_PART 0x80 5390f74e101Schristos #define CLNP_MORE_SEGMENTS 0x40 5400f74e101Schristos #define CLNP_REQUEST_ER 0x20 5410f74e101Schristos 542870189d2Schristos static const struct tok clnp_flag_values[] = { 5430f74e101Schristos { CLNP_SEGMENT_PART, "Segmentation permitted"}, 5440f74e101Schristos { CLNP_MORE_SEGMENTS, "more Segments"}, 5450f74e101Schristos { CLNP_REQUEST_ER, "request Error Report"}, 5460f74e101Schristos { 0, NULL} 5470f74e101Schristos }; 5480f74e101Schristos 549c74ad251Schristos #define ISIS_MASK_LSP_OL_BIT(x) (GET_U_1(x)&0x4) 550c74ad251Schristos #define ISIS_MASK_LSP_ISTYPE_BITS(x) (GET_U_1(x)&0x3) 551c74ad251Schristos #define ISIS_MASK_LSP_PARTITION_BIT(x) (GET_U_1(x)&0x80) 552c74ad251Schristos #define ISIS_MASK_LSP_ATT_BITS(x) (GET_U_1(x)&0x78) 553c74ad251Schristos #define ISIS_MASK_LSP_ATT_ERROR_BIT(x) (GET_U_1(x)&0x40) 554c74ad251Schristos #define ISIS_MASK_LSP_ATT_EXPENSE_BIT(x) (GET_U_1(x)&0x20) 555c74ad251Schristos #define ISIS_MASK_LSP_ATT_DELAY_BIT(x) (GET_U_1(x)&0x10) 556c74ad251Schristos #define ISIS_MASK_LSP_ATT_DEFAULT_BIT(x) (GET_U_1(x)&0x8) 5570f74e101Schristos 5580f74e101Schristos #define ISIS_MASK_MTID(x) ((x)&0x0fff) 5590f74e101Schristos #define ISIS_MASK_MTFLAGS(x) ((x)&0xf000) 5600f74e101Schristos 561870189d2Schristos static const struct tok isis_mt_flag_values[] = { 5620e9868baSchristos { 0x4000, "ATT bit set"}, 5630e9868baSchristos { 0x8000, "Overload bit set"}, 5640f74e101Schristos { 0, NULL} 5650f74e101Schristos }; 5660f74e101Schristos 5670f74e101Schristos #define ISIS_MASK_TLV_EXTD_IP_UPDOWN(x) ((x)&0x80) 5680f74e101Schristos #define ISIS_MASK_TLV_EXTD_IP_SUBTLV(x) ((x)&0x40) 5690f74e101Schristos 5700f74e101Schristos #define ISIS_MASK_TLV_EXTD_IP6_IE(x) ((x)&0x40) 5710f74e101Schristos #define ISIS_MASK_TLV_EXTD_IP6_SUBTLV(x) ((x)&0x20) 5720f74e101Schristos 573c74ad251Schristos #define ISIS_LSP_TLV_METRIC_SUPPORTED(x) (GET_U_1(x)&0x80) 574c74ad251Schristos #define ISIS_LSP_TLV_METRIC_IE(x) (GET_U_1(x)&0x40) 575c74ad251Schristos #define ISIS_LSP_TLV_METRIC_UPDOWN(x) (GET_U_1(x)&0x80) 576c74ad251Schristos #define ISIS_LSP_TLV_METRIC_VALUE(x) (GET_U_1(x)&0x3f) 5770f74e101Schristos 5780f74e101Schristos #define ISIS_MASK_TLV_SHARED_RISK_GROUP(x) ((x)&0x1) 5790f74e101Schristos 580870189d2Schristos static const struct tok isis_mt_values[] = { 5810f74e101Schristos { 0, "IPv4 unicast"}, 5820f74e101Schristos { 1, "In-Band Management"}, 5830f74e101Schristos { 2, "IPv6 unicast"}, 5840f74e101Schristos { 3, "Multicast"}, 5850f74e101Schristos { 4095, "Development, Experimental or Proprietary"}, 5860f74e101Schristos { 0, NULL } 5870f74e101Schristos }; 5880f74e101Schristos 589870189d2Schristos static const struct tok isis_iih_circuit_type_values[] = { 5900f74e101Schristos { 1, "Level 1 only"}, 5910f74e101Schristos { 2, "Level 2 only"}, 5920f74e101Schristos { 3, "Level 1, Level 2"}, 5930f74e101Schristos { 0, NULL} 5940f74e101Schristos }; 5950f74e101Schristos 5960f74e101Schristos #define ISIS_LSP_TYPE_UNUSED0 0 5970f74e101Schristos #define ISIS_LSP_TYPE_LEVEL_1 1 5980f74e101Schristos #define ISIS_LSP_TYPE_UNUSED2 2 5990f74e101Schristos #define ISIS_LSP_TYPE_LEVEL_2 3 6000f74e101Schristos 601870189d2Schristos static const struct tok isis_lsp_istype_values[] = { 6020f74e101Schristos { ISIS_LSP_TYPE_UNUSED0, "Unused 0x0 (invalid)"}, 6030f74e101Schristos { ISIS_LSP_TYPE_LEVEL_1, "L1 IS"}, 6040f74e101Schristos { ISIS_LSP_TYPE_UNUSED2, "Unused 0x2 (invalid)"}, 6050f74e101Schristos { ISIS_LSP_TYPE_LEVEL_2, "L2 IS"}, 6060f74e101Schristos { 0, NULL } 6070f74e101Schristos }; 6080f74e101Schristos 6090f74e101Schristos /* 6100f74e101Schristos * Katz's point to point adjacency TLV uses codes to tell us the state of 6110f74e101Schristos * the remote adjacency. Enumerate them. 6120f74e101Schristos */ 6130f74e101Schristos 6140f74e101Schristos #define ISIS_PTP_ADJ_UP 0 6150f74e101Schristos #define ISIS_PTP_ADJ_INIT 1 6160f74e101Schristos #define ISIS_PTP_ADJ_DOWN 2 6170f74e101Schristos 618*26ba0b50Schristos static const struct tok isis_ptp_adjacency_values[] = { 6190f74e101Schristos { ISIS_PTP_ADJ_UP, "Up" }, 6200f74e101Schristos { ISIS_PTP_ADJ_INIT, "Initializing" }, 6210f74e101Schristos { ISIS_PTP_ADJ_DOWN, "Down" }, 6220f74e101Schristos { 0, NULL} 6230f74e101Schristos }; 6240f74e101Schristos 6250f74e101Schristos struct isis_tlv_ptp_adj { 626c74ad251Schristos nd_uint8_t adjacency_state; 627c74ad251Schristos nd_uint32_t extd_local_circuit_id; 628c74ad251Schristos nd_byte neighbor_sysid[SYSTEM_ID_LEN]; 629c74ad251Schristos nd_uint32_t neighbor_extd_local_circuit_id; 6300f74e101Schristos }; 6310f74e101Schristos 63272c96ff3Schristos static void osi_print_cksum(netdissect_options *, const uint8_t *pptr, 63372c96ff3Schristos uint16_t checksum, int checksum_offset, u_int length); 634b3a00663Schristos static int clnp_print(netdissect_options *, const uint8_t *, u_int); 635b3a00663Schristos static void esis_print(netdissect_options *, const uint8_t *, u_int); 636b3a00663Schristos static int isis_print(netdissect_options *, const uint8_t *, u_int); 6370f74e101Schristos 6380f74e101Schristos struct isis_metric_block { 639c74ad251Schristos nd_uint8_t metric_default; 640c74ad251Schristos nd_uint8_t metric_delay; 641c74ad251Schristos nd_uint8_t metric_expense; 642c74ad251Schristos nd_uint8_t metric_error; 6430f74e101Schristos }; 6440f74e101Schristos 6450f74e101Schristos struct isis_tlv_is_reach { 6460f74e101Schristos struct isis_metric_block isis_metric_block; 647c74ad251Schristos nd_byte neighbor_nodeid[NODE_ID_LEN]; 6480f74e101Schristos }; 6490f74e101Schristos 6500f74e101Schristos struct isis_tlv_es_reach { 6510f74e101Schristos struct isis_metric_block isis_metric_block; 652c74ad251Schristos nd_byte neighbor_sysid[SYSTEM_ID_LEN]; 6530f74e101Schristos }; 6540f74e101Schristos 6550f74e101Schristos struct isis_tlv_ip_reach { 6560f74e101Schristos struct isis_metric_block isis_metric_block; 657c74ad251Schristos nd_ipv4 prefix; 658c74ad251Schristos nd_ipv4 mask; 6590f74e101Schristos }; 6600f74e101Schristos 661870189d2Schristos static const struct tok isis_is_reach_virtual_values[] = { 6620f74e101Schristos { 0, "IsNotVirtual"}, 6630f74e101Schristos { 1, "IsVirtual"}, 6640f74e101Schristos { 0, NULL } 6650f74e101Schristos }; 6660f74e101Schristos 667870189d2Schristos static const struct tok isis_restart_flag_values[] = { 6680f74e101Schristos { 0x1, "Restart Request"}, 6690f74e101Schristos { 0x2, "Restart Acknowledgement"}, 6700f74e101Schristos { 0x4, "Suppress adjacency advertisement"}, 6710f74e101Schristos { 0, NULL } 6720f74e101Schristos }; 6730f74e101Schristos 6740f74e101Schristos struct isis_common_header { 675c74ad251Schristos nd_uint8_t nlpid; 676c74ad251Schristos nd_uint8_t fixed_len; 677c74ad251Schristos nd_uint8_t version; /* Protocol version */ 678c74ad251Schristos nd_uint8_t id_length; 679c74ad251Schristos nd_uint8_t pdu_type; /* 3 MSbits are reserved */ 680c74ad251Schristos nd_uint8_t pdu_version; /* Packet format version */ 681c74ad251Schristos nd_byte reserved; 682c74ad251Schristos nd_uint8_t max_area; 6830f74e101Schristos }; 6840f74e101Schristos 6850f74e101Schristos struct isis_iih_lan_header { 686c74ad251Schristos nd_uint8_t circuit_type; 687c74ad251Schristos nd_byte source_id[SYSTEM_ID_LEN]; 688c74ad251Schristos nd_uint16_t holding_time; 689c74ad251Schristos nd_uint16_t pdu_len; 690c74ad251Schristos nd_uint8_t priority; 691c74ad251Schristos nd_byte lan_id[NODE_ID_LEN]; 6920f74e101Schristos }; 6930f74e101Schristos 6940f74e101Schristos struct isis_iih_ptp_header { 695c74ad251Schristos nd_uint8_t circuit_type; 696c74ad251Schristos nd_byte source_id[SYSTEM_ID_LEN]; 697c74ad251Schristos nd_uint16_t holding_time; 698c74ad251Schristos nd_uint16_t pdu_len; 699c74ad251Schristos nd_uint8_t circuit_id; 7000f74e101Schristos }; 7010f74e101Schristos 7020f74e101Schristos struct isis_lsp_header { 703c74ad251Schristos nd_uint16_t pdu_len; 704c74ad251Schristos nd_uint16_t remaining_lifetime; 705c74ad251Schristos nd_byte lsp_id[LSP_ID_LEN]; 706c74ad251Schristos nd_uint32_t sequence_number; 707c74ad251Schristos nd_uint16_t checksum; 708c74ad251Schristos nd_uint8_t typeblock; 7090f74e101Schristos }; 7100f74e101Schristos 7110f74e101Schristos struct isis_csnp_header { 712c74ad251Schristos nd_uint16_t pdu_len; 713c74ad251Schristos nd_byte source_id[NODE_ID_LEN]; 714c74ad251Schristos nd_byte start_lsp_id[LSP_ID_LEN]; 715c74ad251Schristos nd_byte end_lsp_id[LSP_ID_LEN]; 7160f74e101Schristos }; 7170f74e101Schristos 7180f74e101Schristos struct isis_psnp_header { 719c74ad251Schristos nd_uint16_t pdu_len; 720c74ad251Schristos nd_byte source_id[NODE_ID_LEN]; 7210f74e101Schristos }; 7220f74e101Schristos 7230f74e101Schristos struct isis_tlv_lsp { 724c74ad251Schristos nd_uint16_t remaining_lifetime; 725c74ad251Schristos nd_byte lsp_id[LSP_ID_LEN]; 726c74ad251Schristos nd_uint32_t sequence_number; 727c74ad251Schristos nd_uint16_t checksum; 7280f74e101Schristos }; 7290f74e101Schristos 7300f74e101Schristos #define ISIS_COMMON_HEADER_SIZE (sizeof(struct isis_common_header)) 7310f74e101Schristos #define ISIS_IIH_LAN_HEADER_SIZE (sizeof(struct isis_iih_lan_header)) 7320f74e101Schristos #define ISIS_IIH_PTP_HEADER_SIZE (sizeof(struct isis_iih_ptp_header)) 7330f74e101Schristos #define ISIS_LSP_HEADER_SIZE (sizeof(struct isis_lsp_header)) 7340f74e101Schristos #define ISIS_CSNP_HEADER_SIZE (sizeof(struct isis_csnp_header)) 7350f74e101Schristos #define ISIS_PSNP_HEADER_SIZE (sizeof(struct isis_psnp_header)) 7360f74e101Schristos 737fdccd7e4Schristos void 738c74ad251Schristos isoclns_print(netdissect_options *ndo, const u_char *p, u_int length) 7390f74e101Schristos { 740c74ad251Schristos ndo->ndo_protocol = "isoclns"; 7410f74e101Schristos 742b3a00663Schristos if (ndo->ndo_eflag) 743c74ad251Schristos ND_PRINT("OSI NLPID %s (0x%02x): ", 744c74ad251Schristos tok2str(nlpid_values, "Unknown", GET_U_1(p)), 745c74ad251Schristos GET_U_1(p)); 7460f74e101Schristos 747c74ad251Schristos switch (GET_U_1(p)) { 7480f74e101Schristos 7490f74e101Schristos case NLPID_CLNP: 750b3a00663Schristos if (!clnp_print(ndo, p, length)) 75172c96ff3Schristos print_unknown_data(ndo, p, "\n\t", length); 7520f74e101Schristos break; 7530f74e101Schristos 7540f74e101Schristos case NLPID_ESIS: 755b3a00663Schristos esis_print(ndo, p, length); 7560f74e101Schristos return; 7570f74e101Schristos 7580f74e101Schristos case NLPID_ISIS: 759b3a00663Schristos if (!isis_print(ndo, p, length)) 76072c96ff3Schristos print_unknown_data(ndo, p, "\n\t", length); 7610f74e101Schristos break; 7620f74e101Schristos 7630f74e101Schristos case NLPID_NULLNS: 764c74ad251Schristos ND_PRINT("%slength: %u", ndo->ndo_eflag ? "" : ", ", length); 7650f74e101Schristos break; 7660f74e101Schristos 7670f74e101Schristos case NLPID_Q933: 768b3a00663Schristos q933_print(ndo, p + 1, length - 1); 7690f74e101Schristos break; 7700f74e101Schristos 7710f74e101Schristos case NLPID_IP: 772b3a00663Schristos ip_print(ndo, p + 1, length - 1); 7730f74e101Schristos break; 7740f74e101Schristos 7750f74e101Schristos case NLPID_IP6: 776b3a00663Schristos ip6_print(ndo, p + 1, length - 1); 7770f74e101Schristos break; 7780f74e101Schristos 7790f74e101Schristos case NLPID_PPP: 780b3a00663Schristos ppp_print(ndo, p + 1, length - 1); 7810f74e101Schristos break; 7820f74e101Schristos 7830f74e101Schristos default: 784b3a00663Schristos if (!ndo->ndo_eflag) 785c74ad251Schristos ND_PRINT("OSI NLPID 0x%02x unknown", GET_U_1(p)); 786c74ad251Schristos ND_PRINT("%slength: %u", ndo->ndo_eflag ? "" : ", ", length); 78772c96ff3Schristos if (length > 1) 78872c96ff3Schristos print_unknown_data(ndo, p, "\n\t", length); 7890f74e101Schristos break; 7900f74e101Schristos } 7910f74e101Schristos } 7920f74e101Schristos 7930f74e101Schristos #define CLNP_PDU_ER 1 7940f74e101Schristos #define CLNP_PDU_DT 28 7950f74e101Schristos #define CLNP_PDU_MD 29 7960f74e101Schristos #define CLNP_PDU_ERQ 30 7970f74e101Schristos #define CLNP_PDU_ERP 31 7980f74e101Schristos 799870189d2Schristos static const struct tok clnp_pdu_values[] = { 8000f74e101Schristos { CLNP_PDU_ER, "Error Report"}, 8010f74e101Schristos { CLNP_PDU_MD, "MD"}, 8020f74e101Schristos { CLNP_PDU_DT, "Data"}, 8030f74e101Schristos { CLNP_PDU_ERQ, "Echo Request"}, 8040f74e101Schristos { CLNP_PDU_ERP, "Echo Response"}, 8050f74e101Schristos { 0, NULL } 8060f74e101Schristos }; 8070f74e101Schristos 8080f74e101Schristos struct clnp_header_t { 809c74ad251Schristos nd_uint8_t nlpid; 810c74ad251Schristos nd_uint8_t length_indicator; 811c74ad251Schristos nd_uint8_t version; 812c74ad251Schristos nd_uint8_t lifetime; /* units of 500ms */ 813c74ad251Schristos nd_uint8_t type; 814c74ad251Schristos nd_uint16_t segment_length; 815c74ad251Schristos nd_uint16_t cksum; 8160f74e101Schristos }; 8170f74e101Schristos 8180f74e101Schristos struct clnp_segment_header_t { 819c74ad251Schristos nd_uint16_t data_unit_id; 820c74ad251Schristos nd_uint16_t segment_offset; 821c74ad251Schristos nd_uint16_t total_length; 8220f74e101Schristos }; 8230f74e101Schristos 8240f74e101Schristos /* 8250f74e101Schristos * clnp_print 8260f74e101Schristos * Decode CLNP packets. Return 0 on error. 8270f74e101Schristos */ 8280f74e101Schristos 829b3a00663Schristos static int 830b3a00663Schristos clnp_print(netdissect_options *ndo, 831b3a00663Schristos const uint8_t *pptr, u_int length) 8320f74e101Schristos { 833b3a00663Schristos const uint8_t *optr,*source_address,*dest_address; 834c74ad251Schristos u_int li,li_remaining,tlen,nsap_offset,source_address_length,dest_address_length, clnp_pdu_type, clnp_flags; 8350f74e101Schristos const struct clnp_header_t *clnp_header; 8360f74e101Schristos const struct clnp_segment_header_t *clnp_segment_header; 837c74ad251Schristos uint8_t rfd_error,rfd_error_major,rfd_error_minor; 8380f74e101Schristos 839c74ad251Schristos ndo->ndo_protocol = "clnp"; 8400f74e101Schristos clnp_header = (const struct clnp_header_t *) pptr; 841c74ad251Schristos ND_TCHECK_SIZE(clnp_header); 8420f74e101Schristos 843c74ad251Schristos li = GET_U_1(clnp_header->length_indicator); 844c74ad251Schristos li_remaining = li; 8450f74e101Schristos optr = pptr; 8460f74e101Schristos 847b3a00663Schristos if (!ndo->ndo_eflag) 848c74ad251Schristos nd_print_protocol_caps(ndo); 8490f74e101Schristos 8500f74e101Schristos /* 8510f74e101Schristos * Sanity checking of the header. 8520f74e101Schristos */ 8530f74e101Schristos 854c74ad251Schristos if (GET_U_1(clnp_header->version) != CLNP_VERSION) { 855c74ad251Schristos ND_PRINT("version %u packet not supported", 856c74ad251Schristos GET_U_1(clnp_header->version)); 8570f74e101Schristos return (0); 8580f74e101Schristos } 8590f74e101Schristos 860dc860a36Sspz if (li > length) { 861c74ad251Schristos ND_PRINT(" length indicator(%u) > PDU size (%u)!", li, length); 862dc860a36Sspz return (0); 863dc860a36Sspz } 864dc860a36Sspz 865dc860a36Sspz if (li < sizeof(struct clnp_header_t)) { 866c74ad251Schristos ND_PRINT(" length indicator %u < min PDU size:", li); 867c74ad251Schristos while (pptr < ndo->ndo_snapend) { 868c74ad251Schristos ND_PRINT("%02X", GET_U_1(pptr)); 869c74ad251Schristos pptr++; 870c74ad251Schristos } 871dc860a36Sspz return (0); 872dc860a36Sspz } 873dc860a36Sspz 8740f74e101Schristos /* FIXME further header sanity checking */ 8750f74e101Schristos 876c74ad251Schristos clnp_pdu_type = GET_U_1(clnp_header->type) & CLNP_PDU_TYPE_MASK; 877c74ad251Schristos clnp_flags = GET_U_1(clnp_header->type) & CLNP_FLAG_MASK; 8780f74e101Schristos 8790f74e101Schristos pptr += sizeof(struct clnp_header_t); 880c74ad251Schristos li_remaining -= sizeof(struct clnp_header_t); 881dc860a36Sspz 882c74ad251Schristos if (li_remaining < 1) { 883c74ad251Schristos ND_PRINT("li < size of fixed part of CLNP header and addresses"); 884dc860a36Sspz return (0); 885dc860a36Sspz } 886c74ad251Schristos dest_address_length = GET_U_1(pptr); 887dc860a36Sspz pptr += 1; 888c74ad251Schristos li_remaining -= 1; 889c74ad251Schristos if (li_remaining < dest_address_length) { 890c74ad251Schristos ND_PRINT("li < size of fixed part of CLNP header and addresses"); 891dc860a36Sspz return (0); 892dc860a36Sspz } 893c74ad251Schristos ND_TCHECK_LEN(pptr, dest_address_length); 894dc860a36Sspz dest_address = pptr; 895dc860a36Sspz pptr += dest_address_length; 896c74ad251Schristos li_remaining -= dest_address_length; 8970f74e101Schristos 898c74ad251Schristos if (li_remaining < 1) { 899c74ad251Schristos ND_PRINT("li < size of fixed part of CLNP header and addresses"); 900dc860a36Sspz return (0); 901dc860a36Sspz } 902c74ad251Schristos source_address_length = GET_U_1(pptr); 903dc860a36Sspz pptr += 1; 904c74ad251Schristos li_remaining -= 1; 905c74ad251Schristos if (li_remaining < source_address_length) { 906c74ad251Schristos ND_PRINT("li < size of fixed part of CLNP header and addresses"); 907dc860a36Sspz return (0); 908dc860a36Sspz } 909c74ad251Schristos ND_TCHECK_LEN(pptr, source_address_length); 910dc860a36Sspz source_address = pptr; 911dc860a36Sspz pptr += source_address_length; 912c74ad251Schristos li_remaining -= source_address_length; 9130f74e101Schristos 914b3a00663Schristos if (ndo->ndo_vflag < 1) { 915c74ad251Schristos ND_PRINT("%s%s > %s, %s, length %u", 916b3a00663Schristos ndo->ndo_eflag ? "" : ", ", 917c74ad251Schristos GET_ISONSAP_STRING(source_address, source_address_length), 918c74ad251Schristos GET_ISONSAP_STRING(dest_address, dest_address_length), 9190f74e101Schristos tok2str(clnp_pdu_values,"unknown (%u)",clnp_pdu_type), 920c74ad251Schristos length); 9210f74e101Schristos return (1); 9220f74e101Schristos } 923c74ad251Schristos ND_PRINT("%slength %u", ndo->ndo_eflag ? "" : ", ", length); 9240f74e101Schristos 925c74ad251Schristos ND_PRINT("\n\t%s PDU, hlen: %u, v: %u, lifetime: %u.%us, Segment PDU length: %u, checksum: 0x%04x", 9260f74e101Schristos tok2str(clnp_pdu_values, "unknown (%u)",clnp_pdu_type), 927c74ad251Schristos GET_U_1(clnp_header->length_indicator), 928c74ad251Schristos GET_U_1(clnp_header->version), 929c74ad251Schristos GET_U_1(clnp_header->lifetime)/2, 930c74ad251Schristos (GET_U_1(clnp_header->lifetime)%2)*5, 931c74ad251Schristos GET_BE_U_2(clnp_header->segment_length), 932c74ad251Schristos GET_BE_U_2(clnp_header->cksum)); 9330f74e101Schristos 934c74ad251Schristos osi_print_cksum(ndo, optr, GET_BE_U_2(clnp_header->cksum), 7, 935c74ad251Schristos GET_U_1(clnp_header->length_indicator)); 9360f74e101Schristos 937c74ad251Schristos ND_PRINT("\n\tFlags [%s]", 938c74ad251Schristos bittok2str(clnp_flag_values, "none", clnp_flags)); 9390f74e101Schristos 940c74ad251Schristos ND_PRINT("\n\tsource address (length %u): %s\n\tdest address (length %u): %s", 9410f74e101Schristos source_address_length, 942c74ad251Schristos GET_ISONSAP_STRING(source_address, source_address_length), 9430f74e101Schristos dest_address_length, 944c74ad251Schristos GET_ISONSAP_STRING(dest_address, dest_address_length)); 9450f74e101Schristos 9460f74e101Schristos if (clnp_flags & CLNP_SEGMENT_PART) { 947c74ad251Schristos if (li_remaining < sizeof(struct clnp_segment_header_t)) { 948c74ad251Schristos ND_PRINT("li < size of fixed part of CLNP header, addresses, and segment part"); 949dc860a36Sspz return (0); 950dc860a36Sspz } 9510f74e101Schristos clnp_segment_header = (const struct clnp_segment_header_t *) pptr; 952c74ad251Schristos ND_TCHECK_SIZE(clnp_segment_header); 953c74ad251Schristos ND_PRINT("\n\tData Unit ID: 0x%04x, Segment Offset: %u, Total PDU Length: %u", 954c74ad251Schristos GET_BE_U_2(clnp_segment_header->data_unit_id), 955c74ad251Schristos GET_BE_U_2(clnp_segment_header->segment_offset), 956c74ad251Schristos GET_BE_U_2(clnp_segment_header->total_length)); 957c74ad251Schristos pptr+=sizeof(struct clnp_segment_header_t); 958c74ad251Schristos li_remaining-=sizeof(struct clnp_segment_header_t); 9590f74e101Schristos } 9600f74e101Schristos 9610f74e101Schristos /* now walk the options */ 962c74ad251Schristos while (li_remaining != 0) { 9630f74e101Schristos u_int op, opli; 964b3a00663Schristos const uint8_t *tptr; 9650f74e101Schristos 966c74ad251Schristos if (li_remaining < 2) { 967c74ad251Schristos ND_PRINT(", bad opts/li"); 9680f74e101Schristos return (0); 9690f74e101Schristos } 970c74ad251Schristos op = GET_U_1(pptr); 971c74ad251Schristos opli = GET_U_1(pptr + 1); 972c74ad251Schristos pptr += 2; 973c74ad251Schristos li_remaining -= 2; 974c74ad251Schristos if (opli > li_remaining) { 975c74ad251Schristos ND_PRINT(", opt (%u) too long", op); 9760f74e101Schristos return (0); 9770f74e101Schristos } 978c74ad251Schristos ND_TCHECK_LEN(pptr, opli); 979c74ad251Schristos li_remaining -= opli; 9800f74e101Schristos tptr = pptr; 9810f74e101Schristos tlen = opli; 9820f74e101Schristos 983c74ad251Schristos ND_PRINT("\n\t %s Option #%u, length %u, value: ", 9840f74e101Schristos tok2str(clnp_option_values,"Unknown",op), 9850f74e101Schristos op, 986c74ad251Schristos opli); 9870f74e101Schristos 988dc860a36Sspz /* 989dc860a36Sspz * We've already checked that the entire option is present 990c74ad251Schristos * in the captured packet with the ND_TCHECK_LEN() call. 991c74ad251Schristos * Therefore, we don't need to do ND_TCHECK()/ND_TCHECK_LEN() 992dc860a36Sspz * checks. 993dc860a36Sspz * We do, however, need to check tlen, to make sure we 994dc860a36Sspz * don't run past the end of the option. 995dc860a36Sspz */ 9960f74e101Schristos switch (op) { 9970f74e101Schristos 9980f74e101Schristos 9990f74e101Schristos case CLNP_OPTION_ROUTE_RECORDING: /* those two options share the format */ 10000f74e101Schristos case CLNP_OPTION_SOURCE_ROUTING: 1001dc860a36Sspz if (tlen < 2) { 1002c74ad251Schristos ND_PRINT(", bad opt len"); 1003dc860a36Sspz return (0); 1004dc860a36Sspz } 1005c74ad251Schristos ND_PRINT("%s %s", 1006c74ad251Schristos tok2str(clnp_option_sr_rr_values,"Unknown",GET_U_1(tptr)), 1007c74ad251Schristos tok2str(clnp_option_sr_rr_string_values, "Unknown Option %u", op)); 1008c74ad251Schristos nsap_offset=GET_U_1(tptr + 1); 10090f74e101Schristos if (nsap_offset == 0) { 1010c74ad251Schristos ND_PRINT(" Bad NSAP offset (0)"); 10110f74e101Schristos break; 10120f74e101Schristos } 10130f74e101Schristos nsap_offset-=1; /* offset to nsap list */ 10140f74e101Schristos if (nsap_offset > tlen) { 1015c74ad251Schristos ND_PRINT(" Bad NSAP offset (past end of option)"); 10160f74e101Schristos break; 10170f74e101Schristos } 10180f74e101Schristos tptr+=nsap_offset; 10190f74e101Schristos tlen-=nsap_offset; 10200f74e101Schristos while (tlen > 0) { 1021c74ad251Schristos source_address_length=GET_U_1(tptr); 10220f74e101Schristos if (tlen < source_address_length+1) { 1023c74ad251Schristos ND_PRINT("\n\t NSAP address goes past end of option"); 10240f74e101Schristos break; 10250f74e101Schristos } 10260f74e101Schristos if (source_address_length > 0) { 10270f74e101Schristos source_address=(tptr+1); 1028c74ad251Schristos ND_PRINT("\n\t NSAP address (length %u): %s", 10290f74e101Schristos source_address_length, 1030c74ad251Schristos GET_ISONSAP_STRING(source_address, source_address_length)); 10310f74e101Schristos } 10320f74e101Schristos tlen-=source_address_length+1; 10330f74e101Schristos } 10340f74e101Schristos break; 10350f74e101Schristos 10360f74e101Schristos case CLNP_OPTION_PRIORITY: 1037dc860a36Sspz if (tlen < 1) { 1038c74ad251Schristos ND_PRINT(", bad opt len"); 1039dc860a36Sspz return (0); 1040dc860a36Sspz } 1041c74ad251Schristos ND_PRINT("0x%1x", GET_U_1(tptr)&0x0f); 10420f74e101Schristos break; 10430f74e101Schristos 10440f74e101Schristos case CLNP_OPTION_QOS_MAINTENANCE: 1045dc860a36Sspz if (tlen < 1) { 1046c74ad251Schristos ND_PRINT(", bad opt len"); 1047dc860a36Sspz return (0); 1048dc860a36Sspz } 1049c74ad251Schristos ND_PRINT("\n\t Format Code: %s", 1050c74ad251Schristos tok2str(clnp_option_scope_values, "Reserved", GET_U_1(tptr) & CLNP_OPTION_SCOPE_MASK)); 10510f74e101Schristos 1052c74ad251Schristos if ((GET_U_1(tptr)&CLNP_OPTION_SCOPE_MASK) == CLNP_OPTION_SCOPE_GLOBAL) 1053c74ad251Schristos ND_PRINT("\n\t QoS Flags [%s]", 10540f74e101Schristos bittok2str(clnp_option_qos_global_values, 10550f74e101Schristos "none", 1056c74ad251Schristos GET_U_1(tptr)&CLNP_OPTION_OPTION_QOS_MASK)); 10570f74e101Schristos break; 10580f74e101Schristos 10590f74e101Schristos case CLNP_OPTION_SECURITY: 1060dc860a36Sspz if (tlen < 2) { 1061c74ad251Schristos ND_PRINT(", bad opt len"); 1062dc860a36Sspz return (0); 1063dc860a36Sspz } 1064c74ad251Schristos ND_PRINT("\n\t Format Code: %s, Security-Level %u", 1065c74ad251Schristos tok2str(clnp_option_scope_values,"Reserved",GET_U_1(tptr)&CLNP_OPTION_SCOPE_MASK), 1066c74ad251Schristos GET_U_1(tptr + 1)); 10670f74e101Schristos break; 10680f74e101Schristos 10690f74e101Schristos case CLNP_OPTION_DISCARD_REASON: 1070dc860a36Sspz if (tlen < 1) { 1071c74ad251Schristos ND_PRINT(", bad opt len"); 1072dc860a36Sspz return (0); 1073dc860a36Sspz } 1074c74ad251Schristos rfd_error = GET_U_1(tptr); 1075c74ad251Schristos rfd_error_major = (rfd_error&0xf0) >> 4; 1076c74ad251Schristos rfd_error_minor = rfd_error&0x0f; 1077c74ad251Schristos ND_PRINT("\n\t Class: %s Error (0x%01x), %s (0x%01x)", 10780f74e101Schristos tok2str(clnp_option_rfd_class_values,"Unknown",rfd_error_major), 10790f74e101Schristos rfd_error_major, 10800f74e101Schristos tok2str(clnp_option_rfd_error_class[rfd_error_major],"Unknown",rfd_error_minor), 1081c74ad251Schristos rfd_error_minor); 10820f74e101Schristos break; 10830f74e101Schristos 10840f74e101Schristos case CLNP_OPTION_PADDING: 1085c74ad251Schristos ND_PRINT("padding data"); 10860f74e101Schristos break; 10870f74e101Schristos 10880f74e101Schristos /* 10890f74e101Schristos * FIXME those are the defined Options that lack a decoder 10900f74e101Schristos * you are welcome to contribute code ;-) 10910f74e101Schristos */ 10920f74e101Schristos 10930f74e101Schristos default: 1094b3a00663Schristos print_unknown_data(ndo, tptr, "\n\t ", opli); 10950f74e101Schristos break; 10960f74e101Schristos } 1097b3a00663Schristos if (ndo->ndo_vflag > 1) 1098b3a00663Schristos print_unknown_data(ndo, pptr, "\n\t ", opli); 10990f74e101Schristos pptr += opli; 11000f74e101Schristos } 11010f74e101Schristos 11020f74e101Schristos switch (clnp_pdu_type) { 11030f74e101Schristos 11040f74e101Schristos case CLNP_PDU_ER: /* fall through */ 11050f74e101Schristos case CLNP_PDU_ERP: 1106c74ad251Schristos if (GET_U_1(pptr) == NLPID_CLNP) { 1107c74ad251Schristos ND_PRINT("\n\t-----original packet-----\n\t"); 11080f74e101Schristos /* FIXME recursion protection */ 1109c74ad251Schristos clnp_print(ndo, pptr, length - li); 11100f74e101Schristos break; 11110f74e101Schristos } 11120f74e101Schristos 1113c74ad251Schristos /* The cases above break from the switch block if they see and print 1114c74ad251Schristos * a CLNP header in the Data part. For an Error Report PDU this is 1115c74ad251Schristos * described in Section 7.9.6 of ITU X.233 (1997 E), also known as 1116c74ad251Schristos * ISO/IEC 8473-1:1998(E). It is not clear why in this code the same 1117c74ad251Schristos * applies to an Echo Response PDU, as the standard does not specify 1118c74ad251Schristos * the contents -- could be a proprietary extension or a bug. In either 1119c74ad251Schristos * case, if the Data part does not contain a CLNP header, its structure 1120c74ad251Schristos * is considered unknown and the decoding falls through to print the 1121c74ad251Schristos * contents as-is. 1122c74ad251Schristos */ 1123c74ad251Schristos ND_FALL_THROUGH; 1124c74ad251Schristos 11250f74e101Schristos case CLNP_PDU_DT: 11260f74e101Schristos case CLNP_PDU_MD: 11270f74e101Schristos case CLNP_PDU_ERQ: 11280f74e101Schristos 11290f74e101Schristos default: 11300f74e101Schristos /* dump the PDU specific data */ 1131*26ba0b50Schristos if (length > ND_BYTES_BETWEEN(optr, pptr)) { 1132c74ad251Schristos ND_PRINT("\n\t undecoded non-header data, length %u", length-li); 1133*26ba0b50Schristos print_unknown_data(ndo, pptr, "\n\t ", 1134*26ba0b50Schristos length - ND_BYTES_BETWEEN(optr, pptr)); 11350f74e101Schristos } 11360f74e101Schristos } 11370f74e101Schristos 11380f74e101Schristos return (1); 11390f74e101Schristos 11400f74e101Schristos trunc: 1141c74ad251Schristos nd_print_trunc(ndo); 11420f74e101Schristos return (1); 11430f74e101Schristos 11440f74e101Schristos } 11450f74e101Schristos 11460f74e101Schristos 11470f74e101Schristos #define ESIS_PDU_REDIRECT 6 11480f74e101Schristos #define ESIS_PDU_ESH 2 11490f74e101Schristos #define ESIS_PDU_ISH 4 11500f74e101Schristos 1151870189d2Schristos static const struct tok esis_pdu_values[] = { 11520f74e101Schristos { ESIS_PDU_REDIRECT, "redirect"}, 11530f74e101Schristos { ESIS_PDU_ESH, "ESH"}, 11540f74e101Schristos { ESIS_PDU_ISH, "ISH"}, 11550f74e101Schristos { 0, NULL } 11560f74e101Schristos }; 11570f74e101Schristos 11580f74e101Schristos struct esis_header_t { 1159c74ad251Schristos nd_uint8_t nlpid; 1160c74ad251Schristos nd_uint8_t length_indicator; 1161c74ad251Schristos nd_uint8_t version; 1162c74ad251Schristos nd_byte reserved; 1163c74ad251Schristos nd_uint8_t type; 1164c74ad251Schristos nd_uint16_t holdtime; 1165c74ad251Schristos nd_uint16_t cksum; 11660f74e101Schristos }; 11670f74e101Schristos 11680f74e101Schristos static void 1169b3a00663Schristos esis_print(netdissect_options *ndo, 1170b3a00663Schristos const uint8_t *pptr, u_int length) 11710f74e101Schristos { 1172b3a00663Schristos const uint8_t *optr; 1173c74ad251Schristos u_int li, version, esis_pdu_type, source_address_length, source_address_number; 11740f74e101Schristos const struct esis_header_t *esis_header; 11750f74e101Schristos 1176c74ad251Schristos ndo->ndo_protocol = "esis"; 1177b3a00663Schristos if (!ndo->ndo_eflag) 1178c74ad251Schristos ND_PRINT("ES-IS"); 11790f74e101Schristos 11800f74e101Schristos if (length <= 2) { 1181c74ad251Schristos ND_PRINT(ndo->ndo_qflag ? "bad pkt!" : "no header at all!"); 11820f74e101Schristos return; 11830f74e101Schristos } 11840f74e101Schristos 11850f74e101Schristos esis_header = (const struct esis_header_t *) pptr; 1186c74ad251Schristos ND_TCHECK_SIZE(esis_header); 1187c74ad251Schristos li = GET_U_1(esis_header->length_indicator); 11880f74e101Schristos optr = pptr; 11890f74e101Schristos 11900f74e101Schristos /* 11910f74e101Schristos * Sanity checking of the header. 11920f74e101Schristos */ 11930f74e101Schristos 1194c74ad251Schristos if (GET_U_1(esis_header->nlpid) != NLPID_ESIS) { 1195c74ad251Schristos ND_PRINT(" nlpid 0x%02x packet not supported", 1196c74ad251Schristos GET_U_1(esis_header->nlpid)); 11970f74e101Schristos return; 11980f74e101Schristos } 11990f74e101Schristos 1200c74ad251Schristos version = GET_U_1(esis_header->version); 1201c74ad251Schristos if (version != ESIS_VERSION) { 1202c74ad251Schristos ND_PRINT(" version %u packet not supported", version); 12030f74e101Schristos return; 12040f74e101Schristos } 12050f74e101Schristos 12060f74e101Schristos if (li > length) { 1207c74ad251Schristos ND_PRINT(" length indicator(%u) > PDU size (%u)!", li, length); 12080f74e101Schristos return; 12090f74e101Schristos } 12100f74e101Schristos 12110f74e101Schristos if (li < sizeof(struct esis_header_t) + 2) { 1212c74ad251Schristos ND_PRINT(" length indicator %u < min PDU size:", li); 1213c74ad251Schristos while (pptr < ndo->ndo_snapend) { 1214c74ad251Schristos ND_PRINT("%02X", GET_U_1(pptr)); 1215c74ad251Schristos pptr++; 1216c74ad251Schristos } 12170f74e101Schristos return; 12180f74e101Schristos } 12190f74e101Schristos 1220c74ad251Schristos esis_pdu_type = GET_U_1(esis_header->type) & ESIS_PDU_TYPE_MASK; 12210f74e101Schristos 1222b3a00663Schristos if (ndo->ndo_vflag < 1) { 1223c74ad251Schristos ND_PRINT("%s%s, length %u", 1224b3a00663Schristos ndo->ndo_eflag ? "" : ", ", 12250f74e101Schristos tok2str(esis_pdu_values,"unknown type (%u)",esis_pdu_type), 1226c74ad251Schristos length); 12270f74e101Schristos return; 12280f74e101Schristos } else 1229c74ad251Schristos ND_PRINT("%slength %u\n\t%s (%u)", 1230b3a00663Schristos ndo->ndo_eflag ? "" : ", ", 12310f74e101Schristos length, 12320f74e101Schristos tok2str(esis_pdu_values,"unknown type: %u", esis_pdu_type), 1233c74ad251Schristos esis_pdu_type); 12340f74e101Schristos 1235c74ad251Schristos ND_PRINT(", v: %u%s", version, version == ESIS_VERSION ? "" : "unsupported" ); 1236c74ad251Schristos ND_PRINT(", checksum: 0x%04x", GET_BE_U_2(esis_header->cksum)); 12370f74e101Schristos 1238c74ad251Schristos osi_print_cksum(ndo, pptr, GET_BE_U_2(esis_header->cksum), 7, 1239c74ad251Schristos li); 12400f74e101Schristos 1241c74ad251Schristos ND_PRINT(", holding time: %us, length indicator: %u", 1242c74ad251Schristos GET_BE_U_2(esis_header->holdtime), li); 12430f74e101Schristos 1244b3a00663Schristos if (ndo->ndo_vflag > 1) 1245b3a00663Schristos print_unknown_data(ndo, optr, "\n\t", sizeof(struct esis_header_t)); 12460f74e101Schristos 12470f74e101Schristos pptr += sizeof(struct esis_header_t); 12480f74e101Schristos li -= sizeof(struct esis_header_t); 12490f74e101Schristos 12500f74e101Schristos switch (esis_pdu_type) { 12510f74e101Schristos case ESIS_PDU_REDIRECT: { 1252b3a00663Schristos const uint8_t *dst, *snpa, *neta; 12530f74e101Schristos u_int dstl, snpal, netal; 12540f74e101Schristos 1255c74ad251Schristos ND_TCHECK_1(pptr); 12560f74e101Schristos if (li < 1) { 1257c74ad251Schristos ND_PRINT(", bad redirect/li"); 12580f74e101Schristos return; 12590f74e101Schristos } 1260c74ad251Schristos dstl = GET_U_1(pptr); 12610f74e101Schristos pptr++; 12620f74e101Schristos li--; 1263c74ad251Schristos ND_TCHECK_LEN(pptr, dstl); 12640f74e101Schristos if (li < dstl) { 1265c74ad251Schristos ND_PRINT(", bad redirect/li"); 12660f74e101Schristos return; 12670f74e101Schristos } 12680f74e101Schristos dst = pptr; 12690f74e101Schristos pptr += dstl; 12700f74e101Schristos li -= dstl; 1271c74ad251Schristos ND_PRINT("\n\t %s", GET_ISONSAP_STRING(dst, dstl)); 12720f74e101Schristos 1273c74ad251Schristos ND_TCHECK_1(pptr); 12740f74e101Schristos if (li < 1) { 1275c74ad251Schristos ND_PRINT(", bad redirect/li"); 12760f74e101Schristos return; 12770f74e101Schristos } 1278c74ad251Schristos snpal = GET_U_1(pptr); 12790f74e101Schristos pptr++; 12800f74e101Schristos li--; 1281c74ad251Schristos ND_TCHECK_LEN(pptr, snpal); 12820f74e101Schristos if (li < snpal) { 1283c74ad251Schristos ND_PRINT(", bad redirect/li"); 12840f74e101Schristos return; 12850f74e101Schristos } 12860f74e101Schristos snpa = pptr; 12870f74e101Schristos pptr += snpal; 12880f74e101Schristos li -= snpal; 1289c74ad251Schristos ND_TCHECK_1(pptr); 12900f74e101Schristos if (li < 1) { 1291c74ad251Schristos ND_PRINT(", bad redirect/li"); 12920f74e101Schristos return; 12930f74e101Schristos } 1294c74ad251Schristos netal = GET_U_1(pptr); 12950f74e101Schristos pptr++; 1296c74ad251Schristos ND_TCHECK_LEN(pptr, netal); 12970f74e101Schristos if (li < netal) { 1298c74ad251Schristos ND_PRINT(", bad redirect/li"); 12990f74e101Schristos return; 13000f74e101Schristos } 13010f74e101Schristos neta = pptr; 13020f74e101Schristos pptr += netal; 13030f74e101Schristos li -= netal; 13040f74e101Schristos 1305c74ad251Schristos if (snpal == MAC_ADDR_LEN) 1306c74ad251Schristos ND_PRINT("\n\t SNPA (length: %u): %s", 130772c96ff3Schristos snpal, 1308c74ad251Schristos GET_ETHERADDR_STRING(snpa)); 13090f74e101Schristos else 1310c74ad251Schristos ND_PRINT("\n\t SNPA (length: %u): %s", 131172c96ff3Schristos snpal, 1312c74ad251Schristos GET_LINKADDR_STRING(snpa, LINKADDR_OTHER, snpal)); 131372c96ff3Schristos if (netal != 0) 1314c74ad251Schristos ND_PRINT("\n\t NET (length: %u) %s", 131572c96ff3Schristos netal, 1316c74ad251Schristos GET_ISONSAP_STRING(neta, netal)); 13170f74e101Schristos break; 13180f74e101Schristos } 13190f74e101Schristos 13200f74e101Schristos case ESIS_PDU_ESH: 1321c74ad251Schristos ND_TCHECK_1(pptr); 13220f74e101Schristos if (li < 1) { 1323c74ad251Schristos ND_PRINT(", bad esh/li"); 13240f74e101Schristos return; 13250f74e101Schristos } 1326c74ad251Schristos source_address_number = GET_U_1(pptr); 13270f74e101Schristos pptr++; 13280f74e101Schristos li--; 13290f74e101Schristos 1330c74ad251Schristos ND_PRINT("\n\t Number of Source Addresses: %u", source_address_number); 13310f74e101Schristos 13320f74e101Schristos while (source_address_number > 0) { 1333c74ad251Schristos ND_TCHECK_1(pptr); 13340f74e101Schristos if (li < 1) { 1335c74ad251Schristos ND_PRINT(", bad esh/li"); 13360f74e101Schristos return; 13370f74e101Schristos } 1338c74ad251Schristos source_address_length = GET_U_1(pptr); 13390f74e101Schristos pptr++; 13400f74e101Schristos li--; 13410f74e101Schristos 1342c74ad251Schristos ND_TCHECK_LEN(pptr, source_address_length); 13430f74e101Schristos if (li < source_address_length) { 1344c74ad251Schristos ND_PRINT(", bad esh/li"); 13450f74e101Schristos return; 13460f74e101Schristos } 1347c74ad251Schristos ND_PRINT("\n\t NET (length: %u): %s", 13480f74e101Schristos source_address_length, 1349c74ad251Schristos GET_ISONSAP_STRING(pptr, source_address_length)); 13500f74e101Schristos pptr += source_address_length; 13510f74e101Schristos li -= source_address_length; 13520f74e101Schristos source_address_number--; 13530f74e101Schristos } 13540f74e101Schristos 13550f74e101Schristos break; 13560f74e101Schristos 13570f74e101Schristos case ESIS_PDU_ISH: { 1358c74ad251Schristos ND_TCHECK_1(pptr); 13590f74e101Schristos if (li < 1) { 1360c74ad251Schristos ND_PRINT(", bad ish/li"); 13610f74e101Schristos return; 13620f74e101Schristos } 1363c74ad251Schristos source_address_length = GET_U_1(pptr); 13640f74e101Schristos pptr++; 13650f74e101Schristos li--; 1366c74ad251Schristos ND_TCHECK_LEN(pptr, source_address_length); 13670f74e101Schristos if (li < source_address_length) { 1368c74ad251Schristos ND_PRINT(", bad ish/li"); 13690f74e101Schristos return; 13700f74e101Schristos } 1371c74ad251Schristos ND_PRINT("\n\t NET (length: %u): %s", source_address_length, GET_ISONSAP_STRING(pptr, source_address_length)); 13720f74e101Schristos pptr += source_address_length; 13730f74e101Schristos li -= source_address_length; 13740f74e101Schristos break; 13750f74e101Schristos } 13760f74e101Schristos 13770f74e101Schristos default: 1378b3a00663Schristos if (ndo->ndo_vflag <= 1) { 1379c74ad251Schristos /* 1380c74ad251Schristos * If there's at least one byte to print, print 1381c74ad251Schristos * it/them. 1382c74ad251Schristos */ 1383c74ad251Schristos if (ND_TTEST_LEN(pptr, 1)) 1384c74ad251Schristos print_unknown_data(ndo, pptr, "\n\t ", ND_BYTES_AVAILABLE_AFTER(pptr)); 13850f74e101Schristos } 13860f74e101Schristos return; 13870f74e101Schristos } 13880f74e101Schristos 13890f74e101Schristos /* now walk the options */ 13900e9868baSchristos while (li != 0) { 13910f74e101Schristos u_int op, opli; 1392b3a00663Schristos const uint8_t *tptr; 13930f74e101Schristos 13940f74e101Schristos if (li < 2) { 1395c74ad251Schristos ND_PRINT(", bad opts/li"); 13960f74e101Schristos return; 13970f74e101Schristos } 1398c74ad251Schristos op = GET_U_1(pptr); 1399c74ad251Schristos opli = GET_U_1(pptr + 1); 1400c74ad251Schristos pptr += 2; 14010f74e101Schristos li -= 2; 14020f74e101Schristos if (opli > li) { 1403c74ad251Schristos ND_PRINT(", opt (%u) too long", op); 14040f74e101Schristos return; 14050f74e101Schristos } 14060f74e101Schristos li -= opli; 14070f74e101Schristos tptr = pptr; 14080f74e101Schristos 1409c74ad251Schristos ND_PRINT("\n\t %s Option #%u, length %u, value: ", 14100f74e101Schristos tok2str(esis_option_values,"Unknown",op), 14110f74e101Schristos op, 1412c74ad251Schristos opli); 14130f74e101Schristos 14140f74e101Schristos switch (op) { 14150f74e101Schristos 14160f74e101Schristos case ESIS_OPTION_ES_CONF_TIME: 14170e9868baSchristos if (opli == 2) { 1418c74ad251Schristos ND_TCHECK_2(pptr); 1419c74ad251Schristos ND_PRINT("%us", GET_BE_U_2(tptr)); 14200e9868baSchristos } else 1421c74ad251Schristos ND_PRINT("(bad length)"); 14220f74e101Schristos break; 14230f74e101Schristos 14240f74e101Schristos case ESIS_OPTION_PROTOCOLS: 14250f74e101Schristos while (opli>0) { 1426c74ad251Schristos ND_PRINT("%s (0x%02x)", 14270f74e101Schristos tok2str(nlpid_values, 14280f74e101Schristos "unknown", 1429c74ad251Schristos GET_U_1(tptr)), 1430c74ad251Schristos GET_U_1(tptr)); 14310f74e101Schristos if (opli>1) /* further NPLIDs ? - put comma */ 1432c74ad251Schristos ND_PRINT(", "); 14330f74e101Schristos tptr++; 14340f74e101Schristos opli--; 14350f74e101Schristos } 14360f74e101Schristos break; 14370f74e101Schristos 14380f74e101Schristos /* 14390f74e101Schristos * FIXME those are the defined Options that lack a decoder 14400f74e101Schristos * you are welcome to contribute code ;-) 14410f74e101Schristos */ 14420f74e101Schristos 14430f74e101Schristos case ESIS_OPTION_QOS_MAINTENANCE: 14440f74e101Schristos case ESIS_OPTION_SECURITY: 14450f74e101Schristos case ESIS_OPTION_PRIORITY: 14460f74e101Schristos case ESIS_OPTION_ADDRESS_MASK: 14470f74e101Schristos case ESIS_OPTION_SNPA_MASK: 14480f74e101Schristos 14490f74e101Schristos default: 1450b3a00663Schristos print_unknown_data(ndo, tptr, "\n\t ", opli); 14510f74e101Schristos break; 14520f74e101Schristos } 1453b3a00663Schristos if (ndo->ndo_vflag > 1) 1454b3a00663Schristos print_unknown_data(ndo, pptr, "\n\t ", opli); 14550f74e101Schristos pptr += opli; 14560f74e101Schristos } 1457c74ad251Schristos return; 1458c74ad251Schristos 14590f74e101Schristos trunc: 1460c74ad251Schristos nd_print_trunc(ndo); 14610f74e101Schristos } 14620f74e101Schristos 1463870189d2Schristos static void 1464b3a00663Schristos isis_print_mcid(netdissect_options *ndo, 1465b3a00663Schristos const struct isis_spb_mcid *mcid) 1466870189d2Schristos { 1467870189d2Schristos int i; 1468870189d2Schristos 1469c74ad251Schristos ND_TCHECK_SIZE(mcid); 1470c74ad251Schristos ND_PRINT("ID: %u, Name: ", GET_U_1(mcid->format_id)); 1471870189d2Schristos 1472c74ad251Schristos nd_printjnp(ndo, mcid->name, sizeof(mcid->name)); 1473870189d2Schristos 1474c74ad251Schristos ND_PRINT("\n\t Lvl: %u", GET_BE_U_2(mcid->revision_lvl)); 1475870189d2Schristos 1476c74ad251Schristos ND_PRINT(", Digest: "); 1477870189d2Schristos 1478870189d2Schristos for(i=0;i<16;i++) 1479c74ad251Schristos ND_PRINT("%.2x ", mcid->digest[i]); 1480c74ad251Schristos return; 1481fdccd7e4Schristos 1482fdccd7e4Schristos trunc: 1483c74ad251Schristos nd_print_trunc(ndo); 1484870189d2Schristos } 1485870189d2Schristos 1486870189d2Schristos static int 1487b3a00663Schristos isis_print_mt_port_cap_subtlv(netdissect_options *ndo, 1488c74ad251Schristos const uint8_t *tptr, u_int len) 1489870189d2Schristos { 1490c74ad251Schristos u_int stlv_type, stlv_len; 1491870189d2Schristos const struct isis_subtlv_spb_mcid *subtlv_spb_mcid; 1492870189d2Schristos int i; 1493870189d2Schristos 1494*26ba0b50Schristos while (len > 2) { 1495c74ad251Schristos stlv_type = GET_U_1(tptr); 1496c74ad251Schristos stlv_len = GET_U_1(tptr + 1); 1497870189d2Schristos 1498870189d2Schristos /* first lets see if we know the subTLVs name*/ 1499c74ad251Schristos ND_PRINT("\n\t %s subTLV #%u, length: %u", 1500870189d2Schristos tok2str(isis_mt_port_cap_subtlv_values, "unknown", stlv_type), 1501870189d2Schristos stlv_type, 1502c74ad251Schristos stlv_len); 1503870189d2Schristos 1504c74ad251Schristos tptr += 2; 1505870189d2Schristos /*len -= TLV_TYPE_LEN_OFFSET;*/ 1506c74ad251Schristos len -= 2; 1507870189d2Schristos 150872c96ff3Schristos /* Make sure the subTLV fits within the space left */ 150972c96ff3Schristos if (len < stlv_len) 1510c74ad251Schristos goto subtlv_too_long; 151172c96ff3Schristos /* Make sure the entire subTLV is in the captured data */ 1512c74ad251Schristos ND_TCHECK_LEN(tptr, stlv_len); 151372c96ff3Schristos 1514*26ba0b50Schristos switch (stlv_type) { 1515870189d2Schristos case ISIS_SUBTLV_SPB_MCID: 1516870189d2Schristos { 151772c96ff3Schristos if (stlv_len < ISIS_SUBTLV_SPB_MCID_MIN_LEN) 1518c74ad251Schristos goto subtlv_too_short; 1519870189d2Schristos 1520fdccd7e4Schristos subtlv_spb_mcid = (const struct isis_subtlv_spb_mcid *)tptr; 1521870189d2Schristos 1522c74ad251Schristos ND_PRINT("\n\t MCID: "); 1523b3a00663Schristos isis_print_mcid(ndo, &(subtlv_spb_mcid->mcid)); 1524870189d2Schristos 1525870189d2Schristos /*tptr += SPB_MCID_MIN_LEN; 1526870189d2Schristos len -= SPB_MCID_MIN_LEN; */ 1527870189d2Schristos 1528c74ad251Schristos ND_PRINT("\n\t AUX-MCID: "); 1529b3a00663Schristos isis_print_mcid(ndo, &(subtlv_spb_mcid->aux_mcid)); 1530870189d2Schristos 1531870189d2Schristos /*tptr += SPB_MCID_MIN_LEN; 1532870189d2Schristos len -= SPB_MCID_MIN_LEN; */ 1533c74ad251Schristos tptr += ISIS_SUBTLV_SPB_MCID_MIN_LEN; 1534c74ad251Schristos len -= ISIS_SUBTLV_SPB_MCID_MIN_LEN; 1535c74ad251Schristos stlv_len -= ISIS_SUBTLV_SPB_MCID_MIN_LEN; 1536870189d2Schristos 1537870189d2Schristos break; 1538870189d2Schristos } 1539870189d2Schristos 1540870189d2Schristos case ISIS_SUBTLV_SPB_DIGEST: 1541870189d2Schristos { 154272c96ff3Schristos if (stlv_len < ISIS_SUBTLV_SPB_DIGEST_MIN_LEN) 1543c74ad251Schristos goto subtlv_too_short; 1544870189d2Schristos 1545c74ad251Schristos ND_PRINT("\n\t RES: %u V: %u A: %u D: %u", 1546c74ad251Schristos (GET_U_1(tptr) >> 5), 1547c74ad251Schristos ((GET_U_1(tptr) >> 4) & 0x01), 1548c74ad251Schristos ((GET_U_1(tptr) >> 2) & 0x03), 1549c74ad251Schristos (GET_U_1(tptr) & 0x03)); 1550870189d2Schristos 1551870189d2Schristos tptr++; 1552870189d2Schristos 1553c74ad251Schristos ND_PRINT("\n\t Digest: "); 1554870189d2Schristos 1555*26ba0b50Schristos for(i=1;i<=8; i++) { 1556c74ad251Schristos ND_PRINT("%08x ", GET_BE_U_4(tptr)); 1557870189d2Schristos if (i%4 == 0 && i != 8) 1558c74ad251Schristos ND_PRINT("\n\t "); 1559c74ad251Schristos tptr += 4; 1560870189d2Schristos } 1561870189d2Schristos 1562c74ad251Schristos len -= ISIS_SUBTLV_SPB_DIGEST_MIN_LEN; 1563c74ad251Schristos stlv_len -= ISIS_SUBTLV_SPB_DIGEST_MIN_LEN; 1564870189d2Schristos 1565870189d2Schristos break; 1566870189d2Schristos } 1567870189d2Schristos 1568870189d2Schristos case ISIS_SUBTLV_SPB_BVID: 1569870189d2Schristos { 1570*26ba0b50Schristos while (stlv_len != 0) { 1571c74ad251Schristos if (stlv_len < 4) 1572c74ad251Schristos goto subtlv_too_short; 1573c74ad251Schristos ND_PRINT("\n\t ECT: %08x", 1574c74ad251Schristos GET_BE_U_4(tptr)); 1575870189d2Schristos 1576c74ad251Schristos tptr += 4; 1577c74ad251Schristos len -= 4; 1578c74ad251Schristos stlv_len -= 4; 1579870189d2Schristos 1580c74ad251Schristos if (stlv_len < 2) 1581c74ad251Schristos goto subtlv_too_short; 1582c74ad251Schristos ND_PRINT(" BVID: %u, U:%01x M:%01x ", 1583c74ad251Schristos (GET_BE_U_2(tptr) >> 4) , 1584c74ad251Schristos (GET_BE_U_2(tptr) >> 3) & 0x01, 1585c74ad251Schristos (GET_BE_U_2(tptr) >> 2) & 0x01); 1586870189d2Schristos 1587c74ad251Schristos tptr += 2; 1588c74ad251Schristos len -= 2; 1589c74ad251Schristos stlv_len -= 2; 1590870189d2Schristos } 1591870189d2Schristos 1592870189d2Schristos break; 1593870189d2Schristos } 1594870189d2Schristos 1595870189d2Schristos default: 1596870189d2Schristos break; 1597870189d2Schristos } 159872c96ff3Schristos tptr += stlv_len; 159972c96ff3Schristos len -= stlv_len; 1600870189d2Schristos } 1601c74ad251Schristos return (0); 1602870189d2Schristos 1603dc860a36Sspz trunc: 1604c74ad251Schristos nd_print_trunc(ndo); 1605c74ad251Schristos return (1); 1606c74ad251Schristos 1607c74ad251Schristos subtlv_too_long: 1608c74ad251Schristos ND_PRINT(" (> containing TLV length)"); 1609c74ad251Schristos return (1); 1610c74ad251Schristos 1611c74ad251Schristos subtlv_too_short: 1612c74ad251Schristos ND_PRINT(" (too short)"); 1613870189d2Schristos return (1); 1614870189d2Schristos } 1615870189d2Schristos 1616870189d2Schristos static int 1617b3a00663Schristos isis_print_mt_capability_subtlv(netdissect_options *ndo, 1618c74ad251Schristos const uint8_t *tptr, u_int len) 1619870189d2Schristos { 1620c74ad251Schristos u_int stlv_type, stlv_len, treecount; 1621870189d2Schristos 1622*26ba0b50Schristos while (len > 2) { 1623c74ad251Schristos stlv_type = GET_U_1(tptr); 1624c74ad251Schristos stlv_len = GET_U_1(tptr + 1); 1625c74ad251Schristos tptr += 2; 1626c74ad251Schristos len -= 2; 1627870189d2Schristos 1628870189d2Schristos /* first lets see if we know the subTLVs name*/ 1629c74ad251Schristos ND_PRINT("\n\t %s subTLV #%u, length: %u", 1630870189d2Schristos tok2str(isis_mt_capability_subtlv_values, "unknown", stlv_type), 1631870189d2Schristos stlv_type, 1632c74ad251Schristos stlv_len); 1633870189d2Schristos 163472c96ff3Schristos /* Make sure the subTLV fits within the space left */ 163572c96ff3Schristos if (len < stlv_len) 1636c74ad251Schristos goto subtlv_too_long; 163772c96ff3Schristos /* Make sure the entire subTLV is in the captured data */ 1638c74ad251Schristos ND_TCHECK_LEN(tptr, stlv_len); 163972c96ff3Schristos 1640*26ba0b50Schristos switch (stlv_type) { 1641870189d2Schristos case ISIS_SUBTLV_SPB_INSTANCE: 164272c96ff3Schristos if (stlv_len < ISIS_SUBTLV_SPB_INSTANCE_MIN_LEN) 1643c74ad251Schristos goto subtlv_too_short; 1644870189d2Schristos 1645c74ad251Schristos ND_PRINT("\n\t CIST Root-ID: %08x", GET_BE_U_4(tptr)); 1646c74ad251Schristos tptr += 4; 1647c74ad251Schristos ND_PRINT(" %08x", GET_BE_U_4(tptr)); 1648c74ad251Schristos tptr += 4; 1649c74ad251Schristos ND_PRINT(", Path Cost: %08x", GET_BE_U_4(tptr)); 1650c74ad251Schristos tptr += 4; 1651c74ad251Schristos ND_PRINT(", Prio: %u", GET_BE_U_2(tptr)); 1652c74ad251Schristos tptr += 2; 1653c74ad251Schristos ND_PRINT("\n\t RES: %u", 1654c74ad251Schristos GET_BE_U_2(tptr) >> 5); 1655c74ad251Schristos ND_PRINT(", V: %u", 1656c74ad251Schristos (GET_BE_U_2(tptr) >> 4) & 0x0001); 1657c74ad251Schristos ND_PRINT(", SPSource-ID: %u", 1658c74ad251Schristos (GET_BE_U_4(tptr) & 0x000fffff)); 1659c74ad251Schristos tptr += 4; 1660c74ad251Schristos ND_PRINT(", No of Trees: %x", GET_U_1(tptr)); 1661870189d2Schristos 1662c74ad251Schristos treecount = GET_U_1(tptr); 1663c74ad251Schristos tptr++; 1664870189d2Schristos 1665c74ad251Schristos len -= ISIS_SUBTLV_SPB_INSTANCE_MIN_LEN; 1666c74ad251Schristos stlv_len -= ISIS_SUBTLV_SPB_INSTANCE_MIN_LEN; 1667870189d2Schristos 1668*26ba0b50Schristos while (treecount) { 166972c96ff3Schristos if (stlv_len < ISIS_SUBTLV_SPB_INSTANCE_VLAN_TUPLE_LEN) 167072c96ff3Schristos goto trunc; 1671870189d2Schristos 1672c74ad251Schristos ND_PRINT("\n\t U:%u, M:%u, A:%u, RES:%u", 1673c74ad251Schristos GET_U_1(tptr) >> 7, 1674c74ad251Schristos (GET_U_1(tptr) >> 6) & 0x01, 1675c74ad251Schristos (GET_U_1(tptr) >> 5) & 0x01, 1676c74ad251Schristos (GET_U_1(tptr) & 0x1f)); 1677870189d2Schristos 1678870189d2Schristos tptr++; 1679870189d2Schristos 1680c74ad251Schristos ND_PRINT(", ECT: %08x", GET_BE_U_4(tptr)); 1681870189d2Schristos 1682c74ad251Schristos tptr += 4; 1683870189d2Schristos 1684c74ad251Schristos ND_PRINT(", BVID: %u, SPVID: %u", 1685c74ad251Schristos (GET_BE_U_3(tptr) >> 12) & 0x000fff, 1686c74ad251Schristos GET_BE_U_3(tptr) & 0x000fff); 1687870189d2Schristos 1688c74ad251Schristos tptr += 3; 1689c74ad251Schristos len -= ISIS_SUBTLV_SPB_INSTANCE_VLAN_TUPLE_LEN; 1690c74ad251Schristos stlv_len -= ISIS_SUBTLV_SPB_INSTANCE_VLAN_TUPLE_LEN; 1691c74ad251Schristos treecount--; 1692870189d2Schristos } 1693870189d2Schristos 1694870189d2Schristos break; 1695870189d2Schristos 1696870189d2Schristos case ISIS_SUBTLV_SPBM_SI: 169772c96ff3Schristos if (stlv_len < 8) 169872c96ff3Schristos goto trunc; 1699870189d2Schristos 1700c74ad251Schristos ND_PRINT("\n\t BMAC: %08x", GET_BE_U_4(tptr)); 1701c74ad251Schristos tptr += 4; 1702c74ad251Schristos ND_PRINT("%04x", GET_BE_U_2(tptr)); 1703c74ad251Schristos tptr += 2; 1704870189d2Schristos 1705c74ad251Schristos ND_PRINT(", RES: %u, VID: %u", GET_BE_U_2(tptr) >> 12, 1706c74ad251Schristos (GET_BE_U_2(tptr)) & 0x0fff); 1707870189d2Schristos 1708c74ad251Schristos tptr += 2; 1709c74ad251Schristos len -= 8; 1710c74ad251Schristos stlv_len -= 8; 1711870189d2Schristos 1712fdccd7e4Schristos while (stlv_len >= 4) { 1713c74ad251Schristos ND_PRINT("\n\t T: %u, R: %u, RES: %u, ISID: %u", 1714c74ad251Schristos (GET_BE_U_4(tptr) >> 31), 1715c74ad251Schristos (GET_BE_U_4(tptr) >> 30) & 0x01, 1716c74ad251Schristos (GET_BE_U_4(tptr) >> 24) & 0x03f, 1717c74ad251Schristos (GET_BE_U_4(tptr)) & 0x0ffffff); 1718870189d2Schristos 1719c74ad251Schristos tptr += 4; 1720c74ad251Schristos len -= 4; 1721c74ad251Schristos stlv_len -= 4; 1722870189d2Schristos } 1723870189d2Schristos 1724870189d2Schristos break; 1725870189d2Schristos 1726870189d2Schristos default: 1727870189d2Schristos break; 1728870189d2Schristos } 172972c96ff3Schristos tptr += stlv_len; 173072c96ff3Schristos len -= stlv_len; 1731870189d2Schristos } 1732c74ad251Schristos return (0); 1733870189d2Schristos 1734fdccd7e4Schristos trunc: 1735c74ad251Schristos nd_print_trunc(ndo); 1736c74ad251Schristos return (1); 1737c74ad251Schristos 1738c74ad251Schristos subtlv_too_long: 1739c74ad251Schristos ND_PRINT(" (> containing TLV length)"); 1740c74ad251Schristos return (1); 1741c74ad251Schristos 1742c74ad251Schristos subtlv_too_short: 1743c74ad251Schristos ND_PRINT(" (too short)"); 1744870189d2Schristos return (1); 1745870189d2Schristos } 1746870189d2Schristos 17470f74e101Schristos /* shared routine for printing system, node and lsp-ids */ 17480f74e101Schristos static char * 1749c74ad251Schristos isis_print_id(netdissect_options *ndo, const uint8_t *cp, u_int id_len) 17500f74e101Schristos { 1751c74ad251Schristos u_int i; 17520f74e101Schristos static char id[sizeof("xxxx.xxxx.xxxx.yy-zz")]; 17530f74e101Schristos char *pos = id; 1754c74ad251Schristos u_int sysid_len; 17550f74e101Schristos 175672c96ff3Schristos sysid_len = SYSTEM_ID_LEN; 175772c96ff3Schristos if (sysid_len > id_len) 175872c96ff3Schristos sysid_len = id_len; 175972c96ff3Schristos for (i = 1; i <= sysid_len; i++) { 1760c74ad251Schristos snprintf(pos, sizeof(id) - (pos - id), "%02x", GET_U_1(cp)); 1761c74ad251Schristos cp++; 17620f74e101Schristos pos += strlen(pos); 17630f74e101Schristos if (i == 2 || i == 4) 17640f74e101Schristos *pos++ = '.'; 17650f74e101Schristos } 17660f74e101Schristos if (id_len >= NODE_ID_LEN) { 1767c74ad251Schristos snprintf(pos, sizeof(id) - (pos - id), ".%02x", GET_U_1(cp)); 1768c74ad251Schristos cp++; 17690f74e101Schristos pos += strlen(pos); 17700f74e101Schristos } 17710f74e101Schristos if (id_len == LSP_ID_LEN) 1772c74ad251Schristos snprintf(pos, sizeof(id) - (pos - id), "-%02x", GET_U_1(cp)); 17730f74e101Schristos return (id); 17740f74e101Schristos } 17750f74e101Schristos 17760f74e101Schristos /* print the 4-byte metric block which is common found in the old-style TLVs */ 17770f74e101Schristos static int 1778b3a00663Schristos isis_print_metric_block(netdissect_options *ndo, 1779b3a00663Schristos const struct isis_metric_block *isis_metric_block) 17800f74e101Schristos { 1781c74ad251Schristos ND_PRINT(", Default Metric: %u, %s", 17820f74e101Schristos ISIS_LSP_TLV_METRIC_VALUE(isis_metric_block->metric_default), 1783c74ad251Schristos ISIS_LSP_TLV_METRIC_IE(isis_metric_block->metric_default) ? "External" : "Internal"); 17840f74e101Schristos if (!ISIS_LSP_TLV_METRIC_SUPPORTED(isis_metric_block->metric_delay)) 1785c74ad251Schristos ND_PRINT("\n\t\t Delay Metric: %u, %s", 17860f74e101Schristos ISIS_LSP_TLV_METRIC_VALUE(isis_metric_block->metric_delay), 1787c74ad251Schristos ISIS_LSP_TLV_METRIC_IE(isis_metric_block->metric_delay) ? "External" : "Internal"); 17880f74e101Schristos if (!ISIS_LSP_TLV_METRIC_SUPPORTED(isis_metric_block->metric_expense)) 1789c74ad251Schristos ND_PRINT("\n\t\t Expense Metric: %u, %s", 17900f74e101Schristos ISIS_LSP_TLV_METRIC_VALUE(isis_metric_block->metric_expense), 1791c74ad251Schristos ISIS_LSP_TLV_METRIC_IE(isis_metric_block->metric_expense) ? "External" : "Internal"); 17920f74e101Schristos if (!ISIS_LSP_TLV_METRIC_SUPPORTED(isis_metric_block->metric_error)) 1793c74ad251Schristos ND_PRINT("\n\t\t Error Metric: %u, %s", 17940f74e101Schristos ISIS_LSP_TLV_METRIC_VALUE(isis_metric_block->metric_error), 1795c74ad251Schristos ISIS_LSP_TLV_METRIC_IE(isis_metric_block->metric_error) ? "External" : "Internal"); 17960f74e101Schristos 17970f74e101Schristos return(1); /* everything is ok */ 17980f74e101Schristos } 17990f74e101Schristos 18000f74e101Schristos static int 1801b3a00663Schristos isis_print_tlv_ip_reach(netdissect_options *ndo, 1802c74ad251Schristos const uint8_t *cp, const char *ident, u_int length) 18030f74e101Schristos { 18040f74e101Schristos int prefix_len; 18050f74e101Schristos const struct isis_tlv_ip_reach *tlv_ip_reach; 18060f74e101Schristos 18070f74e101Schristos tlv_ip_reach = (const struct isis_tlv_ip_reach *)cp; 18080f74e101Schristos 18090f74e101Schristos while (length > 0) { 18100f74e101Schristos if ((size_t)length < sizeof(*tlv_ip_reach)) { 1811c74ad251Schristos ND_PRINT("short IPv4 Reachability (%u vs %zu)", 18120f74e101Schristos length, 1813c74ad251Schristos sizeof(*tlv_ip_reach)); 18140f74e101Schristos return (0); 18150f74e101Schristos } 18160f74e101Schristos 1817c74ad251Schristos ND_TCHECK_SIZE(tlv_ip_reach); 18180f74e101Schristos 1819c74ad251Schristos prefix_len = mask2plen(GET_IPV4_TO_HOST_ORDER(tlv_ip_reach->mask)); 18200f74e101Schristos 18210f74e101Schristos if (prefix_len == -1) 1822c74ad251Schristos ND_PRINT("%sIPv4 prefix: %s mask %s", 18230f74e101Schristos ident, 1824c74ad251Schristos GET_IPADDR_STRING(tlv_ip_reach->prefix), 1825c74ad251Schristos GET_IPADDR_STRING(tlv_ip_reach->mask)); 18260f74e101Schristos else 1827c74ad251Schristos ND_PRINT("%sIPv4 prefix: %15s/%u", 18280f74e101Schristos ident, 1829c74ad251Schristos GET_IPADDR_STRING(tlv_ip_reach->prefix), 1830c74ad251Schristos prefix_len); 18310f74e101Schristos 1832c74ad251Schristos ND_PRINT(", Distribution: %s, Metric: %u, %s", 18330f74e101Schristos ISIS_LSP_TLV_METRIC_UPDOWN(tlv_ip_reach->isis_metric_block.metric_default) ? "down" : "up", 18340f74e101Schristos ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->isis_metric_block.metric_default), 1835c74ad251Schristos ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->isis_metric_block.metric_default) ? "External" : "Internal"); 18360f74e101Schristos 18370f74e101Schristos if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_ip_reach->isis_metric_block.metric_delay)) 1838c74ad251Schristos ND_PRINT("%s Delay Metric: %u, %s", 18390f74e101Schristos ident, 18400f74e101Schristos ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->isis_metric_block.metric_delay), 1841c74ad251Schristos ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->isis_metric_block.metric_delay) ? "External" : "Internal"); 18420f74e101Schristos 18430f74e101Schristos if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_ip_reach->isis_metric_block.metric_expense)) 1844c74ad251Schristos ND_PRINT("%s Expense Metric: %u, %s", 18450f74e101Schristos ident, 18460f74e101Schristos ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->isis_metric_block.metric_expense), 1847c74ad251Schristos ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->isis_metric_block.metric_expense) ? "External" : "Internal"); 18480f74e101Schristos 18490f74e101Schristos if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_ip_reach->isis_metric_block.metric_error)) 1850c74ad251Schristos ND_PRINT("%s Error Metric: %u, %s", 18510f74e101Schristos ident, 18520f74e101Schristos ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->isis_metric_block.metric_error), 1853c74ad251Schristos ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->isis_metric_block.metric_error) ? "External" : "Internal"); 18540f74e101Schristos 18550f74e101Schristos length -= sizeof(struct isis_tlv_ip_reach); 18560f74e101Schristos tlv_ip_reach++; 18570f74e101Schristos } 18580f74e101Schristos return (1); 1859c74ad251Schristos trunc: 1860c74ad251Schristos return 0; 18610f74e101Schristos } 18620f74e101Schristos 18630f74e101Schristos /* 18640f74e101Schristos * this is the common IP-REACH subTLV decoder it is called 18650f74e101Schristos * from various EXTD-IP REACH TLVs (135,235,236,237) 18660f74e101Schristos */ 18670f74e101Schristos 18680f74e101Schristos static int 1869b3a00663Schristos isis_print_ip_reach_subtlv(netdissect_options *ndo, 1870c74ad251Schristos const uint8_t *tptr, u_int subt, u_int subl, 1871ba2ff121Schristos const char *ident) 1872ba2ff121Schristos { 18730f74e101Schristos /* first lets see if we know the subTLVs name*/ 1874c74ad251Schristos ND_PRINT("%s%s subTLV #%u, length: %u", 1875b3a00663Schristos ident, tok2str(isis_ext_ip_reach_subtlv_values, "unknown", subt), 1876c74ad251Schristos subt, subl); 18770f74e101Schristos 1878c74ad251Schristos ND_TCHECK_LEN(tptr, subl); 18790f74e101Schristos 18800f74e101Schristos switch(subt) { 18810f74e101Schristos case ISIS_SUBTLV_EXTD_IP_REACH_MGMT_PREFIX_COLOR: /* fall through */ 18820f74e101Schristos case ISIS_SUBTLV_EXTD_IP_REACH_ADMIN_TAG32: 18830f74e101Schristos while (subl >= 4) { 1884c74ad251Schristos ND_PRINT(", 0x%08x (=%u)", 1885c74ad251Schristos GET_BE_U_4(tptr), 1886c74ad251Schristos GET_BE_U_4(tptr)); 18870f74e101Schristos tptr+=4; 18880f74e101Schristos subl-=4; 18890f74e101Schristos } 18900f74e101Schristos break; 18910f74e101Schristos case ISIS_SUBTLV_EXTD_IP_REACH_ADMIN_TAG64: 18920f74e101Schristos while (subl >= 8) { 1893c74ad251Schristos ND_PRINT(", 0x%08x%08x", 1894c74ad251Schristos GET_BE_U_4(tptr), 1895c74ad251Schristos GET_BE_U_4(tptr + 4)); 18960f74e101Schristos tptr+=8; 18970f74e101Schristos subl-=8; 18980f74e101Schristos } 18990f74e101Schristos break; 1900c74ad251Schristos case ISIS_SUBTLV_EXTD_IP_REACH_PREFIX_SID: 1901ba2ff121Schristos { 1902c74ad251Schristos uint8_t algo, flags; 1903c74ad251Schristos uint32_t sid; 19040f74e101Schristos 1905c74ad251Schristos flags = GET_U_1(tptr); 1906c74ad251Schristos algo = GET_U_1(tptr+1); 19070f74e101Schristos 1908c74ad251Schristos if (flags & ISIS_PREFIX_SID_FLAG_V) { 1909c74ad251Schristos if (subl < 5) 1910c74ad251Schristos goto trunc; 1911c74ad251Schristos sid = GET_BE_U_3(tptr+2); 1912c74ad251Schristos tptr+=5; 1913c74ad251Schristos subl-=5; 1914c74ad251Schristos } else { 191572c96ff3Schristos if (subl < 6) 1916c74ad251Schristos goto trunc; 1917c74ad251Schristos sid = GET_BE_U_4(tptr+2); 1918c74ad251Schristos tptr+=6; 1919c74ad251Schristos subl-=6; 19200f74e101Schristos } 1921c74ad251Schristos 1922c74ad251Schristos ND_PRINT(", Flags [%s], Algo %s (%u), %s %u", 1923c74ad251Schristos bittok2str(prefix_sid_flag_values, "None", flags), 1924c74ad251Schristos tok2str(prefix_sid_algo_values, "Unknown", algo), algo, 1925c74ad251Schristos flags & ISIS_PREFIX_SID_FLAG_V ? "label" : "index", 1926c74ad251Schristos sid); 19270f74e101Schristos } 19280f74e101Schristos break; 19290f74e101Schristos default: 1930b3a00663Schristos if (!print_unknown_data(ndo, tptr, "\n\t\t ", subl)) 19310f74e101Schristos return(0); 19320f74e101Schristos break; 19330f74e101Schristos } 19340f74e101Schristos return(1); 19350f74e101Schristos 1936fdccd7e4Schristos trunc: 1937c74ad251Schristos nd_print_trunc(ndo); 19380f74e101Schristos return(0); 19390f74e101Schristos } 19400f74e101Schristos 19410f74e101Schristos /* 19420f74e101Schristos * this is the common IS-REACH decoder it is called 19430f74e101Schristos * from various EXTD-IS REACH style TLVs (22,24,222) 19440f74e101Schristos */ 19450f74e101Schristos 19460f74e101Schristos static int 1947b3a00663Schristos isis_print_ext_is_reach(netdissect_options *ndo, 1948c74ad251Schristos const uint8_t *tptr, const char *ident, u_int tlv_type, 1949c74ad251Schristos u_int tlv_remaining) 1950ba2ff121Schristos { 19510f74e101Schristos char ident_buffer[20]; 1952c74ad251Schristos u_int subtlv_type,subtlv_len,subtlv_sum_len; 19530f74e101Schristos int proc_bytes = 0; /* how many bytes did we process ? */ 1954c74ad251Schristos u_int te_class,priority_level,gmpls_switch_cap; 1955c74ad251Schristos union { /* int to float conversion buffer for several subTLVs */ 1956c74ad251Schristos float f; 1957c74ad251Schristos uint32_t i; 1958c74ad251Schristos } bw; 19590f74e101Schristos 1960c74ad251Schristos ND_TCHECK_LEN(tptr, NODE_ID_LEN); 1961c74ad251Schristos if (tlv_remaining < NODE_ID_LEN) 19620f74e101Schristos return(0); 19630f74e101Schristos 1964c74ad251Schristos ND_PRINT("%sIS Neighbor: %s", ident, isis_print_id(ndo, tptr, NODE_ID_LEN)); 1965c74ad251Schristos tptr+=NODE_ID_LEN; 1966c74ad251Schristos tlv_remaining-=NODE_ID_LEN; 1967c74ad251Schristos proc_bytes+=NODE_ID_LEN; 19680f74e101Schristos 19690f74e101Schristos if (tlv_type != ISIS_TLV_IS_ALIAS_ID) { /* the Alias TLV Metric field is implicit 0 */ 1970c74ad251Schristos ND_TCHECK_3(tptr); 1971c74ad251Schristos if (tlv_remaining < 3) 19720f74e101Schristos return(0); 1973c74ad251Schristos ND_PRINT(", Metric: %u", GET_BE_U_3(tptr)); 19740f74e101Schristos tptr+=3; 1975c74ad251Schristos tlv_remaining-=3; 1976c74ad251Schristos proc_bytes+=3; 19770f74e101Schristos } 19780f74e101Schristos 1979c74ad251Schristos ND_TCHECK_1(tptr); 1980c74ad251Schristos if (tlv_remaining < 1) 19810f74e101Schristos return(0); 1982c74ad251Schristos subtlv_sum_len=GET_U_1(tptr); /* read out subTLV length */ 1983c74ad251Schristos tptr++; 1984c74ad251Schristos tlv_remaining--; 1985c74ad251Schristos proc_bytes++; 1986c74ad251Schristos ND_PRINT(", %ssub-TLVs present",subtlv_sum_len ? "" : "no "); 19870f74e101Schristos if (subtlv_sum_len) { 1988c74ad251Schristos ND_PRINT(" (%u)", subtlv_sum_len); 1989fdccd7e4Schristos /* prepend the indent string */ 19900f74e101Schristos snprintf(ident_buffer, sizeof(ident_buffer), "%s ",ident); 1991c74ad251Schristos ident = ident_buffer; 1992c74ad251Schristos while (subtlv_sum_len != 0) { 1993c74ad251Schristos ND_TCHECK_2(tptr); 1994c74ad251Schristos if (tlv_remaining < 2) { 1995c74ad251Schristos ND_PRINT("%sRemaining data in TLV shorter than a subTLV header",ident); 1996c74ad251Schristos proc_bytes += tlv_remaining; 1997c74ad251Schristos break; 1998c74ad251Schristos } 1999c74ad251Schristos if (subtlv_sum_len < 2) { 2000c74ad251Schristos ND_PRINT("%sRemaining data in subTLVs shorter than a subTLV header",ident); 2001c74ad251Schristos proc_bytes += subtlv_sum_len; 2002c74ad251Schristos break; 2003c74ad251Schristos } 2004c74ad251Schristos subtlv_type=GET_U_1(tptr); 2005c74ad251Schristos subtlv_len=GET_U_1(tptr + 1); 2006c74ad251Schristos tptr += 2; 2007c74ad251Schristos tlv_remaining -= 2; 2008c74ad251Schristos subtlv_sum_len -= 2; 2009c74ad251Schristos proc_bytes += 2; 2010c74ad251Schristos ND_PRINT("%s%s subTLV #%u, length: %u", 2011c74ad251Schristos ident, tok2str(isis_ext_is_reach_subtlv_values, "unknown", subtlv_type), 2012c74ad251Schristos subtlv_type, subtlv_len); 2013c74ad251Schristos 2014c74ad251Schristos if (subtlv_sum_len < subtlv_len) { 2015c74ad251Schristos ND_PRINT(" (remaining data in subTLVs shorter than the current subTLV)"); 2016c74ad251Schristos proc_bytes += subtlv_sum_len; 2017c74ad251Schristos break; 2018c74ad251Schristos } 2019c74ad251Schristos 2020c74ad251Schristos if (tlv_remaining < subtlv_len) { 2021c74ad251Schristos ND_PRINT(" (> remaining tlv length)"); 2022c74ad251Schristos proc_bytes += tlv_remaining; 2023c74ad251Schristos break; 2024c74ad251Schristos } 2025c74ad251Schristos 2026c74ad251Schristos ND_TCHECK_LEN(tptr, subtlv_len); 2027c74ad251Schristos 2028c74ad251Schristos switch(subtlv_type) { 2029c74ad251Schristos case ISIS_SUBTLV_EXT_IS_REACH_ADMIN_GROUP: 2030c74ad251Schristos case ISIS_SUBTLV_EXT_IS_REACH_LINK_LOCAL_REMOTE_ID: 2031c74ad251Schristos case ISIS_SUBTLV_EXT_IS_REACH_LINK_REMOTE_ID: 2032c74ad251Schristos if (subtlv_len >= 4) { 2033c74ad251Schristos ND_PRINT(", 0x%08x", GET_BE_U_4(tptr)); 2034c74ad251Schristos if (subtlv_len == 8) /* rfc4205 */ 2035c74ad251Schristos ND_PRINT(", 0x%08x", GET_BE_U_4(tptr + 4)); 2036c74ad251Schristos } 2037c74ad251Schristos break; 2038c74ad251Schristos case ISIS_SUBTLV_EXT_IS_REACH_IPV4_INTF_ADDR: 2039c74ad251Schristos case ISIS_SUBTLV_EXT_IS_REACH_IPV4_NEIGHBOR_ADDR: 2040c74ad251Schristos if (subtlv_len >= sizeof(nd_ipv4)) 2041c74ad251Schristos ND_PRINT(", %s", GET_IPADDR_STRING(tptr)); 2042c74ad251Schristos break; 2043c74ad251Schristos case ISIS_SUBTLV_EXT_IS_REACH_MAX_LINK_BW : 2044c74ad251Schristos case ISIS_SUBTLV_EXT_IS_REACH_RESERVABLE_BW: 2045c74ad251Schristos if (subtlv_len >= 4) { 2046c74ad251Schristos bw.i = GET_BE_U_4(tptr); 2047c74ad251Schristos ND_PRINT(", %.3f Mbps", bw.f * 8 / 1000000); 2048c74ad251Schristos } 2049c74ad251Schristos break; 2050c74ad251Schristos case ISIS_SUBTLV_EXT_IS_REACH_UNRESERVED_BW : 2051c74ad251Schristos if (subtlv_len >= 32) { 2052c74ad251Schristos for (te_class = 0; te_class < 8; te_class++) { 2053c74ad251Schristos bw.i = GET_BE_U_4(tptr); 2054c74ad251Schristos ND_PRINT("%s TE-Class %u: %.3f Mbps", 2055c74ad251Schristos ident, 2056c74ad251Schristos te_class, 2057c74ad251Schristos bw.f * 8 / 1000000); 2058c74ad251Schristos tptr += 4; 2059c74ad251Schristos subtlv_len -= 4; 2060c74ad251Schristos subtlv_sum_len -= 4; 2061c74ad251Schristos proc_bytes += 4; 2062c74ad251Schristos } 2063c74ad251Schristos } 2064c74ad251Schristos break; 2065c74ad251Schristos case ISIS_SUBTLV_EXT_IS_REACH_BW_CONSTRAINTS: /* fall through */ 2066c74ad251Schristos case ISIS_SUBTLV_EXT_IS_REACH_BW_CONSTRAINTS_OLD: 2067c74ad251Schristos if (subtlv_len == 0) 2068c74ad251Schristos break; 2069c74ad251Schristos ND_PRINT("%sBandwidth Constraints Model ID: %s (%u)", 2070c74ad251Schristos ident, 2071c74ad251Schristos tok2str(diffserv_te_bc_values, "unknown", GET_U_1(tptr)), 2072c74ad251Schristos GET_U_1(tptr)); 2073c74ad251Schristos tptr++; 2074c74ad251Schristos subtlv_len--; 2075c74ad251Schristos subtlv_sum_len--; 2076c74ad251Schristos proc_bytes++; 2077c74ad251Schristos /* decode BCs until the subTLV ends */ 2078c74ad251Schristos for (te_class = 0; subtlv_len != 0; te_class++) { 2079c74ad251Schristos if (subtlv_len < 4) 2080c74ad251Schristos break; 2081c74ad251Schristos bw.i = GET_BE_U_4(tptr); 2082c74ad251Schristos ND_PRINT("%s Bandwidth constraint CT%u: %.3f Mbps", 2083c74ad251Schristos ident, 2084c74ad251Schristos te_class, 2085c74ad251Schristos bw.f * 8 / 1000000); 2086c74ad251Schristos tptr += 4; 2087c74ad251Schristos subtlv_len -= 4; 2088c74ad251Schristos subtlv_sum_len -= 4; 2089c74ad251Schristos proc_bytes += 4; 2090c74ad251Schristos } 2091c74ad251Schristos break; 2092c74ad251Schristos case ISIS_SUBTLV_EXT_IS_REACH_TE_METRIC: 2093c74ad251Schristos if (subtlv_len >= 3) 2094c74ad251Schristos ND_PRINT(", %u", GET_BE_U_3(tptr)); 2095c74ad251Schristos break; 2096c74ad251Schristos case ISIS_SUBTLV_EXT_IS_REACH_LINK_ATTRIBUTE: 2097c74ad251Schristos if (subtlv_len == 2) { 2098c74ad251Schristos ND_PRINT(", [ %s ] (0x%04x)", 2099c74ad251Schristos bittok2str(isis_subtlv_link_attribute_values, 2100c74ad251Schristos "Unknown", 2101c74ad251Schristos GET_BE_U_2(tptr)), 2102c74ad251Schristos GET_BE_U_2(tptr)); 2103c74ad251Schristos } 2104c74ad251Schristos break; 2105c74ad251Schristos case ISIS_SUBTLV_EXT_IS_REACH_LINK_PROTECTION_TYPE: 2106c74ad251Schristos if (subtlv_len >= 2) { 2107c74ad251Schristos ND_PRINT(", %s, Priority %u", 2108c74ad251Schristos bittok2str(gmpls_link_prot_values, "none", GET_U_1(tptr)), 2109c74ad251Schristos GET_U_1(tptr + 1)); 2110c74ad251Schristos } 2111c74ad251Schristos break; 2112c74ad251Schristos case ISIS_SUBTLV_SPB_METRIC: 2113c74ad251Schristos if (subtlv_len >= 6) { 2114c74ad251Schristos ND_PRINT(", LM: %u", GET_BE_U_3(tptr)); 2115c74ad251Schristos tptr += 3; 2116c74ad251Schristos subtlv_len -= 3; 2117c74ad251Schristos subtlv_sum_len -= 3; 2118c74ad251Schristos proc_bytes += 3; 2119c74ad251Schristos ND_PRINT(", P: %u", GET_U_1(tptr)); 2120c74ad251Schristos tptr++; 2121c74ad251Schristos subtlv_len--; 2122c74ad251Schristos subtlv_sum_len--; 2123c74ad251Schristos proc_bytes++; 2124c74ad251Schristos ND_PRINT(", P-ID: %u", GET_BE_U_2(tptr)); 2125c74ad251Schristos } 2126c74ad251Schristos break; 2127c74ad251Schristos case ISIS_SUBTLV_EXT_IS_REACH_INTF_SW_CAP_DESCR: 2128c74ad251Schristos if (subtlv_len >= 36) { 2129c74ad251Schristos gmpls_switch_cap = GET_U_1(tptr); 2130c74ad251Schristos ND_PRINT("%s Interface Switching Capability:%s", 2131c74ad251Schristos ident, 2132c74ad251Schristos tok2str(gmpls_switch_cap_values, "Unknown", gmpls_switch_cap)); 2133c74ad251Schristos ND_PRINT(", LSP Encoding: %s", 2134c74ad251Schristos tok2str(gmpls_encoding_values, "Unknown", GET_U_1((tptr + 1)))); 2135c74ad251Schristos tptr += 4; 2136c74ad251Schristos subtlv_len -= 4; 2137c74ad251Schristos subtlv_sum_len -= 4; 2138c74ad251Schristos proc_bytes += 4; 2139c74ad251Schristos ND_PRINT("%s Max LSP Bandwidth:", ident); 2140c74ad251Schristos for (priority_level = 0; priority_level < 8; priority_level++) { 2141c74ad251Schristos bw.i = GET_BE_U_4(tptr); 2142c74ad251Schristos ND_PRINT("%s priority level %u: %.3f Mbps", 2143c74ad251Schristos ident, 2144c74ad251Schristos priority_level, 2145c74ad251Schristos bw.f * 8 / 1000000); 2146c74ad251Schristos tptr += 4; 2147c74ad251Schristos subtlv_len -= 4; 2148c74ad251Schristos subtlv_sum_len -= 4; 2149c74ad251Schristos proc_bytes += 4; 2150c74ad251Schristos } 2151c74ad251Schristos switch (gmpls_switch_cap) { 2152c74ad251Schristos case GMPLS_PSC1: 2153c74ad251Schristos case GMPLS_PSC2: 2154c74ad251Schristos case GMPLS_PSC3: 2155c74ad251Schristos case GMPLS_PSC4: 2156c74ad251Schristos if (subtlv_len < 6) 2157c74ad251Schristos break; 2158c74ad251Schristos bw.i = GET_BE_U_4(tptr); 2159c74ad251Schristos ND_PRINT("%s Min LSP Bandwidth: %.3f Mbps", ident, bw.f * 8 / 1000000); 2160c74ad251Schristos ND_PRINT("%s Interface MTU: %u", ident, 2161c74ad251Schristos GET_BE_U_2(tptr + 4)); 2162c74ad251Schristos break; 2163c74ad251Schristos case GMPLS_TSC: 2164c74ad251Schristos if (subtlv_len < 8) 2165c74ad251Schristos break; 2166c74ad251Schristos bw.i = GET_BE_U_4(tptr); 2167c74ad251Schristos ND_PRINT("%s Min LSP Bandwidth: %.3f Mbps", ident, bw.f * 8 / 1000000); 2168c74ad251Schristos ND_PRINT("%s Indication %s", ident, 2169c74ad251Schristos tok2str(gmpls_switch_cap_tsc_indication_values, "Unknown (%u)", GET_U_1((tptr + 4)))); 2170c74ad251Schristos break; 2171c74ad251Schristos default: 2172c74ad251Schristos /* there is some optional stuff left to decode but this is as of yet 2173c74ad251Schristos not specified so just lets hexdump what is left */ 2174c74ad251Schristos if (subtlv_len != 0) { 2175c74ad251Schristos if (!print_unknown_data(ndo, tptr, "\n\t\t ", subtlv_len)) 21760f74e101Schristos return(0); 2177c74ad251Schristos } 2178c74ad251Schristos } 2179c74ad251Schristos } 2180c74ad251Schristos break; 2181c74ad251Schristos case ISIS_SUBTLV_EXT_IS_REACH_LAN_ADJ_SEGMENT_ID: 2182c74ad251Schristos if (subtlv_len >= 8) { 2183c74ad251Schristos ND_PRINT("%s Flags: [%s]", ident, 2184c74ad251Schristos bittok2str(isis_lan_adj_sid_flag_values, 2185c74ad251Schristos "none", 2186c74ad251Schristos GET_U_1(tptr))); 2187c74ad251Schristos int vflag = (GET_U_1(tptr) & 0x20) ? 1:0; 2188c74ad251Schristos int lflag = (GET_U_1(tptr) & 0x10) ? 1:0; 2189c74ad251Schristos tptr++; 2190c74ad251Schristos subtlv_len--; 2191c74ad251Schristos subtlv_sum_len--; 2192c74ad251Schristos proc_bytes++; 2193c74ad251Schristos ND_PRINT("%s Weight: %u", ident, GET_U_1(tptr)); 2194c74ad251Schristos tptr++; 2195c74ad251Schristos subtlv_len--; 2196c74ad251Schristos subtlv_sum_len--; 2197c74ad251Schristos proc_bytes++; 2198c74ad251Schristos if(subtlv_len>=SYSTEM_ID_LEN) { 2199c74ad251Schristos ND_TCHECK_LEN(tptr, SYSTEM_ID_LEN); 2200c74ad251Schristos ND_PRINT("%s Neighbor System-ID: %s", ident, 2201c74ad251Schristos isis_print_id(ndo, tptr, SYSTEM_ID_LEN)); 2202c74ad251Schristos } 2203c74ad251Schristos /* RFC 8667 section 2.2.2 */ 2204c74ad251Schristos /* if V-flag is set to 1 and L-flag is set to 1 ==> 3 octet label */ 2205c74ad251Schristos /* if V-flag is set to 0 and L-flag is set to 0 ==> 4 octet index */ 2206c74ad251Schristos if (vflag && lflag) { 2207c74ad251Schristos ND_PRINT("%s Label: %u", 2208c74ad251Schristos ident, GET_BE_U_3(tptr+SYSTEM_ID_LEN)); 2209c74ad251Schristos } else if ((!vflag) && (!lflag)) { 2210c74ad251Schristos ND_PRINT("%s Index: %u", 2211c74ad251Schristos ident, GET_BE_U_4(tptr+SYSTEM_ID_LEN)); 2212c74ad251Schristos } else 2213c74ad251Schristos nd_print_invalid(ndo); 2214c74ad251Schristos } 2215c74ad251Schristos break; 2216c74ad251Schristos default: 2217c74ad251Schristos if (!print_unknown_data(ndo, tptr, "\n\t\t ", subtlv_len)) 2218c74ad251Schristos return(0); 2219c74ad251Schristos break; 2220c74ad251Schristos } 2221c74ad251Schristos 22220f74e101Schristos tptr += subtlv_len; 2223c74ad251Schristos tlv_remaining -= subtlv_len; 2224c74ad251Schristos subtlv_sum_len -= subtlv_len; 2225c74ad251Schristos proc_bytes += subtlv_len; 22260f74e101Schristos } 22270f74e101Schristos } 22280f74e101Schristos return(proc_bytes); 2229c74ad251Schristos 2230c74ad251Schristos trunc: 2231c74ad251Schristos return(0); 22320f74e101Schristos } 22330f74e101Schristos 22340f74e101Schristos /* 22350f74e101Schristos * this is the common Multi Topology ID decoder 22360f74e101Schristos * it is called from various MT-TLVs (222,229,235,237) 22370f74e101Schristos */ 22380f74e101Schristos 2239c74ad251Schristos static uint8_t 2240b3a00663Schristos isis_print_mtid(netdissect_options *ndo, 2241c74ad251Schristos const uint8_t *tptr, const char *ident, u_int tlv_remaining) 2242ba2ff121Schristos { 2243c74ad251Schristos if (tlv_remaining < 2) 2244c74ad251Schristos goto trunc; 22450f74e101Schristos 2246c74ad251Schristos ND_PRINT("%s%s", 22470f74e101Schristos ident, 22480f74e101Schristos tok2str(isis_mt_values, 22490f74e101Schristos "Reserved for IETF Consensus", 2250c74ad251Schristos ISIS_MASK_MTID(GET_BE_U_2(tptr)))); 22510f74e101Schristos 2252c74ad251Schristos ND_PRINT(" Topology (0x%03x), Flags: [%s]", 2253c74ad251Schristos ISIS_MASK_MTID(GET_BE_U_2(tptr)), 2254c74ad251Schristos bittok2str(isis_mt_flag_values, "none",ISIS_MASK_MTFLAGS(GET_BE_U_2(tptr)))); 22550f74e101Schristos 22560f74e101Schristos return(2); 2257c74ad251Schristos trunc: 2258c74ad251Schristos return 0; 22590f74e101Schristos } 22600f74e101Schristos 22610f74e101Schristos /* 22620f74e101Schristos * this is the common extended IP reach decoder 22630f74e101Schristos * it is called from TLVs (135,235,236,237) 22640f74e101Schristos * we process the TLV and optional subTLVs and return 22650f74e101Schristos * the amount of processed bytes 22660f74e101Schristos */ 22670f74e101Schristos 2268c74ad251Schristos static u_int 2269b3a00663Schristos isis_print_extd_ip_reach(netdissect_options *ndo, 2270ba2ff121Schristos const uint8_t *tptr, const char *ident, uint16_t afi) 2271ba2ff121Schristos { 22720f74e101Schristos char ident_buffer[20]; 2273c74ad251Schristos uint8_t prefix[sizeof(nd_ipv6)]; /* shared copy buffer for IPv4 and IPv6 prefixes */ 22740f74e101Schristos u_int metric, status_byte, bit_length, byte_length, sublen, processed, subtlvtype, subtlvlen; 22750f74e101Schristos 2276c74ad251Schristos metric = GET_BE_U_4(tptr); 22770f74e101Schristos processed=4; 22780f74e101Schristos tptr+=4; 22790f74e101Schristos 22800f74e101Schristos if (afi == AF_INET) { 2281c74ad251Schristos status_byte=GET_U_1(tptr); 2282c74ad251Schristos tptr++; 22830f74e101Schristos bit_length = status_byte&0x3f; 22840f74e101Schristos if (bit_length > 32) { 2285c74ad251Schristos ND_PRINT("%sIPv4 prefix: bad bit length %u", 22860f74e101Schristos ident, 2287c74ad251Schristos bit_length); 22880f74e101Schristos return (0); 22890f74e101Schristos } 22900f74e101Schristos processed++; 22910f74e101Schristos } else if (afi == AF_INET6) { 2292c74ad251Schristos status_byte=GET_U_1(tptr); 2293c74ad251Schristos bit_length=GET_U_1(tptr + 1); 22940f74e101Schristos if (bit_length > 128) { 2295c74ad251Schristos ND_PRINT("%sIPv6 prefix: bad bit length %u", 22960f74e101Schristos ident, 2297c74ad251Schristos bit_length); 22980f74e101Schristos return (0); 22990f74e101Schristos } 2300c74ad251Schristos tptr+=2; 23010f74e101Schristos processed+=2; 23020f74e101Schristos } else 23030f74e101Schristos return (0); /* somebody is fooling us */ 23040f74e101Schristos 23050f74e101Schristos byte_length = (bit_length + 7) / 8; /* prefix has variable length encoding */ 23060f74e101Schristos 2307c74ad251Schristos memset(prefix, 0, sizeof(prefix)); /* clear the copy buffer */ 2308c74ad251Schristos GET_CPY_BYTES(prefix,tptr,byte_length); /* copy as much as is stored in the TLV */ 23090f74e101Schristos tptr+=byte_length; 23100f74e101Schristos processed+=byte_length; 23110f74e101Schristos 23120f74e101Schristos if (afi == AF_INET) 2313c74ad251Schristos ND_PRINT("%sIPv4 prefix: %15s/%u", 23140f74e101Schristos ident, 2315c74ad251Schristos ipaddr_string(ndo, prefix), /* local buffer, not packet data; don't use GET_IPADDR_STRING() */ 2316c74ad251Schristos bit_length); 2317fdccd7e4Schristos else if (afi == AF_INET6) 2318c74ad251Schristos ND_PRINT("%sIPv6 prefix: %s/%u", 23190f74e101Schristos ident, 2320c74ad251Schristos ip6addr_string(ndo, prefix), /* local buffer, not packet data; don't use GET_IP6ADDR_STRING() */ 2321c74ad251Schristos bit_length); 23220f74e101Schristos 2323c74ad251Schristos ND_PRINT(", Distribution: %s, Metric: %u", 23240f74e101Schristos ISIS_MASK_TLV_EXTD_IP_UPDOWN(status_byte) ? "down" : "up", 2325c74ad251Schristos metric); 23260f74e101Schristos 23270f74e101Schristos if (afi == AF_INET && ISIS_MASK_TLV_EXTD_IP_SUBTLV(status_byte)) 2328c74ad251Schristos ND_PRINT(", sub-TLVs present"); 2329fdccd7e4Schristos else if (afi == AF_INET6) 2330c74ad251Schristos ND_PRINT(", %s%s", 23310f74e101Schristos ISIS_MASK_TLV_EXTD_IP6_IE(status_byte) ? "External" : "Internal", 2332c74ad251Schristos ISIS_MASK_TLV_EXTD_IP6_SUBTLV(status_byte) ? ", sub-TLVs present" : ""); 23330f74e101Schristos 23340f74e101Schristos if ((afi == AF_INET && ISIS_MASK_TLV_EXTD_IP_SUBTLV(status_byte)) 23350f74e101Schristos || (afi == AF_INET6 && ISIS_MASK_TLV_EXTD_IP6_SUBTLV(status_byte)) 23360f74e101Schristos ) { 23370f74e101Schristos /* assume that one prefix can hold more 23380f74e101Schristos than one subTLV - therefore the first byte must reflect 23390f74e101Schristos the aggregate bytecount of the subTLVs for this prefix 23400f74e101Schristos */ 2341c74ad251Schristos sublen=GET_U_1(tptr); 2342c74ad251Schristos tptr++; 23430f74e101Schristos processed+=sublen+1; 2344c74ad251Schristos ND_PRINT(" (%u)", sublen); /* print out subTLV length */ 23450f74e101Schristos 23460f74e101Schristos while (sublen>0) { 2347c74ad251Schristos subtlvtype=GET_U_1(tptr); 2348c74ad251Schristos subtlvlen=GET_U_1(tptr + 1); 2349c74ad251Schristos tptr+=2; 2350fdccd7e4Schristos /* prepend the indent string */ 23510f74e101Schristos snprintf(ident_buffer, sizeof(ident_buffer), "%s ",ident); 2352b3a00663Schristos if (!isis_print_ip_reach_subtlv(ndo, tptr, subtlvtype, subtlvlen, ident_buffer)) 23530f74e101Schristos return(0); 23540f74e101Schristos tptr+=subtlvlen; 23550f74e101Schristos sublen-=(subtlvlen+2); 23560f74e101Schristos } 23570f74e101Schristos } 23580f74e101Schristos return (processed); 23590f74e101Schristos } 23600f74e101Schristos 2361c74ad251Schristos static void 2362c74ad251Schristos isis_print_router_cap_subtlv(netdissect_options *ndo, const uint8_t *tptr, uint8_t tlen) 2363c74ad251Schristos { 2364c74ad251Schristos uint8_t subt, subl; 2365c74ad251Schristos 2366c74ad251Schristos while (tlen >= 2) { 2367c74ad251Schristos subt = GET_U_1(tptr); 2368c74ad251Schristos subl = GET_U_1(tptr+1); 2369c74ad251Schristos tlen -= 2; 2370c74ad251Schristos tptr += 2; 2371c74ad251Schristos 2372c74ad251Schristos /* first lets see if we know the subTLVs name*/ 2373c74ad251Schristos ND_PRINT("\n\t\t%s subTLV #%u, length: %u", 2374c74ad251Schristos tok2str(isis_router_capability_subtlv_values, "unknown", subt), 2375c74ad251Schristos subt, subl); 2376c74ad251Schristos 2377c74ad251Schristos /* 2378c74ad251Schristos * Boundary check. 2379c74ad251Schristos */ 2380c74ad251Schristos if (subl > tlen) { 2381c74ad251Schristos break; 2382c74ad251Schristos } 2383c74ad251Schristos ND_TCHECK_LEN(tptr, subl); 2384c74ad251Schristos 2385c74ad251Schristos switch (subt) { 2386c74ad251Schristos case ISIS_SUBTLV_ROUTER_CAP_SR: 2387c74ad251Schristos { 2388c74ad251Schristos uint8_t flags, sid_tlen, sid_type, sid_len; 2389c74ad251Schristos uint32_t range; 2390c74ad251Schristos const uint8_t *sid_ptr; 2391c74ad251Schristos 2392c74ad251Schristos flags = GET_U_1(tptr); 2393c74ad251Schristos range = GET_BE_U_3(tptr+1); 2394c74ad251Schristos ND_PRINT(", Flags [%s], Range %u", 2395c74ad251Schristos bittok2str(isis_router_capability_sr_flags, "None", flags), 2396c74ad251Schristos range); 2397c74ad251Schristos sid_ptr = tptr + 4; 2398c74ad251Schristos sid_tlen = subl - 4; 2399c74ad251Schristos 2400c74ad251Schristos while (sid_tlen >= 5) { 2401c74ad251Schristos sid_type = GET_U_1(sid_ptr); 2402c74ad251Schristos sid_len = GET_U_1(sid_ptr+1); 2403c74ad251Schristos sid_tlen -= 2; 2404c74ad251Schristos sid_ptr += 2; 2405c74ad251Schristos 2406c74ad251Schristos /* 2407c74ad251Schristos * Boundary check. 2408c74ad251Schristos */ 2409c74ad251Schristos if (sid_len > sid_tlen) { 2410c74ad251Schristos break; 2411c74ad251Schristos } 2412c74ad251Schristos 2413c74ad251Schristos switch (sid_type) { 2414c74ad251Schristos case 1: 2415c74ad251Schristos if (sid_len == 3) { 2416c74ad251Schristos ND_PRINT(", SID value %u", GET_BE_U_3(sid_ptr)); 2417c74ad251Schristos } else if (sid_len == 4) { 2418c74ad251Schristos ND_PRINT(", SID value %u", GET_BE_U_4(sid_ptr)); 2419c74ad251Schristos } else { 2420c74ad251Schristos ND_PRINT(", Unknown SID length%u", sid_len); 2421c74ad251Schristos } 2422c74ad251Schristos break; 2423c74ad251Schristos default: 2424c74ad251Schristos print_unknown_data(ndo, sid_ptr, "\n\t\t ", sid_len); 2425c74ad251Schristos } 2426c74ad251Schristos 2427c74ad251Schristos sid_ptr += sid_len; 2428c74ad251Schristos sid_tlen -= sid_len; 2429c74ad251Schristos } 2430c74ad251Schristos } 2431c74ad251Schristos break; 2432c74ad251Schristos default: 2433c74ad251Schristos print_unknown_data(ndo, tptr, "\n\t\t", subl); 2434c74ad251Schristos break; 2435c74ad251Schristos } 2436c74ad251Schristos 2437c74ad251Schristos tlen -= subl; 2438c74ad251Schristos tptr += subl; 2439c74ad251Schristos } 2440c74ad251Schristos trunc: 2441c74ad251Schristos return; 2442c74ad251Schristos } 2443c74ad251Schristos 24440f74e101Schristos /* 2445fdccd7e4Schristos * Clear checksum and lifetime prior to signature verification. 2446fdccd7e4Schristos */ 2447fdccd7e4Schristos static void 2448fdccd7e4Schristos isis_clear_checksum_lifetime(void *header) 2449fdccd7e4Schristos { 2450fdccd7e4Schristos struct isis_lsp_header *header_lsp = (struct isis_lsp_header *) header; 2451fdccd7e4Schristos 2452fdccd7e4Schristos header_lsp->checksum[0] = 0; 2453fdccd7e4Schristos header_lsp->checksum[1] = 0; 2454fdccd7e4Schristos header_lsp->remaining_lifetime[0] = 0; 2455fdccd7e4Schristos header_lsp->remaining_lifetime[1] = 0; 2456fdccd7e4Schristos } 2457fdccd7e4Schristos 2458fdccd7e4Schristos /* 24590f74e101Schristos * isis_print 24600f74e101Schristos * Decode IS-IS packets. Return 0 on error. 24610f74e101Schristos */ 24620f74e101Schristos 2463c74ad251Schristos #define INVALID_OR_DECREMENT(length,decr) \ 2464c74ad251Schristos if ((length) < (decr)) { \ 2465c74ad251Schristos ND_PRINT(" [packet length %u < %zu]", (length), (decr)); \ 2466c74ad251Schristos nd_print_invalid(ndo); \ 2467c74ad251Schristos return 1; \ 2468c74ad251Schristos } \ 2469c74ad251Schristos length -= (decr); 2470c74ad251Schristos 2471b3a00663Schristos static int 2472b3a00663Schristos isis_print(netdissect_options *ndo, 2473b3a00663Schristos const uint8_t *p, u_int length) 24740f74e101Schristos { 24750f74e101Schristos const struct isis_common_header *isis_header; 24760f74e101Schristos 24770f74e101Schristos const struct isis_iih_lan_header *header_iih_lan; 24780f74e101Schristos const struct isis_iih_ptp_header *header_iih_ptp; 2479fdccd7e4Schristos const struct isis_lsp_header *header_lsp; 24800f74e101Schristos const struct isis_csnp_header *header_csnp; 24810f74e101Schristos const struct isis_psnp_header *header_psnp; 24820f74e101Schristos 24830f74e101Schristos const struct isis_tlv_lsp *tlv_lsp; 24840f74e101Schristos const struct isis_tlv_ptp_adj *tlv_ptp_adj; 24850f74e101Schristos const struct isis_tlv_is_reach *tlv_is_reach; 24860f74e101Schristos const struct isis_tlv_es_reach *tlv_es_reach; 24870f74e101Schristos 2488c74ad251Schristos uint8_t version, pdu_version, fixed_len; 2489c74ad251Schristos uint8_t pdu_type, pdu_max_area, max_area, pdu_id_length, id_length, tlv_type, tlv_len, tlen, alen, prefix_len; 2490c74ad251Schristos u_int ext_is_len, ext_ip_len; 2491c74ad251Schristos uint8_t mt_len; 2492c74ad251Schristos uint8_t isis_subtlv_idrp; 2493b3a00663Schristos const uint8_t *optr, *pptr, *tptr; 2494c74ad251Schristos u_int packet_len; 2495c74ad251Schristos u_short pdu_len, key_id; 2496c74ad251Schristos u_int i,vendor_id, num_vals; 2497c74ad251Schristos uint8_t auth_type; 2498c74ad251Schristos uint8_t num_system_ids; 24990f74e101Schristos int sigcheck; 25000f74e101Schristos 2501c74ad251Schristos ndo->ndo_protocol = "isis"; 25020f74e101Schristos packet_len=length; 25030f74e101Schristos optr = p; /* initialize the _o_riginal pointer to the packet start - 25040f74e101Schristos need it for parsing the checksum TLV and authentication 25050f74e101Schristos TLV verification */ 25060f74e101Schristos isis_header = (const struct isis_common_header *)p; 2507c74ad251Schristos ND_TCHECK_SIZE(isis_header); 250872c96ff3Schristos if (length < ISIS_COMMON_HEADER_SIZE) 250972c96ff3Schristos goto trunc; 25100f74e101Schristos pptr = p+(ISIS_COMMON_HEADER_SIZE); 25110f74e101Schristos header_iih_lan = (const struct isis_iih_lan_header *)pptr; 25120f74e101Schristos header_iih_ptp = (const struct isis_iih_ptp_header *)pptr; 2513fdccd7e4Schristos header_lsp = (const struct isis_lsp_header *)pptr; 25140f74e101Schristos header_csnp = (const struct isis_csnp_header *)pptr; 25150f74e101Schristos header_psnp = (const struct isis_psnp_header *)pptr; 25160f74e101Schristos 2517b3a00663Schristos if (!ndo->ndo_eflag) 2518c74ad251Schristos ND_PRINT("IS-IS"); 25190f74e101Schristos 25200f74e101Schristos /* 25210f74e101Schristos * Sanity checking of the header. 25220f74e101Schristos */ 25230f74e101Schristos 2524c74ad251Schristos version = GET_U_1(isis_header->version); 2525c74ad251Schristos if (version != ISIS_VERSION) { 2526c74ad251Schristos ND_PRINT("version %u packet not supported", version); 25270f74e101Schristos return (0); 25280f74e101Schristos } 25290f74e101Schristos 2530c74ad251Schristos pdu_id_length = GET_U_1(isis_header->id_length); 2531c74ad251Schristos if ((pdu_id_length != SYSTEM_ID_LEN) && (pdu_id_length != 0)) { 2532c74ad251Schristos ND_PRINT("system ID length of %u is not supported", 2533c74ad251Schristos pdu_id_length); 25340f74e101Schristos return (0); 25350f74e101Schristos } 25360f74e101Schristos 2537c74ad251Schristos pdu_version = GET_U_1(isis_header->pdu_version); 2538c74ad251Schristos if (pdu_version != ISIS_VERSION) { 2539c74ad251Schristos ND_PRINT("version %u packet not supported", pdu_version); 25400f74e101Schristos return (0); 25410f74e101Schristos } 25420f74e101Schristos 2543c74ad251Schristos fixed_len = GET_U_1(isis_header->fixed_len); 2544c74ad251Schristos if (length < fixed_len) { 2545c74ad251Schristos ND_PRINT("fixed header length %u > packet length %u", fixed_len, length); 254672c96ff3Schristos return (0); 254772c96ff3Schristos } 254872c96ff3Schristos 2549c74ad251Schristos if (fixed_len < ISIS_COMMON_HEADER_SIZE) { 2550c74ad251Schristos ND_PRINT("fixed header length %u < minimum header size %u", fixed_len, (u_int)ISIS_COMMON_HEADER_SIZE); 255172c96ff3Schristos return (0); 255272c96ff3Schristos } 255372c96ff3Schristos 2554c74ad251Schristos pdu_max_area = GET_U_1(isis_header->max_area); 2555c74ad251Schristos switch(pdu_max_area) { 25560f74e101Schristos case 0: 25570f74e101Schristos max_area = 3; /* silly shit */ 25580f74e101Schristos break; 25590f74e101Schristos case 255: 2560c74ad251Schristos ND_PRINT("bad packet -- 255 areas"); 25610f74e101Schristos return (0); 25620f74e101Schristos default: 2563c74ad251Schristos max_area = pdu_max_area; 25640f74e101Schristos break; 25650f74e101Schristos } 25660f74e101Schristos 2567c74ad251Schristos switch(pdu_id_length) { 25680f74e101Schristos case 0: 25690f74e101Schristos id_length = 6; /* silly shit again */ 25700f74e101Schristos break; 2571c74ad251Schristos case 1: /* 1-8 are valid sys-ID lengths */ 25720f74e101Schristos case 2: 25730f74e101Schristos case 3: 25740f74e101Schristos case 4: 25750f74e101Schristos case 5: 25760f74e101Schristos case 6: 25770f74e101Schristos case 7: 25780f74e101Schristos case 8: 2579c74ad251Schristos id_length = pdu_id_length; 25800f74e101Schristos break; 25810f74e101Schristos case 255: 25820f74e101Schristos id_length = 0; /* entirely useless */ 25830f74e101Schristos break; 25840f74e101Schristos default: 2585c74ad251Schristos id_length = pdu_id_length; 25860f74e101Schristos break; 25870f74e101Schristos } 25880f74e101Schristos 25890f74e101Schristos /* toss any non 6-byte sys-ID len PDUs */ 25900f74e101Schristos if (id_length != 6 ) { 2591c74ad251Schristos ND_PRINT("bad packet -- illegal sys-ID length (%u)", id_length); 25920f74e101Schristos return (0); 25930f74e101Schristos } 25940f74e101Schristos 2595c74ad251Schristos pdu_type = GET_U_1(isis_header->pdu_type); 25960f74e101Schristos 25970f74e101Schristos /* in non-verbose mode print the basic PDU Type plus PDU specific brief information*/ 259872c96ff3Schristos if (ndo->ndo_vflag == 0) { 2599c74ad251Schristos ND_PRINT("%s%s", 2600b3a00663Schristos ndo->ndo_eflag ? "" : ", ", 2601c74ad251Schristos tok2str(isis_pdu_values, "unknown PDU-Type %u", pdu_type)); 260272c96ff3Schristos } else { 26030f74e101Schristos /* ok they seem to want to know everything - lets fully decode it */ 2604c74ad251Schristos ND_PRINT("%slength %u", ndo->ndo_eflag ? "" : ", ", length); 26050f74e101Schristos 2606c74ad251Schristos ND_PRINT("\n\t%s, hlen: %u, v: %u, pdu-v: %u, sys-id-len: %u (%u), max-area: %u (%u)", 26070f74e101Schristos tok2str(isis_pdu_values, 26080f74e101Schristos "unknown, type %u", 26090f74e101Schristos pdu_type), 2610c74ad251Schristos fixed_len, 2611c74ad251Schristos version, 2612c74ad251Schristos pdu_version, 26130f74e101Schristos id_length, 2614c74ad251Schristos pdu_id_length, 26150f74e101Schristos max_area, 2616c74ad251Schristos pdu_max_area); 26170f74e101Schristos 2618b3a00663Schristos if (ndo->ndo_vflag > 1) { 2619b3a00663Schristos if (!print_unknown_data(ndo, optr, "\n\t", 8)) /* provide the _o_riginal pointer */ 26200f74e101Schristos return (0); /* for optionally debugging the common header */ 26210f74e101Schristos } 262272c96ff3Schristos } 26230f74e101Schristos 26240f74e101Schristos switch (pdu_type) { 26250f74e101Schristos 26260f74e101Schristos case ISIS_PDU_L1_LAN_IIH: 26270f74e101Schristos case ISIS_PDU_L2_LAN_IIH: 2628c74ad251Schristos if (fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE)) { 2629c74ad251Schristos ND_PRINT(", bogus fixed header length %u should be %zu", 2630c74ad251Schristos fixed_len, ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE); 26310f74e101Schristos return (0); 26320f74e101Schristos } 2633c74ad251Schristos ND_TCHECK_SIZE(header_iih_lan); 263472c96ff3Schristos if (length < ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE) 263572c96ff3Schristos goto trunc; 263672c96ff3Schristos if (ndo->ndo_vflag == 0) { 2637c74ad251Schristos ND_PRINT(", src-id %s", 2638c74ad251Schristos isis_print_id(ndo, header_iih_lan->source_id, SYSTEM_ID_LEN)); 2639c74ad251Schristos ND_PRINT(", lan-id %s, prio %u", 2640c74ad251Schristos isis_print_id(ndo, header_iih_lan->lan_id,NODE_ID_LEN), 2641c74ad251Schristos GET_U_1(header_iih_lan->priority)); 2642c74ad251Schristos ND_PRINT(", length %u", length); 264372c96ff3Schristos return (1); 264472c96ff3Schristos } 2645c74ad251Schristos pdu_len=GET_BE_U_2(header_iih_lan->pdu_len); 26460f74e101Schristos if (packet_len>pdu_len) { 26470f74e101Schristos packet_len=pdu_len; /* do TLV decoding as long as it makes sense */ 26480f74e101Schristos length=pdu_len; 26490f74e101Schristos } 26500f74e101Schristos 2651c74ad251Schristos ND_PRINT("\n\t source-id: %s, holding time: %us, Flags: [%s]", 2652c74ad251Schristos isis_print_id(ndo, header_iih_lan->source_id,SYSTEM_ID_LEN), 2653c74ad251Schristos GET_BE_U_2(header_iih_lan->holding_time), 26540f74e101Schristos tok2str(isis_iih_circuit_type_values, 26550f74e101Schristos "unknown circuit type 0x%02x", 2656c74ad251Schristos GET_U_1(header_iih_lan->circuit_type))); 26570f74e101Schristos 2658c74ad251Schristos ND_PRINT("\n\t lan-id: %s, Priority: %u, PDU length: %u", 2659c74ad251Schristos isis_print_id(ndo, header_iih_lan->lan_id, NODE_ID_LEN), 2660c74ad251Schristos GET_U_1(header_iih_lan->priority) & ISIS_LAN_PRIORITY_MASK, 2661c74ad251Schristos pdu_len); 26620f74e101Schristos 2663b3a00663Schristos if (ndo->ndo_vflag > 1) { 2664b3a00663Schristos if (!print_unknown_data(ndo, pptr, "\n\t ", ISIS_IIH_LAN_HEADER_SIZE)) 26650f74e101Schristos return (0); 26660f74e101Schristos } 26670f74e101Schristos 2668c74ad251Schristos INVALID_OR_DECREMENT(packet_len,ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE); 26690f74e101Schristos pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE); 26700f74e101Schristos break; 26710f74e101Schristos 26720f74e101Schristos case ISIS_PDU_PTP_IIH: 2673c74ad251Schristos if (fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE)) { 2674c74ad251Schristos ND_PRINT(", bogus fixed header length %u should be %zu", 2675c74ad251Schristos fixed_len, ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE); 26760f74e101Schristos return (0); 26770f74e101Schristos } 2678c74ad251Schristos ND_TCHECK_SIZE(header_iih_ptp); 267972c96ff3Schristos if (length < ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE) 268072c96ff3Schristos goto trunc; 268172c96ff3Schristos if (ndo->ndo_vflag == 0) { 2682c74ad251Schristos ND_PRINT(", src-id %s", isis_print_id(ndo, header_iih_ptp->source_id, SYSTEM_ID_LEN)); 2683c74ad251Schristos ND_PRINT(", length %u", length); 268472c96ff3Schristos return (1); 268572c96ff3Schristos } 2686c74ad251Schristos pdu_len=GET_BE_U_2(header_iih_ptp->pdu_len); 26870f74e101Schristos if (packet_len>pdu_len) { 26880f74e101Schristos packet_len=pdu_len; /* do TLV decoding as long as it makes sense */ 26890f74e101Schristos length=pdu_len; 26900f74e101Schristos } 26910f74e101Schristos 2692c74ad251Schristos ND_PRINT("\n\t source-id: %s, holding time: %us, Flags: [%s]", 2693c74ad251Schristos isis_print_id(ndo, header_iih_ptp->source_id,SYSTEM_ID_LEN), 2694c74ad251Schristos GET_BE_U_2(header_iih_ptp->holding_time), 26950f74e101Schristos tok2str(isis_iih_circuit_type_values, 26960f74e101Schristos "unknown circuit type 0x%02x", 2697c74ad251Schristos GET_U_1(header_iih_ptp->circuit_type))); 26980f74e101Schristos 2699c74ad251Schristos ND_PRINT("\n\t circuit-id: 0x%02x, PDU length: %u", 2700c74ad251Schristos GET_U_1(header_iih_ptp->circuit_id), 2701c74ad251Schristos pdu_len); 27020f74e101Schristos 2703b3a00663Schristos if (ndo->ndo_vflag > 1) { 2704b3a00663Schristos if (!print_unknown_data(ndo, pptr, "\n\t ", ISIS_IIH_PTP_HEADER_SIZE)) 27050f74e101Schristos return (0); 27060f74e101Schristos } 2707c74ad251Schristos INVALID_OR_DECREMENT(packet_len,ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE); 27080f74e101Schristos pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE); 27090f74e101Schristos break; 27100f74e101Schristos 27110f74e101Schristos case ISIS_PDU_L1_LSP: 27120f74e101Schristos case ISIS_PDU_L2_LSP: 2713c74ad251Schristos if (fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE)) { 2714c74ad251Schristos ND_PRINT(", bogus fixed header length %u should be %zu", 2715c74ad251Schristos fixed_len, ISIS_LSP_HEADER_SIZE); 27160f74e101Schristos return (0); 27170f74e101Schristos } 2718c74ad251Schristos ND_TCHECK_SIZE(header_lsp); 271972c96ff3Schristos if (length < ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE) 272072c96ff3Schristos goto trunc; 272172c96ff3Schristos if (ndo->ndo_vflag == 0) { 2722c74ad251Schristos ND_PRINT(", lsp-id %s, seq 0x%08x, lifetime %5us", 2723c74ad251Schristos isis_print_id(ndo, header_lsp->lsp_id, LSP_ID_LEN), 2724c74ad251Schristos GET_BE_U_4(header_lsp->sequence_number), 2725c74ad251Schristos GET_BE_U_2(header_lsp->remaining_lifetime)); 2726c74ad251Schristos ND_PRINT(", length %u", length); 272772c96ff3Schristos return (1); 272872c96ff3Schristos } 2729c74ad251Schristos pdu_len=GET_BE_U_2(header_lsp->pdu_len); 27300f74e101Schristos if (packet_len>pdu_len) { 27310f74e101Schristos packet_len=pdu_len; /* do TLV decoding as long as it makes sense */ 27320f74e101Schristos length=pdu_len; 27330f74e101Schristos } 27340f74e101Schristos 2735c74ad251Schristos ND_PRINT("\n\t lsp-id: %s, seq: 0x%08x, lifetime: %5us\n\t chksum: 0x%04x", 2736c74ad251Schristos isis_print_id(ndo, header_lsp->lsp_id, LSP_ID_LEN), 2737c74ad251Schristos GET_BE_U_4(header_lsp->sequence_number), 2738c74ad251Schristos GET_BE_U_2(header_lsp->remaining_lifetime), 2739c74ad251Schristos GET_BE_U_2(header_lsp->checksum)); 27400f74e101Schristos 274172c96ff3Schristos osi_print_cksum(ndo, (const uint8_t *)header_lsp->lsp_id, 2742c74ad251Schristos GET_BE_U_2(header_lsp->checksum), 274372c96ff3Schristos 12, length-12); 27440f74e101Schristos 2745c74ad251Schristos ND_PRINT(", PDU length: %u, Flags: [ %s", 27460f74e101Schristos pdu_len, 2747c74ad251Schristos ISIS_MASK_LSP_OL_BIT(header_lsp->typeblock) ? "Overload bit set, " : ""); 27480f74e101Schristos 27490f74e101Schristos if (ISIS_MASK_LSP_ATT_BITS(header_lsp->typeblock)) { 2750c74ad251Schristos ND_PRINT("%s", ISIS_MASK_LSP_ATT_DEFAULT_BIT(header_lsp->typeblock) ? "default " : ""); 2751c74ad251Schristos ND_PRINT("%s", ISIS_MASK_LSP_ATT_DELAY_BIT(header_lsp->typeblock) ? "delay " : ""); 2752c74ad251Schristos ND_PRINT("%s", ISIS_MASK_LSP_ATT_EXPENSE_BIT(header_lsp->typeblock) ? "expense " : ""); 2753c74ad251Schristos ND_PRINT("%s", ISIS_MASK_LSP_ATT_ERROR_BIT(header_lsp->typeblock) ? "error " : ""); 2754c74ad251Schristos ND_PRINT("ATT bit set, "); 27550f74e101Schristos } 2756c74ad251Schristos ND_PRINT("%s", ISIS_MASK_LSP_PARTITION_BIT(header_lsp->typeblock) ? "P bit set, " : ""); 2757c74ad251Schristos ND_PRINT("%s ]", tok2str(isis_lsp_istype_values, "Unknown(0x%x)", 2758c74ad251Schristos ISIS_MASK_LSP_ISTYPE_BITS(header_lsp->typeblock))); 27590f74e101Schristos 2760b3a00663Schristos if (ndo->ndo_vflag > 1) { 2761b3a00663Schristos if (!print_unknown_data(ndo, pptr, "\n\t ", ISIS_LSP_HEADER_SIZE)) 27620f74e101Schristos return (0); 27630f74e101Schristos } 27640f74e101Schristos 2765c74ad251Schristos INVALID_OR_DECREMENT(packet_len,ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE); 27660f74e101Schristos pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE); 27670f74e101Schristos break; 27680f74e101Schristos 27690f74e101Schristos case ISIS_PDU_L1_CSNP: 27700f74e101Schristos case ISIS_PDU_L2_CSNP: 2771c74ad251Schristos if (fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE)) { 2772c74ad251Schristos ND_PRINT(", bogus fixed header length %u should be %zu", 2773c74ad251Schristos fixed_len, ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE); 27740f74e101Schristos return (0); 27750f74e101Schristos } 2776c74ad251Schristos ND_TCHECK_SIZE(header_csnp); 277772c96ff3Schristos if (length < ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE) 277872c96ff3Schristos goto trunc; 277972c96ff3Schristos if (ndo->ndo_vflag == 0) { 2780c74ad251Schristos ND_PRINT(", src-id %s", isis_print_id(ndo, header_csnp->source_id, NODE_ID_LEN)); 2781c74ad251Schristos ND_PRINT(", length %u", length); 278272c96ff3Schristos return (1); 278372c96ff3Schristos } 2784c74ad251Schristos pdu_len=GET_BE_U_2(header_csnp->pdu_len); 27850f74e101Schristos if (packet_len>pdu_len) { 27860f74e101Schristos packet_len=pdu_len; /* do TLV decoding as long as it makes sense */ 27870f74e101Schristos length=pdu_len; 27880f74e101Schristos } 27890f74e101Schristos 2790c74ad251Schristos ND_PRINT("\n\t source-id: %s, PDU length: %u", 2791c74ad251Schristos isis_print_id(ndo, header_csnp->source_id, NODE_ID_LEN), 2792c74ad251Schristos pdu_len); 2793c74ad251Schristos ND_PRINT("\n\t start lsp-id: %s", 2794c74ad251Schristos isis_print_id(ndo, header_csnp->start_lsp_id, LSP_ID_LEN)); 2795c74ad251Schristos ND_PRINT("\n\t end lsp-id: %s", 2796c74ad251Schristos isis_print_id(ndo, header_csnp->end_lsp_id, LSP_ID_LEN)); 27970f74e101Schristos 2798b3a00663Schristos if (ndo->ndo_vflag > 1) { 2799b3a00663Schristos if (!print_unknown_data(ndo, pptr, "\n\t ", ISIS_CSNP_HEADER_SIZE)) 28000f74e101Schristos return (0); 28010f74e101Schristos } 28020f74e101Schristos 2803c74ad251Schristos INVALID_OR_DECREMENT(packet_len,ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE); 28040f74e101Schristos pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE); 28050f74e101Schristos break; 28060f74e101Schristos 28070f74e101Schristos case ISIS_PDU_L1_PSNP: 28080f74e101Schristos case ISIS_PDU_L2_PSNP: 2809c74ad251Schristos if (fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE)) { 2810c74ad251Schristos ND_PRINT("- bogus fixed header length %u should be %zu", 2811c74ad251Schristos fixed_len, ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE); 28120f74e101Schristos return (0); 28130f74e101Schristos } 2814c74ad251Schristos ND_TCHECK_SIZE(header_psnp); 281572c96ff3Schristos if (length < ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE) 281672c96ff3Schristos goto trunc; 281772c96ff3Schristos if (ndo->ndo_vflag == 0) { 2818c74ad251Schristos ND_PRINT(", src-id %s", isis_print_id(ndo, header_psnp->source_id, NODE_ID_LEN)); 2819c74ad251Schristos ND_PRINT(", length %u", length); 282072c96ff3Schristos return (1); 282172c96ff3Schristos } 2822c74ad251Schristos pdu_len=GET_BE_U_2(header_psnp->pdu_len); 28230f74e101Schristos if (packet_len>pdu_len) { 28240f74e101Schristos packet_len=pdu_len; /* do TLV decoding as long as it makes sense */ 28250f74e101Schristos length=pdu_len; 28260f74e101Schristos } 28270f74e101Schristos 2828c74ad251Schristos ND_PRINT("\n\t source-id: %s, PDU length: %u", 2829c74ad251Schristos isis_print_id(ndo, header_psnp->source_id, NODE_ID_LEN), 2830c74ad251Schristos pdu_len); 28310f74e101Schristos 2832b3a00663Schristos if (ndo->ndo_vflag > 1) { 2833b3a00663Schristos if (!print_unknown_data(ndo, pptr, "\n\t ", ISIS_PSNP_HEADER_SIZE)) 28340f74e101Schristos return (0); 28350f74e101Schristos } 28360f74e101Schristos 2837c74ad251Schristos INVALID_OR_DECREMENT(packet_len,ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE); 28380f74e101Schristos pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE); 28390f74e101Schristos break; 28400f74e101Schristos 28410f74e101Schristos default: 284272c96ff3Schristos if (ndo->ndo_vflag == 0) { 2843c74ad251Schristos ND_PRINT(", length %u", length); 284472c96ff3Schristos return (1); 284572c96ff3Schristos } 2846ba2ff121Schristos (void)print_unknown_data(ndo, pptr, "\n\t ", length); 28470f74e101Schristos return (0); 28480f74e101Schristos } 28490f74e101Schristos 28500f74e101Schristos /* 28510f74e101Schristos * Now print the TLV's. 28520f74e101Schristos */ 28530f74e101Schristos 285472c96ff3Schristos while (packet_len > 0) { 2855c74ad251Schristos ND_TCHECK_2(pptr); 285672c96ff3Schristos if (packet_len < 2) 285772c96ff3Schristos goto trunc; 2858c74ad251Schristos tlv_type = GET_U_1(pptr); 2859c74ad251Schristos tlv_len = GET_U_1(pptr + 1); 2860c74ad251Schristos pptr += 2; 28610f74e101Schristos packet_len -= 2; 2862c74ad251Schristos tlen = tlv_len; /* copy temporary len & pointer to packet data */ 2863c74ad251Schristos tptr = pptr; 28640f74e101Schristos 28650f74e101Schristos /* first lets see if we know the TLVs name*/ 2866c74ad251Schristos ND_PRINT("\n\t %s TLV #%u, length: %u", 28670f74e101Schristos tok2str(isis_tlv_values, 28680f74e101Schristos "unknown", 28690f74e101Schristos tlv_type), 28700f74e101Schristos tlv_type, 2871c74ad251Schristos tlv_len); 28720f74e101Schristos 287372c96ff3Schristos if (packet_len < tlv_len) 287472c96ff3Schristos goto trunc; 287572c96ff3Schristos 28760f74e101Schristos /* now check if we have a decoder otherwise do a hexdump at the end*/ 28770f74e101Schristos switch (tlv_type) { 28780f74e101Schristos case ISIS_TLV_AREA_ADDR: 2879c74ad251Schristos while (tlen != 0) { 2880c74ad251Schristos alen = GET_U_1(tptr); 2881c74ad251Schristos tptr++; 2882c74ad251Schristos tlen--; 2883c74ad251Schristos if (tlen < alen) 2884c74ad251Schristos goto tlv_trunc; 2885c74ad251Schristos ND_PRINT("\n\t Area address (length: %u): %s", 28860f74e101Schristos alen, 2887c74ad251Schristos GET_ISONSAP_STRING(tptr, alen)); 28880f74e101Schristos tptr += alen; 2889c74ad251Schristos tlen -= alen; 28900f74e101Schristos } 28910f74e101Schristos break; 28920f74e101Schristos case ISIS_TLV_ISNEIGH: 2893c74ad251Schristos while (tlen != 0) { 2894c74ad251Schristos if (tlen < MAC_ADDR_LEN) 2895c74ad251Schristos goto tlv_trunc; 2896c74ad251Schristos ND_TCHECK_LEN(tptr, MAC_ADDR_LEN); 2897c74ad251Schristos ND_PRINT("\n\t SNPA: %s", isis_print_id(ndo, tptr, MAC_ADDR_LEN)); 2898c74ad251Schristos tlen -= MAC_ADDR_LEN; 2899c74ad251Schristos tptr += MAC_ADDR_LEN; 29000f74e101Schristos } 29010f74e101Schristos break; 29020f74e101Schristos 2903c74ad251Schristos case ISIS_TLV_INSTANCE_ID: 2904c74ad251Schristos if (tlen < 4) 2905c74ad251Schristos goto tlv_trunc; 2906c74ad251Schristos num_vals = (tlen-2)/2; 2907c74ad251Schristos ND_PRINT("\n\t Instance ID: %u, ITIDs(%u)%s ", 2908c74ad251Schristos GET_BE_U_2(tptr), num_vals, 2909c74ad251Schristos num_vals ? ":" : ""); 2910c74ad251Schristos tptr += 2; 2911c74ad251Schristos tlen -= 2; 2912c74ad251Schristos for (i=0; i < num_vals; i++) { 2913c74ad251Schristos ND_PRINT("%u", GET_BE_U_2(tptr)); 2914c74ad251Schristos if (i < (num_vals - 1)) { 2915c74ad251Schristos ND_PRINT(", "); 29160f74e101Schristos } 2917c74ad251Schristos tptr += 2; 2918c74ad251Schristos tlen -= 2; 29190f74e101Schristos } 29200f74e101Schristos break; 29210f74e101Schristos 29220f74e101Schristos case ISIS_TLV_PADDING: 29230f74e101Schristos break; 29240f74e101Schristos 29250f74e101Schristos case ISIS_TLV_MT_IS_REACH: 2926c74ad251Schristos mt_len = isis_print_mtid(ndo, tptr, "\n\t ", tlen); 29270f74e101Schristos if (mt_len == 0) /* did something go wrong ? */ 2928c74ad251Schristos goto trunc; 29290f74e101Schristos tptr+=mt_len; 2930c74ad251Schristos tlen-=mt_len; 2931c74ad251Schristos while (tlen != 0) { 2932c74ad251Schristos ext_is_len = isis_print_ext_is_reach(ndo, tptr, "\n\t ", tlv_type, tlen); 29330f74e101Schristos if (ext_is_len == 0) /* did something go wrong ? */ 2934c74ad251Schristos goto trunc; 2935c74ad251Schristos if (tlen < ext_is_len) { 2936c74ad251Schristos ND_PRINT(" [remaining tlv length %u < %u]", tlen, ext_is_len); 2937c74ad251Schristos nd_print_invalid(ndo); 2938c74ad251Schristos break; 2939c74ad251Schristos } 2940c74ad251Schristos tlen-=(uint8_t)ext_is_len; 2941c74ad251Schristos tptr+=(uint8_t)ext_is_len; 29420f74e101Schristos } 29430f74e101Schristos break; 29440f74e101Schristos 29450f74e101Schristos case ISIS_TLV_IS_ALIAS_ID: 2946c74ad251Schristos while (tlen != 0) { 2947c74ad251Schristos ext_is_len = isis_print_ext_is_reach(ndo, tptr, "\n\t ", tlv_type, tlen); 29480f74e101Schristos if (ext_is_len == 0) /* did something go wrong ? */ 2949c74ad251Schristos goto trunc; 2950c74ad251Schristos if (tlen < ext_is_len) { 2951c74ad251Schristos ND_PRINT(" [remaining tlv length %u < %u]", tlen, ext_is_len); 2952c74ad251Schristos nd_print_invalid(ndo); 2953c74ad251Schristos break; 2954c74ad251Schristos } 2955c74ad251Schristos tlen-=(uint8_t)ext_is_len; 2956c74ad251Schristos tptr+=(uint8_t)ext_is_len; 29570f74e101Schristos } 29580f74e101Schristos break; 29590f74e101Schristos 29600f74e101Schristos case ISIS_TLV_EXT_IS_REACH: 2961c74ad251Schristos while (tlen != 0) { 2962c74ad251Schristos ext_is_len = isis_print_ext_is_reach(ndo, tptr, "\n\t ", tlv_type, tlen); 29630f74e101Schristos if (ext_is_len == 0) /* did something go wrong ? */ 2964c74ad251Schristos goto trunc; 2965c74ad251Schristos if (tlen < ext_is_len) { 2966c74ad251Schristos ND_PRINT(" [remaining tlv length %u < %u]", tlen, ext_is_len); 2967c74ad251Schristos nd_print_invalid(ndo); 2968c74ad251Schristos break; 2969c74ad251Schristos } 2970c74ad251Schristos tlen-=(uint8_t)ext_is_len; 2971c74ad251Schristos tptr+=(uint8_t)ext_is_len; 29720f74e101Schristos } 29730f74e101Schristos break; 29740f74e101Schristos case ISIS_TLV_IS_REACH: 2975c74ad251Schristos if (tlen < 1) 2976c74ad251Schristos goto tlv_trunc; 2977c74ad251Schristos ND_PRINT("\n\t %s", 29780f74e101Schristos tok2str(isis_is_reach_virtual_values, 29790f74e101Schristos "bogus virtual flag 0x%02x", 2980c74ad251Schristos GET_U_1(tptr))); 2981c74ad251Schristos tptr++; 2982c74ad251Schristos tlen--; 29830f74e101Schristos tlv_is_reach = (const struct isis_tlv_is_reach *)tptr; 2984c74ad251Schristos while (tlen != 0) { 2985c74ad251Schristos if (tlen < sizeof(struct isis_tlv_is_reach)) 2986c74ad251Schristos goto tlv_trunc; 2987c74ad251Schristos ND_TCHECK_SIZE(tlv_is_reach); 2988c74ad251Schristos ND_PRINT("\n\t IS Neighbor: %s", 2989c74ad251Schristos isis_print_id(ndo, tlv_is_reach->neighbor_nodeid, NODE_ID_LEN)); 2990b3a00663Schristos isis_print_metric_block(ndo, &tlv_is_reach->isis_metric_block); 2991c74ad251Schristos tlen -= sizeof(struct isis_tlv_is_reach); 29920f74e101Schristos tlv_is_reach++; 29930f74e101Schristos } 29940f74e101Schristos break; 29950f74e101Schristos 29960f74e101Schristos case ISIS_TLV_ESNEIGH: 29970f74e101Schristos tlv_es_reach = (const struct isis_tlv_es_reach *)tptr; 2998c74ad251Schristos while (tlen != 0) { 2999c74ad251Schristos if (tlen < sizeof(struct isis_tlv_es_reach)) 3000c74ad251Schristos goto tlv_trunc; 3001c74ad251Schristos ND_TCHECK_SIZE(tlv_es_reach); 3002c74ad251Schristos ND_PRINT("\n\t ES Neighbor: %s", 3003c74ad251Schristos isis_print_id(ndo, tlv_es_reach->neighbor_sysid, SYSTEM_ID_LEN)); 3004b3a00663Schristos isis_print_metric_block(ndo, &tlv_es_reach->isis_metric_block); 3005c74ad251Schristos tlen -= sizeof(struct isis_tlv_es_reach); 30060f74e101Schristos tlv_es_reach++; 30070f74e101Schristos } 30080f74e101Schristos break; 30090f74e101Schristos 30100f74e101Schristos /* those two TLVs share the same format */ 30110f74e101Schristos case ISIS_TLV_INT_IP_REACH: 30120f74e101Schristos case ISIS_TLV_EXT_IP_REACH: 3013b3a00663Schristos if (!isis_print_tlv_ip_reach(ndo, pptr, "\n\t ", tlv_len)) 30140f74e101Schristos return (1); 30150f74e101Schristos break; 30160f74e101Schristos 30170f74e101Schristos case ISIS_TLV_EXTD_IP_REACH: 3018c74ad251Schristos while (tlen != 0) { 3019b3a00663Schristos ext_ip_len = isis_print_extd_ip_reach(ndo, tptr, "\n\t ", AF_INET); 30200f74e101Schristos if (ext_ip_len == 0) /* did something go wrong ? */ 3021c74ad251Schristos goto trunc; 3022c74ad251Schristos if (tlen < ext_ip_len) { 3023c74ad251Schristos ND_PRINT(" [remaining tlv length %u < %u]", tlen, ext_ip_len); 3024c74ad251Schristos nd_print_invalid(ndo); 3025c74ad251Schristos break; 3026c74ad251Schristos } 3027c74ad251Schristos tlen-=(uint8_t)ext_ip_len; 3028c74ad251Schristos tptr+=(uint8_t)ext_ip_len; 30290f74e101Schristos } 30300f74e101Schristos break; 30310f74e101Schristos 30320f74e101Schristos case ISIS_TLV_MT_IP_REACH: 3033c74ad251Schristos mt_len = isis_print_mtid(ndo, tptr, "\n\t ", tlen); 30340f74e101Schristos if (mt_len == 0) { /* did something go wrong ? */ 3035c74ad251Schristos goto trunc; 30360f74e101Schristos } 30370f74e101Schristos tptr+=mt_len; 3038c74ad251Schristos tlen-=mt_len; 30390f74e101Schristos 3040c74ad251Schristos while (tlen != 0) { 3041b3a00663Schristos ext_ip_len = isis_print_extd_ip_reach(ndo, tptr, "\n\t ", AF_INET); 30420f74e101Schristos if (ext_ip_len == 0) /* did something go wrong ? */ 3043c74ad251Schristos goto trunc; 3044c74ad251Schristos if (tlen < ext_ip_len) { 3045c74ad251Schristos ND_PRINT(" [remaining tlv length %u < %u]", tlen, ext_ip_len); 3046c74ad251Schristos nd_print_invalid(ndo); 3047c74ad251Schristos break; 3048c74ad251Schristos } 3049c74ad251Schristos tlen-=(uint8_t)ext_ip_len; 3050c74ad251Schristos tptr+=(uint8_t)ext_ip_len; 30510f74e101Schristos } 30520f74e101Schristos break; 30530f74e101Schristos 30540f74e101Schristos case ISIS_TLV_IP6_REACH: 3055c74ad251Schristos while (tlen != 0) { 3056b3a00663Schristos ext_ip_len = isis_print_extd_ip_reach(ndo, tptr, "\n\t ", AF_INET6); 30570f74e101Schristos if (ext_ip_len == 0) /* did something go wrong ? */ 3058c74ad251Schristos goto trunc; 3059c74ad251Schristos if (tlen < ext_ip_len) { 3060c74ad251Schristos ND_PRINT(" [remaining tlv length %u < %u]", tlen, ext_ip_len); 3061c74ad251Schristos nd_print_invalid(ndo); 3062c74ad251Schristos break; 3063c74ad251Schristos } 3064c74ad251Schristos tlen-=(uint8_t)ext_ip_len; 3065c74ad251Schristos tptr+=(uint8_t)ext_ip_len; 30660f74e101Schristos } 30670f74e101Schristos break; 30680f74e101Schristos 30690f74e101Schristos case ISIS_TLV_MT_IP6_REACH: 3070c74ad251Schristos mt_len = isis_print_mtid(ndo, tptr, "\n\t ", tlen); 30710f74e101Schristos if (mt_len == 0) { /* did something go wrong ? */ 3072c74ad251Schristos goto trunc; 30730f74e101Schristos } 30740f74e101Schristos tptr+=mt_len; 3075c74ad251Schristos tlen-=mt_len; 30760f74e101Schristos 3077c74ad251Schristos while (tlen != 0) { 3078b3a00663Schristos ext_ip_len = isis_print_extd_ip_reach(ndo, tptr, "\n\t ", AF_INET6); 30790f74e101Schristos if (ext_ip_len == 0) /* did something go wrong ? */ 3080c74ad251Schristos goto trunc; 3081c74ad251Schristos if (tlen < ext_ip_len) { 3082c74ad251Schristos ND_PRINT(" [remaining tlv length %u < %u]", tlen, ext_ip_len); 3083c74ad251Schristos nd_print_invalid(ndo); 3084c74ad251Schristos break; 3085c74ad251Schristos } 3086c74ad251Schristos tlen-=(uint8_t)ext_ip_len; 3087c74ad251Schristos tptr+=(uint8_t)ext_ip_len; 30880f74e101Schristos } 30890f74e101Schristos break; 30900f74e101Schristos 30910f74e101Schristos case ISIS_TLV_IP6ADDR: 3092c74ad251Schristos while (tlen != 0) { 3093c74ad251Schristos if (tlen < sizeof(nd_ipv6)) 3094c74ad251Schristos goto tlv_trunc; 3095c74ad251Schristos ND_PRINT("\n\t IPv6 interface address: %s", 3096c74ad251Schristos GET_IP6ADDR_STRING(tptr)); 30970f74e101Schristos 3098c74ad251Schristos tptr += sizeof(nd_ipv6); 3099c74ad251Schristos tlen -= sizeof(nd_ipv6); 31000f74e101Schristos } 31010f74e101Schristos break; 31020f74e101Schristos case ISIS_TLV_AUTH: 3103c74ad251Schristos if (tlen < 1) 3104c74ad251Schristos goto tlv_trunc; 3105c74ad251Schristos auth_type = GET_U_1(tptr); 3106c74ad251Schristos tptr++; 3107c74ad251Schristos tlen--; 31080f74e101Schristos 3109c74ad251Schristos ND_PRINT("\n\t %s: ", 31100f74e101Schristos tok2str(isis_subtlv_auth_values, 31110f74e101Schristos "unknown Authentication type 0x%02x", 3112c74ad251Schristos auth_type)); 31130f74e101Schristos 3114c74ad251Schristos switch (auth_type) { 31150f74e101Schristos case ISIS_SUBTLV_AUTH_SIMPLE: 3116c74ad251Schristos nd_printjnp(ndo, tptr, tlen); 31170f74e101Schristos break; 31180f74e101Schristos case ISIS_SUBTLV_AUTH_MD5: 3119c74ad251Schristos for(i=0;i<tlen;i++) { 3120c74ad251Schristos ND_PRINT("%02x", GET_U_1(tptr + i)); 31210f74e101Schristos } 3122c74ad251Schristos if (tlen != ISIS_SUBTLV_AUTH_MD5_LEN) 3123c74ad251Schristos ND_PRINT(", (invalid subTLV) "); 31240f74e101Schristos 3125c74ad251Schristos sigcheck = signature_verify(ndo, optr, length, tptr, 3126fdccd7e4Schristos isis_clear_checksum_lifetime, 3127fdccd7e4Schristos header_lsp); 3128c74ad251Schristos ND_PRINT(" (%s)", tok2str(signature_check_values, "Unknown", sigcheck)); 31290f74e101Schristos 31300f74e101Schristos break; 31310e9868baSchristos case ISIS_SUBTLV_AUTH_GENERIC: 3132c74ad251Schristos if (tlen < 2) 3133c74ad251Schristos goto tlv_trunc; 3134c74ad251Schristos key_id = GET_BE_U_2(tptr); 3135c74ad251Schristos ND_PRINT("%u, password: ", key_id); 3136c74ad251Schristos tptr += 2; 3137c74ad251Schristos tlen -= 2; 3138c74ad251Schristos for(i=0;i<tlen;i++) { 3139c74ad251Schristos ND_PRINT("%02x", GET_U_1(tptr + i)); 31400e9868baSchristos } 31410e9868baSchristos break; 31420f74e101Schristos case ISIS_SUBTLV_AUTH_PRIVATE: 31430f74e101Schristos default: 3144c74ad251Schristos if (!print_unknown_data(ndo, tptr, "\n\t\t ", tlen)) 31450f74e101Schristos return(0); 31460f74e101Schristos break; 31470f74e101Schristos } 31480f74e101Schristos break; 31490f74e101Schristos 31500f74e101Schristos case ISIS_TLV_PTP_ADJ: 31510f74e101Schristos tlv_ptp_adj = (const struct isis_tlv_ptp_adj *)tptr; 3152c74ad251Schristos if(tlen>=1) { 3153c74ad251Schristos ND_PRINT("\n\t Adjacency State: %s (%u)", 3154*26ba0b50Schristos tok2str(isis_ptp_adjacency_values, "unknown", GET_U_1(tptr)), 3155c74ad251Schristos GET_U_1(tptr)); 3156c74ad251Schristos tlen--; 31570f74e101Schristos } 3158c74ad251Schristos if(tlen>sizeof(tlv_ptp_adj->extd_local_circuit_id)) { 3159c74ad251Schristos ND_PRINT("\n\t Extended Local circuit-ID: 0x%08x", 3160c74ad251Schristos GET_BE_U_4(tlv_ptp_adj->extd_local_circuit_id)); 3161c74ad251Schristos tlen-=sizeof(tlv_ptp_adj->extd_local_circuit_id); 31620f74e101Schristos } 3163c74ad251Schristos if(tlen>=SYSTEM_ID_LEN) { 3164c74ad251Schristos ND_TCHECK_LEN(tlv_ptp_adj->neighbor_sysid, SYSTEM_ID_LEN); 3165c74ad251Schristos ND_PRINT("\n\t Neighbor System-ID: %s", 3166c74ad251Schristos isis_print_id(ndo, tlv_ptp_adj->neighbor_sysid, SYSTEM_ID_LEN)); 3167c74ad251Schristos tlen-=SYSTEM_ID_LEN; 31680f74e101Schristos } 3169c74ad251Schristos if(tlen>=sizeof(tlv_ptp_adj->neighbor_extd_local_circuit_id)) { 3170c74ad251Schristos ND_PRINT("\n\t Neighbor Extended Local circuit-ID: 0x%08x", 3171c74ad251Schristos GET_BE_U_4(tlv_ptp_adj->neighbor_extd_local_circuit_id)); 31720f74e101Schristos } 31730f74e101Schristos break; 31740f74e101Schristos 31750f74e101Schristos case ISIS_TLV_PROTOCOLS: 3176c74ad251Schristos ND_PRINT("\n\t NLPID(s): "); 3177c74ad251Schristos while (tlen != 0) { 3178c74ad251Schristos ND_PRINT("%s (0x%02x)", 31790f74e101Schristos tok2str(nlpid_values, 31800f74e101Schristos "unknown", 3181c74ad251Schristos GET_U_1(tptr)), 3182c74ad251Schristos GET_U_1(tptr)); 3183c74ad251Schristos if (tlen>1) /* further NPLIDs ? - put comma */ 3184c74ad251Schristos ND_PRINT(", "); 31850f74e101Schristos tptr++; 3186c74ad251Schristos tlen--; 31870f74e101Schristos } 31880f74e101Schristos break; 31890f74e101Schristos 3190870189d2Schristos case ISIS_TLV_MT_PORT_CAP: 3191870189d2Schristos { 3192c74ad251Schristos if (tlen < 2) 3193c74ad251Schristos goto tlv_trunc; 3194870189d2Schristos 3195c74ad251Schristos ND_PRINT("\n\t RES: %u, MTID(s): %u", 3196c74ad251Schristos (GET_BE_U_2(tptr) >> 12), 3197c74ad251Schristos (GET_BE_U_2(tptr) & 0x0fff)); 3198870189d2Schristos 3199c74ad251Schristos tptr += 2; 3200c74ad251Schristos tlen -= 2; 3201870189d2Schristos 3202c74ad251Schristos if (tlen) 3203c74ad251Schristos isis_print_mt_port_cap_subtlv(ndo, tptr, tlen); 3204870189d2Schristos 3205870189d2Schristos break; 3206870189d2Schristos } 3207870189d2Schristos 3208870189d2Schristos case ISIS_TLV_MT_CAPABILITY: 3209c74ad251Schristos if (tlen < 2) 3210c74ad251Schristos goto tlv_trunc; 3211870189d2Schristos 3212c74ad251Schristos ND_PRINT("\n\t O: %u, RES: %u, MTID(s): %u", 3213c74ad251Schristos (GET_BE_U_2(tptr) >> 15) & 0x01, 3214c74ad251Schristos (GET_BE_U_2(tptr) >> 12) & 0x07, 3215c74ad251Schristos GET_BE_U_2(tptr) & 0x0fff); 3216870189d2Schristos 3217c74ad251Schristos tptr += 2; 3218c74ad251Schristos tlen -= 2; 3219870189d2Schristos 3220c74ad251Schristos if (tlen) 3221c74ad251Schristos isis_print_mt_capability_subtlv(ndo, tptr, tlen); 3222870189d2Schristos 3223870189d2Schristos break; 3224870189d2Schristos 32250f74e101Schristos case ISIS_TLV_TE_ROUTER_ID: 3226c74ad251Schristos if (tlen < sizeof(nd_ipv4)) 3227c74ad251Schristos goto tlv_trunc; 3228c74ad251Schristos ND_PRINT("\n\t Traffic Engineering Router ID: %s", GET_IPADDR_STRING(pptr)); 32290f74e101Schristos break; 32300f74e101Schristos 32310f74e101Schristos case ISIS_TLV_IPADDR: 3232c74ad251Schristos while (tlen != 0) { 3233c74ad251Schristos if (tlen < sizeof(nd_ipv4)) 3234c74ad251Schristos goto tlv_trunc; 3235c74ad251Schristos ND_PRINT("\n\t IPv4 interface address: %s", GET_IPADDR_STRING(tptr)); 3236c74ad251Schristos tptr += sizeof(nd_ipv4); 3237c74ad251Schristos tlen -= sizeof(nd_ipv4); 32380f74e101Schristos } 32390f74e101Schristos break; 32400f74e101Schristos 32410f74e101Schristos case ISIS_TLV_HOSTNAME: 3242c74ad251Schristos ND_PRINT("\n\t Hostname: "); 3243c74ad251Schristos nd_printjnp(ndo, tptr, tlen); 32440f74e101Schristos break; 32450f74e101Schristos 32460f74e101Schristos case ISIS_TLV_SHARED_RISK_GROUP: 3247c74ad251Schristos if (tlen < NODE_ID_LEN) 32480f74e101Schristos break; 3249c74ad251Schristos ND_TCHECK_LEN(tptr, NODE_ID_LEN); 3250c74ad251Schristos ND_PRINT("\n\t IS Neighbor: %s", isis_print_id(ndo, tptr, NODE_ID_LEN)); 3251c74ad251Schristos tptr+=NODE_ID_LEN; 3252c74ad251Schristos tlen-=NODE_ID_LEN; 32530f74e101Schristos 3254c74ad251Schristos if (tlen < 1) 32550f74e101Schristos break; 3256c74ad251Schristos ND_PRINT(", Flags: [%s]", 3257c74ad251Schristos ISIS_MASK_TLV_SHARED_RISK_GROUP(GET_U_1(tptr)) ? "numbered" : "unnumbered"); 3258c74ad251Schristos tptr++; 3259c74ad251Schristos tlen--; 32600f74e101Schristos 3261c74ad251Schristos if (tlen < sizeof(nd_ipv4)) 32620f74e101Schristos break; 3263c74ad251Schristos ND_PRINT("\n\t IPv4 interface address: %s", GET_IPADDR_STRING(tptr)); 3264c74ad251Schristos tptr+=sizeof(nd_ipv4); 3265c74ad251Schristos tlen-=sizeof(nd_ipv4); 32660f74e101Schristos 3267c74ad251Schristos if (tlen < sizeof(nd_ipv4)) 32680f74e101Schristos break; 3269c74ad251Schristos ND_PRINT("\n\t IPv4 neighbor address: %s", GET_IPADDR_STRING(tptr)); 3270c74ad251Schristos tptr+=sizeof(nd_ipv4); 3271c74ad251Schristos tlen-=sizeof(nd_ipv4); 32720f74e101Schristos 3273c74ad251Schristos while (tlen != 0) { 3274c74ad251Schristos if (tlen < 4) 3275c74ad251Schristos goto tlv_trunc; 3276c74ad251Schristos ND_PRINT("\n\t Link-ID: 0x%08x", GET_BE_U_4(tptr)); 32770f74e101Schristos tptr+=4; 3278c74ad251Schristos tlen-=4; 32790f74e101Schristos } 32800f74e101Schristos break; 32810f74e101Schristos 32820f74e101Schristos case ISIS_TLV_LSP: 32830f74e101Schristos tlv_lsp = (const struct isis_tlv_lsp *)tptr; 3284c74ad251Schristos while (tlen != 0) { 3285c74ad251Schristos if (tlen < sizeof(struct isis_tlv_lsp)) 3286c74ad251Schristos goto tlv_trunc; 3287c74ad251Schristos ND_TCHECK_1(tlv_lsp->lsp_id + LSP_ID_LEN - 1); 3288c74ad251Schristos ND_PRINT("\n\t lsp-id: %s", 3289c74ad251Schristos isis_print_id(ndo, tlv_lsp->lsp_id, LSP_ID_LEN)); 3290c74ad251Schristos ND_PRINT(", seq: 0x%08x", 3291c74ad251Schristos GET_BE_U_4(tlv_lsp->sequence_number)); 3292c74ad251Schristos ND_PRINT(", lifetime: %5ds", 3293c74ad251Schristos GET_BE_U_2(tlv_lsp->remaining_lifetime)); 3294c74ad251Schristos ND_PRINT(", chksum: 0x%04x", GET_BE_U_2(tlv_lsp->checksum)); 3295c74ad251Schristos tlen-=sizeof(struct isis_tlv_lsp); 32960f74e101Schristos tlv_lsp++; 32970f74e101Schristos } 32980f74e101Schristos break; 32990f74e101Schristos 33000f74e101Schristos case ISIS_TLV_CHECKSUM: 3301c74ad251Schristos if (tlen < ISIS_TLV_CHECKSUM_MINLEN) 33020f74e101Schristos break; 3303c74ad251Schristos ND_TCHECK_LEN(tptr, ISIS_TLV_CHECKSUM_MINLEN); 3304c74ad251Schristos ND_PRINT("\n\t checksum: 0x%04x ", GET_BE_U_2(tptr)); 33050f74e101Schristos /* do not attempt to verify the checksum if it is zero 33060f74e101Schristos * most likely a HMAC-MD5 TLV is also present and 33070f74e101Schristos * to avoid conflicts the checksum TLV is zeroed. 33080f74e101Schristos * see rfc3358 for details 33090f74e101Schristos */ 3310c74ad251Schristos osi_print_cksum(ndo, optr, GET_BE_U_2(tptr), (int)(tptr-optr), 331172c96ff3Schristos length); 3312fdccd7e4Schristos break; 3313fdccd7e4Schristos 3314fdccd7e4Schristos case ISIS_TLV_POI: 3315c74ad251Schristos if (tlen < 1) 3316c74ad251Schristos goto tlv_trunc; 3317c74ad251Schristos num_system_ids = GET_U_1(tptr); 3318c74ad251Schristos tptr++; 3319c74ad251Schristos tlen--; 3320c74ad251Schristos if (num_system_ids == 0) { 3321c74ad251Schristos /* Not valid */ 3322c74ad251Schristos ND_PRINT(" No system IDs supplied"); 3323c74ad251Schristos } else { 3324c74ad251Schristos if (tlen < SYSTEM_ID_LEN) 3325c74ad251Schristos goto tlv_trunc; 3326c74ad251Schristos ND_TCHECK_LEN(tptr, SYSTEM_ID_LEN); 3327c74ad251Schristos ND_PRINT("\n\t Purge Originator System-ID: %s", 3328c74ad251Schristos isis_print_id(ndo, tptr, SYSTEM_ID_LEN)); 3329c74ad251Schristos tptr += SYSTEM_ID_LEN; 3330c74ad251Schristos tlen -= SYSTEM_ID_LEN; 3331fdccd7e4Schristos 3332c74ad251Schristos if (num_system_ids > 1) { 3333c74ad251Schristos if (tlen < SYSTEM_ID_LEN) 3334c74ad251Schristos goto tlv_trunc; 3335c74ad251Schristos ND_TCHECK_LEN(tptr, SYSTEM_ID_LEN); 3336c74ad251Schristos ND_TCHECK_LEN(tptr, 2 * SYSTEM_ID_LEN + 1); 3337c74ad251Schristos ND_PRINT("\n\t Received from System-ID: %s", 3338c74ad251Schristos isis_print_id(ndo, tptr, SYSTEM_ID_LEN)); 3339c74ad251Schristos } 3340fdccd7e4Schristos } 33410f74e101Schristos break; 33420f74e101Schristos 33430f74e101Schristos case ISIS_TLV_MT_SUPPORTED: 3344c74ad251Schristos while (tlen != 0) { 33450f74e101Schristos /* length can only be a multiple of 2, otherwise there is 33460f74e101Schristos something broken -> so decode down until length is 1 */ 3347c74ad251Schristos if (tlen!=1) { 3348c74ad251Schristos mt_len = isis_print_mtid(ndo, tptr, "\n\t ", tlen); 33490f74e101Schristos if (mt_len == 0) /* did something go wrong ? */ 3350c74ad251Schristos goto trunc; 33510f74e101Schristos tptr+=mt_len; 3352c74ad251Schristos tlen-=mt_len; 33530f74e101Schristos } else { 3354c74ad251Schristos ND_PRINT("\n\t invalid MT-ID"); 33550f74e101Schristos break; 33560f74e101Schristos } 33570f74e101Schristos } 33580f74e101Schristos break; 33590f74e101Schristos 33600f74e101Schristos case ISIS_TLV_RESTART_SIGNALING: 33610f74e101Schristos /* first attempt to decode the flags */ 3362c74ad251Schristos if (tlen < ISIS_TLV_RESTART_SIGNALING_FLAGLEN) 33630f74e101Schristos break; 3364c74ad251Schristos ND_TCHECK_LEN(tptr, ISIS_TLV_RESTART_SIGNALING_FLAGLEN); 3365c74ad251Schristos ND_PRINT("\n\t Flags [%s]", 3366c74ad251Schristos bittok2str(isis_restart_flag_values, "none", GET_U_1(tptr))); 33670f74e101Schristos tptr+=ISIS_TLV_RESTART_SIGNALING_FLAGLEN; 3368c74ad251Schristos tlen-=ISIS_TLV_RESTART_SIGNALING_FLAGLEN; 33690f74e101Schristos 33700f74e101Schristos /* is there anything other than the flags field? */ 3371c74ad251Schristos if (tlen == 0) 33720f74e101Schristos break; 33730f74e101Schristos 3374c74ad251Schristos if (tlen < ISIS_TLV_RESTART_SIGNALING_HOLDTIMELEN) 33750f74e101Schristos break; 3376c74ad251Schristos ND_TCHECK_LEN(tptr, ISIS_TLV_RESTART_SIGNALING_HOLDTIMELEN); 33770f74e101Schristos 3378c74ad251Schristos ND_PRINT(", Remaining holding time %us", GET_BE_U_2(tptr)); 33790f74e101Schristos tptr+=ISIS_TLV_RESTART_SIGNALING_HOLDTIMELEN; 3380c74ad251Schristos tlen-=ISIS_TLV_RESTART_SIGNALING_HOLDTIMELEN; 33810f74e101Schristos 33820f74e101Schristos /* is there an additional sysid field present ?*/ 3383c74ad251Schristos if (tlen == SYSTEM_ID_LEN) { 3384c74ad251Schristos ND_TCHECK_LEN(tptr, SYSTEM_ID_LEN); 3385c74ad251Schristos ND_PRINT(", for %s", isis_print_id(ndo, tptr,SYSTEM_ID_LEN)); 33860f74e101Schristos } 33870f74e101Schristos break; 33880f74e101Schristos 33890f74e101Schristos case ISIS_TLV_IDRP_INFO: 3390c74ad251Schristos if (tlen < 1) 33910f74e101Schristos break; 3392c74ad251Schristos isis_subtlv_idrp = GET_U_1(tptr); 3393c74ad251Schristos ND_PRINT("\n\t Inter-Domain Information Type: %s", 33940f74e101Schristos tok2str(isis_subtlv_idrp_values, 33950f74e101Schristos "Unknown (0x%02x)", 3396c74ad251Schristos isis_subtlv_idrp)); 3397c74ad251Schristos tptr++; 3398c74ad251Schristos tlen--; 3399c74ad251Schristos switch (isis_subtlv_idrp) { 34000f74e101Schristos case ISIS_SUBTLV_IDRP_ASN: 3401c74ad251Schristos if (tlen < 2) 3402c74ad251Schristos goto tlv_trunc; 3403c74ad251Schristos ND_PRINT("AS Number: %u", GET_BE_U_2(tptr)); 34040f74e101Schristos break; 34050f74e101Schristos case ISIS_SUBTLV_IDRP_LOCAL: 34060f74e101Schristos case ISIS_SUBTLV_IDRP_RES: 34070f74e101Schristos default: 3408c74ad251Schristos if (!print_unknown_data(ndo, tptr, "\n\t ", tlen)) 34090f74e101Schristos return(0); 34100f74e101Schristos break; 34110f74e101Schristos } 34120f74e101Schristos break; 34130f74e101Schristos 34140f74e101Schristos case ISIS_TLV_LSP_BUFFERSIZE: 3415c74ad251Schristos if (tlen < 2) 34160f74e101Schristos break; 3417c74ad251Schristos ND_PRINT("\n\t LSP Buffersize: %u", GET_BE_U_2(tptr)); 34180f74e101Schristos break; 34190f74e101Schristos 34200f74e101Schristos case ISIS_TLV_PART_DIS: 3421c74ad251Schristos while (tlen != 0) { 3422c74ad251Schristos if (tlen < SYSTEM_ID_LEN) 3423c74ad251Schristos goto tlv_trunc; 3424c74ad251Schristos ND_TCHECK_LEN(tptr, SYSTEM_ID_LEN); 3425c74ad251Schristos ND_PRINT("\n\t %s", isis_print_id(ndo, tptr, SYSTEM_ID_LEN)); 34260f74e101Schristos tptr+=SYSTEM_ID_LEN; 3427c74ad251Schristos tlen-=SYSTEM_ID_LEN; 34280f74e101Schristos } 34290f74e101Schristos break; 34300f74e101Schristos 34310f74e101Schristos case ISIS_TLV_PREFIX_NEIGH: 3432c74ad251Schristos if (tlen < sizeof(struct isis_metric_block)) 34330f74e101Schristos break; 3434c74ad251Schristos ND_TCHECK_LEN(tptr, sizeof(struct isis_metric_block)); 3435c74ad251Schristos ND_PRINT("\n\t Metric Block"); 3436b3a00663Schristos isis_print_metric_block(ndo, (const struct isis_metric_block *)tptr); 34370f74e101Schristos tptr+=sizeof(struct isis_metric_block); 3438c74ad251Schristos tlen-=sizeof(struct isis_metric_block); 34390f74e101Schristos 3440c74ad251Schristos while (tlen != 0) { 3441c74ad251Schristos prefix_len=GET_U_1(tptr); /* read out prefix length in semioctets*/ 3442c74ad251Schristos tptr++; 3443c74ad251Schristos tlen--; 34440f74e101Schristos if (prefix_len < 2) { 3445c74ad251Schristos ND_PRINT("\n\t\tAddress: prefix length %u < 2", prefix_len); 34460f74e101Schristos break; 34470f74e101Schristos } 3448c74ad251Schristos if (tlen < prefix_len/2) 34490f74e101Schristos break; 3450c74ad251Schristos ND_PRINT("\n\t\tAddress: %s/%u", 3451c74ad251Schristos GET_ISONSAP_STRING(tptr, prefix_len / 2), prefix_len * 4); 34520f74e101Schristos tptr+=prefix_len/2; 3453c74ad251Schristos tlen-=prefix_len/2; 34540f74e101Schristos } 34550f74e101Schristos break; 34560f74e101Schristos 34570f74e101Schristos case ISIS_TLV_IIH_SEQNR: 3458c74ad251Schristos if (tlen < 4) 34590f74e101Schristos break; 3460c74ad251Schristos ND_PRINT("\n\t Sequence number: %u", GET_BE_U_4(tptr)); 3461c74ad251Schristos break; 3462c74ad251Schristos 3463c74ad251Schristos case ISIS_TLV_ROUTER_CAPABILITY: 3464c74ad251Schristos if (tlen < 5) { 3465c74ad251Schristos ND_PRINT(" [object length %u < 5]", tlen); 3466c74ad251Schristos nd_print_invalid(ndo); 3467c74ad251Schristos break; 3468c74ad251Schristos } 3469c74ad251Schristos ND_PRINT("\n\t Router-ID %s", GET_IPADDR_STRING(tptr)); 3470c74ad251Schristos ND_PRINT(", Flags [%s]", 3471c74ad251Schristos bittok2str(isis_tlv_router_capability_flags, "none", GET_U_1(tptr+4))); 3472c74ad251Schristos 3473c74ad251Schristos /* Optional set of sub-TLV */ 3474c74ad251Schristos if (tlen > 5) { 3475c74ad251Schristos isis_print_router_cap_subtlv(ndo, tptr+5, tlen-5); 3476c74ad251Schristos } 34770f74e101Schristos break; 34780f74e101Schristos 34790f74e101Schristos case ISIS_TLV_VENDOR_PRIVATE: 3480c74ad251Schristos if (tlen < 3) 34810f74e101Schristos break; 3482c74ad251Schristos vendor_id = GET_BE_U_3(tptr); 3483c74ad251Schristos ND_PRINT("\n\t Vendor: %s (%u)", 34840f74e101Schristos tok2str(oui_values, "Unknown", vendor_id), 3485c74ad251Schristos vendor_id); 34860f74e101Schristos tptr+=3; 3487c74ad251Schristos tlen-=3; 3488c74ad251Schristos if (tlen != 0) /* hexdump the rest */ 3489c74ad251Schristos if (!print_unknown_data(ndo, tptr, "\n\t\t", tlen)) 34900f74e101Schristos return(0); 34910f74e101Schristos break; 34920f74e101Schristos /* 34930f74e101Schristos * FIXME those are the defined TLVs that lack a decoder 34940f74e101Schristos * you are welcome to contribute code ;-) 34950f74e101Schristos */ 34960f74e101Schristos 34970f74e101Schristos case ISIS_TLV_DECNET_PHASE4: 34980f74e101Schristos case ISIS_TLV_LUCENT_PRIVATE: 34990f74e101Schristos case ISIS_TLV_IPAUTH: 35000f74e101Schristos case ISIS_TLV_NORTEL_PRIVATE1: 35010f74e101Schristos case ISIS_TLV_NORTEL_PRIVATE2: 35020f74e101Schristos 35030f74e101Schristos default: 3504b3a00663Schristos if (ndo->ndo_vflag <= 1) { 3505b3a00663Schristos if (!print_unknown_data(ndo, pptr, "\n\t\t", tlv_len)) 35060f74e101Schristos return(0); 35070f74e101Schristos } 35080f74e101Schristos break; 35090f74e101Schristos } 3510c74ad251Schristos tlv_trunc: 35110f74e101Schristos /* do we want to see an additionally hexdump ? */ 3512b3a00663Schristos if (ndo->ndo_vflag> 1) { 3513b3a00663Schristos if (!print_unknown_data(ndo, pptr, "\n\t ", tlv_len)) 35140f74e101Schristos return(0); 35150f74e101Schristos } 35160f74e101Schristos 35170f74e101Schristos pptr += tlv_len; 35180f74e101Schristos packet_len -= tlv_len; 35190f74e101Schristos } 35200f74e101Schristos 35210f74e101Schristos if (packet_len != 0) { 3522c74ad251Schristos ND_PRINT("\n\t %u straggler bytes", packet_len); 35230f74e101Schristos } 35240f74e101Schristos return (1); 35250f74e101Schristos 35260f74e101Schristos trunc: 3527c74ad251Schristos nd_print_trunc(ndo); 35280f74e101Schristos return (1); 35290f74e101Schristos } 35300f74e101Schristos 353172c96ff3Schristos static void 3532fdccd7e4Schristos osi_print_cksum(netdissect_options *ndo, const uint8_t *pptr, 353372c96ff3Schristos uint16_t checksum, int checksum_offset, u_int length) 35340f74e101Schristos { 3535b3a00663Schristos uint16_t calculated_checksum; 35360f74e101Schristos 3537ba2ff121Schristos /* do not attempt to verify the checksum if it is zero, 3538ba2ff121Schristos * if the offset is nonsense, 3539ba2ff121Schristos * or the base pointer is not sane 3540ba2ff121Schristos */ 3541ba2ff121Schristos if (!checksum 3542fdccd7e4Schristos || checksum_offset < 0 3543c74ad251Schristos || !ND_TTEST_2(pptr + checksum_offset) 354472c96ff3Schristos || (u_int)checksum_offset > length 3545c74ad251Schristos || !ND_TTEST_LEN(pptr, length)) { 3546c74ad251Schristos ND_PRINT(" (unverified)"); 35470f74e101Schristos } else { 3548fdccd7e4Schristos #if 0 3549c74ad251Schristos ND_PRINT("\nosi_print_cksum: %p %d %u\n", pptr, checksum_offset, length); 3550fdccd7e4Schristos #endif 35510f74e101Schristos calculated_checksum = create_osi_cksum(pptr, checksum_offset, length); 35520f74e101Schristos if (checksum == calculated_checksum) { 3553c74ad251Schristos ND_PRINT(" (correct)"); 35540f74e101Schristos } else { 3555c74ad251Schristos ND_PRINT(" (incorrect should be 0x%04x)", calculated_checksum); 35560f74e101Schristos } 35570f74e101Schristos } 35580f74e101Schristos } 3559