print-fddi.c revision 56896
117680Spst/*
239300Sfenner * Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997
317680Spst *	The Regents of the University of California.  All rights reserved.
417680Spst *
517680Spst * Redistribution and use in source and binary forms, with or without
617680Spst * modification, are permitted provided that: (1) source code distributions
717680Spst * retain the above copyright notice and this paragraph in its entirety, (2)
817680Spst * distributions including binary code include the above copyright notice and
917680Spst * this paragraph in its entirety in the documentation or other materials
1017680Spst * provided with the distribution, and (3) all advertising materials mentioning
1117680Spst * features or use of this software display the following acknowledgement:
1217680Spst * ``This product includes software developed by the University of California,
1317680Spst * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
1417680Spst * the University nor the names of its contributors may be used to endorse
1517680Spst * or promote products derived from this software without specific prior
1617680Spst * written permission.
1717680Spst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
1817680Spst * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1917680Spst * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2056896Sfenner *
2156896Sfenner * $FreeBSD: head/contrib/tcpdump/print-fddi.c 56896 2000-01-30 01:05:24Z fenner $
2217680Spst */
2317680Spst
2417680Spst#ifndef lint
2526183Sfennerstatic const char rcsid[] =
2656896Sfenner    "@(#) $Header: /tcpdump/master/tcpdump/print-fddi.c,v 1.40 1999/12/14 16:49:02 fenner Exp $ (LBL)";
2717680Spst#endif
2817680Spst
2956896Sfenner#ifdef HAVE_CONFIG_H
3056896Sfenner#include "config.h"
3156896Sfenner#endif
3256896Sfenner
3317680Spst#include <sys/param.h>
3417680Spst#include <sys/time.h>
3517680Spst#include <sys/socket.h>
3617680Spst#include <sys/file.h>
3717680Spst#include <sys/ioctl.h>
3817680Spst
3917680Spst#if __STDC__
4017680Spststruct mbuf;
4117680Spststruct rtentry;
4217680Spst#endif
4317680Spst#include <net/if.h>
4417680Spst
4517680Spst#include <netinet/in.h>
4621262Swollman#include <net/ethernet.h>
4717680Spst#include <netinet/in_systm.h>
4817680Spst#include <netinet/ip.h>
4917680Spst
5017680Spst#include <ctype.h>
5117680Spst#include <netdb.h>
5217680Spst#include <pcap.h>
5317680Spst#include <stdio.h>
5417680Spst#include <string.h>
5517680Spst
5617680Spst#include "interface.h"
5717680Spst#include "addrtoname.h"
5817680Spst#include "ethertype.h"
5917680Spst
6017680Spst#include "fddi.h"
6117680Spst
6217680Spst/*
6317680Spst * Some FDDI interfaces use bit-swapped addresses.
6417680Spst */
6556896Sfenner#if defined(ultrix) || defined(__alpha) || defined(__bsdi) || defined(__NetBSD__)
6617680Spstint	fddi_bitswap = 0;
6717680Spst#else
6817680Spstint	fddi_bitswap = 1;
6917680Spst#endif
7017680Spst
7117680Spst/*
7217680Spst * FDDI support for tcpdump, by Jeffrey Mogul [DECWRL], June 1992
7317680Spst *
7417680Spst * Based in part on code by Van Jacobson, which bears this note:
7517680Spst *
7617680Spst * NOTE:  This is a very preliminary hack for FDDI support.
7717680Spst * There are all sorts of wired in constants & nothing (yet)
7817680Spst * to print SMT packets as anything other than hex dumps.
7917680Spst * Most of the necessary changes are waiting on my redoing
8017680Spst * the "header" that a kernel fddi driver supplies to bpf:  I
8117680Spst * want it to look like one byte of 'direction' (0 or 1
8217680Spst * depending on whether the packet was inbound or outbound),
8317680Spst * two bytes of system/driver dependent data (anything an
8417680Spst * implementor thinks would be useful to filter on and/or
8517680Spst * save per-packet, then the real 21-byte FDDI header.
8617680Spst * Steve McCanne & I have also talked about adding the
8717680Spst * 'direction' byte to all bpf headers (e.g., in the two
8817680Spst * bytes of padding on an ethernet header).  It's not clear
8917680Spst * we could do this in a backwards compatible way & we hate
9017680Spst * the idea of an incompatible bpf change.  Discussions are
9117680Spst * proceeding.
9217680Spst *
9317680Spst * Also, to really support FDDI (and better support 802.2
9417680Spst * over ethernet) we really need to re-think the rather simple
9517680Spst * minded assumptions about fixed length & fixed format link
9617680Spst * level headers made in gencode.c.  One day...
9717680Spst *
9817680Spst *  - vj
9917680Spst */
10017680Spst
10117680Spst#define FDDI_HDRLEN (sizeof(struct fddi_header))
10217680Spst
10317680Spststatic u_char fddi_bit_swap[] = {
10417680Spst	0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
10517680Spst	0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
10617680Spst	0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
10717680Spst	0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
10817680Spst	0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
10917680Spst	0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
11017680Spst	0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
11117680Spst	0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
11217680Spst	0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
11317680Spst	0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
11417680Spst	0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
11517680Spst	0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
11617680Spst	0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
11717680Spst	0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
11817680Spst	0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
11917680Spst	0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
12017680Spst	0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
12117680Spst	0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
12217680Spst	0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
12317680Spst	0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
12417680Spst	0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
12517680Spst	0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
12617680Spst	0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
12717680Spst	0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
12817680Spst	0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
12917680Spst	0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
13017680Spst	0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
13117680Spst	0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
13217680Spst	0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
13317680Spst	0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
13417680Spst	0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
13517680Spst	0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
13617680Spst};
13717680Spst
13817680Spst/*
13917680Spst * Print FDDI frame-control bits
14017680Spst */
14117680Spststatic inline void
14217680Spstprint_fddi_fc(u_char fc)
14317680Spst{
14417680Spst	switch (fc) {
14517680Spst
14617680Spst	case FDDIFC_VOID:                         /* Void frame */
14717680Spst		printf("void ");
14817680Spst		break;
14917680Spst
15017680Spst	case FDDIFC_NRT:                          /* Nonrestricted token */
15117680Spst		printf("nrt ");
15217680Spst		break;
15317680Spst
15417680Spst	case FDDIFC_RT:                           /* Restricted token */
15517680Spst		printf("rt ");
15617680Spst		break;
15717680Spst
15817680Spst	case FDDIFC_SMT_INFO:                     /* SMT Info */
15917680Spst		printf("info ");
16017680Spst		break;
16117680Spst
16217680Spst	case FDDIFC_SMT_NSA:                      /* SMT Next station adrs */
16317680Spst		printf("nsa ");
16417680Spst		break;
16517680Spst
16617680Spst	case FDDIFC_MAC_BEACON:                   /* MAC Beacon frame */
16717680Spst		printf("beacon ");
16817680Spst		break;
16917680Spst
17017680Spst	case FDDIFC_MAC_CLAIM:                    /* MAC Claim frame */
17117680Spst		printf("claim ");
17217680Spst		break;
17317680Spst
17417680Spst	default:
17517680Spst		switch (fc & FDDIFC_CLFF) {
17617680Spst
17717680Spst		case FDDIFC_MAC:
17817680Spst			printf("mac%1x ", fc & FDDIFC_ZZZZ);
17917680Spst			break;
18017680Spst
18117680Spst		case FDDIFC_SMT:
18217680Spst			printf("smt%1x ", fc & FDDIFC_ZZZZ);
18317680Spst			break;
18417680Spst
18517680Spst		case FDDIFC_LLC_ASYNC:
18617680Spst			printf("async%1x ", fc & FDDIFC_ZZZZ);
18717680Spst			break;
18817680Spst
18917680Spst		case FDDIFC_LLC_SYNC:
19017680Spst			printf("sync%1x ", fc & FDDIFC_ZZZZ);
19117680Spst			break;
19217680Spst
19317680Spst		case FDDIFC_IMP_ASYNC:
19417680Spst			printf("imp_async%1x ", fc & FDDIFC_ZZZZ);
19517680Spst			break;
19617680Spst
19717680Spst		case FDDIFC_IMP_SYNC:
19817680Spst			printf("imp_sync%1x ", fc & FDDIFC_ZZZZ);
19917680Spst			break;
20017680Spst
20117680Spst		default:
20217680Spst			printf("%02x ", fc);
20317680Spst			break;
20417680Spst		}
20517680Spst	}
20617680Spst}
20717680Spst
20817680Spst/* Extract src, dst addresses */
20917680Spststatic inline void
21017680Spstextract_fddi_addrs(const struct fddi_header *fddip, char *fsrc, char *fdst)
21117680Spst{
21217680Spst	register int i;
21317680Spst
21417680Spst	if (fddi_bitswap) {
21517680Spst		/*
21617680Spst		 * bit-swap the fddi addresses (isn't the IEEE standards
21717680Spst		 * process wonderful!) then convert them to names.
21817680Spst		 */
21917680Spst		for (i = 0; i < 6; ++i)
22017680Spst			fdst[i] = fddi_bit_swap[fddip->fddi_dhost[i]];
22117680Spst		for (i = 0; i < 6; ++i)
22217680Spst			fsrc[i] = fddi_bit_swap[fddip->fddi_shost[i]];
22317680Spst	}
22417680Spst	else {
22517680Spst		memcpy(fdst, (char *)fddip->fddi_dhost, 6);
22617680Spst		memcpy(fsrc, (char *)fddip->fddi_shost, 6);
22717680Spst	}
22817680Spst}
22917680Spst
23017680Spst/*
23117680Spst * Print the FDDI MAC header
23217680Spst */
23317680Spststatic inline void
23417680Spstfddi_print(register const struct fddi_header *fddip, register u_int length,
23517680Spst	   register const u_char *fsrc, register const u_char *fdst)
23617680Spst{
23717680Spst	char *srcname, *dstname;
23817680Spst
23917680Spst	srcname = etheraddr_string(fsrc);
24017680Spst	dstname = etheraddr_string(fdst);
24117680Spst
24217680Spst	if (vflag)
24317680Spst		(void) printf("%02x %s %s %d: ",
24417680Spst		       fddip->fddi_fc,
24517680Spst		       srcname, dstname,
24617680Spst		       length);
24717680Spst	else if (qflag)
24817680Spst		printf("%s %s %d: ", srcname, dstname, length);
24917680Spst	else {
25017680Spst		(void) print_fddi_fc(fddip->fddi_fc);
25117680Spst		(void) printf("%s %s %d: ", srcname, dstname, length);
25217680Spst	}
25317680Spst}
25417680Spst
25517680Spststatic inline void
25617680Spstfddi_smt_print(const u_char *p, u_int length)
25717680Spst{
25817680Spst	printf("<SMT printer not yet implemented>");
25917680Spst}
26017680Spst
26117680Spst/*
26217680Spst * This is the top level routine of the printer.  'sp' is the points
26317680Spst * to the FDDI header of the packet, 'tvp' is the timestamp,
26417680Spst * 'length' is the length of the packet off the wire, and 'caplen'
26517680Spst * is the number of bytes actually captured.
26617680Spst */
26717680Spstvoid
26817680Spstfddi_if_print(u_char *pcap, const struct pcap_pkthdr *h,
26917680Spst	      register const u_char *p)
27017680Spst{
27117680Spst	u_int caplen = h->caplen;
27217680Spst	u_int length = h->len;
27317680Spst	const struct fddi_header *fddip = (struct fddi_header *)p;
27417680Spst	struct ether_header ehdr;
27556896Sfenner	u_short extracted_ethertype;
27617680Spst
27717680Spst	ts_print(&h->ts);
27817680Spst
27917680Spst	if (caplen < FDDI_HDRLEN) {
28017680Spst		printf("[|fddi]");
28117680Spst		goto out;
28217680Spst	}
28317680Spst	/*
28417680Spst	 * Get the FDDI addresses into a canonical form
28517680Spst	 */
28626183Sfenner	extract_fddi_addrs(fddip, (char *)ESRC(&ehdr), (char *)EDST(&ehdr));
28717680Spst	/*
28817680Spst	 * Some printers want to get back at the link level addresses,
28917680Spst	 * and/or check that they're not walking off the end of the packet.
29017680Spst	 * Rather than pass them all the way down, we set these globals.
29117680Spst	 */
29217680Spst	snapend = p + caplen;
29317680Spst	/*
29417680Spst	 * Actually, the only printer that uses packetp is print-bootp.c,
29517680Spst	 * and it assumes that packetp points to an Ethernet header.  The
29617680Spst	 * right thing to do is to fix print-bootp.c to know which link
29717680Spst	 * type is in use when it excavates. XXX
29817680Spst	 */
29917680Spst	packetp = (u_char *)&ehdr;
30017680Spst
30117680Spst	if (eflag)
30217680Spst		fddi_print(fddip, length, ESRC(&ehdr), EDST(&ehdr));
30317680Spst
30417680Spst	/* Skip over FDDI MAC header */
30517680Spst	length -= FDDI_HDRLEN;
30617680Spst	p += FDDI_HDRLEN;
30717680Spst	caplen -= FDDI_HDRLEN;
30817680Spst
30917680Spst	/* Frame Control field determines interpretation of packet */
31017680Spst	extracted_ethertype = 0;
31117680Spst	if ((fddip->fddi_fc & FDDIFC_CLFF) == FDDIFC_LLC_ASYNC) {
31217680Spst		/* Try to print the LLC-layer header & higher layers */
31317680Spst		if (llc_print(p, length, caplen, ESRC(&ehdr), EDST(&ehdr))
31417680Spst		    == 0) {
31517680Spst			/*
31617680Spst			 * Some kinds of LLC packet we cannot
31717680Spst			 * handle intelligently
31817680Spst			 */
31917680Spst			if (!eflag)
32017680Spst				fddi_print(fddip, length,
32117680Spst				    ESRC(&ehdr), EDST(&ehdr));
32217680Spst			if (extracted_ethertype) {
32317680Spst				printf("(LLC %s) ",
32417680Spst			etherproto_string(htons(extracted_ethertype)));
32517680Spst			}
32617680Spst			if (!xflag && !qflag)
32717680Spst				default_print(p, caplen);
32817680Spst		}
32917680Spst	} else if ((fddip->fddi_fc & FDDIFC_CLFF) == FDDIFC_SMT)
33017680Spst		fddi_smt_print(p, caplen);
33117680Spst	else {
33217680Spst		/* Some kinds of FDDI packet we cannot handle intelligently */
33317680Spst		if (!eflag)
33417680Spst			fddi_print(fddip, length, ESRC(&ehdr), EDST(&ehdr));
33517680Spst		if (!xflag && !qflag)
33617680Spst			default_print(p, caplen);
33717680Spst	}
33817680Spst	if (xflag)
33917680Spst		default_print(p, caplen);
34017680Spstout:
34117680Spst	putchar('\n');
34217680Spst}
343