aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/sme.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/sme.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/sme.c')
-rw-r--r--net/wireless/sme.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 340934f714b..219c3bc2c37 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -256,9 +256,11 @@ void cfg80211_sme_scan_done(struct net_device *dev)
256{ 256{
257 struct wireless_dev *wdev = dev->ieee80211_ptr; 257 struct wireless_dev *wdev = dev->ieee80211_ptr;
258 258
259 mutex_lock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx);
259 wdev_lock(wdev); 260 wdev_lock(wdev);
260 __cfg80211_sme_scan_done(dev); 261 __cfg80211_sme_scan_done(dev);
261 wdev_unlock(wdev); 262 wdev_unlock(wdev);
263 mutex_unlock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx);
262} 264}
263 265
264void cfg80211_sme_rx_auth(struct net_device *dev, 266void cfg80211_sme_rx_auth(struct net_device *dev,
@@ -644,6 +646,7 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
644 struct cfg80211_cached_keys *connkeys) 646 struct cfg80211_cached_keys *connkeys)
645{ 647{
646 struct wireless_dev *wdev = dev->ieee80211_ptr; 648 struct wireless_dev *wdev = dev->ieee80211_ptr;
649 struct ieee80211_channel *chan;
647 int err; 650 int err;
648 651
649 ASSERT_WDEV_LOCK(wdev); 652 ASSERT_WDEV_LOCK(wdev);
@@ -651,6 +654,10 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
651 if (wdev->sme_state != CFG80211_SME_IDLE) 654 if (wdev->sme_state != CFG80211_SME_IDLE)
652 return -EALREADY; 655 return -EALREADY;
653 656
657 chan = rdev_fixed_channel(rdev, wdev);
658 if (chan && chan != connect->channel)
659 return -EBUSY;
660
654 if (WARN_ON(wdev->connect_keys)) { 661 if (WARN_ON(wdev->connect_keys)) {
655 kfree(wdev->connect_keys); 662 kfree(wdev->connect_keys);
656 wdev->connect_keys = NULL; 663 wdev->connect_keys = NULL;
@@ -785,9 +792,11 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
785{ 792{
786 int err; 793 int err;
787 794
795 mutex_lock(&rdev->devlist_mtx);
788 wdev_lock(dev->ieee80211_ptr); 796 wdev_lock(dev->ieee80211_ptr);
789 err = __cfg80211_connect(rdev, dev, connect, connkeys); 797 err = __cfg80211_connect(rdev, dev, connect, connkeys);
790 wdev_unlock(dev->ieee80211_ptr); 798 wdev_unlock(dev->ieee80211_ptr);
799 mutex_unlock(&rdev->devlist_mtx);
791 800
792 return err; 801 return err;
793} 802}