2 * Copyright (c) 1992, 1993, 1994, 1995, 1996
3 * The Regents of the University of California. All rights reserved.
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
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.
21 * Original code by Matt Thomas, Digital Equipment Corporation
25 static const char rcsid
[] =
26 "@(#) $Header: /tcpdump/master/tcpdump/print-isoclns.c,v 1.21 2000-10-10 05:40:22 guy Exp $ (LBL)";
33 #include <sys/types.h>
35 #include <sys/socket.h>
37 #include <netinet/in.h>
41 #include "interface.h"
42 #include "addrtoname.h"
43 #include "ethertype.h"
47 #define NLPID_CLNS 129 /* 0x81 */
48 #define NLPID_ESIS 130 /* 0x82 */
49 #define NLPID_ISIS 131 /* 0x83 */
50 #define NLPID_NULLNS 0
54 * IS-IS is defined in ISO 10589. Look there for protocol definitions.
57 #define SYSTEM_ID_LEN ETHER_ADDR_LEN
58 #define ISIS_VERSION 1
59 #define PDU_TYPE_MASK 0x1F
60 #define PRIORITY_MASK 0x7F
67 #define L1_COMPLETE_SEQ_PDU 24
68 #define L2_COMPLETE_SEQ_PDU 25
71 * A TLV is a tuple of a type, length and a value and is normally used for
72 * encoding information in all sorts of places. This is an enumeration of
73 * the well known types.
76 #define TLV_AREA_ADDR 1
77 #define TLV_IS_REACH 2
78 #define TLV_ES_REACH 3
83 #define TLV_AUTHENT 10
84 #define TLV_IP_REACH 128
85 #define TLV_PROTOCOLS 129
86 #define TLV_IP_EXTERN 130
87 #define TLV_IDRP_INFO 131
88 #define TLV_IPADDR 132
89 #define TLV_IPAUTH 133
90 #define TLV_PTP_ADJ 240
93 * Katz's point to point adjacency TLV uses codes to tell us the state of
94 * the remote adjacency. Enumerate them.
97 #define ISIS_PTP_ADJ_UP 0
98 #define ISIS_PTP_ADJ_INIT 1
99 #define ISIS_PTP_ADJ_DOWN 2
101 static int osi_cksum(const u_char
*, int, u_char
*);
102 static void esis_print(const u_char
*, u_int
);
103 static int isis_print(const u_char
*, u_int
);
106 struct isis_ptp_adjancey_values
{
111 static struct isis_ptp_adjancey_values isis_ptp_adjancey_values
[] = {
112 { ISIS_PTP_ADJ_UP
, "UP" },
113 { ISIS_PTP_ADJ_INIT
, "INIT" },
114 { ISIS_PTP_ADJ_DOWN
, "DOWN" }
117 struct isis_common_header
{
120 u_char version
; /* Protocol version? */
122 u_char enc_pdu_type
; /* 3 MSbs are reserved */
123 u_char pkt_version
; /* Packet format version? */
131 u_char version
; /* Protocol version? */
133 u_char enc_pdu_type
; /* 3 MSbs are reserved */
134 u_char pkt_version
; /* Packet format version? */
138 u_char enc_source_id
[SYSTEM_ID_LEN
];
139 u_char enc_holding_time
[2];
140 u_char enc_packet_len
[2];
142 u_char enc_lan_id
[SYSTEM_ID_LEN
+1];
144 struct isis_lan_header
{
146 u_char enc_source_id
[SYSTEM_ID_LEN
];
147 u_char enc_holding_time
[2];
148 u_char enc_packet_len
[2];
150 u_char enc_lan_id
[SYSTEM_ID_LEN
+1];
153 struct isis_ptp_header
{
155 u_char enc_source_id
[SYSTEM_ID_LEN
];
156 u_char enc_holding_time
[2];
157 u_char enc_packet_len
[2];
158 u_char loc_circuit_id
;
161 #define ISIS_COMMON_HEADER_SIZE (sizeof(struct isis_common_header))
162 #define ISIS_HEADER_SIZE (15+(SYSTEM_ID_LEN<<1))
163 #define ISIS_PTP_HEADER_SIZE (14+SYSTEM_ID_LEN)
164 #define L1_LS_PDU_HEADER_SIZE (21+SYSTEM_ID_LEN)
165 #define L2_LS_PDU_HEADER_SIZE L1_LS_PDU_HEADER_SIZE
166 #define L1_COMPLETE_SEQ_PDU_HEADER_SIZE 33
167 #define L2_COMPLETE_SEQ_PDU_HEADER_SIZE L1_COMPLETE_SEQ_PDU_HEADER_SIZE
172 isoclns_print(const u_char
*p
, u_int length
, u_int caplen
,
173 const u_char
*esrc
, const u_char
*edst
)
176 struct isis_header
*header
;
178 header
= (struct isis_header
*)p
;
179 pdu_type
= header
->enc_pdu_type
& PDU_TYPE_MASK
;
182 printf("[|iso-clns] ");
185 etheraddr_string(esrc
),
186 etheraddr_string(edst
));
195 (void)printf(" %s > %s",
196 etheraddr_string(esrc
),
197 etheraddr_string(edst
));
203 (void)printf(" %s > %s",
204 etheraddr_string(esrc
),
205 etheraddr_string(edst
));
206 esis_print(p
, length
);
212 if(pdu_type
!= PTP_IIH
)
213 (void)printf(" %s > %s",
214 etheraddr_string(esrc
),
215 etheraddr_string(edst
));
217 (void)printf(" len=%d ", length
);
218 if (!isis_print(p
, length
))
219 default_print_unaligned(p
, caplen
);
223 printf("iso nullns");
225 (void)printf(" %s > %s",
226 etheraddr_string(esrc
),
227 etheraddr_string(edst
));
231 printf("iso clns %02x", p
[0]);
233 (void)printf(" %s > %s",
234 etheraddr_string(esrc
),
235 etheraddr_string(edst
));
236 (void)printf(" len=%d ", length
);
238 default_print_unaligned(p
, caplen
);
243 #define ESIS_REDIRECT 6
256 esis_print(const u_char
*p
, u_int length
)
260 const struct esis_hdr
*eh
= (const struct esis_hdr
*) &p
[2];
267 printf(" no header at all!");
275 printf(" LI(%d) > PDU size (%d)!", li
, length
);
278 if (li
< sizeof(struct esis_hdr
) + 2) {
282 printf(" too short for esis header %d:", li
);
283 while (--length
!= 0)
284 printf("%02X", *p
++);
288 switch (eh
->type
& 0x1f) {
303 printf(" type %d", eh
->type
& 0x1f);
306 off
[0] = eh
->cksum
[0];
307 off
[1] = eh
->cksum
[1];
308 if (vflag
&& osi_cksum(p
, li
, off
)) {
309 printf(" bad cksum (got %02x%02x)",
310 eh
->cksum
[1], eh
->cksum
[0]);
311 default_print(p
, length
);
314 if (eh
->version
!= 1) {
315 printf(" unsupported version %d", eh
->version
);
318 p
+= sizeof(*eh
) + 2;
319 li
-= sizeof(*eh
) + 2; /* protoid * li */
321 switch (eh
->type
& 0x1f) {
322 case ESIS_REDIRECT
: {
323 const u_char
*dst
, *snpa
, *is
;
325 dst
= p
; p
+= *p
+ 1;
328 printf("\n\t\t\t %s", isonsap_string(dst
));
329 snpa
= p
; p
+= *p
+ 1;
338 printf(" > %s", etheraddr_string(&snpa
[1]));
340 printf(" > %s", isonsap_string(is
));
360 printf("\n\t\t\t %s", isonsap_string(is
));
366 (void)printf(" len=%d", length
);
367 if (length
&& p
< snapend
) {
368 length
= snapend
- p
;
369 default_print(p
, length
);
374 while (p
< ep
&& li
) {
381 printf(" bad opts/li");
388 printf(" opt (%d) too long", op
);
396 if (op
== 198 && opli
== 2) {
397 printf(" tmo=%d", q
[0] * 256 + q
[1]);
400 printf (" %d:<", op
);
402 printf("%02x", *q
++);
413 print_nsap (register const u_char
*cp
, register int length
)
417 for (i
= 0; i
< length
; i
++) {
418 printf("%02x", *cp
++);
419 if (((i
& 1) == 0) && (i
+ 1 < length
)) {
428 * Decode IS-IS packets. Return 0 on error.
430 * So far, this is only smart enough to print IIH's. Someday...
434 isis_print (const u_char
*p
, u_int length
)
436 struct isis_header
*header
;
437 struct isis_ptp_header
*header_ptp
;
438 u_char pdu_type
, max_area
, priority
, *pptr
, type
, len
, *tptr
, tmp
, alen
;
439 u_short packet_len
, holding_time
;
442 header_ptp
= (struct isis_ptp_header
*)header
= (struct isis_header
*)p
;
446 * Sanity checking of the header.
448 if (header
->nlpid
!= NLPID_ISIS
) {
449 printf(" coding error!");
453 if (header
->version
!= ISIS_VERSION
) {
454 printf(" version %d packet not supported", header
->version
);
458 if ((header
->id_length
!= SYSTEM_ID_LEN
) && (header
->id_length
!= 0)) {
459 printf(" system ID length of %d is not supported",
464 if ((header
->fixed_len
!= ISIS_HEADER_SIZE
) &&
465 (header
->fixed_len
!= ISIS_PTP_HEADER_SIZE
) &&
466 (header
->fixed_len
!= L1_LS_PDU_HEADER_SIZE
) &&
467 (header
-> fixed_len
!= L1_COMPLETE_SEQ_PDU_HEADER_SIZE
) ) {
468 printf(" bogus fixed header length %u",
473 pdu_type
= header
->enc_pdu_type
& PDU_TYPE_MASK
;
474 if ((pdu_type
!= L1_LAN_IIH
) && (pdu_type
!= L2_LAN_IIH
) &&
475 (pdu_type
!= PTP_IIH
) &&
476 (pdu_type
!= L1_COMPLETE_SEQ_PDU
) &&
477 (pdu_type
!= L2_COMPLETE_SEQ_PDU
) ) {
478 printf(" PDU type (%d) not supported", pdu_type
);
482 if (header
->pkt_version
!= ISIS_VERSION
) {
483 printf(" version %d packet not supported", header
->pkt_version
);
487 max_area
= header
->enc_max_area
;
490 max_area
= 3; /* silly shit */
493 printf(" bad packet -- 255 areas");
499 switch (header
->circuit
) {
501 printf(" PDU with circuit type 0");
504 if (pdu_type
== L2_LAN_IIH
) {
505 printf(" L2 IIH on an L1 only circuit");
510 if (pdu_type
== L1_LAN_IIH
) {
511 printf(" L1 IIH on an L2 only circuit");
518 printf(" unknown circuit type");
522 holding_time
= EXTRACT_16BITS(header
->enc_holding_time
);
524 packet_len
= EXTRACT_16BITS(header
->enc_packet_len
);
525 if ((packet_len
< ISIS_HEADER_SIZE
) ||
526 (packet_len
> length
)) {
527 printf(" bogus packet length %d, real length %d", packet_len
,
532 if(pdu_type
!= PTP_IIH
)
533 priority
= header
->enc_priority
& PRIORITY_MASK
;
536 * Now print the fixed header.
540 printf(" L1 lan iih, ");
543 printf(" L2 lan iih, ");
546 printf(" PTP iih, ");
551 switch (header
->circuit
) {
563 printf ("holding time %d ", holding_time
);
564 printf ("\n\t\t\t source %s, length %d",
565 etheraddr_string(header
->enc_source_id
), packet_len
);
566 if((pdu_type
==L1_LAN_IIH
)||(pdu_type
==L2_LAN_IIH
))
567 printf ("\n\t\t\t lan id %s(%d)", etheraddr_string(header
->enc_lan_id
),
568 header
->enc_lan_id
[SYSTEM_ID_LEN
]);
571 * Now print the TLV's.
573 if(pdu_type
==PTP_IIH
) {
574 packet_len
-= ISIS_PTP_HEADER_SIZE
;
575 pptr
= (char *)p
+ ISIS_PTP_HEADER_SIZE
;
577 packet_len
-= ISIS_HEADER_SIZE
;
578 pptr
= (char *)p
+ ISIS_HEADER_SIZE
;
580 while (packet_len
>= 2) {
581 if (pptr
>= snapend
) {
582 printf("\n\t\t\t packet exceeded snapshot");
588 if (len
> packet_len
) {
594 printf("\n\t\t\t area addresses");
598 while (tmp
&& alen
< tmp
) {
600 print_nsap(tptr
, alen
);
601 printf(" (%d)", alen
);
608 printf("\n\t\t\t neighbor addresses");
611 while (tmp
>= ETHER_ADDR_LEN
) {
612 printf("\n\t\t\t %s", etheraddr_string(tptr
));
613 tmp
-= ETHER_ADDR_LEN
;
614 tptr
+= ETHER_ADDR_LEN
;
618 printf("\n\t\t\t padding for %d bytes", len
);
621 printf("\n\t\t\t authentication data");
622 default_print(pptr
, len
);
625 printf("\n\t\t\t PTP adjacency status %s",
626 isis_ptp_adjancey_values
[*pptr
].name
);
629 printf("\n\t\t\t Supports protocols %s", (len
>1)? "are":"is");
631 printf(" %02X", (u_char
)*(pptr
+i
));
634 printf("\n\t\t\t IP address: %s", ipaddr_string(pptr
));
637 printf("\n\t\t\t unknown TLV, type %d, length %d", type
, len
);
645 if (packet_len
!= 0) {
646 printf("\n\t\t\t %d straggler bytes", packet_len
);
652 * Verify the checksum. See 8473-1, Appendix C, section C.4.
656 osi_cksum(register const u_char
*p
, register int len
, u_char
*off
)
658 int32_t c0
= 0, c1
= 0;
660 if ((off
[0] == 0) && (off
[1] == 0))
664 while ((int)--len
>= 0) {