aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/wireless/core.h4
-rw-r--r--net/wireless/nl80211.c50
-rw-r--r--net/wireless/scan.c3
-rw-r--r--net/wireless/util.c35
4 files changed, 73 insertions, 19 deletions
diff --git a/net/wireless/core.h b/net/wireless/core.h
index a570ff9214e..8672e028022 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
448u16 cfg80211_calculate_bitrate(struct rate_info *rate); 448u16 cfg80211_calculate_bitrate(struct rate_info *rate);
449 449
450int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
451 const u8 *rates, unsigned int n_rates,
452 u32 *mask);
453
450int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, 454int 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 44a3fc2ce38..20aa390cf33 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 1c4672e3514..1e7ff949d1a 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 4d7b83fbc32..a329429bfdd 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
1010int 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}