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