diff options
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r-- | net/wireless/nl80211.c | 81 |
1 files changed, 81 insertions, 0 deletions
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, |