xref: /netbsd-src/external/bsd/tcpdump/dist/print-arcnet.c (revision 6cf6fe02a981b55727c49c3d37b0d8191a98c0ee)
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