Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fe7c3a1f authored by Janusz Dziedzic's avatar Janusz Dziedzic Committed by Johannes Berg
Browse files

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: default avatarJanusz Dziedzic <janusz.dziedzic@tieto.com>
Reviewed-by: default avatarLuis R. Rodriguez <mcgrof@do-not-panic.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 40d1ba63
Loading
Loading
Loading
Loading
+74 −0
Original line number Original line Diff line number Diff line
@@ -351,6 +351,80 @@ int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
}
}
EXPORT_SYMBOL(cfg80211_chandef_dfs_required);
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,
static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
					u32 center_freq, u32 bandwidth,
					u32 center_freq, u32 bandwidth,
					u32 prohibited_flags)
					u32 prohibited_flags)
+13 −0
Original line number Original line Diff line number Diff line
@@ -382,6 +382,19 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
				 enum cfg80211_chan_mode chanmode,
				 enum cfg80211_chan_mode chanmode,
				 u8 radar_detect);
				 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,
void cfg80211_set_dfs_state(struct wiphy *wiphy,
			    const struct cfg80211_chan_def *chandef,
			    const struct cfg80211_chan_def *chandef,
			    enum nl80211_dfs_state dfs_state);
			    enum nl80211_dfs_state dfs_state);
+1 −1
Original line number Original line Diff line number Diff line
@@ -5651,7 +5651,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
	if (err == 0)
	if (err == 0)
		return -EINVAL;
		return -EINVAL;


	if (chandef.chan->dfs_state != NL80211_DFS_USABLE)
	if (!cfg80211_chandef_dfs_usable(wdev->wiphy, &chandef))
		return -EINVAL;
		return -EINVAL;


	if (!rdev->ops->start_radar_detection)
	if (!rdev->ops->start_radar_detection)