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