aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/nl80211.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-07-18 12:08:35 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-07-19 16:49:58 -0400
commit34850ab25d74ab4eead62c3b4a9e8036a25cc669 (patch)
treec1aa56f2d94851804969b71523ade13bb9db693c /net/wireless/nl80211.c
parent0b5dd734d3545a9833c0bceeed5088ad9a1ca5e3 (diff)
cfg80211: allow userspace to control supported rates in scan
Some P2P scans are not allowed to advertise 11b rates, but that is a rather special case so instead of having that, allow userspace to request the rate sets (per band) that are advertised in scan probe request frames. Since it's needed in two places now, factor out some common code parsing a rate array. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r--net/wireless/nl80211.c50
1 files changed, 31 insertions, 19 deletions
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] &&