2012-02-04 01:25:53

by Luis R. Rodriguez

[permalink] [raw]
Subject: [RFC 00/11] crda: start combing code for library

I've had these sittng in my queueu for a while, so here they are. Its code
that starts combing CRDA to allow for a small library to be later extracted to
be shared between CRDA and the regulatory simulator [0].

Sending these out for review. The library isn't split yet but I figured I'd
send this out for review so far. I've decided to go with a compromise and
simplify the library by only letting the library deal with reads from the
database file atomically. I think the benefit is cleaner code without having to
shuffle and keep some local mmap()'d value somewhere.

Anyway, let me know if this seems agreeable.

[0] git://github.com/mcgrof/regsim.git

Luis R. Rodriguez (11):
crda: move country2rd() and its helper to reglib.c
crda: add a reglib iterator reglib_for_each_country()
crda: make intersect.c use reglib_for_each_country()
crda: close fd upon leaving
crda: add new reglib_get_country_alpha2()
crda: add dfs_region to the ieee80211_regdomain data structure
crda: make crda use reglib_get_country_alpha2()
crda: clean header files
crda: make country2rd() static
crda: make usage of regdb.h exclusive to reglib.c
crda: rename reglib_get_*() routines

Makefile | 2 +-
crda.c | 114 +++++++------------------------
intersect.c | 96 +++-----------------------
print-regdom.c | 80 +++-------------------
regdbdump.c | 82 +---------------------
reglib.c | 207 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
reglib.h | 17 +++--
7 files changed, 272 insertions(+), 326 deletions(-)

--
1.7.4.15.g7811d



2012-02-04 01:26:07

by Luis R. Rodriguez

[permalink] [raw]
Subject: [RFC 05/11] crda: add new reglib_get_country_alpha2()

This will be used by CRDA to find the alpha2.

Signed-off-by: Luis R. Rodriguez <[email protected]>
---
reglib.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
reglib.h | 3 ++
2 files changed, 77 insertions(+), 0 deletions(-)

diff --git a/reglib.c b/reglib.c
index 0cef7a5..642f907 100644
--- a/reglib.c
+++ b/reglib.c
@@ -7,6 +7,8 @@
#include <stdlib.h>
#include <sys/mman.h>
#include <fcntl.h>
+#include <stdbool.h>
+#include <unistd.h>

#include <arpa/inet.h> /* ntohl */

@@ -281,3 +283,75 @@ reglib_get_country_idx(unsigned int idx, const char *file)

return rd;
}
+
+struct ieee80211_regdomain *
+reglib_get_country_alpha2(const char *alpha2, const char *file)
+{
+ int fd;
+ struct stat stat;
+ uint8_t *db;
+ struct regdb_file_header *header;
+ struct regdb_file_reg_country *countries;
+ int dblen, siglen, num_countries;
+ struct ieee80211_regdomain *rd = NULL;
+ struct regdb_file_reg_country *country;
+ unsigned int i;
+ bool found_country = false;
+
+ fd = open(file, O_RDONLY);
+
+ if (fd < 0)
+ return NULL;
+
+ if (fstat(fd, &stat))
+ return NULL;
+
+ dblen = stat.st_size;
+
+ db = mmap(NULL, dblen, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (db == MAP_FAILED)
+ return NULL;
+
+ header = crda_get_file_ptr(db, dblen, sizeof(*header), 0);
+
+ if (ntohl(header->magic) != REGDB_MAGIC)
+ return NULL;
+
+ if (ntohl(header->version) != REGDB_VERSION)
+ return NULL;
+
+ siglen = ntohl(header->signature_length);
+ /* adjust dblen so later sanity checks don't run into the signature */
+ dblen -= siglen;
+
+ if (dblen <= (int)sizeof(*header))
+ return NULL;
+
+ /* verify signature */
+ if (!crda_verify_db_signature(db, dblen, siglen))
+ return NULL;
+
+ num_countries = ntohl(header->reg_country_num);
+ countries = crda_get_file_ptr(db, dblen,
+ sizeof(struct regdb_file_reg_country) * num_countries,
+ header->reg_country_ptr);
+
+ for (i = 0; i < num_countries; i++) {
+ country = countries + i;
+ if (memcmp(country->alpha2, alpha2, 2) == 0) {
+ found_country = 1;
+ break;
+ }
+ }
+
+ if (!found_country)
+ goto out;
+
+ rd = country2rd(db, dblen, country);
+ if (!rd)
+ goto out;
+
+out:
+ close(fd);
+ return rd;
+}
diff --git a/reglib.h b/reglib.h
index ef85fac..d76ec52 100644
--- a/reglib.h
+++ b/reglib.h
@@ -87,6 +87,9 @@ reglib_get_country_idx(unsigned int idx, const char *file);
__rd = reglib_get_country_idx(__idx, __file), \
__idx++)

+struct ieee80211_regdomain *
+reglib_get_country_alpha2(const char *alpha2, const char *file);
+
/* reg helpers */
void print_regdom(struct ieee80211_regdomain *rd);

--
1.7.4.15.g7811d


2012-02-04 01:25:59

by Luis R. Rodriguez

[permalink] [raw]
Subject: [RFC 02/11] crda: add a reglib iterator reglib_for_each_country()

To allow for a simple library on reglib.c we want to enable
an iterator over the regulatory database that does not have
to lock the file, or pass references to the file. We instead
add an iterator reglib_get_country_idx() which will use a
new reglib_get_country_idx(), that does an O(n) search for
each new regulatory domain it needs to read.

