diff options
author | Arik Nemtsov <arik@wizery.com> | 2014-12-15 12:26:01 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2014-12-17 05:49:55 -0500 |
commit | 1bdd716cbccabc8127fbbaaa663c3090302ef78b (patch) | |
tree | 6640c2203455f00eae2599976c20d8cf833dd289 | |
parent | b0d7aa59592b4270531de5ce65dcf18338a2d98c (diff) |
cfg80211: return private regdom for self-managed devices
If a device has self-managed regulatory, insist on returning the wiphy
specific regdomain if a wiphy-idx is specified. The global regdomain is
meaningless for such devices.
Also add an attribute for self-managed devices, so usermode can
distinguish them as such.
Signed-off-by: Arik Nemtsov <arikx.nemtsov@intel.com>
Reviewed-by: Luis R. Rodriguez <mcgrof@suse.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r-- | include/uapi/linux/nl80211.h | 10 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 24 |
2 files changed, 34 insertions, 0 deletions
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index fb58e654f523..b3ada0b3a276 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h | |||
@@ -261,6 +261,9 @@ | |||
261 | * the regulatory core to help with compliance. A dump version of this API | 261 | * the regulatory core to help with compliance. A dump version of this API |
262 | * is now available which will returns the global regdomain as well as | 262 | * is now available which will returns the global regdomain as well as |
263 | * all private regdomains of present wiphys (for those that have it). | 263 | * all private regdomains of present wiphys (for those that have it). |
264 | * If a wiphy is self-managed (%NL80211_ATTR_WIPHY_SELF_MANAGED_REG), then | ||
265 | * its private regdomain is the only valid one for it. The regulatory | ||
266 | * core is not used to help with compliance in this case. | ||
264 | * @NL80211_CMD_SET_REG: Set current regulatory domain. CRDA sends this command | 267 | * @NL80211_CMD_SET_REG: Set current regulatory domain. CRDA sends this command |
265 | * after being queried by the kernel. CRDA replies by sending a regulatory | 268 | * after being queried by the kernel. CRDA replies by sending a regulatory |
266 | * domain structure which consists of %NL80211_ATTR_REG_ALPHA set to our | 269 | * domain structure which consists of %NL80211_ATTR_REG_ALPHA set to our |
@@ -1702,6 +1705,11 @@ enum nl80211_commands { | |||
1702 | * | 1705 | * |
1703 | * @NL80211_ATTR_MAC_MASK: MAC address mask | 1706 | * @NL80211_ATTR_MAC_MASK: MAC address mask |
1704 | * | 1707 | * |
1708 | * @NL80211_ATTR_WIPHY_SELF_MANAGED_REG: flag attribute indicating this device | ||
1709 | * is self-managing its regulatory information and any regulatory domain | ||
1710 | * obtained from it is coming from the device's wiphy and not the global | ||
1711 | * cfg80211 regdomain. | ||
1712 | * | ||
1705 | * @NUM_NL80211_ATTR: total number of nl80211_attrs available | 1713 | * @NUM_NL80211_ATTR: total number of nl80211_attrs available |
1706 | * @NL80211_ATTR_MAX: highest attribute number currently defined | 1714 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
1707 | * @__NL80211_ATTR_AFTER_LAST: internal use | 1715 | * @__NL80211_ATTR_AFTER_LAST: internal use |
@@ -2059,6 +2067,8 @@ enum nl80211_attrs { | |||
2059 | 2067 | ||
2060 | NL80211_ATTR_MAC_MASK, | 2068 | NL80211_ATTR_MAC_MASK, |
2061 | 2069 | ||
2070 | NL80211_ATTR_WIPHY_SELF_MANAGED_REG, | ||
2071 | |||
2062 | /* add attributes here, update the policy in nl80211.c */ | 2072 | /* add attributes here, update the policy in nl80211.c */ |
2063 | 2073 | ||
2064 | __NL80211_ATTR_AFTER_LAST, | 2074 | __NL80211_ATTR_AFTER_LAST, |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index eebb7e422989..5b1907f4c181 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -396,6 +396,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { | |||
396 | [NL80211_ATTR_ADMITTED_TIME] = { .type = NLA_U16 }, | 396 | [NL80211_ATTR_ADMITTED_TIME] = { .type = NLA_U16 }, |
397 | [NL80211_ATTR_SMPS_MODE] = { .type = NLA_U8 }, | 397 | [NL80211_ATTR_SMPS_MODE] = { .type = NLA_U8 }, |
398 | [NL80211_ATTR_MAC_MASK] = { .len = ETH_ALEN }, | 398 | [NL80211_ATTR_MAC_MASK] = { .len = ETH_ALEN }, |
399 | [NL80211_ATTR_WIPHY_SELF_MANAGED_REG] = { .type = NLA_FLAG }, | ||
399 | }; | 400 | }; |
400 | 401 | ||
401 | /* policy for the key attributes */ | 402 | /* policy for the key attributes */ |
@@ -1701,6 +1702,10 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev, | |||
1701 | rdev->wiphy.max_num_csa_counters)) | 1702 | rdev->wiphy.max_num_csa_counters)) |
1702 | goto nla_put_failure; | 1703 | goto nla_put_failure; |
1703 | 1704 | ||
1705 | if (rdev->wiphy.regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED && | ||
1706 | nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG)) | ||
1707 | goto nla_put_failure; | ||
1708 | |||
1704 | /* done */ | 1709 | /* done */ |
1705 | state->split_start = 0; | 1710 | state->split_start = 0; |
1706 | break; | 1711 | break; |
@@ -5406,6 +5411,8 @@ static int nl80211_get_reg_do(struct sk_buff *skb, struct genl_info *info) | |||
5406 | goto put_failure; | 5411 | goto put_failure; |
5407 | 5412 | ||
5408 | if (info->attrs[NL80211_ATTR_WIPHY]) { | 5413 | if (info->attrs[NL80211_ATTR_WIPHY]) { |
5414 | bool self_managed; | ||
5415 | |||
5409 | rdev = cfg80211_get_dev_from_info(genl_info_net(info), info); | 5416 | rdev = cfg80211_get_dev_from_info(genl_info_net(info), info); |
5410 | if (IS_ERR(rdev)) { | 5417 | if (IS_ERR(rdev)) { |
5411 | nlmsg_free(msg); | 5418 | nlmsg_free(msg); |
@@ -5413,8 +5420,16 @@ static int nl80211_get_reg_do(struct sk_buff *skb, struct genl_info *info) | |||
5413 | } | 5420 | } |
5414 | 5421 | ||
5415 | wiphy = &rdev->wiphy; | 5422 | wiphy = &rdev->wiphy; |
5423 | self_managed = wiphy->regulatory_flags & | ||
5424 | REGULATORY_WIPHY_SELF_MANAGED; | ||
5416 | regdom = get_wiphy_regdom(wiphy); | 5425 | regdom = get_wiphy_regdom(wiphy); |
5417 | 5426 | ||
5427 | /* a self-managed-reg device must have a private regdom */ | ||
5428 | if (WARN_ON(!regdom && self_managed)) { | ||
5429 | nlmsg_free(msg); | ||
5430 | return -EINVAL; | ||
5431 | } | ||
5432 | |||
5418 | if (regdom && | 5433 | if (regdom && |
5419 | nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy))) | 5434 | nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy))) |
5420 | goto nla_put_failure; | 5435 | goto nla_put_failure; |
@@ -5471,6 +5486,10 @@ static int nl80211_send_regdom(struct sk_buff *msg, struct netlink_callback *cb, | |||
5471 | nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy))) | 5486 | nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy))) |
5472 | goto nla_put_failure; | 5487 | goto nla_put_failure; |
5473 | 5488 | ||
5489 | if (wiphy && wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED && | ||
5490 | nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG)) | ||
5491 | goto nla_put_failure; | ||
5492 | |||
5474 | return genlmsg_end(msg, hdr); | 5493 | return genlmsg_end(msg, hdr); |
5475 | 5494 | ||
5476 | nla_put_failure: | 5495 | nla_put_failure: |
@@ -11076,6 +11095,11 @@ static bool nl80211_reg_change_event_fill(struct sk_buff *msg, | |||
11076 | if (wiphy && | 11095 | if (wiphy && |
11077 | nla_put_u32(msg, NL80211_ATTR_WIPHY, request->wiphy_idx)) | 11096 | nla_put_u32(msg, NL80211_ATTR_WIPHY, request->wiphy_idx)) |
11078 | goto nla_put_failure; | 11097 | goto nla_put_failure; |
11098 | |||
11099 | if (wiphy && | ||
11100 | wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED && | ||
11101 | nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG)) | ||
11102 | goto nla_put_failure; | ||
11079 | } | 11103 | } |
11080 | 11104 | ||
11081 | return true; | 11105 | return true; |