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