diff options
Diffstat (limited to 'net/wireless')
-rw-r--r-- | net/wireless/core.c | 11 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 62 | ||||
-rw-r--r-- | net/wireless/nl80211.h | 5 | ||||
-rw-r--r-- | net/wireless/reg.c | 13 |
4 files changed, 90 insertions, 1 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c index c939f5ee065e..17fe39049740 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -365,6 +365,17 @@ int wiphy_register(struct wiphy *wiphy) | |||
365 | if (IS_ERR(drv->wiphy.debugfsdir)) | 365 | if (IS_ERR(drv->wiphy.debugfsdir)) |
366 | drv->wiphy.debugfsdir = NULL; | 366 | drv->wiphy.debugfsdir = NULL; |
367 | 367 | ||
368 | if (wiphy->custom_regulatory) { | ||
369 | struct regulatory_request request; | ||
370 | |||
371 | request.wiphy_idx = get_wiphy_idx(wiphy); | ||
372 | request.initiator = NL80211_REGDOM_SET_BY_DRIVER; | ||
373 | request.alpha2[0] = '9'; | ||
374 | request.alpha2[1] = '9'; | ||
375 | |||
376 | nl80211_send_reg_change_event(&request); | ||
377 | } | ||
378 | |||
368 | res = 0; | 379 | res = 0; |
369 | out_unlock: | 380 | out_unlock: |
370 | mutex_unlock(&cfg80211_mutex); | 381 | mutex_unlock(&cfg80211_mutex); |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 531bb67cf502..8ac3d26014a8 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -2739,6 +2739,9 @@ static struct genl_multicast_group nl80211_config_mcgrp = { | |||
2739 | static struct genl_multicast_group nl80211_scan_mcgrp = { | 2739 | static struct genl_multicast_group nl80211_scan_mcgrp = { |
2740 | .name = "scan", | 2740 | .name = "scan", |
2741 | }; | 2741 | }; |
2742 | static struct genl_multicast_group nl80211_regulatory_mcgrp = { | ||
2743 | .name = "regulatory", | ||
2744 | }; | ||
2742 | 2745 | ||
2743 | /* notification functions */ | 2746 | /* notification functions */ |
2744 | 2747 | ||
@@ -2818,6 +2821,61 @@ void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, | |||
2818 | genlmsg_multicast(msg, 0, nl80211_scan_mcgrp.id, GFP_KERNEL); | 2821 | genlmsg_multicast(msg, 0, nl80211_scan_mcgrp.id, GFP_KERNEL); |
2819 | } | 2822 | } |
2820 | 2823 | ||
2824 | /* | ||
2825 | * This can happen on global regulatory changes or device specific settings | ||
2826 | * based on custom world regulatory domains. | ||
2827 | */ | ||
2828 | void nl80211_send_reg_change_event(struct regulatory_request *request) | ||
2829 | { | ||
2830 | struct sk_buff *msg; | ||
2831 | void *hdr; | ||
2832 | |||
2833 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | ||
2834 | if (!msg) | ||
2835 | return; | ||
2836 | |||
2837 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_REG_CHANGE); | ||
2838 | if (!hdr) { | ||
2839 | nlmsg_free(msg); | ||
2840 | return; | ||
2841 | } | ||
2842 | |||
2843 | /* Userspace can always count this one always being set */ | ||
2844 | NLA_PUT_U8(msg, NL80211_ATTR_REG_INITIATOR, request->initiator); | ||
2845 | |||
2846 | if (request->alpha2[0] == '0' && request->alpha2[1] == '0') | ||
2847 | NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE, | ||
2848 | NL80211_REGDOM_TYPE_WORLD); | ||
2849 | else if (request->alpha2[0] == '9' && request->alpha2[1] == '9') | ||
2850 | NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE, | ||
2851 | NL80211_REGDOM_TYPE_CUSTOM_WORLD); | ||
2852 | else if ((request->alpha2[0] == '9' && request->alpha2[1] == '8') || | ||
2853 | request->intersect) | ||
2854 | NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE, | ||
2855 | NL80211_REGDOM_TYPE_INTERSECTION); | ||
2856 | else { | ||
2857 | NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE, | ||
2858 | NL80211_REGDOM_TYPE_COUNTRY); | ||
2859 | NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, request->alpha2); | ||
2860 | } | ||
2861 | |||
2862 | if (wiphy_idx_valid(request->wiphy_idx)) | ||
2863 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, request->wiphy_idx); | ||
2864 | |||
2865 | if (genlmsg_end(msg, hdr) < 0) { | ||
2866 | nlmsg_free(msg); | ||
2867 | return; | ||
2868 | } | ||
2869 | |||
2870 | genlmsg_multicast(msg, 0, nl80211_regulatory_mcgrp.id, GFP_KERNEL); | ||
2871 | |||
2872 | return; | ||
2873 | |||
2874 | nla_put_failure: | ||
2875 | genlmsg_cancel(msg, hdr); | ||
2876 | nlmsg_free(msg); | ||
2877 | } | ||
2878 | |||
2821 | /* initialisation/exit functions */ | 2879 | /* initialisation/exit functions */ |
2822 | 2880 | ||
2823 | int nl80211_init(void) | 2881 | int nl80211_init(void) |
@@ -2842,6 +2900,10 @@ int nl80211_init(void) | |||
2842 | if (err) | 2900 | if (err) |
2843 | goto err_out; | 2901 | goto err_out; |
2844 | 2902 | ||
2903 | err = genl_register_mc_group(&nl80211_fam, &nl80211_regulatory_mcgrp); | ||
2904 | if (err) | ||
2905 | goto err_out; | ||
2906 | |||
2845 | return 0; | 2907 | return 0; |
2846 | err_out: | 2908 | err_out: |
2847 | genl_unregister_family(&nl80211_fam); | 2909 | genl_unregister_family(&nl80211_fam); |
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index 69787b621365..e65a3c38c52f 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h | |||
@@ -11,6 +11,7 @@ extern void nl80211_send_scan_done(struct cfg80211_registered_device *rdev, | |||
11 | struct net_device *netdev); | 11 | struct net_device *netdev); |
12 | extern void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, | 12 | extern void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, |
13 | struct net_device *netdev); | 13 | struct net_device *netdev); |
14 | extern void nl80211_send_reg_change_event(struct regulatory_request *request); | ||
14 | #else | 15 | #else |
15 | static inline int nl80211_init(void) | 16 | static inline int nl80211_init(void) |
16 | { | 17 | { |
@@ -31,6 +32,10 @@ static inline void nl80211_send_scan_aborted( | |||
31 | struct cfg80211_registered_device *rdev, | 32 | struct cfg80211_registered_device *rdev, |
32 | struct net_device *netdev) | 33 | struct net_device *netdev) |
33 | {} | 34 | {} |
35 | static inline void | ||
36 | nl80211_send_reg_change_event(struct regulatory_request *request) | ||
37 | { | ||
38 | } | ||
34 | #endif /* CONFIG_NL80211 */ | 39 | #endif /* CONFIG_NL80211 */ |
35 | 40 | ||
36 | #endif /* __NET_WIRELESS_NL80211_H */ | 41 | #endif /* __NET_WIRELESS_NL80211_H */ |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 68fde6d33dc3..eb8b8ed16155 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <net/cfg80211.h> | 41 | #include <net/cfg80211.h> |
42 | #include "core.h" | 42 | #include "core.h" |
43 | #include "reg.h" | 43 | #include "reg.h" |
44 | #include "nl80211.h" | ||
44 | 45 | ||
45 | /* Receipt of information from last regulatory request */ | 46 | /* Receipt of information from last regulatory request */ |
46 | static struct regulatory_request *last_request; | 47 | static struct regulatory_request *last_request; |
@@ -1403,8 +1404,16 @@ new_request: | |||
1403 | pending_request = NULL; | 1404 | pending_request = NULL; |
1404 | 1405 | ||
1405 | /* When r == REG_INTERSECT we do need to call CRDA */ | 1406 | /* When r == REG_INTERSECT we do need to call CRDA */ |
1406 | if (r < 0) | 1407 | if (r < 0) { |
1408 | /* | ||
1409 | * Since CRDA will not be called in this case as we already | ||
1410 | * have applied the requested regulatory domain before we just | ||
1411 | * inform userspace we have processed the request | ||
1412 | */ | ||
1413 | if (r == -EALREADY) | ||
1414 | nl80211_send_reg_change_event(last_request); | ||
1407 | return r; | 1415 | return r; |
1416 | } | ||
1408 | 1417 | ||
1409 | /* | 1418 | /* |
1410 | * Note: When CONFIG_WIRELESS_OLD_REGULATORY is enabled | 1419 | * Note: When CONFIG_WIRELESS_OLD_REGULATORY is enabled |
@@ -2084,6 +2093,8 @@ int set_regdom(const struct ieee80211_regdomain *rd) | |||
2084 | 2093 | ||
2085 | print_regdomain(cfg80211_regdomain); | 2094 | print_regdomain(cfg80211_regdomain); |
2086 | 2095 | ||
2096 | nl80211_send_reg_change_event(last_request); | ||
2097 | |||
2087 | return r; | 2098 | return r; |
2088 | } | 2099 | } |
2089 | 2100 | ||