From 5e2e9de9302f43de899d6d450ed75a17a6d73035 Mon Sep 17 00:00:00 2001 From: Guy Harris Date: Wed, 8 Aug 2018 19:25:30 -0700 Subject: [PATCH] Pass zero-length PSDU type information to the radio dissector. We call that dissector even for zero-length PSDUs, so the radio information is shown. We also show the zero-length PSDU type. We don't call the 802.11 dissector for zero-length PSDU frames. That way, you don't have to open up the radiotap information to find out about zero-length PSDU frames, we can support zero-length PSDU information for other pseudo-headers and file types if they support it, and taps using the radio information can get zero-length PSDU frame information. Change-Id: I7d5da4ea978d8ca4889fc76160f11e3416b4d036 Reviewed-on: https://code.wireshark.org/review/29034 Reviewed-by: Guy Harris --- epan/dissectors/packet-ieee80211-radio.c | 32 +++++++++++++++--- epan/dissectors/packet-ieee80211-radiotap.c | 35 +++++++++++-------- wiretap/wtap.h | 37 +++++++++++++-------- 3 files changed, 72 insertions(+), 32 deletions(-) diff --git a/epan/dissectors/packet-ieee80211-radio.c b/epan/dissectors/packet-ieee80211-radio.c index 91bc7ea79d..1800065513 100644 --- a/epan/dissectors/packet-ieee80211-radio.c +++ b/epan/dissectors/packet-ieee80211-radio.c @@ -86,7 +86,7 @@ static int hf_wlan_radio_aggregate_duration = -1; static int hf_wlan_radio_ifs = -1; static int hf_wlan_radio_start_tsf = -1; static int hf_wlan_radio_end_tsf = -1; - +static int hf_wlan_zero_length_psdu_type = -1; static expert_field ei_wlan_radio_assumed_short_preamble = EI_INIT; static expert_field ei_wlan_radio_assumed_non_greenfield = EI_INIT; @@ -170,6 +170,12 @@ static const value_string fec_vals[] = { { 0, NULL } }; +static const value_string zero_length_psdu_vals[] = { + { 0, "sounding PPDU" }, + { 1, "data not captured" }, + { 255, "vendor-specific" }, + { 0, NULL } +}; /* * Lookup for the MCS index (0-76) * returning the number of data bits per symbol @@ -439,9 +445,8 @@ static void adjust_agg_tsf(gpointer data, gpointer user_data) * Dissect 802.11 pseudo-header containing radio information. */ static void -dissect_wlan_radio_phdr (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void *data) +dissect_wlan_radio_phdr(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, struct ieee_802_11_phdr *phdr) { - struct ieee_802_11_phdr *phdr = (struct ieee_802_11_phdr *)data; proto_item *ti; proto_tree *radio_tree; float data_rate = 0.0f; @@ -1189,6 +1194,8 @@ dissect_wlan_radio_phdr (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, } } } /* if (have_data_rate) */ + if (phdr->has_zero_length_psdu_type) + proto_tree_add_uint(radio_tree, hf_wlan_zero_length_psdu_type, tvb, 0, 0, phdr->zero_length_psdu_type); if (wlan_radio_timeline_enabled) { tap_queue_packet(wlan_radio_timeline_tap, pinfo, wlan_radio_info); @@ -1206,7 +1213,13 @@ dissect_wlan_radio_phdr (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, static int dissect_wlan_radio (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void *data) { - dissect_wlan_radio_phdr (tvb, pinfo, tree, data); + struct ieee_802_11_phdr *phdr = (struct ieee_802_11_phdr *)data; + + dissect_wlan_radio_phdr(tvb, pinfo, tree, phdr); + + /* Is there anything there? A 0-length-psdu has no frame data. */ + if (phdr->has_zero_length_psdu_type) + return tvb_captured_length(tvb); /* dissect the 802.11 packet next */ return call_dissector_with_data(ieee80211_handle, tvb, pinfo, tree, data); @@ -1219,7 +1232,13 @@ dissect_wlan_radio (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void static int dissect_wlan_noqos_radio (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void *data) { - dissect_wlan_radio_phdr (tvb, pinfo, tree, data); + struct ieee_802_11_phdr *phdr = (struct ieee_802_11_phdr *)data; + + dissect_wlan_radio_phdr(tvb, pinfo, tree, phdr); + + /* Is there anything there? A 0-length-psdu has no frame data. */ + if (phdr->has_zero_length_psdu_type) + return tvb_captured_length(tvb); /* dissect the 802.11 packet next */ return call_dissector_with_data(ieee80211_noqos_handle, tvb, pinfo, tree, data); @@ -1436,6 +1455,9 @@ void proto_register_ieee80211_radio(void) "Total duration of the aggregate in microseconds, including any preamble or plcp header. " "Calculated from the total subframe lengths, modulation and other phy data.", HFILL }}, + {&hf_wlan_zero_length_psdu_type, + {"Zero-length PSDU Type", "wlan_radio.zero_len_psdu.type", FT_UINT8, BASE_HEX, VALS(zero_length_psdu_vals), 0x0, + "Type of zero-length PSDU", HFILL}}, }; static gint *ett[] = { diff --git a/epan/dissectors/packet-ieee80211-radiotap.c b/epan/dissectors/packet-ieee80211-radiotap.c index 2ba0b45a21..e08b4265f4 100644 --- a/epan/dissectors/packet-ieee80211-radiotap.c +++ b/epan/dissectors/packet-ieee80211-radiotap.c @@ -1330,15 +1330,33 @@ static const range_string zero_length_psdu_rsvals[] = { static void dissect_radiotap_0_length_psdu(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, - int offset) + int offset, struct ieee_802_11_phdr *phdr) { proto_tree *zero_len_tree = NULL; + guint32 psdu_type; zero_len_tree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_radiotap_0_length_psdu, NULL, "0-length PSDU"); - proto_tree_add_item(zero_len_tree, hf_radiotap_0_length_psdu_type, - tvb, offset, 1, ENC_NA); + proto_tree_add_item_ret_uint(zero_len_tree, hf_radiotap_0_length_psdu_type, + tvb, offset, 1, ENC_NA, &psdu_type); + switch (psdu_type) { + + case 0: + phdr->has_zero_length_psdu_type = TRUE; + phdr->zero_length_psdu_type = PHDR_802_11_SOUNDING_PSDU; + break; + + case 1: + phdr->has_zero_length_psdu_type = TRUE; + phdr->zero_length_psdu_type = PHDR_802_11_DATA_NOT_CAPTURED; + break; + + case 0xff: + phdr->has_zero_length_psdu_type = TRUE; + phdr->zero_length_psdu_type = PHDR_802_11_0_LENGTH_PSDU_VENDOR_SPECIFIC; + break; + } } static void @@ -1867,7 +1885,6 @@ dissect_radiotap(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* u static struct _radiotap_info rtp_info_arr; struct ieee80211_radiotap_iterator iter; struct ieee_802_11_phdr phdr; - gboolean zero_length_psdu = FALSE; guchar *bmap_start; guint n_bitmaps; guint i; @@ -2678,8 +2695,7 @@ dissect_radiotap(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* u dissect_radiotap_he_mu_info(tvb, pinfo, radiotap_tree, offset); break; case IEEE80211_RADIOTAP_0_LENGTH_PSDU: - dissect_radiotap_0_length_psdu(tvb, pinfo, radiotap_tree, offset); - zero_length_psdu = TRUE; + dissect_radiotap_0_length_psdu(tvb, pinfo, radiotap_tree, offset, &phdr); break; } } @@ -2691,13 +2707,6 @@ dissect_radiotap(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* u proto_item_append_text(ti, " (malformed)"); } - /* - * Is there anything there? A 0-length-psdu has no frame data. - */ - if (zero_length_psdu) { - return tvb_captured_length(tvb); - } - hand_off_to_80211: /* Grab the rest of the frame. */ next_tvb = tvb_new_subset_remaining(tvb, length); diff --git a/wiretap/wtap.h b/wiretap/wtap.h index 7f2eeb9184..8c7a8dc50f 100644 --- a/wiretap/wtap.h +++ b/wiretap/wtap.h @@ -797,10 +797,10 @@ union ieee_802_11_phy_info { }; struct ieee_802_11_phdr { - gint fcs_len; /* Number of bytes of FCS - -1 means "unknown" */ - gboolean decrypted; /* TRUE if frame is decrypted even if "protected" bit is set */ - gboolean datapad; /* TRUE if frame has padding between 802.11 header and payload */ - guint phy; /* PHY type */ + gint fcs_len; /* Number of bytes of FCS - -1 means "unknown" */ + gboolean decrypted; /* TRUE if frame is decrypted even if "protected" bit is set */ + gboolean datapad; /* TRUE if frame has padding between 802.11 header and payload */ + guint phy; /* PHY type */ union ieee_802_11_phy_info phy_info; /* Which of this information is present? */ @@ -812,18 +812,20 @@ 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 */ + guint has_aggregate_info:1; /* aggregate flags and ID */ + guint has_zero_length_psdu_type:1; /* zero-length PSDU type */ - guint16 channel; /* Channel number */ - guint32 frequency; /* Channel center frequency */ - guint16 data_rate; /* Data rate, in .5 Mb/s units */ - guint8 signal_percent; /* Signal level, as a percentage */ - guint8 noise_percent; /* Noise level, as a percentage */ - gint8 signal_dbm; /* Signal level, in dBm */ - gint8 noise_dbm; /* Noise level, in dBm */ + guint16 channel; /* Channel number */ + guint32 frequency; /* Channel center frequency */ + guint16 data_rate; /* Data rate, in .5 Mb/s units */ + guint8 signal_percent; /* Signal level, as a percentage */ + guint8 noise_percent; /* Noise level, as a percentage */ + 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 */ + guint32 aggregate_flags; /* A-MPDU flags */ + guint32 aggregate_id; /* ID for A-MPDU reassembly */ + guint8 zero_length_psdu_type; /* type of zero-length PSDU */ }; /* @@ -832,6 +834,13 @@ struct ieee_802_11_phdr { #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 */ +/* + * Zero-length PSDU types. + */ +#define PHDR_802_11_SOUNDING_PSDU 0 /* sounding PPDU */ +#define PHDR_802_11_DATA_NOT_CAPTURED 1 /* data not captured, (e.g. multi-user PPDU) */ +#define PHDR_802_11_0_LENGTH_PSDU_VENDOR_SPECIFIC 0xff + /* Packet "pseudo-header" for the output from CoSine L2 debug output. */ #define COSINE_MAX_IF_NAME_LEN 128