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