aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/wext-compat.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-08-07 11:22:35 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-08-14 09:13:42 -0400
commit59bbb6f7574bc693ed8313b98eac641116c95b94 (patch)
treeda24ed15c5e375782e79b3dab7022d2100a7987a /net/wireless/wext-compat.c
parentf26b32ed4bd5780855a79bb17fb1a431fa867dad (diff)
cfg80211: validate channel settings across interfaces
Currently, there's a problem that affects regulatory enforcement and connection stability, in that it is possible to switch the channel while connected to a network or joined to an IBSS. The problem comes from the fact that we only validate the channel against the current interface's type, not against any other interface. Thus, you have any type of interface up, additionally bring up a monitor mode interface and switch the channel on the monitor. This will obviously also switch the channel on the other interface. The problem now is that if you do that while sending beacons for IBSS mode, you can switch to a disabled channel or a channel that doesn't allow beaconing. Combined with a managed mode interface connected to an AP instead of an IBSS interface, you can easily break the connection that way. To fix this, this patch validates any channel change with all available interfaces, and disallows such changes on secondary interfaces if another interface is connected to an AP or joined to an IBSS. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless/wext-compat.c')
-rw-r--r--net/wireless/wext-compat.c55
1 files changed, 19 insertions, 36 deletions
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index e4e90e249bab..17648dc79867 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -267,39 +267,26 @@ EXPORT_SYMBOL_GPL(cfg80211_wext_giwrange);
267 * @wiphy: the wiphy 267 * @wiphy: the wiphy
268 * @freq: the wext freq encoding 268 * @freq: the wext freq encoding
269 * 269 *
270 * Returns a channel, %NULL for auto, or an ERR_PTR for errors! 270 * Returns a frequency, or a negative error code, or 0 for auto.
271 */ 271 */
272struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy, 272int cfg80211_wext_freq(struct wiphy *wiphy, struct iw_freq *freq)
273 struct iw_freq *freq)
274{ 273{
275 struct ieee80211_channel *chan;
276 int f;
277
278 /* 274 /*
279 * Parse frequency - return NULL for auto and 275 * Parse frequency - return 0 for auto and
280 * -EINVAL for impossible things. 276 * -EINVAL for impossible things.
281 */ 277 */
282 if (freq->e == 0) { 278 if (freq->e == 0) {
283 if (freq->m < 0) 279 if (freq->m < 0)
284 return NULL; 280 return 0;
285 f = ieee80211_channel_to_frequency(freq->m); 281 return ieee80211_channel_to_frequency(freq->m);
286 } else { 282 } else {
287 int i, div = 1000000; 283 int i, div = 1000000;
288 for (i = 0; i < freq->e; i++) 284 for (i = 0; i < freq->e; i++)
289 div /= 10; 285 div /= 10;
290 if (div <= 0) 286 if (div <= 0)
291 return ERR_PTR(-EINVAL); 287 return -EINVAL;
292 f = freq->m / div; 288 return freq->m / div;
293 } 289 }
294
295 /*
296 * Look up channel struct and return -EINVAL when
297 * it cannot be found.
298 */
299 chan = ieee80211_get_channel(wiphy, f);
300 if (!chan)
301 return ERR_PTR(-EINVAL);
302 return chan;
303} 290}
304 291
305int cfg80211_wext_siwrts(struct net_device *dev, 292int cfg80211_wext_siwrts(struct net_device *dev,
@@ -761,33 +748,29 @@ EXPORT_SYMBOL_GPL(cfg80211_wext_giwencode);
761 748
762int cfg80211_wext_siwfreq(struct net_device *dev, 749int cfg80211_wext_siwfreq(struct net_device *dev,
763 struct iw_request_info *info, 750 struct iw_request_info *info,
764 struct iw_freq *freq, char *extra) 751 struct iw_freq *wextfreq, char *extra)
765{ 752{
766 struct wireless_dev *wdev = dev->ieee80211_ptr; 753 struct wireless_dev *wdev = dev->ieee80211_ptr;
767 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 754 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
768 struct ieee80211_channel *chan; 755 int freq, err;
769 int err;
770 756
771 switch (wdev->iftype) { 757 switch (wdev->iftype) {
772 case NL80211_IFTYPE_STATION: 758 case NL80211_IFTYPE_STATION:
773 return cfg80211_mgd_wext_siwfreq(dev, info, freq, extra); 759 return cfg80211_mgd_wext_siwfreq(dev, info, wextfreq, extra);
774 case NL80211_IFTYPE_ADHOC: 760 case NL80211_IFTYPE_ADHOC:
775 return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra); 761 return cfg80211_ibss_wext_siwfreq(dev, info, wextfreq, extra);
776 default: 762 default:
777 chan = cfg80211_wext_freq(wdev->wiphy, freq); 763 freq = cfg80211_wext_freq(wdev->wiphy, wextfreq);
778 if (!chan) 764 if (freq < 0)
765 return freq;
766 if (freq == 0)
779 return -EINVAL; 767 return -EINVAL;
780 if (IS_ERR(chan)) 768 mutex_lock(&rdev->devlist_mtx);
781 return PTR_ERR(chan); 769 err = rdev_set_freq(rdev, freq, NL80211_CHAN_NO_HT);
782 err = rdev->ops->set_channel(wdev->wiphy, chan, 770 mutex_unlock(&rdev->devlist_mtx);
783 NL80211_CHAN_NO_HT); 771 return err;
784 if (err)
785 return err;
786 rdev->channel = chan;
787 return 0;
788 } 772 }
789} 773}
790EXPORT_SYMBOL_GPL(cfg80211_wext_siwfreq);
791 774
792int cfg80211_wext_giwfreq(struct net_device *dev, 775int cfg80211_wext_giwfreq(struct net_device *dev,
793 struct iw_request_info *info, 776 struct iw_request_info *info,