*
* From: NetBSD: print-arcnet.c,v 1.2 2000/04/24 13:02:28 itojun Exp
*/
-#ifndef lint
-static const char rcsid[] =
- "@(#) $Header: /tcpdump/master/tcpdump/print-arcnet.c,v 1.10 2002-09-05 21:25:37 guy Exp $ (LBL)";
-#endif
#ifdef HAVE_CONFIG_H
#include "config.h"
#include <pcap.h>
#include "interface.h"
-#include "arcnet.h"
+#include "extract.h"
+
+/*
+ * from: NetBSD: if_arc.h,v 1.13 1999/11/19 20:41:19 thorpej Exp
+ */
+
+/*
+ * Structure of a 2.5MB/s Arcnet header on the BSDs,
+ * as given to interface code.
+ */
+struct arc_header {
+ u_int8_t arc_shost;
+ u_int8_t arc_dhost;
+ u_int8_t arc_type;
+ /*
+ * only present for newstyle encoding with LL fragmentation.
+ * Don't use sizeof(anything), use ARC_HDR{,NEW}LEN instead.
+ */
+ u_int8_t arc_flag;
+ u_int16_t arc_seqid;
+
+ /*
+ * only present in exception packets (arc_flag == 0xff)
+ */
+ u_int8_t arc_type2; /* same as arc_type */
+ u_int8_t arc_flag2; /* real flag value */
+ u_int16_t arc_seqid2; /* real seqid value */
+};
+
+#define ARC_HDRLEN 3
+#define ARC_HDRNEWLEN 6
+#define ARC_HDRNEWLEN_EXC 10
+
+/* RFC 1051 */
+#define ARCTYPE_IP_OLD 240 /* IP protocol */
+#define ARCTYPE_ARP_OLD 241 /* address resolution protocol */
+
+/* RFC 1201 */
+#define ARCTYPE_IP 212 /* IP protocol */
+#define ARCTYPE_ARP 213 /* address resolution protocol */
+#define ARCTYPE_REVARP 214 /* reverse addr resolution protocol */
+
+#define ARCTYPE_ATALK 221 /* Appletalk */
+#define ARCTYPE_BANIAN 247 /* Banyan Vines */
+#define ARCTYPE_IPX 250 /* Novell IPX */
-int arcnet_encap_print(u_char arctype, const u_char *p,
+#define ARCTYPE_INET6 0xc4 /* IPng */
+#define ARCTYPE_DIAGNOSE 0x80 /* as per ANSI/ATA 878.1 */
+
+/*
+ * Structure of a 2.5MB/s Arcnet header on Linux. Linux has
+ * an extra "offset" field when given to interface code, and
+ * never presents packets that look like exception frames.
+ */
+struct arc_linux_header {
+ u_int8_t arc_shost;
+ u_int8_t arc_dhost;
+ u_int16_t arc_offset;
+ u_int8_t arc_type;
+ /*
+ * only present for newstyle encoding with LL fragmentation.
+ * Don't use sizeof(anything), use ARC_LINUX_HDR{,NEW}LEN
+ * instead.
+ */
+ u_int8_t arc_flag;
+ u_int16_t arc_seqid;
+};
+
+#define ARC_LINUX_HDRLEN 5
+#define ARC_LINUX_HDRNEWLEN 8
+
+static int arcnet_encap_print(u_char arctype, const u_char *p,
u_int length, u_int caplen);
-struct tok arctypemap[] = {
+static const struct tok arctypemap[] = {
{ ARCTYPE_IP_OLD, "oldip" },
{ ARCTYPE_ARP_OLD, "oldarp" },
{ ARCTYPE_IP, "ip" },
/*
* This is the top level routine of the printer. 'p' points
* to the ARCNET header of the packet, 'h->ts' is the timestamp,
- * 'h->length' is the length of the packet off the wire, and 'h->caplen'
+ * 'h->len' is the length of the packet off the wire, and 'h->caplen'
* is the number of bytes actually captured.
*/
-void
-arcnet_if_print(u_char *user _U_, const struct pcap_pkthdr *h, const u_char *p)
+u_int
+arcnet_if_print(const struct pcap_pkthdr *h, const u_char *p)
{
u_int caplen = h->caplen;
u_int length = h->len;
u_int seqid = 0;
u_char arc_type;
- ++infodelay;
- ts_print(&h->ts);
-
if (caplen < ARC_HDRLEN) {
printf("[|arcnet]");
- goto out;
+ return (caplen);
}
ap = (const struct arc_header *)p;
if (caplen < ARC_HDRNEWLEN) {
arcnet_print(p, length, 0, 0, 0);
printf("[|phds]");
- goto out;
+ return (caplen);
}
if (ap->arc_flag == 0xff) {
if (caplen < ARC_HDRNEWLEN_EXC) {
arcnet_print(p, length, 0, 0, 0);
printf("[|phds extended]");
- goto out;
+ return (caplen);
}
flag = ap->arc_flag2;
- seqid = ap->arc_seqid2;
+ seqid = EXTRACT_16BITS(&ap->arc_seqid2);
archdrlen = ARC_HDRNEWLEN_EXC;
} else {
flag = ap->arc_flag;
- seqid = ap->arc_seqid;
+ seqid = EXTRACT_16BITS(&ap->arc_seqid);
archdrlen = ARC_HDRNEWLEN;
}
}
arcnet_print(p, length, phds, flag, seqid);
/*
- * Some printers want to get back at the ethernet addresses,
- * and/or check that they're not walking off the end of the packet.
- * Rather than pass them all the way down, we set these globals.
+ * Go past the ARCNET header.
*/
- packetp = p;
- snapend = p + caplen;
-
length -= archdrlen;
caplen -= archdrlen;
p += archdrlen;
- if (phds && flag && (flag & 1) == 0)
- goto out2;
+ if (phds && flag && (flag & 1) == 0) {
+ /*
+ * This is a middle fragment.
+ */
+ return (archdrlen);
+ }
- if (!arcnet_encap_print(arc_type, p, length, caplen)) {
+ if (!arcnet_encap_print(arc_type, p, length, caplen))
default_print(p, caplen);
- goto out;
+
+ return (archdrlen);
+}
+
+/*
+ * This is the top level routine of the printer. 'p' points
+ * to the ARCNET header of the packet, 'h->ts' is the timestamp,
+ * 'h->len' is the length of the packet off the wire, and 'h->caplen'
+ * is the number of bytes actually captured. It is quite similar
+ * to the non-Linux style printer except that Linux doesn't ever
+ * supply packets that look like exception frames, it always supplies
+ * reassembled packets rather than raw frames, and headers have an
+ * extra "offset" field between the src/dest and packet type.
+ */
+u_int
+arcnet_linux_if_print(const struct pcap_pkthdr *h, const u_char *p)
+{
+ u_int caplen = h->caplen;
+ u_int length = h->len;
+ const struct arc_linux_header *ap;
+
+ int archdrlen = 0;
+ u_char arc_type;
+
+ if (caplen < ARC_LINUX_HDRLEN) {
+ printf("[|arcnet]");
+ return (caplen);
+ }
+
+ ap = (const struct arc_linux_header *)p;
+ arc_type = ap->arc_type;
+
+ switch (arc_type) {
+ default:
+ archdrlen = ARC_LINUX_HDRNEWLEN;
+ if (caplen < ARC_LINUX_HDRNEWLEN) {
+ printf("[|arcnet]");
+ return (caplen);
+ }
+ break;
+ case ARCTYPE_IP_OLD:
+ case ARCTYPE_ARP_OLD:
+ case ARCTYPE_DIAGNOSE:
+ archdrlen = ARC_LINUX_HDRLEN;
+ break;
}
- out2:
- if (xflag)
+ if (eflag)
+ arcnet_print(p, length, 0, 0, 0);
+
+ /*
+ * Go past the ARCNET header.
+ */
+ length -= archdrlen;
+ caplen -= archdrlen;
+ p += archdrlen;
+
+ if (!arcnet_encap_print(arc_type, p, length, caplen))
default_print(p, caplen);
- out:
- putchar('\n');
- --infodelay;
- if (infoprint)
- info(0);
+ return (archdrlen);
}
/*
*/
-int
+static int
arcnet_encap_print(u_char arctype, const u_char *p,
u_int length, u_int caplen)
{
case ARCTYPE_IP_OLD:
case ARCTYPE_IP:
- ip_print(p, length);
+ ip_print(gndo, p, length);
return (1);
#ifdef INET6
case ARCTYPE_INET6:
- ip6_print(p, length);
+ ip6_print(gndo, p, length);
return (1);
#endif /*INET6*/
case ARCTYPE_ARP_OLD:
case ARCTYPE_ARP:
case ARCTYPE_REVARP:
- arp_print(p, length, caplen);
+ arp_print(gndo, p, length, caplen);
return (1);
case ARCTYPE_ATALK: /* XXX was this ever used? */
atalk_print(p, length);
return (1);
+ case ARCTYPE_IPX:
+ ipx_print(p, length);
+ return (1);
+
default:
return (0);
}
}
+
+/*
+ * Local Variables:
+ * c-style: bsd
+ * End:
+ */
+