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