cfg80211: DFS check chandef usable before CAC
Check chandef we get in CAC request is usable for CAC. All channels have to be DFS channels. Allow DFS_USABLE and DFS_AVAILABLE channels mix. At least one channel has to be DFS_USABLE (require CAC). Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com> Reviewed-by: Luis R. Rodriguez <mcgrof@do-not-panic.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Родитель
40d1ba63ff
Коммит
fe7c3a1f20
|
@ -351,6 +351,80 @@ int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
|
|||
}
|
||||
EXPORT_SYMBOL(cfg80211_chandef_dfs_required);
|
||||
|
||||
static int cfg80211_get_chans_dfs_usable(struct wiphy *wiphy,
|
||||
u32 center_freq,
|
||||
u32 bandwidth)
|
||||
{
|
||||
struct ieee80211_channel *c;
|
||||
u32 freq, start_freq, end_freq;
|
||||
int count = 0;
|
||||
|
||||
start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
|
||||
end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
|
||||
|
||||
/*
|
||||
* Check entire range of channels for the bandwidth.
|
||||
* Check all channels are DFS channels (DFS_USABLE or
|
||||
* DFS_AVAILABLE). Return number of usable channels
|
||||
* (require CAC). Allow DFS and non-DFS channel mix.
|
||||
*/
|
||||
for (freq = start_freq; freq <= end_freq; freq += 20) {
|
||||
c = ieee80211_get_channel(wiphy, freq);
|
||||
if (!c)
|
||||
return -EINVAL;
|
||||
|
||||
if (c->flags & IEEE80211_CHAN_DISABLED)
|
||||
return -EINVAL;
|
||||
|
||||
if (c->flags & IEEE80211_CHAN_RADAR) {
|
||||
if (c->dfs_state == NL80211_DFS_UNAVAILABLE)
|
||||
return -EINVAL;
|
||||
|
||||
if (c->dfs_state == NL80211_DFS_USABLE)
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy,
|
||||
const struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
int width;
|
||||
int r1, r2 = 0;
|
||||
|
||||
if (WARN_ON(!cfg80211_chandef_valid(chandef)))
|
||||
return false;
|
||||
|
||||
width = cfg80211_chandef_get_width(chandef);
|
||||
if (width < 0)
|
||||
return false;
|
||||
|
||||
r1 = cfg80211_get_chans_dfs_usable(wiphy, chandef->center_freq1,
|
||||
width);
|
||||
|
||||
if (r1 < 0)
|
||||
return false;
|
||||
|
||||
switch (chandef->width) {
|
||||
case NL80211_CHAN_WIDTH_80P80:
|
||||
WARN_ON(!chandef->center_freq2);
|
||||
r2 = cfg80211_get_chans_dfs_usable(wiphy,
|
||||
chandef->center_freq2,
|
||||
width);
|
||||
if (r2 < 0)
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
WARN_ON(chandef->center_freq2);
|
||||
break;
|
||||
}
|
||||
|
||||
return (r1 + r2 > 0);
|
||||
}
|
||||
|
||||
|
||||
static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
|
||||
u32 center_freq, u32 bandwidth,
|
||||
u32 prohibited_flags)
|
||||
|
|
|
@ -382,6 +382,19 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
|
|||
enum cfg80211_chan_mode chanmode,
|
||||
u8 radar_detect);
|
||||
|
||||
/**
|
||||
* cfg80211_chandef_dfs_usable - checks if chandef is DFS usable
|
||||
* @wiphy: the wiphy to validate against
|
||||
* @chandef: the channel definition to check
|
||||
*
|
||||
* Checks if chandef is usable and we can/need start CAC on such channel.
|
||||
*
|
||||
* Return: Return true if all channels available and at least
|
||||
* one channel require CAC (NL80211_DFS_USABLE)
|
||||
*/
|
||||
bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy,
|
||||
const struct cfg80211_chan_def *chandef);
|
||||
|
||||
void cfg80211_set_dfs_state(struct wiphy *wiphy,
|
||||
const struct cfg80211_chan_def *chandef,
|
||||
enum nl80211_dfs_state dfs_state);
|
||||
|
|
|
@ -5651,7 +5651,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
|
|||
if (err == 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (chandef.chan->dfs_state != NL80211_DFS_USABLE)
|
||||
if (!cfg80211_chandef_dfs_usable(wdev->wiphy, &chandef))
|
||||
return -EINVAL;
|
||||
|
||||
if (!rdev->ops->start_radar_detection)
|
||||
|
|
Загрузка…
Ссылка в новой задаче