aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-06-17 11:41:49 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-07-10 14:57:54 -0400
commit83f5e2cf79390f7ca909b7035dd415230257cc4d (patch)
treec6b2fdf4a727ae6a7d87afe205dde078339d151d
parent386aa23dd5f94b810210b9f849807946a5100b57 (diff)
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>
-rw-r--r--net/wireless/nl80211.c33
1 files changed, 30 insertions, 3 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 5a6c4ca59398..7946b82c5716 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2695,6 +2695,31 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
2695 return r; 2695 return r;
2696} 2696}
2697 2697
2698static int validate_scan_freqs(struct nlattr *freqs)
2699{
2700 struct nlattr *attr1, *attr2;
2701 int n_channels = 0, tmp1, tmp2;
2702
2703 nla_for_each_nested(attr1, freqs, tmp1) {
2704 n_channels++;
2705 /*
2706 * Some hardware has a limited channel list for
2707 * scanning, and it is pretty much nonsensical
2708 * to scan for a channel twice, so disallow that
2709 * and don't require drivers to check that the
2710 * channel list they get isn't longer than what
2711 * they can scan, as long as they can scan all
2712 * the channels they registered at once.
2713 */
2714 nla_for_each_nested(attr2, freqs, tmp2)
2715 if (attr1 != attr2 &&
2716 nla_get_u32(attr1) == nla_get_u32(attr2))
2717 return 0;
2718 }
2719
2720 return n_channels;
2721}
2722
2698static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) 2723static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
2699{ 2724{
2700 struct cfg80211_registered_device *drv; 2725 struct cfg80211_registered_device *drv;
@@ -2704,7 +2729,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
2704 struct ieee80211_channel *channel; 2729 struct ieee80211_channel *channel;
2705 struct nlattr *attr; 2730 struct nlattr *attr;
2706 struct wiphy *wiphy; 2731 struct wiphy *wiphy;
2707 int err, tmp, n_ssids = 0, n_channels = 0, i; 2732 int err, tmp, n_ssids = 0, n_channels, i;
2708 enum ieee80211_band band; 2733 enum ieee80211_band band;
2709 size_t ie_len; 2734 size_t ie_len;
2710 2735
@@ -2735,13 +2760,15 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
2735 } 2760 }
2736 2761
2737 if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { 2762 if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
2738 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_FREQUENCIES], tmp) 2763 n_channels = validate_scan_freqs(
2739 n_channels++; 2764 info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
2740 if (!n_channels) { 2765 if (!n_channels) {
2741 err = -EINVAL; 2766 err = -EINVAL;
2742 goto out; 2767 goto out;
2743 } 2768 }
2744 } else { 2769 } else {
2770 n_channels = 0;
2771
2745 for (band = 0; band < IEEE80211_NUM_BANDS; band++) 2772 for (band = 0; band < IEEE80211_NUM_BANDS; band++)
2746 if (wiphy->bands[band]) 2773 if (wiphy->bands[band])
2747 n_channels += wiphy->bands[band]->n_channels; 2774 n_channels += wiphy->bands[band]->n_channels;