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
- Follow-Ups:
- Prev by Date: [Ethereal-dev] What that arrays of structs like udphstruct for
- Next by Date: [Ethereal-dev] Gtk-CRITICAL **: file gtkobject.c: line 1033 (gtk_object_set_data): assertion `object != NULL' failed.
- Previous by thread: Re: [Ethereal-dev] What that arrays of structs like udphstruct for
- Next by thread: Re: [Ethereal-dev] Wiretap patch to support reading from Endace ERF trace files
- Index(es):