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