1 /* 2 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 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 * From: NetBSD: print-arcnet.c,v 1.2 2000/04/24 13:02:28 itojun Exp 22 */ 23 #include <sys/cdefs.h> 24 #ifndef lint 25 #if 0 26 static const char rcsid[] _U_ = 27 "@(#) Header: /tcpdump/master/tcpdump/print-arcnet.c,v 1.20 2005-04-06 21:32:38 mcr Exp (LBL)"; 28 #else 29 __RCSID("$NetBSD: print-arcnet.c,v 1.4 2013/12/31 17:33:31 christos Exp $"); 30 #endif 31 #endif 32 33 #ifdef HAVE_CONFIG_H 34 #include "config.h" 35 #endif 36 37 #include <tcpdump-stdinc.h> 38 39 #include <stdio.h> 40 #include <pcap.h> 41 42 #include "interface.h" 43 #include "extract.h" 44 #include "arcnet.h" 45 46 static int arcnet_encap_print(u_char arctype, const u_char *p, 47 u_int length, u_int caplen); 48 49 static const struct tok arctypemap[] = { 50 { ARCTYPE_IP_OLD, "oldip" }, 51 { ARCTYPE_ARP_OLD, "oldarp" }, 52 { ARCTYPE_IP, "ip" }, 53 { ARCTYPE_ARP, "arp" }, 54 { ARCTYPE_REVARP, "rarp" }, 55 { ARCTYPE_ATALK, "atalk" }, 56 { ARCTYPE_BANIAN, "banyan" }, 57 { ARCTYPE_IPX, "ipx" }, 58 { ARCTYPE_INET6, "ipv6" }, 59 { ARCTYPE_DIAGNOSE, "diag" }, 60 { 0, 0 } 61 }; 62 63 static inline void 64 arcnet_print(const u_char *bp, u_int length, int phds, int flag, u_int seqid) 65 { 66 const struct arc_header *ap; 67 const char *arctypename; 68 69 70 ap = (const struct arc_header *)bp; 71 72 73 if (qflag) { 74 (void)printf("%02x %02x %d: ", 75 ap->arc_shost, 76 ap->arc_dhost, 77 length); 78 return; 79 } 80 81 arctypename = tok2str(arctypemap, "%02x", ap->arc_type); 82 83 if (!phds) { 84 (void)printf("%02x %02x %s %d: ", 85 ap->arc_shost, ap->arc_dhost, arctypename, 86 length); 87 return; 88 } 89 90 if (flag == 0) { 91 (void)printf("%02x %02x %s seqid %04x %d: ", 92 ap->arc_shost, ap->arc_dhost, arctypename, seqid, 93 length); 94 return; 95 } 96 97 if (flag & 1) 98 (void)printf("%02x %02x %s seqid %04x " 99 "(first of %d fragments) %d: ", 100 ap->arc_shost, ap->arc_dhost, arctypename, seqid, 101 (flag + 3) / 2, length); 102 else 103 (void)printf("%02x %02x %s seqid %04x " 104 "(fragment %d) %d: ", 105 ap->arc_shost, ap->arc_dhost, arctypename, seqid, 106 flag/2 + 1, length); 107 } 108 109 /* 110 * This is the top level routine of the printer. 'p' points 111 * to the ARCNET header of the packet, 'h->ts' is the timestamp, 112 * 'h->len' is the length of the packet off the wire, and 'h->caplen' 113 * is the number of bytes actually captured. 114 */ 115 u_int 116 arcnet_if_print(const struct pcap_pkthdr *h, const u_char *p) 117 { 118 u_int caplen = h->caplen; 119 u_int length = h->len; 120 const struct arc_header *ap; 121 122 int phds, flag = 0, archdrlen = 0; 123 u_int seqid = 0; 124 u_char arc_type; 125 126 if (caplen < ARC_HDRLEN) { 127 printf("[|arcnet]"); 128 return (caplen); 129 } 130 131 ap = (const struct arc_header *)p; 132 arc_type = ap->arc_type; 133 134 switch (arc_type) { 135 default: 136 phds = 1; 137 break; 138 case ARCTYPE_IP_OLD: 139 case ARCTYPE_ARP_OLD: 140 case ARCTYPE_DIAGNOSE: 141 phds = 0; 142 archdrlen = ARC_HDRLEN; 143 break; 144 } 145 146 if (phds) { 147 if (caplen < ARC_HDRNEWLEN) { 148 arcnet_print(p, length, 0, 0, 0); 149 printf("[|phds]"); 150 return (caplen); 151 } 152 153 if (ap->arc_flag == 0xff) { 154 if (caplen < ARC_HDRNEWLEN_EXC) { 155 arcnet_print(p, length, 0, 0, 0); 156 printf("[|phds extended]"); 157 return (caplen); 158 } 159 flag = ap->arc_flag2; 160 seqid = EXTRACT_16BITS(&ap->arc_seqid2); 161 archdrlen = ARC_HDRNEWLEN_EXC; 162 } else { 163 flag = ap->arc_flag; 164 seqid = EXTRACT_16BITS(&ap->arc_seqid); 165 archdrlen = ARC_HDRNEWLEN; 166 } 167 } 168 169 170 if (eflag) 171 arcnet_print(p, length, phds, flag, seqid); 172 173 /* 174 * Go past the ARCNET header. 175 */ 176 length -= archdrlen; 177 caplen -= archdrlen; 178 p += archdrlen; 179 180 if (phds && flag && (flag & 1) == 0) { 181 /* 182 * This is a middle fragment. 183 */ 184 return (archdrlen); 185 } 186 187 if (!arcnet_encap_print(arc_type, p, length, caplen)) 188 default_print(p, caplen); 189 190 return (archdrlen); 191 } 192 193 /* 194 * This is the top level routine of the printer. 'p' points 195 * to the ARCNET header of the packet, 'h->ts' is the timestamp, 196 * 'h->len' is the length of the packet off the wire, and 'h->caplen' 197 * is the number of bytes actually captured. It is quite similar 198 * to the non-Linux style printer except that Linux doesn't ever 199 * supply packets that look like exception frames, it always supplies 200 * reassembled packets rather than raw frames, and headers have an 201 * extra "offset" field between the src/dest and packet type. 202 */ 203 u_int 204 arcnet_linux_if_print(const struct pcap_pkthdr *h, const u_char *p) 205 { 206 u_int caplen = h->caplen; 207 u_int length = h->len; 208 const struct arc_linux_header *ap; 209 210 int archdrlen = 0; 211 u_char arc_type; 212 213 if (caplen < ARC_LINUX_HDRLEN) { 214 printf("[|arcnet]"); 215 return (caplen); 216 } 217 218 ap = (const struct arc_linux_header *)p; 219 arc_type = ap->arc_type; 220 221 switch (arc_type) { 222 default: 223 archdrlen = ARC_LINUX_HDRNEWLEN; 224 if (caplen < ARC_LINUX_HDRNEWLEN) { 225 printf("[|arcnet]"); 226 return (caplen); 227 } 228 break; 229 case ARCTYPE_IP_OLD: 230 case ARCTYPE_ARP_OLD: 231 case ARCTYPE_DIAGNOSE: 232 archdrlen = ARC_LINUX_HDRLEN; 233 break; 234 } 235 236 if (eflag) 237 arcnet_print(p, length, 0, 0, 0); 238 239 /* 240 * Go past the ARCNET header. 241 */ 242 length -= archdrlen; 243 caplen -= archdrlen; 244 p += archdrlen; 245 246 if (!arcnet_encap_print(arc_type, p, length, caplen)) 247 default_print(p, caplen); 248 249 return (archdrlen); 250 } 251 252 /* 253 * Prints the packet encapsulated in an ARCnet data field, 254 * given the ARCnet system code. 255 * 256 * Returns non-zero if it can do so, zero if the system code is unknown. 257 */ 258 259 260 static int 261 arcnet_encap_print(u_char arctype, const u_char *p, 262 u_int length, u_int caplen) 263 { 264 switch (arctype) { 265 266 case ARCTYPE_IP_OLD: 267 case ARCTYPE_IP: 268 ip_print(gndo, p, length); 269 return (1); 270 271 #ifdef INET6 272 case ARCTYPE_INET6: 273 ip6_print(gndo, p, length); 274 return (1); 275 #endif /*INET6*/ 276 277 case ARCTYPE_ARP_OLD: 278 case ARCTYPE_ARP: 279 case ARCTYPE_REVARP: 280 arp_print(gndo, p, length, caplen); 281 return (1); 282 283 case ARCTYPE_ATALK: /* XXX was this ever used? */ 284 if (vflag) 285 fputs("et1 ", stdout); 286 atalk_print(p, length); 287 return (1); 288 289 case ARCTYPE_IPX: 290 ipx_print(p, length); 291 return (1); 292 293 default: 294 return (0); 295 } 296 } 297 298 /* 299 * Local Variables: 300 * c-style: bsd 301 * End: 302 */ 303 304