diff options
Diffstat (limited to 'net/wireless')
| -rw-r--r-- | net/wireless/nl80211.c | 46 |
1 files changed, 35 insertions, 11 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index a10484da60c0..b8441e60b0f6 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
| @@ -3569,13 +3569,12 @@ out: | |||
| 3569 | return 0; | 3569 | return 0; |
| 3570 | } | 3570 | } |
| 3571 | 3571 | ||
| 3572 | static int validate_beacon_tx_rate(struct cfg80211_ap_settings *params) | 3572 | static int validate_beacon_tx_rate(struct cfg80211_registered_device *rdev, |
| 3573 | enum nl80211_band band, | ||
| 3574 | struct cfg80211_bitrate_mask *beacon_rate) | ||
| 3573 | { | 3575 | { |
| 3574 | u32 rate, count_ht, count_vht, i; | 3576 | u32 count_ht, count_vht, i; |
| 3575 | enum nl80211_band band; | 3577 | u32 rate = beacon_rate->control[band].legacy; |
| 3576 | |||
| 3577 | band = params->chandef.chan->band; | ||
| 3578 | rate = params->beacon_rate.control[band].legacy; | ||
| 3579 | 3578 | ||
| 3580 | /* Allow only one rate */ | 3579 | /* Allow only one rate */ |
| 3581 | if (hweight32(rate) > 1) | 3580 | if (hweight32(rate) > 1) |
| @@ -3583,9 +3582,9 @@ static int validate_beacon_tx_rate(struct cfg80211_ap_settings *params) | |||
| 3583 | 3582 | ||
| 3584 | count_ht = 0; | 3583 | count_ht = 0; |
| 3585 | for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) { | 3584 | for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) { |
| 3586 | if (hweight8(params->beacon_rate.control[band].ht_mcs[i]) > 1) { | 3585 | if (hweight8(beacon_rate->control[band].ht_mcs[i]) > 1) { |
| 3587 | return -EINVAL; | 3586 | return -EINVAL; |
| 3588 | } else if (params->beacon_rate.control[band].ht_mcs[i]) { | 3587 | } else if (beacon_rate->control[band].ht_mcs[i]) { |
| 3589 | count_ht++; | 3588 | count_ht++; |
| 3590 | if (count_ht > 1) | 3589 | if (count_ht > 1) |
| 3591 | return -EINVAL; | 3590 | return -EINVAL; |
| @@ -3596,9 +3595,9 @@ static int validate_beacon_tx_rate(struct cfg80211_ap_settings *params) | |||
| 3596 | 3595 | ||
| 3597 | count_vht = 0; | 3596 | count_vht = 0; |
| 3598 | for (i = 0; i < NL80211_VHT_NSS_MAX; i++) { | 3597 | for (i = 0; i < NL80211_VHT_NSS_MAX; i++) { |
| 3599 | if (hweight16(params->beacon_rate.control[band].vht_mcs[i]) > 1) { | 3598 | if (hweight16(beacon_rate->control[band].vht_mcs[i]) > 1) { |
| 3600 | return -EINVAL; | 3599 | return -EINVAL; |
| 3601 | } else if (params->beacon_rate.control[band].vht_mcs[i]) { | 3600 | } else if (beacon_rate->control[band].vht_mcs[i]) { |
| 3602 | count_vht++; | 3601 | count_vht++; |
| 3603 | if (count_vht > 1) | 3602 | if (count_vht > 1) |
| 3604 | return -EINVAL; | 3603 | return -EINVAL; |
| @@ -3610,6 +3609,19 @@ static int validate_beacon_tx_rate(struct cfg80211_ap_settings *params) | |||
| 3610 | if ((count_ht && count_vht) || (!rate && !count_ht && !count_vht)) | 3609 | if ((count_ht && count_vht) || (!rate && !count_ht && !count_vht)) |
| 3611 | return -EINVAL; | 3610 | return -EINVAL; |
| 3612 | 3611 | ||
| 3612 | if (rate && | ||
| 3613 | !wiphy_ext_feature_isset(&rdev->wiphy, | ||
| 3614 | NL80211_EXT_FEATURE_BEACON_RATE_LEGACY)) | ||
| 3615 | return -EINVAL; | ||
| 3616 | if (count_ht && | ||
| 3617 | !wiphy_ext_feature_isset(&rdev->wiphy, | ||
| 3618 | NL80211_EXT_FEATURE_BEACON_RATE_HT)) | ||
| 3619 | return -EINVAL; | ||
| 3620 | if (count_vht && | ||
| 3621 | !wiphy_ext_feature_isset(&rdev->wiphy, | ||
| 3622 | NL80211_EXT_FEATURE_BEACON_RATE_VHT)) | ||
| 3623 | return -EINVAL; | ||
| 3624 | |||
| 3613 | return 0; | 3625 | return 0; |
| 3614 | } | 3626 | } |
| 3615 | 3627 | ||
| @@ -3847,7 +3859,8 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) | |||
| 3847 | if (err) | 3859 | if (err) |
| 3848 | return err; | 3860 | return err; |
| 3849 | 3861 | ||
| 3850 | err = validate_beacon_tx_rate(¶ms); | 3862 | err = validate_beacon_tx_rate(rdev, params.chandef.chan->band, |
| 3863 | ¶ms.beacon_rate); | ||
| 3851 | if (err) | 3864 | if (err) |
| 3852 | return err; | 3865 | return err; |
| 3853 | } | 3866 | } |
| @@ -9406,6 +9419,17 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info) | |||
| 9406 | return err; | 9419 | return err; |
| 9407 | } | 9420 | } |
| 9408 | 9421 | ||
| 9422 | if (info->attrs[NL80211_ATTR_TX_RATES]) { | ||
| 9423 | err = nl80211_parse_tx_bitrate_mask(info, &setup.beacon_rate); | ||
| 9424 | if (err) | ||
| 9425 | return err; | ||
| 9426 | |||
| 9427 | err = validate_beacon_tx_rate(rdev, setup.chandef.chan->band, | ||
| 9428 | &setup.beacon_rate); | ||
| 9429 | if (err) | ||
| 9430 | return err; | ||
| 9431 | } | ||
| 9432 | |||
| 9409 | return cfg80211_join_mesh(rdev, dev, &setup, &cfg); | 9433 | return cfg80211_join_mesh(rdev, dev, &setup, &cfg); |
| 9410 | } | 9434 | } |
| 9411 | 9435 | ||
