source: rtems-libbsd/freebsd/contrib/tcpdump/print-isoclns.c @ 8440506

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 8440506 was 8440506, checked in by Chris Johns <chrisj@…>, on 06/15/15 at 07:42:23

Add tcpdump and libpcap.

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