xref: /freebsd/contrib/tcpdump/print-fddi.c (revision cc391cce1125c1163b0cc425704a4279ca0dbe9a)
14edb46e9SPaul Traina /*
2699fc314SBill Fenner  * Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997
34edb46e9SPaul Traina  *	The Regents of the University of California.  All rights reserved.
44edb46e9SPaul Traina  *
54edb46e9SPaul Traina  * Redistribution and use in source and binary forms, with or without
64edb46e9SPaul Traina  * modification, are permitted provided that: (1) source code distributions
74edb46e9SPaul Traina  * retain the above copyright notice and this paragraph in its entirety, (2)
84edb46e9SPaul Traina  * distributions including binary code include the above copyright notice and
94edb46e9SPaul Traina  * this paragraph in its entirety in the documentation or other materials
104edb46e9SPaul Traina  * provided with the distribution, and (3) all advertising materials mentioning
114edb46e9SPaul Traina  * features or use of this software display the following acknowledgement:
124edb46e9SPaul Traina  * ``This product includes software developed by the University of California,
134edb46e9SPaul Traina  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
144edb46e9SPaul Traina  * the University nor the names of its contributors may be used to endorse
154edb46e9SPaul Traina  * or promote products derived from this software without specific prior
164edb46e9SPaul Traina  * written permission.
174edb46e9SPaul Traina  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
184edb46e9SPaul Traina  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
194edb46e9SPaul Traina  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20a88113a8SBill Fenner  *
21a88113a8SBill Fenner  * $FreeBSD$
224edb46e9SPaul Traina  */
234edb46e9SPaul Traina 
244edb46e9SPaul Traina #ifndef lint
25cc391cceSBruce M Simpson static const char rcsid[] _U_ =
26cc391cceSBruce M Simpson     "@(#) $Header: /tcpdump/master/tcpdump/print-fddi.c,v 1.61.2.2 2003/11/16 08:51:20 guy Exp $ (LBL)";
274edb46e9SPaul Traina #endif
284edb46e9SPaul Traina 
29a88113a8SBill Fenner #ifdef HAVE_CONFIG_H
30a88113a8SBill Fenner #include "config.h"
31a88113a8SBill Fenner #endif
32a88113a8SBill Fenner 
33cc391cceSBruce M Simpson #include <tcpdump-stdinc.h>
344edb46e9SPaul Traina 
354edb46e9SPaul Traina #include <pcap.h>
364edb46e9SPaul Traina #include <stdio.h>
374edb46e9SPaul Traina #include <string.h>
384edb46e9SPaul Traina 
394edb46e9SPaul Traina #include "interface.h"
404edb46e9SPaul Traina #include "addrtoname.h"
414edb46e9SPaul Traina #include "ethertype.h"
424edb46e9SPaul Traina 
43943ee2b1SBill Fenner #include "ether.h"
444edb46e9SPaul Traina #include "fddi.h"
454edb46e9SPaul Traina 
464edb46e9SPaul Traina /*
474edb46e9SPaul Traina  * Some FDDI interfaces use bit-swapped addresses.
484edb46e9SPaul Traina  */
49a1c2090eSBill Fenner #if defined(ultrix) || defined(__alpha) || defined(__bsdi) || defined(__NetBSD__) || defined(__linux__)
504edb46e9SPaul Traina int	fddi_bitswap = 0;
514edb46e9SPaul Traina #else
524edb46e9SPaul Traina int	fddi_bitswap = 1;
534edb46e9SPaul Traina #endif
544edb46e9SPaul Traina 
554edb46e9SPaul Traina /*
564edb46e9SPaul Traina  * FDDI support for tcpdump, by Jeffrey Mogul [DECWRL], June 1992
574edb46e9SPaul Traina  *
584edb46e9SPaul Traina  * Based in part on code by Van Jacobson, which bears this note:
594edb46e9SPaul Traina  *
604edb46e9SPaul Traina  * NOTE:  This is a very preliminary hack for FDDI support.
614edb46e9SPaul Traina  * There are all sorts of wired in constants & nothing (yet)
624edb46e9SPaul Traina  * to print SMT packets as anything other than hex dumps.
634edb46e9SPaul Traina  * Most of the necessary changes are waiting on my redoing
644edb46e9SPaul Traina  * the "header" that a kernel fddi driver supplies to bpf:  I
654edb46e9SPaul Traina  * want it to look like one byte of 'direction' (0 or 1
664edb46e9SPaul Traina  * depending on whether the packet was inbound or outbound),
674edb46e9SPaul Traina  * two bytes of system/driver dependent data (anything an
684edb46e9SPaul Traina  * implementor thinks would be useful to filter on and/or
694edb46e9SPaul Traina  * save per-packet, then the real 21-byte FDDI header.
704edb46e9SPaul Traina  * Steve McCanne & I have also talked about adding the
714edb46e9SPaul Traina  * 'direction' byte to all bpf headers (e.g., in the two
724edb46e9SPaul Traina  * bytes of padding on an ethernet header).  It's not clear
734edb46e9SPaul Traina  * we could do this in a backwards compatible way & we hate
744edb46e9SPaul Traina  * the idea of an incompatible bpf change.  Discussions are
754edb46e9SPaul Traina  * proceeding.
764edb46e9SPaul Traina  *
774edb46e9SPaul Traina  * Also, to really support FDDI (and better support 802.2
784edb46e9SPaul Traina  * over ethernet) we really need to re-think the rather simple
794edb46e9SPaul Traina  * minded assumptions about fixed length & fixed format link
804edb46e9SPaul Traina  * level headers made in gencode.c.  One day...
814edb46e9SPaul Traina  *
824edb46e9SPaul Traina  *  - vj
834edb46e9SPaul Traina  */
844edb46e9SPaul Traina 
854edb46e9SPaul Traina static u_char fddi_bit_swap[] = {
864edb46e9SPaul Traina 	0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
874edb46e9SPaul Traina 	0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
884edb46e9SPaul Traina 	0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
894edb46e9SPaul Traina 	0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
904edb46e9SPaul Traina 	0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
914edb46e9SPaul Traina 	0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
924edb46e9SPaul Traina 	0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
934edb46e9SPaul Traina 	0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
944edb46e9SPaul Traina 	0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
954edb46e9SPaul Traina 	0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
964edb46e9SPaul Traina 	0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
974edb46e9SPaul Traina 	0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
984edb46e9SPaul Traina 	0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
994edb46e9SPaul Traina 	0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
1004edb46e9SPaul Traina 	0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
1014edb46e9SPaul Traina 	0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
1024edb46e9SPaul Traina 	0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
1034edb46e9SPaul Traina 	0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
1044edb46e9SPaul Traina 	0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
1054edb46e9SPaul Traina 	0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
1064edb46e9SPaul Traina 	0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
1074edb46e9SPaul Traina 	0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
1084edb46e9SPaul Traina 	0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
1094edb46e9SPaul Traina 	0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
1104edb46e9SPaul Traina 	0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
1114edb46e9SPaul Traina 	0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
1124edb46e9SPaul Traina 	0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
1134edb46e9SPaul Traina 	0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
1144edb46e9SPaul Traina 	0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
1154edb46e9SPaul Traina 	0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
1164edb46e9SPaul Traina 	0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
1174edb46e9SPaul Traina 	0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
1184edb46e9SPaul Traina };
1194edb46e9SPaul Traina 
1204edb46e9SPaul Traina /*
1214edb46e9SPaul Traina  * Print FDDI frame-control bits
1224edb46e9SPaul Traina  */
1234edb46e9SPaul Traina static inline void
1244edb46e9SPaul Traina print_fddi_fc(u_char fc)
1254edb46e9SPaul Traina {
1264edb46e9SPaul Traina 	switch (fc) {
1274edb46e9SPaul Traina 
1284edb46e9SPaul Traina 	case FDDIFC_VOID:                         /* Void frame */
1294edb46e9SPaul Traina 		printf("void ");
1304edb46e9SPaul Traina 		break;
1314edb46e9SPaul Traina 
1324edb46e9SPaul Traina 	case FDDIFC_NRT:                          /* Nonrestricted token */
1334edb46e9SPaul Traina 		printf("nrt ");
1344edb46e9SPaul Traina 		break;
1354edb46e9SPaul Traina 
1364edb46e9SPaul Traina 	case FDDIFC_RT:                           /* Restricted token */
1374edb46e9SPaul Traina 		printf("rt ");
1384edb46e9SPaul Traina 		break;
1394edb46e9SPaul Traina 
1404edb46e9SPaul Traina 	case FDDIFC_SMT_INFO:                     /* SMT Info */
1414edb46e9SPaul Traina 		printf("info ");
1424edb46e9SPaul Traina 		break;
1434edb46e9SPaul Traina 
1444edb46e9SPaul Traina 	case FDDIFC_SMT_NSA:                      /* SMT Next station adrs */
1454edb46e9SPaul Traina 		printf("nsa ");
1464edb46e9SPaul Traina 		break;
1474edb46e9SPaul Traina 
1484edb46e9SPaul Traina 	case FDDIFC_MAC_BEACON:                   /* MAC Beacon frame */
1494edb46e9SPaul Traina 		printf("beacon ");
1504edb46e9SPaul Traina 		break;
1514edb46e9SPaul Traina 
1524edb46e9SPaul Traina 	case FDDIFC_MAC_CLAIM:                    /* MAC Claim frame */
1534edb46e9SPaul Traina 		printf("claim ");
1544edb46e9SPaul Traina 		break;
1554edb46e9SPaul Traina 
1564edb46e9SPaul Traina 	default:
1574edb46e9SPaul Traina 		switch (fc & FDDIFC_CLFF) {
1584edb46e9SPaul Traina 
1594edb46e9SPaul Traina 		case FDDIFC_MAC:
1604edb46e9SPaul Traina 			printf("mac%1x ", fc & FDDIFC_ZZZZ);
1614edb46e9SPaul Traina 			break;
1624edb46e9SPaul Traina 
1634edb46e9SPaul Traina 		case FDDIFC_SMT:
1644edb46e9SPaul Traina 			printf("smt%1x ", fc & FDDIFC_ZZZZ);
1654edb46e9SPaul Traina 			break;
1664edb46e9SPaul Traina 
1674edb46e9SPaul Traina 		case FDDIFC_LLC_ASYNC:
1684edb46e9SPaul Traina 			printf("async%1x ", fc & FDDIFC_ZZZZ);
1694edb46e9SPaul Traina 			break;
1704edb46e9SPaul Traina 
1714edb46e9SPaul Traina 		case FDDIFC_LLC_SYNC:
1724edb46e9SPaul Traina 			printf("sync%1x ", fc & FDDIFC_ZZZZ);
1734edb46e9SPaul Traina 			break;
1744edb46e9SPaul Traina 
1754edb46e9SPaul Traina 		case FDDIFC_IMP_ASYNC:
1764edb46e9SPaul Traina 			printf("imp_async%1x ", fc & FDDIFC_ZZZZ);
1774edb46e9SPaul Traina 			break;
1784edb46e9SPaul Traina 
1794edb46e9SPaul Traina 		case FDDIFC_IMP_SYNC:
1804edb46e9SPaul Traina 			printf("imp_sync%1x ", fc & FDDIFC_ZZZZ);
1814edb46e9SPaul Traina 			break;
1824edb46e9SPaul Traina 
1834edb46e9SPaul Traina 		default:
1844edb46e9SPaul Traina 			printf("%02x ", fc);
1854edb46e9SPaul Traina 			break;
1864edb46e9SPaul Traina 		}
1874edb46e9SPaul Traina 	}
1884edb46e9SPaul Traina }
1894edb46e9SPaul Traina 
1904edb46e9SPaul Traina /* Extract src, dst addresses */
1914edb46e9SPaul Traina static inline void
1924edb46e9SPaul Traina extract_fddi_addrs(const struct fddi_header *fddip, char *fsrc, char *fdst)
1934edb46e9SPaul Traina {
1944edb46e9SPaul Traina 	register int i;
1954edb46e9SPaul Traina 
1964edb46e9SPaul Traina 	if (fddi_bitswap) {
1974edb46e9SPaul Traina 		/*
1984edb46e9SPaul Traina 		 * bit-swap the fddi addresses (isn't the IEEE standards
1994edb46e9SPaul Traina 		 * process wonderful!) then convert them to names.
2004edb46e9SPaul Traina 		 */
2014edb46e9SPaul Traina 		for (i = 0; i < 6; ++i)
2024edb46e9SPaul Traina 			fdst[i] = fddi_bit_swap[fddip->fddi_dhost[i]];
2034edb46e9SPaul Traina 		for (i = 0; i < 6; ++i)
2044edb46e9SPaul Traina 			fsrc[i] = fddi_bit_swap[fddip->fddi_shost[i]];
2054edb46e9SPaul Traina 	}
2064edb46e9SPaul Traina 	else {
207a1c2090eSBill Fenner 		memcpy(fdst, (const char *)fddip->fddi_dhost, 6);
208a1c2090eSBill Fenner 		memcpy(fsrc, (const char *)fddip->fddi_shost, 6);
2094edb46e9SPaul Traina 	}
2104edb46e9SPaul Traina }
2114edb46e9SPaul Traina 
2124edb46e9SPaul Traina /*
2134edb46e9SPaul Traina  * Print the FDDI MAC header
2144edb46e9SPaul Traina  */
2154edb46e9SPaul Traina static inline void
216cc391cceSBruce M Simpson fddi_hdr_print(register const struct fddi_header *fddip, register u_int length,
2174edb46e9SPaul Traina 	   register const u_char *fsrc, register const u_char *fdst)
2184edb46e9SPaul Traina {
219a1c2090eSBill Fenner 	const char *srcname, *dstname;
2204edb46e9SPaul Traina 
2214edb46e9SPaul Traina 	srcname = etheraddr_string(fsrc);
2224edb46e9SPaul Traina 	dstname = etheraddr_string(fdst);
2234edb46e9SPaul Traina 
2244edb46e9SPaul Traina 	if (vflag)
2254edb46e9SPaul Traina 		(void) printf("%02x %s %s %d: ",
2264edb46e9SPaul Traina 		       fddip->fddi_fc,
2274edb46e9SPaul Traina 		       srcname, dstname,
2284edb46e9SPaul Traina 		       length);
2294edb46e9SPaul Traina 	else if (qflag)
2304edb46e9SPaul Traina 		printf("%s %s %d: ", srcname, dstname, length);
2314edb46e9SPaul Traina 	else {
2324edb46e9SPaul Traina 		(void) print_fddi_fc(fddip->fddi_fc);
2334edb46e9SPaul Traina 		(void) printf("%s %s %d: ", srcname, dstname, length);
2344edb46e9SPaul Traina 	}
2354edb46e9SPaul Traina }
2364edb46e9SPaul Traina 
2374edb46e9SPaul Traina static inline void
238cc391cceSBruce M Simpson fddi_smt_print(const u_char *p _U_, u_int length _U_)
2394edb46e9SPaul Traina {
2404edb46e9SPaul Traina 	printf("<SMT printer not yet implemented>");
2414edb46e9SPaul Traina }
2424edb46e9SPaul Traina 
2434edb46e9SPaul Traina void
244cc391cceSBruce M Simpson fddi_print(const u_char *p, u_int length, u_int caplen)
2454edb46e9SPaul Traina {
246a1c2090eSBill Fenner 	const struct fddi_header *fddip = (const struct fddi_header *)p;
2474edb46e9SPaul Traina 	struct ether_header ehdr;
248a88113a8SBill Fenner 	u_short extracted_ethertype;
2494edb46e9SPaul Traina 
2504edb46e9SPaul Traina 	if (caplen < FDDI_HDRLEN) {
2514edb46e9SPaul Traina 		printf("[|fddi]");
252cc391cceSBruce M Simpson 		return;
2534edb46e9SPaul Traina 	}
254cc391cceSBruce M Simpson 
2554edb46e9SPaul Traina 	/*
2564edb46e9SPaul Traina 	 * Get the FDDI addresses into a canonical form
2574edb46e9SPaul Traina 	 */
2584edb46e9SPaul Traina 	extract_fddi_addrs(fddip, (char *)ESRC(&ehdr), (char *)EDST(&ehdr));
2594edb46e9SPaul Traina 
2604edb46e9SPaul Traina 	if (eflag)
261cc391cceSBruce M Simpson 		fddi_hdr_print(fddip, length, ESRC(&ehdr), EDST(&ehdr));
2624edb46e9SPaul Traina 
2634edb46e9SPaul Traina 	/* Skip over FDDI MAC header */
2644edb46e9SPaul Traina 	length -= FDDI_HDRLEN;
2654edb46e9SPaul Traina 	p += FDDI_HDRLEN;
2664edb46e9SPaul Traina 	caplen -= FDDI_HDRLEN;
2674edb46e9SPaul Traina 
2684edb46e9SPaul Traina 	/* Frame Control field determines interpretation of packet */
2694edb46e9SPaul Traina 	extracted_ethertype = 0;
2704edb46e9SPaul Traina 	if ((fddip->fddi_fc & FDDIFC_CLFF) == FDDIFC_LLC_ASYNC) {
2714edb46e9SPaul Traina 		/* Try to print the LLC-layer header & higher layers */
272943ee2b1SBill Fenner 		if (llc_print(p, length, caplen, ESRC(&ehdr), EDST(&ehdr),
273943ee2b1SBill Fenner 		    &extracted_ethertype) == 0) {
2744edb46e9SPaul Traina 			/*
2754edb46e9SPaul Traina 			 * Some kinds of LLC packet we cannot
2764edb46e9SPaul Traina 			 * handle intelligently
2774edb46e9SPaul Traina 			 */
2784edb46e9SPaul Traina 			if (!eflag)
279cc391cceSBruce M Simpson 				fddi_hdr_print(fddip, length + FDDI_HDRLEN,
2804edb46e9SPaul Traina 				    ESRC(&ehdr), EDST(&ehdr));
2814edb46e9SPaul Traina 			if (extracted_ethertype) {
2824edb46e9SPaul Traina 				printf("(LLC %s) ",
2834edb46e9SPaul Traina 			etherproto_string(htons(extracted_ethertype)));
2844edb46e9SPaul Traina 			}
2854edb46e9SPaul Traina 			if (!xflag && !qflag)
2864edb46e9SPaul Traina 				default_print(p, caplen);
2874edb46e9SPaul Traina 		}
2884edb46e9SPaul Traina 	} else if ((fddip->fddi_fc & FDDIFC_CLFF) == FDDIFC_SMT)
2894edb46e9SPaul Traina 		fddi_smt_print(p, caplen);
2904edb46e9SPaul Traina 	else {
2914edb46e9SPaul Traina 		/* Some kinds of FDDI packet we cannot handle intelligently */
2924edb46e9SPaul Traina 		if (!eflag)
293cc391cceSBruce M Simpson 			fddi_hdr_print(fddip, length + FDDI_HDRLEN, ESRC(&ehdr),
294943ee2b1SBill Fenner 			    EDST(&ehdr));
2954edb46e9SPaul Traina 		if (!xflag && !qflag)
2964edb46e9SPaul Traina 			default_print(p, caplen);
2974edb46e9SPaul Traina 	}
298cc391cceSBruce M Simpson }
299cc391cceSBruce M Simpson 
300cc391cceSBruce M Simpson /*
301cc391cceSBruce M Simpson  * This is the top level routine of the printer.  'p' points
302cc391cceSBruce M Simpson  * to the FDDI header of the packet, 'h->ts' is the timestamp,
303cc391cceSBruce M Simpson  * 'h->length' is the length of the packet off the wire, and 'h->caplen'
304cc391cceSBruce M Simpson  * is the number of bytes actually captured.
305cc391cceSBruce M Simpson  */
306cc391cceSBruce M Simpson u_int
307cc391cceSBruce M Simpson fddi_if_print(const struct pcap_pkthdr *h, register const u_char *p)
308cc391cceSBruce M Simpson {
309cc391cceSBruce M Simpson 	fddi_print(p, h->len, h->caplen);
310cc391cceSBruce M Simpson 
311cc391cceSBruce M Simpson 	return (FDDI_HDRLEN);
3124edb46e9SPaul Traina }
313