len += 8;
if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
len += 1;
- if (local->hw.flags & IEEE80211_HW_NOISE_DBM)
- len += 1;
if (len & 1) /* padding for RX_FLAGS if necessary */
len++;
if (ieee80211_is_action(hdr->frame_control)) {
mgmt = (struct ieee80211_mgmt *)hdr;
- if (mgmt->u.action.category != MESH_PLINK_CATEGORY)
+ if (mgmt->u.action.category != WLAN_CATEGORY_MESH_PLINK)
return RX_DROP_MONITOR;
return RX_CONTINUE;
}
tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
- if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL)
- goto dont_reorder;
+ spin_lock(&sta->lock);
+
+ if (!sta->ampdu_mlme.tid_active_rx[tid])
+ goto dont_reorder_unlock;
tid_agg_rx = sta->ampdu_mlme.tid_rx[tid];
/* qos null data frames are excluded */
if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC)))
- goto dont_reorder;
+ goto dont_reorder_unlock;
/* new, potentially un-ordered, ampdu frame - process it */
/* if this mpdu is fragmented - terminate rx aggregation session */
sc = le16_to_cpu(hdr->seq_ctrl);
if (sc & IEEE80211_SCTL_FRAG) {
- ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr,
- tid, 0, WLAN_REASON_QSTA_REQUIRE_SETUP);
+ spin_unlock(&sta->lock);
+ __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT,
+ WLAN_REASON_QSTA_REQUIRE_SETUP);
dev_kfree_skb(skb);
return;
}
- if (ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb, frames))
+ if (ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb, frames)) {
+ spin_unlock(&sta->lock);
return;
+ }
+ dont_reorder_unlock:
+ spin_unlock(&sta->lock);
dont_reorder:
__skb_queue_tail(frames, skb);
}
rx->key = key;
return RX_CONTINUE;
} else {
+ u8 keyid;
/*
* The device doesn't give us the IV so we won't be
* able to look up the key. That's ok though, we
* no need to call ieee80211_wep_get_keyidx,
* it verifies a bunch of things we've done already
*/
- keyidx = rx->skb->data[hdrlen + 3] >> 6;
+ skb_copy_bits(rx->skb, hdrlen + 3, &keyid, 1);
+ keyidx = keyid >> 6;
rx->key = rcu_dereference(rx->sdata->keys[keyidx]);
if (skb_linearize(rx->skb))
return RX_DROP_UNUSABLE;
+ hdr = (struct ieee80211_hdr *)rx->skb->data;
+
/* Check for weak IVs if possible */
if (rx->sta && rx->key->conf.alg == ALG_WEP &&
ieee80211_is_data(hdr->frame_control) &&
ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
__le16 fc = hdr->frame_control;
- int res;
- res = ieee80211_drop_unencrypted(rx, fc);
- if (unlikely(res))
- return res;
+ /*
+ * Pass through unencrypted frames if the hardware has
+ * decrypted them already.
+ */
+ if (status->flag & RX_FLAG_DECRYPTED)
+ return 0;
if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) {
- if (unlikely(ieee80211_is_unicast_robust_mgmt_frame(rx->skb) &&
+ if (unlikely(!ieee80211_has_protected(fc) &&
+ ieee80211_is_unicast_robust_mgmt_frame(rx->skb) &&
rx->key))
return -EACCES;
/* BIP does not use Protected field, so need to check MMIE */
if (unlikely(ieee80211_is_multicast_robust_mgmt_frame(rx->skb) &&
- ieee80211_get_mmie_keyidx(rx->skb) < 0 &&
- rx->key))
+ ieee80211_get_mmie_keyidx(rx->skb) < 0))
return -EACCES;
/*
* When using MFP, Action frames are not allowed prior to
if (ieee80211_is_back_req(bar->frame_control)) {
if (!rx->sta)
return RX_DROP_MONITOR;
+ spin_lock(&rx->sta->lock);
tid = le16_to_cpu(bar->control) >> 12;
- if (rx->sta->ampdu_mlme.tid_state_rx[tid]
- != HT_AGG_STATE_OPERATIONAL)
+ if (!rx->sta->ampdu_mlme.tid_active_rx[tid]) {
+ spin_unlock(&rx->sta->lock);
return RX_DROP_MONITOR;
+ }
tid_agg_rx = rx->sta->ampdu_mlme.tid_rx[tid];
start_seq_num = le16_to_cpu(bar->start_seq_num) >> 4;
ieee80211_release_reorder_frames(hw, tid_agg_rx, start_seq_num,
frames);
kfree_skb(skb);
+ spin_unlock(&rx->sta->lock);
return RX_QUEUED;
}
goto handled;
}
break;
+ case WLAN_CATEGORY_MESH_PLINK:
+ case WLAN_CATEGORY_MESH_PATH_SEL:
+ if (ieee80211_vif_is_mesh(&sdata->vif))
+ return ieee80211_mesh_rx_mgmt(sdata, rx->skb);
+ break;
}
/*