Search Linux Wireless

[PATCH] iw: add get regulatory domain support

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

 



Signed-off-by: Luis R. Rodriguez <lrodriguez@xxxxxxxxxxx>
---
 COPYING   |    2 +-
 nl80211.h |    4 ++
 reg.c     |  100 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 105 insertions(+), 1 deletions(-)

diff --git a/COPYING b/COPYING
index 3ba767c..73e19ac 100644
--- 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
diff --git a/nl80211.h b/nl80211.h
index 76aae3d..4bc2704 100644
--- a/nl80211.h
+++ b/nl80211.h
@@ -113,6 +113,8 @@
  * @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 01573d3..ab210eb 100644
--- a/reg.c
+++ b/reg.c
@@ -11,6 +11,13 @@
 #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,96 @@ 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 FLAG_BUF_LEN 200
+#define PARSE_FLAG(nl_flag, string_value, len)  do { \
+		if ((flags & nl_flag)) { \
+			if (idx + len + 2 > FLAG_BUF_LEN) { \
+				fprintf(stderr, "flags_buf size limit (%d) reached\n", FLAG_BUF_LEN); \
+				return NL_STOP; \
+			} \
+			sprintf(flags_buf + idx, ", "); \
+			sprintf(flags_buf + idx + 2, string_value); \
+			idx += len + 2; \
+		} \
+	} 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;
+		int idx = 0;
+		char antenna_gain_buf[20];
+		char flags_buf[200];
+
+		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]);
+
+		if (MBI_TO_DBI(max_ant_gain_mbi))
+			sprintf(antenna_gain_buf, "%d", MBI_TO_DBI(max_ant_gain_mbi));
+		else
+			sprintf(antenna_gain_buf, "N/A");
+
+		/* Sync this output format to match that of dbparse.py from wireless-regdb.git */
+		PARSE_FLAG(NL80211_RRF_NO_OFDM, "NO-OFDM", 7);
+		PARSE_FLAG(NL80211_RRF_NO_CCK, "NO-CCK", 6);
+		PARSE_FLAG(NL80211_RRF_NO_INDOOR, "NO-INDOOR", 9);
+		PARSE_FLAG(NL80211_RRF_NO_OUTDOOR, "NO-OUTDOOR", 10);
+		PARSE_FLAG(NL80211_RRF_DFS, "DFS", 3);
+		PARSE_FLAG(NL80211_RRF_PTP_ONLY, "PTP-ONLY", 8);
+		PARSE_FLAG(NL80211_RRF_PASSIVE_SCAN, "PASSIVE-SCAN", 12);
+		PARSE_FLAG(NL80211_RRF_NO_IBSS, "NO-IBSS", 7);
+
+		printf("\t(%d - %d @ %d), (%s, %d)%s\n",
+			KHZ_TO_MHZ(start_freq_khz), KHZ_TO_MHZ(end_freq_khz), KHZ_TO_MHZ(max_bw_khz),
+			antenna_gain_buf, MBM_TO_DBM(max_eirp_mbm), (!idx) ? "" : flags_buf);
+	}
+	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);
-- 
1.6.1.rc3.51.g5832d

--
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 Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]
  Powered by Linux