xref: /freebsd/contrib/tcpdump/print-token.c (revision ee67461e56828dd1f8de165947ba83f6d9148a87)
1722012ccSJulian Elischer /*
2722012ccSJulian Elischer  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
3722012ccSJulian Elischer  *	The Regents of the University of California.  All rights reserved.
4722012ccSJulian Elischer  *
5722012ccSJulian Elischer  * Redistribution and use in source and binary forms, with or without
6722012ccSJulian Elischer  * modification, are permitted provided that: (1) source code distributions
7722012ccSJulian Elischer  * retain the above copyright notice and this paragraph in its entirety, (2)
8722012ccSJulian Elischer  * distributions including binary code include the above copyright notice and
9722012ccSJulian Elischer  * this paragraph in its entirety in the documentation or other materials
10722012ccSJulian Elischer  * provided with the distribution, and (3) all advertising materials mentioning
11722012ccSJulian Elischer  * features or use of this software display the following acknowledgement:
12722012ccSJulian Elischer  * ``This product includes software developed by the University of California,
13722012ccSJulian Elischer  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14722012ccSJulian Elischer  * the University nor the names of its contributors may be used to endorse
15722012ccSJulian Elischer  * or promote products derived from this software without specific prior
16722012ccSJulian Elischer  * written permission.
17722012ccSJulian Elischer  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18722012ccSJulian Elischer  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19722012ccSJulian Elischer  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20722012ccSJulian Elischer  *
21722012ccSJulian Elischer  * Hacked version of print-ether.c  Larry Lile <lile@stdio.com>
22a88113a8SBill Fenner  *
23a1c2090eSBill Fenner  * Further tweaked to more closely resemble print-fddi.c
24a1c2090eSBill Fenner  *	Guy Harris <guy@alum.mit.edu>
25722012ccSJulian Elischer  */
26a1c2090eSBill Fenner 
273340d773SGleb Smirnoff /* \summary: Token Ring printer */
283340d773SGleb Smirnoff 
29a1c2090eSBill Fenner #ifdef HAVE_CONFIG_H
30*ee67461eSJoseph Mingrone #include <config.h>
31722012ccSJulian Elischer #endif
32722012ccSJulian Elischer 
33*ee67461eSJoseph Mingrone #include "netdissect-stdinc.h"
34722012ccSJulian Elischer 
35a1c2090eSBill Fenner #include <string.h>
36722012ccSJulian Elischer 
373340d773SGleb Smirnoff #include "netdissect.h"
3827df3f5dSRui Paulo #include "extract.h"
39722012ccSJulian Elischer #include "addrtoname.h"
403c602fabSXin LI 
413c602fabSXin LI /*
423c602fabSXin LI  * Copyright (c) 1998, Larry Lile
433c602fabSXin LI  * All rights reserved.
443c602fabSXin LI  *
453c602fabSXin LI  * Redistribution and use in source and binary forms, with or without
463c602fabSXin LI  * modification, are permitted provided that the following conditions
473c602fabSXin LI  * are met:
483c602fabSXin LI  * 1. Redistributions of source code must retain the above copyright
493c602fabSXin LI  *    notice unmodified, this list of conditions, and the following
503c602fabSXin LI  *    disclaimer.
513c602fabSXin LI  * 2. Redistributions in binary form must reproduce the above copyright
523c602fabSXin LI  *    notice, this list of conditions and the following disclaimer in the
533c602fabSXin LI  *    documentation and/or other materials provided with the distribution.
543c602fabSXin LI  *
553c602fabSXin LI  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
563c602fabSXin LI  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
573c602fabSXin LI  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
583c602fabSXin LI  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
593c602fabSXin LI  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
603c602fabSXin LI  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
613c602fabSXin LI  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
623c602fabSXin LI  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
633c602fabSXin LI  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
643c602fabSXin LI  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
653c602fabSXin LI  * SUCH DAMAGE.
663c602fabSXin LI  *
673c602fabSXin LI  */
683c602fabSXin LI 
693c602fabSXin LI #define TOKEN_HDRLEN		14
703c602fabSXin LI #define ROUTING_SEGMENT_MAX	16
713c602fabSXin LI #define IS_SOURCE_ROUTED(trp)	((trp)->token_shost[0] & 0x80)
72*ee67461eSJoseph Mingrone #define FRAME_TYPE(trp)		((GET_U_1((trp)->token_fc) & 0xC0) >> 6)
733c602fabSXin LI #define TOKEN_FC_LLC		1
743c602fabSXin LI 
75*ee67461eSJoseph Mingrone #define BROADCAST(trp)		((GET_BE_U_2((trp)->token_rcf) & 0xE000) >> 13)
76*ee67461eSJoseph Mingrone #define RIF_LENGTH(trp)		((GET_BE_U_2((trp)->token_rcf) & 0x1f00) >> 8)
77*ee67461eSJoseph Mingrone #define DIRECTION(trp)		((GET_BE_U_2((trp)->token_rcf) & 0x0080) >> 7)
78*ee67461eSJoseph Mingrone #define LARGEST_FRAME(trp)	((GET_BE_U_2((trp)->token_rcf) & 0x0070) >> 4)
79*ee67461eSJoseph Mingrone #define RING_NUMBER(trp, x)	((GET_BE_U_2((trp)->token_rseg[x]) & 0xfff0) >> 4)
80*ee67461eSJoseph Mingrone #define BRIDGE_NUMBER(trp, x)	(GET_BE_U_2((trp)->token_rseg[x]) & 0x000f)
813c602fabSXin LI #define SEGMENT_COUNT(trp)	((int)((RIF_LENGTH(trp) - 2) / 2))
823c602fabSXin LI 
833c602fabSXin LI struct token_header {
84*ee67461eSJoseph Mingrone 	nd_uint8_t   token_ac;
85*ee67461eSJoseph Mingrone 	nd_uint8_t   token_fc;
86*ee67461eSJoseph Mingrone 	nd_mac_addr  token_dhost;
87*ee67461eSJoseph Mingrone 	nd_mac_addr  token_shost;
88*ee67461eSJoseph Mingrone 	nd_uint16_t  token_rcf;
89*ee67461eSJoseph Mingrone 	nd_uint16_t  token_rseg[ROUTING_SEGMENT_MAX];
903c602fabSXin LI };
913c602fabSXin LI 
92722012ccSJulian Elischer 
93a1c2090eSBill Fenner /* Extract src, dst addresses */
94*ee67461eSJoseph Mingrone static void
95a1c2090eSBill Fenner extract_token_addrs(const struct token_header *trp, char *fsrc, char *fdst)
96722012ccSJulian Elischer {
97a1c2090eSBill Fenner 	memcpy(fdst, (const char *)trp->token_dhost, 6);
98a1c2090eSBill Fenner 	memcpy(fsrc, (const char *)trp->token_shost, 6);
9914fffcebSLarry Lile }
100722012ccSJulian Elischer 
101722012ccSJulian Elischer /*
102a1c2090eSBill Fenner  * Print the TR MAC header
103722012ccSJulian Elischer  */
104*ee67461eSJoseph Mingrone static void
1053c602fabSXin LI token_hdr_print(netdissect_options *ndo,
106*ee67461eSJoseph Mingrone                 const struct token_header *trp, u_int length,
107*ee67461eSJoseph Mingrone                 const u_char *fsrc, const u_char *fdst)
108a1c2090eSBill Fenner {
109a1c2090eSBill Fenner 	const char *srcname, *dstname;
110722012ccSJulian Elischer 
1113c602fabSXin LI 	srcname = etheraddr_string(ndo, fsrc);
1123c602fabSXin LI 	dstname = etheraddr_string(ndo, fdst);
113a1c2090eSBill Fenner 
1143340d773SGleb Smirnoff 	if (!ndo->ndo_qflag)
115*ee67461eSJoseph Mingrone 		ND_PRINT("%02x %02x ",
116*ee67461eSJoseph Mingrone 		       GET_U_1(trp->token_ac),
117*ee67461eSJoseph Mingrone 		       GET_U_1(trp->token_fc));
118*ee67461eSJoseph Mingrone 	ND_PRINT("%s > %s, length %u: ",
119a1c2090eSBill Fenner 	       srcname, dstname,
120*ee67461eSJoseph Mingrone 	       length);
121722012ccSJulian Elischer }
122722012ccSJulian Elischer 
123a1c2090eSBill Fenner static const char *broadcast_indicator[] = {
124a1c2090eSBill Fenner 	"Non-Broadcast", "Non-Broadcast",
125a1c2090eSBill Fenner 	"Non-Broadcast", "Non-Broadcast",
126a1c2090eSBill Fenner 	"All-routes",    "All-routes",
127a1c2090eSBill Fenner 	"Single-route",  "Single-route"
128a1c2090eSBill Fenner };
129a1c2090eSBill Fenner 
130a1c2090eSBill Fenner static const char *direction[] = {
131a1c2090eSBill Fenner 	"Forward", "Backward"
132a1c2090eSBill Fenner };
133a1c2090eSBill Fenner 
134a1c2090eSBill Fenner static const char *largest_frame[] = {
135a1c2090eSBill Fenner 	"516",
136a1c2090eSBill Fenner 	"1500",
137a1c2090eSBill Fenner 	"2052",
138a1c2090eSBill Fenner 	"4472",
139a1c2090eSBill Fenner 	"8144",
140a1c2090eSBill Fenner 	"11407",
141a1c2090eSBill Fenner 	"17800",
142a1c2090eSBill Fenner 	"??"
143a1c2090eSBill Fenner };
144a1c2090eSBill Fenner 
145cc391cceSBruce M Simpson u_int
1463c602fabSXin LI token_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen)
147722012ccSJulian Elischer {
148a1c2090eSBill Fenner 	const struct token_header *trp;
1493340d773SGleb Smirnoff 	int llc_hdrlen;
150*ee67461eSJoseph Mingrone 	nd_mac_addr srcmac, dstmac;
1513340d773SGleb Smirnoff 	struct lladdr_info src, dst;
152cc391cceSBruce M Simpson 	u_int route_len = 0, hdr_len = TOKEN_HDRLEN;
153cc391cceSBruce M Simpson 	int seg;
154722012ccSJulian Elischer 
155*ee67461eSJoseph Mingrone 	ndo->ndo_protocol = "token-ring";
156a1c2090eSBill Fenner 	trp = (const struct token_header *)p;
157722012ccSJulian Elischer 
158a1c2090eSBill Fenner 	if (caplen < TOKEN_HDRLEN) {
159*ee67461eSJoseph Mingrone 		nd_print_trunc(ndo);
160cc391cceSBruce M Simpson 		return hdr_len;
161722012ccSJulian Elischer 	}
162cc391cceSBruce M Simpson 
163a1c2090eSBill Fenner 	/*
164a1c2090eSBill Fenner 	 * Get the TR addresses into a canonical form
165a1c2090eSBill Fenner 	 */
166*ee67461eSJoseph Mingrone 	extract_token_addrs(trp, (char*)srcmac, (char*)dstmac);
167722012ccSJulian Elischer 
168722012ccSJulian Elischer 	/* Adjust for source routing information in the MAC header */
169a1c2090eSBill Fenner 	if (IS_SOURCE_ROUTED(trp)) {
170a1c2090eSBill Fenner 		/* Clear source-routed bit */
171*ee67461eSJoseph Mingrone 		srcmac[0] &= 0x7f;
17214fffcebSLarry Lile 
1733c602fabSXin LI 		if (ndo->ndo_eflag)
174*ee67461eSJoseph Mingrone 			token_hdr_print(ndo, trp, length, srcmac, dstmac);
17514fffcebSLarry Lile 
17627df3f5dSRui Paulo 		if (caplen < TOKEN_HDRLEN + 2) {
177*ee67461eSJoseph Mingrone 			nd_print_trunc(ndo);
17827df3f5dSRui Paulo 			return hdr_len;
17927df3f5dSRui Paulo 		}
180a1c2090eSBill Fenner 		route_len = RIF_LENGTH(trp);
18127df3f5dSRui Paulo 		hdr_len += route_len;
18227df3f5dSRui Paulo 		if (caplen < hdr_len) {
183*ee67461eSJoseph Mingrone 			nd_print_trunc(ndo);
18427df3f5dSRui Paulo 			return hdr_len;
18527df3f5dSRui Paulo 		}
1863c602fabSXin LI 		if (ndo->ndo_vflag) {
187*ee67461eSJoseph Mingrone 			ND_PRINT("%s ", broadcast_indicator[BROADCAST(trp)]);
188*ee67461eSJoseph Mingrone 			ND_PRINT("%s", direction[DIRECTION(trp)]);
18914fffcebSLarry Lile 
190a1c2090eSBill Fenner 			for (seg = 0; seg < SEGMENT_COUNT(trp); seg++)
191*ee67461eSJoseph Mingrone 				ND_PRINT(" [%u:%u]", RING_NUMBER(trp, seg),
192*ee67461eSJoseph Mingrone 				    BRIDGE_NUMBER(trp, seg));
19314fffcebSLarry Lile 		} else {
194*ee67461eSJoseph Mingrone 			ND_PRINT("rt = %x", GET_BE_U_2(trp->token_rcf));
19514fffcebSLarry Lile 
196a1c2090eSBill Fenner 			for (seg = 0; seg < SEGMENT_COUNT(trp); seg++)
197*ee67461eSJoseph Mingrone 				ND_PRINT(":%x",
198*ee67461eSJoseph Mingrone 					 GET_BE_U_2(trp->token_rseg[seg]));
19914fffcebSLarry Lile 		}
200*ee67461eSJoseph Mingrone 		ND_PRINT(" (%s) ", largest_frame[LARGEST_FRAME(trp)]);
20114fffcebSLarry Lile 	} else {
2023c602fabSXin LI 		if (ndo->ndo_eflag)
203*ee67461eSJoseph Mingrone 			token_hdr_print(ndo, trp, length, srcmac, dstmac);
204722012ccSJulian Elischer 	}
205722012ccSJulian Elischer 
206*ee67461eSJoseph Mingrone 	src.addr = srcmac;
2073340d773SGleb Smirnoff 	src.addr_string = etheraddr_string;
208*ee67461eSJoseph Mingrone 	dst.addr = dstmac;
2093340d773SGleb Smirnoff 	dst.addr_string = etheraddr_string;
2103340d773SGleb Smirnoff 
211a1c2090eSBill Fenner 	/* Skip over token ring MAC header and routing information */
212cc391cceSBruce M Simpson 	length -= hdr_len;
213cc391cceSBruce M Simpson 	p += hdr_len;
214cc391cceSBruce M Simpson 	caplen -= hdr_len;
215722012ccSJulian Elischer 
216a1c2090eSBill Fenner 	/* Frame Control field determines interpretation of packet */
217a1c2090eSBill Fenner 	if (FRAME_TYPE(trp) == TOKEN_FC_LLC) {
218722012ccSJulian Elischer 		/* Try to print the LLC-layer header & higher layers */
2193340d773SGleb Smirnoff 		llc_hdrlen = llc_print(ndo, p, length, caplen, &src, &dst);
2203340d773SGleb Smirnoff 		if (llc_hdrlen < 0) {
2213340d773SGleb Smirnoff 			/* packet type not known, print raw packet */
2223c602fabSXin LI 			if (!ndo->ndo_suppress_default_print)
2233c602fabSXin LI 				ND_DEFAULTPRINT(p, caplen);
2243340d773SGleb Smirnoff 			llc_hdrlen = -llc_hdrlen;
225722012ccSJulian Elischer 		}
2263340d773SGleb Smirnoff 		hdr_len += llc_hdrlen;
227a1c2090eSBill Fenner 	} else {
228a1c2090eSBill Fenner 		/* Some kinds of TR packet we cannot handle intelligently */
229a1c2090eSBill Fenner 		/* XXX - dissect MAC packets if frame type is 0 */
2303c602fabSXin LI 		if (!ndo->ndo_eflag)
2313c602fabSXin LI 			token_hdr_print(ndo, trp, length + TOKEN_HDRLEN + route_len,
232*ee67461eSJoseph Mingrone 			    srcmac, dstmac);
2333c602fabSXin LI 		if (!ndo->ndo_suppress_default_print)
2343c602fabSXin LI 			ND_DEFAULTPRINT(p, caplen);
235a1c2090eSBill Fenner 	}
236cc391cceSBruce M Simpson 	return (hdr_len);
237cc391cceSBruce M Simpson }
238cc391cceSBruce M Simpson 
239cc391cceSBruce M Simpson /*
240cc391cceSBruce M Simpson  * This is the top level routine of the printer.  'p' points
241cc391cceSBruce M Simpson  * to the TR header of the packet, 'h->ts' is the timestamp,
242c1ad1296SSam Leffler  * 'h->len' is the length of the packet off the wire, and 'h->caplen'
243cc391cceSBruce M Simpson  * is the number of bytes actually captured.
244cc391cceSBruce M Simpson  */
245*ee67461eSJoseph Mingrone void
2463c602fabSXin LI token_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
247cc391cceSBruce M Simpson {
248*ee67461eSJoseph Mingrone 	ndo->ndo_protocol = "token-ring";
249*ee67461eSJoseph Mingrone 	ndo->ndo_ll_hdr_len += token_print(ndo, p, h->len, h->caplen);
250722012ccSJulian Elischer }
251