Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 258498
b: refs/heads/master
c: 34850ab
h: refs/heads/master
v: v3
  • Loading branch information
Johannes Berg authored and John W. Linville committed Jul 19, 2011
1 parent 5ac85a1 commit 24170b3
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 20 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 0b5dd734d3545a9833c0bceeed5088ad9a1ca5e3
refs/heads/master: 34850ab25d74ab4eead62c3b4a9e8036a25cc669
7 changes: 7 additions & 0 deletions trunk/include/linux/nl80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -1014,6 +1014,11 @@ enum nl80211_commands {
* @%NL80211_ATTR_REKEY_DATA: nested attribute containing the information
* necessary for GTK rekeying in the device, see &enum nl80211_rekey_data.
*
* @NL80211_ATTR_SCAN_SUPP_RATES: rates per to be advertised as supported in scan,
* nested array attribute containing an entry for each band, with the entry
* being a list of supported rates as defined by IEEE 802.11 7.3.2.2 but
* without the length restriction (at most %NL80211_MAX_SUPP_RATES).
*
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
Expand Down Expand Up @@ -1217,6 +1222,8 @@ enum nl80211_attrs {
NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS,
NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN,

NL80211_ATTR_SCAN_SUPP_RATES,

/* add attributes here, update the policy in nl80211.c */

__NL80211_ATTR_AFTER_LAST,
Expand Down
3 changes: 3 additions & 0 deletions trunk/include/net/cfg80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,7 @@ struct cfg80211_ssid {
* @n_channels: total number of channels to scan
* @ie: optional information element(s) to add into Probe Request or %NULL
* @ie_len: length of ie in octets
* @rates: bitmap of rates to advertise for each band
* @wiphy: the wiphy this was for
* @dev: the interface
* @aborted: (internal) scan request was notified as aborted
Expand All @@ -788,6 +789,8 @@ struct cfg80211_scan_request {
const u8 *ie;
size_t ie_len;

u32 rates[IEEE80211_NUM_BANDS];

/* internal */
struct wiphy *wiphy;
struct net_device *dev;
Expand Down
4 changes: 4 additions & 0 deletions trunk/net/wireless/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,10 @@ int cfg80211_set_freq(struct cfg80211_registered_device *rdev,

u16 cfg80211_calculate_bitrate(struct rate_info *rate);

int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
const u8 *rates, unsigned int n_rates,
u32 *mask);

int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
u32 beacon_int);

Expand Down
50 changes: 31 additions & 19 deletions trunk/net/wireless/nl80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
[NL80211_ATTR_STA_PLINK_STATE] = { .type = NLA_U8 },
[NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 },
[NL80211_ATTR_REKEY_DATA] = { .type = NLA_NESTED },
[NL80211_ATTR_SCAN_SUPP_RATES] = { .type = NLA_NESTED },
};

/* policy for the key attributes */
Expand Down Expand Up @@ -3324,7 +3325,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
struct nlattr *attr;
struct wiphy *wiphy;
int err, tmp, n_ssids = 0, n_channels, i;
enum ieee80211_band band;
size_t ie_len;

if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
Expand All @@ -3344,6 +3344,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
if (!n_channels)
return -EINVAL;
} else {
enum ieee80211_band band;
n_channels = 0;

for (band = 0; band < IEEE80211_NUM_BANDS; band++)
Expand Down Expand Up @@ -3404,6 +3405,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
i++;
}
} else {
enum ieee80211_band band;

/* all channels */
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
int j;
Expand Down Expand Up @@ -3450,6 +3453,28 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
request->ie_len);
}

for (i = 0; i < IEEE80211_NUM_BANDS; i++)
request->rates[i] = (1 << wiphy->bands[i]->n_bitrates) - 1;

if (info->attrs[NL80211_ATTR_SCAN_SUPP_RATES]) {
nla_for_each_nested(attr,
info->attrs[NL80211_ATTR_SCAN_SUPP_RATES],
tmp) {
enum ieee80211_band band = nla_type(attr);

if (band < 0 || band > IEEE80211_NUM_BANDS) {
err = -EINVAL;
goto out_free;
}
err = ieee80211_get_ratemask(wiphy->bands[band],
nla_data(attr),
nla_len(attr),
&request->rates[band]);
if (err)
goto out_free;
}
}

request->dev = dev;
request->wiphy = &rdev->wiphy;

Expand Down Expand Up @@ -4336,25 +4361,12 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
struct ieee80211_supported_band *sband =
wiphy->bands[ibss.channel->band];
int i, j;

if (n_rates == 0)
return -EINVAL;

for (i = 0; i < n_rates; i++) {
int rate = (rates[i] & 0x7f) * 5;
bool found = false;
int err;

for (j = 0; j < sband->n_bitrates; j++) {
if (sband->bitrates[j].bitrate == rate) {
found = true;
ibss.basic_rates |= BIT(j);
break;
}
}
if (!found)
return -EINVAL;
}
err = ieee80211_get_ratemask(sband, rates, n_rates,
&ibss.basic_rates);
if (err)
return err;
}

if (info->attrs[NL80211_ATTR_MCAST_RATE] &&
Expand Down
3 changes: 3 additions & 0 deletions trunk/net/wireless/scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -862,6 +862,9 @@ int cfg80211_wext_siwscan(struct net_device *dev,
creq->n_ssids = 0;
}

for (i = 0; i < IEEE80211_NUM_BANDS; i++)
creq->rates[i] = (1 << wiphy->bands[i]->n_bitrates) - 1;

rdev->scan_req = creq;
err = rdev->ops->scan(wiphy, dev, creq);
if (err) {
Expand Down
35 changes: 35 additions & 0 deletions trunk/net/wireless/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -1006,3 +1006,38 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,

return -EBUSY;
}

int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
const u8 *rates, unsigned int n_rates,
u32 *mask)
{
int i, j;

if (n_rates == 0 || n_rates > NL80211_MAX_SUPP_RATES)
return -EINVAL;

*mask = 0;

for (i = 0; i < n_rates; i++) {
int rate = (rates[i] & 0x7f) * 5;
bool found = false;

for (j = 0; j < sband->n_bitrates; j++) {
if (sband->bitrates[j].bitrate == rate) {
found = true;
*mask |= BIT(j);
break;
}
}
if (!found)
return -EINVAL;
}

/*
* mask must have at least one bit set here since we
* didn't accept a 0-length rates array nor allowed
* entries in the array that didn't exist
*/

return 0;
}

0 comments on commit 24170b3

Please sign in to comment.