Commit 3619b088 authored by Johannes Berg's avatar Johannes Berg Committed by Luca Coelho

iwlwifi: mvm: don't hide HE radiotap data in SKB

Hiding the HE radiotap data for further processing of the SKB just
caused another bug when adding the L-SIG data. Simply stop doing
this and adjust the skb->data pointer accordingly when we need to
get the 802.11 header.

While at it, also verify and fix the data alignment, we need to add
2 bytes padding with the vendor data to ensure the whole length of
all radiotap headers is a multiple of 4.
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Fixes: 6721039d ("iwlwifi: mvm: add L-SIG length to radiotap")
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent 32a37853
...@@ -66,11 +66,37 @@ ...@@ -66,11 +66,37 @@
#include "mvm.h" #include "mvm.h"
#include "fw-api.h" #include "fw-api.h"
static void *iwl_mvm_skb_get_hdr(struct sk_buff *skb)
{
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
u8 *data = skb->data;
/* Alignment concerns */
BUILD_BUG_ON(sizeof(struct ieee80211_radiotap_he) % 4);
BUILD_BUG_ON(sizeof(struct ieee80211_radiotap_he_mu) % 4);
BUILD_BUG_ON(sizeof(struct ieee80211_radiotap_lsig) % 4);
BUILD_BUG_ON(sizeof(struct ieee80211_vendor_radiotap) % 4);
if (rx_status->flag & RX_FLAG_RADIOTAP_HE)
data += sizeof(struct ieee80211_radiotap_he);
if (rx_status->flag & RX_FLAG_RADIOTAP_HE_MU)
data += sizeof(struct ieee80211_radiotap_he_mu);
if (rx_status->flag & RX_FLAG_RADIOTAP_LSIG)
data += sizeof(struct ieee80211_radiotap_lsig);
if (rx_status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA) {
struct ieee80211_vendor_radiotap *radiotap = (void *)data;
data += sizeof(*radiotap) + radiotap->len + radiotap->pad;
}
return data;
}
static inline int iwl_mvm_check_pn(struct iwl_mvm *mvm, struct sk_buff *skb, static inline int iwl_mvm_check_pn(struct iwl_mvm *mvm, struct sk_buff *skb,
int queue, struct ieee80211_sta *sta) int queue, struct ieee80211_sta *sta)
{ {
struct iwl_mvm_sta *mvmsta; struct iwl_mvm_sta *mvmsta;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_hdr *hdr = iwl_mvm_skb_get_hdr(skb);
struct ieee80211_rx_status *stats = IEEE80211_SKB_RXCB(skb); struct ieee80211_rx_status *stats = IEEE80211_SKB_RXCB(skb);
struct iwl_mvm_key_pn *ptk_pn; struct iwl_mvm_key_pn *ptk_pn;
int res; int res;
...@@ -197,12 +223,15 @@ static void iwl_mvm_add_rtap_sniffer_config(struct iwl_mvm *mvm, ...@@ -197,12 +223,15 @@ static void iwl_mvm_add_rtap_sniffer_config(struct iwl_mvm *mvm,
{ {
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
struct ieee80211_vendor_radiotap *radiotap; struct ieee80211_vendor_radiotap *radiotap;
int size = sizeof(*radiotap) + sizeof(__le16); const int size = sizeof(*radiotap) + sizeof(__le16);
if (!mvm->cur_aid) if (!mvm->cur_aid)
return; return;
radiotap = skb_put(skb, size); /* ensure alignment */
BUILD_BUG_ON((size + 2) % 4);
radiotap = skb_put(skb, size + 2);
radiotap->align = 1; radiotap->align = 1;
/* Intel OUI */ /* Intel OUI */
radiotap->oui[0] = 0xf6; radiotap->oui[0] = 0xf6;
...@@ -212,10 +241,12 @@ static void iwl_mvm_add_rtap_sniffer_config(struct iwl_mvm *mvm, ...@@ -212,10 +241,12 @@ static void iwl_mvm_add_rtap_sniffer_config(struct iwl_mvm *mvm,
radiotap->subns = 1; radiotap->subns = 1;
radiotap->present = 0x1; radiotap->present = 0x1;
radiotap->len = size - sizeof(*radiotap); radiotap->len = size - sizeof(*radiotap);
radiotap->pad = 0; radiotap->pad = 2;
/* fill the data now */ /* fill the data now */
memcpy(radiotap->data, &mvm->cur_aid, sizeof(mvm->cur_aid)); memcpy(radiotap->data, &mvm->cur_aid, sizeof(mvm->cur_aid));
/* and clear the padding */
memset(radiotap->data + sizeof(__le16), 0, radiotap->pad);
rx_status->flag |= RX_FLAG_RADIOTAP_VENDOR_DATA; rx_status->flag |= RX_FLAG_RADIOTAP_VENDOR_DATA;
} }
...@@ -663,7 +694,7 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm, ...@@ -663,7 +694,7 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
struct sk_buff *skb, struct sk_buff *skb,
struct iwl_rx_mpdu_desc *desc) struct iwl_rx_mpdu_desc *desc)
{ {
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_hdr *hdr = iwl_mvm_skb_get_hdr(skb);
struct iwl_mvm_sta *mvm_sta; struct iwl_mvm_sta *mvm_sta;
struct iwl_mvm_baid_data *baid_data; struct iwl_mvm_baid_data *baid_data;
struct iwl_mvm_reorder_buffer *buffer; struct iwl_mvm_reorder_buffer *buffer;
...@@ -1174,22 +1205,16 @@ static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -1174,22 +1205,16 @@ static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb,
.flags2 = cpu_to_le16(IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW_KNOWN | .flags2 = cpu_to_le16(IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW_KNOWN |
IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN), IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN),
}; };
unsigned int radiotap_len = 0;
he = skb_put_data(skb, &known, sizeof(known)); he = skb_put_data(skb, &known, sizeof(known));
radiotap_len += sizeof(known);
rx_status->flag |= RX_FLAG_RADIOTAP_HE; rx_status->flag |= RX_FLAG_RADIOTAP_HE;
if (phy_data->info_type == IWL_RX_PHY_INFO_TYPE_HE_MU || if (phy_data->info_type == IWL_RX_PHY_INFO_TYPE_HE_MU ||
phy_data->info_type == IWL_RX_PHY_INFO_TYPE_HE_MU_EXT) { phy_data->info_type == IWL_RX_PHY_INFO_TYPE_HE_MU_EXT) {
he_mu = skb_put_data(skb, &mu_known, sizeof(mu_known)); he_mu = skb_put_data(skb, &mu_known, sizeof(mu_known));
radiotap_len += sizeof(mu_known);
rx_status->flag |= RX_FLAG_RADIOTAP_HE_MU; rx_status->flag |= RX_FLAG_RADIOTAP_HE_MU;
} }
/* temporarily hide the radiotap data */
__skb_pull(skb, radiotap_len);
/* report the AMPDU-EOF bit on single frames */ /* report the AMPDU-EOF bit on single frames */
if (!queue && !(phy_info & IWL_RX_MPDU_PHY_AMPDU)) { if (!queue && !(phy_info & IWL_RX_MPDU_PHY_AMPDU)) {
rx_status->flag |= RX_FLAG_AMPDU_DETAILS; rx_status->flag |= RX_FLAG_AMPDU_DETAILS;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment