144165Sjulian/*
244165Sjulian * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
344165Sjulian *	The Regents of the University of California.  All rights reserved.
444165Sjulian *
544165Sjulian * Redistribution and use in source and binary forms, with or without
644165Sjulian * modification, are permitted provided that: (1) source code distributions
744165Sjulian * retain the above copyright notice and this paragraph in its entirety, (2)
844165Sjulian * distributions including binary code include the above copyright notice and
944165Sjulian * this paragraph in its entirety in the documentation or other materials
1044165Sjulian * provided with the distribution, and (3) all advertising materials mentioning
1144165Sjulian * features or use of this software display the following acknowledgement:
1244165Sjulian * ``This product includes software developed by the University of California,
1344165Sjulian * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
1444165Sjulian * the University nor the names of its contributors may be used to endorse
1544165Sjulian * or promote products derived from this software without specific prior
1644165Sjulian * written permission.
1744165Sjulian * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
1844165Sjulian * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1944165Sjulian * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2044165Sjulian *
2144165Sjulian * Hacked version of print-ether.c  Larry Lile <lile@stdio.com>
2256896Sfenner *
2398527Sfenner * Further tweaked to more closely resemble print-fddi.c
2498527Sfenner *	Guy Harris <guy@alum.mit.edu>
2598527Sfenner *
2656896Sfenner * $FreeBSD: releng/11.0/contrib/tcpdump/print-token.c 276788 2015-01-07 19:55:18Z delphij $
2744165Sjulian */
2844165Sjulian
29276788Sdelphij#define NETDISSECT_REWORKED
3098527Sfenner#ifdef HAVE_CONFIG_H
3198527Sfenner#include "config.h"
3298527Sfenner#endif
3398527Sfenner
34127675Sbms#include <tcpdump-stdinc.h>
3544165Sjulian
3698527Sfenner#include <string.h>
3744165Sjulian
3844165Sjulian#include "interface.h"
39214478Srpaulo#include "extract.h"
4044165Sjulian#include "addrtoname.h"
4198527Sfenner#include "ether.h"
4244165Sjulian
43276788Sdelphij/*
44276788Sdelphij * Copyright (c) 1998, Larry Lile
45276788Sdelphij * All rights reserved.
46276788Sdelphij *
47276788Sdelphij * Redistribution and use in source and binary forms, with or without
48276788Sdelphij * modification, are permitted provided that the following conditions
49276788Sdelphij * are met:
50276788Sdelphij * 1. Redistributions of source code must retain the above copyright
51276788Sdelphij *    notice unmodified, this list of conditions, and the following
52276788Sdelphij *    disclaimer.
53276788Sdelphij * 2. Redistributions in binary form must reproduce the above copyright
54276788Sdelphij *    notice, this list of conditions and the following disclaimer in the
55276788Sdelphij *    documentation and/or other materials provided with the distribution.
56276788Sdelphij *
57276788Sdelphij * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
58276788Sdelphij * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
59276788Sdelphij * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
60276788Sdelphij * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
61276788Sdelphij * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
62276788Sdelphij * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
63276788Sdelphij * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
64276788Sdelphij * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
65276788Sdelphij * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
66276788Sdelphij * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
67276788Sdelphij * SUCH DAMAGE.
68276788Sdelphij *
69276788Sdelphij */
70276788Sdelphij
71276788Sdelphij#define TOKEN_HDRLEN		14
72276788Sdelphij#define TOKEN_RING_MAC_LEN	6
73276788Sdelphij#define ROUTING_SEGMENT_MAX	16
74276788Sdelphij#define IS_SOURCE_ROUTED(trp)	((trp)->token_shost[0] & 0x80)
75276788Sdelphij#define FRAME_TYPE(trp)		(((trp)->token_fc & 0xC0) >> 6)
76276788Sdelphij#define TOKEN_FC_LLC		1
77276788Sdelphij
78276788Sdelphij#define BROADCAST(trp)		((EXTRACT_16BITS(&(trp)->token_rcf) & 0xE000) >> 13)
79276788Sdelphij#define RIF_LENGTH(trp)		((EXTRACT_16BITS(&(trp)->token_rcf) & 0x1f00) >> 8)
80276788Sdelphij#define DIRECTION(trp)		((EXTRACT_16BITS(&(trp)->token_rcf) & 0x0080) >> 7)
81276788Sdelphij#define LARGEST_FRAME(trp)	((EXTRACT_16BITS(&(trp)->token_rcf) & 0x0070) >> 4)
82276788Sdelphij#define RING_NUMBER(trp, x)	((EXTRACT_16BITS(&(trp)->token_rseg[x]) & 0xfff0) >> 4)
83276788Sdelphij#define BRIDGE_NUMBER(trp, x)	((EXTRACT_16BITS(&(trp)->token_rseg[x]) & 0x000f))
84276788Sdelphij#define SEGMENT_COUNT(trp)	((int)((RIF_LENGTH(trp) - 2) / 2))
85276788Sdelphij
86276788Sdelphijstruct token_header {
87276788Sdelphij	uint8_t  token_ac;
88276788Sdelphij	uint8_t  token_fc;
89276788Sdelphij	uint8_t  token_dhost[TOKEN_RING_MAC_LEN];
90276788Sdelphij	uint8_t  token_shost[TOKEN_RING_MAC_LEN];
91276788Sdelphij	uint16_t token_rcf;
92276788Sdelphij	uint16_t token_rseg[ROUTING_SEGMENT_MAX];
93276788Sdelphij};
94276788Sdelphij
95276788Sdelphijstatic const char tstr[] = "[|token-ring]";
96276788Sdelphij
9798527Sfenner/* Extract src, dst addresses */
9844165Sjulianstatic inline void
9998527Sfennerextract_token_addrs(const struct token_header *trp, char *fsrc, char *fdst)
10044165Sjulian{
10198527Sfenner	memcpy(fdst, (const char *)trp->token_dhost, 6);
10298527Sfenner	memcpy(fsrc, (const char *)trp->token_shost, 6);
10398527Sfenner}
10444165Sjulian
10598527Sfenner/*
10698527Sfenner * Print the TR MAC header
10798527Sfenner */
10898527Sfennerstatic inline void
109276788Sdelphijtoken_hdr_print(netdissect_options *ndo,
110276788Sdelphij                register const struct token_header *trp, register u_int length,
111276788Sdelphij                register const u_char *fsrc, register const u_char *fdst)
11298527Sfenner{
11398527Sfenner	const char *srcname, *dstname;
11450514Slile
115276788Sdelphij	srcname = etheraddr_string(ndo, fsrc);
116276788Sdelphij	dstname = etheraddr_string(ndo, fdst);
11744165Sjulian
118276788Sdelphij	if (ndo->ndo_vflag)
119276788Sdelphij		ND_PRINT((ndo, "%02x %02x %s %s %d: ",
12098527Sfenner		       trp->token_ac,
12198527Sfenner		       trp->token_fc,
12298527Sfenner		       srcname, dstname,
123276788Sdelphij		       length));
12444165Sjulian	else
125276788Sdelphij		ND_PRINT((ndo, "%s %s %d: ", srcname, dstname, length));
12644165Sjulian}
12744165Sjulian
12898527Sfennerstatic const char *broadcast_indicator[] = {
12998527Sfenner	"Non-Broadcast", "Non-Broadcast",
13098527Sfenner	"Non-Broadcast", "Non-Broadcast",
13198527Sfenner	"All-routes",    "All-routes",
13298527Sfenner	"Single-route",  "Single-route"
13398527Sfenner};
13498527Sfenner
13598527Sfennerstatic const char *direction[] = {
13698527Sfenner	"Forward", "Backward"
13798527Sfenner};
13898527Sfenner
13998527Sfennerstatic const char *largest_frame[] = {
14098527Sfenner	"516",
14198527Sfenner	"1500",
14298527Sfenner	"2052",
14398527Sfenner	"4472",
14498527Sfenner	"8144",
14598527Sfenner	"11407",
14698527Sfenner	"17800",
14798527Sfenner	"??"
14898527Sfenner};
14998527Sfenner
150127675Sbmsu_int
151276788Sdelphijtoken_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen)
15244165Sjulian{
15398527Sfenner	const struct token_header *trp;
15456896Sfenner	u_short extracted_ethertype;
15598527Sfenner	struct ether_header ehdr;
156127675Sbms	u_int route_len = 0, hdr_len = TOKEN_HDRLEN;
157127675Sbms	int seg;
15844165Sjulian
15998527Sfenner	trp = (const struct token_header *)p;
16044165Sjulian
16198527Sfenner	if (caplen < TOKEN_HDRLEN) {
162276788Sdelphij		ND_PRINT((ndo, "%s", tstr));
163127675Sbms		return hdr_len;
16444165Sjulian	}
165127675Sbms
16644165Sjulian	/*
16798527Sfenner	 * Get the TR addresses into a canonical form
16898527Sfenner	 */
16998527Sfenner	extract_token_addrs(trp, (char*)ESRC(&ehdr), (char*)EDST(&ehdr));
17044165Sjulian
17198527Sfenner	/* Adjust for source routing information in the MAC header */
17298527Sfenner	if (IS_SOURCE_ROUTED(trp)) {
17398527Sfenner		/* Clear source-routed bit */
17498527Sfenner		*ESRC(&ehdr) &= 0x7f;
17550514Slile
176276788Sdelphij		if (ndo->ndo_eflag)
177276788Sdelphij			token_hdr_print(ndo, trp, length, ESRC(&ehdr), EDST(&ehdr));
17850514Slile
179214478Srpaulo		if (caplen < TOKEN_HDRLEN + 2) {
180276788Sdelphij			ND_PRINT((ndo, "%s", tstr));
181214478Srpaulo			return hdr_len;
182214478Srpaulo		}
18398527Sfenner		route_len = RIF_LENGTH(trp);
184214478Srpaulo		hdr_len += route_len;
185214478Srpaulo		if (caplen < hdr_len) {
186276788Sdelphij			ND_PRINT((ndo, "%s", tstr));
187214478Srpaulo			return hdr_len;
188214478Srpaulo		}
189276788Sdelphij		if (ndo->ndo_vflag) {
190276788Sdelphij			ND_PRINT((ndo, "%s ", broadcast_indicator[BROADCAST(trp)]));
191276788Sdelphij			ND_PRINT((ndo, "%s", direction[DIRECTION(trp)]));
192127675Sbms
19398527Sfenner			for (seg = 0; seg < SEGMENT_COUNT(trp); seg++)
194276788Sdelphij				ND_PRINT((ndo, " [%d:%d]", RING_NUMBER(trp, seg),
195276788Sdelphij				    BRIDGE_NUMBER(trp, seg)));
19698527Sfenner		} else {
197276788Sdelphij			ND_PRINT((ndo, "rt = %x", EXTRACT_16BITS(&trp->token_rcf)));
198127675Sbms
19998527Sfenner			for (seg = 0; seg < SEGMENT_COUNT(trp); seg++)
200276788Sdelphij				ND_PRINT((ndo, ":%x", EXTRACT_16BITS(&trp->token_rseg[seg])));
20198527Sfenner		}
202276788Sdelphij		ND_PRINT((ndo, " (%s) ", largest_frame[LARGEST_FRAME(trp)]));
20398527Sfenner	} else {
204276788Sdelphij		if (ndo->ndo_eflag)
205276788Sdelphij			token_hdr_print(ndo, trp, length, ESRC(&ehdr), EDST(&ehdr));
20698527Sfenner	}
20744165Sjulian
20898527Sfenner	/* Skip over token ring MAC header and routing information */
209127675Sbms	length -= hdr_len;
210127675Sbms	p += hdr_len;
211127675Sbms	caplen -= hdr_len;
21244165Sjulian
21398527Sfenner	/* Frame Control field determines interpretation of packet */
21498527Sfenner	if (FRAME_TYPE(trp) == TOKEN_FC_LLC) {
21598527Sfenner		/* Try to print the LLC-layer header & higher layers */
216276788Sdelphij		if (llc_print(ndo, p, length, caplen, ESRC(&ehdr), EDST(&ehdr),
21798527Sfenner		    &extracted_ethertype) == 0) {
21898527Sfenner			/* ether_type not known, print raw packet */
219276788Sdelphij			if (!ndo->ndo_eflag)
220276788Sdelphij				token_hdr_print(ndo, trp,
22198527Sfenner				    length + TOKEN_HDRLEN + route_len,
22298527Sfenner				    ESRC(&ehdr), EDST(&ehdr));
22398527Sfenner			if (extracted_ethertype) {
224276788Sdelphij				ND_PRINT((ndo, "(LLC %s) ",
225276788Sdelphij			etherproto_string(htons(extracted_ethertype))));
22698527Sfenner			}
227276788Sdelphij			if (!ndo->ndo_suppress_default_print)
228276788Sdelphij				ND_DEFAULTPRINT(p, caplen);
22998527Sfenner		}
23098527Sfenner	} else {
23198527Sfenner		/* Some kinds of TR packet we cannot handle intelligently */
23298527Sfenner		/* XXX - dissect MAC packets if frame type is 0 */
233276788Sdelphij		if (!ndo->ndo_eflag)
234276788Sdelphij			token_hdr_print(ndo, trp, length + TOKEN_HDRLEN + route_len,
23598527Sfenner			    ESRC(&ehdr), EDST(&ehdr));
236276788Sdelphij		if (!ndo->ndo_suppress_default_print)
237276788Sdelphij			ND_DEFAULTPRINT(p, caplen);
23844165Sjulian	}
239127675Sbms	return (hdr_len);
24044165Sjulian}
241127675Sbms
242127675Sbms/*
243127675Sbms * This is the top level routine of the printer.  'p' points
244127675Sbms * to the TR header of the packet, 'h->ts' is the timestamp,
245146778Ssam * 'h->len' is the length of the packet off the wire, and 'h->caplen'
246127675Sbms * is the number of bytes actually captured.
247127675Sbms */
248127675Sbmsu_int
249276788Sdelphijtoken_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
250127675Sbms{
251276788Sdelphij	return (token_print(ndo, p, h->len, h->caplen));
252127675Sbms}
253