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