diff options
Diffstat (limited to 'epan')
-rw-r--r-- | epan/CMakeLists.txt | 2 | ||||
-rw-r--r-- | epan/dissectors/Makefile.common | 2 | ||||
-rw-r--r-- | epan/dissectors/packet-ixveriwave.c | 1544 | ||||
-rw-r--r-- | epan/dissectors/packet-waveagent.c | 1943 |
4 files changed, 3491 insertions, 0 deletions
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; + } +} + + |