aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2015-06-18 13:12:43 -0700
committerGuy Harris <guy@alum.mit.edu>2015-06-18 20:13:50 +0000
commitd9b36c46d025519a309bf34c1255e1f9a2856a41 (patch)
treec4058af3b6ab611043dff9a26364ae2232a1f984
parentf00e6fbefe073bd74e934c2e5f2494e0d0da13ff (diff)
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>
-rw-r--r--epan/dissectors/packet-ieee80211-radio.c8
-rw-r--r--epan/dissectors/packet-ieee80211-radiotap.c37
-rw-r--r--epan/dissectors/packet-ieee80211.c80
-rw-r--r--epan/dissectors/packet-ppi.c40
4 files changed, 106 insertions, 59 deletions
diff --git a/epan/dissectors/packet-ieee80211-radio.c b/epan/dissectors/packet-ieee80211-radio.c
index da32cfd376..f965396e14 100644
--- a/epan/dissectors/packet-ieee80211-radio.c
+++ b/epan/dissectors/packet-ieee80211-radio.c
@@ -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");
diff --git a/epan/dissectors/packet-ieee80211-radiotap.c b/epan/dissectors/packet-ieee80211-radiotap.c
index 179c650956..44d7c2e0fb 100644
--- a/epan/dissectors/packet-ieee80211-radiotap.c
+++ b/epan/dissectors/packet-ieee80211-radiotap.c
@@ -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);
}
diff --git a/epan/dissectors/packet-ieee80211.c b/epan/dissectors/packet-ieee80211.c
index 339dcf5c75..a09caaca2c 100644
--- a/epan/dissectors/packet-ieee80211.c
+++ b/epan/dissectors/packet-ieee80211.c
@@ -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 */
diff --git a/epan/dissectors/packet-ppi.c b/epan/dissectors/packet-ppi.c
index c6ef8173a4..5541bcd779 100644
--- a/epan/dissectors/packet-ppi.c
+++ b/epan/dissectors/packet-ppi.c
@@ -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");