Add conversion utitlies, standardize printing
authorLuis R. Rodriguez <lrodriguez@atheros.com>
Tue, 28 Oct 2008 22:44:37 +0000 (15:44 -0700)
committerLuis R. Rodriguez <lrodriguez@atheros.com>
Tue, 28 Oct 2008 22:44:37 +0000 (15:44 -0700)
This adds country2rd() and friends which allows us to
use more friendlier data structures that are not big endian
and standardizes printing this new rd structure.

Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
dump.c
regdb.h
reglib.c
reglib.h

diff --git a/dump.c b/dump.c
index 36fbe0e..0ddf659 100644 (file)
--- a/dump.c
+++ b/dump.c
@@ -9,57 +9,6 @@
 #include "regdb.h"
 #include "reglib.h"
 
-static void print_reg_rule(__u8 *db, int dblen, __be32 ruleptr)
-{
-       struct regdb_file_reg_rule *rule;
-       struct regdb_file_freq_range *freq;
-       struct regdb_file_power_rule *power;
-       __u32 flags;
-
-       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);
-
-       printf("\t(%.3f - %.3f @ %.3f), ",
-              ((float)ntohl(freq->start_freq))/1000.0,
-              ((float)ntohl(freq->end_freq))/1000.0,
-              ((float)ntohl(freq->max_bandwidth))/1000.0);
-
-       printf("(");
-
-       if (power->max_antenna_gain)
-               printf("%.2f, ", ((float)ntohl(power->max_antenna_gain)/100.0));
-       else
-               printf("N/A, ");
-
-       if (power->max_eirp)
-               printf("%.2f)", ((float)ntohl(power->max_eirp)/100.0));
-       else
-               printf("N/A)");
-
-       flags = ntohl(rule->flags);
-       if (flags & RRF_NO_OFDM)
-               printf(", NO-OFDM");
-       if (flags & RRF_NO_CCK)
-               printf(", NO-CCK");
-       if (flags & RRF_NO_INDOOR)
-               printf(", NO-INDOOR");
-       if (flags & RRF_NO_OUTDOOR)
-               printf(", NO-OUTDOOR");
-       if (flags & RRF_DFS)
-               printf(", DFS");
-       if (flags & RRF_PTP_ONLY)
-               printf(", PTP-ONLY");
-       if (flags & RRF_PTMP_ONLY)
-               printf(", PTMP-ONLY");
-       if (flags & RRF_PASSIVE_SCAN)
-               printf(", PASSIVE-SCAN");
-       if (flags & RRF_NO_IBSS)
-               printf(", NO-IBSS");
-
-       printf("\n");
-}
-
 int main(int argc, char **argv)
 {
        int fd;
@@ -67,7 +16,8 @@ int main(int argc, char **argv)
        __u8 *db;
        struct regdb_file_header *header;
        struct regdb_file_reg_country *countries;
-       int dblen, siglen, num_countries, i, j;
+       int dblen, siglen, num_countries, i, r = 0;
+       struct ieee80211_regdomain *rd = NULL;
 
        if (argc != 2) {
                fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
@@ -124,22 +74,20 @@ int main(int argc, char **argv)
                        header->reg_country_ptr);
 
        for (i = 0; i < num_countries; i++) {
-               struct regdb_file_reg_rules_collection *rcoll;
                struct regdb_file_reg_country *country = countries + i;
-               int num_rules;
-
-               printf("country %.2s:\n", country->alpha2);
-               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);
-               for (j = 0; j < num_rules; j++)
-                       print_reg_rule(db, dblen, rcoll->reg_rule_ptrs[j]);
-               printf("\n");
-       }
 
-       return 0;
+               r = country2rd(db, dblen, country, &rd);
+               if (r) {
+                       fprintf(stderr, "Could not covert country "
+                       "(%.2s) to rd\n", country->alpha2);
+                       goto out;
+               }
+
+               print_regdom(rd);
+               free(rd);
+               rd = NULL;
+
+       }
+out:
+       return r;
 }
