Ethereal-dev: [Ethereal-dev] Wiretap patch to support reading from Endace ERF trace files

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Jesper Peterson <jesper@xxxxxxxxxx>
Date: Mon, 04 Aug 2003 17:08:43 +1200

Attached is a wiretap ERF read patch for your consideration, along with some simple (mostly truncated) test packets. I've tested the patch on Sparc/Solaris2.6 and i386/Debian.

--
Jesper Peterson, Senior Software Developer
http://www.endace.com, +64 7 839 0540

? wiretap/erf.c
? wiretap/erf.h
Index: wiretap/Makefile.am
===================================================================
RCS file: /cvsroot/ethereal/wiretap/Makefile.am,v
retrieving revision 1.42
diff -u -r1.42 Makefile.am
--- wiretap/Makefile.am	29 Jul 2003 19:42:00 -0000	1.42
+++ wiretap/Makefile.am	4 Aug 2003 03:38:52 -0000
@@ -47,6 +47,8 @@
 	csids.h			\
 	dbs-etherwatch.c	\
 	dbs-etherwatch.h	\
+	erf.c			\
+	erf.h			\
 	etherpeek.c             \
 	etherpeek.h             \
 	file.c			\
Index: wiretap/file.c
===================================================================
RCS file: /cvsroot/ethereal/wiretap/file.c,v
retrieving revision 1.100
diff -u -r1.100 file.c
--- wiretap/file.c	29 Jul 2003 19:42:01 -0000	1.100
+++ wiretap/file.c	4 Aug 2003 03:38:53 -0000
@@ -69,6 +69,7 @@
 #include "visual.h"
 #include "cosine.h"
 #include "5views.h"
+#include "erf.h"
 
 /* The open_file_* routines should return:
  *
@@ -118,6 +119,7 @@
 	vms_open,
 	dbs_etherwatch_open,
 	cosine_open,
+	erf_open,
 };
 
 #define	N_FILE_TYPES	(sizeof open_routines / sizeof open_routines[0])
@@ -448,6 +450,10 @@
 	/* WTAP_FILE_5VIEWS */
 	{ "Accellent 5Views capture", "5views",
 	  _5views_dump_can_write_encap, _5views_dump_open },
+
+	/* WTAP_FILE_ERF */
+	{ "Endace DAG capture", "erf",
+	  NULL, NULL },
 };
 
 /* Name that should be somewhat descriptive. */
Index: wiretap/wtap-int.h
===================================================================
RCS file: /cvsroot/ethereal/wiretap/wtap-int.h,v
retrieving revision 1.38
diff -u -r1.38 wtap-int.h
--- wiretap/wtap-int.h	29 Jul 2003 20:49:32 -0000	1.38
+++ wiretap/wtap-int.h	4 Aug 2003 03:38:53 -0000
@@ -117,6 +117,11 @@
 	struct timeval reference_time;
 } etherpeek_t;
 
+typedef struct {
+	guint32 fcs_bits;
+	guint32 atm_encap;
+} erf_t;
+
 typedef gboolean (*subtype_read_func)(struct wtap*, int*, long*);
 typedef gboolean (*subtype_seek_read_func)(struct wtap*, long, union wtap_pseudo_header*,
 					guint8*, int, int *);
@@ -143,6 +148,7 @@
 		ascend_t		*ascend;
 		csids_t			*csids;
 		etherpeek_t		*etherpeek;
+		erf_t			*erf;
 		void			*generic;
 	} capture;
 
Index: wiretap/wtap.h
===================================================================
RCS file: /cvsroot/ethereal/wiretap/wtap.h,v
retrieving revision 1.139
diff -u -r1.139 wtap.h
--- wiretap/wtap.h	29 Jul 2003 19:42:01 -0000	1.139
+++ wiretap/wtap.h	4 Aug 2003 03:38:53 -0000
@@ -170,9 +170,10 @@
 #define WTAP_FILE_VISUAL_NETWORKS		32
 #define WTAP_FILE_COSINE			33
 #define WTAP_FILE_5VIEWS			34
