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