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