From d12747796cd563c5f8ec284b88cb3716ccca2098 Mon Sep 17 00:00:00 2001 From: Anders Broman Date: Tue, 11 Oct 2011 18:43:13 +0000 Subject: From Jouni Malinen: ieee80211: Start splitting add_tagged_field into helper functions. https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=6443 svn path=/trunk/; revision=39370 --- epan/dissectors/packet-ieee80211.c | 657 +++++++++++++++++++++++-------------- 1 file changed, 413 insertions(+), 244 deletions(-) (limited to 'epan/dissectors/packet-ieee80211.c') diff --git a/epan/dissectors/packet-ieee80211.c b/epan/dissectors/packet-ieee80211.c index 9d6fd2b223..0f2c444c0b 100644 --- a/epan/dissectors/packet-ieee80211.c +++ b/epan/dissectors/packet-ieee80211.c @@ -7822,308 +7822,477 @@ dissect_roaming_consortium(packet_info *pinfo, proto_tree *tree, /* ************************************************************************* */ +static int beacon_padding = 0; /* beacon padding bug */ -static const value_string environment_vals[] = { - { 0x20, "Any" }, - { 0x4f, "Outdoor" }, - { 0x49, "Indoor" }, - { 0, NULL } -}; +static int ieee80211_tag_ssid(packet_info *pinfo, proto_tree *tree, + proto_item *ti, proto_item *ti_len, + guint32 tag_len, tvbuff_t *tvb, int offset) +{ + /* 7.3.2.1 SSID element (0) */ + guint8 *ssid; /* The SSID may consist of arbitrary bytes */ -static int beacon_padding = 0; /* beacon padding bug */ -static int -add_tagged_field(packet_info * pinfo, proto_tree * tree, tvbuff_t * tvb, int offset, int ftype) + if (beacon_padding != 0) /* padding bug */ + return offset; + + if(tag_len > MAX_SSID_LEN) { + expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR, + "SSID length (%u) greater than maximum (%u)", + tag_len, MAX_SSID_LEN); + } + + ssid = tvb_get_ephemeral_string(tvb, offset + 2, tag_len); + AirPDcapSetLastSSID(&airpdcap_ctx, (CHAR *) ssid, tag_len); + proto_tree_add_item(tree, hf_ieee80211_tag_ssid, tvb, offset + 2, tag_len, + ENC_BIG_ENDIAN); + if (tag_len > 0) { + proto_item_append_text(ti, ": %s", ssid); + + col_append_fstr(pinfo->cinfo, COL_INFO, ", SSID=%s", ssid); + + /* Wlan Stats */ + memcpy(wlan_stats.ssid, ssid, MIN(tag_len, MAX_SSID_LEN)); + wlan_stats.ssid_len = tag_len; + } else { + proto_item_append_text(ti, ": Broadcast"); + + col_append_str(pinfo->cinfo, COL_INFO, ", SSID=Broadcast"); + } + + beacon_padding++; /* padding bug */ + + return offset + 2 + tag_len; +} + +static int ieee80211_tag_supp_rates(packet_info *pinfo, proto_tree *tree, + proto_item *ti, proto_item *ti_len, + guint32 tag_len, tvbuff_t *tvb, + int offset, int tag_end) { - guint32 oui; - tvbuff_t *tag_tvb; - const guint8 *tag_data_ptr; - guint32 tag_no, tag_len; - int n, ret; - char print_buff[SHORT_STR]; - proto_tree * orig_tree=tree; - proto_item *ti = NULL, *ti_len = NULL; - int tag_end; - guint8 tag_len_len; /* The length of the length parameter in bytes*/ + /* 7.3.2.2 Supported Rates element (1) */ + if (tag_len < 1) { + expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR, + "Tag length %u too short, must be greater than 0", + tag_len); + return offset; + } - tag_no = tvb_get_guint8(tvb, offset); - if(tag_no == TAG_WSIE){ - tag_len_len = 2; - tag_len = tvb_get_letohl(tvb, offset + 1); - } else - { - tag_len_len = 1; - tag_len = tvb_get_guint8(tvb, offset + 1); + offset += 2; + + while (offset < tag_end) { + proto_tree_add_item(tree, hf_ieee80211_tag_supp_rates, tvb, offset, 1, + ENC_BIG_ENDIAN); + proto_item_append_text(ti, " %s,", + val_to_str(tvb_get_guint8(tvb, offset), + ieee80211_supported_rates_vals, + "Unknown Rate") ); + offset++; } - tag_end = offset + 2 + tag_len; - if (tree) { - ti = proto_tree_add_item(orig_tree, hf_ieee80211_tag, tvb, offset, 2 + tag_len , ENC_NA); - proto_item_append_text(ti, ": %s", val_to_str(tag_no, tag_num_vals, "Reserved (%d)")); - tree = proto_item_add_subtree(ti, ett_80211_mgt_ie); + proto_item_append_text(ti, " [Mbit/sec]"); - proto_tree_add_item(tree, hf_ieee80211_tag_number, tvb, offset, 1, ENC_BIG_ENDIAN); + return offset; +} +static int ieee80211_tag_fh_parameter(packet_info *pinfo, proto_tree *tree, + proto_item *ti_len, guint32 tag_len, + tvbuff_t *tvb, int offset) +{ + /* 7.3.2.3 FH Parameter Set element (2) */ + if (tag_len < 5) { + expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR, + "Tag length %u too short, must be >= 5", tag_len); + return offset; } - ti_len = proto_tree_add_uint(tree, hf_ieee80211_tag_length, tvb, offset + 1, tag_len_len, tag_len); - switch (tag_no) - { + offset += 2; - case TAG_SSID: /* 7.3.2.1 SSID element (0) */ - if(beacon_padding == 0) /* padding bug */ - { - guint8 *ssid; /* The SSID may consist of arbitrary bytes */ + proto_tree_add_item(tree, hf_ieee80211_tag_fh_dwell_time, + tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; - if(tag_len > MAX_SSID_LEN) { - expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR, - "SSID length (%u) greater than maximum (%u)", - tag_len, MAX_SSID_LEN); - } + proto_tree_add_item(tree, hf_ieee80211_tag_fh_hop_set, + tvb, offset, 1, ENC_LITTLE_ENDIAN); + offset++; - ssid = tvb_get_ephemeral_string(tvb, offset + 2, tag_len); - AirPDcapSetLastSSID(&airpdcap_ctx, (CHAR *) ssid, tag_len); - proto_tree_add_item(tree, hf_ieee80211_tag_ssid, tvb, offset + 2, tag_len, ENC_BIG_ENDIAN); - if (tag_len > 0) { - proto_item_append_text(ti, ": %s", ssid); + proto_tree_add_item(tree, hf_ieee80211_tag_fh_hop_pattern, + tvb, offset, 1, ENC_LITTLE_ENDIAN); + offset++; - col_append_fstr(pinfo->cinfo, COL_INFO, ", SSID=%s", ssid ); + proto_tree_add_item(tree, hf_ieee80211_tag_fh_hop_index, + tvb, offset, 1, ENC_LITTLE_ENDIAN); + offset++; - /* Wlan Stats */ - memcpy(wlan_stats.ssid, ssid, MIN(tag_len, MAX_SSID_LEN)); - wlan_stats.ssid_len = tag_len; - } else { - proto_item_append_text(ti, ": Broadcast"); + return offset; +} - col_append_str(pinfo->cinfo, COL_INFO, ", SSID=Broadcast"); - } +static int ieee80211_tag_ds_parameter(packet_info *pinfo, proto_tree *tree, + proto_item *ti, proto_item *ti_len, + guint32 tag_len, tvbuff_t *tvb, + int offset) +{ + /* 7.3.2.4 DS Parameter Set element (3) */ + if (tag_len != 1) { + expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR, + "Tag length %u wrong, must be = 1", tag_len); + return offset; + } - beacon_padding++; /* padding bug */ - } - break; + offset += 2; - case TAG_SUPP_RATES: /* 7.3.2.2 Supported Rates element (1) */ - if(tag_len < 1) - { - expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR, "Tag length %u too short, must be greater than 0", tag_len); - break; - } - offset += 2; + proto_tree_add_item(tree, hf_ieee80211_tag_ds_param_channel, + tvb, offset, 1, ENC_BIG_ENDIAN); - while(offset < tag_end) - { - proto_tree_add_item(tree, hf_ieee80211_tag_supp_rates, tvb, offset, 1, ENC_BIG_ENDIAN); - proto_item_append_text(ti, " %s,", val_to_str(tvb_get_guint8(tvb, offset), ieee80211_supported_rates_vals, "Unknown Rate") ); - offset += 1; - } - proto_item_append_text(ti, " [Mbit/sec]"); - break; + proto_item_append_text(ti, " : Current Channel: %u", + tvb_get_guint8(tvb, offset)); - case TAG_FH_PARAMETER: /* 7.3.2.3 FH Parameter Set element (2) */ - if(tag_len < 5) - { - expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR, "Tag length %u too short, must be >= 5", tag_len); - break; - } - offset += 2; + wlan_stats.channel = tvb_get_guint8(tvb, offset); + offset++; - proto_tree_add_item(tree, hf_ieee80211_tag_fh_dwell_time, tvb, offset, 2, ENC_LITTLE_ENDIAN); - offset += 2; + return offset; +} - proto_tree_add_item(tree, hf_ieee80211_tag_fh_hop_set, tvb, offset, 1, ENC_LITTLE_ENDIAN); - offset += 1; +static int ieee80211_tag_cf_parameter(packet_info *pinfo, proto_tree *tree, + proto_item *ti, proto_item *ti_len, + guint32 tag_len, tvbuff_t *tvb, + int offset) +{ + /* 7.3.2.5 CF Parameter Set element (4) */ + if (tag_len != 6) { + expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR, + "Tag length %u wrong, must be = 6", tag_len); + return offset; + } - proto_tree_add_item(tree, hf_ieee80211_tag_fh_hop_pattern, tvb, offset, 1, ENC_LITTLE_ENDIAN); - offset += 1; + offset += 2; - proto_tree_add_item(tree, hf_ieee80211_tag_fh_hop_index, tvb, offset, 1, ENC_LITTLE_ENDIAN); - offset += 1; - break; + proto_tree_add_item(tree, hf_ieee80211_tag_cfp_count, + tvb, offset, 1, ENC_BIG_ENDIAN); + proto_item_append_text(ti, ": CFP count %u", tvb_get_guint8(tvb, offset)); + offset++; - case TAG_DS_PARAMETER: /* 7.3.2.4 DS Parameter Set element (3) */ - if(tag_len != 1) - { - expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR, "Tag length %u wrong, must be = 1", tag_len); - break; - } - offset += 2; + proto_tree_add_item(tree, hf_ieee80211_tag_cfp_period, + tvb, offset, 1, ENC_BIG_ENDIAN); + proto_item_append_text(ti, ": CFP Period %u", tvb_get_guint8(tvb, offset)); + offset++; - proto_tree_add_item(tree, hf_ieee80211_tag_ds_param_channel, tvb, offset , 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_ieee80211_tag_cfp_max_duration, + tvb, offset, 2, ENC_LITTLE_ENDIAN); + proto_item_append_text(ti, ": CFP Max Duration %u", + tvb_get_letohs(tvb, offset)); + offset += 2; - proto_item_append_text(ti, " : Current Channel: %u", tvb_get_guint8(tvb, offset)); + proto_tree_add_item(tree, hf_ieee80211_tag_cfp_dur_remaining, + tvb, offset, 2, ENC_LITTLE_ENDIAN); + proto_item_append_text(ti, ": CFP Dur Remaining %u", + tvb_get_letohs(tvb, offset)); + offset++; - wlan_stats.channel = tvb_get_guint8(tvb, offset); - break; + return offset; +} - case TAG_CF_PARAMETER: /* 7.3.2.5 CF Parameter Set element (4) */ - if(tag_len != 6) - { - expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR, "Tag length %u wrong, must be = 6", tag_len); - break; - } - offset += 2; +static int ieee80211_tag_tim(packet_info *pinfo, proto_tree *tree, + proto_item *ti, proto_item *ti_len, + guint32 tag_len, tvbuff_t *tvb, int offset) +{ + proto_tree *bmapctl_tree; + proto_item *bmapctl_item; - proto_tree_add_item(tree, hf_ieee80211_tag_cfp_count, tvb, offset , 1, ENC_BIG_ENDIAN); - proto_item_append_text(ti, ": CFP count %u", tvb_get_guint8(tvb, offset)); - offset += 1; + /* 7.3.2.6 TIM (5) */ + if (tag_len < 4) { + expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR, + "Tag length %u too short, must be >= 4", tag_len); + return offset; + } - proto_tree_add_item(tree, hf_ieee80211_tag_cfp_period, tvb, offset , 1, ENC_BIG_ENDIAN); - proto_item_append_text(ti, ": CFP Period %u", tvb_get_guint8(tvb, offset)); - offset += 1; + offset += 2; - proto_tree_add_item(tree, hf_ieee80211_tag_cfp_max_duration, tvb, offset , 2, ENC_LITTLE_ENDIAN); - proto_item_append_text(ti, ": CFP Max Duration %u", tvb_get_letohs(tvb, offset)); - offset += 2; + proto_tree_add_item(tree, hf_ieee80211_tim_dtim_count, + tvb, offset, 1, ENC_LITTLE_ENDIAN); + proto_item_append_text(ti, ": DTIM %u of", tvb_get_guint8(tvb, offset)); + offset++; - proto_tree_add_item(tree, hf_ieee80211_tag_cfp_dur_remaining, tvb, offset , 2, ENC_LITTLE_ENDIAN); - proto_item_append_text(ti, ": CFP Dur Remaining %u", tvb_get_letohs(tvb, offset)); - offset += 2; - break; + proto_tree_add_item(tree, hf_ieee80211_tim_dtim_period, + tvb, offset, 1, ENC_LITTLE_ENDIAN); + proto_item_append_text(ti, " %u bitmap", tvb_get_guint8(tvb, offset + 1)); + offset++; - case TAG_TIM: /* 7.3.2.6 TIM (5) */ - { - proto_tree *bmapctl_tree; - proto_item *bmapctl_item; - if (tag_len < 4) - { - expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR, "Tag length %u too short, must be >= 4", tag_len); - break; - } - offset += 2; + bmapctl_item = proto_tree_add_item(tree, hf_ieee80211_tim_bmapctl, + tvb, offset, 1, ENC_LITTLE_ENDIAN); + bmapctl_tree = proto_item_add_subtree(bmapctl_item, ett_tag_bmapctl_tree); + proto_tree_add_item(bmapctl_tree, hf_ieee80211_tim_bmapctl_mcast, + tvb, offset, 1, ENC_LITTLE_ENDIAN); + proto_tree_add_item(bmapctl_tree, hf_ieee80211_tim_bmapctl_offset, + tvb, offset, 1, ENC_LITTLE_ENDIAN); + offset++; - proto_tree_add_item(tree, hf_ieee80211_tim_dtim_count, tvb, offset, 1, ENC_LITTLE_ENDIAN); - proto_item_append_text(ti, ": DTIM %u of", tvb_get_guint8(tvb, offset)); - offset += 1; + proto_tree_add_item(tree, hf_ieee80211_tim_partial_virtual_bitmap, + tvb, offset, tag_len - 3, ENC_NA); + offset += tag_len - 3; - proto_tree_add_item(tree, hf_ieee80211_tim_dtim_period, tvb, offset, 1, ENC_LITTLE_ENDIAN); - proto_item_append_text(ti, " %u bitmap", tvb_get_guint8(tvb, offset + 1)); - offset += 1; + return offset; +} - bmapctl_item = proto_tree_add_item(tree, hf_ieee80211_tim_bmapctl, tvb, offset, 1, ENC_LITTLE_ENDIAN); - bmapctl_tree = proto_item_add_subtree(bmapctl_item, ett_tag_bmapctl_tree); - proto_tree_add_item(bmapctl_tree, hf_ieee80211_tim_bmapctl_mcast, tvb, offset, 1, ENC_LITTLE_ENDIAN); - proto_tree_add_item(bmapctl_tree, hf_ieee80211_tim_bmapctl_offset, tvb, offset, 1, ENC_LITTLE_ENDIAN); - offset += 1; +static int ieee80211_tag_ibss_parameter(packet_info *pinfo, proto_tree *tree, + proto_item *ti, proto_item *ti_len, + guint32 tag_len, tvbuff_t *tvb, + int offset) +{ + /* 7.3.2.7 IBSS Parameter Set element (6) */ - proto_tree_add_item(tree, hf_ieee80211_tim_partial_virtual_bitmap, tvb, offset, tag_len - 3, ENC_NA); + if (tag_len != 2) { + expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR, + "Tag length %u wrong, must be = 2", tag_len); + return offset; + } - break; + offset += 2; + + proto_tree_add_item(tree, hf_ieee80211_tag_ibss_atim_window, + tvb, offset, 2, ENC_LITTLE_ENDIAN); + proto_item_append_text(ti, ": ATIM window 0x%x", + tvb_get_letohs(tvb, offset)); + offset += 2; + + return offset; +} + +static const value_string environment_vals[] = { + { 0x20, "Any" }, + { 0x4f, "Outdoor" }, + { 0x49, "Indoor" }, + { 0, NULL } +}; + +static int ieee80211_tag_country_info(packet_info *pinfo, proto_tree *tree, + proto_item *ti, proto_item *ti_len, + guint32 tag_len, tvbuff_t *tvb, + int offset, int tag_end) +{ + /* 7.3.2.9 Country information element (7) */ + proto_tree *sub_tree; + proto_item *sub_item; + + if (tag_len < 6) { + expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR, + "Tag length %u too short, must be >= 6", tag_len); + return offset; + } + + offset += 2; + + proto_tree_add_item(tree, hf_ieee80211_tag_country_info_code, + tvb, offset, 2, ENC_BIG_ENDIAN); + proto_item_append_text(ti, ": Country Code %s", + tvb_get_ephemeral_string(tvb, offset, 2)); + offset += 2; + + proto_tree_add_item(tree, hf_ieee80211_tag_country_info_env, + tvb, offset, 1, ENC_BIG_ENDIAN); + proto_item_append_text(ti, ", Environment %s", + val_to_str(tvb_get_guint8(tvb, offset), + environment_vals,"Unknown (0x%02x)")); + offset++; + + while (offset < tag_end) { + /* Padding ? */ + if ((tag_end - offset) < 3) { + proto_tree_add_item(tree, hf_ieee80211_tag_country_info_pad, + tvb, offset, 1, ENC_NA); + offset++; + continue; } - case TAG_IBSS_PARAMETER: /* 7.3.2.7 IBSS Parameter Set element (6) */ - if(tag_len != 2) - { - expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR, "Tag length %u wrong, must be = 2", tag_len); - break; - } - offset += 2; + if (tvb_get_guint8(tvb, offset) <= 200) { /* 802.11d */ + sub_item = proto_tree_add_item(tree, hf_ieee80211_tag_country_info_fnm, + tvb, offset, 3, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_tag_country_fnm_tree); - proto_tree_add_item(tree, hf_ieee80211_tag_ibss_atim_window, tvb, offset, 2, ENC_LITTLE_ENDIAN); - proto_item_append_text(ti, ": ATIM window 0x%x", tvb_get_letohs(tvb, offset)); + proto_tree_add_item(sub_tree, hf_ieee80211_tag_country_info_fnm_fcn, + tvb, offset, 1, ENC_BIG_ENDIAN); + proto_item_append_text(sub_item, ": First Channel Number: %d", + tvb_get_guint8(tvb, offset)); + offset++; + proto_tree_add_item(sub_tree, hf_ieee80211_tag_country_info_fnm_nc, + tvb, offset, 1, ENC_BIG_ENDIAN); + proto_item_append_text(sub_item, ", Number of Channels: %d", + tvb_get_guint8(tvb, offset)); + offset++; + proto_tree_add_item(sub_tree, hf_ieee80211_tag_country_info_fnm_mtpl, + tvb, offset, 1, ENC_BIG_ENDIAN); + proto_item_append_text(sub_item, + ", Maximum Transmit Power Level: %d dBm", + tvb_get_guint8(tvb, offset)); + offset++; + } else { /* 802.11j */ + sub_item = proto_tree_add_item(tree, hf_ieee80211_tag_country_info_rrc, + tvb, offset, 3, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_tag_country_rcc_tree); - break; - case TAG_COUNTRY_INFO: /* 7.3.2.9 Country information element (7) */ - { - proto_tree *sub_tree; - proto_item *sub_item; - if (tag_len < 6) - { - expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR, "Tag length %u too short, must be >= 6", tag_len); - break; - } - offset += 2; + proto_tree_add_item(sub_tree, hf_ieee80211_tag_country_info_rrc_rei, + tvb, offset, 1, ENC_BIG_ENDIAN); + proto_item_append_text(sub_item, + ": Regulatory Extension Identifier: %d", + tvb_get_guint8(tvb, offset)); + offset++; + proto_tree_add_item(sub_tree, hf_ieee80211_tag_country_info_rrc_rc, + tvb, offset, 1, ENC_BIG_ENDIAN); + proto_item_append_text(sub_item, ", Regulatory Class: %d", + tvb_get_guint8(tvb, offset)); + offset++; + proto_tree_add_item(sub_tree, hf_ieee80211_tag_country_info_rrc_cc, + tvb, offset, 1, ENC_BIG_ENDIAN); + proto_item_append_text(sub_item, ", Coverage Class: %d", + tvb_get_guint8(tvb, offset)); + offset++; + } + } - proto_tree_add_item(tree, hf_ieee80211_tag_country_info_code, tvb, offset, 2, ENC_BIG_ENDIAN); - proto_item_append_text(ti, ": Country Code %s", tvb_get_ephemeral_string(tvb, offset, 2)); - offset += 2; + return offset; +} - proto_tree_add_item(tree, hf_ieee80211_tag_country_info_env, tvb, offset, 1, ENC_BIG_ENDIAN); - proto_item_append_text(ti, ", Environment %s", val_to_str(tvb_get_guint8(tvb, offset), environment_vals,"Unknown (0x%02x)")); - offset += 1; +static int ieee80211_tag_fh_hopping_parameter(packet_info *pinfo, + proto_tree *tree, + proto_item *ti, + proto_item *ti_len, + guint32 tag_len, tvbuff_t *tvb, + int offset) +{ + /* 7.3.2.10 Hopping Pattern Parameters information element (8) */ + if (tag_len < 2) { + expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR, + "Tag length %u too short, must be >= 2", tag_len); + return offset; + } - while(offset < tag_end) - { - /* Padding ? */ - if ((tag_end - offset) < 3) - { - proto_tree_add_item(tree, hf_ieee80211_tag_country_info_pad, tvb, offset, 1, ENC_NA); - offset += 1; - continue; - } - if(tvb_get_guint8(tvb, offset) <= 200) { /* 802.11d */ - sub_item = proto_tree_add_item(tree, hf_ieee80211_tag_country_info_fnm, tvb, offset, 3, ENC_NA); - sub_tree = proto_item_add_subtree(sub_item, ett_tag_country_fnm_tree); + offset += 2; - proto_tree_add_item(sub_tree, hf_ieee80211_tag_country_info_fnm_fcn, tvb, offset, 1, ENC_BIG_ENDIAN); - proto_item_append_text(sub_item, ": First Channel Number: %d", tvb_get_guint8(tvb, offset)); - offset += 1; - proto_tree_add_item(sub_tree, hf_ieee80211_tag_country_info_fnm_nc, tvb, offset, 1, ENC_BIG_ENDIAN); - proto_item_append_text(sub_item, ", Number of Channels: %d", tvb_get_guint8(tvb, offset)); - offset += 1; - proto_tree_add_item(sub_tree, hf_ieee80211_tag_country_info_fnm_mtpl, tvb, offset, 1, ENC_BIG_ENDIAN); - proto_item_append_text(sub_item, ", Maximum Transmit Power Level: %d dBm", tvb_get_guint8(tvb, offset)); - offset += 1; - } else { /* 802.11j */ - sub_item = proto_tree_add_item(tree, hf_ieee80211_tag_country_info_rrc, tvb, offset, 3, ENC_NA); - sub_tree = proto_item_add_subtree(sub_item, ett_tag_country_rcc_tree); + proto_tree_add_item(tree, hf_ieee80211_tag_fh_hopping_parameter_prime_radix, + tvb, offset, 1, ENC_BIG_ENDIAN); + proto_item_append_text(ti, ": Prime Radix: %u", tvb_get_guint8(tvb, offset)); + offset++; - proto_tree_add_item(sub_tree, hf_ieee80211_tag_country_info_rrc_rei, tvb, offset, 1, ENC_BIG_ENDIAN); - proto_item_append_text(sub_item, ": Regulatory Extension Identifier: %d", tvb_get_guint8(tvb, offset)); - offset += 1; - proto_tree_add_item(sub_tree, hf_ieee80211_tag_country_info_rrc_rc, tvb, offset, 1, ENC_BIG_ENDIAN); - proto_item_append_text(sub_item, ", Regulatory Class: %d", tvb_get_guint8(tvb, offset)); - offset += 1; - proto_tree_add_item(sub_tree, hf_ieee80211_tag_country_info_rrc_cc, tvb, offset, 1, ENC_BIG_ENDIAN); - proto_item_append_text(sub_item, ", Coverage Class: %d", tvb_get_guint8(tvb, offset)); - offset += 1; - } + proto_tree_add_item(tree, hf_ieee80211_tag_fh_hopping_parameter_nb_channels, + tvb, offset, 1, ENC_BIG_ENDIAN); + proto_item_append_text(ti, ", Number of Channels: %u", + tvb_get_guint8(tvb, offset)); + offset++; - } + return offset; +} - } - break; +static int ieee80211_tag_fh_hopping_table(packet_info *pinfo, proto_tree *tree, + proto_item *ti_len, + guint32 tag_len, tvbuff_t *tvb, + int offset, int tag_end) +{ + /* 7.3.2.11 Hopping Pattern Table information element (9) */ + if (tag_len < 4) { + expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR, + "Tag length %u too short, must be >= 4", tag_len); + return offset; + } - case TAG_FH_HOPPING_PARAMETER: /* 7.3.2.10 Hopping Pattern Parameters information element (8) */ - if (tag_len < 2) - { - expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR, "Tag length %u too short, must be >= 2", tag_len); - break; - } - offset += 2; + offset += 2; - proto_tree_add_item(tree, hf_ieee80211_tag_fh_hopping_parameter_prime_radix, tvb, offset, 1, ENC_BIG_ENDIAN); - proto_item_append_text(ti, ": Prime Radix: %u", tvb_get_guint8(tvb, offset)); - offset += 1; + proto_tree_add_item(tree, hf_ieee80211_tag_fh_hopping_table_flag, + tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; - proto_tree_add_item(tree, hf_ieee80211_tag_fh_hopping_parameter_nb_channels, tvb, offset, 1, ENC_BIG_ENDIAN); - proto_item_append_text(ti, ", Number of Channels: %u", tvb_get_guint8(tvb, offset)); - offset += 1; - break; + proto_tree_add_item(tree, hf_ieee80211_tag_fh_hopping_table_number_of_sets, + tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; - case TAG_FH_HOPPING_TABLE: /* 7.3.2.11 Hopping Pattern Table information element (9) */ - if (tag_len < 4) - { - expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR, "Tag length %u too short, must be >= 4", tag_len); - break; - } - offset += 2; + proto_tree_add_item(tree, hf_ieee80211_tag_fh_hopping_table_modulus, + tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; - proto_tree_add_item(tree, hf_ieee80211_tag_fh_hopping_table_flag, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; + proto_tree_add_item(tree, hf_ieee80211_tag_fh_hopping_table_offset, + tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; - proto_tree_add_item(tree, hf_ieee80211_tag_fh_hopping_table_number_of_sets, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; + while (offset < tag_end) { + proto_tree_add_item(tree, hf_ieee80211_tag_fh_hopping_random_table, + tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + } - proto_tree_add_item(tree, hf_ieee80211_tag_fh_hopping_table_modulus, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; + return offset; +} - proto_tree_add_item(tree, hf_ieee80211_tag_fh_hopping_table_offset, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; +static int +add_tagged_field(packet_info * pinfo, proto_tree * tree, tvbuff_t * tvb, int offset, int ftype) +{ + guint32 oui; + tvbuff_t *tag_tvb; + const guint8 *tag_data_ptr; + guint32 tag_no, tag_len; + int n, ret; + char print_buff[SHORT_STR]; + proto_tree * orig_tree=tree; + proto_item *ti = NULL, *ti_len = NULL; + int tag_end; + guint8 tag_len_len; /* The length of the length parameter in bytes*/ - while(offset < tag_end ) - { - proto_tree_add_item(tree, hf_ieee80211_tag_fh_hopping_random_table, tvb, offset, 2, ENC_BIG_ENDIAN); - offset += 2; - } - break; + tag_no = tvb_get_guint8(tvb, offset); + if(tag_no == TAG_WSIE){ + tag_len_len = 2; + tag_len = tvb_get_letohl(tvb, offset + 1); + } else + { + tag_len_len = 1; + tag_len = tvb_get_guint8(tvb, offset + 1); + } + tag_end = offset + 2 + tag_len; + if (tree) { + ti = proto_tree_add_item(orig_tree, hf_ieee80211_tag, tvb, offset, 2 + tag_len , ENC_NA); + proto_item_append_text(ti, ": %s", val_to_str(tag_no, tag_num_vals, "Reserved (%d)")); + + tree = proto_item_add_subtree(ti, ett_80211_mgt_ie); + + proto_tree_add_item(tree, hf_ieee80211_tag_number, tvb, offset, 1, ENC_BIG_ENDIAN); + + } + ti_len = proto_tree_add_uint(tree, hf_ieee80211_tag_length, tvb, offset + 1, tag_len_len, tag_len); + + switch (tag_no) { + case TAG_SSID: + offset += ieee80211_tag_ssid(pinfo, tree, ti, ti_len, tag_len, tvb, + offset); + break; + case TAG_SUPP_RATES: + offset += ieee80211_tag_supp_rates(pinfo, tree, ti, ti_len, tag_len, tvb, + offset, tag_end); + break; + case TAG_FH_PARAMETER: + offset += ieee80211_tag_fh_parameter(pinfo, tree, ti_len, tag_len, tvb, + offset); + break; + case TAG_DS_PARAMETER: + offset += ieee80211_tag_ds_parameter(pinfo, tree, ti, ti_len, tag_len, tvb, + offset); + break; + case TAG_CF_PARAMETER: + offset += ieee80211_tag_cf_parameter(pinfo, tree, ti, ti_len, tag_len, tvb, + offset); + break; + case TAG_TIM: + offset += ieee80211_tag_tim(pinfo, tree, ti, ti_len, tag_len, tvb, offset); + break; + case TAG_IBSS_PARAMETER: + offset += ieee80211_tag_ibss_parameter(pinfo, tree, ti, ti_len, tag_len, + tvb, offset); + break; + case TAG_COUNTRY_INFO: + offset += ieee80211_tag_country_info(pinfo, tree, ti, ti_len, tag_len, tvb, + offset, tag_end); + break; + case TAG_FH_HOPPING_PARAMETER: + offset += ieee80211_tag_fh_hopping_parameter(pinfo, tree, ti, ti_len, + tag_len, tvb, offset); + break; + case TAG_FH_HOPPING_TABLE: + offset += ieee80211_tag_fh_hopping_table(pinfo, tree, ti_len, tag_len, + tvb, offset, tag_end); + break; case TAG_REQUEST: /* 7.3.2.12 Request information element (10) */ while(offset < tag_end ) -- cgit v1.2.3