]> The Tcpdump Group git mirrors - tcpdump/blob - print-isoclns.c
9554ec0f7f69c15f1a64a93887de7e6a4e6377e0
[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.126 2005-01-27 10:13:52 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 if (eflag)
497 printf("OSI NLPID %s (0x%02x): ",
498 tok2str(nlpid_values,"Unknown",*p),
499 *p);
500
501 switch (*p) {
502
503 case NLPID_CLNP:
504 if (!clnp_print(p, length))
505 print_unknown_data(p,"\n\t",caplen);
506 break;
507
508 case NLPID_ESIS:
509 esis_print(p, length);
510 return;
511
512 case NLPID_ISIS:
513 if (!isis_print(p, length))
514 print_unknown_data(p,"\n\t",caplen);
515 break;
516
517 case NLPID_NULLNS:
518 (void)printf(", length: %u", length);
519 break;
520
521 case NLPID_Q933:
522 q933_print(p+1, length-1);
523 break;
524
525 case NLPID_IP:
526 ip_print(p+1, length-1);
527 break;
528
529 #ifdef INET6
530 case NLPID_IP6:
531 ip6_print(p+1, length-1);
532 break;
533 #endif
534
535 case NLPID_PPP:
536 ppp_print(p+1, length-1);
537 break;
538
539 default:
540 if (!eflag)
541 printf("OSI NLPID 0x%02x unknown",*p);
542 (void)printf(", length: %u", length);
543 if (caplen > 1)
544 print_unknown_data(p,"\n\t",caplen);
545 break;
546 }
547 }
548
549 #define CLNP_PDU_ER 1
550 #define CLNP_PDU_DT 28
551 #define CLNP_PDU_MD 29
552 #define CLNP_PDU_ERQ 30
553 #define CLNP_PDU_ERP 31
554
555 static struct tok clnp_pdu_values[] = {
556 { CLNP_PDU_ER, "Error Report"},
557 { CLNP_PDU_MD, "MD"},
558 { CLNP_PDU_DT, "Data"},
559 { CLNP_PDU_ERQ, "Echo Request"},
560 { CLNP_PDU_ERP, "Echo Response"},
561 { 0, NULL }
562 };
563
564 struct clnp_header_t {
565 u_int8_t nlpid;
566 u_int8_t length_indicator;
567 u_int8_t version;
568 u_int8_t lifetime; /* units of 500ms */
569 u_int8_t type;
570 u_int8_t segment_length[2];
571 u_int8_t cksum[2];
572 };
573
574 /*
575 * clnp_print
576 * Decode CLNP packets. Return 0 on error.
577 */
578
579 static int clnp_print (const u_int8_t *pptr, u_int length)
580 {
581 const u_int8_t *optr,*source_address,*dest_address;
582 u_int li,source_address_length,dest_address_length, clnp_pdu_type;
583 const struct clnp_header_t *clnp_header;
584
585 clnp_header = (const struct clnp_header_t *) pptr;
586 li = clnp_header->length_indicator;
587 optr = pptr;
588
589 if (!eflag)
590 printf("CLNP");
591
592 /*
593 * Sanity checking of the header.
594 */
595
596 /* FIXME */
597
598 clnp_pdu_type = clnp_header->type & CLNP_PDU_TYPE_MASK;
599
600 pptr += sizeof(struct clnp_header_t);
601 dest_address_length = *pptr;
602 dest_address = pptr + 1;
603
604 pptr += (1 + dest_address_length);
605 source_address_length = *pptr;
606 source_address = pptr +1;
607
608 pptr += (1 + source_address_length);
609
610 if (vflag < 1) {
611 printf("%s%s > %s, length %u",
612 eflag ? "" : ", ",
613 print_nsap(source_address, source_address_length),
614 print_nsap(dest_address, dest_address_length),
615 length);
616 return (1);
617 }
618 printf("%slength %u",eflag ? "" : ", ",length);
619
620 printf("\n\t%s PDU, hlen: %u, v: %u, lifetime: %u.%us, PDU length: %u, checksum: 0x%04x ",
621 tok2str(clnp_pdu_values,
622 "unknown (%u)",
623 clnp_pdu_type),
624 clnp_header->length_indicator,
625 clnp_header->version,
626 clnp_header->lifetime/2,
627 (clnp_header->lifetime%2)*5,
628 EXTRACT_16BITS(clnp_header->segment_length),
629 EXTRACT_16BITS(clnp_header->cksum));
630
631 /* do not attempt to verify the checksum if it is zero */
632 if (EXTRACT_16BITS(clnp_header->cksum) == 0)
633 printf("(unverified)");
634 else printf("(%s)", osi_cksum(optr, li) ? "incorrect" : "correct");
635
636 printf("\n\tsource address (length %u): %s\n\tdest address (length %u): %s",
637 source_address_length,
638 print_nsap(source_address, source_address_length),
639 dest_address_length,
640 print_nsap(dest_address, dest_address_length));
641
642 /* dump the remaining header data */
643 printf("\n\tundecoded header data");
644 print_unknown_data(pptr,"\n\t",clnp_header->length_indicator-(pptr-optr));
645
646 switch (clnp_pdu_type) {
647
648 case CLNP_PDU_ER:
649 case CLNP_PDU_DT:
650 case CLNP_PDU_MD:
651 case CLNP_PDU_ERQ:
652 case CLNP_PDU_ERP:
653
654 default:
655 /* dump the PDU specific data */
656 printf("\n\t undecoded non-header data");
657 print_unknown_data(optr+clnp_header->length_indicator,"\n\t ",length-clnp_header->length_indicator);
658
659 }
660
661 return (1);
662 }
663
664
665 #define ESIS_PDU_REDIRECT 6
666 #define ESIS_PDU_ESH 2
667 #define ESIS_PDU_ISH 4
668
669 static struct tok esis_pdu_values[] = {
670 { ESIS_PDU_REDIRECT, "redirect"},
671 { ESIS_PDU_ESH, "ESH"},
672 { ESIS_PDU_ISH, "ISH"},
673 { 0, NULL }
674 };
675
676 struct esis_header_t {
677 u_int8_t nlpid;
678 u_int8_t length_indicator;
679 u_int8_t version;
680 u_int8_t reserved;
681 u_int8_t type;
682 u_int8_t holdtime[2];
683 u_int8_t cksum[2];
684 };
685
686 static void
687 esis_print(const u_int8_t *pptr, u_int length)
688 {
689 const u_int8_t *optr;
690 u_int li,esis_pdu_type,source_address_length, source_address_number;
691 const struct esis_header_t *esis_header;
692
693 if (!eflag)
694 printf("ES-IS");
695
696 if (length <= 2) {
697 if (qflag)
698 printf("bad pkt!");
699 else
700 printf("no header at all!");
701 return;
702 }
703
704 esis_header = (const struct esis_header_t *) pptr;
705 li = esis_header->length_indicator;
706 optr = pptr;
707
708 /*
709 * Sanity checking of the header.
710 */
711
712 if (esis_header->nlpid != NLPID_ESIS) {
713 printf(" nlpid 0x%02x packet not supported", esis_header->nlpid);
714 return;
715 }
716
717 if (esis_header->version != ESIS_VERSION) {
718 printf(" version %d packet not supported", esis_header->version);
719 return;
720 }
721
722 if (li > length) {
723 printf(" length indicator(%d) > PDU size (%d)!", li, length);
724 return;
725 }
726
727 if (li < sizeof(struct esis_header_t) + 2) {
728 printf(" length indicator < min PDU size %d:", li);
729 while (--length != 0)
730 printf("%02X", *pptr++);
731 return;
732 }
733
734 esis_pdu_type = esis_header->type & ESIS_PDU_TYPE_MASK;
735
736 if (vflag < 1) {
737 printf("%s%s, length %u",
738 eflag ? "" : ", ",
739 tok2str(esis_pdu_values,"unknown type (%u)",esis_pdu_type),
740 length);
741 return;
742 } else
743 printf("%slength %u\n\t%s (%u)",
744 eflag ? "" : ", ",
745 length,
746 tok2str(esis_pdu_values,"unknown type: %u", esis_pdu_type),
747 esis_pdu_type);
748
749 printf(", v: %u%s", esis_header->version, esis_header->version == ESIS_VERSION ? "" : "unsupported" );
750 printf(", checksum: 0x%04x ", EXTRACT_16BITS(esis_header->cksum));
751 /* do not attempt to verify the checksum if it is zero */
752 if (EXTRACT_16BITS(esis_header->cksum) == 0)
753 printf("(unverified)");
754 else printf("(%s)", osi_cksum(pptr, li) ? "incorrect" : "correct");
755
756 printf(", holding time: %us, length indicator: %u",EXTRACT_16BITS(esis_header->holdtime),li);
757
758 if (vflag > 1)
759 print_unknown_data(optr,"\n\t",sizeof(struct esis_header_t));
760
761 pptr += sizeof(struct esis_header_t);
762 li -= sizeof(struct esis_header_t);
763
764 switch (esis_pdu_type) {
765 case ESIS_PDU_REDIRECT: {
766 const u_int8_t *dst, *snpa, *tptr;
767
768 dst = pptr; pptr += *pptr + 1;
769 if (pptr > snapend)
770 return;
771 printf("\n\t %s", isonsap_string(dst));
772 snpa = pptr; pptr += *pptr + 1;
773 tptr = pptr; pptr += *pptr + 1;
774 if (pptr > snapend)
775 return;
776
777 if (tptr[0] == 0)
778 printf("\n\t %s", etheraddr_string(&snpa[1]));
779 else
780 printf("\n\t %s", isonsap_string(tptr));
781 break;
782 }
783
784 case ESIS_PDU_ESH:
785 source_address_number = *pptr;
786 pptr++;
787 li--;
788
789 printf("\n\t Number of Source Addresses: %u", source_address_number);
790
791 while (source_address_number > 0) {
792 source_address_length = *pptr;
793 printf("\n\t NET (length: %u): %s",
794 source_address_length,
795 print_nsap(pptr+1, source_address_length));
796
797 pptr += source_address_length+1;
798 li -= source_address_length+1;
799 source_address_number--;
800 }
801
802 break;
803
804 case ESIS_PDU_ISH: {
805 source_address_length = *pptr;
806 printf("\n\t NET (length: %u): %s", source_address_length, print_nsap(pptr+1, source_address_length));
807 pptr += source_address_length+1;
808 li -= source_address_length +1;
809 break;
810 }
811
812 default:
813 if (vflag <= 1) {
814 if (pptr < snapend)
815 print_unknown_data(pptr,"\n\t ",snapend-pptr);
816 }
817 return;
818 }
819
820 /* now walk the options */
821 while (li >= 2) {
822 u_int op, opli;
823 const u_int8_t *tptr;
824
825 if (snapend - pptr < 2)
826 return;
827 if (li < 2) {
828 printf(", bad opts/li");
829 return;
830 }
831 op = *pptr++;
832 opli = *pptr++;
833 li -= 2;
834 if (opli > li) {
835 printf(", opt (%d) too long", op);
836 return;
837 }
838 li -= opli;
839 tptr = pptr;
840
841 if (snapend < pptr)
842 return;
843
844 printf("\n\t %s Option #%u, length %u, value: ",
845 tok2str(esis_option_values,"Unknown",op),
846 op,
847 opli);
848
849 switch (op) {
850
851 case ESIS_OPTION_ES_CONF_TIME:
852 printf("%us", EXTRACT_16BITS(tptr));
853 break;
854
855
856 case ESIS_OPTION_PROTOCOLS:
857 while (opli>0) {
858 printf("%s (0x%02x)",
859 tok2str(nlpid_values,
860 "unknown",
861 *tptr),
862 *tptr);
863 if (opli>1) /* further NPLIDs ? - put comma */
864 printf(", ");
865 tptr++;
866 opli--;
867 }
868 break;
869
870 /*
871 * FIXME those are the defined Options that lack a decoder
872 * you are welcome to contribute code ;-)
873 */
874
875 case ESIS_OPTION_QOS_MAINTENANCE:
876 case ESIS_OPTION_SECURITY:
877 case ESIS_OPTION_PRIORITY:
878 case ESIS_OPTION_ADDRESS_MASK:
879 case ESIS_OPTION_SNPA_MASK:
880
881 default:
882 print_unknown_data(tptr,"\n\t ",opli);
883 break;
884 }
885 if (vflag > 1)
886 print_unknown_data(pptr,"\n\t ",opli);
887 pptr += opli;
888 }
889 }
890
891 /* shared routine for printing system, node and lsp-ids */
892 static char *
893 isis_print_id(const u_int8_t *cp, int id_len)
894 {
895 int i;
896 static char id[sizeof("xxxx.xxxx.xxxx.yy-zz")];
897 char *pos = id;
898
899 for (i = 1; i <= SYSTEM_ID_LEN; i++) {
900 snprintf(pos, sizeof(id) - (pos - id), "%02x", *cp++);
901 pos += strlen(pos);
902 if (i == 2 || i == 4)
903 *pos++ = '.';
904 }
905 if (id_len >= NODE_ID_LEN) {
906 snprintf(pos, sizeof(id) - (pos - id), ".%02x", *cp++);
907 pos += strlen(pos);
908 }
909 if (id_len == LSP_ID_LEN)
910 snprintf(pos, sizeof(id) - (pos - id), "-%02x", *cp);
911 return (id);
912 }
913
914 /* print the 4-byte metric block which is common found in the old-style TLVs */
915 static int
916 isis_print_metric_block (const struct isis_metric_block *isis_metric_block)
917 {
918 printf(", Default Metric: %d, %s",
919 ISIS_LSP_TLV_METRIC_VALUE(isis_metric_block->metric_default),
920 ISIS_LSP_TLV_METRIC_IE(isis_metric_block->metric_default) ? "External" : "Internal");
921 if (!ISIS_LSP_TLV_METRIC_SUPPORTED(isis_metric_block->metric_delay))
922 printf("\n\t\t Delay Metric: %d, %s",
923 ISIS_LSP_TLV_METRIC_VALUE(isis_metric_block->metric_delay),
924 ISIS_LSP_TLV_METRIC_IE(isis_metric_block->metric_delay) ? "External" : "Internal");
925 if (!ISIS_LSP_TLV_METRIC_SUPPORTED(isis_metric_block->metric_expense))
926 printf("\n\t\t Expense Metric: %d, %s",
927 ISIS_LSP_TLV_METRIC_VALUE(isis_metric_block->metric_expense),
928 ISIS_LSP_TLV_METRIC_IE(isis_metric_block->metric_expense) ? "External" : "Internal");
929 if (!ISIS_LSP_TLV_METRIC_SUPPORTED(isis_metric_block->metric_error))
930 printf("\n\t\t Error Metric: %d, %s",
931 ISIS_LSP_TLV_METRIC_VALUE(isis_metric_block->metric_error),
932 ISIS_LSP_TLV_METRIC_IE(isis_metric_block->metric_error) ? "External" : "Internal");
933
934 return(1); /* everything is ok */
935 }
936
937 static int
938 isis_print_tlv_ip_reach (const u_int8_t *cp, const char *ident, int length)
939 {
940 int prefix_len;
941 const struct isis_tlv_ip_reach *tlv_ip_reach;
942
943 tlv_ip_reach = (const struct isis_tlv_ip_reach *)cp;
944
945 while (length > 0) {
946 if ((size_t)length < sizeof(*tlv_ip_reach)) {
947 printf("short IPv4 Reachability (%d vs %lu)",
948 length,
949 (unsigned long)sizeof(*tlv_ip_reach));
950 return (0);
951 }
952
953 if (!TTEST(*tlv_ip_reach))
954 return (0);
955
956 prefix_len = mask2plen(EXTRACT_32BITS(tlv_ip_reach->mask));
957
958 if (prefix_len == -1)
959 printf("%sIPv4 prefix: %s mask %s",
960 ident,
961 ipaddr_string((tlv_ip_reach->prefix)),
962 ipaddr_string((tlv_ip_reach->mask)));
963 else
964 printf("%sIPv4 prefix: %15s/%u",
965 ident,
966 ipaddr_string((tlv_ip_reach->prefix)),
967 prefix_len);
968
969 printf(", Distribution: %s, Metric: %u, %s",
970 ISIS_LSP_TLV_METRIC_UPDOWN(tlv_ip_reach->isis_metric_block.metric_default) ? "down" : "up",
971 ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->isis_metric_block.metric_default),
972 ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->isis_metric_block.metric_default) ? "External" : "Internal");
973
974 if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_ip_reach->isis_metric_block.metric_delay))
975 printf("%s Delay Metric: %u, %s",
976 ident,
977 ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->isis_metric_block.metric_delay),
978 ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->isis_metric_block.metric_delay) ? "External" : "Internal");
979
980 if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_ip_reach->isis_metric_block.metric_expense))
981 printf("%s Expense Metric: %u, %s",
982 ident,
983 ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->isis_metric_block.metric_expense),
984 ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->isis_metric_block.metric_expense) ? "External" : "Internal");
985
986 if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_ip_reach->isis_metric_block.metric_error))
987 printf("%s Error Metric: %u, %s",
988 ident,
989 ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->isis_metric_block.metric_error),
990 ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->isis_metric_block.metric_error) ? "External" : "Internal");
991
992 length -= sizeof(struct isis_tlv_ip_reach);
993 tlv_ip_reach++;
994 }
995 return (1);
996 }
997
998 /*
999 * this is the common IP-REACH subTLV decoder it is called
1000 * from various EXTD-IP REACH TLVs (135,235,236,237)
1001 */
1002
1003 static int
1004 isis_print_ip_reach_subtlv (const u_int8_t *tptr,int subt,int subl,const char *ident) {
1005
1006 /* first lets see if we know the subTLVs name*/
1007 printf("%s%s subTLV #%u, length: %u",
1008 ident,
1009 tok2str(isis_ext_ip_reach_subtlv_values,
1010 "unknown",
1011 subt),
1012 subt,
1013 subl);
1014
1015 if (!TTEST2(*tptr,subl))
1016 goto trunctlv;
1017
1018 switch(subt) {
1019 case ISIS_SUBTLV_EXTD_IP_REACH_MGMT_PREFIX_COLOR: /* fall through */
1020 case ISIS_SUBTLV_EXTD_IP_REACH_ADMIN_TAG32:
1021 while (subl >= 4) {
1022 printf(", 0x%08x (=%u)",
1023 EXTRACT_32BITS(tptr),
1024 EXTRACT_32BITS(tptr));
1025 tptr+=4;
1026 subl-=4;
1027 }
1028 break;
1029 case ISIS_SUBTLV_EXTD_IP_REACH_ADMIN_TAG64:
1030 while (subl >= 8) {
1031 printf(", 0x%08x%08x",
1032 EXTRACT_32BITS(tptr),
1033 EXTRACT_32BITS(tptr+4));
1034 tptr+=8;
1035 subl-=8;
1036 }
1037 break;
1038 default:
1039 if(!print_unknown_data(tptr,"\n\t\t ",
1040 subl))
1041 return(0);
1042 break;
1043 }
1044 return(1);
1045
1046 trunctlv:
1047 printf("%spacket exceeded snapshot",ident);
1048 return(0);
1049 }
1050
1051 /*
1052 * this is the common IS-REACH subTLV decoder it is called
1053 * from isis_print_ext_is_reach()
1054 */
1055
1056 static int
1057 isis_print_is_reach_subtlv (const u_int8_t *tptr,int subt,int subl,const char *ident) {
1058
1059 int priority_level,bandwidth_constraint;
1060 union { /* int to float conversion buffer for several subTLVs */
1061 float f;
1062 u_int32_t i;
1063 } bw;
1064
1065 /* first lets see if we know the subTLVs name*/
1066 printf("%s%s subTLV #%u, length: %u",
1067 ident,
1068 tok2str(isis_ext_is_reach_subtlv_values,
1069 "unknown",
1070 subt),
1071 subt,
1072 subl);
1073
1074 if (!TTEST2(*tptr,subl))
1075 goto trunctlv;
1076
1077 switch(subt) {
1078 case ISIS_SUBTLV_EXT_IS_REACH_ADMIN_GROUP:
1079 case ISIS_SUBTLV_EXT_IS_REACH_LINK_LOCAL_REMOTE_ID:
1080 case ISIS_SUBTLV_EXT_IS_REACH_LINK_REMOTE_ID:
1081 if (subl >= 4) {
1082 printf(", 0x%08x", EXTRACT_32BITS(tptr));
1083 if (subl == 8) /* draft-ietf-isis-gmpls-extensions */
1084 printf(", 0x%08x", EXTRACT_32BITS(tptr+4));
1085 }
1086 break;
1087 case ISIS_SUBTLV_EXT_IS_REACH_IPV4_INTF_ADDR:
1088 case ISIS_SUBTLV_EXT_IS_REACH_IPV4_NEIGHBOR_ADDR:
1089 if (subl >= 4)
1090 printf(", %s", ipaddr_string(tptr));
1091 break;
1092 case ISIS_SUBTLV_EXT_IS_REACH_MAX_LINK_BW :
1093 case ISIS_SUBTLV_EXT_IS_REACH_RESERVABLE_BW:
1094 if (subl >= 4) {
1095 bw.i = EXTRACT_32BITS(tptr);
1096 printf(", %.3f Mbps", bw.f*8/1000000 );
1097 }
1098 break;
1099 case ISIS_SUBTLV_EXT_IS_REACH_UNRESERVED_BW :
1100 if (subl >= 32) {
1101 for (priority_level = 0; priority_level < 8; priority_level++) {
1102 bw.i = EXTRACT_32BITS(tptr);
1103 printf("%s priority level %d: %.3f Mbps",
1104 ident,
1105 priority_level,
1106 bw.f*8/1000000 );
1107 tptr+=4;
1108 }
1109 }
1110 break;
1111 case ISIS_SUBTLV_EXT_IS_REACH_DIFFSERV_TE:
1112 printf("%sBandwidth Constraints Model ID: %s (%u)",
1113 ident,
1114 tok2str(diffserv_te_bc_values, "unknown", *tptr),
1115 *tptr);
1116 tptr++;
1117 /* decode BCs until the subTLV ends */
1118 for (bandwidth_constraint = 0; bandwidth_constraint < (subl-1)/4; bandwidth_constraint++) {
1119 bw.i = EXTRACT_32BITS(tptr);
1120 printf("%s Bandwidth constraint %d: %.3f Mbps",
1121 ident,
1122 bandwidth_constraint,
1123 bw.f*8/1000000 );
1124 tptr+=4;
1125 }
1126 break;
1127 case ISIS_SUBTLV_EXT_IS_REACH_TE_METRIC:
1128 if (subl >= 3)
1129 printf(", %u", EXTRACT_24BITS(tptr));
1130 break;
1131 case ISIS_SUBTLV_EXT_IS_REACH_LINK_PROTECTION_TYPE:
1132 if (subl >= 2) {
1133 printf(", %s, Priority %u",
1134 bittok2str(gmpls_link_prot_values, "none", *tptr),
1135 *(tptr+1));
1136 }
1137 break;
1138 case ISIS_SUBTLV_EXT_IS_REACH_INTF_SW_CAP_DESCR:
1139 if (subl >= 36) {
1140 printf("%s Interface Switching Capability:%s",
1141 ident,
1142 tok2str(gmpls_switch_cap_values, "Unknown", *(tptr)));
1143 printf(", LSP Encoding: %s",
1144 tok2str(gmpls_encoding_values, "Unknown", *(tptr+1)));
1145 tptr+=4;
1146 printf("%s Max LSP Bandwidth:",ident);
1147 for (priority_level = 0; priority_level < 8; priority_level++) {
1148 bw.i = EXTRACT_32BITS(tptr);
1149 printf("%s priority level %d: %.3f Mbps",
1150 ident,
1151 priority_level,
1152 bw.f*8/1000000 );
1153 tptr+=4;
1154 }
1155 subl-=36;
1156 /* there is some optional stuff left to decode but this is as of yet
1157 not specified so just lets hexdump what is left */
1158 if(subl>0){
1159 if(!print_unknown_data(tptr,"\n\t\t ",
1160 subl-36))
1161 return(0);
1162 }
1163 }
1164 break;
1165 default:
1166 if(!print_unknown_data(tptr,"\n\t\t ",
1167 subl))
1168 return(0);
1169 break;
1170 }
1171 return(1);
1172
1173 trunctlv:
1174 printf("%spacket exceeded snapshot",ident);
1175 return(0);
1176 }
1177
1178
1179 /*
1180 * this is the common IS-REACH decoder it is called
1181 * from various EXTD-IS REACH style TLVs (22,24,222)
1182 */
1183
1184 static int
1185 isis_print_ext_is_reach (const u_int8_t *tptr,const char *ident, int tlv_type) {
1186
1187 char ident_buffer[20];
1188 int subtlv_type,subtlv_len,subtlv_sum_len;
1189 int proc_bytes = 0; /* how many bytes did we process ? */
1190
1191 if (!TTEST2(*tptr, NODE_ID_LEN))
1192 return(0);
1193
1194 printf("%sIS Neighbor: %s", ident, isis_print_id(tptr, NODE_ID_LEN));
1195 tptr+=(NODE_ID_LEN);
1196
1197 if (tlv_type != ISIS_TLV_IS_ALIAS_ID) { /* the Alias TLV Metric field is implicit 0 */
1198 if (!TTEST2(*tptr, 3)) /* and is therefore skipped */
1199 return(0);
1200 printf(", Metric: %d",EXTRACT_24BITS(tptr));
1201 tptr+=3;
1202 }
1203
1204 if (!TTEST2(*tptr, 1))
1205 return(0);
1206 subtlv_sum_len=*(tptr++); /* read out subTLV length */
1207 proc_bytes=NODE_ID_LEN+3+1;
1208 printf(", %ssub-TLVs present",subtlv_sum_len ? "" : "no ");
1209 if (subtlv_sum_len) {
1210 printf(" (%u)",subtlv_sum_len);
1211 while (subtlv_sum_len>0) {
1212 if (!TTEST2(*tptr,2))
1213 return(0);
1214 subtlv_type=*(tptr++);
1215 subtlv_len=*(tptr++);
1216 /* prepend the ident string */
1217 snprintf(ident_buffer, sizeof(ident_buffer), "%s ",ident);
1218 if(!isis_print_is_reach_subtlv(tptr,subtlv_type,subtlv_len,ident_buffer))
1219 return(0);
1220 tptr+=subtlv_len;
1221 subtlv_sum_len-=(subtlv_len+2);
1222 proc_bytes+=(subtlv_len+2);
1223 }
1224 }
1225 return(proc_bytes);
1226 }
1227
1228 /*
1229 * this is the common Multi Topology ID decoder
1230 * it is called from various MT-TLVs (222,229,235,237)
1231 */
1232
1233 static int
1234 isis_print_mtid (const u_int8_t *tptr,const char *ident) {
1235
1236 if (!TTEST2(*tptr, 2))
1237 return(0);
1238
1239 printf("%s%s",
1240 ident,
1241 tok2str(isis_mt_values,
1242 "Reserved for IETF Consensus",
1243 ISIS_MASK_MTID(EXTRACT_16BITS(tptr))));
1244
1245 printf(" Topology (0x%03x), Flags: [%s]",
1246 ISIS_MASK_MTID(EXTRACT_16BITS(tptr)),
1247 bittok2str(isis_mt_flag_values, "none",ISIS_MASK_MTFLAGS(EXTRACT_16BITS(tptr))));
1248
1249 return(2);
1250 }
1251
1252 /*
1253 * this is the common extended IP reach decoder
1254 * it is called from TLVs (135,235,236,237)
1255 * we process the TLV and optional subTLVs and return
1256 * the amount of processed bytes
1257 */
1258
1259 static int
1260 isis_print_extd_ip_reach (const u_int8_t *tptr, const char *ident, u_int16_t afi) {
1261
1262 char ident_buffer[20];
1263 u_int8_t prefix[16]; /* shared copy buffer for IPv4 and IPv6 prefixes */
1264 u_int metric, status_byte, bit_length, byte_length, sublen, processed, subtlvtype, subtlvlen;
1265
1266 if (!TTEST2(*tptr, 4))
1267 return (0);
1268 metric = EXTRACT_32BITS(tptr);
1269 processed=4;
1270 tptr+=4;
1271
1272 if (afi == IPV4) {
1273 if (!TTEST2(*tptr, 1)) /* fetch status byte */
1274 return (0);
1275 status_byte=*(tptr++);
1276 bit_length = status_byte&0x3f;
1277 processed++;
1278 #ifdef INET6
1279 } else if (afi == IPV6) {
1280 if (!TTEST2(*tptr, 1)) /* fetch status & prefix_len byte */
1281 return (0);
1282 status_byte=*(tptr++);
1283 bit_length=*(tptr++);
1284 processed+=2;
1285 #endif
1286 } else
1287 return (0); /* somebody is fooling us */
1288
1289 byte_length = (bit_length + 7) / 8; /* prefix has variable length encoding */
1290
1291 if (!TTEST2(*tptr, byte_length))
1292 return (0);
1293 memset(prefix, 0, 16); /* clear the copy buffer */
1294 memcpy(prefix,tptr,byte_length); /* copy as much as is stored in the TLV */
1295 tptr+=byte_length;
1296 processed+=byte_length;
1297
1298 if (afi == IPV4)
1299 printf("%sIPv4 prefix: %15s/%u",
1300 ident,
1301 ipaddr_string(prefix),
1302 bit_length);
1303 #ifdef INET6
1304 if (afi == IPV6)
1305 printf("%sIPv6 prefix: %s/%u",
1306 ident,
1307 ip6addr_string(prefix),
1308 bit_length);
1309 #endif
1310
1311 printf(", Distribution: %s, Metric: %u",
1312 ISIS_MASK_TLV_EXTD_IP_UPDOWN(status_byte) ? "down" : "up",
1313 metric);
1314
1315 if (afi == IPV4 && ISIS_MASK_TLV_EXTD_IP_SUBTLV(status_byte))
1316 printf(", sub-TLVs present");
1317 #ifdef INET6
1318 if (afi == IPV6)
1319 printf(", %s%s",
1320 ISIS_MASK_TLV_EXTD_IP6_IE(status_byte) ? "External" : "Internal",
1321 ISIS_MASK_TLV_EXTD_IP6_SUBTLV(status_byte) ? ", sub-TLVs present" : "");
1322 #endif
1323
1324 if ((ISIS_MASK_TLV_EXTD_IP_SUBTLV(status_byte) && afi == IPV4) ||
1325 (ISIS_MASK_TLV_EXTD_IP6_SUBTLV(status_byte) && afi == IPV6)) {
1326 /* assume that one prefix can hold more
1327 than one subTLV - therefore the first byte must reflect
1328 the aggregate bytecount of the subTLVs for this prefix
1329 */
1330 if (!TTEST2(*tptr, 1))
1331 return (0);
1332 sublen=*(tptr++);
1333 processed+=sublen+1;
1334 printf(" (%u)",sublen); /* print out subTLV length */
1335
1336 while (sublen>0) {
1337 if (!TTEST2(*tptr,2))
1338 return (0);
1339 subtlvtype=*(tptr++);
1340 subtlvlen=*(tptr++);
1341 /* prepend the ident string */
1342 snprintf(ident_buffer, sizeof(ident_buffer), "%s ",ident);
1343 if(!isis_print_ip_reach_subtlv(tptr,subtlvtype,subtlvlen,ident_buffer))
1344 return(0);
1345 tptr+=subtlvlen;
1346 sublen-=(subtlvlen+2);
1347 }
1348 }
1349 return (processed);
1350 }
1351
1352 /*
1353 * isis_print
1354 * Decode IS-IS packets. Return 0 on error.
1355 */
1356
1357 static int isis_print (const u_int8_t *p, u_int length)
1358 {
1359 const struct isis_common_header *isis_header;
1360
1361 const struct isis_iih_lan_header *header_iih_lan;
1362 const struct isis_iih_ptp_header *header_iih_ptp;
1363 const struct isis_lsp_header *header_lsp;
1364 const struct isis_csnp_header *header_csnp;
1365 const struct isis_psnp_header *header_psnp;
1366
1367 const struct isis_tlv_lsp *tlv_lsp;
1368 const struct isis_tlv_ptp_adj *tlv_ptp_adj;
1369 const struct isis_tlv_is_reach *tlv_is_reach;
1370 const struct isis_tlv_es_reach *tlv_es_reach;
1371
1372 u_int8_t pdu_type, max_area, id_length, tlv_type, tlv_len, tmp, alen, lan_alen, prefix_len;
1373 u_int8_t ext_is_len, ext_ip_len, mt_len;
1374 const u_int8_t *optr, *pptr, *tptr;
1375 u_short packet_len,pdu_len;
1376 u_int i,vendor_id;
1377
1378 packet_len=length;
1379 optr = p; /* initialize the _o_riginal pointer to the packet start -
1380 need it for parsing the checksum TLV */
1381 isis_header = (const struct isis_common_header *)p;
1382 TCHECK(*isis_header);
1383 pptr = p+(ISIS_COMMON_HEADER_SIZE);
1384 header_iih_lan = (const struct isis_iih_lan_header *)pptr;
1385 header_iih_ptp = (const struct isis_iih_ptp_header *)pptr;
1386 header_lsp = (const struct isis_lsp_header *)pptr;
1387 header_csnp = (const struct isis_csnp_header *)pptr;
1388 header_psnp = (const struct isis_psnp_header *)pptr;
1389
1390 if (!eflag)
1391 printf("IS-IS");
1392
1393 /*
1394 * Sanity checking of the header.
1395 */
1396
1397 if (isis_header->version != ISIS_VERSION) {
1398 printf("version %d packet not supported", isis_header->version);
1399 return (0);
1400 }
1401
1402 if ((isis_header->id_length != SYSTEM_ID_LEN) && (isis_header->id_length != 0)) {
1403 printf("system ID length of %d is not supported",
1404 isis_header->id_length);
1405 return (0);
1406 }
1407
1408 if (isis_header->pdu_version != ISIS_VERSION) {
1409 printf("version %d packet not supported", isis_header->pdu_version);
1410 return (0);
1411 }
1412
1413 max_area = isis_header->max_area;
1414 switch(max_area) {
1415 case 0:
1416 max_area = 3; /* silly shit */
1417 break;
1418 case 255:
1419 printf("bad packet -- 255 areas");
1420 return (0);
1421 default:
1422 break;
1423 }
1424
1425 id_length = isis_header->id_length;
1426 switch(id_length) {
1427 case 0:
1428 id_length = 6; /* silly shit again */
1429 break;
1430 case 1: /* 1-8 are valid sys-ID lenghts */
1431 case 2:
1432 case 3:
1433 case 4:
1434 case 5:
1435 case 6:
1436 case 7:
1437 case 8:
1438 break;
1439 case 255:
1440 id_length = 0; /* entirely useless */
1441 break;
1442 default:
1443 break;
1444 }
1445
1446 /* toss any non 6-byte sys-ID len PDUs */
1447 if (id_length != 6 ) {
1448 printf("bad packet -- illegal sys-ID length (%u)", id_length);
1449 return (0);
1450 }
1451
1452 pdu_type=isis_header->pdu_type;
1453
1454 /* in non-verbose mode print the basic PDU Type plus PDU specific brief information*/
1455 if (vflag < 1) {
1456 printf("%s%s",
1457 eflag ? "" : ", ",
1458 tok2str(isis_pdu_values,"unknown PDU-Type %u",pdu_type));
1459
1460 switch (pdu_type) {
1461
1462 case ISIS_PDU_L1_LAN_IIH:
1463 case ISIS_PDU_L2_LAN_IIH:
1464 printf(", src-id %s",
1465 isis_print_id(header_iih_lan->source_id,SYSTEM_ID_LEN));
1466 printf(", lan-id %s, prio %u",
1467 isis_print_id(header_iih_lan->lan_id,NODE_ID_LEN),
1468 header_iih_lan->priority);
1469 break;
1470 case ISIS_PDU_PTP_IIH:
1471 printf(", src-id %s", isis_print_id(header_iih_ptp->source_id,SYSTEM_ID_LEN));
1472 break;
1473 case ISIS_PDU_L1_LSP:
1474 case ISIS_PDU_L2_LSP:
1475 printf(", lsp-id %s, seq 0x%08x, lifetime %5us",
1476 isis_print_id(header_lsp->lsp_id, LSP_ID_LEN),
1477 EXTRACT_32BITS(header_lsp->sequence_number),
1478 EXTRACT_16BITS(header_lsp->remaining_lifetime));
1479 break;
1480 case ISIS_PDU_L1_CSNP:
1481 case ISIS_PDU_L2_CSNP:
1482 printf(", src-id %s", isis_print_id(header_csnp->source_id,NODE_ID_LEN));
1483 break;
1484 case ISIS_PDU_L1_PSNP:
1485 case ISIS_PDU_L2_PSNP:
1486 printf(", src-id %s", isis_print_id(header_psnp->source_id,NODE_ID_LEN));
1487 break;
1488
1489 }
1490 printf(", length %u", length);
1491
1492 return(1);
1493 }
1494
1495 /* ok they seem to want to know everything - lets fully decode it */
1496 printf("%slength %u", eflag ? "" : ", ",length);
1497
1498 printf("\n\t%s, hlen: %u, v: %u, pdu-v: %u, sys-id-len: %u (%u), max-area: %u (%u)",
1499 tok2str(isis_pdu_values,
1500 "unknown, type %u",
1501 pdu_type),
1502 isis_header->fixed_len,
1503 isis_header->version,
1504 isis_header->pdu_version,
1505 id_length,
1506 isis_header->id_length,
1507 max_area,
1508 isis_header->max_area);
1509
1510 if (vflag > 1) {
1511 if(!print_unknown_data(optr,"\n\t",8)) /* provide the _o_riginal pointer */
1512 return(0); /* for optionally debugging the common header */
1513 }
1514
1515 switch (pdu_type) {
1516
1517 case ISIS_PDU_L1_LAN_IIH:
1518 case ISIS_PDU_L2_LAN_IIH:
1519 if (isis_header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE)) {
1520 printf(", bogus fixed header length %u should be %lu",
1521 isis_header->fixed_len, (unsigned long)ISIS_IIH_LAN_HEADER_SIZE);
1522 return (0);
1523 }
1524
1525 pdu_len=EXTRACT_16BITS(header_iih_lan->pdu_len);
1526 if (packet_len>pdu_len) {
1527 packet_len=pdu_len; /* do TLV decoding as long as it makes sense */
1528 length=pdu_len;
1529 }
1530
1531 TCHECK(*header_iih_lan);
1532 printf("\n\t source-id: %s, holding time: %us, Flags: [%s]",
1533 isis_print_id(header_iih_lan->source_id,SYSTEM_ID_LEN),
1534 EXTRACT_16BITS(header_iih_lan->holding_time),
1535 tok2str(isis_iih_circuit_type_values,
1536 "unknown circuit type 0x%02x",
1537 header_iih_lan->circuit_type));
1538
1539 printf("\n\t lan-id: %s, Priority: %u, PDU length: %u",
1540 isis_print_id(header_iih_lan->lan_id, NODE_ID_LEN),
1541 (header_iih_lan->priority) & ISIS_LAN_PRIORITY_MASK,
1542 pdu_len);
1543
1544 if (vflag > 1) {
1545 if(!print_unknown_data(pptr,"\n\t ",ISIS_IIH_LAN_HEADER_SIZE))
1546 return(0);
1547 }
1548
1549 packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE);
1550 pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE);
1551 break;
1552
1553 case ISIS_PDU_PTP_IIH:
1554 if (isis_header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE)) {
1555 printf(", bogus fixed header length %u should be %lu",
1556 isis_header->fixed_len, (unsigned long)ISIS_IIH_PTP_HEADER_SIZE);
1557 return (0);
1558 }
1559
1560 pdu_len=EXTRACT_16BITS(header_iih_ptp->pdu_len);
1561 if (packet_len>pdu_len) {
1562 packet_len=pdu_len; /* do TLV decoding as long as it makes sense */
1563 length=pdu_len;
1564 }
1565
1566 TCHECK(*header_iih_ptp);
1567 printf("\n\t source-id: %s, holding time: %us, Flags: [%s]",
1568 isis_print_id(header_iih_ptp->source_id,SYSTEM_ID_LEN),
1569 EXTRACT_16BITS(header_iih_ptp->holding_time),
1570 tok2str(isis_iih_circuit_type_values,
1571 "unknown circuit type 0x%02x",
1572 header_iih_ptp->circuit_type));
1573
1574 printf("\n\t circuit-id: 0x%02x, PDU length: %u",
1575 header_iih_ptp->circuit_id,
1576 pdu_len);
1577
1578 if (vflag > 1) {
1579 if(!print_unknown_data(pptr,"\n\t ",ISIS_IIH_PTP_HEADER_SIZE))
1580 return(0);
1581 }
1582
1583 packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE);
1584 pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE);
1585 break;
1586
1587 case ISIS_PDU_L1_LSP:
1588 case ISIS_PDU_L2_LSP:
1589 if (isis_header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE)) {
1590 printf(", bogus fixed header length %u should be %lu",
1591 isis_header->fixed_len, (unsigned long)ISIS_LSP_HEADER_SIZE);
1592 return (0);
1593 }
1594
1595 pdu_len=EXTRACT_16BITS(header_lsp->pdu_len);
1596 if (packet_len>pdu_len) {
1597 packet_len=pdu_len; /* do TLV decoding as long as it makes sense */
1598 length=pdu_len;
1599 }
1600
1601 TCHECK(*header_lsp);
1602 printf("\n\t lsp-id: %s, seq: 0x%08x, lifetime: %5us\n\t chksum: 0x%04x",
1603 isis_print_id(header_lsp->lsp_id, LSP_ID_LEN),
1604 EXTRACT_32BITS(header_lsp->sequence_number),
1605 EXTRACT_16BITS(header_lsp->remaining_lifetime),
1606 EXTRACT_16BITS(header_lsp->checksum));
1607
1608 /* if this is a purge do not attempt to verify the checksum */
1609 if ( EXTRACT_16BITS(header_lsp->remaining_lifetime) == 0 &&
1610 EXTRACT_16BITS(header_lsp->checksum) == 0)
1611 printf(" (purged)");
1612 else
1613 /* verify the checksum -
1614 * checking starts at the lsp-id field at byte position [12]
1615 * hence the length needs to be reduced by 12 bytes */
1616 printf(" (%s)", (osi_cksum((u_int8_t *)header_lsp->lsp_id, length-12)) ? "incorrect" : "correct");
1617
1618 printf(", PDU length: %u, Flags: [ %s",
1619 pdu_len,
1620 ISIS_MASK_LSP_OL_BIT(header_lsp->typeblock) ? "Overload bit set, " : "");
1621
1622 if (ISIS_MASK_LSP_ATT_BITS(header_lsp->typeblock)) {
1623 printf("%s", ISIS_MASK_LSP_ATT_DEFAULT_BIT(header_lsp->typeblock) ? "default " : "");
1624 printf("%s", ISIS_MASK_LSP_ATT_DELAY_BIT(header_lsp->typeblock) ? "delay " : "");
1625 printf("%s", ISIS_MASK_LSP_ATT_EXPENSE_BIT(header_lsp->typeblock) ? "expense " : "");
1626 printf("%s", ISIS_MASK_LSP_ATT_ERROR_BIT(header_lsp->typeblock) ? "error " : "");
1627 printf("ATT bit set, ");
1628 }
1629 printf("%s", ISIS_MASK_LSP_PARTITION_BIT(header_lsp->typeblock) ? "P bit set, " : "");
1630 printf("%s ]", tok2str(isis_lsp_istype_values,"Unknown(0x%x)",ISIS_MASK_LSP_ISTYPE_BITS(header_lsp->typeblock)));
1631
1632 if (vflag > 1) {
1633 if(!print_unknown_data(pptr,"\n\t ",ISIS_LSP_HEADER_SIZE))
1634 return(0);
1635 }
1636
1637 packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE);
1638 pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE);
1639 break;
1640
1641 case ISIS_PDU_L1_CSNP:
1642 case ISIS_PDU_L2_CSNP:
1643 if (isis_header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE)) {
1644 printf(", bogus fixed header length %u should be %lu",
1645 isis_header->fixed_len, (unsigned long)ISIS_CSNP_HEADER_SIZE);
1646 return (0);
1647 }
1648
1649 pdu_len=EXTRACT_16BITS(header_csnp->pdu_len);
1650 if (packet_len>pdu_len) {
1651 packet_len=pdu_len; /* do TLV decoding as long as it makes sense */
1652 length=pdu_len;
1653 }
1654
1655 TCHECK(*header_csnp);
1656 printf("\n\t source-id: %s, PDU length: %u",
1657 isis_print_id(header_csnp->source_id, NODE_ID_LEN),
1658 pdu_len);
1659 printf("\n\t start lsp-id: %s",
1660 isis_print_id(header_csnp->start_lsp_id, LSP_ID_LEN));
1661 printf("\n\t end lsp-id: %s",
1662 isis_print_id(header_csnp->end_lsp_id, LSP_ID_LEN));
1663
1664 if (vflag > 1) {
1665 if(!print_unknown_data(pptr,"\n\t ",ISIS_CSNP_HEADER_SIZE))
1666 return(0);
1667 }
1668
1669 packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE);
1670 pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE);
1671 break;
1672
1673 case ISIS_PDU_L1_PSNP:
1674 case ISIS_PDU_L2_PSNP:
1675 if (isis_header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE)) {
1676 printf("- bogus fixed header length %u should be %lu",
1677 isis_header->fixed_len, (unsigned long)ISIS_PSNP_HEADER_SIZE);
1678 return (0);
1679 }
1680
1681 pdu_len=EXTRACT_16BITS(header_psnp->pdu_len);
1682 if (packet_len>pdu_len) {
1683 packet_len=pdu_len; /* do TLV decoding as long as it makes sense */
1684 length=pdu_len;
1685 }
1686
1687 TCHECK(*header_psnp);
1688 printf("\n\t source-id: %s, PDU length: %u",
1689 isis_print_id(header_psnp->source_id, NODE_ID_LEN),
1690 pdu_len);
1691
1692 if (vflag > 1) {
1693 if(!print_unknown_data(pptr,"\n\t ",ISIS_PSNP_HEADER_SIZE))
1694 return(0);
1695 }
1696
1697 packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE);
1698 pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE);
1699 break;
1700
1701 default:
1702 if(!print_unknown_data(pptr,"\n\t ",length))
1703 return(0);
1704 return (0);
1705 }
1706
1707 /*
1708 * Now print the TLV's.
1709 */
1710
1711 while (packet_len >= 2) {
1712 if (pptr == snapend) {
1713 return (1);
1714 }
1715
1716 if (!TTEST2(*pptr, 2)) {
1717 printf("\n\t\t packet exceeded snapshot (%ld) bytes",
1718 (long)(pptr-snapend));
1719 return (1);
1720 }
1721 tlv_type = *pptr++;
1722 tlv_len = *pptr++;
1723 tmp =tlv_len; /* copy temporary len & pointer to packet data */
1724 tptr = pptr;
1725 packet_len -= 2;
1726 if (tlv_len > packet_len) {
1727 break;
1728 }
1729
1730 /* first lets see if we know the TLVs name*/
1731 printf("\n\t %s TLV #%u, length: %u",
1732 tok2str(isis_tlv_values,
1733 "unknown",
1734 tlv_type),
1735 tlv_type,
1736 tlv_len);
1737
1738 /* now check if we have a decoder otherwise do a hexdump at the end*/
1739 switch (tlv_type) {
1740 case ISIS_TLV_AREA_ADDR:
1741 if (!TTEST2(*tptr, 1))
1742 goto trunctlv;
1743 alen = *tptr++;
1744 while (tmp && alen < tmp) {
1745 printf("\n\t Area address (length: %u): %s",
1746 alen,
1747 print_nsap(tptr, alen));
1748 tptr += alen;
1749 tmp -= alen + 1;
1750 if (tmp==0) /* if this is the last area address do not attemt a boundary check */
1751 break;
1752 if (!TTEST2(*tptr, 1))
1753 goto trunctlv;
1754 alen = *tptr++;
1755 }
1756 break;
1757 case ISIS_TLV_ISNEIGH:
1758 while (tmp >= ETHER_ADDR_LEN) {
1759 if (!TTEST2(*tptr, ETHER_ADDR_LEN))
1760 goto trunctlv;
1761 printf("\n\t SNPA: %s",isis_print_id(tptr,ETHER_ADDR_LEN));
1762 tmp -= ETHER_ADDR_LEN;
1763 tptr += ETHER_ADDR_LEN;
1764 }
1765 break;
1766
1767 case ISIS_TLV_ISNEIGH_VARLEN:
1768 if (!TTEST2(*tptr, 1))
1769 goto trunctlv;
1770 lan_alen = *tptr++; /* LAN adress length */
1771 tmp --;
1772 printf("\n\t LAN address length %u bytes ",lan_alen);
1773 while (tmp >= lan_alen) {
1774 if (!TTEST2(*tptr, lan_alen))
1775 goto trunctlv;
1776 printf("\n\t\tIS Neighbor: %s",isis_print_id(tptr,lan_alen));
1777 tmp -= lan_alen;
1778 tptr +=lan_alen;
1779 }
1780 break;
1781
1782 case ISIS_TLV_PADDING:
1783 break;
1784
1785 case ISIS_TLV_MT_IS_REACH:
1786 while (tmp >= 2+NODE_ID_LEN+3+1) {
1787 mt_len = isis_print_mtid(tptr, "\n\t ");
1788 if (mt_len == 0) /* did something go wrong ? */
1789 goto trunctlv;
1790 tptr+=mt_len;
1791 tmp-=mt_len;
1792
1793 ext_is_len = isis_print_ext_is_reach(tptr,"\n\t ",tlv_type);
1794 if (ext_is_len == 0) /* did something go wrong ? */
1795 goto trunctlv;
1796
1797 tmp-=ext_is_len;
1798 tptr+=ext_is_len;
1799 }
1800 break;
1801
1802 case ISIS_TLV_IS_ALIAS_ID:
1803 while (tmp >= NODE_ID_LEN+1) { /* is it worth attempting a decode ? */
1804 ext_is_len = isis_print_ext_is_reach(tptr,"\n\t ",tlv_type);
1805 if (ext_is_len == 0) /* did something go wrong ? */
1806 goto trunctlv;
1807 tmp-=ext_is_len;
1808 tptr+=ext_is_len;
1809 }
1810 break;
1811
1812 case ISIS_TLV_EXT_IS_REACH:
1813 while (tmp >= NODE_ID_LEN+3+1) { /* is it worth attempting a decode ? */
1814 ext_is_len = isis_print_ext_is_reach(tptr,"\n\t ",tlv_type);
1815 if (ext_is_len == 0) /* did something go wrong ? */
1816 goto trunctlv;
1817 tmp-=ext_is_len;
1818 tptr+=ext_is_len;
1819 }
1820 break;
1821 case ISIS_TLV_IS_REACH:
1822 if (!TTEST2(*tptr,1)) /* check if there is one byte left to read out the virtual flag */
1823 goto trunctlv;
1824 printf("\n\t %s",
1825 tok2str(isis_is_reach_virtual_values,
1826 "bogus virtual flag 0x%02x",
1827 *tptr++));
1828 tlv_is_reach = (const struct isis_tlv_is_reach *)tptr;
1829 while (tmp >= sizeof(struct isis_tlv_is_reach)) {
1830 if (!TTEST(*tlv_is_reach))
1831 goto trunctlv;
1832 printf("\n\t IS Neighbor: %s",
1833 isis_print_id(tlv_is_reach->neighbor_nodeid, NODE_ID_LEN));
1834 isis_print_metric_block(&tlv_is_reach->isis_metric_block);
1835 tmp -= sizeof(struct isis_tlv_is_reach);
1836 tlv_is_reach++;
1837 }
1838 break;
1839
1840 case ISIS_TLV_ESNEIGH:
1841 tlv_es_reach = (const struct isis_tlv_es_reach *)tptr;
1842 while (tmp >= sizeof(struct isis_tlv_es_reach)) {
1843 if (!TTEST(*tlv_es_reach))
1844 goto trunctlv;
1845 printf("\n\t ES Neighbor: %s",
1846 isis_print_id(tlv_es_reach->neighbor_sysid,SYSTEM_ID_LEN));
1847 isis_print_metric_block(&tlv_es_reach->isis_metric_block);
1848 tmp -= sizeof(struct isis_tlv_es_reach);
1849 tlv_es_reach++;
1850 }
1851 break;
1852
1853 /* those two TLVs share the same format */
1854 case ISIS_TLV_INT_IP_REACH:
1855 case ISIS_TLV_EXT_IP_REACH:
1856 if (!isis_print_tlv_ip_reach(pptr, "\n\t ", tlv_len))
1857 return (1);
1858 break;
1859
1860 case ISIS_TLV_EXTD_IP_REACH:
1861 while (tmp>0) {
1862 ext_ip_len = isis_print_extd_ip_reach(tptr, "\n\t ", IPV4);
1863 if (ext_ip_len == 0) /* did something go wrong ? */
1864 goto trunctlv;
1865 tptr+=ext_ip_len;
1866 tmp-=ext_ip_len;
1867 }
1868 break;
1869
1870 case ISIS_TLV_MT_IP_REACH:
1871 while (tmp>0) {
1872 mt_len = isis_print_mtid(tptr, "\n\t ");
1873 if (mt_len == 0) /* did something go wrong ? */
1874 goto trunctlv;
1875 tptr+=mt_len;
1876 tmp-=mt_len;
1877
1878 ext_ip_len = isis_print_extd_ip_reach(tptr, "\n\t ", IPV4);
1879 if (ext_ip_len == 0) /* did something go wrong ? */
1880 goto trunctlv;
1881 tptr+=ext_ip_len;
1882 tmp-=ext_ip_len;
1883 }
1884 break;
1885
1886 #ifdef INET6
1887 case ISIS_TLV_IP6_REACH:
1888 while (tmp>0) {
1889 ext_ip_len = isis_print_extd_ip_reach(tptr, "\n\t ", IPV6);
1890 if (ext_ip_len == 0) /* did something go wrong ? */
1891 goto trunctlv;
1892 tptr+=ext_ip_len;
1893 tmp-=ext_ip_len;
1894 }
1895 break;
1896
1897 case ISIS_TLV_MT_IP6_REACH:
1898 while (tmp>0) {
1899 mt_len = isis_print_mtid(tptr, "\n\t ");
1900 if (mt_len == 0) /* did something go wrong ? */
1901 goto trunctlv;
1902 tptr+=mt_len;
1903 tmp-=mt_len;
1904
1905 ext_ip_len = isis_print_extd_ip_reach(tptr, "\n\t ", IPV6);
1906 if (ext_ip_len == 0) /* did something go wrong ? */
1907 goto trunctlv;
1908 tptr+=ext_ip_len;
1909 tmp-=ext_ip_len;
1910 }
1911 break;
1912
1913 case ISIS_TLV_IP6ADDR:
1914 while (tmp>0) {
1915 if (!TTEST2(*tptr, 16))
1916 goto trunctlv;
1917
1918 printf("\n\t IPv6 interface address: %s",
1919 ip6addr_string(tptr));
1920
1921 tptr += 16;
1922 tmp -= 16;
1923 }
1924 break;
1925 #endif
1926 case ISIS_TLV_AUTH:
1927 if (!TTEST2(*tptr, 1))
1928 goto trunctlv;
1929
1930 printf("\n\t %s: ",
1931 tok2str(isis_subtlv_auth_values,
1932 "unknown Authentication type 0x%02x",
1933 *tptr));
1934
1935 switch (*tptr) {
1936 case ISIS_SUBTLV_AUTH_SIMPLE:
1937 for(i=1;i<tlv_len;i++) {
1938 if (!TTEST2(*(tptr+i), 1))
1939 goto trunctlv;
1940 printf("%c",*(tptr+i));
1941 }
1942 break;
1943 case ISIS_SUBTLV_AUTH_MD5:
1944 for(i=1;i<tlv_len;i++) {
1945 if (!TTEST2(*(tptr+i), 1))
1946 goto trunctlv;
1947 printf("%02x",*(tptr+i));
1948 }
1949 if (tlv_len != ISIS_SUBTLV_AUTH_MD5_LEN+1)
1950 printf(", (malformed subTLV) ");
1951 break;
1952 case ISIS_SUBTLV_AUTH_PRIVATE:
1953 default:
1954 if(!print_unknown_data(tptr+1,"\n\t\t ",tlv_len-1))
1955 return(0);
1956 break;
1957 }
1958 break;
1959
1960 case ISIS_TLV_PTP_ADJ:
1961 tlv_ptp_adj = (const struct isis_tlv_ptp_adj *)tptr;
1962 if(tmp>=1) {
1963 if (!TTEST2(*tptr, 1))
1964 goto trunctlv;
1965 printf("\n\t Adjacency State: %s (%u)",
1966 tok2str(isis_ptp_adjancey_values, "unknown", *tptr),
1967 *tptr);
1968 tmp--;
1969 }
1970 if(tmp>sizeof(tlv_ptp_adj->extd_local_circuit_id)) {
1971 if (!TTEST2(tlv_ptp_adj->extd_local_circuit_id,
1972 sizeof(tlv_ptp_adj->extd_local_circuit_id)))
1973 goto trunctlv;
1974 printf("\n\t Extended Local circuit-ID: 0x%08x",
1975 EXTRACT_32BITS(tlv_ptp_adj->extd_local_circuit_id));
1976 tmp-=sizeof(tlv_ptp_adj->extd_local_circuit_id);
1977 }
1978 if(tmp>=SYSTEM_ID_LEN) {
1979 if (!TTEST2(tlv_ptp_adj->neighbor_sysid, SYSTEM_ID_LEN))
1980 goto trunctlv;
1981 printf("\n\t Neighbor System-ID: %s",
1982 isis_print_id(tlv_ptp_adj->neighbor_sysid,SYSTEM_ID_LEN));
1983 tmp-=SYSTEM_ID_LEN;
1984 }
1985 if(tmp>=sizeof(tlv_ptp_adj->neighbor_extd_local_circuit_id)) {
1986 if (!TTEST2(tlv_ptp_adj->neighbor_extd_local_circuit_id,
1987 sizeof(tlv_ptp_adj->neighbor_extd_local_circuit_id)))
1988 goto trunctlv;
1989 printf("\n\t Neighbor Extended Local circuit-ID: 0x%08x",
1990 EXTRACT_32BITS(tlv_ptp_adj->neighbor_extd_local_circuit_id));
1991 }
1992 break;
1993
1994 case ISIS_TLV_PROTOCOLS:
1995 printf("\n\t NLPID(s): ");
1996 while (tmp>0) {
1997 if (!TTEST2(*(tptr), 1))
1998 goto trunctlv;
1999 printf("%s (0x%02x)",
2000 tok2str(nlpid_values,
2001 "unknown",
2002 *tptr),
2003 *tptr);
2004 if (tmp>1) /* further NPLIDs ? - put comma */
2005 printf(", ");
2006 tptr++;
2007 tmp--;
2008 }
2009 break;
2010
2011 case ISIS_TLV_TE_ROUTER_ID:
2012 if (!TTEST2(*pptr, 4))
2013 goto trunctlv;
2014 printf("\n\t Traffic Engineering Router ID: %s", ipaddr_string(pptr));
2015 break;
2016
2017 case ISIS_TLV_IPADDR:
2018 while (tmp>0) {
2019 if (!TTEST2(*tptr, 4))
2020 goto trunctlv;
2021 printf("\n\t IPv4 interface address: %s", ipaddr_string(tptr));
2022 tptr += 4;
2023 tmp -= 4;
2024 }
2025 break;
2026
2027 case ISIS_TLV_HOSTNAME:
2028 printf("\n\t Hostname: ");
2029 while (tmp>0) {
2030 if (!TTEST2(*tptr, 1))
2031 goto trunctlv;
2032 printf("%c",*tptr++);
2033 tmp--;
2034 }
2035 break;
2036
2037 case ISIS_TLV_SHARED_RISK_GROUP:
2038 if (!TTEST2(*tptr, NODE_ID_LEN))
2039 goto trunctlv;
2040 printf("\n\t IS Neighbor: %s", isis_print_id(tptr, NODE_ID_LEN));
2041 tptr+=(NODE_ID_LEN);
2042 tmp-=(NODE_ID_LEN);
2043
2044 if (!TTEST2(*tptr, 1))
2045 goto trunctlv;
2046 printf(", Flags: [%s]", ISIS_MASK_TLV_SHARED_RISK_GROUP(*tptr++) ? "numbered" : "unnumbered");
2047 tmp--;
2048
2049 if (!TTEST2(*tptr,4))
2050 goto trunctlv;
2051 printf("\n\t IPv4 interface address: %s", ipaddr_string(tptr));
2052 tptr+=4;
2053 tmp-=4;
2054
2055 if (!TTEST2(*tptr,4))
2056 goto trunctlv;
2057 printf("\n\t IPv4 neighbor address: %s", ipaddr_string(tptr));
2058 tptr+=4;
2059 tmp-=4;
2060
2061 while (tmp>0) {
2062 if (!TTEST2(*tptr, 4))
2063 goto trunctlv;
2064 printf("\n\t Link-ID: 0x%08x", EXTRACT_32BITS(tptr));
2065 tptr+=4;
2066 tmp-=4;
2067 }
2068 break;
2069
2070 case ISIS_TLV_LSP:
2071 tlv_lsp = (const struct isis_tlv_lsp *)tptr;
2072 while(tmp>0) {
2073 if (!TTEST((tlv_lsp->lsp_id)[LSP_ID_LEN-1]))
2074 goto trunctlv;
2075 printf("\n\t lsp-id: %s",
2076 isis_print_id(tlv_lsp->lsp_id, LSP_ID_LEN));
2077 if (!TTEST2(tlv_lsp->sequence_number, 4))
2078 goto trunctlv;
2079 printf(", seq: 0x%08x",EXTRACT_32BITS(tlv_lsp->sequence_number));
2080 if (!TTEST2(tlv_lsp->remaining_lifetime, 2))
2081 goto trunctlv;
2082 printf(", lifetime: %5ds",EXTRACT_16BITS(tlv_lsp->remaining_lifetime));
2083 if (!TTEST2(tlv_lsp->checksum, 2))
2084 goto trunctlv;
2085 printf(", chksum: 0x%04x",EXTRACT_16BITS(tlv_lsp->checksum));
2086 tmp-=sizeof(struct isis_tlv_lsp);
2087 tlv_lsp++;
2088 }
2089 break;
2090
2091 case ISIS_TLV_CHECKSUM:
2092 if (!TTEST2(*tptr, 2))
2093 goto trunctlv;
2094 printf("\n\t checksum: 0x%04x ", EXTRACT_16BITS(tptr));
2095 /* do not attempt to verify the checksum if it is zero
2096 * most likely a HMAC-MD5 TLV is also present and
2097 * to avoid conflicts the checksum TLV is zeroed.
2098 * see rfc3358 for details
2099 */
2100 if (EXTRACT_16BITS(tptr) == 0)
2101 printf("(unverified)");
2102 else printf("(%s)", osi_cksum(optr, length) ? "incorrect" : "correct");
2103 break;
2104
2105 case ISIS_TLV_MT_SUPPORTED:
2106 while (tmp>1) {
2107 /* length can only be a multiple of 2, otherwise there is
2108 something broken -> so decode down until length is 1 */
2109 if (tmp!=1) {
2110 mt_len = isis_print_mtid(tptr, "\n\t ");
2111 if (mt_len == 0) /* did something go wrong ? */
2112 goto trunctlv;
2113 tptr+=mt_len;
2114 tmp-=mt_len;
2115 } else {
2116 printf("\n\t malformed MT-ID");
2117 break;
2118 }
2119 }
2120 break;
2121
2122 case ISIS_TLV_RESTART_SIGNALING:
2123 if (!TTEST2(*tptr, 3))
2124 goto trunctlv;
2125 printf("\n\t Flags [%s], Remaining holding time %us",
2126 bittok2str(isis_restart_flag_values, "none", *tptr),
2127 EXTRACT_16BITS(tptr+1));
2128 tptr+=3;
2129 break;
2130
2131 case ISIS_TLV_IDRP_INFO:
2132 if (!TTEST2(*tptr, 1))
2133 goto trunctlv;
2134 printf("\n\t Inter-Domain Information Type: %s",
2135 tok2str(isis_subtlv_idrp_values,
2136 "Unknown (0x%02x)",
2137 *tptr));
2138 switch (*tptr++) {
2139 case ISIS_SUBTLV_IDRP_ASN:
2140 if (!TTEST2(*tptr, 2)) /* fetch AS number */
2141 goto trunctlv;
2142 printf("AS Number: %u",EXTRACT_16BITS(tptr));
2143 break;
2144 case ISIS_SUBTLV_IDRP_LOCAL:
2145 case ISIS_SUBTLV_IDRP_RES:
2146 default:
2147 if(!print_unknown_data(tptr,"\n\t ",tlv_len-1))
2148 return(0);
2149 break;
2150 }
2151 break;
2152
2153 case ISIS_TLV_LSP_BUFFERSIZE:
2154 if (!TTEST2(*tptr, 2))
2155 goto trunctlv;
2156 printf("\n\t LSP Buffersize: %u",EXTRACT_16BITS(tptr));
2157 break;
2158
2159 case ISIS_TLV_PART_DIS:
2160 while (tmp >= SYSTEM_ID_LEN) {
2161 if (!TTEST2(*tptr, SYSTEM_ID_LEN))
2162 goto trunctlv;
2163 printf("\n\t %s",isis_print_id(tptr,SYSTEM_ID_LEN));
2164 tptr+=SYSTEM_ID_LEN;
2165 tmp-=SYSTEM_ID_LEN;
2166 }
2167 break;
2168
2169 case ISIS_TLV_PREFIX_NEIGH:
2170 if (!TTEST2(*tptr, sizeof(struct isis_metric_block)))
2171 goto trunctlv;
2172 printf("\n\t Metric Block");
2173 isis_print_metric_block((const struct isis_metric_block *)tptr);
2174 tptr+=sizeof(struct isis_metric_block);
2175 tmp-=sizeof(struct isis_metric_block);
2176
2177 while(tmp>0) {
2178 if (!TTEST2(*tptr, 1))
2179 goto trunctlv;
2180 prefix_len=*tptr++; /* read out prefix length in semioctets*/
2181 tmp--;
2182 if (!TTEST2(*tptr, prefix_len/2))
2183 goto trunctlv;
2184 printf("\n\t\tAddress: %s/%u",
2185 print_nsap(tptr,prefix_len/2),
2186 prefix_len*4);
2187 tptr+=prefix_len/2;
2188 tmp-=prefix_len/2;
2189 }
2190 break;
2191
2192 case ISIS_TLV_IIH_SEQNR:
2193 if (!TTEST2(*tptr, 4)) /* check if four bytes are on the wire */
2194 goto trunctlv;
2195 printf("\n\t Sequence number: %u", EXTRACT_32BITS(tptr) );
2196 break;
2197
2198 case ISIS_TLV_VENDOR_PRIVATE:
2199 if (!TTEST2(*tptr, 3)) /* check if enough byte for a full oui */
2200 goto trunctlv;
2201 vendor_id = EXTRACT_24BITS(tptr);
2202 printf("\n\t Vendor: %s (%u)",
2203 tok2str(oui_values,"Unknown",vendor_id),
2204 vendor_id);
2205 tptr+=3;
2206 tmp-=3;
2207 if (tmp > 0) /* hexdump the rest */
2208 if(!print_unknown_data(tptr,"\n\t\t",tmp))
2209 return(0);
2210 break;
2211 /*
2212 * FIXME those are the defined TLVs that lack a decoder
2213 * you are welcome to contribute code ;-)
2214 */
2215
2216 case ISIS_TLV_DECNET_PHASE4:
2217 case ISIS_TLV_LUCENT_PRIVATE:
2218 case ISIS_TLV_IPAUTH:
2219 case ISIS_TLV_NORTEL_PRIVATE1:
2220 case ISIS_TLV_NORTEL_PRIVATE2:
2221
2222 default:
2223 if (vflag <= 1) {
2224 if(!print_unknown_data(pptr,"\n\t\t",tlv_len))
2225 return(0);
2226 }
2227 break;
2228 }
2229 /* do we want to see an additionally hexdump ? */
2230 if (vflag> 1) {
2231 if(!print_unknown_data(pptr,"\n\t ",tlv_len))
2232 return(0);
2233 }
2234
2235 pptr += tlv_len;
2236 packet_len -= tlv_len;
2237 }
2238
2239 if (packet_len != 0) {
2240 printf("\n\t %u straggler bytes", packet_len);
2241 }
2242 return (1);
2243
2244 trunc:
2245 fputs("[|isis]", stdout);
2246 return (1);
2247
2248 trunctlv:
2249 printf("\n\t\t packet exceeded snapshot");
2250 return(1);
2251 }
2252
2253 /*
2254 * Verify the checksum. See 8473-1, Appendix C, section C.4.
2255 */
2256
2257 static int
2258 osi_cksum(const u_int8_t *tptr, u_int len)
2259 {
2260 int32_t c0 = 0, c1 = 0;
2261
2262 while ((int)--len >= 0) {
2263 c0 += *tptr++;
2264 c0 %= 255;
2265 c1 += c0;
2266 c1 %= 255;
2267 }
2268 return (c0 | c1);
2269 }