144165Sjulian/* 244165Sjulian * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996 344165Sjulian * The Regents of the University of California. All rights reserved. 444165Sjulian * 544165Sjulian * Redistribution and use in source and binary forms, with or without 644165Sjulian * modification, are permitted provided that: (1) source code distributions 744165Sjulian * retain the above copyright notice and this paragraph in its entirety, (2) 844165Sjulian * distributions including binary code include the above copyright notice and 944165Sjulian * this paragraph in its entirety in the documentation or other materials 1044165Sjulian * provided with the distribution, and (3) all advertising materials mentioning 1144165Sjulian * features or use of this software display the following acknowledgement: 1244165Sjulian * ``This product includes software developed by the University of California, 1344165Sjulian * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1444165Sjulian * the University nor the names of its contributors may be used to endorse 1544165Sjulian * or promote products derived from this software without specific prior 1644165Sjulian * written permission. 1744165Sjulian * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1844165Sjulian * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 1944165Sjulian * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2044165Sjulian * 2144165Sjulian * Hacked version of print-ether.c Larry Lile <lile@stdio.com> 2256896Sfenner * 2398527Sfenner * Further tweaked to more closely resemble print-fddi.c 2498527Sfenner * Guy Harris <guy@alum.mit.edu> 2598527Sfenner * 2656896Sfenner * $FreeBSD: releng/11.0/contrib/tcpdump/print-token.c 276788 2015-01-07 19:55:18Z delphij $ 2744165Sjulian */ 2844165Sjulian 29276788Sdelphij#define NETDISSECT_REWORKED 3098527Sfenner#ifdef HAVE_CONFIG_H 3198527Sfenner#include "config.h" 3298527Sfenner#endif 3398527Sfenner 34127675Sbms#include <tcpdump-stdinc.h> 3544165Sjulian 3698527Sfenner#include <string.h> 3744165Sjulian 3844165Sjulian#include "interface.h" 39214478Srpaulo#include "extract.h" 4044165Sjulian#include "addrtoname.h" 4198527Sfenner#include "ether.h" 4244165Sjulian 43276788Sdelphij/* 44276788Sdelphij * Copyright (c) 1998, Larry Lile 45276788Sdelphij * All rights reserved. 46276788Sdelphij * 47276788Sdelphij * Redistribution and use in source and binary forms, with or without 48276788Sdelphij * modification, are permitted provided that the following conditions 49276788Sdelphij * are met: 50276788Sdelphij * 1. Redistributions of source code must retain the above copyright 51276788Sdelphij * notice unmodified, this list of conditions, and the following 52276788Sdelphij * disclaimer. 53276788Sdelphij * 2. Redistributions in binary form must reproduce the above copyright 54276788Sdelphij * notice, this list of conditions and the following disclaimer in the 55276788Sdelphij * documentation and/or other materials provided with the distribution. 56276788Sdelphij * 57276788Sdelphij * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 58276788Sdelphij * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 59276788Sdelphij * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 60276788Sdelphij * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 61276788Sdelphij * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 62276788Sdelphij * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 63276788Sdelphij * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 64276788Sdelphij * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 65276788Sdelphij * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 66276788Sdelphij * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 67276788Sdelphij * SUCH DAMAGE. 68276788Sdelphij * 69276788Sdelphij */ 70276788Sdelphij 71276788Sdelphij#define TOKEN_HDRLEN 14 72276788Sdelphij#define TOKEN_RING_MAC_LEN 6 73276788Sdelphij#define ROUTING_SEGMENT_MAX 16 74276788Sdelphij#define IS_SOURCE_ROUTED(trp) ((trp)->token_shost[0] & 0x80) 75276788Sdelphij#define FRAME_TYPE(trp) (((trp)->token_fc & 0xC0) >> 6) 76276788Sdelphij#define TOKEN_FC_LLC 1 77276788Sdelphij 78276788Sdelphij#define BROADCAST(trp) ((EXTRACT_16BITS(&(trp)->token_rcf) & 0xE000) >> 13) 79276788Sdelphij#define RIF_LENGTH(trp) ((EXTRACT_16BITS(&(trp)->token_rcf) & 0x1f00) >> 8) 80276788Sdelphij#define DIRECTION(trp) ((EXTRACT_16BITS(&(trp)->token_rcf) & 0x0080) >> 7) 81276788Sdelphij#define LARGEST_FRAME(trp) ((EXTRACT_16BITS(&(trp)->token_rcf) & 0x0070) >> 4) 82276788Sdelphij#define RING_NUMBER(trp, x) ((EXTRACT_16BITS(&(trp)->token_rseg[x]) & 0xfff0) >> 4) 83276788Sdelphij#define BRIDGE_NUMBER(trp, x) ((EXTRACT_16BITS(&(trp)->token_rseg[x]) & 0x000f)) 84276788Sdelphij#define SEGMENT_COUNT(trp) ((int)((RIF_LENGTH(trp) - 2) / 2)) 85276788Sdelphij 86276788Sdelphijstruct token_header { 87276788Sdelphij uint8_t token_ac; 88276788Sdelphij uint8_t token_fc; 89276788Sdelphij uint8_t token_dhost[TOKEN_RING_MAC_LEN]; 90276788Sdelphij uint8_t token_shost[TOKEN_RING_MAC_LEN]; 91276788Sdelphij uint16_t token_rcf; 92276788Sdelphij uint16_t token_rseg[ROUTING_SEGMENT_MAX]; 93276788Sdelphij}; 94276788Sdelphij 95276788Sdelphijstatic const char tstr[] = "[|token-ring]"; 96276788Sdelphij 9798527Sfenner/* Extract src, dst addresses */ 9844165Sjulianstatic inline void 9998527Sfennerextract_token_addrs(const struct token_header *trp, char *fsrc, char *fdst) 10044165Sjulian{ 10198527Sfenner memcpy(fdst, (const char *)trp->token_dhost, 6); 10298527Sfenner memcpy(fsrc, (const char *)trp->token_shost, 6); 10398527Sfenner} 10444165Sjulian 10598527Sfenner/* 10698527Sfenner * Print the TR MAC header 10798527Sfenner */ 10898527Sfennerstatic inline void 109276788Sdelphijtoken_hdr_print(netdissect_options *ndo, 110276788Sdelphij register const struct token_header *trp, register u_int length, 111276788Sdelphij register const u_char *fsrc, register const u_char *fdst) 11298527Sfenner{ 11398527Sfenner const char *srcname, *dstname; 11450514Slile 115276788Sdelphij srcname = etheraddr_string(ndo, fsrc); 116276788Sdelphij dstname = etheraddr_string(ndo, fdst); 11744165Sjulian 118276788Sdelphij if (ndo->ndo_vflag) 119276788Sdelphij ND_PRINT((ndo, "%02x %02x %s %s %d: ", 12098527Sfenner trp->token_ac, 12198527Sfenner trp->token_fc, 12298527Sfenner srcname, dstname, 123276788Sdelphij length)); 12444165Sjulian else 125276788Sdelphij ND_PRINT((ndo, "%s %s %d: ", srcname, dstname, length)); 12644165Sjulian} 12744165Sjulian 12898527Sfennerstatic const char *broadcast_indicator[] = { 12998527Sfenner "Non-Broadcast", "Non-Broadcast", 13098527Sfenner "Non-Broadcast", "Non-Broadcast", 13198527Sfenner "All-routes", "All-routes", 13298527Sfenner "Single-route", "Single-route" 13398527Sfenner}; 13498527Sfenner 13598527Sfennerstatic const char *direction[] = { 13698527Sfenner "Forward", "Backward" 13798527Sfenner}; 13898527Sfenner 13998527Sfennerstatic const char *largest_frame[] = { 14098527Sfenner "516", 14198527Sfenner "1500", 14298527Sfenner "2052", 14398527Sfenner "4472", 14498527Sfenner "8144", 14598527Sfenner "11407", 14698527Sfenner "17800", 14798527Sfenner "??" 14898527Sfenner}; 14998527Sfenner 150127675Sbmsu_int 151276788Sdelphijtoken_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen) 15244165Sjulian{ 15398527Sfenner const struct token_header *trp; 15456896Sfenner u_short extracted_ethertype; 15598527Sfenner struct ether_header ehdr; 156127675Sbms u_int route_len = 0, hdr_len = TOKEN_HDRLEN; 157127675Sbms int seg; 15844165Sjulian 15998527Sfenner trp = (const struct token_header *)p; 16044165Sjulian 16198527Sfenner if (caplen < TOKEN_HDRLEN) { 162276788Sdelphij ND_PRINT((ndo, "%s", tstr)); 163127675Sbms return hdr_len; 16444165Sjulian } 165127675Sbms 16644165Sjulian /* 16798527Sfenner * Get the TR addresses into a canonical form 16898527Sfenner */ 16998527Sfenner extract_token_addrs(trp, (char*)ESRC(&ehdr), (char*)EDST(&ehdr)); 17044165Sjulian 17198527Sfenner /* Adjust for source routing information in the MAC header */ 17298527Sfenner if (IS_SOURCE_ROUTED(trp)) { 17398527Sfenner /* Clear source-routed bit */ 17498527Sfenner *ESRC(&ehdr) &= 0x7f; 17550514Slile 176276788Sdelphij if (ndo->ndo_eflag) 177276788Sdelphij token_hdr_print(ndo, trp, length, ESRC(&ehdr), EDST(&ehdr)); 17850514Slile 179214478Srpaulo if (caplen < TOKEN_HDRLEN + 2) { 180276788Sdelphij ND_PRINT((ndo, "%s", tstr)); 181214478Srpaulo return hdr_len; 182214478Srpaulo } 18398527Sfenner route_len = RIF_LENGTH(trp); 184214478Srpaulo hdr_len += route_len; 185214478Srpaulo if (caplen < hdr_len) { 186276788Sdelphij ND_PRINT((ndo, "%s", tstr)); 187214478Srpaulo return hdr_len; 188214478Srpaulo } 189276788Sdelphij if (ndo->ndo_vflag) { 190276788Sdelphij ND_PRINT((ndo, "%s ", broadcast_indicator[BROADCAST(trp)])); 191276788Sdelphij ND_PRINT((ndo, "%s", direction[DIRECTION(trp)])); 192127675Sbms 19398527Sfenner for (seg = 0; seg < SEGMENT_COUNT(trp); seg++) 194276788Sdelphij ND_PRINT((ndo, " [%d:%d]", RING_NUMBER(trp, seg), 195276788Sdelphij BRIDGE_NUMBER(trp, seg))); 19698527Sfenner } else { 197276788Sdelphij ND_PRINT((ndo, "rt = %x", EXTRACT_16BITS(&trp->token_rcf))); 198127675Sbms 19998527Sfenner for (seg = 0; seg < SEGMENT_COUNT(trp); seg++) 200276788Sdelphij ND_PRINT((ndo, ":%x", EXTRACT_16BITS(&trp->token_rseg[seg]))); 20198527Sfenner } 202276788Sdelphij ND_PRINT((ndo, " (%s) ", largest_frame[LARGEST_FRAME(trp)])); 20398527Sfenner } else { 204276788Sdelphij if (ndo->ndo_eflag) 205276788Sdelphij token_hdr_print(ndo, trp, length, ESRC(&ehdr), EDST(&ehdr)); 20698527Sfenner } 20744165Sjulian 20898527Sfenner /* Skip over token ring MAC header and routing information */ 209127675Sbms length -= hdr_len; 210127675Sbms p += hdr_len; 211127675Sbms caplen -= hdr_len; 21244165Sjulian 21398527Sfenner /* Frame Control field determines interpretation of packet */ 21498527Sfenner if (FRAME_TYPE(trp) == TOKEN_FC_LLC) { 21598527Sfenner /* Try to print the LLC-layer header & higher layers */ 216276788Sdelphij if (llc_print(ndo, p, length, caplen, ESRC(&ehdr), EDST(&ehdr), 21798527Sfenner &extracted_ethertype) == 0) { 21898527Sfenner /* ether_type not known, print raw packet */ 219276788Sdelphij if (!ndo->ndo_eflag) 220276788Sdelphij token_hdr_print(ndo, trp, 22198527Sfenner length + TOKEN_HDRLEN + route_len, 22298527Sfenner ESRC(&ehdr), EDST(&ehdr)); 22398527Sfenner if (extracted_ethertype) { 224276788Sdelphij ND_PRINT((ndo, "(LLC %s) ", 225276788Sdelphij etherproto_string(htons(extracted_ethertype)))); 22698527Sfenner } 227276788Sdelphij if (!ndo->ndo_suppress_default_print) 228276788Sdelphij ND_DEFAULTPRINT(p, caplen); 22998527Sfenner } 23098527Sfenner } else { 23198527Sfenner /* Some kinds of TR packet we cannot handle intelligently */ 23298527Sfenner /* XXX - dissect MAC packets if frame type is 0 */ 233276788Sdelphij if (!ndo->ndo_eflag) 234276788Sdelphij token_hdr_print(ndo, trp, length + TOKEN_HDRLEN + route_len, 23598527Sfenner ESRC(&ehdr), EDST(&ehdr)); 236276788Sdelphij if (!ndo->ndo_suppress_default_print) 237276788Sdelphij ND_DEFAULTPRINT(p, caplen); 23844165Sjulian } 239127675Sbms return (hdr_len); 24044165Sjulian} 241127675Sbms 242127675Sbms/* 243127675Sbms * This is the top level routine of the printer. 'p' points 244127675Sbms * to the TR header of the packet, 'h->ts' is the timestamp, 245146778Ssam * 'h->len' is the length of the packet off the wire, and 'h->caplen' 246127675Sbms * is the number of bytes actually captured. 247127675Sbms */ 248127675Sbmsu_int 249276788Sdelphijtoken_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) 250127675Sbms{ 251276788Sdelphij return (token_print(ndo, p, h->len, h->caplen)); 252127675Sbms} 253