From: Arik Nemtsov <[email protected]>

If a TDLS station is not allowed to beacon on a channel, don't accept
a channel switch request to this channel.
Move channel building code up to avoid lockdep violations - reg_can_beacon
needs to take the wdev lock.

Signed-off-by: Arik Nemtsov <[email protected]>
Signed-off-by: Emmanuel Grumbach <[email protected]>
---
 net/mac80211/tdls.c | 49 +++++++++++++++++++++++++++++++------------------
 1 file changed, 31 insertions(+), 18 deletions(-)

diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c
index 91e86bf..aee701a 100644
--- a/net/mac80211/tdls.c
+++ b/net/mac80211/tdls.c
@@ -1737,6 +1737,31 @@ ieee80211_process_tdls_channel_switch_req(struct 
ieee80211_sub_if_data *sdata,
                return -EINVAL;
        }
 
+       if (!elems.sec_chan_offs) {
+               chan_type = NL80211_CHAN_HT20;
+       } else {
+               switch (elems.sec_chan_offs->sec_chan_offs) {
+               case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
+                       chan_type = NL80211_CHAN_HT40PLUS;
+                       break;
+               case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
+                       chan_type = NL80211_CHAN_HT40MINUS;
+                       break;
+               default:
+                       chan_type = NL80211_CHAN_HT20;
+                       break;
+               }
+       }
+
+       cfg80211_chandef_create(&chandef, chan, chan_type);
+
+       /* we will be active on the TDLS link */
+       if (!cfg80211_reg_can_beacon_relax(sdata->local->hw.wiphy, &chandef,
+                                          sdata->wdev.iftype)) {
+               tdls_dbg(sdata, "TDLS chan switch to forbidden channel\n");
+               return -EINVAL;
+       }
+
        mutex_lock(&local->sta_mtx);
        sta = sta_info_get(sdata, tf->sa);
        if (!sta || !test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH)) {
@@ -1757,27 +1782,15 @@ ieee80211_process_tdls_channel_switch_req(struct 
ieee80211_sub_if_data *sdata,
                goto out;
        }
 
-       if (!sta->sta.ht_cap.ht_supported) {
-               chan_type = NL80211_CHAN_NO_HT;
-       } else if (!elems.sec_chan_offs) {
-               chan_type = NL80211_CHAN_HT20;
-       } else {
-               switch (elems.sec_chan_offs->sec_chan_offs) {
-               case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
-                       chan_type = NL80211_CHAN_HT40PLUS;
-                       break;
-               case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
-                       chan_type = NL80211_CHAN_HT40MINUS;
-                       break;
-               default:
-                       chan_type = NL80211_CHAN_HT20;
-                       break;
-               }
+       /* peer should have known better */
+       if (!sta->sta.ht_cap.ht_supported && elems.sec_chan_offs &&
+           elems.sec_chan_offs->sec_chan_offs) {
+               tdls_dbg(sdata, "TDLS chan switch - wide chan unsupported\n");
+               ret = -ENOTSUPP;
+               goto out;
        }
 
-       cfg80211_chandef_create(&chandef, chan, chan_type);
        params.chandef = &chandef;
-
        params.switch_time = le16_to_cpu(elems.ch_sw_timing->switch_time);
        params.switch_timeout = le16_to_cpu(elems.ch_sw_timing->switch_timeout);
 
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to