diff options
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r-- | net/mac80211/mlme.c | 80 |
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 | ||