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