diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/wireless/core.h | 4 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 50 | ||||
-rw-r--r-- | net/wireless/scan.c | 3 | ||||
-rw-r--r-- | net/wireless/util.c | 35 |
4 files changed, 73 insertions, 19 deletions
diff --git a/net/wireless/core.h b/net/wireless/core.h index a570ff9214ec..8672e028022f 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -447,6 +447,10 @@ int cfg80211_set_freq(struct cfg80211_registered_device *rdev, | |||
447 | 447 | ||
448 | u16 cfg80211_calculate_bitrate(struct rate_info *rate); | 448 | u16 cfg80211_calculate_bitrate(struct rate_info *rate); |
449 | 449 | ||
450 | int ieee80211_get_ratemask(struct ieee80211_supported_band *sband, | ||
451 | const u8 *rates, unsigned int n_rates, | ||
452 | u32 *mask); | ||
453 | |||
450 | int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, | 454 | int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, |
451 | u32 beacon_int); | 455 | u32 beacon_int); |
452 | 456 | ||
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 44a3fc2ce38d..20aa390cf338 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -177,6 +177,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
177 | [NL80211_ATTR_STA_PLINK_STATE] = { .type = NLA_U8 }, | 177 | [NL80211_ATTR_STA_PLINK_STATE] = { .type = NLA_U8 }, |
178 | [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 }, | 178 | [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 }, |
179 | [NL80211_ATTR_REKEY_DATA] = { .type = NLA_NESTED }, | 179 | [NL80211_ATTR_REKEY_DATA] = { .type = NLA_NESTED }, |
180 | [NL80211_ATTR_SCAN_SUPP_RATES] = { .type = NLA_NESTED }, | ||
180 | }; | 181 | }; |
181 | 182 | ||
182 | /* policy for the key attributes */ | 183 | /* policy for the key attributes */ |
@@ -3324,7 +3325,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
3324 | struct nlattr *attr; | 3325 | struct nlattr *attr; |
3325 | struct wiphy *wiphy; | 3326 | struct wiphy *wiphy; |
3326 | int err, tmp, n_ssids = 0, n_channels, i; | 3327 | int err, tmp, n_ssids = 0, n_channels, i; |
3327 | enum ieee80211_band band; | ||
3328 | size_t ie_len; | 3328 | size_t ie_len; |
3329 | 3329 | ||
3330 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) | 3330 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) |
@@ -3344,6 +3344,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
3344 | if (!n_channels) | 3344 | if (!n_channels) |
3345 | return -EINVAL; | 3345 | return -EINVAL; |
3346 | } else { | 3346 | } else { |
3347 | enum ieee80211_band band; | ||
3347 | n_channels = 0; | 3348 | n_channels = 0; |
3348 | 3349 | ||
3349 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) | 3350 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) |
@@ -3404,6 +3405,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
3404 | i++; | 3405 | i++; |
3405 | } | 3406 | } |
3406 | } else { | 3407 | } else { |
3408 | enum ieee80211_band band; | ||
3409 | |||
3407 | /* all channels */ | 3410 | /* all channels */ |
3408 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | 3411 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { |
3409 | int j; | 3412 | int j; |
@@ -3450,6 +3453,28 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
3450 | request->ie_len); | 3453 | request->ie_len); |
3451 | } | 3454 | } |
3452 | 3455 | ||
3456 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) | ||
3457 | request->rates[i] = (1 << wiphy->bands[i]->n_bitrates) - 1; | ||
3458 | |||
3459 | if (info->attrs[NL80211_ATTR_SCAN_SUPP_RATES]) { | ||
3460 | nla_for_each_nested(attr, | ||
3461 | info->attrs[NL80211_ATTR_SCAN_SUPP_RATES], | ||
3462 | tmp) { | ||
3463 | enum ieee80211_band band = nla_type(attr); | ||
3464 | |||
3465 | if (band < 0 || band > IEEE80211_NUM_BANDS) { | ||
3466 | err = -EINVAL; | ||
3467 | goto out_free; | ||
3468 | } | ||
3469 | err = ieee80211_get_ratemask(wiphy->bands[band], | ||
3470 | nla_data(attr), | ||
3471 | nla_len(attr), | ||
3472 | &request->rates[band]); | ||
3473 | if (err) | ||
3474 | goto out_free; | ||
3475 | } | ||
3476 | } | ||
3477 | |||
3453 | request->dev = dev; | 3478 | request->dev = dev; |
3454 | request->wiphy = &rdev->wiphy; | 3479 | request->wiphy = &rdev->wiphy; |
3455 | 3480 | ||
@@ -4336,25 +4361,12 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) | |||
4336 | nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); | 4361 | nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); |
4337 | struct ieee80211_supported_band *sband = | 4362 | struct ieee80211_supported_band *sband = |
4338 | wiphy->bands[ibss.channel->band]; | 4363 | wiphy->bands[ibss.channel->band]; |
4339 | int i, j; | 4364 | int err; |
4340 | |||
4341 | if (n_rates == 0) | ||
4342 | return -EINVAL; | ||
4343 | |||
4344 | for (i = 0; i < n_rates; i++) { | ||
4345 | int rate = (rates[i] & 0x7f) * 5; | ||
4346 | bool found = false; | ||
4347 | 4365 | ||
4348 | for (j = 0; j < sband->n_bitrates; j++) { | 4366 | err = ieee80211_get_ratemask(sband, rates, n_rates, |
4349 | if (sband->bitrates[j].bitrate == rate) { | 4367 | &ibss.basic_rates); |
4350 | found = true; | 4368 | if (err) |
4351 | ibss.basic_rates |= BIT(j); | 4369 | return err; |
4352 | break; | ||
4353 | } | ||
4354 | } | ||
4355 | if (!found) | ||
4356 | return -EINVAL; | ||
4357 | } | ||
4358 | } | 4370 | } |
4359 | 4371 | ||
4360 | if (info->attrs[NL80211_ATTR_MCAST_RATE] && | 4372 | if (info->attrs[NL80211_ATTR_MCAST_RATE] && |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 1c4672e35144..1e7ff949d1aa 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -862,6 +862,9 @@ int cfg80211_wext_siwscan(struct net_device *dev, | |||
862 | creq->n_ssids = 0; | 862 | creq->n_ssids = 0; |
863 | } | 863 | } |
864 | 864 | ||
865 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) | ||
866 | creq->rates[i] = (1 << wiphy->bands[i]->n_bitrates) - 1; | ||
867 | |||
865 | rdev->scan_req = creq; | 868 | rdev->scan_req = creq; |
866 | err = rdev->ops->scan(wiphy, dev, creq); | 869 | err = rdev->ops->scan(wiphy, dev, creq); |
867 | if (err) { | 870 | if (err) { |
diff --git a/net/wireless/util.c b/net/wireless/util.c index 4d7b83fbc32f..a329429bfdd8 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -1006,3 +1006,38 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, | |||
1006 | 1006 | ||
1007 | return -EBUSY; | 1007 | return -EBUSY; |
1008 | } | 1008 | } |
1009 | |||
1010 | int ieee80211_get_ratemask(struct ieee80211_supported_band *sband, | ||
1011 | const u8 *rates, unsigned int n_rates, | ||
1012 | u32 *mask) | ||
1013 | { | ||
1014 | int i, j; | ||
1015 | |||
1016 | if (n_rates == 0 || n_rates > NL80211_MAX_SUPP_RATES) | ||
1017 | return -EINVAL; | ||
1018 | |||
1019 | *mask = 0; | ||
1020 | |||
1021 | for (i = 0; i < n_rates; i++) { | ||
1022 | int rate = (rates[i] & 0x7f) * 5; | ||
1023 | bool found = false; | ||
1024 | |||
1025 | for (j = 0; j < sband->n_bitrates; j++) { | ||
1026 | if (sband->bitrates[j].bitrate == rate) { | ||
1027 | found = true; | ||
1028 | *mask |= BIT(j); | ||
1029 | break; | ||
1030 | } | ||
1031 | } | ||
1032 | if (!found) | ||
1033 | return -EINVAL; | ||
1034 | } | ||
1035 | |||
1036 | /* | ||
1037 | * mask must have at least one bit set here since we | ||
1038 | * didn't accept a 0-length rates array nor allowed | ||
1039 | * entries in the array that didn't exist | ||
1040 | */ | ||
1041 | |||
1042 | return 0; | ||
1043 | } | ||