diff --git a/epan/dissectors/packet-ieee80211-radio.c b/epan/dissectors/packet-ieee80211-radio.c index be08dd09b0..0f7b9133c9 100644 --- a/epan/dissectors/packet-ieee80211-radio.c +++ b/epan/dissectors/packet-ieee80211-radio.c @@ -77,6 +77,9 @@ static int hf_wlan_radio_signal_dbm = -1; static int hf_wlan_radio_noise_percent = -1; static int hf_wlan_radio_noise_dbm = -1; static int hf_wlan_radio_timestamp = -1; +static int hf_wlan_last_part_of_a_mpdu = -1; +static int hf_wlan_a_mpdu_delim_crc_error = -1; +static int hf_wlan_a_mpdu_aggregate_id = -1; static const value_string phy_vals[] = { { PHDR_802_11_PHY_11_FHSS, "802.11 FHSS" }, @@ -562,6 +565,16 @@ dissect_wlan_radio (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void proto_tree_add_uint64(radio_tree, hf_wlan_radio_timestamp, tvb, 0, 0, phdr->tsf_timestamp); } + if (phdr->has_aggregate_info) { + proto_tree_add_boolean(radio_tree, hf_wlan_last_part_of_a_mpdu, tvb, 0, 0, + (phdr->aggregate_flags & PHDR_802_11_LAST_PART_OF_A_MPDU) ? + TRUE : FALSE); + proto_tree_add_boolean(radio_tree, hf_wlan_a_mpdu_delim_crc_error, tvb, 0, 0, + (phdr->aggregate_flags & PHDR_802_11_A_MPDU_DELIM_CRC_ERROR) ? + TRUE : FALSE); + proto_tree_add_uint(radio_tree, hf_wlan_a_mpdu_aggregate_id, tvb, 0, 0, + phdr->aggregate_id); + } } /* dissect the 802.11 packet next */ @@ -716,6 +729,18 @@ static hf_register_info hf_wlan_radio[] = { {&hf_wlan_radio_timestamp, {"TSF timestamp", "wlan_radio.timestamp", FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL }}, + + {&hf_wlan_last_part_of_a_mpdu, + {"Last part of an A-MPDU", "wlan_radio.last_part_of_an_ampdu", FT_BOOLEAN, 0, NULL, 0, + "This is the last part of an A-MPDU", HFILL }}, + + {&hf_wlan_a_mpdu_delim_crc_error, + {"A-MPDU delimiter CRC error", "wlan_radio.a_mpdu_delim_crc_error", FT_BOOLEAN, 0, NULL, 0, + NULL, HFILL }}, + + {&hf_wlan_a_mpdu_aggregate_id, + {"A-MPDU aggregate ID", "wlan_radio.a_mpdu_aggregate_id", FT_UINT32, BASE_DEC, NULL, 0, + NULL, HFILL }}, }; static gint *tree_array[] = { diff --git a/epan/dissectors/packet-ieee80211-radiotap.c b/epan/dissectors/packet-ieee80211-radiotap.c index 5c3fb011bf..4668b6e61e 100644 --- a/epan/dissectors/packet-ieee80211-radiotap.c +++ b/epan/dissectors/packet-ieee80211-radiotap.c @@ -1492,7 +1492,15 @@ dissect_radiotap(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* u proto_tree *ampdu_tree = NULL, *ampdu_flags_tree; guint16 ampdu_flags; + phdr.has_aggregate_info = 1; + phdr.aggregate_flags = 0; + phdr.aggregate_id = tvb_get_letohl(tvb, offset); + ampdu_flags = tvb_get_letohs(tvb, offset + 4); + if (ampdu_flags & IEEE80211_RADIOTAP_AMPDU_IS_LAST) + phdr.aggregate_flags |= PHDR_802_11_LAST_PART_OF_A_MPDU; + if (ampdu_flags & IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR) + phdr.aggregate_flags |= PHDR_802_11_A_MPDU_DELIM_CRC_ERROR; if (tree) { it = proto_tree_add_item(radiotap_tree, hf_radiotap_ampdu, diff --git a/epan/dissectors/packet-ppi.c b/epan/dissectors/packet-ppi.c index d5c5515457..8dc8d69f76 100644 --- a/epan/dissectors/packet-ppi.c +++ b/epan/dissectors/packet-ppi.c @@ -629,14 +629,10 @@ dissect_80211n_mac(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int { proto_tree *ftree = tree; ptvcursor_t *csr; - int subtree_off = add_subtree ? 4 : 0; guint32 flags; phdr->phy = PHDR_802_11_PHY_11N; - *n_mac_flags = tvb_get_letohl(tvb, offset + subtree_off); - *ampdu_id = tvb_get_letohl(tvb, offset + 4 + subtree_off); - if (add_subtree) { ftree = proto_tree_add_subtree(tree, tvb, offset, data_len, ett_dot11n_mac, NULL, "802.11n MAC"); add_ppi_field_header(tvb, ftree, &offset); @@ -651,10 +647,19 @@ dissect_80211n_mac(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int csr = ptvcursor_new(ftree, tvb, offset); flags = tvb_get_letohl(tvb, ptvcursor_current_offset(csr)); + *n_mac_flags = flags; phdr->phy_info.info_11n.has_short_gi = TRUE; phdr->phy_info.info_11n.has_greenfield = TRUE; phdr->phy_info.info_11n.short_gi = ((flags & DOT11N_FLAG_SHORT_GI) != 0); phdr->phy_info.info_11n.greenfield = ((flags & DOT11N_FLAG_GREENFIELD) != 0); + if (DOT11N_IS_AGGREGATE(flags)) { + phdr->has_aggregate_info = 1; + phdr->aggregate_flags = 0; + if (!(flags & DOT11N_FLAG_MORE_AGGREGATES)) + phdr->aggregate_flags |= PHDR_802_11_LAST_PART_OF_A_MPDU; + if (flags & DOT11N_FLAG_AGG_CRC_ERROR) + phdr->aggregate_flags |= PHDR_802_11_A_MPDU_DELIM_CRC_ERROR; + } ptvcursor_add_with_subtree(csr, hf_80211n_mac_flags, 4, ENC_LITTLE_ENDIAN, ett_dot11n_mac_flags); ptvcursor_add_no_advance(csr, hf_80211n_mac_flags_greenfield, 4, ENC_LITTLE_ENDIAN); @@ -666,6 +671,10 @@ dissect_80211n_mac(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int ptvcursor_add(csr, hf_80211n_mac_flags_delimiter_crc_after, 4, ENC_LITTLE_ENDIAN); /* Last */ ptvcursor_pop_subtree(csr); + if (DOT11N_IS_AGGREGATE(flags)) { + *ampdu_id = tvb_get_letohl(tvb, ptvcursor_current_offset(csr)); + phdr->aggregate_id = *ampdu_id; + } ptvcursor_add(csr, hf_80211n_mac_ampdu_id, 4, ENC_LITTLE_ENDIAN); ptvcursor_add(csr, hf_80211n_mac_num_delimiters, 1, ENC_LITTLE_ENDIAN); diff --git a/wiretap/wtap.h b/wiretap/wtap.h index 5c7b7afa52..0b9dbcb620 100644 --- a/wiretap/wtap.h +++ b/wiretap/wtap.h @@ -779,6 +779,7 @@ struct ieee_802_11_phdr { guint has_signal_dbm:1; guint has_noise_dbm:1; guint has_tsf_timestamp:1; + guint has_aggregate_info:1; /* aggregate flags and ID */ guint16 channel; /* Channel number */ guint32 frequency; /* Channel center frequency */ @@ -788,8 +789,16 @@ struct ieee_802_11_phdr { gint8 signal_dbm; /* Signal level, in dBm */ gint8 noise_dbm; /* Noise level, in dBm */ guint64 tsf_timestamp; + guint32 aggregate_flags; /* A-MPDU flags */ + guint32 aggregate_id; /* ID for A-MPDU reassembly */ }; +/* + * A-MPDU flags. + */ +#define PHDR_802_11_LAST_PART_OF_A_MPDU 0x00000001 /* this is the last part of an A-MPDU */ +#define PHDR_802_11_A_MPDU_DELIM_CRC_ERROR 0x00000002 /* delimiter CRC error after this part */ + /* Packet "pseudo-header" for the output from CoSine L2 debug output. */ #define COSINE_MAX_IF_NAME_LEN 128