aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/chan.c
diff options
context:
space:
mode:
authorLuis R. Rodriguez <lrodriguez@atheros.com>2010-11-12 19:31:23 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-11-16 15:59:39 -0500
commit9236d838c920e90708570d9bbd7bb82d30a38130 (patch)
treeee2d9ae6b4f82efe3b28e33abebec96b7e136141 /net/wireless/chan.c
parentb5261cf4f3860bd772346a3e692683b6144dd44c (diff)
cfg80211: fix extension channel checks to initiate communication
When operating in a mode that initiates communication and using HT40 we should fail if we cannot use both primary and secondary channels to initiate communication. Our current ht40 allowmap only covers STA mode of operation, for beaconing modes we need a check on the fly as the mode of operation is dynamic and there other flags other than disable which we should read to check if we can initiate communication. Do not allow for initiating communication if our secondary HT40 channel has is either disabled, has a passive scan flag, a no-ibss flag or is a radar channel. Userspace now has similar checks but this is also needed in-kernel. Reported-by: Jouni Malinen <jouni.malinen@atheros.com> Cc: stable@kernel.org Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless/chan.c')
-rw-r--r--net/wireless/chan.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index d0c92dddb26b..c8d190d911e4 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -44,6 +44,36 @@ rdev_freq_to_chan(struct cfg80211_registered_device *rdev,
44 return chan; 44 return chan;
45} 45}
46 46
47static bool can_beacon_sec_chan(struct wiphy *wiphy,
48 struct ieee80211_channel *chan,
49 enum nl80211_channel_type channel_type)
50{
51 struct ieee80211_channel *sec_chan;
52 int diff;
53
54 switch (channel_type) {
55 case NL80211_CHAN_HT40PLUS:
56 diff = 20;
57 case NL80211_CHAN_HT40MINUS:
58 diff = -20;
59 default:
60 return false;
61 }
62
63 sec_chan = ieee80211_get_channel(wiphy, chan->center_freq + diff);
64 if (!sec_chan)
65 return false;
66
67 /* we'll need a DFS capability later */
68 if (sec_chan->flags & (IEEE80211_CHAN_DISABLED |
69 IEEE80211_CHAN_PASSIVE_SCAN |
70 IEEE80211_CHAN_NO_IBSS |
71 IEEE80211_CHAN_RADAR))
72 return false;
73
74 return true;
75}
76
47int cfg80211_set_freq(struct cfg80211_registered_device *rdev, 77int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
48 struct wireless_dev *wdev, int freq, 78 struct wireless_dev *wdev, int freq,
49 enum nl80211_channel_type channel_type) 79 enum nl80211_channel_type channel_type)
@@ -68,6 +98,28 @@ int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
68 if (!chan) 98 if (!chan)
69 return -EINVAL; 99 return -EINVAL;
70 100
101 /* Both channels should be able to initiate communication */
102 if (wdev && (wdev->iftype == NL80211_IFTYPE_ADHOC ||
103 wdev->iftype == NL80211_IFTYPE_AP ||
104 wdev->iftype == NL80211_IFTYPE_AP_VLAN ||
105 wdev->iftype == NL80211_IFTYPE_MESH_POINT ||
106 wdev->iftype == NL80211_IFTYPE_P2P_GO)) {
107 switch (channel_type) {
108 case NL80211_CHAN_HT40PLUS:
109 case NL80211_CHAN_HT40MINUS:
110 if (!can_beacon_sec_chan(&rdev->wiphy, chan,
111 channel_type)) {
112 printk(KERN_DEBUG
113 "cfg80211: Secondary channel not "
114 "allowed to initiate communication\n");
115 return -EINVAL;
116 }
117 break;
118 default:
119 break;
120 }
121 }
122
71 result = rdev->ops->set_channel(&rdev->wiphy, 123 result = rdev->ops->set_channel(&rdev->wiphy,
72 wdev ? wdev->netdev : NULL, 124 wdev ? wdev->netdev : NULL,
73 chan, channel_type); 125 chan, channel_type);