+#define WTAP_FILE_ERF				35
 
 /* last WTAP_FILE_ value + 1 */
-#define WTAP_NUM_FILE_TYPES			35
+#define WTAP_NUM_FILE_TYPES			36
 
 /*
  * Maximum packet size we'll support.
--- /dev/null	Thu Apr 10 23:07:11 2003
+++ wiretap/erf.c	Mon Aug  4 15:35:59 2003
@@ -0,0 +1,343 @@
+/*
+ *
+ * Copyright (c) 2003 Endace Technology Ltd, Hamilton, New Zealand.
+ *                    All rights reserved.
+ *
+ * This software and documentation has been developed by Endace Technology Ltd.
+ * along with the DAG PCI network capture cards. For further information please
+ * visit http://www.endace.com/.
+ *
+ * Redistribution and use of software in source and binary forms and
+ * documentation, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * 1. Redistributions of source code and documentation must retain the above
+ *    copyright notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Endace Technology Ltd.,
+ *      Hamilton, New Zealand, and its contributors.
+ * 4. Neither the name of Endace Technology nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY ENDACE TECHNOLOGY AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ENDACE TECHNOLOGY
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: $
+ */
+
+/* 
+ * erf - Endace ERF (Extensible Record Format)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+
+#include "wtap-int.h"
+#include "file_wrappers.h"
+#include "buffer.h"
+#include "atm.h"
+#include "erf.h"
+
+static int erf_read_header(
+		FILE_T fh,
+		struct wtap_pkthdr *phdr,
+		union wtap_pseudo_header *pseudo_header,
+		erf_header_t *erf_header,
+		erf_t *erf,
+		int *err,
+		guint32 *bytes_read,
+		guint32 *packet_size);
+static gboolean erf_read(wtap *wth, int *err, long *data_offset);
+static gboolean erf_seek_read(wtap *wth, long seek_off,
+		union wtap_pseudo_header *pseudo_header, guchar *pd,
+		int length, int *err);
+static void erf_close(wtap *wth);
+
+int erf_open(wtap *wth, int *err)
+{
+	guint32 i, n;
+	char *s;
+	guint32 fcs_bits = FCS_BITS;
+	guint32 records_for_erf_check = RECORDS_FOR_ERF_CHECK;
+	guint32 atm_encap = WTAP_ENCAP_ATM_RFC1483;
+	erf_timestamp_t prevts;
+
+	memset(&prevts, 0, sizeof(prevts));
+
+	/*
+	 * The wirelength value in the ERF file is needed to calculate the
+	 * original payload length. Unfortunately the value includes a
+	 * 0, 2 or 4 byte checksum for Ethernet and PoS, and there is no
+	 * way of telling which it is. So assume 4 bytes checksum unless
+	 * told differently through the environment.
+	 */
+	if ((s = getenv("ERF_FCS_BITS")) != NULL) {
+		if ((n = atoi(s)) == 0 || n == 16|| n == 32) {
+			fcs_bits = n;
+		}
+	}
+
+	if ((s = getenv("ERF_ATM_ENCAP")) != NULL) {
+		if (!strcmp(s, "sunatm")) {
+			atm_encap = WTAP_ENCAP_ATM_PDUS;
+		}
+	}
+
+	/* number of records to scan before deciding if this really is ERF (dflt=3) */
+	if ((s = getenv("ERF_RECORDS_TO_CHECK")) != NULL) {
+		if ((n = atoi(s)) > 0 && n < 101) {
+			records_for_erf_check = n;
+		}
+	}
+
+	/* ERF is a little hard because there's no magic number */
+
+	for (i = 0; i < records_for_erf_check; i++) {
+
+		erf_header_t header;
+		guint32 packet_size;
+		erf_timestamp_t ts;
+
+		if (file_read(&header,1,sizeof(header),wth->fh) != sizeof(header)) {
+			if ((*err = file_error(wth->fh)) != 0)
+				return -1;
+			else
+				break; /* eof */
+		}
+
+		packet_size = g_ntohs(header.rlen) - sizeof(header);
+
+		/* fail on invalid record type, decreasing timestamps or non-zero pad-bits */
+		if (header.type == 0 || header.type > TYPE_AAL5 ||
+		    (header.flags & 0xc0) != 0) {
+			return 0;
+		}
+
+#ifdef G_HAVE_GINT64
+		if ((ts = pletohll(&header.ts)) < prevts) {
+			return 0;
+		}
+#else
+		ts[0] = pletohl(&header.ts[0]); /* frac */
+		ts[1] = pletohl(&header.ts[1]); /* sec */
+		if ((ts[1] < prevts[1]) ||
+				(ts[1] >= prevts[1] && ts[0] < prevts[0])) {
+			return 0;
+		}
+#endif
+		memcpy(&prevts, &ts, sizeof(prevts));
+
+		if (file_seek(wth->fh, packet_size, SEEK_CUR, err) == -1) {
+			return -1;
+		}
+	}
+
+	if (file_seek(wth->fh, 0L, SEEK_SET, err) == -1) {	/* rewind */
+		return -1;
+	}
+
+	wth->data_offset = 0;
+
+	/* This is an ERF file */
+	wth->file_type = WTAP_FILE_ERF;
+	wth->capture.erf = g_malloc(sizeof(erf_t));
+	wth->capture.erf->fcs_bits = fcs_bits;
+	wth->capture.erf->atm_encap = atm_encap;
+	wth->subtype_read = erf_read;
+	wth->subtype_seek_read = erf_seek_read;
+	wth->subtype_close = erf_close;
+	wth->snapshot_length = 0;	/* not available in header, only in frame */
+
+	return 1;
+}
+
+/* Read the next packet */
+static gboolean erf_read(wtap *wth, int *err, long *data_offset)
+{
+	erf_header_t erf_header;
+	guint32 packet_size, bytes_read;
+
+	*data_offset = wth->data_offset;
+
+	if (!erf_read_header(
+			wth->fh,
+			&wth->phdr, &wth->pseudo_header, &erf_header, wth->capture.erf,
+			err, &bytes_read, &packet_size)) {
+		return FALSE;
+	}
+	wth->data_offset += bytes_read;
+
+	buffer_assure_space(wth->frame_buffer, packet_size);
+	wtap_file_read_expected_bytes(
+		buffer_start_ptr(wth->frame_buffer), (gint32)packet_size, wth->fh, err
+	);
+	wth->data_offset += packet_size;
+
+	if (erf_header.type == TYPE_ATM && wth->capture.erf->atm_encap == WTAP_ENCAP_ATM_PDUS) {
+		atm_guess_traffic_type(
+			buffer_start_ptr(wth->frame_buffer), packet_size, &wth->pseudo_header
+		);
+	}
+
+	return TRUE;
+}
+
+static gboolean erf_seek_read(wtap *wth, long seek_off,
+		union wtap_pseudo_header *pseudo_header, guchar *pd,
+		int length, int *err)
+{
+	erf_header_t erf_header;
+	guint32 packet_size;
+
+	if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
+		return FALSE;
+
+	erf_read_header(wth->random_fh, NULL, pseudo_header, &erf_header, wth->capture.erf, err, NULL, &packet_size);
+
+	wtap_file_read_expected_bytes(pd, (int)packet_size, wth->random_fh, err);
+
+	if (erf_header.type == TYPE_ATM && wth->capture.erf->atm_encap == WTAP_ENCAP_ATM_PDUS) {
+		atm_guess_traffic_type(pd, length, pseudo_header);
+	}
+
+	return TRUE;
+}
+
+static void erf_close(wtap *wth)
+{
+    g_free(wth->capture.erf);
+}
+
+static int erf_read_header(
+	FILE_T fh,
+	struct wtap_pkthdr *phdr,
+	union wtap_pseudo_header *pseudo_header,
+	erf_header_t *erf_header,
+	erf_t *erf,
+	int *err,
+	guint32 *bytes_read,
+	guint32 *packet_size)
+{
+	guint32 rec_size, skip;
+
+	wtap_file_read_expected_bytes(erf_header, sizeof(*erf_header), fh, err);
+	if (bytes_read != NULL) {
+		*bytes_read = sizeof(*erf_header);
+	}
+
+	rec_size = g_ntohs(erf_header->rlen);
+	*packet_size = rec_size - sizeof(*erf_header);
+	skip = 0; /* # bytes of payload to ignore */
+
+	if (*packet_size > WTAP_MAX_PACKET_SIZE) {
+		/*
+		 * Probably a corrupt capture file; don't blow up trying
+		 * to allocate space for an immensely-large packet.
+		 */
+		g_message("erf: File has %u-byte packet, bigger than maximum of %u",
+		    *packet_size, WTAP_MAX_PACKET_SIZE);
+		*err = WTAP_ERR_BAD_RECORD;
+		return FALSE;
+	}
+
+	if (phdr != NULL ) {
+#ifdef G_HAVE_GINT64
+		guint64 ts = pletohll(&erf_header->ts);
+
+		phdr->ts.tv_sec = ts >> 32;
+		ts = ((ts &  0xffffffffULL) * 1000 * 1000);
+		ts += (ts & 0x80000000ULL) << 1; /* rounding */
+		phdr->ts.tv_usec = ts >> 32;		
+		if (phdr->ts.tv_usec >= 1000000) {
+			phdr->ts.tv_usec -= 1000000;
+			phdr->ts.tv_sec += 1;
+		}
+#else
+		phdr->ts.tv_sec = pletohl(&erf_header->ts[1]);
+		phdr->ts.tv_usec =
+			(unsigned long)((pletohl(&erf_header->ts[0])*1000000.0)/0xffffffffUL);
+#endif
+	}
+
+	switch (erf_header->type) {
+
+	case TYPE_ATM:
+
+		if (phdr != NULL) {
+			phdr->caplen = ATM_SLEN(erf_header, NULL);
+			phdr->len = ATM_WLEN(erf_header, NULL);
+			phdr->pkt_encap = erf->atm_encap;
+		}
+
+		if (erf->atm_encap == WTAP_ENCAP_ATM_PDUS) {
+			guint32 atm_hdr;
+
+			wtap_file_read_expected_bytes(&atm_hdr, sizeof(atm_hdr), fh, err);
+			if (bytes_read != NULL) {
+				*bytes_read += sizeof(atm_hdr);
+			}
+			*packet_size -= sizeof(atm_hdr);
+			
+			atm_hdr = g_ntohl(atm_hdr);
+
+			memset(&pseudo_header->atm, 0, sizeof(pseudo_header->atm));
+			pseudo_header->atm.vpi = ((atm_hdr & 0x0ff00000) >> 20);
+			pseudo_header->atm.vci = ((atm_hdr & 0x000ffff0) >>  4);
+			pseudo_header->atm.channel = (erf_header->flags & 0x03);
+
+		} else {
+			skip = 4;
+		}
+		break;
+	case TYPE_ETH:
+		if (phdr != NULL) {
+			phdr->caplen = ETHERNET_SLEN(erf_header, erf);
+			phdr->len = ETHERNET_WLEN(erf_header, erf);
+			phdr->pkt_encap = WTAP_ENCAP_ETHERNET;
+		}
+		skip = 2;
+		break;
+	case TYPE_HDLC_POS:
+		if (phdr != NULL) {
+			phdr->caplen = HDLC_SLEN(erf_header, erf);
+			phdr->len = HDLC_WLEN(erf_header, erf);
+			phdr->pkt_encap = WTAP_ENCAP_CHDLC;
+		}
+		memset(&pseudo_header->p2p, 0, sizeof(pseudo_header->p2p));
+		pseudo_header->p2p.sent = ((erf_header->flags & 0x03) ? TRUE : FALSE);
+		break;
+	default:
+		*err = WTAP_ERR_UNSUPPORTED_ENCAP;
+		return FALSE;
+	}
+
+	if (skip > 0) {
+		if (file_seek(fh, skip, SEEK_CUR, err) == -1) {
+			return FALSE;
+		}
+		if (bytes_read != NULL) {
+			*bytes_read += skip;
+		}
+		*packet_size -= skip;
+	}
+
+	return TRUE;
+}
+
--- /dev/null	Thu Apr 10 23:07:11 2003
+++ wiretap/erf.h	Mon Aug  4 15:01:06 2003
@@ -0,0 +1,105 @@
+/*
+ *
+ * Copyright (c) 2003 Endace Technology Ltd, Hamilton, New Zealand.
+ *                    All rights reserved.
+ *
+ * This software and documentation has been developed by Endace Technology Ltd.
+ * along with the DAG PCI network capture cards. For further information please
+ * visit http://www.endace.com/.
+ *
+ * Redistribution and use of software in source and binary forms and
+ * documentation, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * 1. Redistributions of source code and documentation must retain the above
+ *    copyright notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Endace Technology Ltd.,
+ *      Hamilton, New Zealand, and its contributors.
+ * 4. Neither the name of Endace Technology nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY ENDACE TECHNOLOGY AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ENDACE TECHNOLOGY
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: $
+ */
+
+#ifndef __W_ERF_H__
+#define __W_ERF_H__
+
+/* Record type defines */
+#define TYPE_LEGACY	0
+#define TYPE_HDLC_POS	1
+#define TYPE_ETH	2
+#define TYPE_ATM	3
+#define TYPE_AAL5	4
+
+ /*
+  * The timestamp is 64bit unsigned fixed point little-endian value with
+  * 32 bits for second and 32 bits for fraction. For portablility it is
+  * given as two 32 bit valies here, ts[1] == secs, ts[0] == fraction
+  */
+#ifdef G_HAVE_GINT64
+typedef guint64 erf_timestamp_t;
+#else
+typedef guint32	erf_timestamp_t[2];
+#endif
+
+typedef struct erf_record {
+	erf_timestamp_t	ts;
+	guint8		type;
+	guint8		flags;
+	guint16		rlen;
+	guint16		lctr;
+	guint16		wlen;
+} erf_header_t;
+
+#define MAX_RECORD_LEN	0x10000 /* 64k */
+#define RECORDS_FOR_ERF_CHECK	3
+#define FCS_BITS	32
+
+#ifndef min
+#define min(a, b) ((a) > (b) ? (b) : (a))
+#endif
+
+/*
+ * ATM snaplength
+ */
+#define ATM_SNAPLEN		48
+
+/*
+ * Size of ATM payload 
+ */
+#define ATM_SLEN(h, e)		ATM_SNAPLEN
+#define ATM_WLEN(h, e)		ATM_SNAPLEN
+
+/*
+ * Size of Ethernet payload
+ */
+#define ETHERNET_WLEN(h, e)	(g_htons((h)->wlen) - ((e)->fcs_bits >> 3))
+#define ETHERNET_SLEN(h, e)	min(ETHERNET_WLEN(h, e), g_htons((h)->rlen) - sizeof(*(h)) - 2)
+
+/*
+ * Size of HDLC payload
+ */
+#define HDLC_WLEN(h, e)		(g_htons((h)->wlen) - ((e)->fcs_bits >> 3))
+#define HDLC_SLEN(h, e)		min(HDLC_WLEN(h, e), g_htons((h)->rlen) - sizeof(*(h)))
+
+int erf_open(wtap *wth, int *err);
+
+#endif /* __W_ERF_H__ */

Attachment: atm.erf
Description: Binary data

Attachment: chdlc.erf
Description: Binary data

Attachment: eth.erf
Description: Binary data