]> git.ipfire.org Git - thirdparty/iw.git/commitdiff
iw: add get regulatory domain support
authorLuis R. Rodriguez <lrodriguez@atheros.com>
Wed, 28 Jan 2009 16:57:59 +0000 (08:57 -0800)
committerJohannes Berg <johannes@sipsolutions.net>
Wed, 4 Feb 2009 22:34:48 +0000 (23:34 +0100)
Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
COPYING
nl80211.h
reg.c

diff --git a/COPYING b/COPYING
index 3ba767caef5035235325c86aa3caa2c786212602..73e19ac9ba450d28c5be547548c1fc3ea9e45c26 100644 (file)
--- a/COPYING
+++ b/COPYING
@@ -1,7 +1,7 @@
 Copyright (c) 2007, 2008       Johannes Berg
 Copyright (c) 2007             Andy Lutomirski
 Copyright (c) 2007             Mike Kershaw
-Copyright (c) 2008             Luis R. Rodriguez
+Copyright (c) 2008-2009                Luis R. Rodriguez
 
 Permission to use, copy, modify, and/or distribute this software for any
 purpose with or without fee is hereby granted, provided that the above
index 76aae3d8e97e9c636190498055489f88ea025768..4bc27049f4e5736bb7d77b0c4fa947d975314c6c 100644 (file)
--- a/nl80211.h
+++ b/nl80211.h
  * @NL80211_CMD_SET_BSS: Set BSS attributes for BSS identified by
  *     %NL80211_ATTR_IFINDEX.
  *
+ * @NL80211_CMD_GET_REG: ask the wireless core to send us its currently set
+ *     regulatory domain.
  * @NL80211_CMD_SET_REG: Set current regulatory domain. CRDA sends this command
  *     after being queried by the kernel. CRDA replies by sending a regulatory
  *     domain structure which consists of %NL80211_ATTR_REG_ALPHA set to our
