/* vwr.c
* Copyright (c) 2011 by Tom Alexander <talexander@ixiacom.com>
- *
+ *
* $Id$
*
* Wiretap Library
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
-#ifdef HAVE_CONFIG_H
#include "config.h"
-#endif
#include <errno.h>
#include <string.h>
} stats_common_fields;
/* Size of those fields - regardless of how the compiler packs them */
-#define STATS_COMMON_FIELDS_LEN (2+2+2+2+4+2+2+4+4+8+8+4+4)
+#define STATS_COMMON_FIELDS_LEN (2+2+2+2+4+2+2+4+4+8+8+4+4)
/* Veriwave-specific extended radiotap header fields (following vwr_rtap_hdr above) */
/* structure elements correspond one-to-one with the RADIOTAP_PRESENT bitmask below */
} ext_rtap_fields;
/* Size of those fields - regardless of how the compiler packs them */
-#define EXT_RTAP_FIELDS_LEN (2+2+2+1+1+1+1+2+2+2+4)
+#define EXT_RTAP_FIELDS_LEN (2+2+2+1+1+1+1+2+2+2+4)
/* Veriwave-specific Ethernettap header */
typedef struct {
} stats_ethernettap_fields;
/* Size of those fields - regardless of how the compiler packs them */
-#define STATS_ETHERNETTAP_FIELDS_LEN (2+2+2+2+4+4+4)
+#define STATS_ETHERNETTAP_FIELDS_LEN (2+2+2+2+4+4+4)
/* the bitmap offsets of the bits in it_present, above */
/* also lists the expected field sizes in bytes */
static void setup_defaults(vwr_t *, guint16);
static gboolean vwr_read(wtap *, int *, gchar **, gint64 *);
-static gboolean vwr_seek_read(wtap *, gint64, union wtap_pseudo_header *, guchar *,
+static gboolean vwr_seek_read(wtap *, gint64, struct wtap_pkthdr *phdr, guchar *,
int, int *, gchar **);
static gboolean vwr_read_rec_header(vwr_t *, FILE_T, int *, int *, int *, gchar **);
-static void vwr_read_rec_data(wtap *, guint8 *, guint8 *, int);
+static void vwr_read_rec_data(wtap *, struct wtap_pkthdr *, guint8 *, guint8 *, int);
static int vwr_get_fpga_version(wtap *, int *, gchar **);
-static void vwr_read_rec_data_vVW510021(wtap *, guint8 *, guint8 *, int, int);
-static void vwr_read_rec_data_ethernet(wtap *, guint8 *, guint8 *, int, int);
+static void vwr_read_rec_data_vVW510021(wtap *, struct wtap_pkthdr *, guint8 *, guint8 *, int, int);
+static void vwr_read_rec_data_ethernet(wtap *, struct wtap_pkthdr *, guint8 *, guint8 *, int, int);
-static int find_signature(register guint8 *, int, register guint32, register guint8);
+static int find_signature(register guint8 *, int, int, register guint32, register guint8);
static guint64 get_signature_ts(register guint8 *, int);
/* open a .vwr file for reading */
wth->file_type = WTAP_FILE_VWR_80211;
wth->file_encap = WTAP_ENCAP_IXVERIWAVE;
- }
+ }
else if (fpgaVer == vVW510012_E_FPGA) {
wth->file_type = WTAP_FILE_VWR_ETH;
wth->file_encap = WTAP_ENCAP_IXVERIWAVE;
return(FALSE);
}
-
+ if (rec_size < (int)vwr->STATS_LEN) {
+ *err = file_error(wth->fh, err_info);
+ if (*err == 0)
+ *err_info = g_strdup_printf("vwr: Invalid record length %d (must be at least %u)", rec_size, vwr->STATS_LEN);
+ *err = WTAP_ERR_BAD_FILE;
+ return(FALSE);
+ }
/* before writing anything out, make sure the buffer has enough space for everything */
if ((vwr->FPGA_VERSION == vVW510021_W_FPGA) || (vwr->FPGA_VERSION == vVW510006_W_FPGA) )
switch (vwr->FPGA_VERSION)
{
case vVW510006_W_FPGA:
- vwr_read_rec_data(wth, data_ptr, rec, rec_size);
+ vwr_read_rec_data(wth, &wth->phdr, data_ptr, rec, rec_size);
break;
case vVW510021_W_FPGA:
- vwr_read_rec_data_vVW510021(wth, data_ptr, rec, rec_size, IS_TX);
+ vwr_read_rec_data_vVW510021(wth, &wth->phdr, data_ptr, rec, rec_size, IS_TX);
break;
case vVW510012_E_FPGA:
- vwr_read_rec_data_ethernet(wth, data_ptr, rec, rec_size, IS_TX);
+ vwr_read_rec_data_ethernet(wth, &wth->phdr, data_ptr, rec, rec_size, IS_TX);
break;
case vVW510024_E_FPGA:
- vwr_read_rec_data_ethernet(wth, data_ptr, rec, rec_size, IS_TX);
+ vwr_read_rec_data_ethernet(wth, &wth->phdr, data_ptr, rec, rec_size, IS_TX);
break;
}
/* read a random frame in the middle of a file; the start of the PLCP frame is @ seek_off */
-static gboolean vwr_seek_read(wtap *wth, gint64 seek_off, union wtap_pseudo_header *pseudo_header _U_, guchar *pd, int pkt_size _U_,
+static gboolean vwr_seek_read(wtap *wth, gint64 seek_off,
+ struct wtap_pkthdr *phdr, guchar *pd, int pkt_size _U_,
int *err, gchar **err_info)
{
vwr_t *vwr = (vwr_t *)wth->priv;
/* now format up the frame data into the passed buffer, according to the FPGA type */
switch (vwr->FPGA_VERSION) {
case vVW510006_W_FPGA:
- vwr_read_rec_data(wth, pd, rec, rec_size);
+ vwr_read_rec_data(wth, phdr, pd, rec, rec_size);
break;
case vVW510021_W_FPGA:
- vwr_read_rec_data_vVW510021(wth, pd, rec, rec_size, IS_TX);
+ vwr_read_rec_data_vVW510021(wth, phdr, pd, rec, rec_size, IS_TX);
break;
case vVW510012_E_FPGA:
- vwr_read_rec_data_ethernet(wth, pd, rec, rec_size, IS_TX);
+ vwr_read_rec_data_ethernet(wth, phdr, pd, rec, rec_size, IS_TX);
break;
case vVW510024_E_FPGA:
- vwr_read_rec_data_ethernet(wth, pd, rec, rec_size, IS_TX);
+ vwr_read_rec_data_ethernet(wth, phdr, pd, rec, rec_size, IS_TX);
break;
}
static gboolean vwr_read_rec_header(vwr_t *vwr, FILE_T fh, int *rec_size, int *IS_TX, int *err, gchar **err_info)
{
- int bytes_read;
int f_len, v_type;
guint8 header[16];
/* variable-length item, we read the variable length item out and discard it */
/* if we find a frame, we return (with the header in the passed buffer) */
while (1) {
- if ((bytes_read = file_read(header, 16, fh)) != 16) {
+ if (file_read(header, 16, fh) != 16) {
*err = file_error(fh, err_info);
return(FALSE);
}
int rec_size = 0;
guint8 i;
guint8 *s_510006_ptr = NULL;
- guint8 *s_510024_ptr = NULL;
+ guint8 *s_510024_ptr = NULL;
guint8 *s_510012_ptr = NULL; /* stats pointers */
gint64 filePos = -1;
guint32 frame_type = 0;
/* if we don't get it all, assume this isn't a vwr file */
if (file_read(rec, rec_size, wth->fh) != rec_size) {
*err = file_error(wth->fh, err_info);
- if (*err == 0)
- return(UNKNOWN_FPGA); /* short read - not a vwr file */
- return(-1);
+ if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
+ return(-1);
+ return(UNKNOWN_FPGA); /* short read - not a vwr file */
}
if (rec_size > v22_W_STATS_LEN) {
s_510006_ptr = &(rec[rec_size - v22_W_STATS_LEN]); /* point to 510006 WLAN */
/* stats block */
-
+
data_length = pntohs(&s_510006_ptr[v22_W_OCTET_OFF]);
i = 0;
while (((data_length + i) % 4) != 0)
frame_type = pntohl(&s_510006_ptr[v22_W_FRAME_TYPE_OFF]);
if (rec_size == (data_length + v22_W_STATS_LEN + i) && (frame_type & v22_W_IS_80211) == 0x1000000) {
- fpga_version = vVW510006_W_FPGA;
+ fpga_version = vVW510006_W_FPGA;
}
}
i = i + 1;
if (rec_size == (data_length + v22_E_STATS_LEN + i))
- fpga_version = vVW510012_E_FPGA;
+ fpga_version = vVW510012_E_FPGA;
}
/*the 12 is from the 12 bytes of plcp header */
if (rec_size == (data_length + vVW510021_W_STATS_LEN +vVW510021_W_AFTERHEADER_LEN+12+i))
- fpga_version = vVW510021_W_FPGA;
+ fpga_version = vVW510021_W_FPGA;
}
/* Finally the Series II Ethernet */
i = i + 1;
if (rec_size == (data_length + vVW510024_E_STATS_LEN + i))
- fpga_version = vVW510024_E_FPGA;
+ fpga_version = vVW510024_E_FPGA;
}
if (fpga_version != 1000)
{
}
*err = file_error(wth->fh, err_info);
- if (*err == 0)
- return(UNKNOWN_FPGA); /* short read - not a vwr file */
- return(-1);
+ if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
+ return(-1);
+ return(UNKNOWN_FPGA); /* short read - not a vwr file */
}
/* copy the actual packet data from the capture file into the target data block */
/* the packet is constructed as a 38-byte VeriWave-extended Radiotap header plus the raw */
/* MAC octets */
-static void vwr_read_rec_data(wtap *wth, guint8 *data_ptr, guint8 *rec, int rec_size)
+static void vwr_read_rec_data(wtap *wth, struct wtap_pkthdr *phdr,
+ guint8 *data_ptr, guint8 *rec, int rec_size)
{
vwr_t *vwr = (vwr_t *)wth->priv;
int bytes_written = 0; /* bytes output to buf so far */
pay_off = mac_snap + 20;
}
- sig_off = find_signature(m_ptr, pay_off, flow_id, flow_seq);
+ sig_off = find_signature(m_ptr, pay_off, rec_size, flow_id, flow_seq);
if ((m_ptr[sig_off] == 0xdd) && (sig_off + 15 <= msdu_length) && (f_flow != 0))
sig_ts = get_signature_ts(m_ptr, sig_off);
else
/* the FCS is NOT included */
r_hdr_len = STATS_COMMON_FIELDS_LEN + EXT_RTAP_FIELDS_LEN;
- wth->phdr.len = (msdu_length - 4) + r_hdr_len;
- wth->phdr.caplen = (octets - 4) + r_hdr_len;
+ phdr->len = (msdu_length - 4) + r_hdr_len;
+ phdr->caplen = (octets - 4) + r_hdr_len;
- wth->phdr.presence_flags = WTAP_HAS_TS;
+ phdr->presence_flags = WTAP_HAS_TS;
- wth->phdr.ts.secs = (time_t)s_sec;
- wth->phdr.ts.nsecs = (long)(s_usec * 1000);
- wth->phdr.pkt_encap = WTAP_ENCAP_IXVERIWAVE;
+ phdr->ts.secs = (time_t)s_sec;
+ phdr->ts.nsecs = (int)(s_usec * 1000);
+ phdr->pkt_encap = WTAP_ENCAP_IXVERIWAVE;
/* generate and copy out the radiotap header, set the port type to 0 (WLAN) */
common_fields.vw_port_type = 0;
bytes_written += 4;
/* finally, copy the whole MAC frame to the packet buffer as-is; exclude FCS */
- if ( rec_size < ((int)msdu_length + (int)vwr->STATS_LEN) )
+ if ( rec_size < ((int)msdu_length + (int)vwr->STATS_LEN) )
/*something's been truncated, DUMP AS-IS*/
memcpy(&data_ptr[bytes_written], m_ptr, octets);
else if (octets >= 4)
/* the packet is constructed as a 38-byte VeriWave-extended Radiotap header plus the raw */
/* MAC octets */
-static void vwr_read_rec_data_vVW510021(wtap *wth, guint8 *data_ptr, guint8 *rec, int rec_size, int IS_TX)
+static void vwr_read_rec_data_vVW510021(wtap *wth, struct wtap_pkthdr *phdr,
+ guint8 *data_ptr, guint8 *rec, int rec_size, int IS_TX)
{
vwr_t *vwr = (vwr_t *)wth->priv;
int bytes_written = 0; /* bytes output to buf so far */
guint16 chanflags = 0; /* extended radio tap channel flags */
guint16 radioflags = 0; /* extended radio tap flags */
guint64 delta_b; /* Used for calculating latency */
-
+
/* calculate the start of the statistics block in the buffer */
/* also get a bunch of fields from the stats block */
s_start_ptr = &(rec[0]);
/* If the packet has an MSDU length of 0, then bail - malformed packet */
/* if (msdu_length < 4) return; */
actual_octets = msdu_length;
-
+
f_tx = IS_TX;
vc_id = pntohs(&s_start_ptr[vwr->VCID_OFF]);
else {
rate = 1;
}
-
+
/* calculate the MPDU size/ptr stuff; MPDU starts at 4 or 6 depending on OFDM/CCK */
/* note that the number of octets in the frame also varies depending on OFDM/CCK, */
/* because the PLCP header is prepended to the actual MPDU */
- /*the 8 is from the 8 bytes of stats block that precede the plcps ,
+ /*the 8 is from the 8 bytes of stats block that precede the plcps ,
the 12 is for 11 bytes plcp and 1 byte of pad before the data*/
m_ptr = &(rec[8+12]);
pay_off = mac_snap + 20;
}
- sig_off = find_signature(m_ptr, pay_off, flow_id, flow_seq);
+ sig_off = find_signature(m_ptr, pay_off, rec_size, flow_id, flow_seq);
if ((m_ptr[sig_off] == 0xdd) && (sig_off + 15 <= msdu_length) && (f_flow != 0))
sig_ts = get_signature_ts(m_ptr, sig_off);
else
/* len is the length of the original packet before truncation */
/* the FCS is NOT included */
r_hdr_len = STATS_COMMON_FIELDS_LEN + EXT_RTAP_FIELDS_LEN;
- wth->phdr.len = (actual_octets - 4) + r_hdr_len;
- wth->phdr.caplen = (msdu_length - 4) + r_hdr_len;
+ phdr->len = (actual_octets - 4) + r_hdr_len;
+ phdr->caplen = (msdu_length - 4) + r_hdr_len;
- wth->phdr.presence_flags = WTAP_HAS_TS;
+ phdr->presence_flags = WTAP_HAS_TS;
- wth->phdr.ts.secs = (time_t)s_sec;
- wth->phdr.ts.nsecs = (long)(s_usec * 1000);
- wth->phdr.pkt_encap = WTAP_ENCAP_IXVERIWAVE;
+ phdr->ts.secs = (time_t)s_sec;
+ phdr->ts.nsecs = (int)(s_usec * 1000);
+ phdr->pkt_encap = WTAP_ENCAP_IXVERIWAVE;
/* generate and copy out the radiotap header, set the port type to 0 (WLAN) */
common_fields.vw_port_type = 0;
er_fields.flags |= RADIOTAP_F_SHORTPRE;
er_fields.rate = rate;
- er_fields.chanflags = chanflags;
-
+ er_fields.chanflags = chanflags;
+
if (f_tx) {
er_fields.tx_power = (gint8)tx_power;
er_fields.signal = 100;
bytes_written += 4;
/* finally, copy the whole MAC frame to the packet buffer as-is; exclude 4-byte FCS */
- if ( rec_size < ((int)actual_octets + (int)vwr->STATS_LEN) )
+ if ( rec_size < ((int)actual_octets + (int)vwr->STATS_LEN) )
/*something's been truncated, DUMP AS-IS*/
memcpy(&data_ptr[bytes_written], m_ptr, msdu_length);
else if (msdu_length >= 4)
/* the packet is constructed as a 38-byte VeriWave-extended Radiotap header plus the raw */
/* MAC octets */
-static void vwr_read_rec_data_ethernet(wtap *wth, guint8 *data_ptr, guint8 *rec, int rec_size, int IS_TX)
+static void vwr_read_rec_data_ethernet(wtap *wth, struct wtap_pkthdr *phdr,
+ guint8 *data_ptr, guint8 *rec, int rec_size, int IS_TX)
{
vwr_t *vwr = (vwr_t *)wth->priv;
int bytes_written = 0; /* bytes output to buf so far */
/* also get a bunch of fields from the stats block */
m_ptr = &(rec[0]); /* point to the data block */
s_ptr = &(rec[rec_size - vwr->STATS_LEN]); /* point to the stats block */
-
+
msdu_length = pntohs(&s_ptr[vwr->OCTET_OFF]);
actual_octets = msdu_length;
/* sanity check the msdu_length field to determine if it is OK (or segfaults result) */
pay_off = mac_len + 20;
}
- sig_off = find_signature(m_ptr, pay_off, flow_id, flow_seq);
+ sig_off = find_signature(m_ptr, pay_off, rec_size, flow_id, flow_seq);
if ((m_ptr[sig_off] == 0xdd) && (sig_off + 15 <= msdu_length) && (f_flow != 0))
sig_ts = get_signature_ts(m_ptr, sig_off);
else
/* len is the length of the original packet before truncation*/
/* the FCS is NEVER included */
e_hdr_len = STATS_COMMON_FIELDS_LEN + STATS_ETHERNETTAP_FIELDS_LEN;
- wth->phdr.len = (actual_octets - 4) + e_hdr_len;
- wth->phdr.caplen = (msdu_length - 4) + e_hdr_len;
+ phdr->len = (actual_octets - 4) + e_hdr_len;
+ phdr->caplen = (msdu_length - 4) + e_hdr_len;
- wth->phdr.presence_flags = WTAP_HAS_TS;
+ phdr->presence_flags = WTAP_HAS_TS;
- wth->phdr.ts.secs = (time_t)s_sec;
- wth->phdr.ts.nsecs = (long)(s_usec * 1000);
- wth->phdr.pkt_encap = WTAP_ENCAP_IXVERIWAVE;
+ phdr->ts.secs = (time_t)s_sec;
+ phdr->ts.nsecs = (int)(s_usec * 1000);
+ phdr->pkt_encap = WTAP_ENCAP_IXVERIWAVE;
/* generate and copy out the ETHERNETTAP header, set the port type to 1 (Ethernet) */
common_hdr.vw_port_type = 1;
bytes_written += 4;
/* finally, copy the whole MAC frame to the packet bufffer as-is; ALWAYS exclude 4-byte FCS */
- if ( rec_size < ((int)actual_octets + (int)vwr->STATS_LEN) )
+ if ( rec_size < ((int)actual_octets + (int)vwr->STATS_LEN) )
/*something's been truncated, DUMP AS-IS*/
memcpy(&data_ptr[bytes_written], m_ptr, msdu_length);
else if (msdu_length >= 4)
/* utility routine: check that signature is at specified location; scan for it if not */
/* if we can't find a signature at all, then simply return the originally supplied offset */
-int find_signature(guint8 *m_ptr, int pay_off, guint32 flow_id, guint8 flow_seq)
+int find_signature(guint8 *m_ptr, int pay_off, gint rec_size, guint32 flow_id, guint8 flow_seq)
{
int tgt; /* temps */
guint32 fid;
/* payload until maximum scan range exhausted to see if we can find it */
/* the scanning process consists of looking for a '0xdd', then checking for the correct */
/* flow ID and sequence number at the appropriate offsets */
- for (tgt = pay_off; tgt < (pay_off + SIG_SCAN_RANGE); tgt++) {
+ for (tgt = pay_off; tgt < (pay_off + SIG_SCAN_RANGE) && tgt < rec_size; tgt++) {
if (m_ptr[tgt] == 0xdd) { /* found magic byte? check fields */
if (m_ptr[tgt + 15] == 0xe2) {
if (m_ptr[tgt + 4] != flow_seq)