Commit 584991dc authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville

cfg80211: validate scan channels

Currently it is possible to request a scan on only
disabled channels, which could be problematic for
some drivers. Reject such scans, and also ignore
disabled channels that are given. This resuls in
the scan begin/end event only including channels
that are actually used.

This makes the mac80211 check for disabled channels
superfluous. At the same time, remove the no-IBSS
check from mac80211 -- nothing says that we should
not find any networks on channels that cannot be
used for an IBSS, even when operating in IBSS mode.
Signed-off-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 6c085227
...@@ -614,22 +614,13 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local, ...@@ -614,22 +614,13 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local,
{ {
int skip; int skip;
struct ieee80211_channel *chan; struct ieee80211_channel *chan;
struct ieee80211_sub_if_data *sdata = local->scan_sdata;
skip = 0; skip = 0;
chan = local->scan_req->channels[local->scan_channel_idx]; chan = local->scan_req->channels[local->scan_channel_idx];
if (chan->flags & IEEE80211_CHAN_DISABLED ||
(sdata->vif.type == NL80211_IFTYPE_ADHOC &&
chan->flags & IEEE80211_CHAN_NO_IBSS))
skip = 1;
if (!skip) {
local->scan_channel = chan; local->scan_channel = chan;
if (ieee80211_hw_config(local, if (ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL))
IEEE80211_CONF_CHANGE_CHANNEL))
skip = 1; skip = 1;
}
/* advance state machine to next channel/band */ /* advance state machine to next channel/band */
local->scan_channel_idx++; local->scan_channel_idx++;
......
...@@ -2988,7 +2988,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) ...@@ -2988,7 +2988,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
goto out; goto out;
} }
request->n_channels = n_channels;
if (n_ssids) if (n_ssids)
request->ssids = (void *)&request->channels[n_channels]; request->ssids = (void *)&request->channels[n_channels];
request->n_ssids = n_ssids; request->n_ssids = n_ssids;
...@@ -2999,32 +2998,53 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) ...@@ -2999,32 +2998,53 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
request->ie = (void *)(request->channels + n_channels); request->ie = (void *)(request->channels + n_channels);
} }
i = 0;
if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
/* user specified, bail out if channel not found */ /* user specified, bail out if channel not found */
request->n_channels = n_channels;
i = 0;
nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_FREQUENCIES], tmp) { nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_FREQUENCIES], tmp) {
request->channels[i] = ieee80211_get_channel(wiphy, nla_get_u32(attr)); struct ieee80211_channel *chan;
if (!request->channels[i]) {
chan = ieee80211_get_channel(wiphy, nla_get_u32(attr));
if (!chan) {
err = -EINVAL; err = -EINVAL;
goto out_free; goto out_free;
} }
/* ignore disabled channels */
if (chan->flags & IEEE80211_CHAN_DISABLED)
continue;
request->channels[i] = chan;
i++; i++;
} }
} else { } else {
/* all channels */ /* all channels */
i = 0;
for (band = 0; band < IEEE80211_NUM_BANDS; band++) { for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
int j; int j;
if (!wiphy->bands[band]) if (!wiphy->bands[band])
continue; continue;
for (j = 0; j < wiphy->bands[band]->n_channels; j++) { for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
request->channels[i] = &wiphy->bands[band]->channels[j]; struct ieee80211_channel *chan;
chan = &wiphy->bands[band]->channels[j];
if (chan->flags & IEEE80211_CHAN_DISABLED)
continue;
request->channels[i] = chan;
i++; i++;
} }
} }
} }
if (!i) {
err = -EINVAL;
goto out_free;
}
request->n_channels = i;
i = 0; i = 0;
if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) { if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) {
nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) { nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) {
......
...@@ -650,9 +650,15 @@ int cfg80211_wext_siwscan(struct net_device *dev, ...@@ -650,9 +650,15 @@ int cfg80211_wext_siwscan(struct net_device *dev,
i = 0; i = 0;
for (band = 0; band < IEEE80211_NUM_BANDS; band++) { for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
int j; int j;
if (!wiphy->bands[band]) if (!wiphy->bands[band])
continue; continue;
for (j = 0; j < wiphy->bands[band]->n_channels; j++) { for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
/* ignore disabled channels */
if (wiphy->bands[band]->channels[j].flags &
IEEE80211_CHAN_DISABLED)
continue;
/* If we have a wireless request structure and the /* If we have a wireless request structure and the
* wireless request specifies frequencies, then search * wireless request specifies frequencies, then search
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment