diff options
author | Luis R. Rodriguez <lrodriguez@atheros.com> | 2009-01-30 12:26:42 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-02-09 15:03:45 -0500 |
commit | f130347c2dd8e7ce0757cd3cf80bedbc6ed63c4c (patch) | |
tree | 868f78203b5f529d80a014ed2169e7eab0a260ed | |
parent | 47f4d8872ffc57ad92d0fb344e677d12acc34acd (diff) |
cfg80211: add get reg command
This lets userspace request to get the currently set
regulatory domain.
Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | include/linux/nl80211.h | 4 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 81 | ||||
-rw-r--r-- | net/wireless/reg.c | 2 | ||||
-rw-r--r-- | net/wireless/reg.h | 2 |
4 files changed, 88 insertions, 1 deletions
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 76aae3d8e97e..4bc27049f4e5 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h | |||
@@ -113,6 +113,8 @@ | |||
113 | * @NL80211_CMD_SET_BSS: Set BSS attributes for BSS identified by | 113 | * @NL80211_CMD_SET_BSS: Set BSS attributes for BSS identified by |
114 | * %NL80211_ATTR_IFINDEX. | 114 | * %NL80211_ATTR_IFINDEX. |
115 | * | 115 | * |
116 | * @NL80211_CMD_GET_REG: ask the wireless core to send us its currently set | ||
117 | * regulatory domain. | ||
116 | * @NL80211_CMD_SET_REG: Set current regulatory domain. CRDA sends this command | 118 | * @NL80211_CMD_SET_REG: Set current regulatory domain. CRDA sends this command |
117 | * after being queried by the kernel. CRDA replies by sending a regulatory | 119 | * after being queried by the kernel. CRDA replies by sending a regulatory |
118 | * domain structure which consists of %NL80211_ATTR_REG_ALPHA set to our | 120 | * domain structure which consists of %NL80211_ATTR_REG_ALPHA set to our |
@@ -188,6 +190,8 @@ enum nl80211_commands { | |||
188 | 190 | ||
189 | NL80211_CMD_SET_MGMT_EXTRA_IE, | 191 | NL80211_CMD_SET_MGMT_EXTRA_IE, |
190 | 192 | ||
193 | NL80211_CMD_GET_REG, | ||
194 | |||
191 | /* add new commands above here */ | 195 | /* add new commands above here */ |
192 | 196 | ||
193 | /* used to define NL80211_CMD_MAX below */ | 197 | /* used to define NL80211_CMD_MAX below */ |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index e69da8d20474..d452396006ee 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -2093,6 +2093,81 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info) | |||
2093 | 2093 | ||
2094 | #undef FILL_IN_MESH_PARAM_IF_SET | 2094 | #undef FILL_IN_MESH_PARAM_IF_SET |
2095 | 2095 | ||
2096 | static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) | ||
2097 | { | ||
2098 | struct sk_buff *msg; | ||
2099 | void *hdr = NULL; | ||
2100 | struct nlattr *nl_reg_rules; | ||
2101 | unsigned int i; | ||
2102 | int err = -EINVAL; | ||
2103 | |||
2104 | mutex_lock(&cfg80211_drv_mutex); | ||
2105 | |||
2106 | if (!cfg80211_regdomain) | ||
2107 | goto out; | ||
2108 | |||
2109 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | ||
2110 | if (!msg) { | ||
2111 | err = -ENOBUFS; | ||
2112 | goto out; | ||
2113 | } | ||
2114 | |||
2115 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, | ||
2116 | NL80211_CMD_GET_REG); | ||
2117 | if (!hdr) | ||
2118 | goto nla_put_failure; | ||
2119 | |||
2120 | NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, | ||
2121 | cfg80211_regdomain->alpha2); | ||
2122 | |||
2123 | nl_reg_rules = nla_nest_start(msg, NL80211_ATTR_REG_RULES); | ||
2124 | if (!nl_reg_rules) | ||
2125 | goto nla_put_failure; | ||
2126 | |||
2127 | for (i = 0; i < cfg80211_regdomain->n_reg_rules; i++) { | ||
2128 | struct nlattr *nl_reg_rule; | ||
2129 | const struct ieee80211_reg_rule *reg_rule; | ||
2130 | const struct ieee80211_freq_range *freq_range; | ||
2131 | const struct ieee80211_power_rule *power_rule; | ||
2132 | |||
2133 | reg_rule = &cfg80211_regdomain->reg_rules[i]; | ||
2134 | freq_range = ®_rule->freq_range; | ||
2135 | power_rule = ®_rule->power_rule; | ||
2136 | |||
2137 | nl_reg_rule = nla_nest_start(msg, i); | ||
2138 | if (!nl_reg_rule) | ||
2139 | goto nla_put_failure; | ||
2140 | |||
2141 | NLA_PUT_U32(msg, NL80211_ATTR_REG_RULE_FLAGS, | ||
2142 | reg_rule->flags); | ||
2143 | NLA_PUT_U32(msg, NL80211_ATTR_FREQ_RANGE_START, | ||
2144 | freq_range->start_freq_khz); | ||
2145 | NLA_PUT_U32(msg, NL80211_ATTR_FREQ_RANGE_END, | ||
2146 | freq_range->end_freq_khz); | ||
2147 | NLA_PUT_U32(msg, NL80211_ATTR_FREQ_RANGE_MAX_BW, | ||
2148 | freq_range->max_bandwidth_khz); | ||
2149 | NLA_PUT_U32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN, | ||
2150 | power_rule->max_antenna_gain); | ||
2151 | NLA_PUT_U32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP, | ||
2152 | power_rule->max_eirp); | ||
2153 | |||
2154 | nla_nest_end(msg, nl_reg_rule); | ||
2155 | } | ||
2156 | |||
2157 | nla_nest_end(msg, nl_reg_rules); | ||
2158 | |||
2159 | genlmsg_end(msg, hdr); | ||
2160 | err = genlmsg_unicast(msg, info->snd_pid); | ||
2161 | goto out; | ||
2162 | |||
2163 | nla_put_failure: | ||
2164 | genlmsg_cancel(msg, hdr); | ||
2165 | err = -EMSGSIZE; | ||
2166 | out: | ||
2167 | mutex_unlock(&cfg80211_drv_mutex); | ||
2168 | return err; | ||
2169 | } | ||
2170 | |||
2096 | static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) | 2171 | static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) |
2097 | { | 2172 | { |
2098 | struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1]; | 2173 | struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1]; |
@@ -2333,6 +2408,12 @@ static struct genl_ops nl80211_ops[] = { | |||
2333 | .flags = GENL_ADMIN_PERM, | 2408 | .flags = GENL_ADMIN_PERM, |
2334 | }, | 2409 | }, |
2335 | { | 2410 | { |
2411 | .cmd = NL80211_CMD_GET_REG, | ||
2412 | .doit = nl80211_get_reg, | ||
2413 | .policy = nl80211_policy, | ||
2414 | /* can be retrieved by unprivileged users */ | ||
2415 | }, | ||
2416 | { | ||
2336 | .cmd = NL80211_CMD_SET_REG, | 2417 | .cmd = NL80211_CMD_SET_REG, |
2337 | .doit = nl80211_set_reg, | 2418 | .doit = nl80211_set_reg, |
2338 | .policy = nl80211_policy, | 2419 | .policy = nl80211_policy, |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index f643d3981102..2323644330cd 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -57,7 +57,7 @@ static u32 supported_bandwidths[] = { | |||
57 | /* Central wireless core regulatory domains, we only need two, | 57 | /* Central wireless core regulatory domains, we only need two, |
58 | * the current one and a world regulatory domain in case we have no | 58 | * the current one and a world regulatory domain in case we have no |
59 | * information to give us an alpha2 */ | 59 | * information to give us an alpha2 */ |
60 | static const struct ieee80211_regdomain *cfg80211_regdomain; | 60 | const struct ieee80211_regdomain *cfg80211_regdomain; |
61 | 61 | ||
62 | /* We use this as a place for the rd structure built from the | 62 | /* We use this as a place for the rd structure built from the |
63 | * last parsed country IE to rest until CRDA gets back to us with | 63 | * last parsed country IE to rest until CRDA gets back to us with |
diff --git a/net/wireless/reg.h b/net/wireless/reg.h index eb1dd5bc9b27..fe8c83f34fb7 100644 --- a/net/wireless/reg.h +++ b/net/wireless/reg.h | |||
@@ -1,6 +1,8 @@ | |||
1 | #ifndef __NET_WIRELESS_REG_H | 1 | #ifndef __NET_WIRELESS_REG_H |
2 | #define __NET_WIRELESS_REG_H | 2 | #define __NET_WIRELESS_REG_H |
3 | 3 | ||
4 | extern const struct ieee80211_regdomain *cfg80211_regdomain; | ||
5 | |||
4 | bool is_world_regdom(const char *alpha2); | 6 | bool is_world_regdom(const char *alpha2); |
5 | bool reg_is_valid_request(const char *alpha2); | 7 | bool reg_is_valid_request(const char *alpha2); |
6 | 8 | ||