Commit 8d9de16f authored by Benjamin Berg's avatar Benjamin Berg Committed by Johannes Berg

wireless: Require HANDLE_DFS flag to switch channel for non-AP mode

In the case the channel should be switched to one requiring DFS we need
to make sure that userspace will handle radar events when they happen.
For AP mode this is assumed to be the case, as a manager like hostapd
is required. However IBSS and MESH modes can work without further
userspace assistance, so refuse to use DFS channels unless userspace
vouches that it handles DFS.

NOTE: Userspace should have already flagged support earlier during mesh
or IBSS setup. However, this information is not readily accessible
currently.
Signed-off-by: default avatarBenjamin Berg <benjamin@sipsolutions.net>
[sw: style cleanups]
Signed-off-by: default avatarSimon Wunderlich <sw@simonwunderlich.de>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent d37d49c2
...@@ -7501,6 +7501,7 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) ...@@ -7501,6 +7501,7 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
static struct nlattr *csa_attrs[NL80211_ATTR_MAX+1]; static struct nlattr *csa_attrs[NL80211_ATTR_MAX+1];
int err; int err;
bool need_new_beacon = false; bool need_new_beacon = false;
bool need_handle_dfs_flag = true;
int len, i; int len, i;
u32 cs_count; u32 cs_count;
...@@ -7512,6 +7513,12 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) ...@@ -7512,6 +7513,12 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
case NL80211_IFTYPE_AP: case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_P2P_GO: case NL80211_IFTYPE_P2P_GO:
need_new_beacon = true; need_new_beacon = true;
/* For all modes except AP the handle_dfs flag needs to be
* supplied to tell the kernel that userspace will handle radar
* events when they happen. Otherwise a switch to a channel
* requiring DFS will be rejected.
*/
need_handle_dfs_flag = false;
/* useless if AP is not running */ /* useless if AP is not running */
if (!wdev->beacon_interval) if (!wdev->beacon_interval)
...@@ -7634,8 +7641,13 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) ...@@ -7634,8 +7641,13 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
if (err < 0) if (err < 0)
return err; return err;
if (err > 0) if (err > 0) {
params.radar_required = true; params.radar_required = true;
if (need_handle_dfs_flag &&
!nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS])) {
return -EINVAL;
}
}
if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX]) if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX])
params.block_tx = true; params.block_tx = true;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment