Remove Nmake build system
[metze/wireshark/wip.git] / wiretap / vwr.c
index 7588651d6ed04bd5223520254444bb1d6ed0b31e..23bf4b5c8934e7964ce1c15753116073f0d1d255 100644 (file)
@@ -26,7 +26,6 @@
 
 #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 */
 
@@ -277,7 +145,7 @@ enum radiotap_type {
 #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 */
@@ -285,20 +153,29 @@ enum radiotap_type {
 #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
 
@@ -308,10 +185,6 @@ enum radiotap_type {
 
 #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 */
 
@@ -339,38 +212,60 @@ enum radiotap_type {
 #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 */
 
@@ -386,7 +281,8 @@ enum radiotap_type {
     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 */
@@ -428,28 +324,66 @@ enum radiotap_type {
 #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
@@ -458,13 +392,12 @@ enum radiotap_type {
 #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:
@@ -505,10 +438,8 @@ enum radiotap_type {
 #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 */
@@ -560,109 +491,104 @@ enum radiotap_type {
 /* 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;
@@ -671,10 +597,10 @@ int vwr_open(wtap *wth, int *err, gchar **err_info)
 
     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 */
@@ -688,7 +614,7 @@ int vwr_open(wtap *wth, int *err, gchar **err_info)
     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)
@@ -696,7 +622,7 @@ int vwr_open(wtap *wth, int *err, gchar **err_info)
     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;
 }
 
 
@@ -714,7 +640,7 @@ static gboolean vwr_read(wtap *wth, int *err, gchar **err_info, gint64 *data_off
     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 */
 
     /*
@@ -755,7 +681,7 @@ static gboolean vwr_seek_read(wtap *wth, gint64 seek_off,
         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,
@@ -767,12 +693,11 @@ static gboolean vwr_seek_read(wtap *wth, gint64 seek_off,
 /* 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,  */
@@ -781,23 +706,21 @@ static gboolean vwr_read_rec_header(vwr_t *vwr, FILE_T fh, int *rec_size, int *I
     /*  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 {
@@ -821,7 +744,7 @@ static int vwr_get_fpga_version(wtap *wth, int *err, gchar **err_info)
     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;
@@ -842,12 +765,12 @@ static int vwr_get_fpga_version(wtap *wth, int *err, gchar **err_info)
     /* 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. */
@@ -863,11 +786,10 @@ static int vwr_get_fpga_version(wtap *wth, int *err, gchar **err_info)
                 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;
                 }
 
 
@@ -909,18 +831,22 @@ static int vwr_get_fpga_version(wtap *wth, int *err, gchar **err_info)
 
 
                 /* 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 */
@@ -935,11 +861,6 @@ static int vwr_get_fpga_version(wtap *wth, int *err, gchar **err_info)
                     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 */
@@ -957,156 +878,84 @@ static int vwr_get_fpga_version(wtap *wth, int *err, gchar **err_info)
     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.  */
@@ -1118,34 +967,43 @@ static int parse_s1_W_stats(vwr_t *vwr, struct wtap_pkthdr *phdr, guint8 *rec,
         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 */
@@ -1161,92 +1019,175 @@ static int parse_s1_W_stats(vwr_t *vwr, struct wtap_pkthdr *phdr, guint8 *rec,
     /* 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;
@@ -1254,67 +1195,95 @@ static int parse_s2_W_stats(vwr_t *vwr, struct wtap_pkthdr *phdr,
     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)
@@ -1327,24 +1296,40 @@ static int parse_s2_W_stats(vwr_t *vwr, struct wtap_pkthdr *phdr,
             }
         }
 
+        /*** 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]);
 
@@ -1352,6 +1337,27 @@ static int parse_s2_W_stats(vwr_t *vwr, struct wtap_pkthdr *phdr,
     /* 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;
         }
@@ -1360,35 +1366,63 @@ static int parse_s2_W_stats(vwr_t *vwr, struct wtap_pkthdr *phdr,
         }
     }
     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 */
@@ -1405,7 +1439,7 @@ static int parse_s2_W_stats(vwr_t *vwr, struct wtap_pkthdr *phdr,
     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;
@@ -1425,84 +1459,175 @@ static int parse_s2_W_stats(vwr_t *vwr, struct wtap_pkthdr *phdr,
           }
     }
 
-    /* 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 */
@@ -1510,33 +1635,39 @@ static int parse_s2_W_stats(vwr_t *vwr, struct wtap_pkthdr *phdr,
 /* 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.           */
@@ -1545,11 +1676,25 @@ static void vwr_read_rec_data_ethernet(vwr_t *vwr, struct wtap_pkthdr *phdr,
 
     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];
@@ -1577,15 +1722,31 @@ static void vwr_read_rec_data_ethernet(vwr_t *vwr, struct wtap_pkthdr *phdr,
     /*  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]);
@@ -1643,106 +1804,99 @@ static void vwr_read_rec_data_ethernet(vwr_t *vwr, struct wtap_pkthdr *phdr,
                 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;
@@ -1750,37 +1904,44 @@ static int decode_msg(vwr_t *vwr, guint8 *rec, int *v_type, int *IS_TX)
                                         /* 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;
     }
 
@@ -1794,7 +1955,7 @@ static int decode_msg(vwr_t *vwr, guint8 *rec, int *v_type, int *IS_TX)
 /* 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) {
@@ -1810,7 +1971,7 @@ static guint8 get_ofdm_rate(guint8 *plcp)
     }
 }
 
-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]) {
@@ -1830,7 +1991,7 @@ static void setup_defaults(vwr_t *vwr, guint16 fpga)
     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;
@@ -1856,10 +2017,7 @@ static void setup_defaults(vwr_t *vwr, guint16 fpga)
             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;
@@ -1881,9 +2039,9 @@ static void setup_defaults(vwr_t *vwr, guint16 fpga)
             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;
@@ -1892,16 +2050,23 @@ static void setup_defaults(vwr_t *vwr, guint16 fpga)
             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;
 
@@ -1923,9 +2088,6 @@ static void setup_defaults(vwr_t *vwr, guint16 fpga)
             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;
@@ -1986,9 +2148,6 @@ static void setup_defaults(vwr_t *vwr, guint16 fpga)
             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;
@@ -2037,9 +2196,6 @@ static void setup_defaults(vwr_t *vwr, guint16 fpga)
             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;
@@ -2059,7 +2215,7 @@ static void setup_defaults(vwr_t *vwr, guint16 fpga)
 
 /* 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;
@@ -2074,7 +2230,7 @@ int find_signature(guint8 *m_ptr, int rec_size, int pay_off, guint32 flow_id, gu
     /*  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;
 
@@ -2085,7 +2241,7 @@ int find_signature(guint8 *m_ptr, int rec_size, int pay_off, guint32 flow_id, gu
 
                 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 */
@@ -2105,7 +2261,7 @@ int find_signature(guint8 *m_ptr, int rec_size, int pay_off, guint32 flow_id, gu
 }
 
 /* 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;
@@ -2123,46 +2279,50 @@ guint64 get_signature_ts(guint8 *m_ptr,int sig_off)
 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
         {
@@ -2182,50 +2342,30 @@ vwr_process_rec_data(FILE_T fh, int rec_size,
                      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);
 }
 
 /*