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