aboutsummaryrefslogtreecommitdiffstats
path: root/wiretap/airopeek9.c
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2004-02-06 02:11:52 +0000
committerGuy Harris <guy@alum.mit.edu>2004-02-06 02:11:52 +0000
commit0875bf3afe0bf45cf1ea1f9174489e991e90b3a5 (patch)
tree28fc1c8c08b83283a2d470d4c18df720ab88b78a /wiretap/airopeek9.c
parent2cbe1a0bf55394b821ad0ade85bc276f1647021b (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/airopeek9.c')
-rw-r--r--wiretap/airopeek9.c303
1 files changed, 218 insertions, 85 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]);
-}