diff --git a/regdb.h b/regdb.h
index 09cc403..045a0e3 100644 (file)
--- a/regdb.h
+++ b/regdb.h
@@ -1,3 +1,6 @@
+#ifndef REG_DB_H
+#define REG_DB_H
+
 #include <linux/types.h>
 
 /*
@@ -120,3 +123,5 @@ static inline void check_db_binary_structs(void)
        CHECK_STRUCT(regdb_file_reg_rules_collection, 4);
        CHECK_STRUCT(regdb_file_reg_country, 8);
 }
+
+#endif
index e2e2185..de6bb10 100644 (file)
--- a/reglib.c
+++ b/reglib.c
@@ -1,5 +1,7 @@
+#include <errno.h>
 #include <stdio.h>
 #include <arpa/inet.h>
+#include "reglib.h"
 
 #ifdef USE_OPENSSL
 #include <openssl/objects.h>
@@ -11,7 +13,7 @@
 #include <gcrypt.h>
 #endif
 
-#include "regdb.h"
+#include "reglib.h"
 
 #ifdef USE_OPENSSL
 #include "keys-ssl.c"
@@ -130,3 +132,144 @@ out:
        return 1;
 #endif
 }
+
+void reg_rule2rd(__u8 *db, int dblen,
+       __be32 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 */
+int country2rd(__u8 *db, int dblen,
+       struct regdb_file_reg_country *country,
+       struct ieee80211_regdomain **rdp)
+{
+       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(__be32),
+                       country->reg_collection_ptr);
+
+       size_of_rd = sizeof(struct ieee80211_regdomain) +
+               num_rules * sizeof(struct ieee80211_reg_rule);
+
+       *rdp = malloc(size_of_rd);
+       if (!*rdp)
+               return -ENOMEM;
+
+       rd = *rdp;
+
+       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 0;
+}
+
+/* Sanity check on a regulatory rule */
+int is_valid_reg_rule(const struct ieee80211_reg_rule *rule)
+{
+       const struct ieee80211_freq_range *freq_range = &rule->freq_range;
+       __u32 freq_diff;
+
+       if (freq_range->start_freq_khz == 0 || freq_range->end_freq_khz == 0)
+               return 0;
+
+       if (freq_range->start_freq_khz > freq_range->end_freq_khz)
+               return 0;
+
+       freq_diff = freq_range->end_freq_khz - freq_range->start_freq_khz;
+
+       if (freq_range->max_bandwidth_khz > freq_diff)
+               return 0;
+
+       return 1;
+}
+
+void print_reg_rule(struct ieee80211_reg_rule *rule)
+{
+       struct ieee80211_freq_range *freq;
+       struct ieee80211_power_rule *power;
+
+       freq  = &rule->freq_range;
+       power = &rule->power_rule;
+
+       printf("\t(%.3f - %.3f @ %.3f), ",
+              ((float)(freq->start_freq_khz))/1000.0,
+              ((float)(freq->end_freq_khz))/1000.0,
+              ((float)(freq->max_bandwidth_khz))/1000.0);
+
+       printf("(");
+
+       if (power->max_antenna_gain)
+               printf("%.2f, ", ((float)(power->max_antenna_gain)/100.0));
+       else
+               printf("N/A, ");
+
+       if (power->max_eirp)
+               printf("%.2f)", ((float)(power->max_eirp)/100.0));
+       else
+               printf("N/A)");
+
+       if (rule->flags & RRF_NO_OFDM)
+               printf(", NO-OFDM");
+       if (rule->flags & RRF_NO_CCK)
+               printf(", NO-CCK");
+       if (rule->flags & RRF_NO_INDOOR)
+               printf(", NO-INDOOR");
+       if (rule->flags & RRF_NO_OUTDOOR)
+               printf(", NO-OUTDOOR");
+       if (rule->flags & RRF_DFS)
+               printf(", DFS");
+       if (rule->flags & RRF_PTP_ONLY)
+               printf(", PTP-ONLY");
+       if (rule->flags & RRF_PTMP_ONLY)
+               printf(", PTMP-ONLY");
+       if (rule->flags & RRF_PASSIVE_SCAN)
+               printf(", PASSIVE-SCAN");
+       if (rule->flags & RRF_NO_IBSS)
+               printf(", NO-IBSS");
+
+       printf("\n");
+}
+
+void print_regdom(struct ieee80211_regdomain *rd)
+{
+       unsigned int i;
+       printf("country %.2s:\n", rd->alpha2);
+       for (i = 0; i < rd->n_reg_rules; i++)
+               print_reg_rule(&rd->reg_rules[i]);
+       printf("\n");
+}
+
index eec4ec4..22a9fb4 100644 (file)
--- a/reglib.h
+++ b/reglib.h
@@ -1,10 +1,36 @@
+#ifndef REG_LIB_H
+#define REG_LIB_H
+
 #include <stdlib.h>
 #include <linux/types.h>
 
-/* Common regulatory functions and helpers */
+#include "regdb.h"
 
-void *crda_get_file_ptr(__u8 *db, int dblen, int structlen, __be32 ptr);
-int crda_verify_db_signature(__u8 *db, int dblen, int siglen);
+/* Common regulatory structures, functions and helpers */
+
+/* This matches the kernel's data structures */
+struct ieee80211_freq_range {
+       __u32 start_freq_khz;
+       __u32 end_freq_khz;
+       __u32 max_bandwidth_khz;
+};
+
+struct ieee80211_power_rule {
+       __u32 max_antenna_gain;
+       __u32 max_eirp;
+};
+
+struct ieee80211_reg_rule {
+       struct ieee80211_freq_range freq_range;
+       struct ieee80211_power_rule power_rule;
+       __u32 flags;
+};
+
+struct ieee80211_regdomain {
+       __u32 n_reg_rules;
+       char alpha2[2];
+       struct ieee80211_reg_rule reg_rules[];
+};
 
 static inline int is_world_regdom(const char *alpha2)
 {
@@ -47,3 +73,30 @@ static inline int is_valid_regdom(const char *alpha2)
 
        return 1;
 }
+
+static inline __u32 max(__u32 a, __u32 b)
+{
+       return (a > b) ? a : b;
+}
+
+static inline __u32 min(__u32 a, __u32 b)
+{
+       return (a > b) ? b : a;
+}
+
+void *crda_get_file_ptr(__u8 *db, int dblen, int structlen, __be32 ptr);
+int crda_verify_db_signature(__u8 *db, int dblen, int siglen);
+
+/* File reg db entry -> rd converstion utilities */
+void reg_rule2rd(__u8 *db, int dblen,
+       __be32 ruleptr, struct ieee80211_reg_rule *rd_reg_rule);
+int country2rd(__u8 *db, int dblen,
+       struct regdb_file_reg_country *country,
+       struct ieee80211_regdomain **rdp);
+
+/* reg helpers */
+int is_valid_reg_rule(const struct ieee80211_reg_rule *rule);
+void print_reg_rule(struct ieee80211_reg_rule *rule);
+void print_regdom(struct ieee80211_regdomain *rd);
+
+#endif