print-fddi.c revision 146778
1327952Sdim/* 2286425Sdim * Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997 3353358Sdim * The Regents of the University of California. All rights reserved. 4353358Sdim * 5353358Sdim * Redistribution and use in source and binary forms, with or without 6286425Sdim * modification, are permitted provided that: (1) source code distributions 7286425Sdim * retain the above copyright notice and this paragraph in its entirety, (2) 8286425Sdim * distributions including binary code include the above copyright notice and 9314564Sdim * this paragraph in its entirety in the documentation or other materials 10314564Sdim * provided with the distribution, and (3) all advertising materials mentioning 11314564Sdim * features or use of this software display the following acknowledgement: 12314564Sdim * ``This product includes software developed by the University of California, 13314564Sdim * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14286425Sdim * the University nor the names of its contributors may be used to endorse 15286425Sdim * or promote products derived from this software without specific prior 16327952Sdim * written permission. 17286425Sdim * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18321369Sdim * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19314564Sdim * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20314564Sdim * 21314564Sdim * $FreeBSD: head/contrib/tcpdump/print-fddi.c 146778 2005-05-29 19:09:28Z sam $ 22314564Sdim */ 23286425Sdim 24286425Sdim#ifndef lint 25286425Sdimstatic const char rcsid[] _U_ = 26314564Sdim "@(#) $Header: /tcpdump/master/tcpdump/print-fddi.c,v 1.64 2004/03/17 23:24:37 guy Exp $ (LBL)"; 27286425Sdim#endif 28314564Sdim 29286425Sdim#ifdef HAVE_CONFIG_H 30327952Sdim#include "config.h" 31314564Sdim#endif 32360784Sdim 33309124Sdim#include <tcpdump-stdinc.h> 34286425Sdim 35286425Sdim#include <pcap.h> 36314564Sdim#include <stdio.h> 37321369Sdim#include <string.h> 38314564Sdim 39314564Sdim#include "interface.h" 40314564Sdim#include "addrtoname.h" 41314564Sdim#include "ethertype.h" 42314564Sdim 43314564Sdim#include "ether.h" 44286425Sdim#include "fddi.h" 45286425Sdim 46321369Sdim/* 47321369Sdim * Some FDDI interfaces use bit-swapped addresses. 48286425Sdim */ 49286425Sdim#if defined(ultrix) || defined(__alpha) || defined(__bsdi) || defined(__NetBSD__) || defined(__linux__) 50286425Sdimint fddi_bitswap = 0; 51286425Sdim#else 52286425Sdimint fddi_bitswap = 1; 53286425Sdim#endif 54286425Sdim 55286425Sdim/* 56286425Sdim * FDDI support for tcpdump, by Jeffrey Mogul [DECWRL], June 1992 57286425Sdim * 58341825Sdim * Based in part on code by Van Jacobson, which bears this note: 59341825Sdim * 60341825Sdim * NOTE: This is a very preliminary hack for FDDI support. 61341825Sdim * There are all sorts of wired in constants & nothing (yet) 62341825Sdim * to print SMT packets as anything other than hex dumps. 63341825Sdim * Most of the necessary changes are waiting on my redoing 64286425Sdim * the "header" that a kernel fddi driver supplies to bpf: I 65286425Sdim * want it to look like one byte of 'direction' (0 or 1 66286425Sdim * depending on whether the packet was inbound or outbound), 67286425Sdim * two bytes of system/driver dependent data (anything an 68286425Sdim * implementor thinks would be useful to filter on and/or 69286425Sdim * save per-packet, then the real 21-byte FDDI header. 70286425Sdim * Steve McCanne & I have also talked about adding the 71286425Sdim * 'direction' byte to all bpf headers (e.g., in the two 72286425Sdim * bytes of padding on an ethernet header). It's not clear 73286425Sdim * we could do this in a backwards compatible way & we hate 74286425Sdim * the idea of an incompatible bpf change. Discussions are 75286425Sdim * proceeding. 76286425Sdim * 77286425Sdim * Also, to really support FDDI (and better support 802.2 78286425Sdim * over ethernet) we really need to re-think the rather simple 79314564Sdim * minded assumptions about fixed length & fixed format link 80314564Sdim * level headers made in gencode.c. One day... 81314564Sdim * 82286425Sdim * - vj 83314564Sdim */ 84286425Sdim 85314564Sdimstatic u_char fddi_bit_swap[] = { 86286425Sdim 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 87286425Sdim 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, 88286425Sdim 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 89314564Sdim 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 90286425Sdim 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 91286425Sdim 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 92286425Sdim 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 93296417Sdim 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 94286425Sdim 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 95341825Sdim 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 96360784Sdim 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 97360784Sdim 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 98360784Sdim 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 99360784Sdim 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, 100286425Sdim 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 101286425Sdim 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 102286425Sdim 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 103286425Sdim 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 104286425Sdim 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 105286425Sdim 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 106286425Sdim 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 107286425Sdim 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 108286425Sdim 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 109286425Sdim 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 110286425Sdim 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 111286425Sdim 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 112286425Sdim 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 113286425Sdim 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 114286425Sdim 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 115286425Sdim 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 116286425Sdim 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 117286425Sdim 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, 118286425Sdim}; 119286425Sdim 120286425Sdim/* 121286425Sdim * Print FDDI frame-control bits 122286425Sdim */ 123286425Sdimstatic inline void 124286425Sdimprint_fddi_fc(u_char fc) 125286425Sdim{ 126286425Sdim switch (fc) { 127286425Sdim 128286425Sdim case FDDIFC_VOID: /* Void frame */ 129286425Sdim printf("void "); 130286425Sdim break; 131286425Sdim 132286425Sdim case FDDIFC_NRT: /* Nonrestricted token */ 133286425Sdim printf("nrt "); 134286425Sdim break; 135286425Sdim 136286425Sdim case FDDIFC_RT: /* Restricted token */ 137286425Sdim printf("rt "); 138286425Sdim break; 139286425Sdim 140286425Sdim case FDDIFC_SMT_INFO: /* SMT Info */ 141286425Sdim printf("info "); 142286425Sdim break; 143286425Sdim 144286425Sdim case FDDIFC_SMT_NSA: /* SMT Next station adrs */ 145286425Sdim printf("nsa "); 146286425Sdim break; 147286425Sdim 148286425Sdim case FDDIFC_MAC_BEACON: /* MAC Beacon frame */ 149286425Sdim printf("beacon "); 150286425Sdim break; 151286425Sdim 152286425Sdim case FDDIFC_MAC_CLAIM: /* MAC Claim frame */ 153286425Sdim printf("claim "); 154286425Sdim break; 155286425Sdim 156286425Sdim default: 157286425Sdim switch (fc & FDDIFC_CLFF) { 158286425Sdim 159286425Sdim case FDDIFC_MAC: 160286425Sdim printf("mac%1x ", fc & FDDIFC_ZZZZ); 161286425Sdim break; 162286425Sdim 163286425Sdim case FDDIFC_SMT: 164286425Sdim printf("smt%1x ", fc & FDDIFC_ZZZZ); 165286425Sdim break; 166286425Sdim 167286425Sdim case FDDIFC_LLC_ASYNC: 168286425Sdim printf("async%1x ", fc & FDDIFC_ZZZZ); 169314564Sdim break; 170286425Sdim 171360784Sdim case FDDIFC_LLC_SYNC: 172286425Sdim printf("sync%1x ", fc & FDDIFC_ZZZZ); 173314564Sdim break; 174286425Sdim 175360784Sdim case FDDIFC_IMP_ASYNC: 176286425Sdim printf("imp_async%1x ", fc & FDDIFC_ZZZZ); 177286425Sdim break; 178286425Sdim 179286425Sdim case FDDIFC_IMP_SYNC: 180286425Sdim printf("imp_sync%1x ", fc & FDDIFC_ZZZZ); 181286425Sdim break; 182314564Sdim 183286425Sdim default: 184286425Sdim printf("%02x ", fc); 185314564Sdim break; 186286425Sdim } 187286425Sdim } 188286425Sdim} 189286425Sdim 190286425Sdim/* Extract src, dst addresses */ 191286425Sdimstatic inline void 192286425Sdimextract_fddi_addrs(const struct fddi_header *fddip, char *fsrc, char *fdst) 193286425Sdim{ 194327952Sdim register int i; 195286425Sdim 196286425Sdim if (fddi_bitswap) { 197286425Sdim /* 198286425Sdim * bit-swap the fddi addresses (isn't the IEEE standards 199286425Sdim * process wonderful!) then convert them to names. 200286425Sdim */ 201286425Sdim for (i = 0; i < 6; ++i) 202314564Sdim fdst[i] = fddi_bit_swap[fddip->fddi_dhost[i]]; 203314564Sdim for (i = 0; i < 6; ++i) 204286425Sdim fsrc[i] = fddi_bit_swap[fddip->fddi_shost[i]]; 205327952Sdim } 206286425Sdim else { 207286425Sdim memcpy(fdst, (const char *)fddip->fddi_dhost, 6); 208286425Sdim memcpy(fsrc, (const char *)fddip->fddi_shost, 6); 209286425Sdim } 210286425Sdim} 211286425Sdim 212286425Sdim/* 213286425Sdim * Print the FDDI MAC header 214314564Sdim */ 215314564Sdimstatic inline void 216286425Sdimfddi_hdr_print(register const struct fddi_header *fddip, register u_int length, 217286425Sdim register const u_char *fsrc, register const u_char *fdst) 218286425Sdim{ 219286425Sdim const char *srcname, *dstname; 220286425Sdim 221314564Sdim srcname = etheraddr_string(fsrc); 222286425Sdim dstname = etheraddr_string(fdst); 223286425Sdim 224286425Sdim if (vflag) 225286425Sdim (void) printf("%02x %s %s %d: ", 226286425Sdim fddip->fddi_fc, 227286425Sdim srcname, dstname, 228286425Sdim length); 229286425Sdim else if (qflag) 230286425Sdim printf("%s %s %d: ", srcname, dstname, length); 231286425Sdim else { 232286425Sdim (void) print_fddi_fc(fddip->fddi_fc); 233286425Sdim (void) printf("%s %s %d: ", srcname, dstname, length); 234286425Sdim } 235286425Sdim} 236286425Sdim 237314564Sdimstatic inline void 238286425Sdimfddi_smt_print(const u_char *p _U_, u_int length _U_) 239286425Sdim{ 240314564Sdim printf("<SMT printer not yet implemented>"); 241286425Sdim} 242286425Sdim 243286425Sdimvoid 244314564Sdimfddi_print(const u_char *p, u_int length, u_int caplen) 245286425Sdim{ 246286425Sdim const struct fddi_header *fddip = (const struct fddi_header *)p; 247286425Sdim struct ether_header ehdr; 248286425Sdim u_short extracted_ethertype; 249286425Sdim 250286425Sdim if (caplen < FDDI_HDRLEN) { 251286425Sdim printf("[|fddi]"); 252286425Sdim return; 253286425Sdim } 254286425Sdim 255286425Sdim /* 256286425Sdim * Get the FDDI addresses into a canonical form 257286425Sdim */ 258286425Sdim extract_fddi_addrs(fddip, (char *)ESRC(&ehdr), (char *)EDST(&ehdr)); 259286425Sdim 260286425Sdim if (eflag) 261286425Sdim fddi_hdr_print(fddip, length, ESRC(&ehdr), EDST(&ehdr)); 262286425Sdim 263286425Sdim /* Skip over FDDI MAC header */ 264286425Sdim length -= FDDI_HDRLEN; 265286425Sdim p += FDDI_HDRLEN; 266314564Sdim caplen -= FDDI_HDRLEN; 267286425Sdim 268286425Sdim /* Frame Control field determines interpretation of packet */ 269286425Sdim extracted_ethertype = 0; 270286425Sdim if ((fddip->fddi_fc & FDDIFC_CLFF) == FDDIFC_LLC_ASYNC) { 271286425Sdim /* Try to print the LLC-layer header & higher layers */ 272286425Sdim if (llc_print(p, length, caplen, ESRC(&ehdr), EDST(&ehdr), 273314564Sdim &extracted_ethertype) == 0) { 274286425Sdim /* 275360784Sdim * Some kinds of LLC packet we cannot 276286425Sdim * handle intelligently 277286425Sdim */ 278314564Sdim if (!eflag) 279286425Sdim fddi_hdr_print(fddip, length + FDDI_HDRLEN, 280314564Sdim ESRC(&ehdr), EDST(&ehdr)); 281286425Sdim if (extracted_ethertype) { 282286425Sdim printf("(LLC %s) ", 283286425Sdim etherproto_string(htons(extracted_ethertype))); 284286425Sdim } 285286425Sdim if (!xflag && !qflag) 286286425Sdim default_print(p, caplen); 287286425Sdim } 288327952Sdim } else if ((fddip->fddi_fc & FDDIFC_CLFF) == FDDIFC_SMT) 289327952Sdim fddi_smt_print(p, caplen); 290286425Sdim else { 291286425Sdim /* Some kinds of FDDI packet we cannot handle intelligently */ 292286425Sdim if (!eflag) 293286425Sdim fddi_hdr_print(fddip, length + FDDI_HDRLEN, ESRC(&ehdr), 294286425Sdim EDST(&ehdr)); 295286425Sdim if (!xflag && !qflag) 296286425Sdim default_print(p, caplen); 297286425Sdim } 298314564Sdim} 299286425Sdim 300314564Sdim/* 301286425Sdim * This is the top level routine of the printer. 'p' points 302286425Sdim * to the FDDI header of the packet, 'h->ts' is the timestamp, 303286425Sdim * 'h->len' is the length of the packet off the wire, and 'h->caplen' 304286425Sdim * is the number of bytes actually captured. 305286425Sdim */ 306286425Sdimu_int 307286425Sdimfddi_if_print(const struct pcap_pkthdr *h, register const u_char *p) 308286425Sdim{ 309286425Sdim fddi_print(p, h->len, h->caplen); 310286425Sdim 311286425Sdim return (FDDI_HDRLEN); 312286425Sdim} 313286425Sdim