@@ -188,6 +190,8 @@ enum nl80211_commands {
 
        NL80211_CMD_SET_MGMT_EXTRA_IE,
 
+       NL80211_CMD_GET_REG,
+
        /* add new commands above here */
 
        /* used to define NL80211_CMD_MAX below */
diff --git a/reg.c b/reg.c
index 01573d3c534269ffedf49abc2e681be19726a7b5..cb58ed9fd0544e6ba4f5aef5198404c15cbc18e5 100644 (file)
--- a/reg.c
+++ b/reg.c
 #include "nl80211.h"
 #include "iw.h"
 
+#define MHZ_TO_KHZ(freq) ((freq) * 1000)
+#define KHZ_TO_MHZ(freq) ((freq) / 1000)
+#define DBI_TO_MBI(gain) ((gain) * 100)
+#define MBI_TO_DBI(gain) ((gain) / 100)
+#define DBM_TO_MBM(gain) ((gain) * 100)
+#define MBM_TO_DBM(gain) ((gain) / 100)
+
 static int isalpha_upper(char letter)
 {
        if (letter >= 65 && letter <= 90)
@@ -67,3 +74,95 @@ static int handle_reg_set(struct nl_cb *cb,
 }
 COMMAND(reg, set, "<ISO/IEC 3166-1 alpha2>",
        NL80211_CMD_REQ_SET_REG, 0, CIB_NONE, handle_reg_set);
+
+static int print_reg_handler(struct nl_msg *msg, void *arg)
+
+{
+#define PARSE_FLAG(nl_flag, string_value)  do { \
+               if ((flags & nl_flag)) { \
+                       printf(", %s", string_value); \
+               } \
+       } while (0)
+       struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
+       struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+       char *alpha2;
+       struct nlattr *nl_rule;
+       int rem_rule;
+       static struct nla_policy reg_rule_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {
+               [NL80211_ATTR_REG_RULE_FLAGS]           = { .type = NLA_U32 },
+               [NL80211_ATTR_FREQ_RANGE_START]         = { .type = NLA_U32 },
+               [NL80211_ATTR_FREQ_RANGE_END]           = { .type = NLA_U32 },
+               [NL80211_ATTR_FREQ_RANGE_MAX_BW]        = { .type = NLA_U32 },
+               [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]  = { .type = NLA_U32 },
+               [NL80211_ATTR_POWER_RULE_MAX_EIRP]      = { .type = NLA_U32 },
+       };
+
+       nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+               genlmsg_attrlen(gnlh, 0), NULL);
+
+       if (!tb_msg[NL80211_ATTR_REG_ALPHA2]) {
+               printf("No alpha2\n");
+               return NL_SKIP;
+       }
+
+       if (!tb_msg[NL80211_ATTR_REG_RULES]) {
+               printf("No reg rules\n");
+               return NL_SKIP;
+       }
+
+       alpha2 = nla_data(tb_msg[NL80211_ATTR_REG_ALPHA2]);
+       printf("country %s:\n", alpha2);
+
+       nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule) {
+               struct nlattr *tb_rule[NL80211_FREQUENCY_ATTR_MAX + 1];
+               __u32 flags, start_freq_khz, end_freq_khz, max_bw_khz, max_ant_gain_mbi, max_eirp_mbm;
+
+               nla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX, nla_data(nl_rule), nla_len(nl_rule), reg_rule_policy);
+
+               flags = nla_get_u32(tb_rule[NL80211_ATTR_REG_RULE_FLAGS]);
+               start_freq_khz = nla_get_u32(tb_rule[NL80211_ATTR_FREQ_RANGE_START]);
+               end_freq_khz = nla_get_u32(tb_rule[NL80211_ATTR_FREQ_RANGE_END]);
+               max_bw_khz = nla_get_u32(tb_rule[NL80211_ATTR_FREQ_RANGE_MAX_BW]);
+               max_ant_gain_mbi = nla_get_u32(tb_rule[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]);
+               max_eirp_mbm = nla_get_u32(tb_rule[NL80211_ATTR_POWER_RULE_MAX_EIRP]);
+
+
+               printf("\t(%d - %d @ %d), (",
+                       KHZ_TO_MHZ(start_freq_khz), KHZ_TO_MHZ(end_freq_khz), KHZ_TO_MHZ(max_bw_khz));
+
+               if (MBI_TO_DBI(max_ant_gain_mbi))
+                       printf("%d", MBI_TO_DBI(max_ant_gain_mbi));
+               else
+                       printf("N/A");
+
+               printf(", %d)", MBM_TO_DBM(max_eirp_mbm));
+
+               if (!flags) {
+                       printf("\n");
+                       continue;
+               }
+
+               /* Sync this output format to match that of dbparse.py from wireless-regdb.git */
+               PARSE_FLAG(NL80211_RRF_NO_OFDM, "NO-OFDM");
+               PARSE_FLAG(NL80211_RRF_NO_CCK, "NO-CCK");
+               PARSE_FLAG(NL80211_RRF_NO_INDOOR, "NO-INDOOR");
+               PARSE_FLAG(NL80211_RRF_NO_OUTDOOR, "NO-OUTDOOR");
+               PARSE_FLAG(NL80211_RRF_DFS, "DFS");
+               PARSE_FLAG(NL80211_RRF_PTP_ONLY, "PTP-ONLY");
+               PARSE_FLAG(NL80211_RRF_PASSIVE_SCAN, "PASSIVE-SCAN");
+               PARSE_FLAG(NL80211_RRF_NO_IBSS, "NO-IBSS");
+
+               printf("\n");
+       }
+       return NL_OK;
+#undef PARSE_FLAG
+}
+
+static int handle_reg_get(struct nl_cb *cb,
+                         struct nl_msg *msg,
+                         int argc, char **argv)
+{
+       nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_reg_handler, NULL);
+       return 0;
+}
+COMMAND(reg, get, NULL, NL80211_CMD_GET_REG, 0, CIB_NONE, handle_reg_get);