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$ 2217680Spst */ 2317680Spst 2417680Spst#ifndef lint 25127675Sbmsstatic const char rcsid[] _U_ = 26190207Srpaulo "@(#) $Header: /tcpdump/master/tcpdump/print-fddi.c,v 1.66 2005-11-13 12:12:41 guy Exp $ (LBL)"; 2717680Spst#endif 2817680Spst 2956896Sfenner#ifdef HAVE_CONFIG_H 3056896Sfenner#include "config.h" 3156896Sfenner#endif 3256896Sfenner 33127675Sbms#include <tcpdump-stdinc.h> 3417680Spst 3517680Spst#include <pcap.h> 3617680Spst#include <stdio.h> 3717680Spst#include <string.h> 3817680Spst 3917680Spst#include "interface.h" 4017680Spst#include "addrtoname.h" 4117680Spst#include "ethertype.h" 4217680Spst 4375118Sfenner#include "ether.h" 4417680Spst#include "fddi.h" 4517680Spst 4617680Spst/* 4717680Spst * Some FDDI interfaces use bit-swapped addresses. 4817680Spst */ 4998527Sfenner#if defined(ultrix) || defined(__alpha) || defined(__bsdi) || defined(__NetBSD__) || defined(__linux__) 5017680Spstint fddi_bitswap = 0; 5117680Spst#else 5217680Spstint fddi_bitswap = 1; 5317680Spst#endif 5417680Spst 5517680Spst/* 5617680Spst * FDDI support for tcpdump, by Jeffrey Mogul [DECWRL], June 1992 5717680Spst * 5817680Spst * Based in part on code by Van Jacobson, which bears this note: 5917680Spst * 6017680Spst * NOTE: This is a very preliminary hack for FDDI support. 6117680Spst * There are all sorts of wired in constants & nothing (yet) 6217680Spst * to print SMT packets as anything other than hex dumps. 6317680Spst * Most of the necessary changes are waiting on my redoing 6417680Spst * the "header" that a kernel fddi driver supplies to bpf: I 6517680Spst * want it to look like one byte of 'direction' (0 or 1 6617680Spst * depending on whether the packet was inbound or outbound), 6717680Spst * two bytes of system/driver dependent data (anything an 6817680Spst * implementor thinks would be useful to filter on and/or 6917680Spst * save per-packet, then the real 21-byte FDDI header. 7017680Spst * Steve McCanne & I have also talked about adding the 7117680Spst * 'direction' byte to all bpf headers (e.g., in the two 7217680Spst * bytes of padding on an ethernet header). It's not clear 7317680Spst * we could do this in a backwards compatible way & we hate 7417680Spst * the idea of an incompatible bpf change. Discussions are 7517680Spst * proceeding. 7617680Spst * 7717680Spst * Also, to really support FDDI (and better support 802.2 7817680Spst * over ethernet) we really need to re-think the rather simple 7917680Spst * minded assumptions about fixed length & fixed format link 8017680Spst * level headers made in gencode.c. One day... 8117680Spst * 8217680Spst * - vj 8317680Spst */ 8417680Spst 8517680Spststatic u_char fddi_bit_swap[] = { 8617680Spst 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 8717680Spst 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, 8817680Spst 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 8917680Spst 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 9017680Spst 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 9117680Spst 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 9217680Spst 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 9317680Spst 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 9417680Spst 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 9517680Spst 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 9617680Spst 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 9717680Spst 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 9817680Spst 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 9917680Spst 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, 10017680Spst 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 10117680Spst 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 10217680Spst 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 10317680Spst 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 10417680Spst 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 10517680Spst 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 10617680Spst 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 10717680Spst 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 10817680Spst 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 10917680Spst 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 11017680Spst 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 11117680Spst 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 11217680Spst 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 11317680Spst 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 11417680Spst 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 11517680Spst 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 11617680Spst 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 11717680Spst 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, 11817680Spst}; 11917680Spst 12017680Spst/* 12117680Spst * Print FDDI frame-control bits 12217680Spst */ 12317680Spststatic inline void 12417680Spstprint_fddi_fc(u_char fc) 12517680Spst{ 12617680Spst switch (fc) { 12717680Spst 12817680Spst case FDDIFC_VOID: /* Void frame */ 12917680Spst printf("void "); 13017680Spst break; 13117680Spst 13217680Spst case FDDIFC_NRT: /* Nonrestricted token */ 13317680Spst printf("nrt "); 13417680Spst break; 13517680Spst 13617680Spst case FDDIFC_RT: /* Restricted token */ 13717680Spst printf("rt "); 13817680Spst break; 13917680Spst 14017680Spst case FDDIFC_SMT_INFO: /* SMT Info */ 14117680Spst printf("info "); 14217680Spst break; 14317680Spst 14417680Spst case FDDIFC_SMT_NSA: /* SMT Next station adrs */ 14517680Spst printf("nsa "); 14617680Spst break; 14717680Spst 14817680Spst case FDDIFC_MAC_BEACON: /* MAC Beacon frame */ 14917680Spst printf("beacon "); 15017680Spst break; 15117680Spst 15217680Spst case FDDIFC_MAC_CLAIM: /* MAC Claim frame */ 15317680Spst printf("claim "); 15417680Spst break; 15517680Spst 15617680Spst default: 15717680Spst switch (fc & FDDIFC_CLFF) { 15817680Spst 15917680Spst case FDDIFC_MAC: 16017680Spst printf("mac%1x ", fc & FDDIFC_ZZZZ); 16117680Spst break; 16217680Spst 16317680Spst case FDDIFC_SMT: 16417680Spst printf("smt%1x ", fc & FDDIFC_ZZZZ); 16517680Spst break; 16617680Spst 16717680Spst case FDDIFC_LLC_ASYNC: 16817680Spst printf("async%1x ", fc & FDDIFC_ZZZZ); 16917680Spst break; 17017680Spst 17117680Spst case FDDIFC_LLC_SYNC: 17217680Spst printf("sync%1x ", fc & FDDIFC_ZZZZ); 17317680Spst break; 17417680Spst 17517680Spst case FDDIFC_IMP_ASYNC: 17617680Spst printf("imp_async%1x ", fc & FDDIFC_ZZZZ); 17717680Spst break; 17817680Spst 17917680Spst case FDDIFC_IMP_SYNC: 18017680Spst printf("imp_sync%1x ", fc & FDDIFC_ZZZZ); 18117680Spst break; 18217680Spst 18317680Spst default: 18417680Spst printf("%02x ", fc); 18517680Spst break; 18617680Spst } 18717680Spst } 18817680Spst} 18917680Spst 19017680Spst/* Extract src, dst addresses */ 19117680Spststatic inline void 19217680Spstextract_fddi_addrs(const struct fddi_header *fddip, char *fsrc, char *fdst) 19317680Spst{ 19417680Spst register int i; 19517680Spst 19617680Spst if (fddi_bitswap) { 19717680Spst /* 19817680Spst * bit-swap the fddi addresses (isn't the IEEE standards 19917680Spst * process wonderful!) then convert them to names. 20017680Spst */ 20117680Spst for (i = 0; i < 6; ++i) 20217680Spst fdst[i] = fddi_bit_swap[fddip->fddi_dhost[i]]; 20317680Spst for (i = 0; i < 6; ++i) 20417680Spst fsrc[i] = fddi_bit_swap[fddip->fddi_shost[i]]; 20517680Spst } 20617680Spst else { 20798527Sfenner memcpy(fdst, (const char *)fddip->fddi_dhost, 6); 20898527Sfenner memcpy(fsrc, (const char *)fddip->fddi_shost, 6); 20917680Spst } 21017680Spst} 21117680Spst 21217680Spst/* 21317680Spst * Print the FDDI MAC header 21417680Spst */ 21517680Spststatic inline void 216127675Sbmsfddi_hdr_print(register const struct fddi_header *fddip, register u_int length, 21717680Spst register const u_char *fsrc, register const u_char *fdst) 21817680Spst{ 21998527Sfenner const char *srcname, *dstname; 22017680Spst 22117680Spst srcname = etheraddr_string(fsrc); 22217680Spst dstname = etheraddr_string(fdst); 22317680Spst 22417680Spst if (vflag) 22517680Spst (void) printf("%02x %s %s %d: ", 22617680Spst fddip->fddi_fc, 22717680Spst srcname, dstname, 22817680Spst length); 22917680Spst else if (qflag) 23017680Spst printf("%s %s %d: ", srcname, dstname, length); 23117680Spst else { 23217680Spst (void) print_fddi_fc(fddip->fddi_fc); 23317680Spst (void) printf("%s %s %d: ", srcname, dstname, length); 23417680Spst } 23517680Spst} 23617680Spst 23717680Spststatic inline void 238127675Sbmsfddi_smt_print(const u_char *p _U_, u_int length _U_) 23917680Spst{ 24017680Spst printf("<SMT printer not yet implemented>"); 24117680Spst} 24217680Spst 24317680Spstvoid 244127675Sbmsfddi_print(const u_char *p, u_int length, u_int caplen) 24517680Spst{ 24698527Sfenner const struct fddi_header *fddip = (const struct fddi_header *)p; 24717680Spst struct ether_header ehdr; 24856896Sfenner u_short extracted_ethertype; 24917680Spst 25017680Spst if (caplen < FDDI_HDRLEN) { 25117680Spst printf("[|fddi]"); 252127675Sbms return; 25317680Spst } 254127675Sbms 25517680Spst /* 25617680Spst * Get the FDDI addresses into a canonical form 25717680Spst */ 25826183Sfenner extract_fddi_addrs(fddip, (char *)ESRC(&ehdr), (char *)EDST(&ehdr)); 25917680Spst 26017680Spst if (eflag) 261127675Sbms fddi_hdr_print(fddip, length, ESRC(&ehdr), EDST(&ehdr)); 26217680Spst 26317680Spst /* Skip over FDDI MAC header */ 26417680Spst length -= FDDI_HDRLEN; 26517680Spst p += FDDI_HDRLEN; 26617680Spst caplen -= FDDI_HDRLEN; 26717680Spst 26817680Spst /* Frame Control field determines interpretation of packet */ 26917680Spst if ((fddip->fddi_fc & FDDIFC_CLFF) == FDDIFC_LLC_ASYNC) { 27017680Spst /* Try to print the LLC-layer header & higher layers */ 27175118Sfenner if (llc_print(p, length, caplen, ESRC(&ehdr), EDST(&ehdr), 27275118Sfenner &extracted_ethertype) == 0) { 27317680Spst /* 27417680Spst * Some kinds of LLC packet we cannot 27517680Spst * handle intelligently 27617680Spst */ 27717680Spst if (!eflag) 278127675Sbms fddi_hdr_print(fddip, length + FDDI_HDRLEN, 27917680Spst ESRC(&ehdr), EDST(&ehdr)); 28017680Spst if (extracted_ethertype) { 28117680Spst printf("(LLC %s) ", 28217680Spst etherproto_string(htons(extracted_ethertype))); 28317680Spst } 284162021Ssam if (!suppress_default_print) 28517680Spst default_print(p, caplen); 28617680Spst } 28717680Spst } else if ((fddip->fddi_fc & FDDIFC_CLFF) == FDDIFC_SMT) 28817680Spst fddi_smt_print(p, caplen); 28917680Spst else { 29017680Spst /* Some kinds of FDDI packet we cannot handle intelligently */ 29117680Spst if (!eflag) 292127675Sbms fddi_hdr_print(fddip, length + FDDI_HDRLEN, ESRC(&ehdr), 29375118Sfenner EDST(&ehdr)); 294162021Ssam if (!suppress_default_print) 29517680Spst default_print(p, caplen); 29617680Spst } 29717680Spst} 298127675Sbms 299127675Sbms/* 300127675Sbms * This is the top level routine of the printer. 'p' points 301127675Sbms * to the FDDI header of the packet, 'h->ts' is the timestamp, 302146778Ssam * 'h->len' is the length of the packet off the wire, and 'h->caplen' 303127675Sbms * is the number of bytes actually captured. 304127675Sbms */ 305127675Sbmsu_int 306127675Sbmsfddi_if_print(const struct pcap_pkthdr *h, register const u_char *p) 307127675Sbms{ 308127675Sbms fddi_print(p, h->len, h->caplen); 309127675Sbms 310127675Sbms return (FDDI_HDRLEN); 311127675Sbms} 312