print-fddi.c revision 39300
1132718Skan/*
2169689Skan * Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997
3132718Skan *	The Regents of the University of California.  All rights reserved.
4132718Skan *
5132718Skan * Redistribution and use in source and binary forms, with or without
6132718Skan * modification, are permitted provided that: (1) source code distributions
7132718Skan * retain the above copyright notice and this paragraph in its entirety, (2)
8132718Skan * distributions including binary code include the above copyright notice and
9132718Skan * this paragraph in its entirety in the documentation or other materials
10132718Skan * provided with the distribution, and (3) all advertising materials mentioning
11132718Skan * features or use of this software display the following acknowledgement:
12132718Skan * ``This product includes software developed by the University of California,
13132718Skan * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14132718Skan * the University nor the names of its contributors may be used to endorse
15132718Skan * or promote products derived from this software without specific prior
16132718Skan * written permission.
17132718Skan * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18169689Skan * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19169689Skan * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20132718Skan */
21132718Skan
22132718Skan#ifndef lint
23132718Skanstatic const char rcsid[] =
24132718Skan    "@(#) $Header: print-fddi.c,v 1.36 97/05/26 17:13:35 leres Exp $ (LBL)";
25132718Skan#endif
26132718Skan
27132718Skan#ifdef HAVE_FDDI
28132718Skan#include <sys/param.h>
29132718Skan#include <sys/time.h>
30132718Skan#include <sys/socket.h>
31132718Skan#include <sys/file.h>
32132718Skan#include <sys/ioctl.h>
33132718Skan
34169689Skan#if __STDC__
35132718Skanstruct mbuf;
36132718Skanstruct rtentry;
37132718Skan#endif
38132718Skan#include <net/if.h>
39132718Skan
40132718Skan#include <netinet/in.h>
41132718Skan#include <net/ethernet.h>
42132718Skan#include <netinet/in_systm.h>
43132718Skan#include <netinet/ip.h>
44169689Skan
45169689Skan#include <ctype.h>
46169689Skan#include <netdb.h>
47169689Skan#include <pcap.h>
48169689Skan#include <stdio.h>
49132718Skan#include <string.h>
50132718Skan
51132718Skan#include "interface.h"
52132718Skan#include "addrtoname.h"
53132718Skan#include "ethertype.h"
54169689Skan
55169689Skan#include "fddi.h"
56169689Skan
57169689Skan/*
58169689Skan * Some FDDI interfaces use bit-swapped addresses.
59169689Skan */
60169689Skan#if defined(ultrix) || defined(__alpha) || defined(__bsdi)
61169689Skanint	fddi_bitswap = 0;
62169689Skan#else
63169689Skanint	fddi_bitswap = 1;
64132718Skan#endif
65132718Skan
66132718Skan/*
67132718Skan * FDDI support for tcpdump, by Jeffrey Mogul [DECWRL], June 1992
68132718Skan *
69132718Skan * Based in part on code by Van Jacobson, which bears this note:
70132718Skan *
71132718Skan * NOTE:  This is a very preliminary hack for FDDI support.
72132718Skan * There are all sorts of wired in constants & nothing (yet)
73132718Skan * to print SMT packets as anything other than hex dumps.
74132718Skan * Most of the necessary changes are waiting on my redoing
75132718Skan * the "header" that a kernel fddi driver supplies to bpf:  I
76132718Skan * want it to look like one byte of 'direction' (0 or 1
77132718Skan * depending on whether the packet was inbound or outbound),
78132718Skan * two bytes of system/driver dependent data (anything an
79132718Skan * implementor thinks would be useful to filter on and/or
80132718Skan * save per-packet, then the real 21-byte FDDI header.
81132718Skan * Steve McCanne & I have also talked about adding the
82132718Skan * 'direction' byte to all bpf headers (e.g., in the two
83132718Skan * bytes of padding on an ethernet header).  It's not clear
84132718Skan * we could do this in a backwards compatible way & we hate
85132718Skan * the idea of an incompatible bpf change.  Discussions are
86132718Skan * proceeding.
87132718Skan *
88132718Skan * Also, to really support FDDI (and better support 802.2
89132718Skan * over ethernet) we really need to re-think the rather simple
90132718Skan * minded assumptions about fixed length & fixed format link
91132718Skan * level headers made in gencode.c.  One day...
92132718Skan *
93132718Skan *  - vj
94132718Skan */
95132718Skan
96132718Skan#define FDDI_HDRLEN (sizeof(struct fddi_header))
97132718Skan
98132718Skanstatic u_char fddi_bit_swap[] = {
99132718Skan	0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
100132718Skan	0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
101132718Skan	0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
102132718Skan	0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
103132718Skan	0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
104132718Skan	0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
105132718Skan	0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
106132718Skan	0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
107132718Skan	0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
108132718Skan	0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
109132718Skan	0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
110132718Skan	0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
111132718Skan	0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
112132718Skan	0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
113132718Skan	0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
114132718Skan	0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
115132718Skan	0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
116132718Skan	0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
117132718Skan	0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
118132718Skan	0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
119132718Skan	0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
120132718Skan	0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
121132718Skan	0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
122132718Skan	0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
123132718Skan	0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
124132718Skan	0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
125132718Skan	0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
126132718Skan	0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
127132718Skan	0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
128132718Skan	0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
129132718Skan	0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
130132718Skan	0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
131132718Skan};
132132718Skan
133132718Skan/*
134132718Skan * Print FDDI frame-control bits
135132718Skan */
136132718Skanstatic inline void
137132718Skanprint_fddi_fc(u_char fc)
138132718Skan{
139132718Skan	switch (fc) {
140132718Skan
141132718Skan	case FDDIFC_VOID:                         /* Void frame */
142132718Skan		printf("void ");
143132718Skan		break;
144169689Skan
145169689Skan	case FDDIFC_NRT:                          /* Nonrestricted token */
146169689Skan		printf("nrt ");
147169689Skan		break;
148169689Skan
149169689Skan	case FDDIFC_RT:                           /* Restricted token */
150169689Skan		printf("rt ");
151169689Skan		break;
152169689Skan
153169689Skan	case FDDIFC_SMT_INFO:                     /* SMT Info */
154		printf("info ");
155		break;
156
157	case FDDIFC_SMT_NSA:                      /* SMT Next station adrs */
158		printf("nsa ");
159		break;
160
161	case FDDIFC_MAC_BEACON:                   /* MAC Beacon frame */
162		printf("beacon ");
163		break;
164
165	case FDDIFC_MAC_CLAIM:                    /* MAC Claim frame */
166		printf("claim ");
167		break;
168
169	default:
170		switch (fc & FDDIFC_CLFF) {
171
172		case FDDIFC_MAC:
173			printf("mac%1x ", fc & FDDIFC_ZZZZ);
174			break;
175
176		case FDDIFC_SMT:
177			printf("smt%1x ", fc & FDDIFC_ZZZZ);
178			break;
179
180		case FDDIFC_LLC_ASYNC:
181			printf("async%1x ", fc & FDDIFC_ZZZZ);
182			break;
183
184		case FDDIFC_LLC_SYNC:
185			printf("sync%1x ", fc & FDDIFC_ZZZZ);
186			break;
187
188		case FDDIFC_IMP_ASYNC:
189			printf("imp_async%1x ", fc & FDDIFC_ZZZZ);
190			break;
191
192		case FDDIFC_IMP_SYNC:
193			printf("imp_sync%1x ", fc & FDDIFC_ZZZZ);
194			break;
195
196		default:
197			printf("%02x ", fc);
198			break;
199		}
200	}
201}
202
203/* Extract src, dst addresses */
204static inline void
205extract_fddi_addrs(const struct fddi_header *fddip, char *fsrc, char *fdst)
206{
207	register int i;
208
209	if (fddi_bitswap) {
210		/*
211		 * bit-swap the fddi addresses (isn't the IEEE standards
212		 * process wonderful!) then convert them to names.
213		 */
214		for (i = 0; i < 6; ++i)
215			fdst[i] = fddi_bit_swap[fddip->fddi_dhost[i]];
216		for (i = 0; i < 6; ++i)
217			fsrc[i] = fddi_bit_swap[fddip->fddi_shost[i]];
218	}
219	else {
220		memcpy(fdst, (char *)fddip->fddi_dhost, 6);
221		memcpy(fsrc, (char *)fddip->fddi_shost, 6);
222	}
223}
224
225/*
226 * Print the FDDI MAC header
227 */
228static inline void
229fddi_print(register const struct fddi_header *fddip, register u_int length,
230	   register const u_char *fsrc, register const u_char *fdst)
231{
232	char *srcname, *dstname;
233
234	srcname = etheraddr_string(fsrc);
235	dstname = etheraddr_string(fdst);
236
237	if (vflag)
238		(void) printf("%02x %s %s %d: ",
239		       fddip->fddi_fc,
240		       srcname, dstname,
241		       length);
242	else if (qflag)
243		printf("%s %s %d: ", srcname, dstname, length);
244	else {
245		(void) print_fddi_fc(fddip->fddi_fc);
246		(void) printf("%s %s %d: ", srcname, dstname, length);
247	}
248}
249
250static inline void
251fddi_smt_print(const u_char *p, u_int length)
252{
253	printf("<SMT printer not yet implemented>");
254}
255
256/*
257 * This is the top level routine of the printer.  'sp' is the points
258 * to the FDDI header of the packet, 'tvp' is the timestamp,
259 * 'length' is the length of the packet off the wire, and 'caplen'
260 * is the number of bytes actually captured.
261 */
262void
263fddi_if_print(u_char *pcap, const struct pcap_pkthdr *h,
264	      register const u_char *p)
265{
266	u_int caplen = h->caplen;
267	u_int length = h->len;
268	const struct fddi_header *fddip = (struct fddi_header *)p;
269	extern u_short extracted_ethertype;
270	struct ether_header ehdr;
271
272	ts_print(&h->ts);
273
274	if (caplen < FDDI_HDRLEN) {
275		printf("[|fddi]");
276		goto out;
277	}
278	/*
279	 * Get the FDDI addresses into a canonical form
280	 */
281	extract_fddi_addrs(fddip, (char *)ESRC(&ehdr), (char *)EDST(&ehdr));
282	/*
283	 * Some printers want to get back at the link level addresses,
284	 * and/or check that they're not walking off the end of the packet.
285	 * Rather than pass them all the way down, we set these globals.
286	 */
287	snapend = p + caplen;
288	/*
289	 * Actually, the only printer that uses packetp is print-bootp.c,
290	 * and it assumes that packetp points to an Ethernet header.  The
291	 * right thing to do is to fix print-bootp.c to know which link
292	 * type is in use when it excavates. XXX
293	 */
294	packetp = (u_char *)&ehdr;
295
296	if (eflag)
297		fddi_print(fddip, length, ESRC(&ehdr), EDST(&ehdr));
298
299	/* Skip over FDDI MAC header */
300	length -= FDDI_HDRLEN;
301	p += FDDI_HDRLEN;
302	caplen -= FDDI_HDRLEN;
303
304	/* Frame Control field determines interpretation of packet */
305	extracted_ethertype = 0;
306	if ((fddip->fddi_fc & FDDIFC_CLFF) == FDDIFC_LLC_ASYNC) {
307		/* Try to print the LLC-layer header & higher layers */
308		if (llc_print(p, length, caplen, ESRC(&ehdr), EDST(&ehdr))
309		    == 0) {
310			/*
311			 * Some kinds of LLC packet we cannot
312			 * handle intelligently
313			 */
314			if (!eflag)
315				fddi_print(fddip, length,
316				    ESRC(&ehdr), EDST(&ehdr));
317			if (extracted_ethertype) {
318				printf("(LLC %s) ",
319			etherproto_string(htons(extracted_ethertype)));
320			}
321			if (!xflag && !qflag)
322				default_print(p, caplen);
323		}
324	} else if ((fddip->fddi_fc & FDDIFC_CLFF) == FDDIFC_SMT)
325		fddi_smt_print(p, caplen);
326	else {
327		/* Some kinds of FDDI packet we cannot handle intelligently */
328		if (!eflag)
329			fddi_print(fddip, length, ESRC(&ehdr), EDST(&ehdr));
330		if (!xflag && !qflag)
331			default_print(p, caplen);
332	}
333	if (xflag)
334		default_print(p, caplen);
335out:
336	putchar('\n');
337}
338#else
339#include <sys/types.h>
340#include <sys/time.h>
341
342#include <stdio.h>
343
344#include "interface.h"
345void
346fddi_if_print(u_char *pcap, const struct pcap_pkthdr *h,
347	      register const u_char *p)
348{
349
350	error("not configured for fddi");
351	/* NOTREACHED */
352}
353#endif
354