]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcpdump/print-isoclns.c
This commit was generated by cvs2svn to compensate for changes in r146773,
[FreeBSD/FreeBSD.git] / contrib / tcpdump / print-isoclns.c
1 /*
2  * Copyright (c) 1992, 1993, 1994, 1995, 1996
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that: (1) source code distributions
7  * retain the above copyright notice and this paragraph in its entirety, (2)
8  * distributions including binary code include the above copyright notice and
9  * this paragraph in its entirety in the documentation or other materials
10  * provided with the distribution, and (3) all advertising materials mentioning
11  * features or use of this software display the following acknowledgement:
12  * ``This product includes software developed by the University of California,
13  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14  * the University nor the names of its contributors may be used to endorse
15  * or promote products derived from this software without specific prior
16  * written permission.
17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20  *
21  * Original code by Matt Thomas, Digital Equipment Corporation
22  *
23  * Extensively modified by Hannes Gredler (hannes@juniper.net) for more
24  * complete IS-IS support.
25  *
26  * $FreeBSD$
27  */
28
29 #ifndef lint
30 static const char rcsid[] _U_ =
31     "@(#) $Header: /tcpdump/master/tcpdump/print-isoclns.c,v 1.106.2.5 2004/03/24 01:45:26 guy Exp $ (LBL)";
32 #endif
33
34 #ifdef HAVE_CONFIG_H
35 #include "config.h"
36 #endif
37
38 #include <tcpdump-stdinc.h>
39
40 #include <stdio.h>
41 #include <string.h>
42
43 #include "interface.h"
44 #include "addrtoname.h"
45 #include "ethertype.h"
46 #include "ether.h"
47 #include "extract.h"
48 #include "gmpls.h"
49
50 #define NLPID_CLNS      129     /* 0x81 */
51 #define NLPID_ESIS      130     /* 0x82 */
52 #define NLPID_ISIS      131     /* 0x83 */
53 #define NLPID_IP6       0x8e
54 #define NLPID_IP        0xcc
55 #define NLPID_NULLNS    0
56
57 #define IPV4            1       /* AFI value */
58 #define IPV6            2       /* AFI value */
59
60 /*
61  * IS-IS is defined in ISO 10589.  Look there for protocol definitions.
62  */
63
64 #define SYSTEM_ID_LEN   ETHER_ADDR_LEN
65 #define NODE_ID_LEN     SYSTEM_ID_LEN+1
66 #define LSP_ID_LEN      SYSTEM_ID_LEN+2
67
68 #define ISIS_VERSION    1
69 #define PDU_TYPE_MASK   0x1F
70 #define PRIORITY_MASK   0x7F
71
72 #define L1_LAN_IIH      15
73 #define L2_LAN_IIH      16
74 #define PTP_IIH         17
75 #define L1_LSP          18
76 #define L2_LSP          20
77 #define L1_CSNP         24
78 #define L2_CSNP         25
79 #define L1_PSNP         26
80 #define L2_PSNP         27
81
82 static struct tok isis_pdu_values[] = {
83     { L1_LAN_IIH,       "L1 Lan IIH"},
84     { L2_LAN_IIH,       "L2 Lan IIH"},
85     { PTP_IIH,          "p2p IIH"},
86     { L1_LSP,           "L1 LSP"},
87     { L2_LSP,           "L2 LSP"},
88     { L1_CSNP,          "L1 CSNP"},
89     { L2_CSNP,          "L2 CSNP"},
90     { L1_PSNP,          "L1 PSNP"},
91     { L2_PSNP,          "L2 PSNP"},
92     { 0, NULL}
93 };
94
95 /*
96  * A TLV is a tuple of a type, length and a value and is normally used for
97  * encoding information in all sorts of places.  This is an enumeration of
98  * the well known types.
99  *
100  * list taken from rfc3359 plus some memory from veterans ;-)
101  */
102
103 #define TLV_AREA_ADDR           1   /* iso10589 */
104 #define TLV_IS_REACH            2   /* iso10589 */
105 #define TLV_ESNEIGH             3   /* iso10589 */
106 #define TLV_PART_DIS            4   /* iso10589 */
107 #define TLV_PREFIX_NEIGH        5   /* iso10589 */
108 #define TLV_ISNEIGH             6   /* iso10589 */
109 #define TLV_ISNEIGH_VARLEN      7   /* iso10589 */
110 #define TLV_PADDING             8   /* iso10589 */
111 #define TLV_LSP                 9   /* iso10589 */
112 #define TLV_AUTH                10  /* iso10589, rfc3567 */
113 #define TLV_CHECKSUM            12  /* rfc3358 */
114 #define TLV_LSP_BUFFERSIZE      14  /* iso10589 rev2 */
115 #define TLV_EXT_IS_REACH        22  /* draft-ietf-isis-traffic-05 */
116 #define TLV_IS_ALIAS_ID         24  /* draft-ietf-isis-ext-lsp-frags-02 */
117 #define TLV_DECNET_PHASE4       42
118 #define TLV_LUCENT_PRIVATE      66
119 #define TLV_INT_IP_REACH        128 /* rfc1195, rfc2966 */
120 #define TLV_PROTOCOLS           129 /* rfc1195 */
121 #define TLV_EXT_IP_REACH        130 /* rfc1195, rfc2966 */
122 #define TLV_IDRP_INFO           131 /* rfc1195 */
123 #define TLV_IPADDR              132 /* rfc1195 */
124 #define TLV_IPAUTH              133 /* rfc1195 */
125 #define TLV_TE_ROUTER_ID        134 /* draft-ietf-isis-traffic-05 */
126 #define TLV_EXTD_IP_REACH       135 /* draft-ietf-isis-traffic-05 */
127 #define TLV_HOSTNAME            137 /* rfc2763 */
128 #define TLV_SHARED_RISK_GROUP   138 /* draft-ietf-isis-gmpls-extensions */
129 #define TLV_NORTEL_PRIVATE1     176
130 #define TLV_NORTEL_PRIVATE2     177
131 #define TLV_HOLDTIME            198 /* ES-IS */
132 #define TLV_RESTART_SIGNALING   211 /* draft-ietf-isis-restart-01 */
133 #define TLV_MT_IS_REACH         222 /* draft-ietf-isis-wg-multi-topology-05 */
134 #define TLV_MT_SUPPORTED        229 /* draft-ietf-isis-wg-multi-topology-05 */
135 #define TLV_IP6ADDR             232 /* draft-ietf-isis-ipv6-02 */
136 #define TLV_MT_IP_REACH         235 /* draft-ietf-isis-wg-multi-topology-05 */
137 #define TLV_IP6_REACH           236 /* draft-ietf-isis-ipv6-02 */
138 #define TLV_MT_IP6_REACH        237 /* draft-ietf-isis-wg-multi-topology-05 */
139 #define TLV_PTP_ADJ             240 /* rfc3373 */
140 #define TLV_IIH_SEQNR           241 /* draft-shen-isis-iih-sequence-00 */
141 #define TLV_VENDOR_PRIVATE      250 /* draft-ietf-isis-proprietary-tlv-00 */
142
143 static struct tok isis_tlv_values[] = {
144     { TLV_AREA_ADDR,         "Area address(es)"},
145     { TLV_IS_REACH,          "IS Reachability"},
146     { TLV_ESNEIGH,           "ES Neighbor(s)"},
147     { TLV_PART_DIS,          "Partition DIS"},
148     { TLV_PREFIX_NEIGH,      "Prefix Neighbors"},
149     { TLV_ISNEIGH,           "IS Neighbor(s)"},
150     { TLV_ISNEIGH_VARLEN,    "IS Neighbor(s) (variable length)"},
151     { TLV_PADDING,           "Padding"},
152     { TLV_LSP,               "LSP entries"},
153     { TLV_AUTH,              "Authentication"},
154     { TLV_CHECKSUM,          "Checksum"},
155     { TLV_LSP_BUFFERSIZE,    "LSP Buffersize"},
156     { TLV_EXT_IS_REACH,      "Extended IS Reachability"},
157     { TLV_IS_ALIAS_ID,       "IS Alias ID"},
158     { TLV_DECNET_PHASE4,     "DECnet Phase IV"},
159     { TLV_LUCENT_PRIVATE,    "Lucent Proprietary"},
160     { TLV_INT_IP_REACH,      "IPv4 Internal Reachability"},
161     { TLV_PROTOCOLS,         "Protocols supported"},
162     { TLV_EXT_IP_REACH,      "IPv4 External Reachability"},
163     { TLV_IDRP_INFO,         "Inter-Domain Information Type"},
164     { TLV_IPADDR,            "IPv4 Interface address(es)"},
165     { TLV_IPAUTH,            "IPv4 authentication (deprecated)"},
166     { TLV_TE_ROUTER_ID,      "Traffic Engineering Router ID"},
167     { TLV_EXTD_IP_REACH,      "Extended IPv4 Reachability"},
168     { TLV_HOSTNAME,          "Hostname"},
169     { TLV_SHARED_RISK_GROUP, "Shared Risk Link Group"},
170     { TLV_NORTEL_PRIVATE1,   "Nortel Proprietary"},
171     { TLV_NORTEL_PRIVATE2,   "Nortel Proprietary"},
172     { TLV_HOLDTIME,          "Holdtime"},
173     { TLV_RESTART_SIGNALING, "Restart Signaling"},
174     { TLV_MT_IS_REACH,       "Multi Topology IS Reachability"},
175     { TLV_MT_SUPPORTED,      "Multi Topology"},
176     { TLV_IP6ADDR,           "IPv6 Interface address(es)"},
177     { TLV_MT_IP_REACH,       "Multi-Topology IPv4 Reachability"},
178     { TLV_IP6_REACH,         "IPv6 reachability"},
179     { TLV_MT_IP6_REACH,      "Multi-Topology IP6 Reachability"},
180     { TLV_PTP_ADJ,           "Point-to-point Adjacency State"},
181     { TLV_IIH_SEQNR,         "Hello PDU Sequence Number"},
182     { TLV_VENDOR_PRIVATE,    "Vendor Private"},
183     { 0, NULL }
184 };
185
186 #define SUBTLV_EXT_IS_REACH_ADMIN_GROUP           3 /* draft-ietf-isis-traffic-05 */
187 #define SUBTLV_EXT_IS_REACH_LINK_LOCAL_REMOTE_ID  4 /* draft-ietf-isis-gmpls-extensions */
188 #define SUBTLV_EXT_IS_REACH_LINK_REMOTE_ID        5 /* draft-ietf-isis-traffic-05 */
189 #define SUBTLV_EXT_IS_REACH_IPV4_INTF_ADDR        6 /* draft-ietf-isis-traffic-05 */
190 #define SUBTLV_EXT_IS_REACH_IPV4_NEIGHBOR_ADDR    8 /* draft-ietf-isis-traffic-05 */
191 #define SUBTLV_EXT_IS_REACH_MAX_LINK_BW           9 /* draft-ietf-isis-traffic-05 */
192 #define SUBTLV_EXT_IS_REACH_RESERVABLE_BW        10 /* draft-ietf-isis-traffic-05 */
193 #define SUBTLV_EXT_IS_REACH_UNRESERVED_BW        11 /* draft-ietf-isis-traffic-05 */
194 #define SUBTLV_EXT_IS_REACH_TE_METRIC            18 /* draft-ietf-isis-traffic-05 */
195 #define SUBTLV_EXT_IS_REACH_LINK_PROTECTION_TYPE 20 /* draft-ietf-isis-gmpls-extensions */
196 #define SUBTLV_EXT_IS_REACH_INTF_SW_CAP_DESCR    21 /* draft-ietf-isis-gmpls-extensions */
197
198 static struct tok isis_ext_is_reach_subtlv_values[] = {
199     { SUBTLV_EXT_IS_REACH_ADMIN_GROUP,            "Administrative groups" },
200     { SUBTLV_EXT_IS_REACH_LINK_LOCAL_REMOTE_ID,   "Link Local/Remote Identifier" },
201     { SUBTLV_EXT_IS_REACH_LINK_REMOTE_ID,         "Link Remote Identifier" },
202     { SUBTLV_EXT_IS_REACH_IPV4_INTF_ADDR,         "IPv4 interface address" },
203     { SUBTLV_EXT_IS_REACH_IPV4_NEIGHBOR_ADDR,     "IPv4 neighbor address" },
204     { SUBTLV_EXT_IS_REACH_MAX_LINK_BW,            "Maximum link bandwidth" },
205     { SUBTLV_EXT_IS_REACH_RESERVABLE_BW,          "Reservable link bandwidth" },
206     { SUBTLV_EXT_IS_REACH_UNRESERVED_BW,          "Unreserved bandwidth" },
207     { SUBTLV_EXT_IS_REACH_TE_METRIC,              "Traffic Engineering Metric" },
208     { SUBTLV_EXT_IS_REACH_LINK_PROTECTION_TYPE,   "Link Protection Type" },
209     { SUBTLV_EXT_IS_REACH_INTF_SW_CAP_DESCR,      "Interface Switching Capability" },
210     { 250,                                        "Reserved for cisco specific extensions" },
211     { 251,                                        "Reserved for cisco specific extensions" },
212     { 252,                                        "Reserved for cisco specific extensions" },
213     { 253,                                        "Reserved for cisco specific extensions" },
214     { 254,                                        "Reserved for cisco specific extensions" },
215     { 255,                                        "Reserved for future expansion" },
216     { 0, NULL }
217 };
218
219 #define SUBTLV_EXTD_IP_REACH_ADMIN_TAG32          1
220 #define SUBTLV_EXTD_IP_REACH_ADMIN_TAG64          2
221
222 static struct tok isis_ext_ip_reach_subtlv_values[] = {
223     { SUBTLV_EXTD_IP_REACH_ADMIN_TAG32,           "32-Bit Administrative tag" },
224     { SUBTLV_EXTD_IP_REACH_ADMIN_TAG64,           "64-Bit Administrative tag" },
225     { 0, NULL }
226 };
227
228 #define SUBTLV_AUTH_SIMPLE        1
229 #define SUBTLV_AUTH_MD5          54
230 #define SUBTLV_AUTH_MD5_LEN      16
231 #define SUBTLV_AUTH_PRIVATE     255
232
233 static struct tok isis_subtlv_auth_values[] = {
234     { SUBTLV_AUTH_SIMPLE,       "simple text password"},
235     { SUBTLV_AUTH_MD5,          "HMAC-MD5 password"},
236     { SUBTLV_AUTH_PRIVATE,      "Routing Domain private password"},
237     { 0, NULL }
238 };
239
240 #define SUBTLV_IDRP_RES           0
241 #define SUBTLV_IDRP_LOCAL         1
242 #define SUBTLV_IDRP_ASN           2
243
244 static struct tok isis_subtlv_idrp_values[] = {
245     { SUBTLV_IDRP_RES,         "Reserved"},
246     { SUBTLV_IDRP_LOCAL,       "Routing-Domain Specific"},
247     { SUBTLV_IDRP_ASN,         "AS Number Tag"},
248     { 0, NULL}
249 };
250
251 #define ISIS_8BIT_MASK(x)                  ((x)&0xff)
252
253 #define ISIS_MASK_LSP_OL_BIT(x)            ((x)&0x4)
254 #define ISIS_MASK_LSP_ISTYPE_BITS(x)       ((x)&0x3)
255 #define ISIS_MASK_LSP_PARTITION_BIT(x)     ((x)&0x80)
256 #define ISIS_MASK_LSP_ATT_BITS(x)          ((x)&0x78)
257 #define ISIS_MASK_LSP_ATT_ERROR_BIT(x)     ((x)&0x40)
258 #define ISIS_MASK_LSP_ATT_EXPENSE_BIT(x)   ((x)&0x20)
259 #define ISIS_MASK_LSP_ATT_DELAY_BIT(x)     ((x)&0x10)
260 #define ISIS_MASK_LSP_ATT_DEFAULT_BIT(x)   ((x)&0x8)
261
262 #define ISIS_MASK_MTID(x)                  ((x)&0x0fff)
263 #define ISIS_MASK_MTFLAGS(x)               ((x)&0xf000)
264
265 static struct tok isis_mt_flag_values[] = {
266     { 0x4000,                  "sub-TLVs present"},
267     { 0x8000,                  "ATT bit set"},
268     { 0, NULL}
269 };
270
271 #define ISIS_MASK_TLV_EXTD_IP_UPDOWN(x)     ((x)&0x80)
272 #define ISIS_MASK_TLV_EXTD_IP_SUBTLV(x)     ((x)&0x40)
273
274 #define ISIS_MASK_TLV_EXTD_IP6_IE(x)        ((x)&0x40)
275 #define ISIS_MASK_TLV_EXTD_IP6_SUBTLV(x)    ((x)&0x20)
276
277 #define ISIS_LSP_TLV_METRIC_SUPPORTED(x)   ((x)&0x80)
278 #define ISIS_LSP_TLV_METRIC_IE(x)          ((x)&0x40)
279 #define ISIS_LSP_TLV_METRIC_UPDOWN(x)      ((x)&0x80)
280 #define ISIS_LSP_TLV_METRIC_VALUE(x)       ((x)&0x3f)
281
282 #define ISIS_MASK_TLV_SHARED_RISK_GROUP(x) ((x)&0x1)
283
284 static struct tok isis_mt_values[] = {
285     { 0,    "IPv4 unicast"},
286     { 1,    "In-Band Management"},
287     { 2,    "IPv6 unicast"},
288     { 3,    "Multicast"},
289     { 4095, "Development, Experimental or Proprietary"},
290     { 0, NULL }
291 };
292
293 static struct tok isis_iih_circuit_type_values[] = {
294     { 1,    "Level 1 only"},
295     { 2,    "Level 2 only"},
296     { 3,    "Level 1, Level 2"},
297     { 0, NULL}
298 };
299
300 #define ISIS_LSP_TYPE_UNUSED0   0
301 #define ISIS_LSP_TYPE_LEVEL_1   1
302 #define ISIS_LSP_TYPE_UNUSED2   2
303 #define ISIS_LSP_TYPE_LEVEL_2   3
304
305 static struct tok isis_lsp_istype_values[] = {
306     { ISIS_LSP_TYPE_UNUSED0,    "Unused 0x0 (invalid)"},
307     { ISIS_LSP_TYPE_LEVEL_1,    "L1 IS"},
308     { ISIS_LSP_TYPE_UNUSED2,    "Unused 0x2 (invalid)"},
309     { ISIS_LSP_TYPE_LEVEL_2,    "L1L2 IS"},
310     { 0, NULL }
311 };
312
313 static struct tok osi_nlpid_values[] = {
314     { NLPID_CLNS,   "CLNS"},
315     { NLPID_IP,     "IPv4"},
316     { NLPID_IP6,    "IPv6"},
317     { 0, NULL }
318 };
319
320 /*
321  * Katz's point to point adjacency TLV uses codes to tell us the state of
322  * the remote adjacency.  Enumerate them.
323  */
324
325 #define ISIS_PTP_ADJ_UP   0
326 #define ISIS_PTP_ADJ_INIT 1
327 #define ISIS_PTP_ADJ_DOWN 2
328
329
330 static struct tok isis_ptp_adjancey_values[] = {
331     { ISIS_PTP_ADJ_UP,    "Up" },
332     { ISIS_PTP_ADJ_INIT,  "Initializing" },
333     { ISIS_PTP_ADJ_DOWN,  "Down" },
334     { 0, NULL}
335 };
336
337 struct isis_tlv_ptp_adj {
338     u_int8_t adjacency_state;
339     u_int8_t extd_local_circuit_id[4];
340     u_int8_t neighbor_sysid[SYSTEM_ID_LEN];
341     u_int8_t neighbor_extd_local_circuit_id[4];
342 };
343
344 static int osi_cksum(const u_int8_t *, u_int);
345 static void esis_print(const u_int8_t *, u_int);
346 static int isis_print(const u_int8_t *, u_int);
347
348 struct isis_metric_block {
349     u_int8_t metric_default;
350     u_int8_t metric_delay;
351     u_int8_t metric_expense;
352     u_int8_t metric_error;
353 };
354
355 struct isis_tlv_is_reach {
356     struct isis_metric_block isis_metric_block;
357     u_int8_t neighbor_nodeid[NODE_ID_LEN];
358 };
359
360 struct isis_tlv_es_reach {
361     struct isis_metric_block isis_metric_block;
362     u_int8_t neighbor_sysid[SYSTEM_ID_LEN];
363 };
364
365 struct isis_tlv_ip_reach {
366     struct isis_metric_block isis_metric_block;
367     u_int8_t prefix[4];
368     u_int8_t mask[4];
369 };
370
371 static struct tok isis_is_reach_virtual_values[] = {
372     { 0,    "IsNotVirtual"},
373     { 1,    "IsVirtual"},
374     { 0, NULL }
375 };
376
377 static struct tok isis_restart_flag_values[] = {
378     { 0x1,  "Restart Request"},
379     { 0x2,  "Restart Acknowledgement"},
380     { 0, NULL }
381 };
382
383 struct isis_common_header {
384     u_int8_t nlpid;
385     u_int8_t fixed_len;
386     u_int8_t version;                   /* Protocol version */
387     u_int8_t id_length;
388     u_int8_t pdu_type;                  /* 3 MSbits are reserved */
389     u_int8_t pdu_version;               /* Packet format version */
390     u_int8_t reserved;
391     u_int8_t max_area;
392 };
393
394 struct isis_iih_lan_header {
395     u_int8_t circuit_type;
396     u_int8_t source_id[SYSTEM_ID_LEN];
397     u_int8_t holding_time[2];
398     u_int8_t pdu_len[2];
399     u_int8_t priority;
400     u_int8_t lan_id[NODE_ID_LEN];
401 };
402
403 struct isis_iih_ptp_header {
404     u_int8_t circuit_type;
405     u_int8_t source_id[SYSTEM_ID_LEN];
406     u_int8_t holding_time[2];
407     u_int8_t pdu_len[2];
408     u_int8_t circuit_id;
409 };
410
411 struct isis_lsp_header {
412     u_int8_t pdu_len[2];
413     u_int8_t remaining_lifetime[2];
414     u_int8_t lsp_id[LSP_ID_LEN];
415     u_int8_t sequence_number[4];
416     u_int8_t checksum[2];
417     u_int8_t typeblock;
418 };
419
420 struct isis_csnp_header {
421     u_int8_t pdu_len[2];
422     u_int8_t source_id[NODE_ID_LEN];
423     u_int8_t start_lsp_id[LSP_ID_LEN];
424     u_int8_t end_lsp_id[LSP_ID_LEN];
425 };
426
427 struct isis_psnp_header {
428     u_int8_t pdu_len[2];
429     u_int8_t source_id[NODE_ID_LEN];
430 };
431
432 struct isis_tlv_lsp {
433     u_int8_t remaining_lifetime[2];
434     u_int8_t lsp_id[LSP_ID_LEN];
435     u_int8_t sequence_number[4];
436     u_int8_t checksum[2];
437 };
438
439 static char *
440 print_nsap(register const u_int8_t *pptr, register int nsap_length)
441 {
442         int nsap_idx;
443         static char nsap_ascii_output[sizeof("xx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xx")];
444         char *junk_buf = nsap_ascii_output;
445
446         if (nsap_length < 1 || nsap_length > 20) {
447                 snprintf(nsap_ascii_output, sizeof(nsap_ascii_output),
448                     "illegal length");
449                 return (nsap_ascii_output);
450         }
451
452         for (nsap_idx = 0; nsap_idx < nsap_length; nsap_idx++) {
453                 if (!TTEST2(*pptr, 1))
454                         return (0);
455                 snprintf(junk_buf,
456                     sizeof(nsap_ascii_output) - (junk_buf - nsap_ascii_output),
457                     "%02x", *pptr++);
458                 junk_buf += strlen(junk_buf);
459                 if (((nsap_idx & 1) == 0) &&
460                      (nsap_idx + 1 < nsap_length)) {
461                         *junk_buf++ = '.';
462                 }
463         }
464         *(junk_buf) = '\0';
465         return (nsap_ascii_output);
466 }
467
468 #define ISIS_COMMON_HEADER_SIZE (sizeof(struct isis_common_header))
469 #define ISIS_IIH_LAN_HEADER_SIZE (sizeof(struct isis_iih_lan_header))
470 #define ISIS_IIH_PTP_HEADER_SIZE (sizeof(struct isis_iih_ptp_header))
471 #define ISIS_LSP_HEADER_SIZE (sizeof(struct isis_lsp_header))
472 #define ISIS_CSNP_HEADER_SIZE (sizeof(struct isis_csnp_header))
473 #define ISIS_PSNP_HEADER_SIZE (sizeof(struct isis_psnp_header))
474
475 void isoclns_print(const u_int8_t *p, u_int length, u_int caplen)
476 {
477         const struct isis_common_header *header;
478
479         header = (const struct isis_common_header *)p;
480
481         printf("%sOSI", caplen < 1 ? "|" : "");
482
483         if (caplen < 1) /* enough bytes on the wire ? */
484                 return;
485
486         switch (*p) {
487
488         case NLPID_CLNS:
489                 (void)printf(", CLNS, length %u", length);
490                 break;
491
492         case NLPID_ESIS:
493                 esis_print(p, length);
494                 return;
495
496         case NLPID_ISIS:
497                 if (!isis_print(p, length))
498                         print_unknown_data(p,"\n\t",caplen);
499                 break;
500
501         case NLPID_NULLNS:
502                 (void)printf(", ISO NULLNS, length: %u", length);
503                 break;
504
505         default:
506                 (void)printf(", Unknown NLPID 0x%02x, length: %u", p[0], length);
507                 if (caplen > 1)
508                         print_unknown_data(p,"\n\t",caplen);
509                 break;
510         }
511 }
512
513 #define ESIS_REDIRECT   6
514 #define ESIS_ESH        2
515 #define ESIS_ISH        4
516
517 static struct tok esis_values[] = {
518     { ESIS_REDIRECT, "redirect"},
519     { ESIS_ESH,      "ESH"},
520     { ESIS_ISH,      "ISH"},
521     { 0, NULL }
522 };
523
524 struct esis_hdr {
525         u_int8_t version;
526         u_int8_t reserved;
527         u_int8_t type;
528         u_int8_t tmo[2];
529         u_int8_t cksum[2];
530 };
531
532 static void
533 esis_print(const u_int8_t *p, u_int length)
534 {
535         const u_int8_t *ep;
536         u_int li;
537         const struct esis_hdr *eh;
538
539         if (length <= 2) {
540                 if (qflag)
541                         printf(" bad pkt!");
542                 else
543                         printf(" no header at all!");
544                 return;
545         }
546         li = p[1];
547         eh = (const struct esis_hdr *) &p[2];
548         ep = p + li;
549         if (li > length) {
550                 if (qflag)
551                         printf(" bad pkt!");
552                 else
553                         printf(" LI(%d) > PDU size (%d)!", li, length);
554                 return;
555         }
556         if (li < sizeof(struct esis_hdr) + 2) {
557                 if (qflag)
558                         printf(" bad pkt!");
559                 else {
560                         printf(" too short for esis header %d:", li);
561                         while (--length != 0)
562                                 printf("%02X", *p++);
563                 }
564                 return;
565         }
566
567         printf(", ES-IS, %s, length %u",
568                tok2str(esis_values,"unknown type: %u",eh->type & 0x1f),
569                length);
570
571         if(vflag < 1)
572                return;
573
574         if (vflag && osi_cksum(p, li)) {
575                 printf(" bad cksum (got 0x%02x%02x)",
576                        eh->cksum[1], eh->cksum[0]);
577                 default_print(p, length);
578                 return;
579         }
580         if (eh->version != 1) {
581                 printf(" unsupported version %d", eh->version);
582                 return;
583         }
584         p += sizeof(*eh) + 2;
585         li -= sizeof(*eh) + 2;  /* protoid * li */
586
587         switch (eh->type & 0x1f) {
588         case ESIS_REDIRECT: {
589                 const u_int8_t *dst, *snpa, *is;
590
591                 dst = p; p += *p + 1;
592                 if (p > snapend)
593                         return;
594                 printf("\n\t\t %s", isonsap_string(dst));
595                 snpa = p; p += *p + 1;
596                 is = p;   p += *p + 1;
597                 if (p > snapend)
598                         return;
599                 if (p > ep) {
600                         printf(" [bad li]");
601                         return;
602                 }
603                 if (is[0] == 0)
604                         printf(" > %s", etheraddr_string(&snpa[1]));
605                 else
606                         printf(" > %s", isonsap_string(is));
607                 li = ep - p;
608                 break;
609         }
610
611         case ESIS_ESH:
612                 break;
613
614         case ESIS_ISH: {
615                 const u_int8_t *is;
616
617                 is = p; p += *p + 1;
618                 if (p > ep) {
619                         printf(" [bad li]");
620                         return;
621                 }
622                 if (p > snapend)
623                         return;
624                 if (!qflag)
625                         printf("\n\tNET: %s", print_nsap(is+1,*is));
626                 li = ep - p;
627                 break;
628         }
629
630         default:
631             if (vflag <= 1) {
632                     if (p < snapend) 
633                             print_unknown_data(p,"\n\t  ",snapend-p);
634             }
635             return;
636         }
637
638         /* hexdump - FIXME ? */
639         if (vflag > 1) {
640                     if (p < snapend)
641                             print_unknown_data(p,"\n\t  ",snapend-p);
642         }
643         if (vflag)
644                 while (p < ep && li) {
645                         u_int op, opli;
646                         const u_int8_t *q;
647
648                         if (snapend - p < 2)
649                                 return;
650                         if (li < 2) {
651                                 printf(", bad opts/li");
652                                 return;
653                         }
654                         op = *p++;
655                         opli = *p++;
656                         li -= 2;
657                         if (opli > li) {
658                                 printf(", opt (%d) too long", op);
659                                 return;
660                         }
661                         li -= opli;
662                         q = p;
663                         p += opli;
664
665                         if (snapend < p)
666                                 return;
667
668                         if (op == TLV_HOLDTIME && opli == 2) {
669                                 printf("\n\tholdtime: %us", EXTRACT_16BITS(q));
670                                 continue;
671                         }
672
673                         if (op == TLV_PROTOCOLS && opli >= 1) {
674                                 printf("\n\t%s (length: %u): %s",
675                                        tok2str(isis_tlv_values, "unknown", op),
676                                        opli,
677                                        tok2str(osi_nlpid_values,"Unknown 0x%02x",*q));
678                                 continue;
679                         }
680
681                         print_unknown_data(q,"\n\t  ",opli);
682                 }
683 }
684
685 /* shared routine for printing system, node and lsp-ids */
686 static char *
687 isis_print_id(const u_int8_t *cp, int id_len)
688 {
689     int i;
690     static char id[sizeof("xxxx.xxxx.xxxx.yy-zz")];
691     char *pos = id;
692
693     for (i = 1; i <= SYSTEM_ID_LEN; i++) {
694         snprintf(pos, sizeof(id) - (pos - id), "%02x", *cp++);
695         pos += strlen(pos);
696         if (i == 2 || i == 4)
697             *pos++ = '.';
698         }
699     if (id_len >= NODE_ID_LEN) {
700         snprintf(pos, sizeof(id) - (pos - id), ".%02x", *cp++);
701         pos += strlen(pos);
702     }
703     if (id_len == LSP_ID_LEN)
704         snprintf(pos, sizeof(id) - (pos - id), "-%02x", *cp);
705     return (id);
706 }
707
708 /* print the 4-byte metric block which is common found in the old-style TLVs */
709 static int
710 isis_print_metric_block (const struct isis_metric_block *isis_metric_block)
711 {
712     printf(", Default Metric: %d, %s",
713            ISIS_LSP_TLV_METRIC_VALUE(isis_metric_block->metric_default),
714            ISIS_LSP_TLV_METRIC_IE(isis_metric_block->metric_default) ? "External" : "Internal");
715     if (!ISIS_LSP_TLV_METRIC_SUPPORTED(isis_metric_block->metric_delay))
716         printf("\n\t\t  Delay Metric: %d, %s",
717                ISIS_LSP_TLV_METRIC_VALUE(isis_metric_block->metric_delay),
718                ISIS_LSP_TLV_METRIC_IE(isis_metric_block->metric_delay) ? "External" : "Internal");
719     if (!ISIS_LSP_TLV_METRIC_SUPPORTED(isis_metric_block->metric_expense))
720         printf("\n\t\t  Expense Metric: %d, %s",
721                ISIS_LSP_TLV_METRIC_VALUE(isis_metric_block->metric_expense),
722                ISIS_LSP_TLV_METRIC_IE(isis_metric_block->metric_expense) ? "External" : "Internal");
723     if (!ISIS_LSP_TLV_METRIC_SUPPORTED(isis_metric_block->metric_error))
724         printf("\n\t\t  Error Metric: %d, %s",
725                ISIS_LSP_TLV_METRIC_VALUE(isis_metric_block->metric_error),
726                ISIS_LSP_TLV_METRIC_IE(isis_metric_block->metric_error) ? "External" : "Internal");
727
728     return(1); /* everything is ok */
729 }
730
731 static int
732 isis_print_tlv_ip_reach (const u_int8_t *cp, const char *ident, int length)
733 {
734         int prefix_len;
735         const struct isis_tlv_ip_reach *tlv_ip_reach;
736
737         tlv_ip_reach = (const struct isis_tlv_ip_reach *)cp;
738
739         while (length > 0) {
740                 if ((size_t)length < sizeof(*tlv_ip_reach)) {
741                         printf("short IPv4 Reachability (%d vs %lu)",
742                                length,
743                                (unsigned long)sizeof(*tlv_ip_reach));
744                         return (0);
745                 }
746
747                 if (!TTEST(*tlv_ip_reach))
748                     return (0);
749
750                 prefix_len = mask2plen(EXTRACT_32BITS(tlv_ip_reach->mask));
751
752                 if (prefix_len == -1)
753                         printf("%sIPv4 prefix: %s mask %s",
754                                ident,
755                                ipaddr_string((tlv_ip_reach->prefix)),
756                                ipaddr_string((tlv_ip_reach->mask)));
757                 else
758                         printf("%sIPv4 prefix: %15s/%u",
759                                ident,
760                                ipaddr_string((tlv_ip_reach->prefix)),
761                                prefix_len);
762
763                 printf(", Distribution: %s, Metric: %u, %s",
764                        ISIS_LSP_TLV_METRIC_UPDOWN(tlv_ip_reach->isis_metric_block.metric_default) ? "down" : "up",
765                        ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->isis_metric_block.metric_default),
766                        ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->isis_metric_block.metric_default) ? "External" : "Internal");
767
768                 if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_ip_reach->isis_metric_block.metric_delay))
769                     printf("%s  Delay Metric: %u, %s",
770                            ident,
771                            ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->isis_metric_block.metric_delay),
772                            ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->isis_metric_block.metric_delay) ? "External" : "Internal");
773                 
774                 if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_ip_reach->isis_metric_block.metric_expense))
775                     printf("%s  Expense Metric: %u, %s",
776                            ident,
777                            ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->isis_metric_block.metric_expense),
778                            ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->isis_metric_block.metric_expense) ? "External" : "Internal");
779                 
780                 if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_ip_reach->isis_metric_block.metric_error))
781                     printf("%s  Error Metric: %u, %s",
782                            ident,
783                            ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->isis_metric_block.metric_error),
784                            ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->isis_metric_block.metric_error) ? "External" : "Internal");
785
786                 length -= sizeof(struct isis_tlv_ip_reach);
787                 tlv_ip_reach++;
788         }
789         return (1);
790 }
791
792 /*
793  * this is the common IP-REACH subTLV decoder it is called
794  * from various EXTD-IP REACH TLVs (135,235,236,237)
795  */
796
797 static int
798 isis_print_ip_reach_subtlv (const u_int8_t *tptr,int subt,int subl,const char *ident) {
799
800         /* first lets see if we know the subTLVs name*/
801         printf("%s%s subTLV #%u, length: %u",
802                ident,
803                tok2str(isis_ext_ip_reach_subtlv_values,
804                        "unknown",
805                        subt),
806                subt,
807                subl);
808
809         if (!TTEST2(*tptr,subl))
810             goto trunctlv;
811
812     switch(subt) {
813     case SUBTLV_EXTD_IP_REACH_ADMIN_TAG32:
814         while (subl >= 4) {
815             printf(", 0x%08x (=%u)",
816                    EXTRACT_32BITS(tptr),
817                    EXTRACT_32BITS(tptr));
818             tptr+=4;
819             subl-=4;
820         }
821         break;
822     case SUBTLV_EXTD_IP_REACH_ADMIN_TAG64:
823         while (subl >= 8) {
824             printf(", 0x%08x%08x",
825                    EXTRACT_32BITS(tptr),
826                    EXTRACT_32BITS(tptr+4));
827             tptr+=8;
828             subl-=8;
829         }
830         break;
831     default:
832         if(!print_unknown_data(tptr,"\n\t\t    ",
833                                subl))
834           return(0);
835         break;
836     }
837     return(1);
838         
839 trunctlv:
840     printf("%spacket exceeded snapshot",ident);
841     return(0);
842 }
843
844 /*
845  * this is the common IS-REACH subTLV decoder it is called
846  * from isis_print_ext_is_reach()
847  */
848
849 static int
850 isis_print_is_reach_subtlv (const u_int8_t *tptr,int subt,int subl,const char *ident) {
851
852         int priority_level;
853         union { /* int to float conversion buffer for several subTLVs */
854             float f; 
855             u_int32_t i;
856         } bw;
857
858         /* first lets see if we know the subTLVs name*/
859         printf("%s%s subTLV #%u, length: %u",
860                ident,
861                tok2str(isis_ext_is_reach_subtlv_values,
862                        "unknown",
863                        subt),
864                subt,
865                subl);
866
867         if (!TTEST2(*tptr,subl))
868             goto trunctlv;
869
870         switch(subt) {
871         case SUBTLV_EXT_IS_REACH_ADMIN_GROUP:      
872         case SUBTLV_EXT_IS_REACH_LINK_LOCAL_REMOTE_ID:
873         case SUBTLV_EXT_IS_REACH_LINK_REMOTE_ID:
874             if (subl >= 4) {
875               printf(", 0x%08x", EXTRACT_32BITS(tptr));
876               if (subl == 8) /* draft-ietf-isis-gmpls-extensions */
877                 printf(", 0x%08x", EXTRACT_32BITS(tptr+4));
878             }
879             break;
880         case SUBTLV_EXT_IS_REACH_IPV4_INTF_ADDR:
881         case SUBTLV_EXT_IS_REACH_IPV4_NEIGHBOR_ADDR:
882             if (subl >= 4)
883               printf(", %s", ipaddr_string(tptr));
884             break;
885         case SUBTLV_EXT_IS_REACH_MAX_LINK_BW :
886         case SUBTLV_EXT_IS_REACH_RESERVABLE_BW:  
887             if (subl >= 4) {
888               bw.i = EXTRACT_32BITS(tptr);
889               printf(", %.3f Mbps", bw.f*8/1000000 );
890             }
891             break;
892         case SUBTLV_EXT_IS_REACH_UNRESERVED_BW :
893             if (subl >= 32) {
894               for (priority_level = 0; priority_level < 8; priority_level++) {
895                 bw.i = EXTRACT_32BITS(tptr);
896                 printf("%s  priority level %d: %.3f Mbps",
897                        ident,
898                        priority_level,
899                        bw.f*8/1000000 );
900                 tptr+=4;
901               }
902             }
903             break;
904         case SUBTLV_EXT_IS_REACH_TE_METRIC:
905             if (subl >= 3)
906               printf(", %u", EXTRACT_24BITS(tptr));
907             break;
908         case SUBTLV_EXT_IS_REACH_LINK_PROTECTION_TYPE:
909             if (subl >= 2) {
910               printf(", %s, Priority %u",
911                    bittok2str(gmpls_link_prot_values, "none", *tptr),
912                    *(tptr+1));
913             }
914             break;
915         case SUBTLV_EXT_IS_REACH_INTF_SW_CAP_DESCR:
916             if (subl >= 36) {
917               printf("%s  Interface Switching Capability:%s",
918                    ident,
919                    tok2str(gmpls_switch_cap_values, "Unknown", *(tptr)));
920               printf(", LSP Encoding: %s",
921                    tok2str(gmpls_encoding_values, "Unknown", *(tptr+1)));
922               tptr+=4;
923               printf("%s  Max LSP Bandwidth:",ident);
924               for (priority_level = 0; priority_level < 8; priority_level++) {
925                 bw.i = EXTRACT_32BITS(tptr);
926                 printf("%s    priority level %d: %.3f Mbps",
927                        ident,
928                        priority_level,
929                        bw.f*8/1000000 );
930                 tptr+=4;
931               }
932               subl-=36;
933               /* there is some optional stuff left to decode but this is as of yet
934                  not specified so just lets hexdump what is left */
935               if(subl>0){
936                 if(!print_unknown_data(tptr,"\n\t\t    ",
937                                        subl-36))
938                     return(0);
939               }
940             }
941             break;
942         default:
943             if(!print_unknown_data(tptr,"\n\t\t    ",
944                                    subl))
945                 return(0);
946             break;
947         }
948         return(1);
949
950 trunctlv:
951     printf("%spacket exceeded snapshot",ident);
952     return(0);
953 }
954
955
956 /*
957  * this is the common IS-REACH decoder it is called
958  * from various EXTD-IS REACH style TLVs (22,24,222)
959  */
960
961 static int
962 isis_print_ext_is_reach (const u_int8_t *tptr,const char *ident, int tlv_type) {
963
964     char ident_buffer[20];
965     int subtlv_type,subtlv_len,subtlv_sum_len;
966     int proc_bytes = 0; /* how many bytes did we process ? */
967     
968     if (!TTEST2(*tptr, NODE_ID_LEN))
969         return(0);
970
971     printf("%sIS Neighbor: %s", ident, isis_print_id(tptr, NODE_ID_LEN));
972     tptr+=(NODE_ID_LEN);
973
974     if (tlv_type != TLV_IS_ALIAS_ID) { /* the Alias TLV Metric field is implicit 0 */
975         if (!TTEST2(*tptr, 3))    /* and is therefore skipped */
976             return(0);
977         printf(", Metric: %d",EXTRACT_24BITS(tptr));
978         tptr+=3;
979     }
980         
981     if (!TTEST2(*tptr, 1))
982         return(0);
983     subtlv_sum_len=*(tptr++); /* read out subTLV length */
984     proc_bytes=NODE_ID_LEN+3+1;
985     printf(", %ssub-TLVs present",subtlv_sum_len ? "" : "no ");
986     if (subtlv_sum_len) {
987         printf(" (%u)",subtlv_sum_len);
988         while (subtlv_sum_len>0) {
989             if (!TTEST2(*tptr,2))
990                 return(0);
991             subtlv_type=*(tptr++);
992             subtlv_len=*(tptr++);
993             /* prepend the ident string */
994             snprintf(ident_buffer, sizeof(ident_buffer), "%s  ",ident);
995             if(!isis_print_is_reach_subtlv(tptr,subtlv_type,subtlv_len,ident_buffer))
996                 return(0);
997             tptr+=subtlv_len;
998             subtlv_sum_len-=(subtlv_len+2);
999             proc_bytes+=(subtlv_len+2);
1000         }
1001     }
1002     return(proc_bytes);
1003 }
1004
1005 /*
1006  * this is the common Multi Topology ID decoder
1007  * it is called from various MT-TLVs (222,229,235,237)
1008  */
1009
1010 static int
1011 isis_print_mtid (const u_int8_t *tptr,const char *ident) {
1012     
1013     if (!TTEST2(*tptr, 2))
1014         return(0);
1015
1016     printf("%s%s",
1017            ident,
1018            tok2str(isis_mt_values,
1019                    "Reserved for IETF Consensus",
1020                    ISIS_MASK_MTID(EXTRACT_16BITS(tptr))));
1021
1022     printf(" Topology (0x%03x), Flags: [%s]",
1023            ISIS_MASK_MTID(EXTRACT_16BITS(tptr)),
1024            bittok2str(isis_mt_flag_values, "none",ISIS_MASK_MTFLAGS(EXTRACT_16BITS(tptr))));
1025
1026     return(2);
1027 }
1028
1029 /*
1030  * this is the common extended IP reach decoder
1031  * it is called from TLVs (135,235,236,237)
1032  * we process the TLV and optional subTLVs and return
1033  * the amount of processed bytes
1034  */
1035
1036 static int
1037 isis_print_extd_ip_reach (const u_int8_t *tptr, const char *ident, u_int16_t afi) {
1038
1039     char ident_buffer[20];
1040     u_int8_t prefix[16]; /* shared copy buffer for IPv4 and IPv6 prefixes */
1041     u_int metric, status_byte, bit_length, byte_length, sublen, processed, subtlvtype, subtlvlen;
1042
1043     if (!TTEST2(*tptr, 4))
1044         return (0);
1045     metric = EXTRACT_32BITS(tptr);
1046     processed=4;
1047     tptr+=4;
1048     
1049     if (afi == IPV4) {
1050         if (!TTEST2(*tptr, 1)) /* fetch status byte */
1051             return (0);
1052         status_byte=*(tptr++);
1053         bit_length = status_byte&0x3f;
1054         processed++;
1055 #ifdef INET6
1056     } else if (afi == IPV6) {
1057         if (!TTEST2(*tptr, 1)) /* fetch status & prefix_len byte */
1058             return (0);
1059         status_byte=*(tptr++);
1060         bit_length=*(tptr++);
1061         processed+=2;
1062 #endif
1063     } else
1064         return (0); /* somebody is fooling us */
1065
1066     byte_length = (bit_length + 7) / 8; /* prefix has variable length encoding */
1067    
1068     if (!TTEST2(*tptr, byte_length))
1069         return (0);
1070     memset(prefix, 0, 16);              /* clear the copy buffer */
1071     memcpy(prefix,tptr,byte_length);    /* copy as much as is stored in the TLV */
1072     tptr+=byte_length;
1073     processed+=byte_length;
1074
1075     if (afi == IPV4)
1076         printf("%sIPv4 prefix: %15s/%u",
1077                ident,
1078                ipaddr_string(prefix),
1079                bit_length);
1080 #ifdef INET6
1081     if (afi == IPV6)
1082         printf("%sIPv6 prefix: %s/%u",
1083                ident,
1084                ip6addr_string(prefix),
1085                bit_length);
1086 #endif 
1087    
1088     printf(", Distribution: %s, Metric: %u",
1089            ISIS_MASK_TLV_EXTD_IP_UPDOWN(status_byte) ? "down" : "up",
1090            metric);
1091
1092     if (afi == IPV4 && ISIS_MASK_TLV_EXTD_IP_SUBTLV(status_byte))
1093         printf(", sub-TLVs present");
1094 #ifdef INET6
1095     if (afi == IPV6)
1096         printf(", %s%s",
1097                ISIS_MASK_TLV_EXTD_IP6_IE(status_byte) ? "External" : "Internal",
1098                ISIS_MASK_TLV_EXTD_IP6_SUBTLV(status_byte) ? ", sub-TLVs present" : "");
1099 #endif
1100     
1101     if ((ISIS_MASK_TLV_EXTD_IP_SUBTLV(status_byte)  && afi == IPV4) ||
1102         (ISIS_MASK_TLV_EXTD_IP6_SUBTLV(status_byte) && afi == IPV6)) {
1103         /* assume that one prefix can hold more
1104            than one subTLV - therefore the first byte must reflect
1105            the aggregate bytecount of the subTLVs for this prefix
1106         */
1107         if (!TTEST2(*tptr, 1))
1108             return (0);
1109         sublen=*(tptr++);
1110         processed+=sublen+1;
1111         printf(" (%u)",sublen);   /* print out subTLV length */
1112         
1113         while (sublen>0) {
1114             if (!TTEST2(*tptr,2))
1115                 return (0);
1116             subtlvtype=*(tptr++);
1117             subtlvlen=*(tptr++);
1118             /* prepend the ident string */
1119             snprintf(ident_buffer, sizeof(ident_buffer), "%s  ",ident);
1120             if(!isis_print_ip_reach_subtlv(tptr,subtlvtype,subtlvlen,ident_buffer))
1121                 return(0);
1122             tptr+=subtlvlen;
1123             sublen-=(subtlvlen+2);
1124         }
1125     }
1126     return (processed);
1127 }
1128
1129 /*
1130  * isis_print
1131  * Decode IS-IS packets.  Return 0 on error.
1132  */
1133
1134 static int isis_print (const u_int8_t *p, u_int length)
1135 {
1136     const struct isis_common_header *header;
1137
1138     const struct isis_iih_lan_header *header_iih_lan;
1139     const struct isis_iih_ptp_header *header_iih_ptp;
1140     const struct isis_lsp_header *header_lsp;
1141     const struct isis_csnp_header *header_csnp;
1142     const struct isis_psnp_header *header_psnp;
1143
1144     const struct isis_tlv_lsp *tlv_lsp;
1145     const struct isis_tlv_ptp_adj *tlv_ptp_adj;
1146     const struct isis_tlv_is_reach *tlv_is_reach;
1147     const struct isis_tlv_es_reach *tlv_es_reach;
1148
1149     u_int8_t pdu_type, max_area, id_length, tlv_type, tlv_len, tmp, alen, lan_alen, prefix_len;
1150     u_int8_t ext_is_len, ext_ip_len, mt_len;
1151     const u_int8_t *optr, *pptr, *tptr;
1152     u_short packet_len,pdu_len;
1153     u_int i;
1154
1155     packet_len=length;
1156     optr = p; /* initialize the _o_riginal pointer to the packet start -
1157                  need it for parsing the checksum TLV */
1158     header = (const struct isis_common_header *)p;
1159     TCHECK(*header);
1160     pptr = p+(ISIS_COMMON_HEADER_SIZE);
1161     header_iih_lan = (const struct isis_iih_lan_header *)pptr;
1162     header_iih_ptp = (const struct isis_iih_ptp_header *)pptr;
1163     header_lsp = (const struct isis_lsp_header *)pptr;
1164     header_csnp = (const struct isis_csnp_header *)pptr;
1165     header_psnp = (const struct isis_psnp_header *)pptr;
1166
1167     /*
1168      * Sanity checking of the header.
1169      */
1170
1171     if (header->version != ISIS_VERSION) {
1172         printf(", version %d packet not supported", header->version);
1173         return (0);
1174     }
1175
1176     if ((header->id_length != SYSTEM_ID_LEN) && (header->id_length != 0)) {
1177         printf(", system ID length of %d is not supported",
1178                header->id_length);
1179         return (0);
1180     }
1181
1182     if (header->pdu_version != ISIS_VERSION) {
1183         printf(", version %d packet not supported", header->pdu_version);
1184         return (0);
1185     }
1186
1187     max_area = header->max_area;
1188     switch(max_area) {
1189     case 0:
1190         max_area = 3;    /* silly shit */
1191         break;
1192     case 255:
1193         printf(", bad packet -- 255 areas");
1194         return (0);
1195     default:
1196         break;
1197     }
1198
1199     id_length = header->id_length;
1200     switch(id_length) {
1201     case 0:
1202         id_length = 6;   /* silly shit again */
1203         break;
1204     case 1:              /* 1-8 are valid sys-ID lenghts */
1205     case 2:
1206     case 3:
1207     case 4:
1208     case 5:
1209     case 6:
1210     case 7:
1211     case 8:
1212         break;
1213     case 255:
1214         id_length = 0;   /* entirely useless */
1215         break;
1216     default:
1217         break;
1218     }
1219
1220     /* toss any non 6-byte sys-ID len PDUs */
1221     if (id_length != 6 ) { 
1222         printf(", bad packet -- illegal sys-ID length (%u)", id_length);
1223         return (0);
1224     }
1225
1226     pdu_type=header->pdu_type;
1227
1228     /* in non-verbose mode print the basic PDU Type plus PDU specific brief information*/
1229     if (vflag < 1) {
1230         printf(", IS-IS, %s",
1231                tok2str(isis_pdu_values,"unknown PDU-Type %u",pdu_type));
1232
1233         switch (pdu_type) {
1234
1235         case L1_LAN_IIH:
1236         case L2_LAN_IIH:
1237             printf(", src-id %s",
1238                    isis_print_id(header_iih_lan->source_id,SYSTEM_ID_LEN));
1239             printf(", lan-id %s, prio %u",
1240                    isis_print_id(header_iih_lan->lan_id,NODE_ID_LEN),
1241                    header_iih_lan->priority);
1242             break;
1243         case PTP_IIH:
1244             printf(", src-id %s", isis_print_id(header_iih_ptp->source_id,SYSTEM_ID_LEN));
1245             break;
1246         case L1_LSP:
1247         case L2_LSP:
1248             printf(", lsp-id %s, seq 0x%08x, lifetime %5us",
1249                    isis_print_id(header_lsp->lsp_id, LSP_ID_LEN),
1250                    EXTRACT_32BITS(header_lsp->sequence_number),
1251                    EXTRACT_16BITS(header_lsp->remaining_lifetime));
1252             break;
1253         case L1_CSNP:
1254         case L2_CSNP:
1255             printf(", src-id %s", isis_print_id(header_csnp->source_id,SYSTEM_ID_LEN));
1256             break;
1257         case L1_PSNP:
1258         case L2_PSNP:
1259             printf(", src-id %s", isis_print_id(header_psnp->source_id,SYSTEM_ID_LEN));
1260             break;
1261
1262         }
1263         printf(", length %u", length);
1264
1265         return(1);
1266     }
1267
1268     /* ok they seem to want to know everything - lets fully decode it */
1269     printf(", IS-IS, length: %u",length);
1270
1271     printf("\n\t%s, hlen: %u, v: %u, pdu-v: %u, sys-id-len: %u (%u), max-area: %u (%u)",
1272            tok2str(isis_pdu_values,
1273                    "unknown, type %u",
1274                    pdu_type),
1275            header->fixed_len,
1276            header->version,
1277            header->pdu_version,
1278            id_length,
1279            header->id_length,
1280            max_area,
1281            header->max_area);
1282
1283     if (vflag > 1) {
1284         if(!print_unknown_data(optr,"\n\t",8)) /* provide the _o_riginal pointer */
1285             return(0);                         /* for optionally debugging the common header */
1286     }
1287
1288     switch (pdu_type) {
1289
1290     case L1_LAN_IIH:
1291     case L2_LAN_IIH:
1292         if (header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE)) {
1293             printf(", bogus fixed header length %u should be %lu",
1294                    header->fixed_len, (unsigned long)ISIS_IIH_LAN_HEADER_SIZE);
1295             return (0);
1296         }
1297
1298         pdu_len=EXTRACT_16BITS(header_iih_lan->pdu_len);
1299         if (packet_len>pdu_len) {
1300             packet_len=pdu_len; /* do TLV decoding as long as it makes sense */
1301             length=pdu_len;
1302         }
1303
1304         TCHECK(*header_iih_lan);
1305         printf("\n\t  source-id: %s,  holding time: %us, Flags: [%s]",
1306                isis_print_id(header_iih_lan->source_id,SYSTEM_ID_LEN),
1307                EXTRACT_16BITS(header_iih_lan->holding_time),
1308                tok2str(isis_iih_circuit_type_values,
1309                        "unknown circuit type 0x%02x",
1310                        header_iih_lan->circuit_type));
1311
1312         printf("\n\t  lan-id:    %s, Priority: %u, PDU length: %u",
1313                isis_print_id(header_iih_lan->lan_id, NODE_ID_LEN),
1314                (header_iih_lan->priority) & PRIORITY_MASK,
1315                pdu_len);
1316
1317         if (vflag > 1) {
1318             if(!print_unknown_data(pptr,"\n\t  ",ISIS_IIH_LAN_HEADER_SIZE))
1319                 return(0);
1320         }
1321
1322         packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE);
1323         pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE);
1324         break;
1325
1326     case PTP_IIH:
1327         if (header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE)) {
1328             printf(", bogus fixed header length %u should be %lu",
1329                    header->fixed_len, (unsigned long)ISIS_IIH_PTP_HEADER_SIZE);
1330             return (0);
1331         }
1332
1333         pdu_len=EXTRACT_16BITS(header_iih_ptp->pdu_len);
1334         if (packet_len>pdu_len) {
1335             packet_len=pdu_len; /* do TLV decoding as long as it makes sense */
1336             length=pdu_len;
1337         }
1338
1339         TCHECK(*header_iih_ptp);
1340         printf("\n\t  source-id: %s, holding time: %us, Flags: [%s]",
1341                isis_print_id(header_iih_ptp->source_id,SYSTEM_ID_LEN),
1342                EXTRACT_16BITS(header_iih_ptp->holding_time),
1343                tok2str(isis_iih_circuit_type_values,
1344                        "unknown circuit type 0x%02x",
1345                        header_iih_ptp->circuit_type));
1346
1347         printf("\n\t  circuit-id: 0x%02x, PDU length: %u",
1348                header_iih_ptp->circuit_id,
1349                pdu_len);
1350
1351         if (vflag > 1) {
1352             if(!print_unknown_data(pptr,"\n\t  ",ISIS_IIH_PTP_HEADER_SIZE))
1353                 return(0);
1354         }
1355
1356         packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE);
1357         pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE);
1358         break;
1359
1360     case L1_LSP:
1361     case L2_LSP:
1362         if (header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE)) {
1363             printf(", bogus fixed header length %u should be %lu",
1364                    header->fixed_len, (unsigned long)ISIS_LSP_HEADER_SIZE);
1365             return (0);
1366         }
1367
1368         pdu_len=EXTRACT_16BITS(header_lsp->pdu_len);
1369         if (packet_len>pdu_len) {
1370             packet_len=pdu_len; /* do TLV decoding as long as it makes sense */
1371             length=pdu_len;
1372         }
1373
1374         TCHECK(*header_lsp);
1375         printf("\n\t  lsp-id: %s, seq: 0x%08x, lifetime: %5us\n\t  chksum: 0x%04x",
1376                isis_print_id(header_lsp->lsp_id, LSP_ID_LEN),
1377                EXTRACT_32BITS(header_lsp->sequence_number),
1378                EXTRACT_16BITS(header_lsp->remaining_lifetime),
1379                EXTRACT_16BITS(header_lsp->checksum));
1380
1381         /* if this is a purge do not attempt to verify the checksum */
1382         if ( EXTRACT_16BITS(header_lsp->remaining_lifetime) == 0 &&
1383              EXTRACT_16BITS(header_lsp->checksum) == 0)
1384             printf(" (purged)");
1385         else
1386             /* verify the checksum -
1387              * checking starts at the lsp-id field at byte position [12]
1388              * hence the length needs to be reduced by 12 bytes */
1389             printf(" (%s)", (osi_cksum((u_int8_t *)header_lsp->lsp_id, length-12)) ? "incorrect" : "correct");
1390
1391         printf(", PDU length: %u, Flags: [ %s",
1392                pdu_len,
1393                ISIS_MASK_LSP_OL_BIT(header_lsp->typeblock) ? "Overload bit set, " : "");
1394
1395         if (ISIS_MASK_LSP_ATT_BITS(header_lsp->typeblock)) {
1396             printf("%s", ISIS_MASK_LSP_ATT_DEFAULT_BIT(header_lsp->typeblock) ? "default " : "");
1397             printf("%s", ISIS_MASK_LSP_ATT_DELAY_BIT(header_lsp->typeblock) ? "delay " : "");
1398             printf("%s", ISIS_MASK_LSP_ATT_EXPENSE_BIT(header_lsp->typeblock) ? "expense " : "");
1399             printf("%s", ISIS_MASK_LSP_ATT_ERROR_BIT(header_lsp->typeblock) ? "error " : "");
1400             printf("ATT bit set, ");
1401         }
1402         printf("%s", ISIS_MASK_LSP_PARTITION_BIT(header_lsp->typeblock) ? "P bit set, " : "");
1403         printf("%s ]", tok2str(isis_lsp_istype_values,"Unknown(0x%x)",ISIS_MASK_LSP_ISTYPE_BITS(header_lsp->typeblock)));
1404
1405         if (vflag > 1) {
1406             if(!print_unknown_data(pptr,"\n\t  ",ISIS_LSP_HEADER_SIZE))
1407                 return(0);
1408         }
1409
1410         packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE);
1411         pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE);
1412         break;
1413
1414     case L1_CSNP:
1415     case L2_CSNP:
1416         if (header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE)) {
1417             printf(", bogus fixed header length %u should be %lu",
1418                    header->fixed_len, (unsigned long)ISIS_CSNP_HEADER_SIZE);
1419             return (0);
1420         }
1421
1422         pdu_len=EXTRACT_16BITS(header_csnp->pdu_len);
1423         if (packet_len>pdu_len) {
1424             packet_len=pdu_len; /* do TLV decoding as long as it makes sense */
1425             length=pdu_len;
1426         }
1427
1428         TCHECK(*header_csnp);
1429         printf("\n\t  source-id:    %s, PDU length: %u",
1430                isis_print_id(header_csnp->source_id, NODE_ID_LEN),
1431                pdu_len);
1432         printf("\n\t  start lsp-id: %s",
1433                isis_print_id(header_csnp->start_lsp_id, LSP_ID_LEN));
1434         printf("\n\t  end lsp-id:   %s",
1435                isis_print_id(header_csnp->end_lsp_id, LSP_ID_LEN));
1436
1437         if (vflag > 1) {
1438             if(!print_unknown_data(pptr,"\n\t  ",ISIS_CSNP_HEADER_SIZE))
1439                 return(0);
1440         }
1441
1442         packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE);
1443         pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE);
1444         break;
1445
1446     case L1_PSNP:
1447     case L2_PSNP:
1448         if (header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE)) {
1449             printf("- bogus fixed header length %u should be %lu",
1450                    header->fixed_len, (unsigned long)ISIS_PSNP_HEADER_SIZE);
1451             return (0);
1452         }
1453
1454         pdu_len=EXTRACT_16BITS(header_psnp->pdu_len);
1455         if (packet_len>pdu_len) {
1456             packet_len=pdu_len; /* do TLV decoding as long as it makes sense */
1457             length=pdu_len;
1458         }
1459
1460         TCHECK(*header_psnp);
1461         printf("\n\t  source-id:    %s, PDU length: %u",
1462                isis_print_id(header_psnp->source_id, NODE_ID_LEN),
1463                pdu_len);
1464
1465         if (vflag > 1) {
1466             if(!print_unknown_data(pptr,"\n\t  ",ISIS_PSNP_HEADER_SIZE))
1467                 return(0);
1468         }
1469
1470         packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE);
1471         pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE);
1472         break;
1473
1474     default:
1475         if(!print_unknown_data(pptr,"\n\t  ",length))
1476             return(0);
1477         return (0);
1478     }
1479
1480     /*
1481      * Now print the TLV's.
1482      */
1483
1484     while (packet_len >= 2) {
1485         if (pptr == snapend) {
1486             return (1);
1487         }
1488
1489         if (!TTEST2(*pptr, 2)) {
1490             printf("\n\t\t packet exceeded snapshot (%ld) bytes",
1491                    (long)(pptr-snapend));
1492             return (1);
1493         }
1494         tlv_type = *pptr++;
1495         tlv_len = *pptr++;
1496         tmp =tlv_len; /* copy temporary len & pointer to packet data */
1497         tptr = pptr;
1498         packet_len -= 2;
1499         if (tlv_len > packet_len) {
1500             break;
1501         }
1502
1503         /* first lets see if we know the TLVs name*/
1504         printf("\n\t    %s TLV #%u, length: %u",
1505                tok2str(isis_tlv_values,
1506                        "unknown",
1507                        tlv_type),
1508                tlv_type,
1509                tlv_len);
1510
1511         /* now check if we have a decoder otherwise do a hexdump at the end*/
1512         switch (tlv_type) {
1513         case TLV_AREA_ADDR:
1514             if (!TTEST2(*tptr, 1))
1515                 goto trunctlv;
1516             alen = *tptr++;
1517             while (tmp && alen < tmp) {
1518                 printf("\n\t      Area address (length: %u): %s",
1519                        alen,
1520                        print_nsap(tptr, alen));
1521                 tptr += alen;
1522                 tmp -= alen + 1;
1523                 if (tmp==0) /* if this is the last area address do not attemt a boundary check */
1524                     break;
1525                 if (!TTEST2(*tptr, 1))
1526                     goto trunctlv;
1527                 alen = *tptr++;
1528             }
1529             break;
1530         case TLV_ISNEIGH:
1531             while (tmp >= ETHER_ADDR_LEN) {
1532                 if (!TTEST2(*tptr, ETHER_ADDR_LEN))
1533                     goto trunctlv;
1534                 printf("\n\t      SNPA: %s",isis_print_id(tptr,ETHER_ADDR_LEN));
1535                 tmp -= ETHER_ADDR_LEN;
1536                 tptr += ETHER_ADDR_LEN;
1537             }
1538             break;
1539
1540         case TLV_ISNEIGH_VARLEN:
1541             if (!TTEST2(*tptr, 1))
1542                 goto trunctlv;
1543             lan_alen = *tptr++; /* LAN adress length */
1544             tmp --;
1545             printf("\n\t      LAN address length %u bytes ",lan_alen);
1546             while (tmp >= lan_alen) {
1547                 if (!TTEST2(*tptr, lan_alen))
1548                     goto trunctlv;
1549                 printf("\n\t\tIS Neighbor: %s",isis_print_id(tptr,lan_alen));
1550                 tmp -= lan_alen;
1551                 tptr +=lan_alen;
1552             }
1553             break;
1554
1555         case TLV_PADDING:
1556             break;
1557
1558         case TLV_MT_IS_REACH:
1559             while (tmp >= 2+NODE_ID_LEN+3+1) {
1560                 mt_len = isis_print_mtid(tptr, "\n\t      ");
1561                 if (mt_len == 0) /* did something go wrong ? */
1562                     goto trunctlv;
1563                 tptr+=mt_len;
1564                 tmp-=mt_len;
1565
1566                 ext_is_len = isis_print_ext_is_reach(tptr,"\n\t      ",tlv_type);
1567                 if (ext_is_len == 0) /* did something go wrong ? */
1568                     goto trunctlv;
1569                    
1570                 tmp-=ext_is_len;
1571                 tptr+=ext_is_len;
1572             }
1573             break;
1574
1575         case TLV_IS_ALIAS_ID:
1576             while (tmp >= NODE_ID_LEN+1) { /* is it worth attempting a decode ? */
1577                 ext_is_len = isis_print_ext_is_reach(tptr,"\n\t      ",tlv_type);
1578                 if (ext_is_len == 0) /* did something go wrong ? */
1579                     goto trunctlv;
1580                 tmp-=ext_is_len;
1581                 tptr+=ext_is_len;
1582             }
1583             break;
1584
1585         case TLV_EXT_IS_REACH:
1586             while (tmp >= NODE_ID_LEN+3+1) { /* is it worth attempting a decode ? */
1587                 ext_is_len = isis_print_ext_is_reach(tptr,"\n\t      ",tlv_type);
1588                 if (ext_is_len == 0) /* did something go wrong ? */
1589                     goto trunctlv;                   
1590                 tmp-=ext_is_len;
1591                 tptr+=ext_is_len;
1592             }
1593             break;
1594         case TLV_IS_REACH:
1595             if (!TTEST2(*tptr,1))  /* check if there is one byte left to read out the virtual flag */
1596                 goto trunctlv;
1597             printf("\n\t      %s",
1598                    tok2str(isis_is_reach_virtual_values,
1599                            "bogus virtual flag 0x%02x",
1600                            *tptr++));
1601             tlv_is_reach = (const struct isis_tlv_is_reach *)tptr;
1602             while (tmp >= sizeof(struct isis_tlv_is_reach)) {
1603                 if (!TTEST(*tlv_is_reach))
1604                     goto trunctlv;
1605                 printf("\n\t      IS Neighbor: %s",
1606                        isis_print_id(tlv_is_reach->neighbor_nodeid, NODE_ID_LEN));
1607                 isis_print_metric_block(&tlv_is_reach->isis_metric_block);
1608                 tmp -= sizeof(struct isis_tlv_is_reach);
1609                 tlv_is_reach++;
1610             }
1611             break;
1612
1613         case TLV_ESNEIGH:
1614             tlv_es_reach = (const struct isis_tlv_es_reach *)tptr;
1615             while (tmp >= sizeof(struct isis_tlv_es_reach)) {
1616                 if (!TTEST(*tlv_es_reach))
1617                     goto trunctlv;
1618                 printf("\n\t      ES Neighbor: %s",
1619                        isis_print_id(tlv_es_reach->neighbor_sysid,SYSTEM_ID_LEN));
1620                 isis_print_metric_block(&tlv_es_reach->isis_metric_block);
1621                 tmp -= sizeof(struct isis_tlv_es_reach);
1622                 tlv_es_reach++;
1623             }
1624             break;
1625
1626             /* those two TLVs share the same format */
1627         case TLV_INT_IP_REACH:
1628         case TLV_EXT_IP_REACH:
1629             if (!isis_print_tlv_ip_reach(pptr, "\n\t      ", tlv_len))
1630                 return (1);
1631             break;
1632
1633         case TLV_EXTD_IP_REACH:
1634             while (tmp>0) {
1635                 ext_ip_len = isis_print_extd_ip_reach(tptr, "\n\t      ", IPV4);
1636                 if (ext_ip_len == 0) /* did something go wrong ? */
1637                     goto trunctlv;
1638                 tptr+=ext_ip_len;
1639                 tmp-=ext_ip_len;
1640             }
1641             break;
1642
1643         case TLV_MT_IP_REACH:
1644             while (tmp>0) {
1645                 mt_len = isis_print_mtid(tptr, "\n\t      ");
1646                 if (mt_len == 0) /* did something go wrong ? */
1647                     goto trunctlv;
1648                 tptr+=mt_len;
1649                 tmp-=mt_len;
1650
1651                 ext_ip_len = isis_print_extd_ip_reach(tptr, "\n\t      ", IPV4);
1652                 if (ext_ip_len == 0) /* did something go wrong ? */
1653                     goto trunctlv;
1654                 tptr+=ext_ip_len;
1655                 tmp-=ext_ip_len;
1656             }
1657             break;
1658
1659 #ifdef INET6
1660         case TLV_IP6_REACH:
1661             while (tmp>0) {
1662                 ext_ip_len = isis_print_extd_ip_reach(tptr, "\n\t      ", IPV6);
1663                 if (ext_ip_len == 0) /* did something go wrong ? */
1664                     goto trunctlv;
1665                 tptr+=ext_ip_len;
1666                 tmp-=ext_ip_len;
1667             }
1668             break;
1669
1670         case TLV_MT_IP6_REACH:
1671             while (tmp>0) {
1672                 mt_len = isis_print_mtid(tptr, "\n\t      ");
1673                 if (mt_len == 0) /* did something go wrong ? */
1674                     goto trunctlv;
1675                 tptr+=mt_len;
1676                 tmp-=mt_len;
1677
1678                 ext_ip_len = isis_print_extd_ip_reach(tptr, "\n\t      ", IPV6);
1679                 if (ext_ip_len == 0) /* did something go wrong ? */
1680                     goto trunctlv;
1681                 tptr+=ext_ip_len;
1682                 tmp-=ext_ip_len;
1683             }
1684             break;
1685
1686         case TLV_IP6ADDR:
1687             while (tmp>0) {
1688                 if (!TTEST2(*tptr, 16))
1689                     goto trunctlv;
1690
1691                 printf("\n\t      IPv6 interface address: %s",
1692                        ip6addr_string(tptr));
1693
1694                 tptr += 16;
1695                 tmp -= 16;
1696             }
1697             break;
1698 #endif
1699         case TLV_AUTH:
1700             if (!TTEST2(*tptr, 1))
1701                 goto trunctlv;
1702
1703             printf("\n\t      %s: ",
1704                    tok2str(isis_subtlv_auth_values,
1705                            "unknown Authentication type 0x%02x",
1706                            *tptr));
1707
1708             switch (*tptr) {
1709             case SUBTLV_AUTH_SIMPLE:
1710                 for(i=1;i<tlv_len;i++) {
1711                     if (!TTEST2(*(tptr+i), 1))
1712                         goto trunctlv;
1713                     printf("%c",*(tptr+i));
1714                 }
1715                 break;
1716             case SUBTLV_AUTH_MD5:
1717                 for(i=1;i<tlv_len;i++) {
1718                     if (!TTEST2(*(tptr+i), 1))
1719                         goto trunctlv;
1720                     printf("%02x",*(tptr+i));
1721                 }
1722                 if (tlv_len != SUBTLV_AUTH_MD5_LEN+1)
1723                     printf(", (malformed subTLV) ");
1724                 break;
1725             case SUBTLV_AUTH_PRIVATE:
1726             default:
1727                 if(!print_unknown_data(tptr+1,"\n\t\t  ",tlv_len-1))
1728                     return(0);
1729                 break;
1730             }
1731             break;
1732
1733         case TLV_PTP_ADJ:
1734             tlv_ptp_adj = (const struct isis_tlv_ptp_adj *)tptr;
1735             if(tmp>=1) {
1736                 if (!TTEST2(*tptr, 1))
1737                     goto trunctlv;
1738                 printf("\n\t      Adjacency State: %s (%u)",
1739                        tok2str(isis_ptp_adjancey_values, "unknown", *tptr),
1740                         *tptr);
1741                 tmp--;
1742             }
1743             if(tmp>sizeof(tlv_ptp_adj->extd_local_circuit_id)) {
1744                 if (!TTEST2(tlv_ptp_adj->extd_local_circuit_id,
1745                             sizeof(tlv_ptp_adj->extd_local_circuit_id)))
1746                     goto trunctlv;
1747                 printf("\n\t      Extended Local circuit-ID: 0x%08x",
1748                        EXTRACT_32BITS(tlv_ptp_adj->extd_local_circuit_id));
1749                 tmp-=sizeof(tlv_ptp_adj->extd_local_circuit_id);
1750             }
1751             if(tmp>=SYSTEM_ID_LEN) {
1752                 if (!TTEST2(tlv_ptp_adj->neighbor_sysid, SYSTEM_ID_LEN))
1753                     goto trunctlv;
1754                 printf("\n\t      Neighbor System-ID: %s",
1755                        isis_print_id(tlv_ptp_adj->neighbor_sysid,SYSTEM_ID_LEN));
1756                 tmp-=SYSTEM_ID_LEN;
1757             }
1758             if(tmp>=sizeof(tlv_ptp_adj->neighbor_extd_local_circuit_id)) {
1759                 if (!TTEST2(tlv_ptp_adj->neighbor_extd_local_circuit_id,
1760                             sizeof(tlv_ptp_adj->neighbor_extd_local_circuit_id)))
1761                     goto trunctlv;
1762                 printf("\n\t      Neighbor Extended Local circuit-ID: 0x%08x",
1763                        EXTRACT_32BITS(tlv_ptp_adj->neighbor_extd_local_circuit_id));
1764             }
1765             break;
1766
1767         case TLV_PROTOCOLS:
1768             printf("\n\t      NLPID(s): ");
1769             while (tmp>0) {
1770                 if (!TTEST2(*(tptr), 1))
1771                     goto trunctlv;
1772                 printf("%s (0x%02x)",
1773                        tok2str(osi_nlpid_values,
1774                                "unknown",
1775                                *tptr),
1776                        *tptr);
1777                 if (tmp>1) /* further NPLIDs ? - put comma */
1778                     printf(", ");
1779                 tptr++;
1780                 tmp--;
1781             }
1782             break;
1783
1784         case TLV_TE_ROUTER_ID:
1785             if (!TTEST2(*pptr, 4))
1786                 goto trunctlv;
1787             printf("\n\t      Traffic Engineering Router ID: %s", ipaddr_string(pptr));
1788             break;
1789
1790         case TLV_IPADDR:
1791             while (tmp>0) {
1792                 if (!TTEST2(*tptr, 4))
1793                     goto trunctlv;
1794                 printf("\n\t      IPv4 interface address: %s", ipaddr_string(tptr));
1795                 tptr += 4;
1796                 tmp -= 4;
1797             }
1798             break;
1799
1800         case TLV_HOSTNAME:
1801             printf("\n\t      Hostname: ");
1802             while (tmp>0) {
1803                 if (!TTEST2(*tptr, 1))
1804                     goto trunctlv;
1805                 printf("%c",*tptr++);
1806                 tmp--;
1807             }
1808             break;
1809
1810         case TLV_SHARED_RISK_GROUP:
1811             if (!TTEST2(*tptr, NODE_ID_LEN))
1812                 goto trunctlv;
1813             printf("\n\t      IS Neighbor: %s", isis_print_id(tptr, NODE_ID_LEN));
1814             tptr+=(NODE_ID_LEN);
1815             tmp-=(NODE_ID_LEN);
1816
1817             if (!TTEST2(*tptr, 1))
1818                 goto trunctlv;
1819             printf(", Flags: [%s]", ISIS_MASK_TLV_SHARED_RISK_GROUP(*tptr++) ? "numbered" : "unnumbered");
1820             tmp--;
1821
1822             if (!TTEST2(*tptr,4))
1823                 goto trunctlv;
1824             printf("\n\t      IPv4 interface address: %s", ipaddr_string(tptr));
1825             tptr+=4;
1826             tmp-=4;
1827
1828             if (!TTEST2(*tptr,4))
1829                 goto trunctlv;
1830             printf("\n\t      IPv4 neighbor address: %s", ipaddr_string(tptr));
1831             tptr+=4;
1832             tmp-=4;
1833
1834             while (tmp>0) {
1835                 if (!TTEST2(*tptr, 4))
1836                     goto trunctlv;
1837                 printf("\n\t      Link-ID: 0x%08x", EXTRACT_32BITS(tptr));
1838                 tptr+=4;
1839                 tmp-=4;
1840             }
1841             break;
1842
1843         case TLV_LSP:
1844             tlv_lsp = (const struct isis_tlv_lsp *)tptr;
1845             while(tmp>0) {
1846                 if (!TTEST((tlv_lsp->lsp_id)[LSP_ID_LEN-1]))
1847                     goto trunctlv;
1848                 printf("\n\t      lsp-id: %s",
1849                        isis_print_id(tlv_lsp->lsp_id, LSP_ID_LEN));
1850                 if (!TTEST2(tlv_lsp->sequence_number, 4))
1851                     goto trunctlv;
1852                 printf(", seq: 0x%08x",EXTRACT_32BITS(tlv_lsp->sequence_number));
1853                 if (!TTEST2(tlv_lsp->remaining_lifetime, 2))
1854                     goto trunctlv;
1855                 printf(", lifetime: %5ds",EXTRACT_16BITS(tlv_lsp->remaining_lifetime));
1856                 if (!TTEST2(tlv_lsp->checksum, 2))
1857                     goto trunctlv;
1858                 printf(", chksum: 0x%04x",EXTRACT_16BITS(tlv_lsp->checksum));
1859                 tmp-=sizeof(struct isis_tlv_lsp);
1860                 tlv_lsp++;
1861             }
1862             break;
1863
1864         case TLV_CHECKSUM:
1865             if (!TTEST2(*tptr, 2))
1866                 goto trunctlv;
1867             printf("\n\t      checksum: 0x%04x ", EXTRACT_16BITS(tptr));
1868             /* do not attempt to verify the checksum if it is zero
1869              * most likely a HMAC-MD5 TLV is also present and
1870              * to avoid conflicts the checksum TLV is zeroed.
1871              * see rfc3358 for details
1872              */
1873             if (EXTRACT_16BITS(tptr) == 0)
1874                 printf("(unverified)");
1875             else printf("(%s)", osi_cksum(optr, length) ? "incorrect" : "correct");
1876             break;
1877
1878         case TLV_MT_SUPPORTED:
1879             while (tmp>1) {
1880                 /* length can only be a multiple of 2, otherwise there is
1881                    something broken -> so decode down until length is 1 */
1882                 if (tmp!=1) {
1883                     mt_len = isis_print_mtid(tptr, "\n\t      ");
1884                     if (mt_len == 0) /* did something go wrong ? */
1885                         goto trunctlv;
1886                     tptr+=mt_len;
1887                     tmp-=mt_len;
1888                 } else {
1889                     printf("\n\t      malformed MT-ID");
1890                     break;
1891                 }
1892             }
1893             break;
1894
1895         case TLV_RESTART_SIGNALING:
1896             if (!TTEST2(*tptr, 3))
1897                 goto trunctlv;
1898             printf("\n\t      Flags [%s], Remaining holding time %us",
1899                    bittok2str(isis_restart_flag_values, "none", *tptr),
1900                    EXTRACT_16BITS(tptr+1));
1901             tptr+=3;
1902             break;
1903
1904         case TLV_IDRP_INFO:
1905             if (!TTEST2(*tptr, 1))
1906                 goto trunctlv;
1907             printf("\n\t      Inter-Domain Information Type: %s",
1908                    tok2str(isis_subtlv_idrp_values,
1909                            "Unknown (0x%02x)",
1910                            *tptr));
1911             switch (*tptr++) {
1912             case SUBTLV_IDRP_ASN:
1913                 if (!TTEST2(*tptr, 2)) /* fetch AS number */
1914                     goto trunctlv;
1915                 printf("AS Number: %u",EXTRACT_16BITS(tptr));
1916                 break;
1917             case SUBTLV_IDRP_LOCAL:
1918             case SUBTLV_IDRP_RES:
1919             default:
1920                 if(!print_unknown_data(tptr,"\n\t      ",tlv_len-1))
1921                     return(0);
1922                 break;
1923             }
1924             break;
1925
1926         case TLV_LSP_BUFFERSIZE:
1927             if (!TTEST2(*tptr, 2))
1928                 goto trunctlv;
1929             printf("\n\t      LSP Buffersize: %u",EXTRACT_16BITS(tptr));
1930             break;
1931
1932         case TLV_PART_DIS:
1933             while (tmp >= SYSTEM_ID_LEN) {
1934                 if (!TTEST2(*tptr, SYSTEM_ID_LEN))
1935                     goto trunctlv;
1936                 printf("\n\t      %s",isis_print_id(tptr,SYSTEM_ID_LEN));
1937                 tptr+=SYSTEM_ID_LEN;
1938                 tmp-=SYSTEM_ID_LEN;
1939             }
1940             break;
1941
1942         case TLV_PREFIX_NEIGH:
1943             if (!TTEST2(*tptr, sizeof(struct isis_metric_block)))
1944                 goto trunctlv;
1945             printf("\n\t      Metric Block");
1946             isis_print_metric_block((const struct isis_metric_block *)tptr);
1947             tptr+=sizeof(struct isis_metric_block);
1948             tmp-=sizeof(struct isis_metric_block);
1949
1950             while(tmp>0) {
1951                 if (!TTEST2(*tptr, 1))
1952                     goto trunctlv;
1953                 prefix_len=*tptr++; /* read out prefix length in semioctets*/
1954                 tmp--;
1955                 if (!TTEST2(*tptr, prefix_len/2))
1956                     goto trunctlv;
1957                 printf("\n\t\tAddress: %s/%u",
1958                        print_nsap(tptr,prefix_len/2),
1959                        prefix_len*4);
1960                 tptr+=prefix_len/2;
1961                 tmp-=prefix_len/2;
1962             }
1963             break;
1964
1965         case TLV_IIH_SEQNR:
1966             if (!TTEST2(*tptr, 4)) /* check if four bytes are on the wire */
1967                 goto trunctlv;
1968             printf("\n\t      Sequence number: %u", EXTRACT_32BITS(tptr) );
1969             break;
1970
1971         case TLV_VENDOR_PRIVATE:
1972             if (!TTEST2(*tptr, 3)) /* check if enough byte for a full oui */
1973                 goto trunctlv;
1974             printf("\n\t      Vendor OUI Code: 0x%06x", EXTRACT_24BITS(tptr) );
1975             tptr+=3;
1976             tmp-=3;
1977             if (tmp > 0) /* hexdump the rest */
1978                 if(!print_unknown_data(tptr,"\n\t\t",tmp))
1979                     return(0);
1980             break;
1981             /*
1982              * FIXME those are the defined TLVs that lack a decoder
1983              * you are welcome to contribute code ;-)
1984              */
1985
1986         case TLV_DECNET_PHASE4:
1987         case TLV_LUCENT_PRIVATE:
1988         case TLV_IPAUTH:
1989         case TLV_NORTEL_PRIVATE1:
1990         case TLV_NORTEL_PRIVATE2:
1991
1992         default:
1993             if (vflag <= 1) {
1994                 if(!print_unknown_data(pptr,"\n\t\t",tlv_len))
1995                     return(0);
1996             }
1997             break;
1998         }
1999         /* do we want to see an additionally hexdump ? */
2000         if (vflag> 1) {
2001             if(!print_unknown_data(pptr,"\n\t      ",tlv_len))
2002                 return(0);
2003         }
2004
2005         pptr += tlv_len;
2006         packet_len -= tlv_len;
2007     }
2008
2009     if (packet_len != 0) {
2010         printf("\n\t      %u straggler bytes", packet_len);
2011     }
2012     return (1);
2013
2014  trunc:
2015     fputs("[|isis]", stdout);
2016     return (1);
2017
2018  trunctlv:
2019     printf("\n\t\t packet exceeded snapshot");
2020     return(1);
2021 }
2022
2023 /*
2024  * Verify the checksum.  See 8473-1, Appendix C, section C.4.
2025  */
2026
2027 static int
2028 osi_cksum(const u_int8_t *tptr, u_int len)
2029 {
2030         int32_t c0 = 0, c1 = 0;
2031
2032         while ((int)--len >= 0) {
2033                 c0 += *tptr++;
2034                 c0 %= 255;
2035                 c1 += c0;
2036                 c1 %= 255;
2037         }
2038         return (c0 | c1);
2039 }