Use actual list of regulatory domains for wifi dialog.
This commit is contained in:
+233
-198
@@ -18,6 +18,7 @@
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include "RegDb.hpp"
|
||||
|
||||
#include "ss.hpp"
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
@@ -30,8 +31,12 @@
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include "json_variant.hpp"
|
||||
#include "json.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#define REGDB_MAGIC 0x52474442
|
||||
#define REGDB_VERSION 19 // pre-bookwork
|
||||
#define REGDB_VERSION_2 20 // bookworm and later.
|
||||
@@ -40,7 +45,7 @@ using namespace pipedal;
|
||||
using namespace std;
|
||||
|
||||
static std::unique_ptr<RegDb> g_Instance;
|
||||
RegDb&RegDb::GetInstance()
|
||||
RegDb &RegDb::GetInstance()
|
||||
{
|
||||
if (!g_Instance)
|
||||
{
|
||||
@@ -49,9 +54,9 @@ RegDb&RegDb::GetInstance()
|
||||
return *g_Instance;
|
||||
}
|
||||
|
||||
const WifiRegulations& RegDb::getWifiRegulations(const std::string&countryIso3661) const
|
||||
const WifiRegulations &RegDb::getWifiRegulations(const std::string &countryIso3661) const
|
||||
{
|
||||
for (const auto ®ulation: this->regulations)
|
||||
for (const auto ®ulation : this->regulations)
|
||||
{
|
||||
if (regulation.reg_alpha2 == countryIso3661)
|
||||
{
|
||||
@@ -61,28 +66,31 @@ const WifiRegulations& RegDb::getWifiRegulations(const std::string&countryIso366
|
||||
throw std::runtime_error("Invalid country code.");
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
T NlSwap(T value)
|
||||
{
|
||||
if constexpr (std::endian::native == std::endian::big)
|
||||
{
|
||||
return value;
|
||||
} else {
|
||||
auto value_rep = std::bit_cast<std::array<std::uint8_t,sizeof(T)>,T >(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto value_rep = std::bit_cast<std::array<std::uint8_t, sizeof(T)>, T>(value);
|
||||
std::ranges::reverse(value_rep);
|
||||
return std::bit_cast<T>(value_rep);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class BigEndian {
|
||||
class BigEndian
|
||||
{
|
||||
public:
|
||||
BigEndian(): m_value(0) { }
|
||||
explicit BigEndian(T value): m_value(NlSwap(value)) {}
|
||||
T value() const { return NlSwap(m_value);}
|
||||
bool operator==(const BigEndian<T>&other) const { return m_value == other.m_value; }
|
||||
BigEndian() : m_value(0) {}
|
||||
explicit BigEndian(T value) : m_value(NlSwap(value)) {}
|
||||
T value() const { return NlSwap(m_value); }
|
||||
bool operator==(const BigEndian<T> &other) const { return m_value == other.m_value; }
|
||||
explicit operator bool() const { return m_value != 0; }
|
||||
|
||||
private:
|
||||
T m_value;
|
||||
};
|
||||
@@ -141,17 +149,15 @@ struct RulesCollection19
|
||||
{
|
||||
this->ruleCount = NlSwap(this->ruleCount);
|
||||
}
|
||||
Rule*getRule(
|
||||
Rule *getRule(
|
||||
uint32_t nRule,
|
||||
char *pData
|
||||
)
|
||||
char *pData)
|
||||
{
|
||||
uint32_t ruleOffset = NlSwap(ruleOffsets[nRule]);
|
||||
return (Rule*)(pData+ruleOffset);
|
||||
}
|
||||
return (Rule *)(pData + ruleOffset);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct FrequencyRange
|
||||
{
|
||||
uint32_t startFrequency; // in khz.
|
||||
@@ -203,7 +209,7 @@ RegDb::RegDb()
|
||||
{
|
||||
}
|
||||
RegDb::RegDb(const std::filesystem::path &path)
|
||||
: pData(nullptr)
|
||||
: pData(nullptr)
|
||||
{
|
||||
ifstream f(path);
|
||||
if (!f.is_open())
|
||||
@@ -255,23 +261,22 @@ void RegDb::Load19()
|
||||
{
|
||||
WifiRegulations wifiRegulations;
|
||||
|
||||
|
||||
CountryHeader countryHeader = pCountryHeader[i];
|
||||
countryHeader.toNs();
|
||||
wifiRegulations.reg_alpha2 = SS(countryHeader.alpha2[0] << countryHeader.alpha2[1]);
|
||||
wifiRegulations.reg_alpha2 = SS(countryHeader.alpha2[0] << countryHeader.alpha2[1]);
|
||||
wifiRegulations.dfs_region = (DfsRegion)(countryHeader.dfsRegion & 0x03);
|
||||
|
||||
RulesCollection19 *pRules = (RulesCollection19 *)(pData + countryHeader.rulesOffset);
|
||||
uint32_t ruleCount = NlSwap(pRules->ruleCount);
|
||||
for (uint32_t nRule = 0; nRule < ruleCount; ++nRule)
|
||||
{
|
||||
Rule *pRule = pRules->getRule(nRule,pData);
|
||||
{
|
||||
Rule *pRule = pRules->getRule(nRule, pData);
|
||||
Rule rule = *pRule;
|
||||
rule.toNs();
|
||||
|
||||
FrequencyRange fr = *(FrequencyRange *)(pData + rule.frequencyRangeOffset);
|
||||
fr.toNs();
|
||||
|
||||
|
||||
PowerRule pr = *(PowerRule *)(pData + rule.powerRuleOffset);
|
||||
pr.toNs();
|
||||
|
||||
@@ -291,7 +296,7 @@ void RegDb::Load19()
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// glue
|
||||
#define IEEE80211_NUM_ACS 4 // linux/ieee80211.h Number of hardware queues?
|
||||
#define IEEE80211_NUM_ACS 4 // linux/ieee80211.h Number of hardware queues?
|
||||
|
||||
#define __aligned(n)
|
||||
#define __packed
|
||||
@@ -305,16 +310,14 @@ using __be16 = BigEndian<uint16_t>;
|
||||
#define BIT(n) (1 << n)
|
||||
|
||||
template <typename T>
|
||||
T ALIGN(T value,int bits)
|
||||
T ALIGN(T value, int bits)
|
||||
{
|
||||
intptr_t v = (intptr_t)value;
|
||||
|
||||
intptr_t mask = (1 << bits)-1;
|
||||
intptr_t mask = (1 << bits) - 1;
|
||||
v = (v + mask) & (~mask);
|
||||
return (T)v;
|
||||
|
||||
}
|
||||
|
||||
|
||||
inline BigEndian<uint32_t> cpu_to_be32(uint32_t value)
|
||||
{
|
||||
@@ -326,196 +329,203 @@ inline BigEndian<uint16_t> cpu_to_be16(uint16_t value)
|
||||
return BigEndian<uint16_t>(value);
|
||||
}
|
||||
|
||||
|
||||
inline uint16_t be16_to_cpu(const BigEndian<uint16_t>&value)
|
||||
inline uint16_t be16_to_cpu(const BigEndian<uint16_t> &value)
|
||||
{
|
||||
return value.value();
|
||||
}
|
||||
inline uint32_t be32_to_cpu(const BigEndian<uint32_t>&value)
|
||||
inline uint32_t be32_to_cpu(const BigEndian<uint32_t> &value)
|
||||
{
|
||||
return value.value();
|
||||
}
|
||||
|
||||
bool regdb_has_valid_signature(const u8 *data, unsigned int size) { return true; }
|
||||
|
||||
#define offsetofend(TYPE,FIELD) ((uint32_t)(offsetof(TYPE,FIELD)+sizeof(((TYPE*)0)->FIELD)))
|
||||
#define offsetofend(TYPE, FIELD) ((uint32_t)(offsetof(TYPE, FIELD) + sizeof(((TYPE *)0)->FIELD)))
|
||||
#define ASSERT_RTNL() // in the original, assert that rtnl is not locked.
|
||||
|
||||
/////////////////////////
|
||||
/////////////////////////
|
||||
// shamelessly lifted from linux net/wireless/reg.c
|
||||
|
||||
struct fwdb_country {
|
||||
u8 alpha2[2];
|
||||
__be16 coll_ptr;
|
||||
/* this struct cannot be extended */
|
||||
struct fwdb_country
|
||||
{
|
||||
u8 alpha2[2];
|
||||
__be16 coll_ptr;
|
||||
/* this struct cannot be extended */
|
||||
} __packed __aligned(4);
|
||||
|
||||
struct fwdb_collection {
|
||||
u8 len;
|
||||
u8 n_rules;
|
||||
u8 dfs_region;
|
||||
/* no optional data yet */
|
||||
/* aligned to 2, then followed by __be16 array of rule pointers */
|
||||
struct fwdb_collection
|
||||
{
|
||||
u8 len;
|
||||
u8 n_rules;
|
||||
u8 dfs_region;
|
||||
/* no optional data yet */
|
||||
/* aligned to 2, then followed by __be16 array of rule pointers */
|
||||
} __packed __aligned(4);
|
||||
|
||||
struct fwdb_header {
|
||||
__be32 magic;
|
||||
__be32 version;
|
||||
struct fwdb_country country[];
|
||||
struct fwdb_header
|
||||
{
|
||||
__be32 magic;
|
||||
__be32 version;
|
||||
struct fwdb_country country[];
|
||||
} __packed __aligned(4);
|
||||
|
||||
|
||||
enum fwdb_flags {
|
||||
FWDB_FLAG_NO_OFDM = BIT(0),
|
||||
FWDB_FLAG_NO_OUTDOOR = BIT(1),
|
||||
FWDB_FLAG_DFS = BIT(2),
|
||||
FWDB_FLAG_NO_IR = BIT(3),
|
||||
FWDB_FLAG_AUTO_BW = BIT(4),
|
||||
enum fwdb_flags
|
||||
{
|
||||
FWDB_FLAG_NO_OFDM = BIT(0),
|
||||
FWDB_FLAG_NO_OUTDOOR = BIT(1),
|
||||
FWDB_FLAG_DFS = BIT(2),
|
||||
FWDB_FLAG_NO_IR = BIT(3),
|
||||
FWDB_FLAG_AUTO_BW = BIT(4),
|
||||
};
|
||||
|
||||
struct fwdb_wmm_ac {
|
||||
u8 ecw;
|
||||
u8 aifsn;
|
||||
__be16 cot;
|
||||
struct fwdb_wmm_ac
|
||||
{
|
||||
u8 ecw;
|
||||
u8 aifsn;
|
||||
__be16 cot;
|
||||
} __packed;
|
||||
|
||||
struct fwdb_wmm_rule {
|
||||
struct fwdb_wmm_ac client[IEEE80211_NUM_ACS];
|
||||
struct fwdb_wmm_ac ap[IEEE80211_NUM_ACS];
|
||||
struct fwdb_wmm_rule
|
||||
{
|
||||
struct fwdb_wmm_ac client[IEEE80211_NUM_ACS];
|
||||
struct fwdb_wmm_ac ap[IEEE80211_NUM_ACS];
|
||||
} __packed;
|
||||
|
||||
struct fwdb_rule {
|
||||
u8 len;
|
||||
u8 flags;
|
||||
__be16 max_eirp;
|
||||
__be32 start, end, max_bw;
|
||||
/* start of optional data */
|
||||
__be16 cac_timeout;
|
||||
__be16 wmm_ptr;
|
||||
struct fwdb_rule
|
||||
{
|
||||
u8 len;
|
||||
u8 flags;
|
||||
__be16 max_eirp;
|
||||
__be32 start, end, max_bw;
|
||||
/* start of optional data */
|
||||
__be16 cac_timeout;
|
||||
__be16 wmm_ptr;
|
||||
} __packed __aligned(4);
|
||||
|
||||
#define FWDB_MAGIC 0x52474442
|
||||
#define FWDB_VERSION 20
|
||||
|
||||
|
||||
static int ecw2cw(int ecw)
|
||||
{
|
||||
return (1 << ecw) - 1;
|
||||
return (1 << ecw) - 1;
|
||||
}
|
||||
|
||||
static bool valid_wmm(struct fwdb_wmm_rule *rule)
|
||||
{
|
||||
struct fwdb_wmm_ac *ac = (struct fwdb_wmm_ac *)rule;
|
||||
int i;
|
||||
struct fwdb_wmm_ac *ac = (struct fwdb_wmm_ac *)rule;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < IEEE80211_NUM_ACS * 2; i++) {
|
||||
u16 cw_min = ecw2cw((ac[i].ecw & 0xf0) >> 4);
|
||||
u16 cw_max = ecw2cw(ac[i].ecw & 0x0f);
|
||||
u8 aifsn = ac[i].aifsn;
|
||||
for (i = 0; i < IEEE80211_NUM_ACS * 2; i++)
|
||||
{
|
||||
u16 cw_min = ecw2cw((ac[i].ecw & 0xf0) >> 4);
|
||||
u16 cw_max = ecw2cw(ac[i].ecw & 0x0f);
|
||||
u8 aifsn = ac[i].aifsn;
|
||||
|
||||
if (cw_min >= cw_max)
|
||||
return false;
|
||||
if (cw_min >= cw_max)
|
||||
return false;
|
||||
|
||||
if (aifsn < 1)
|
||||
return false;
|
||||
}
|
||||
if (aifsn < 1)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool valid_rule(const u8 *data, unsigned int size, u16 rule_ptr)
|
||||
{
|
||||
struct fwdb_rule *rule = (fwdb_rule *)(data + (rule_ptr << 2));
|
||||
struct fwdb_rule *rule = (fwdb_rule *)(data + (rule_ptr << 2));
|
||||
|
||||
if ((u8 *)rule + sizeof(rule->len) > data + size)
|
||||
return false;
|
||||
if ((u8 *)rule + sizeof(rule->len) > data + size)
|
||||
return false;
|
||||
|
||||
/* mandatory fields */
|
||||
if (rule->len < offsetofend(struct fwdb_rule, max_bw))
|
||||
return false;
|
||||
if (rule->len >= offsetofend(struct fwdb_rule, wmm_ptr)) {
|
||||
u32 wmm_ptr = be16_to_cpu(rule->wmm_ptr) << 2;
|
||||
struct fwdb_wmm_rule *wmm;
|
||||
/* mandatory fields */
|
||||
if (rule->len < offsetofend(struct fwdb_rule, max_bw))
|
||||
return false;
|
||||
if (rule->len >= offsetofend(struct fwdb_rule, wmm_ptr))
|
||||
{
|
||||
u32 wmm_ptr = be16_to_cpu(rule->wmm_ptr) << 2;
|
||||
struct fwdb_wmm_rule *wmm;
|
||||
|
||||
if (wmm_ptr + sizeof(struct fwdb_wmm_rule) > size)
|
||||
return false;
|
||||
if (wmm_ptr + sizeof(struct fwdb_wmm_rule) > size)
|
||||
return false;
|
||||
|
||||
wmm = (fwdb_wmm_rule *)(data + wmm_ptr);
|
||||
wmm = (fwdb_wmm_rule *)(data + wmm_ptr);
|
||||
|
||||
if (!valid_wmm(wmm))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
if (!valid_wmm(wmm))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool valid_country(const u8 *data, unsigned int size,
|
||||
const struct fwdb_country *country)
|
||||
const struct fwdb_country *country)
|
||||
{
|
||||
unsigned int ptr = be16_to_cpu(country->coll_ptr) << 2;
|
||||
struct fwdb_collection *coll = (struct fwdb_collection *)(data + ptr);
|
||||
__be16 *rules_ptr;
|
||||
unsigned int i;
|
||||
unsigned int ptr = be16_to_cpu(country->coll_ptr) << 2;
|
||||
struct fwdb_collection *coll = (struct fwdb_collection *)(data + ptr);
|
||||
__be16 *rules_ptr;
|
||||
unsigned int i;
|
||||
|
||||
/* make sure we can read len/n_rules */
|
||||
if ((u8 *)coll + offsetofend(typeof(*coll), n_rules) > data + size)
|
||||
return false;
|
||||
/* make sure we can read len/n_rules */
|
||||
if ((u8 *)coll + offsetofend(typeof(*coll), n_rules) > data + size)
|
||||
return false;
|
||||
|
||||
/* make sure base struct and all rules fit */
|
||||
if ((u8 *)coll + ALIGN(coll->len, 2) +
|
||||
(coll->n_rules * 2) > data + size)
|
||||
return false;
|
||||
/* make sure base struct and all rules fit */
|
||||
if ((u8 *)coll + ALIGN(coll->len, 2) +
|
||||
(coll->n_rules * 2) >
|
||||
data + size)
|
||||
return false;
|
||||
|
||||
/* mandatory fields must exist */
|
||||
if (coll->len < offsetofend(struct fwdb_collection, dfs_region))
|
||||
return false;
|
||||
/* mandatory fields must exist */
|
||||
if (coll->len < offsetofend(struct fwdb_collection, dfs_region))
|
||||
return false;
|
||||
|
||||
rules_ptr = (__be16 *)((u8 *)coll + ALIGN(coll->len, 2));
|
||||
rules_ptr = (__be16 *)((u8 *)coll + ALIGN(coll->len, 2));
|
||||
|
||||
for (i = 0; i < coll->n_rules; i++) {
|
||||
u16 rule_ptr = be16_to_cpu(rules_ptr[i]);
|
||||
for (i = 0; i < coll->n_rules; i++)
|
||||
{
|
||||
u16 rule_ptr = be16_to_cpu(rules_ptr[i]);
|
||||
|
||||
if (!valid_rule(data, size, rule_ptr))
|
||||
return false;
|
||||
}
|
||||
if (!valid_rule(data, size, rule_ptr))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool valid_regdb(const u8 *data, unsigned int size)
|
||||
{
|
||||
const struct fwdb_header *hdr = (fwdb_header *)data;
|
||||
const struct fwdb_country *country;
|
||||
const struct fwdb_header *hdr = (fwdb_header *)data;
|
||||
const struct fwdb_country *country;
|
||||
|
||||
if (size < sizeof(*hdr))
|
||||
return false;
|
||||
if (size < sizeof(*hdr))
|
||||
return false;
|
||||
|
||||
if (hdr->magic != cpu_to_be32(FWDB_MAGIC))
|
||||
return false;
|
||||
if (hdr->magic != cpu_to_be32(FWDB_MAGIC))
|
||||
return false;
|
||||
|
||||
if (hdr->version != cpu_to_be32(FWDB_VERSION))
|
||||
return false;
|
||||
if (hdr->version != cpu_to_be32(FWDB_VERSION))
|
||||
return false;
|
||||
|
||||
if (!regdb_has_valid_signature(data, size))
|
||||
return false;
|
||||
if (!regdb_has_valid_signature(data, size))
|
||||
return false;
|
||||
|
||||
country = &hdr->country[0];
|
||||
while ((u8 *)(country + 1) <= data + size) {
|
||||
if (!country->coll_ptr)
|
||||
break;
|
||||
if (!valid_country(data, size, country))
|
||||
return false;
|
||||
country++;
|
||||
}
|
||||
country = &hdr->country[0];
|
||||
while ((u8 *)(country + 1) <= data + size)
|
||||
{
|
||||
if (!country->coll_ptr)
|
||||
break;
|
||||
if (!valid_country(data, size, country))
|
||||
return false;
|
||||
country++;
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void set_wmm_rule(const struct fwdb_header *db,
|
||||
const struct fwdb_country *country,
|
||||
const struct fwdb_rule *rule,
|
||||
WifiRule*rrule)
|
||||
const struct fwdb_country *country,
|
||||
const struct fwdb_rule *rule,
|
||||
WifiRule *rrule)
|
||||
{
|
||||
// not implemented.
|
||||
return;
|
||||
@@ -528,11 +538,11 @@ static void set_wmm_rule(const struct fwdb_header *db,
|
||||
// wmm = (fwdb_wmm_rule *)((u8 *)db + wmm_ptr);
|
||||
|
||||
// if (!valid_wmm(wmm)) {
|
||||
// std::cout
|
||||
// std::cout
|
||||
// << "Invalid regulatory WMM rule "
|
||||
// << be32_to_cpu(rule->start)
|
||||
// << be32_to_cpu(rule->start)
|
||||
// << "-" << be32_to_cpu(rule->end)
|
||||
// << " in domain " << country->alpha2[0] << country->alpha2[1]
|
||||
// << " in domain " << country->alpha2[0] << country->alpha2[1]
|
||||
// << std::endl;
|
||||
// return;
|
||||
// }
|
||||
@@ -553,90 +563,115 @@ static void set_wmm_rule(const struct fwdb_header *db,
|
||||
// rrule->has_wmm = true;
|
||||
// }
|
||||
|
||||
|
||||
static WifiRegulations regdb_load_country(const struct fwdb_header *db,
|
||||
const struct fwdb_country *country)
|
||||
const struct fwdb_country *country)
|
||||
{
|
||||
unsigned int ptr = be16_to_cpu(country->coll_ptr) << 2;
|
||||
struct fwdb_collection *coll = (fwdb_collection *)((u8 *)db + ptr);
|
||||
unsigned int i;
|
||||
unsigned int ptr = be16_to_cpu(country->coll_ptr) << 2;
|
||||
struct fwdb_collection *coll = (fwdb_collection *)((u8 *)db + ptr);
|
||||
unsigned int i;
|
||||
|
||||
WifiRegulations wifiRegulations;
|
||||
|
||||
wifiRegulations.reg_alpha2 = SS(country->alpha2[0] << country->alpha2[1]);
|
||||
wifiRegulations.dfs_region = (DfsRegion)(coll->dfs_region);
|
||||
unsigned int nRules = coll->n_rules;
|
||||
wifiRegulations.reg_alpha2 = SS(country->alpha2[0] << country->alpha2[1]);
|
||||
wifiRegulations.dfs_region = (DfsRegion)(coll->dfs_region);
|
||||
unsigned int nRules = coll->n_rules;
|
||||
|
||||
for (i = 0; i < nRules; i++) {
|
||||
const __be16 *rules_ptr = (const __be16 *)((u8 *)coll + ALIGN(coll->len, 2));
|
||||
unsigned int rule_ptr = be16_to_cpu(rules_ptr[i]) << 2;
|
||||
struct fwdb_rule *rule = (fwdb_rule *)((u8 *)db + rule_ptr);
|
||||
for (i = 0; i < nRules; i++)
|
||||
{
|
||||
const __be16 *rules_ptr = (const __be16 *)((u8 *)coll + ALIGN(coll->len, 2));
|
||||
unsigned int rule_ptr = be16_to_cpu(rules_ptr[i]) << 2;
|
||||
struct fwdb_rule *rule = (fwdb_rule *)((u8 *)db + rule_ptr);
|
||||
|
||||
WifiRule wifiRule;
|
||||
wifiRule.start_freq_khz = be32_to_cpu(rule->start);
|
||||
wifiRule.end_freq_khz = be32_to_cpu(rule->end);
|
||||
wifiRule.max_bandwidth_khz = be32_to_cpu(rule->max_bw);
|
||||
wifiRule.end_freq_khz = be32_to_cpu(rule->end);
|
||||
wifiRule.max_bandwidth_khz = be32_to_cpu(rule->max_bw);
|
||||
wifiRule.max_antenna_gain = 0;
|
||||
wifiRule.max_eirp = be16_to_cpu(rule->max_eirp);
|
||||
wifiRule.flags = RegRuleFlags::NONE;
|
||||
|
||||
if (rule->flags & FWDB_FLAG_NO_OFDM)
|
||||
wifiRule.flags |= RegRuleFlags::NO_OFDM;
|
||||
if (rule->flags & FWDB_FLAG_NO_OUTDOOR)
|
||||
wifiRule.flags |= RegRuleFlags::NO_OUTDOOR;
|
||||
if (rule->flags & FWDB_FLAG_DFS)
|
||||
wifiRule.flags |= RegRuleFlags::DFS;
|
||||
if (rule->flags & FWDB_FLAG_NO_IR)
|
||||
wifiRule.flags |= RegRuleFlags::NO_IR;
|
||||
if (rule->flags & FWDB_FLAG_AUTO_BW)
|
||||
wifiRule.flags |= RegRuleFlags::AUTO_BW;
|
||||
if (rule->flags & FWDB_FLAG_NO_OFDM)
|
||||
wifiRule.flags |= RegRuleFlags::NO_OFDM;
|
||||
if (rule->flags & FWDB_FLAG_NO_OUTDOOR)
|
||||
wifiRule.flags |= RegRuleFlags::NO_OUTDOOR;
|
||||
if (rule->flags & FWDB_FLAG_DFS)
|
||||
wifiRule.flags |= RegRuleFlags::DFS;
|
||||
if (rule->flags & FWDB_FLAG_NO_IR)
|
||||
wifiRule.flags |= RegRuleFlags::NO_IR;
|
||||
if (rule->flags & FWDB_FLAG_AUTO_BW)
|
||||
wifiRule.flags |= RegRuleFlags::AUTO_BW;
|
||||
|
||||
wifiRule.dfs_cac_ms = 0;
|
||||
wifiRule.dfs_cac_ms = 0;
|
||||
|
||||
/* handle optional data */
|
||||
if (rule->len >= offsetofend(struct fwdb_rule, cac_timeout))
|
||||
wifiRule.dfs_cac_ms =
|
||||
1000 * be16_to_cpu(rule->cac_timeout);
|
||||
// if (rule->len >= offsetofend(struct fwdb_rule, wmm_ptr))
|
||||
// set_wmm_rule(db, country, rule, &wifiRule);
|
||||
/* handle optional data */
|
||||
if (rule->len >= offsetofend(struct fwdb_rule, cac_timeout))
|
||||
wifiRule.dfs_cac_ms =
|
||||
1000 * be16_to_cpu(rule->cac_timeout);
|
||||
// if (rule->len >= offsetofend(struct fwdb_rule, wmm_ptr))
|
||||
// set_wmm_rule(db, country, rule, &wifiRule);
|
||||
wifiRegulations.rules.push_back(std::move(wifiRule));
|
||||
}
|
||||
}
|
||||
|
||||
return wifiRegulations;
|
||||
return wifiRegulations;
|
||||
}
|
||||
|
||||
|
||||
static std::vector<WifiRegulations> load_regdb(u8*pData)
|
||||
static std::vector<WifiRegulations> load_regdb(u8 *pData)
|
||||
{
|
||||
const struct fwdb_header *hdr = (const fwdb_header*)pData;
|
||||
const struct fwdb_country *country;
|
||||
const struct fwdb_header *hdr = (const fwdb_header *)pData;
|
||||
const struct fwdb_country *country;
|
||||
|
||||
ASSERT_RTNL();
|
||||
if (!pData)
|
||||
ASSERT_RTNL();
|
||||
if (!pData)
|
||||
{
|
||||
throw std::runtime_error("Regdb not loaded.");
|
||||
}
|
||||
std::vector<WifiRegulations> result;
|
||||
|
||||
country = &hdr->country[0];
|
||||
while (country->coll_ptr) {
|
||||
country = &hdr->country[0];
|
||||
while (country->coll_ptr)
|
||||
{
|
||||
result.push_back(regdb_load_country(hdr, country));
|
||||
country++;
|
||||
}
|
||||
country++;
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void RegDb::Load20()
|
||||
{
|
||||
u8*data = (u8*)ptr();
|
||||
u8 *data = (u8 *)ptr();
|
||||
unsigned int size = (unsigned int)this->data.size();
|
||||
if (!valid_regdb(data,size))
|
||||
if (!valid_regdb(data, size))
|
||||
{
|
||||
throw std::runtime_error("Invalid file format.");
|
||||
|
||||
}
|
||||
this->regulations = load_regdb(data);
|
||||
this->regulations = load_regdb(data);
|
||||
this->isValid = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static std::map<std::string,std::string> getIsoNamesDict(const std::filesystem::path&filename)
|
||||
{
|
||||
std::map<std::string,std::string> result;
|
||||
std::ifstream f(filename);
|
||||
if (!f.is_open())
|
||||
{
|
||||
throw std::runtime_error("Can't open WiFi regulatory domain names file.");
|
||||
}
|
||||
json_reader reader(f);
|
||||
reader.read(&result);
|
||||
return result;
|
||||
}
|
||||
std::map<std::string,std::string> RegDb::getRegulatoryDomains(const std::filesystem::path&isoFilenamesfile) const
|
||||
{
|
||||
std::map<std::string,std::string> keyToNameDict = getIsoNamesDict(isoFilenamesfile);
|
||||
std::map<std::string,std::string> result;
|
||||
|
||||
for (const auto ®ulation : this->regulations)
|
||||
{
|
||||
if (keyToNameDict.contains(regulation.reg_alpha2))
|
||||
{
|
||||
result[regulation.reg_alpha2] = keyToNameDict[regulation.reg_alpha2];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user