The trade off here is to allow for a simple reglib.c implementation
at the cost that upon each iteration reglib_get_country_idx()
we will will be opening the regdb, and verifying the db signature.
Given that the only user of this iterator is regdbdump though and
that this is used for debugging for now this is trade off I am
willing to live with.

Systems that want to use the regdb as a database for fine tuning
radio parameters dynamically and reading this file very *often*
(seconds, minutes, who knows what the future holds) may want to
consider a slight optimization of exporting the direct mmap()
through the library but we are I think light years away from that.

Signed-off-by: Luis R. Rodriguez <[email protected]>
---
Makefile | 2 +-
regdbdump.c | 79 +++--------------------------------------------------------
reglib.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++
reglib.h | 9 ++++++
4 files changed, 83 insertions(+), 76 deletions(-)

diff --git a/Makefile b/Makefile
index 5a8ed46..1d34bde 100644
--- a/Makefile
+++ b/Makefile
@@ -105,7 +105,7 @@ keys-%.c: utils/key2pub.py $(wildcard $(PUBKEY_DIR)/*.pem)
$(NQ) ' Trusted pubkeys:' $(wildcard $(PUBKEY_DIR)/*.pem)
$(Q)./utils/key2pub.py --$* $(wildcard $(PUBKEY_DIR)/*.pem) $@

-%.o: %.c regdb.h
+%.o: %.c regdb.h reglib.h
$(NQ) ' CC ' $@
$(Q)$(CC) -c $(CPPFLAGS) $(CFLAGS) -o $@ $<

diff --git a/regdbdump.c b/regdbdump.c
index 9ba806c..6d4cf56 100644
--- a/regdbdump.c
+++ b/regdbdump.c
@@ -1,94 +1,23 @@
#include <errno.h>
-#include <stdlib.h>
#include <stdio.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <arpa/inet.h> /* ntohl */

#include "regdb.h"
#include "reglib.h"

int main(int argc, char **argv)
{
- int fd;
- struct stat stat;
- uint8_t *db;
- struct regdb_file_header *header;
- struct regdb_file_reg_country *countries;
- int dblen, siglen, num_countries, i, r = 0;
struct ieee80211_regdomain *rd = NULL;
+ unsigned int idx = 0;

if (argc != 2) {
fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
return 2;
}

- fd = open(argv[1], O_RDONLY);
- if (fd < 0) {
- perror("failed to open db file");
- return 2;
- }
-
- if (fstat(fd, &stat)) {
- perror("failed to fstat db file");
- return 2;
- }
-
- dblen = stat.st_size;
-
- db = mmap(NULL, dblen, PROT_READ, MAP_PRIVATE, fd, 0);
- if (db == MAP_FAILED) {
- perror("failed to mmap db file");
- return 2;
- }
-
- header = crda_get_file_ptr(db, dblen, sizeof(*header), 0);
-
- if (ntohl(header->magic) != REGDB_MAGIC) {
- fprintf(stderr, "Invalid database magic\n");
- return 2;
- }
-
- if (ntohl(header->version) != REGDB_VERSION) {
- fprintf(stderr, "Invalid database version\n");
- return 2;
- }
-
- siglen = ntohl(header->signature_length);
- /* adjust dblen so later sanity checks don't run into the signature */
- dblen -= siglen;
-
- if (dblen <= (int)sizeof(*header)) {
- fprintf(stderr, "Invalid signature length %d\n", siglen);
- return 2;
- }
-
- /* verify signature */
- if (!crda_verify_db_signature(db, dblen, siglen))
- return -EINVAL;
-
- num_countries = ntohl(header->reg_country_num);
- countries = crda_get_file_ptr(db, dblen,
- sizeof(struct regdb_file_reg_country) * num_countries,
- header->reg_country_ptr);
-
- for (i = 0; i < num_countries; i++) {
- struct regdb_file_reg_country *country = countries + i;
-
- rd = country2rd(db, dblen, country);
- if (!rd) {
- r = -ENOMEM;
- fprintf(stderr, "Could not covert country "
- "(%.2s) to rd\n", country->alpha2);
- goto out;
- }
-
+ reglib_for_each_country(rd, idx, argv[1]) {
print_regdom(rd);
free(rd);
- rd = NULL;
-
}
-out:
- return r;
+
+ return 0;
}
diff --git a/reglib.c b/reglib.c
index 5d66481..0cef7a5 100644
--- a/reglib.c
+++ b/reglib.c
@@ -3,6 +3,13 @@
#include <arpa/inet.h>
#include <sys/types.h>
#include <dirent.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+
+#include <arpa/inet.h> /* ntohl */
+
#include "reglib.h"

#ifdef USE_OPENSSL
@@ -212,3 +219,65 @@ struct ieee80211_regdomain *country2rd(uint8_t *db, int dblen,

return rd;
}
+
+struct ieee80211_regdomain *
+reglib_get_country_idx(unsigned int idx, const char *file)
+{
+ int fd;
+ struct stat stat;
+ uint8_t *db;
+ struct regdb_file_header *header;
+ struct regdb_file_reg_country *countries;
+ int dblen, siglen, num_countries;
+ struct ieee80211_regdomain *rd = NULL;
+ struct regdb_file_reg_country *country;
+
+ fd = open(file, O_RDONLY);
+
+ if (fd < 0)
+ return NULL;
+
+ if (fstat(fd, &stat))
+ return NULL;
+
+ dblen = stat.st_size;
+
+ db = mmap(NULL, dblen, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (db == MAP_FAILED)
+ return NULL;
+
+ header = crda_get_file_ptr(db, dblen, sizeof(*header), 0);
+
+ if (ntohl(header->magic) != REGDB_MAGIC)
+ return NULL;
+
+ if (ntohl(header->version) != REGDB_VERSION)
+ return NULL;
+
+ siglen = ntohl(header->signature_length);
+ /* adjust dblen so later sanity checks don't run into the signature */
+ dblen -= siglen;
+
+ if (dblen <= (int)sizeof(*header))
+ return NULL;
+
+ /* verify signature */
+ if (!crda_verify_db_signature(db, dblen, siglen))
+ return NULL;
+
+ num_countries = ntohl(header->reg_country_num);
+ countries = crda_get_file_ptr(db, dblen,
+ sizeof(struct regdb_file_reg_country) * num_countries,
+ header->reg_country_ptr);
+
+ if (idx >= num_countries)
+ return NULL;
+
+ country = countries + idx;
+
+ rd = country2rd(db, dblen, country);
+ if (!rd)
+ return NULL;
+
+ return rd;
+}
diff --git a/reglib.h b/reglib.h
index e6adc14..ef85fac 100644
--- a/reglib.h
+++ b/reglib.h
@@ -78,6 +78,15 @@ int crda_verify_db_signature(uint8_t *db, int dblen, int siglen);
struct ieee80211_regdomain *country2rd(uint8_t *db, int dblen,
struct regdb_file_reg_country *country);

+struct ieee80211_regdomain *
+reglib_get_country_idx(unsigned int idx, const char *file);
+
+#define reglib_for_each_country(__rd, __idx, __file) \
+ for (__rd = reglib_get_country_idx(__idx, __file); \
+ __rd != NULL; \
+ __rd = reglib_get_country_idx(__idx, __file), \
+ __idx++)
+
/* reg helpers */
void print_regdom(struct ieee80211_regdomain *rd);

--
1.7.4.15.g7811d


2012-02-04 01:26:26

by Luis R. Rodriguez

[permalink] [raw]
Subject: [RFC 11/11] crda: rename reglib_get_*() routines

reglib_get_country_idx() --> reglib_get_rd_alpha2()
reglib_get_country_alpha2() --> reglib_get_rd_alpha2()

This reflects better what we provide back out.

Signed-off-by: Luis R. Rodriguez <[email protected]>
---
crda.c | 2 +-
reglib.c | 4 ++--
reglib.h | 8 ++++----
3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/crda.c b/crda.c
index c6dc3d4..cdbc69a 100644
--- a/crda.c
+++ b/crda.c
@@ -191,7 +191,7 @@ int main(int argc, char **argv)

close(fd);

- rd = reglib_get_country_alpha2(alpha2, *regdb);
+ rd = reglib_get_rd_alpha2(alpha2, *regdb);
if (!rd) {
fprintf(stderr, "No country match in regulatory database.\n");
return -1;
diff --git a/reglib.c b/reglib.c
index 12698fa..bc81974 100644
--- a/reglib.c
+++ b/reglib.c
@@ -226,7 +226,7 @@ country2rd(uint8_t *db, int dblen,
}

struct ieee80211_regdomain *
-reglib_get_country_idx(unsigned int idx, const char *file)
+reglib_get_rd_idx(unsigned int idx, const char *file)
{
int fd;
struct stat stat;
@@ -288,7 +288,7 @@ reglib_get_country_idx(unsigned int idx, const char *file)
}

struct ieee80211_regdomain *
-reglib_get_country_alpha2(const char *alpha2, const char *file)
+reglib_get_rd_alpha2(const char *alpha2, const char *file)
{
int fd;
struct stat stat;
diff --git a/reglib.h b/reglib.h
index 99e6c76..9b9bd5c 100644
--- a/reglib.h
+++ b/reglib.h
@@ -74,16 +74,16 @@ void *crda_get_file_ptr(uint8_t *db, int dblen, int structlen, uint32_t ptr);
int crda_verify_db_signature(uint8_t *db, int dblen, int siglen);

struct ieee80211_regdomain *
-reglib_get_country_idx(unsigned int idx, const char *file);
+reglib_get_rd_idx(unsigned int idx, const char *file);

#define reglib_for_each_country(__rd, __idx, __file) \
- for (__rd = reglib_get_country_idx(__idx, __file); \
+ for (__rd = reglib_get_rd_idx(__idx, __file); \
__rd != NULL; \
- __rd = reglib_get_country_idx(__idx, __file), \
+ __rd = reglib_get_rd_idx(__idx, __file), \
__idx++)

struct ieee80211_regdomain *
-reglib_get_country_alpha2(const char *alpha2, const char *file);
+reglib_get_rd_alpha2(const char *alpha2, const char *file);

/* reg helpers */
void print_regdom(struct ieee80211_regdomain *rd);
--
1.7.4.15.g7811d


2012-02-04 01:26:04

by Luis R. Rodriguez

[permalink] [raw]
Subject: [RFC 04/11] crda: close fd upon leaving

This was never done. Do this at the end for now but soon
this will be changed in preference for the file opening
only to be done by crda for checking which file to use
to pass on to reglib for usage.

Signed-off-by: Luis R. Rodriguez <[email protected]>
---
crda.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/crda.c b/crda.c
index 1db54a5..5a1cd83 100644
--- a/crda.c
+++ b/crda.c
@@ -10,6 +10,7 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <arpa/inet.h>
+#include <unistd.h>

#include <netlink/genl/genl.h>
#include <netlink/genl/family.h>
@@ -333,5 +334,7 @@ nla_put_failure:
nlmsg_free(msg);
out:
nl80211_cleanup(&nlstate);
+ close(fd);
+
return r;
}
--
1.7.4.15.g7811d


2012-02-04 01:26:11

by Luis R. Rodriguez

[permalink] [raw]
Subject: [RFC 06/11] crda: add dfs_region to the ieee80211_regdomain data structure

This will be used later once crda.c starts using the
ieee80211_regdomain data structure passed on from reglib
instead of using the mmap()'d regulatory file directly.

Signed-off-by: Luis R. Rodriguez <[email protected]>
---
reglib.c | 1 +
reglib.h | 1 +
2 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/reglib.c b/reglib.c
index 642f907..759c676 100644
--- a/reglib.c
+++ b/reglib.c
@@ -212,6 +212,7 @@ struct ieee80211_regdomain *country2rd(uint8_t *db, int dblen,

rd->alpha2[0] = country->alpha2[0];
rd->alpha2[1] = country->alpha2[1];
+ rd->dfs_region = country->creqs & 0x3;
rd->n_reg_rules = num_rules;

for (i = 0; i < num_rules; i++) {
diff --git a/reglib.h b/reglib.h
index d76ec52..bec6359 100644
--- a/reglib.h
+++ b/reglib.h
@@ -29,6 +29,7 @@ struct ieee80211_reg_rule {
struct ieee80211_regdomain {
uint32_t n_reg_rules;
char alpha2[2];
+ uint8_t dfs_region;
struct ieee80211_reg_rule reg_rules[];
};

--
1.7.4.15.g7811d


2012-02-04 01:25:56

by Luis R. Rodriguez

[permalink] [raw]
Subject: [RFC 01/11] crda: move country2rd() and its helper to reglib.c

Start cleaning the way we deal with reglib.c as the goal
is to make that stuff a library to be shared first in
userspace with the regulatory simulator [0]. We start
off by moving country2rd() and its helper over to
reglib.c.

[0] git://github.com/mcgrof/regsim.git

Signed-off-by: Luis R. Rodriguez <[email protected]>
---
print-regdom.c | 61 --------------------------------------------------------
reglib.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 61 insertions(+), 61 deletions(-)

diff --git a/print-regdom.c b/print-regdom.c
index f34a8db..a3bedeb 100644
--- a/print-regdom.c
+++ b/print-regdom.c
@@ -4,67 +4,6 @@
#include <arpa/inet.h>
#include "reglib.h"

-static void reg_rule2rd(uint8_t *db, int dblen,
- uint32_t ruleptr, struct ieee80211_reg_rule *rd_reg_rule)
-{
- struct regdb_file_reg_rule *rule;
- struct regdb_file_freq_range *freq;
- struct regdb_file_power_rule *power;
-
- struct ieee80211_freq_range *rd_freq_range = &rd_reg_rule->freq_range;
- struct ieee80211_power_rule *rd_power_rule = &rd_reg_rule->power_rule;
-
- rule = crda_get_file_ptr(db, dblen, sizeof(*rule), ruleptr);
- freq = crda_get_file_ptr(db, dblen, sizeof(*freq), rule->freq_range_ptr);
- power = crda_get_file_ptr(db, dblen, sizeof(*power), rule->power_rule_ptr);
-
- rd_freq_range->start_freq_khz = ntohl(freq->start_freq);
- rd_freq_range->end_freq_khz = ntohl(freq->end_freq);
- rd_freq_range->max_bandwidth_khz = ntohl(freq->max_bandwidth);
-
- rd_power_rule->max_antenna_gain = ntohl(power->max_antenna_gain);
- rd_power_rule->max_eirp = ntohl(power->max_eirp);
-
- rd_reg_rule->flags = ntohl(rule->flags);
-}
-
-/* Converts a file regdomain to ieee80211_regdomain, easier to manage */
-struct ieee80211_regdomain *country2rd(uint8_t *db, int dblen,
- struct regdb_file_reg_country *country)
-{
- struct regdb_file_reg_rules_collection *rcoll;
- struct ieee80211_regdomain *rd;
- int i, num_rules, size_of_rd;
-
- rcoll = crda_get_file_ptr(db, dblen, sizeof(*rcoll),
- country->reg_collection_ptr);
- num_rules = ntohl(rcoll->reg_rule_num);
- /* re-get pointer with sanity checking for num_rules */
- rcoll = crda_get_file_ptr(db, dblen,
- sizeof(*rcoll) + num_rules * sizeof(uint32_t),
- country->reg_collection_ptr);
-
- size_of_rd = sizeof(struct ieee80211_regdomain) +
- num_rules * sizeof(struct ieee80211_reg_rule);
-
- rd = malloc(size_of_rd);
- if (!rd)
- return NULL;
-
- memset(rd, 0, size_of_rd);
-
- rd->alpha2[0] = country->alpha2[0];
- rd->alpha2[1] = country->alpha2[1];
- rd->n_reg_rules = num_rules;
-
- for (i = 0; i < num_rules; i++) {
- reg_rule2rd(db, dblen, rcoll->reg_rule_ptrs[i],
- &rd->reg_rules[i]);
- }
-
- return rd;
-}
-
static void print_reg_rule(struct ieee80211_reg_rule *rule)
{
struct ieee80211_freq_range *freq;
diff --git a/reglib.c b/reglib.c
index ebf0fb1..5d66481 100644
--- a/reglib.c
+++ b/reglib.c
@@ -151,3 +151,64 @@ out:
return 1;
#endif
}
+
+static void reg_rule2rd(uint8_t *db, int dblen,
+ uint32_t ruleptr, struct ieee80211_reg_rule *rd_reg_rule)
+{
+ struct regdb_file_reg_rule *rule;
+ struct regdb_file_freq_range *freq;
+ struct regdb_file_power_rule *power;
+
+ struct ieee80211_freq_range *rd_freq_range = &rd_reg_rule->freq_range;
+ struct ieee80211_power_rule *rd_power_rule = &rd_reg_rule->power_rule;
+
+ rule = crda_get_file_ptr(db, dblen, sizeof(*rule), ruleptr);
+ freq = crda_get_file_ptr(db, dblen, sizeof(*freq), rule->freq_range_ptr);
+ power = crda_get_file_ptr(db, dblen, sizeof(*power), rule->power_rule_ptr);
+
+ rd_freq_range->start_freq_khz = ntohl(freq->start_freq);
+ rd_freq_range->end_freq_khz = ntohl(freq->end_freq);
+ rd_freq_range->max_bandwidth_khz = ntohl(freq->max_bandwidth);
+
+ rd_power_rule->max_antenna_gain = ntohl(power->max_antenna_gain);
+ rd_power_rule->max_eirp = ntohl(power->max_eirp);
+
+ rd_reg_rule->flags = ntohl(rule->flags);
+}
+
+/* Converts a file regdomain to ieee80211_regdomain, easier to manage */
+struct ieee80211_regdomain *country2rd(uint8_t *db, int dblen,
+ struct regdb_file_reg_country *country)
+{
+ struct regdb_file_reg_rules_collection *rcoll;
+ struct ieee80211_regdomain *rd;
+ int i, num_rules, size_of_rd;
+
+ rcoll = crda_get_file_ptr(db, dblen, sizeof(*rcoll),
+ country->reg_collection_ptr);
+ num_rules = ntohl(rcoll->reg_rule_num);
+ /* re-get pointer with sanity checking for num_rules */
+ rcoll = crda_get_file_ptr(db, dblen,
+ sizeof(*rcoll) + num_rules * sizeof(uint32_t),
+ country->reg_collection_ptr);
+
+ size_of_rd = sizeof(struct ieee80211_regdomain) +
+ num_rules * sizeof(struct ieee80211_reg_rule);
+
+ rd = malloc(size_of_rd);
+ if (!rd)
+ return NULL;
+
+ memset(rd, 0, size_of_rd);
+
+ rd->alpha2[0] = country->alpha2[0];
+ rd->alpha2[1] = country->alpha2[1];
+ rd->n_reg_rules = num_rules;
+
+ for (i = 0; i < num_rules; i++) {
+ reg_rule2rd(db, dblen, rcoll->reg_rule_ptrs[i],
+ &rd->reg_rules[i]);
+ }
+
+ return rd;
+}
--
1.7.4.15.g7811d


2012-02-04 01:26:02

by Luis R. Rodriguez

[permalink] [raw]
Subject: [RFC 03/11] crda: make intersect.c use reglib_for_each_country()

Signed-off-by: Luis R. Rodriguez <[email protected]>
---
intersect.c | 93 +++++++---------------------------------------------------
1 files changed, 12 insertions(+), 81 deletions(-)

diff --git a/intersect.c b/intersect.c
index 2e5dacf..6d3d393 100644
--- a/intersect.c
+++ b/intersect.c
@@ -182,101 +182,26 @@ static struct ieee80211_regdomain *regdom_intersect(

int main(int argc, char **argv)
{
- int fd;
- struct stat stat;
- uint8_t *db;
- struct regdb_file_header *header;
- struct regdb_file_reg_country *countries;
- int dblen, siglen, num_countries, i, r = 0;
+ int r = 0;
struct ieee80211_regdomain *prev_world = NULL, *rd = NULL, *world = NULL;
int intersected = 0;
+ unsigned int idx = 0;

if (argc != 2) {
- fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
- return 2;
- }
-
- fd = open(argv[1], O_RDONLY);
- if (fd < 0) {
- perror("failed to open db file");
- return 2;
- }
-
- if (fstat(fd, &stat)) {
- perror("failed to fstat db file");
- return 2;
- }
-
- dblen = stat.st_size;
-
- db = mmap(NULL, dblen, PROT_READ, MAP_PRIVATE, fd, 0);
- if (db == MAP_FAILED) {
- perror("failed to mmap db file");
- return 2;
- }
-
- header = crda_get_file_ptr(db, dblen, sizeof(*header), 0);
-
- if (ntohl(header->magic) != REGDB_MAGIC) {
- fprintf(stderr, "Invalid database magic\n");
- return 2;
- }
-
- if (ntohl(header->version) != REGDB_VERSION) {
- fprintf(stderr, "Invalid database version\n");
- return 2;
- }
-
- siglen = ntohl(header->signature_length);
- /* adjust dblen so later sanity checks don't run into the signature */
- dblen -= siglen;
-
- if (dblen <= (int)sizeof(*header)) {
- fprintf(stderr, "Invalid signature length %d\n", siglen);
- return 2;
- }
-
- /* verify signature */
- if (!crda_verify_db_signature(db, dblen, siglen))
+ fprintf(stderr, "You must specify a file\n");
return -EINVAL;
-
- num_countries = ntohl(header->reg_country_num);
-
- if (num_countries <= 0)
- return 0;
-
- countries = crda_get_file_ptr(db, dblen,
- sizeof(struct regdb_file_reg_country) * num_countries,
- header->reg_country_ptr);
+ }

/* We intersect only when we have to rd structures ready */
- for (i = 0; i < num_countries; i++) {
- struct regdb_file_reg_country *country = countries + i;
-
- if (is_world_regdom((const char *) country->alpha2))
+ reglib_for_each_country(rd, idx, argv[1]) {
+ if (is_world_regdom((const char *) rd->alpha2))
continue;

- /* Gets the rd for the current country */
- rd = country2rd(db, dblen, country);
- if (!rd) {
- r = -ENOMEM;
- fprintf(stderr, "Could not covert country "
- "(%.2s) to rd\n", country->alpha2);
- goto out;
- }
-
- if (num_countries == 1) {
- world = rd;
- rd = NULL;
- break;
- }
-
if (!prev_world) {
prev_world = rd;
continue;
}

-
if (world) {
free(prev_world);
prev_world = world;
@@ -318,6 +243,12 @@ int main(int argc, char **argv)
intersected++;
}

+ if (idx == 1) {
+ world = rd;
+ rd = NULL;
+ }
+
+
if (intersected > 1)
printf("%d regulatory domains intersected\n", intersected);
else
--
1.7.4.15.g7811d


2012-02-04 01:26:14

by Luis R. Rodriguez

[permalink] [raw]
Subject: [RFC 07/11] crda: make crda use reglib_get_country_alpha2()

This removes all file specific operations over to the
reglib. This also required converting the processing of the
regulatory domain from the mmap'd rules to the standard
ieee80211_regdomain data structure.

Signed-off-by: Luis R. Rodriguez <[email protected]>
---
crda.c | 110 +++++++++++++--------------------------------------------------
1 files changed, 23 insertions(+), 87 deletions(-)

diff --git a/crda.c b/crda.c
index 5a1cd83..344fd60 100644
--- a/crda.c
+++ b/crda.c
@@ -119,22 +119,20 @@ static int error_handler(struct sockaddr_nl __attribute__((unused)) *nla,
exit(err->error);
}

-static int put_reg_rule(__u8 *db, int dblen, __be32 ruleptr, struct nl_msg *msg)
+static int put_reg_rule(struct ieee80211_reg_rule *rule, struct nl_msg *msg)
{
- struct regdb_file_reg_rule *rule;
- struct regdb_file_freq_range *freq;
- struct regdb_file_power_rule *power;
+ struct ieee80211_freq_range *freq_range;
+ struct ieee80211_power_rule *power_rule;

- rule = crda_get_file_ptr(db, dblen, sizeof(*rule), ruleptr);
- freq = crda_get_file_ptr(db, dblen, sizeof(*freq), rule->freq_range_ptr);
- power = crda_get_file_ptr(db, dblen, sizeof(*power), rule->power_rule_ptr);
+ freq_range = &rule->freq_range;
+ power_rule = &rule->power_rule;

- NLA_PUT_U32(msg, NL80211_ATTR_REG_RULE_FLAGS, ntohl(rule->flags));
- NLA_PUT_U32(msg, NL80211_ATTR_FREQ_RANGE_START, ntohl(freq->start_freq));
- NLA_PUT_U32(msg, NL80211_ATTR_FREQ_RANGE_END, ntohl(freq->end_freq));
- NLA_PUT_U32(msg, NL80211_ATTR_FREQ_RANGE_MAX_BW, ntohl(freq->max_bandwidth));
- NLA_PUT_U32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN, ntohl(power->max_antenna_gain));
- NLA_PUT_U32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP, ntohl(power->max_eirp));
+ NLA_PUT_U32(msg, NL80211_ATTR_REG_RULE_FLAGS, rule->flags);
+ NLA_PUT_U32(msg, NL80211_ATTR_FREQ_RANGE_START, freq_range->start_freq_khz);
+ NLA_PUT_U32(msg, NL80211_ATTR_FREQ_RANGE_END, freq_range->end_freq_khz);
+ NLA_PUT_U32(msg, NL80211_ATTR_FREQ_RANGE_MAX_BW, freq_range->max_bandwidth_khz);
+ NLA_PUT_U32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN, power_rule->max_antenna_gain);
+ NLA_PUT_U32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP, power_rule->max_eirp);

return 0;

@@ -145,23 +143,16 @@ nla_put_failure:
int main(int argc, char **argv)
{
int fd = -1;
- struct stat stat;
- __u8 *db;
- struct regdb_file_header *header;
- struct regdb_file_reg_country *countries;
- int dblen, siglen, num_countries, i, j, r;
+ int i = 0, j, r;
char alpha2[3] = {}; /* NUL-terminate */
char *env_country;
struct nl80211_state nlstate;
struct nl_cb *cb = NULL;
struct nl_msg *msg;
- int found_country = 0;
int finished = 0;

- struct regdb_file_reg_rules_collection *rcoll;
- struct regdb_file_reg_country *country;
struct nlattr *nl_reg_rules;
- int num_rules;
+ struct ieee80211_regdomain *rd = NULL;

const char *regdb_paths[] = {
"/usr/local/lib/crda/regulatory.bin", /* Users/preloads can override */
@@ -201,66 +192,19 @@ int main(int argc, char **argv)
return -ENOENT;
}

- if (fstat(fd, &stat)) {
- perror("failed to fstat db file");
- return -EIO;
- }
-
- dblen = stat.st_size;
-
- db = mmap(NULL, dblen, PROT_READ, MAP_PRIVATE, fd, 0);
- if (db == MAP_FAILED) {
- perror("failed to mmap db file");
- return -EIO;
- }
-
- /* db file starts with a struct regdb_file_header */
- header = crda_get_file_ptr(db, dblen, sizeof(*header), 0);
-
- if (ntohl(header->magic) != REGDB_MAGIC) {
- fprintf(stderr, "Invalid database magic\n");
- return -EINVAL;
- }
-
- if (ntohl(header->version) != REGDB_VERSION) {
- fprintf(stderr, "Invalid database version\n");
- return -EINVAL;
- }
-
- siglen = ntohl(header->signature_length);
- /* adjust dblen so later sanity checks don't run into the signature */
- dblen -= siglen;
-
- if (dblen <= (int)sizeof(*header)) {
- fprintf(stderr, "Invalid signature length %d\n", siglen);
- return -EINVAL;
- }
-
- /* verify signature */
- if (!crda_verify_db_signature(db, dblen, siglen))
- return -EINVAL;
-
- num_countries = ntohl(header->reg_country_num);
- countries = crda_get_file_ptr(db, dblen,
- sizeof(struct regdb_file_reg_country) * num_countries,
- header->reg_country_ptr);
-
- for (i = 0; i < num_countries; i++) {
- country = countries + i;
- if (memcmp(country->alpha2, alpha2, 2) == 0) {
- found_country = 1;
- break;
- }
- }
+ close(fd);

- if (!found_country) {
+ rd = reglib_get_country_alpha2(alpha2, *regdb);
+ if (!rd) {
fprintf(stderr, "No country match in regulatory database.\n");
return -1;
}

r = nl80211_init(&nlstate);
- if (r)
+ if (r) {
+ free(rd);
return -EIO;
+ }

msg = nlmsg_alloc();
if (!msg) {
@@ -272,16 +216,8 @@ int main(int argc, char **argv)
genlmsg_put(msg, 0, 0, genl_family_get_id(nlstate.nl80211), 0,
0, NL80211_CMD_SET_REG, 0);

- rcoll = crda_get_file_ptr(db, dblen, sizeof(*rcoll),
- country->reg_collection_ptr);
- num_rules = ntohl(rcoll->reg_rule_num);
- /* re-get pointer with sanity checking for num_rules */
- rcoll = crda_get_file_ptr(db, dblen,
- sizeof(*rcoll) + num_rules * sizeof(__be32),
- country->reg_collection_ptr);
-
NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, alpha2);
- NLA_PUT_U8(msg, NL80211_ATTR_DFS_REGION, country->creqs & 0x3);
+ NLA_PUT_U8(msg, NL80211_ATTR_DFS_REGION, rd->dfs_region);

nl_reg_rules = nla_nest_start(msg, NL80211_ATTR_REG_RULES);
if (!nl_reg_rules) {
@@ -289,13 +225,13 @@ int main(int argc, char **argv)
goto nla_put_failure;
}

- for (j = 0; j < num_rules; j++) {
+ for (j = 0; j < rd->n_reg_rules; j++) {
struct nlattr *nl_reg_rule;
nl_reg_rule = nla_nest_start(msg, i);
if (!nl_reg_rule)
goto nla_put_failure;

- r = put_reg_rule(db, dblen, rcoll->reg_rule_ptrs[j], msg);
+ r = put_reg_rule(&rd->reg_rules[j], msg);
if (r)
goto nla_put_failure;

@@ -334,7 +270,7 @@ nla_put_failure:
nlmsg_free(msg);
out:
nl80211_cleanup(&nlstate);
- close(fd);
+ free(rd);

return r;
}
--
1.7.4.15.g7811d


2012-02-04 01:26:23

by Luis R. Rodriguez

[permalink] [raw]
Subject: [RFC 10/11] crda: make usage of regdb.h exclusive to reglib.c

The only other remaining user of regdb.h is regdbdump tool
but as I see it this utility can exist in either a reglib
library, or on each OS for its own specific adaptation of
the reglib code. For now we just make regdbump use the local
copy of nl80211.h. Later the reglib library can have its own
print / dump utility if we deem it necessary.

Signed-off-by: Luis R. Rodriguez <[email protected]>
---
print-regdom.c | 21 ++++++++++++---------
reglib.c | 1 +
reglib.h | 2 --
3 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/print-regdom.c b/print-regdom.c
index a3bedeb..075eea8 100644
--- a/print-regdom.c
+++ b/print-regdom.c
@@ -2,6 +2,9 @@
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
+
+#include "nl80211.h"
+
#include "reglib.h"

static void print_reg_rule(struct ieee80211_reg_rule *rule)
@@ -29,23 +32,23 @@ static void print_reg_rule(struct ieee80211_reg_rule *rule)
else
printf("N/A)");

- if (rule->flags & RRF_NO_OFDM)
+ if (rule->flags & NL80211_RRF_NO_OFDM)
printf(", NO-OFDM");
- if (rule->flags & RRF_NO_CCK)
+ if (rule->flags & NL80211_RRF_NO_CCK)
printf(", NO-CCK");
- if (rule->flags & RRF_NO_INDOOR)
+ if (rule->flags & NL80211_RRF_NO_INDOOR)
printf(", NO-INDOOR");
- if (rule->flags & RRF_NO_OUTDOOR)
+ if (rule->flags & NL80211_RRF_NO_OUTDOOR)
printf(", NO-OUTDOOR");
- if (rule->flags & RRF_DFS)
+ if (rule->flags & NL80211_RRF_DFS)
printf(", DFS");
- if (rule->flags & RRF_PTP_ONLY)
+ if (rule->flags & NL80211_RRF_PTP_ONLY)
printf(", PTP-ONLY");
- if (rule->flags & RRF_PTMP_ONLY)
+ if (rule->flags & NL80211_RRF_PTMP_ONLY)
printf(", PTMP-ONLY");
- if (rule->flags & RRF_PASSIVE_SCAN)
+ if (rule->flags & NL80211_RRF_PASSIVE_SCAN)
printf(", PASSIVE-SCAN");
- if (rule->flags & RRF_NO_IBSS)
+ if (rule->flags & NL80211_RRF_NO_IBSS)
printf(", NO-IBSS");

printf("\n");
diff --git a/reglib.c b/reglib.c
index 3cb7f72..12698fa 100644
--- a/reglib.c
+++ b/reglib.c
@@ -13,6 +13,7 @@
#include <arpa/inet.h> /* ntohl */

#include "reglib.h"
+#include "regdb.h"

#ifdef USE_OPENSSL
#include <openssl/objects.h>
diff --git a/reglib.h b/reglib.h
index 42c7999..99e6c76 100644
--- a/reglib.h
+++ b/reglib.h
@@ -4,8 +4,6 @@
#include <stdlib.h>
#include <stdint.h>

-#include "regdb.h"
-
/* Common regulatory structures, functions and helpers */

/* This matches the kernel's data structures */
--
1.7.4.15.g7811d


2012-02-04 01:26:17

by Luis R. Rodriguez

[permalink] [raw]
Subject: [RFC 08/11] crda: clean header files

Remove unused headers now that we have an object
(soon to be library) using what it has to separately.

Signed-off-by: Luis R. Rodriguez <[email protected]>
---
crda.c | 3 ---
intersect.c | 3 ---
regdbdump.c | 3 ---
3 files changed, 0 insertions(+), 9 deletions(-)

diff --git a/crda.c b/crda.c
index 344fd60..c6dc3d4 100644
--- a/crda.c
+++ b/crda.c
@@ -6,8 +6,6 @@

#include <errno.h>
#include <stdio.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <unistd.h>
@@ -19,7 +17,6 @@
#include <netlink/attr.h>
#include "nl80211.h"

-#include "regdb.h"
#include "reglib.h"

#if !defined(CONFIG_LIBNL20) && !defined(CONFIG_LIBNL30) && !defined(CONFIG_LIBNL32)
diff --git a/intersect.c b/intersect.c
index 6d3d393..012750d 100644
--- a/intersect.c
+++ b/intersect.c
@@ -1,9 +1,6 @@
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <fcntl.h>
#include <arpa/inet.h> /* ntohl */
#include <string.h>

diff --git a/regdbdump.c b/regdbdump.c
index 6d4cf56..6f9592a 100644
--- a/regdbdump.c
+++ b/regdbdump.c
@@ -1,7 +1,4 @@
-#include <errno.h>
#include <stdio.h>
-
-#include "regdb.h"
#include "reglib.h"

int main(int argc, char **argv)
--
1.7.4.15.g7811d


2012-02-04 01:26:20

by Luis R. Rodriguez

[permalink] [raw]
Subject: [RFC 09/11] crda: make country2rd() static

Signed-off-by: Luis R. Rodriguez <[email protected]>
---
reglib.c | 5 +++--
reglib.h | 4 ----
2 files changed, 3 insertions(+), 6 deletions(-)

diff --git a/reglib.c b/reglib.c
index 759c676..3cb7f72 100644
--- a/reglib.c
+++ b/reglib.c
@@ -186,8 +186,9 @@ static void reg_rule2rd(uint8_t *db, int dblen,
}

/* Converts a file regdomain to ieee80211_regdomain, easier to manage */
-struct ieee80211_regdomain *country2rd(uint8_t *db, int dblen,
- struct regdb_file_reg_country *country)
+static struct ieee80211_regdomain *
+country2rd(uint8_t *db, int dblen,
+ struct regdb_file_reg_country *country)
{
struct regdb_file_reg_rules_collection *rcoll;
struct ieee80211_regdomain *rd;
diff --git a/reglib.h b/reglib.h
index bec6359..42c7999 100644
--- a/reglib.h
+++ b/reglib.h
@@ -75,10 +75,6 @@ static inline uint32_t min(uint32_t a, uint32_t b)
void *crda_get_file_ptr(uint8_t *db, int dblen, int structlen, uint32_t ptr);
int crda_verify_db_signature(uint8_t *db, int dblen, int siglen);

-/* File reg db entry -> rd converstion utilities */
-struct ieee80211_regdomain *country2rd(uint8_t *db, int dblen,
- struct regdb_file_reg_country *country);
-
struct ieee80211_regdomain *
reglib_get_country_idx(unsigned int idx, const char *file);

--
1.7.4.15.g7811d