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