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