diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index ad63332f690c..c31e302d05c9 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -434,7 +434,7 @@ int wfx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, wvif->link_id_map |= BIT(sta_priv->link_id); WARN_ON(!sta_priv->link_id); WARN_ON(sta_priv->link_id >= HIF_LINK_ID_MAX); - hif_map_link(wvif, sta->addr, 0, sta_priv->link_id); + hif_map_link(wvif, sta->addr, sta->mfp ? 2 : 0, sta_priv->link_id); return 0; } @@ -474,6 +474,31 @@ static int wfx_upload_ap_templates(struct wfx_vif *wvif) return 0; } +static void wfx_set_mfp_ap(struct wfx_vif *wvif) +{ + struct sk_buff *skb = ieee80211_beacon_get(wvif->wdev->hw, wvif->vif); + const int ieoffset = offsetof(struct ieee80211_mgmt, u.beacon.variable); + const u16 *ptr = (u16 *)cfg80211_find_ie(WLAN_EID_RSN, + skb->data + ieoffset, + skb->len - ieoffset); + const int pairwise_cipher_suite_count_offset = 8 / sizeof(u16); + const int pairwise_cipher_suite_size = 4 / sizeof(u16); + const int akm_suite_size = 4 / sizeof(u16); + + if (ptr) { + ptr += pairwise_cipher_suite_count_offset; + if (WARN_ON(ptr > (u16 *)skb_tail_pointer(skb))) + return; + ptr += 1 + pairwise_cipher_suite_size * *ptr; + if (WARN_ON(ptr > (u16 *)skb_tail_pointer(skb))) + return; + ptr += 1 + akm_suite_size * *ptr; + if (WARN_ON(ptr > (u16 *)skb_tail_pointer(skb))) + return; + hif_set_mfp(wvif, *ptr & BIT(7), *ptr & BIT(6)); + } +} + int wfx_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; @@ -488,6 +513,7 @@ int wfx_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif) ret = hif_start(wvif, &vif->bss_conf, wvif->channel); if (ret > 0) return -EIO; + wfx_set_mfp_ap(wvif); return ret; }