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