• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997
3   *	The Regents of the University of California.  All rights reserved.
4   *
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
16   * written permission.
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.
20   */
21  
22  #ifndef lint
23  static const char rcsid[] _U_ =
24      "@(#) $Header: /tcpdump/master/tcpdump/print-fddi.c,v 1.64.2.2 2005/11/13 12:12:59 guy Exp $ (LBL)";
25  #endif
26  
27  #ifdef HAVE_CONFIG_H
28  #include "config.h"
29  #endif
30  
31  #include <tcpdump-stdinc.h>
32  
33  #include <pcap.h>
34  #include <stdio.h>
35  #include <string.h>
36  
37  #include "interface.h"
38  #include "addrtoname.h"
39  #include "ethertype.h"
40  
41  #include "ether.h"
42  #include "fddi.h"
43  
44  /*
45   * Some FDDI interfaces use bit-swapped addresses.
46   */
47  #if defined(ultrix) || defined(__alpha) || defined(__bsdi) || defined(__NetBSD__) || defined(__linux__)
48  int	fddi_bitswap = 0;
49  #else
50  int	fddi_bitswap = 1;
51  #endif
52  
53  /*
54   * FDDI support for tcpdump, by Jeffrey Mogul [DECWRL], June 1992
55   *
56   * Based in part on code by Van Jacobson, which bears this note:
57   *
58   * NOTE:  This is a very preliminary hack for FDDI support.
59   * There are all sorts of wired in constants & nothing (yet)
60   * to print SMT packets as anything other than hex dumps.
61   * Most of the necessary changes are waiting on my redoing
62   * the "header" that a kernel fddi driver supplies to bpf:  I
63   * want it to look like one byte of 'direction' (0 or 1
64   * depending on whether the packet was inbound or outbound),
65   * two bytes of system/driver dependent data (anything an
66   * implementor thinks would be useful to filter on and/or
67   * save per-packet, then the real 21-byte FDDI header.
68   * Steve McCanne & I have also talked about adding the
69   * 'direction' byte to all bpf headers (e.g., in the two
70   * bytes of padding on an ethernet header).  It's not clear
71   * we could do this in a backwards compatible way & we hate
72   * the idea of an incompatible bpf change.  Discussions are
73   * proceeding.
74   *
75   * Also, to really support FDDI (and better support 802.2
76   * over ethernet) we really need to re-think the rather simple
77   * minded assumptions about fixed length & fixed format link
78   * level headers made in gencode.c.  One day...
79   *
80   *  - vj
81   */
82  
83  static u_char fddi_bit_swap[] = {
84  	0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
85  	0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
86  	0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
87  	0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
88  	0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
89  	0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
90  	0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
91  	0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
92  	0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
93  	0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
94  	0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
95  	0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
96  	0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
97  	0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
98  	0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
99  	0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
100  	0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
101  	0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
102  	0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
103  	0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
104  	0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
105  	0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
106  	0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
107  	0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
108  	0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
109  	0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
110  	0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
111  	0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
112  	0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
113  	0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
114  	0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
115  	0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
116  };
117  
118  /*
119   * Print FDDI frame-control bits
120   */
121  static inline void
print_fddi_fc(u_char fc)122  print_fddi_fc(u_char fc)
123  {
124  	switch (fc) {
125  
126  	case FDDIFC_VOID:                         /* Void frame */
127  		printf("void ");
128  		break;
129  
130  	case FDDIFC_NRT:                          /* Nonrestricted token */
131  		printf("nrt ");
132  		break;
133  
134  	case FDDIFC_RT:                           /* Restricted token */
135  		printf("rt ");
136  		break;
137  
138  	case FDDIFC_SMT_INFO:                     /* SMT Info */
139  		printf("info ");
140  		break;
141  
142  	case FDDIFC_SMT_NSA:                      /* SMT Next station adrs */
143  		printf("nsa ");
144  		break;
145  
146  	case FDDIFC_MAC_BEACON:                   /* MAC Beacon frame */
147  		printf("beacon ");
148  		break;
149  
150  	case FDDIFC_MAC_CLAIM:                    /* MAC Claim frame */
151  		printf("claim ");
152  		break;
153  
154  	default:
155  		switch (fc & FDDIFC_CLFF) {
156  
157  		case FDDIFC_MAC:
158  			printf("mac%1x ", fc & FDDIFC_ZZZZ);
159  			break;
160  
161  		case FDDIFC_SMT:
162  			printf("smt%1x ", fc & FDDIFC_ZZZZ);
163  			break;
164  
165  		case FDDIFC_LLC_ASYNC:
166  			printf("async%1x ", fc & FDDIFC_ZZZZ);
167  			break;
168  
169  		case FDDIFC_LLC_SYNC:
170  			printf("sync%1x ", fc & FDDIFC_ZZZZ);
171  			break;
172  
173  		case FDDIFC_IMP_ASYNC:
174  			printf("imp_async%1x ", fc & FDDIFC_ZZZZ);
175  			break;
176  
177  		case FDDIFC_IMP_SYNC:
178  			printf("imp_sync%1x ", fc & FDDIFC_ZZZZ);
179  			break;
180  
181  		default:
182  			printf("%02x ", fc);
183  			break;
184  		}
185  	}
186  }
187  
188  /* Extract src, dst addresses */
189  static inline void
extract_fddi_addrs(const struct fddi_header * fddip,char * fsrc,char * fdst)190  extract_fddi_addrs(const struct fddi_header *fddip, char *fsrc, char *fdst)
191  {
192  	register int i;
193  
194  	if (fddi_bitswap) {
195  		/*
196  		 * bit-swap the fddi addresses (isn't the IEEE standards
197  		 * process wonderful!) then convert them to names.
198  		 */
199  		for (i = 0; i < 6; ++i)
200  			fdst[i] = fddi_bit_swap[fddip->fddi_dhost[i]];
201  		for (i = 0; i < 6; ++i)
202  			fsrc[i] = fddi_bit_swap[fddip->fddi_shost[i]];
203  	}
204  	else {
205  		memcpy(fdst, (const char *)fddip->fddi_dhost, 6);
206  		memcpy(fsrc, (const char *)fddip->fddi_shost, 6);
207  	}
208  }
209  
210  /*
211   * Print the FDDI MAC header
212   */
213  static inline void
fddi_hdr_print(register const struct fddi_header * fddip,register u_int length,register const u_char * fsrc,register const u_char * fdst)214  fddi_hdr_print(register const struct fddi_header *fddip, register u_int length,
215  	   register const u_char *fsrc, register const u_char *fdst)
216  {
217  	const char *srcname, *dstname;
218  
219  	srcname = etheraddr_string(fsrc);
220  	dstname = etheraddr_string(fdst);
221  
222  	if (vflag)
223  		(void) printf("%02x %s %s %d: ",
224  		       fddip->fddi_fc,
225  		       srcname, dstname,
226  		       length);
227  	else if (qflag)
228  		printf("%s %s %d: ", srcname, dstname, length);
229  	else {
230  		(void) print_fddi_fc(fddip->fddi_fc);
231  		(void) printf("%s %s %d: ", srcname, dstname, length);
232  	}
233  }
234  
235  static inline void
fddi_smt_print(const u_char * p _U_,u_int length _U_)236  fddi_smt_print(const u_char *p _U_, u_int length _U_)
237  {
238  	printf("<SMT printer not yet implemented>");
239  }
240  
241  void
fddi_print(const u_char * p,u_int length,u_int caplen)242  fddi_print(const u_char *p, u_int length, u_int caplen)
243  {
244  	const struct fddi_header *fddip = (const struct fddi_header *)p;
245  	struct ether_header ehdr;
246  	u_short extracted_ethertype;
247  
248  	if (caplen < FDDI_HDRLEN) {
249  		printf("[|fddi]");
250  		return;
251  	}
252  
253  	/*
254  	 * Get the FDDI addresses into a canonical form
255  	 */
256  	extract_fddi_addrs(fddip, (char *)ESRC(&ehdr), (char *)EDST(&ehdr));
257  
258  	if (eflag)
259  		fddi_hdr_print(fddip, length, ESRC(&ehdr), EDST(&ehdr));
260  
261  	/* Skip over FDDI MAC header */
262  	length -= FDDI_HDRLEN;
263  	p += FDDI_HDRLEN;
264  	caplen -= FDDI_HDRLEN;
265  
266  	/* Frame Control field determines interpretation of packet */
267  	if ((fddip->fddi_fc & FDDIFC_CLFF) == FDDIFC_LLC_ASYNC) {
268  		/* Try to print the LLC-layer header & higher layers */
269  		if (llc_print(p, length, caplen, ESRC(&ehdr), EDST(&ehdr),
270  		    &extracted_ethertype) == 0) {
271  			/*
272  			 * Some kinds of LLC packet we cannot
273  			 * handle intelligently
274  			 */
275  			if (!eflag)
276  				fddi_hdr_print(fddip, length + FDDI_HDRLEN,
277  				    ESRC(&ehdr), EDST(&ehdr));
278  			if (extracted_ethertype) {
279  				printf("(LLC %s) ",
280  			etherproto_string(htons(extracted_ethertype)));
281  			}
282  			if (!suppress_default_print)
283  				default_print(p, caplen);
284  		}
285  	} else if ((fddip->fddi_fc & FDDIFC_CLFF) == FDDIFC_SMT)
286  		fddi_smt_print(p, caplen);
287  	else {
288  		/* Some kinds of FDDI packet we cannot handle intelligently */
289  		if (!eflag)
290  			fddi_hdr_print(fddip, length + FDDI_HDRLEN, ESRC(&ehdr),
291  			    EDST(&ehdr));
292  		if (!suppress_default_print)
293  			default_print(p, caplen);
294  	}
295  }
296  
297  /*
298   * This is the top level routine of the printer.  'p' points
299   * to the FDDI header of the packet, 'h->ts' is the timestamp,
300   * 'h->len' is the length of the packet off the wire, and 'h->caplen'
301   * is the number of bytes actually captured.
302   */
303  u_int
fddi_if_print(const struct pcap_pkthdr * h,register const u_char * p)304  fddi_if_print(const struct pcap_pkthdr *h, register const u_char *p)
305  {
306  	fddi_print(p, h->len, h->caplen);
307  
308  	return (FDDI_HDRLEN);
309  }
310