diff options
author | Guy Harris <guy@alum.mit.edu> | 2004-02-06 02:11:52 +0000 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2004-02-06 02:11:52 +0000 |
commit | 0875bf3afe0bf45cf1ea1f9174489e991e90b3a5 (patch) | |
tree | 28fc1c8c08b83283a2d470d4c18df720ab88b78a /wiretap | |
parent | 2cbe1a0bf55394b821ad0ade85bc276f1647021b (diff) |
V9 format appears to be used by some versions of EtherPeek, too.
The MediaType field seems to be 0 for the Ethernet captures; however,
the MediaSubType field is different.
The fields in the header are different - we can't use hard-coded offsets
for the fields, we have to process them as a sequence of tag/value
items.
Rename some routines to use the same naming convention as the V9 open
routine rather than the same convention as the V5/V6/V7 read and
seek/read routines.
svn path=/trunk/; revision=9990
Diffstat (limited to 'wiretap')
-rw-r--r-- | wiretap/airopeek9.c | 303 | ||||
-rw-r--r-- | wiretap/file_access.c | 4 |
2 files changed, 220 insertions, 87 deletions
diff --git a/wiretap/airopeek9.c b/wiretap/airopeek9.c index 4598d55ebd..9647c9008a 100644 --- a/wiretap/airopeek9.c +++ b/wiretap/airopeek9.c @@ -1,7 +1,7 @@ /* airopeek9.c - * Routines for opening AiroPeek V9 files + * Routines for opening EtherPeek and AiroPeek V9 files * - * $Id: airopeek9.c,v 1.5 2004/01/27 08:06:11 guy Exp $ + * $Id: airopeek9.c,v 1.6 2004/02/06 02:11:52 guy Exp $ * * Wiretap Library * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu> @@ -39,6 +39,12 @@ * Martin Regner and Guy Harris, and the etherpeek.c file. */ +/* + * NOTE: it says "airopeek" because the first files seen that use this + * format were AiroPeek files; however, EtherPeek files using it have + * also been seen. + */ + /* section header */ typedef struct airopeek_section_header { gint8 section_id[4]; @@ -46,20 +52,18 @@ typedef struct airopeek_section_header { guint32 section_const; } airopeek_section_header_t; -#define AIROPEEK_V9_LENGTH_OFFSET 2 -#define AIROPEEK_V9_TIMESTAMP_LOWER_OFFSET 8 -#define AIROPEEK_V9_TIMESTAMP_UPPER_OFFSET 14 -#define AIROPEEK_V9_FLAGS_OFFSET 20 -#define AIROPEEK_V9_STATUS_OFFSET 22 -#define AIROPEEK_V9_CHANNEL_OFFSET 26 -#define AIROPEEK_V9_RATE_OFFSET 32 -#define AIROPEEK_V9_SIGNAL_PERC_OFFSET 38 -#define AIROPEEK_V9_SIGNAL_DBM_OFFSET 44 -#define AIROPEEK_V9_NOISE_PERC_OFFSET 50 -#define AIROPEEK_V9_NOISE_DBM_OFFSET 56 -#define AIROPEEK_V9_SLICE_LENGTH_OFFSET 62 - -#define AIROPEEK_V9_PKT_SIZE 66 +#define TAG_AIROPEEK_V9_LENGTH 0x0000 +#define TAG_AIROPEEK_V9_TIMESTAMP_LOWER 0x0001 +#define TAG_AIROPEEK_V9_TIMESTAMP_UPPER 0x0002 +#define TAG_AIROPEEK_V9_FLAGS_AND_STATUS 0x0003 +#define TAG_AIROPEEK_V9_CHANNEL 0x0004 +#define TAG_AIROPEEK_V9_RATE 0x0005 +#define TAG_AIROPEEK_V9_SIGNAL_PERC 0x0006 +#define TAG_AIROPEEK_V9_SIGNAL_DBM 0x0007 +#define TAG_AIROPEEK_V9_NOISE_PERC 0x0008 +#define TAG_AIROPEEK_V9_NOISE_DBM 0x0009 +#define TAG_AIROPEEK_V9_UNKNOWN_0x000D 0x000D +#define TAG_AIROPEEK_V9_SLICE_LENGTH 0xffff /* 64-bit time in nano seconds from the (Mac) epoch */ typedef struct airopeek_utime { @@ -69,13 +73,11 @@ typedef struct airopeek_utime { static const unsigned int mac2unix = 2082844800u; -static gboolean airopeek_read_v9(wtap *wth, int *err, gchar **err_info, +static gboolean airopeekv9_read(wtap *wth, int *err, gchar **err_info, long *data_offset); -static gboolean airopeek_seek_read_v9(wtap *wth, long seek_off, +static gboolean airopeekv9_seek_read(wtap *wth, long seek_off, union wtap_pseudo_header *pseudo_header, guchar *pd, int length, int *err, gchar **err_info); -static void airopeek_fill_pseudo_header(union wtap_pseudo_header *pseudo_header, - guchar *ap_pkt); static int wtap_file_read_pattern (wtap *wth, char *pattern, int *err) { @@ -172,7 +174,15 @@ int airopeek9_open(wtap *wth, int *err, gchar **err_info) int ret; guint32 fileVersion; guint32 mediaType; + guint32 mediaSubType; int file_encap; + static const int airopeek9_encap[] = { + WTAP_ENCAP_ETHERNET, + WTAP_ENCAP_UNKNOWN, + WTAP_ENCAP_UNKNOWN, + WTAP_ENCAP_IEEE_802_11_WITH_RADIO + }; + #define NUM_AIROPEEK9_ENCAPS (sizeof airopeek9_encap / sizeof airopeek9_encap[0]) wtap_file_read_unknown_bytes(&ap_hdr, sizeof(ap_hdr), wth->fh, err); @@ -215,7 +225,7 @@ int airopeek9_open(wtap *wth, int *err, gchar **err_info) * Then we should get the length of the "sess" section, check * that it's followed by a little-endian 0x00000200, and then, * when reading the XML, make sure we don't go past the end of - * that section, and skip to the end of tha section when + * that section, and skip to the end of the section when * we have the file version (and possibly check to make sure all * tags are properly opened and closed). */ @@ -227,9 +237,8 @@ int airopeek9_open(wtap *wth, int *err, gchar **err_info) *err_info = g_strdup("airopeekv9: <MediaType> tag not found"); return -1; } - /* XXX - this appears to be 0, which is also the media type for - 802.11 in the older AiroPeek format; should we require it to be - 0? And should we check the MediaSubType value as well? */ + /* XXX - this appears to be 0 in both the EtherPeek and AiroPeek + files we've seen; should we require it to be 0? */ ret = wtap_file_read_number (wth, &mediaType, err); if (ret == -1) return -1; @@ -239,6 +248,30 @@ int airopeek9_open(wtap *wth, int *err, gchar **err_info) return -1; } + ret = wtap_file_read_pattern (wth, "<MediaSubType>", err); + if (ret == -1) + return -1; + if (ret == 0) { + *err = WTAP_ERR_UNSUPPORTED; + *err_info = g_strdup("airopeekv9: <MediaSubType> tag not found"); + return -1; + } + ret = wtap_file_read_number (wth, &mediaSubType, err); + if (ret == -1) + return -1; + if (ret == 0) { + *err = WTAP_ERR_UNSUPPORTED; + *err_info = g_strdup("airopeekv9: <MediaSubType> value not found"); + return -1; + } + if (mediaSubType >= NUM_AIROPEEK9_ENCAPS + || airopeek9_encap[mediaSubType] == WTAP_ENCAP_UNKNOWN) { + *err = WTAP_ERR_UNSUPPORTED_ENCAP; + *err_info = g_strdup_printf("airopeekv9: network type %u unknown or unsupported", + mediaSubType); + return -1; + } + ret = wtap_file_read_pattern (wth, "pkts", err); if (ret == -1) return -1; @@ -257,59 +290,165 @@ int airopeek9_open(wtap *wth, int *err, gchar **err_info) wth->data_offset = file_tell (wth->fh); - file_encap = WTAP_ENCAP_IEEE_802_11_WITH_RADIO; + file_encap = airopeek9_encap[mediaSubType]; wth->file_type = WTAP_FILE_AIROPEEK_V9; wth->file_encap = file_encap; - wth->subtype_read = airopeek_read_v9; - wth->subtype_seek_read = airopeek_seek_read_v9; + wth->subtype_read = airopeekv9_read; + wth->subtype_seek_read = airopeekv9_seek_read; wth->snapshot_length = 0; /* not available in header */ return 1; } -static gboolean airopeek_read_v9(wtap *wth, int *err, gchar **err_info _U_, - long *data_offset) -{ - guchar ap_pkt[AIROPEEK_V9_PKT_SIZE]; +typedef struct { guint32 length; guint32 sliceLength; airopeek_utime timestamp; + struct ieee_802_11_phdr ieee_802_11; +} hdr_info_t; + +/* + * Process the packet header. + * + * XXX - we should supply the additional radio information; + * the pseudo-header should probably be supplied in a fashion + * similar to the new BSD radio header, so that the 802.11 + * dissector can determine which, if any, information items + * are present. + */ +static int +airopeekv9_process_header(FILE_T fh, hdr_info_t *hdr_info, int *err) +{ + long header_len = 0; + int bytes_read; + guint8 tag_value[6]; + guint16 tag; + + hdr_info->ieee_802_11.fcs_len = 0; /* no FCS for 802.11 */ + + /* Extract the fields from the packet header */ + do { + /* Get the tag and value. + XXX - this assumes all values are 4 bytes long. */ + bytes_read = file_read(tag_value, 1, sizeof tag_value, fh); + if (bytes_read != (int) sizeof tag_value) { + *err = file_error(fh); + if (*err == 0) { + if (bytes_read > 0) + *err = WTAP_ERR_SHORT_READ; + else if (bytes_read == 0) { + /* + * Short read if we've read something already; + * just an EOF if we haven't. + */ + if (header_len != 0) + *err = WTAP_ERR_SHORT_READ; + } + } + return -1; + } + header_len += sizeof(tag_value); + tag = pletohs(&tag_value[0]); + switch (tag) { + + case TAG_AIROPEEK_V9_LENGTH: + hdr_info->length = pletohl(&tag_value[2]); + break; + + case TAG_AIROPEEK_V9_TIMESTAMP_LOWER: + hdr_info->timestamp.lower = pletohl(&tag_value[2]); + break; + + case TAG_AIROPEEK_V9_TIMESTAMP_UPPER: + hdr_info->timestamp.upper = pletohl(&tag_value[2]); + break; + + case TAG_AIROPEEK_V9_CHANNEL: + hdr_info->ieee_802_11.channel = pletohl(&tag_value[2]); + break; + + case TAG_AIROPEEK_V9_RATE: + hdr_info->ieee_802_11.data_rate = pletohl(&tag_value[2]); + break; + + case TAG_AIROPEEK_V9_SIGNAL_PERC: + hdr_info->ieee_802_11.signal_level = pletohl(&tag_value[2]); + break; + + case TAG_AIROPEEK_V9_SIGNAL_DBM: + /* XXX - not used yet */ + break; + + case TAG_AIROPEEK_V9_NOISE_PERC: + /* XXX - not used yet */ + break; + + case TAG_AIROPEEK_V9_NOISE_DBM: + /* XXX - not used yet */ + break; + + case TAG_AIROPEEK_V9_UNKNOWN_0x000D: + /* XXX - seen in an EtherPeek capture; value unknown */ + break; + + case TAG_AIROPEEK_V9_SLICE_LENGTH: + hdr_info->sliceLength = pletohl(&tag_value[2]); + break; + + default: + break; + } + } while (tag != TAG_AIROPEEK_V9_SLICE_LENGTH); /* last tag */ + + return header_len; +} + +static gboolean airopeekv9_read(wtap *wth, int *err, gchar **err_info _U_, + long *data_offset) +{ + hdr_info_t hdr_info; + int hdrlen; double t; *data_offset = wth->data_offset; - wtap_file_read_expected_bytes(ap_pkt, sizeof(ap_pkt), wth->fh, err); - wth->data_offset += sizeof(ap_pkt); - - /* Extract the fields from the packet */ - length = pletohl(&ap_pkt[AIROPEEK_V9_LENGTH_OFFSET]); - sliceLength = pletohl(&ap_pkt[AIROPEEK_V9_SLICE_LENGTH_OFFSET]); - timestamp.upper = pletohl(&ap_pkt[AIROPEEK_V9_TIMESTAMP_UPPER_OFFSET]); - timestamp.lower = pletohl(&ap_pkt[AIROPEEK_V9_TIMESTAMP_LOWER_OFFSET]); + /* Process the packet header. */ + hdrlen = airopeekv9_process_header(wth->fh, &hdr_info, err); + if (hdrlen == -1) + return FALSE; + wth->data_offset += hdrlen; /* force sliceLength to be the actual length of the packet */ - if (sliceLength == 0) { - sliceLength = length; - } + if (hdr_info.sliceLength == 0) + hdr_info.sliceLength = hdr_info.length; /* fill in packet header length values before slicelength may be adjusted */ - wth->phdr.len = length; - wth->phdr.caplen = sliceLength; + wth->phdr.len = hdr_info.length; + wth->phdr.caplen = hdr_info.sliceLength; + + switch (wth->file_encap) { - airopeek_fill_pseudo_header(&wth->pseudo_header, ap_pkt); + case WTAP_ENCAP_IEEE_802_11_WITH_RADIO: + wth->pseudo_header.ieee_802_11 = hdr_info.ieee_802_11; + break; + + case WTAP_ENCAP_ETHERNET: + wth->pseudo_header.eth.fcs_len = 0; /* XXX - always? */ + break; + } /* read the frame data */ - buffer_assure_space(wth->frame_buffer, sliceLength); + buffer_assure_space(wth->frame_buffer, hdr_info.sliceLength); wtap_file_read_expected_bytes(buffer_start_ptr(wth->frame_buffer), - sliceLength, wth->fh, err); - wth->data_offset += sliceLength; + hdr_info.sliceLength, wth->fh, err); + wth->data_offset += hdr_info.sliceLength; /* recalculate and fill in packet time stamp */ - t = (double) timestamp.lower + - (double) timestamp.upper * 4294967296.0; + t = (double) hdr_info.timestamp.lower + + (double) hdr_info.timestamp.upper * 4294967296.0; t = t / 1000.0; /* nano seconds -> micro seconds */ t -= (double) mac2unix * 1000000.0; @@ -317,15 +456,20 @@ static gboolean airopeek_read_v9(wtap *wth, int *err, gchar **err_info _U_, wth->phdr.ts.tv_usec = (guint32) (t - (double) wth->phdr.ts.tv_sec * 1000000.0); - /* - * The last 4 bytes sometimes contains the FCS but on a lot of - * interfaces these are zero. To eleminate problems we reduce - * the length by 4. - * - * XXX - is there any way to find out whether it's an FCS or not? - */ - wth->phdr.len -= 4; - wth->phdr.caplen -= 4; + switch (wth->file_encap) { + + case WTAP_ENCAP_IEEE_802_11_WITH_RADIO: + /* + * The last 4 bytes sometimes contains the FCS but on a lot of + * interfaces these are zero. To eleminate problems we reduce + * the length by 4. + * + * XXX - is there any way to find out whether it's an FCS or not? + */ + wth->phdr.len -= 4; + wth->phdr.caplen -= 4; + break; + } wth->phdr.pkt_encap = wth->file_encap; return TRUE; @@ -333,19 +477,29 @@ static gboolean airopeek_read_v9(wtap *wth, int *err, gchar **err_info _U_, static gboolean -airopeek_seek_read_v9(wtap *wth, long seek_off, +airopeekv9_seek_read(wtap *wth, long seek_off, union wtap_pseudo_header *pseudo_header, guchar *pd, int length, int *err, gchar **err_info _U_) { - guchar ap_pkt[AIROPEEK_V9_PKT_SIZE]; + hdr_info_t hdr_info; if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1) return FALSE; - /* Read the packet header. */ - wtap_file_read_expected_bytes(ap_pkt, sizeof(ap_pkt), wth->random_fh, err); + /* Process the packet header. */ + if (airopeekv9_process_header(wth->random_fh, &hdr_info, err) == -1) + return FALSE; + + switch (wth->file_encap) { + + case WTAP_ENCAP_IEEE_802_11_WITH_RADIO: + pseudo_header->ieee_802_11 = hdr_info.ieee_802_11; + break; - airopeek_fill_pseudo_header(pseudo_header, ap_pkt); + case WTAP_ENCAP_ETHERNET: + pseudo_header->eth.fcs_len = 0; /* XXX - always? */ + break; + } /* * XXX - should "errno" be set in "wtap_file_read_expected_bytes()"? @@ -354,24 +508,3 @@ airopeek_seek_read_v9(wtap *wth, long seek_off, wtap_file_read_expected_bytes(pd, length, wth->random_fh, err); return TRUE; } - -/* - * Fill the pseudo header with radio information. - * XXX - we should supply the additional information; - * the pseudo-header should probably be supplied in a fashion - * similar to the new BSD radio header, so that the 802.11 - * dissector can determine which, if any, information items - * are present. - */ -static void -airopeek_fill_pseudo_header(union wtap_pseudo_header *pseudo_header, - guchar *ap_pkt) -{ - pseudo_header->ieee_802_11.fcs_len = 0; /* no FCS */ - pseudo_header->ieee_802_11.channel = - pletohl(&ap_pkt[AIROPEEK_V9_CHANNEL_OFFSET]); - pseudo_header->ieee_802_11.data_rate = - pletohl(&ap_pkt[AIROPEEK_V9_RATE_OFFSET]); - pseudo_header->ieee_802_11.signal_level = - pletohl(&ap_pkt[AIROPEEK_V9_SIGNAL_PERC_OFFSET]); -} diff --git a/wiretap/file_access.c b/wiretap/file_access.c index b6cb870ded..d7cfa4bbaa 100644 --- a/wiretap/file_access.c +++ b/wiretap/file_access.c @@ -1,6 +1,6 @@ /* file_access.c * - * $Id: file_access.c,v 1.9 2004/01/25 21:55:13 guy Exp $ + * $Id: file_access.c,v 1.10 2004/02/06 02:11:52 guy Exp $ * * Wiretap Library * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu> @@ -452,7 +452,7 @@ static const struct file_type_info { network_instruments_dump_can_write_encap, network_instruments_dump_open }, /* WTAP_FILE_AIROPEEK_V9 */ - { "AiroPeek trace (V9 file format)", NULL, + { "EtherPeek/AiroPeek trace (V9 file format)", NULL, NULL, NULL }, }; |