1 /* 2 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that: (1) source code distributions 7 * retain the above copyright notice and this paragraph in its entirety, (2) 8 * distributions including binary code include the above copyright notice and 9 * this paragraph in its entirety in the documentation or other materials 10 * provided with the distribution, and (3) all advertising materials mentioning 11 * features or use of this software display the following acknowledgement: 12 * ``This product includes software developed by the University of California, 13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14 * the University nor the names of its contributors may be used to endorse 15 * or promote products derived from this software without specific prior 16 * written permission. 17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20 * 21 * Hacked version of print-ether.c Larry Lile <lile@stdio.com> 22 * 23 * Further tweaked to more closely resemble print-fddi.c 24 * Guy Harris <guy@alum.mit.edu> 25 * 26 * $FreeBSD$ 27 */ 28 29 #define NETDISSECT_REWORKED 30 #ifdef HAVE_CONFIG_H 31 #include "config.h" 32 #endif 33 34 #include <tcpdump-stdinc.h> 35 36 #include <string.h> 37 38 #include "interface.h" 39 #include "extract.h" 40 #include "addrtoname.h" 41 #include "ether.h" 42 43 /* 44 * Copyright (c) 1998, Larry Lile 45 * All rights reserved. 46 * 47 * Redistribution and use in source and binary forms, with or without 48 * modification, are permitted provided that the following conditions 49 * are met: 50 * 1. Redistributions of source code must retain the above copyright 51 * notice unmodified, this list of conditions, and the following 52 * disclaimer. 53 * 2. Redistributions in binary form must reproduce the above copyright 54 * notice, this list of conditions and the following disclaimer in the 55 * documentation and/or other materials provided with the distribution. 56 * 57 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 58 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 59 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 60 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 61 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 62 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 63 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 64 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 65 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 66 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 67 * SUCH DAMAGE. 68 * 69 */ 70 71 #define TOKEN_HDRLEN 14 72 #define TOKEN_RING_MAC_LEN 6 73 #define ROUTING_SEGMENT_MAX 16 74 #define IS_SOURCE_ROUTED(trp) ((trp)->token_shost[0] & 0x80) 75 #define FRAME_TYPE(trp) (((trp)->token_fc & 0xC0) >> 6) 76 #define TOKEN_FC_LLC 1 77 78 #define BROADCAST(trp) ((EXTRACT_16BITS(&(trp)->token_rcf) & 0xE000) >> 13) 79 #define RIF_LENGTH(trp) ((EXTRACT_16BITS(&(trp)->token_rcf) & 0x1f00) >> 8) 80 #define DIRECTION(trp) ((EXTRACT_16BITS(&(trp)->token_rcf) & 0x0080) >> 7) 81 #define LARGEST_FRAME(trp) ((EXTRACT_16BITS(&(trp)->token_rcf) & 0x0070) >> 4) 82 #define RING_NUMBER(trp, x) ((EXTRACT_16BITS(&(trp)->token_rseg[x]) & 0xfff0) >> 4) 83 #define BRIDGE_NUMBER(trp, x) ((EXTRACT_16BITS(&(trp)->token_rseg[x]) & 0x000f)) 84 #define SEGMENT_COUNT(trp) ((int)((RIF_LENGTH(trp) - 2) / 2)) 85 86 struct token_header { 87 uint8_t token_ac; 88 uint8_t token_fc; 89 uint8_t token_dhost[TOKEN_RING_MAC_LEN]; 90 uint8_t token_shost[TOKEN_RING_MAC_LEN]; 91 uint16_t token_rcf; 92 uint16_t token_rseg[ROUTING_SEGMENT_MAX]; 93 }; 94 95 static const char tstr[] = "[|token-ring]"; 96 97 /* Extract src, dst addresses */ 98 static inline void 99 extract_token_addrs(const struct token_header *trp, char *fsrc, char *fdst) 100 { 101 memcpy(fdst, (const char *)trp->token_dhost, 6); 102 memcpy(fsrc, (const char *)trp->token_shost, 6); 103 } 104 105 /* 106 * Print the TR MAC header 107 */ 108 static inline void 109 token_hdr_print(netdissect_options *ndo, 110 register const struct token_header *trp, register u_int length, 111 register const u_char *fsrc, register const u_char *fdst) 112 { 113 const char *srcname, *dstname; 114 115 srcname = etheraddr_string(ndo, fsrc); 116 dstname = etheraddr_string(ndo, fdst); 117 118 if (ndo->ndo_vflag) 119 ND_PRINT((ndo, "%02x %02x %s %s %d: ", 120 trp->token_ac, 121 trp->token_fc, 122 srcname, dstname, 123 length)); 124 else 125 ND_PRINT((ndo, "%s %s %d: ", srcname, dstname, length)); 126 } 127 128 static const char *broadcast_indicator[] = { 129 "Non-Broadcast", "Non-Broadcast", 130 "Non-Broadcast", "Non-Broadcast", 131 "All-routes", "All-routes", 132 "Single-route", "Single-route" 133 }; 134 135 static const char *direction[] = { 136 "Forward", "Backward" 137 }; 138 139 static const char *largest_frame[] = { 140 "516", 141 "1500", 142 "2052", 143 "4472", 144 "8144", 145 "11407", 146 "17800", 147 "??" 148 }; 149 150 u_int 151 token_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen) 152 { 153 const struct token_header *trp; 154 u_short extracted_ethertype; 155 struct ether_header ehdr; 156 u_int route_len = 0, hdr_len = TOKEN_HDRLEN; 157 int seg; 158 159 trp = (const struct token_header *)p; 160 161 if (caplen < TOKEN_HDRLEN) { 162 ND_PRINT((ndo, "%s", tstr)); 163 return hdr_len; 164 } 165 166 /* 167 * Get the TR addresses into a canonical form 168 */ 169 extract_token_addrs(trp, (char*)ESRC(&ehdr), (char*)EDST(&ehdr)); 170 171 /* Adjust for source routing information in the MAC header */ 172 if (IS_SOURCE_ROUTED(trp)) { 173 /* Clear source-routed bit */ 174 *ESRC(&ehdr) &= 0x7f; 175 176 if (ndo->ndo_eflag) 177 token_hdr_print(ndo, trp, length, ESRC(&ehdr), EDST(&ehdr)); 178 179 if (caplen < TOKEN_HDRLEN + 2) { 180 ND_PRINT((ndo, "%s", tstr)); 181 return hdr_len; 182 } 183 route_len = RIF_LENGTH(trp); 184 hdr_len += route_len; 185 if (caplen < hdr_len) { 186 ND_PRINT((ndo, "%s", tstr)); 187 return hdr_len; 188 } 189 if (ndo->ndo_vflag) { 190 ND_PRINT((ndo, "%s ", broadcast_indicator[BROADCAST(trp)])); 191 ND_PRINT((ndo, "%s", direction[DIRECTION(trp)])); 192 193 for (seg = 0; seg < SEGMENT_COUNT(trp); seg++) 194 ND_PRINT((ndo, " [%d:%d]", RING_NUMBER(trp, seg), 195 BRIDGE_NUMBER(trp, seg))); 196 } else { 197 ND_PRINT((ndo, "rt = %x", EXTRACT_16BITS(&trp->token_rcf))); 198 199 for (seg = 0; seg < SEGMENT_COUNT(trp); seg++) 200 ND_PRINT((ndo, ":%x", EXTRACT_16BITS(&trp->token_rseg[seg]))); 201 } 202 ND_PRINT((ndo, " (%s) ", largest_frame[LARGEST_FRAME(trp)])); 203 } else { 204 if (ndo->ndo_eflag) 205 token_hdr_print(ndo, trp, length, ESRC(&ehdr), EDST(&ehdr)); 206 } 207 208 /* Skip over token ring MAC header and routing information */ 209 length -= hdr_len; 210 p += hdr_len; 211 caplen -= hdr_len; 212 213 /* Frame Control field determines interpretation of packet */ 214 if (FRAME_TYPE(trp) == TOKEN_FC_LLC) { 215 /* Try to print the LLC-layer header & higher layers */ 216 if (llc_print(ndo, p, length, caplen, ESRC(&ehdr), EDST(&ehdr), 217 &extracted_ethertype) == 0) { 218 /* ether_type not known, print raw packet */ 219 if (!ndo->ndo_eflag) 220 token_hdr_print(ndo, trp, 221 length + TOKEN_HDRLEN + route_len, 222 ESRC(&ehdr), EDST(&ehdr)); 223 if (extracted_ethertype) { 224 ND_PRINT((ndo, "(LLC %s) ", 225 etherproto_string(htons(extracted_ethertype)))); 226 } 227 if (!ndo->ndo_suppress_default_print) 228 ND_DEFAULTPRINT(p, caplen); 229 } 230 } else { 231 /* Some kinds of TR packet we cannot handle intelligently */ 232 /* XXX - dissect MAC packets if frame type is 0 */ 233 if (!ndo->ndo_eflag) 234 token_hdr_print(ndo, trp, length + TOKEN_HDRLEN + route_len, 235 ESRC(&ehdr), EDST(&ehdr)); 236 if (!ndo->ndo_suppress_default_print) 237 ND_DEFAULTPRINT(p, caplen); 238 } 239 return (hdr_len); 240 } 241 242 /* 243 * This is the top level routine of the printer. 'p' points 244 * to the TR header of the packet, 'h->ts' is the timestamp, 245 * 'h->len' is the length of the packet off the wire, and 'h->caplen' 246 * is the number of bytes actually captured. 247 */ 248 u_int 249 token_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) 250 { 251 return (token_print(ndo, p, h->len, h->caplen)); 252 } 253