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