Ethereal-dev: [Ethereal-dev] PATCH: ethereal file reader
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Daniel Thompson <d.thompson@xxxxxxx>
Date: 22 Feb 2001 20:40:17 +0000
Hi Folks. Attached is a patch to provide limited etherpeek file format support to ethereal. It provides read only support for macintosh formats V5, 6 & 7. If you are happy with its quality please commit it to CVS at this point (the patch is for 0.8.15 - let me know if it does not apply cleanly to the wavefront). Note that this code has not been heavily tested as I do not have very many packet captures to test it with (one V7 file in fact). If anyone has any etherpeek captures lying around then let me know, I don't like providing such sparsely tested code but ... Cheers Daniel --xx-- -- Daniel Thompson (Merlin) <d.thompson@xxxxxxx> How many dull people does it take to change a light bulb? One.
diff -Naur ethereal-0.8.15/wiretap/Makefile.am ethereal/wiretap/Makefile.am --- ethereal-0.8.15/wiretap/Makefile.am Tue Sep 19 18:22:09 2000 +++ ethereal/wiretap/Makefile.am Sat Feb 3 09:41:23 2001 @@ -42,6 +42,8 @@ buffer.h \ csids.c \ csids.h \ + etherpeek.c \ + etherpeek.h \ file.c \ file_wrappers.c \ file_wrappers.h \ diff -Naur ethereal-0.8.15/wiretap/etherpeek.c ethereal/wiretap/etherpeek.c --- ethereal-0.8.15/wiretap/etherpeek.c Thu Jan 1 01:00:00 1970 +++ ethereal/wiretap/etherpeek.c Thu Feb 22 20:19:56 2001 @@ -0,0 +1,314 @@ +/* etherpeek.c + * Routines for opening etherpeek files + * Copyright (c) 2001, Daniel Thompson <d.thompson@xxxxxxx> + * + * $Id: $ + * + * Wiretap Library + * Copyright (c) 1998 by Gilbert Ramirez <gram@xxxxxxxxxx> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include <errno.h> +#include <string.h> +#include "wtap-int.h" +#include "file_wrappers.h" +#include "buffer.h" +#include "snoop.h" +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif + +/* CREDITS + * + * This file decoder could not have been writen without examining how + * tcptrace (http://www.tcptrace.org/) handles etherpeek files. + */ + +/* master header */ +typedef struct etherpeek_master_header { + guint8 version; + guint8 status; +} etherpeek_master_header_t; +#define ETHERPEEK_MASTER_HDR_SIZE 2 + +/* secondary header (Mac V5,V6,V7) */ +typedef struct etherpeek_m567_header { + guint32 filelength; + guint32 numPackets; + guint32 timeDate; + guint32 timeStart; + guint32 timeStop; + guint32 reserved[7]; +} etherpeek_m567_header_t; +#define ETHERPEEK_M567_HDR_SIZE 48 + +/* full header */ +typedef struct etherpeek_header { + etherpeek_master_header_t master; + union { + etherpeek_m567_header_t m567; + } secondary; +} etherpeek_header_t; + +/* packet header (Mac V5, V6) */ +typedef struct etherpeek_m56_packet { + guint16 length; + guint16 sliceLength; + guint8 flags; + guint8 status; + guint32 timestamp; + guint16 destNum; + guint16 srcNum; + guint16 protoNum; + char protoStr[8]; +} etherpeek_m56_packet_t; +#define ETHERPEEK_M56_PKT_SIZE 24 + +/* 64-bit time in micro seconds from the (Mac) epoch */ +typedef struct etherpeek_utime { + guint32 upper; + guint32 lower; +} etherpeek_utime; + +/* packet header (Mac V7) */ +typedef struct etherpeek_m7_packet { + guint16 protoNum; + guint16 length; + guint16 sliceLength; + guint8 flags; + guint8 status; + etherpeek_utime + timestamp; +} etherpeek_m7_packet_t; +#define ETHERPEEK_M7_PKT_SIZE 16 + +typedef struct etherpeek_encap_lookup { + guint16 protoNum; + int encap; +} etherpeek_encap_lookup_t; + +static const unsigned int mac2unix = 2082844800u; +static const etherpeek_encap_lookup_t etherpeek_encap[] = { + { 1400, WTAP_ENCAP_ETHERNET } +}; +#define NUM_ETHERPEEK_ENCAPS \ + (sizeof (etherpeek_encap) / sizeof (etherpeek_encap[0])) + +static gboolean etherpeek_read_m7(wtap *wth, int *err, int *data_offset); +static gboolean etherpeek_read_m56(wtap *wth, int *err, int *data_offset); + +int etherpeek_open(wtap *wth, int *err) +{ + etherpeek_header_t ep_hdr; + + /* etherpeek files to not start with a magic value large enough + * to be unique hence we use the following algorithm to determine + * the type of an unknown file + * - populate the master header and reject file if there is no match + * - populate the secondary header and check that the reserved space + * is zero; there is an obvious flaw here so this algorithm will + * probably need to be revisiting when improving etherpeek + * support + */ + + file_seek(wth->fh, 0, SEEK_SET); + wth->data_offset = 0; + + g_assert(sizeof(ep_hdr.master) == ETHERPEEK_MASTER_HDR_SIZE); + wtap_file_read_unknown_bytes( + &ep_hdr.master, sizeof(ep_hdr.master), wth->fh, err); + wth->data_offset += sizeof(ep_hdr.master); + + /* switch on the file version */ + switch (ep_hdr.master.version) { + case 5: + case 6: + case 7: + /* get the secondary header */ + g_assert(sizeof(ep_hdr.secondary.m567) == + ETHERPEEK_M567_HDR_SIZE); + wtap_file_read_unknown_bytes( + &ep_hdr.secondary.m567, + sizeof(ep_hdr.secondary.m567), wth->fh, err); + wth->data_offset += sizeof(ep_hdr.secondary.m567); + + if ((0 != ep_hdr.secondary.m567.reserved[0]) || + (0 != ep_hdr.secondary.m567.reserved[1]) || + (0 != ep_hdr.secondary.m567.reserved[2]) || + (0 != ep_hdr.secondary.m567.reserved[3])) { + /* still unknown */ + return 0; + } + + /* we have a match for a Mac V5, V6 or V7, + * so it is worth preforming byte swaps + */ + ep_hdr.secondary.m567.filelength = + ntohl(ep_hdr.secondary.m567.filelength); + ep_hdr.secondary.m567.numPackets = + ntohl(ep_hdr.secondary.m567.numPackets); + ep_hdr.secondary.m567.timeDate = + ntohl(ep_hdr.secondary.m567.timeDate); + ep_hdr.secondary.m567.timeStart = + ntohl(ep_hdr.secondary.m567.timeStart); + ep_hdr.secondary.m567.timeStop = + ntohl(ep_hdr.secondary.m567.timeStop); + + /* populate the pseudo header */ + wth->pseudo_header.etherpeek.reference_time.tv_sec = + ep_hdr.secondary.m567.timeDate - mac2unix; + wth->pseudo_header.etherpeek.reference_time.tv_usec = + 0; + break; + default: + return 0; + } + + /* at this point we have recognised the file type and have populated + * the whole ep_hdr structure in host byte order + */ + + switch (ep_hdr.master.version) { + case 5: + case 6: + wth->file_type = WTAP_FILE_ETHERPEEK_MAC_V56; + wth->subtype_read = etherpeek_read_m56; + wth->subtype_seek_read = wtap_def_seek_read; + break; + case 7: + wth->file_type = WTAP_FILE_ETHERPEEK_MAC_V7; + wth->subtype_read = etherpeek_read_m7; + wth->subtype_seek_read = wtap_def_seek_read; + break; + default: + /* this is impossible */ + g_assert_not_reached(); + }; + + wth->file_encap = WTAP_ENCAP_PER_PACKET; + wth->snapshot_length = 16384; /* just guessing */ + + return 1; +} + +static gboolean etherpeek_read_m7(wtap *wth, int *err, int *data_offset) +{ + etherpeek_m7_packet_t ep_pkt; + double t; + int i; + + g_assert(sizeof(ep_pkt) == ETHERPEEK_M7_PKT_SIZE); + wtap_file_read_expected_bytes(&ep_pkt, sizeof(ep_pkt), wth->fh, err); + wth->data_offset += sizeof(ep_pkt); + + /* byte swaps */ + ep_pkt.protoNum = ntohs(ep_pkt.protoNum); + ep_pkt.length = ntohs(ep_pkt.length); + ep_pkt.sliceLength = ntohs(ep_pkt.sliceLength); + ep_pkt.timestamp.upper = ntohl(ep_pkt.timestamp.upper); + ep_pkt.timestamp.lower = ntohl(ep_pkt.timestamp.lower); + + /* force sliceLength to be the actual length of the packet */ + if (0 == ep_pkt.sliceLength) { + ep_pkt.sliceLength = ep_pkt.length; + } + + /* test for corrupt data */ + if (ep_pkt.sliceLength > WTAP_MAX_PACKET_SIZE) { + *err = WTAP_ERR_BAD_RECORD; + return FALSE; + } + + *data_offset = wth->data_offset; + + /* read the frame data */ + buffer_assure_space(wth->frame_buffer, ep_pkt.sliceLength); + wtap_file_read_expected_bytes(buffer_start_ptr(wth->frame_buffer), + ep_pkt.sliceLength, wth->fh, err); + wth->data_offset += ep_pkt.sliceLength; + + /* fill in packet header values */ + wth->phdr.len = ep_pkt.length; + wth->phdr.caplen = ep_pkt.sliceLength; + + t = (double) ep_pkt.timestamp.lower + + (double) ep_pkt.timestamp.upper * 4294967296.0; + t -= (double) mac2unix * 1000000.0; + wth->phdr.ts.tv_sec = (time_t) (t/1000000.0); + wth->phdr.ts.tv_usec = (guint32) (t - (double) wth->phdr.ts.tv_sec * + 1000000.0); + wth->phdr.pkt_encap = WTAP_ENCAP_UNKNOWN; + for (i=0; i<NUM_ETHERPEEK_ENCAPS; i++) { + if (etherpeek_encap[i].protoNum == ep_pkt.protoNum) { + wth->phdr.pkt_encap = etherpeek_encap[i].encap; + } + } + + return TRUE; +} + +static gboolean etherpeek_read_m56(wtap *wth, int *err, int *data_offset) +{ + etherpeek_m56_packet_t ep_pkt; + int i; + + g_assert(sizeof(ep_pkt) == ETHERPEEK_M56_PKT_SIZE); + wtap_file_read_expected_bytes(&ep_pkt, sizeof(ep_pkt), wth->fh, err); + wth->data_offset += sizeof(ep_pkt); + + /* byte swaps */ + ep_pkt.length = ntohs(ep_pkt.length); + ep_pkt.sliceLength = ntohs(ep_pkt.sliceLength); + ep_pkt.timestamp = ntohl(ep_pkt.timestamp); + ep_pkt.destNum = ntohs(ep_pkt.destNum); + ep_pkt.srcNum = ntohs(ep_pkt.srcNum); + ep_pkt.protoNum = ntohs(ep_pkt.protoNum); + + /* force sliceLength to be the actual length of the packet */ + if (0 == ep_pkt.sliceLength) { + ep_pkt.sliceLength = ep_pkt.length; + } + + /* test for corrupt data */ + if (ep_pkt.sliceLength > WTAP_MAX_PACKET_SIZE) { + *err = WTAP_ERR_BAD_RECORD; + return FALSE; + } + + *data_offset = wth->data_offset; + + /* fill in packet header values */ + wth->phdr.len = ep_pkt.length; + wth->phdr.caplen = ep_pkt.sliceLength; + /* timestamp is in milliseconds since reference_time */ + wth->phdr.ts.tv_sec = wth->pseudo_header.etherpeek. + reference_time.tv_sec + (ep_pkt.timestamp / 1000); + wth->phdr.ts.tv_usec = 1000 * (ep_pkt.timestamp % 1000); + + wth->phdr.pkt_encap = WTAP_ENCAP_UNKNOWN; + for (i=0; i<NUM_ETHERPEEK_ENCAPS; i++) { + if (etherpeek_encap[i].protoNum == ep_pkt.protoNum) { + wth->phdr.pkt_encap = etherpeek_encap[i].encap; + } + } + + return TRUE; +} diff -Naur ethereal-0.8.15/wiretap/etherpeek.h ethereal/wiretap/etherpeek.h --- ethereal-0.8.15/wiretap/etherpeek.h Thu Jan 1 01:00:00 1970 +++ ethereal/wiretap/etherpeek.h Sat Feb 3 09:37:25 2001 @@ -0,0 +1,29 @@ +/* etherpeek.h + * + * $Id: snoop.h,v 1.8 2000/08/11 13:32:34 deniel Exp $ + * + * Wiretap Library + * Copyright (c) 1998 by Gilbert Ramirez <gram@xxxxxxxxxx> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef __W_ETHERPEEK_H__ +#define __W_ETHERPEEK_H__ + +int etherpeek_open(wtap *wth, int *err); + +#endif diff -Naur ethereal-0.8.15/wiretap/file.c ethereal/wiretap/file.c --- ethereal-0.8.15/wiretap/file.c Tue Sep 19 18:22:09 2000 +++ ethereal/wiretap/file.c Sat Feb 3 09:50:09 2001 @@ -59,6 +59,7 @@ #include "i4btrace.h" #include "csids.h" #include "pppdump.h" +#include "etherpeek.h" /* The open_file_* routines should return: * @@ -96,6 +97,7 @@ radcom_open, nettl_open, pppdump_open, + etherpeek_open, /* Files whose magic headers are in text *somewhere* in the * file (usually because the trace is just a saved copy of @@ -345,6 +347,13 @@ { "pppd log (pppdump format)", NULL, NULL, NULL }, + /* WTAP_FILE_ETHERPEEK_MAC_V56 */ + { "Etherpeek trace (Macintosh V5 & V6)", NULL, + NULL, NULL }, + + /* WTAP_FILE_ETHERPEEK_MAC_V7 */ + { "Etherpeek trace (Macintosh V7)", NULL, + NULL, NULL }, }; /* Name that should be somewhat descriptive. */ diff -Naur ethereal-0.8.15/wiretap/wtap.h ethereal/wiretap/wtap.h --- ethereal-0.8.15/wiretap/wtap.h Mon Jan 8 22:18:22 2001 +++ ethereal/wiretap/wtap.h Thu Feb 22 20:18:56 2001 @@ -129,9 +129,11 @@ #define WTAP_FILE_I4BTRACE 22 #define WTAP_FILE_CSIDS 23 #define WTAP_FILE_PPPDUMP 24 +#define WTAP_FILE_ETHERPEEK_MAC_V56 25 +#define WTAP_FILE_ETHERPEEK_MAC_V7 26 /* last WTAP_FILE_ value + 1 */ -#define WTAP_NUM_FILE_TYPES 25 +#define WTAP_NUM_FILE_TYPES 27 /* * Maximum packet size we'll support. @@ -189,6 +191,10 @@ guint32 task; /* Task number */ }; +/* Packet "pseudo_header" for etherpeek capture files. */ +struct etherpeek_phdr { + struct timeval reference_time; +}; struct p2p_phdr { gboolean sent; /* TRUE=sent, FALSE=received */ @@ -251,6 +257,7 @@ struct x25_phdr x25; struct ngsniffer_atm_phdr ngsniffer_atm; struct ascend_phdr ascend; + struct etherpeek_phdr etherpeek; struct p2p_phdr p2p; };
- Follow-Ups:
- Re: [Ethereal-dev] PATCH: ethereal file reader
- From: Guy Harris
- Re: [Ethereal-dev] PATCH: ethereal file reader
- Prev by Date: [Ethereal-dev] Re: [Ethereal-users] protocol tree
- Next by Date: Re: [Ethereal-dev] PATCH: ethereal file reader
- Previous by thread: [Ethereal-dev] Re: [Ethereal-users] protocol tree
- Next by thread: Re: [Ethereal-dev] PATCH: ethereal file reader
- Index(es):