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: releng/11.0/contrib/tcpdump/print-fddi.c 276788 2015-01-07 19:55:18Z delphij $ 2217680Spst */ 2317680Spst 24276788Sdelphij#define NETDISSECT_REWORKED 2556896Sfenner#ifdef HAVE_CONFIG_H 2656896Sfenner#include "config.h" 2756896Sfenner#endif 2856896Sfenner 29127675Sbms#include <tcpdump-stdinc.h> 3017680Spst 3117680Spst#include <string.h> 3217680Spst 3317680Spst#include "interface.h" 3417680Spst#include "addrtoname.h" 3575118Sfenner#include "ether.h" 3617680Spst 3717680Spst/* 38276788Sdelphij * Based on Ultrix if_fddi.h 39276788Sdelphij */ 40276788Sdelphij 41276788Sdelphijstruct fddi_header { 42276788Sdelphij u_char fddi_fc; /* frame control */ 43276788Sdelphij u_char fddi_dhost[6]; 44276788Sdelphij u_char fddi_shost[6]; 45276788Sdelphij}; 46276788Sdelphij 47276788Sdelphij/* 48276788Sdelphij * Length of an FDDI header; note that some compilers may pad 49276788Sdelphij * "struct fddi_header" to a multiple of 4 bytes, for example, so 50276788Sdelphij * "sizeof (struct fddi_header)" may not give the right 51276788Sdelphij * answer. 52276788Sdelphij */ 53276788Sdelphij#define FDDI_HDRLEN 13 54276788Sdelphij 55276788Sdelphij/* Useful values for fddi_fc (frame control) field */ 56276788Sdelphij 57276788Sdelphij/* 58276788Sdelphij * FDDI Frame Control bits 59276788Sdelphij */ 60276788Sdelphij#define FDDIFC_C 0x80 /* Class bit */ 61276788Sdelphij#define FDDIFC_L 0x40 /* Address length bit */ 62276788Sdelphij#define FDDIFC_F 0x30 /* Frame format bits */ 63276788Sdelphij#define FDDIFC_Z 0x0f /* Control bits */ 64276788Sdelphij 65276788Sdelphij/* 66276788Sdelphij * FDDI Frame Control values. (48-bit addressing only). 67276788Sdelphij */ 68276788Sdelphij#define FDDIFC_VOID 0x40 /* Void frame */ 69276788Sdelphij#define FDDIFC_NRT 0x80 /* Nonrestricted token */ 70276788Sdelphij#define FDDIFC_RT 0xc0 /* Restricted token */ 71276788Sdelphij#define FDDIFC_SMT_INFO 0x41 /* SMT Info */ 72276788Sdelphij#define FDDIFC_SMT_NSA 0x4F /* SMT Next station adrs */ 73276788Sdelphij#define FDDIFC_MAC_BEACON 0xc2 /* MAC Beacon frame */ 74276788Sdelphij#define FDDIFC_MAC_CLAIM 0xc3 /* MAC Claim frame */ 75276788Sdelphij#define FDDIFC_LLC_ASYNC 0x50 /* Async. LLC frame */ 76276788Sdelphij#define FDDIFC_LLC_SYNC 0xd0 /* Sync. LLC frame */ 77276788Sdelphij#define FDDIFC_IMP_ASYNC 0x60 /* Implementor Async. */ 78276788Sdelphij#define FDDIFC_IMP_SYNC 0xe0 /* Implementor Synch. */ 79276788Sdelphij#define FDDIFC_SMT 0x40 /* SMT frame */ 80276788Sdelphij#define FDDIFC_MAC 0xc0 /* MAC frame */ 81276788Sdelphij 82276788Sdelphij#define FDDIFC_CLFF 0xF0 /* Class/Length/Format bits */ 83276788Sdelphij#define FDDIFC_ZZZZ 0x0F /* Control bits */ 84276788Sdelphij 85276788Sdelphij/* 8617680Spst * Some FDDI interfaces use bit-swapped addresses. 8717680Spst */ 8898527Sfenner#if defined(ultrix) || defined(__alpha) || defined(__bsdi) || defined(__NetBSD__) || defined(__linux__) 8917680Spstint fddi_bitswap = 0; 9017680Spst#else 9117680Spstint fddi_bitswap = 1; 9217680Spst#endif 9317680Spst 9417680Spst/* 9517680Spst * FDDI support for tcpdump, by Jeffrey Mogul [DECWRL], June 1992 9617680Spst * 9717680Spst * Based in part on code by Van Jacobson, which bears this note: 9817680Spst * 9917680Spst * NOTE: This is a very preliminary hack for FDDI support. 10017680Spst * There are all sorts of wired in constants & nothing (yet) 10117680Spst * to print SMT packets as anything other than hex dumps. 10217680Spst * Most of the necessary changes are waiting on my redoing 10317680Spst * the "header" that a kernel fddi driver supplies to bpf: I 10417680Spst * want it to look like one byte of 'direction' (0 or 1 10517680Spst * depending on whether the packet was inbound or outbound), 10617680Spst * two bytes of system/driver dependent data (anything an 10717680Spst * implementor thinks would be useful to filter on and/or 10817680Spst * save per-packet, then the real 21-byte FDDI header. 10917680Spst * Steve McCanne & I have also talked about adding the 11017680Spst * 'direction' byte to all bpf headers (e.g., in the two 11117680Spst * bytes of padding on an ethernet header). It's not clear 11217680Spst * we could do this in a backwards compatible way & we hate 11317680Spst * the idea of an incompatible bpf change. Discussions are 11417680Spst * proceeding. 11517680Spst * 11617680Spst * Also, to really support FDDI (and better support 802.2 11717680Spst * over ethernet) we really need to re-think the rather simple 11817680Spst * minded assumptions about fixed length & fixed format link 11917680Spst * level headers made in gencode.c. One day... 12017680Spst * 12117680Spst * - vj 12217680Spst */ 12317680Spst 124276788Sdelphijstatic const u_char fddi_bit_swap[] = { 12517680Spst 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 12617680Spst 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, 12717680Spst 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 12817680Spst 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 12917680Spst 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 13017680Spst 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 13117680Spst 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 13217680Spst 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 13317680Spst 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 13417680Spst 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 13517680Spst 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 13617680Spst 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 13717680Spst 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 13817680Spst 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, 13917680Spst 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 14017680Spst 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 14117680Spst 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 14217680Spst 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 14317680Spst 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 14417680Spst 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 14517680Spst 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 14617680Spst 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 14717680Spst 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 14817680Spst 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 14917680Spst 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 15017680Spst 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 15117680Spst 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 15217680Spst 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 15317680Spst 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 15417680Spst 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 15517680Spst 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 15617680Spst 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, 15717680Spst}; 15817680Spst 15917680Spst/* 16017680Spst * Print FDDI frame-control bits 16117680Spst */ 16217680Spststatic inline void 163276788Sdelphijprint_fddi_fc(netdissect_options *ndo, u_char fc) 16417680Spst{ 16517680Spst switch (fc) { 16617680Spst 16717680Spst case FDDIFC_VOID: /* Void frame */ 168276788Sdelphij ND_PRINT((ndo, "void ")); 16917680Spst break; 17017680Spst 17117680Spst case FDDIFC_NRT: /* Nonrestricted token */ 172276788Sdelphij ND_PRINT((ndo, "nrt ")); 17317680Spst break; 17417680Spst 17517680Spst case FDDIFC_RT: /* Restricted token */ 176276788Sdelphij ND_PRINT((ndo, "rt ")); 17717680Spst break; 17817680Spst 17917680Spst case FDDIFC_SMT_INFO: /* SMT Info */ 180276788Sdelphij ND_PRINT((ndo, "info ")); 18117680Spst break; 18217680Spst 18317680Spst case FDDIFC_SMT_NSA: /* SMT Next station adrs */ 184276788Sdelphij ND_PRINT((ndo, "nsa ")); 18517680Spst break; 18617680Spst 18717680Spst case FDDIFC_MAC_BEACON: /* MAC Beacon frame */ 188276788Sdelphij ND_PRINT((ndo, "beacon ")); 18917680Spst break; 19017680Spst 19117680Spst case FDDIFC_MAC_CLAIM: /* MAC Claim frame */ 192276788Sdelphij ND_PRINT((ndo, "claim ")); 19317680Spst break; 19417680Spst 19517680Spst default: 19617680Spst switch (fc & FDDIFC_CLFF) { 19717680Spst 19817680Spst case FDDIFC_MAC: 199276788Sdelphij ND_PRINT((ndo, "mac%1x ", fc & FDDIFC_ZZZZ)); 20017680Spst break; 20117680Spst 20217680Spst case FDDIFC_SMT: 203276788Sdelphij ND_PRINT((ndo, "smt%1x ", fc & FDDIFC_ZZZZ)); 20417680Spst break; 20517680Spst 20617680Spst case FDDIFC_LLC_ASYNC: 207276788Sdelphij ND_PRINT((ndo, "async%1x ", fc & FDDIFC_ZZZZ)); 20817680Spst break; 20917680Spst 21017680Spst case FDDIFC_LLC_SYNC: 211276788Sdelphij ND_PRINT((ndo, "sync%1x ", fc & FDDIFC_ZZZZ)); 21217680Spst break; 21317680Spst 21417680Spst case FDDIFC_IMP_ASYNC: 215276788Sdelphij ND_PRINT((ndo, "imp_async%1x ", fc & FDDIFC_ZZZZ)); 21617680Spst break; 21717680Spst 21817680Spst case FDDIFC_IMP_SYNC: 219276788Sdelphij ND_PRINT((ndo, "imp_sync%1x ", fc & FDDIFC_ZZZZ)); 22017680Spst break; 22117680Spst 22217680Spst default: 223276788Sdelphij ND_PRINT((ndo, "%02x ", fc)); 22417680Spst break; 22517680Spst } 22617680Spst } 22717680Spst} 22817680Spst 22917680Spst/* Extract src, dst addresses */ 23017680Spststatic inline void 23117680Spstextract_fddi_addrs(const struct fddi_header *fddip, char *fsrc, char *fdst) 23217680Spst{ 23317680Spst register int i; 23417680Spst 23517680Spst if (fddi_bitswap) { 23617680Spst /* 23717680Spst * bit-swap the fddi addresses (isn't the IEEE standards 23817680Spst * process wonderful!) then convert them to names. 23917680Spst */ 24017680Spst for (i = 0; i < 6; ++i) 24117680Spst fdst[i] = fddi_bit_swap[fddip->fddi_dhost[i]]; 24217680Spst for (i = 0; i < 6; ++i) 24317680Spst fsrc[i] = fddi_bit_swap[fddip->fddi_shost[i]]; 24417680Spst } 24517680Spst else { 24698527Sfenner memcpy(fdst, (const char *)fddip->fddi_dhost, 6); 24798527Sfenner memcpy(fsrc, (const char *)fddip->fddi_shost, 6); 24817680Spst } 24917680Spst} 25017680Spst 25117680Spst/* 25217680Spst * Print the FDDI MAC header 25317680Spst */ 25417680Spststatic inline void 255276788Sdelphijfddi_hdr_print(netdissect_options *ndo, 256276788Sdelphij register const struct fddi_header *fddip, register u_int length, 257276788Sdelphij register const u_char *fsrc, register const u_char *fdst) 25817680Spst{ 25998527Sfenner const char *srcname, *dstname; 26017680Spst 261276788Sdelphij srcname = etheraddr_string(ndo, fsrc); 262276788Sdelphij dstname = etheraddr_string(ndo, fdst); 26317680Spst 264276788Sdelphij if (ndo->ndo_vflag) 265276788Sdelphij ND_PRINT((ndo, "%02x %s %s %d: ", 26617680Spst fddip->fddi_fc, 26717680Spst srcname, dstname, 268276788Sdelphij length)); 269276788Sdelphij else if (ndo->ndo_qflag) 270276788Sdelphij ND_PRINT((ndo, "%s %s %d: ", srcname, dstname, length)); 27117680Spst else { 272276788Sdelphij print_fddi_fc(ndo, fddip->fddi_fc); 273276788Sdelphij ND_PRINT((ndo, "%s %s %d: ", srcname, dstname, length)); 27417680Spst } 27517680Spst} 27617680Spst 27717680Spststatic inline void 278276788Sdelphijfddi_smt_print(netdissect_options *ndo, const u_char *p _U_, u_int length _U_) 27917680Spst{ 280276788Sdelphij ND_PRINT((ndo, "<SMT printer not yet implemented>")); 28117680Spst} 28217680Spst 28317680Spstvoid 284276788Sdelphijfddi_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen) 28517680Spst{ 28698527Sfenner const struct fddi_header *fddip = (const struct fddi_header *)p; 28717680Spst struct ether_header ehdr; 28856896Sfenner u_short extracted_ethertype; 28917680Spst 29017680Spst if (caplen < FDDI_HDRLEN) { 291276788Sdelphij ND_PRINT((ndo, "[|fddi]")); 292127675Sbms return; 29317680Spst } 294127675Sbms 29517680Spst /* 29617680Spst * Get the FDDI addresses into a canonical form 29717680Spst */ 29826183Sfenner extract_fddi_addrs(fddip, (char *)ESRC(&ehdr), (char *)EDST(&ehdr)); 29917680Spst 300276788Sdelphij if (ndo->ndo_eflag) 301276788Sdelphij fddi_hdr_print(ndo, fddip, length, ESRC(&ehdr), EDST(&ehdr)); 30217680Spst 30317680Spst /* Skip over FDDI MAC header */ 30417680Spst length -= FDDI_HDRLEN; 30517680Spst p += FDDI_HDRLEN; 30617680Spst caplen -= FDDI_HDRLEN; 30717680Spst 30817680Spst /* Frame Control field determines interpretation of packet */ 30917680Spst if ((fddip->fddi_fc & FDDIFC_CLFF) == FDDIFC_LLC_ASYNC) { 31017680Spst /* Try to print the LLC-layer header & higher layers */ 311276788Sdelphij if (llc_print(ndo, p, length, caplen, ESRC(&ehdr), EDST(&ehdr), 31275118Sfenner &extracted_ethertype) == 0) { 31317680Spst /* 31417680Spst * Some kinds of LLC packet we cannot 31517680Spst * handle intelligently 31617680Spst */ 317276788Sdelphij if (!ndo->ndo_eflag) 318276788Sdelphij fddi_hdr_print(ndo, fddip, length + FDDI_HDRLEN, 31917680Spst ESRC(&ehdr), EDST(&ehdr)); 32017680Spst if (extracted_ethertype) { 321276788Sdelphij ND_PRINT((ndo, "(LLC %s) ", 322276788Sdelphij etherproto_string(htons(extracted_ethertype)))); 32317680Spst } 324276788Sdelphij if (!ndo->ndo_suppress_default_print) 325276788Sdelphij ND_DEFAULTPRINT(p, caplen); 32617680Spst } 32717680Spst } else if ((fddip->fddi_fc & FDDIFC_CLFF) == FDDIFC_SMT) 328276788Sdelphij fddi_smt_print(ndo, p, caplen); 32917680Spst else { 33017680Spst /* Some kinds of FDDI packet we cannot handle intelligently */ 331276788Sdelphij if (!ndo->ndo_eflag) 332276788Sdelphij fddi_hdr_print(ndo, fddip, length + FDDI_HDRLEN, ESRC(&ehdr), 33375118Sfenner EDST(&ehdr)); 334276788Sdelphij if (!ndo->ndo_suppress_default_print) 335276788Sdelphij ND_DEFAULTPRINT(p, caplen); 33617680Spst } 33717680Spst} 338127675Sbms 339127675Sbms/* 340127675Sbms * This is the top level routine of the printer. 'p' points 341127675Sbms * to the FDDI header of the packet, 'h->ts' is the timestamp, 342146778Ssam * 'h->len' is the length of the packet off the wire, and 'h->caplen' 343127675Sbms * is the number of bytes actually captured. 344127675Sbms */ 345127675Sbmsu_int 346276788Sdelphijfddi_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, register const u_char *p) 347127675Sbms{ 348276788Sdelphij fddi_print(ndo, p, h->len, h->caplen); 349127675Sbms 350127675Sbms return (FDDI_HDRLEN); 351127675Sbms} 352