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$
2744165Sjulian */
2844165Sjulian#ifndef lint
29127675Sbmsstatic const char rcsid[] _U_ =
30190207Srpaulo    "@(#) $Header: /tcpdump/master/tcpdump/print-token.c,v 1.27 2005-11-13 12:12:43 guy Exp $";
3144165Sjulian#endif
3244165Sjulian
3398527Sfenner#ifdef HAVE_CONFIG_H
3498527Sfenner#include "config.h"
3598527Sfenner#endif
3698527Sfenner
37127675Sbms#include <tcpdump-stdinc.h>
3844165Sjulian
3998527Sfenner#include <pcap.h>
4044165Sjulian#include <stdio.h>
4198527Sfenner#include <string.h>
4244165Sjulian
4344165Sjulian#include "interface.h"
44214478Srpaulo#include "extract.h"
4544165Sjulian#include "addrtoname.h"
4644165Sjulian#include "ethertype.h"
4744165Sjulian
4898527Sfenner#include "ether.h"
4998527Sfenner#include "token.h"
5044165Sjulian
5198527Sfenner/* Extract src, dst addresses */
5244165Sjulianstatic inline void
5398527Sfennerextract_token_addrs(const struct token_header *trp, char *fsrc, char *fdst)
5444165Sjulian{
5598527Sfenner	memcpy(fdst, (const char *)trp->token_dhost, 6);
5698527Sfenner	memcpy(fsrc, (const char *)trp->token_shost, 6);
5798527Sfenner}
5844165Sjulian
5998527Sfenner/*
6098527Sfenner * Print the TR MAC header
6198527Sfenner */
6298527Sfennerstatic inline void
63127675Sbmstoken_hdr_print(register const struct token_header *trp, register u_int length,
6498527Sfenner	   register const u_char *fsrc, register const u_char *fdst)
6598527Sfenner{
6698527Sfenner	const char *srcname, *dstname;
6750514Slile
6898527Sfenner	srcname = etheraddr_string(fsrc);
6998527Sfenner	dstname = etheraddr_string(fdst);
7044165Sjulian
7198527Sfenner	if (vflag)
7298527Sfenner		(void) printf("%02x %02x %s %s %d: ",
7398527Sfenner		       trp->token_ac,
7498527Sfenner		       trp->token_fc,
7598527Sfenner		       srcname, dstname,
7698527Sfenner		       length);
7744165Sjulian	else
7898527Sfenner		printf("%s %s %d: ", srcname, dstname, length);
7944165Sjulian}
8044165Sjulian
8198527Sfennerstatic const char *broadcast_indicator[] = {
8298527Sfenner	"Non-Broadcast", "Non-Broadcast",
8398527Sfenner	"Non-Broadcast", "Non-Broadcast",
8498527Sfenner	"All-routes",    "All-routes",
8598527Sfenner	"Single-route",  "Single-route"
8698527Sfenner};
8798527Sfenner
8898527Sfennerstatic const char *direction[] = {
8998527Sfenner	"Forward", "Backward"
9098527Sfenner};
9198527Sfenner
9298527Sfennerstatic const char *largest_frame[] = {
9398527Sfenner	"516",
9498527Sfenner	"1500",
9598527Sfenner	"2052",
9698527Sfenner	"4472",
9798527Sfenner	"8144",
9898527Sfenner	"11407",
9998527Sfenner	"17800",
10098527Sfenner	"??"
10198527Sfenner};
10298527Sfenner
103127675Sbmsu_int
104127675Sbmstoken_print(const u_char *p, u_int length, u_int caplen)
10544165Sjulian{
10698527Sfenner	const struct token_header *trp;
10756896Sfenner	u_short extracted_ethertype;
10898527Sfenner	struct ether_header ehdr;
109127675Sbms	u_int route_len = 0, hdr_len = TOKEN_HDRLEN;
110127675Sbms	int seg;
11144165Sjulian
11298527Sfenner	trp = (const struct token_header *)p;
11344165Sjulian
11498527Sfenner	if (caplen < TOKEN_HDRLEN) {
11544165Sjulian		printf("[|token-ring]");
116127675Sbms		return hdr_len;
11744165Sjulian	}
118127675Sbms
11944165Sjulian	/*
12098527Sfenner	 * Get the TR addresses into a canonical form
12198527Sfenner	 */
12298527Sfenner	extract_token_addrs(trp, (char*)ESRC(&ehdr), (char*)EDST(&ehdr));
12344165Sjulian
12498527Sfenner	/* Adjust for source routing information in the MAC header */
12598527Sfenner	if (IS_SOURCE_ROUTED(trp)) {
12698527Sfenner		/* Clear source-routed bit */
12798527Sfenner		*ESRC(&ehdr) &= 0x7f;
12850514Slile
12998527Sfenner		if (eflag)
130127675Sbms			token_hdr_print(trp, length, ESRC(&ehdr), EDST(&ehdr));
13150514Slile
132214478Srpaulo		if (caplen < TOKEN_HDRLEN + 2) {
133214478Srpaulo			printf("[|token-ring]");
134214478Srpaulo			return hdr_len;
135214478Srpaulo		}
13698527Sfenner		route_len = RIF_LENGTH(trp);
137214478Srpaulo		hdr_len += route_len;
138214478Srpaulo		if (caplen < hdr_len) {
139214478Srpaulo			printf("[|token-ring]");
140214478Srpaulo			return hdr_len;
141214478Srpaulo		}
14298527Sfenner		if (vflag) {
14398527Sfenner			printf("%s ", broadcast_indicator[BROADCAST(trp)]);
14498527Sfenner			printf("%s", direction[DIRECTION(trp)]);
145127675Sbms
14698527Sfenner			for (seg = 0; seg < SEGMENT_COUNT(trp); seg++)
14798527Sfenner				printf(" [%d:%d]", RING_NUMBER(trp, seg),
14898527Sfenner				    BRIDGE_NUMBER(trp, seg));
14998527Sfenner		} else {
150214478Srpaulo			printf("rt = %x", EXTRACT_16BITS(&trp->token_rcf));
151127675Sbms
15298527Sfenner			for (seg = 0; seg < SEGMENT_COUNT(trp); seg++)
153214478Srpaulo				printf(":%x", EXTRACT_16BITS(&trp->token_rseg[seg]));
15498527Sfenner		}
15598527Sfenner		printf(" (%s) ", largest_frame[LARGEST_FRAME(trp)]);
15698527Sfenner	} else {
15798527Sfenner		if (eflag)
158127675Sbms			token_hdr_print(trp, length, ESRC(&ehdr), EDST(&ehdr));
15998527Sfenner	}
16044165Sjulian
16198527Sfenner	/* Skip over token ring MAC header and routing information */
162127675Sbms	length -= hdr_len;
163127675Sbms	p += hdr_len;
164127675Sbms	caplen -= hdr_len;
16544165Sjulian
16698527Sfenner	/* Frame Control field determines interpretation of packet */
16798527Sfenner	if (FRAME_TYPE(trp) == TOKEN_FC_LLC) {
16898527Sfenner		/* Try to print the LLC-layer header & higher layers */
16998527Sfenner		if (llc_print(p, length, caplen, ESRC(&ehdr), EDST(&ehdr),
17098527Sfenner		    &extracted_ethertype) == 0) {
17198527Sfenner			/* ether_type not known, print raw packet */
17298527Sfenner			if (!eflag)
173127675Sbms				token_hdr_print(trp,
17498527Sfenner				    length + TOKEN_HDRLEN + route_len,
17598527Sfenner				    ESRC(&ehdr), EDST(&ehdr));
17698527Sfenner			if (extracted_ethertype) {
17798527Sfenner				printf("(LLC %s) ",
17898527Sfenner			etherproto_string(htons(extracted_ethertype)));
17998527Sfenner			}
180162021Ssam			if (!suppress_default_print)
18198527Sfenner				default_print(p, caplen);
18298527Sfenner		}
18398527Sfenner	} else {
18498527Sfenner		/* Some kinds of TR packet we cannot handle intelligently */
18598527Sfenner		/* XXX - dissect MAC packets if frame type is 0 */
18644165Sjulian		if (!eflag)
187127675Sbms			token_hdr_print(trp, length + TOKEN_HDRLEN + route_len,
18898527Sfenner			    ESRC(&ehdr), EDST(&ehdr));
189162021Ssam		if (!suppress_default_print)
19044165Sjulian			default_print(p, caplen);
19144165Sjulian	}
192127675Sbms	return (hdr_len);
19344165Sjulian}
194127675Sbms
195127675Sbms/*
196127675Sbms * This is the top level routine of the printer.  'p' points
197127675Sbms * to the TR header of the packet, 'h->ts' is the timestamp,
198146778Ssam * 'h->len' is the length of the packet off the wire, and 'h->caplen'
199127675Sbms * is the number of bytes actually captured.
200127675Sbms */
201127675Sbmsu_int
202127675Sbmstoken_if_print(const struct pcap_pkthdr *h, const u_char *p)
203127675Sbms{
204127675Sbms	return (token_print(p, h->len, h->caplen));
205127675Sbms}
206