aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AUTHORS2
-rw-r--r--epan/CMakeLists.txt2
-rw-r--r--epan/dissectors/Makefile.common2
-rw-r--r--epan/dissectors/packet-ixveriwave.c1544
-rw-r--r--epan/dissectors/packet-waveagent.c1943
-rw-r--r--wiretap/CMakeLists.txt1
-rw-r--r--wiretap/Makefile.common2
-rw-r--r--wiretap/file_access.c10
-rw-r--r--wiretap/vwr.c2105
-rw-r--r--wiretap/wtap.c3
-rw-r--r--wiretap/wtap.h3
11 files changed, 5617 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
index 591d68d870..e8fd9f25e2 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -3618,6 +3618,8 @@ Jakob Hirsch <jh.wireshark-bugzilla [AT] plonk.de>
Роман Донченко <DXDragon [AT] yandex.ru>
<billyjeans [AT] gmail.com>
Evan Huus <eapache [AT] gmail.com>
+Tom Cook <tcook [AT] ixiacom.com>
+Tom Alexander <talexander [AT] ixiacom.com>
Dan Lasley <dlasley[AT]promus.com> gave permission for his
dumpit() hex-dump routine to be used.
diff --git a/epan/CMakeLists.txt b/epan/CMakeLists.txt
index 4eeabb0249..297ff49690 100644
--- a/epan/CMakeLists.txt
+++ b/epan/CMakeLists.txt
@@ -749,6 +749,7 @@ set(DISSECTOR_SRC
dissectors/packet-iuup.c
dissectors/packet-iwarp-ddp-rdmap.c
dissectors/packet-iwarp-mpa.c
+ dissectors/packet-ixveriwave.c
dissectors/packet-jmirror.c
dissectors/packet-jpeg.c
dissectors/packet-json.c
@@ -1158,6 +1159,7 @@ set(DISSECTOR_SRC
dissectors/packet-wai.c
dissectors/packet-wap.c
dissectors/packet-wassp.c
+ dissectors/packet-waveagent.c
dissectors/packet-wbxml.c
dissectors/packet-wccp.c
dissectors/packet-wcp.c
diff --git a/epan/dissectors/Makefile.common b/epan/dissectors/Makefile.common
index f3c49a9aaa..c16888110c 100644
--- a/epan/dissectors/Makefile.common
+++ b/epan/dissectors/Makefile.common
@@ -668,6 +668,7 @@ DISSECTOR_SRC = \
packet-iuup.c \
packet-iwarp-ddp-rdmap.c\
packet-iwarp-mpa.c \
+ packet-ixveriwave.c \
packet-jmirror.c \
packet-jpeg.c \
packet-json.c \
@@ -1076,6 +1077,7 @@ DISSECTOR_SRC = \
packet-vxlan.c \
packet-wai.c \
packet-wap.c \
+ packet-waveagent.c \
packet-wassp.c \
packet-wbxml.c \
packet-wccp.c \
diff --git a/epan/dissectors/packet-ixveriwave.c b/epan/dissectors/packet-ixveriwave.c
new file mode 100644
index 0000000000..569c53e72b
--- /dev/null
+++ b/epan/dissectors/packet-ixveriwave.c
@@ -0,0 +1,1544 @@
+/* packet-ixveriwave-common.c
+ * Routines for calling the right protocol for the ethertype.
+ *
+ * $Id$
+ *
+ * Tom Cook <tcook@ixiacom.com>
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <string.h>
+#include <epan/packet.h>
+#include <epan/crc32-tvb.h>
+
+#include "packet-eth.h"
+
+static void dissect_ixveriwave(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+static void ethernettap_dissect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_tree *tap_tree);
+static void wlantap_dissect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_tree *tap_tree);
+
+typedef struct {
+ guint32 previous_frame_num;
+ guint64 previous_end_time;
+} frame_end_data;
+
+typedef struct ifg_info {
+ guint32 ifg;
+ guint64 previous_end_time;
+ guint64 current_start_time;
+} ifg_info;
+
+static frame_end_data previous_frame_data = {0,0};
+
+/* static int ieee80211_mhz2ieee(int freq, int flags); */
+
+#define COMMON_LENGTH_OFFSET 2
+#define ETHERNETTAP_VWF_TXF 0x01 /* frame was transmitted flag */
+#define ETHERNETTAP_VWF_FCSERR 0x02 /* frame has FCS error */
+
+#define VW_RADIOTAPF_TXF 0x01 /* frame was transmitted */
+#define VW_RADIOTAPF_FCSERR 0x02 /* FCS error detected */
+#define VW_RADIOTAPF_RETRERR 0x04 /* excess retry error detected */
+#define VW_RADIOTAPF_DCRERR 0x10 /* decrypt error detected */
+#define VW_RADIOTAPF_ENCMSK 0x60 /* encryption type mask */
+ /* 0 = none, 1 = WEP, 2 = TKIP, 3 = CCKM */
+#define VW_RADIOTAPF_ENCSHIFT 5 /* shift amount to right-align above field */
+#define VW_RADIOTAPF_IS_WEP 0x20 /* encryption type value = WEP */
+#define VW_RADIOTAPF_IS_TKIP 0x40 /* encryption type value = TKIP */
+#define VW_RADIOTAPF_IS_CCMP 0x60 /* encryption type value = CCMP */
+#define VW_RADIOTAPF_SEQ_ERR 0x80 /* flow sequence error detected */
+
+#define VW_RADIOTAP_FPGA_VER_vVW510021 0x000C /* vVW510021 version detected */
+#define VW_RADIOTAP_FPGA_VER_vVW510021_11n 0x000D
+
+#define IEEE80211_CHAN_CCK 0x00020 /* CCK channel */
+#define IEEE80211_CHAN_OFDM 0x00040 /* OFDM channel */
+#define IEEE80211_CHAN_2GHZ 0x00080 /* 2 GHz spectrum channel. */
+#define IEEE80211_CHAN_5GHZ 0x00100 /* 5 GHz spectrum channel */
+
+#define IEEE80211_RADIOTAP_F_FCS 0x0010 /* frame includes FCS */
+#define IEEE80211_RADIOTAP_F_DATAPAD 0x0020 /* frame has padding between
+ * 802.11 header and payload
+ * (to 32-bit boundary)
+ */
+#define IEEE80211_RADIOTAP_F_HT 0x0040 /* HT mode */
+#define IEEE80211_RADIOTAP_F_CFP 0x0001 /* sent/received
+ * during CFP
+ */
+#define IEEE80211_RADIOTAP_F_SHORTPRE 0x0002 /* sent/received
+ * with short
+ * preamble
+ */
+#define IEEE80211_RADIOTAP_F_WEP 0x0004 /* sent/received
+ * with WEP encryption
+ */
+#define IEEE80211_RADIOTAP_F_FRAG 0x0008 /* sent/received
+ * with fragmentation
+ */
+#define IEEE80211_PLCP_RATE_MASK 0x7f /* parses out the rate or MCS index from the PLCP header(s) */
+#define IEEE80211_RADIOTAP_F_40MHZ 0x0080 /* 40 Mhz channel bandwidth */
+#define IEEE80211_RADIOTAP_F_SHORTGI 0x0100
+
+#define ETHERNET_PORT 1
+#define WLAN_PORT 0
+
+static int proto_ixveriwave = -1;
+static dissector_handle_t ethernet_handle;
+
+/* static int hf_ixveriwave_version = -1; */
+static int hf_ixveriwave_frame_length = -1;
+
+/* static int hf_ixveriwave_fcs = -1; */
+
+static int hf_ixveriwave_vw_vcid = -1;
+static int hf_ixveriwave_vw_msdu_length = -1;
+static int hf_ixveriwave_vw_seqnum = -1;
+static int hf_ixveriwave_vw_flowid = -1;
+
+static int hf_ixveriwave_vw_mslatency = -1;
+static int hf_ixveriwave_vw_latency = -1;
+static int hf_ixveriwave_vw_pktdur = -1;
+static int hf_ixveriwave_vw_ifg = -1;
+static int hf_ixveriwave = -1;
+static int hf_ixveriwave_vw_startt = -1;
+static int hf_ixveriwave_vw_endt = -1;
+
+static gint ett_commontap = -1;
+static gint ett_commontap_times = -1;
+static gint ett_ethernettap_info = -1;
+static gint ett_ethernettap_error = -1;
+static gint ett_ethernettap_flags = -1;
+
+/* static gint ett_radiotap = -1;
+static gint ett_radiotap_present = -1;
+*/
+static gint ett_radiotap_flags = -1;
+/* static gint ett_radiotap_channel_flags = -1; */
+
+static dissector_handle_t ieee80211_handle;
+static dissector_handle_t ieee80211_datapad_handle;
+
+/* Ethernet fields */
+static int hf_ixveriwave_vw_info = -1;
+static int hf_ixveriwave_vw_error = -1;
+
+static int hf_ixveriwave_vwf_txf = -1;
+static int hf_ixveriwave_vwf_fcserr = -1;
+
+static int hf_ixveriwave_vw_l4id = -1;
+
+/*veriwave note: i know the below method seems clunky, but
+they didn't have a item_format at the time to dynamically add the appropriate decode text*/
+static int hf_ixveriwave_vw_info_retryCount = -1;
+static int hf_ixveriwave_vw_info_tx_bit15 = -1;
+
+static int hf_ixveriwave_vw_info_rx_1_bit8 = -1;
+static int hf_ixveriwave_vw_info_rx_1_bit9 = -1;
+
+/*error flags*/
+static int hf_ixveriwave_vw_error_tx_bit1 = -1;
+static int hf_ixveriwave_vw_error_tx_bit5 = -1;
+static int hf_ixveriwave_vw_error_tx_bit9 = -1;
+static int hf_ixveriwave_vw_error_tx_bit10 = -1;
+static int hf_ixveriwave_vw_error_tx_bit11 = -1;
+
+static int hf_ixveriwave_vw_error_rx_1_bit0 = -1;
+static int hf_ixveriwave_vw_error_rx_1_bit1 = -1;
+static int hf_ixveriwave_vw_error_rx_1_bit2 = -1;
+static int hf_ixveriwave_vw_error_rx_1_bit3 = -1;
+static int hf_ixveriwave_vw_error_rx_1_bit4 = -1;
+static int hf_ixveriwave_vw_error_rx_1_bit5 = -1;
+static int hf_ixveriwave_vw_error_rx_1_bit6 = -1;
+static int hf_ixveriwave_vw_error_rx_1_bit7 = -1;
+static int hf_ixveriwave_vw_error_rx_1_bit8 = -1;
+static int hf_ixveriwave_vw_error_rx_1_bit9 = -1;
+
+static int hf_radiotap_flags = -1;
+static int hf_radiotap_datarate = -1;
+static int hf_radiotap_dbm_antsignal = -1;
+static int hf_radiotap_txpower = -1;
+static int hf_radiotap_fcs_bad = -1;
+
+static int hf_radiotap_flags_cfp = -1;
+static int hf_radiotap_flags_preamble = -1;
+static int hf_radiotap_flags_wep = -1;
+static int hf_radiotap_flags_frag = -1;
+static int hf_radiotap_flags_fcs = -1;
+static int hf_radiotap_flags_datapad = -1;
+static int hf_radiotap_flags_ht = -1;
+static int hf_radiotap_flags_40mhz = -1;
+static int hf_radiotap_flags_shortgi = -1;
+
+/* start VeriWave specific 6-2007*/
+static int hf_radiotap_vw_errors = -1;
+static int hf_radiotap_vw_info = -1;
+static int hf_radiotap_vw_ht_length = -1;
+
+static int hf_radiotap_vw_info_tx_bit10 = -1;
+static int hf_radiotap_vw_info_tx_bit11 = -1;
+static int hf_radiotap_vw_info_tx_bit12 = -1;
+static int hf_radiotap_vw_info_tx_bit13 = -1;
+static int hf_radiotap_vw_info_tx_bit14 = -1;
+static int hf_radiotap_vw_info_tx_bit15 = -1;
+
+static int hf_radiotap_vw_info_rx_2_bit8 = -1;
+static int hf_radiotap_vw_info_rx_2_bit9 = -1;
+static int hf_radiotap_vw_info_rx_2_bit10 = -1;
+static int hf_radiotap_vw_info_rx_2_bit11 = -1;
+static int hf_radiotap_vw_info_rx_2_bit12 = -1;
+static int hf_radiotap_vw_info_rx_2_bit13 = -1;
+static int hf_radiotap_vw_info_rx_2_bit14 = -1;
+static int hf_radiotap_vw_info_rx_2_bit15 = -1;
+
+static int hf_radiotap_vw_errors_rx_1_bit0 = -1;
+static int hf_radiotap_vw_errors_rx_1_bit1 = -1;
+static int hf_radiotap_vw_errors_rx_1_bit2 = -1;
+static int hf_radiotap_vw_errors_rx_1_bit3 = -1;
+static int hf_radiotap_vw_errors_rx_1_bit4 = -1;
+static int hf_radiotap_vw_errors_rx_1_bit5 = -1;
+static int hf_radiotap_vw_errors_rx_1_bit6 = -1;
+static int hf_radiotap_vw_errors_rx_1_bit7 = -1;
+static int hf_radiotap_vw_errors_rx_1_bit8 = -1;
+static int hf_radiotap_vw_errors_rx_1_bit9 = -1;
+static int hf_radiotap_vw_errors_rx_1_bit10 = -1;
+static int hf_radiotap_vw_errors_rx_1_bit11 = -1;
+static int hf_radiotap_vw_errors_rx_1_bit12 = -1;
+static int hf_radiotap_vw_errors_rx_1_bit13 = -1;
+static int hf_radiotap_vw_errors_rx_1_bit14 = -1;
+static int hf_radiotap_vw_errors_rx_1_bit15 = -1;
+
+static int hf_radiotap_vw_errors_rx_2_bit0 = -1;
+static int hf_radiotap_vw_errors_rx_2_bit1 = -1;
+static int hf_radiotap_vw_errors_rx_2_bit2 = -1;
+static int hf_radiotap_vw_errors_rx_2_bit4 = -1;
+static int hf_radiotap_vw_errors_rx_2_bit5 = -1;
+static int hf_radiotap_vw_errors_rx_2_bit6 = -1;
+static int hf_radiotap_vw_errors_rx_2_bit7 = -1;
+static int hf_radiotap_vw_errors_rx_2_bit8 = -1;
+static int hf_radiotap_vw_errors_rx_2_bit10 = -1;
+static int hf_radiotap_vw_errors_rx_2_bit11 = -1;
+
+static int hf_radiotap_vw_errors_tx_bit1 = -1;
+static int hf_radiotap_vw_errors_tx_bit5 = -1;
+
+static int hf_radiotap_vwf_txf = -1;
+static int hf_radiotap_vwf_fcserr = -1;
+static int hf_radiotap_vwf_dcrerr = -1;
+static int hf_radiotap_vwf_retrerr = -1;
+static int hf_radiotap_vwf_enctype = -1;
+
+static gint ett_radiotap_info = -1;
+static gint ett_radiotap_errors = -1;
+static gint ett_radiotap_times = -1;
+
+#define ALIGN_OFFSET(offset, width) \
+ ( (((offset) + ((width) - 1)) & (~((width) - 1))) - offset )
+
+/* Conversion of MCS index, guard interval, channel bandwidth to HT rate */
+static int canonical_ndbps_20[] = {26, 52, 78, 104, 156, 208, 234, 260};
+static int canonical_ndbps_40[] = {54, 108, 162, 216, 324, 432, 486, 540};
+static float getHTrate( guint8 rate, guint8 rflags );
+
+static void
+dissect_ixveriwave(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *common_tree = NULL;
+ proto_item *ti = NULL;
+ proto_item *vw_times_ti = NULL;
+ proto_tree *vw_times_tree = NULL;
+ int align_offset, offset, time_tree_offset=0;
+ guint16 version, length;
+ guint length_remaining;
+ guint64 vw_startt=0, vw_endt=0;
+ gint32 vwf_txf, vwf_fcserr;
+ guint32 true_length;
+ guint32 vw_latency, vw_pktdur, vw_flowid;
+ guint16 vw_vcid, vw_msdu_length, vw_seqnum;
+ tvbuff_t *next_tvb;
+ ifg_info *p_ifg_info;
+
+ vwf_fcserr = vwf_txf = 0;
+ align_offset = 0;
+
+ offset = 0;
+ version = tvb_get_letohs(tvb, offset);
+
+ length = tvb_get_letohs(tvb, offset + COMMON_LENGTH_OFFSET);
+
+ col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "%s", version ? "ETH" : "WLAN");
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ true_length = pinfo->fd->pkt_len - length - tvb_get_letohs(tvb, offset + length) + 4; /* add FCS length into captured length */
+
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s Capture, Length %u",
+ version ? "IxVeriWave Ethernet Tap" : "IxVeriWave Radio Tap", length);
+
+ /* Dissect the packet */
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_ixveriwave,
+ tvb, 0, length, "%s Header, Length %u", version ? "IxVeriWave Ethernet Tap" : "IxVeriWave Radio Tap", length);
+
+ common_tree = proto_item_add_subtree(ti, ett_commontap);
+
+ proto_tree_add_uint(common_tree, hf_ixveriwave_frame_length,
+ tvb, 4, 2, true_length);
+ }
+
+ length_remaining = length;
+
+ offset+=4;
+ length_remaining-=4;
+
+ /*extract msdu/octets , 2bytes*/
+ align_offset = ALIGN_OFFSET(offset, 2);
+ offset += align_offset;
+ length_remaining -= align_offset;
+
+ if (length_remaining >= 2) {
+
+ vw_msdu_length = tvb_get_letohs(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint(common_tree, hf_ixveriwave_vw_msdu_length,
+ tvb, offset, 2, vw_msdu_length);
+ }
+
+ offset+=2;
+ length_remaining-=2;
+ }
+
+ /*extract flow id , 4bytes*/
+ if (length_remaining >= 4) {
+ align_offset = ALIGN_OFFSET(offset, 4);
+ offset += align_offset;
+ length_remaining -= align_offset;
+
+ vw_flowid = tvb_get_letohl(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint(common_tree, hf_ixveriwave_vw_flowid,
+ tvb, offset, 4, vw_flowid);
+ }
+
+ offset+=4;
+ length_remaining-=4;
+ }
+
+ /*extract client id, 2bytes*/
+ if (length_remaining >= 2) {
+ align_offset = ALIGN_OFFSET(offset, 2);
+ offset += align_offset;
+ length_remaining -= align_offset;
+
+ vw_vcid = tvb_get_letohs(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint(common_tree, hf_ixveriwave_vw_vcid,
+ tvb, offset, 2, vw_vcid);
+ }
+
+ offset+=2;
+ length_remaining-=2;
+ }
+
+ /*extract sequence number , 2bytes*/
+ if (length_remaining >= 2) {
+
+ vw_seqnum = tvb_get_letohs(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint(common_tree, hf_ixveriwave_vw_seqnum,
+ tvb, offset, 2, vw_seqnum);
+ }
+
+ offset+=2;
+ length_remaining-=2;
+ }
+
+ /*extract latency, 4 bytes*/
+ if (length_remaining >= 4) {
+ align_offset = ALIGN_OFFSET(offset, 4);
+ offset += align_offset;
+ length_remaining -= align_offset;
+ vw_latency = tvb_get_letohl(tvb, offset);
+
+ if (tree) {
+ /* start a tree going for the various packet times */
+ if (vw_latency != 0) {
+ vw_times_ti = proto_tree_add_float_format(common_tree,
+ hf_ixveriwave_vw_mslatency,
+ tvb, offset, 4, (float)(vw_latency/1000000.0),
+ "Frame timestamp values: (latency %.3f msec)",
+ (float)(vw_latency/1000000.0));
+ vw_times_tree = proto_item_add_subtree(vw_times_ti, ett_commontap_times);
+
+ proto_tree_add_uint_format(vw_times_tree, hf_ixveriwave_vw_latency,
+ tvb, offset, 4, vw_latency,
+ "Frame latency: %u nsec", vw_latency);
+ }
+ else
+ {
+ vw_times_ti = proto_tree_add_float_format(common_tree,
+ hf_ixveriwave_vw_mslatency,
+ tvb, offset, 4, (float)(vw_latency/1000000.0),
+ "Frame timestamp values:");
+ vw_times_tree = proto_item_add_subtree(vw_times_ti, ett_commontap_times);
+
+ proto_tree_add_uint_format(vw_times_tree, hf_ixveriwave_vw_latency,
+ tvb, offset, 4, vw_latency,
+ "Frame latency: N/A");
+ }
+ }
+
+ offset+=4;
+ length_remaining-=4;
+ }
+
+
+
+ /*extract signature timestamp, 4 bytes (32 LSBs only, nsec)*/
+ if (length_remaining >= 4) {
+ align_offset = ALIGN_OFFSET(offset, 4);
+ offset += align_offset;
+ length_remaining -= align_offset;
+
+ if (tree) {
+ if (vw_times_tree != NULL) {
+ /* TODO: what should this fieldname be? */
+ proto_tree_add_item(vw_times_tree, hf_ixveriwave,
+ tvb, offset, 4, ENC_BIG_ENDIAN);
+ }
+ }
+ time_tree_offset = offset;
+ offset+=4;
+ length_remaining-=4;
+ }
+
+ /*extract frame start timestamp, 8 bytes (nsec)*/
+ if (length_remaining >= 8) {
+ align_offset = ALIGN_OFFSET(offset, 8);
+ offset += align_offset;
+ length_remaining -= align_offset;
+ vw_startt = tvb_get_letoh64(tvb, offset);
+
+ if (tree) {
+ if (vw_times_tree != NULL) {
+ proto_tree_add_uint64_format(vw_times_tree, hf_ixveriwave_vw_startt,
+ tvb, offset, 8, vw_startt,
+ "Frame start timestamp: %" G_GINT64_MODIFIER "u usec", vw_startt);
+ }
+ }
+
+ offset+=8;
+ length_remaining-=8;
+ }
+
+ /*extract frame end timestamp, 8 bytes (nsec)*/
+ if (length_remaining >= 8) {
+ align_offset = ALIGN_OFFSET(offset, 8);
+ offset += align_offset;
+ length_remaining -= align_offset;
+ vw_endt = tvb_get_letoh64(tvb, offset);
+
+ if (tree) {
+ if (vw_times_tree != NULL) {
+ proto_tree_add_uint64_format(vw_times_tree, hf_ixveriwave_vw_endt,
+ tvb, offset, 8, vw_endt,
+ "Frame end timestamp: %" G_GINT64_MODIFIER "u usec", vw_endt);
+ }
+ }
+
+ offset+=8;
+ length_remaining-=8;
+ }
+ /*extract frame duration , 4 bytes*/
+ if (length_remaining >= 4) {
+ align_offset = ALIGN_OFFSET(offset, 4);
+ offset += align_offset;
+ length_remaining -= align_offset;
+ vw_pktdur = tvb_get_letohl(tvb, offset);
+
+ if (tree) {
+ if (vw_times_tree != NULL) {
+ proto_item *duration_ti;
+ if (vw_endt >= vw_startt) {
+ duration_ti = proto_tree_add_uint_format(vw_times_tree, hf_ixveriwave_vw_pktdur,
+ tvb, offset-16, 16, vw_pktdur,
+ "Frame duration: %u nsec", vw_pktdur);
+
+ /* Add to root summary */
+ proto_item_append_text(vw_times_ti, " (Frame duration=%u nsecs)", vw_pktdur);
+ }
+ else {
+ duration_ti = proto_tree_add_uint_format(vw_times_tree, hf_ixveriwave_vw_pktdur,
+ tvb, offset, 0, vw_pktdur,
+ "Frame duration: N/A");
+
+ /* Add to root summary */
+ proto_item_append_text(vw_times_ti, " (Frame duration=N/A)");
+ }
+
+ PROTO_ITEM_SET_GENERATED(duration_ti);
+ }
+ }
+
+ offset+=4;
+ length_remaining-=4;
+ }
+
+ if (vw_times_ti) {
+ proto_item_set_len(vw_times_ti, offset-time_tree_offset);
+ }
+
+ /* Calculate the IFG */
+
+ /* Check for an existing ifg value associated with the frame */
+ p_ifg_info = p_get_proto_data(pinfo->fd, proto_ixveriwave);
+ if (!p_ifg_info)
+ {
+ /* allocate the space */
+ p_ifg_info = se_alloc0(sizeof(struct ifg_info));
+
+ /* Doesn't exist, so we need to calculate the value */
+ if (previous_frame_data.previous_frame_num !=0 && (pinfo->fd->num - previous_frame_data.previous_frame_num == 1))
+ {
+ p_ifg_info->ifg = (guint32)(vw_startt - previous_frame_data.previous_end_time);
+ p_ifg_info->previous_end_time = previous_frame_data.previous_end_time;
+ }
+ else
+ {
+ p_ifg_info->ifg = 0;
+ p_ifg_info->previous_end_time = 0;
+ }
+
+ /* Store current data into the static structure */
+ previous_frame_data.previous_end_time = vw_endt;
+ previous_frame_data.previous_frame_num = pinfo->fd->num;
+
+ /* Record the current start time */
+ p_ifg_info->current_start_time = vw_startt;
+
+ /* Add the ifg onto the frame */
+ p_add_proto_data(pinfo->fd, proto_ixveriwave, p_ifg_info);
+ }
+
+ if (tree) {
+ ti = proto_tree_add_uint(common_tree, hf_ixveriwave_vw_ifg,
+ tvb, offset, 0, p_ifg_info->ifg);
+ PROTO_ITEM_SET_GENERATED(ti);
+ }
+
+ /* Grab the rest of the frame. */
+ next_tvb = tvb_new_subset(tvb, length, -1, -1);
+
+ /* dissect the ethernet or wlan header next */
+ if (version == ETHERNET_PORT)
+ ethernettap_dissect(next_tvb, pinfo, tree, common_tree);
+ else
+ wlantap_dissect(next_tvb, pinfo, tree, common_tree);
+}
+
+/*
+ * Returns the amount required to align "offset" with "width"
+ */
+#define ALIGN_OFFSET(offset, width) \
+ ( (((offset) + ((width) - 1)) & (~((width) - 1))) - offset )
+
+static void
+ethernettap_dissect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_tree *tap_tree)
+{
+ proto_tree *vweft, *vw_errorFlags_tree = NULL, *vwift,*vw_infoFlags_tree = NULL;
+ int align_offset, offset;
+ tvbuff_t *next_tvb;
+ guint length, length_remaining;
+ guint16 vw_flags, vw_info;
+ guint16 vw_l4id;
+ guint32 vw_error;
+ gint32 vwf_txf, vwf_fcserr;
+
+ vwf_fcserr = vwf_txf = 0;
+ align_offset = 0;
+
+ offset = 0;
+
+ length = tvb_get_letohs(tvb, offset);
+ length_remaining = length;
+
+ offset += 2;
+ length_remaining -= 2;
+
+ /* extract flags (currently use only TX/RX and FCS error flag) */
+ if (length >= 2) {
+ align_offset = ALIGN_OFFSET(offset, 2);
+ offset += align_offset;
+ length_remaining -= align_offset;
+ vw_flags = tvb_get_letohs(tvb, offset);
+ vwf_txf = ((vw_flags & ETHERNETTAP_VWF_TXF) == 0) ? 0 : 1;
+ vwf_fcserr = ((vw_flags & ETHERNETTAP_VWF_FCSERR) == 0) ? 0 : 1;
+
+ if (tap_tree) {
+ proto_tree_add_uint(tap_tree, hf_ixveriwave_vwf_txf,
+ tvb, 0, 0, vwf_txf);
+ proto_tree_add_uint(tap_tree, hf_ixveriwave_vwf_fcserr,
+ tvb, 0, 0, vwf_fcserr);
+ }
+
+ offset += 2;
+ length_remaining -= 2;
+ }
+
+ /*extract info flags , 2bytes*/
+
+ if (length_remaining >= 2) {
+ vw_info = tvb_get_letohs(tvb, offset);
+
+ if (tap_tree) {
+ vwift = proto_tree_add_uint(tap_tree, hf_ixveriwave_vw_info,
+ tvb, offset, 2, vw_info);
+ vw_infoFlags_tree = proto_item_add_subtree(vwift, ett_ethernettap_info);
+
+ if (vwf_txf == 0) {
+ /* then it's an rx case */
+ proto_tree_add_item(vw_infoFlags_tree, hf_ixveriwave_vw_info_rx_1_bit8,
+ tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(vw_infoFlags_tree, hf_ixveriwave_vw_info_rx_1_bit9,
+ tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ } else {
+ /* it's a tx case */
+ proto_tree_add_uint_format(vw_infoFlags_tree, hf_ixveriwave_vw_info_retryCount,
+ tvb, offset, 2, vw_info,
+ "Retry count: %u ", vw_info);
+ }
+ } /*end of if tree */
+
+ offset+=2;
+ length_remaining-=2;
+ }
+
+ /*extract error , 4bytes*/
+ if (length_remaining >= 4) {
+ vw_error = tvb_get_letohl(tvb, offset);
+
+ if (tap_tree) {
+ vweft = proto_tree_add_uint(tap_tree, hf_ixveriwave_vw_error,
+ tvb, offset, 4, vw_error);
+ vw_errorFlags_tree = proto_item_add_subtree(vweft, ett_ethernettap_error);
+
+ if (vwf_txf == 0) {
+ /* then it's an rx case */
+ proto_tree_add_item(vw_errorFlags_tree, hf_ixveriwave_vw_error_rx_1_bit0,
+ tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(vw_errorFlags_tree, hf_ixveriwave_vw_error_rx_1_bit1,
+ tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(vw_errorFlags_tree, hf_ixveriwave_vw_error_rx_1_bit2,
+ tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(vw_errorFlags_tree, hf_ixveriwave_vw_error_rx_1_bit3,
+ tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(vw_errorFlags_tree, hf_ixveriwave_vw_error_rx_1_bit4,
+ tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(vw_errorFlags_tree, hf_ixveriwave_vw_error_rx_1_bit5,
+ tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(vw_errorFlags_tree, hf_ixveriwave_vw_error_rx_1_bit6,
+ tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(vw_errorFlags_tree, hf_ixveriwave_vw_error_rx_1_bit7,
+ tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(vw_errorFlags_tree, hf_ixveriwave_vw_error_rx_1_bit8,
+ tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(vw_errorFlags_tree, hf_ixveriwave_vw_error_rx_1_bit9,
+ tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ } else {
+ /* it's a tx case */
+ proto_tree_add_item(vw_errorFlags_tree, hf_ixveriwave_vw_error_tx_bit1,
+ tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(vw_errorFlags_tree, hf_ixveriwave_vw_error_tx_bit5,
+ tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(vw_errorFlags_tree, hf_ixveriwave_vw_error_tx_bit9,
+ tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(vw_errorFlags_tree, hf_ixveriwave_vw_error_tx_bit10,
+ tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(vw_errorFlags_tree, hf_ixveriwave_vw_error_tx_bit11,
+ tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ }
+ } /*end of if (tree) */
+
+ offset+=4;
+ length_remaining-=4;
+ }
+ /*extract l4id , 4bytes*/
+ if (length_remaining >= 4) {
+ vw_l4id = tvb_get_letohl(tvb, offset);
+ if (tap_tree) {
+ proto_tree_add_uint(tap_tree, hf_ixveriwave_vw_l4id,
+ tvb, offset, 4, vw_l4id);
+ }
+ offset+=4;
+ length_remaining-=4;
+ }
+
+ /*extract pad, 4bytes*/
+ if (length_remaining >= 4) {
+ tvb_get_letohl(tvb, offset); /* throw away pad */
+ offset+=4;
+ length_remaining-=4;
+ }
+
+ /* Grab the rest of the frame. */
+ next_tvb = tvb_new_subset(tvb, length, -1, -1);
+
+ /* dissect the ethernet header next */
+ call_dissector(ethernet_handle, next_tvb, pinfo, tree);
+}
+
+static void
+wlantap_dissect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_tree *tap_tree)
+{
+ proto_tree *ft, *flags_tree = NULL;
+/* proto_item *ti = NULL; */
+ proto_item *hdr_fcs_ti = NULL;
+ int align_offset, offset;
+ guint32 calc_fcs;
+ tvbuff_t *next_tvb;
+ guint length, length_remaining;
+ guint32 rate;
+ gint8 dbm;
+ guint8 rflags=0;
+
+ /* start veriwave addition 6-2007 */
+ proto_tree *vweft, *vw_errorFlags_tree = NULL, *vwift,*vw_infoFlags_tree = NULL;
+ guint16 vw_flags, vw_info, vw_ht_length, vw_rflags;
+ guint32 vw_errors;
+ gint8 tx_power;
+ /* end veriwave additions 6-2007 */
+ float ht_rate;
+ /* start veriwave additions 6-14-2007 */
+ tx_power = 0;
+ /* end veriwave additions 6-14-2007 */
+
+ offset = 0;
+ length = tvb_get_letohs(tvb, offset);
+ length_remaining = length;
+
+ align_offset = ALIGN_OFFSET(offset, 2);
+ offset += 2;
+ length_remaining -= 2;
+
+ vw_rflags = tvb_get_letohs(tvb, offset);
+ if (tree) {
+ ft = proto_tree_add_uint(tap_tree, hf_radiotap_flags,
+ tvb, offset, 2, vw_rflags);
+ flags_tree = proto_item_add_subtree(ft, ett_radiotap_flags);
+ proto_tree_add_boolean(flags_tree, hf_radiotap_flags_cfp,
+ tvb, offset, 2, vw_rflags);
+ proto_tree_add_boolean(flags_tree, hf_radiotap_flags_preamble,
+ tvb, offset, 2, vw_rflags);
+ proto_tree_add_boolean(flags_tree, hf_radiotap_flags_wep,
+ tvb, offset, 2, vw_rflags);
+ proto_tree_add_boolean(flags_tree, hf_radiotap_flags_frag,
+ tvb, offset, 2, vw_rflags);
+ proto_tree_add_boolean(flags_tree, hf_radiotap_flags_fcs,
+ tvb, offset, 2, vw_rflags);
+ proto_tree_add_boolean(flags_tree, hf_radiotap_flags_datapad,
+ tvb, offset, 2, vw_rflags);
+ if ( vw_rflags & IEEE80211_RADIOTAP_F_HT ) {
+ proto_tree_add_boolean(flags_tree, hf_radiotap_flags_ht,
+ tvb, offset, 2, vw_rflags);
+ proto_tree_add_boolean(flags_tree, hf_radiotap_flags_40mhz,
+ tvb, offset, 2, vw_rflags);
+ proto_tree_add_boolean(flags_tree, hf_radiotap_flags_shortgi,
+ tvb, offset, 2, vw_rflags);
+ }
+ }
+ offset+=2;
+ length_remaining-=2;
+
+ /* Need to add in 2 more bytes to the offset to account for the channel flags */
+ offset+=2;
+ length_remaining-=2;
+
+ rate = tvb_get_guint8(tvb, offset);
+ if (vw_rflags & IEEE80211_RADIOTAP_F_HT) {
+ ht_rate = getHTrate( rate, rflags );
+ col_add_fstr(pinfo->cinfo, COL_TX_RATE, "%.1f",
+ ht_rate);
+ if (tree) {
+ proto_tree_add_uint_format(tap_tree, hf_radiotap_datarate,
+ tvb, offset, 1, tvb_get_guint8(tvb, offset),
+ "Data rate: %.1f (MCS %d)", ht_rate, rate & IEEE80211_PLCP_RATE_MASK);
+ }
+ } else {
+ col_add_fstr(pinfo->cinfo, COL_TX_RATE, "%d.%d",
+ (rate & IEEE80211_PLCP_RATE_MASK)/ 2, rate & 1 ? 5 : 0);
+ if (tree) {
+ proto_tree_add_uint_format(tap_tree, hf_radiotap_datarate,
+ tvb, offset, 1, tvb_get_guint8(tvb, offset),
+ "Data rate: %d.%d Mb/s", (rate & IEEE80211_PLCP_RATE_MASK)/ 2,
+ (rate & IEEE80211_PLCP_RATE_MASK) & 1 ? 5 : 0);
+ }
+ }
+ offset++;
+ length_remaining--;
+
+ dbm = (gint8) tvb_get_guint8(tvb, offset);
+ align_offset = ALIGN_OFFSET(offset, 1);
+ offset++;
+ length_remaining--;
+
+ tx_power = (gint8)tvb_get_guint8(tvb, offset);
+ if (dbm != 100)
+ {
+ col_add_fstr(pinfo->cinfo, COL_RSSI, "%d dBm", dbm);
+ if (tree) {
+ proto_tree_add_int_format(tap_tree,
+ hf_radiotap_dbm_antsignal,
+ tvb, offset, 1, dbm,
+ "RX SSI signal: %d dBm", dbm);
+ }
+ }
+ else if (tx_power != 100)
+ {
+ col_add_fstr(pinfo->cinfo, COL_RSSI, "%d dBm", tx_power);
+ if (tree) {
+ proto_tree_add_int_format(tap_tree,
+ hf_radiotap_txpower,
+ tvb, offset, 1, tx_power,
+ "Transmit power (TX): %d ", tx_power);
+ }
+ }
+ offset+=2;
+ length_remaining-=2;
+
+ vw_flags = tvb_get_letohs(tvb, offset);
+
+ if (tree) {
+ proto_tree_add_uint(tap_tree, hf_radiotap_vwf_txf,
+ tvb, offset, 2, (vw_flags & VW_RADIOTAPF_TXF) != 0);
+ proto_tree_add_uint(tap_tree, hf_radiotap_vwf_fcserr,
+ tvb, offset, 2, (vw_flags & VW_RADIOTAPF_FCSERR) != 0);
+ proto_tree_add_uint(tap_tree, hf_radiotap_vwf_dcrerr,
+ tvb, offset, 2, (vw_flags & VW_RADIOTAPF_DCRERR) != 0);
+ proto_tree_add_uint(tap_tree, hf_radiotap_vwf_retrerr,
+ tvb, offset, 2, (vw_flags & VW_RADIOTAPF_RETRERR) != 0);
+ proto_tree_add_uint(tap_tree, hf_radiotap_vwf_enctype,
+ tvb, offset, 2, (vw_flags & VW_RADIOTAPF_ENCMSK) >>
+ VW_RADIOTAPF_ENCSHIFT);
+ }
+
+ offset+=2;
+ length_remaining-=2;
+
+ align_offset = ALIGN_OFFSET(offset, 2);
+ offset += align_offset;
+ length_remaining -= align_offset;
+
+ vw_ht_length = tvb_get_letohs(tvb, offset);
+ if ((tree) && (vw_ht_length != 0)) {
+ proto_tree_add_uint_format(tap_tree, hf_radiotap_vw_ht_length,
+ tvb, offset, 2, vw_ht_length, "HT length: %u (includes the sum of the pieces of the aggregate and their respective Start_Spacing + Delimiter + MPDU + Padding)",
+ vw_ht_length);
+ }
+ offset+=2;
+ length_remaining-=2;
+
+ align_offset = ALIGN_OFFSET(offset, 2);
+ offset += align_offset;
+ length_remaining -= align_offset;
+
+ vw_info = tvb_get_letohs(tvb, offset);
+
+ if (tree) {
+ vwift = proto_tree_add_uint(tap_tree, hf_radiotap_vw_info,
+ tvb, offset, 2, vw_info);
+ vw_infoFlags_tree = proto_item_add_subtree(vwift, ett_radiotap_info);
+
+ if (tx_power == 0) { /* then it's an rx case */
+ /*FPGA_VER_vVW510021 version decodes */
+
+ proto_tree_add_item(vw_infoFlags_tree,
+ hf_radiotap_vw_info_rx_2_bit8, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(vw_infoFlags_tree,
+ hf_radiotap_vw_info_rx_2_bit9, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(vw_infoFlags_tree,
+ hf_radiotap_vw_info_rx_2_bit10, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(vw_infoFlags_tree,
+ hf_radiotap_vw_info_rx_2_bit11, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(vw_infoFlags_tree,
+ hf_radiotap_vw_info_rx_2_bit12, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(vw_infoFlags_tree,
+ hf_radiotap_vw_info_rx_2_bit13, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(vw_infoFlags_tree,
+ hf_radiotap_vw_info_rx_2_bit14, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(vw_infoFlags_tree,
+ hf_radiotap_vw_info_rx_2_bit15, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ } else { /* it's a tx case */
+ /* FPGA_VER_vVW510021 and VW_FPGA_VER_vVW510006 tx info decodes same*/
+ proto_tree_add_item(vw_infoFlags_tree,
+ hf_radiotap_vw_info_tx_bit10, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(vw_infoFlags_tree,
+ hf_radiotap_vw_info_tx_bit11, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(vw_infoFlags_tree,
+ hf_radiotap_vw_info_tx_bit12, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(vw_infoFlags_tree,
+ hf_radiotap_vw_info_tx_bit13, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(vw_infoFlags_tree,
+ hf_radiotap_vw_info_tx_bit14, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(vw_infoFlags_tree,
+ hf_radiotap_vw_info_tx_bit15, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ }
+ }
+
+ offset+=2;
+ length_remaining-=2;
+
+ align_offset = ALIGN_OFFSET(offset, 4);
+ offset += align_offset;
+ length_remaining -= align_offset;
+
+ vw_errors = tvb_get_letohl(tvb, offset);
+
+ if (tree) {
+ vweft = proto_tree_add_uint(tap_tree, hf_radiotap_vw_errors,
+ tvb, offset, 4, vw_errors);
+ vw_errorFlags_tree = proto_item_add_subtree(vweft,
+ ett_radiotap_errors);
+
+ /* build the individual subtrees for the various types of error flags */
+ /* NOTE: as the upper 16 bits aren't used at the moment, we pretend that */
+ /* the error flags field is only 16 bits (instead of 32) to save space */
+ if (tx_power == 0) {
+ /* then it's an rx case */
+
+ /*FPGA_VER_vVW510021 version decodes */
+ proto_tree_add_item(vw_errorFlags_tree,
+ hf_radiotap_vw_errors_rx_2_bit0, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(vw_errorFlags_tree,
+ hf_radiotap_vw_errors_rx_2_bit1, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(vw_errorFlags_tree,
+ hf_radiotap_vw_errors_rx_2_bit2, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+
+ /* veriwave removed 8-2007, don't display reserved bit*/
+
+ proto_tree_add_item(vw_errorFlags_tree,
+ hf_radiotap_vw_errors_rx_2_bit4, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(vw_errorFlags_tree,
+ hf_radiotap_vw_errors_rx_2_bit5, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(vw_errorFlags_tree,
+ hf_radiotap_vw_errors_rx_2_bit6, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(vw_errorFlags_tree,
+ hf_radiotap_vw_errors_rx_2_bit7, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(vw_errorFlags_tree,
+ hf_radiotap_vw_errors_rx_2_bit8, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+
+ proto_tree_add_item(vw_errorFlags_tree,
+ hf_radiotap_vw_errors_rx_2_bit10, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(vw_errorFlags_tree,
+ hf_radiotap_vw_errors_rx_2_bit11, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+
+ } else { /* it's a tx case */
+ /* FPGA_VER_vVW510021 and VW_FPGA_VER_vVW510006 tx error decodes same*/
+
+ proto_tree_add_item(vw_errorFlags_tree,
+ hf_radiotap_vw_errors_tx_bit1, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+
+ proto_tree_add_item(vw_errorFlags_tree,
+ hf_radiotap_vw_errors_tx_bit5, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+
+ }
+ }
+
+ offset+=4;
+ length_remaining-=4;
+
+ /* This handles the case of an FCS existing at the end of the frame. */
+ if (rflags & IEEE80211_RADIOTAP_F_FCS)
+ pinfo->pseudo_header->ieee_802_11.fcs_len = 4;
+ else
+ pinfo->pseudo_header->ieee_802_11.fcs_len = 0;
+
+ /* Grab the rest of the frame. */
+ next_tvb = tvb_new_subset(tvb, length, -1, -1);
+
+ /* If we had an in-header FCS, check it. */
+ if (hdr_fcs_ti) {
+ /* It would be very strange for the header to have an FCS for the
+ * frame *and* the frame to have the FCS at the end, but it's possible, so
+ * take that into account by using the FCS length recorded in pinfo. */
+
+ /* Watch out for [erroneously] short frames */
+ if (tvb_length(next_tvb) > (unsigned int) pinfo->pseudo_header->ieee_802_11.fcs_len) {
+ guint32 sent_fcs = 0;
+ calc_fcs = crc32_802_tvb(next_tvb,
+ tvb_length(next_tvb) - pinfo->pseudo_header->ieee_802_11.fcs_len);
+
+ /* By virtue of hdr_fcs_ti being set, we know that 'tree' is set,
+ * so there's no need to check it here. */
+ if (calc_fcs == sent_fcs) {
+ proto_item_append_text(hdr_fcs_ti, " [correct]");
+ }
+ else {
+ proto_item_append_text(hdr_fcs_ti, " [incorrect, should be 0x%08x]", calc_fcs);
+ proto_tree_add_boolean(tap_tree, hf_radiotap_fcs_bad,
+ tvb, 0, 4, TRUE);
+ }
+ }
+ else {
+ proto_item_append_text(hdr_fcs_ti,
+ " [cannot verify - not enough data]");
+ }
+ }
+
+ /* dissect the 802.11 header next */
+ call_dissector((rflags & IEEE80211_RADIOTAP_F_DATAPAD) ?
+ ieee80211_datapad_handle : ieee80211_handle,
+ next_tvb, pinfo, tree);
+}
+
+void proto_register_ixveriwave(void)
+{
+ /* value_strings for TX/RX and FCS error flags */
+ static const value_string tx_rx_type[] = {
+ { 0, "Received" },
+ { 1, "Transmitted" },
+ { 0, NULL },
+ };
+
+ static const value_string fcserr_type[] = {
+ { 0, "Correct" },
+ { 1, "Incorrect" },
+ { 0, NULL },
+ };
+
+ static const true_false_string preamble_type = {
+ "Short",
+ "Long",
+ };
+
+ /* Added value_string for decrypt error flag */
+ static const value_string decrypterr_type[] = {
+ { 0, "Decrypt Succeeded" },
+ { 1, "Decrypt Failed" },
+ { 0, NULL },
+ };
+
+ /* Added value_string for excess retry error flag */
+ static const value_string retryerr_type[] = {
+ { 0, "Retry limit not reached" },
+ { 1, "Excess retry abort" },
+ { 0, NULL },
+ };
+
+ /* Added value_string for encryption type field */
+ static const value_string encrypt_type[] = {
+ { 0, "No encryption" },
+ { 1, "WEP encryption" },
+ { 2, "TKIP encryption" },
+ { 3, "AES-CCMP encryption" },
+ { 0, NULL },
+ };
+
+ static hf_register_info hf[] = {
+ { &hf_ixveriwave_frame_length,
+ { "Actual frame length", "ixveriwave.frame_length",
+ FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
+
+ { &hf_ixveriwave_vw_msdu_length,
+ { "MSDU length", "ixveriwave.msdu_length",
+ FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
+
+ { &hf_ixveriwave_vw_vcid,
+ { "Client ID", "ixveriwave.clientid",
+ FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
+
+ { &hf_ixveriwave_vw_flowid,
+ { "Flow ID", "ixveriwave.flowid",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
+
+ { &hf_ixveriwave_vw_seqnum,
+ { "Sequence number", "ixveriwave.seqnum",
+ FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
+
+ { &hf_ixveriwave_vw_mslatency,
+ { "Msec latency", "ixveriwave.mslatency",
+ FT_FLOAT, 0, NULL, 0x0, NULL, HFILL } },
+
+ { &hf_ixveriwave_vw_latency,
+ { "Latency", "ixveriwave.latency",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
+
+ { &hf_ixveriwave,
+ { "Signature (32 LSBs)", "ixveriwave.sig_ts",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
+
+ { &hf_ixveriwave_vw_startt,
+ { "Starting frame timestamp", "ixveriwave.startt",
+ FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL } },
+
+ { &hf_ixveriwave_vw_endt,
+ { "Ending frame timestamp", "ixveriwave.endt",
+ FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL } },
+
+ { &hf_ixveriwave_vw_pktdur,
+ { "Packet duration", "ixveriwave.pktdur",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
+
+ { &hf_ixveriwave_vw_ifg,
+ { "Inter-frame gap (usecs)", "ixveriwave.ifg",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
+
+ { &hf_ixveriwave_vwf_txf,
+ { "Frame direction", "ixveriwave.vwflags.txframe",
+ FT_UINT32, BASE_DEC, VALS(tx_rx_type), 0x0, NULL, HFILL } },
+
+ { &hf_ixveriwave_vwf_fcserr,
+ { "MAC FCS check", "ixveriwave.vwflags.fcserr",
+ FT_UINT32, BASE_DEC, VALS(fcserr_type), 0x0, NULL, HFILL } },
+
+ { &hf_ixveriwave_vw_info,
+ { "Info field", "ixveriwave.info",
+ FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } },
+
+ { &hf_ixveriwave_vw_info_retryCount,
+ { "Info field retry count", "ixveriwave.info",
+ FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
+
+/* tx info decodes for VW510024 and 510012 */
+/* we don't need to enumerate through these, basically for both,
+info is the retry count. for 510024, the 15th bit indicates if
+the frame was impressed on the enet tx media with one or more octets having tx_en
+framing signal deasserted. this is caused by software setting the drain all register bit.
+*/
+ { &hf_ixveriwave_vw_info_tx_bit15,
+ { "Info bit 15-frame was impressed on the ent tx media with one or more octets having tx_en framing signal deasserted.", "ixveriwave.info.bit15",
+ FT_BOOLEAN, 16, NULL, 0x8000, NULL, HFILL } },
+
+ /* rx info decodes for fpga ver VW510024 */
+ /*all are reserved*/
+
+ /* rx info decodes for fpga ver VW510012 */
+ { &hf_ixveriwave_vw_info_rx_1_bit8,
+ { "Go no flow", "ixveriwave.info.bit8",
+ FT_BOOLEAN, 16, NULL, 0x0100, NULL, HFILL } },
+ { &hf_ixveriwave_vw_info_rx_1_bit9,
+ { "Go with flow", "ixveriwave.info.bit9",
+ FT_BOOLEAN, 16, NULL, 0x0200, NULL, HFILL } },
+
+ { &hf_ixveriwave_vw_error,
+ { "Errors", "ixveriwave.error",
+ FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
+ /* tx error decodes for VW510024 and previous versions */
+
+ { &hf_ixveriwave_vw_error_tx_bit1,
+ { "Packet FCS error", "ixveriwave.error.bit1",
+ FT_BOOLEAN, 12, NULL, 0x0002, NULL, HFILL } },
+ { &hf_ixveriwave_vw_error_tx_bit5,
+ { "IP checksum error", "ixveriwave.error.bit5",
+ FT_BOOLEAN, 12, NULL, 0x0020, NULL, HFILL } },
+ /*bit 6 is actually reserved in 500012, but i thought it would be okay to leave it here*/
+ { &hf_ixveriwave_vw_error_tx_bit9,
+ { "Underflow error", "ixveriwave.error.bit9",
+ FT_BOOLEAN, 12, NULL, 0x0200, NULL, HFILL } },
+ { &hf_ixveriwave_vw_error_tx_bit10,
+ { "Late collision error", "ixveriwave.error.bit10",
+ FT_BOOLEAN, 12, NULL, 0x0400, NULL, HFILL } },
+ { &hf_ixveriwave_vw_error_tx_bit11,
+ { "Excessive collisions error", "ixveriwave.error.bit11",
+ FT_BOOLEAN, 12, NULL, 0x0800, NULL, HFILL } },
+ /*all other bits are reserved */
+
+ /* rx error decodes for fpga ver VW510012 and VW510024 */
+ { &hf_ixveriwave_vw_error_rx_1_bit0,
+ { "Alignment error", "ixveriwave.error.bit0",
+ FT_BOOLEAN, 12, NULL, 0x0001, "error bit 0", HFILL } },
+ { &hf_ixveriwave_vw_error_rx_1_bit1,
+ { "Packet FCS error", "ixveriwave.error.bit1",
+ FT_BOOLEAN, 12, NULL, 0x0002, NULL, HFILL } },
+ { &hf_ixveriwave_vw_error_rx_1_bit2,
+ { "Bad magic byte signature.", "ixveriwave.error.bit2",
+ FT_BOOLEAN, 12, NULL, 0x0004, NULL, HFILL } },
+ { &hf_ixveriwave_vw_error_rx_1_bit3,
+ { "Bad payload checksum.", "ixveriwave.error.bit3",
+ FT_BOOLEAN, 12, NULL, 0x0008, NULL, HFILL } },
+ { &hf_ixveriwave_vw_error_rx_1_bit4,
+ { "Frame too long error", "ixveriwave.error.bit4",
+ FT_BOOLEAN, 12, NULL, 0x0010, NULL, HFILL } },
+ { &hf_ixveriwave_vw_error_rx_1_bit5,
+ { "IP checksum error", "ixveriwave.error.bit5",
+ FT_BOOLEAN, 12, NULL, 0x0020, NULL, HFILL } },
+ { &hf_ixveriwave_vw_error_rx_1_bit6,
+ { "TCP/ICMP/IGMP/UDP checksum error", "ixveriwave.error.bit6",
+ FT_BOOLEAN, 12, NULL, 0x0040, NULL, HFILL } },
+ { &hf_ixveriwave_vw_error_rx_1_bit7,
+ { "ID mismatch(for fpga510012)", "ixveriwave.error.bit7",
+ FT_BOOLEAN, 12, NULL, 0x0080, NULL, HFILL } },
+ { &hf_ixveriwave_vw_error_rx_1_bit8,
+ { "Length error", "ixveriwave.error.bit8",
+ FT_BOOLEAN, 12, NULL, 0x0100, NULL, HFILL } },
+ { &hf_ixveriwave_vw_error_rx_1_bit9,
+ { "Underflow", "ixveriwave.error.bit9",
+ FT_BOOLEAN, 12, NULL, 0x0200, NULL, HFILL } },
+ { &hf_radiotap_vw_errors_tx_bit1,
+ { "Packet FCS error", "ixveriwave.errors.bit1",
+ FT_BOOLEAN, 16, NULL, 0x0002, NULL, HFILL } },
+ { &hf_radiotap_vw_errors_tx_bit5,
+ { "IP checksum error", "ixveriwave.errors.bit5",
+ FT_BOOLEAN, 16, NULL, 0x0002, NULL, HFILL } },
+
+ /* All other enumerations are reserved.*/
+
+ { &hf_ixveriwave_vw_l4id,
+ { "Layer 4 ID", "ixveriwave.layer4id",
+ FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } },
+
+ /* Presense flags */
+ #define RADIOTAP_MASK_VW_FPGA_VERSION (1 << VW_RADIOTAP_FPGA_VERSION)
+ #define RADIOTAP_MASK_VW_MCID (1 << VW_RADIOTAP_MCID)
+ #define RADIOTAP_MASK_VW_ERRORS (1 << VW_RADIOTAP_ERRORS)
+ #define RADIOTAP_MASK_VW_INFO (1 << VW_RADIOTAP_INFO)
+ #define RADIOTAP_MASK_VW_MSDU_LENGTH (1 << VW_RADIOTAP_MSDU_LENGTH)
+ #define RADIOTAP_MASK_VW_HT_LENGTH (1 << VW_RADIOTAP_HT_LENGTH)
+ #define RADIOTAP_MASK_VW_FLOWID (1 << VW_RADIOTAP_FLOWID)
+ #define RADIOTAP_MASK_VW_SEQNUM (1 << VW_RADIOTAP_SEQNUM)
+ #define RADIOTAP_MASK_VW_LATENCY (1 << VW_RADIOTAP_LATENCY)
+ #define RADIOTAP_MASK_VW_SIG_TS (1 << VW_RADIOTAP_SIG_TS)
+ #define RADIOTAP_MASK_VW_STARTT (1 << VW_RADIOTAP_STARTT)
+ #define RADIOTAP_MASK_VW_ENDT (1 << VW_RADIOTAP_ENDT)
+ #define RADIOTAP_MASK_VW_PKTDUR (1 << VW_RADIOTAP_PKTDUR)
+ #define RADIOTAP_MASK_VW_IFG (1 << VW_RADIOTAP_IFG)
+ /* end veriwave addition*/
+
+ { &hf_radiotap_datarate,
+ { "Data rate", "ixveriwave.datarate",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Speed this frame was sent/received at", HFILL } },
+
+ /* Boolean 'present.flags' flags */
+ { &hf_radiotap_flags,
+ { "Flags", "ixveriwave.flags",
+ FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } },
+
+ { &hf_radiotap_flags_cfp,
+ { "CFP", "ixveriwave.flags.cfp",
+ FT_BOOLEAN, 12, NULL, IEEE80211_RADIOTAP_F_CFP,
+ "Sent/Received during CFP", HFILL } },
+
+ { &hf_radiotap_flags_preamble,
+ { "Preamble", "ixveriwave.flags.preamble",
+ FT_BOOLEAN, 12, TFS(&preamble_type), IEEE80211_RADIOTAP_F_SHORTPRE,
+ "Sent/Received with short preamble", HFILL } },
+
+ { &hf_radiotap_flags_wep,
+ { "WEP", "ixveriwave.flags.wep",
+ FT_BOOLEAN, 12, NULL, IEEE80211_RADIOTAP_F_WEP,
+ "Sent/Received with WEP encryption", HFILL } },
+
+ { &hf_radiotap_flags_frag,
+ { "Fragmentation", "ixveriwave.flags.frag",
+ FT_BOOLEAN, 12, NULL, IEEE80211_RADIOTAP_F_FRAG,
+ "Sent/Received with fragmentation", HFILL } },
+
+ { &hf_radiotap_flags_fcs,
+ { "FCS at end", "ixveriwave.flags.fcs",
+ FT_BOOLEAN, 12, NULL, IEEE80211_RADIOTAP_F_FCS,
+ "Frame includes FCS at end", HFILL } },
+
+ { &hf_radiotap_flags_datapad,
+ { "Data Pad", "ixveriwave.flags.datapad",
+ FT_BOOLEAN, 12, NULL, IEEE80211_RADIOTAP_F_DATAPAD,
+ "Frame has padding between 802.11 header and payload", HFILL } },
+
+ { &hf_radiotap_flags_ht,
+ { "HT frame", "ixveriwave.flags.ht",
+ FT_BOOLEAN, 12, NULL, IEEE80211_RADIOTAP_F_HT, NULL, HFILL } },
+
+ { &hf_radiotap_flags_40mhz,
+ { "40 MHz channel bandwidth", "ixveriwave.flags.40mhz",
+ FT_BOOLEAN, 12, NULL, IEEE80211_RADIOTAP_F_40MHZ, NULL, HFILL } },
+
+ { &hf_radiotap_flags_shortgi,
+ { "Short guard interval", "ixveriwave.flags.shortgi",
+ FT_BOOLEAN, 12, NULL, IEEE80211_RADIOTAP_F_SHORTGI, NULL, HFILL } },
+
+ { &hf_radiotap_dbm_antsignal,
+ { "SSI Signal (dBm)", "ixveriwave.dbm_antsignal",
+ FT_INT32, BASE_DEC, NULL, 0x0,
+ "RF signal power at the antenna from a fixed, arbitrary value in decibels from one milliwatt", HFILL } },
+
+ { &hf_radiotap_txpower,
+ { "Transmit power", "ixveriwave.txpower",
+ FT_INT32, BASE_DEC, NULL, 0x0,
+ "Transmit power in decibels per one milliwatt (dBm)", HFILL } },
+
+ /* Boolean 'present' flags */
+ /* VeriWave-specific flags */
+ { &hf_radiotap_vwf_txf,
+ { "Frame direction", "ixveriwave.vwflags.txframe",
+ FT_UINT32, BASE_DEC, VALS(tx_rx_type), 0x0, NULL, HFILL } },
+
+ { &hf_radiotap_vwf_fcserr,
+ { "MAC FCS check", "ixveriwave.vwflags.fcserr",
+ FT_UINT32, BASE_DEC, VALS(fcserr_type), 0x0, NULL, HFILL } },
+
+ { &hf_radiotap_vwf_dcrerr,
+ { "Decryption error", "ixveriwave.vwflags.decrypterr",
+ FT_UINT32, BASE_DEC, VALS(decrypterr_type), 0x0, NULL, HFILL } },
+
+ { &hf_radiotap_vwf_retrerr,
+ { "TX retry limit", "ixveriwave.vwflags.retryerr",
+ FT_UINT32, BASE_DEC, VALS(retryerr_type), 0x0, NULL, HFILL } },
+
+ { &hf_radiotap_vwf_enctype,
+ { "Encryption type", "ixveriwave.vwflags.encrypt",
+ FT_UINT32, BASE_DEC, VALS(encrypt_type), 0x0, NULL, HFILL } },
+
+ /* start VeriWave-specific radiotap header elements 6-2007 */
+ { &hf_radiotap_vw_ht_length,
+ { "Total IP length (incl all pieces of an aggregate)", "ixveriwave.ht_length",
+ FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
+
+ { &hf_radiotap_vw_errors,
+ { "Errors", "ixveriwave.errors",
+ FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
+
+ /* rx error decodes for fpga ver VW510006 */
+ { &hf_radiotap_vw_errors_rx_1_bit0,
+ { "L1 error", "ixveriwave.errors.bit0",
+ FT_BOOLEAN, 16, NULL, 0x0001, "error bit 0", HFILL } },
+
+ { &hf_radiotap_vw_errors_rx_1_bit1,
+ { "Packet FCS error", "ixveriwave.errors.bit1",
+ FT_BOOLEAN, 16, NULL, 0x0002, NULL, HFILL } },
+
+ { &hf_radiotap_vw_errors_rx_1_bit2,
+ { "Bad magic byte signature.", "ixveriwave.errors.bit2",
+ FT_BOOLEAN, 16, NULL, 0x0004, NULL, HFILL } },
+
+ { &hf_radiotap_vw_errors_rx_1_bit3,
+ { "Bad payload checksum.", "ixveriwave.errors.bit3",
+ FT_BOOLEAN, 16, NULL, 0x0008, NULL, HFILL } },
+
+ { &hf_radiotap_vw_errors_rx_1_bit4,
+ { "Duplicate MPDU", "ixveriwave.errors.bit4",
+ FT_BOOLEAN, 16, NULL, 0x0010, NULL, HFILL } },
+
+ { &hf_radiotap_vw_errors_rx_1_bit5,
+ { "IP checksum error", "ixveriwave.errors.bit5",
+ FT_BOOLEAN, 16, NULL, 0x0020, NULL, HFILL } },
+
+ { &hf_radiotap_vw_errors_rx_1_bit6,
+ { "TCP/ICMP/IGMP/UDP checksum error", "ixveriwave.errors.bit6",
+ FT_BOOLEAN, 16, NULL, 0x0040, NULL, HFILL } },
+
+ { &hf_radiotap_vw_errors_rx_1_bit7,
+ { "Reserved", "ixveriwave.errors.bit7",
+ FT_BOOLEAN, 16, NULL, 0x0080, NULL, HFILL } },
+
+ { &hf_radiotap_vw_errors_rx_1_bit8,
+ { "RX WEP IVC / TKIP/CCMP MIC miscompare", "ixveriwave.errors.bit8",
+ FT_BOOLEAN, 16, NULL, 0x0100, NULL, HFILL } },
+
+ { &hf_radiotap_vw_errors_rx_1_bit9,
+ { "RX TKIP / CCMP TSC SEQERR", "ixveriwave.errors.bit9",
+ FT_BOOLEAN, 16, NULL, 0x0200, NULL, HFILL } },
+
+ { &hf_radiotap_vw_errors_rx_1_bit10,
+ { "RX crypto short", "ixveriwave.errors.bit10",
+ FT_BOOLEAN, 16, NULL, 0x0400, NULL, HFILL } },
+
+ { &hf_radiotap_vw_errors_rx_1_bit11,
+ { "RX EXTIV fault A", "ixveriwave.errors.bit11",
+ FT_BOOLEAN, 16, NULL, 0x0800, NULL, HFILL } },
+
+ { &hf_radiotap_vw_errors_rx_1_bit12,
+ { "RX EXTIV fault B", "ixveriwave.errors.bit12",
+ FT_BOOLEAN, 16, NULL, 0x1000, NULL, HFILL } },
+
+ { &hf_radiotap_vw_errors_rx_1_bit13,
+ { "RX protected fault A", "ixveriwave.errors.bit13",
+ FT_BOOLEAN, 16, NULL, 0x2000, NULL, HFILL } },
+
+ { &hf_radiotap_vw_errors_rx_1_bit14,
+ { "RX protected fault B", "ixveriwave.errors.bit14",
+ FT_BOOLEAN, 16, NULL, 0x4000, NULL, HFILL } },
+
+ { &hf_radiotap_vw_errors_rx_1_bit15,
+ { "Reserved", "ixveriwave.errors.bit15",
+ FT_BOOLEAN, 16, NULL, 0x8000, NULL, HFILL } },
+ /* All other enumerations are reserved.*/
+
+ /* rx error decodes for fpga ver VW510021 */
+ { &hf_radiotap_vw_errors_rx_2_bit0,
+ { "CRC16 or parity error", "ixveriwave.errors.bit0",
+ FT_BOOLEAN, 16, NULL, 0x0001, "error bit 0", HFILL } },
+
+ { &hf_radiotap_vw_errors_rx_2_bit1,
+ { "Non-supported rate or service field", "ixveriwave.errors.bit1",
+ FT_BOOLEAN, 16, NULL, 0x0002, NULL, HFILL } },
+
+ { &hf_radiotap_vw_errors_rx_2_bit2,
+ { "Short frame error. Frame is shorter than length.", "ixveriwave.errors.bit2",
+ FT_BOOLEAN, 16, NULL, 0x0004, NULL, HFILL } },
+
+ { &hf_radiotap_vw_errors_rx_2_bit4,
+ { "FCS_Error", "ixveriwave.errors.bit4",
+ FT_BOOLEAN, 16, NULL, 0x0010, NULL, HFILL } },
+
+ { &hf_radiotap_vw_errors_rx_2_bit5,
+ { "L2 de-aggregation error", "ixveriwave.errors.bit5",
+ FT_BOOLEAN, 16, NULL, 0x0020, NULL, HFILL } },
+
+ { &hf_radiotap_vw_errors_rx_2_bit6,
+ { "Duplicate MPDU", "ixveriwave.errors.bit6",
+ FT_BOOLEAN, 16, NULL, 0x0040, NULL, HFILL } },
+
+ { &hf_radiotap_vw_errors_rx_2_bit7,
+ { "Bad_Sig: Bad flow magic number (includes bad flow crc16)", "ixveriwave.errors.bit7",
+ FT_BOOLEAN, 16, NULL, 0x0080, NULL, HFILL } },
+
+ { &hf_radiotap_vw_errors_rx_2_bit8,
+ { "Bad flow payload checksum", "ixveriwave.errors.bit8",
+ FT_BOOLEAN, 16, NULL, 0x0100, NULL, HFILL } },
+
+ { &hf_radiotap_vw_errors_rx_2_bit10,
+ { "Bad IP checksum error", "ixveriwave.errors.bit10",
+ FT_BOOLEAN, 16, NULL, 0x0400, NULL, HFILL } },
+
+ { &hf_radiotap_vw_errors_rx_2_bit11,
+ { "L4(TCP/ICMP/IGMP/UDP) checksum error", "ixveriwave.errors.bit11",
+ FT_BOOLEAN, 16, NULL, 0x0800, NULL, HFILL } },
+
+ { &hf_radiotap_vw_info,
+ { "Info field", "ixveriwave.info",
+ FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } },
+
+ /* tx info decodes for VW510021 and previous versions */
+ { &hf_radiotap_vw_info_tx_bit10,
+ { "MPDU of A-MPDU", "ixveriwave.info.bit10",
+ FT_BOOLEAN, 16, NULL, 0x0400, NULL, HFILL } },
+
+ { &hf_radiotap_vw_info_tx_bit11,
+ { "First MPDU of A-MPDU", "ixveriwave.info.bit11",
+ FT_BOOLEAN, 16, NULL, 0x0800, NULL, HFILL } },
+
+ { &hf_radiotap_vw_info_tx_bit12,
+ { "Last MPDU of A-MPDU", "ixveriwave.info.bit12",
+ FT_BOOLEAN, 16, NULL, 0x1000, NULL, HFILL } },
+
+ { &hf_radiotap_vw_info_tx_bit13,
+ { "MSDU of A-MSDU", "ixveriwave.info.bit13",
+ FT_BOOLEAN, 16, NULL, 0x2000, NULL, HFILL } },
+
+ { &hf_radiotap_vw_info_tx_bit14,
+ { "First MSDU of A-MSDU", "ixveriwave.info.bit14",
+ FT_BOOLEAN, 16, NULL, 0x4000, NULL, HFILL } },
+
+ { &hf_radiotap_vw_info_tx_bit15,
+ { "Last MSDU of A-MSDU", "ixveriwave.info.bit15",
+ FT_BOOLEAN, 16, NULL, 0x8000, NULL, HFILL } },
+ /*v510006 uses bits */
+
+ /* rx info decodes for fpga ver VW510021 */
+ { &hf_radiotap_vw_info_rx_2_bit8,
+ { "ACK withheld from frame", "ixveriwave.info.bit8",
+ FT_BOOLEAN, 16, NULL, 0x0100, NULL, HFILL } },
+
+ { &hf_radiotap_vw_info_rx_2_bit9,
+ { "Sent CTS to self before data", "ixveriwave.info.bit9",
+ FT_BOOLEAN, 16, NULL, 0x0200, NULL, HFILL } },
+
+ { &hf_radiotap_vw_info_rx_2_bit10,
+ { "MPDU of an A-MPDU", "ixveriwave.info.bit10",
+ FT_BOOLEAN, 16, NULL, 0x0400, NULL, HFILL } },
+
+ { &hf_radiotap_vw_info_rx_2_bit11,
+ { "First MPDU of A-MPDU", "ixveriwave.info.bit11",
+ FT_BOOLEAN, 16, NULL, 0x0800, NULL, HFILL } },
+
+ { &hf_radiotap_vw_info_rx_2_bit12,
+ { "Last MPDU of A-MPDU", "ixveriwave.info.bit12",
+ FT_BOOLEAN, 16, NULL, 0x1000, NULL, HFILL } },
+
+ { &hf_radiotap_vw_info_rx_2_bit13,
+ { "MSDU of A-MSDU", "ixveriwave.info.bit13",
+ FT_BOOLEAN, 16, NULL, 0x2000, NULL, HFILL } },
+
+ { &hf_radiotap_vw_info_rx_2_bit14,
+ { "First MSDU of A-MSDU", "ixveriwave.info.bit14",
+ FT_BOOLEAN, 16, NULL, 0x4000, NULL, HFILL } },
+
+ { &hf_radiotap_vw_info_rx_2_bit15,
+ { "Last MSDU of A-MSDU", "ixveriwave.info.bit15",
+ FT_BOOLEAN, 16, NULL, 0x8000, NULL, HFILL } },
+ };
+
+ static gint *ett[] = {
+ &ett_commontap,
+ &ett_commontap_times,
+ &ett_ethernettap_info,
+ &ett_ethernettap_error,
+ &ett_ethernettap_flags,
+ &ett_radiotap_flags,
+ &ett_radiotap_info,
+ &ett_radiotap_times,
+ &ett_radiotap_errors
+ };
+
+ proto_ixveriwave = proto_register_protocol("ixveriwave", "ixveriwave", "ixveriwave");
+ proto_register_field_array(proto_ixveriwave, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ register_dissector("ixveriwave", dissect_ixveriwave, proto_ixveriwave);
+}
+
+void proto_reg_handoff_ixveriwave(void)
+{
+ dissector_handle_t ixveriwave_handle;
+
+ /* handle for ethertype dissector */
+ ethernet_handle = find_dissector("eth_withoutfcs");
+ /* handle for 802.11 dissector */
+ ieee80211_handle = find_dissector("wlan");
+ ieee80211_datapad_handle = find_dissector("wlan_datapad");
+
+ ixveriwave_handle = create_dissector_handle(dissect_ixveriwave, proto_ixveriwave);
+ dissector_add_uint("wtap_encap", WTAP_ENCAP_IXVERIWAVE, ixveriwave_handle);
+}
+
+static float getHTrate( guint8 rate, guint8 rflags )
+{
+ int mcs_index, ndbps;
+ float symbol_tx_time, bitrate;
+
+ /* Guard interval is the most significant bit. Short GI if the bit is set */
+ if ( rate & 0x80)
+ symbol_tx_time = (float)3.6;
+ else
+ symbol_tx_time = (float)4.0;
+
+ mcs_index = rate & IEEE80211_PLCP_RATE_MASK;
+
+ if ( rflags & IEEE80211_RADIOTAP_F_40MHZ )
+ ndbps = canonical_ndbps_40[ mcs_index - 8*(int)(mcs_index/8) ];
+ else
+ ndbps = canonical_ndbps_20[ mcs_index - 8*(int)(mcs_index/8) ];
+
+ bitrate = ( ndbps * (((int)(mcs_index/8) + 1) )) / symbol_tx_time;
+
+ return bitrate;
+}
+
diff --git a/epan/dissectors/packet-waveagent.c b/epan/dissectors/packet-waveagent.c
new file mode 100644
index 0000000000..e99af99a05
--- /dev/null
+++ b/epan/dissectors/packet-waveagent.c
@@ -0,0 +1,1943 @@
+/* packet-waveagent.c
+ * Routines for WaveAgent dissection
+ * Copyright 2009-2011, Tom Cook <tcook@ixiacom.com>
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ * *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/prefs.h>
+
+#define ETHERNET_INTERFACE 1
+#define WLAN_INTERFACE 2
+
+#define IPV4_TYPE 2
+#define IPV6_TYPE 10
+
+#define NUM_STATE_CHANGES 8
+#define NUM_BSS 8
+#define SHORT_STR 256
+
+#define WA_V2_PAYLOAD_OFFSET 40
+#define WA_V3_PAYLOAD_OFFSET 44
+
+/* Forward declaration we need below */
+void proto_reg_handoff_waveagent(void);
+
+/* Initialize the protocol and registered fields */
+static int proto_waveagent = -1;
+static int hf_waveagent_controlword = -1;
+static int hf_waveagent_payloadlen = -1;
+static int hf_waveagent_transnum = -1;
+static int hf_waveagent_rtoken = -1;
+static int hf_waveagent_flowid = -1;
+static int hf_waveagent_capstatus = -1;
+static int hf_waveagent_protocolversion = -1;
+static int hf_waveagent_capimpl = -1;
+static int hf_waveagent_id = -1;
+static int hf_waveagent_bindtag = -1;
+static int hf_waveagent_version = -1;
+static int hf_waveagent_brokerip = -1;
+static int hf_waveagent_brokerport = -1;
+static int hf_waveagent_bindlevel = -1;
+static int hf_waveagent_bindport = -1;
+static int hf_waveagent_numinterfaces = -1;
+static int hf_waveagent_capabilities2 = -1;
+static int hf_waveagent_ifmask = -1;
+static int hf_waveagent_commandstatus = -1;
+static int hf_waveagent_syserrno = -1;
+static int hf_waveagent_statusstring = -1;
+static int hf_waveagent_rxdatapckts = -1;
+static int hf_waveagent_rxdatabytes = -1;
+static int hf_waveagent_rxpcktrate = -1;
+static int hf_waveagent_rxbyterate = -1;
+static int hf_waveagent_txdatapckts = -1;
+static int hf_waveagent_txdatabytes = -1;
+static int hf_waveagent_txpcktrate = -1;
+static int hf_waveagent_txbyterate = -1;
+static int hf_waveagent_looppckts = -1;
+static int hf_waveagent_loopbytes = -1;
+static int hf_waveagent_rxctlpckts = -1;
+static int hf_waveagent_rxctlbytes = -1;
+static int hf_waveagent_txctlpckts = -1;
+static int hf_waveagent_txctlbytes = -1;
+static int hf_waveagent_unknowncmds = -1;
+static int hf_waveagent_snap = -1;
+static int hf_waveagent_state = -1;
+static int hf_waveagent_appstate = -1;
+static int hf_waveagent_rx1pl = -1;
+static int hf_waveagent_rx2pl = -1;
+static int hf_waveagent_rx3pl = -1;
+static int hf_waveagent_rx4pl = -1;
+static int hf_waveagent_rx5pl = -1;
+static int hf_waveagent_rxoospkts = -1;
+static int hf_waveagent_rxmeanlatency = -1;
+static int hf_waveagent_rxminlatency = -1;
+static int hf_waveagent_rxmaxlatency = -1;
+static int hf_waveagent_latencysum = -1;
+static int hf_waveagent_latencycount = -1;
+static int hf_waveagent_txflowstop = -1;
+static int hf_waveagent_jitter = -1;
+static int hf_waveagent_remoteport = -1;
+static int hf_waveagent_remoteaddr = -1;
+static int hf_waveagent_dscp = -1;
+static int hf_waveagent_fsflags = -1;
+static int hf_waveagent_fscbrflag = -1;
+static int hf_waveagent_fscombinedsetupflag = -1;
+/* static int hf_waveagent_totalbytes = -1; */
+static int hf_waveagent_payfill = -1;
+static int hf_waveagent_paysize = -1;
+static int hf_waveagent_avgrate = -1;
+static int hf_waveagent_rxflownum = -1;
+static int hf_waveagent_mode = -1;
+static int hf_waveagent_endpointtype = -1;
+static int hf_waveagent_totalframes = -1;
+static int hf_waveagent_bssidstartindex = -1;
+static int hf_waveagent_bssidstopindex = -1;
+static int hf_waveagent_ifindex = -1;
+static int hf_waveagent_iftype = -1;
+static int hf_waveagent_ifdescription = -1;
+static int hf_waveagent_ifmacaddr = -1;
+static int hf_waveagent_iflinkspeed = -1;
+static int hf_waveagent_ifdhcp = -1;
+static int hf_waveagent_ifwlanbssid = -1;
+static int hf_waveagent_ifwlanssid = -1;
+static int hf_waveagent_ifiptype = -1;
+static int hf_waveagent_ifipv4 = -1;
+static int hf_waveagent_ifipv6 = -1;
+static int hf_waveagent_ifdhcpserver = -1;
+static int hf_waveagent_ifgateway = -1;
+static int hf_waveagent_ifdnsserver = -1;
+static int hf_waveagent_ifethl2status = -1;
+static int hf_waveagent_ifwlanl2status = -1;
+static int hf_waveagent_ifl3status = -1;
+static int hf_waveagent_totalbssid = -1;
+static int hf_waveagent_returnedbssid = -1;
+static int hf_waveagent_scanbssid = -1;
+static int hf_waveagent_scanssid = -1;
+static int hf_waveagent_ifwlanrssi = -1;
+static int hf_waveagent_ifwlansupprates = -1;
+static int hf_waveagent_ifwlancapabilities = -1;
+static int hf_waveagent_ifwlanchannel = -1;
+static int hf_waveagent_ifwlanprivacy = -1;
+static int hf_waveagent_ifwlanbssmode = -1;
+static int hf_waveagent_ifwlannoise = -1;
+static int hf_waveagent_ifphytypes = -1;
+static int hf_waveagent_ifphytypebit0 = -1;
+static int hf_waveagent_ifphytypebit1 = -1;
+static int hf_waveagent_ifphytypebit2 = -1;
+static int hf_waveagent_ifphytypebit3 = -1;
+/* static int hf_waveagent_ifphytypebit4 = -1; */
+static int hf_waveagent_ifwlanauthentication = -1;
+static int hf_waveagent_ifwlancipher = -1;
+static int hf_waveagent_delayfactor = -1;
+static int hf_waveagent_medialossrate = -1;
+static int hf_waveagent_txstartts = -1;
+static int hf_waveagent_txendts = -1;
+static int hf_waveagent_rxstartts = -1;
+static int hf_waveagent_rxendts = -1;
+static int hf_waveagent_oidcode = -1;
+static int hf_waveagent_oidvalue = -1;
+static int hf_waveagent_destip = -1;
+static int hf_waveagent_destport = -1;
+static int hf_waveagent_connectflags = -1;
+static int hf_waveagent_connecttype = -1;
+static int hf_waveagent_minrssi = -1;
+static int hf_waveagent_connecttimeout = -1;
+static int hf_waveagent_connectattempts = -1;
+static int hf_waveagent_reason = -1;
+static int hf_waveagent_sigsequencenum = -1;
+static int hf_waveagent_relaydestid = -1;
+static int hf_waveagent_relaysrcid = -1;
+static int hf_waveagent_relaymessagest = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_waveagent = -1;
+static gint ett_statechange = -1;
+static gint ett_phytypes = -1;
+static gint ett_fsflags = -1;
+static gint ett_scindex0 = -1;
+static gint ett_scindex1 = -1;
+static gint ett_scindex2 = -1;
+static gint ett_scindex3 = -1;
+static gint ett_scindex4 = -1;
+static gint ett_scindex5 = -1;
+static gint ett_scindex6 = -1;
+static gint ett_scindex7 = -1;
+static gint ett_bss0 = -1;
+static gint ett_bss1 = -1;
+static gint ett_bss2 = -1;
+static gint ett_bss3 = -1;
+static gint ett_bss4 = -1;
+static gint ett_bss5 = -1;
+static gint ett_bss6 = -1;
+static gint ett_bss7 = -1;
+static gint ett_relaymessage = -1;
+
+static const value_string control_words[] = {
+ { 0x01, "Receive, Count, Discard"},
+ { 0x02, "Receive, Count, Loopback"},
+ { 0x03, "Receive, Count, Push timestamp, Discard"},
+ { 0x04, "Receive, Count, Push timestamp, Loopback"},
+ { 0x08, "Transmit"},
+ { 0x11, "Start Flow"},
+ { 0x12, "Stop Flow"},
+ { 0x20, "Stats Reset"},
+ { 0x21, "Stats Request"},
+ { 0x22, "Flow Stats Reset"},
+ { 0x23, "Scan Results Request"},
+ { 0x24, "Interface Info Request"},
+ { 0x25, "Interface Change Info Request"},
+ { 0x26, "OID Request"},
+ { 0x2e, "Scan Results Response"},
+ { 0x2f, "Stats Response"},
+ { 0x30, "Interface Info Response"},
+ { 0x31, "Interface Change Info Response"},
+ { 0x3e, "Relay Message"},
+ { 0x3f, "Relay Response"},
+ { 0x40, "Client Connect Request"},
+ { 0x41, "Client Disconnect Request"},
+ { 0x32, "OID Response"},
+ { 0x80, "Capabilities Request"},
+ { 0x81, "Capabilities Response"},
+ { 0x82, "Reserve Request"},
+ { 0x84, "Release Request"},
+ { 0x85, "Flow Setup"},
+ { 0x86, "Flow Destroy"},
+ { 0x87, "Flow Connect"},
+ { 0x88, "Flow Disconnect"},
+ { 0x89, "Flow Listen"},
+ { 0x8a, "Scan Request"},
+ { 0x8b, "Learning Message"},
+ { 0x8f, "Command Response"},
+ { 0, NULL},
+};
+
+/* Dissects the WLAN interface stats structure */
+static void dissect_wlan_if_stats(guint32 starting_offset, proto_item *parent_tree, tvbuff_t *tvb)
+{
+ proto_item *phy_types;
+ proto_tree *phy_types_tree;
+ guint32 phy_types_bitfield, noise_floor;
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_ifwlanbssid, tvb, starting_offset, 6, ENC_NA);
+
+ /* two bytes of pad go here */
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_ifwlanssid, tvb, starting_offset + 8, 32, ENC_ASCII|ENC_NA);
+
+ /* 4 byte SSID length field not reported */
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_ifwlanrssi, tvb, starting_offset + 44, 4, ENC_BIG_ENDIAN);
+
+ noise_floor = tvb_get_ntohl(tvb, starting_offset + 48);
+
+ if (noise_floor != 0x7fffffff) {
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_ifwlannoise, tvb, starting_offset + 48, 4, ENC_BIG_ENDIAN);
+ }
+ else {
+ proto_tree_add_int_format(parent_tree,
+ hf_waveagent_ifwlannoise, tvb, starting_offset + 48, 4, noise_floor,
+ "WLAN Interface Noise Floor (dBm): Not Reported");
+ }
+
+ phy_types_bitfield = tvb_get_ntohl(tvb, starting_offset + 52);
+
+ phy_types = proto_tree_add_uint(parent_tree, hf_waveagent_ifphytypes,
+ tvb, starting_offset + 52, 4, phy_types_bitfield);
+
+ phy_types_tree = proto_item_add_subtree(phy_types, ett_phytypes);
+
+ proto_tree_add_item(phy_types_tree,
+ hf_waveagent_ifphytypebit0, tvb, starting_offset + 55, 1, ENC_LITTLE_ENDIAN);
+
+ proto_tree_add_item(phy_types_tree,
+ hf_waveagent_ifphytypebit1, tvb, starting_offset + 55, 1, ENC_LITTLE_ENDIAN);
+
+ proto_tree_add_item(phy_types_tree,
+ hf_waveagent_ifphytypebit2, tvb, starting_offset + 55, 1, ENC_LITTLE_ENDIAN);
+
+ proto_tree_add_item(phy_types_tree,
+ hf_waveagent_ifphytypebit3, tvb, starting_offset + 55, 1, ENC_LITTLE_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_ifwlanauthentication, tvb, starting_offset + 56, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_ifwlancipher, tvb, starting_offset + 60, 4, ENC_BIG_ENDIAN);
+}
+
+static void dissect_wa_payload(guint32 starting_offset, proto_item *parent_tree, tvbuff_t *tvb, guint32 control_word, guint8 version)
+{
+ guint32 if_type, if_status, flags_bitfield;
+ guint8 iLoop, isr, n, ret;
+ guint32 offset, delta, num_bss_entries, st_index[NUM_STATE_CHANGES], bss_array[NUM_BSS];
+ proto_tree *st_change_index_tree[NUM_STATE_CHANGES], *fs_flags;
+ proto_tree *bss_tree[NUM_BSS], *fs_flags_tree;
+ proto_item *stIndex[NUM_STATE_CHANGES], *bssIndex[NUM_BSS];
+ const guint8 *tag_data_ptr;
+ guint32 tag_len;
+ char out_buff[SHORT_STR];
+ char print_buff[SHORT_STR];
+
+ switch (control_word)
+ {
+ case 0x11: /* Flow start message */
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_payfill, tvb, starting_offset, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_paysize, tvb, starting_offset+4, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_avgrate, tvb, starting_offset+8, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_totalframes, tvb, starting_offset+12, 4, ENC_BIG_ENDIAN);
+
+ break;
+
+ case 0x23: /* Scan results request */
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_ifindex, tvb, starting_offset, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_bssidstartindex, tvb, starting_offset+4, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_bssidstopindex, tvb, starting_offset+8, 4, ENC_BIG_ENDIAN);
+
+ break;
+
+ case 0x24: /* Interface info request */
+ case 0x25: /* Interface change info request */
+ case 0x8a: /* Scan request */
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_ifindex, tvb, starting_offset, 4, ENC_BIG_ENDIAN);
+
+ break;
+
+ case 0x26: /* OID request */
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_ifindex, tvb, starting_offset, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_oidcode, tvb, starting_offset+4, 4, ENC_BIG_ENDIAN);
+
+ break;
+
+ case 0x30: /* Interface stats response */
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_ifindex, tvb, starting_offset, 4, ENC_BIG_ENDIAN);
+
+ if_type = tvb_get_ntohl(tvb, starting_offset + 4);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_iftype, tvb, starting_offset + 4, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_ifdhcp, tvb, starting_offset + 8, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_ifmacaddr, tvb, starting_offset + 12, 6, ENC_NA);
+
+ /* 2 bytes of pad go here */
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_iflinkspeed, tvb, starting_offset + 20, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_ifdescription, tvb, starting_offset + 24, 128, ENC_ASCII|ENC_NA);
+
+ /* 4 byte length field goes here - skip it */
+
+ /* two bytes of pad go here */
+
+ /* If we have WLAN interface, then report the following */
+ if (if_type == WLAN_INTERFACE)
+ dissect_wlan_if_stats(starting_offset + 156, parent_tree, tvb);
+
+ /* Next come the BindingAddress fields (for each address):
+ 2 bytes: IP type (v4 or v6)
+ 2 bytes: address length
+ 4 bytes: service number (not used)
+ 16 bytes: IP address */
+
+ /* for the bound IP address, report both IP type and address */
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_ifiptype, tvb, starting_offset + 252, 2, ENC_BIG_ENDIAN);
+
+ if (tvb_get_ntohs(tvb, starting_offset + 252) == IPV4_TYPE) {
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_ifipv4, tvb, starting_offset + 260, 4, ENC_BIG_ENDIAN); /* grab the last 4 bytes of the IP address field */
+ }
+ else {
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_ifipv6, tvb, starting_offset + 260, 16, ENC_NA);
+ }
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_ifdhcpserver, tvb, starting_offset + 284, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_ifgateway, tvb, starting_offset + 308, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_ifdnsserver, tvb, starting_offset + 332, 4, ENC_BIG_ENDIAN);
+
+ break;
+
+ case 0x31: /* Interface change info response */
+ /* Create the array of subtree elements for the state change array */
+ st_index[0] = ett_scindex0;
+ st_index[1] = ett_scindex1;
+ st_index[2] = ett_scindex2;
+ st_index[3] = ett_scindex3;
+ st_index[4] = ett_scindex4;
+ st_index[5] = ett_scindex5;
+ st_index[6] = ett_scindex6;
+ st_index[7] = ett_scindex7;
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_ifindex, tvb, starting_offset, 4, ENC_BIG_ENDIAN);
+
+ if_type = tvb_get_ntohl(tvb, starting_offset + 4);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_iftype, tvb, starting_offset + 4, 4, ENC_BIG_ENDIAN);
+
+ offset = starting_offset + 8;
+ delta = 156;
+
+ for (iLoop = 0; iLoop < NUM_STATE_CHANGES; iLoop++) {
+ int current_offset;
+ current_offset = offset + iLoop * delta;
+
+ /* Check to see if the interface entry is valid */
+ if_status = tvb_get_ntohl(tvb, current_offset);
+ if (if_status == 0) continue; /* No entry at this index, keep going */
+
+ /* Add index specific trees to hide the details */
+ stIndex[iLoop] = proto_tree_add_uint_format_value(parent_tree,
+ hf_waveagent_ifwlanl2status, tvb, current_offset, 4, if_status, "Interface state change %d", iLoop);
+
+ st_change_index_tree[iLoop] = proto_item_add_subtree(stIndex[iLoop], st_index[iLoop]);
+
+ if (if_type == WLAN_INTERFACE) {
+ proto_tree_add_item(st_change_index_tree[iLoop],
+ hf_waveagent_ifwlanl2status, tvb, current_offset, 4, ENC_BIG_ENDIAN);
+ } else {
+ proto_tree_add_item(st_change_index_tree[iLoop],
+ hf_waveagent_ifethl2status, tvb, current_offset, 4, ENC_BIG_ENDIAN);
+ }
+
+ proto_tree_add_item(st_change_index_tree[iLoop],
+ hf_waveagent_ifl3status, tvb, current_offset + 4, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(st_change_index_tree[iLoop],
+ hf_waveagent_iflinkspeed, tvb, current_offset + 8, 4, ENC_BIG_ENDIAN);
+
+ if (if_type == WLAN_INTERFACE) {
+ dissect_wlan_if_stats(current_offset + 12, st_change_index_tree[iLoop], tvb);
+ }
+
+ proto_tree_add_item(st_change_index_tree[iLoop],
+ hf_waveagent_snap, tvb, current_offset + 108, 8, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(st_change_index_tree[iLoop],
+ hf_waveagent_ifiptype, tvb, current_offset + 116, 2, ENC_BIG_ENDIAN);
+
+ if (tvb_get_ntohs(tvb, current_offset + 116) == IPV4_TYPE) {
+ proto_tree_add_item(st_change_index_tree[iLoop],
+ hf_waveagent_ifipv4, tvb, current_offset + 124, 4, ENC_BIG_ENDIAN); /* grab the last 4 bytes of the IP address field */
+ }
+ else {
+ proto_tree_add_item(st_change_index_tree[iLoop],
+ hf_waveagent_ifipv6, tvb, current_offset + 124, 16, ENC_NA);
+ }
+
+ /* 16 bytes of padding */
+ }
+
+ break;
+
+ case 0x32: /* OID response */
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_ifindex, tvb, starting_offset, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_oidcode, tvb, starting_offset + 4, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_oidvalue, tvb, starting_offset + 12, 1024, ENC_ASCII|ENC_NA);
+
+ break;
+
+ case 0x2e: /* scan results response message */
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_ifindex, tvb, starting_offset, 4, ENC_BIG_ENDIAN);
+
+ bss_array[0] = ett_bss0;
+ bss_array[1] = ett_bss1;
+ bss_array[2] = ett_bss2;
+ bss_array[3] = ett_bss3;
+ bss_array[4] = ett_bss4;
+ bss_array[5] = ett_bss5;
+ bss_array[6] = ett_bss6;
+ bss_array[7] = ett_bss7;
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_totalbssid, tvb, starting_offset + 4, 4, ENC_BIG_ENDIAN);
+
+ num_bss_entries = tvb_get_ntohl(tvb, starting_offset + 8);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_returnedbssid, tvb, starting_offset + 8, 4, ENC_BIG_ENDIAN);
+
+ /* Add 4 bytes of pad for the offset */
+
+ offset = starting_offset + 16;
+ delta = 148;
+
+ for (iLoop = 0; iLoop < num_bss_entries; iLoop++)
+ {
+ int current_offset;
+ current_offset = offset + iLoop * delta;
+
+ bssIndex[iLoop] = proto_tree_add_item(parent_tree,
+ hf_waveagent_scanssid, tvb, current_offset, 32, ENC_ASCII|ENC_NA);
+
+ bss_tree[iLoop] = proto_item_add_subtree(bssIndex[iLoop], bss_array[iLoop]);
+
+ tag_len = tvb_get_ntohl(tvb, current_offset + 52);
+
+ if (tag_len > 0) {
+ tag_data_ptr = tvb_get_ptr (tvb, offset + 36, tag_len);
+
+ for (isr = 0, n = 0; isr < tag_len; isr++) {
+ if (tag_data_ptr[isr] == 0xFF){
+ proto_tree_add_string (bss_tree[iLoop], hf_waveagent_ifwlansupprates, tvb, offset + 36 + isr,
+ 1, "BSS requires support for mandatory features of HT PHY (IEEE 802.11 - Clause 20)");
+ } else {
+ ret = g_snprintf (print_buff + n, SHORT_STR - n, "%2.1f%s ",
+ (tag_data_ptr[isr] & 0x7F) * 0.5,
+ (tag_data_ptr[isr] & 0x80) ? "(B)" : "");
+ if (ret >= SHORT_STR - n) {
+ /* ret = <buf_size> or greater. means buffer truncated */
+ break;
+ }
+ n += ret;
+ }
+ }
+
+ g_snprintf (out_buff, SHORT_STR, "%s [Mbit/sec]", print_buff);
+ }
+ else {
+ g_snprintf (out_buff, SHORT_STR, "Not defined");
+ }
+
+ proto_tree_add_string (bss_tree[iLoop], hf_waveagent_ifwlansupprates, tvb, offset + 36,
+ tag_len, out_buff);
+
+ proto_tree_add_item(bss_tree[iLoop],
+ hf_waveagent_scanbssid, tvb, current_offset + 56, 6, ENC_NA);
+
+ proto_tree_add_item(bss_tree[iLoop],
+ hf_waveagent_ifwlancapabilities, tvb, current_offset + 62, 2, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(bss_tree[iLoop],
+ hf_waveagent_ifwlanrssi, tvb, current_offset + 64, 4, ENC_BIG_ENDIAN);
+
+ /* For now this is just a 4 byte pad, so comment it out... */
+ /* proto_tree_add_item(bss_tree[iLoop],
+ hf_waveagent_ifwlansigquality, tvb, current_offset + 68, 4, ENC_BIG_ENDIAN);
+ */
+ proto_tree_add_item(bss_tree[iLoop],
+ hf_waveagent_ifwlanchannel, tvb, current_offset + 72, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(bss_tree[iLoop],
+ hf_waveagent_ifwlanprivacy, tvb, current_offset + 76, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(bss_tree[iLoop],
+ hf_waveagent_ifwlanbssmode, tvb, current_offset + 80, 4, ENC_BIG_ENDIAN);
+ }
+
+ break;
+
+ case 0x2f: /* Stats response message */
+ if (version < 3) {
+ /* For version 2 WA protocol the capability status is not in the header but in the CAP
+ RESPONSE. Need to read it here and then advance the payload offset. This is a
+ packet that had a structure change in the beginning of the packet when moving
+ to v3 */
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_capstatus, tvb, starting_offset, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_protocolversion, tvb, starting_offset, 1, ENC_BIG_ENDIAN);
+
+ starting_offset += 4;
+ }
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_capimpl, tvb, starting_offset, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_state, tvb, starting_offset + 4, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_appstate, tvb, starting_offset + 8, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_rxdatapckts, tvb, starting_offset + 12, 8, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_rxdatabytes, tvb, starting_offset + 20, 8, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_rxpcktrate, tvb, starting_offset + 28, 8, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_rxbyterate, tvb, starting_offset + 36, 8, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_txdatapckts, tvb, starting_offset + 44, 8, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_txdatabytes, tvb, starting_offset + 52, 8, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_txpcktrate, tvb, starting_offset + 60, 8, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_txbyterate, tvb, starting_offset + 68, 8, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_looppckts, tvb, starting_offset + 76, 8, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_loopbytes, tvb, starting_offset + 84, 8, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_rxctlpckts, tvb, starting_offset + 92, 8, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_rxctlbytes, tvb, starting_offset + 100, 8, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_txctlpckts, tvb, starting_offset + 108, 8, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_txctlbytes, tvb, starting_offset + 116, 8, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_unknowncmds, tvb, starting_offset + 124, 8, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_snap, tvb, starting_offset + 132, 8, ENC_BIG_ENDIAN);
+
+ /* proto_tree_add_item(parent_tree,
+ hf_waveagent_tstamp1, tvb, 140, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_tstamp2, tvb, 144, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_tstamp3, tvb, 148, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_tstamp4, tvb, 152, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_tstamp5, tvb, 156, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_tstamp6, tvb, 160, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_tstamp7, tvb, 164, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_tstamp8, tvb, 168, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_minlcldelta, tvb, 172, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_maxlcldelta, tvb, 176, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_avglcldelta, tvb, 180, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_minremdelta, tvb, 184, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_maxremdelta, tvb, 188, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_avgremdelta, tvb, 192, 4, ENC_BIG_ENDIAN);
+ */
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_rx1pl, tvb, starting_offset + 284, 8, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_rx2pl, tvb, starting_offset + 292, 8, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_rx3pl, tvb, starting_offset + 300, 8, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_rx4pl, tvb, starting_offset + 308, 8, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_rx5pl, tvb, starting_offset + 316, 8, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_rxoospkts, tvb, starting_offset + 324, 8, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_jitter, tvb, starting_offset + 356, 8, ENC_BIG_ENDIAN);
+
+ if (version >= 3) {
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_delayfactor, tvb, starting_offset + 364, 8, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_medialossrate, tvb, starting_offset + 372, 8, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_txstartts, tvb, starting_offset + 380, 8, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_txendts, tvb, starting_offset + 388, 8, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_rxstartts, tvb, starting_offset + 396, 8, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_rxendts, tvb, starting_offset + 404, 8, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_latencysum, tvb, starting_offset + 412, 8, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_latencycount, tvb, starting_offset + 420, 8, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_txflowstop, tvb, starting_offset + 428, 8, ENC_BIG_ENDIAN);
+ }
+
+ break;
+
+ case 0x40:
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_ifindex, tvb, starting_offset, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_connectflags, tvb, starting_offset + 4, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_connecttype, tvb, starting_offset + 8, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_scanssid, tvb, starting_offset + 12, 32, ENC_ASCII|ENC_NA);
+
+ num_bss_entries = tvb_get_ntohl(tvb, starting_offset + 142);
+
+ offset = starting_offset + 46;
+ delta = 6;
+ for (iLoop = 0; iLoop < num_bss_entries; iLoop++)
+ {
+ int current_offset;
+ current_offset = offset + iLoop * delta;
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_scanbssid, tvb, current_offset, 6, ENC_NA);
+ }
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_minrssi, tvb, starting_offset + 146, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_connecttimeout, tvb, starting_offset + 150, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_connectattempts, tvb, starting_offset + 154, 4, ENC_BIG_ENDIAN);
+
+ break;
+
+ case 0x41:
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_ifindex, tvb, starting_offset, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_reason, tvb, starting_offset + 4, 4, ENC_BIG_ENDIAN);
+
+ break;
+
+ case 0x81: /* Capabilities response */
+ if (version < 3) {
+ /* For version 2 WA protocol the capability status is not in the header but in the CAP
+ RESPONSE. Need to read it here and then advance the payload offset. This is a
+ packet that had a structure change in the beginning of the packet when moving
+ to v3 */
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_capstatus, tvb, starting_offset, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_protocolversion, tvb, starting_offset, 1, ENC_BIG_ENDIAN);
+
+ starting_offset += 4;
+ }
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_capimpl, tvb, starting_offset, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_id, tvb, starting_offset + 4, 128, ENC_ASCII|ENC_NA);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_bindtag, tvb, starting_offset + 136, 128, ENC_ASCII|ENC_NA);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_version, tvb, starting_offset + 268, 128, ENC_ASCII|ENC_NA);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_brokerip, tvb, starting_offset + 400, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_brokerport, tvb, starting_offset + 404, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_bindlevel, tvb, starting_offset + 408, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_bindport, tvb, starting_offset + 412, 4, ENC_BIG_ENDIAN);
+
+ if (version >= 3) {
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_capabilities2, tvb, starting_offset + 416, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_numinterfaces, tvb, starting_offset + 420, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_ifmask, tvb, starting_offset + 424, 4, ENC_BIG_ENDIAN);
+ }
+
+ break;
+
+ case 0x82: /* Reserve request */
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_bindtag, tvb, starting_offset, 128, ENC_ASCII|ENC_NA);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_brokerip, tvb, starting_offset + 132, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_brokerport, tvb, starting_offset + 136, 4, ENC_BIG_ENDIAN);
+
+ break;
+
+ case 0x85: /* Flow setup */
+ if (version < 3) {
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_rxflownum, tvb, starting_offset, 4, ENC_BIG_ENDIAN);
+ }
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_mode, tvb, starting_offset + 7, 1, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_endpointtype, tvb, starting_offset + 7, 1, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_bindport, tvb, starting_offset + 8, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_bindlevel, tvb, starting_offset + 12, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_remoteport, tvb, starting_offset + 16, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_remoteaddr, tvb, starting_offset + 24, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_dscp, tvb, starting_offset + 40, 4, ENC_BIG_ENDIAN);
+
+ flags_bitfield = tvb_get_ntohl(tvb, starting_offset + 44);
+
+ fs_flags = proto_tree_add_uint(parent_tree, hf_waveagent_fsflags,
+ tvb, starting_offset + 44, 4, flags_bitfield);
+
+ fs_flags_tree = proto_item_add_subtree(fs_flags, ett_fsflags);
+
+ proto_tree_add_item(fs_flags_tree,
+ hf_waveagent_fscbrflag, tvb, starting_offset + 47, 1, ENC_LITTLE_ENDIAN);
+
+ proto_tree_add_item(fs_flags_tree,
+ hf_waveagent_fscombinedsetupflag, tvb, starting_offset + 47, 1, ENC_LITTLE_ENDIAN);
+
+ if (version >= 3) {
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_ifindex, tvb, starting_offset + 48, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_payfill, tvb, starting_offset + 52, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_paysize, tvb, starting_offset + 56, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_avgrate, tvb, starting_offset + 60, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_totalframes, tvb, starting_offset + 64, 4, ENC_BIG_ENDIAN);
+ }
+
+ break;
+
+ case 0x8b:
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_destip, tvb, starting_offset, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_destport, tvb, starting_offset + 4, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_connectflags, tvb, starting_offset + 8, 4, ENC_BIG_ENDIAN);
+
+ break;
+
+ case 0x3f: /* Relay response */
+ case 0x8f: /* Command Response */
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_commandstatus, tvb, starting_offset, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_syserrno, tvb, starting_offset + 4, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_statusstring, tvb, starting_offset + 8, 128, ENC_ASCII|ENC_NA);
+
+ break;
+ }
+}
+
+
+
+static guint32 dissect_wa_header(guint32 starting_offset, proto_item *parent_tree, tvbuff_t *tvb, guint8 version)
+{
+ guint32 wa_payload_offset;
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_controlword, tvb, 30+starting_offset, 2, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_payloadlen, tvb, 20+starting_offset, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_transnum, tvb, 24+starting_offset, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_rtoken, tvb, 32+starting_offset, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_flowid, tvb, 36+starting_offset, 4, ENC_BIG_ENDIAN);
+
+ if (version >= 3) {
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_capstatus, tvb, 40+starting_offset, 4, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_protocolversion, tvb, 40+starting_offset, 1, ENC_BIG_ENDIAN);
+
+ wa_payload_offset = WA_V3_PAYLOAD_OFFSET + starting_offset;
+ }
+ else {
+ wa_payload_offset = WA_V2_PAYLOAD_OFFSET + starting_offset;
+ }
+
+ proto_tree_add_item(parent_tree,
+ hf_waveagent_sigsequencenum, tvb, 4+starting_offset, 1, ENC_BIG_ENDIAN);
+
+ return wa_payload_offset;
+}
+
+/* Code to actually dissect the packets */
+static int dissect_waveagent(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+
+/* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti, *rmi;
+ proto_tree *waveagent_tree, *relay_message_tree, *payload_tree;
+ guint8 signature_start, signature_end;
+ guint8 version;
+ guint32 magic_number;
+ guint32 control_word, paylen;
+ guint32 wa_payload_offset;
+
+/* First, if at all possible, do some heuristics to check if the packet cannot
+ * possibly belong to your protocol. This is especially important for
+ * protocols directly on top of TCP or UDP where port collisions are
+ * common place (e.g., even though your protocol uses a well known port,
+ * someone else may set up, for example, a web server on that port which,
+ * if someone analyzed that web server's traffic in Wireshark, would result
+ * in Wireshark handing an HTTP packet to your dissector). For example:
+ */
+ /* Check that there's enough data */
+ if (tvb_length(tvb) < 52 )
+ return 0;
+
+ signature_start = tvb_get_guint8(tvb, 0);
+ signature_end = tvb_get_guint8(tvb, 15);
+ version = ((tvb_get_ntohl(tvb, 16) & 0xF0000000) >> 28 == 1) ? 3 : 2; /* Mask version bit off */
+ magic_number = tvb_get_ntohl(tvb, 16) & 0x0FFFFFFF; /* Mask magic number off */
+
+ /* Get some values from the packet header, probably using tvb_get_*() */
+ if ( (signature_start != 0xcc && signature_start !=0xdd) ||
+ signature_end != 0xE2 || magic_number != 0x0F87C3A5 )
+ /* This packet does not appear to belong to WaveAgent.
+ * Return 0 to give another dissector a chance to dissect it.
+ */
+ return 0;
+
+/* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "WA");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+
+/* Grab the control word, parse the WaveAgent payload accordingly */
+
+ control_word = tvb_get_ntohl(tvb, 28);
+ paylen = tvb_get_ntohl(tvb, 20);
+
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s (0x%x)",
+ val_to_str_const(control_word, control_words, "Unknown"), control_word);
+
+ if (tree) {
+/* create display subtree for the protocol */
+ ti = proto_tree_add_protocol_format(tree, proto_waveagent, tvb, 0, -1,
+ "WaveAgent, %s (0x%x), Payload Length %u Bytes",
+ val_to_str_const(control_word, control_words, "Unknown"), control_word, paylen);
+
+ waveagent_tree = proto_item_add_subtree(ti, ett_waveagent);
+
+ wa_payload_offset = dissect_wa_header(0, waveagent_tree, tvb, version);
+
+ payload_tree = waveagent_tree;
+
+ /* Need to check for a relay message. If so, parse the extra fields and then parse the WA packet */
+ if (control_word == 0x3e)
+ {
+ proto_tree_add_item(waveagent_tree,
+ hf_waveagent_relaydestid, tvb, wa_payload_offset, 4, ENC_BIG_ENDIAN);
+ proto_tree_add_item(waveagent_tree,
+ hf_waveagent_relaysrcid, tvb, wa_payload_offset+4, 4, ENC_BIG_ENDIAN);
+
+ /* Parse control_word of the relay message */
+ control_word = tvb_get_ntohl(tvb, wa_payload_offset+12+28);
+ rmi = proto_tree_add_none_format(waveagent_tree, hf_waveagent_relaymessagest, tvb, wa_payload_offset+12+28, 0,
+ "Relayed WaveAgent Message, %s (0x%x)",
+ val_to_str_const(control_word, control_words, "Unknown"), control_word);
+
+ relay_message_tree = proto_item_add_subtree(rmi, ett_relaymessage);
+
+ wa_payload_offset = dissect_wa_header(wa_payload_offset+12, relay_message_tree, tvb, version);
+ payload_tree = relay_message_tree;
+ }
+
+ dissect_wa_payload(wa_payload_offset, payload_tree, tvb, control_word, version);
+ }
+
+/* Return the amount of data this dissector was able to dissect */
+ return tvb_length(tvb);
+}
+
+/* Register the protocol with Wireshark */
+
+/* this format is require because a script is used to build the C function
+ that calls all the protocol registration.
+*/
+
+static const value_string status_values[] = {
+ { 0, "OK" },
+ { 1, "In Use" },
+ { 0, NULL }
+};
+
+void proto_register_waveagent(void)
+{
+ static const value_string tcp_states[] = {
+ { 0, "Closed" },
+ { 1, "Listen" },
+ { 2, "SYN Sent" },
+ { 3, "SYN received" },
+ { 4, "Established" },
+ { 5, "FIN Wait 1" },
+ { 6, "FIN Wait 2" },
+ { 7, "Close Wait" },
+ { 8, "Closing" },
+ { 9, "Last ACK" },
+ { 10, "Time Wait" },
+ { 0, NULL },
+ };
+
+ static const value_string app_states[] = {
+ { 0, "IDLE" },
+ { 1, "READY" },
+ { 0, NULL },
+ };
+
+ static const value_string wa_modes[] = {
+ { 0, "In-band" },
+ { 1, "Source" },
+ { 2, "Sink" },
+ { 3, "Loopback" },
+ { 0, NULL },
+ };
+
+ static const value_string wa_endpointtypes[] = {
+ { 0, "Undefined" },
+ { 1, "Server" },
+ { 2, "Client" },
+ { 0, NULL },
+ };
+
+ static const value_string binding_levels[] = {
+ { 0, "WLAN" },
+ { 1, "Ethernet" },
+ { 2, "IP" },
+ { 3, "UDP" },
+ { 4, "TCP" },
+ { 5, "FIN Wait 1" },
+ { 6, "FIN Wait 2" },
+ { 7, "Close Wait" },
+ { 8, "Closing" },
+ { 9, "Last ACK" },
+ { 10, "Time Wait" },
+ { 0, NULL },
+ };
+
+ static const value_string if_types[] = {
+ { ETHERNET_INTERFACE, "Ethernet" },
+ { WLAN_INTERFACE, "WLAN" },
+ { 0, NULL },
+ };
+
+ static const value_string no_yes[] = {
+ { 0, "No" },
+ { 1, "Yes" },
+ { 0, NULL },
+ };
+
+ static const value_string ip_types[] = {
+ { 0, "Unspecified" },
+ { IPV4_TYPE, "IPv4" },
+ { IPV6_TYPE, "IPv6" },
+ { 0, NULL },
+ };
+
+ static const value_string if_l3_states[] = {
+ { 0, "Uninitialized" },
+ { 1, "Disconnected" },
+ { 2, "Connected" },
+ { 3, "Error" },
+ { 0, NULL },
+ };
+
+ static const value_string if_wlan_states[] = {
+ { 0, "Uninitialized" },
+ { 1, "Not ready" },
+ { 2, "Connected" },
+ { 3, "Ad Hoc network formed" },
+ { 4, "Disconnecting" },
+ { 5, "Disconnected" },
+ { 6, "Associating" },
+ { 7, "Discovering" },
+ { 8, "Authenticating" },
+ { 0, NULL },
+ };
+
+ static const value_string if_eth_states[] = {
+ { 0, "Uninitialized" },
+ { 1, "Not Operational" },
+ { 2, "Unreachable" },
+ { 3, "Disconnected" },
+ { 4, "Connecting" },
+ { 5, "Connected" },
+ { 6, "Operational" },
+ { 7, "Error" },
+ { 0, NULL },
+ };
+
+ static const value_string bss_modes[] = {
+ { 0, "Infrastructure" },
+ { 1, "IBSS" },
+ { 2, "Unknown" },
+ { 0, NULL },
+ };
+
+ static const value_string auth_algs[] = {
+ { 0, "Open" },
+ { 1, "Shared Key" },
+ { 2, "WPA" },
+ { 4, "WPA PSK" },
+ { 8, "WPA2" },
+ { 16, "WPA2 PSK" },
+ { 0, NULL },
+ };
+
+ static const value_string cipher_algs[] = {
+ { 0, "None" },
+ { 1, "WEP 40" },
+ { 2, "WEP 104" },
+ { 4, "WEP" },
+ { 8, "TKIP" },
+ { 16, "CCMP" },
+ { 0, NULL },
+ };
+
+ /* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+
+ /* START: General purpose message fields - used in multiple messages */
+ { &hf_waveagent_controlword,
+ { "Control Word", "waveagent.cword",
+ FT_UINT16, BASE_HEX, VALS(control_words), 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_payloadlen,
+ { "Payload Length", "waveagent.paylen",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_transnum,
+ { "Transaction Number", "waveagent.transnum",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_rtoken,
+ { "Reservation Token", "waveagent.rtoken",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_flowid,
+ { "Flow ID", "waveagent.flowid",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_capstatus,
+ { "Capabilities Status", "waveagent.capstatus",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_protocolversion,
+ { "Protocol Version", "waveagent.protocolversion",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_capimpl,
+ { "Capabilities Implementation", "waveagent.capimpl",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_sigsequencenum,
+ { "Signature Sequence Number", "waveagent.sigsequencenum",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_id,
+ { "ID", "waveagent.id",
+ FT_STRING, 0, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_bindtag,
+ { "Binding Tag", "waveagent.bindtag",
+ FT_STRING, 0, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_version,
+ { "Version", "waveagent.version",
+ FT_STRING, 0, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_brokerip,
+ { "Broker IP address", "waveagent.brokerip",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_brokerport,
+ { "Broker Port", "waveagent.brokerport",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_bindlevel,
+ { "Binding Level", "waveagent.bindlevel",
+ FT_UINT32, BASE_DEC, VALS(binding_levels), 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_bindport,
+ { "Binding Port", "waveagent.bindport",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_ifindex,
+ { "Interface Index", "waveagent.ifindex",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+ /* END: General purpose message fields - used in multiple messages */
+
+ /* START: Capabilities response fields (specific to this message, other general fields are also used) */
+ { &hf_waveagent_capabilities2,
+ { "Additional Capabilities", "waveagent.capabilities2",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_numinterfaces,
+ { "Number of WA Interfaces", "waveagent.numinterfaces",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_ifmask,
+ { "Mask of Active Interfaces", "waveagent.ifmask",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ NULL, HFILL } },
+ /* END: Capabilities response fields (specific to this message, other general fields are also used) */
+
+ /* START: Command response message fields */
+ { &hf_waveagent_commandstatus,
+ { "Status of Previous Command", "waveagent.cmdstat",
+ FT_INT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_syserrno,
+ { "System Error Number", "waveagent.syserrno",
+ FT_INT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_statusstring,
+ { "Status Message", "waveagent.statmsg",
+ FT_STRING, 0, NULL, 0x0,
+ NULL, HFILL } },
+ /* END: Command response message fields */
+
+ /* START: Stats response message fields */
+ { &hf_waveagent_rxdatapckts,
+ { "Received Data Packets", "waveagent.rxdpkts",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_rxdatabytes,
+ { "Received Data Bytes", "waveagent.rxdbytes",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_rxpcktrate,
+ { "Received Data Packet Rate (pps)", "waveagent.rxpktrate",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_rxbyterate,
+ { "Received Byte Rate", "waveagent.rxbyterate",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_txdatapckts,
+ { "Transmitted Data Packets", "waveagent.txdpkts",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_txdatabytes,
+ { "Transmitted Data Bytes", "waveagent.txdbytes",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_txpcktrate,
+ { "Transmitted Data Packet Rate (pps)", "waveagent.txpktrate",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_txbyterate,
+ { "Transmitted Byte Rate", "waveagent.txbyterate",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_looppckts,
+ { "Loopback Packets", "waveagent.looppckts",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_loopbytes,
+ { "Loopback Bytes", "waveagent.loopbytes",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_rxctlpckts,
+ { "Received Control Packets", "waveagent.rxctlpkts",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_rxctlbytes,
+ { "Received Control Bytes", "waveagent.rxctlbytes",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_txctlpckts,
+ { "Transmitted Control Packets", "waveagent.txctlpkts",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_txctlbytes,
+ { "Transmitted Control Bytes", "waveagent.txctlbytes",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_unknowncmds,
+ { "Unknown Commands", "waveagent.unkcmds",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_snap,
+ { "Time Snap for Counters", "waveagent.snap",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_appstate,
+ { "TCP State", "waveagent.state",
+ FT_UINT32, BASE_DEC, VALS(tcp_states), 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_state,
+ { "Application State", "waveagent.appstate",
+ FT_UINT32, BASE_DEC, VALS(app_states), 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_rx1pl,
+ { "Instances of single packet loss", "waveagent.rx1pl",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_rx2pl,
+ { "Instances of 2 sequential packets lost", "waveagent.rx2pl",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_rx3pl,
+ { "Instances of 3 sequential packets lost", "waveagent.rx3pl",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_rx4pl,
+ { "Instances of 4 sequential packets lost", "waveagent.rx4pl",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_rx5pl,
+ { "Instances of 5 sequential packets lost", "waveagent.rx5pl",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_rxoospkts,
+ { "Instances of out-of-sequence packets", "waveagent.rxoospkts",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_rxmeanlatency,
+ { "Rx Mean latency", "waveagent.rxmeanlatency",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_rxminlatency,
+ { "Rx Minimum latency", "waveagent.rxminlatency",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_rxmaxlatency,
+ { "Rx Maximum latency", "waveagent.rxmaxlatency",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_jitter,
+ { "Jitter (microseconds)", "waveagent.jitter",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_delayfactor,
+ { "Delay Factor", "waveagent.delayfactor",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_medialossrate,
+ { "Media Loss Rate", "waveagent.medialossrate",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_txstartts,
+ { "Timestamp for first Tx flow packet", "waveagent.txstartts",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_txendts,
+ { "Timestamp for last Tx flow packet", "waveagent.txendts",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_rxstartts,
+ { "Timestamp for first Rx flow packet", "waveagent.rxstartts",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_rxendts,
+ { "Timestamp for last Rx flow packet", "waveagent.rxendts",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_latencysum,
+ { "Sum of latencies across all received packets", "waveagent.latencysum",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_latencycount,
+ { "Count of packets included in the latency sum", "waveagent.latencycount",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_txflowstop,
+ { "Timestamp for Tx flow stop message", "waveagent.txflowstop",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+ /* END Stats response message fields */
+
+ /* START: Flow setup message */
+ { &hf_waveagent_rxflownum,
+ { "Received Flow Number", "waveagent.rxflownum",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_mode,
+ { "WaveAgent Mode", "waveagent.trafficmode",
+ FT_UINT8, BASE_DEC, VALS(wa_modes), 0x03,
+ NULL, HFILL } },
+
+ { &hf_waveagent_endpointtype,
+ { "WaveAgent Endpoint Type", "waveagent.endpointtype",
+ FT_UINT8, BASE_DEC, VALS(wa_endpointtypes), 0x0c,
+ NULL, HFILL } },
+
+ { &hf_waveagent_remoteport,
+ { "Remote port", "waveagent.remoteport",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_remoteaddr,
+ { "Remote address", "waveagent.remoteaddr",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_dscp,
+ { "DSCP Setting", "waveagent.dscp",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_fsflags,
+ { "Flow Setup Flags", "waveagent.fsflags",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_fscbrflag,
+ { "CBR Transmit Mode", "waveagent.fscbrflag",
+ FT_BOOLEAN, 4, NULL, 0x01, NULL, HFILL } },
+
+ { &hf_waveagent_fscombinedsetupflag,
+ { "Setup, Connect/Listen, Start Combined", "waveagent.fscombinedsetupflag",
+ FT_BOOLEAN, 4, NULL, 0x02, NULL, HFILL } },
+
+ /* END: Flow setup message */
+
+ /* START: Flow start message fields */
+ { &hf_waveagent_payfill,
+ { "Payload Fill", "waveagent.payfill",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_paysize,
+ { "WaveAgent Payload Size (bytes)", "waveagent.paysize",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_avgrate,
+ { "Average Rate (header + payload + trailer bytes/s)", "waveagent.avgrate",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_totalframes,
+ { "Total Frames", "waveagent.totalframes",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ /* END: Flow start message fields */
+
+ /* START: Scan results request (0x23) fields */
+ { &hf_waveagent_bssidstartindex,
+ { "Starting Index of BSSID list for reporting", "waveagent.bssidstartindex",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_bssidstopindex,
+ { "Ending Index of BSSID list for reporting", "waveagent.bssidstopindex",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ /* END: Scan results request (0x23) fields */
+
+ /* START: WLAN Interface stats fields */
+ { &hf_waveagent_ifwlanbssid,
+ { "WLAN Interface Connected to BSSID", "waveagent.ifwlanbssid",
+ FT_ETHER, 0, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_ifwlanssid,
+ { "WLAN Interface Connected to SSID", "waveagent.ifwlanssid",
+ FT_STRING, 0, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_ifwlanrssi,
+ { "WLAN Interface RSSI", "waveagent.ifwlanrssi",
+ FT_INT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_ifwlannoise,
+ { "WLAN Interface Noise Floor (dBm)", "waveagent.ifwlannoise",
+ FT_INT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_ifphytypes,
+ { "WLAN Interface Supported PHY Types", "waveagent.ifphytypes",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_ifphytypebit0,
+ { "11b", "waveagent.ifphytypebit0",
+ FT_BOOLEAN, 4, NULL, 0x01, NULL, HFILL } },
+
+ { &hf_waveagent_ifphytypebit1,
+ { "11g", "waveagent.ifphytypebit1",
+ FT_BOOLEAN, 4, NULL, 0x02, NULL, HFILL } },
+
+ { &hf_waveagent_ifphytypebit2,
+ { "11a", "waveagent.ifphytypebit2",
+ FT_BOOLEAN, 4, NULL, 0x04, NULL, HFILL } },
+
+ { &hf_waveagent_ifphytypebit3,
+ { "11n", "waveagent.ifphytypebit3",
+ FT_BOOLEAN, 4, NULL, 0x08, NULL, HFILL } },
+
+ { &hf_waveagent_ifwlanauthentication,
+ { "WLAN Interface Authentication Algorithm", "waveagent.ifwlanauthentication",
+ FT_UINT32, BASE_DEC, VALS(auth_algs), 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_ifwlancipher,
+ { "WLAN Interface Encryption/Cipher Algorithm", "waveagent.ifwlancipher",
+ FT_UINT32, BASE_DEC, VALS(cipher_algs), 0x0,
+ NULL, HFILL } },
+ /* END: WLAN Interface stats fields */
+
+ /* START: Interface stats response (0x2d) fields */
+ { &hf_waveagent_iftype,
+ { "Interface type", "waveagent.iftype",
+ FT_UINT32, BASE_DEC, VALS(if_types), 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_ifdescription,
+ { "Name/Description of the adapter", "waveagent.ifdescription",
+ FT_STRING, 0, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_ifmacaddr,
+ { "Interface MAC Address", "waveagent.ifmacaddr",
+ FT_ETHER, 0, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_iflinkspeed,
+ { "Interface Link Speed (kbps)", "waveagent.iflinkspeed",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_ifdhcp,
+ { "Interface DHCP Enabled", "waveagent.ifdhcp",
+ FT_UINT32, BASE_DEC, VALS(no_yes), 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_ifiptype,
+ { "Interface IP Type", "waveagent.ifiptype",
+ FT_UINT32, BASE_DEC, VALS(ip_types), 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_ifipv4,
+ { "Interface Bound to IP Address", "waveagent.ifipv4",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_ifipv6,
+ { "Interface Bound to IP Address", "waveagent.ifipv6",
+ FT_IPv6, BASE_NONE, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_ifdhcpserver,
+ { "Interface DHCP Server Address", "waveagent.ifdhcpserver",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_ifgateway,
+ { "Interface Gateway", "waveagent.ifgateway",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_ifdnsserver,
+ { "Interface DNS Server Address", "waveagent.ifdnsserver",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_ifethl2status,
+ { "Ethernet L2 Interface Status", "waveagent.ifethl2status",
+ FT_UINT32, BASE_DEC, VALS(if_eth_states), 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_ifwlanl2status,
+ { "WLAN L2 Interface Status", "waveagent.ifwlanl2status",
+ FT_UINT32, BASE_DEC, VALS(if_wlan_states), 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_ifl3status,
+ { "L3 Interface Status", "waveagent.ifl3status",
+ FT_UINT32, BASE_DEC, VALS(if_l3_states), 0x0,
+ NULL, HFILL } },
+
+ /* END: Interface stats response (0x2d) fields */
+
+ /* START: Scan results response (0x2e) fields */
+ { &hf_waveagent_totalbssid,
+ { "Number of Found BSSID", "waveagent.totalbssid",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_returnedbssid,
+ { "Number of BSSID Reported in This Response", "waveagent.returnedbssid",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_scanbssid,
+ { "BSSID", "waveagent.scanbssid",
+ FT_ETHER, 0, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_scanssid,
+ { "SSID", "waveagent.scanssid",
+ FT_STRING, 0, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_ifwlansupprates,
+ { "Supported Rates", "waveagent.ifwlansupportedrates",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_ifwlancapabilities,
+ { "Capabilities field", "waveagent.ifwlancapabilities",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_ifwlanchannel,
+ { "Channel", "waveagent.ifwlanchannel",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_ifwlanprivacy,
+ { "Privacy Enabled", "waveagent.ifwlanprivacy",
+ FT_UINT32, BASE_DEC, VALS(no_yes), 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_ifwlanbssmode,
+ { "BSS Mode", "waveagent.ifwlanbssmode",
+ FT_UINT32, BASE_DEC, VALS(bss_modes), 0x0,
+ NULL, HFILL } },
+ /* END: Scan results response (0x2e) fields */
+
+ /* START: OID fields */
+ { &hf_waveagent_oidcode,
+ { "OID Code", "waveagent.oidcode",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_oidvalue,
+ { "OID Value", "waveagent.oidvalue",
+ FT_STRING, 0, NULL, 0x0,
+ NULL, HFILL } },
+ /* END: OID fields */
+
+ /* START: Learning Message fields */
+ { &hf_waveagent_destip,
+ { "Destination IP", "waveagent.destip",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_destport,
+ { "Destination Port", "waveagent.destport",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_connectflags,
+ { "Connect Flags", "waveagent.connectflags",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ NULL, HFILL } },
+ /* END: Learning Message fields */
+
+ /* START: client connect fields */
+ { &hf_waveagent_connecttype,
+ { "Connect Type", "waveagent.connecttype",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_minrssi,
+ { "Minimum RSSI", "waveagent.minrssi",
+ FT_INT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_connecttimeout,
+ { "Connect timeout (s)", "waveagent.connecttimeout",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_connectattempts,
+ { "Connect attempts", "waveagent.connectattempt",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_reason,
+ { "Reason", "waveagent.reason",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+ /* END: client connect fields */
+
+ /* START: relay server fields */
+ { &hf_waveagent_relaydestid,
+ { "ID of destination client (assigned by relay server)", "waveagent.relaydestid",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_relaysrcid,
+ { "ID of source client (assigned by relay server)", "waveagent.relaysrcid",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL } },
+
+ { &hf_waveagent_relaymessagest,
+ { "Relayed WaveAgent Message", "waveagent.relaymessagest",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "This is a relayed WaveAgent message", HFILL } },
+
+/* END: relay server fields */
+
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_waveagent,
+ &ett_statechange,
+ &ett_phytypes,
+ &ett_fsflags,
+ &ett_scindex0,
+ &ett_scindex1,
+ &ett_scindex2,
+ &ett_scindex3,
+ &ett_scindex4,
+ &ett_scindex5,
+ &ett_scindex6,
+ &ett_scindex7,
+ &ett_bss0,
+ &ett_bss1,
+ &ett_bss2,
+ &ett_bss3,
+ &ett_bss4,
+ &ett_bss5,
+ &ett_bss6,
+ &ett_bss7,
+ &ett_relaymessage,
+ };
+
+/* Register the protocol name and description */
+ proto_waveagent = proto_register_protocol("WaveAgent",
+ "waveagent", "waveagent");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_waveagent, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+
+/* If this dissector uses sub-dissector registration add a registration routine.
+ This exact format is required because a script is used to find these
+ routines and create the code that calls these routines.
+
+ This function is also called by preferences whenever "Apply" is pressed
+ (see prefs_register_protocol above) so it should accommodate being called
+ more than once.
+*/
+
+void proto_reg_handoff_waveagent(void)
+{
+ static gboolean inited = FALSE;
+
+ if (!inited) {
+
+ /* Use new_create_dissector_handle() to indicate that dissect_waveagent()
+ * returns the number of bytes it dissected (or 0 if it thinks the packet
+ * does not belong to WaveAgent).
+ */
+ new_create_dissector_handle(dissect_waveagent,
+ proto_waveagent);
+ heur_dissector_add("udp", dissect_waveagent, proto_waveagent);
+
+ inited = TRUE;
+ }
+}
+
+
diff --git a/wiretap/CMakeLists.txt b/wiretap/CMakeLists.txt
index 16be261a49..c55b092b44 100644
--- a/wiretap/CMakeLists.txt
+++ b/wiretap/CMakeLists.txt
@@ -71,6 +71,7 @@ set(WIRETAP_FILES
toshiba.c
visual.c
vms.c
+ vwr.c
wtap.c
)
diff --git a/wiretap/Makefile.common b/wiretap/Makefile.common
index 702e37b979..1fc6397fd4 100644
--- a/wiretap/Makefile.common
+++ b/wiretap/Makefile.common
@@ -77,6 +77,7 @@ NONGENERATED_C_FILES = \
toshiba.c \
visual.c \
vms.c \
+ vwr.c \
wtap.c
# Header files that are not generated from other files
@@ -131,6 +132,7 @@ NONGENERATED_HEADER_FILES = \
toshiba.h \
visual.h \
vms.h \
+ vwr.h \
wtap.h \
wtap-int.h
diff --git a/wiretap/file_access.c b/wiretap/file_access.c
index 5fb1ae6762..1a903a5d59 100644
--- a/wiretap/file_access.c
+++ b/wiretap/file_access.c
@@ -86,6 +86,7 @@
#include "netscaler.h"
#include "mime_file.h"
#include "ipfix.h"
+#include "vwr.h"
#include "pcap-encap.h"
/* The open_file_* routines should return:
@@ -130,6 +131,7 @@ static wtap_open_routine_t open_routines_base[] = {
pcapng_open,
aethra_open,
btsnoop_open,
+ vwr_open,
packetlogger_open, /* This type does not have a magic number, but its
* files are sometimes grabbed by mpeg_open. */
mpeg_open,
@@ -655,6 +657,14 @@ static const struct file_type_info dump_open_table_base[] = {
/* WTAP_FILE_MPEG_2_TS */
{ "MPEG2 transport stream", "mp2t", "mp2t", "ts;mpg", FALSE, FALSE,
+ NULL, NULL },
+
+ /* WTAP_FILE_VWR_80211 */
+ { "Ixia IxVeriWave .vwr Raw 802.11 Capture", "vwr80211", "*.vwr", ".vwr", FALSE, FALSE,
+ NULL, NULL },
+
+ /* WTAP_FILE_VWR_ETH */
+ { "Ixia IxVeriWave .vwr Raw Ethernet Capture", "vwreth", "*.vwr", ".vwr", FALSE, FALSE,
NULL, NULL }
};
diff --git a/wiretap/vwr.c b/wiretap/vwr.c
new file mode 100644
index 0000000000..5b4117cd76
--- /dev/null
+++ b/wiretap/vwr.c
@@ -0,0 +1,2105 @@
+/* vwr.c
+ * Copyright (c) 2011 by Tom Alexander <talexander@ixiacom.com>
+ *
+ * $Id$
+ *
+ * Wiretap Library
+ * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include "wtap-int.h"
+#include "file_wrappers.h"
+#include "buffer.h"
+#include "vwr.h"
+
+
+/* platform-specific definitions for portability */
+static int find_signature(register guint8*, int, register guint32,
+ register guint8);
+static guint64 get_signature_ts(register guint8*, int);
+
+/* unsigned long long constants */
+# define NS_IN_US G_GINT64_CONSTANT(1000U) /* nanoseconds-to-microseconds */
+# define NS_IN_SEC G_GINT64_CONSTANT(1000000000U) /* nanoseconds-to-seconds */
+# define US_IN_SEC G_GINT64_CONSTANT(1000000U) /* microseconds-to-seconds */
+# define LL_ZERO G_GINT64_CONSTANT(0U) /* zero in unsigned long long */
+
+/* .vwr log file defines */
+#define B_SIZE 32768 /* max var len message = 32 kB */
+#define VT_FRAME 0 /* varlen msg is a frame */
+#define VT_CPMSG 1 /* varlen msg is a CP<->PP msg */
+#define MAX_TRACKED_CLIENTS 1024 /* track 1024 clients */
+#define MAX_TRACKED_FLOWS 65536 /* and 64K flows */
+
+/* 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;
+
+/* 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 */
+ guint8 rate; /* PHY bit rate, 500 kb/s units */
+ gint8 signal; /* RF signal power, +/- dBm */
+ gint8 tx_power; /* transmit power, +/- dBm */
+ guint8 pad;
+ 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;
+
+/* 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;
+
+/* 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))
+
+/*
+ * 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.
+*/
+
+/* 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_40MHZ 0x080 /* 40 Mhz CBW */
+#define RADIOTAP_F_CHAN_SHORTGI 0x100 /* Short guard interval */
+
+
+/* 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 */
+
+/* FPGA-generated frame buffer STATS block offsets and definitions */
+
+/* definitions for v2.2 frames, Ethernet format */
+#define v22_E_STATS_LEN 44 /* length of stats block trailer */
+#define v22_E_VALID_OFF 0 /* bit 6 (0x40) is flow-is-valid flag */
+#define v22_E_MTYPE_OFF 1 /* offset of modulation type */
+#define v22_E_VCID_OFF 2 /* offset of VC ID */
+#define v22_E_FLOWSEQ_OFF 4 /* offset of signature sequence number */
+#define v22_E_FLOWID_OFF 5 /* offset of flow ID */
+#define v22_E_OCTET_OFF 8 /* offset of octets */
+#define v22_E_ERRORS_OFF 10 /* offset of error vector */
+#define v22_E_PATN_OFF 12 /* offset of pattern match vector */
+#define v22_E_L4ID_OFF 12
+#define v22_E_IPLEN_OFF 14
+#define v22_E_FRAME_TYPE_OFF 16 /* offset of frame type, 32 bits */
+#define v22_E_RSSI_OFF 21 /* RSSI (NOTE: invalid for Ethernet) */
+#define v22_E_STARTT_OFF 20 /* offset of start time, 64 bits */
+#define v22_E_ENDT_OFF 28 /* offset of end time, 64 bits */
+#define v22_E_LATVAL_OFF 36 /* offset of latency, 32 bits */
+#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 */
+
+#define v22_E_MT_10_HALF 0 /* 10 Mb/s half-duplex */
+#define v22_E_MT_10_FULL 1 /* 10 Mb/s full-duplex */
+#define v22_E_MT_100_HALF 2 /* 100 Mb/s half-duplex */
+#define v22_E_MT_100_FULL 3 /* 100 Mb/s full-duplex */
+#define v22_E_MT_1G_HALF 4 /* 1 Gb/s half-duplex */
+#define v22_E_MT_1G_FULL 5 /* 1 Gb/s full-duplex */
+
+#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)*/
+#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_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 */
+#define v22_E_IS_QOS 0x80 /* QoS bit in MTYPE field (WLAN only) */
+#define v22_E_IS_VLAN 0x00200000
+
+
+#define v22_E_RX_DECRYPTS 0x0007 /* RX-frame-was-decrypted (UNUSED) */
+#define v22_E_TX_DECRYPTS 0x0007 /* TX-frame-was-decrypted (UNUSED) */
+
+#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 */
+
+/* definitions for v2.2 frames, WLAN format for VW510006 FPGA*/
+#define v22_W_STATS_LEN 64 /* length of stats block trailer */
+#define v22_W_VALID_OFF 0 /* bit 6 (0x40) is flow-is-valid flag */
+#define v22_W_MTYPE_OFF 1 /* offset of modulation type */
+#define v22_W_VCID_OFF 2 /* offset of VC ID */
+#define v22_W_FLOWSEQ_OFF 4 /* offset of signature sequence number */
+#define v22_W_FLOWID_OFF 5 /* offset of flow ID */
+#define v22_W_OCTET_OFF 8 /* offset of octets */
+#define v22_W_ERRORS_OFF 10 /* offset of error vector */
+#define v22_W_PATN_OFF 12
+#define v22_W_L4ID_OFF 12
+#define v22_W_IPLEN_OFF 14
+#define v22_W_FRAME_TYPE_OFF 16 /* offset of frame type, 32 bits */
+#define v22_W_RSSI_OFF 21 /* RSSI (NOTE: RSSI must be negated!) */
+#define v22_W_STARTT_OFF 24 /* offset of start time, 64 bits */
+#define v22_W_ENDT_OFF 32 /* offset of end time, 64 bits */
+#define v22_W_LATVAL_OFF 40 /* offset of latency, 32 bits */
+#define v22_W_INFO_OFF 54 /* offset of INFO field, 16 LSBs */
+#define v22_W_DIFFERENTIATOR_OFF 20 /* offset to determine whether */
+ /* eth/802.11, 32 bits */
+
+#define v22_W_PLCP_LENGTH_OFF 4 /* LENGTH field in the plcp header */
+
+
+#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) */
+
+
+#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 */
+#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
+
+#define v22_W_FC_PROT_BIT 0x40 /* Protected Frame bit in FC1 of frame */
+
+#define v22_W_IS_ETHERNET 0x00100000 /* bits set in frame type if ethernet */
+#define v22_W_IS_80211 0x7F000000 /* bits set in frame type if 802.11 */
+
+/* definitions for VW510021 FPGA, WLAN format */
+/* FORMAT:
+ 16 BYTE header
+ 8 bytes of stat block
+ plcp stuff (11 bytes plcp + 1 byte pad)
+ data
+ 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_STARTT_OFF 0 /* offset of start time, 64 bits */
+#define vVW510021_W_ENDT_OFF 8 /* offset of end time, 64 bits */
+#define vVW510021_W_ERRORS_OFF 16 /* offset of error vector */
+#define vVW510021_W_VALID_OFF 20 /* 2 Bytes with different validity bits */
+#define vVW510021_W_INFO_OFF 22 /* offset of INFO field, 16 LSBs */
+#define vVW510021_W_FRAME_TYPE_OFF 24
+#define vVW510021_W_L4ID_OFF 28
+#define vVW510021_W_IPLEN_OFF 30 /* offset of IP Total Length field */
+#define vVW510021_W_FLOWSEQ_OFF 32 /* offset of signature sequence number */
+#define vVW510021_W_FLOWID_OFF 33 /* offset of flow ID */
+#define vVW510021_W_LATVAL_OFF 36 /* offset of delay/flowtimestamp, 32b */
+#define vVW510021_W_DEBUG_OFF 40 /* offset of debug, 16 bits */
+#define vVW510021_W_FPGA_VERSION_OFF 44 /* offset of fpga version, 16 bits */
+#define vVW510021_W_MATCH_OFF 47 /* offset of pattern match vector */
+
+/* offsets in the header block */
+#define vVW510021_W_HEADER_LEN 16 /* length of FRAME header */
+#define vVW510021_W_RXTX_OFF 0 /* rxtx offset, cmd byte of header */
+#define vVW510021_W_HEADER_VERSION_OFF 9 /* version, 2bytes */
+#define vVW510021_MSG_LENGTH_OFF 10 /* MSG LENGTH, 2bytes */
+#define vVW510021_W_DEVICE_TYPE_OFF 8 /* version, 2bytes */
+
+/* offsets that occurs right after the header */
+#define vVW510021_W_AFTERHEADER_LEN 8 /* length of STATs info directly after header */
+#define vVW510021_W_L1P_1_OFF 0 /* offset of 1st byte of layer one info */
+#define vVW510021_W_L1P_2_OFF 1 /* offset of 2nd byte of layer one info */
+#define vVW510021_W_MTYPE_OFF vVW510021_W_L1P_2_OFF
+#define vVW510021_W_PREAMBLE_OFF vVW510021_W_L1P_1_OFF
+#define vVW510021_W_RSSI_TXPOWER_OFF 2 /* RSSI (NOTE: RSSI must be negated!) */
+#define vVW510021_W_MSDU_LENGTH_OFF 3 /* 7:0 of length, next byte 11:8 in top 4 bits */
+#define vVW510021_W_BVCV_VALID_OFF 4 /* BV,CV Determine validaity of bssid and txpower */
+#define vVW510021_W_VCID_OFF 6 /* offset of VC (client) ID */
+#define vVW510021_W_PLCP_LENGTH_OFF 12 /* LENGTH field in the plcp header */
+
+/* Masks and defines */
+#define vVW510021_W_IS_BV 0x04 /* BV bit in STATS block */
+#define vVW510021_W_IS_CV 0x02 /* BV bit in STATS block */
+#define vVW510021_W_FLOW_VALID 0x8000 /* valid_off flow-is-valid flag (else 0) */
+#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 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_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 */
+
+
+#define vVW510021_W_HEADER_VERSION 0x00
+#define vVW510021_W_DEVICE_TYPE 0x15
+#define vVW510021_W_11n_DEVICE_TYPE 0x20
+#define vVW510021_W_FPGA_VERSION 0x000C
+#define vVW510021_W_11n_FPGA_VERSION 0x000D
+
+/* Error masks */
+#define vVW510021_W_FCS_ERROR 0x10
+#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 */
+
+/* definitions for VW510024 FPGA, wired ethernet format */
+/* FORMAT:
+ 16 BYTE header
+ 52 bytes of stats block trailer
+*/
+/* offsets in the stats block */
+#define vVW510024_E_STATS_LEN 48 /* length of stats block trailer */
+#define vVW510024_E_MSDU_LENGTH_OFF 0 /* MSDU 16 BITS */
+#define vVW510024_E_BMCV_VALID_OFF 2 /* BM,CV Determine validITY */
+#define vVW510024_E_VCID_OFF 2 /* offset of VC (client) ID 13:8, */
+ /* 7:0 IN offset 7*/
+#define vVW510024_E_STARTT_OFF 4 /* offset of start time, 64 bits */
+#define vVW510024_E_ENDT_OFF 12 /* offset of end time, 64 bits */
+#define vVW510024_E_ERRORS_OFF 22 /* offset of error vector */
+#define vVW510024_E_VALID_OFF 24 /* 2 Bytes with different validity bits */
+#define vVW510024_E_INFO_OFF 26 /* offset of INFO field, 16 LSBs */
+#define vVW510024_E_FRAME_TYPE_OFF 28
+#define vVW510024_E_L4ID_OFF 32
+#define vVW510024_E_IPLEN_OFF 34
+#define vVW510024_E_FLOWSEQ_OFF 36 /* offset of signature sequence number */
+#define vVW510024_E_FLOWID_OFF 37 /* offset of flow ID */
+#define vVW510024_E_LATVAL_OFF 40 /* offset of delay/flowtimestamp, 32 bits */
+#define vVW510024_E_FPGA_VERSION_OFF 20 /* offset of fpga version, 16 bits */
+#define vVW510024_E_MATCH_OFF 51 /* offset of pattern match vector */
+
+/* offsets in the header block */
+#define vVW510024_E_HEADER_LEN vVW510021_W_HEADER_LEN /* length of FRAME header */
+#define vVW510024_E_RXTX_OFF vVW510021_W_RXTX_OFF /* rxtx offset, cmd byte */
+#define vVW510024_E_HEADER_VERSION_OFF 16 /* version, 2bytes */
+#define vVW510024_E_MSG_LENGTH_OFF vVW510021_MSG_LENGTH_OFF /* MSG LENGTH, 2bytes */
+#define vVW510024_E_DEVICE_TYPE_OFF vVW510021_W_DEVICE_TYPE_OFF /* Device Type, 2bytes */
+
+/* Masks and defines */
+#define vVW510024_E_IS_BV 0x80 /* Bm bit in STATS block */
+#define vVW510024_E_IS_CV 0x40 /* cV bit in STATS block */
+#define vVW510024_E_FLOW_VALID 0x8000 /* valid_off flow-is-valid flag (else force to 0) */
+#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_IS_TCP 0x01000000 /* TCP bit in FRAME_TYPE field */
+#define vVW510024_E_IS_UDP 0x00100000 /* UDP bit in FRAME_TYPE field */
+#define vVW510024_E_IS_ICMP 0x00001000 /* ICMP bit in FRAME_TYPE field */
+#define vVW510024_E_IS_IGMP 0x00010000
+#define vVW510024_E_IS_VLAN 0x4000
+
+#define vVW510024_E_HEADER_VERSION 0x00
+#define vVW510024_E_DEVICE_TYPE 0x18
+#define vVW510024_E_FPGA_VERSION 0x0001
+
+#define FPGA_VER_NOT_APPLICABLE 0
+
+#define UNKNOWN_FPGA 0
+#define vVW510021_W_FPGA 1
+#define vVW510006_W_FPGA 2
+#define vVW510012_E_FPGA 3
+#define vVW510024_E_FPGA 4
+
+ /*the flow signature is:
+ Byte Description
+0 Magic Number (0xDD)
+1 Chassis Number[7:0]
+2 Slot Number[7:0]
+3 Port Number[7:0]
+4 Flow ID[7:0]
+5 Flow ID[15:8]
+6 Flow ID[23:16]
+7 Flow Sequence Number[7:0]
+8 Timestamp[7:0]
+9 Timestamp[15:8]
+10 Timestamp[23:16]
+11 Timestamp[31:24]
+12 Timestamp[39:32]
+13 Timestamp[47:40]
+14 CRC16
+15 CRC16
+
+*/
+#define SIG_SIZE 16 /* size of signature field, bytes */
+#define SIG_FID_OFF 4 /* offset of flow ID in signature */
+#define SIG_FSQ_OFF 7 /* offset of flow seqnum in signature */
+#define SIG_TS_OFF 8 /* offset of flow seqnum in signature */
+
+
+
+/*--------------------------------------------------------------------------------------*/
+/* various internal variables */
+
+/* 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() */
+static guint32 STATS_LEN; /* length of stats block trailer */
+static guint32 STATS_START_OFF; /* STATS OFF AFTER HEADER */
+static guint32 VALID_OFF; /* bit 6 (0x40) is flow-is-valid flag */
+static guint32 MTYPE_OFF; /* offset of modulation type */
+static guint32 VCID_OFF; /* offset of VC ID */
+static guint32 FLOWSEQ_OFF; /* offset of signature sequence number */
+static guint32 FLOWID_OFF; /* offset of flow ID */
+static guint32 OCTET_OFF; /* offset of octets */
+static guint32 ERRORS_OFF; /* offset of error vector */
+static guint32 PATN_OFF; /* offset of pattern match vector */
+static guint32 RSSI_OFF; /* RSSI (NOTE: RSSI must be negated!) */
+static guint32 STARTT_OFF; /* offset of start time, 64 bits */
+static guint32 ENDT_OFF; /* offset of end time, 64 bits */
+static guint32 LATVAL_OFF; /* offset of latency, 32 bits */
+static guint32 INFO_OFF; /* offset of INFO field, 16 bits */
+static guint32 L1P_1_OFF; /* offset 1ST Byte of l1params */
+static guint32 L1P_2_OFF; /* offset 2nd Byte of l1params */
+static guint32 L4ID_OFF; /* LAYER 4 id offset*/
+static guint32 IPLEN_OFF; /* */
+static guint32 PLCP_LENGTH_OFF; /* plcp length offset*/
+static guint32 FPGA_VERSION_OFF; /* offset of fpga version field, 16 bits */
+static guint32 HEADER_VERSION_OFF; /* offset of header version, 16 bits */
+static guint32 RXTX_OFF; /* offset of CMD bit, rx or tx */
+static guint32 MT_10_HALF; /* 10 Mb/s half-duplex */
+static guint32 MT_10_FULL; /* 10 Mb/s full-duplex */
+static guint32 MT_100_HALF; /* 100 Mb/s half-duplex */
+static guint32 MT_100_FULL; /* 100 Mb/s full-duplex */
+static guint32 MT_1G_HALF; /* 1 Gb/s half-duplex */
+static guint32 MT_1G_FULL; /* 1 Gb/s full-duplex */
+static guint32 FCS_ERROR; /* FCS error in frame */
+static guint32 CRYPTO_ERR; /* RX decrypt error flags */
+static guint32 PAYCHK_ERR; /* payload checksum failure */
+static guint32 RETRY_ERR; /* excessive retries on TX failure */
+static guint32 IS_RX; /* TX/RX bit in STATS block */
+static guint32 MT_MASK; /* modulation type mask */
+static guint32 VCID_MASK; /* VC ID is only 9 bits */
+static guint32 FLOW_VALID; /* flow-is-valid flag (else force to 0) */
+static guint32 RX_DECRYPTS; /* RX-frame-was-decrypted bits */
+static guint32 TX_DECRYPTS; /* TX-frame-was-decrypted bits */
+static guint32 FC_PROT_BIT; /* Protected Frame bit in FC1 of frame */
+static guint32 MT_CCKL; /* CCK modulation, long preamble */
+static guint32 MT_CCKS; /* CCK modulation, short preamble */
+static guint32 MT_OFDM; /* OFDM modulation */
+static guint32 MCS_INDEX_MASK; /* mcs index type mask */
+static guint32 PREAMBLE_MASK; /* preamble type mask */
+static guint32 IS_TX; /* FOR FPGA500021 this is true if tx */
+static guint32 FPGA_VERSION;
+static guint32 HEADER_IS_RX;
+static guint32 HEADER_IS_TX;
+static guint32 WEPTYPE; /* frame is WEP */
+static guint32 TKIPTYPE; /* frame is TKIP */
+static guint32 CCMPTYPE; /* frame is CCMP */
+static guint32 FRAME_TYPE_OFF;
+static guint32 IS_TCP;
+static guint32 IS_UDP;
+static guint32 IS_ICMP;
+static guint32 IS_IGMP;
+static guint32 IS_QOS;
+static guint32 IS_VLAN;
+
+/* internal utility functions */
+static int decode_msg(register guint8 *, int *);
+static guint8 get_ofdm_rate(guint8 *);
+static guint8 get_cck_rate(guint8 *plcp);
+static void setup_defaults(guint16);
+
+static gboolean vwr_read(wtap *, int *, gchar **, gint64 *);
+static gboolean vwr_seek_read(wtap *, gint64, union wtap_pseudo_header *, guchar *,
+ int, int *, gchar **);
+
+static int vwr_read_rec_header(FILE_T, int *, int *, gchar **);
+static void vwr_read_rec_data(wtap *, guint8 *, guint8 *, int);
+
+static guint16 vwr_get_fpga_version(wtap *, int *, gchar **);
+
+
+static void vwr_read_rec_data_vVW510021(wtap *, guint8 *, guint8 *, int);
+static void vwr_read_rec_data_ethernet(wtap *, guint8 *, guint8 *, int);
+
+static int find_signature(register guint8 *, int, register guint32, register guint8);
+static guint64 get_signature_ts(register guint8 *, int);
+
+/* open a .vwr file for reading */
+/* this does very little, except setting the wiretap header for a VWR file type */
+/* and the timestamp precision to microseconds */
+
+int vwr_open(wtap *wth, int *err, gchar **err_info _U_)
+{
+ guint16 fpgaVer;
+
+ *err = 0;
+
+ fpgaVer = vwr_get_fpga_version(wth, err, err_info);
+ if ((*err != 0) || (fpgaVer == UNKNOWN_FPGA))
+ return (-1);
+ FPGA_VERSION = fpgaVer;
+ /* set the local module options first (this is a WLAN capture) */
+ setup_defaults(fpgaVer);
+
+ wth->snapshot_length = 0;
+ wth->subtype_read = vwr_read;
+ wth->subtype_seek_read = vwr_seek_read;
+ wth->tsprecision = WTAP_FILE_TSPREC_USEC;
+
+ if (fpgaVer == vVW510021_W_FPGA) {
+ wth->file_type = WTAP_FILE_VWR_80211;
+ wth->file_encap = WTAP_ENCAP_IXVERIWAVE;
+
+ }
+ else if (fpgaVer == vVW510006_W_FPGA) {
+ wth->file_type = WTAP_FILE_VWR_80211;
+ wth->file_encap = WTAP_ENCAP_IXVERIWAVE;
+
+ }
+ else if (fpgaVer == vVW510012_E_FPGA) {
+ wth->file_type = WTAP_FILE_VWR_ETH;
+ wth->file_encap = WTAP_ENCAP_IXVERIWAVE;
+
+ }
+ else if (fpgaVer == vVW510024_E_FPGA) {
+ wth->file_type = WTAP_FILE_VWR_ETH;
+ wth->file_encap = WTAP_ENCAP_IXVERIWAVE;
+
+ }
+
+ return(1);
+}
+
+
+/* Read the next packet */
+/* note that the VWR file format consists of a sequence of fixed 16-byte record headers of */
+/* different types; some types, including frame record headers, are followed by */
+/* variable-length data */
+/* a frame record consists of: the above 16-byte record header, a 1-16384 byte raw PLCP */
+/* frame, and a 64-byte statistics block trailer */
+/* the PLCP frame consists of a 4-byte or 6-byte PLCP header, followed by the MAC frame */
+
+static gboolean vwr_read(wtap *wth, int *err, gchar **err_info _U_, gint64 *data_offset)
+{
+ int ret;
+ guint8 rec[B_SIZE]; /* local buffer (holds input record) */
+ int rec_size = 0;
+ guint8 *data_ptr;
+ guint16 pkt_len; /* length of radiotap headers */
+
+ /* read the next frame record header in the capture file; if no more frames, return */
+ /* if we found a frame record, set the data_offset value to the start of the frame */
+ /* record (i.e., the record header for the frame) */
+ if ((ret = vwr_read_rec_header(wth->fh, &rec_size, err, err_info)) <= 0) {
+ *err_info = g_strdup_printf("Record not readable or EOF encountered");
+ return(FALSE); /* Read error or EOF */
+ } else
+ wth->data_offset += ret; /* bump offset past header */
+
+ *data_offset = (wth->data_offset - 16); /* set offset for random seek @PLCP */
+
+ /* got a frame record; read over 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, wth->fh) != rec_size) {
+ *err = file_error(wth->fh, err_info);
+ if (*err == 0)
+ *err = WTAP_ERR_SHORT_READ;
+ return(FALSE);
+ }
+ else
+ wth->data_offset += rec_size; /* got it OK, bump to next rec */
+
+
+
+ /* before writing anything out, make sure the buffer has enough space for everything */
+ if ((FPGA_VERSION == vVW510021_W_FPGA) || (FPGA_VERSION == vVW510006_W_FPGA) )
+ /* frames are always 802.11 with an extended radiotap header */
+ pkt_len = rec_size + sizeof(stats_common_fields) + sizeof(ext_rtap_fields);
+ else
+ /* frames are always ethernet with an extended ethernettap header */
+ pkt_len = rec_size + sizeof(stats_common_fields) + sizeof(stats_ethernettap_fields);
+ buffer_assure_space(wth->frame_buffer, pkt_len);
+ data_ptr = buffer_start_ptr(wth->frame_buffer);
+
+ /* now format up the frame data */
+ switch (FPGA_VERSION)
+ {
+ case vVW510006_W_FPGA:
+ vwr_read_rec_data(wth, data_ptr, rec, rec_size);
+ break;
+ case vVW510021_W_FPGA:
+ vwr_read_rec_data_vVW510021(wth, data_ptr, rec, rec_size);
+ break;
+ case vVW510012_E_FPGA:
+ vwr_read_rec_data_ethernet(wth, data_ptr, rec, rec_size);
+ break;
+ case vVW510024_E_FPGA:
+ vwr_read_rec_data_ethernet(wth, data_ptr, rec, rec_size);
+ break;
+ }
+
+ /* If the per-file encapsulation isn't known, set it to this packet's encapsulation */
+ /* If it *is* known, and it isn't this packet's encapsulation, set it to */
+ /* WTAP_ENCAP_PER_PACKET, as this file doesn't have a single encapsulation for all */
+ /* packets in the file */
+ if (wth->file_encap == WTAP_ENCAP_UNKNOWN)
+ wth->file_encap = wth->phdr.pkt_encap;
+ else {
+ if (wth->file_encap != wth->phdr.pkt_encap)
+ wth->file_encap = WTAP_ENCAP_PER_PACKET;
+ }
+
+ return(TRUE);
+}
+
+/* read a random frame in the middle of a file; the start of the PLCP frame is @ seek_off */
+
+static gboolean vwr_seek_read(wtap *wth, gint64 seek_off, union wtap_pseudo_header *pseudo_header _U_, guchar *pd, int pkt_size _U_,
+ int *err, gchar **err_info _U_)
+{
+ guint8 rec[B_SIZE]; /* local buffer (holds input record) */
+ int rec_size;
+
+ /* first seek to the indicated record header */
+ if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
+ return(FALSE);
+
+ /* read in the record header */
+ if (vwr_read_rec_header(wth->random_fh, &rec_size, err, err_info) <= 0)
+ return(FALSE); /* Read error or EOF */
+
+ /* 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, wth->random_fh) != rec_size) {
+ *err = file_error(wth->random_fh, err_info);
+ if (*err == 0)
+ *err = WTAP_ERR_SHORT_READ;
+ return(FALSE);
+ }
+
+ /* now format up the frame data into the passed buffer, according to the FPGA type */
+ switch (FPGA_VERSION) {
+ case vVW510006_W_FPGA:
+ vwr_read_rec_data(wth, pd, rec, rec_size);
+ break;
+ case vVW510021_W_FPGA:
+ vwr_read_rec_data_vVW510021(wth, pd, rec, rec_size);
+ break;
+ case vVW510012_E_FPGA:
+ vwr_read_rec_data_ethernet(wth, pd, rec, rec_size);
+ break;
+ case vVW510024_E_FPGA:
+ vwr_read_rec_data_ethernet(wth, pd, rec, rec_size);
+ break;
+ }
+
+ return(TRUE);
+}
+
+/* scan down in the input capture file to find the next frame header */
+/* decode and skip over all non-frame messages that are in the way */
+/* return the offset into the file for the first byte of the frame (if found); -1 on */
+/* error; zero if EOF with no frame */
+/* also return the frame size in bytes */
+
+static int vwr_read_rec_header(FILE_T fh, int *rec_size, int *err, gchar **err_info)
+{
+ int bytes_read, file_off;
+ int f_len, v_type;
+ guint8 header[16];
+
+ errno = WTAP_ERR_CANT_READ;
+ file_off = 0;
+ *rec_size = 0;
+
+ /* read out the file data in 16-byte messages, stopping either after we find a frame, */
+ /* or if we run out of data */
+ /* 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 (1) {
+ if ((bytes_read = file_read(header, 16, fh)) != 16) {
+ *err = file_error(fh, err_info);
+ if (*err != 0)
+ return(-1);
+ else
+ return(0);
+ }
+ else
+ file_off += bytes_read;
+
+ /* 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(header, &v_type)) != 0) {
+ if (f_len > B_SIZE) {
+ *err = WTAP_ERR_CANT_READ;
+ return(-1);
+ }
+ else if (v_type != VT_FRAME) {
+ if (file_seek(fh, f_len, SEEK_CUR, err) < 0)
+ return(-1);
+ else
+ file_off += f_len;
+ }
+ else {
+ *rec_size = f_len;
+ return(file_off);
+ }
+ }
+ }
+}
+
+/* figure out the FPGA version (and also see whether this is a VWR file type */
+
+static guint16 vwr_get_fpga_version(wtap *wth, int *err, gchar **err_info _U_)
+{
+ guint8 rec[B_SIZE]; /* local buffer (holds input record) */
+ guint8 header[16];
+ int rec_size = 0;
+ guint8 i;
+ guint8 *s_510021_ptr = NULL;
+ guint8 *s_510006_ptr = NULL;
+ guint8 *s_510024_ptr = NULL;
+ guint8 *s_510012_ptr = NULL; /* stats pointers */
+ guint8 device_type,header_version; /* length of radiotap headers */
+ gint64 filePos = -1;
+ guint32 frame_type = 0;
+ int f_len, v_type;
+ gboolean found_frame = FALSE;
+ guint16 data_length = 0;
+ guint16 fpga_version;
+
+ device_type = 0;
+ header_version = 0;
+
+ filePos = file_tell(wth->fh);
+ if (filePos == -1) {
+ *err = WTAP_ERR_SHORT_READ;
+ return(UNKNOWN_FPGA);
+ }
+
+ fpga_version = 1000;
+ /* got a frame record; see if it is vwr */
+ /* if we don't get it all, then declare an error, we can't process the frame */
+ /* read out the file data in 16-byte messages, stopping either after we find a frame, */
+ /* or if we run out of data */
+ /* 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, 16, wth->fh)) == 16) {
+ /* 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(header, &v_type)) != 0) {
+ if (f_len > B_SIZE) {
+ *err = WTAP_ERR_CANT_READ;
+ return(UNKNOWN_FPGA);
+ }
+ else if (v_type != VT_FRAME) {
+ if (file_seek(wth->fh, f_len, SEEK_CUR, err) < 0)
+ return(UNKNOWN_FPGA);
+ }
+ else {
+ rec_size = f_len;
+ found_frame = TRUE;
+ /* got a frame record; read over 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, wth->fh) != rec_size) {
+ *err = file_error(wth->fh, err_info);
+ if (*err == 0)
+ *err = WTAP_ERR_SHORT_READ;
+
+ return(UNKNOWN_FPGA);
+ }
+
+
+ /* I'll grab the bytes where the Ethernet "octets" field should be and the bytes where */
+ /* the 802.11 "octets" field should be. Then if I do rec_size - octets - */
+ /* size_of_stats_block and it's 0, I can select the correct type. */
+ /* octets + stats_len = rec_size only when octets have been incremented to nearest */
+ /* number divisible by 4. */
+
+ /* First check for series I WLAN since the check is more rigorous. */
+ if (rec_size > v22_W_STATS_LEN) {
+ s_510006_ptr = &(rec[rec_size - v22_W_STATS_LEN]); /* point to 510006 WLAN */
+ /* stats block */
+
+ data_length = (s_510006_ptr[v22_W_OCTET_OFF] << 8) + s_510006_ptr[v22_W_OCTET_OFF + 1];
+ i = 0;
+ while (((data_length + i) % 4) != 0)
+ i = i + 1;
+
+ frame_type = (s_510006_ptr[v22_W_FRAME_TYPE_OFF] << 24) | (s_510006_ptr[v22_W_FRAME_TYPE_OFF + 1] << 16) |
+ (s_510006_ptr[v22_W_FRAME_TYPE_OFF + 2] << 8) | (s_510006_ptr[v22_W_FRAME_TYPE_OFF + 3]);
+
+ if (rec_size == (data_length + v22_W_STATS_LEN + i) && (frame_type & v22_W_IS_80211) == 0x1000000) {
+ fpga_version = vVW510006_W_FPGA;
+ }
+ }
+
+ /* Next for the series I Ethernet */
+ if ((rec_size > v22_E_STATS_LEN) && (fpga_version == 1000)) {
+ s_510012_ptr = &(rec[rec_size - v22_E_STATS_LEN]); /* point to 510012 enet */
+ /* stats block */
+ data_length = (s_510012_ptr[v22_E_OCTET_OFF] << 8) + s_510012_ptr[v22_E_OCTET_OFF + 1];
+ i = 0;
+ while (((data_length + i) % 4) != 0)
+ i = i + 1;
+
+ if (rec_size == (data_length + v22_E_STATS_LEN + i))
+ fpga_version = vVW510012_E_FPGA;
+ }
+
+
+ /* Next the series II WLAN */
+ if ((rec_size > vVW510021_W_STATS_LEN) && (fpga_version == 1000)) {
+ s_510021_ptr = &(rec[rec_size - vVW510021_W_STATS_LEN]); /* point to 510021 WLAN */
+ /* stats block */
+
+ 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;
+
+ /*the 12 is from the 12 bytes of plcp header */
+ if (rec_size == (data_length + vVW510021_W_STATS_LEN +vVW510021_W_AFTERHEADER_LEN+12+i))
+ fpga_version = vVW510021_W_FPGA;
+ }
+
+ /* Finally the Series II Ethernet */
+ if ((rec_size > vVW510024_E_STATS_LEN) && (fpga_version == 1000)) {
+ s_510024_ptr = &(rec[rec_size - vVW510024_E_STATS_LEN]); /* point to 510024 ENET */
+ data_length = (s_510024_ptr[vVW510024_E_MSDU_LENGTH_OFF] << 8) + s_510024_ptr[vVW510024_E_MSDU_LENGTH_OFF + 1];
+
+ i = 0;
+ while (((data_length + i) % 4) != 0)
+ i = i + 1;
+
+ if (rec_size == (data_length + vVW510024_E_STATS_LEN + i)) {
+ if (s_510024_ptr != NULL)
+ fpga_version = vVW510024_E_FPGA;
+ }
+ }
+ if (fpga_version != 1000)
+ {
+ /* reset the file position offset */
+ if (file_seek (wth->fh, filePos, SEEK_SET, err) == -1) {
+ *err = WTAP_ERR_SHORT_READ;
+ return (UNKNOWN_FPGA);
+ }
+ /* We found an FPGA that works */
+ return(fpga_version);
+ }
+ }
+ }
+ }
+
+ *err = file_error(wth->fh, err_info);
+ return(UNKNOWN_FPGA);
+}
+
+/* copy the actual packet data from the capture file into the target data block */
+/* the packet is constructed as a 38-byte VeriWave-extended Radiotap header plus the raw */
+/* MAC octets */
+
+static void vwr_read_rec_data(wtap *wth, guint8 *data_ptr, guint8 *rec, int rec_size)
+{
+ int bytes_written = 0; /* bytes output to buf so far */
+ register int i; /* temps */
+ register guint8 *s_ptr, *m_ptr; /* stats and MPDU pointers */
+ gint16 octets, msdu_length; /* octets in frame */
+ guint8 m_type, flow_seq; /* mod type (CCK-L/CCK-S/OFDM), seqnum */
+ 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, e_sec, e_usec = LL_ZERO; /* end time, sec + usec */
+ guint16 info; /* INFO/ERRORS fields in stats blk */
+ gint16 rssi; /* RSSI, signed 16-bit number */
+ int f_tx; /* flag: if set, is a TX frame */
+ int f_flow, f_qos; /* flags: flow valid, frame is QoS */
+ guint32 frame_type; /* frame type field */
+ int rate; /* PHY bit rate in 0.5 Mb/s units */
+ guint16 vc_id, flow_id,ip_len, ht_len=0; /* VC ID, flow ID, total ip length */
+ guint32 d_time, errors; /* packet duration & errors */
+ guint16 r_hdr_len; /* length of radiotap headers */
+ ext_rtap_fields er_fields; /* extended radiotap fields */
+ stats_common_fields common_fields; /* extended radiotap fields */
+ int mac_snap, sig_off, pay_off; /* MAC+SNAP header len, signature offset */
+ guint64 sig_ts; /* 32 LSBs of timestamp in signature */
+ gint32 remaining_length = 0;
+
+ /* 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 - STATS_LEN]); /* point to it */
+ m_type = s_ptr[MTYPE_OFF] & (guint8)MT_MASK;
+ f_tx = !(s_ptr[MTYPE_OFF] & (guint8)IS_RX);
+ octets = (s_ptr[OCTET_OFF] << 8) + s_ptr[OCTET_OFF + 1];
+ vc_id = ((s_ptr[VCID_OFF] << 8) + s_ptr[VCID_OFF + 1]) & (guint8)VCID_MASK;
+ flow_seq = s_ptr[FLOWSEQ_OFF];
+ ip_len = (s_ptr[IPLEN_OFF] << 8) | s_ptr[IPLEN_OFF+1];
+
+ f_flow = (s_ptr[VALID_OFF] & (guint8)FLOW_VALID) != 0;
+ f_qos = (s_ptr[MTYPE_OFF] & (guint8)IS_QOS) != 0;
+ frame_type = (s_ptr[FRAME_TYPE_OFF] << 24) | (s_ptr[FRAME_TYPE_OFF + 1] << 16) |
+ (s_ptr[FRAME_TYPE_OFF + 2] << 8) | (s_ptr[FRAME_TYPE_OFF + 3]);
+
+ latency = (s_ptr[LATVAL_OFF + 6] << 8) | (s_ptr[LATVAL_OFF + 7]); /* latency MSbytes */
+ for (i = 0; i < 4; i++)
+ latency = (latency << 8) | s_ptr[LATVAL_OFF + i];
+
+ flow_id = 0; /* init flow ID to 0 */
+ flow_id = (s_ptr[FLOWID_OFF + 1] << 8) + s_ptr[FLOWID_OFF + 2]; /* only 16 LSBs kept */
+ errors = (s_ptr[ERRORS_OFF] << 8) + s_ptr[ERRORS_OFF + 1];
+
+ info = (s_ptr[INFO_OFF] << 8) + s_ptr[INFO_OFF + 1];
+ rssi = (s_ptr[RSSI_OFF] & 0x80) ? (-1 * (s_ptr[RSSI_OFF] & 0x7f)) : s_ptr[RSSI_OFF];
+ /*if ((info && AGGREGATE_MASK) != 0)*/
+ /* this length includes the Start_Spacing + Delimiter + MPDU + Padding for each piece of the aggregate*/
+ /*ht_len = (int)rec[PLCP_LENGTH_OFF] + ((int)rec[PLCP_LENGTH_OFF+1] << 8);*/
+
+ /* 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 (m_type == MT_OFDM)
+ rate = get_ofdm_rate(rec);
+ else if ((m_type == MT_CCKL) || (m_type == MT_CCKS))
+ rate = get_cck_rate(rec);
+ else
+ rate = 1;
+ /* calculate the MPDU size/ptr stuff; MPDU starts at 4 or 6 depending on OFDM/CCK */
+ /* note that the number of octets in the frame also varies depending on OFDM/CCK, */
+ /* because the PLCP header is prepended to the actual MPDU */
+ m_ptr = &(rec[((m_type == MT_OFDM) ? 4 : 6)]);
+ octets -= (m_type == MT_OFDM) ? 4 : 6;
+
+ /* sanity check the octets field to determine if it is OK (or segfaults result) */
+ /* if it's greater, then truncate to actual record size */
+ remaining_length = rec_size - STATS_LEN;
+
+ if (octets > (rec_size - (int)STATS_LEN))
+ octets = (rec_size - (int)STATS_LEN);
+ msdu_length = octets;
+
+
+ /* calculate start & end times (in sec/usec), converting 64-bit times to usec */
+ for (i = 0; i < 4; i++) /* 64-bit times are "Corey-endian" */
+ s_time = (s_time << 8) | s_ptr[STARTT_OFF + i + 4];
+ for (i = 0; i < 4; i++)
+ s_time = (s_time << 8) | s_ptr[STARTT_OFF + i];
+ for (i = 0; i < 4; i++)
+ e_time = (e_time << 8) | s_ptr[ENDT_OFF + i + 4];
+ for (i = 0; i < 4; i++)
+ e_time = (e_time << 8) | s_ptr[ENDT_OFF + i];
+
+ /* 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 */
+
+ /* also convert the packet start time to seconds and microseconds */
+ start_time = s_time / NS_IN_US; /* convert to microseconds first */
+ s_sec = (start_time / US_IN_SEC); /* get the number of seconds */
+ s_usec = start_time - (s_sec * US_IN_SEC); /* get the number of microseconds */
+
+ /* also convert the packet end time to seconds and microseconds */
+ end_time = e_time / NS_IN_US; /* convert to microseconds first */
+ e_sec = (end_time / US_IN_SEC); /* get the number of seconds */
+ e_usec = end_time - (e_sec * US_IN_SEC); /* get the number of microseconds */
+
+ /* extract the 32 LSBs of the signature timestamp field from the data block*/
+ mac_snap = (f_qos ? 34 : 32); /* 24 (MAC) + 2 (QoS) + 8 (SNAP) */
+
+ if (frame_type & IS_TCP) /* signature offset for TCP frame */
+ {
+ pay_off = mac_snap + 40;
+ }
+ else if (frame_type & IS_UDP) /* signature offset for UDP frame */
+ {
+ pay_off = mac_snap + 28;
+ }
+ else if (frame_type & IS_ICMP) /* signature offset for ICMP frame */
+ {
+ pay_off = mac_snap + 24;
+ }
+ else if (frame_type & IS_IGMP) /* signature offset for IGMPv2 frame */
+ {
+ pay_off = mac_snap + 28;
+ }
+ else /* signature offset for raw IP frame */
+ {
+ pay_off = mac_snap + 20;
+ }
+
+ sig_off = find_signature(m_ptr, pay_off, flow_id, flow_seq);
+ if ((m_ptr[sig_off] == 0xdd) && (sig_off + 15 <= msdu_length) && (f_flow != 0))
+ sig_ts = get_signature_ts(m_ptr, sig_off);
+ else
+ sig_ts = 0;
+
+ /* fill up the per-packet header (amazingly like a PCAP packet header! ;-) */
+ /* frames are always 802.11, with an extended radiotap header */
+ /* caplen is the length that is captured into the file (i.e., the written-out frame */
+ /* block), and should always represent the actual number of bytes in the file */
+ /* len is the length of the original packet before truncation; */
+ /* the FCS is NOT included */
+ r_hdr_len = sizeof(stats_common_fields) + sizeof(er_fields);
+
+ wth->phdr.len = (msdu_length - 4) + r_hdr_len;
+ wth->phdr.caplen = (octets - 4) + r_hdr_len;
+
+ wth->phdr.presence_flags = WTAP_HAS_TS;
+
+ wth->phdr.ts.secs = (time_t)s_sec;
+ wth->phdr.ts.nsecs = (long)(s_usec * 1000);
+ wth->phdr.pkt_encap = WTAP_ENCAP_IXVERIWAVE;
+
+ /* generate and write out the radiotap header, set the version number to 1 (extended) */
+ common_fields.vw_port_type = 0;
+ common_fields.it_len = sizeof(stats_common_fields);
+ er_fields.it_len = sizeof(er_fields);
+
+ /* create the extended radiotap header fields */
+ er_fields.flags = 0;
+ er_fields.flags = (m_type == MT_CCKS) ? RADIOTAP_F_SHORTPRE : 0;
+
+ er_fields.rate = rate;
+ er_fields.chanflags = (m_type == MT_OFDM) ? CHAN_OFDM : CHAN_CCK;
+ er_fields.signal = f_tx ? 100 : (gint8)rssi;
+ er_fields.tx_power = f_tx ? ((gint8)rssi) : 100;
+
+ /* fill in the VeriWave flags field */
+ er_fields.vw_flags = 0;
+ if (f_tx)
+ er_fields.vw_flags |= RADIOTAP_VWF_TXF;
+ if (errors & FCS_ERROR)
+ er_fields.vw_flags |= RADIOTAP_VWF_FCSERR;
+ if (!f_tx && (errors & CRYPTO_ERR))
+ er_fields.vw_flags |= RADIOTAP_VWF_DCRERR;
+ if (!f_tx && (errors & RETRY_ERR))
+ er_fields.vw_flags |= RADIOTAP_VWF_RETRERR;
+ if (info & WEPTYPE)
+ er_fields.vw_flags |= RADIOTAP_VWF_IS_WEP;
+ else if (info & TKIPTYPE)
+ er_fields.vw_flags |= RADIOTAP_VWF_IS_TKIP;
+ else if (info & CCMPTYPE)
+ er_fields.vw_flags |= RADIOTAP_VWF_IS_CCMP;
+
+ er_fields.vw_errors = (guint32)errors;
+ 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;
+ er_fields.vw_info = (guint16)info;
+ common_fields.vw_msdu_length = (guint16)msdu_length;
+ er_fields.vw_ht_length = (guint16)ht_len;
+ 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;
+
+ memcpy(&data_ptr[bytes_written], &common_fields, sizeof(common_fields));
+ bytes_written += sizeof(common_fields);
+
+ memcpy(&data_ptr[bytes_written], &er_fields, sizeof(er_fields));
+ bytes_written += sizeof(er_fields);
+
+ /* finally, dump the whole MAC frame to file as-is; exclude FCS */
+ if ( rec_size < ((int)msdu_length + (int)STATS_LEN) )
+ /*something's been truncated, DUMP AS-IS*/
+ memcpy(&data_ptr[bytes_written], m_ptr, octets);
+ else if (octets >= 4)
+ memcpy(&data_ptr[bytes_written], m_ptr, octets - 4);
+ else
+ memcpy(&data_ptr[bytes_written], m_ptr, octets);
+}
+
+/* Read the next packet for vVW510021 FPGAs */
+/* note that the VWR file format consists of a sequence of fixed 16-byte record headers of */
+/* different types; some types, including frame record headers, are followed by */
+/* variable-length data */
+/* a frame record consists of: the above 16-byte record header, a 1-16384 byte raw PLCP */
+/* frame, and a 56-byte statistics block trailer */
+/* the PLCP frame consists of a 4-byte or 6-byte PLCP header, followed by the MAC frame */
+/* copy the actual packet data from the capture file into the target data block */
+/* the packet is constructed as a 38-byte VeriWave-extended Radiotap header plus the raw */
+/* MAC octets */
+
+static void vwr_read_rec_data_vVW510021(wtap *wth, guint8 *data_ptr, guint8 *rec, int rec_size)
+{
+ int bytes_written = 0; /* bytes output to buf so far */
+ int PLCP_OFF = 8;
+ register int i; /* temps */
+ register guint8 *s_start_ptr,*s_trail_ptr, *m_ptr,*plcp_ptr; /* stats & MPDU ptr */
+ gint16 msdu_length, plcp_offset, actual_octets; /* octets in frame */
+ guint8 l1p_1,l1p_2,sel_type, flow_seq, plcp_type, mcs_index; /* mod (CCK-L/CCK-S/OFDM) */
+ guint64 s_time = LL_ZERO, e_time = LL_ZERO; /* start/end */
+ /* times, nsec */
+ guint64 latency = LL_ZERO;
+ guint64 start_time, s_sec, s_usec = LL_ZERO; /* start time, sec + usec */
+ guint64 end_time, e_sec, e_usec = LL_ZERO; /* end time, sec + usec */
+ guint16 info, fpga_version, validityBits; /* INFO/ERRORS fields in stats blk */
+ guint32 errors = 0;
+ gint16 rssi; /* RSSI, signed 16-bit number */
+ int f_tx; /* flag: if set, is a TX frame */
+ int f_flow, f_qos; /* flags: flow valid, frame is QoS */
+ guint32 frame_type; /* frame type field */
+ guint8 rate; /* PHY bit rate in 0.5 Mb/s units */
+ guint16 vc_id, ip_len, 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 */
+ ext_rtap_fields er_fields; /* extended radiotap fields */
+ stats_common_fields common_fields; /* extended radiotap fields */
+ gint8 tx_power = 0; /* transmit power value in dBm */
+ int mac_snap, 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 */
+ guint64 delta_b; /* Used for calculating latency */
+
+ /* calculate the start of the statistics block in the buffer */
+ /* also get a bunch of fields from the stats block */
+ s_start_ptr = &(rec[0]);
+ s_trail_ptr = &(rec[rec_size - STATS_LEN]); /* point to it */
+
+ l1p_1 = s_start_ptr[L1P_1_OFF];
+ sel_type = l1p_1 & (guint8)vVW510021_W_SEL_MASK;
+ mcs_index = l1p_1 & (guint8)vVW510021_W_MCS_MASK;
+ l1p_2 = s_start_ptr[L1P_2_OFF];
+ plcp_type = l1p_2 & (guint8)vVW510021_W_PLCPC_MASK;
+ msdu_length = (256 * (s_start_ptr[OCTET_OFF + 1] & 0x1f)) + s_start_ptr[OCTET_OFF];
+ /* If the packet has an MSDU length of 0, then bail - malformed packet */
+ /* if (msdu_length < 4) return; */
+ actual_octets = msdu_length;
+
+
+ f_tx = IS_TX;
+ vc_id = ((s_start_ptr[VCID_OFF] << 8) | (s_start_ptr[VCID_OFF + 1]));
+ flow_seq = s_trail_ptr[FLOWSEQ_OFF];
+ fpga_version = (s_trail_ptr[FPGA_VERSION_OFF] << 8) + s_trail_ptr[FPGA_VERSION_OFF + 1];
+ validityBits = (s_trail_ptr[VALID_OFF] << 8) + s_trail_ptr[VALID_OFF + 1];
+
+ f_flow = (validityBits & FLOW_VALID) != 0;
+ f_qos = (validityBits & IS_QOS) != 0;
+
+ frame_type = (s_trail_ptr[FRAME_TYPE_OFF] << 24) | (s_trail_ptr[FRAME_TYPE_OFF + 1] << 16) |
+ (s_trail_ptr[FRAME_TYPE_OFF + 2] << 8) | (s_trail_ptr[FRAME_TYPE_OFF + 3]);
+
+ flow_id = 0x00000000; latency = 0x00000000; /* clear flow ID & latency */
+ flow_id = (s_trail_ptr[FLOWID_OFF] << 16) | (s_trail_ptr[FLOWID_OFF + 1] << 8) |
+ s_trail_ptr[FLOWID_OFF + 2]; /* all 24 bits valid */
+ ip_len = (s_trail_ptr[IPLEN_OFF] << 8) | s_trail_ptr[IPLEN_OFF+1];
+ /* for tx latency is duration, for rx latency is timestamp */
+ /* get 48-bit latency value */
+ tsid = (s_trail_ptr[LATVAL_OFF + 6] << 8) | (s_trail_ptr[LATVAL_OFF + 7]);
+
+ for (i = 0; i < 4; i++)
+ tsid = (tsid << 8) | s_trail_ptr[LATVAL_OFF + i];
+
+ for (i = 0; i < 4; i++)
+ errors = (errors << 8) | s_trail_ptr[ERRORS_OFF + i];
+ info = (s_trail_ptr[INFO_OFF] << 8) + s_trail_ptr[INFO_OFF + 1];
+ if ((info && 0xFC00) != 0)
+ /* this length includes the Start_Spacing + Delimiter + MPDU + Padding for each piece of the aggregate*/
+ ht_len = s_start_ptr[PLCP_LENGTH_OFF] + (s_start_ptr[PLCP_LENGTH_OFF+1] << 8);
+
+ rssi = s_start_ptr[RSSI_OFF];
+ if (f_tx) {
+ if (rssi & 0x80)
+ tx_power = -1 * (rssi & 0x7f);
+ else
+ tx_power = rssi & 0x7f;
+ } else {
+ if (rssi > 128) rssi = rssi - 256; /* Signed 2's complement */
+ }
+
+ /* 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 */
+ plcp_ptr = &(rec[PLCP_OFF]);
+ if (plcp_type == vVW510021_W_PLCP_LEGACY){
+ if (mcs_index < 4) {
+ rate = get_cck_rate(plcp_ptr);
+ chanflags |= CHAN_CCK;
+ }
+ else {
+ rate = get_ofdm_rate(plcp_ptr);
+ chanflags |= CHAN_OFDM;
+ }
+ }
+ else if (plcp_type == vVW510021_W_PLCP_MIXED) {
+ /* pack the rate field with mcs index and gi */
+ rate = (plcp_ptr[3] & 0x7f) + (plcp_ptr[6] & 0x80);
+ /* set the appropriate flags to indicate HT mode and CB */
+ radioflags |= RADIOTAP_F_CHAN_HT | ((plcp_ptr[3] & 0x80) ? RADIOTAP_F_CHAN_40MHZ : 0) |
+ ((plcp_ptr[6] & 0x80) ? RADIOTAP_F_CHAN_SHORTGI : 0);
+ chanflags |= CHAN_OFDM;
+ }
+ else if (plcp_type == vVW510021_W_PLCP_GREENFIELD) {
+ /* pack the rate field with mcs index and gi */
+ rate = (plcp_ptr[0] & 0x7f) + (plcp_ptr[3] & 0x80);
+ /* set the appropriate flags to indicate HT mode and CB */
+ radioflags |= RADIOTAP_F_CHAN_HT | ((plcp_ptr[0] & 0x80) ? RADIOTAP_F_CHAN_40MHZ : 0) |
+ ((plcp_ptr[3] & 0x80) ? RADIOTAP_F_CHAN_SHORTGI : 0);
+ chanflags |= CHAN_OFDM;
+ }
+ else {
+ rate = 1;
+ plcp_offset = 6;
+ }
+
+ /* 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*/
+ m_ptr = &(rec[8+12]);
+
+ /* 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 */
+ /*changed the comparison
+ if (msdu_length > (rec_size )) {
+ msdu_length = (rec_size );
+ }
+*/
+ if (msdu_length > (rec_size - (int)STATS_LEN)) {
+ msdu_length = (rec_size - (int)STATS_LEN);
+ }
+
+ /* calculate start & end times (in sec/usec), converting 64-bit times to usec */
+ for (i = 0; i < 4; i++) /* 64-bit times are "Corey-endian" */
+ s_time = (s_time << 8) | s_trail_ptr[STARTT_OFF + i + 4];
+ for (i = 0; i < 4; i++)
+ s_time = (s_time << 8) | s_trail_ptr[STARTT_OFF + i];
+ for (i = 0; i < 4; i++)
+ e_time = (e_time << 8) | s_trail_ptr[ENDT_OFF + i + 4];
+ for (i = 0; i < 4; i++)
+ e_time = (e_time << 8) | s_trail_ptr[ENDT_OFF + i];
+
+ /* 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 */
+
+ /* also convert the packet start time to seconds and microseconds */
+ start_time = s_time / NS_IN_US; /* convert to microseconds first */
+ s_sec = (start_time / US_IN_SEC); /* get the number of seconds */
+ s_usec = start_time - (s_sec * US_IN_SEC); /* get the number of microseconds */
+
+ /* also convert the packet end time to seconds and microseconds */
+ end_time = e_time / NS_IN_US; /* convert to microseconds first */
+ e_sec = (end_time / US_IN_SEC); /* get the number of seconds */
+ e_usec = end_time - (e_sec * US_IN_SEC); /* get the number of microseconds */
+
+ /* extract the 32 LSBs of the signature timestamp field */
+ mac_snap = (f_qos ? 34 : 32); /* 24 (MAC) + 2 (QoS) + 8 (SNAP) */
+
+ if (frame_type & IS_TCP) /* signature offset for TCP frame */
+ {
+ pay_off = mac_snap + 40;
+ }
+ else if (frame_type & IS_UDP) /* signature offset for UDP frame */
+ {
+ pay_off = mac_snap + 28;
+ }
+ else if (frame_type & IS_ICMP) /* signature offset for ICMP frame */
+ {
+ pay_off = mac_snap + 24;
+ }
+ else if (frame_type & IS_IGMP) /* signature offset for IGMPv2 frame */
+ {
+ pay_off = mac_snap + 28;
+ }
+ else /* signature offset for raw IP frame */
+ {
+ pay_off = mac_snap + 20;
+ }
+
+ sig_off = find_signature(m_ptr, pay_off, flow_id, flow_seq);
+ if ((m_ptr[sig_off] == 0xdd) && (sig_off + 15 <= msdu_length) && (f_flow != 0))
+ sig_ts = get_signature_ts(m_ptr, sig_off);
+ else
+ sig_ts = 0;
+
+ /* Set latency based on rx/tx and signature timestamp */
+
+ /* Set latency based on rx/tx and signature timestamp */
+ if (!IS_TX) {
+ if (tsid < s_time) {
+ latency = s_time - tsid;
+ } else {
+ /* Account for the rollover case. Since we cannot use 0x100000000 - l_time + s_time */
+ /* we look for a large difference between l_time and s_time. */
+ delta_b = tsid - s_time;
+ if (delta_b > 0x10000000)
+ latency = 0;
+ else
+ latency = delta_b;
+ }
+ }
+
+ /* 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 = sizeof(common_fields) + sizeof(er_fields);
+ wth->phdr.len = (actual_octets - 4) + r_hdr_len;
+ wth->phdr.caplen = (msdu_length - 4) + r_hdr_len;
+
+ wth->phdr.presence_flags = WTAP_HAS_TS;
+
+ wth->phdr.ts.secs = (time_t)s_sec;
+ wth->phdr.ts.nsecs = (long)(s_usec * 1000);
+ wth->phdr.pkt_encap = WTAP_ENCAP_IXVERIWAVE;
+
+ /* generate and write out the radiotap header, set the version number to 1 (extended) */
+ common_fields.vw_port_type = 0;
+ common_fields.it_len = sizeof(stats_common_fields);
+ er_fields.it_len = sizeof(er_fields);
+
+ /* create the extended radiotap header fields */
+ er_fields.flags = radioflags;
+ if (info & (guint16)vVW510021_W_IS_WEP)
+ er_fields.flags |= RADIOTAP_F_WEP;
+ if ((l1p_1 & (guint8)PREAMBLE_MASK) != vVW510021_W_IS_LONGPREAMBLE)
+ er_fields.flags |= RADIOTAP_F_SHORTPRE;
+
+ er_fields.rate = rate;
+ er_fields.chanflags = chanflags;
+
+ if (f_tx) {
+ er_fields.tx_power = (gint8)tx_power;
+ er_fields.signal = 100;
+ }
+ else {
+ er_fields.tx_power = 100;
+ er_fields.signal = (gint8)rssi;
+ }
+
+ /* fill in the VeriWave flags field */
+ er_fields.vw_flags = 0;
+ if (f_tx)
+ er_fields.vw_flags |= RADIOTAP_VWF_TXF;
+ if (errors & FCS_ERROR)
+ er_fields.vw_flags |= RADIOTAP_VWF_FCSERR;
+ if (!f_tx && (errors & CRYPTO_ERR))
+ er_fields.vw_flags |= RADIOTAP_VWF_DCRERR;
+ if (!f_tx && (errors & RETRY_ERR))
+ er_fields.vw_flags |= RADIOTAP_VWF_RETRERR;
+ if (info & WEPTYPE)
+ er_fields.vw_flags |= RADIOTAP_VWF_IS_WEP;
+ else if (info & TKIPTYPE)
+ er_fields.vw_flags |= RADIOTAP_VWF_IS_TKIP;
+ else if (info & CCMPTYPE)
+ er_fields.vw_flags |= RADIOTAP_VWF_IS_CCMP;
+
+ er_fields.vw_errors = (guint32)errors;
+ common_fields.vw_vcid = (guint16)vc_id;
+
+ common_fields.vw_msdu_length = (guint16)msdu_length;
+ er_fields.vw_ht_length = (guint16)ht_len;
+
+ 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;
+ er_fields.vw_info = (guint16)info;
+ /*
+ er_fields.vw_startt = s_time;
+ er_fields.vw_endt = e_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 */
+
+ memcpy(&data_ptr[bytes_written], &common_fields, sizeof(common_fields));
+ bytes_written += sizeof(common_fields);
+
+ memcpy(&data_ptr[bytes_written], &er_fields, sizeof(er_fields));
+ bytes_written += sizeof(er_fields);
+
+ /* finally, dump the whole MAC frame to file as-is; exclude 4-byte FCS */
+ if ( rec_size < ((int)actual_octets + (int)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);
+}
+
+/* read an Ethernet packet */
+/* copy the actual packet data from the capture file into the target data block */
+/* the packet is constructed as a 38-byte VeriWave-extended Radiotap header plus the raw */
+/* MAC octets */
+
+static void vwr_read_rec_data_ethernet(wtap *wth, guint8 *data_ptr, guint8 *rec, int rec_size)
+{
+ int bytes_written = 0; /* bytes output to buf so far */
+ register int i; /* temps */
+ register guint8 *s_ptr, *m_ptr; /* stats and MPDU pointers */
+ gint16 msdu_length,actual_octets; /* octets in frame */
+ guint8 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, e_sec, e_usec = LL_ZERO; /* end time, sec + usec */
+ guint16 l4id, info, fpga_version, validityBits; /* INFO/ERRORS fields in stats */
+ guint32 errors;
+ guint16 vc_id, ip_len; /* VC ID, total (incl of aggregates) ip length */
+ guint32 flow_id, d_time; /* packet duration */
+ int f_flow; /* flags: flow valid */
+ guint32 frame_type; /* frame type field */
+ stats_ethernettap_fields etap_hdr; /* VWR ethernettap header */
+ stats_common_fields common_hdr; /* VWR common header */
+ 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 */
+ guint64 delta_b; /* Used for calculating latency */
+
+ flow_id = 0x00000000; /* initialize flow ID to 0 */
+
+ /* calculate the start of the statistics block in the buffer */
+ /* also get a bunch of fields from the stats block */
+ m_ptr = &(rec[0]); /* point to the data block */
+ s_ptr = &(rec[rec_size - STATS_LEN]); /* point to the stats block */
+
+ msdu_length = (s_ptr[OCTET_OFF] << 8) + s_ptr[OCTET_OFF + 1];
+ 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)STATS_LEN)) {
+ msdu_length = (rec_size - (int)STATS_LEN);
+ }
+
+ vc_id = (((s_ptr[VCID_OFF] << 8) | (s_ptr[VCID_OFF + 1]))) & VCID_MASK;
+ flow_seq = s_ptr[FLOWSEQ_OFF];
+ frame_type = (s_ptr[FRAME_TYPE_OFF] << 24) | (s_ptr[FRAME_TYPE_OFF + 1] << 16) |
+ (s_ptr[FRAME_TYPE_OFF + 2] << 8) | (s_ptr[FRAME_TYPE_OFF + 3]);
+
+ if (FPGA_VERSION == vVW510024_E_FPGA) {
+ fpga_version = (s_ptr[FPGA_VERSION_OFF] << 8) + s_ptr[FPGA_VERSION_OFF + 1];
+ validityBits = (s_ptr[VALID_OFF] << 8) + s_ptr[VALID_OFF + 1];
+ f_flow = validityBits & FLOW_VALID;
+
+ mac_len = (validityBits & IS_VLAN) ? 16 : 14; /* MAC hdr length based on VLAN tag */
+
+
+ errors = (s_ptr[ERRORS_OFF] << 8) + s_ptr[ERRORS_OFF + 1];
+ }
+ else {
+ fpga_version = 0;
+
+ validityBits = 0;
+ f_flow = s_ptr[VALID_OFF] & FLOW_VALID;
+ mac_len = (frame_type & IS_VLAN) ? 16 : 14; /* MAC hdr length based on VLAN tag */
+
+
+ /*for older fpga errors is only represented by 16 bits)*/
+ errors = (s_ptr[ERRORS_OFF] << 8) + s_ptr[ERRORS_OFF + 1];
+ }
+
+ info = (s_ptr[INFO_OFF] << 8) + s_ptr[INFO_OFF + 1];
+ ip_len = (s_ptr[IPLEN_OFF] << 8) | s_ptr[IPLEN_OFF+1];
+ /* 24 LSBs */
+ flow_id = (s_ptr[FLOWID_OFF] << 16) | (s_ptr[FLOWID_OFF + 1] << 8) |
+ s_ptr[FLOWID_OFF + 2];
+
+ /* for tx latency is duration, for rx latency is timestamp */
+ /* get 64-bit latency value */
+ tsid = (s_ptr[LATVAL_OFF + 6] << 8) | (s_ptr[LATVAL_OFF + 7]);
+ for (i = 0; i < 4; i++)
+ tsid = (tsid << 8) | s_ptr[LATVAL_OFF + i];
+
+
+ l4id = (s_ptr[L4ID_OFF] << 8) + s_ptr[L4ID_OFF + 1];
+
+ /* calculate start & end times (in sec/usec), converting 64-bit times to usec */
+ for (i = 0; i < 4; i++) /* 64-bit times are "Corey-endian" */
+ s_time = (s_time << 8) | s_ptr[STARTT_OFF + i + 4];
+ for (i = 0; i < 4; i++)
+ s_time = (s_time << 8) | s_ptr[STARTT_OFF + i];
+ for (i = 0; i < 4; i++)
+ e_time = (e_time << 8) | s_ptr[ENDT_OFF + i + 4];
+ for (i = 0; i < 4; i++)
+ e_time = (e_time << 8) | s_ptr[ENDT_OFF + i];
+
+ /* find the packet duration (difference between start and end times) */
+ d_time = (guint32)((e_time - s_time)); /* find diff, leaving in nsec for Ethernet */
+
+ /* also convert the packet start time to seconds and microseconds */
+ start_time = s_time / NS_IN_US; /* convert to microseconds first */
+ s_sec = (start_time / US_IN_SEC); /* get the number of seconds */
+ s_usec = start_time - (s_sec * US_IN_SEC); /* get the number of microseconds */
+
+ /* also convert the packet end time to seconds and microseconds */
+ end_time = e_time / NS_IN_US; /* convert to microseconds first */
+ e_sec = (end_time / US_IN_SEC); /* get the number of seconds */
+ e_usec = end_time - (e_sec * US_IN_SEC); /* get the number of microseconds */
+
+ if (frame_type & IS_TCP) /* signature offset for TCP frame */
+ {
+ pay_off = mac_len + 40;
+ }
+ else if (frame_type & IS_UDP) /* signature offset for UDP frame */
+ {
+ pay_off = mac_len + 28;
+ }
+ else if (frame_type & IS_ICMP) /* signature offset for ICMP frame */
+ {
+ pay_off = mac_len + 24;
+ }
+ else if (frame_type & IS_IGMP) /* signature offset for IGMPv2 frame */
+ {
+ pay_off = mac_len + 28;
+ }
+ else /* signature offset for raw IP frame */
+ {
+ pay_off = mac_len + 20;
+ }
+
+ sig_off = find_signature(m_ptr, pay_off, flow_id, flow_seq);
+ if ((m_ptr[sig_off] == 0xdd) && (sig_off + 15 <= msdu_length) && (f_flow != 0))
+ sig_ts = get_signature_ts(m_ptr, sig_off);
+ else
+ sig_ts = 0;
+
+ /* Set latency based on rx/tx and signature timestamp */
+ if (!IS_TX) {
+ if (sig_ts < s_time) {
+ latency = (guint32)(s_time - sig_ts);
+ } else {
+ /* Account for the rollover case. Since we cannot use 0x100000000 - l_time + s_time */
+ /* we look for a large difference between l_time and s_time. */
+ delta_b = sig_ts - s_time;
+ if (delta_b > 0x10000000) {
+
+ latency = 0;
+
+ } else
+ 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 = sizeof(common_hdr) + sizeof(etap_hdr);
+ wth->phdr.len = (actual_octets - 4) + e_hdr_len;
+ wth->phdr.caplen = (msdu_length - 4) + e_hdr_len;
+
+ wth->phdr.presence_flags = WTAP_HAS_TS;
+
+ wth->phdr.ts.secs = (time_t)s_sec;
+ wth->phdr.ts.nsecs = (long)(s_usec * 1000);
+ wth->phdr.pkt_encap = WTAP_ENCAP_IXVERIWAVE;
+
+ /* generate and write out the ETHERNETTAP header, set the version number to 1 */
+ common_hdr.vw_port_type = 1;
+ common_hdr.it_len = sizeof(common_hdr);
+ etap_hdr.it_len = sizeof(etap_hdr);
+
+ 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;
+
+ 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 & 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;
+
+ memcpy(&data_ptr[bytes_written], &common_hdr, sizeof(common_hdr));
+ bytes_written += sizeof(common_hdr);
+ memcpy(&data_ptr[bytes_written], &etap_hdr, sizeof(etap_hdr));
+ bytes_written += sizeof(etap_hdr);
+
+ /* finally, dump the whole MAC frame to file as-is; ALWAYS exclude 4-byte FCS */
+ if ( rec_size < ((int)actual_octets + (int)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);
+}
+
+/*--------------------------------------------------------------------------------------*/
+/* utility to split up and decode a 16-byte message record */
+
+static int decode_msg(guint8 *rec, int *v_type)
+{
+ guint8 cmd; /* components of message */
+ guint32 wd2, wd3;
+ int v_size = 0; /* size of var-len message */
+ /* assume it's zero */
+
+ /* break up the message record into its pieces */
+ cmd = rec[0];
+ wd2 = ((guint32)rec[8] << 24) | ((guint32)rec[9] << 16) | ((guint32)rec[10] << 8) |
+ (guint32)rec[11];
+ wd3 = ((guint32)rec[12] << 24) | ((guint32)rec[13] << 16) | ((guint32)rec[14] << 8) |
+ (guint32)rec[15];
+
+ if ((cmd & HEADER_IS_TX) == HEADER_IS_TX)
+ IS_TX = 1;
+ else if ((cmd & HEADER_IS_RX) == HEADER_IS_RX)
+ IS_TX = 0;
+ else IS_TX = 2; /*NULL case*/
+ /* now decode based on the command byte */
+ switch (cmd) {
+ case 0x21:
+ case 0x31:
+ v_size = (int)(wd2 & 0xffff);
+ *v_type = VT_FRAME;
+ break;
+
+ case 0xc1:
+ case 0x8b:
+ v_size = (int)(wd2 & 0xffff);
+ *v_type = VT_CPMSG;
+ break;
+
+ case 0xfe:
+ v_size = (int)(wd3 & 0xffff);
+ *v_type = VT_CPMSG;
+ break;
+
+ default:
+ break;
+ }
+
+ return(v_size);
+}
+
+
+/*--------------------------------------------------------------------------------------*/
+/* utilities to extract and decode the PHY bit rate from 802.11 PLCP headers (OFDM/CCK) */
+/* they are passed a pointer to 4 or 6 consecutive bytes of PLCP header */
+/* 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)
+{
+ /* extract the RATE field (LS nibble of first byte) then decode it */
+ switch (plcp[0] & 0x0f) {
+ case 0x0b: return(6 * 2);
+ case 0x0f: return(9 * 2);
+ case 0x0a: return(12 * 2);
+ case 0x0e: return(18 * 2);
+ case 0x09: return(24 * 2);
+ case 0x0d: return(36 * 2);
+ case 0x08: return(48 * 2);
+ case 0x0c: return(54 * 2);
+ default: return(0);
+ }
+}
+
+static guint8 get_cck_rate(guint8 *plcp)
+{
+ /* extract rate from the SIGNAL field, 1 byte */
+ switch (plcp[0]) {
+ case 0x0a: return(1 * 2);
+ case 0x14: return(2 * 2);
+ case 0x37: return(11); /* 5.5 Mb/s */
+ case 0x6e: return(11 * 2);
+ default: return(0);
+ }
+}
+
+/*--------------------------------------------------------------------------------------*/
+/* utility to set up offsets and bitmasks for decoding the stats blocks */
+
+static void setup_defaults( guint16 fpga)
+{
+ switch (fpga) {
+ /* WLAN frames */
+ case vVW510021_W_FPGA:
+ STATS_LEN = vVW510021_W_STATS_LEN;
+
+ VALID_OFF = vVW510021_W_VALID_OFF;
+ MTYPE_OFF = vVW510021_W_MTYPE_OFF;
+ VCID_OFF = vVW510021_W_VCID_OFF;
+ FLOWSEQ_OFF = vVW510021_W_FLOWSEQ_OFF;
+ FLOWID_OFF = vVW510021_W_FLOWID_OFF;
+
+ /*OCTET_OFF = v22_W_OCTET_OFF;*/
+
+ ERRORS_OFF = vVW510021_W_ERRORS_OFF;
+ PATN_OFF = vVW510021_W_MATCH_OFF;
+ RSSI_OFF = vVW510021_W_RSSI_TXPOWER_OFF;
+ STARTT_OFF = vVW510021_W_STARTT_OFF;
+ ENDT_OFF = vVW510021_W_ENDT_OFF;
+ LATVAL_OFF = vVW510021_W_LATVAL_OFF;
+ INFO_OFF = vVW510021_W_INFO_OFF;
+ FPGA_VERSION_OFF = vVW510021_W_FPGA_VERSION_OFF;
+ HEADER_VERSION_OFF = vVW510021_W_HEADER_VERSION_OFF;
+ OCTET_OFF = vVW510021_W_MSDU_LENGTH_OFF;
+ L1P_1_OFF = vVW510021_W_L1P_1_OFF;
+ L1P_2_OFF = vVW510021_W_L1P_2_OFF;
+ L4ID_OFF = vVW510021_W_L4ID_OFF;
+ IPLEN_OFF = vVW510021_W_IPLEN_OFF;
+ PLCP_LENGTH_OFF = vVW510021_W_PLCP_LENGTH_OFF;
+
+ HEADER_IS_RX = vVW510021_W_HEADER_IS_RX;
+ HEADER_IS_TX = vVW510021_W_HEADER_IS_TX;
+ MT_MASK = vVW510021_W_SEL_MASK;
+ MCS_INDEX_MASK = vVW510021_W_MCS_MASK;
+ PREAMBLE_MASK = vVW510021_W_PREAMBLE_MASK;
+ VCID_MASK = 0xffff;
+ FLOW_VALID = vVW510021_W_FLOW_VALID;
+ STATS_START_OFF = vVW510021_W_HEADER_LEN;
+ FCS_ERROR = vVW510021_W_FCS_ERROR;
+ CRYPTO_ERR = v22_W_CRYPTO_ERR;
+ RETRY_ERR = v22_W_RETRY_ERR;
+
+ /*STATS_START_OFF = 0;*/
+
+ RXTX_OFF = vVW510021_W_RXTX_OFF;
+
+ MT_10_HALF = 0;
+ MT_10_FULL = 0;
+ MT_100_HALF = 0;
+ MT_100_FULL = 0;
+ MT_1G_HALF = 0;
+ MT_1G_FULL = 0;
+ MT_CCKL = v22_W_MT_CCKL;
+ MT_CCKS = v22_W_MT_CCKS;
+ /*MT_OFDM = vVW510021_W_MT_OFDM;*/
+
+ WEPTYPE = vVW510021_W_WEPTYPE;
+ TKIPTYPE = vVW510021_W_TKIPTYPE;
+ CCMPTYPE = vVW510021_W_CCMPTYPE;
+
+ FRAME_TYPE_OFF = vVW510021_W_FRAME_TYPE_OFF;
+ IS_TCP = vVW510021_W_IS_TCP;
+ IS_UDP = vVW510021_W_IS_UDP;
+ IS_ICMP = vVW510021_W_IS_ICMP;
+ IS_IGMP = vVW510021_W_IS_IGMP;
+ IS_QOS = vVW510021_W_QOS_VALID;
+
+ break;
+
+ /* Ethernet frames */
+ case vVW510012_E_FPGA:
+ STATS_LEN = v22_E_STATS_LEN;
+
+ VALID_OFF = v22_E_VALID_OFF;
+ MTYPE_OFF = v22_E_MTYPE_OFF;
+ VCID_OFF = v22_E_VCID_OFF;
+ FLOWSEQ_OFF = v22_E_FLOWSEQ_OFF;
+ FLOWID_OFF = v22_E_FLOWID_OFF;
+ OCTET_OFF = v22_E_OCTET_OFF;
+ ERRORS_OFF = v22_E_ERRORS_OFF;
+ PATN_OFF = v22_E_PATN_OFF;
+ RSSI_OFF = v22_E_RSSI_OFF;
+ STARTT_OFF = v22_E_STARTT_OFF;
+ ENDT_OFF = v22_E_ENDT_OFF;
+ LATVAL_OFF = v22_E_LATVAL_OFF;
+ INFO_OFF = v22_E_INFO_OFF;
+ L4ID_OFF = v22_E_L4ID_OFF;
+
+ HEADER_IS_RX = v22_E_HEADER_IS_RX;
+ HEADER_IS_TX = v22_E_HEADER_IS_TX;
+
+ IS_RX = v22_E_IS_RX;
+ MT_MASK = v22_E_MT_MASK;
+ VCID_MASK = v22_E_VCID_MASK;
+ FLOW_VALID = v22_E_FLOW_VALID;
+ FCS_ERROR = v22_E_FCS_ERROR;
+
+ RX_DECRYPTS = v22_E_RX_DECRYPTS;
+ TX_DECRYPTS = v22_E_TX_DECRYPTS;
+ FC_PROT_BIT = v22_E_FC_PROT_BIT;
+
+ MT_10_HALF = v22_E_MT_10_HALF;
+ MT_10_FULL = v22_E_MT_10_FULL;
+ MT_100_HALF = v22_E_MT_100_HALF;
+ MT_100_FULL = v22_E_MT_100_FULL;
+ MT_1G_HALF = v22_E_MT_1G_HALF;
+ MT_1G_FULL = v22_E_MT_1G_FULL;
+ MT_CCKL = 0;
+ MT_CCKS = 0;
+ MT_OFDM = 0;
+
+ FRAME_TYPE_OFF = v22_E_FRAME_TYPE_OFF;
+ IS_TCP = v22_E_IS_TCP;
+ IS_UDP = v22_E_IS_UDP;
+ IS_ICMP = v22_E_IS_ICMP;
+ IS_IGMP = v22_E_IS_IGMP;
+ IS_QOS = v22_E_IS_QOS;
+ IS_VLAN = v22_E_IS_VLAN;
+
+ break;
+
+ /* WLAN frames */
+ case vVW510006_W_FPGA:
+ STATS_LEN = v22_W_STATS_LEN;
+
+ MTYPE_OFF = v22_W_MTYPE_OFF;
+ VALID_OFF = v22_W_VALID_OFF;
+ VCID_OFF = v22_W_VCID_OFF;
+ FLOWSEQ_OFF = v22_W_FLOWSEQ_OFF;
+ FLOWID_OFF = v22_W_FLOWID_OFF;
+ OCTET_OFF = v22_W_OCTET_OFF;
+ ERRORS_OFF = v22_W_ERRORS_OFF;
+ PATN_OFF = v22_W_PATN_OFF;
+ RSSI_OFF = v22_W_RSSI_OFF;
+ STARTT_OFF = v22_W_STARTT_OFF;
+ ENDT_OFF = v22_W_ENDT_OFF;
+ LATVAL_OFF = v22_W_LATVAL_OFF;
+ INFO_OFF = v22_W_INFO_OFF;
+ L4ID_OFF = v22_W_L4ID_OFF;
+ IPLEN_OFF = v22_W_IPLEN_OFF;
+ PLCP_LENGTH_OFF = v22_W_PLCP_LENGTH_OFF;
+
+ FCS_ERROR = v22_W_FCS_ERROR;
+ CRYPTO_ERR = v22_W_CRYPTO_ERR;
+ PAYCHK_ERR = v22_W_PAYCHK_ERR;
+ RETRY_ERR = v22_W_RETRY_ERR;
+ IS_RX = v22_W_IS_RX;
+ MT_MASK = v22_W_MT_MASK;
+ VCID_MASK = v22_W_VCID_MASK;
+ FLOW_VALID = v22_W_FLOW_VALID;
+
+ HEADER_IS_RX = v22_W_HEADER_IS_RX;
+ HEADER_IS_TX = v22_W_HEADER_IS_TX;
+
+ RX_DECRYPTS = v22_W_RX_DECRYPTS;
+ TX_DECRYPTS = v22_W_TX_DECRYPTS;
+ FC_PROT_BIT = v22_W_FC_PROT_BIT;
+
+ MT_10_HALF = 0;
+ MT_10_FULL = 0;
+ MT_100_HALF = 0;
+ MT_100_FULL = 0;
+ MT_1G_HALF = 0;
+ MT_1G_FULL = 0;
+ MT_CCKL = v22_W_MT_CCKL;
+ MT_CCKS = v22_W_MT_CCKS;
+ MT_OFDM = v22_W_MT_OFDM;
+
+ WEPTYPE = v22_W_WEPTYPE;
+ TKIPTYPE = v22_W_TKIPTYPE;
+ CCMPTYPE = v22_W_CCMPTYPE;
+
+ FRAME_TYPE_OFF = v22_W_FRAME_TYPE_OFF;
+ IS_TCP = v22_W_IS_TCP;
+ IS_UDP = v22_W_IS_UDP;
+ IS_ICMP = v22_W_IS_ICMP;
+ IS_IGMP = v22_W_IS_IGMP;
+ IS_QOS = v22_W_IS_QOS;
+
+ break;
+
+ /* Ethernet frames */
+ case vVW510024_E_FPGA:
+ STATS_LEN = vVW510024_E_STATS_LEN;
+
+ VALID_OFF = vVW510024_E_VALID_OFF;
+ VCID_OFF = vVW510024_E_VCID_OFF;
+ FLOWSEQ_OFF = vVW510024_E_FLOWSEQ_OFF;
+ FLOWID_OFF = vVW510024_E_FLOWID_OFF;
+ OCTET_OFF = vVW510024_E_MSDU_LENGTH_OFF;
+ ERRORS_OFF = vVW510024_E_ERRORS_OFF;
+ PATN_OFF = vVW510024_E_MATCH_OFF;
+ STARTT_OFF = vVW510024_E_STARTT_OFF;
+ ENDT_OFF = vVW510024_E_ENDT_OFF;
+ LATVAL_OFF = vVW510024_E_LATVAL_OFF;
+ INFO_OFF = vVW510024_E_INFO_OFF;
+ L4ID_OFF = vVW510024_E_L4ID_OFF;
+ IPLEN_OFF = vVW510024_E_IPLEN_OFF;
+
+ FPGA_VERSION_OFF = vVW510024_E_FPGA_VERSION_OFF;
+ HEADER_VERSION_OFF = vVW510024_E_HEADER_VERSION_OFF;
+
+ HEADER_IS_RX = vVW510024_E_HEADER_IS_RX;
+ HEADER_IS_TX = vVW510024_E_HEADER_IS_TX;
+
+ VCID_MASK = vVW510024_E_VCID_MASK;
+ FLOW_VALID = vVW510024_E_FLOW_VALID;
+ FCS_ERROR = v22_E_FCS_ERROR;
+
+ FRAME_TYPE_OFF = vVW510024_E_FRAME_TYPE_OFF;
+ IS_TCP = vVW510024_E_IS_TCP;
+ IS_UDP = vVW510024_E_IS_UDP;
+ IS_ICMP = vVW510024_E_IS_ICMP;
+ IS_IGMP = vVW510024_E_IS_IGMP;
+ IS_QOS = vVW510024_E_QOS_VALID;
+ IS_VLAN = vVW510024_E_IS_VLAN;
+
+ break;
+ }
+}
+#define SIG_SCAN_RANGE 64 /* range of signature scanning region */
+
+/* utility routine: check that signature is at specified location; scan for it if not */
+/* if we can't find a signature at all, then simply return the originally supplied offset */
+int find_signature(guint8 *m_ptr, int pay_off, guint32 flow_id, guint8 flow_seq)
+{
+ int tgt; /* temps */
+ guint32 fid;
+
+ /* initial check is very simple: look for a '0xdd' at the target location */
+ if (m_ptr[pay_off] == 0xdd) /* if magic byte is present */
+ return(pay_off); /* got right offset, return it */
+
+ /* hmmm, signature magic byte is not where it is supposed to be; scan from start of */
+ /* payload until maximum scan range exhausted to see if we can find it */
+ /* the scanning process consists of looking for a '0xdd', then checking for the correct */
+ /* flow ID and sequence number at the appropriate offsets */
+ for (tgt = pay_off; tgt < (pay_off + SIG_SCAN_RANGE); tgt++) {
+ if (m_ptr[tgt] == 0xdd) { /* found magic byte? check fields */
+ if (m_ptr[tgt + 15] == 0xe2) {
+ if (m_ptr[tgt + 4] != flow_seq)
+ continue;
+
+ fid = m_ptr[tgt + 1] | (m_ptr[tgt + 2] << 8) |
+ (m_ptr[tgt + 3] << 16);
+
+ if (fid != flow_id)
+ continue;
+
+ return (tgt);
+ }
+ else
+ { /* out which one... */
+ if (m_ptr[tgt + SIG_FSQ_OFF] != flow_seq) /* check sequence number */
+ continue; /* if failed, keep scanning */
+
+ fid = m_ptr[tgt + SIG_FID_OFF] | (m_ptr[tgt + SIG_FID_OFF + 1] << 8) |
+ (m_ptr[tgt + SIG_FID_OFF + 2] << 16); /* assemble flow ID from signature */
+ if (fid != flow_id) /* check flow ID against expected */
+ continue; /* if failed, keep scanning */
+
+ /* matched magic byte, sequence number, flow ID; found the signature */
+ return (tgt); /* return offset of signature */
+ }
+ }
+ }
+
+ /* failed to find the signature, return the original offset as default */
+ return(pay_off);
+}
+
+/* utility routine: harvest the signature time stamp from the data frame */
+guint64 get_signature_ts(guint8 *m_ptr,int sig_off)
+{
+ int ts_offset;
+ guint64 sig_ts;
+
+ if (m_ptr[sig_off + 15] == 0xe2)
+ ts_offset = 5;
+ else
+ ts_offset = 8;
+
+ sig_ts = (m_ptr[sig_off + ts_offset + 3] << 24) | (m_ptr[sig_off + ts_offset + 2] << 16) |
+ (m_ptr[sig_off + ts_offset + 1] << 8) | (m_ptr[sig_off + ts_offset + 0]);
+
+ return(sig_ts & 0xffffffff);
+}
+
diff --git a/wiretap/wtap.c b/wiretap/wtap.c
index 2bf90b26fc..c18756adb5 100644
--- a/wiretap/wtap.c
+++ b/wiretap/wtap.c
@@ -574,6 +574,9 @@ static struct encap_type_info encap_table_base[] = {
/* WTAP_ENCAP_BACNET_MS_TP_WITH_PHDR */
{ "BACnet MS/TP with Directional Info", "bacnet-ms-tp-with-direction" },
+
+ /* WTAP_ENCAP_IXVERIWAVE */
+ { "IxVeriWave header and stats block", "ixveriwave" }
};
gint wtap_num_encap_types = sizeof(encap_table_base) / sizeof(struct encap_type_info);
diff --git a/wiretap/wtap.h b/wiretap/wtap.h
index c049cce071..c0618c43af 100644
--- a/wiretap/wtap.h
+++ b/wiretap/wtap.h
@@ -233,6 +233,7 @@ extern "C" {
#define WTAP_ENCAP_NFLOG 141
#define WTAP_ENCAP_V5_EF 142
#define WTAP_ENCAP_BACNET_MS_TP_WITH_PHDR 143
+#define WTAP_ENCAP_IXVERIWAVE 144
#define WTAP_NUM_ENCAP_TYPES wtap_get_num_encap_types()
@@ -301,6 +302,8 @@ extern "C" {
#define WTAP_FILE_MIME 59
#define WTAP_FILE_AETHRA 60
#define WTAP_FILE_MPEG_2_TS 61
+#define WTAP_FILE_VWR_80211 62
+#define WTAP_FILE_VWR_ETH 63
#define WTAP_NUM_FILE_TYPES wtap_get_num_file_types()