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