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> 2544165Sjulian */ 2644165Sjulian 27313537Sglebius/* \summary: Token Ring printer */ 28313537Sglebius 2998527Sfenner#ifdef HAVE_CONFIG_H 3098527Sfenner#include "config.h" 3198527Sfenner#endif 3298527Sfenner 33313537Sglebius#include <netdissect-stdinc.h> 3444165Sjulian 3598527Sfenner#include <string.h> 3644165Sjulian 37313537Sglebius#include "netdissect.h" 38214478Srpaulo#include "extract.h" 3944165Sjulian#include "addrtoname.h" 4098527Sfenner#include "ether.h" 4144165Sjulian 42276788Sdelphij/* 43276788Sdelphij * Copyright (c) 1998, Larry Lile 44276788Sdelphij * All rights reserved. 45276788Sdelphij * 46276788Sdelphij * Redistribution and use in source and binary forms, with or without 47276788Sdelphij * modification, are permitted provided that the following conditions 48276788Sdelphij * are met: 49276788Sdelphij * 1. Redistributions of source code must retain the above copyright 50276788Sdelphij * notice unmodified, this list of conditions, and the following 51276788Sdelphij * disclaimer. 52276788Sdelphij * 2. Redistributions in binary form must reproduce the above copyright 53276788Sdelphij * notice, this list of conditions and the following disclaimer in the 54276788Sdelphij * documentation and/or other materials provided with the distribution. 55276788Sdelphij * 56276788Sdelphij * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 57276788Sdelphij * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 58276788Sdelphij * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 59276788Sdelphij * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 60276788Sdelphij * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 61276788Sdelphij * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 62276788Sdelphij * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 63276788Sdelphij * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 64276788Sdelphij * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 65276788Sdelphij * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 66276788Sdelphij * SUCH DAMAGE. 67276788Sdelphij * 68276788Sdelphij */ 69276788Sdelphij 70276788Sdelphij#define TOKEN_HDRLEN 14 71276788Sdelphij#define TOKEN_RING_MAC_LEN 6 72276788Sdelphij#define ROUTING_SEGMENT_MAX 16 73276788Sdelphij#define IS_SOURCE_ROUTED(trp) ((trp)->token_shost[0] & 0x80) 74276788Sdelphij#define FRAME_TYPE(trp) (((trp)->token_fc & 0xC0) >> 6) 75276788Sdelphij#define TOKEN_FC_LLC 1 76276788Sdelphij 77276788Sdelphij#define BROADCAST(trp) ((EXTRACT_16BITS(&(trp)->token_rcf) & 0xE000) >> 13) 78276788Sdelphij#define RIF_LENGTH(trp) ((EXTRACT_16BITS(&(trp)->token_rcf) & 0x1f00) >> 8) 79276788Sdelphij#define DIRECTION(trp) ((EXTRACT_16BITS(&(trp)->token_rcf) & 0x0080) >> 7) 80276788Sdelphij#define LARGEST_FRAME(trp) ((EXTRACT_16BITS(&(trp)->token_rcf) & 0x0070) >> 4) 81276788Sdelphij#define RING_NUMBER(trp, x) ((EXTRACT_16BITS(&(trp)->token_rseg[x]) & 0xfff0) >> 4) 82276788Sdelphij#define BRIDGE_NUMBER(trp, x) ((EXTRACT_16BITS(&(trp)->token_rseg[x]) & 0x000f)) 83276788Sdelphij#define SEGMENT_COUNT(trp) ((int)((RIF_LENGTH(trp) - 2) / 2)) 84276788Sdelphij 85276788Sdelphijstruct token_header { 86276788Sdelphij uint8_t token_ac; 87276788Sdelphij uint8_t token_fc; 88276788Sdelphij uint8_t token_dhost[TOKEN_RING_MAC_LEN]; 89276788Sdelphij uint8_t token_shost[TOKEN_RING_MAC_LEN]; 90276788Sdelphij uint16_t token_rcf; 91276788Sdelphij uint16_t token_rseg[ROUTING_SEGMENT_MAX]; 92276788Sdelphij}; 93276788Sdelphij 94276788Sdelphijstatic const char tstr[] = "[|token-ring]"; 95276788Sdelphij 9698527Sfenner/* Extract src, dst addresses */ 9744165Sjulianstatic inline void 9898527Sfennerextract_token_addrs(const struct token_header *trp, char *fsrc, char *fdst) 9944165Sjulian{ 10098527Sfenner memcpy(fdst, (const char *)trp->token_dhost, 6); 10198527Sfenner memcpy(fsrc, (const char *)trp->token_shost, 6); 10298527Sfenner} 10344165Sjulian 10498527Sfenner/* 10598527Sfenner * Print the TR MAC header 10698527Sfenner */ 10798527Sfennerstatic inline void 108276788Sdelphijtoken_hdr_print(netdissect_options *ndo, 109276788Sdelphij register const struct token_header *trp, register u_int length, 110276788Sdelphij register const u_char *fsrc, register const u_char *fdst) 11198527Sfenner{ 11298527Sfenner const char *srcname, *dstname; 11350514Slile 114276788Sdelphij srcname = etheraddr_string(ndo, fsrc); 115276788Sdelphij dstname = etheraddr_string(ndo, fdst); 11644165Sjulian 117313537Sglebius if (!ndo->ndo_qflag) 118313537Sglebius ND_PRINT((ndo, "%02x %02x ", 11998527Sfenner trp->token_ac, 120313537Sglebius trp->token_fc)); 121313537Sglebius ND_PRINT((ndo, "%s > %s, length %u: ", 122313537Sglebius srcname, dstname, 123313537Sglebius length)); 12444165Sjulian} 12544165Sjulian 12698527Sfennerstatic const char *broadcast_indicator[] = { 12798527Sfenner "Non-Broadcast", "Non-Broadcast", 12898527Sfenner "Non-Broadcast", "Non-Broadcast", 12998527Sfenner "All-routes", "All-routes", 13098527Sfenner "Single-route", "Single-route" 13198527Sfenner}; 13298527Sfenner 13398527Sfennerstatic const char *direction[] = { 13498527Sfenner "Forward", "Backward" 13598527Sfenner}; 13698527Sfenner 13798527Sfennerstatic const char *largest_frame[] = { 13898527Sfenner "516", 13998527Sfenner "1500", 14098527Sfenner "2052", 14198527Sfenner "4472", 14298527Sfenner "8144", 14398527Sfenner "11407", 14498527Sfenner "17800", 14598527Sfenner "??" 14698527Sfenner}; 14798527Sfenner 148127675Sbmsu_int 149276788Sdelphijtoken_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen) 15044165Sjulian{ 15198527Sfenner const struct token_header *trp; 152313537Sglebius int llc_hdrlen; 15398527Sfenner struct ether_header ehdr; 154313537Sglebius struct lladdr_info src, dst; 155127675Sbms u_int route_len = 0, hdr_len = TOKEN_HDRLEN; 156127675Sbms int seg; 15744165Sjulian 15898527Sfenner trp = (const struct token_header *)p; 15944165Sjulian 16098527Sfenner if (caplen < TOKEN_HDRLEN) { 161276788Sdelphij ND_PRINT((ndo, "%s", tstr)); 162127675Sbms return hdr_len; 16344165Sjulian } 164127675Sbms 16544165Sjulian /* 16698527Sfenner * Get the TR addresses into a canonical form 16798527Sfenner */ 16898527Sfenner extract_token_addrs(trp, (char*)ESRC(&ehdr), (char*)EDST(&ehdr)); 16944165Sjulian 17098527Sfenner /* Adjust for source routing information in the MAC header */ 17198527Sfenner if (IS_SOURCE_ROUTED(trp)) { 17298527Sfenner /* Clear source-routed bit */ 17398527Sfenner *ESRC(&ehdr) &= 0x7f; 17450514Slile 175276788Sdelphij if (ndo->ndo_eflag) 176276788Sdelphij token_hdr_print(ndo, trp, length, ESRC(&ehdr), EDST(&ehdr)); 17750514Slile 178214478Srpaulo if (caplen < TOKEN_HDRLEN + 2) { 179276788Sdelphij ND_PRINT((ndo, "%s", tstr)); 180214478Srpaulo return hdr_len; 181214478Srpaulo } 18298527Sfenner route_len = RIF_LENGTH(trp); 183214478Srpaulo hdr_len += route_len; 184214478Srpaulo if (caplen < hdr_len) { 185276788Sdelphij ND_PRINT((ndo, "%s", tstr)); 186214478Srpaulo return hdr_len; 187214478Srpaulo } 188276788Sdelphij if (ndo->ndo_vflag) { 189276788Sdelphij ND_PRINT((ndo, "%s ", broadcast_indicator[BROADCAST(trp)])); 190276788Sdelphij ND_PRINT((ndo, "%s", direction[DIRECTION(trp)])); 191127675Sbms 19298527Sfenner for (seg = 0; seg < SEGMENT_COUNT(trp); seg++) 193276788Sdelphij ND_PRINT((ndo, " [%d:%d]", RING_NUMBER(trp, seg), 194276788Sdelphij BRIDGE_NUMBER(trp, seg))); 19598527Sfenner } else { 196276788Sdelphij ND_PRINT((ndo, "rt = %x", EXTRACT_16BITS(&trp->token_rcf))); 197127675Sbms 19898527Sfenner for (seg = 0; seg < SEGMENT_COUNT(trp); seg++) 199276788Sdelphij ND_PRINT((ndo, ":%x", EXTRACT_16BITS(&trp->token_rseg[seg]))); 20098527Sfenner } 201276788Sdelphij ND_PRINT((ndo, " (%s) ", largest_frame[LARGEST_FRAME(trp)])); 20298527Sfenner } else { 203276788Sdelphij if (ndo->ndo_eflag) 204276788Sdelphij token_hdr_print(ndo, trp, length, ESRC(&ehdr), EDST(&ehdr)); 20598527Sfenner } 20644165Sjulian 207313537Sglebius src.addr = ESRC(&ehdr); 208313537Sglebius src.addr_string = etheraddr_string; 209313537Sglebius dst.addr = EDST(&ehdr); 210313537Sglebius dst.addr_string = etheraddr_string; 211313537Sglebius 21298527Sfenner /* Skip over token ring MAC header and routing information */ 213127675Sbms length -= hdr_len; 214127675Sbms p += hdr_len; 215127675Sbms caplen -= hdr_len; 21644165Sjulian 21798527Sfenner /* Frame Control field determines interpretation of packet */ 21898527Sfenner if (FRAME_TYPE(trp) == TOKEN_FC_LLC) { 21998527Sfenner /* Try to print the LLC-layer header & higher layers */ 220313537Sglebius llc_hdrlen = llc_print(ndo, p, length, caplen, &src, &dst); 221313537Sglebius if (llc_hdrlen < 0) { 222313537Sglebius /* packet type not known, print raw packet */ 223276788Sdelphij if (!ndo->ndo_suppress_default_print) 224276788Sdelphij ND_DEFAULTPRINT(p, caplen); 225313537Sglebius llc_hdrlen = -llc_hdrlen; 22698527Sfenner } 227313537Sglebius hdr_len += llc_hdrlen; 22898527Sfenner } else { 22998527Sfenner /* Some kinds of TR packet we cannot handle intelligently */ 23098527Sfenner /* XXX - dissect MAC packets if frame type is 0 */ 231276788Sdelphij if (!ndo->ndo_eflag) 232276788Sdelphij token_hdr_print(ndo, trp, length + TOKEN_HDRLEN + route_len, 23398527Sfenner ESRC(&ehdr), EDST(&ehdr)); 234276788Sdelphij if (!ndo->ndo_suppress_default_print) 235276788Sdelphij ND_DEFAULTPRINT(p, caplen); 23644165Sjulian } 237127675Sbms return (hdr_len); 23844165Sjulian} 239127675Sbms 240127675Sbms/* 241127675Sbms * This is the top level routine of the printer. 'p' points 242127675Sbms * to the TR header of the packet, 'h->ts' is the timestamp, 243146778Ssam * 'h->len' is the length of the packet off the wire, and 'h->caplen' 244127675Sbms * is the number of bytes actually captured. 245127675Sbms */ 246127675Sbmsu_int 247276788Sdelphijtoken_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) 248127675Sbms{ 249276788Sdelphij return (token_print(ndo, p, h->len, h->caplen)); 250127675Sbms} 251