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