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[] = 25 "@(#) $Header: /tcpdump/master/tcpdump/print-arcnet.c,v 1.6.4.1 2002/06/01 23:51:11 guy Exp $ (LBL)"; 26 #endif 27 28 #ifdef HAVE_CONFIG_H 29 #include "config.h" 30 #endif 31 32 #include <sys/param.h> 33 #include <sys/time.h> 34 #include <sys/socket.h> 35 36 #include <netinet/in.h> 37 38 #include <stdio.h> 39 #include <pcap.h> 40 41 #include "interface.h" 42 #include "arcnet.h" 43 44 int arcnet_encap_print(u_char arctype, const u_char *p, 45 u_int length, u_int caplen); 46 47 struct tok arctypemap[] = { 48 { ARCTYPE_IP_OLD, "oldip" }, 49 { ARCTYPE_ARP_OLD, "oldarp" }, 50 { ARCTYPE_IP, "ip" }, 51 { ARCTYPE_ARP, "arp" }, 52 { ARCTYPE_REVARP, "rarp" }, 53 { ARCTYPE_ATALK, "atalk" }, 54 { ARCTYPE_BANIAN, "banyan" }, 55 { ARCTYPE_IPX, "ipx" }, 56 { ARCTYPE_INET6, "ipv6" }, 57 { ARCTYPE_DIAGNOSE, "diag" }, 58 { 0, 0 } 59 }; 60 61 static inline void 62 arcnet_print(const u_char *bp, u_int length, int phds, int flag, u_int seqid) 63 { 64 const struct arc_header *ap; 65 const char *arctypename; 66 67 68 ap = (const struct arc_header *)bp; 69 70 71 if (qflag) { 72 (void)printf("%02x %02x %d: ", 73 ap->arc_shost, 74 ap->arc_dhost, 75 length); 76 return; 77 } 78 79 arctypename = tok2str(arctypemap, "%02x", ap->arc_type); 80 81 if (!phds) { 82 (void)printf("%02x %02x %s %d: ", 83 ap->arc_shost, ap->arc_dhost, arctypename, 84 length); 85 return; 86 } 87 88 if (flag == 0) { 89 (void)printf("%02x %02x %s seqid %04x %d: ", 90 ap->arc_shost, ap->arc_dhost, arctypename, seqid, 91 length); 92 return; 93 } 94 95 if (flag & 1) 96 (void)printf("%02x %02x %s seqid %04x " 97 "(first of %d fragments) %d: ", 98 ap->arc_shost, ap->arc_dhost, arctypename, seqid, 99 (flag + 3) / 2, length); 100 else 101 (void)printf("%02x %02x %s seqid %04x " 102 "(fragment %d) %d: ", 103 ap->arc_shost, ap->arc_dhost, arctypename, seqid, 104 flag/2 + 1, length); 105 } 106 107 /* 108 * This is the top level routine of the printer. 'p' is the points 109 * to the ether header of the packet, 'tvp' is the timestamp, 110 * 'length' is the length of the packet off the wire, and 'caplen' 111 * is the number of bytes actually captured. 112 */ 113 void 114 arcnet_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p) 115 { 116 u_int caplen = h->caplen; 117 u_int length = h->len; 118 const struct arc_header *ap; 119 120 int phds, flag = 0, archdrlen = 0; 121 u_int seqid = 0; 122 u_char arc_type; 123 124 ++infodelay; 125 ts_print(&h->ts); 126 127 if (caplen < ARC_HDRLEN) { 128 printf("[|arcnet]"); 129 goto out; 130 } 131 132 ap = (const struct arc_header *)p; 133 arc_type = ap->arc_type; 134 135 switch (arc_type) { 136 default: 137 phds = 1; 138 break; 139 case ARCTYPE_IP_OLD: 140 case ARCTYPE_ARP_OLD: 141 case ARCTYPE_DIAGNOSE: 142 phds = 0; 143 archdrlen = ARC_HDRLEN; 144 break; 145 } 146 147 if (phds) { 148 if (caplen < ARC_HDRNEWLEN) { 149 arcnet_print(p, length, 0, 0, 0); 150 printf("[|phds]"); 151 goto out; 152 } 153 154 if (ap->arc_flag == 0xff) { 155 if (caplen < ARC_HDRNEWLEN_EXC) { 156 arcnet_print(p, length, 0, 0, 0); 157 printf("[|phds extended]"); 158 goto out; 159 } 160 flag = ap->arc_flag2; 161 seqid = ap->arc_seqid2; 162 archdrlen = ARC_HDRNEWLEN_EXC; 163 } else { 164 flag = ap->arc_flag; 165 seqid = ap->arc_seqid; 166 archdrlen = ARC_HDRNEWLEN; 167 } 168 } 169 170 171 if (eflag) 172 arcnet_print(p, length, phds, flag, seqid); 173 174 /* 175 * Some printers want to get back at the ethernet addresses, 176 * and/or check that they're not walking off the end of the packet. 177 * Rather than pass them all the way down, we set these globals. 178 */ 179 packetp = p; 180 snapend = p + caplen; 181 182 length -= archdrlen; 183 caplen -= archdrlen; 184 p += archdrlen; 185 186 if (phds && flag && (flag & 1) == 0) 187 goto out2; 188 189 if (!arcnet_encap_print(arc_type, p, length, caplen)) { 190 default_print(p, caplen); 191 goto out; 192 } 193 194 out2: 195 if (xflag) 196 default_print(p, caplen); 197 198 out: 199 putchar('\n'); 200 --infodelay; 201 if (infoprint) 202 info(0); 203 } 204 205 /* 206 * Prints the packet encapsulated in an ARCnet data field, 207 * given the ARCnet system code. 208 * 209 * Returns non-zero if it can do so, zero if the system code is unknown. 210 */ 211 212 213 int 214 arcnet_encap_print(u_char arctype, const u_char *p, 215 u_int length, u_int caplen) 216 { 217 switch (arctype) { 218 219 case ARCTYPE_IP_OLD: 220 case ARCTYPE_IP: 221 ip_print(p, length); 222 return (1); 223 224 #ifdef INET6 225 case ARCTYPE_INET6: 226 ip6_print(p, length); 227 return (1); 228 #endif /*INET6*/ 229 230 case ARCTYPE_ARP_OLD: 231 case ARCTYPE_ARP: 232 case ARCTYPE_REVARP: 233 arp_print(p, length, caplen); 234 return (1); 235 236 case ARCTYPE_ATALK: /* XXX was this ever used? */ 237 if (vflag) 238 fputs("et1 ", stdout); 239 atalk_print(p, length); 240 return (1); 241 242 default: 243 return (0); 244 } 245 } 246