diff options
author | Guy Harris <guy@alum.mit.edu> | 2015-06-18 13:12:43 -0700 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2015-06-18 20:13:50 +0000 |
commit | d9b36c46d025519a309bf34c1255e1f9a2856a41 (patch) | |
tree | c4058af3b6ab611043dff9a26364ae2232a1f984 | |
parent | f00e6fbefe073bd74e934c2e5f2494e0d0da13ff (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.c | 8 | ||||
-rw-r--r-- | epan/dissectors/packet-ieee80211-radiotap.c | 37 | ||||
-rw-r--r-- | epan/dissectors/packet-ieee80211.c | 80 | ||||
-rw-r--r-- | epan/dissectors/packet-ppi.c | 40 |
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"); |