cfg80211: prohibit scanning the same channel more than once
It isn't very useful to scan the same channel more than once during a given scan, and some hardware (notably iwlwifi) can only scan a limited number of channels at a time. To prevent any overflows, simply disallow scanning any channel multiple times in a given scan command. This is a small change in the userspace ABI, but the only user, wpa_supplicant, never asks for a scan with the same frequency listed twice. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
386aa23dd5
commit
83f5e2cf79
1 changed files with 30 additions and 3 deletions
|
@ -2695,6 +2695,31 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int validate_scan_freqs(struct nlattr *freqs)
|
||||||
|
{
|
||||||
|
struct nlattr *attr1, *attr2;
|
||||||
|
int n_channels = 0, tmp1, tmp2;
|
||||||
|
|
||||||
|
nla_for_each_nested(attr1, freqs, tmp1) {
|
||||||
|
n_channels++;
|
||||||
|
/*
|
||||||
|
* Some hardware has a limited channel list for
|
||||||
|
* scanning, and it is pretty much nonsensical
|
||||||
|
* to scan for a channel twice, so disallow that
|
||||||
|
* and don't require drivers to check that the
|
||||||
|
* channel list they get isn't longer than what
|
||||||
|
* they can scan, as long as they can scan all
|
||||||
|
* the channels they registered at once.
|
||||||
|
*/
|
||||||
|
nla_for_each_nested(attr2, freqs, tmp2)
|
||||||
|
if (attr1 != attr2 &&
|
||||||
|
nla_get_u32(attr1) == nla_get_u32(attr2))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return n_channels;
|
||||||
|
}
|
||||||
|
|
||||||
static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
|
static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
|
||||||
{
|
{
|
||||||
struct cfg80211_registered_device *drv;
|
struct cfg80211_registered_device *drv;
|
||||||
|
@ -2704,7 +2729,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
|
||||||
struct ieee80211_channel *channel;
|
struct ieee80211_channel *channel;
|
||||||
struct nlattr *attr;
|
struct nlattr *attr;
|
||||||
struct wiphy *wiphy;
|
struct wiphy *wiphy;
|
||||||
int err, tmp, n_ssids = 0, n_channels = 0, i;
|
int err, tmp, n_ssids = 0, n_channels, i;
|
||||||
enum ieee80211_band band;
|
enum ieee80211_band band;
|
||||||
size_t ie_len;
|
size_t ie_len;
|
||||||
|
|
||||||
|
@ -2735,13 +2760,15 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
|
if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
|
||||||
nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_FREQUENCIES], tmp)
|
n_channels = validate_scan_freqs(
|
||||||
n_channels++;
|
info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
|
||||||
if (!n_channels) {
|
if (!n_channels) {
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
n_channels = 0;
|
||||||
|
|
||||||
for (band = 0; band < IEEE80211_NUM_BANDS; band++)
|
for (band = 0; band < IEEE80211_NUM_BANDS; band++)
|
||||||
if (wiphy->bands[band])
|
if (wiphy->bands[band])
|
||||||
n_channels += wiphy->bands[band]->n_channels;
|
n_channels += wiphy->bands[band]->n_channels;
|
||||||
|
|
Loading…
Add table
Reference in a new issue