]> The Tcpdump Group git mirrors - tcpdump/blob - print-arcnet.c
Move the contents of arcnet.h to print-arcnet.c.
[tcpdump] / print-arcnet.c
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 "extract.h"
39
40 /*
41 * from: NetBSD: if_arc.h,v 1.13 1999/11/19 20:41:19 thorpej Exp
42 */
43
44 /*
45 * Structure of a 2.5MB/s Arcnet header on the BSDs,
46 * as given to interface code.
47 */
48 struct arc_header {
49 u_int8_t arc_shost;
50 u_int8_t arc_dhost;
51 u_int8_t arc_type;
52 /*
53 * only present for newstyle encoding with LL fragmentation.
54 * Don't use sizeof(anything), use ARC_HDR{,NEW}LEN instead.
55 */
56 u_int8_t arc_flag;
57 u_int16_t arc_seqid;
58
59 /*
60 * only present in exception packets (arc_flag == 0xff)
61 */
62 u_int8_t arc_type2; /* same as arc_type */
63 u_int8_t arc_flag2; /* real flag value */
64 u_int16_t arc_seqid2; /* real seqid value */
65 };
66
67 #define ARC_HDRLEN 3
68 #define ARC_HDRNEWLEN 6
69 #define ARC_HDRNEWLEN_EXC 10
70
71 /* RFC 1051 */
72 #define ARCTYPE_IP_OLD 240 /* IP protocol */
73 #define ARCTYPE_ARP_OLD 241 /* address resolution protocol */
74
75 /* RFC 1201 */
76 #define ARCTYPE_IP 212 /* IP protocol */
77 #define ARCTYPE_ARP 213 /* address resolution protocol */
78 #define ARCTYPE_REVARP 214 /* reverse addr resolution protocol */
79
80 #define ARCTYPE_ATALK 221 /* Appletalk */
81 #define ARCTYPE_BANIAN 247 /* Banyan Vines */
82 #define ARCTYPE_IPX 250 /* Novell IPX */
83
84 #define ARCTYPE_INET6 0xc4 /* IPng */
85 #define ARCTYPE_DIAGNOSE 0x80 /* as per ANSI/ATA 878.1 */
86
87 /*
88 * Structure of a 2.5MB/s Arcnet header on Linux. Linux has
89 * an extra "offset" field when given to interface code, and
90 * never presents packets that look like exception frames.
91 */
92 struct arc_linux_header {
93 u_int8_t arc_shost;
94 u_int8_t arc_dhost;
95 u_int16_t arc_offset;
96 u_int8_t arc_type;
97 /*
98 * only present for newstyle encoding with LL fragmentation.
99 * Don't use sizeof(anything), use ARC_LINUX_HDR{,NEW}LEN
100 * instead.
101 */
102 u_int8_t arc_flag;
103 u_int16_t arc_seqid;
104 };
105
106 #define ARC_LINUX_HDRLEN 5
107 #define ARC_LINUX_HDRNEWLEN 8
108
109 static int arcnet_encap_print(u_char arctype, const u_char *p,
110 u_int length, u_int caplen);
111
112 static const struct tok arctypemap[] = {
113 { ARCTYPE_IP_OLD, "oldip" },
114 { ARCTYPE_ARP_OLD, "oldarp" },
115 { ARCTYPE_IP, "ip" },
116 { ARCTYPE_ARP, "arp" },
117 { ARCTYPE_REVARP, "rarp" },
118 { ARCTYPE_ATALK, "atalk" },
119 { ARCTYPE_BANIAN, "banyan" },
120 { ARCTYPE_IPX, "ipx" },
121 { ARCTYPE_INET6, "ipv6" },
122 { ARCTYPE_DIAGNOSE, "diag" },
123 { 0, 0 }
124 };
125
126 static inline void
127 arcnet_print(const u_char *bp, u_int length, int phds, int flag, u_int seqid)
128 {
129 const struct arc_header *ap;
130 const char *arctypename;
131
132
133 ap = (const struct arc_header *)bp;
134
135
136 if (qflag) {
137 (void)printf("%02x %02x %d: ",
138 ap->arc_shost,
139 ap->arc_dhost,
140 length);
141 return;
142 }
143
144 arctypename = tok2str(arctypemap, "%02x", ap->arc_type);
145
146 if (!phds) {
147 (void)printf("%02x %02x %s %d: ",
148 ap->arc_shost, ap->arc_dhost, arctypename,
149 length);
150 return;
151 }
152
153 if (flag == 0) {
154 (void)printf("%02x %02x %s seqid %04x %d: ",
155 ap->arc_shost, ap->arc_dhost, arctypename, seqid,
156 length);
157 return;
158 }
159
160 if (flag & 1)
161 (void)printf("%02x %02x %s seqid %04x "
162 "(first of %d fragments) %d: ",
163 ap->arc_shost, ap->arc_dhost, arctypename, seqid,
164 (flag + 3) / 2, length);
165 else
166 (void)printf("%02x %02x %s seqid %04x "
167 "(fragment %d) %d: ",
168 ap->arc_shost, ap->arc_dhost, arctypename, seqid,
169 flag/2 + 1, length);
170 }
171
172 /*
173 * This is the top level routine of the printer. 'p' points
174 * to the ARCNET header of the packet, 'h->ts' is the timestamp,
175 * 'h->len' is the length of the packet off the wire, and 'h->caplen'
176 * is the number of bytes actually captured.
177 */
178 u_int
179 arcnet_if_print(const struct pcap_pkthdr *h, const u_char *p)
180 {
181 u_int caplen = h->caplen;
182 u_int length = h->len;
183 const struct arc_header *ap;
184
185 int phds, flag = 0, archdrlen = 0;
186 u_int seqid = 0;
187 u_char arc_type;
188
189 if (caplen < ARC_HDRLEN) {
190 printf("[|arcnet]");
191 return (caplen);
192 }
193
194 ap = (const struct arc_header *)p;
195 arc_type = ap->arc_type;
196
197 switch (arc_type) {
198 default:
199 phds = 1;
200 break;
201 case ARCTYPE_IP_OLD:
202 case ARCTYPE_ARP_OLD:
203 case ARCTYPE_DIAGNOSE:
204 phds = 0;
205 archdrlen = ARC_HDRLEN;
206 break;
207 }
208
209 if (phds) {
210 if (caplen < ARC_HDRNEWLEN) {
211 arcnet_print(p, length, 0, 0, 0);
212 printf("[|phds]");
213 return (caplen);
214 }
215
216 if (ap->arc_flag == 0xff) {
217 if (caplen < ARC_HDRNEWLEN_EXC) {
218 arcnet_print(p, length, 0, 0, 0);
219 printf("[|phds extended]");
220 return (caplen);
221 }
222 flag = ap->arc_flag2;
223 seqid = EXTRACT_16BITS(&ap->arc_seqid2);
224 archdrlen = ARC_HDRNEWLEN_EXC;
225 } else {
226 flag = ap->arc_flag;
227 seqid = EXTRACT_16BITS(&ap->arc_seqid);
228 archdrlen = ARC_HDRNEWLEN;
229 }
230 }
231
232
233 if (eflag)
234 arcnet_print(p, length, phds, flag, seqid);
235
236 /*
237 * Go past the ARCNET header.
238 */
239 length -= archdrlen;
240 caplen -= archdrlen;
241 p += archdrlen;
242
243 if (phds && flag && (flag & 1) == 0) {
244 /*
245 * This is a middle fragment.
246 */
247 return (archdrlen);
248 }
249
250 if (!arcnet_encap_print(arc_type, p, length, caplen))
251 default_print(p, caplen);
252
253 return (archdrlen);
254 }
255
256 /*
257 * This is the top level routine of the printer. 'p' points
258 * to the ARCNET header of the packet, 'h->ts' is the timestamp,
259 * 'h->len' is the length of the packet off the wire, and 'h->caplen'
260 * is the number of bytes actually captured. It is quite similar
261 * to the non-Linux style printer except that Linux doesn't ever
262 * supply packets that look like exception frames, it always supplies
263 * reassembled packets rather than raw frames, and headers have an
264 * extra "offset" field between the src/dest and packet type.
265 */
266 u_int
267 arcnet_linux_if_print(const struct pcap_pkthdr *h, const u_char *p)
268 {
269 u_int caplen = h->caplen;
270 u_int length = h->len;
271 const struct arc_linux_header *ap;
272
273 int archdrlen = 0;
274 u_char arc_type;
275
276 if (caplen < ARC_LINUX_HDRLEN) {
277 printf("[|arcnet]");
278 return (caplen);
279 }
280
281 ap = (const struct arc_linux_header *)p;
282 arc_type = ap->arc_type;
283
284 switch (arc_type) {
285 default:
286 archdrlen = ARC_LINUX_HDRNEWLEN;
287 if (caplen < ARC_LINUX_HDRNEWLEN) {
288 printf("[|arcnet]");
289 return (caplen);
290 }
291 break;
292 case ARCTYPE_IP_OLD:
293 case ARCTYPE_ARP_OLD:
294 case ARCTYPE_DIAGNOSE:
295 archdrlen = ARC_LINUX_HDRLEN;
296 break;
297 }
298
299 if (eflag)
300 arcnet_print(p, length, 0, 0, 0);
301
302 /*
303 * Go past the ARCNET header.
304 */
305 length -= archdrlen;
306 caplen -= archdrlen;
307 p += archdrlen;
308
309 if (!arcnet_encap_print(arc_type, p, length, caplen))
310 default_print(p, caplen);
311
312 return (archdrlen);
313 }
314
315 /*
316 * Prints the packet encapsulated in an ARCnet data field,
317 * given the ARCnet system code.
318 *
319 * Returns non-zero if it can do so, zero if the system code is unknown.
320 */
321
322
323 static int
324 arcnet_encap_print(u_char arctype, const u_char *p,
325 u_int length, u_int caplen)
326 {
327 switch (arctype) {
328
329 case ARCTYPE_IP_OLD:
330 case ARCTYPE_IP:
331 ip_print(gndo, p, length);
332 return (1);
333
334 #ifdef INET6
335 case ARCTYPE_INET6:
336 ip6_print(gndo, p, length);
337 return (1);
338 #endif /*INET6*/
339
340 case ARCTYPE_ARP_OLD:
341 case ARCTYPE_ARP:
342 case ARCTYPE_REVARP:
343 arp_print(gndo, p, length, caplen);
344 return (1);
345
346 case ARCTYPE_ATALK: /* XXX was this ever used? */
347 if (vflag)
348 fputs("et1 ", stdout);
349 atalk_print(p, length);
350 return (1);
351
352 case ARCTYPE_IPX:
353 ipx_print(p, length);
354 return (1);
355
356 default:
357 return (0);
358 }
359 }
360
361 /*
362 * Local Variables:
363 * c-style: bsd
364 * End:
365 */
366