aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorMichal Kazior <michal.kazior@tieto.com>2014-01-29 08:22:27 -0500
committerJohannes Berg <johannes.berg@intel.com>2014-02-04 15:58:17 -0500
commit9e0e29615a2077be852b1245b57c5b00fa609522 (patch)
tree73d899373e01efe1fd72a895d8e2fe2f6bc8fcb2 /net
parentfe94f3a4ffaa20c7470038c69ffc8e545ef5f90a (diff)
cfg80211: consider existing DFS interfaces
It was possible to break interface combinations in the following way: combo 1: iftype = AP, num_ifaces = 2, num_chans = 2, combo 2: iftype = AP, num_ifaces = 1, num_chans = 1, radar = HT20 With the above interface combinations it was possible to: step 1. start AP on DFS channel by matching combo 2 step 2. start AP on non-DFS channel by matching combo 1 This was possible beacuse (step 2) did not consider if other interfaces require radar detection. The patch changes how cfg80211 tracks channels - instead of channel itself now a complete chandef is stored. Signed-off-by: Michal Kazior <michal.kazior@tieto.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net')
-rw-r--r--net/wireless/ap.c2
-rw-r--r--net/wireless/chan.c23
-rw-r--r--net/wireless/core.h3
-rw-r--r--net/wireless/ibss.c2
-rw-r--r--net/wireless/mesh.c6
-rw-r--r--net/wireless/mlme.c2
-rw-r--r--net/wireless/nl80211.c6
-rw-r--r--net/wireless/util.c2
8 files changed, 32 insertions, 14 deletions
diff --git a/net/wireless/ap.c b/net/wireless/ap.c
index 4760d6554e62..68602be07cc1 100644
--- a/net/wireless/ap.c
+++ b/net/wireless/ap.c
@@ -27,7 +27,7 @@ static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
27 err = rdev_stop_ap(rdev, dev); 27 err = rdev_stop_ap(rdev, dev);
28 if (!err) { 28 if (!err) {
29 wdev->beacon_interval = 0; 29 wdev->beacon_interval = 0;
30 wdev->channel = NULL; 30 memset(&wdev->chandef, 0, sizeof(wdev->chandef));
31 wdev->ssid_len = 0; 31 wdev->ssid_len = 0;
32 rdev_set_qos_map(rdev, dev, NULL); 32 rdev_set_qos_map(rdev, dev, NULL);
33 nl80211_send_ap_stopped(wdev); 33 nl80211_send_ap_stopped(wdev);
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 78559b5bbd1f..f8ab7df1ab0d 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -642,7 +642,8 @@ int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
642void 642void
643cfg80211_get_chan_state(struct wireless_dev *wdev, 643cfg80211_get_chan_state(struct wireless_dev *wdev,
644 struct ieee80211_channel **chan, 644 struct ieee80211_channel **chan,
645 enum cfg80211_chan_mode *chanmode) 645 enum cfg80211_chan_mode *chanmode,
646 u8 *radar_detect)
646{ 647{
647 *chan = NULL; 648 *chan = NULL;
648 *chanmode = CHAN_MODE_UNDEFINED; 649 *chanmode = CHAN_MODE_UNDEFINED;
@@ -660,6 +661,11 @@ cfg80211_get_chan_state(struct wireless_dev *wdev,
660 !wdev->ibss_dfs_possible) 661 !wdev->ibss_dfs_possible)
661 ? CHAN_MODE_SHARED 662 ? CHAN_MODE_SHARED
662 : CHAN_MODE_EXCLUSIVE; 663 : CHAN_MODE_EXCLUSIVE;
664
665 /* consider worst-case - IBSS can try to return to the
666 * original user-specified channel as creator */
667 if (wdev->ibss_dfs_possible)
668 *radar_detect |= BIT(wdev->chandef.width);
663 return; 669 return;
664 } 670 }
665 break; 671 break;
@@ -674,17 +680,26 @@ cfg80211_get_chan_state(struct wireless_dev *wdev,
674 case NL80211_IFTYPE_AP: 680 case NL80211_IFTYPE_AP:
675 case NL80211_IFTYPE_P2P_GO: 681 case NL80211_IFTYPE_P2P_GO:
676 if (wdev->cac_started) { 682 if (wdev->cac_started) {
677 *chan = wdev->channel; 683 *chan = wdev->chandef.chan;
678 *chanmode = CHAN_MODE_SHARED; 684 *chanmode = CHAN_MODE_SHARED;
685 *radar_detect |= BIT(wdev->chandef.width);
679 } else if (wdev->beacon_interval) { 686 } else if (wdev->beacon_interval) {
680 *chan = wdev->channel; 687 *chan = wdev->chandef.chan;
681 *chanmode = CHAN_MODE_SHARED; 688 *chanmode = CHAN_MODE_SHARED;
689
690 if (cfg80211_chandef_dfs_required(wdev->wiphy,
691 &wdev->chandef))
692 *radar_detect |= BIT(wdev->chandef.width);
682 } 693 }
683 return; 694 return;
684 case NL80211_IFTYPE_MESH_POINT: 695 case NL80211_IFTYPE_MESH_POINT:
685 if (wdev->mesh_id_len) { 696 if (wdev->mesh_id_len) {
686 *chan = wdev->channel; 697 *chan = wdev->chandef.chan;
687 *chanmode = CHAN_MODE_SHARED; 698 *chanmode = CHAN_MODE_SHARED;
699
700 if (cfg80211_chandef_dfs_required(wdev->wiphy,
701 &wdev->chandef))
702 *radar_detect |= BIT(wdev->chandef.width);
688 } 703 }
689 return; 704 return;
690 case NL80211_IFTYPE_MONITOR: 705 case NL80211_IFTYPE_MONITOR:
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 8a820f9c4a76..9895ab16c051 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -443,7 +443,8 @@ static inline unsigned int elapsed_jiffies_msecs(unsigned long start)
443void 443void
444cfg80211_get_chan_state(struct wireless_dev *wdev, 444cfg80211_get_chan_state(struct wireless_dev *wdev,
445 struct ieee80211_channel **chan, 445 struct ieee80211_channel **chan,
446 enum cfg80211_chan_mode *chanmode); 446 enum cfg80211_chan_mode *chanmode,
447 u8 *radar_detect);
447 448
448int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev, 449int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
449 struct cfg80211_chan_def *chandef); 450 struct cfg80211_chan_def *chandef);
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
index e37e39c29dfb..1470b90e438f 100644
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -122,6 +122,7 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
122 122
123 wdev->ibss_fixed = params->channel_fixed; 123 wdev->ibss_fixed = params->channel_fixed;
124 wdev->ibss_dfs_possible = params->userspace_handles_dfs; 124 wdev->ibss_dfs_possible = params->userspace_handles_dfs;
125 wdev->chandef = params->chandef;
125#ifdef CONFIG_CFG80211_WEXT 126#ifdef CONFIG_CFG80211_WEXT
126 wdev->wext.ibss.chandef = params->chandef; 127 wdev->wext.ibss.chandef = params->chandef;
127#endif 128#endif
@@ -205,6 +206,7 @@ static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext)
205 206
206 wdev->current_bss = NULL; 207 wdev->current_bss = NULL;
207 wdev->ssid_len = 0; 208 wdev->ssid_len = 0;
209 memset(&wdev->chandef, 0, sizeof(wdev->chandef));
208#ifdef CONFIG_CFG80211_WEXT 210#ifdef CONFIG_CFG80211_WEXT
209 if (!nowext) 211 if (!nowext)
210 wdev->wext.ibss.ssid_len = 0; 212 wdev->wext.ibss.ssid_len = 0;
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c
index 885862447b63..d42a3fcb2f67 100644
--- a/net/wireless/mesh.c
+++ b/net/wireless/mesh.c
@@ -195,7 +195,7 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
195 if (!err) { 195 if (!err) {
196 memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len); 196 memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len);
197 wdev->mesh_id_len = setup->mesh_id_len; 197 wdev->mesh_id_len = setup->mesh_id_len;
198 wdev->channel = setup->chandef.chan; 198 wdev->chandef = setup->chandef;
199 } 199 }
200 200
201 return err; 201 return err;
@@ -244,7 +244,7 @@ int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev,
244 err = rdev_libertas_set_mesh_channel(rdev, wdev->netdev, 244 err = rdev_libertas_set_mesh_channel(rdev, wdev->netdev,
245 chandef->chan); 245 chandef->chan);
246 if (!err) 246 if (!err)
247 wdev->channel = chandef->chan; 247 wdev->chandef = *chandef;
248 248
249 return err; 249 return err;
250 } 250 }
@@ -276,7 +276,7 @@ static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
276 err = rdev_leave_mesh(rdev, dev); 276 err = rdev_leave_mesh(rdev, dev);
277 if (!err) { 277 if (!err) {
278 wdev->mesh_id_len = 0; 278 wdev->mesh_id_len = 0;
279 wdev->channel = NULL; 279 memset(&wdev->chandef, 0, sizeof(wdev->chandef));
280 rdev_set_qos_map(rdev, dev, NULL); 280 rdev_set_qos_map(rdev, dev, NULL);
281 } 281 }
282 282
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 52cca05044a8..d47c9d127b1e 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -772,7 +772,7 @@ void cfg80211_cac_event(struct net_device *netdev,
772 if (WARN_ON(!wdev->cac_started)) 772 if (WARN_ON(!wdev->cac_started))
773 return; 773 return;
774 774
775 if (WARN_ON(!wdev->channel)) 775 if (WARN_ON(!wdev->chandef.chan))
776 return; 776 return;
777 777
778 switch (event) { 778 switch (event) {
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 0a186013728c..be091ddd43a4 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3281,7 +3281,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
3281 if (!err) { 3281 if (!err) {
3282 wdev->preset_chandef = params.chandef; 3282 wdev->preset_chandef = params.chandef;
3283 wdev->beacon_interval = params.beacon_interval; 3283 wdev->beacon_interval = params.beacon_interval;
3284 wdev->channel = params.chandef.chan; 3284 wdev->chandef = params.chandef;
3285 wdev->ssid_len = params.ssid_len; 3285 wdev->ssid_len = params.ssid_len;
3286 memcpy(wdev->ssid, params.ssid, wdev->ssid_len); 3286 memcpy(wdev->ssid, params.ssid, wdev->ssid_len);
3287 } 3287 }
@@ -5797,7 +5797,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
5797 5797
5798 err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef); 5798 err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef);
5799 if (!err) { 5799 if (!err) {
5800 wdev->channel = chandef.chan; 5800 wdev->chandef = chandef;
5801 wdev->cac_started = true; 5801 wdev->cac_started = true;
5802 wdev->cac_start_time = jiffies; 5802 wdev->cac_start_time = jiffies;
5803 } 5803 }
@@ -11215,7 +11215,7 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
11215 wdev->iftype != NL80211_IFTYPE_MESH_POINT)) 11215 wdev->iftype != NL80211_IFTYPE_MESH_POINT))
11216 return; 11216 return;
11217 11217
11218 wdev->channel = chandef->chan; 11218 wdev->chandef = *chandef;
11219 wdev->preset_chandef = *chandef; 11219 wdev->preset_chandef = *chandef;
11220 nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL); 11220 nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL);
11221} 11221}
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 7526a4d8aa16..780b4546c9c7 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1357,7 +1357,7 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
1357 */ 1357 */
1358 mutex_lock_nested(&wdev_iter->mtx, 1); 1358 mutex_lock_nested(&wdev_iter->mtx, 1);
1359 __acquire(wdev_iter->mtx); 1359 __acquire(wdev_iter->mtx);
1360 cfg80211_get_chan_state(wdev_iter, &ch, &chmode); 1360 cfg80211_get_chan_state(wdev_iter, &ch, &chmode, &radar_detect);
1361 wdev_unlock(wdev_iter); 1361 wdev_unlock(wdev_iter);
1362 1362
1363 switch (chmode) { 1363 switch (chmode) {