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