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