#include "wtap-int.h"
#include "file_wrappers.h"
-#include "buffer.h"
#include "vwr.h"
(guint64)*((const guint8 *)(p)+2)<<8| \
(guint64)*((const guint8 *)(p)+3)<<0)
+/*
+ * Fetch a 48-bit value in "Corey-endian" form; it's stored as
+ * a 64-bit Corey-endian value, with the upper 16 bits ignored.
+ */
+#define pcorey48tohll(p) ((guint64)*((const guint8 *)(p)+6)<<40| \
+ (guint64)*((const guint8 *)(p)+7)<<32| \
+ (guint64)*((const guint8 *)(p)+0)<<24| \
+ (guint64)*((const guint8 *)(p)+1)<<16| \
+ (guint64)*((const guint8 *)(p)+2)<<8| \
+ (guint64)*((const guint8 *)(p)+3)<<0)
+
/* .vwr log file defines */
#define B_SIZE 32768 /* max var len message = 32 kB */
#define VT_FRAME 0 /* varlen msg is a frame */
* A record begins with a 16-byte header, the first 8 bytes of which
* begin with a byte containing a command plus transmit-receive flags.
*
- * Following that are two big-endian 32-bi quantities; for some records
+ * Following that are two big-endian 32-bit quantities; for some records
* one or the other of them is the length of the rest of the record.
* Other records contain only the header.
*/
-#define VW_RECORD_HEADER_LENGTH 16
+#define VW_RECORD_HEADER_LENGTH 16
-/* the radiotap header */
-
-/* IxVeriwave common header fields */
-typedef struct {
- guint16 vw_port_type; /* 0 for WLAN, 1 for Ethernet */
- guint16 it_len; /* WHOLE radiotap header length (incl. */
- guint16 vw_msdu_length; /* length of MAC SDU */
- guint32 vw_flowid; /* VeriWave-specific flow ID for packet */
- guint16 vw_vcid; /* VeriWave-specific vC ID (client id) */
- guint16 vw_seqnum; /* VeriWave-specific signature seqnum */
- guint32 vw_latency; /* VeriWave-specific packet latency, ns */
- guint32 vw_sig_ts; /* signature timestamp, 32 LSBs, nsec */
- guint64 vw_startt; /* frame start time (nsec) */
- guint64 vw_endt; /* frame end time (nsec) */
- guint32 vw_pktdur; /* VeriWave-specific pkt duration, us */
-
-} stats_common_fields;
-
-/* Size of those fields - regardless of how the compiler packs them */
-#define STATS_COMMON_FIELDS_LEN (2+2+2+4+2+2+4+4+8+8+4)
+/* Command byte values */
+#define COMMAND_RX 0x21
+#define COMMAND_TX 0x31
-/* Veriwave-specific extended radiotap header fields (following vwr_rtap_hdr above) */
-/* structure elements correspond one-to-one with the RADIOTAP_PRESENT bitmask below */
-/* NOTE: must ensure that elements are aligned to their "natural" packing */
-/* NOTE: must ensure that "latency" precedes all other packet timing details, because it */
-/* is used to start a subtree */
-typedef struct {
- guint16 it_len; /* WHOLE radiotap header length (incl. */
- guint16 flags; /* short preamble, WEP, frag */
- guint16 chanflags; /* channel flags bitmap */
- guint16 phyRate; /* The PHY rate of the packet * 10 (accommodates the 5.5 on CCK) */
- guint8 plcpType; /* PLCP type - 0: Legacy, 1: HT Mixed, 2: HT Green field, 3: VHT mixed */
- guint8 mcsIndex; /* 0 - 31 possible */
- guint8 nss; /* Guard interval */
- gint8 signal; /* RF signal power, +/- dBm */
- gint8 signalb; /* transmit power, +/- dBm */
- gint8 signalc; /* transmit power, +/- dBm */
- gint8 signald; /* transmit power, +/- dBm */
- guint16 vw_flags; /* VeriWave-specific packet flags */
- guint16 vw_ht_length; /* ht length (in plcp header)*/
- guint16 vw_info; /* VeriWave-specific information */
- guint32 vw_errors; /* VeriWave-specific errors */
-
-} ext_rtap_fields;
-
-/* Size of those fields - regardless of how the compiler packs them */
-#define EXT_RTAP_FIELDS_LEN (2+2+2+2+1+1+1+1+1+1+1+1+2+2+2+4)
-
-/* Veriwave-specific Ethernettap header */
-typedef struct {
- guint16 it_len; /* WHOLE radiotap header length (incl. */
- guint16 vw_flags; /* Veriwave-specific flags (see above) */
- guint16 vw_info; /* VeriWave-specific information */
- guint32 vw_errors; /* VeriWave-specific flags */
- guint32 vw_l4id; /* layer four id*/
- guint32 it_pad2; /* pad out header to 16-byte boundary */
-} stats_ethernettap_fields;
-
-/* Size of those fields - regardless of how the compiler packs them */
-#define STATS_ETHERNETTAP_FIELDS_LEN (2+2+2+4+4+4)
-
-/* the bitmap offsets of the bits in it_present, above */
-/* also lists the expected field sizes in bytes */
-/* MUST BE IN SAME ORDER AS THE STRUCTURE ELEMENTS ABOVE */
-enum radiotap_type {
- VW_RADIOTAP_FLAGS = 0, /* 2 bytes */
- VW_RADIOTAP_RATE = 1, /* 1 byte */
- VW_RADIOTAP_CHANNEL = 2, /* 4 bytes (mhz + chanflags) */
- VW_RADIOTAP_DBM_ANTSIGNAL = 3, /* 1 byte */
- VW_RADIOTAP_DBM_TX_POWER = 4, /* 1 byte */
- /* start of veriwave addition */
- VW_RADIOTAP_FPGA_VERSION = 5, /* 2 bytes */
- VW_RADIOTAP_VW_FLAGS = 6, /* 2 bytes */
- VW_RADIOTAP_MSDU_LENGTH = 7, /* 2 bytes */
- VW_RADIOTAP_HT_LENGTH = 8, /* 2 bytes */
- VW_RADIOTAP_INFO = 9, /* 2 bytes */
- VW_RADIOTAP_ERRORS = 10, /* 4 bytes */
- VW_RADIOTAP_FLOWID = 11, /* 4 bytes */
- VW_RADIOTAP_MCID = 12, /* 2 bytes */
- VW_RADIOTAP_SEQNUM = 13, /* 2 bytes */
- VW_RADIOTAP_LATENCY = 14, /* 4 bytes (MUST COME BEFORE OTHER TIMES)*/
- VW_RADIOTAP_SIG_TS = 15, /* 4 bytes */
- VW_RADIOTAP_STARTT = 16, /* 8 bytes */
- VW_RADIOTAP_ENDT = 17, /* 8 bytes */
- VW_RADIOTAP_PKTDUR = 18, /* 4 bytes */
- VW_RADIOTAP_IFG = 19, /* 4 bytes */
-
- /* end of Veriwave addition 6-2007 */
-
- VW_RADIOTAP_EXT = 31
-};
-
-/* standard field-present bitmap corresponding to above fixed-size set of fields */
-/* this produces a 16-byte header */
-#define VW_RADIOTAP_PRESENT ((1 << VW_RADIOTAP_FLAGS) | \
- (1 << VW_RADIOTAP_RATE) | \
- (1 << VW_RADIOTAP_CHANNEL) | \
- (1 << VW_RADIOTAP_DBM_ANTSIGNAL) | \
- (1 << VW_RADIOTAP_DBM_TX_POWER))
-
-/* extended field-present bitmap corresponding to above fixed-size set of fields */
-/* this produces a 32-byte header */
-#define VW_EXT_RTAP_PRESENT ((1 << VW_RADIOTAP_FLAGS) | \
- (1 << VW_RADIOTAP_RATE) | \
- (1 << VW_RADIOTAP_CHANNEL) | \
- (1 << VW_RADIOTAP_DBM_ANTSIGNAL) | \
- (1 << VW_RADIOTAP_DBM_TX_POWER) | \
- (1 << VW_RADIOTAP_FPGA_VERSION) | \
- (1 << VW_RADIOTAP_VW_FLAGS) | \
- (1 << VW_RADIOTAP_MSDU_LENGTH) | \
- (1 << VW_RADIOTAP_HT_LENGTH) | \
- (1 << VW_RADIOTAP_ERRORS) | \
- (1 << VW_RADIOTAP_INFO) | \
- (1 << VW_RADIOTAP_MCID) | \
- (1 << VW_RADIOTAP_FLOWID) | \
- (1 << VW_RADIOTAP_SEQNUM) | \
- (1 << VW_RADIOTAP_LATENCY) | \
- (1 << VW_RADIOTAP_SIG_TS) | \
- (1 << VW_RADIOTAP_STARTT) | \
- (1 << VW_RADIOTAP_ENDT) |\
- (1 << VW_RADIOTAP_PKTDUR) |\
- (1 << VW_RADIOTAP_IFG))
+/* the metadata headers */
-/*
- * RADIOTAP_FLAGS u_int8_t bitmap
- * See flags definitions below
- *
- * RADIOTAP_RATE u_int8_t 500kb/s
- * Tx/Rx data rate
- *
- * RADIOTAP_CHANNEL 2 x u_int16_t MHz+bitmap
- * Tx/Rx frequency in MHz, followed by flags (see below).
- *
- * RADIOTAP_DBM_ANTSIGNAL int8_t dBm
- * RF signal power at the antenna, dBm
- *
- * RADIOTAP_DBM_ANTNOISE int8_t dBm
- * RF noise power at the antenna, dBm
- *
- * RADIOTAP_BARKER_CODE_LOCK u_int16_t unitless
- * Quality of Barker code lock. Monotonically nondecreasing with "better" lock strength.
- * Called "Signal Quality" in datasheets.
- *
- * RADIOTAP_DBM_TX_POWER int8_t dBm
- * Transmit power expressed as dBm.
-*/
+/* Size of the IxVeriwave common header */
+#define STATS_COMMON_FIELDS_LEN (2+2+2+4+2+2+4+4+8+8+4)
-/* Channel flags for IEEE80211_RADIOTAP_CHANNEL */
-#define CHAN_TURBO 0x0010 /* Turbo channel */
-#define CHAN_CCK 0x0020 /* CCK channel */
-#define CHAN_OFDM 0x0040 /* OFDM channel */
-#define CHAN_2GHZ 0x0080 /* 2 GHz spectrum channel. */
-#define CHAN_5GHZ 0x0100 /* 5 GHz spectrum channel */
-#define CHAN_PASSIVE 0x0200 /* Only passive scan allowed */
-
-/* For RADIOTAP_FLAGS */
-#define RADIOTAP_F_CFP 0x001 /* sent/received during CFP */
-#define RADIOTAP_F_SHORTPRE 0x002 /* sent/received with short preamble */
-#define RADIOTAP_F_WEP 0x004 /* sent/received with WEP encryption */
-#define RADIOTAP_F_FRAG 0x008 /* sent/received with fragmentation */
-#define RADIOTAP_F_FCS 0x010 /* frame includes FCS */
-#define RADIOTAP_F_DATAPAD 0x020 /* padding between 802.11 hdr & payload */
-#define RADIOTAP_F_CHAN_HT 0x040 /* In HT mode */
-#define RADIOTAP_F_CHAN_VHT 0x080 /* VHT Mode */
-#define RADIOTAP_F_CHAN_SHORTGI 0x100 /* Short guard interval */
-#define RADIOTAP_F_CHAN_40MHZ 0x200 /* 40 Mhz CBW */
-#define RADIOTAP_F_CHAN_80MHZ 0x400 /* 80 MHz channel bandwidth */
-#define RADIOTAP_F_CHAN_160MHZ 0x800 /* 160 MHz channel bandwidth */
-
-/* For VeriWave-specific RADIOTAP_FLAGS and ETHERNETTAP_FLAGS */
-#define RADIOTAP_VWF_TXF 0x01 /* frame was transmitted */
-#define RADIOTAP_VWF_FCSERR 0x02 /* FCS error detected */
-#define RADIOTAP_VWF_RETRERR 0x04 /* excess retry error detected */
-#define RADIOTAP_VWF_DCRERR 0x10 /* decrypt error detected (WLAN) */
-#define RADIOTAP_VWF_ENCMSK 0x60 /* encryption type mask */
- /* 0 = none, 1 = WEP, 2 = TKIP, 3 = CCKM */
-#define RADIOTAP_VWF_IS_WEP 0x20 /* WEP */
-#define RADIOTAP_VWF_IS_TKIP 0x40 /* TKIP */
-#define RADIOTAP_VWF_IS_CCMP 0x60 /* CCMP */
-#define RADIOTAP_VWF_SEQ_ERR 0x80 /* flow sequence error detected */
-
-#define IEEE80211_PLCP_RATE_MASK 0x7f /* parses out the rate or MCS index from the PLCP header(s) */
-#define IEEE80211_RADIOTAP_F_40MHZ 0x0200 /* 40 Mhz channel bandwidth */
-#define IEEE80211_RADIOTAP_F_80MHZ 0x0400 /* 80 Mhz channel bandwidth */
-#define IEEE80211_RADIOTAP_F_160MHZ 0x0800 /* 80 Mhz channel bandwidth */
-#define IEEE80211_RADIOTAP_F_SHORTGI 0x0100
+/* For VeriWave WLAN and Ethernet metadata headers vw_flags field */
+#define VW_FLAGS_TXF 0x01 /* frame was transmitted */
+#define VW_FLAGS_FCSERR 0x02 /* FCS error detected */
+
+/* For VeriWave WLAN metadata header vw_flags field */
+#define VW_FLAGS_RETRERR 0x04 /* excess retry error detected */
+#define VW_FLAGS_DCRERR 0x10 /* decrypt error detected (WLAN) */
+#define VW_FLAGS_ENCMSK 0x60 /* encryption type mask */
+ /* 0 = none, 1 = WEP, 2 = TKIP, 3 = CCKM */
+#define VW_FLAGS_IS_WEP 0x20 /* WEP */
+#define VW_FLAGS_IS_TKIP 0x40 /* TKIP */
+#define VW_FLAGS_IS_CCMP 0x60 /* CCMP */
+
+/* Veriwave WLAN metadata header */
+
+/* Channel flags, for chanflags field */
+#define CHAN_CCK 0x0020 /* CCK channel */
+#define CHAN_OFDM 0x0040 /* OFDM channel */
+
+/* Flags, for flags field */
+#define FLAGS_SHORTPRE 0x0002 /* sent/received with short preamble */
+#define FLAGS_WEP 0x0004 /* sent/received with WEP encryption */
+#define FLAGS_FCS 0x0010 /* frame includes FCS */
+#define FLAGS_CHAN_HT 0x0040 /* In HT mode */
+#define FLAGS_CHAN_VHT 0x0080 /* VHT Mode */
+#define FLAGS_CHAN_SHORTGI 0x0100 /* Short guard interval */
+#define FLAGS_CHAN_40MHZ 0x0200 /* 40 Mhz channel bandwidth */
+#define FLAGS_CHAN_80MHZ 0x0400 /* 80 Mhz channel bandwidth */
+#define FLAGS_CHAN_160MHZ 0x0800 /* 160 Mhz channel bandwidth */
+
+/* Size of the VeriWave WLAN metadata header */
+#define EXT_WLAN_FIELDS_LEN (2+2+2+2+1+1+1+1+1+1+1+1+2+2+2+4)
+
+/* Size of the VeriWave Ethernet metadata header */
+#define EXT_ETHERNET_FIELDS_LEN (2+2+2+4+4+4)
/* FPGA-generated frame buffer STATS block offsets and definitions */
#define v22_E_INFO_OFF 40 /* NO INFO FIELD IN ETHERNET STATS! */
#define v22_E_DIFFERENTIATOR_OFF 0 /* offset to determine whether */
/* eth/802.11, 8 bits */
-
+/* Media types */
#define v22_E_MT_10_HALF 0 /* 10 Mb/s half-duplex */
#define v22_E_MT_10_FULL 1 /* 10 Mb/s full-duplex */
#define v22_E_MT_100_HALF 2 /* 100 Mb/s half-duplex */
#define v22_E_MT_1G_HALF 4 /* 1 Gb/s half-duplex */
#define v22_E_MT_1G_FULL 5 /* 1 Gb/s full-duplex */
+/* Error flags */
#define v22_E_FCS_ERROR 0x0002 /* FCS error flag in error vector */
#define v22_E_CRYPTO_ERR 0x1f00 /* RX decrypt error flags (UNUSED) */
#define v22_E_SIG_ERR 0x0004 /* signature magic byte mismatch */
#define v22_E_PAYCHK_ERR 0x0008 /* payload checksum failure */
#define v22_E_RETRY_ERR 0x0400 /* excessive retries on TX fail (UNUSED)*/
+
+/* Masks and defines */
#define v22_E_IS_RX 0x08 /* TX/RX bit in STATS block */
#define v22_E_MT_MASK 0x07 /* modulation type mask (UNUSED) */
-#define v22_E_VCID_MASK 0x03ff /* VC ID is only 9 bits */
+
+#define v22_E_VCID_MASK 0x03ff /* VC ID is only 10 bits */
+
#define v22_E_FLOW_VALID 0x40 /* flow-is-valid flag (else force to 0) */
+
#define v22_E_DIFFERENTIATOR_MASK 0X3F /* mask to differentiate ethernet from */
-#define v22_E_IS_TCP 0x00000040 /* TCP bit in FRAME_TYPE field */
-#define v22_E_IS_UDP 0x00000010 /* UDP bit in FRAME_TYPE field */
-#define v22_E_IS_ICMP 0x00000020 /* ICMP bit in FRAME_TYPE field */
-#define v22_E_IS_IGMP 0x00000080 /* IGMP bit in FRAME_TYPE field */
+
+/* Bits in FRAME_TYPE field */
+#define v22_E_IS_TCP 0x00000040 /* TCP */
+#define v22_E_IS_UDP 0x00000010 /* UDP */
+#define v22_E_IS_ICMP 0x00000020 /* ICMP */
+#define v22_E_IS_IGMP 0x00000080 /* IGMP */
+
#define v22_E_IS_QOS 0x80 /* QoS bit in MTYPE field (WLAN only) */
#define v22_E_IS_VLAN 0x00200000
#define v22_E_FC_PROT_BIT 0x40 /* Protected Frame bit in FC1 of frame */
-
-#define v22_E_HEADER_IS_RX 0x21
-#define v22_E_HEADER_IS_TX 0x31
-
#define v22_E_IS_ETHERNET 0x00700000 /* bits set in frame type if ethernet */
#define v22_E_IS_80211 0x7F000000 /* bits set in frame type if 802.11 */
#define v22_W_PLCP_LENGTH_OFF 4 /* LENGTH field in the plcp header */
+/* Modulation types */
#define v22_W_MT_CCKL 0 /* CCK modulation, long preamble */
#define v22_W_MT_CCKS 1 /* CCK modulation, short preamble */
#define v22_W_MT_OFDM 2 /* OFDM modulation */
-#define v22_W_IS_TCP 0x00000040 /* TCP bit in FRAME_TYPE field */
-#define v22_W_IS_UDP 0x00000010 /* UDP bit in FRAME_TYPE field */
-#define v22_W_IS_ICMP 0x00000020 /* ICMP bit in FRAME_TYPE field */
-#define v22_W_IS_IGMP 0x00000080 /* IGMP bit in FRAME_TYPE field */
-#define v22_W_IS_QOS 0x80 /* QoS bit in MTYPE field (WLAN only) */
+/* Bits in FRAME_TYPE field */
+#define v22_W_IS_TCP 0x00000040 /* TCP */
+#define v22_W_IS_UDP 0x00000010 /* UDP */
+#define v22_W_IS_ICMP 0x00000020 /* ICMP */
+#define v22_W_IS_IGMP 0x00000080 /* IGMP */
+/* Bits in MTYPE field (WLAN only) */
+#define v22_W_IS_QOS 0x80 /* QoS */
+/* Error flags */
#define v22_W_FCS_ERROR 0x0002 /* FCS error flag in error vector */
#define v22_W_CRYPTO_ERR 0x1f00 /* RX decrypt error flags */
#define v22_W_SIG_ERR 0x0004 /* signature magic byte mismatch */
#define v22_W_PAYCHK_ERR 0x0008 /* payload checksum failure */
#define v22_W_RETRY_ERR 0x0400 /* excessive retries on TX failure */
+
+/* Masks and defines */
#define v22_W_IS_RX 0x08 /* TX/RX bit in STATS block */
#define v22_W_MT_MASK 0x07 /* modulation type mask */
+
#define v22_W_VCID_MASK 0x01ff /* VC ID is only 9 bits */
+
#define v22_W_FLOW_VALID 0x40 /* flow-is-valid flag (else force to 0) */
+
#define v22_W_DIFFERENTIATOR_MASK 0Xf0ff /* mask to differentiate ethernet from */
/* 802.11 capture */
#define v22_W_RX_DECRYPTS 0x0007 /* RX-frame-was-decrypted bits */
#define v22_W_TX_DECRYPTS 0x0007 /* TX-frame-was-decrypted bits */
-#define v22_W_WEPTYPE 0x0001 /* WEP frame */
-#define v22_W_TKIPTYPE 0x0002 /* TKIP frame */
-#define v22_W_CCMPTYPE 0x0004 /* CCMP frame */
-
-#define v22_W_HEADER_IS_RX 0x21
-#define v22_W_HEADER_IS_TX 0x31
+/* Info bits */
+#define v22_W_WEPTYPE 0x0001 /* WEP frame */
+#define v22_W_TKIPTYPE 0x0002 /* TKIP frame */
+#define v22_W_CCMPTYPE 0x0004 /* CCMP frame */
+#define v22_W_MPDU_OF_A_MPDU 0x0400 /* MPDU of A-MPDU */
+#define v22_W_FIRST_MPDU_OF_A_MPDU 0x0800 /* first MPDU of A-MPDU */
+#define v22_W_LAST_MPDU_OF_A_MPDU 0x1000 /* last MPDU of A-MPDU */
+#define v22_W_MSDU_OF_A_MSDU 0x2000 /* MSDU of A-MSDU */
+#define v22_W_FIRST_MSDU_OF_A_MSDU 0x4000 /* first MSDU of A-MSDU */
+#define v22_W_LAST_MSDU_OF_A_MSDU 0x8000 /* last MSDU of A-MSDU */
+
+/* All aggregation flags */
+#define v22_W_AGGREGATE_FLAGS \
+ (v22_W_MPDU_OF_A_MPDU | \
+ v22_W_FIRST_MPDU_OF_A_MPDU | \
+ v22_W_LAST_MPDU_OF_A_MPDU | \
+ v22_W_MSDU_OF_A_MSDU | \
+ v22_W_FIRST_MSDU_OF_A_MSDU | \
+ v22_W_LAST_MSDU_OF_A_MSDU)
#define v22_W_FC_PROT_BIT 0x40 /* Protected Frame bit in FC1 of frame */
remaining 48 bytes of stat block
*/
/* offsets in the stats block */
-#define vVW510021_W_STATS_LEN 48 /* length of stats block trailer after the plcp portion*/
+#define vVW510021_W_STATS_HEADER_LEN 8 /* length of stats block header at beginning of record data */
+#define vVW510021_W_STATS_TRAILER_LEN 48 /* length of stats block trailer after the plcp portion*/
#define vVW510021_W_STARTT_OFF 0 /* offset of start time, 64 bits */
#define vVW510021_W_ENDT_OFF 8 /* offset of end time, 64 bits */
#define vVW510021_W_ERRORS_OFF 16 /* offset of error vector */
#define vVW510021_W_QOS_VALID 0x4000
#define vVW510021_W_HT_VALID 0x2000
#define vVW510021_W_L4ID_VALID 0x1000
-#define vVW510021_W_PREAMBLE_MASK 0x40 /* short/long preamble/guard(ofdm) mask */
-#define vVW510021_W_MCS_MASK 0x3f /* mcs index (a/b) type mask */
#define vVW510021_W_MOD_SCHEME_MASK 0x3f /* modulation type mask */
-#define vVW510021_W_PLCPC_MASK 0x03 /* PLPCP type mask */
#define vVW510021_W_SEL_MASK 0x80
#define vVW510021_W_WEP_MASK 0x0001
#define vVW510021_W_CBW_MASK 0xC0
+#define vVW510024_W_VCID_MASK 0x03ff /* VC ID is only 10 bits */
+
#define vVW510021_W_MT_SEL_LEGACY 0x00
-#define vVW510021_W_PLCP_LEGACY 0x00
-#define vVW510021_W_PLCP_MIXED 0x01
-#define vVW510021_W_PLCP_GREENFIELD 0x02
-#define vVW510021_W_PLCP_VHT_MIXED 0x03
-#define vVW510021_W_HEADER_IS_RX 0x21
-#define vVW510021_W_HEADER_IS_TX 0x31
+
#define vVW510021_W_IS_WEP 0x0001
-#define vVW510021_W_IS_LONGPREAMBLE 0x40
-#define vVW510021_W_IS_TCP 0x01000000 /* TCP bit in FRAME_TYPE field */
-#define vVW510021_W_IS_UDP 0x00100000 /* UDP bit in FRAME_TYPE field */
-#define vVW510021_W_IS_ICMP 0x00001000 /* ICMP bit in FRAME_TYPE field */
-#define vVW510021_W_IS_IGMP 0x00010000 /* IGMP bit in FRAME_TYPE field */
+/* L1p byte 1 info */
+
+/* Common to Series II and Series III */
+
+#define vVW510021_W_IS_LONGPREAMBLE 0x40 /* short/long preamble bit */
+#define vVW510021_W_IS_LONGGI 0x40 /* short/long guard interval bit */
+
+/* Series II */
+
+#define vVW510021_W_S2_MCS_INDEX(l1p_1) ((l1p_1) & 0x3f) /* MCS index */
+
+/* Series III */
+
+/*
+ * VHT - contains MCS index and number of spatial streams.
+ * The number of spatial streams from the FPGA is zero-based, so we add
+ * 1 to it.
+ */
+#define vVW510021_W_S3_MCS_INDEX_VHT(l1p_1) ((l1p_1) & 0x0f) /* MCS index */
+#define vVW510021_W_S3_NSS_VHT(l1p_1) (((l1p_1) >> 4 & 0x3) + 1) /* NSS */
+
+/*
+ * HT - contains MCS index
+ */
+#define vVW510021_W_S3_MCS_INDEX_HT(l1p_1) ((l1p_1) & 0x3f)
+
+/* L1p byte 2 info */
+
+/* Common to Series II and Series III */
+#define vVW510021_W_BANDWIDTH_VHT(l1p_2) (((l1p_2) >> 4) & 0xf)
+/* 3 = 40 MHz, 4 = 80 MHz; what about 20 and 160 MHz? */
+
+/* Series II */
+#define vVW510021_W_S2_PLCP_TYPE(l1p_2) ((l1p_2) & 0x03) /* PLCP type */
+
+/* Series III */
+#define vVW510021_W_S3_PLCP_TYPE(l1p_2) ((l1p_2) & 0x0f) /* PLCP type */
+
+/* PLCP types */
+#define vVW510021_W_PLCP_LEGACY 0x00 /* pre-HT (11b/a/g) */
+#define vVW510021_W_PLCP_MIXED 0x01 /* HT, mixed (11n) */
+#define vVW510021_W_PLCP_GREENFIELD 0x02 /* HT, greenfield (11n) */
+#define vVW510021_W_PLCP_VHT_MIXED 0x03 /* VHT (11ac) */
+
+/* Bits in FRAME_TYPE field */
+#define vVW510021_W_IS_TCP 0x01000000 /* TCP */
+#define vVW510021_W_IS_UDP 0x00100000 /* UDP */
+#define vVW510021_W_IS_ICMP 0x00001000 /* ICMP */
+#define vVW510021_W_IS_IGMP 0x00010000 /* IGMP */
#define vVW510021_W_HEADER_VERSION 0x00
#define S2_W_FPGA_VERSION 0x000C
#define vVW510021_W_11n_FPGA_VERSION 0x000D
-/* Error masks */
+/* Error flags */
#define vVW510021_W_FCS_ERROR 0x01
+
#define vVW510021_W_CRYPTO_ERROR 0x50000
-#define vVW510021_W_WEPTYPE 0x0001 /* WEP frame */
-#define vVW510021_W_TKIPTYPE 0x0002 /* TKIP frame */
-#define vVW510021_W_CCMPTYPE 0x0004 /* CCMP frame */
+/* Info bits are the same as for the VWS10006 FPGA */
/* definitions for VW510024 FPGA, wired ethernet format */
/* FORMAT:
#define vVW510024_E_QOS_VALID 0x0000 /** not valid for ethernet **/
#define vVW510024_E_L4ID_VALID 0x1000
#define vVW510024_E_CBW_MASK 0xC0
-#define vVW510024_E_VCID_MASK 0x3FFF
-#define vVW510024_E_HEADER_IS_RX 0x21
-#define vVW510024_E_HEADER_IS_TX 0x31
+#define vVW510024_E_VCID_MASK 0x3fff /* VCID is only 14 bits */
#define vVW510024_E_IS_TCP 0x01000000 /* TCP bit in FRAME_TYPE field */
#define vVW510024_E_IS_UDP 0x00100000 /* UDP bit in FRAME_TYPE field */
/* Per-capture file private data structure */
typedef struct {
- /* offsets in stats block; these are dependent on the frame type (Ethernet/WLAN) and */
- /* version number of .vwr file, and are set up by setup_defaults() */
- guint32 STATS_LEN; /* length of stats block trailer */
- guint32 STATS_START_OFF; /* STATS OFF AFTER HEADER */
- guint32 VALID_OFF; /* bit 6 (0x40) is flow-is-valid flag */
- guint32 MTYPE_OFF; /* offset of modulation type */
- guint32 VCID_OFF; /* offset of VC ID */
- guint32 FLOWSEQ_OFF; /* offset of signature sequence number */
- guint32 FLOWID_OFF; /* offset of flow ID */
- guint32 OCTET_OFF; /* offset of octets */
- guint32 ERRORS_OFF; /* offset of error vector */
- guint32 PATN_OFF; /* offset of pattern match vector */
- guint32 RSSI_OFF; /* RSSI (NOTE: RSSI must be negated!) */
- guint32 STARTT_OFF; /* offset of start time, 64 bits */
- guint32 ENDT_OFF; /* offset of end time, 64 bits */
- guint32 LATVAL_OFF; /* offset of latency, 32 bits */
- guint32 INFO_OFF; /* offset of INFO field, 16 bits */
- guint32 L1P_1_OFF; /* offset 1ST Byte of l1params */
- guint32 L1P_2_OFF; /* offset 2nd Byte of l1params */
- guint32 L4ID_OFF; /* LAYER 4 id offset*/
- guint32 IPLEN_OFF; /* */
- guint32 PLCP_LENGTH_OFF; /* plcp length offset*/
- guint32 FPGA_VERSION_OFF; /* offset of fpga version field, 16 bits */
- guint32 HEADER_VERSION_OFF; /* offset of header version, 16 bits */
- guint32 RXTX_OFF; /* offset of CMD bit, rx or tx */
- guint32 FRAME_TYPE_OFF;
-
- /* other information about the file in question */
- guint32 MT_10_HALF; /* 10 Mb/s half-duplex */
- guint32 MT_10_FULL; /* 10 Mb/s full-duplex */
- guint32 MT_100_HALF; /* 100 Mb/s half-duplex */
- guint32 MT_100_FULL; /* 100 Mb/s full-duplex */
- guint32 MT_1G_HALF; /* 1 Gb/s half-duplex */
- guint32 MT_1G_FULL; /* 1 Gb/s full-duplex */
- guint32 FCS_ERROR; /* FCS error in frame */
- guint32 CRYPTO_ERR; /* RX decrypt error flags */
- guint32 PAYCHK_ERR; /* payload checksum failure */
- guint32 RETRY_ERR; /* excessive retries on TX failure */
- guint8 IS_RX; /* TX/RX bit in STATS block */
- guint8 MT_MASK; /* modulation type mask */
- guint16 VCID_MASK; /* VC ID is only 9 bits */
- guint32 FLOW_VALID; /* flow-is-valid flag (else force to 0) */
- guint16 QOS_VALID;
- guint32 RX_DECRYPTS; /* RX-frame-was-decrypted bits */
- guint32 TX_DECRYPTS; /* TX-frame-was-decrypted bits */
- guint32 FC_PROT_BIT; /* Protected Frame bit in FC1 of frame */
- guint32 MT_CCKL; /* CCK modulation, long preamble */
- guint32 MT_CCKS; /* CCK modulation, short preamble */
- guint32 MT_OFDM; /* OFDM modulation */
- guint32 MCS_INDEX_MASK; /* mcs index type mask */
- guint32 FPGA_VERSION;
- guint32 HEADER_IS_RX;
- guint32 HEADER_IS_TX;
- guint32 WEPTYPE; /* frame is WEP */
- guint32 TKIPTYPE; /* frame is TKIP */
- guint32 CCMPTYPE; /* frame is CCMP */
- guint32 IS_TCP;
- guint32 IS_UDP;
- guint32 IS_ICMP;
- guint32 IS_IGMP;
- guint16 IS_QOS;
- guint32 IS_VLAN;
- guint32 MPDU_OFF;
+ /* offsets in stats block; these are dependent on the frame type (Ethernet/WLAN) and */
+ /* version number of .vwr file, and are set up by setup_defaults() */
+ guint32 STATS_LEN; /* length of stats block trailer */
+ guint32 STATS_START_OFF; /* STATS OFF AFTER HEADER */
+ guint32 VALID_OFF; /* bit 6 (0x40) is flow-is-valid flag */
+ guint32 MTYPE_OFF; /* offset of modulation type */
+ guint32 VCID_OFF; /* offset of VC ID */
+ guint32 FLOWSEQ_OFF; /* offset of signature sequence number */
+ guint32 FLOWID_OFF; /* offset of flow ID */
+ guint32 OCTET_OFF; /* offset of octets */
+ guint32 ERRORS_OFF; /* offset of error vector */
+ guint32 PATN_OFF; /* offset of pattern match vector */
+ guint32 RSSI_OFF; /* RSSI (NOTE: RSSI must be negated!) */
+ guint32 STARTT_OFF; /* offset of start time, 64 bits */
+ guint32 ENDT_OFF; /* offset of end time, 64 bits */
+ guint32 LATVAL_OFF; /* offset of latency, 32 bits */
+ guint32 INFO_OFF; /* offset of INFO field, 16 bits */
+ guint32 L1P_1_OFF; /* offset 1ST Byte of l1params */
+ guint32 L1P_2_OFF; /* offset 2nd Byte of l1params */
+ guint32 L4ID_OFF; /* LAYER 4 id offset*/
+ guint32 IPLEN_OFF; /* */
+ guint32 PLCP_LENGTH_OFF; /* offset of length field in the PLCP header */
+ guint32 FPGA_VERSION_OFF; /* offset of fpga version field, 16 bits */
+ guint32 HEADER_VERSION_OFF; /* offset of header version, 16 bits */
+ guint32 RXTX_OFF; /* offset of CMD bit, rx or tx */
+ guint32 FRAME_TYPE_OFF;
+
+ /* other information about the file in question */
+ guint32 MT_10_HALF; /* 10 Mb/s half-duplex */
+ guint32 MT_10_FULL; /* 10 Mb/s full-duplex */
+ guint32 MT_100_HALF; /* 100 Mb/s half-duplex */
+ guint32 MT_100_FULL; /* 100 Mb/s full-duplex */
+ guint32 MT_1G_HALF; /* 1 Gb/s half-duplex */
+ guint32 MT_1G_FULL; /* 1 Gb/s full-duplex */
+ guint32 FCS_ERROR; /* FCS error in frame */
+ guint32 CRYPTO_ERR; /* RX decrypt error flags */
+ guint32 PAYCHK_ERR; /* payload checksum failure */
+ guint32 RETRY_ERR; /* excessive retries on TX failure */
+ guint8 IS_RX; /* TX/RX bit in STATS block */
+ guint8 MT_MASK; /* modulation type mask */
+ guint16 VCID_MASK; /* VC ID might not be a full 16 bits */
+ guint32 FLOW_VALID; /* flow-is-valid flag (else force to 0) */
+ guint16 QOS_VALID;
+ guint32 RX_DECRYPTS; /* RX-frame-was-decrypted bits */
+ guint32 TX_DECRYPTS; /* TX-frame-was-decrypted bits */
+ guint32 FC_PROT_BIT; /* Protected Frame bit in FC1 of frame */
+ guint32 MT_CCKL; /* CCK modulation, long preamble */
+ guint32 MT_CCKS; /* CCK modulation, short preamble */
+ guint32 MT_OFDM; /* OFDM modulation */
+ guint32 FPGA_VERSION;
+ guint32 WEPTYPE; /* frame is WEP */
+ guint32 TKIPTYPE; /* frame is TKIP */
+ guint32 CCMPTYPE; /* frame is CCMP */
+ guint32 IS_TCP;
+ guint32 IS_UDP;
+ guint32 IS_ICMP;
+ guint32 IS_IGMP;
+ guint16 IS_QOS;
+ guint32 IS_VLAN;
+ guint32 MPDU_OFF;
} vwr_t;
/* internal utility functions */
-static int decode_msg(vwr_t *vwr, register guint8 *, int *, int *);
-static guint8 get_ofdm_rate(guint8 *);
-static guint8 get_cck_rate(guint8 *plcp);
+static int decode_msg(register guint8 *, int *, int *);
+static guint8 get_ofdm_rate(const guint8 *);
+static guint8 get_cck_rate(const guint8 *plcp);
static void setup_defaults(vwr_t *, guint16);
static gboolean vwr_read(wtap *, int *, gchar **, gint64 *);
static gboolean vwr_seek_read(wtap *, gint64, struct wtap_pkthdr *phdr,
Buffer *, int *, gchar **);
-static gboolean vwr_read_rec_header(vwr_t *, FILE_T, int *, int *, int *, gchar **);
+static gboolean vwr_read_rec_header(FILE_T, int *, int *, int *, gchar **);
static gboolean vwr_process_rec_data(FILE_T fh, int rec_size,
struct wtap_pkthdr *phdr, Buffer *buf,
vwr_t *vwr, int IS_TX, int *err,
gchar **err_info);
-static void vwr_read_rec_data_wlan(vwr_t *, struct wtap_pkthdr *,
- guint8 *, guint8 *, int, int);
static int vwr_get_fpga_version(wtap *, int *, gchar **);
-static int parse_s1_W_stats(vwr_t *, struct wtap_pkthdr *, guint8 *,
- int, ext_rtap_fields *,
- stats_common_fields *);
-static int parse_s2_W_stats(vwr_t *, struct wtap_pkthdr *, guint8 *,
- int, ext_rtap_fields *,
- stats_common_fields *, int);
-static void vwr_read_rec_data_ethernet(vwr_t *, struct wtap_pkthdr *,
- guint8 *, guint8 *, int, int);
-
-static int find_signature(register guint8 *, int, int, register guint32, register guint8);
-static guint64 get_signature_ts(register guint8 *, int);
+static gboolean vwr_read_s1_W_rec(vwr_t *, struct wtap_pkthdr *, Buffer *,
+ const guint8 *, int, int *, gchar **);
+static gboolean vwr_read_s2_s3_W_rec(vwr_t *, struct wtap_pkthdr *, Buffer *,
+ const guint8 *, int, int, int *,
+ gchar **);
+static gboolean vwr_read_rec_data_ethernet(vwr_t *, struct wtap_pkthdr *,
+ Buffer *, const guint8 *, int,
+ int, int *, gchar **);
+
+static int find_signature(const guint8 *, int, int, register guint32, register guint8);
+static guint64 get_signature_ts(const guint8 *, int);
static float getRate( guint8 plcpType, guint8 mcsIndex, guint16 rflags, guint8 nss );
/* Open a .vwr file for reading */
/* This does very little, except setting the wiretap header for a VWR file type */
/* and setting the timestamp precision to microseconds. */
-int vwr_open(wtap *wth, int *err, gchar **err_info)
+wtap_open_return_val vwr_open(wtap *wth, int *err, gchar **err_info)
{
int fpgaVer;
vwr_t *vwr;
fpgaVer = vwr_get_fpga_version(wth, err, err_info);
if (fpgaVer == -1) {
- return -1; /* I/O error */
+ return WTAP_OPEN_ERROR; /* I/O error */
}
if (fpgaVer == UNKNOWN_FPGA) {
- return 0; /* not a VWR file */
+ return WTAP_OPEN_NOT_MINE; /* not a VWR file */
}
/* This is a vwr file */
wth->snapshot_length = 0;
wth->subtype_read = vwr_read;
wth->subtype_seek_read = vwr_seek_read;
- wth->tsprecision = WTAP_FILE_TSPREC_USEC;
+ wth->file_tsprec = WTAP_TSPREC_USEC;
wth->file_encap = WTAP_ENCAP_IXVERIWAVE;
if (fpgaVer == S2_W_FPGA || fpgaVer == S1_W_FPGA || fpgaVer == S3_W_FPGA)
else if (fpgaVer == vVW510012_E_FPGA || fpgaVer == vVW510024_E_FPGA)
wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_VWR_ETH;
- return 1;
+ return WTAP_OPEN_MINE;
}
int rec_size = 0, IS_TX;
/* read the next frame record header in the capture file; if no more frames, return */
- if (!vwr_read_rec_header(vwr, wth->fh, &rec_size, &IS_TX, err, err_info))
+ if (!vwr_read_rec_header(wth->fh, &rec_size, &IS_TX, err, err_info))
return FALSE; /* Read error or EOF */
/*
return FALSE;
/* read in the record header */
- if (!vwr_read_rec_header(vwr, wth->random_fh, &rec_size, &IS_TX, err, err_info))
+ if (!vwr_read_rec_header(wth->random_fh, &rec_size, &IS_TX, err, err_info))
return FALSE; /* Read error or EOF */
return vwr_process_rec_data(wth->random_fh, rec_size, phdr, buf,
/* Return TRUE on success, FALSE on EOF or error. */
/* Also return the frame size in bytes and the "is transmitted frame" flag. */
-static gboolean vwr_read_rec_header(vwr_t *vwr, FILE_T fh, int *rec_size, int *IS_TX, int *err, gchar **err_info)
+static gboolean vwr_read_rec_header(FILE_T fh, int *rec_size, int *IS_TX, int *err, gchar **err_info)
{
int f_len, v_type;
guint8 header[VW_RECORD_HEADER_LENGTH];
- errno = WTAP_ERR_CANT_READ;
*rec_size = 0;
/* Read out the file data in 16-byte messages, stopping either after we find a frame, */
/* 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 (file_read(header, VW_RECORD_HEADER_LENGTH, fh) != VW_RECORD_HEADER_LENGTH) {
- *err = file_error(fh, err_info);
+ if (!wtap_read_bytes_or_eof(fh, header, VW_RECORD_HEADER_LENGTH, err, err_info))
return FALSE;
- }
/* Got a header; invoke decode-message function to parse and process it. */
/* If the function returns a length, then a frame or variable-length message */
/* follows the 16-byte message. */
/* If the variable length message is not a frame, simply skip over it. */
- if ((f_len = decode_msg(vwr, header, &v_type, IS_TX)) != 0) {
+ if ((f_len = decode_msg(header, &v_type, IS_TX)) != 0) {
if (f_len > B_SIZE) {
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("vwr: Invalid message record length %d", f_len);
return FALSE;
}
else if (v_type != VT_FRAME) {
- if (file_seek(fh, f_len, SEEK_CUR, err) < 0)
+ if (!file_skip(fh, f_len, err))
return FALSE;
}
else {
guint8 *s_510006_ptr = NULL;
guint8 *s_510024_ptr = NULL;
guint8 *s_510012_ptr = NULL; /* stats pointers */
- gint64 filePos = -1;
+ gint64 filePos;
guint32 frame_type = 0;
int f_len, v_type;
guint16 data_length = 0;
/* Each 16-byte message is decoded; if we run across a non-frame message followed by a */
/* 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 ((file_read(header, VW_RECORD_HEADER_LENGTH, wth->fh)) == VW_RECORD_HEADER_LENGTH) {
+ while (wtap_read_bytes(wth->fh, header, VW_RECORD_HEADER_LENGTH, err, err_info)) {
/* Got a header; invoke decode-message function to parse and process it. */
/* If the function returns a length, then a frame or variable-length message */
/* follows the 16-byte message. */
/* If the variable length message is not a frame, simply skip over it. */
- if ((f_len = decode_msg(NULL, header, &v_type, NULL)) != 0) {
+ if ((f_len = decode_msg(header, &v_type, NULL)) != 0) {
if (f_len > B_SIZE) {
/* Treat this here as an indication that the file probably */
/* isn't a vwr file. */
rec_size = f_len;
/* Got a frame record; read over entire record (frame + trailer) into a local buffer */
/* 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 && *err != WTAP_ERR_SHORT_READ)
- return -1;
- return UNKNOWN_FPGA; /* short read - not a vwr file */
+ if (!wtap_read_bytes(wth->fh, rec, rec_size, err, err_info)) {
+ if (*err == WTAP_ERR_SHORT_READ)
+ return UNKNOWN_FPGA; /* short read - not a vwr file */
+ return -1;
}
/* Next the series II WLAN */
- if ((rec_size > vVW510021_W_STATS_LEN) && (fpga_version == 1000)) {
+ if ((rec_size > vVW510021_W_STATS_TRAILER_LEN) && (fpga_version == 1000)) {
/* stats block */
- data_length = (256 * (rec[vVW510021_W_MSDU_LENGTH_OFF + 1] & 0x1f)) + rec[vVW510021_W_MSDU_LENGTH_OFF];
+ if ((header[8] == 48) || (header[8] == 61) || (header[8] == 68))
+ fpga_version = S3_W_FPGA;
+ else {
+ data_length = (256 * (rec[vVW510021_W_MSDU_LENGTH_OFF + 1] & 0x1f)) + rec[vVW510021_W_MSDU_LENGTH_OFF];
- i = 0;
- while (((data_length + i) % 4) != 0)
- i = i + 1;
+ i = 0;
+ while (((data_length + i) % 4) != 0)
+ i = i + 1;
- /*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 = S2_W_FPGA;
+ /*the 12 is from the 12 bytes of plcp header */
+ if (rec_size == (data_length + vVW510021_W_STATS_TRAILER_LEN +vVW510021_W_AFTERHEADER_LEN+12+i))
+ fpga_version = S2_W_FPGA;
+ }
}
/* Finally the Series II Ethernet */
if (rec_size == (data_length + vVW510024_E_STATS_LEN + i))
fpga_version = vVW510024_E_FPGA;
}
- if ((rec_size > vVW510021_W_STATS_LEN) && (fpga_version == 1000)) {
- /* Check the version of the FPGA */
- if (header[8] == 48)
- fpga_version = S3_W_FPGA;
- }
if (fpga_version != 1000)
{
/* reset the file position offset */
if (valid_but_empty_file > 0)
return(S3_W_FPGA);
- *err = file_error(wth->fh, err_info);
- if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
- return -1;
- return UNKNOWN_FPGA; /* short read - not a vwr file */
+ if (*err == WTAP_ERR_SHORT_READ)
+ return UNKNOWN_FPGA; /* short read - not a vwr file */
+ return -1;
}
/* 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 */
+/* The packet is constructed as a 38-byte VeriWave metadata header plus the raw */
/* MAC octets. */
-static void vwr_read_rec_data_wlan(vwr_t *vwr, struct wtap_pkthdr *phdr,
- guint8 *data_ptr, guint8 *rec,
- int rec_size, int IS_TX)
-{
- int bytes_written = 0; /* bytes output to buf so far */
- ext_rtap_fields er_fields; /* extended radiotap fields */
- stats_common_fields common_fields; /* extended radiotap fields */
- int mpdu_offset;
-
- /* Parse the stats block and fill the common and er structs */
- switch (vwr->FPGA_VERSION) {
- case S1_W_FPGA:
- mpdu_offset = parse_s1_W_stats(vwr, phdr, rec, rec_size, &er_fields, &common_fields);
- break;
- case S2_W_FPGA:
- case S3_W_FPGA:
- mpdu_offset = parse_s2_W_stats(vwr, phdr, rec, rec_size, &er_fields, &common_fields, IS_TX);
- break;
- default:
- return;
- }
-
- /* put common_fields into the packet buffer in little-endian byte order */
- phtoles(&data_ptr[bytes_written], common_fields.vw_port_type);
- bytes_written += 2;
- phtoles(&data_ptr[bytes_written], common_fields.it_len);
- bytes_written += 2;
- phtoles(&data_ptr[bytes_written], common_fields.vw_msdu_length);
- bytes_written += 2;
-
- phtolel(&data_ptr[bytes_written], common_fields.vw_flowid);
- bytes_written += 4;
- phtoles(&data_ptr[bytes_written], common_fields.vw_vcid);
- bytes_written += 2;
- phtoles(&data_ptr[bytes_written], common_fields.vw_seqnum);
- bytes_written += 2;
- phtolel(&data_ptr[bytes_written], common_fields.vw_latency);
- bytes_written += 4;
- phtolel(&data_ptr[bytes_written], common_fields.vw_sig_ts);
- bytes_written += 4;
- phtolell(&data_ptr[bytes_written], common_fields.vw_startt);
- bytes_written += 8;
- phtolell(&data_ptr[bytes_written], common_fields.vw_endt);
- bytes_written += 8;
- phtolel(&data_ptr[bytes_written], common_fields.vw_pktdur);
- bytes_written += 4;
-
- /* put er_fields into the packet buffer in little-endian byte order */
- phtoles(&data_ptr[bytes_written], er_fields.it_len);
- bytes_written += 2;
- phtoles(&data_ptr[bytes_written], er_fields.flags);
- bytes_written += 2;
- phtoles(&data_ptr[bytes_written], er_fields.chanflags);
- bytes_written += 2;
- phtoles(&data_ptr[bytes_written], er_fields.phyRate);
- bytes_written += 2;
- data_ptr[bytes_written] = er_fields.plcpType;
- bytes_written += 1;
- data_ptr[bytes_written] = er_fields.mcsIndex;
- bytes_written += 1;
- data_ptr[bytes_written] = er_fields.nss;
- bytes_written += 1;
- data_ptr[bytes_written] = er_fields.signal;
- bytes_written += 1;
- /* antennae b, c, d signal power */
- data_ptr[bytes_written] = er_fields.signalb;
- bytes_written += 1;
- data_ptr[bytes_written] = er_fields.signalc;
- bytes_written += 1;
- data_ptr[bytes_written] = er_fields.signald;
- bytes_written += 1;
- /* padding */
- data_ptr[bytes_written] = 0;
- bytes_written += 1;
- phtoles(&data_ptr[bytes_written], er_fields.vw_flags);
- bytes_written += 2;
- phtoles(&data_ptr[bytes_written], er_fields.vw_ht_length);
- bytes_written += 2;
- phtoles(&data_ptr[bytes_written], er_fields.vw_info);
- bytes_written += 2;
- phtolel(&data_ptr[bytes_written], er_fields.vw_errors);
- bytes_written += 4;
-
- /* finally, copy the whole MAC frame to the packet buffer as-is; exclude 4-byte FCS */
- if ( rec_size < ((int)common_fields.vw_msdu_length + (int)vwr->STATS_LEN) )
- /*something's been truncated, DUMP AS-IS*/
- memcpy(&data_ptr[bytes_written], &rec[mpdu_offset], common_fields.vw_msdu_length);
- else if (common_fields.vw_msdu_length >= 4)
- memcpy(&data_ptr[bytes_written], &rec[mpdu_offset], common_fields.vw_msdu_length - 4);
- else
- memcpy(&data_ptr[bytes_written], &rec[mpdu_offset], common_fields.vw_msdu_length);
-}
-
-
-static int parse_s1_W_stats(vwr_t *vwr, struct wtap_pkthdr *phdr, guint8 *rec,
- int rec_size, ext_rtap_fields * er_fields,
- stats_common_fields * common_fields)
+static gboolean vwr_read_s1_W_rec(vwr_t *vwr, struct wtap_pkthdr *phdr,
+ Buffer *buf, const guint8 *rec, int rec_size,
+ int *err, gchar **err_info)
{
- register int i; /* temps */
- register guint8 *s_ptr, *m_ptr; /* stats pointer */
- guint16 octets, msdu_length; /* octets in frame */
- guint64 tmp_len;
+ guint8 *data_ptr;
+ int bytes_written = 0; /* bytes output to buf so far */
+ const guint8 *s_ptr, *m_ptr; /* stats pointer */
+ guint16 msdu_length, actual_octets; /* octets in frame */
+ guint16 plcp_hdr_len; /* PLCP header length */
guint16 rflags;
- guint8 m_type, flow_seq; /* mod type (CCK-L/CCK-S/OFDM), seqnum */
+ guint8 m_type; /* mod type (CCK-L/CCK-S/OFDM), seqnum */
+ guint flow_seq;
guint64 s_time = LL_ZERO, e_time = LL_ZERO; /* start/end */
/* times, nsec */
guint32 latency;
guint64 start_time, s_sec, s_usec = LL_ZERO; /* start time, sec + usec */
guint64 end_time; /* end time */
guint32 info; /* INFO/ERRORS fields in stats blk */
- gint16 rssi; /* RSSI, signed 16-bit number */
+ gint8 rssi; /* RSSI, signed 8-bit number */
int f_tx; /* flag: if set, is a TX frame */
guint8 plcp_type, mcs_index, nss; /* PLCP type 0: Legacy, 1: Mixed, 2: Green field, 3: VHT Mixed */
- guint16 vc_id, flow_id, ht_len=0; /* VC ID, flow ID, total ip length */
+ guint16 vc_id, ht_len=0; /* VC ID, total ip length */
+ guint flow_id; /* flow ID */
guint32 d_time, errors; /* packet duration & errors */
- guint16 r_hdr_len; /* length of radiotap headers */
int sig_off, pay_off; /* MAC+SNAP header len, signature offset */
guint64 sig_ts; /* 32 LSBs of timestamp in signature */
- float phyRate;
+ guint16 phyRate;
+ guint16 vw_flags; /* VeriWave-specific packet flags */
+ /*
+ * The record data must be large enough to hold the statistics trailer.
+ */
+ if (rec_size < v22_W_STATS_LEN) {
+ *err_info = g_strdup_printf("vwr: Invalid record length %d (must be at least %u)",
+ rec_size, v22_W_STATS_LEN);
+ *err = WTAP_ERR_BAD_FILE;
+ return FALSE;
+ }
/* Calculate the start of the statistics block in the buffer */
/* Also get a bunch of fields from the stats block */
- s_ptr = &(rec[rec_size - vwr->STATS_LEN]); /* point to it */
- m_type = s_ptr[1] & 0x7;
- f_tx = !(s_ptr[1] & 0x8);
- octets = pntoh16(&s_ptr[8]);
- vc_id = pntoh16(&s_ptr[2]) & 0x3ff;
- flow_seq = s_ptr[4];
+ s_ptr = &(rec[rec_size - v22_W_STATS_LEN]); /* point to it */
+ m_type = s_ptr[v22_W_MTYPE_OFF] & 0x7;
+ f_tx = !(s_ptr[v22_W_MTYPE_OFF] & 0x8);
+ actual_octets = pntoh16(&s_ptr[v22_W_OCTET_OFF]);
+ vc_id = pntoh16(&s_ptr[v22_W_VCID_OFF]) & 0x3ff;
+ flow_seq = s_ptr[v22_W_FLOWSEQ_OFF];
+
+ latency = (guint32)pcorey48tohll(&s_ptr[v22_W_LATVAL_OFF]);
- /* XXX - this is 48 bits, in a weird byte order */
- latency = (s_ptr[40 + 6] << 8) | (s_ptr[40 + 7]); /* latency MSbytes */
- for (i = 0; i < 4; i++)
- latency = (latency << 8) | s_ptr[40 + i];
+ flow_id = pntoh16(&s_ptr[v22_W_FLOWID_OFF+1]); /* only 16 LSBs kept */
+ errors = pntoh16(&s_ptr[v22_W_ERRORS_OFF]);
- flow_id = pntoh16(&s_ptr[6]); /* only 16 LSBs kept */
- errors = pntoh16(&s_ptr[10]);
+ info = pntoh16(&s_ptr[v22_W_INFO_OFF]);
+ rssi = (s_ptr[v22_W_RSSI_OFF] & 0x80) ? (-1 * (s_ptr[v22_W_RSSI_OFF] & 0x7f)) : s_ptr[v22_W_RSSI_OFF];
- info = pntoh16(&s_ptr[54]);
- rssi = (s_ptr[21] & 0x80) ? (-1 * (s_ptr[21] & 0x7f)) : s_ptr[21];
+ /*
+ * Sanity check the octets field to determine if it's greater than
+ * the packet data available in the record - i.e., the record size
+ * minus the length of the statistics block.
+ *
+ * Report an error if it is.
+ */
+ if (actual_octets > rec_size - v22_W_STATS_LEN) {
+ *err_info = g_strdup_printf("vwr: Invalid data length %u (runs past the end of the record)",
+ actual_octets);
+ *err = WTAP_ERR_BAD_FILE;
+ return FALSE;
+ }
/* Decode OFDM or CCK PLCP header and determine rate and short preamble flag. */
/* The SIGNAL byte is always the first byte of the PLCP header in the frame. */
mcs_index = get_cck_rate(rec);
else
mcs_index = 1;
- rflags = (m_type == vwr->MT_CCKS) ? RADIOTAP_F_SHORTPRE : 0;
- phyRate = getRate(plcp_type, mcs_index, rflags, nss);
+ rflags = (m_type == vwr->MT_CCKS) ? FLAGS_SHORTPRE : 0;
/* 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. */
- m_ptr = &(rec[((m_type == vwr->MT_OFDM) ? 4 : 6)]);
- tmp_len = (m_type == vwr->MT_OFDM) ? 4 : 6;
- if (octets >= tmp_len)
- octets -= (guint16) tmp_len;
- else
- octets = 0;
+ plcp_hdr_len = (m_type == vwr->MT_OFDM) ? 4 : 6;
+ if (actual_octets >= plcp_hdr_len)
+ actual_octets -= plcp_hdr_len;
+ else {
+ *err_info = g_strdup_printf("vwr: Invalid data length %u (too short to include %u-byte PLCP header)",
+ actual_octets, plcp_hdr_len);
+ *err = WTAP_ERR_BAD_FILE;
+ return FALSE;
+ }
+ m_ptr = &rec[plcp_hdr_len];
+ msdu_length = actual_octets;
/*
- * Sanity check the octets field to determine if it's greater than
- * the packet data available in the record - i.e., the record size
- * minus the length of the statistics block.
+ * The MSDU length includes the FCS.
+ *
+ * The packet data does *not* include the FCS - it's just 4 bytes
+ * of junk - so we have to remove it.
*
- * Truncate it if it is.
+ * We'll be stripping off an FCS (?), so make sure we have at
+ * least 4 octets worth of FCS.
*/
- if (octets > (rec_size - vwr->STATS_LEN))
- octets = (rec_size - vwr->STATS_LEN);
- msdu_length = octets;
-
+ if (actual_octets < 4) {
+ *err_info = g_strdup_printf("vwr: Invalid data length %u (too short to include %u-byte PLCP header and 4 bytes of FCS)",
+ actual_octets, plcp_hdr_len);
+ *err = WTAP_ERR_BAD_FILE;
+ return FALSE;
+ }
+ actual_octets -= 4;
/* Calculate start & end times (in sec/usec), converting 64-bit times to usec. */
/* 64-bit times are "Corey-endian" */
- s_time = pcoreytohll(&s_ptr[24]);
- e_time = pcoreytohll(&s_ptr[32]);
+ s_time = pcoreytohll(&s_ptr[v22_W_STARTT_OFF]);
+ e_time = pcoreytohll(&s_ptr[v22_W_ENDT_OFF]);
/* find the packet duration (difference between start and end times) */
d_time = (guint32)((e_time - s_time) / NS_IN_US); /* find diff, converting to usec */
/* extract the 32 LSBs of the signature timestamp field from the data block*/
pay_off = 42; /* 24 (MAC) + 8 (SNAP) + IP */
sig_off = find_signature(m_ptr, rec_size - 6, pay_off, flow_id, flow_seq);
- if ((m_ptr[sig_off] == 0xdd) && (sig_off + 15 <= (rec_size - 48)))
+ if ((m_ptr[sig_off] == 0xdd) && (sig_off + 15 <= (rec_size - v22_W_STATS_LEN)))
sig_ts = get_signature_ts(m_ptr, sig_off);
else
sig_ts = 0;
- /* Pack the common and er structs) */
- r_hdr_len = STATS_COMMON_FIELDS_LEN + EXT_RTAP_FIELDS_LEN;
-
- tmp_len = (msdu_length - 4) + r_hdr_len;
- phdr->len = tmp_len<=G_MAXUINT32 ? (guint32) tmp_len : 0;
- tmp_len = (octets - 4) + r_hdr_len;
- phdr->caplen = tmp_len<=G_MAXUINT32 ? (guint32) tmp_len : 0;
-
- phdr->len = (msdu_length - 4) + r_hdr_len;
- phdr->caplen = (octets - 4) + r_hdr_len;
-
- phdr->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
+ /*
+ * Fill up the per-packet header.
+ *
+ * We also zero out 16 bytes PLCP header and 1 byte of L1P for user
+ * position.
+ *
+ * XXX - for S1, do we even have that? The current Veriwave dissector
+ * just blindly assumes there's a 17-byte blob before the 802.11
+ * header, which is why we fill in those extra zero bytes.
+ *
+ * We include the length of the metadata headers in the packet lengths.
+ *
+ * The maximum value of actual_octets is 65535, which, even after
+ * adding the lengths of the metadata headers, is less than
+ * WTAP_MAX_PACKET_SIZE will ever be, so we don't need to check it.
+ */
+ phdr->len = STATS_COMMON_FIELDS_LEN + EXT_WLAN_FIELDS_LEN + 1 + 16 + actual_octets;
+ phdr->caplen = STATS_COMMON_FIELDS_LEN + EXT_WLAN_FIELDS_LEN + 1 + 16 + actual_octets;
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;
- common_fields->it_len = STATS_COMMON_FIELDS_LEN;
- common_fields->vw_vcid = (guint16)vc_id;
- common_fields->vw_flowid = (guint16)flow_id;
- common_fields->vw_seqnum = (guint16)flow_seq;
- if (!f_tx && sig_ts != 0)
- common_fields->vw_latency = (guint32)latency;
- else
- common_fields->vw_latency = 0;
- common_fields->vw_pktdur = (guint32)d_time;
- common_fields->vw_msdu_length = (guint16)msdu_length;
- common_fields->vw_sig_ts = (guint32)sig_ts; /* 32 LSBs of signature timestamp (nsec) */
- common_fields->vw_startt = start_time; /* record start & end times of frame */
- common_fields->vw_endt = end_time;
-
- er_fields->it_len = EXT_RTAP_FIELDS_LEN;
- er_fields->flags = rflags;
- er_fields->phyRate = (guint16)(phyRate * 10);
- er_fields->plcpType = plcp_type;
- er_fields->mcsIndex = mcs_index;
- er_fields->nss = nss;
- er_fields->chanflags = (m_type == vwr->MT_OFDM) ? CHAN_OFDM : CHAN_CCK;
- er_fields->signal = (gint8)rssi;
- er_fields->signalb = 100;
- er_fields->signalc = 100;
- er_fields->signald = 100;
+ phdr->rec_type = REC_TYPE_PACKET;
+ phdr->presence_flags = WTAP_HAS_TS;
+
+ ws_buffer_assure_space(buf, phdr->caplen);
+ data_ptr = ws_buffer_start_ptr(buf);
+
+ /*
+ * Generate and copy out the common metadata headers,
+ * set the port type to 0 (WLAN).
+ *
+ * All values are copied out in little-endian byte order.
+ */
+ phtoles(&data_ptr[bytes_written], 0); /* port_type */
+ bytes_written += 2;
+ phtoles(&data_ptr[bytes_written], STATS_COMMON_FIELDS_LEN); /* it_len */
+ bytes_written += 2;
+ phtoles(&data_ptr[bytes_written], msdu_length);
+ bytes_written += 2;
+ phtolel(&data_ptr[bytes_written], flow_id);
+ bytes_written += 4;
+ phtoles(&data_ptr[bytes_written], vc_id);
+ bytes_written += 2;
+ phtoles(&data_ptr[bytes_written], flow_seq);
+ bytes_written += 2;
+ if (!f_tx && sig_ts != 0) {
+ phtolel(&data_ptr[bytes_written], latency);
+ } else {
+ phtolel(&data_ptr[bytes_written], 0);
+ }
+ bytes_written += 4;
+ phtolel(&data_ptr[bytes_written], sig_ts); /* 32 LSBs of signature timestamp (nsec) */
+ bytes_written += 4;
+ phtolell(&data_ptr[bytes_written], start_time); /* record start & end times of frame */
+ bytes_written += 8;
+ phtolell(&data_ptr[bytes_written], end_time);
+ bytes_written += 8;
+ phtolel(&data_ptr[bytes_written], d_time);
+ bytes_written += 4;
+
+ /*
+ * Generate and copy out the WLAN metadata headers.
+ *
+ * All values are copied out in little-endian byte order.
+ */
+ phtoles(&data_ptr[bytes_written], EXT_WLAN_FIELDS_LEN);
+ bytes_written += 2;
+ phtoles(&data_ptr[bytes_written], rflags);
+ bytes_written += 2;
+ if (m_type == vwr->MT_OFDM) {
+ phtoles(&data_ptr[bytes_written], CHAN_OFDM);
+ } else {
+ phtoles(&data_ptr[bytes_written], CHAN_CCK);
+ }
+ bytes_written += 2;
+ phyRate = (guint16)(getRate(plcp_type, mcs_index, rflags, nss) * 10);
+ phtoles(&data_ptr[bytes_written], phyRate);
+ bytes_written += 2;
+ data_ptr[bytes_written] = plcp_type;
+ bytes_written += 1;
+ data_ptr[bytes_written] = mcs_index;
+ bytes_written += 1;
+ data_ptr[bytes_written] = nss;
+ bytes_written += 1;
+ data_ptr[bytes_written] = rssi;
+ bytes_written += 1;
+ /* antennae b, c, d signal power */
+ data_ptr[bytes_written] = 100;
+ bytes_written += 1;
+ data_ptr[bytes_written] = 100;
+ bytes_written += 1;
+ data_ptr[bytes_written] = 100;
+ bytes_written += 1;
+ /* padding */
+ data_ptr[bytes_written] = 0;
+ bytes_written += 1;
/* fill in the VeriWave flags field */
- er_fields->vw_flags = 0;
+ vw_flags = 0;
if (f_tx)
- er_fields->vw_flags |= RADIOTAP_VWF_TXF;
+ vw_flags |= VW_FLAGS_TXF;
if (errors & vwr->FCS_ERROR)
- er_fields->vw_flags |= RADIOTAP_VWF_FCSERR;
+ vw_flags |= VW_FLAGS_FCSERR;
if (!f_tx && (errors & vwr->CRYPTO_ERR))
- er_fields->vw_flags |= RADIOTAP_VWF_DCRERR;
+ vw_flags |= VW_FLAGS_DCRERR;
if (!f_tx && (errors & vwr->RETRY_ERR))
- er_fields->vw_flags |= RADIOTAP_VWF_RETRERR;
+ vw_flags |= VW_FLAGS_RETRERR;
if (info & vwr->WEPTYPE)
- er_fields->vw_flags |= RADIOTAP_VWF_IS_WEP;
+ vw_flags |= VW_FLAGS_IS_WEP;
else if (info & vwr->TKIPTYPE)
- er_fields->vw_flags |= RADIOTAP_VWF_IS_TKIP;
+ vw_flags |= VW_FLAGS_IS_TKIP;
else if (info & vwr->CCMPTYPE)
- er_fields->vw_flags |= RADIOTAP_VWF_IS_CCMP;
- er_fields->vw_errors = (guint32)errors;
- er_fields->vw_info = (guint16)info;
- er_fields->vw_ht_length = (guint16)ht_len;
+ vw_flags |= VW_FLAGS_IS_CCMP;
+ phtoles(&data_ptr[bytes_written], vw_flags);
+ bytes_written += 2;
- /* return the offset to the actual frame data */
- return (m_type == vwr->MT_OFDM) ? 4 : 6;
+ phtoles(&data_ptr[bytes_written], ht_len);
+ bytes_written += 2;
+ phtoles(&data_ptr[bytes_written], info);
+ bytes_written += 2;
+ phtolel(&data_ptr[bytes_written], errors);
+ bytes_written += 4;
+
+ /*
+ * No VHT, no VHT NDP flag, so just zero.
+ *
+ * XXX - is this supposed to be the RX L1 info, i.e. the "1 byte of L1P
+ * for user position"?
+ */
+ data_ptr[bytes_written] = 0;
+ bytes_written += 1;
+
+ /*
+ * XXX - put a PLCP header here? That's what's done for S3.
+ */
+ memset(&data_ptr[bytes_written], 0, 16);
+ bytes_written += 16;
+
+ /*
+ * Finally, copy the whole MAC frame to the packet buffer as-is.
+ * This does not include the PLCP; the MPDU starts at 4 or 6
+ * depending on OFDM/CCK.
+ * This also does not include the last 4 bytes, as those don't
+ * contain an FCS, they just contain junk.
+ */
+ memcpy(&data_ptr[bytes_written], &rec[plcp_hdr_len], actual_octets);
+
+ return TRUE;
}
-static int parse_s2_W_stats(vwr_t *vwr, struct wtap_pkthdr *phdr,
- guint8 *rec, int rec_size,
- ext_rtap_fields * er_fields,
- stats_common_fields * common_fields, int IS_TX)
+static gboolean vwr_read_s2_s3_W_rec(vwr_t *vwr, struct wtap_pkthdr *phdr,
+ Buffer *buf, const guint8 *rec, int rec_size,
+ int IS_TX, int *err, gchar **err_info)
{
+ guint8 *data_ptr;
+ int bytes_written = 0; /* bytes output to buf so far */
register int i; /* temps */
- register guint8 *s_start_ptr,*s_trail_ptr, *plcp_ptr, *m_ptr; /* stats & MPDU ptr */
-
+ const guint8 *s_start_ptr,*s_trail_ptr, *plcp_ptr, *m_ptr; /* stats & MPDU ptr */
guint32 msdu_length, actual_octets; /* octets in frame */
- guint64 tmp_len;
- guint8 l1p_1,l1p_2, flow_seq, plcp_type, mcs_index, nss; /* mod (CCK-L/CCK-S/OFDM) */
+ guint8 l1p_1,l1p_2, plcp_type, mcs_index, nss; /* mod (CCK-L/CCK-S/OFDM) */
+ guint flow_seq;
guint64 s_time = LL_ZERO, e_time = LL_ZERO; /* start/end */
/* times, nsec */
guint64 latency = LL_ZERO;
guint64 end_time; /* end time */
guint16 info; /* INFO/ERRORS fields in stats blk */
guint32 errors;
- gint16 rssi[] = {0,0,0,0}; /* RSSI, signed 16-bit number */
+ gint8 rssi[] = {0,0,0,0}; /* RSSI, signed 8-bit number */
int f_tx; /* flag: if set, is a TX frame */
guint16 vc_id, ht_len=0; /* VC ID , total ip length*/
guint32 flow_id, d_time; /* flow ID, packet duration*/
- guint16 r_hdr_len; /* length of radiotap headers */
int sig_off, pay_off; /* MAC+SNAP header len, signature offset */
guint64 sig_ts, tsid; /* 32 LSBs of timestamp in signature */
- guint16 chanflags = 0; /* extended radio tap channel flags */
- guint16 radioflags = 0; /* extended radio tap flags */
+ guint16 chanflags = 0; /* channel flags for WLAN metadata header */
+ guint16 radioflags = 0; /* flags for WLAN metadata header */
guint64 delta_b; /* Used for calculating latency */
+ guint16 phyRate;
+ guint16 vw_flags; /* VeriWave-specific packet flags */
+ guint8 vht_ndp_flag = 0;
+ /*
+ * The record data must be large enough to hold the statistics header,
+ * the PLCP, and the statistics trailer.
+ */
+ if ((guint)rec_size < vwr->MPDU_OFF + vVW510021_W_STATS_TRAILER_LEN) {
+ *err_info = g_strdup_printf("vwr: Invalid record length %d (must be at least %u)",
+ rec_size,
+ vwr->MPDU_OFF + vVW510021_W_STATS_TRAILER_LEN);
+ *err = WTAP_ERR_BAD_FILE;
+ return FALSE;
+ }
/* Calculate the start of the statistics blocks in the buffer */
/* Also get a bunch of fields from the stats blocks */
s_start_ptr = &(rec[0]); /* point to stats header */
- s_trail_ptr = &(rec[rec_size - vwr->STATS_LEN]); /* point to stats trailer */
+ s_trail_ptr = &(rec[rec_size - vVW510021_W_STATS_TRAILER_LEN]); /* point to stats trailer */
/* L1p info is different for series III and for Series II - need to check */
- l1p_1 = s_start_ptr[0];
- l1p_2 = s_start_ptr[1];
+ l1p_1 = s_start_ptr[vVW510021_W_L1P_1_OFF];
+ l1p_2 = s_start_ptr[vVW510021_W_L1P_2_OFF];
if (vwr->FPGA_VERSION == S2_W_FPGA)
{
- mcs_index = l1p_1 & 0x3f;
- plcp_type = l1p_2 & 0x03;
+ mcs_index = vVW510021_W_S2_MCS_INDEX(l1p_1);
+ plcp_type = vVW510021_W_S2_PLCP_TYPE(l1p_2);
/* we do the range checks at the end before copying the values
into the wtap header */
- msdu_length = ((s_start_ptr[4] & 0x1f) << 8) + s_start_ptr[3];
- actual_octets = msdu_length;
+ msdu_length = ((s_start_ptr[vVW510021_W_MSDU_LENGTH_OFF+1] & 0x1f) << 8)
+ + s_start_ptr[vVW510021_W_MSDU_LENGTH_OFF];
- vc_id = pntoh16(&s_start_ptr[6]);
+ vc_id = pntoh16(&s_start_ptr[vVW510021_W_VCID_OFF]);
if (IS_TX)
{
- rssi[0] = (s_start_ptr[2] & 0x80) ? -1 * (s_start_ptr[2] & 0x7f) : s_start_ptr[2] & 0x7f;
+ rssi[0] = (s_start_ptr[vVW510021_W_RSSI_TXPOWER_OFF] & 0x80) ?
+ -1 * (s_start_ptr[vVW510021_W_RSSI_TXPOWER_OFF] & 0x7f) :
+ s_start_ptr[vVW510021_W_RSSI_TXPOWER_OFF] & 0x7f;
}
else
{
- rssi[0] = (s_start_ptr[2] & 0x80) ? (s_start_ptr[2]- 256) : s_start_ptr[2];
+ rssi[0] = (s_start_ptr[vVW510021_W_RSSI_TXPOWER_OFF] & 0x80) ?
+ (s_start_ptr[vVW510021_W_RSSI_TXPOWER_OFF]- 256) :
+ s_start_ptr[vVW510021_W_RSSI_TXPOWER_OFF];
}
rssi[1] = 100;
rssi[2] = 100;
rssi[3] = 100;
nss = 0;
+
+ /* XXX - S2 claims to have 11 bytes of PLCP and 1 byte of pad */
plcp_ptr = &(rec[8]);
}
else
{
- plcp_type = l1p_2 & 0xf;
+ /* XXX - what indicates which packets include the FCS? */
+ radioflags |= FLAGS_FCS;
+ plcp_type = vVW510021_W_S3_PLCP_TYPE(l1p_2);
if (plcp_type == vVW510021_W_PLCP_VHT_MIXED)
{
- mcs_index = l1p_1 & 0x0f;
- nss = (l1p_1 >> 4 & 0x3) + 1; /* The nss is zero based from the fpga - increment it here */
+ /* VHT */
+ mcs_index = vVW510021_W_S3_MCS_INDEX_VHT(l1p_1);
+ nss = vVW510021_W_S3_NSS_VHT(l1p_1);
}
else
{
- mcs_index = l1p_1 & 0x3f;
+ /* HT */
+ mcs_index = vVW510021_W_S3_MCS_INDEX_HT(l1p_1);
nss = 0;
}
+
+ /*** Extract NDP Flag if it is a received frame ***/
+ if (!IS_TX){
+ vht_ndp_flag = s_start_ptr[8];
+ }
+
msdu_length = pntoh24(&s_start_ptr[9]);
- actual_octets = msdu_length;
- vc_id = pntoh16(&s_start_ptr[14]) & 0x3ff;
+ vc_id = pntoh16(&s_start_ptr[14]) & vVW510024_W_VCID_MASK;
for (i = 0; i < 4; i++)
{
if (IS_TX)
}
}
+ /*** 16 bytes of PLCP header + 1 byte of L1P for user position ***/
+ /* XXX - S3 claims to have 16 bytes of stats block and 16 bytes of
+ *something*. Are those 16 bytes the PLCP? */
plcp_ptr = &(rec[16]);
}
+ actual_octets = msdu_length;
+
+ /*
+ * Sanity check the octets field to determine if it's greater than
+ * the packet data available in the record - i.e., the record size
+ * minus the sum of (length of statistics header + PLCP) and
+ * (length of statistics trailer).
+ *
+ * Report an error if it is.
+ */
+ if (actual_octets > rec_size - (vwr->MPDU_OFF + vVW510021_W_STATS_TRAILER_LEN)) {
+ *err_info = g_strdup_printf("vwr: Invalid data length %u (runs past the end of the record)",
+ actual_octets);
+ *err = WTAP_ERR_BAD_FILE;
+ return FALSE;
+ }
f_tx = IS_TX;
- flow_seq = s_trail_ptr[32];
+ flow_seq = s_trail_ptr[vVW510021_W_FLOWSEQ_OFF];
latency = 0x00000000; /* clear latency */
- flow_id = pntoh24(&s_trail_ptr[33]); /* all 24 bits valid */
+ flow_id = pntoh24(&s_trail_ptr[vVW510021_W_FLOWID_OFF]); /* all 24 bits valid */
/* For tx latency is duration, for rx latency is timestamp */
/* Get 48-bit latency value */
- tsid = (s_trail_ptr[36 + 6] << 8) | (s_trail_ptr[36 + 7]);
+ tsid = pcorey48tohll(&s_trail_ptr[vVW510021_W_LATVAL_OFF]);
- for (i = 0; i < 4; i++)
- tsid = (tsid << 8) | s_trail_ptr[36 + i];
-
- errors = pntoh32(&s_trail_ptr[16]);
- info = pntoh16(&s_trail_ptr[22]);
- if ((info & 0xFC00) != 0)
+ errors = pntoh32(&s_trail_ptr[vVW510021_W_ERRORS_OFF]);
+ info = pntoh16(&s_trail_ptr[vVW510021_W_INFO_OFF]);
+ if ((info & v22_W_AGGREGATE_FLAGS) != 0)
/* this length includes the Start_Spacing + Delimiter + MPDU + Padding for each piece of the aggregate*/
ht_len = pletoh16(&s_start_ptr[vwr->PLCP_LENGTH_OFF]);
/* decode OFDM or CCK PLCP header and determine rate and short preamble flag */
/* the SIGNAL byte is always the first byte of the PLCP header in the frame */
if (plcp_type == vVW510021_W_PLCP_LEGACY){
+ /*
+ * From IEEE Std 802.11-2012:
+ *
+ * According to section 17.2.2 "PPDU format", the PLCP header
+ * for the High Rate DSSS PHY (11b) has a SIGNAL field that's
+ * 8 bits, followed by a SERVICE field that's 8 bits, followed
+ * by a LENGTH field that's 16 bits, followed by a CRC field
+ * that's 16 bits. The PSDU follows it. Section 17.2.3 "PPDU
+ * field definitions" describes those fields.
+ *
+ * According to sections 18.3.2 "PLCP frame format" and 18.3.4
+ * "SIGNAL field", the PLCP for the OFDM PHY (11a) has a SIGNAL
+ * field that's 24 bits, followed by a service field that's
+ * 16 bits, followed by the PSDU. Section 18.3.5.2 "SERVICE
+ * field" describes the SERVICE field.
+ *
+ * According to section 19.3.2 "PPDU format", the frames for the
+ * Extended Rate PHY (11g) either extend the 11b format, using
+ * additional bits in the SERVICE field, or extend the 11a
+ * format.
+ */
if (mcs_index < 4) {
chanflags |= CHAN_CCK;
}
}
}
else if (plcp_type == vVW510021_W_PLCP_MIXED) {
+ /*
+ * According to section 20.3.2 "PPDU format", the HT-mixed
+ * PLCP header has a "Non-HT SIGNAL field" (L-SIG), which
+ * looks like an 11a SIGNAL field, followed by an HT SIGNAL
+ * field (HT-SIG) described in section 20.3.9.4.3 "HT-SIG
+ * definition".
+ *
+ * This means that the first octet of HT-SIG is at
+ * plcp_ptr[3], skipping the 3 octets of the L-SIG field.
+ *
+ * 0x80 is the CBW 20/40 bit of HT-SIG.
+ */
/* set the appropriate flags to indicate HT mode and CB */
- radioflags |= RADIOTAP_F_CHAN_HT | ((plcp_ptr[3] & 0x80) ? RADIOTAP_F_CHAN_40MHZ : 0) |
- ((l1p_1 & 0x40) ? 0 : RADIOTAP_F_CHAN_SHORTGI);
+ radioflags |= FLAGS_CHAN_HT | ((plcp_ptr[3] & 0x80) ? FLAGS_CHAN_40MHZ : 0) |
+ ((l1p_1 & vVW510021_W_IS_LONGGI) ? 0 : FLAGS_CHAN_SHORTGI);
chanflags |= CHAN_OFDM;
}
else if (plcp_type == vVW510021_W_PLCP_GREENFIELD) {
+ /*
+ * According to section 20.3.2 "PPDU format", the HT-greenfield
+ * PLCP header just has the HT SIGNAL field (HT-SIG) above, with
+ * no L-SIG field.
+ *
+ * This means that the first octet of HT-SIG is at
+ * plcp_ptr[0], as there's no L-SIG field to skip.
+ *
+ * 0x80 is the CBW 20/40 bit of HT-SIG.
+ */
/* set the appropriate flags to indicate HT mode and CB */
- radioflags |= RADIOTAP_F_CHAN_HT | ((plcp_ptr[0] & 0x80) ? RADIOTAP_F_CHAN_40MHZ : 0) |
- ((l1p_1 & 0x40) ? 0 : RADIOTAP_F_CHAN_SHORTGI);
+ radioflags |= FLAGS_CHAN_HT | ((plcp_ptr[0] & 0x80) ? FLAGS_CHAN_40MHZ : 0) |
+ ((l1p_1 & vVW510021_W_IS_LONGGI) ? 0 : FLAGS_CHAN_SHORTGI);
chanflags |= CHAN_OFDM;
}
else if (plcp_type == vVW510021_W_PLCP_VHT_MIXED) {
- guint8 SBW = l1p_2 >> 4 & 0xf;
- radioflags |= RADIOTAP_F_CHAN_VHT | ((l1p_1 & 0x40) ? 0 : RADIOTAP_F_CHAN_SHORTGI);
+ /*
+ * According to section 22.3.2 "VHTPPDU format" of IEEE Std
+ * 802.11ac-2013, the VHT PLCP header has a "non-HT SIGNAL field"
+ * (L-SIG), which looks like an 11a SIGNAL field, followed by
+ * a VHT Signal A field (VHT-SIG-A) described in section
+ * 22.3.8.3.3 "VHT-SIG-A definition", with training fields
+ * between it and a VHT Signal B field (VHT-SIG-B) described
+ * in section 22.3.8.3.6 "VHT-SIG-B definition", followed by
+ * the PSDU.
+ */
+ guint8 SBW = vVW510021_W_BANDWIDTH_VHT(l1p_2);
+ radioflags |= FLAGS_CHAN_VHT | ((l1p_1 & vVW510021_W_IS_LONGGI) ? 0 : FLAGS_CHAN_SHORTGI);
chanflags |= CHAN_OFDM;
if (SBW == 3)
- radioflags |= RADIOTAP_F_CHAN_40MHZ;
+ radioflags |= FLAGS_CHAN_40MHZ;
else if (SBW == 4)
- radioflags |= RADIOTAP_F_CHAN_80MHZ;
- }
-
- if (msdu_length > (guint32)(rec_size - 48)) {
- msdu_length = (guint32)(rec_size - 48);
+ radioflags |= FLAGS_CHAN_80MHZ;
}
/* Calculate start & end times (in sec/usec), converting 64-bit times to usec. */
/* 64-bit times are "Corey-endian" */
- s_time = pcoreytohll(&s_trail_ptr[0]);
- e_time = pcoreytohll(&s_trail_ptr[8]);
+ s_time = pcoreytohll(&s_trail_ptr[vVW510021_W_STARTT_OFF]);
+ e_time = pcoreytohll(&s_trail_ptr[vVW510021_W_ENDT_OFF]);
/* find the packet duration (difference between start and end times) */
d_time = (guint32)((e_time - s_time) / NS_IN_US); /* find diff, converting to usec */
m_ptr = &(rec[8+12]);
pay_off = 42; /* 24 (MAC) + 8 (SNAP) + IP */
sig_off = find_signature(m_ptr, rec_size - 20, pay_off, flow_id, flow_seq);
- if ((m_ptr[sig_off] == 0xdd) && (sig_off + 15 <= (rec_size - 48)))
+ if ((m_ptr[sig_off] == 0xdd) && (sig_off + 15 <= (rec_size - vVW510021_W_STATS_TRAILER_LEN)))
sig_ts = get_signature_ts(m_ptr, sig_off);
else
sig_ts = 0;
}
}
- /* Fill up the per-packet header (amazingly like a PCAP packet header! ;-) */
- /* Frames are always 802.11, with an extended radiotap header. */
- /* caplen is the length that is captured into the file (i.e., the written-out frame */
- /* block), and should always represent the actual number of bytes in the file. */
- /* 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;
- tmp_len = (actual_octets - 4) + r_hdr_len;
- phdr->len = tmp_len<=G_MAXUINT32 ? (guint32) tmp_len : 0;
- tmp_len = (msdu_length - 4) + r_hdr_len;
- phdr->caplen = tmp_len<=G_MAXUINT32 ? (guint32) tmp_len : 0;
-
- phdr->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
+ /*
+ * Fill up the per-packet header.
+ *
+ * We also copy over 16 bytes of PLCP header + 1 byte of L1P for user
+ * position.
+ *
+ * XXX - for S2, we don't have 16 bytes of PLCP header; do we have
+ * the 1 byte of L1P? The current Veriwave dissector just blindly
+ * assumes there's a 17-byte blob before the 802.11 header.
+ *
+ * We include the length of the metadata headers in the packet lengths.
+ */
+ phdr->len = STATS_COMMON_FIELDS_LEN + EXT_WLAN_FIELDS_LEN + 1 + 16 + actual_octets;
+ phdr->caplen = STATS_COMMON_FIELDS_LEN + EXT_WLAN_FIELDS_LEN + 1 + 16 + actual_octets;
+ if (phdr->caplen > WTAP_MAX_PACKET_SIZE) {
+ /*
+ * Probably a corrupt capture file; return an error,
+ * so that our caller doesn't blow up trying to allocate
+ * space for an immensely-large packet.
+ */
+ *err_info = g_strdup_printf("vwr: File has %u-byte packet, bigger than maximum of %u",
+ phdr->caplen, WTAP_MAX_PACKET_SIZE);
+ *err = WTAP_ERR_BAD_FILE;
+ return FALSE;
+ }
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;
- common_fields->it_len = STATS_COMMON_FIELDS_LEN;
- common_fields->vw_vcid = (guint16)vc_id;
- common_fields->vw_msdu_length = (guint16)msdu_length;
- common_fields->vw_flowid = (guint32)flow_id;
- common_fields->vw_seqnum = (guint16)flow_seq;
- if (!f_tx && (sig_ts != 0) )
- common_fields->vw_latency = (guint32)latency;
- else
- common_fields->vw_latency = 0;
- common_fields->vw_pktdur = (guint32)d_time;
- common_fields->vw_startt = start_time; /* record start & end times of frame */
- common_fields->vw_endt = end_time;
- common_fields->vw_sig_ts = (guint32)(sig_ts); /* 32 LSBs of signature */
-
- er_fields->it_len = EXT_RTAP_FIELDS_LEN;
- er_fields->flags = radioflags;
+ phdr->rec_type = REC_TYPE_PACKET;
+ phdr->presence_flags = WTAP_HAS_TS;
+
+ ws_buffer_assure_space(buf, phdr->caplen);
+ data_ptr = ws_buffer_start_ptr(buf);
+
+ /*
+ * Generate and copy out the common metadata headers,
+ * set the port type to 0 (WLAN).
+ *
+ * All values are copied out in little-endian byte order.
+ */
+ /*** msdu_length = msdu_length + 16; ***/
+ phtoles(&data_ptr[bytes_written], 0); /* port_type */
+ bytes_written += 2;
+ phtoles(&data_ptr[bytes_written], STATS_COMMON_FIELDS_LEN); /* it_len */
+ bytes_written += 2;
+ phtoles(&data_ptr[bytes_written], msdu_length);
+ bytes_written += 2;
+ phtolel(&data_ptr[bytes_written], flow_id);
+ bytes_written += 4;
+ phtoles(&data_ptr[bytes_written], vc_id);
+ bytes_written += 2;
+ phtoles(&data_ptr[bytes_written], flow_seq);
+ bytes_written += 2;
+ if (!f_tx && sig_ts != 0) {
+ phtolel(&data_ptr[bytes_written], latency);
+ } else {
+ phtolel(&data_ptr[bytes_written], 0);
+ }
+ bytes_written += 4;
+ phtolel(&data_ptr[bytes_written], sig_ts); /* 32 LSBs of signature timestamp (nsec) */
+ bytes_written += 4;
+ phtolell(&data_ptr[bytes_written], start_time); /* record start & end times of frame */
+ bytes_written += 8;
+ phtolell(&data_ptr[bytes_written], end_time);
+ bytes_written += 8;
+ phtolel(&data_ptr[bytes_written], d_time);
+ bytes_written += 4;
+
+ /*
+ * Generate and copy out the WLAN metadata headers.
+ *
+ * All values are copied out in little-endian byte order.
+ */
+ phtoles(&data_ptr[bytes_written], EXT_WLAN_FIELDS_LEN);
+ bytes_written += 2;
if (info & vVW510021_W_IS_WEP)
- er_fields->flags |= RADIOTAP_F_WEP;
- if ((l1p_1 & vVW510021_W_PREAMBLE_MASK) != vVW510021_W_IS_LONGPREAMBLE && (plcp_type == vVW510021_W_PLCP_LEGACY))
- er_fields->flags |= RADIOTAP_F_SHORTPRE;
- er_fields->phyRate = (guint16)(getRate(plcp_type, mcs_index, er_fields->flags, nss) * 10);
- er_fields->plcpType = plcp_type;
- er_fields->mcsIndex = mcs_index;
- er_fields->nss = nss;
- er_fields->chanflags = chanflags;
- er_fields->signal = (gint8)rssi[0];
- er_fields->signalb = (gint8)rssi[1];
- er_fields->signalc = (gint8)rssi[2];
- er_fields->signald = (gint8)rssi[3];
+ radioflags |= FLAGS_WEP;
+ if (!(l1p_1 & vVW510021_W_IS_LONGPREAMBLE) && (plcp_type == vVW510021_W_PLCP_LEGACY))
+ radioflags |= FLAGS_SHORTPRE;
+ phtoles(&data_ptr[bytes_written], radioflags);
+ bytes_written += 2;
+ phtoles(&data_ptr[bytes_written], chanflags);
+ bytes_written += 2;
+ phyRate = (guint16)(getRate(plcp_type, mcs_index, radioflags, nss) * 10);
+ phtoles(&data_ptr[bytes_written], phyRate);
+ bytes_written += 2;
+
+ /*** If received frame populate the ndp_flag in the same byte as plcp_type***/
+
+ if (!IS_TX) {
+ plcp_type = vht_ndp_flag + plcp_type;
+ }
+
+ data_ptr[bytes_written] = plcp_type;
+ bytes_written += 1;
+
+ data_ptr[bytes_written] = mcs_index;
+ bytes_written += 1;
+
+ data_ptr[bytes_written] = nss;
+ bytes_written += 1;
+ data_ptr[bytes_written] = rssi[0];
+ bytes_written += 1;
+ data_ptr[bytes_written] = rssi[1];
+ bytes_written += 1;
+ data_ptr[bytes_written] = rssi[2];
+ bytes_written += 1;
+ data_ptr[bytes_written] = rssi[3];
+ bytes_written += 1;
+ /* padding */
+ data_ptr[bytes_written] = 0;
+ bytes_written += 1;
+
/* fill in the VeriWave flags field */
- er_fields->vw_flags = 0;
+ vw_flags = 0;
if (f_tx)
- er_fields->vw_flags |= RADIOTAP_VWF_TXF;
+ vw_flags |= VW_FLAGS_TXF;
if (errors & 0x1f) /* If any error is flagged, then set the FCS error bit */
- er_fields->vw_flags |= RADIOTAP_VWF_FCSERR;
+ vw_flags |= VW_FLAGS_FCSERR;
if (!f_tx && (errors & vwr->CRYPTO_ERR))
- er_fields->vw_flags |= RADIOTAP_VWF_DCRERR;
+ vw_flags |= VW_FLAGS_DCRERR;
if (!f_tx && (errors & vwr->RETRY_ERR))
- er_fields->vw_flags |= RADIOTAP_VWF_RETRERR;
+ vw_flags |= VW_FLAGS_RETRERR;
if (info & vwr->WEPTYPE)
- er_fields->vw_flags |= RADIOTAP_VWF_IS_WEP;
+ vw_flags |= VW_FLAGS_IS_WEP;
else if (info & vwr->TKIPTYPE)
- er_fields->vw_flags |= RADIOTAP_VWF_IS_TKIP;
+ vw_flags |= VW_FLAGS_IS_TKIP;
else if (info & vwr->CCMPTYPE)
- er_fields->vw_flags |= RADIOTAP_VWF_IS_CCMP;
+ vw_flags |= VW_FLAGS_IS_CCMP;
+ phtoles(&data_ptr[bytes_written], vw_flags);
+ bytes_written += 2;
- er_fields->vw_errors = (guint32)errors;
- er_fields->vw_ht_length = (guint16)ht_len;
- er_fields->vw_info = (guint16)info;
+ phtoles(&data_ptr[bytes_written], ht_len);
+ bytes_written += 2;
+ phtoles(&data_ptr[bytes_written], info);
+ bytes_written += 2;
+ phtolel(&data_ptr[bytes_written], errors);
+ bytes_written += 4;
- /* return the offset to the actual frame data */
- /* 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 12 is for 11 bytes plcp and 1 byte of pad before the data. */
+ /*
+ * XXX - is this supposed to be the RX L1 info, i.e. the "1 byte of L1P
+ * for user position"?
+ */
+ if (!IS_TX){
+ data_ptr[bytes_written] = vht_ndp_flag;
+ } else {
+ data_ptr[bytes_written] = 0;
+ }
+ bytes_written += 1;
+
+ /*
+ * Copy PLCP header.
+ *
+ * XXX - shouldn't that use plcp_ptr?
+ *
+ * XXX - what about S2, where we don't have 16 bytes of PLCP?
+ */
+ memcpy(&data_ptr[bytes_written], &rec[16], 16);
+ bytes_written += 16;
- return vwr->MPDU_OFF;
+ /*
+ * Finally, copy the whole MAC frame to the packet buffer as-is.
+ * This does not include the stats header or the PLCP header.
+ */
+ memcpy(&data_ptr[bytes_written], &rec[vwr->MPDU_OFF], actual_octets);
+
+ return TRUE;
}
/* read an Ethernet packet */
/* The packet is constructed as a 38-byte VeriWave-extended Radiotap header plus the raw */
/* MAC octets. */
-static void vwr_read_rec_data_ethernet(vwr_t *vwr, struct wtap_pkthdr *phdr,
- guint8 *data_ptr, guint8 *rec,
- int rec_size, int IS_TX)
+static gboolean vwr_read_rec_data_ethernet(vwr_t *vwr, struct wtap_pkthdr *phdr,
+ Buffer *buf, const guint8 *rec,
+ int rec_size, int IS_TX, int *err,
+ gchar **err_info)
{
+ guint8 *data_ptr;
int bytes_written = 0; /* bytes output to buf so far */
- register int i; /* temps */
- register guint8 *s_ptr, *m_ptr; /* stats and MPDU pointers */
- guint16 msdu_length,actual_octets; /* octets in frame */
- guint8 flow_seq; /* seqnum */
+ const guint8 *s_ptr, *m_ptr; /* stats and MPDU pointers */
+ guint16 msdu_length, actual_octets; /* octets in frame */
+ guint flow_seq; /* seqnum */
guint64 s_time = LL_ZERO, e_time = LL_ZERO; /* start/end */
/* times, nsec */
guint32 latency = 0;
guint64 start_time, s_sec, s_usec = LL_ZERO; /* start time, sec + usec */
guint64 end_time; /* end time */
- guint16 l4id, info, validityBits; /* INFO/ERRORS fields in stats */
+ guint l4id;
+ guint16 info, validityBits; /* INFO/ERRORS fields in stats */
guint32 errors;
guint16 vc_id; /* VC ID, total (incl of aggregates) */
guint32 flow_id, d_time; /* packet duration */
int f_flow; /* flags: flow valid */
guint32 frame_type; /* frame type field */
- guint16 e_hdr_len; /* length of ethernettap headers */
int mac_len, sig_off, pay_off; /* MAC header len, signature offset */
- guint64 sig_ts, tsid; /* 32 LSBs of timestamp in signature */
+ /* XXX - the code here fetched tsid, but never used it! */
+ guint64 sig_ts/*, tsid*/; /* 32 LSBs of timestamp in signature */
guint64 delta_b; /* Used for calculating latency */
+ guint16 vw_flags; /* VeriWave-specific packet flags */
- stats_ethernettap_fields etap_hdr; /* VWR ethernettap header */
- stats_common_fields common_hdr; /* VWR common header */
+ if ((guint)rec_size < vwr->STATS_LEN) {
+ *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;
+ }
/* Calculate the start of the statistics block in the buffer. */
/* Also get a bunch of fields from the stats block. */
msdu_length = pntoh16(&s_ptr[vwr->OCTET_OFF]);
actual_octets = msdu_length;
- /* Sanity check the msdu_length field to determine if it is OK (or segfaults result). */
- /* If it's greater, then truncate to the indicated message length. */
- if (msdu_length > (rec_size - (int)vwr->STATS_LEN)) {
- msdu_length = (rec_size - (int)vwr->STATS_LEN);
+
+ /*
+ * Sanity check the octets field to determine if it's greater than
+ * the packet data available in the record - i.e., the record size
+ * minus the length of the statistics block.
+ *
+ * Report an error if it is.
+ */
+ if (actual_octets > rec_size - vwr->STATS_LEN) {
+ *err_info = g_strdup_printf("vwr: Invalid data length %u (runs past the end of the record)",
+ actual_octets);
+ *err = WTAP_ERR_BAD_FILE;
+ return FALSE;
}
+ /*
+ * The maximum value of actual_octets is 65535, which, even after
+ * adding the lengths of the metadata headers, is less than
+ * WTAP_MAX_PACKET_SIZE will ever be, so we don't need to check it.
+ */
vc_id = pntoh16(&s_ptr[vwr->VCID_OFF]) & vwr->VCID_MASK;
flow_seq = s_ptr[vwr->FLOWSEQ_OFF];
/* 24 LSBs */
flow_id = pntoh24(&s_ptr[vwr->FLOWID_OFF]);
+#if 0
/* For tx latency is duration, for rx latency is timestamp. */
/* Get 64-bit latency value. */
- tsid = (s_ptr[vwr->LATVAL_OFF + 6] << 8) | (s_ptr[vwr->LATVAL_OFF + 7]);
- for (i = 0; i < 4; i++)
- tsid = (tsid << 8) | s_ptr[vwr->LATVAL_OFF + i];
-
+ tsid = pcorey48tohll(&s_ptr[vwr->LATVAL_OFF]);
+#endif
l4id = pntoh16(&s_ptr[vwr->L4ID_OFF]);
+ /*
+ * The MSDU length includes the FCS.
+ *
+ * The packet data does *not* include the FCS - it's just 4 bytes
+ * of junk - so we have to remove it.
+ *
+ * We'll be stripping off an FCS (?), so make sure we have at
+ * least 4 octets worth of FCS.
+ */
+ if (actual_octets < 4) {
+ *err_info = g_strdup_printf("vwr: Invalid data length %u (too short to include 4 bytes of FCS)",
+ actual_octets);
+ *err = WTAP_ERR_BAD_FILE;
+ return FALSE;
+ }
+ actual_octets -= 4;
+
/* Calculate start & end times (in sec/usec), converting 64-bit times to usec. */
/* 64-bit times are "Corey-endian" */
s_time = pcoreytohll(&s_ptr[vwr->STARTT_OFF]);
latency = (guint32)delta_b;
}
}
- /* Fill up the per-packet header (amazingly like a PCAP packet header! ;-) */
- /* Frames are always wired ethernet with a wired ethernettap header. */
- /* Caplen is the length that is captured into the file (i.e., the written-out frame */
- /* block), and should always represent the actual number of bytes in the file. */
- /* 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;
- phdr->len = (actual_octets - 4) + e_hdr_len;
- phdr->caplen = (msdu_length - 4) + e_hdr_len;
- phdr->presence_flags = WTAP_HAS_TS;
+ /*
+ * Fill up the per-packet header.
+ *
+ * We include the length of the metadata headers in the packet lengths.
+ */
+ phdr->len = STATS_COMMON_FIELDS_LEN + EXT_ETHERNET_FIELDS_LEN + actual_octets;
+ phdr->caplen = STATS_COMMON_FIELDS_LEN + EXT_ETHERNET_FIELDS_LEN + actual_octets;
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;
- common_hdr.it_len = STATS_COMMON_FIELDS_LEN;
- etap_hdr.it_len = STATS_ETHERNETTAP_FIELDS_LEN;
+ phdr->rec_type = REC_TYPE_PACKET;
+ phdr->presence_flags = WTAP_HAS_TS;
- etap_hdr.vw_errors = (guint32)errors;
- etap_hdr.vw_info = (guint16)info;
- common_hdr.vw_msdu_length = (guint16)msdu_length;
/*etap_hdr.vw_ip_length = (guint16)ip_len;*/
- common_hdr.vw_flowid = (guint32)flow_id;
- common_hdr.vw_vcid = (guint16)vc_id;
- common_hdr.vw_seqnum = (guint16)flow_seq;
+ ws_buffer_assure_space(buf, phdr->caplen);
+ data_ptr = ws_buffer_start_ptr(buf);
- if (!IS_TX && (sig_ts != 0))
- common_hdr.vw_latency = (guint32)latency;
- else
- common_hdr.vw_latency = 0;
- common_hdr.vw_pktdur = (guint32)d_time;
- etap_hdr.vw_l4id = (guint32)l4id;
- etap_hdr.vw_flags = 0;
- if (IS_TX)
- etap_hdr.vw_flags |= RADIOTAP_VWF_TXF;
- if (errors & vwr->FCS_ERROR)
- etap_hdr.vw_flags |= RADIOTAP_VWF_FCSERR;
- common_hdr.vw_startt = start_time; /* record start & end times of frame */
- common_hdr.vw_endt = end_time;
- common_hdr.vw_sig_ts = (guint32)(sig_ts);
-
- etap_hdr.it_pad2 = 0;
-
- /* put common_hdr into the packet buffer in little-endian byte order */
- phtoles(&data_ptr[bytes_written], common_hdr.vw_port_type);
+ /*
+ * Generate and copy out the common metadata headers,
+ * set the port type to 1 (Ethernet).
+ *
+ * All values are copied out in little-endian byte order.
+ */
+ phtoles(&data_ptr[bytes_written], 1);
bytes_written += 2;
- phtoles(&data_ptr[bytes_written], common_hdr.it_len);
+ phtoles(&data_ptr[bytes_written], STATS_COMMON_FIELDS_LEN);
bytes_written += 2;
- phtoles(&data_ptr[bytes_written], common_hdr.vw_msdu_length);
+ phtoles(&data_ptr[bytes_written], msdu_length);
bytes_written += 2;
- phtolel(&data_ptr[bytes_written], common_hdr.vw_flowid);
+ phtolel(&data_ptr[bytes_written], flow_id);
bytes_written += 4;
- phtoles(&data_ptr[bytes_written], common_hdr.vw_vcid);
+ phtoles(&data_ptr[bytes_written], vc_id);
bytes_written += 2;
- phtoles(&data_ptr[bytes_written], common_hdr.vw_seqnum);
+ phtoles(&data_ptr[bytes_written], flow_seq);
bytes_written += 2;
- phtolel(&data_ptr[bytes_written], common_hdr.vw_latency);
+ if (!IS_TX && (sig_ts != 0)) {
+ phtolel(&data_ptr[bytes_written], latency);
+ } else {
+ phtolel(&data_ptr[bytes_written], 0);
+ }
bytes_written += 4;
- phtolel(&data_ptr[bytes_written], common_hdr.vw_sig_ts);
+ phtolel(&data_ptr[bytes_written], sig_ts);
bytes_written += 4;
- phtolell(&data_ptr[bytes_written], common_hdr.vw_startt);
+ phtolell(&data_ptr[bytes_written], start_time) /* record start & end times of frame */
bytes_written += 8;
- phtolell(&data_ptr[bytes_written], common_hdr.vw_endt);
+ phtolell(&data_ptr[bytes_written], end_time);
bytes_written += 8;
- phtolel(&data_ptr[bytes_written], common_hdr.vw_pktdur);
+ phtolel(&data_ptr[bytes_written], d_time);
bytes_written += 4;
- /* put etap_hdr into the packet buffer in little-endian byte order */
- phtoles(&data_ptr[bytes_written], etap_hdr.it_len);
+ /*
+ * Generate and copy out the Ethernet metadata headers.
+ *
+ * All values are copied out in little-endian byte order.
+ */
+ phtoles(&data_ptr[bytes_written], EXT_ETHERNET_FIELDS_LEN);
bytes_written += 2;
- phtoles(&data_ptr[bytes_written], etap_hdr.vw_flags);
+ vw_flags = 0;
+ if (IS_TX)
+ vw_flags |= VW_FLAGS_TXF;
+ if (errors & vwr->FCS_ERROR)
+ vw_flags |= VW_FLAGS_FCSERR;
+ phtoles(&data_ptr[bytes_written], vw_flags);
bytes_written += 2;
- phtoles(&data_ptr[bytes_written], etap_hdr.vw_info);
+ phtoles(&data_ptr[bytes_written], info);
bytes_written += 2;
- phtolel(&data_ptr[bytes_written], etap_hdr.vw_errors);
+ phtolel(&data_ptr[bytes_written], errors);
bytes_written += 4;
- phtolel(&data_ptr[bytes_written], etap_hdr.vw_l4id);
+ phtolel(&data_ptr[bytes_written], l4id);
bytes_written += 4;
/* Add in pad */
+ phtolel(&data_ptr[bytes_written], 0);
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) )
- /*something's been truncated, DUMP AS-IS*/
- memcpy(&data_ptr[bytes_written], m_ptr, msdu_length);
- else if (msdu_length >= 4)
- memcpy(&data_ptr[bytes_written], m_ptr, msdu_length - 4);
- else
- memcpy(&data_ptr[bytes_written], m_ptr, msdu_length);
+ /*
+ * Finally, copy the whole MAC frame to the packet buffer as-is.
+ * This also does not include the last 4 bytes, as those don't
+ * contain an FCS, they just contain junk.
+ */
+ memcpy(&data_ptr[bytes_written], m_ptr, actual_octets);
+
+ return TRUE;
}
/*--------------------------------------------------------------------------------------*/
/* utility to split up and decode a 16-byte message record */
-static int decode_msg(vwr_t *vwr, guint8 *rec, int *v_type, int *IS_TX)
+static int decode_msg(guint8 *rec, int *v_type, int *IS_TX)
{
guint8 cmd; /* components of message */
guint32 wd2, wd3;
/* assume it's zero */
/* break up the message record into its pieces */
- cmd = rec[0];
- wd2 = pntoh32(&rec[8]);
- wd3 = pntoh32(&rec[12]);
-
- if (vwr != NULL) {
- if ((cmd & vwr->HEADER_IS_TX) == vwr->HEADER_IS_TX)
- *IS_TX = 1;
- else if ((cmd & vwr->HEADER_IS_RX) == vwr->HEADER_IS_RX)
- *IS_TX = 0;
- else *IS_TX = 2; /*NULL case*/
- }
+ cmd = rec[0]; /* command byte */
+ wd2 = pntoh32(&rec[8]); /* first 32-bit quantity */
+ wd3 = pntoh32(&rec[12]); /* second 32-bit quantity */
+
/* now decode based on the command byte */
switch (cmd) {
- case 0x21:
- case 0x31:
+ case COMMAND_RX:
+ if (IS_TX != NULL)
+ *IS_TX = 0;
+ v_size = (int)(wd2 & 0xffff);
+ *v_type = VT_FRAME;
+ break;
+
+ case COMMAND_TX:
+ if (IS_TX != NULL)
+ *IS_TX = 1;
v_size = (int)(wd2 & 0xffff);
*v_type = VT_FRAME;
break;
case 0xc1:
case 0x8b:
+ if (IS_TX != NULL)
+ *IS_TX = 2; /*NULL case*/
v_size = (int)(wd2 & 0xffff);
*v_type = VT_CPMSG;
break;
case 0xfe:
+ if (IS_TX != NULL)
+ *IS_TX = 2; /*NULL case*/
v_size = (int)(wd3 & 0xffff);
*v_type = VT_CPMSG;
break;
default:
+ if (IS_TX != NULL)
+ *IS_TX = 2; /*NULL case*/
break;
}
/* The integer returned by the get_xxx_rate() functions is in units of 0.5 Mb/s. */
/* The string returned by the decode_xxx_rate() functions is 3 characters wide. */
-static guint8 get_ofdm_rate(guint8 *plcp)
+static guint8 get_ofdm_rate(const guint8 *plcp)
{
/* extract the RATE field (LS nibble of first byte) then convert it to the MCS index used by the L1p fields */
switch (plcp[0] & 0x0f) {
}
}
-static guint8 get_cck_rate(guint8 *plcp)
+static guint8 get_cck_rate(const guint8 *plcp)
{
/* extract rate from the SIGNAL field then convert it to the MCS index used by the L1p fields */
switch (plcp[0]) {
switch (fpga) {
/* WLAN frames */
case S2_W_FPGA:
- vwr->STATS_LEN = vVW510021_W_STATS_LEN;
+ vwr->STATS_LEN = vVW510021_W_STATS_TRAILER_LEN;
vwr->VALID_OFF = vVW510021_W_VALID_OFF;
vwr->MTYPE_OFF = vVW510021_W_MTYPE_OFF;
vwr->IPLEN_OFF = vVW510021_W_IPLEN_OFF;
vwr->PLCP_LENGTH_OFF = vVW510021_W_PLCP_LENGTH_OFF;
- vwr->HEADER_IS_RX = vVW510021_W_HEADER_IS_RX;
- vwr->HEADER_IS_TX = vVW510021_W_HEADER_IS_TX;
vwr->MT_MASK = vVW510021_W_SEL_MASK;
- vwr->MCS_INDEX_MASK = vVW510021_W_MCS_MASK;
vwr->VCID_MASK = 0xffff;
vwr->FLOW_VALID = vVW510021_W_FLOW_VALID;
vwr->STATS_START_OFF = vVW510021_W_HEADER_LEN;
vwr->MT_CCKS = v22_W_MT_CCKS;
/*vwr->MT_OFDM = vVW510021_W_MT_OFDM;*/
- vwr->WEPTYPE = vVW510021_W_WEPTYPE;
- vwr->TKIPTYPE = vVW510021_W_TKIPTYPE;
- vwr->CCMPTYPE = vVW510021_W_CCMPTYPE;
+ vwr->WEPTYPE = v22_W_WEPTYPE;
+ vwr->TKIPTYPE = v22_W_TKIPTYPE;
+ vwr->CCMPTYPE = v22_W_CCMPTYPE;
vwr->FRAME_TYPE_OFF = vVW510021_W_FRAME_TYPE_OFF;
vwr->IS_TCP = vVW510021_W_IS_TCP;
vwr->IS_IGMP = vVW510021_W_IS_IGMP;
vwr->IS_QOS = vVW510021_W_QOS_VALID;
- vwr->MPDU_OFF = 20;
+ /*
+ * The 12 is for 11 bytes of PLCP and 1 byte of pad
+ * before the data.
+ */
+ vwr->MPDU_OFF = vVW510021_W_STATS_HEADER_LEN + 12;
break;
case S3_W_FPGA:
- vwr->STATS_LEN = STATS_COMMON_FIELDS_LEN + EXT_RTAP_FIELDS_LEN;
+ vwr->STATS_LEN = vVW510021_W_STATS_TRAILER_LEN;
vwr->PLCP_LENGTH_OFF = 16;
- vwr->HEADER_IS_RX = vVW510021_W_HEADER_IS_RX;
- vwr->HEADER_IS_TX = vVW510021_W_HEADER_IS_TX;
- vwr->MPDU_OFF = 32;
+
+ /*
+ * The first 16 is from the 16 bytes of stats block that
+ * precede the PLCP; the 16 is for 16 bytes of PLCP.
+ */
+ vwr->MPDU_OFF = 16 + 16;
break;
vwr->INFO_OFF = v22_E_INFO_OFF;
vwr->L4ID_OFF = v22_E_L4ID_OFF;
- vwr->HEADER_IS_RX = v22_E_HEADER_IS_RX;
- vwr->HEADER_IS_TX = v22_E_HEADER_IS_TX;
-
vwr->IS_RX = v22_E_IS_RX;
vwr->MT_MASK = v22_E_MT_MASK;
vwr->VCID_MASK = v22_E_VCID_MASK;
vwr->VCID_MASK = v22_W_VCID_MASK;
vwr->FLOW_VALID = v22_W_FLOW_VALID;
- vwr->HEADER_IS_RX = v22_W_HEADER_IS_RX;
- vwr->HEADER_IS_TX = v22_W_HEADER_IS_TX;
-
vwr->RX_DECRYPTS = v22_W_RX_DECRYPTS;
vwr->TX_DECRYPTS = v22_W_TX_DECRYPTS;
vwr->FC_PROT_BIT = v22_W_FC_PROT_BIT;
vwr->FPGA_VERSION_OFF = vVW510024_E_FPGA_VERSION_OFF;
vwr->HEADER_VERSION_OFF = vVW510024_E_HEADER_VERSION_OFF;
- vwr->HEADER_IS_RX = vVW510024_E_HEADER_IS_RX;
- vwr->HEADER_IS_TX = vVW510024_E_HEADER_IS_TX;
-
vwr->VCID_MASK = vVW510024_E_VCID_MASK;
vwr->FLOW_VALID = vVW510024_E_FLOW_VALID;
vwr->FCS_ERROR = v22_E_FCS_ERROR;
/* 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 rec_size, int pay_off, guint32 flow_id, guint8 flow_seq)
+int find_signature(const guint8 *m_ptr, int rec_size, int pay_off, guint32 flow_id, guint8 flow_seq)
{
int tgt; /* temps */
guint32 fid;
/* flow ID and sequence number at the appropriate offsets. */
for (tgt = pay_off; tgt < (rec_size); tgt++) {
if (m_ptr[tgt] == 0xdd) { /* found magic byte? check fields */
- if (m_ptr[tgt + 15] == 0xe2) {
+ if ((tgt + 15 < rec_size) && (m_ptr[tgt + 15] == 0xe2)) {
if (m_ptr[tgt + 4] != flow_seq)
continue;
return (tgt);
}
- else
+ else if (tgt + SIG_FSQ_OFF < rec_size)
{ /* out which one... */
if (m_ptr[tgt + SIG_FSQ_OFF] != flow_seq) /* check sequence number */
continue; /* if failed, keep scanning */
}
/* utility routine: harvest the signature time stamp from the data frame */
-guint64 get_signature_ts(guint8 *m_ptr,int sig_off)
+guint64 get_signature_ts(const guint8 *m_ptr,int sig_off)
{
int ts_offset;
guint64 sig_ts;
static float getRate( guint8 plcpType, guint8 mcsIndex, guint16 rflags, guint8 nss )
{
/* Rate conversion data */
- float canonical_rate_legacy[] = {1.0f, 2.0f, 5.5f, 11.0f, 6.0f, 9.0f, 12.0f, 18.0f, 24.0f, 36.0f, 48.0f, 54.0f};
+ static const float canonical_rate_legacy[] = {1.0f, 2.0f, 5.5f, 11.0f, 6.0f, 9.0f, 12.0f, 18.0f, 24.0f, 36.0f, 48.0f, 54.0f};
- int canonical_ndbps_20_ht[] = {26, 52, 78, 104, 156, 208, 234, 260};
- int canonical_ndbps_40_ht[] = {54, 108, 162, 216, 324, 432, 486, 540};
+ static const int canonical_ndbps_20_ht[8] = {26, 52, 78, 104, 156, 208, 234, 260};
+ static const int canonical_ndbps_40_ht[8] = {54, 108, 162, 216, 324, 432, 486, 540};
- int canonical_ndbps_20_vht[] = {26,52, 78, 104, 156, 208, 234, 260, 312};
- int canonical_ndbps_40_vht[] = {54, 108, 162, 216, 324, 432, 486, 540, 648, 720};
- int canonical_ndbps_80_vht[] = {117, 234, 351, 468, 702, 936, 1053, 1170, 1404, 1560};
+ static const int canonical_ndbps_20_vht[] = {26, 52, 78, 104, 156, 208, 234, 260, 312};
+ static const int canonical_ndbps_40_vht[] = {54, 108, 162, 216, 324, 432, 486, 540, 648, 720};
+ static const int canonical_ndbps_80_vht[] = {117, 234, 351, 468, 702, 936, 1053, 1170, 1404, 1560};
- int ndbps;
float symbol_tx_time, bitrate = 0.0f;
if (plcpType == 0)
- bitrate = canonical_rate_legacy[mcsIndex];
+ {
+ if (mcsIndex < G_N_ELEMENTS(canonical_rate_legacy))
+ bitrate = canonical_rate_legacy[mcsIndex];
+ }
else if (plcpType == 1 || plcpType == 2)
{
- if ( rflags & IEEE80211_RADIOTAP_F_SHORTGI)
+ int ndbps;
+
+ if ( rflags & FLAGS_CHAN_SHORTGI)
symbol_tx_time = 3.6f;
else
symbol_tx_time = 4.0f;
- if ( rflags & IEEE80211_RADIOTAP_F_40MHZ )
- ndbps = canonical_ndbps_40_ht[ mcsIndex - 8*(int)(mcsIndex/8) ];
+ if ( rflags & FLAGS_CHAN_40MHZ )
+ ndbps = canonical_ndbps_40_ht[mcsIndex & 0x07];
else
- ndbps = canonical_ndbps_20_ht[ mcsIndex - 8*(int)(mcsIndex/8) ];
+ ndbps = canonical_ndbps_20_ht[mcsIndex & 0x07];
- bitrate = ( ndbps * (((int)(mcsIndex/8) + 1) )) / symbol_tx_time;
+ bitrate = ( ndbps * (((int)(mcsIndex >> 3) + 1) )) / symbol_tx_time;
}
else
{
- if ( rflags & IEEE80211_RADIOTAP_F_SHORTGI)
+ if ( rflags & FLAGS_CHAN_SHORTGI)
symbol_tx_time = 3.6f;
else
symbol_tx_time = 4.0f;
- /* Check for the out of range mcsIndex. Should never happen, but if mcs index is greater than 9 assume 9 is the value */
- if (mcsIndex > 9) mcsIndex = 9;
- if ( rflags & IEEE80211_RADIOTAP_F_40MHZ )
+ /* Check for the out of range mcsIndex. Should never happen, but if mcs index is greater than 9 assume 9 is the value */
+ if (mcsIndex > 9) mcsIndex = 9;
+ if ( rflags & FLAGS_CHAN_40MHZ )
bitrate = (canonical_ndbps_40_vht[ mcsIndex ] * nss) / symbol_tx_time;
- else if (rflags & IEEE80211_RADIOTAP_F_80MHZ )
+ else if (rflags & FLAGS_CHAN_80MHZ )
bitrate = (canonical_ndbps_80_vht[ mcsIndex ] * nss) / symbol_tx_time;
else
{
int IS_TX, int *err, gchar **err_info)
{
guint8 rec[B_SIZE]; /* local buffer (holds input record) */
- guint16 pkt_len; /* length of radiotap headers */
- guint8 *data_ptr;
/* Read over the entire record (frame + trailer) into a local buffer. */
/* If we don't get it all, then declare an error, we can't process the frame. */
- if (file_read(rec, rec_size, fh) != rec_size) {
- *err = file_error(fh, err_info);
- if (*err == 0)
- *err = WTAP_ERR_SHORT_READ;
+ if (!wtap_read_bytes(fh, rec, rec_size, err, err_info))
return FALSE;
- }
-
- if (rec_size < (int)vwr->STATS_LEN) {
- *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 == S2_W_FPGA) || (vwr->FPGA_VERSION == S1_W_FPGA) || (vwr->FPGA_VERSION == S3_W_FPGA) )
- /* frames are always 802.11 with an extended radiotap header */
- pkt_len = (guint16)(rec_size + STATS_COMMON_FIELDS_LEN + EXT_RTAP_FIELDS_LEN);
- else
- /* frames are always ethernet with an extended ethernettap header */
- pkt_len = (guint16)(rec_size + STATS_COMMON_FIELDS_LEN + STATS_ETHERNETTAP_FIELDS_LEN);
- buffer_assure_space(buf, pkt_len);
- data_ptr = buffer_start_ptr(buf);
/* now format up the frame data */
switch (vwr->FPGA_VERSION)
{
case S1_W_FPGA:
+ return vwr_read_s1_W_rec(vwr, phdr, buf, rec, rec_size, err, err_info);
+ break;
case S2_W_FPGA:
case S3_W_FPGA:
- vwr_read_rec_data_wlan(vwr, phdr, data_ptr, rec, rec_size, IS_TX);
+ return vwr_read_s2_s3_W_rec(vwr, phdr, buf, rec, rec_size, IS_TX, err, err_info);
break;
case vVW510012_E_FPGA:
- vwr_read_rec_data_ethernet(vwr, phdr, data_ptr, rec, rec_size, IS_TX);
- break;
case vVW510024_E_FPGA:
- vwr_read_rec_data_ethernet(vwr, phdr, data_ptr, rec, rec_size, IS_TX);
+ return vwr_read_rec_data_ethernet(vwr, phdr, buf, rec, rec_size, IS_TX, err, err_info);
break;
+ default:
+ g_assert_not_reached();
+ return FALSE;
}
- return (TRUE);
}
/*