1a90e161bSBill Fenner /*
2a90e161bSBill Fenner * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
3a90e161bSBill Fenner * The Regents of the University of California. All rights reserved.
4a90e161bSBill Fenner *
5a90e161bSBill Fenner * Redistribution and use in source and binary forms, with or without
6a90e161bSBill Fenner * modification, are permitted provided that: (1) source code distributions
7a90e161bSBill Fenner * retain the above copyright notice and this paragraph in its entirety, (2)
8a90e161bSBill Fenner * distributions including binary code include the above copyright notice and
9a90e161bSBill Fenner * this paragraph in its entirety in the documentation or other materials
10a90e161bSBill Fenner * provided with the distribution, and (3) all advertising materials mentioning
11a90e161bSBill Fenner * features or use of this software display the following acknowledgement:
12a90e161bSBill Fenner * ``This product includes software developed by the University of California,
13a90e161bSBill Fenner * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14a90e161bSBill Fenner * the University nor the names of its contributors may be used to endorse
15a90e161bSBill Fenner * or promote products derived from this software without specific prior
16a90e161bSBill Fenner * written permission.
17a90e161bSBill Fenner * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18a90e161bSBill Fenner * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19a90e161bSBill Fenner * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20a90e161bSBill Fenner *
21a90e161bSBill Fenner * From: NetBSD: print-arcnet.c,v 1.2 2000/04/24 13:02:28 itojun Exp
22a90e161bSBill Fenner */
23a90e161bSBill Fenner
243340d773SGleb Smirnoff /* \summary: Attached Resource Computer NETwork (ARCNET) printer */
253340d773SGleb Smirnoff
26*ee67461eSJoseph Mingrone #include <config.h>
27a90e161bSBill Fenner
28*ee67461eSJoseph Mingrone #include "netdissect-stdinc.h"
29a90e161bSBill Fenner
303340d773SGleb Smirnoff #include "netdissect.h"
3127df3f5dSRui Paulo #include "extract.h"
32a90e161bSBill Fenner
333c602fabSXin LI /*
343c602fabSXin LI * from: NetBSD: if_arc.h,v 1.13 1999/11/19 20:41:19 thorpej Exp
353c602fabSXin LI */
363c602fabSXin LI
373c602fabSXin LI /*
383c602fabSXin LI * Structure of a 2.5MB/s Arcnet header on the BSDs,
393c602fabSXin LI * as given to interface code.
403c602fabSXin LI */
413c602fabSXin LI struct arc_header {
42*ee67461eSJoseph Mingrone nd_uint8_t arc_shost;
43*ee67461eSJoseph Mingrone nd_uint8_t arc_dhost;
44*ee67461eSJoseph Mingrone nd_uint8_t arc_type;
453c602fabSXin LI /*
463c602fabSXin LI * only present for newstyle encoding with LL fragmentation.
473c602fabSXin LI * Don't use sizeof(anything), use ARC_HDR{,NEW}LEN instead.
483c602fabSXin LI */
49*ee67461eSJoseph Mingrone nd_uint8_t arc_flag;
50*ee67461eSJoseph Mingrone nd_uint16_t arc_seqid;
513c602fabSXin LI
523c602fabSXin LI /*
533c602fabSXin LI * only present in exception packets (arc_flag == 0xff)
543c602fabSXin LI */
55*ee67461eSJoseph Mingrone nd_uint8_t arc_type2; /* same as arc_type */
56*ee67461eSJoseph Mingrone nd_uint8_t arc_flag2; /* real flag value */
57*ee67461eSJoseph Mingrone nd_uint16_t arc_seqid2; /* real seqid value */
583c602fabSXin LI };
593c602fabSXin LI
603c602fabSXin LI #define ARC_HDRLEN 3
613c602fabSXin LI #define ARC_HDRNEWLEN 6
623c602fabSXin LI #define ARC_HDRNEWLEN_EXC 10
633c602fabSXin LI
643c602fabSXin LI /* RFC 1051 */
653c602fabSXin LI #define ARCTYPE_IP_OLD 240 /* IP protocol */
663c602fabSXin LI #define ARCTYPE_ARP_OLD 241 /* address resolution protocol */
673c602fabSXin LI
683c602fabSXin LI /* RFC 1201 */
693c602fabSXin LI #define ARCTYPE_IP 212 /* IP protocol */
703c602fabSXin LI #define ARCTYPE_ARP 213 /* address resolution protocol */
713c602fabSXin LI #define ARCTYPE_REVARP 214 /* reverse addr resolution protocol */
723c602fabSXin LI
733c602fabSXin LI #define ARCTYPE_ATALK 221 /* Appletalk */
743c602fabSXin LI #define ARCTYPE_BANIAN 247 /* Banyan Vines */
753c602fabSXin LI #define ARCTYPE_IPX 250 /* Novell IPX */
763c602fabSXin LI
773c602fabSXin LI #define ARCTYPE_INET6 0xc4 /* IPng */
783c602fabSXin LI #define ARCTYPE_DIAGNOSE 0x80 /* as per ANSI/ATA 878.1 */
793c602fabSXin LI
803c602fabSXin LI /*
813c602fabSXin LI * Structure of a 2.5MB/s Arcnet header on Linux. Linux has
823c602fabSXin LI * an extra "offset" field when given to interface code, and
833c602fabSXin LI * never presents packets that look like exception frames.
843c602fabSXin LI */
853c602fabSXin LI struct arc_linux_header {
86*ee67461eSJoseph Mingrone nd_uint8_t arc_shost;
87*ee67461eSJoseph Mingrone nd_uint8_t arc_dhost;
88*ee67461eSJoseph Mingrone nd_uint16_t arc_offset;
89*ee67461eSJoseph Mingrone nd_uint8_t arc_type;
903c602fabSXin LI /*
913c602fabSXin LI * only present for newstyle encoding with LL fragmentation.
923c602fabSXin LI * Don't use sizeof(anything), use ARC_LINUX_HDR{,NEW}LEN
933c602fabSXin LI * instead.
943c602fabSXin LI */
95*ee67461eSJoseph Mingrone nd_uint8_t arc_flag;
96*ee67461eSJoseph Mingrone nd_uint16_t arc_seqid;
973c602fabSXin LI };
983c602fabSXin LI
993c602fabSXin LI #define ARC_LINUX_HDRLEN 5
1003c602fabSXin LI #define ARC_LINUX_HDRNEWLEN 8
1013c602fabSXin LI
1023c602fabSXin LI static int arcnet_encap_print(netdissect_options *, u_char arctype, const u_char *p,
103a90e161bSBill Fenner u_int length, u_int caplen);
104a90e161bSBill Fenner
1053c602fabSXin LI static const struct tok arctypemap[] = {
106a90e161bSBill Fenner { ARCTYPE_IP_OLD, "oldip" },
107a90e161bSBill Fenner { ARCTYPE_ARP_OLD, "oldarp" },
108a90e161bSBill Fenner { ARCTYPE_IP, "ip" },
109a90e161bSBill Fenner { ARCTYPE_ARP, "arp" },
110a90e161bSBill Fenner { ARCTYPE_REVARP, "rarp" },
111a90e161bSBill Fenner { ARCTYPE_ATALK, "atalk" },
112a90e161bSBill Fenner { ARCTYPE_BANIAN, "banyan" },
113a90e161bSBill Fenner { ARCTYPE_IPX, "ipx" },
114a90e161bSBill Fenner { ARCTYPE_INET6, "ipv6" },
115a90e161bSBill Fenner { ARCTYPE_DIAGNOSE, "diag" },
116*ee67461eSJoseph Mingrone { 0, NULL }
117a90e161bSBill Fenner };
118a90e161bSBill Fenner
119*ee67461eSJoseph Mingrone static void
arcnet_print(netdissect_options * ndo,const u_char * bp,u_int length,int phds,u_int flag,u_int seqid)1203c602fabSXin LI arcnet_print(netdissect_options *ndo, const u_char *bp, u_int length, int phds,
121*ee67461eSJoseph Mingrone u_int flag, u_int seqid)
122a90e161bSBill Fenner {
123a90e161bSBill Fenner const struct arc_header *ap;
124a90e161bSBill Fenner const char *arctypename;
125a90e161bSBill Fenner
126*ee67461eSJoseph Mingrone ndo->ndo_protocol = "arcnet";
127a90e161bSBill Fenner ap = (const struct arc_header *)bp;
128a90e161bSBill Fenner
1293c602fabSXin LI if (ndo->ndo_qflag) {
130*ee67461eSJoseph Mingrone ND_PRINT("%02x %02x %u: ",
131*ee67461eSJoseph Mingrone GET_U_1(ap->arc_shost),
132*ee67461eSJoseph Mingrone GET_U_1(ap->arc_dhost),
133*ee67461eSJoseph Mingrone length);
134a90e161bSBill Fenner return;
135a90e161bSBill Fenner }
136a90e161bSBill Fenner
137*ee67461eSJoseph Mingrone arctypename = tok2str(arctypemap, "%02x", GET_U_1(ap->arc_type));
138a90e161bSBill Fenner
139a90e161bSBill Fenner if (!phds) {
140*ee67461eSJoseph Mingrone ND_PRINT("%02x %02x %s %u: ",
141*ee67461eSJoseph Mingrone GET_U_1(ap->arc_shost),
142*ee67461eSJoseph Mingrone GET_U_1(ap->arc_dhost),
143*ee67461eSJoseph Mingrone arctypename,
144*ee67461eSJoseph Mingrone length);
145a90e161bSBill Fenner return;
146a90e161bSBill Fenner }
147a90e161bSBill Fenner
148a90e161bSBill Fenner if (flag == 0) {
149*ee67461eSJoseph Mingrone ND_PRINT("%02x %02x %s seqid %04x %u: ",
150*ee67461eSJoseph Mingrone GET_U_1(ap->arc_shost),
151*ee67461eSJoseph Mingrone GET_U_1(ap->arc_dhost),
152*ee67461eSJoseph Mingrone arctypename, seqid,
153*ee67461eSJoseph Mingrone length);
154a90e161bSBill Fenner return;
155a90e161bSBill Fenner }
156a90e161bSBill Fenner
157a90e161bSBill Fenner if (flag & 1)
158*ee67461eSJoseph Mingrone ND_PRINT("%02x %02x %s seqid %04x "
159*ee67461eSJoseph Mingrone "(first of %u fragments) %u: ",
160*ee67461eSJoseph Mingrone GET_U_1(ap->arc_shost),
161*ee67461eSJoseph Mingrone GET_U_1(ap->arc_dhost),
162*ee67461eSJoseph Mingrone arctypename, seqid,
163*ee67461eSJoseph Mingrone (flag + 3) / 2, length);
164a90e161bSBill Fenner else
165*ee67461eSJoseph Mingrone ND_PRINT("%02x %02x %s seqid %04x "
166*ee67461eSJoseph Mingrone "(fragment %u) %u: ",
167*ee67461eSJoseph Mingrone GET_U_1(ap->arc_shost),
168*ee67461eSJoseph Mingrone GET_U_1(ap->arc_dhost),
169*ee67461eSJoseph Mingrone arctypename, seqid,
170*ee67461eSJoseph Mingrone flag/2 + 1, length);
171a90e161bSBill Fenner }
172a90e161bSBill Fenner
173a90e161bSBill Fenner /*
1745b0fe478SBruce M Simpson * This is the top level routine of the printer. 'p' points
1755b0fe478SBruce M Simpson * to the ARCNET header of the packet, 'h->ts' is the timestamp,
1761de50e9fSSam Leffler * 'h->len' is the length of the packet off the wire, and 'h->caplen'
177a90e161bSBill Fenner * is the number of bytes actually captured.
178a90e161bSBill Fenner */
179*ee67461eSJoseph Mingrone void
arcnet_if_print(netdissect_options * ndo,const struct pcap_pkthdr * h,const u_char * p)1803c602fabSXin LI arcnet_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
181a90e161bSBill Fenner {
182a90e161bSBill Fenner u_int caplen = h->caplen;
183a90e161bSBill Fenner u_int length = h->len;
184a90e161bSBill Fenner const struct arc_header *ap;
185a90e161bSBill Fenner
186*ee67461eSJoseph Mingrone int phds;
187*ee67461eSJoseph Mingrone u_int flag = 0, archdrlen = 0;
188a90e161bSBill Fenner u_int seqid = 0;
189a90e161bSBill Fenner u_char arc_type;
190a90e161bSBill Fenner
191*ee67461eSJoseph Mingrone ndo->ndo_protocol = "arcnet";
192*ee67461eSJoseph Mingrone if (caplen < ARC_HDRLEN) {
193*ee67461eSJoseph Mingrone ndo->ndo_ll_hdr_len += caplen;
194*ee67461eSJoseph Mingrone nd_trunc_longjmp(ndo);
195a90e161bSBill Fenner }
196a90e161bSBill Fenner
197a90e161bSBill Fenner ap = (const struct arc_header *)p;
198*ee67461eSJoseph Mingrone arc_type = GET_U_1(ap->arc_type);
199a90e161bSBill Fenner
200a90e161bSBill Fenner switch (arc_type) {
201a90e161bSBill Fenner default:
202a90e161bSBill Fenner phds = 1;
203a90e161bSBill Fenner break;
204a90e161bSBill Fenner case ARCTYPE_IP_OLD:
205a90e161bSBill Fenner case ARCTYPE_ARP_OLD:
206a90e161bSBill Fenner case ARCTYPE_DIAGNOSE:
207a90e161bSBill Fenner phds = 0;
208a90e161bSBill Fenner archdrlen = ARC_HDRLEN;
209a90e161bSBill Fenner break;
210a90e161bSBill Fenner }
211a90e161bSBill Fenner
212a90e161bSBill Fenner if (phds) {
213*ee67461eSJoseph Mingrone if (caplen < ARC_HDRNEWLEN) {
2143c602fabSXin LI arcnet_print(ndo, p, length, 0, 0, 0);
215*ee67461eSJoseph Mingrone ND_PRINT(" phds");
216*ee67461eSJoseph Mingrone ndo->ndo_ll_hdr_len += caplen;
217*ee67461eSJoseph Mingrone nd_trunc_longjmp(ndo);
218a90e161bSBill Fenner }
219a90e161bSBill Fenner
220*ee67461eSJoseph Mingrone flag = GET_U_1(ap->arc_flag);
221*ee67461eSJoseph Mingrone if (flag == 0xff) {
222*ee67461eSJoseph Mingrone if (caplen < ARC_HDRNEWLEN_EXC) {
2233c602fabSXin LI arcnet_print(ndo, p, length, 0, 0, 0);
224*ee67461eSJoseph Mingrone ND_PRINT(" phds extended");
225*ee67461eSJoseph Mingrone ndo->ndo_ll_hdr_len += caplen;
226*ee67461eSJoseph Mingrone nd_trunc_longjmp(ndo);
227a90e161bSBill Fenner }
228*ee67461eSJoseph Mingrone flag = GET_U_1(ap->arc_flag2);
229*ee67461eSJoseph Mingrone seqid = GET_BE_U_2(ap->arc_seqid2);
230a90e161bSBill Fenner archdrlen = ARC_HDRNEWLEN_EXC;
231a90e161bSBill Fenner } else {
232*ee67461eSJoseph Mingrone seqid = GET_BE_U_2(ap->arc_seqid);
233a90e161bSBill Fenner archdrlen = ARC_HDRNEWLEN;
234a90e161bSBill Fenner }
235a90e161bSBill Fenner }
236a90e161bSBill Fenner
237a90e161bSBill Fenner
2383c602fabSXin LI if (ndo->ndo_eflag)
2393c602fabSXin LI arcnet_print(ndo, p, length, phds, flag, seqid);
240a90e161bSBill Fenner
241a90e161bSBill Fenner /*
2425b0fe478SBruce M Simpson * Go past the ARCNET header.
243a90e161bSBill Fenner */
244a90e161bSBill Fenner length -= archdrlen;
245a90e161bSBill Fenner caplen -= archdrlen;
246a90e161bSBill Fenner p += archdrlen;
247a90e161bSBill Fenner
2485b0fe478SBruce M Simpson if (phds && flag && (flag & 1) == 0) {
2495b0fe478SBruce M Simpson /*
2505b0fe478SBruce M Simpson * This is a middle fragment.
2515b0fe478SBruce M Simpson */
252*ee67461eSJoseph Mingrone ndo->ndo_ll_hdr_len += archdrlen;
253*ee67461eSJoseph Mingrone return;
254a90e161bSBill Fenner }
255a90e161bSBill Fenner
2563c602fabSXin LI if (!arcnet_encap_print(ndo, arc_type, p, length, caplen))
2573c602fabSXin LI ND_DEFAULTPRINT(p, caplen);
258a90e161bSBill Fenner
259*ee67461eSJoseph Mingrone ndo->ndo_ll_hdr_len += archdrlen;
2605b0fe478SBruce M Simpson }
2615b0fe478SBruce M Simpson
2625b0fe478SBruce M Simpson /*
2635b0fe478SBruce M Simpson * This is the top level routine of the printer. 'p' points
2645b0fe478SBruce M Simpson * to the ARCNET header of the packet, 'h->ts' is the timestamp,
2651de50e9fSSam Leffler * 'h->len' is the length of the packet off the wire, and 'h->caplen'
2665b0fe478SBruce M Simpson * is the number of bytes actually captured. It is quite similar
2675b0fe478SBruce M Simpson * to the non-Linux style printer except that Linux doesn't ever
2685b0fe478SBruce M Simpson * supply packets that look like exception frames, it always supplies
2695b0fe478SBruce M Simpson * reassembled packets rather than raw frames, and headers have an
2705b0fe478SBruce M Simpson * extra "offset" field between the src/dest and packet type.
2715b0fe478SBruce M Simpson */
272*ee67461eSJoseph Mingrone void
arcnet_linux_if_print(netdissect_options * ndo,const struct pcap_pkthdr * h,const u_char * p)2733c602fabSXin LI arcnet_linux_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
2745b0fe478SBruce M Simpson {
2755b0fe478SBruce M Simpson u_int caplen = h->caplen;
2765b0fe478SBruce M Simpson u_int length = h->len;
2775b0fe478SBruce M Simpson const struct arc_linux_header *ap;
2785b0fe478SBruce M Simpson
2795b0fe478SBruce M Simpson int archdrlen = 0;
2805b0fe478SBruce M Simpson u_char arc_type;
2815b0fe478SBruce M Simpson
282*ee67461eSJoseph Mingrone ndo->ndo_protocol = "arcnet_linux";
283*ee67461eSJoseph Mingrone if (caplen < ARC_LINUX_HDRLEN) {
284*ee67461eSJoseph Mingrone ndo->ndo_ll_hdr_len += caplen;
285*ee67461eSJoseph Mingrone nd_trunc_longjmp(ndo);
2865b0fe478SBruce M Simpson }
2875b0fe478SBruce M Simpson
2885b0fe478SBruce M Simpson ap = (const struct arc_linux_header *)p;
289*ee67461eSJoseph Mingrone arc_type = GET_U_1(ap->arc_type);
2905b0fe478SBruce M Simpson
2915b0fe478SBruce M Simpson switch (arc_type) {
2925b0fe478SBruce M Simpson default:
2935b0fe478SBruce M Simpson archdrlen = ARC_LINUX_HDRNEWLEN;
294*ee67461eSJoseph Mingrone if (caplen < ARC_LINUX_HDRNEWLEN) {
295*ee67461eSJoseph Mingrone ndo->ndo_ll_hdr_len += caplen;
296*ee67461eSJoseph Mingrone nd_trunc_longjmp(ndo);
2975b0fe478SBruce M Simpson }
2985b0fe478SBruce M Simpson break;
2995b0fe478SBruce M Simpson case ARCTYPE_IP_OLD:
3005b0fe478SBruce M Simpson case ARCTYPE_ARP_OLD:
3015b0fe478SBruce M Simpson case ARCTYPE_DIAGNOSE:
3025b0fe478SBruce M Simpson archdrlen = ARC_LINUX_HDRLEN;
3035b0fe478SBruce M Simpson break;
3045b0fe478SBruce M Simpson }
3055b0fe478SBruce M Simpson
3063c602fabSXin LI if (ndo->ndo_eflag)
3073c602fabSXin LI arcnet_print(ndo, p, length, 0, 0, 0);
3085b0fe478SBruce M Simpson
3095b0fe478SBruce M Simpson /*
3105b0fe478SBruce M Simpson * Go past the ARCNET header.
3115b0fe478SBruce M Simpson */
3125b0fe478SBruce M Simpson length -= archdrlen;
3135b0fe478SBruce M Simpson caplen -= archdrlen;
3145b0fe478SBruce M Simpson p += archdrlen;
3155b0fe478SBruce M Simpson
3163c602fabSXin LI if (!arcnet_encap_print(ndo, arc_type, p, length, caplen))
3173c602fabSXin LI ND_DEFAULTPRINT(p, caplen);
3185b0fe478SBruce M Simpson
319*ee67461eSJoseph Mingrone ndo->ndo_ll_hdr_len += archdrlen;
320a90e161bSBill Fenner }
321a90e161bSBill Fenner
322a90e161bSBill Fenner /*
323a90e161bSBill Fenner * Prints the packet encapsulated in an ARCnet data field,
324a90e161bSBill Fenner * given the ARCnet system code.
325a90e161bSBill Fenner *
326a90e161bSBill Fenner * Returns non-zero if it can do so, zero if the system code is unknown.
327a90e161bSBill Fenner */
328a90e161bSBill Fenner
329a90e161bSBill Fenner
3305b0fe478SBruce M Simpson static int
arcnet_encap_print(netdissect_options * ndo,u_char arctype,const u_char * p,u_int length,u_int caplen)3313c602fabSXin LI arcnet_encap_print(netdissect_options *ndo, u_char arctype, const u_char *p,
332a90e161bSBill Fenner u_int length, u_int caplen)
333a90e161bSBill Fenner {
334a90e161bSBill Fenner switch (arctype) {
335a90e161bSBill Fenner
336a90e161bSBill Fenner case ARCTYPE_IP_OLD:
337a90e161bSBill Fenner case ARCTYPE_IP:
3383c602fabSXin LI ip_print(ndo, p, length);
339a90e161bSBill Fenner return (1);
340a90e161bSBill Fenner
341a90e161bSBill Fenner case ARCTYPE_INET6:
3423c602fabSXin LI ip6_print(ndo, p, length);
343a90e161bSBill Fenner return (1);
344a90e161bSBill Fenner
345a90e161bSBill Fenner case ARCTYPE_ARP_OLD:
346a90e161bSBill Fenner case ARCTYPE_ARP:
347a90e161bSBill Fenner case ARCTYPE_REVARP:
3483c602fabSXin LI arp_print(ndo, p, length, caplen);
349a90e161bSBill Fenner return (1);
350a90e161bSBill Fenner
351a90e161bSBill Fenner case ARCTYPE_ATALK: /* XXX was this ever used? */
3523c602fabSXin LI if (ndo->ndo_vflag)
353*ee67461eSJoseph Mingrone ND_PRINT("et1 ");
3543c602fabSXin LI atalk_print(ndo, p, length);
355a90e161bSBill Fenner return (1);
356a90e161bSBill Fenner
3575b0fe478SBruce M Simpson case ARCTYPE_IPX:
3583c602fabSXin LI ipx_print(ndo, p, length);
3595b0fe478SBruce M Simpson return (1);
3605b0fe478SBruce M Simpson
361a90e161bSBill Fenner default:
362a90e161bSBill Fenner return (0);
363a90e161bSBill Fenner }
364a90e161bSBill Fenner }
365