Pass the 802.11 pseudo-header as an argument.

Rather than accessing it through pinfo->pseudo_header, have it passed as
an argument.

This means we no longer tweak the pseudo-header filled in by libwiretap,
but instead construct our own pseudo-header, which is a bit cleaner.

It also opens up the possibility of other dissectors passing radio
information down to the 802.11 dissector, so it can display it in a
better-organized format than the raw metadata headers for
radiotap/PPI/Prism/AVS/etc., and having some of the options for 802.11
dissection (Atheros padding, Centrino stuff, etc.) also passed in
through that pseudo-header so we have fewer arguments to
dissect_ieee80211_common().

Change-Id: I470300a0407ebf029c542f7ca5878593563a70a9
Reviewed-on: https://code.wireshark.org/review/8980
Reviewed-by: Guy Harris <guy@alum.mit.edu>
This commit is contained in:
Guy Harris 2015-06-18 13:12:43 -07:00
parent f00e6fbefe
commit d9b36c46d0
4 changed files with 106 additions and 59 deletions

View File

@ -464,8 +464,8 @@ static gint ett_radio = -1;
* Dissect 802.11 with a variable-length link-layer header and a pseudo-
* header containing radio information.
*/
static void
dissect_radio (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
static int
dissect_radio (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void *data)
{
proto_item *ti = NULL;
proto_tree *radio_tree = NULL;
@ -590,7 +590,7 @@ dissect_radio (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
/* dissect the 802.11 header next */
pinfo->current_proto = "IEEE 802.11";
call_dissector(ieee80211_handle, tvb, pinfo, tree);
return call_dissector_with_data(ieee80211_handle, tvb, pinfo, tree, data);
}
static hf_register_info hf_radio[] = {
@ -652,7 +652,7 @@ void proto_reg_handoff_ieee80211_radio(void)
dissector_handle_t radio_handle;
/* Register handoff to radio-header dissectors */
radio_handle = create_dissector_handle(dissect_radio, proto_radio);
radio_handle = new_create_dissector_handle(dissect_radio, proto_radio);
dissector_add_uint("wtap_encap", WTAP_ENCAP_IEEE_802_11_WITH_RADIO,
radio_handle);
ieee80211_handle = find_dissector("wlan");

View File

@ -586,6 +586,7 @@ dissect_radiotap(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
struct _radiotap_info *radiotap_info;
static struct _radiotap_info rtp_info_arr;
struct ieee80211_radiotap_iterator iter;
struct ieee_802_11_phdr phdr;
/* our non-standard overrides */
static struct radiotap_override overrides[] = {
@ -601,6 +602,11 @@ dissect_radiotap(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
radiotap_info = &rtp_info_arr;
/* We don't have any 802.11 metadata yet. */
phdr.fcs_len = -1;
phdr.decrypted = FALSE;
phdr.presence_flags = 0;
col_set_str(pinfo->cinfo, COL_PROTOCOL, "WLAN");
col_clear(pinfo->cinfo, COL_INFO);
@ -827,6 +833,11 @@ dissect_radiotap(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
case IEEE80211_RADIOTAP_FLAGS: {
rflags = tvb_get_guint8(tvb, offset);
if (rflags & IEEE80211_RADIOTAP_F_FCS)
phdr.fcs_len = 4;
else
phdr.fcs_len = 0;
if (tree) {
proto_tree *flags_tree;
@ -1438,12 +1449,6 @@ dissect_radiotap(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
proto_item_append_text(ti, " (malformed)");
}
/* This handles the case of an FCS exiting 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;
hand_off_to_80211:
/* Grab the rest of the frame. */
next_tvb = tvb_new_subset_remaining(tvb, length);
@ -1452,17 +1457,19 @@ dissect_radiotap(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
* This can only happen if the backward-compat configuration option
* is chosen by the user. */
if (hdr_fcs_ti) {
guint captured_length = tvb_captured_length(next_tvb);
guint reported_length = tvb_reported_length(next_tvb);
guint fcs_len = (phdr.fcs_len > 0) ? phdr.fcs_len : 0;
/* 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) {
if (captured_length >= reported_length &&
captured_length > fcs_len) {
calc_fcs =
crc32_802_tvb(next_tvb,
tvb_length(next_tvb) -
pinfo->pseudo_header->ieee_802_11.fcs_len);
crc32_802_tvb(next_tvb, tvb_length(next_tvb) - 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. */
@ -1486,10 +1493,10 @@ dissect_radiotap(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
}
}
/* dissect the 802.11 header next */
call_dissector((rflags & IEEE80211_RADIOTAP_F_DATAPAD) ?
ieee80211_datapad_handle : ieee80211_handle,
next_tvb, pinfo, tree);
/* dissect the 802.11 packet next */
call_dissector_with_data((rflags & IEEE80211_RADIOTAP_F_DATAPAD) ?
ieee80211_datapad_handle : ieee80211_handle, next_tvb, pinfo,
tree, &phdr);
tap_queue_packet(radiotap_tap, pinfo, radiotap_info);
}

View File

@ -16561,11 +16561,12 @@ typedef enum {
* have to go digging for bits in various locations instead.
*/
static void
static int
dissect_ieee80211_common (tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, gboolean fixed_length_header, gint fcs_len,
gboolean wlan_broken_fc, gboolean datapad,
gboolean is_ht, gboolean is_centrino)
gboolean is_ht, gboolean is_centrino,
struct ieee_802_11_phdr *phdr)
{
guint16 fcf, flags, frame_type_subtype, ctrl_fcf, ctrl_type_subtype;
guint16 seq_control;
@ -17701,7 +17702,7 @@ dissect_ieee80211_common (tvbuff_t *tvb, packet_info *pinfo,
* No-data frames don't have a body.
*/
if (DATA_FRAME_IS_NULL(frame_type_subtype))
return;
return tvb_captured_length(tvb);
if (!wlan_subdissector) {
guint fnum = 0;
@ -17759,15 +17760,17 @@ dissect_ieee80211_common (tvbuff_t *tvb, packet_info *pinfo,
break;
case CONTROL_FRAME:
return;
case EXTENSION_FRAME:
return tvb_captured_length(tvb);
case EXTENSION_FRAME:
break;
default:
return;
return tvb_captured_length(tvb);
}
if (IS_PROTECTED(FCF_FLAGS(fcf))
&& !pinfo->pseudo_header->ieee_802_11.decrypted
&& (phdr == NULL || !phdr->decrypted)
&& (wlan_ignore_wep != WLAN_IGNORE_WEP_WO_IV)) {
/*
* It's a WEP or WPA encrypted frame, and it hasn't already been
@ -18263,17 +18266,21 @@ dissect_ieee80211_common (tvbuff_t *tvb, packet_info *pinfo,
whdr->stats = wlan_stats;
tap_queue_packet(wlan_tap, pinfo, whdr);
memset (&wlan_stats, 0, sizeof wlan_stats);
return tvb_captured_length(tvb);
}
/*
* Dissect 802.11 with a variable-length link-layer header and with the FCS
* presence or absence indicated by the pseudo-header.
*/
static void
dissect_ieee80211 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
static int
dissect_ieee80211 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
dissect_ieee80211_common (tvb, pinfo, tree, FALSE,
pinfo->pseudo_header->ieee_802_11.fcs_len, FALSE, FALSE, FALSE, FALSE);
struct ieee_802_11_phdr *phdr = (struct ieee_802_11_phdr *)data;
return dissect_ieee80211_common (tvb, pinfo, tree, FALSE,
(phdr == NULL) ? -1 : phdr->fcs_len, FALSE, FALSE, FALSE, FALSE, phdr);
}
/*
@ -18283,7 +18290,7 @@ dissect_ieee80211 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
static void
dissect_ieee80211_withfcs (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
dissect_ieee80211_common (tvb, pinfo, tree, FALSE, 4, FALSE, FALSE, FALSE, FALSE);
dissect_ieee80211_common (tvb, pinfo, tree, FALSE, 4, FALSE, FALSE, FALSE, FALSE, NULL);
}
/*
@ -18293,28 +18300,32 @@ dissect_ieee80211_withfcs (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
static void
dissect_ieee80211_withoutfcs (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
dissect_ieee80211_common (tvb, pinfo, tree, FALSE, 0, FALSE, FALSE, FALSE, FALSE);
dissect_ieee80211_common (tvb, pinfo, tree, FALSE, 0, FALSE, FALSE, FALSE, FALSE, NULL);
}
/*
* Dissect 802.11 with a variable-length link-layer header.
*/
static void
dissect_ieee80211_centrino(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
static int
dissect_ieee80211_centrino(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
dissect_ieee80211_common (tvb, pinfo, tree, FALSE,
pinfo->pseudo_header->ieee_802_11.fcs_len, FALSE, FALSE, FALSE, TRUE);
struct ieee_802_11_phdr *phdr = (struct ieee_802_11_phdr *)data;
return dissect_ieee80211_common (tvb, pinfo, tree, FALSE,
(phdr == NULL) ? -1 : phdr->fcs_len, FALSE, FALSE, FALSE, TRUE, phdr);
}
/*
* Dissect 802.11 with a variable-length link-layer header and data padding
* and with the FCS presence or absence indicated by the pseudo-header.
*/
static void
dissect_ieee80211_datapad (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
static int
dissect_ieee80211_datapad (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
dissect_ieee80211_common (tvb, pinfo, tree, FALSE,
pinfo->pseudo_header->ieee_802_11.fcs_len, FALSE, TRUE, FALSE, FALSE);
struct ieee_802_11_phdr *phdr = (struct ieee_802_11_phdr *)data;
return dissect_ieee80211_common (tvb, pinfo, tree, FALSE,
(phdr == NULL) ? -1 : phdr->fcs_len, FALSE, TRUE, FALSE, FALSE, phdr);
}
/*
@ -18324,7 +18335,7 @@ dissect_ieee80211_datapad (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
static void
dissect_ieee80211_datapad_withfcs (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
dissect_ieee80211_common (tvb, pinfo, tree, FALSE, 4, FALSE, TRUE, FALSE, FALSE);
dissect_ieee80211_common (tvb, pinfo, tree, FALSE, 4, FALSE, TRUE, FALSE, FALSE, NULL);
}
/*
@ -18334,7 +18345,7 @@ dissect_ieee80211_datapad_withfcs (tvbuff_t *tvb, packet_info *pinfo, proto_tree
static void
dissect_ieee80211_datapad_withoutfcs (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
dissect_ieee80211_common (tvb, pinfo, tree, FALSE, 0, FALSE, TRUE, FALSE, FALSE);
dissect_ieee80211_common (tvb, pinfo, tree, FALSE, 0, FALSE, TRUE, FALSE, FALSE, NULL);
}
/*
@ -18345,7 +18356,7 @@ dissect_ieee80211_datapad_withoutfcs (tvbuff_t *tvb, packet_info *pinfo, proto_t
static void
dissect_ieee80211_bsfc (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
dissect_ieee80211_common (tvb, pinfo, tree, FALSE, 0, TRUE, FALSE, FALSE, FALSE);
dissect_ieee80211_common (tvb, pinfo, tree, FALSE, 0, TRUE, FALSE, FALSE, FALSE, NULL);
}
/*
@ -18355,7 +18366,7 @@ dissect_ieee80211_bsfc (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
static void
dissect_ieee80211_fixed (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
dissect_ieee80211_common (tvb, pinfo, tree, TRUE, 0, FALSE, FALSE, FALSE, FALSE);
dissect_ieee80211_common (tvb, pinfo, tree, TRUE, 0, FALSE, FALSE, FALSE, FALSE, NULL);
}
/*
@ -18363,11 +18374,13 @@ dissect_ieee80211_fixed (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
* XXX - Can we tell if a frame is +HTC just by looking at the MAC header?
* If so, we can dispense with this.
*/
static void
dissect_ieee80211_ht (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
static int
dissect_ieee80211_ht (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
dissect_ieee80211_common (tvb, pinfo, tree, FALSE,
pinfo->pseudo_header->ieee_802_11.fcs_len, FALSE, FALSE, TRUE, FALSE);
struct ieee_802_11_phdr *phdr = (struct ieee_802_11_phdr *)data;
return dissect_ieee80211_common (tvb, pinfo, tree, FALSE,
(phdr == NULL) ? -1 : phdr->fcs_len, FALSE, FALSE, TRUE, FALSE, phdr);
}
static void
@ -26914,15 +26927,15 @@ proto_register_ieee80211 (void)
expert_ieee80211 = expert_register_protocol(proto_wlan);
expert_register_field_array(expert_ieee80211, ei, array_length(ei));
register_dissector("wlan", dissect_ieee80211, proto_wlan);
new_register_dissector("wlan", dissect_ieee80211, proto_wlan);
register_dissector("wlan_withfcs", dissect_ieee80211_withfcs, proto_wlan);
register_dissector("wlan_withoutfcs", dissect_ieee80211_withoutfcs, proto_wlan);
register_dissector("wlan_fixed", dissect_ieee80211_fixed, proto_wlan);
register_dissector("wlan_bsfc", dissect_ieee80211_bsfc, proto_wlan);
register_dissector("wlan_datapad", dissect_ieee80211_datapad, proto_wlan);
new_register_dissector("wlan_datapad", dissect_ieee80211_datapad, proto_wlan);
register_dissector("wlan_datapad_withfcs", dissect_ieee80211_datapad_withfcs, proto_wlan);
register_dissector("wlan_datapad_withoutfcs", dissect_ieee80211_datapad_withoutfcs, proto_wlan);
register_dissector("wlan_ht", dissect_ieee80211_ht, proto_wlan);
new_register_dissector("wlan_ht", dissect_ieee80211_ht, proto_wlan);
register_init_routine(wlan_defragment_init);
register_init_routine(wlan_retransmit_init);
@ -27145,8 +27158,9 @@ proto_reg_handoff_ieee80211(void)
ieee80211_handle = find_dissector("wlan");
dissector_add_uint("wtap_encap", WTAP_ENCAP_IEEE_802_11, ieee80211_handle);
dissector_add_uint("wtap_encap", WTAP_ENCAP_IEEE_802_11_WITH_RADIO, ieee80211_handle);
centrino_handle = create_dissector_handle( dissect_ieee80211_centrino, proto_wlan );
centrino_handle = new_create_dissector_handle( dissect_ieee80211_centrino, proto_wlan );
dissector_add_uint("ethertype", ETHERTYPE_CENTRINO_PROMISC, centrino_handle);
/* Register handoff to Aruba GRE */

View File

@ -333,6 +333,7 @@ static expert_field ei_ppi_invalid_length = EI_INIT;
static dissector_handle_t ppi_handle;
static dissector_handle_t data_handle;
static dissector_handle_t ieee80211_handle;
static dissector_handle_t ieee80211_ht_handle;
static dissector_handle_t ppi_gps_handle, ppi_vector_handle, ppi_sensor_handle, ppi_antenna_handle;
static dissector_handle_t ppi_fnet_handle;
@ -476,7 +477,7 @@ add_ppi_field_header(tvbuff_t *tvb, proto_tree *tree, int *offset)
/* XXX - The main dissection function in the 802.11 dissector has the same name. */
static void
dissect_80211_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int data_len)
dissect_80211_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int data_len, struct ieee_802_11_phdr *phdr)
{
proto_tree *ftree;
proto_item *ti;
@ -497,9 +498,9 @@ dissect_80211_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int of
common_flags = tvb_get_letohs(tvb, offset + 8);
if (common_flags & DOT11_FLAG_HAVE_FCS)
pinfo->pseudo_header->ieee_802_11.fcs_len = 4;
phdr->fcs_len = 4;
else
pinfo->pseudo_header->ieee_802_11.fcs_len = 0;
phdr->fcs_len = 0;
csr = ptvcursor_new(ftree, tvb, offset);
@ -752,6 +753,7 @@ dissect_ppi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
guint last_frame = 0;
gboolean is_ht = FALSE;
gint len_remain, /*pad_len = 0,*/ ampdu_len = 0;
struct ieee_802_11_phdr phdr;
col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPI");
col_clear(pinfo->cinfo, COL_INFO);
@ -790,6 +792,11 @@ dissect_ppi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
tot_len -= PPI_V0_HEADER_LEN;
offset += 8;
/* We don't have any 802.11 metadata yet. */
phdr.fcs_len = -1;
phdr.decrypted = FALSE;
phdr.presence_flags = 0;
while (tot_len > 0) {
data_type = tvb_get_letohs(tvb, offset);
data_len = tvb_get_letohs(tvb, offset + 2) + 4;
@ -797,7 +804,8 @@ dissect_ppi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
switch (data_type) {
case PPI_80211_COMMON:
dissect_80211_common(tvb, pinfo, ppi_tree, offset, data_len);
dissect_80211_common(tvb, pinfo, ppi_tree, offset, data_len,
&phdr);
break;
case PPI_80211N_MAC:
@ -988,7 +996,7 @@ dissect_ppi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
add_new_data_source(pinfo, next_tvb, mpdu_str);
ampdu_tree = proto_tree_add_subtree(agg_tree, next_tvb, 0, -1, ett_ampdu_segment, NULL, mpdu_str);
call_dissector(ieee80211_ht_handle, next_tvb, pinfo, ampdu_tree);
call_dissector_with_data(ieee80211_ht_handle, next_tvb, pinfo, ampdu_tree, &phdr);
}
fd_head = fd_head->next;
}
@ -1004,9 +1012,26 @@ dissect_ppi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
}
next_tvb = tvb_new_subset_remaining(tvb, offset);
if (is_ht) { /* We didn't hit the reassembly code */
call_dissector(ieee80211_ht_handle, next_tvb, pinfo, tree);
/*
* You can't just call an arbitrary subdissector based on a
* LINKTYPE_ value, because they may expect a particular
* pseudo-header to be passed to them.
*
* So we look for LINKTYPE_IEEE802_11, which is 105, and, if
* that's what the LINKTYPE_ value is, pass it a pointer
* to a struct ieee_802_11_phdr; otherwise, we pass it
* a null pointer - if it actually matters, we need to
* construct the appropriate pseudo-header and pass that.
*/
if (dlt == 105) {
/* LINKTYPE_IEEE802_11 */
if (is_ht) { /* We didn't hit the reassembly code */
call_dissector_with_data(ieee80211_ht_handle, next_tvb, pinfo, tree, &phdr);
} else {
call_dissector_with_data(ieee80211_handle, next_tvb, pinfo, tree, &phdr);
}
} else {
/* Everything else. This will pass a NULL data argument. */
dissector_try_uint(wtap_encap_dissector_table,
wtap_pcap_encap_to_wtap_encap(dlt), next_tvb, pinfo, tree);
}
@ -1376,6 +1401,7 @@ void
proto_reg_handoff_ppi(void)
{
data_handle = find_dissector("data");
ieee80211_handle = find_dissector("wlan");
ieee80211_ht_handle = find_dissector("wlan_ht");
ppi_gps_handle = find_dissector("ppi_gps");
ppi_vector_handle = find_dissector("ppi_vector");