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