aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c80
1 files changed, 49 insertions, 31 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 35d8cffc973a..481d5035b397 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1382,19 +1382,26 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
1382 sdata->u.mgd.flags |= IEEE80211_STA_RESET_SIGNAL_AVE; 1382 sdata->u.mgd.flags |= IEEE80211_STA_RESET_SIGNAL_AVE;
1383 1383
1384 if (sdata->vif.p2p) { 1384 if (sdata->vif.p2p) {
1385 u8 noa[2]; 1385 const struct cfg80211_bss_ies *ies;
1386 int ret;
1387 1386
1388 ret = cfg80211_get_p2p_attr(cbss->information_elements, 1387 rcu_read_lock();
1389 cbss->len_information_elements, 1388 ies = rcu_dereference(cbss->ies);
1390 IEEE80211_P2P_ATTR_ABSENCE_NOTICE, 1389 if (ies) {
1391 noa, sizeof(noa)); 1390 u8 noa[2];
1392 if (ret >= 2) { 1391 int ret;
1393 bss_conf->p2p_oppps = noa[1] & 0x80; 1392
1394 bss_conf->p2p_ctwindow = noa[1] & 0x7f; 1393 ret = cfg80211_get_p2p_attr(
1395 bss_info_changed |= BSS_CHANGED_P2P_PS; 1394 ies->data, ies->len,
1396 sdata->u.mgd.p2p_noa_index = noa[0]; 1395 IEEE80211_P2P_ATTR_ABSENCE_NOTICE,
1396 noa, sizeof(noa));
1397 if (ret >= 2) {
1398 bss_conf->p2p_oppps = noa[1] & 0x80;
1399 bss_conf->p2p_ctwindow = noa[1] & 0x7f;
1400 bss_info_changed |= BSS_CHANGED_P2P_PS;
1401 sdata->u.mgd.p2p_noa_index = noa[0];
1402 }
1397 } 1403 }
1404 rcu_read_unlock();
1398 } 1405 }
1399 1406
1400 /* just to be sure */ 1407 /* just to be sure */
@@ -1659,6 +1666,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
1659 } else { 1666 } else {
1660 int ssid_len; 1667 int ssid_len;
1661 1668
1669 rcu_read_lock();
1662 ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); 1670 ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID);
1663 if (WARN_ON_ONCE(ssid == NULL)) 1671 if (WARN_ON_ONCE(ssid == NULL))
1664 ssid_len = 0; 1672 ssid_len = 0;
@@ -1668,6 +1676,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
1668 ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid_len, NULL, 1676 ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid_len, NULL,
1669 0, (u32) -1, true, false, 1677 0, (u32) -1, true, false,
1670 ifmgd->associated->channel, false); 1678 ifmgd->associated->channel, false);
1679 rcu_read_unlock();
1671 } 1680 }
1672 1681
1673 ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms); 1682 ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms);
@@ -1763,6 +1772,7 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
1763 else 1772 else
1764 return NULL; 1773 return NULL;
1765 1774
1775 rcu_read_lock();
1766 ssid = ieee80211_bss_get_ie(cbss, WLAN_EID_SSID); 1776 ssid = ieee80211_bss_get_ie(cbss, WLAN_EID_SSID);
1767 if (WARN_ON_ONCE(ssid == NULL)) 1777 if (WARN_ON_ONCE(ssid == NULL))
1768 ssid_len = 0; 1778 ssid_len = 0;
@@ -1773,6 +1783,7 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
1773 (u32) -1, cbss->channel, 1783 (u32) -1, cbss->channel,
1774 ssid + 2, ssid_len, 1784 ssid + 2, ssid_len,
1775 NULL, 0, true); 1785 NULL, 0, true);
1786 rcu_read_unlock();
1776 1787
1777 return skb; 1788 return skb;
1778} 1789}
@@ -2858,9 +2869,12 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
2858 auth_data->bss->bssid, auth_data->tries, 2869 auth_data->bss->bssid, auth_data->tries,
2859 IEEE80211_AUTH_MAX_TRIES); 2870 IEEE80211_AUTH_MAX_TRIES);
2860 2871
2872 rcu_read_lock();
2861 ssidie = ieee80211_bss_get_ie(auth_data->bss, WLAN_EID_SSID); 2873 ssidie = ieee80211_bss_get_ie(auth_data->bss, WLAN_EID_SSID);
2862 if (!ssidie) 2874 if (!ssidie) {
2875 rcu_read_unlock();
2863 return -EINVAL; 2876 return -EINVAL;
2877 }
2864 /* 2878 /*
2865 * Direct probe is sent to broadcast address as some APs 2879 * Direct probe is sent to broadcast address as some APs
2866 * will not answer to direct packet in unassociated state. 2880 * will not answer to direct packet in unassociated state.
@@ -2868,6 +2882,7 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
2868 ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1], 2882 ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1],
2869 NULL, 0, (u32) -1, true, false, 2883 NULL, 0, (u32) -1, true, false,
2870 auth_data->bss->channel, false); 2884 auth_data->bss->channel, false);
2885 rcu_read_unlock();
2871 } 2886 }
2872 2887
2873 auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; 2888 auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
@@ -3404,9 +3419,7 @@ static u8 ieee80211_ht_vht_rx_chains(struct ieee80211_sub_if_data *sdata,
3404 if (ifmgd->flags & IEEE80211_STA_DISABLE_HT) 3419 if (ifmgd->flags & IEEE80211_STA_DISABLE_HT)
3405 return chains; 3420 return chains;
3406 3421
3407 ht_cap_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, 3422 ht_cap_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_CAPABILITY);
3408 cbss->information_elements,
3409 cbss->len_information_elements);
3410 if (ht_cap_ie && ht_cap_ie[1] >= sizeof(*ht_cap)) { 3423 if (ht_cap_ie && ht_cap_ie[1] >= sizeof(*ht_cap)) {
3411 ht_cap = (void *)(ht_cap_ie + 2); 3424 ht_cap = (void *)(ht_cap_ie + 2);
3412 chains = ieee80211_mcs_to_chains(&ht_cap->mcs); 3425 chains = ieee80211_mcs_to_chains(&ht_cap->mcs);
@@ -3419,9 +3432,7 @@ static u8 ieee80211_ht_vht_rx_chains(struct ieee80211_sub_if_data *sdata,
3419 if (ifmgd->flags & IEEE80211_STA_DISABLE_VHT) 3432 if (ifmgd->flags & IEEE80211_STA_DISABLE_VHT)
3420 return chains; 3433 return chains;
3421 3434
3422 vht_cap_ie = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, 3435 vht_cap_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_VHT_CAPABILITY);
3423 cbss->information_elements,
3424 cbss->len_information_elements);
3425 if (vht_cap_ie && vht_cap_ie[1] >= sizeof(*vht_cap)) { 3436 if (vht_cap_ie && vht_cap_ie[1] >= sizeof(*vht_cap)) {
3426 u8 nss; 3437 u8 nss;
3427 u16 tx_mcs_map; 3438 u16 tx_mcs_map;
@@ -3457,13 +3468,13 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
3457 IEEE80211_STA_DISABLE_80P80MHZ | 3468 IEEE80211_STA_DISABLE_80P80MHZ |
3458 IEEE80211_STA_DISABLE_160MHZ); 3469 IEEE80211_STA_DISABLE_160MHZ);
3459 3470
3471 rcu_read_lock();
3472
3460 if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) && 3473 if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) &&
3461 sband->ht_cap.ht_supported) { 3474 sband->ht_cap.ht_supported) {
3462 const u8 *ht_oper_ie; 3475 const u8 *ht_oper_ie;
3463 3476
3464 ht_oper_ie = cfg80211_find_ie(WLAN_EID_HT_OPERATION, 3477 ht_oper_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_OPERATION);
3465 cbss->information_elements,
3466 cbss->len_information_elements);
3467 if (ht_oper_ie && ht_oper_ie[1] >= sizeof(*ht_oper)) 3478 if (ht_oper_ie && ht_oper_ie[1] >= sizeof(*ht_oper))
3468 ht_oper = (void *)(ht_oper_ie + 2); 3479 ht_oper = (void *)(ht_oper_ie + 2);
3469 } 3480 }
@@ -3472,9 +3483,8 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
3472 sband->vht_cap.vht_supported) { 3483 sband->vht_cap.vht_supported) {
3473 const u8 *vht_oper_ie; 3484 const u8 *vht_oper_ie;
3474 3485
3475 vht_oper_ie = cfg80211_find_ie(WLAN_EID_VHT_OPERATION, 3486 vht_oper_ie = ieee80211_bss_get_ie(cbss,
3476 cbss->information_elements, 3487 WLAN_EID_VHT_OPERATION);
3477 cbss->len_information_elements);
3478 if (vht_oper_ie && vht_oper_ie[1] >= sizeof(*vht_oper)) 3488 if (vht_oper_ie && vht_oper_ie[1] >= sizeof(*vht_oper))
3479 vht_oper = (void *)(vht_oper_ie + 2); 3489 vht_oper = (void *)(vht_oper_ie + 2);
3480 if (vht_oper && !ht_oper) { 3490 if (vht_oper && !ht_oper) {
@@ -3494,6 +3504,8 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
3494 sdata->needed_rx_chains = min(ieee80211_ht_vht_rx_chains(sdata, cbss), 3504 sdata->needed_rx_chains = min(ieee80211_ht_vht_rx_chains(sdata, cbss),
3495 local->rx_chains); 3505 local->rx_chains);
3496 3506
3507 rcu_read_unlock();
3508
3497 /* will change later if needed */ 3509 /* will change later if needed */
3498 sdata->smps_mode = IEEE80211_SMPS_OFF; 3510 sdata->smps_mode = IEEE80211_SMPS_OFF;
3499 3511
@@ -3734,14 +3746,21 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
3734 const u8 *ssidie, *ht_ie; 3746 const u8 *ssidie, *ht_ie;
3735 int i, err; 3747 int i, err;
3736 3748
3737 ssidie = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID);
3738 if (!ssidie)
3739 return -EINVAL;
3740
3741 assoc_data = kzalloc(sizeof(*assoc_data) + req->ie_len, GFP_KERNEL); 3749 assoc_data = kzalloc(sizeof(*assoc_data) + req->ie_len, GFP_KERNEL);
3742 if (!assoc_data) 3750 if (!assoc_data)
3743 return -ENOMEM; 3751 return -ENOMEM;
3744 3752
3753 rcu_read_lock();
3754 ssidie = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID);
3755 if (!ssidie) {
3756 rcu_read_unlock();
3757 kfree(assoc_data);
3758 return -EINVAL;
3759 }
3760 memcpy(assoc_data->ssid, ssidie + 2, ssidie[1]);
3761 assoc_data->ssid_len = ssidie[1];
3762 rcu_read_unlock();
3763
3745 mutex_lock(&ifmgd->mtx); 3764 mutex_lock(&ifmgd->mtx);
3746 3765
3747 if (ifmgd->associated) 3766 if (ifmgd->associated)
@@ -3836,12 +3855,14 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
3836 assoc_data->supp_rates = bss->supp_rates; 3855 assoc_data->supp_rates = bss->supp_rates;
3837 assoc_data->supp_rates_len = bss->supp_rates_len; 3856 assoc_data->supp_rates_len = bss->supp_rates_len;
3838 3857
3858 rcu_read_lock();
3839 ht_ie = ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_OPERATION); 3859 ht_ie = ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_OPERATION);
3840 if (ht_ie && ht_ie[1] >= sizeof(struct ieee80211_ht_operation)) 3860 if (ht_ie && ht_ie[1] >= sizeof(struct ieee80211_ht_operation))
3841 assoc_data->ap_ht_param = 3861 assoc_data->ap_ht_param =
3842 ((struct ieee80211_ht_operation *)(ht_ie + 2))->ht_param; 3862 ((struct ieee80211_ht_operation *)(ht_ie + 2))->ht_param;
3843 else 3863 else
3844 ifmgd->flags |= IEEE80211_STA_DISABLE_HT; 3864 ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
3865 rcu_read_unlock();
3845 3866
3846 if (bss->wmm_used && bss->uapsd_supported && 3867 if (bss->wmm_used && bss->uapsd_supported &&
3847 (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) { 3868 (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) {
@@ -3852,9 +3873,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
3852 ifmgd->flags &= ~IEEE80211_STA_UAPSD_ENABLED; 3873 ifmgd->flags &= ~IEEE80211_STA_UAPSD_ENABLED;
3853 } 3874 }
3854 3875
3855 memcpy(assoc_data->ssid, ssidie + 2, ssidie[1]);
3856 assoc_data->ssid_len = ssidie[1];
3857
3858 if (req->prev_bssid) 3876 if (req->prev_bssid)
3859 memcpy(assoc_data->prev_bssid, req->prev_bssid, ETH_ALEN); 3877 memcpy(assoc_data->prev_bssid, req->prev_bssid, ETH_ALEN);
3860 3878