|
@@ -1113,6 +1113,40 @@ static inline u8 get_rate_idx(u32 rate, enum ieee80211_band band)
|
|
|
return rate_idx;
|
|
|
}
|
|
|
|
|
|
+/* If keys are configured, HW decrypts all frames
|
|
|
+ * with protected bit set. Mark such frames as decrypted.
|
|
|
+ */
|
|
|
+static void ath10k_wmi_handle_wep_reauth(struct ath10k *ar,
|
|
|
+ struct sk_buff *skb,
|
|
|
+ struct ieee80211_rx_status *status)
|
|
|
+{
|
|
|
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
|
|
+ unsigned int hdrlen;
|
|
|
+ bool peer_key;
|
|
|
+ u8 *addr, keyidx;
|
|
|
+
|
|
|
+ if (!ieee80211_is_auth(hdr->frame_control) ||
|
|
|
+ !ieee80211_has_protected(hdr->frame_control))
|
|
|
+ return;
|
|
|
+
|
|
|
+ hdrlen = ieee80211_hdrlen(hdr->frame_control);
|
|
|
+ if (skb->len < (hdrlen + IEEE80211_WEP_IV_LEN))
|
|
|
+ return;
|
|
|
+
|
|
|
+ keyidx = skb->data[hdrlen + (IEEE80211_WEP_IV_LEN - 1)] >> WEP_KEYID_SHIFT;
|
|
|
+ addr = ieee80211_get_SA(hdr);
|
|
|
+
|
|
|
+ spin_lock_bh(&ar->data_lock);
|
|
|
+ peer_key = ath10k_mac_is_peer_wep_key_set(ar, addr, keyidx);
|
|
|
+ spin_unlock_bh(&ar->data_lock);
|
|
|
+
|
|
|
+ if (peer_key) {
|
|
|
+ ath10k_dbg(ar, ATH10K_DBG_MAC,
|
|
|
+ "mac wep key present for peer %pM\n", addr);
|
|
|
+ status->flag |= RX_FLAG_DECRYPTED;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
|
|
|
{
|
|
|
struct wmi_mgmt_rx_event_v1 *ev_v1;
|
|
@@ -1203,6 +1237,8 @@ static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
|
|
|
hdr = (struct ieee80211_hdr *)skb->data;
|
|
|
fc = le16_to_cpu(hdr->frame_control);
|
|
|
|
|
|
+ ath10k_wmi_handle_wep_reauth(ar, skb, status);
|
|
|
+
|
|
|
/* FW delivers WEP Shared Auth frame with Protected Bit set and
|
|
|
* encrypted payload. However in case of PMF it delivers decrypted
|
|
|
* frames with Protected Bit set. */
|