Search Linux Wireless

[RFC 1/5] cfg80211: regulatory rules, fix bw checking

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Allow BW cross over REG_RULES if rules continous.

Signed-off-by: Janusz Dziedzic <janusz.dziedzic@xxxxxxxxx>
---
I am not sure about rule_intersect() here ...

 net/wireless/reg.c |   68 +++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 59 insertions(+), 9 deletions(-)

diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 7d20d84..4414fa5 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -522,9 +522,55 @@ bool reg_is_valid_request(const char *alpha2)
 	return alpha2_equal(lr->alpha2, alpha2);
 }
 
+static u32 get_frequency_diff(const struct ieee80211_reg_rule *rules,
+			      unsigned int rule_no,
+			      unsigned int rule_max)
+{
+	u32 start_freq, end_freq;
+	u32 no = rule_no;
+	const struct ieee80211_reg_rule *rule = &rules[rule_no];
+	const struct ieee80211_freq_range *freq_range = &rule->freq_range;
+	const struct ieee80211_freq_range *freq_range_tmp;
+
+	/* get start_freq */
+	while (no) {
+		rule = &rules[--no];
+		freq_range_tmp = &rule->freq_range;
+
+		if (freq_range_tmp->end_freq_khz != freq_range->start_freq_khz)
+			break;
+
+		freq_range = freq_range_tmp;
+	};
+
+	start_freq = freq_range->start_freq_khz;
+
+	/* get end_freq */
+	rule = &rules[rule_no];
+	freq_range = &rule->freq_range;
+	no = rule_no;
+
+	while (no < rule_max - 1) {
+		rule = &rules[++no];
+		freq_range_tmp = &rule->freq_range;
+
+		if (freq_range_tmp->start_freq_khz != freq_range->end_freq_khz)
+			break;
+
+		freq_range = freq_range_tmp;
+	}
+
+	end_freq = freq_range->end_freq_khz;
+
+	return end_freq - start_freq;
+}
+
 /* Sanity check on a regulatory rule */
-static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rule)
+static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rules,
+			      unsigned int rule_no,
+			      unsigned int rule_max)
 {
+	const struct ieee80211_reg_rule *rule = &rules[rule_no];
 	const struct ieee80211_freq_range *freq_range = &rule->freq_range;
 	u32 freq_diff;
 
@@ -534,10 +580,17 @@ static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rule)
 	if (freq_range->start_freq_khz > freq_range->end_freq_khz)
 		return false;
 
+	if (freq_range->end_freq_khz <= freq_range->start_freq_khz)
+		return false;
+
+	/* First do quick check */
 	freq_diff = freq_range->end_freq_khz - freq_range->start_freq_khz;
+	if (freq_range->max_bandwidth_khz <= freq_diff)
+		return true;
 
-	if (freq_range->end_freq_khz <= freq_range->start_freq_khz ||
-	    freq_range->max_bandwidth_khz > freq_diff)
+	/* Next check adjacent rules (if continous) */
+	freq_diff = get_frequency_diff(rules, rule_no, rule_max);
+	if (freq_range->max_bandwidth_khz > freq_diff)
 		return false;
 
 	return true;
@@ -545,7 +598,6 @@ static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rule)
 
 static bool is_valid_rd(const struct ieee80211_regdomain *rd)
 {
-	const struct ieee80211_reg_rule *reg_rule = NULL;
 	unsigned int i;
 
 	if (!rd->n_reg_rules)
@@ -554,11 +606,9 @@ static bool is_valid_rd(const struct ieee80211_regdomain *rd)
 	if (WARN_ON(rd->n_reg_rules > NL80211_MAX_SUPP_REG_RULES))
 		return false;
 
-	for (i = 0; i < rd->n_reg_rules; i++) {
-		reg_rule = &rd->reg_rules[i];
-		if (!is_valid_reg_rule(reg_rule))
+	for (i = 0; i < rd->n_reg_rules; i++)
+		if (!is_valid_reg_rule(rd->reg_rules, i, rd->n_reg_rules))
 			return false;
-	}
 
 	return true;
 }
@@ -666,7 +716,7 @@ static int reg_rules_intersect(const struct ieee80211_reg_rule *rule1,
 
 	intersected_rule->flags = rule1->flags | rule2->flags;
 
-	if (!is_valid_reg_rule(intersected_rule))
+	if (!is_valid_reg_rule(intersected_rule, 0, 1))
 		return -EINVAL;
 
 	return 0;
-- 
1.7.9.5

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




[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux