aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-03-30 17:53:32 -0400
committerIngo Molnar <mingo@elte.hu>2009-03-30 17:53:32 -0400
commit65fb0d23fcddd8697c871047b700c78817bdaa43 (patch)
tree119e6e5f276622c4c862f6c9b6d795264ba1603a /net/wireless
parent8c083f081d0014057901c68a0a3e0f8ca7ac8d23 (diff)
parentdfbbe89e197a77f2c8046a51c74e33e35f878080 (diff)
Merge branch 'linus' into cpumask-for-linus
Conflicts: arch/x86/kernel/cpu/common.c
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/Kconfig60
-rw-r--r--net/wireless/Makefile3
-rw-r--r--net/wireless/core.c162
-rw-r--r--net/wireless/core.h64
-rw-r--r--net/wireless/lib80211_crypt_ccmp.c2
-rw-r--r--net/wireless/lib80211_crypt_tkip.c4
-rw-r--r--net/wireless/mlme.c46
-rw-r--r--net/wireless/nl80211.c1335
-rw-r--r--net/wireless/nl80211.h31
-rw-r--r--net/wireless/reg.c1255
-rw-r--r--net/wireless/reg.h45
-rw-r--r--net/wireless/scan.c891
-rw-r--r--net/wireless/sysfs.c39
-rw-r--r--net/wireless/util.c2
-rw-r--r--net/wireless/wext-compat.c108
15 files changed, 3501 insertions, 546 deletions
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig
index e28e2b8fa436..3c3bc9e579ed 100644
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -10,51 +10,19 @@ config CFG80211_REG_DEBUG
10 10
11 If unsure, say N. 11 If unsure, say N.
12 12
13config NL80211
14 bool "nl80211 new netlink interface support"
15 depends on CFG80211
16 default y
17 ---help---
18 This option turns on the new netlink interface
19 (nl80211) support in cfg80211.
20
21 If =n, drivers using mac80211 will be configured via
22 wireless extension support provided by that subsystem.
23
24 If unsure, say Y.
25
26config WIRELESS_OLD_REGULATORY 13config WIRELESS_OLD_REGULATORY
27 bool "Old wireless static regulatory definitions" 14 bool "Old wireless static regulatory definitions"
28 default y 15 default n
29 ---help--- 16 ---help---
30 This option enables the old static regulatory information 17 This option enables the old static regulatory information
31 and uses it within the new framework. This is available 18 and uses it within the new framework. This option is available
32 temporarily as an option to help prevent immediate issues 19 for historical reasons and it is advised to leave it off.
33 due to the switch to the new regulatory framework which 20
34 does require a new userspace application which has the 21 For details see:
35 database of regulatory information (CRDA) and another for 22
36 setting regulatory domains (iw). 23 http://wireless.kernel.org/en/developers/Regulatory
37 24
38 For more information see: 25 Say N and if you say Y, please tell us why. The default is N.
39
40 http://wireless.kernel.org/en/developers/Regulatory/CRDA
41 http://wireless.kernel.org/en/users/Documentation/iw
42
43 It is important to note though that if you *do* have CRDA present
44 and if this option is enabled CRDA *will* be called to update the
45 regulatory domain (for US and JP only). Support for letting the user
46 set the regulatory domain through iw is also supported. This option
47 mainly exists to leave around for a kernel release some old static
48 regulatory domains that were defined and to keep around the old
49 ieee80211_regdom module parameter. This is being phased out and you
50 should stop using them ASAP.
51
52 Note: You will need CRDA if you want 802.11d support
53
54 Say Y unless you have installed a new userspace application.
55 Also say Y if have one currently depending on the ieee80211_regdom
56 module parameter and cannot port it to use the new userspace
57 interfaces.
58 26
59config WIRELESS_EXT 27config WIRELESS_EXT
60 bool "Wireless extensions" 28 bool "Wireless extensions"
@@ -102,3 +70,13 @@ config LIB80211_CRYPT_CCMP
102 70
103config LIB80211_CRYPT_TKIP 71config LIB80211_CRYPT_TKIP
104 tristate 72 tristate
73
74config LIB80211_DEBUG
75 bool "lib80211 debugging messages"
76 depends on LIB80211
77 default n
78 ---help---
79 You can enable this if you want verbose debugging messages
80 from lib80211.
81
82 If unsure, say N.
diff --git a/net/wireless/Makefile b/net/wireless/Makefile
index 938a334c8dbc..6d1e7b27b752 100644
--- a/net/wireless/Makefile
+++ b/net/wireless/Makefile
@@ -5,8 +5,7 @@ obj-$(CONFIG_LIB80211_CRYPT_WEP) += lib80211_crypt_wep.o
5obj-$(CONFIG_LIB80211_CRYPT_CCMP) += lib80211_crypt_ccmp.o 5obj-$(CONFIG_LIB80211_CRYPT_CCMP) += lib80211_crypt_ccmp.o
6obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib80211_crypt_tkip.o 6obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib80211_crypt_tkip.o
7 7
8cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o 8cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o mlme.o
9cfg80211-$(CONFIG_WIRELESS_EXT) += wext-compat.o 9cfg80211-$(CONFIG_WIRELESS_EXT) += wext-compat.o
10cfg80211-$(CONFIG_NL80211) += nl80211.o
11 10
12ccflags-y += -D__CHECK_ENDIAN__ 11ccflags-y += -D__CHECK_ENDIAN__
diff --git a/net/wireless/core.c b/net/wireless/core.c
index b96fc0c3f1c4..d1f556535f6d 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -7,7 +7,6 @@
7#include <linux/if.h> 7#include <linux/if.h>
8#include <linux/module.h> 8#include <linux/module.h>
9#include <linux/err.h> 9#include <linux/err.h>
10#include <linux/mutex.h>
11#include <linux/list.h> 10#include <linux/list.h>
12#include <linux/nl80211.h> 11#include <linux/nl80211.h>
13#include <linux/debugfs.h> 12#include <linux/debugfs.h>
@@ -31,18 +30,29 @@ MODULE_DESCRIPTION("wireless configuration support");
31 * only read the list, and that can happen quite 30 * only read the list, and that can happen quite
32 * often because we need to do it for each command */ 31 * often because we need to do it for each command */
33LIST_HEAD(cfg80211_drv_list); 32LIST_HEAD(cfg80211_drv_list);
34DEFINE_MUTEX(cfg80211_drv_mutex); 33
34/*
35 * This is used to protect the cfg80211_drv_list, cfg80211_regdomain,
36 * country_ie_regdomain, the reg_beacon_list and the the last regulatory
37 * request receipt (last_request).
38 */
39DEFINE_MUTEX(cfg80211_mutex);
35 40
36/* for debugfs */ 41/* for debugfs */
37static struct dentry *ieee80211_debugfs_dir; 42static struct dentry *ieee80211_debugfs_dir;
38 43
39/* requires cfg80211_drv_mutex to be held! */ 44/* requires cfg80211_mutex to be held! */
40static struct cfg80211_registered_device *cfg80211_drv_by_wiphy(int wiphy) 45struct cfg80211_registered_device *cfg80211_drv_by_wiphy_idx(int wiphy_idx)
41{ 46{
42 struct cfg80211_registered_device *result = NULL, *drv; 47 struct cfg80211_registered_device *result = NULL, *drv;
43 48
49 if (!wiphy_idx_valid(wiphy_idx))
50 return NULL;
51
52 assert_cfg80211_lock();
53
44 list_for_each_entry(drv, &cfg80211_drv_list, list) { 54 list_for_each_entry(drv, &cfg80211_drv_list, list) {
45 if (drv->idx == wiphy) { 55 if (drv->wiphy_idx == wiphy_idx) {
46 result = drv; 56 result = drv;
47 break; 57 break;
48 } 58 }
@@ -51,17 +61,44 @@ static struct cfg80211_registered_device *cfg80211_drv_by_wiphy(int wiphy)
51 return result; 61 return result;
52} 62}
53 63
64int get_wiphy_idx(struct wiphy *wiphy)
65{
66 struct cfg80211_registered_device *drv;
67 if (!wiphy)
68 return WIPHY_IDX_STALE;
69 drv = wiphy_to_dev(wiphy);
70 return drv->wiphy_idx;
71}
72
54/* requires cfg80211_drv_mutex to be held! */ 73/* requires cfg80211_drv_mutex to be held! */
55static struct cfg80211_registered_device * 74struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx)
75{
76 struct cfg80211_registered_device *drv;
77
78 if (!wiphy_idx_valid(wiphy_idx))
79 return NULL;
80
81 assert_cfg80211_lock();
82
83 drv = cfg80211_drv_by_wiphy_idx(wiphy_idx);
84 if (!drv)
85 return NULL;
86 return &drv->wiphy;
87}
88
89/* requires cfg80211_mutex to be held! */
90struct cfg80211_registered_device *
56__cfg80211_drv_from_info(struct genl_info *info) 91__cfg80211_drv_from_info(struct genl_info *info)
57{ 92{
58 int ifindex; 93 int ifindex;
59 struct cfg80211_registered_device *bywiphy = NULL, *byifidx = NULL; 94 struct cfg80211_registered_device *bywiphyidx = NULL, *byifidx = NULL;
60 struct net_device *dev; 95 struct net_device *dev;
61 int err = -EINVAL; 96 int err = -EINVAL;
62 97
98 assert_cfg80211_lock();
99
63 if (info->attrs[NL80211_ATTR_WIPHY]) { 100 if (info->attrs[NL80211_ATTR_WIPHY]) {
64 bywiphy = cfg80211_drv_by_wiphy( 101 bywiphyidx = cfg80211_drv_by_wiphy_idx(
65 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY])); 102 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY]));
66 err = -ENODEV; 103 err = -ENODEV;
67 } 104 }
@@ -78,14 +115,14 @@ __cfg80211_drv_from_info(struct genl_info *info)
78 err = -ENODEV; 115 err = -ENODEV;
79 } 116 }
80 117
81 if (bywiphy && byifidx) { 118 if (bywiphyidx && byifidx) {
82 if (bywiphy != byifidx) 119 if (bywiphyidx != byifidx)
83 return ERR_PTR(-EINVAL); 120 return ERR_PTR(-EINVAL);
84 else 121 else
85 return bywiphy; /* == byifidx */ 122 return bywiphyidx; /* == byifidx */
86 } 123 }
87 if (bywiphy) 124 if (bywiphyidx)
88 return bywiphy; 125 return bywiphyidx;
89 126
90 if (byifidx) 127 if (byifidx)
91 return byifidx; 128 return byifidx;
@@ -98,7 +135,7 @@ cfg80211_get_dev_from_info(struct genl_info *info)
98{ 135{
99 struct cfg80211_registered_device *drv; 136 struct cfg80211_registered_device *drv;
100 137
101 mutex_lock(&cfg80211_drv_mutex); 138 mutex_lock(&cfg80211_mutex);
102 drv = __cfg80211_drv_from_info(info); 139 drv = __cfg80211_drv_from_info(info);
103 140
104 /* if it is not an error we grab the lock on 141 /* if it is not an error we grab the lock on
@@ -107,7 +144,7 @@ cfg80211_get_dev_from_info(struct genl_info *info)
107 if (!IS_ERR(drv)) 144 if (!IS_ERR(drv))
108 mutex_lock(&drv->mtx); 145 mutex_lock(&drv->mtx);
109 146
110 mutex_unlock(&cfg80211_drv_mutex); 147 mutex_unlock(&cfg80211_mutex);
111 148
112 return drv; 149 return drv;
113} 150}
@@ -118,7 +155,7 @@ cfg80211_get_dev_from_ifindex(int ifindex)
118 struct cfg80211_registered_device *drv = ERR_PTR(-ENODEV); 155 struct cfg80211_registered_device *drv = ERR_PTR(-ENODEV);
119 struct net_device *dev; 156 struct net_device *dev;
120 157
121 mutex_lock(&cfg80211_drv_mutex); 158 mutex_lock(&cfg80211_mutex);
122 dev = dev_get_by_index(&init_net, ifindex); 159 dev = dev_get_by_index(&init_net, ifindex);
123 if (!dev) 160 if (!dev)
124 goto out; 161 goto out;
@@ -129,7 +166,7 @@ cfg80211_get_dev_from_ifindex(int ifindex)
129 drv = ERR_PTR(-ENODEV); 166 drv = ERR_PTR(-ENODEV);
130 dev_put(dev); 167 dev_put(dev);
131 out: 168 out:
132 mutex_unlock(&cfg80211_drv_mutex); 169 mutex_unlock(&cfg80211_mutex);
133 return drv; 170 return drv;
134} 171}
135 172
@@ -139,49 +176,43 @@ void cfg80211_put_dev(struct cfg80211_registered_device *drv)
139 mutex_unlock(&drv->mtx); 176 mutex_unlock(&drv->mtx);
140} 177}
141 178
179/* requires cfg80211_mutex to be held */
142int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, 180int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
143 char *newname) 181 char *newname)
144{ 182{
145 struct cfg80211_registered_device *drv; 183 struct cfg80211_registered_device *drv;
146 int idx, taken = -1, result, digits; 184 int wiphy_idx, taken = -1, result, digits;
147 185
148 mutex_lock(&cfg80211_drv_mutex); 186 assert_cfg80211_lock();
149 187
150 /* prohibit calling the thing phy%d when %d is not its number */ 188 /* prohibit calling the thing phy%d when %d is not its number */
151 sscanf(newname, PHY_NAME "%d%n", &idx, &taken); 189 sscanf(newname, PHY_NAME "%d%n", &wiphy_idx, &taken);
152 if (taken == strlen(newname) && idx != rdev->idx) { 190 if (taken == strlen(newname) && wiphy_idx != rdev->wiphy_idx) {
153 /* count number of places needed to print idx */ 191 /* count number of places needed to print wiphy_idx */
154 digits = 1; 192 digits = 1;
155 while (idx /= 10) 193 while (wiphy_idx /= 10)
156 digits++; 194 digits++;
157 /* 195 /*
158 * deny the name if it is phy<idx> where <idx> is printed 196 * deny the name if it is phy<idx> where <idx> is printed
159 * without leading zeroes. taken == strlen(newname) here 197 * without leading zeroes. taken == strlen(newname) here
160 */ 198 */
161 result = -EINVAL;
162 if (taken == strlen(PHY_NAME) + digits) 199 if (taken == strlen(PHY_NAME) + digits)
163 goto out_unlock; 200 return -EINVAL;
164 } 201 }
165 202
166 203
167 /* Ignore nop renames */ 204 /* Ignore nop renames */
168 result = 0;
169 if (strcmp(newname, dev_name(&rdev->wiphy.dev)) == 0) 205 if (strcmp(newname, dev_name(&rdev->wiphy.dev)) == 0)
170 goto out_unlock; 206 return 0;
171 207
172 /* Ensure another device does not already have this name. */ 208 /* Ensure another device does not already have this name. */
173 list_for_each_entry(drv, &cfg80211_drv_list, list) { 209 list_for_each_entry(drv, &cfg80211_drv_list, list)
174 result = -EINVAL;
175 if (strcmp(newname, dev_name(&drv->wiphy.dev)) == 0) 210 if (strcmp(newname, dev_name(&drv->wiphy.dev)) == 0)
176 goto out_unlock; 211 return -EINVAL;
177 }
178 212
179 /* this will only check for collisions in sysfs
180 * which is not even always compiled in.
181 */
182 result = device_rename(&rdev->wiphy.dev, newname); 213 result = device_rename(&rdev->wiphy.dev, newname);
183 if (result) 214 if (result)
184 goto out_unlock; 215 return result;
185 216
186 if (rdev->wiphy.debugfsdir && 217 if (rdev->wiphy.debugfsdir &&
187 !debugfs_rename(rdev->wiphy.debugfsdir->d_parent, 218 !debugfs_rename(rdev->wiphy.debugfsdir->d_parent,
@@ -191,13 +222,9 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
191 printk(KERN_ERR "cfg80211: failed to rename debugfs dir to %s!\n", 222 printk(KERN_ERR "cfg80211: failed to rename debugfs dir to %s!\n",
192 newname); 223 newname);
193 224
194 result = 0; 225 nl80211_notify_dev_rename(rdev);
195out_unlock:
196 mutex_unlock(&cfg80211_drv_mutex);
197 if (result == 0)
198 nl80211_notify_dev_rename(rdev);
199 226
200 return result; 227 return 0;
201} 228}
202 229
203/* exported functions */ 230/* exported functions */
@@ -220,26 +247,28 @@ struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv)
220 247
221 drv->ops = ops; 248 drv->ops = ops;
222 249
223 mutex_lock(&cfg80211_drv_mutex); 250 mutex_lock(&cfg80211_mutex);
224 251
225 drv->idx = wiphy_counter++; 252 drv->wiphy_idx = wiphy_counter++;
226 253
227 if (unlikely(drv->idx < 0)) { 254 if (unlikely(!wiphy_idx_valid(drv->wiphy_idx))) {
228 wiphy_counter--; 255 wiphy_counter--;
229 mutex_unlock(&cfg80211_drv_mutex); 256 mutex_unlock(&cfg80211_mutex);
230 /* ugh, wrapped! */ 257 /* ugh, wrapped! */
231 kfree(drv); 258 kfree(drv);
232 return NULL; 259 return NULL;
233 } 260 }
234 261
235 mutex_unlock(&cfg80211_drv_mutex); 262 mutex_unlock(&cfg80211_mutex);
236 263
237 /* give it a proper name */ 264 /* give it a proper name */
238 dev_set_name(&drv->wiphy.dev, PHY_NAME "%d", drv->idx); 265 dev_set_name(&drv->wiphy.dev, PHY_NAME "%d", drv->wiphy_idx);
239 266
240 mutex_init(&drv->mtx); 267 mutex_init(&drv->mtx);
241 mutex_init(&drv->devlist_mtx); 268 mutex_init(&drv->devlist_mtx);
242 INIT_LIST_HEAD(&drv->netdev_list); 269 INIT_LIST_HEAD(&drv->netdev_list);
270 spin_lock_init(&drv->bss_lock);
271 INIT_LIST_HEAD(&drv->bss_list);
243 272
244 device_initialize(&drv->wiphy.dev); 273 device_initialize(&drv->wiphy.dev);
245 drv->wiphy.dev.class = &ieee80211_class; 274 drv->wiphy.dev.class = &ieee80211_class;
@@ -259,6 +288,9 @@ int wiphy_register(struct wiphy *wiphy)
259 int i; 288 int i;
260 u16 ifmodes = wiphy->interface_modes; 289 u16 ifmodes = wiphy->interface_modes;
261 290
291 if (WARN_ON(wiphy->max_scan_ssids < 1))
292 return -EINVAL;
293
262 /* sanity check ifmodes */ 294 /* sanity check ifmodes */
263 WARN_ON(!ifmodes); 295 WARN_ON(!ifmodes);
264 ifmodes &= ((1 << __NL80211_IFTYPE_AFTER_LAST) - 1) & ~1; 296 ifmodes &= ((1 << __NL80211_IFTYPE_AFTER_LAST) - 1) & ~1;
@@ -273,10 +305,16 @@ int wiphy_register(struct wiphy *wiphy)
273 305
274 sband->band = band; 306 sband->band = band;
275 307
276 if (!sband->n_channels || !sband->n_bitrates) { 308 if (WARN_ON(!sband->n_channels || !sband->n_bitrates))
277 WARN_ON(1); 309 return -EINVAL;
310
311 /*
312 * Since we use a u32 for rate bitmaps in
313 * ieee80211_get_response_rate, we cannot
314 * have more than 32 legacy rates.
315 */
316 if (WARN_ON(sband->n_bitrates > 32))
278 return -EINVAL; 317 return -EINVAL;
279 }
280 318
281 for (i = 0; i < sband->n_channels; i++) { 319 for (i = 0; i < sband->n_channels; i++) {
282 sband->channels[i].orig_flags = 320 sband->channels[i].orig_flags =
@@ -299,10 +337,10 @@ int wiphy_register(struct wiphy *wiphy)
299 /* check and set up bitrates */ 337 /* check and set up bitrates */
300 ieee80211_set_bitrate_flags(wiphy); 338 ieee80211_set_bitrate_flags(wiphy);
301 339
302 mutex_lock(&cfg80211_drv_mutex); 340 mutex_lock(&cfg80211_mutex);
303 341
304 /* set up regulatory info */ 342 /* set up regulatory info */
305 wiphy_update_regulatory(wiphy, REGDOM_SET_BY_CORE); 343 wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE);
306 344
307 res = device_add(&drv->wiphy.dev); 345 res = device_add(&drv->wiphy.dev);
308 if (res) 346 if (res)
@@ -317,9 +355,20 @@ int wiphy_register(struct wiphy *wiphy)
317 if (IS_ERR(drv->wiphy.debugfsdir)) 355 if (IS_ERR(drv->wiphy.debugfsdir))
318 drv->wiphy.debugfsdir = NULL; 356 drv->wiphy.debugfsdir = NULL;
319 357
358 if (wiphy->custom_regulatory) {
359 struct regulatory_request request;
360
361 request.wiphy_idx = get_wiphy_idx(wiphy);
362 request.initiator = NL80211_REGDOM_SET_BY_DRIVER;
363 request.alpha2[0] = '9';
364 request.alpha2[1] = '9';
365
366 nl80211_send_reg_change_event(&request);
367 }
368
320 res = 0; 369 res = 0;
321out_unlock: 370out_unlock:
322 mutex_unlock(&cfg80211_drv_mutex); 371 mutex_unlock(&cfg80211_mutex);
323 return res; 372 return res;
324} 373}
325EXPORT_SYMBOL(wiphy_register); 374EXPORT_SYMBOL(wiphy_register);
@@ -329,7 +378,7 @@ void wiphy_unregister(struct wiphy *wiphy)
329 struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy); 378 struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy);
330 379
331 /* protect the device list */ 380 /* protect the device list */
332 mutex_lock(&cfg80211_drv_mutex); 381 mutex_lock(&cfg80211_mutex);
333 382
334 BUG_ON(!list_empty(&drv->netdev_list)); 383 BUG_ON(!list_empty(&drv->netdev_list));
335 384
@@ -355,14 +404,17 @@ void wiphy_unregister(struct wiphy *wiphy)
355 device_del(&drv->wiphy.dev); 404 device_del(&drv->wiphy.dev);
356 debugfs_remove(drv->wiphy.debugfsdir); 405 debugfs_remove(drv->wiphy.debugfsdir);
357 406
358 mutex_unlock(&cfg80211_drv_mutex); 407 mutex_unlock(&cfg80211_mutex);
359} 408}
360EXPORT_SYMBOL(wiphy_unregister); 409EXPORT_SYMBOL(wiphy_unregister);
361 410
362void cfg80211_dev_free(struct cfg80211_registered_device *drv) 411void cfg80211_dev_free(struct cfg80211_registered_device *drv)
363{ 412{
413 struct cfg80211_internal_bss *scan, *tmp;
364 mutex_destroy(&drv->mtx); 414 mutex_destroy(&drv->mtx);
365 mutex_destroy(&drv->devlist_mtx); 415 mutex_destroy(&drv->devlist_mtx);
416 list_for_each_entry_safe(scan, tmp, &drv->bss_list, list)
417 cfg80211_put_bss(&scan->pub);
366 kfree(drv); 418 kfree(drv);
367} 419}
368 420
diff --git a/net/wireless/core.h b/net/wireless/core.h
index f7fb9f413028..d43daa236ef9 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -8,6 +8,9 @@
8#include <linux/mutex.h> 8#include <linux/mutex.h>
9#include <linux/list.h> 9#include <linux/list.h>
10#include <linux/netdevice.h> 10#include <linux/netdevice.h>
11#include <linux/kref.h>
12#include <linux/rbtree.h>
13#include <linux/mutex.h>
11#include <net/genetlink.h> 14#include <net/genetlink.h>
12#include <net/wireless.h> 15#include <net/wireless.h>
13#include <net/cfg80211.h> 16#include <net/cfg80211.h>
@@ -35,12 +38,20 @@ struct cfg80211_registered_device {
35 enum environment_cap env; 38 enum environment_cap env;
36 39
37 /* wiphy index, internal only */ 40 /* wiphy index, internal only */
38 int idx; 41 int wiphy_idx;
39 42
40 /* associate netdev list */ 43 /* associate netdev list */
41 struct mutex devlist_mtx; 44 struct mutex devlist_mtx;
42 struct list_head netdev_list; 45 struct list_head netdev_list;
43 46
47 /* BSSes/scanning */
48 spinlock_t bss_lock;
49 struct list_head bss_list;
50 struct rb_root bss_tree;
51 u32 bss_generation;
52 struct cfg80211_scan_request *scan_req; /* protected by RTNL */
53 unsigned long suspend_at;
54
44 /* must be last because of the way we do wiphy_priv(), 55 /* must be last because of the way we do wiphy_priv(),
45 * and it should at least be aligned to NETDEV_ALIGN */ 56 * and it should at least be aligned to NETDEV_ALIGN */
46 struct wiphy wiphy __attribute__((__aligned__(NETDEV_ALIGN))); 57 struct wiphy wiphy __attribute__((__aligned__(NETDEV_ALIGN)));
@@ -53,9 +64,44 @@ struct cfg80211_registered_device *wiphy_to_dev(struct wiphy *wiphy)
53 return container_of(wiphy, struct cfg80211_registered_device, wiphy); 64 return container_of(wiphy, struct cfg80211_registered_device, wiphy);
54} 65}
55 66
56extern struct mutex cfg80211_drv_mutex; 67/* Note 0 is valid, hence phy0 */
68static inline
69bool wiphy_idx_valid(int wiphy_idx)
70{
71 return (wiphy_idx >= 0);
72}
73
74extern struct mutex cfg80211_mutex;
57extern struct list_head cfg80211_drv_list; 75extern struct list_head cfg80211_drv_list;
58 76
77static inline void assert_cfg80211_lock(void)
78{
79 WARN_ON(!mutex_is_locked(&cfg80211_mutex));
80}
81
82/*
83 * You can use this to mark a wiphy_idx as not having an associated wiphy.
84 * It guarantees cfg80211_drv_by_wiphy_idx(wiphy_idx) will return NULL
85 */
86#define WIPHY_IDX_STALE -1
87
88struct cfg80211_internal_bss {
89 struct list_head list;
90 struct rb_node rbn;
91 unsigned long ts;
92 struct kref ref;
93 bool hold;
94
95 /* must be last because of priv member */
96 struct cfg80211_bss pub;
97};
98
99struct cfg80211_registered_device *cfg80211_drv_by_wiphy_idx(int wiphy_idx);
100int get_wiphy_idx(struct wiphy *wiphy);
101
102struct cfg80211_registered_device *
103__cfg80211_drv_from_info(struct genl_info *info);
104
59/* 105/*
60 * This function returns a pointer to the driver 106 * This function returns a pointer to the driver
61 * that the genl_info item that is passed refers to. 107 * that the genl_info item that is passed refers to.
@@ -63,13 +109,13 @@ extern struct list_head cfg80211_drv_list;
63 * the driver's mutex! 109 * the driver's mutex!
64 * 110 *
65 * This means that you need to call cfg80211_put_dev() 111 * This means that you need to call cfg80211_put_dev()
66 * before being allowed to acquire &cfg80211_drv_mutex! 112 * before being allowed to acquire &cfg80211_mutex!
67 * 113 *
68 * This is necessary because we need to lock the global 114 * This is necessary because we need to lock the global
69 * mutex to get an item off the list safely, and then 115 * mutex to get an item off the list safely, and then
70 * we lock the drv mutex so it doesn't go away under us. 116 * we lock the drv mutex so it doesn't go away under us.
71 * 117 *
72 * We don't want to keep cfg80211_drv_mutex locked 118 * We don't want to keep cfg80211_mutex locked
73 * for all the time in order to allow requests on 119 * for all the time in order to allow requests on
74 * other interfaces to go through at the same time. 120 * other interfaces to go through at the same time.
75 * 121 *
@@ -79,6 +125,9 @@ extern struct list_head cfg80211_drv_list;
79extern struct cfg80211_registered_device * 125extern struct cfg80211_registered_device *
80cfg80211_get_dev_from_info(struct genl_info *info); 126cfg80211_get_dev_from_info(struct genl_info *info);
81 127
128/* requires cfg80211_drv_mutex to be held! */
129struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx);
130
82/* identical to cfg80211_get_dev_from_info but only operate on ifindex */ 131/* identical to cfg80211_get_dev_from_info but only operate on ifindex */
83extern struct cfg80211_registered_device * 132extern struct cfg80211_registered_device *
84cfg80211_get_dev_from_ifindex(int ifindex); 133cfg80211_get_dev_from_ifindex(int ifindex);
@@ -92,6 +141,11 @@ extern int cfg80211_dev_rename(struct cfg80211_registered_device *drv,
92 char *newname); 141 char *newname);
93 142
94void ieee80211_set_bitrate_flags(struct wiphy *wiphy); 143void ieee80211_set_bitrate_flags(struct wiphy *wiphy);
95void wiphy_update_regulatory(struct wiphy *wiphy, enum reg_set_by setby); 144void wiphy_update_regulatory(struct wiphy *wiphy,
145 enum nl80211_reg_initiator setby);
146
147void cfg80211_bss_expire(struct cfg80211_registered_device *dev);
148void cfg80211_bss_age(struct cfg80211_registered_device *dev,
149 unsigned long age_secs);
96 150
97#endif /* __NET_WIRELESS_CORE_H */ 151#endif /* __NET_WIRELESS_CORE_H */
diff --git a/net/wireless/lib80211_crypt_ccmp.c b/net/wireless/lib80211_crypt_ccmp.c
index db428194c16a..2301dc1edc4c 100644
--- a/net/wireless/lib80211_crypt_ccmp.c
+++ b/net/wireless/lib80211_crypt_ccmp.c
@@ -337,6 +337,7 @@ static int lib80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
337 pos += 8; 337 pos += 8;
338 338
339 if (ccmp_replay_check(pn, key->rx_pn)) { 339 if (ccmp_replay_check(pn, key->rx_pn)) {
340#ifdef CONFIG_LIB80211_DEBUG
340 if (net_ratelimit()) { 341 if (net_ratelimit()) {
341 printk(KERN_DEBUG "CCMP: replay detected: STA=%pM " 342 printk(KERN_DEBUG "CCMP: replay detected: STA=%pM "
342 "previous PN %02x%02x%02x%02x%02x%02x " 343 "previous PN %02x%02x%02x%02x%02x%02x "
@@ -346,6 +347,7 @@ static int lib80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
346 key->rx_pn[3], key->rx_pn[4], key->rx_pn[5], 347 key->rx_pn[3], key->rx_pn[4], key->rx_pn[5],
347 pn[0], pn[1], pn[2], pn[3], pn[4], pn[5]); 348 pn[0], pn[1], pn[2], pn[3], pn[4], pn[5]);
348 } 349 }
350#endif
349 key->dot11RSNAStatsCCMPReplays++; 351 key->dot11RSNAStatsCCMPReplays++;
350 return -4; 352 return -4;
351 } 353 }
diff --git a/net/wireless/lib80211_crypt_tkip.c b/net/wireless/lib80211_crypt_tkip.c
index 7e8e22bfed90..c36287399d7e 100644
--- a/net/wireless/lib80211_crypt_tkip.c
+++ b/net/wireless/lib80211_crypt_tkip.c
@@ -465,12 +465,14 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
465 pos += 8; 465 pos += 8;
466 466
467 if (tkip_replay_check(iv32, iv16, tkey->rx_iv32, tkey->rx_iv16)) { 467 if (tkip_replay_check(iv32, iv16, tkey->rx_iv32, tkey->rx_iv16)) {
468#ifdef CONFIG_LIB80211_DEBUG
468 if (net_ratelimit()) { 469 if (net_ratelimit()) {
469 printk(KERN_DEBUG "TKIP: replay detected: STA=%pM" 470 printk(KERN_DEBUG "TKIP: replay detected: STA=%pM"
470 " previous TSC %08x%04x received TSC " 471 " previous TSC %08x%04x received TSC "
471 "%08x%04x\n", hdr->addr2, 472 "%08x%04x\n", hdr->addr2,
472 tkey->rx_iv32, tkey->rx_iv16, iv32, iv16); 473 tkey->rx_iv32, tkey->rx_iv16, iv32, iv16);
473 } 474 }
475#endif
474 tkey->dot11RSNAStatsTKIPReplays++; 476 tkey->dot11RSNAStatsTKIPReplays++;
475 return -4; 477 return -4;
476 } 478 }
@@ -505,10 +507,12 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
505 * it needs to be recalculated for the next packet. */ 507 * it needs to be recalculated for the next packet. */
506 tkey->rx_phase1_done = 0; 508 tkey->rx_phase1_done = 0;
507 } 509 }
510#ifdef CONFIG_LIB80211_DEBUG
508 if (net_ratelimit()) { 511 if (net_ratelimit()) {
509 printk(KERN_DEBUG "TKIP: ICV error detected: STA=" 512 printk(KERN_DEBUG "TKIP: ICV error detected: STA="
510 "%pM\n", hdr->addr2); 513 "%pM\n", hdr->addr2);
511 } 514 }
515#endif
512 tkey->dot11RSNAStatsTKIPICVErrors++; 516 tkey->dot11RSNAStatsTKIPICVErrors++;
513 return -5; 517 return -5;
514 } 518 }
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
new file mode 100644
index 000000000000..bec5721b6f99
--- /dev/null
+++ b/net/wireless/mlme.c
@@ -0,0 +1,46 @@
1/*
2 * cfg80211 MLME SAP interface
3 *
4 * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
5 */
6
7#include <linux/kernel.h>
8#include <linux/module.h>
9#include <linux/netdevice.h>
10#include <linux/nl80211.h>
11#include <net/cfg80211.h>
12#include "core.h"
13#include "nl80211.h"
14
15void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len)
16{
17 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
18 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
19 nl80211_send_rx_auth(rdev, dev, buf, len);
20}
21EXPORT_SYMBOL(cfg80211_send_rx_auth);
22
23void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len)
24{
25 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
26 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
27 nl80211_send_rx_assoc(rdev, dev, buf, len);
28}
29EXPORT_SYMBOL(cfg80211_send_rx_assoc);
30
31void cfg80211_send_rx_deauth(struct net_device *dev, const u8 *buf, size_t len)
32{
33 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
34 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
35 nl80211_send_rx_deauth(rdev, dev, buf, len);
36}
37EXPORT_SYMBOL(cfg80211_send_rx_deauth);
38
39void cfg80211_send_rx_disassoc(struct net_device *dev, const u8 *buf,
40 size_t len)
41{
42 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
43 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
44 nl80211_send_rx_disassoc(rdev, dev, buf, len);
45}
46EXPORT_SYMBOL(cfg80211_send_rx_disassoc);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 1e728fff474e..353e1a4ece83 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -7,13 +7,13 @@
7#include <linux/if.h> 7#include <linux/if.h>
8#include <linux/module.h> 8#include <linux/module.h>
9#include <linux/err.h> 9#include <linux/err.h>
10#include <linux/mutex.h>
11#include <linux/list.h> 10#include <linux/list.h>
12#include <linux/if_ether.h> 11#include <linux/if_ether.h>
13#include <linux/ieee80211.h> 12#include <linux/ieee80211.h>
14#include <linux/nl80211.h> 13#include <linux/nl80211.h>
15#include <linux/rtnetlink.h> 14#include <linux/rtnetlink.h>
16#include <linux/netlink.h> 15#include <linux/netlink.h>
16#include <linux/etherdevice.h>
17#include <net/genetlink.h> 17#include <net/genetlink.h>
18#include <net/cfg80211.h> 18#include <net/cfg80211.h>
19#include "core.h" 19#include "core.h"
@@ -105,6 +105,17 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
105 105
106 [NL80211_ATTR_HT_CAPABILITY] = { .type = NLA_BINARY, 106 [NL80211_ATTR_HT_CAPABILITY] = { .type = NLA_BINARY,
107 .len = NL80211_HT_CAPABILITY_LEN }, 107 .len = NL80211_HT_CAPABILITY_LEN },
108
109 [NL80211_ATTR_MGMT_SUBTYPE] = { .type = NLA_U8 },
110 [NL80211_ATTR_IE] = { .type = NLA_BINARY,
111 .len = IEEE80211_MAX_DATA_LEN },
112 [NL80211_ATTR_SCAN_FREQUENCIES] = { .type = NLA_NESTED },
113 [NL80211_ATTR_SCAN_SSIDS] = { .type = NLA_NESTED },
114
115 [NL80211_ATTR_SSID] = { .type = NLA_BINARY,
116 .len = IEEE80211_MAX_SSID_LEN },
117 [NL80211_ATTR_AUTH_TYPE] = { .type = NLA_U32 },
118 [NL80211_ATTR_REASON_CODE] = { .type = NLA_U16 },
108}; 119};
109 120
110/* message building helper */ 121/* message building helper */
@@ -125,6 +136,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
125 struct nlattr *nl_freqs, *nl_freq; 136 struct nlattr *nl_freqs, *nl_freq;
126 struct nlattr *nl_rates, *nl_rate; 137 struct nlattr *nl_rates, *nl_rate;
127 struct nlattr *nl_modes; 138 struct nlattr *nl_modes;
139 struct nlattr *nl_cmds;
128 enum ieee80211_band band; 140 enum ieee80211_band band;
129 struct ieee80211_channel *chan; 141 struct ieee80211_channel *chan;
130 struct ieee80211_rate *rate; 142 struct ieee80211_rate *rate;
@@ -135,8 +147,10 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
135 if (!hdr) 147 if (!hdr)
136 return -1; 148 return -1;
137 149
138 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->idx); 150 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx);
139 NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy)); 151 NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy));
152 NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
153 dev->wiphy.max_scan_ssids);
140 154
141 nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES); 155 nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES);
142 if (!nl_modes) 156 if (!nl_modes)
@@ -234,6 +248,35 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
234 } 248 }
235 nla_nest_end(msg, nl_bands); 249 nla_nest_end(msg, nl_bands);
236 250
251 nl_cmds = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_COMMANDS);
252 if (!nl_cmds)
253 goto nla_put_failure;
254
255 i = 0;
256#define CMD(op, n) \
257 do { \
258 if (dev->ops->op) { \
259 i++; \
260 NLA_PUT_U32(msg, i, NL80211_CMD_ ## n); \
261 } \
262 } while (0)
263
264 CMD(add_virtual_intf, NEW_INTERFACE);
265 CMD(change_virtual_intf, SET_INTERFACE);
266 CMD(add_key, NEW_KEY);
267 CMD(add_beacon, NEW_BEACON);
268 CMD(add_station, NEW_STATION);
269 CMD(add_mpath, NEW_MPATH);
270 CMD(set_mesh_params, SET_MESH_PARAMS);
271 CMD(change_bss, SET_BSS);
272 CMD(auth, AUTHENTICATE);
273 CMD(assoc, ASSOCIATE);
274 CMD(deauth, DEAUTHENTICATE);
275 CMD(disassoc, DISASSOCIATE);
276
277#undef CMD
278 nla_nest_end(msg, nl_cmds);
279
237 return genlmsg_end(msg, hdr); 280 return genlmsg_end(msg, hdr);
238 281
239 nla_put_failure: 282 nla_put_failure:
@@ -247,7 +290,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
247 int start = cb->args[0]; 290 int start = cb->args[0];
248 struct cfg80211_registered_device *dev; 291 struct cfg80211_registered_device *dev;
249 292
250 mutex_lock(&cfg80211_drv_mutex); 293 mutex_lock(&cfg80211_mutex);
251 list_for_each_entry(dev, &cfg80211_drv_list, list) { 294 list_for_each_entry(dev, &cfg80211_drv_list, list) {
252 if (++idx <= start) 295 if (++idx <= start)
253 continue; 296 continue;
@@ -258,7 +301,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
258 break; 301 break;
259 } 302 }
260 } 303 }
261 mutex_unlock(&cfg80211_drv_mutex); 304 mutex_unlock(&cfg80211_mutex);
262 305
263 cb->args[0] = idx; 306 cb->args[0] = idx;
264 307
@@ -323,16 +366,26 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
323 int result = 0, rem_txq_params = 0; 366 int result = 0, rem_txq_params = 0;
324 struct nlattr *nl_txq_params; 367 struct nlattr *nl_txq_params;
325 368
326 rdev = cfg80211_get_dev_from_info(info); 369 rtnl_lock();
327 if (IS_ERR(rdev)) 370
328 return PTR_ERR(rdev); 371 mutex_lock(&cfg80211_mutex);
372
373 rdev = __cfg80211_drv_from_info(info);
374 if (IS_ERR(rdev)) {
375 result = PTR_ERR(rdev);
376 goto unlock;
377 }
378
379 mutex_lock(&rdev->mtx);
329 380
330 if (info->attrs[NL80211_ATTR_WIPHY_NAME]) { 381 if (info->attrs[NL80211_ATTR_WIPHY_NAME])
331 result = cfg80211_dev_rename( 382 result = cfg80211_dev_rename(
332 rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME])); 383 rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
333 if (result) 384
334 goto bad_res; 385 mutex_unlock(&cfg80211_mutex);
335 } 386
387 if (result)
388 goto bad_res;
336 389
337 if (info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS]) { 390 if (info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS]) {
338 struct ieee80211_txq_params txq_params; 391 struct ieee80211_txq_params txq_params;
@@ -428,7 +481,9 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
428 481
429 482
430 bad_res: 483 bad_res:
431 cfg80211_put_dev(rdev); 484 mutex_unlock(&rdev->mtx);
485 unlock:
486 rtnl_unlock();
432 return result; 487 return result;
433} 488}
434 489
@@ -461,7 +516,7 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
461 struct cfg80211_registered_device *dev; 516 struct cfg80211_registered_device *dev;
462 struct wireless_dev *wdev; 517 struct wireless_dev *wdev;
463 518
464 mutex_lock(&cfg80211_drv_mutex); 519 mutex_lock(&cfg80211_mutex);
465 list_for_each_entry(dev, &cfg80211_drv_list, list) { 520 list_for_each_entry(dev, &cfg80211_drv_list, list) {
466 if (wp_idx < wp_start) { 521 if (wp_idx < wp_start) {
467 wp_idx++; 522 wp_idx++;
@@ -488,7 +543,7 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
488 wp_idx++; 543 wp_idx++;
489 } 544 }
490 out: 545 out:
491 mutex_unlock(&cfg80211_drv_mutex); 546 mutex_unlock(&cfg80211_mutex);
492 547
493 cb->args[0] = wp_idx; 548 cb->args[0] = wp_idx;
494 cb->args[1] = if_idx; 549 cb->args[1] = if_idx;
@@ -564,21 +619,31 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
564 enum nl80211_iftype type; 619 enum nl80211_iftype type;
565 struct net_device *dev; 620 struct net_device *dev;
566 u32 _flags, *flags = NULL; 621 u32 _flags, *flags = NULL;
622 bool change = false;
567 623
568 memset(&params, 0, sizeof(params)); 624 memset(&params, 0, sizeof(params));
569 625
626 rtnl_lock();
627
570 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 628 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
571 if (err) 629 if (err)
572 return err; 630 goto unlock_rtnl;
631
573 ifindex = dev->ifindex; 632 ifindex = dev->ifindex;
574 type = dev->ieee80211_ptr->iftype; 633 type = dev->ieee80211_ptr->iftype;
575 dev_put(dev); 634 dev_put(dev);
576 635
577 err = -EINVAL;
578 if (info->attrs[NL80211_ATTR_IFTYPE]) { 636 if (info->attrs[NL80211_ATTR_IFTYPE]) {
579 type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]); 637 enum nl80211_iftype ntype;
580 if (type > NL80211_IFTYPE_MAX) 638
639 ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
640 if (type != ntype)
641 change = true;
642 type = ntype;
643 if (type > NL80211_IFTYPE_MAX) {
644 err = -EINVAL;
581 goto unlock; 645 goto unlock;
646 }
582 } 647 }
583 648
584 if (!drv->ops->change_virtual_intf || 649 if (!drv->ops->change_virtual_intf ||
@@ -594,6 +659,7 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
594 } 659 }
595 params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]); 660 params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
596 params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); 661 params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
662 change = true;
597 } 663 }
598 664
599 if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) { 665 if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) {
@@ -603,20 +669,26 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
603 } 669 }
604 err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS], 670 err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS],
605 &_flags); 671 &_flags);
606 if (!err) 672 if (err)
607 flags = &_flags; 673 goto unlock;
674
675 flags = &_flags;
676 change = true;
608 } 677 }
609 rtnl_lock(); 678
610 err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, 679 if (change)
611 type, flags, &params); 680 err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex,
681 type, flags, &params);
682 else
683 err = 0;
612 684
613 dev = __dev_get_by_index(&init_net, ifindex); 685 dev = __dev_get_by_index(&init_net, ifindex);
614 WARN_ON(!dev || (!err && dev->ieee80211_ptr->iftype != type)); 686 WARN_ON(!dev || (!err && dev->ieee80211_ptr->iftype != type));
615 687
616 rtnl_unlock();
617
618 unlock: 688 unlock:
619 cfg80211_put_dev(drv); 689 cfg80211_put_dev(drv);
690 unlock_rtnl:
691 rtnl_unlock();
620 return err; 692 return err;
621} 693}
622 694
@@ -639,9 +711,13 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
639 return -EINVAL; 711 return -EINVAL;
640 } 712 }
641 713
714 rtnl_lock();
715
642 drv = cfg80211_get_dev_from_info(info); 716 drv = cfg80211_get_dev_from_info(info);
643 if (IS_ERR(drv)) 717 if (IS_ERR(drv)) {
644 return PTR_ERR(drv); 718 err = PTR_ERR(drv);
719 goto unlock_rtnl;
720 }
645 721
646 if (!drv->ops->add_virtual_intf || 722 if (!drv->ops->add_virtual_intf ||
647 !(drv->wiphy.interface_modes & (1 << type))) { 723 !(drv->wiphy.interface_modes & (1 << type))) {
@@ -655,18 +731,17 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
655 params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); 731 params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
656 } 732 }
657 733
658 rtnl_lock();
659 err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ? 734 err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
660 info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL, 735 info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
661 &flags); 736 &flags);
662 err = drv->ops->add_virtual_intf(&drv->wiphy, 737 err = drv->ops->add_virtual_intf(&drv->wiphy,
663 nla_data(info->attrs[NL80211_ATTR_IFNAME]), 738 nla_data(info->attrs[NL80211_ATTR_IFNAME]),
664 type, err ? NULL : &flags, &params); 739 type, err ? NULL : &flags, &params);
665 rtnl_unlock();
666
667 740
668 unlock: 741 unlock:
669 cfg80211_put_dev(drv); 742 cfg80211_put_dev(drv);
743 unlock_rtnl:
744 rtnl_unlock();
670 return err; 745 return err;
671} 746}
672 747
@@ -676,9 +751,11 @@ static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
676 int ifindex, err; 751 int ifindex, err;
677 struct net_device *dev; 752 struct net_device *dev;
678 753
754 rtnl_lock();
755
679 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 756 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
680 if (err) 757 if (err)
681 return err; 758 goto unlock_rtnl;
682 ifindex = dev->ifindex; 759 ifindex = dev->ifindex;
683 dev_put(dev); 760 dev_put(dev);
684 761
@@ -687,12 +764,12 @@ static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
687 goto out; 764 goto out;
688 } 765 }
689 766
690 rtnl_lock();
691 err = drv->ops->del_virtual_intf(&drv->wiphy, ifindex); 767 err = drv->ops->del_virtual_intf(&drv->wiphy, ifindex);
692 rtnl_unlock();
693 768
694 out: 769 out:
695 cfg80211_put_dev(drv); 770 cfg80211_put_dev(drv);
771 unlock_rtnl:
772 rtnl_unlock();
696 return err; 773 return err;
697} 774}
698 775
@@ -738,15 +815,17 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
738 if (info->attrs[NL80211_ATTR_KEY_IDX]) 815 if (info->attrs[NL80211_ATTR_KEY_IDX])
739 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); 816 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
740 817
741 if (key_idx > 3) 818 if (key_idx > 5)
742 return -EINVAL; 819 return -EINVAL;
743 820
744 if (info->attrs[NL80211_ATTR_MAC]) 821 if (info->attrs[NL80211_ATTR_MAC])
745 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 822 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
746 823
824 rtnl_lock();
825
747 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 826 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
748 if (err) 827 if (err)
749 return err; 828 goto unlock_rtnl;
750 829
751 if (!drv->ops->get_key) { 830 if (!drv->ops->get_key) {
752 err = -EOPNOTSUPP; 831 err = -EOPNOTSUPP;
@@ -774,10 +853,8 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
774 if (mac_addr) 853 if (mac_addr)
775 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr); 854 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
776 855
777 rtnl_lock();
778 err = drv->ops->get_key(&drv->wiphy, dev, key_idx, mac_addr, 856 err = drv->ops->get_key(&drv->wiphy, dev, key_idx, mac_addr,
779 &cookie, get_key_callback); 857 &cookie, get_key_callback);
780 rtnl_unlock();
781 858
782 if (err) 859 if (err)
783 goto out; 860 goto out;
@@ -795,6 +872,9 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
795 out: 872 out:
796 cfg80211_put_dev(drv); 873 cfg80211_put_dev(drv);
797 dev_put(dev); 874 dev_put(dev);
875 unlock_rtnl:
876 rtnl_unlock();
877
798 return err; 878 return err;
799} 879}
800 880
@@ -804,35 +884,50 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
804 int err; 884 int err;
805 struct net_device *dev; 885 struct net_device *dev;
806 u8 key_idx; 886 u8 key_idx;
887 int (*func)(struct wiphy *wiphy, struct net_device *netdev,
888 u8 key_index);
807 889
808 if (!info->attrs[NL80211_ATTR_KEY_IDX]) 890 if (!info->attrs[NL80211_ATTR_KEY_IDX])
809 return -EINVAL; 891 return -EINVAL;
810 892
811 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); 893 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
812 894
813 if (key_idx > 3) 895 if (info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT]) {
896 if (key_idx < 4 || key_idx > 5)
897 return -EINVAL;
898 } else if (key_idx > 3)
814 return -EINVAL; 899 return -EINVAL;
815 900
816 /* currently only support setting default key */ 901 /* currently only support setting default key */
817 if (!info->attrs[NL80211_ATTR_KEY_DEFAULT]) 902 if (!info->attrs[NL80211_ATTR_KEY_DEFAULT] &&
903 !info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT])
818 return -EINVAL; 904 return -EINVAL;
819 905
906 rtnl_lock();
907
820 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 908 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
821 if (err) 909 if (err)
822 return err; 910 goto unlock_rtnl;
911
912 if (info->attrs[NL80211_ATTR_KEY_DEFAULT])
913 func = drv->ops->set_default_key;
914 else
915 func = drv->ops->set_default_mgmt_key;
823 916
824 if (!drv->ops->set_default_key) { 917 if (!func) {
825 err = -EOPNOTSUPP; 918 err = -EOPNOTSUPP;
826 goto out; 919 goto out;
827 } 920 }
828 921
829 rtnl_lock(); 922 err = func(&drv->wiphy, dev, key_idx);
830 err = drv->ops->set_default_key(&drv->wiphy, dev, key_idx);
831 rtnl_unlock();
832 923
833 out: 924 out:
834 cfg80211_put_dev(drv); 925 cfg80211_put_dev(drv);
835 dev_put(dev); 926 dev_put(dev);
927
928 unlock_rtnl:
929 rtnl_unlock();
930
836 return err; 931 return err;
837} 932}
838 933
@@ -863,7 +958,7 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
863 if (info->attrs[NL80211_ATTR_MAC]) 958 if (info->attrs[NL80211_ATTR_MAC])
864 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 959 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
865 960
866 if (key_idx > 3) 961 if (key_idx > 5)
867 return -EINVAL; 962 return -EINVAL;
868 963
869 /* 964 /*
@@ -894,26 +989,33 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
894 if (params.key_len != 13) 989 if (params.key_len != 13)
895 return -EINVAL; 990 return -EINVAL;
896 break; 991 break;
992 case WLAN_CIPHER_SUITE_AES_CMAC:
993 if (params.key_len != 16)
994 return -EINVAL;
995 break;
897 default: 996 default:
898 return -EINVAL; 997 return -EINVAL;
899 } 998 }
900 999
1000 rtnl_lock();
1001
901 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 1002 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
902 if (err) 1003 if (err)
903 return err; 1004 goto unlock_rtnl;
904 1005
905 if (!drv->ops->add_key) { 1006 if (!drv->ops->add_key) {
906 err = -EOPNOTSUPP; 1007 err = -EOPNOTSUPP;
907 goto out; 1008 goto out;
908 } 1009 }
909 1010
910 rtnl_lock();
911 err = drv->ops->add_key(&drv->wiphy, dev, key_idx, mac_addr, &params); 1011 err = drv->ops->add_key(&drv->wiphy, dev, key_idx, mac_addr, &params);
912 rtnl_unlock();
913 1012
914 out: 1013 out:
915 cfg80211_put_dev(drv); 1014 cfg80211_put_dev(drv);
916 dev_put(dev); 1015 dev_put(dev);
1016 unlock_rtnl:
1017 rtnl_unlock();
1018
917 return err; 1019 return err;
918} 1020}
919 1021
@@ -928,28 +1030,32 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
928 if (info->attrs[NL80211_ATTR_KEY_IDX]) 1030 if (info->attrs[NL80211_ATTR_KEY_IDX])
929 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); 1031 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
930 1032
931 if (key_idx > 3) 1033 if (key_idx > 5)
932 return -EINVAL; 1034 return -EINVAL;
933 1035
934 if (info->attrs[NL80211_ATTR_MAC]) 1036 if (info->attrs[NL80211_ATTR_MAC])
935 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 1037 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
936 1038
1039 rtnl_lock();
1040
937 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 1041 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
938 if (err) 1042 if (err)
939 return err; 1043 goto unlock_rtnl;
940 1044
941 if (!drv->ops->del_key) { 1045 if (!drv->ops->del_key) {
942 err = -EOPNOTSUPP; 1046 err = -EOPNOTSUPP;
943 goto out; 1047 goto out;
944 } 1048 }
945 1049
946 rtnl_lock();
947 err = drv->ops->del_key(&drv->wiphy, dev, key_idx, mac_addr); 1050 err = drv->ops->del_key(&drv->wiphy, dev, key_idx, mac_addr);
948 rtnl_unlock();
949 1051
950 out: 1052 out:
951 cfg80211_put_dev(drv); 1053 cfg80211_put_dev(drv);
952 dev_put(dev); 1054 dev_put(dev);
1055
1056 unlock_rtnl:
1057 rtnl_unlock();
1058
953 return err; 1059 return err;
954} 1060}
955 1061
@@ -963,9 +1069,16 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
963 struct beacon_parameters params; 1069 struct beacon_parameters params;
964 int haveinfo = 0; 1070 int haveinfo = 0;
965 1071
1072 rtnl_lock();
1073
966 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 1074 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
967 if (err) 1075 if (err)
968 return err; 1076 goto unlock_rtnl;
1077
1078 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) {
1079 err = -EOPNOTSUPP;
1080 goto out;
1081 }
969 1082
970 switch (info->genlhdr->cmd) { 1083 switch (info->genlhdr->cmd) {
971 case NL80211_CMD_NEW_BEACON: 1084 case NL80211_CMD_NEW_BEACON:
@@ -1026,13 +1139,14 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
1026 goto out; 1139 goto out;
1027 } 1140 }
1028 1141
1029 rtnl_lock();
1030 err = call(&drv->wiphy, dev, &params); 1142 err = call(&drv->wiphy, dev, &params);
1031 rtnl_unlock();
1032 1143
1033 out: 1144 out:
1034 cfg80211_put_dev(drv); 1145 cfg80211_put_dev(drv);
1035 dev_put(dev); 1146 dev_put(dev);
1147 unlock_rtnl:
1148 rtnl_unlock();
1149
1036 return err; 1150 return err;
1037} 1151}
1038 1152
@@ -1042,22 +1156,29 @@ static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info)
1042 int err; 1156 int err;
1043 struct net_device *dev; 1157 struct net_device *dev;
1044 1158
1159 rtnl_lock();
1160
1045 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 1161 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1046 if (err) 1162 if (err)
1047 return err; 1163 goto unlock_rtnl;
1048 1164
1049 if (!drv->ops->del_beacon) { 1165 if (!drv->ops->del_beacon) {
1050 err = -EOPNOTSUPP; 1166 err = -EOPNOTSUPP;
1051 goto out; 1167 goto out;
1052 } 1168 }
1053 1169
1054 rtnl_lock(); 1170 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) {
1171 err = -EOPNOTSUPP;
1172 goto out;
1173 }
1055 err = drv->ops->del_beacon(&drv->wiphy, dev); 1174 err = drv->ops->del_beacon(&drv->wiphy, dev);
1056 rtnl_unlock();
1057 1175
1058 out: 1176 out:
1059 cfg80211_put_dev(drv); 1177 cfg80211_put_dev(drv);
1060 dev_put(dev); 1178 dev_put(dev);
1179 unlock_rtnl:
1180 rtnl_unlock();
1181
1061 return err; 1182 return err;
1062} 1183}
1063 1184
@@ -1182,6 +1303,12 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
1182 1303
1183 nla_nest_end(msg, txrate); 1304 nla_nest_end(msg, txrate);
1184 } 1305 }
1306 if (sinfo->filled & STATION_INFO_RX_PACKETS)
1307 NLA_PUT_U32(msg, NL80211_STA_INFO_RX_PACKETS,
1308 sinfo->rx_packets);
1309 if (sinfo->filled & STATION_INFO_TX_PACKETS)
1310 NLA_PUT_U32(msg, NL80211_STA_INFO_TX_PACKETS,
1311 sinfo->tx_packets);
1185 nla_nest_end(msg, sinfoattr); 1312 nla_nest_end(msg, sinfoattr);
1186 1313
1187 return genlmsg_end(msg, hdr); 1314 return genlmsg_end(msg, hdr);
@@ -1217,30 +1344,32 @@ static int nl80211_dump_station(struct sk_buff *skb,
1217 return -EINVAL; 1344 return -EINVAL;
1218 } 1345 }
1219 1346
1220 netdev = dev_get_by_index(&init_net, ifidx); 1347 rtnl_lock();
1221 if (!netdev) 1348
1222 return -ENODEV; 1349 netdev = __dev_get_by_index(&init_net, ifidx);
1350 if (!netdev) {
1351 err = -ENODEV;
1352 goto out_rtnl;
1353 }
1223 1354
1224 dev = cfg80211_get_dev_from_ifindex(ifidx); 1355 dev = cfg80211_get_dev_from_ifindex(ifidx);
1225 if (IS_ERR(dev)) { 1356 if (IS_ERR(dev)) {
1226 err = PTR_ERR(dev); 1357 err = PTR_ERR(dev);
1227 goto out_put_netdev; 1358 goto out_rtnl;
1228 } 1359 }
1229 1360
1230 if (!dev->ops->dump_station) { 1361 if (!dev->ops->dump_station) {
1231 err = -ENOSYS; 1362 err = -EOPNOTSUPP;
1232 goto out_err; 1363 goto out_err;
1233 } 1364 }
1234 1365
1235 rtnl_lock();
1236
1237 while (1) { 1366 while (1) {
1238 err = dev->ops->dump_station(&dev->wiphy, netdev, sta_idx, 1367 err = dev->ops->dump_station(&dev->wiphy, netdev, sta_idx,
1239 mac_addr, &sinfo); 1368 mac_addr, &sinfo);
1240 if (err == -ENOENT) 1369 if (err == -ENOENT)
1241 break; 1370 break;
1242 if (err) 1371 if (err)
1243 goto out_err_rtnl; 1372 goto out_err;
1244 1373
1245 if (nl80211_send_station(skb, 1374 if (nl80211_send_station(skb,
1246 NETLINK_CB(cb->skb).pid, 1375 NETLINK_CB(cb->skb).pid,
@@ -1256,12 +1385,10 @@ static int nl80211_dump_station(struct sk_buff *skb,
1256 out: 1385 out:
1257 cb->args[1] = sta_idx; 1386 cb->args[1] = sta_idx;
1258 err = skb->len; 1387 err = skb->len;
1259 out_err_rtnl:
1260 rtnl_unlock();
1261 out_err: 1388 out_err:
1262 cfg80211_put_dev(dev); 1389 cfg80211_put_dev(dev);
1263 out_put_netdev: 1390 out_rtnl:
1264 dev_put(netdev); 1391 rtnl_unlock();
1265 1392
1266 return err; 1393 return err;
1267} 1394}
@@ -1282,19 +1409,18 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
1282 1409
1283 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 1410 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1284 1411
1412 rtnl_lock();
1413
1285 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 1414 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1286 if (err) 1415 if (err)
1287 return err; 1416 goto out_rtnl;
1288 1417
1289 if (!drv->ops->get_station) { 1418 if (!drv->ops->get_station) {
1290 err = -EOPNOTSUPP; 1419 err = -EOPNOTSUPP;
1291 goto out; 1420 goto out;
1292 } 1421 }
1293 1422
1294 rtnl_lock();
1295 err = drv->ops->get_station(&drv->wiphy, dev, mac_addr, &sinfo); 1423 err = drv->ops->get_station(&drv->wiphy, dev, mac_addr, &sinfo);
1296 rtnl_unlock();
1297
1298 if (err) 1424 if (err)
1299 goto out; 1425 goto out;
1300 1426
@@ -1311,10 +1437,12 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
1311 1437
1312 out_free: 1438 out_free:
1313 nlmsg_free(msg); 1439 nlmsg_free(msg);
1314
1315 out: 1440 out:
1316 cfg80211_put_dev(drv); 1441 cfg80211_put_dev(drv);
1317 dev_put(dev); 1442 dev_put(dev);
1443 out_rtnl:
1444 rtnl_unlock();
1445
1318 return err; 1446 return err;
1319} 1447}
1320 1448
@@ -1382,9 +1510,11 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
1382 params.plink_action = 1510 params.plink_action =
1383 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); 1511 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
1384 1512
1513 rtnl_lock();
1514
1385 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 1515 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1386 if (err) 1516 if (err)
1387 return err; 1517 goto out_rtnl;
1388 1518
1389 err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, &params.vlan); 1519 err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, &params.vlan);
1390 if (err) 1520 if (err)
@@ -1395,15 +1525,16 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
1395 goto out; 1525 goto out;
1396 } 1526 }
1397 1527
1398 rtnl_lock();
1399 err = drv->ops->change_station(&drv->wiphy, dev, mac_addr, &params); 1528 err = drv->ops->change_station(&drv->wiphy, dev, mac_addr, &params);
1400 rtnl_unlock();
1401 1529
1402 out: 1530 out:
1403 if (params.vlan) 1531 if (params.vlan)
1404 dev_put(params.vlan); 1532 dev_put(params.vlan);
1405 cfg80211_put_dev(drv); 1533 cfg80211_put_dev(drv);
1406 dev_put(dev); 1534 dev_put(dev);
1535 out_rtnl:
1536 rtnl_unlock();
1537
1407 return err; 1538 return err;
1408} 1539}
1409 1540
@@ -1445,9 +1576,11 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
1445 &params.station_flags)) 1576 &params.station_flags))
1446 return -EINVAL; 1577 return -EINVAL;
1447 1578
1579 rtnl_lock();
1580
1448 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 1581 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1449 if (err) 1582 if (err)
1450 return err; 1583 goto out_rtnl;
1451 1584
1452 err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, &params.vlan); 1585 err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, &params.vlan);
1453 if (err) 1586 if (err)
@@ -1458,15 +1591,21 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
1458 goto out; 1591 goto out;
1459 } 1592 }
1460 1593
1461 rtnl_lock(); 1594 if (!netif_running(dev)) {
1595 err = -ENETDOWN;
1596 goto out;
1597 }
1598
1462 err = drv->ops->add_station(&drv->wiphy, dev, mac_addr, &params); 1599 err = drv->ops->add_station(&drv->wiphy, dev, mac_addr, &params);
1463 rtnl_unlock();
1464 1600
1465 out: 1601 out:
1466 if (params.vlan) 1602 if (params.vlan)
1467 dev_put(params.vlan); 1603 dev_put(params.vlan);
1468 cfg80211_put_dev(drv); 1604 cfg80211_put_dev(drv);
1469 dev_put(dev); 1605 dev_put(dev);
1606 out_rtnl:
1607 rtnl_unlock();
1608
1470 return err; 1609 return err;
1471} 1610}
1472 1611
@@ -1480,22 +1619,25 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
1480 if (info->attrs[NL80211_ATTR_MAC]) 1619 if (info->attrs[NL80211_ATTR_MAC])
1481 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 1620 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1482 1621
1622 rtnl_lock();
1623
1483 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 1624 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1484 if (err) 1625 if (err)
1485 return err; 1626 goto out_rtnl;
1486 1627
1487 if (!drv->ops->del_station) { 1628 if (!drv->ops->del_station) {
1488 err = -EOPNOTSUPP; 1629 err = -EOPNOTSUPP;
1489 goto out; 1630 goto out;
1490 } 1631 }
1491 1632
1492 rtnl_lock();
1493 err = drv->ops->del_station(&drv->wiphy, dev, mac_addr); 1633 err = drv->ops->del_station(&drv->wiphy, dev, mac_addr);
1494 rtnl_unlock();
1495 1634
1496 out: 1635 out:
1497 cfg80211_put_dev(drv); 1636 cfg80211_put_dev(drv);
1498 dev_put(dev); 1637 dev_put(dev);
1638 out_rtnl:
1639 rtnl_unlock();
1640
1499 return err; 1641 return err;
1500} 1642}
1501 1643
@@ -1576,22 +1718,29 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
1576 return -EINVAL; 1718 return -EINVAL;
1577 } 1719 }
1578 1720
1579 netdev = dev_get_by_index(&init_net, ifidx); 1721 rtnl_lock();
1580 if (!netdev) 1722
1581 return -ENODEV; 1723 netdev = __dev_get_by_index(&init_net, ifidx);
1724 if (!netdev) {
1725 err = -ENODEV;
1726 goto out_rtnl;
1727 }
1582 1728
1583 dev = cfg80211_get_dev_from_ifindex(ifidx); 1729 dev = cfg80211_get_dev_from_ifindex(ifidx);
1584 if (IS_ERR(dev)) { 1730 if (IS_ERR(dev)) {
1585 err = PTR_ERR(dev); 1731 err = PTR_ERR(dev);
1586 goto out_put_netdev; 1732 goto out_rtnl;
1587 } 1733 }
1588 1734
1589 if (!dev->ops->dump_mpath) { 1735 if (!dev->ops->dump_mpath) {
1590 err = -ENOSYS; 1736 err = -EOPNOTSUPP;
1591 goto out_err; 1737 goto out_err;
1592 } 1738 }
1593 1739
1594 rtnl_lock(); 1740 if (netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) {
1741 err = -EOPNOTSUPP;
1742 goto out;
1743 }
1595 1744
1596 while (1) { 1745 while (1) {
1597 err = dev->ops->dump_mpath(&dev->wiphy, netdev, path_idx, 1746 err = dev->ops->dump_mpath(&dev->wiphy, netdev, path_idx,
@@ -1599,7 +1748,7 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
1599 if (err == -ENOENT) 1748 if (err == -ENOENT)
1600 break; 1749 break;
1601 if (err) 1750 if (err)
1602 goto out_err_rtnl; 1751 goto out_err;
1603 1752
1604 if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).pid, 1753 if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).pid,
1605 cb->nlh->nlmsg_seq, NLM_F_MULTI, 1754 cb->nlh->nlmsg_seq, NLM_F_MULTI,
@@ -1614,12 +1763,10 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
1614 out: 1763 out:
1615 cb->args[1] = path_idx; 1764 cb->args[1] = path_idx;
1616 err = skb->len; 1765 err = skb->len;
1617 out_err_rtnl:
1618 rtnl_unlock();
1619 out_err: 1766 out_err:
1620 cfg80211_put_dev(dev); 1767 cfg80211_put_dev(dev);
1621 out_put_netdev: 1768 out_rtnl:
1622 dev_put(netdev); 1769 rtnl_unlock();
1623 1770
1624 return err; 1771 return err;
1625} 1772}
@@ -1641,19 +1788,23 @@ static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
1641 1788
1642 dst = nla_data(info->attrs[NL80211_ATTR_MAC]); 1789 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
1643 1790
1791 rtnl_lock();
1792
1644 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 1793 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1645 if (err) 1794 if (err)
1646 return err; 1795 goto out_rtnl;
1647 1796
1648 if (!drv->ops->get_mpath) { 1797 if (!drv->ops->get_mpath) {
1649 err = -EOPNOTSUPP; 1798 err = -EOPNOTSUPP;
1650 goto out; 1799 goto out;
1651 } 1800 }
1652 1801
1653 rtnl_lock(); 1802 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) {
1654 err = drv->ops->get_mpath(&drv->wiphy, dev, dst, next_hop, &pinfo); 1803 err = -EOPNOTSUPP;
1655 rtnl_unlock(); 1804 goto out;
1805 }
1656 1806
1807 err = drv->ops->get_mpath(&drv->wiphy, dev, dst, next_hop, &pinfo);
1657 if (err) 1808 if (err)
1658 goto out; 1809 goto out;
1659 1810
@@ -1670,10 +1821,12 @@ static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
1670 1821
1671 out_free: 1822 out_free:
1672 nlmsg_free(msg); 1823 nlmsg_free(msg);
1673
1674 out: 1824 out:
1675 cfg80211_put_dev(drv); 1825 cfg80211_put_dev(drv);
1676 dev_put(dev); 1826 dev_put(dev);
1827 out_rtnl:
1828 rtnl_unlock();
1829
1677 return err; 1830 return err;
1678} 1831}
1679 1832
@@ -1694,22 +1847,35 @@ static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
1694 dst = nla_data(info->attrs[NL80211_ATTR_MAC]); 1847 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
1695 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]); 1848 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
1696 1849
1850 rtnl_lock();
1851
1697 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 1852 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1698 if (err) 1853 if (err)
1699 return err; 1854 goto out_rtnl;
1700 1855
1701 if (!drv->ops->change_mpath) { 1856 if (!drv->ops->change_mpath) {
1702 err = -EOPNOTSUPP; 1857 err = -EOPNOTSUPP;
1703 goto out; 1858 goto out;
1704 } 1859 }
1705 1860
1706 rtnl_lock(); 1861 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) {
1862 err = -EOPNOTSUPP;
1863 goto out;
1864 }
1865
1866 if (!netif_running(dev)) {
1867 err = -ENETDOWN;
1868 goto out;
1869 }
1870
1707 err = drv->ops->change_mpath(&drv->wiphy, dev, dst, next_hop); 1871 err = drv->ops->change_mpath(&drv->wiphy, dev, dst, next_hop);
1708 rtnl_unlock();
1709 1872
1710 out: 1873 out:
1711 cfg80211_put_dev(drv); 1874 cfg80211_put_dev(drv);
1712 dev_put(dev); 1875 dev_put(dev);
1876 out_rtnl:
1877 rtnl_unlock();
1878
1713 return err; 1879 return err;
1714} 1880}
1715static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info) 1881static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
@@ -1729,22 +1895,35 @@ static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
1729 dst = nla_data(info->attrs[NL80211_ATTR_MAC]); 1895 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
1730 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]); 1896 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
1731 1897
1898 rtnl_lock();
1899
1732 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 1900 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1733 if (err) 1901 if (err)
1734 return err; 1902 goto out_rtnl;
1735 1903
1736 if (!drv->ops->add_mpath) { 1904 if (!drv->ops->add_mpath) {
1737 err = -EOPNOTSUPP; 1905 err = -EOPNOTSUPP;
1738 goto out; 1906 goto out;
1739 } 1907 }
1740 1908
1741 rtnl_lock(); 1909 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) {
1910 err = -EOPNOTSUPP;
1911 goto out;
1912 }
1913
1914 if (!netif_running(dev)) {
1915 err = -ENETDOWN;
1916 goto out;
1917 }
1918
1742 err = drv->ops->add_mpath(&drv->wiphy, dev, dst, next_hop); 1919 err = drv->ops->add_mpath(&drv->wiphy, dev, dst, next_hop);
1743 rtnl_unlock();
1744 1920
1745 out: 1921 out:
1746 cfg80211_put_dev(drv); 1922 cfg80211_put_dev(drv);
1747 dev_put(dev); 1923 dev_put(dev);
1924 out_rtnl:
1925 rtnl_unlock();
1926
1748 return err; 1927 return err;
1749} 1928}
1750 1929
@@ -1758,22 +1937,25 @@ static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
1758 if (info->attrs[NL80211_ATTR_MAC]) 1937 if (info->attrs[NL80211_ATTR_MAC])
1759 dst = nla_data(info->attrs[NL80211_ATTR_MAC]); 1938 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
1760 1939
1940 rtnl_lock();
1941
1761 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 1942 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1762 if (err) 1943 if (err)
1763 return err; 1944 goto out_rtnl;
1764 1945
1765 if (!drv->ops->del_mpath) { 1946 if (!drv->ops->del_mpath) {
1766 err = -EOPNOTSUPP; 1947 err = -EOPNOTSUPP;
1767 goto out; 1948 goto out;
1768 } 1949 }
1769 1950
1770 rtnl_lock();
1771 err = drv->ops->del_mpath(&drv->wiphy, dev, dst); 1951 err = drv->ops->del_mpath(&drv->wiphy, dev, dst);
1772 rtnl_unlock();
1773 1952
1774 out: 1953 out:
1775 cfg80211_put_dev(drv); 1954 cfg80211_put_dev(drv);
1776 dev_put(dev); 1955 dev_put(dev);
1956 out_rtnl:
1957 rtnl_unlock();
1958
1777 return err; 1959 return err;
1778} 1960}
1779 1961
@@ -1806,22 +1988,30 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
1806 nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); 1988 nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
1807 } 1989 }
1808 1990
1991 rtnl_lock();
1992
1809 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 1993 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1810 if (err) 1994 if (err)
1811 return err; 1995 goto out_rtnl;
1812 1996
1813 if (!drv->ops->change_bss) { 1997 if (!drv->ops->change_bss) {
1814 err = -EOPNOTSUPP; 1998 err = -EOPNOTSUPP;
1815 goto out; 1999 goto out;
1816 } 2000 }
1817 2001
1818 rtnl_lock(); 2002 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) {
2003 err = -EOPNOTSUPP;
2004 goto out;
2005 }
2006
1819 err = drv->ops->change_bss(&drv->wiphy, dev, &params); 2007 err = drv->ops->change_bss(&drv->wiphy, dev, &params);
1820 rtnl_unlock();
1821 2008
1822 out: 2009 out:
1823 cfg80211_put_dev(drv); 2010 cfg80211_put_dev(drv);
1824 dev_put(dev); 2011 dev_put(dev);
2012 out_rtnl:
2013 rtnl_unlock();
2014
1825 return err; 2015 return err;
1826} 2016}
1827 2017
@@ -1876,6 +2066,19 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
1876 int r; 2066 int r;
1877 char *data = NULL; 2067 char *data = NULL;
1878 2068
2069 /*
2070 * You should only get this when cfg80211 hasn't yet initialized
2071 * completely when built-in to the kernel right between the time
2072 * window between nl80211_init() and regulatory_init(), if that is
2073 * even possible.
2074 */
2075 mutex_lock(&cfg80211_mutex);
2076 if (unlikely(!cfg80211_regdomain)) {
2077 mutex_unlock(&cfg80211_mutex);
2078 return -EINPROGRESS;
2079 }
2080 mutex_unlock(&cfg80211_mutex);
2081
1879 if (!info->attrs[NL80211_ATTR_REG_ALPHA2]) 2082 if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
1880 return -EINVAL; 2083 return -EINVAL;
1881 2084
@@ -1886,9 +2089,9 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
1886 if (is_world_regdom(data)) 2089 if (is_world_regdom(data))
1887 return -EINVAL; 2090 return -EINVAL;
1888#endif 2091#endif
1889 mutex_lock(&cfg80211_drv_mutex); 2092
1890 r = __regulatory_hint(NULL, REGDOM_SET_BY_USER, data, 0, ENVIRON_ANY); 2093 r = regulatory_hint_user(data);
1891 mutex_unlock(&cfg80211_drv_mutex); 2094
1892 return r; 2095 return r;
1893} 2096}
1894 2097
@@ -1903,15 +2106,20 @@ static int nl80211_get_mesh_params(struct sk_buff *skb,
1903 struct nlattr *pinfoattr; 2106 struct nlattr *pinfoattr;
1904 struct sk_buff *msg; 2107 struct sk_buff *msg;
1905 2108
2109 rtnl_lock();
2110
1906 /* Look up our device */ 2111 /* Look up our device */
1907 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 2112 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1908 if (err) 2113 if (err)
1909 return err; 2114 goto out_rtnl;
2115
2116 if (!drv->ops->get_mesh_params) {
2117 err = -EOPNOTSUPP;
2118 goto out;
2119 }
1910 2120
1911 /* Get the mesh params */ 2121 /* Get the mesh params */
1912 rtnl_lock();
1913 err = drv->ops->get_mesh_params(&drv->wiphy, dev, &cur_params); 2122 err = drv->ops->get_mesh_params(&drv->wiphy, dev, &cur_params);
1914 rtnl_unlock();
1915 if (err) 2123 if (err)
1916 goto out; 2124 goto out;
1917 2125
@@ -1960,13 +2168,16 @@ static int nl80211_get_mesh_params(struct sk_buff *skb,
1960 err = genlmsg_unicast(msg, info->snd_pid); 2168 err = genlmsg_unicast(msg, info->snd_pid);
1961 goto out; 2169 goto out;
1962 2170
1963nla_put_failure: 2171 nla_put_failure:
1964 genlmsg_cancel(msg, hdr); 2172 genlmsg_cancel(msg, hdr);
1965 err = -EMSGSIZE; 2173 err = -EMSGSIZE;
1966out: 2174 out:
1967 /* Cleanup */ 2175 /* Cleanup */
1968 cfg80211_put_dev(drv); 2176 cfg80211_put_dev(drv);
1969 dev_put(dev); 2177 dev_put(dev);
2178 out_rtnl:
2179 rtnl_unlock();
2180
1970 return err; 2181 return err;
1971} 2182}
1972 2183
@@ -2013,9 +2224,16 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
2013 parent_attr, nl80211_meshconf_params_policy)) 2224 parent_attr, nl80211_meshconf_params_policy))
2014 return -EINVAL; 2225 return -EINVAL;
2015 2226
2227 rtnl_lock();
2228
2016 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 2229 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
2017 if (err) 2230 if (err)
2018 return err; 2231 goto out_rtnl;
2232
2233 if (!drv->ops->set_mesh_params) {
2234 err = -EOPNOTSUPP;
2235 goto out;
2236 }
2019 2237
2020 /* This makes sure that there aren't more than 32 mesh config 2238 /* This makes sure that there aren't more than 32 mesh config
2021 * parameters (otherwise our bitfield scheme would not work.) */ 2239 * parameters (otherwise our bitfield scheme would not work.) */
@@ -2057,18 +2275,95 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
2057 nla_get_u16); 2275 nla_get_u16);
2058 2276
2059 /* Apply changes */ 2277 /* Apply changes */
2060 rtnl_lock();
2061 err = drv->ops->set_mesh_params(&drv->wiphy, dev, &cfg, mask); 2278 err = drv->ops->set_mesh_params(&drv->wiphy, dev, &cfg, mask);
2062 rtnl_unlock();
2063 2279
2280 out:
2064 /* cleanup */ 2281 /* cleanup */
2065 cfg80211_put_dev(drv); 2282 cfg80211_put_dev(drv);
2066 dev_put(dev); 2283 dev_put(dev);
2284 out_rtnl:
2285 rtnl_unlock();
2286
2067 return err; 2287 return err;
2068} 2288}
2069 2289
2070#undef FILL_IN_MESH_PARAM_IF_SET 2290#undef FILL_IN_MESH_PARAM_IF_SET
2071 2291
2292static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
2293{
2294 struct sk_buff *msg;
2295 void *hdr = NULL;
2296 struct nlattr *nl_reg_rules;
2297 unsigned int i;
2298 int err = -EINVAL;
2299
2300 mutex_lock(&cfg80211_mutex);
2301
2302 if (!cfg80211_regdomain)
2303 goto out;
2304
2305 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
2306 if (!msg) {
2307 err = -ENOBUFS;
2308 goto out;
2309 }
2310
2311 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
2312 NL80211_CMD_GET_REG);
2313 if (!hdr)
2314 goto nla_put_failure;
2315
2316 NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2,
2317 cfg80211_regdomain->alpha2);
2318
2319 nl_reg_rules = nla_nest_start(msg, NL80211_ATTR_REG_RULES);
2320 if (!nl_reg_rules)
2321 goto nla_put_failure;
2322
2323 for (i = 0; i < cfg80211_regdomain->n_reg_rules; i++) {
2324 struct nlattr *nl_reg_rule;
2325 const struct ieee80211_reg_rule *reg_rule;
2326 const struct ieee80211_freq_range *freq_range;
2327 const struct ieee80211_power_rule *power_rule;
2328
2329 reg_rule = &cfg80211_regdomain->reg_rules[i];
2330 freq_range = &reg_rule->freq_range;
2331 power_rule = &reg_rule->power_rule;
2332
2333 nl_reg_rule = nla_nest_start(msg, i);
2334 if (!nl_reg_rule)
2335 goto nla_put_failure;
2336
2337 NLA_PUT_U32(msg, NL80211_ATTR_REG_RULE_FLAGS,
2338 reg_rule->flags);
2339 NLA_PUT_U32(msg, NL80211_ATTR_FREQ_RANGE_START,
2340 freq_range->start_freq_khz);
2341 NLA_PUT_U32(msg, NL80211_ATTR_FREQ_RANGE_END,
2342 freq_range->end_freq_khz);
2343 NLA_PUT_U32(msg, NL80211_ATTR_FREQ_RANGE_MAX_BW,
2344 freq_range->max_bandwidth_khz);
2345 NLA_PUT_U32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN,
2346 power_rule->max_antenna_gain);
2347 NLA_PUT_U32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP,
2348 power_rule->max_eirp);
2349
2350 nla_nest_end(msg, nl_reg_rule);
2351 }
2352
2353 nla_nest_end(msg, nl_reg_rules);
2354
2355 genlmsg_end(msg, hdr);
2356 err = genlmsg_unicast(msg, info->snd_pid);
2357 goto out;
2358
2359nla_put_failure:
2360 genlmsg_cancel(msg, hdr);
2361 err = -EMSGSIZE;
2362out:
2363 mutex_unlock(&cfg80211_mutex);
2364 return err;
2365}
2366
2072static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) 2367static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
2073{ 2368{
2074 struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1]; 2369 struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1];
@@ -2124,9 +2419,9 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
2124 2419
2125 BUG_ON(rule_idx != num_rules); 2420 BUG_ON(rule_idx != num_rules);
2126 2421
2127 mutex_lock(&cfg80211_drv_mutex); 2422 mutex_lock(&cfg80211_mutex);
2128 r = set_regdom(rd); 2423 r = set_regdom(rd);
2129 mutex_unlock(&cfg80211_drv_mutex); 2424 mutex_unlock(&cfg80211_mutex);
2130 return r; 2425 return r;
2131 2426
2132 bad_reg: 2427 bad_reg:
@@ -2134,6 +2429,553 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
2134 return -EINVAL; 2429 return -EINVAL;
2135} 2430}
2136 2431
2432static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
2433{
2434 struct cfg80211_registered_device *drv;
2435 struct net_device *dev;
2436 struct cfg80211_scan_request *request;
2437 struct cfg80211_ssid *ssid;
2438 struct ieee80211_channel *channel;
2439 struct nlattr *attr;
2440 struct wiphy *wiphy;
2441 int err, tmp, n_ssids = 0, n_channels = 0, i;
2442 enum ieee80211_band band;
2443 size_t ie_len;
2444
2445 rtnl_lock();
2446
2447 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
2448 if (err)
2449 goto out_rtnl;
2450
2451 wiphy = &drv->wiphy;
2452
2453 if (!drv->ops->scan) {
2454 err = -EOPNOTSUPP;
2455 goto out;
2456 }
2457
2458 if (!netif_running(dev)) {
2459 err = -ENETDOWN;
2460 goto out;
2461 }
2462
2463 if (drv->scan_req) {
2464 err = -EBUSY;
2465 goto out;
2466 }
2467
2468 if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
2469 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_FREQUENCIES], tmp)
2470 n_channels++;
2471 if (!n_channels) {
2472 err = -EINVAL;
2473 goto out;
2474 }
2475 } else {
2476 for (band = 0; band < IEEE80211_NUM_BANDS; band++)
2477 if (wiphy->bands[band])
2478 n_channels += wiphy->bands[band]->n_channels;
2479 }
2480
2481 if (info->attrs[NL80211_ATTR_SCAN_SSIDS])
2482 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp)
2483 n_ssids++;
2484
2485 if (n_ssids > wiphy->max_scan_ssids) {
2486 err = -EINVAL;
2487 goto out;
2488 }
2489
2490 if (info->attrs[NL80211_ATTR_IE])
2491 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
2492 else
2493 ie_len = 0;
2494
2495 request = kzalloc(sizeof(*request)
2496 + sizeof(*ssid) * n_ssids
2497 + sizeof(channel) * n_channels
2498 + ie_len, GFP_KERNEL);
2499 if (!request) {
2500 err = -ENOMEM;
2501 goto out;
2502 }
2503
2504 request->channels = (void *)((char *)request + sizeof(*request));
2505 request->n_channels = n_channels;
2506 if (n_ssids)
2507 request->ssids = (void *)(request->channels + n_channels);
2508 request->n_ssids = n_ssids;
2509 if (ie_len) {
2510 if (request->ssids)
2511 request->ie = (void *)(request->ssids + n_ssids);
2512 else
2513 request->ie = (void *)(request->channels + n_channels);
2514 }
2515
2516 if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
2517 /* user specified, bail out if channel not found */
2518 request->n_channels = n_channels;
2519 i = 0;
2520 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_FREQUENCIES], tmp) {
2521 request->channels[i] = ieee80211_get_channel(wiphy, nla_get_u32(attr));
2522 if (!request->channels[i]) {
2523 err = -EINVAL;
2524 goto out_free;
2525 }
2526 i++;
2527 }
2528 } else {
2529 /* all channels */
2530 i = 0;
2531 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
2532 int j;
2533 if (!wiphy->bands[band])
2534 continue;
2535 for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
2536 request->channels[i] = &wiphy->bands[band]->channels[j];
2537 i++;
2538 }
2539 }
2540 }
2541
2542 i = 0;
2543 if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) {
2544 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) {
2545 if (request->ssids[i].ssid_len > IEEE80211_MAX_SSID_LEN) {
2546 err = -EINVAL;
2547 goto out_free;
2548 }
2549 memcpy(request->ssids[i].ssid, nla_data(attr), nla_len(attr));
2550 request->ssids[i].ssid_len = nla_len(attr);
2551 i++;
2552 }
2553 }
2554
2555 if (info->attrs[NL80211_ATTR_IE]) {
2556 request->ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
2557 memcpy(request->ie, nla_data(info->attrs[NL80211_ATTR_IE]),
2558 request->ie_len);
2559 }
2560
2561 request->ifidx = dev->ifindex;
2562 request->wiphy = &drv->wiphy;
2563
2564 drv->scan_req = request;
2565 err = drv->ops->scan(&drv->wiphy, dev, request);
2566
2567 out_free:
2568 if (err) {
2569 drv->scan_req = NULL;
2570 kfree(request);
2571 }
2572 out:
2573 cfg80211_put_dev(drv);
2574 dev_put(dev);
2575 out_rtnl:
2576 rtnl_unlock();
2577
2578 return err;
2579}
2580
2581static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags,
2582 struct cfg80211_registered_device *rdev,
2583 struct net_device *dev,
2584 struct cfg80211_bss *res)
2585{
2586 void *hdr;
2587 struct nlattr *bss;
2588
2589 hdr = nl80211hdr_put(msg, pid, seq, flags,
2590 NL80211_CMD_NEW_SCAN_RESULTS);
2591 if (!hdr)
2592 return -1;
2593
2594 NLA_PUT_U32(msg, NL80211_ATTR_SCAN_GENERATION,
2595 rdev->bss_generation);
2596 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
2597
2598 bss = nla_nest_start(msg, NL80211_ATTR_BSS);
2599 if (!bss)
2600 goto nla_put_failure;
2601 if (!is_zero_ether_addr(res->bssid))
2602 NLA_PUT(msg, NL80211_BSS_BSSID, ETH_ALEN, res->bssid);
2603 if (res->information_elements && res->len_information_elements)
2604 NLA_PUT(msg, NL80211_BSS_INFORMATION_ELEMENTS,
2605 res->len_information_elements,
2606 res->information_elements);
2607 if (res->tsf)
2608 NLA_PUT_U64(msg, NL80211_BSS_TSF, res->tsf);
2609 if (res->beacon_interval)
2610 NLA_PUT_U16(msg, NL80211_BSS_BEACON_INTERVAL, res->beacon_interval);
2611 NLA_PUT_U16(msg, NL80211_BSS_CAPABILITY, res->capability);
2612 NLA_PUT_U32(msg, NL80211_BSS_FREQUENCY, res->channel->center_freq);
2613
2614 switch (rdev->wiphy.signal_type) {
2615 case CFG80211_SIGNAL_TYPE_MBM:
2616 NLA_PUT_U32(msg, NL80211_BSS_SIGNAL_MBM, res->signal);
2617 break;
2618 case CFG80211_SIGNAL_TYPE_UNSPEC:
2619 NLA_PUT_U8(msg, NL80211_BSS_SIGNAL_UNSPEC, res->signal);
2620 break;
2621 default:
2622 break;
2623 }
2624
2625 nla_nest_end(msg, bss);
2626
2627 return genlmsg_end(msg, hdr);
2628
2629 nla_put_failure:
2630 genlmsg_cancel(msg, hdr);
2631 return -EMSGSIZE;
2632}
2633
2634static int nl80211_dump_scan(struct sk_buff *skb,
2635 struct netlink_callback *cb)
2636{
2637 struct cfg80211_registered_device *dev;
2638 struct net_device *netdev;
2639 struct cfg80211_internal_bss *scan;
2640 int ifidx = cb->args[0];
2641 int start = cb->args[1], idx = 0;
2642 int err;
2643
2644 if (!ifidx) {
2645 err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
2646 nl80211_fam.attrbuf, nl80211_fam.maxattr,
2647 nl80211_policy);
2648 if (err)
2649 return err;
2650
2651 if (!nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX])
2652 return -EINVAL;
2653
2654 ifidx = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]);
2655 if (!ifidx)
2656 return -EINVAL;
2657 cb->args[0] = ifidx;
2658 }
2659
2660 netdev = dev_get_by_index(&init_net, ifidx);
2661 if (!netdev)
2662 return -ENODEV;
2663
2664 dev = cfg80211_get_dev_from_ifindex(ifidx);
2665 if (IS_ERR(dev)) {
2666 err = PTR_ERR(dev);
2667 goto out_put_netdev;
2668 }
2669
2670 spin_lock_bh(&dev->bss_lock);
2671 cfg80211_bss_expire(dev);
2672
2673 list_for_each_entry(scan, &dev->bss_list, list) {
2674 if (++idx <= start)
2675 continue;
2676 if (nl80211_send_bss(skb,
2677 NETLINK_CB(cb->skb).pid,
2678 cb->nlh->nlmsg_seq, NLM_F_MULTI,
2679 dev, netdev, &scan->pub) < 0) {
2680 idx--;
2681 goto out;
2682 }
2683 }
2684
2685 out:
2686 spin_unlock_bh(&dev->bss_lock);
2687
2688 cb->args[1] = idx;
2689 err = skb->len;
2690 cfg80211_put_dev(dev);
2691 out_put_netdev:
2692 dev_put(netdev);
2693
2694 return err;
2695}
2696
2697static bool nl80211_valid_auth_type(enum nl80211_auth_type auth_type)
2698{
2699 return auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM ||
2700 auth_type == NL80211_AUTHTYPE_SHARED_KEY ||
2701 auth_type == NL80211_AUTHTYPE_FT ||
2702 auth_type == NL80211_AUTHTYPE_NETWORK_EAP;
2703}
2704
2705static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
2706{
2707 struct cfg80211_registered_device *drv;
2708 struct net_device *dev;
2709 struct cfg80211_auth_request req;
2710 struct wiphy *wiphy;
2711 int err;
2712
2713 rtnl_lock();
2714
2715 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
2716 if (err)
2717 goto unlock_rtnl;
2718
2719 if (!drv->ops->auth) {
2720 err = -EOPNOTSUPP;
2721 goto out;
2722 }
2723
2724 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) {
2725 err = -EOPNOTSUPP;
2726 goto out;
2727 }
2728
2729 if (!netif_running(dev)) {
2730 err = -ENETDOWN;
2731 goto out;
2732 }
2733
2734 if (!info->attrs[NL80211_ATTR_MAC]) {
2735 err = -EINVAL;
2736 goto out;
2737 }
2738
2739 wiphy = &drv->wiphy;
2740 memset(&req, 0, sizeof(req));
2741
2742 req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
2743
2744 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
2745 req.chan = ieee80211_get_channel(
2746 wiphy,
2747 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
2748 if (!req.chan) {
2749 err = -EINVAL;
2750 goto out;
2751 }
2752 }
2753
2754 if (info->attrs[NL80211_ATTR_SSID]) {
2755 req.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
2756 req.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
2757 }
2758
2759 if (info->attrs[NL80211_ATTR_IE]) {
2760 req.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
2761 req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
2762 }
2763
2764 if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
2765 req.auth_type =
2766 nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
2767 if (!nl80211_valid_auth_type(req.auth_type)) {
2768 err = -EINVAL;
2769 goto out;
2770 }
2771 }
2772
2773 err = drv->ops->auth(&drv->wiphy, dev, &req);
2774
2775out:
2776 cfg80211_put_dev(drv);
2777 dev_put(dev);
2778unlock_rtnl:
2779 rtnl_unlock();
2780 return err;
2781}
2782
2783static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
2784{
2785 struct cfg80211_registered_device *drv;
2786 struct net_device *dev;
2787 struct cfg80211_assoc_request req;
2788 struct wiphy *wiphy;
2789 int err;
2790
2791 rtnl_lock();
2792
2793 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
2794 if (err)
2795 goto unlock_rtnl;
2796
2797 if (!drv->ops->assoc) {
2798 err = -EOPNOTSUPP;
2799 goto out;
2800 }
2801
2802 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) {
2803 err = -EOPNOTSUPP;
2804 goto out;
2805 }
2806
2807 if (!netif_running(dev)) {
2808 err = -ENETDOWN;
2809 goto out;
2810 }
2811
2812 if (!info->attrs[NL80211_ATTR_MAC] ||
2813 !info->attrs[NL80211_ATTR_SSID]) {
2814 err = -EINVAL;
2815 goto out;
2816 }
2817
2818 wiphy = &drv->wiphy;
2819 memset(&req, 0, sizeof(req));
2820
2821 req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
2822
2823 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
2824 req.chan = ieee80211_get_channel(
2825 wiphy,
2826 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
2827 if (!req.chan) {
2828 err = -EINVAL;
2829 goto out;
2830 }
2831 }
2832
2833 req.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
2834 req.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
2835
2836 if (info->attrs[NL80211_ATTR_IE]) {
2837 req.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
2838 req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
2839 }
2840
2841 err = drv->ops->assoc(&drv->wiphy, dev, &req);
2842
2843out:
2844 cfg80211_put_dev(drv);
2845 dev_put(dev);
2846unlock_rtnl:
2847 rtnl_unlock();
2848 return err;
2849}
2850
2851static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
2852{
2853 struct cfg80211_registered_device *drv;
2854 struct net_device *dev;
2855 struct cfg80211_deauth_request req;
2856 struct wiphy *wiphy;
2857 int err;
2858
2859 rtnl_lock();
2860
2861 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
2862 if (err)
2863 goto unlock_rtnl;
2864
2865 if (!drv->ops->deauth) {
2866 err = -EOPNOTSUPP;
2867 goto out;
2868 }
2869
2870 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) {
2871 err = -EOPNOTSUPP;
2872 goto out;
2873 }
2874
2875 if (!netif_running(dev)) {
2876 err = -ENETDOWN;
2877 goto out;
2878 }
2879
2880 if (!info->attrs[NL80211_ATTR_MAC]) {
2881 err = -EINVAL;
2882 goto out;
2883 }
2884
2885 wiphy = &drv->wiphy;
2886 memset(&req, 0, sizeof(req));
2887
2888 req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
2889
2890 if (info->attrs[NL80211_ATTR_REASON_CODE]) {
2891 req.reason_code =
2892 nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
2893 if (req.reason_code == 0) {
2894 /* Reason Code 0 is reserved */
2895 err = -EINVAL;
2896 goto out;
2897 }
2898 }
2899
2900 if (info->attrs[NL80211_ATTR_IE]) {
2901 req.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
2902 req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
2903 }
2904
2905 err = drv->ops->deauth(&drv->wiphy, dev, &req);
2906
2907out:
2908 cfg80211_put_dev(drv);
2909 dev_put(dev);
2910unlock_rtnl:
2911 rtnl_unlock();
2912 return err;
2913}
2914
2915static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
2916{
2917 struct cfg80211_registered_device *drv;
2918 struct net_device *dev;
2919 struct cfg80211_disassoc_request req;
2920 struct wiphy *wiphy;
2921 int err;
2922
2923 rtnl_lock();
2924
2925 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
2926 if (err)
2927 goto unlock_rtnl;
2928
2929 if (!drv->ops->disassoc) {
2930 err = -EOPNOTSUPP;
2931 goto out;
2932 }
2933
2934 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) {
2935 err = -EOPNOTSUPP;
2936 goto out;
2937 }
2938
2939 if (!netif_running(dev)) {
2940 err = -ENETDOWN;
2941 goto out;
2942 }
2943
2944 if (!info->attrs[NL80211_ATTR_MAC]) {
2945 err = -EINVAL;
2946 goto out;
2947 }
2948
2949 wiphy = &drv->wiphy;
2950 memset(&req, 0, sizeof(req));
2951
2952 req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
2953
2954 if (info->attrs[NL80211_ATTR_REASON_CODE]) {
2955 req.reason_code =
2956 nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
2957 if (req.reason_code == 0) {
2958 /* Reason Code 0 is reserved */
2959 err = -EINVAL;
2960 goto out;
2961 }
2962 }
2963
2964 if (info->attrs[NL80211_ATTR_IE]) {
2965 req.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
2966 req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
2967 }
2968
2969 err = drv->ops->disassoc(&drv->wiphy, dev, &req);
2970
2971out:
2972 cfg80211_put_dev(drv);
2973 dev_put(dev);
2974unlock_rtnl:
2975 rtnl_unlock();
2976 return err;
2977}
2978
2137static struct genl_ops nl80211_ops[] = { 2979static struct genl_ops nl80211_ops[] = {
2138 { 2980 {
2139 .cmd = NL80211_CMD_GET_WIPHY, 2981 .cmd = NL80211_CMD_GET_WIPHY,
@@ -2220,7 +3062,6 @@ static struct genl_ops nl80211_ops[] = {
2220 .doit = nl80211_get_station, 3062 .doit = nl80211_get_station,
2221 .dumpit = nl80211_dump_station, 3063 .dumpit = nl80211_dump_station,
2222 .policy = nl80211_policy, 3064 .policy = nl80211_policy,
2223 .flags = GENL_ADMIN_PERM,
2224 }, 3065 },
2225 { 3066 {
2226 .cmd = NL80211_CMD_SET_STATION, 3067 .cmd = NL80211_CMD_SET_STATION,
@@ -2272,6 +3113,12 @@ static struct genl_ops nl80211_ops[] = {
2272 .flags = GENL_ADMIN_PERM, 3113 .flags = GENL_ADMIN_PERM,
2273 }, 3114 },
2274 { 3115 {
3116 .cmd = NL80211_CMD_GET_REG,
3117 .doit = nl80211_get_reg,
3118 .policy = nl80211_policy,
3119 /* can be retrieved by unprivileged users */
3120 },
3121 {
2275 .cmd = NL80211_CMD_SET_REG, 3122 .cmd = NL80211_CMD_SET_REG,
2276 .doit = nl80211_set_reg, 3123 .doit = nl80211_set_reg,
2277 .policy = nl80211_policy, 3124 .policy = nl80211_policy,
@@ -2295,12 +3142,56 @@ static struct genl_ops nl80211_ops[] = {
2295 .policy = nl80211_policy, 3142 .policy = nl80211_policy,
2296 .flags = GENL_ADMIN_PERM, 3143 .flags = GENL_ADMIN_PERM,
2297 }, 3144 },
3145 {
3146 .cmd = NL80211_CMD_TRIGGER_SCAN,
3147 .doit = nl80211_trigger_scan,
3148 .policy = nl80211_policy,
3149 .flags = GENL_ADMIN_PERM,
3150 },
3151 {
3152 .cmd = NL80211_CMD_GET_SCAN,
3153 .policy = nl80211_policy,
3154 .dumpit = nl80211_dump_scan,
3155 },
3156 {
3157 .cmd = NL80211_CMD_AUTHENTICATE,
3158 .doit = nl80211_authenticate,
3159 .policy = nl80211_policy,
3160 .flags = GENL_ADMIN_PERM,
3161 },
3162 {
3163 .cmd = NL80211_CMD_ASSOCIATE,
3164 .doit = nl80211_associate,
3165 .policy = nl80211_policy,
3166 .flags = GENL_ADMIN_PERM,
3167 },
3168 {
3169 .cmd = NL80211_CMD_DEAUTHENTICATE,
3170 .doit = nl80211_deauthenticate,
3171 .policy = nl80211_policy,
3172 .flags = GENL_ADMIN_PERM,
3173 },
3174 {
3175 .cmd = NL80211_CMD_DISASSOCIATE,
3176 .doit = nl80211_disassociate,
3177 .policy = nl80211_policy,
3178 .flags = GENL_ADMIN_PERM,
3179 },
3180};
3181static struct genl_multicast_group nl80211_mlme_mcgrp = {
3182 .name = "mlme",
2298}; 3183};
2299 3184
2300/* multicast groups */ 3185/* multicast groups */
2301static struct genl_multicast_group nl80211_config_mcgrp = { 3186static struct genl_multicast_group nl80211_config_mcgrp = {
2302 .name = "config", 3187 .name = "config",
2303}; 3188};
3189static struct genl_multicast_group nl80211_scan_mcgrp = {
3190 .name = "scan",
3191};
3192static struct genl_multicast_group nl80211_regulatory_mcgrp = {
3193 .name = "regulatory",
3194};
2304 3195
2305/* notification functions */ 3196/* notification functions */
2306 3197
@@ -2320,6 +3211,186 @@ void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev)
2320 genlmsg_multicast(msg, 0, nl80211_config_mcgrp.id, GFP_KERNEL); 3211 genlmsg_multicast(msg, 0, nl80211_config_mcgrp.id, GFP_KERNEL);
2321} 3212}
2322 3213
3214static int nl80211_send_scan_donemsg(struct sk_buff *msg,
3215 struct cfg80211_registered_device *rdev,
3216 struct net_device *netdev,
3217 u32 pid, u32 seq, int flags,
3218 u32 cmd)
3219{
3220 void *hdr;
3221
3222 hdr = nl80211hdr_put(msg, pid, seq, flags, cmd);
3223 if (!hdr)
3224 return -1;
3225
3226 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
3227 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
3228
3229 /* XXX: we should probably bounce back the request? */
3230
3231 return genlmsg_end(msg, hdr);
3232
3233 nla_put_failure:
3234 genlmsg_cancel(msg, hdr);
3235 return -EMSGSIZE;
3236}
3237
3238void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
3239 struct net_device *netdev)
3240{
3241 struct sk_buff *msg;
3242
3243 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
3244 if (!msg)
3245 return;
3246
3247 if (nl80211_send_scan_donemsg(msg, rdev, netdev, 0, 0, 0,
3248 NL80211_CMD_NEW_SCAN_RESULTS) < 0) {
3249 nlmsg_free(msg);
3250 return;
3251 }
3252
3253 genlmsg_multicast(msg, 0, nl80211_scan_mcgrp.id, GFP_KERNEL);
3254}
3255
3256void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
3257 struct net_device *netdev)
3258{
3259 struct sk_buff *msg;
3260
3261 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
3262 if (!msg)
3263 return;
3264
3265 if (nl80211_send_scan_donemsg(msg, rdev, netdev, 0, 0, 0,
3266 NL80211_CMD_SCAN_ABORTED) < 0) {
3267 nlmsg_free(msg);
3268 return;
3269 }
3270
3271 genlmsg_multicast(msg, 0, nl80211_scan_mcgrp.id, GFP_KERNEL);
3272}
3273
3274/*
3275 * This can happen on global regulatory changes or device specific settings
3276 * based on custom world regulatory domains.
3277 */
3278void nl80211_send_reg_change_event(struct regulatory_request *request)
3279{
3280 struct sk_buff *msg;
3281 void *hdr;
3282
3283 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
3284 if (!msg)
3285 return;
3286
3287 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_REG_CHANGE);
3288 if (!hdr) {
3289 nlmsg_free(msg);
3290 return;
3291 }
3292
3293 /* Userspace can always count this one always being set */
3294 NLA_PUT_U8(msg, NL80211_ATTR_REG_INITIATOR, request->initiator);
3295
3296 if (request->alpha2[0] == '0' && request->alpha2[1] == '0')
3297 NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE,
3298 NL80211_REGDOM_TYPE_WORLD);
3299 else if (request->alpha2[0] == '9' && request->alpha2[1] == '9')
3300 NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE,
3301 NL80211_REGDOM_TYPE_CUSTOM_WORLD);
3302 else if ((request->alpha2[0] == '9' && request->alpha2[1] == '8') ||
3303 request->intersect)
3304 NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE,
3305 NL80211_REGDOM_TYPE_INTERSECTION);
3306 else {
3307 NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE,
3308 NL80211_REGDOM_TYPE_COUNTRY);
3309 NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, request->alpha2);
3310 }
3311
3312 if (wiphy_idx_valid(request->wiphy_idx))
3313 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, request->wiphy_idx);
3314
3315 if (genlmsg_end(msg, hdr) < 0) {
3316 nlmsg_free(msg);
3317 return;
3318 }
3319
3320 genlmsg_multicast(msg, 0, nl80211_regulatory_mcgrp.id, GFP_KERNEL);
3321
3322 return;
3323
3324nla_put_failure:
3325 genlmsg_cancel(msg, hdr);
3326 nlmsg_free(msg);
3327}
3328
3329static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev,
3330 struct net_device *netdev,
3331 const u8 *buf, size_t len,
3332 enum nl80211_commands cmd)
3333{
3334 struct sk_buff *msg;
3335 void *hdr;
3336
3337 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
3338 if (!msg)
3339 return;
3340
3341 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
3342 if (!hdr) {
3343 nlmsg_free(msg);
3344 return;
3345 }
3346
3347 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
3348 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
3349 NLA_PUT(msg, NL80211_ATTR_FRAME, len, buf);
3350
3351 if (genlmsg_end(msg, hdr) < 0) {
3352 nlmsg_free(msg);
3353 return;
3354 }
3355
3356 genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, GFP_KERNEL);
3357 return;
3358
3359 nla_put_failure:
3360 genlmsg_cancel(msg, hdr);
3361 nlmsg_free(msg);
3362}
3363
3364void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev,
3365 struct net_device *netdev, const u8 *buf, size_t len)
3366{
3367 nl80211_send_mlme_event(rdev, netdev, buf, len,
3368 NL80211_CMD_AUTHENTICATE);
3369}
3370
3371void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
3372 struct net_device *netdev, const u8 *buf,
3373 size_t len)
3374{
3375 nl80211_send_mlme_event(rdev, netdev, buf, len, NL80211_CMD_ASSOCIATE);
3376}
3377
3378void nl80211_send_rx_deauth(struct cfg80211_registered_device *rdev,
3379 struct net_device *netdev, const u8 *buf,
3380 size_t len)
3381{
3382 nl80211_send_mlme_event(rdev, netdev, buf, len,
3383 NL80211_CMD_DEAUTHENTICATE);
3384}
3385
3386void nl80211_send_rx_disassoc(struct cfg80211_registered_device *rdev,
3387 struct net_device *netdev, const u8 *buf,
3388 size_t len)
3389{
3390 nl80211_send_mlme_event(rdev, netdev, buf, len,
3391 NL80211_CMD_DISASSOCIATE);
3392}
3393
2323/* initialisation/exit functions */ 3394/* initialisation/exit functions */
2324 3395
2325int nl80211_init(void) 3396int nl80211_init(void)
@@ -2340,6 +3411,18 @@ int nl80211_init(void)
2340 if (err) 3411 if (err)
2341 goto err_out; 3412 goto err_out;
2342 3413
3414 err = genl_register_mc_group(&nl80211_fam, &nl80211_scan_mcgrp);
3415 if (err)
3416 goto err_out;
3417
3418 err = genl_register_mc_group(&nl80211_fam, &nl80211_regulatory_mcgrp);
3419 if (err)
3420 goto err_out;
3421
3422 err = genl_register_mc_group(&nl80211_fam, &nl80211_mlme_mcgrp);
3423 if (err)
3424 goto err_out;
3425
2343 return 0; 3426 return 0;
2344 err_out: 3427 err_out:
2345 genl_unregister_family(&nl80211_fam); 3428 genl_unregister_family(&nl80211_fam);
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h
index f3ea5c029aee..b77af4ab80be 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -3,22 +3,25 @@
3 3
4#include "core.h" 4#include "core.h"
5 5
6#ifdef CONFIG_NL80211
7extern int nl80211_init(void); 6extern int nl80211_init(void);
8extern void nl80211_exit(void); 7extern void nl80211_exit(void);
9extern void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev); 8extern void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev);
10#else 9extern void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
11static inline int nl80211_init(void) 10 struct net_device *netdev);
12{ 11extern void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
13 return 0; 12 struct net_device *netdev);
14} 13extern void nl80211_send_reg_change_event(struct regulatory_request *request);
15static inline void nl80211_exit(void) 14extern void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev,
16{ 15 struct net_device *netdev,
17} 16 const u8 *buf, size_t len);
18static inline void nl80211_notify_dev_rename( 17extern void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
19 struct cfg80211_registered_device *rdev) 18 struct net_device *netdev,
20{ 19 const u8 *buf, size_t len);
21} 20extern void nl80211_send_rx_deauth(struct cfg80211_registered_device *rdev,
22#endif /* CONFIG_NL80211 */ 21 struct net_device *netdev,
22 const u8 *buf, size_t len);
23extern void nl80211_send_rx_disassoc(struct cfg80211_registered_device *rdev,
24 struct net_device *netdev,
25 const u8 *buf, size_t len);
23 26
24#endif /* __NET_WIRELESS_NL80211_H */ 27#endif /* __NET_WIRELESS_NL80211_H */
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index bd0a16c3de5e..6327e1617acb 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -41,38 +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 44#include "nl80211.h"
45/**
46 * struct regulatory_request - receipt of last regulatory request
47 *
48 * @wiphy: this is set if this request's initiator is
49 * %REGDOM_SET_BY_COUNTRY_IE or %REGDOM_SET_BY_DRIVER. This
50 * can be used by the wireless core to deal with conflicts
51 * and potentially inform users of which devices specifically
52 * cased the conflicts.
53 * @initiator: indicates who sent this request, could be any of
54 * of those set in reg_set_by, %REGDOM_SET_BY_*
55 * @alpha2: the ISO / IEC 3166 alpha2 country code of the requested
56 * regulatory domain. We have a few special codes:
57 * 00 - World regulatory domain
58 * 99 - built by driver but a specific alpha2 cannot be determined
59 * 98 - result of an intersection between two regulatory domains
60 * @intersect: indicates whether the wireless core should intersect
61 * the requested regulatory domain with the presently set regulatory
62 * domain.
63 * @country_ie_checksum: checksum of the last processed and accepted
64 * country IE
65 * @country_ie_env: lets us know if the AP is telling us we are outdoor,
66 * indoor, or if it doesn't matter
67 */
68struct regulatory_request {
69 struct wiphy *wiphy;
70 enum reg_set_by initiator;
71 char alpha2[2];
72 bool intersect;
73 u32 country_ie_checksum;
74 enum environment_cap country_ie_env;
75};
76 45
77/* Receipt of information from last regulatory request */ 46/* Receipt of information from last regulatory request */
78static struct regulatory_request *last_request; 47static struct regulatory_request *last_request;
@@ -86,22 +55,63 @@ static u32 supported_bandwidths[] = {
86 MHZ_TO_KHZ(20), 55 MHZ_TO_KHZ(20),
87}; 56};
88 57
89/* Central wireless core regulatory domains, we only need two, 58/*
59 * Central wireless core regulatory domains, we only need two,
90 * the current one and a world regulatory domain in case we have no 60 * the current one and a world regulatory domain in case we have no
91 * information to give us an alpha2 */ 61 * information to give us an alpha2
92static const struct ieee80211_regdomain *cfg80211_regdomain; 62 */
63const struct ieee80211_regdomain *cfg80211_regdomain;
93 64
94/* We use this as a place for the rd structure built from the 65/*
66 * We use this as a place for the rd structure built from the
95 * last parsed country IE to rest until CRDA gets back to us with 67 * last parsed country IE to rest until CRDA gets back to us with
96 * what it thinks should apply for the same country */ 68 * what it thinks should apply for the same country
69 */
97static const struct ieee80211_regdomain *country_ie_regdomain; 70static const struct ieee80211_regdomain *country_ie_regdomain;
98 71
72/* Used to queue up regulatory hints */
73static LIST_HEAD(reg_requests_list);
74static spinlock_t reg_requests_lock;
75
76/* Used to queue up beacon hints for review */
77static LIST_HEAD(reg_pending_beacons);
78static spinlock_t reg_pending_beacons_lock;
79
80/* Used to keep track of processed beacon hints */
81static LIST_HEAD(reg_beacon_list);
82
83struct reg_beacon {
84 struct list_head list;
85 struct ieee80211_channel chan;
86};
87
99/* We keep a static world regulatory domain in case of the absence of CRDA */ 88/* We keep a static world regulatory domain in case of the absence of CRDA */
100static const struct ieee80211_regdomain world_regdom = { 89static const struct ieee80211_regdomain world_regdom = {
101 .n_reg_rules = 1, 90 .n_reg_rules = 5,
102 .alpha2 = "00", 91 .alpha2 = "00",
103 .reg_rules = { 92 .reg_rules = {
104 REG_RULE(2412-10, 2462+10, 40, 6, 20, 93 /* IEEE 802.11b/g, channels 1..11 */
94 REG_RULE(2412-10, 2462+10, 40, 6, 20, 0),
95 /* IEEE 802.11b/g, channels 12..13. No HT40
96 * channel fits here. */
97 REG_RULE(2467-10, 2472+10, 20, 6, 20,
98 NL80211_RRF_PASSIVE_SCAN |
99 NL80211_RRF_NO_IBSS),
100 /* IEEE 802.11 channel 14 - Only JP enables
101 * this and for 802.11b only */
102 REG_RULE(2484-10, 2484+10, 20, 6, 20,
103 NL80211_RRF_PASSIVE_SCAN |
104 NL80211_RRF_NO_IBSS |
105 NL80211_RRF_NO_OFDM),
106 /* IEEE 802.11a, channel 36..48 */
107 REG_RULE(5180-10, 5240+10, 40, 6, 20,
108 NL80211_RRF_PASSIVE_SCAN |
109 NL80211_RRF_NO_IBSS),
110
111 /* NB: 5260 MHz - 5700 MHz requies DFS */
112
113 /* IEEE 802.11a, channel 149..165 */
114 REG_RULE(5745-10, 5825+10, 40, 6, 20,
105 NL80211_RRF_PASSIVE_SCAN | 115 NL80211_RRF_PASSIVE_SCAN |
106 NL80211_RRF_NO_IBSS), 116 NL80211_RRF_NO_IBSS),
107 } 117 }
@@ -112,12 +122,19 @@ static const struct ieee80211_regdomain *cfg80211_world_regdom =
112 122
113#ifdef CONFIG_WIRELESS_OLD_REGULATORY 123#ifdef CONFIG_WIRELESS_OLD_REGULATORY
114static char *ieee80211_regdom = "US"; 124static char *ieee80211_regdom = "US";
125#else
126static char *ieee80211_regdom = "00";
127#endif
128
115module_param(ieee80211_regdom, charp, 0444); 129module_param(ieee80211_regdom, charp, 0444);
116MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); 130MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code");
117 131
118/* We assume 40 MHz bandwidth for the old regulatory work. 132#ifdef CONFIG_WIRELESS_OLD_REGULATORY
133/*
134 * We assume 40 MHz bandwidth for the old regulatory work.
119 * We make emphasis we are using the exact same frequencies 135 * We make emphasis we are using the exact same frequencies
120 * as before */ 136 * as before
137 */
121 138
122static const struct ieee80211_regdomain us_regdom = { 139static const struct ieee80211_regdomain us_regdom = {
123 .n_reg_rules = 6, 140 .n_reg_rules = 6,
@@ -156,8 +173,10 @@ static const struct ieee80211_regdomain jp_regdom = {
156 173
157static const struct ieee80211_regdomain eu_regdom = { 174static const struct ieee80211_regdomain eu_regdom = {
158 .n_reg_rules = 6, 175 .n_reg_rules = 6,
159 /* This alpha2 is bogus, we leave it here just for stupid 176 /*
160 * backward compatibility */ 177 * This alpha2 is bogus, we leave it here just for stupid
178 * backward compatibility
179 */
161 .alpha2 = "EU", 180 .alpha2 = "EU",
162 .reg_rules = { 181 .reg_rules = {
163 /* IEEE 802.11b/g, channels 1..13 */ 182 /* IEEE 802.11b/g, channels 1..13 */
@@ -226,8 +245,10 @@ static void reset_regdomains(void)
226 cfg80211_regdomain = NULL; 245 cfg80211_regdomain = NULL;
227} 246}
228 247
229/* Dynamic world regulatory domain requested by the wireless 248/*
230 * core upon initialization */ 249 * Dynamic world regulatory domain requested by the wireless
250 * core upon initialization
251 */
231static void update_world_regdomain(const struct ieee80211_regdomain *rd) 252static void update_world_regdomain(const struct ieee80211_regdomain *rd)
232{ 253{
233 BUG_ON(!last_request); 254 BUG_ON(!last_request);
@@ -268,8 +289,10 @@ static bool is_unknown_alpha2(const char *alpha2)
268{ 289{
269 if (!alpha2) 290 if (!alpha2)
270 return false; 291 return false;
271 /* Special case where regulatory domain was built by driver 292 /*
272 * but a specific alpha2 cannot be determined */ 293 * Special case where regulatory domain was built by driver
294 * but a specific alpha2 cannot be determined
295 */
273 if (alpha2[0] == '9' && alpha2[1] == '9') 296 if (alpha2[0] == '9' && alpha2[1] == '9')
274 return true; 297 return true;
275 return false; 298 return false;
@@ -279,9 +302,11 @@ static bool is_intersected_alpha2(const char *alpha2)
279{ 302{
280 if (!alpha2) 303 if (!alpha2)
281 return false; 304 return false;
282 /* Special case where regulatory domain is the 305 /*
306 * Special case where regulatory domain is the
283 * result of an intersection between two regulatory domain 307 * result of an intersection between two regulatory domain
284 * structures */ 308 * structures
309 */
285 if (alpha2[0] == '9' && alpha2[1] == '8') 310 if (alpha2[0] == '9' && alpha2[1] == '8')
286 return true; 311 return true;
287 return false; 312 return false;
@@ -306,8 +331,10 @@ static bool alpha2_equal(const char *alpha2_x, const char *alpha2_y)
306 return false; 331 return false;
307} 332}
308 333
309static bool regdom_changed(const char *alpha2) 334static bool regdom_changes(const char *alpha2)
310{ 335{
336 assert_cfg80211_lock();
337
311 if (!cfg80211_regdomain) 338 if (!cfg80211_regdomain)
312 return true; 339 return true;
313 if (alpha2_equal(cfg80211_regdomain->alpha2, alpha2)) 340 if (alpha2_equal(cfg80211_regdomain->alpha2, alpha2))
@@ -334,8 +361,10 @@ static bool country_ie_integrity_changes(u32 checksum)
334 return false; 361 return false;
335} 362}
336 363
337/* This lets us keep regulatory code which is updated on a regulatory 364/*
338 * basis in userspace. */ 365 * This lets us keep regulatory code which is updated on a regulatory
366 * basis in userspace.
367 */
339static int call_crda(const char *alpha2) 368static int call_crda(const char *alpha2)
340{ 369{
341 char country_env[9 + 2] = "COUNTRY="; 370 char country_env[9 + 2] = "COUNTRY=";
@@ -447,10 +476,12 @@ static bool freq_in_rule_band(const struct ieee80211_freq_range *freq_range,
447#undef ONE_GHZ_IN_KHZ 476#undef ONE_GHZ_IN_KHZ
448} 477}
449 478
450/* Converts a country IE to a regulatory domain. A regulatory domain 479/*
480 * Converts a country IE to a regulatory domain. A regulatory domain
451 * structure has a lot of information which the IE doesn't yet have, 481 * structure has a lot of information which the IE doesn't yet have,
452 * so for the other values we use upper max values as we will intersect 482 * so for the other values we use upper max values as we will intersect
453 * with our userspace regulatory agent to get lower bounds. */ 483 * with our userspace regulatory agent to get lower bounds.
484 */
454static struct ieee80211_regdomain *country_ie_2_rd( 485static struct ieee80211_regdomain *country_ie_2_rd(
455 u8 *country_ie, 486 u8 *country_ie,
456 u8 country_ie_len, 487 u8 country_ie_len,
@@ -495,9 +526,11 @@ static struct ieee80211_regdomain *country_ie_2_rd(
495 526
496 *checksum ^= ((flags ^ alpha2[0] ^ alpha2[1]) << 8); 527 *checksum ^= ((flags ^ alpha2[0] ^ alpha2[1]) << 8);
497 528
498 /* We need to build a reg rule for each triplet, but first we must 529 /*
530 * We need to build a reg rule for each triplet, but first we must
499 * calculate the number of reg rules we will need. We will need one 531 * calculate the number of reg rules we will need. We will need one
500 * for each channel subband */ 532 * for each channel subband
533 */
501 while (country_ie_len >= 3) { 534 while (country_ie_len >= 3) {
502 int end_channel = 0; 535 int end_channel = 0;
503 struct ieee80211_country_ie_triplet *triplet = 536 struct ieee80211_country_ie_triplet *triplet =
@@ -535,9 +568,11 @@ static struct ieee80211_regdomain *country_ie_2_rd(
535 if (cur_sub_max_channel < cur_channel) 568 if (cur_sub_max_channel < cur_channel)
536 return NULL; 569 return NULL;
537 570
538 /* Do not allow overlapping channels. Also channels 571 /*
572 * Do not allow overlapping channels. Also channels
539 * passed in each subband must be monotonically 573 * passed in each subband must be monotonically
540 * increasing */ 574 * increasing
575 */
541 if (last_sub_max_channel) { 576 if (last_sub_max_channel) {
542 if (cur_channel <= last_sub_max_channel) 577 if (cur_channel <= last_sub_max_channel)
543 return NULL; 578 return NULL;
@@ -545,10 +580,12 @@ static struct ieee80211_regdomain *country_ie_2_rd(
545 return NULL; 580 return NULL;
546 } 581 }
547 582
548 /* When dot11RegulatoryClassesRequired is supported 583 /*
584 * When dot11RegulatoryClassesRequired is supported
549 * we can throw ext triplets as part of this soup, 585 * we can throw ext triplets as part of this soup,
550 * for now we don't care when those change as we 586 * for now we don't care when those change as we
551 * don't support them */ 587 * don't support them
588 */
552 *checksum ^= ((cur_channel ^ cur_sub_max_channel) << 8) | 589 *checksum ^= ((cur_channel ^ cur_sub_max_channel) << 8) |
553 ((cur_sub_max_channel ^ cur_sub_max_channel) << 16) | 590 ((cur_sub_max_channel ^ cur_sub_max_channel) << 16) |
554 ((triplet->chans.max_power ^ cur_sub_max_channel) << 24); 591 ((triplet->chans.max_power ^ cur_sub_max_channel) << 24);
@@ -559,8 +596,10 @@ static struct ieee80211_regdomain *country_ie_2_rd(
559 country_ie_len -= 3; 596 country_ie_len -= 3;
560 num_rules++; 597 num_rules++;
561 598
562 /* Note: this is not a IEEE requirement but 599 /*
563 * simply a memory requirement */ 600 * Note: this is not a IEEE requirement but
601 * simply a memory requirement
602 */
564 if (num_rules > NL80211_MAX_SUPP_REG_RULES) 603 if (num_rules > NL80211_MAX_SUPP_REG_RULES)
565 return NULL; 604 return NULL;
566 } 605 }
@@ -588,8 +627,10 @@ static struct ieee80211_regdomain *country_ie_2_rd(
588 struct ieee80211_freq_range *freq_range = NULL; 627 struct ieee80211_freq_range *freq_range = NULL;
589 struct ieee80211_power_rule *power_rule = NULL; 628 struct ieee80211_power_rule *power_rule = NULL;
590 629
591 /* Must parse if dot11RegulatoryClassesRequired is true, 630 /*
592 * we don't support this yet */ 631 * Must parse if dot11RegulatoryClassesRequired is true,
632 * we don't support this yet
633 */
593 if (triplet->ext.reg_extension_id >= 634 if (triplet->ext.reg_extension_id >=
594 IEEE80211_COUNTRY_EXTENSION_ID) { 635 IEEE80211_COUNTRY_EXTENSION_ID) {
595 country_ie += 3; 636 country_ie += 3;
@@ -611,10 +652,12 @@ static struct ieee80211_regdomain *country_ie_2_rd(
611 end_channel = triplet->chans.first_channel + 652 end_channel = triplet->chans.first_channel +
612 (4 * (triplet->chans.num_channels - 1)); 653 (4 * (triplet->chans.num_channels - 1));
613 654
614 /* The +10 is since the regulatory domain expects 655 /*
656 * The +10 is since the regulatory domain expects
615 * the actual band edge, not the center of freq for 657 * the actual band edge, not the center of freq for
616 * its start and end freqs, assuming 20 MHz bandwidth on 658 * its start and end freqs, assuming 20 MHz bandwidth on
617 * the channels passed */ 659 * the channels passed
660 */
618 freq_range->start_freq_khz = 661 freq_range->start_freq_khz =
619 MHZ_TO_KHZ(ieee80211_channel_to_frequency( 662 MHZ_TO_KHZ(ieee80211_channel_to_frequency(
620 triplet->chans.first_channel) - 10); 663 triplet->chans.first_channel) - 10);
@@ -622,9 +665,11 @@ static struct ieee80211_regdomain *country_ie_2_rd(
622 MHZ_TO_KHZ(ieee80211_channel_to_frequency( 665 MHZ_TO_KHZ(ieee80211_channel_to_frequency(
623 end_channel) + 10); 666 end_channel) + 10);
624 667
625 /* Large arbitrary values, we intersect later */ 668 /*
626 /* Increment this if we ever support >= 40 MHz channels 669 * These are large arbitrary values we use to intersect later.
627 * in IEEE 802.11 */ 670 * Increment this if we ever support >= 40 MHz channels
671 * in IEEE 802.11
672 */
628 freq_range->max_bandwidth_khz = MHZ_TO_KHZ(40); 673 freq_range->max_bandwidth_khz = MHZ_TO_KHZ(40);
629 power_rule->max_antenna_gain = DBI_TO_MBI(100); 674 power_rule->max_antenna_gain = DBI_TO_MBI(100);
630 power_rule->max_eirp = DBM_TO_MBM(100); 675 power_rule->max_eirp = DBM_TO_MBM(100);
@@ -640,8 +685,10 @@ static struct ieee80211_regdomain *country_ie_2_rd(
640} 685}
641 686
642 687
643/* Helper for regdom_intersect(), this does the real 688/*
644 * mathematical intersection fun */ 689 * Helper for regdom_intersect(), this does the real
690 * mathematical intersection fun
691 */
645static int reg_rules_intersect( 692static int reg_rules_intersect(
646 const struct ieee80211_reg_rule *rule1, 693 const struct ieee80211_reg_rule *rule1,
647 const struct ieee80211_reg_rule *rule2, 694 const struct ieee80211_reg_rule *rule2,
@@ -719,11 +766,13 @@ static struct ieee80211_regdomain *regdom_intersect(
719 if (!rd1 || !rd2) 766 if (!rd1 || !rd2)
720 return NULL; 767 return NULL;
721 768
722 /* First we get a count of the rules we'll need, then we actually 769 /*
770 * First we get a count of the rules we'll need, then we actually
723 * build them. This is to so we can malloc() and free() a 771 * build them. This is to so we can malloc() and free() a
724 * regdomain once. The reason we use reg_rules_intersect() here 772 * regdomain once. The reason we use reg_rules_intersect() here
725 * is it will return -EINVAL if the rule computed makes no sense. 773 * is it will return -EINVAL if the rule computed makes no sense.
726 * All rules that do check out OK are valid. */ 774 * All rules that do check out OK are valid.
775 */
727 776
728 for (x = 0; x < rd1->n_reg_rules; x++) { 777 for (x = 0; x < rd1->n_reg_rules; x++) {
729 rule1 = &rd1->reg_rules[x]; 778 rule1 = &rd1->reg_rules[x];
@@ -751,14 +800,18 @@ static struct ieee80211_regdomain *regdom_intersect(
751 rule1 = &rd1->reg_rules[x]; 800 rule1 = &rd1->reg_rules[x];
752 for (y = 0; y < rd2->n_reg_rules; y++) { 801 for (y = 0; y < rd2->n_reg_rules; y++) {
753 rule2 = &rd2->reg_rules[y]; 802 rule2 = &rd2->reg_rules[y];
754 /* This time around instead of using the stack lets 803 /*
804 * This time around instead of using the stack lets
755 * write to the target rule directly saving ourselves 805 * write to the target rule directly saving ourselves
756 * a memcpy() */ 806 * a memcpy()
807 */
757 intersected_rule = &rd->reg_rules[rule_idx]; 808 intersected_rule = &rd->reg_rules[rule_idx];
758 r = reg_rules_intersect(rule1, rule2, 809 r = reg_rules_intersect(rule1, rule2,
759 intersected_rule); 810 intersected_rule);
760 /* No need to memset here the intersected rule here as 811 /*
761 * we're not using the stack anymore */ 812 * No need to memset here the intersected rule here as
813 * we're not using the stack anymore
814 */
762 if (r) 815 if (r)
763 continue; 816 continue;
764 rule_idx++; 817 rule_idx++;
@@ -777,8 +830,10 @@ static struct ieee80211_regdomain *regdom_intersect(
777 return rd; 830 return rd;
778} 831}
779 832
780/* XXX: add support for the rest of enum nl80211_reg_rule_flags, we may 833/*
781 * want to just have the channel structure use these */ 834 * XXX: add support for the rest of enum nl80211_reg_rule_flags, we may
835 * want to just have the channel structure use these
836 */
782static u32 map_regdom_flags(u32 rd_flags) 837static u32 map_regdom_flags(u32 rd_flags)
783{ 838{
784 u32 channel_flags = 0; 839 u32 channel_flags = 0;
@@ -791,48 +846,45 @@ static u32 map_regdom_flags(u32 rd_flags)
791 return channel_flags; 846 return channel_flags;
792} 847}
793 848
794/** 849static int freq_reg_info_regd(struct wiphy *wiphy,
795 * freq_reg_info - get regulatory information for the given frequency 850 u32 center_freq,
796 * @center_freq: Frequency in KHz for which we want regulatory information for 851 u32 *bandwidth,
797 * @bandwidth: the bandwidth requirement you have in KHz, if you do not have one 852 const struct ieee80211_reg_rule **reg_rule,
798 * you can set this to 0. If this frequency is allowed we then set 853 const struct ieee80211_regdomain *custom_regd)
799 * this value to the maximum allowed bandwidth.
800 * @reg_rule: the regulatory rule which we have for this frequency
801 *
802 * Use this function to get the regulatory rule for a specific frequency on
803 * a given wireless device. If the device has a specific regulatory domain
804 * it wants to follow we respect that unless a country IE has been received
805 * and processed already.
806 *
807 * Returns 0 if it was able to find a valid regulatory rule which does
808 * apply to the given center_freq otherwise it returns non-zero. It will
809 * also return -ERANGE if we determine the given center_freq does not even have
810 * a regulatory rule for a frequency range in the center_freq's band. See
811 * freq_in_rule_band() for our current definition of a band -- this is purely
812 * subjective and right now its 802.11 specific.
813 */
814static int freq_reg_info(u32 center_freq, u32 *bandwidth,
815 const struct ieee80211_reg_rule **reg_rule)
816{ 854{
817 int i; 855 int i;
818 bool band_rule_found = false; 856 bool band_rule_found = false;
857 const struct ieee80211_regdomain *regd;
819 u32 max_bandwidth = 0; 858 u32 max_bandwidth = 0;
820 859
821 if (!cfg80211_regdomain) 860 regd = custom_regd ? custom_regd : cfg80211_regdomain;
861
862 /*
863 * Follow the driver's regulatory domain, if present, unless a country
864 * IE has been processed or a user wants to help complaince further
865 */
866 if (last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE &&
867 last_request->initiator != NL80211_REGDOM_SET_BY_USER &&
868 wiphy->regd)
869 regd = wiphy->regd;
870
871 if (!regd)
822 return -EINVAL; 872 return -EINVAL;
823 873
824 for (i = 0; i < cfg80211_regdomain->n_reg_rules; i++) { 874 for (i = 0; i < regd->n_reg_rules; i++) {
825 const struct ieee80211_reg_rule *rr; 875 const struct ieee80211_reg_rule *rr;
826 const struct ieee80211_freq_range *fr = NULL; 876 const struct ieee80211_freq_range *fr = NULL;
827 const struct ieee80211_power_rule *pr = NULL; 877 const struct ieee80211_power_rule *pr = NULL;
828 878
829 rr = &cfg80211_regdomain->reg_rules[i]; 879 rr = &regd->reg_rules[i];
830 fr = &rr->freq_range; 880 fr = &rr->freq_range;
831 pr = &rr->power_rule; 881 pr = &rr->power_rule;
832 882
833 /* We only need to know if one frequency rule was 883 /*
884 * We only need to know if one frequency rule was
834 * was in center_freq's band, that's enough, so lets 885 * was in center_freq's band, that's enough, so lets
835 * not overwrite it once found */ 886 * not overwrite it once found
887 */
836 if (!band_rule_found) 888 if (!band_rule_found)
837 band_rule_found = freq_in_rule_band(fr, center_freq); 889 band_rule_found = freq_in_rule_band(fr, center_freq);
838 890
@@ -850,6 +902,14 @@ static int freq_reg_info(u32 center_freq, u32 *bandwidth,
850 902
851 return !max_bandwidth; 903 return !max_bandwidth;
852} 904}
905EXPORT_SYMBOL(freq_reg_info);
906
907int freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 *bandwidth,
908 const struct ieee80211_reg_rule **reg_rule)
909{
910 return freq_reg_info_regd(wiphy, center_freq,
911 bandwidth, reg_rule, NULL);
912}
853 913
854static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, 914static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
855 unsigned int chan_idx) 915 unsigned int chan_idx)
@@ -861,6 +921,11 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
861 const struct ieee80211_power_rule *power_rule = NULL; 921 const struct ieee80211_power_rule *power_rule = NULL;
862 struct ieee80211_supported_band *sband; 922 struct ieee80211_supported_band *sband;
863 struct ieee80211_channel *chan; 923 struct ieee80211_channel *chan;
924 struct wiphy *request_wiphy = NULL;
925
926 assert_cfg80211_lock();
927
928 request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx);
864 929
865 sband = wiphy->bands[band]; 930 sband = wiphy->bands[band];
866 BUG_ON(chan_idx >= sband->n_channels); 931 BUG_ON(chan_idx >= sband->n_channels);
@@ -868,11 +933,12 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
868 933
869 flags = chan->orig_flags; 934 flags = chan->orig_flags;
870 935
871 r = freq_reg_info(MHZ_TO_KHZ(chan->center_freq), 936 r = freq_reg_info(wiphy, MHZ_TO_KHZ(chan->center_freq),
872 &max_bandwidth, &reg_rule); 937 &max_bandwidth, &reg_rule);
873 938
874 if (r) { 939 if (r) {
875 /* This means no regulatory rule was found in the country IE 940 /*
941 * This means no regulatory rule was found in the country IE
876 * with a frequency range on the center_freq's band, since 942 * with a frequency range on the center_freq's band, since
877 * IEEE-802.11 allows for a country IE to have a subset of the 943 * IEEE-802.11 allows for a country IE to have a subset of the
878 * regulatory information provided in a country we ignore 944 * regulatory information provided in a country we ignore
@@ -883,7 +949,8 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
883 * http://tinyurl.com/11d-clarification 949 * http://tinyurl.com/11d-clarification
884 */ 950 */
885 if (r == -ERANGE && 951 if (r == -ERANGE &&
886 last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) { 952 last_request->initiator ==
953 NL80211_REGDOM_SET_BY_COUNTRY_IE) {
887#ifdef CONFIG_CFG80211_REG_DEBUG 954#ifdef CONFIG_CFG80211_REG_DEBUG
888 printk(KERN_DEBUG "cfg80211: Leaving channel %d MHz " 955 printk(KERN_DEBUG "cfg80211: Leaving channel %d MHz "
889 "intact on %s - no rule found in band on " 956 "intact on %s - no rule found in band on "
@@ -891,10 +958,13 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
891 chan->center_freq, wiphy_name(wiphy)); 958 chan->center_freq, wiphy_name(wiphy));
892#endif 959#endif
893 } else { 960 } else {
894 /* In this case we know the country IE has at least one reg rule 961 /*
895 * for the band so we respect its band definitions */ 962 * In this case we know the country IE has at least one reg rule
963 * for the band so we respect its band definitions
964 */
896#ifdef CONFIG_CFG80211_REG_DEBUG 965#ifdef CONFIG_CFG80211_REG_DEBUG
897 if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) 966 if (last_request->initiator ==
967 NL80211_REGDOM_SET_BY_COUNTRY_IE)
898 printk(KERN_DEBUG "cfg80211: Disabling " 968 printk(KERN_DEBUG "cfg80211: Disabling "
899 "channel %d MHz on %s due to " 969 "channel %d MHz on %s due to "
900 "Country IE\n", 970 "Country IE\n",
@@ -908,6 +978,24 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
908 978
909 power_rule = &reg_rule->power_rule; 979 power_rule = &reg_rule->power_rule;
910 980
981 if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
982 request_wiphy && request_wiphy == wiphy &&
983 request_wiphy->strict_regulatory) {
984 /*
985 * This gaurantees the driver's requested regulatory domain
986 * will always be used as a base for further regulatory
987 * settings
988 */
989 chan->flags = chan->orig_flags =
990 map_regdom_flags(reg_rule->flags);
991 chan->max_antenna_gain = chan->orig_mag =
992 (int) MBI_TO_DBI(power_rule->max_antenna_gain);
993 chan->max_bandwidth = KHZ_TO_MHZ(max_bandwidth);
994 chan->max_power = chan->orig_mpwr =
995 (int) MBM_TO_DBM(power_rule->max_eirp);
996 return;
997 }
998
911 chan->flags = flags | map_regdom_flags(reg_rule->flags); 999 chan->flags = flags | map_regdom_flags(reg_rule->flags);
912 chan->max_antenna_gain = min(chan->orig_mag, 1000 chan->max_antenna_gain = min(chan->orig_mag,
913 (int) MBI_TO_DBI(power_rule->max_antenna_gain)); 1001 (int) MBI_TO_DBI(power_rule->max_antenna_gain));
@@ -931,116 +1019,513 @@ static void handle_band(struct wiphy *wiphy, enum ieee80211_band band)
931 handle_channel(wiphy, band, i); 1019 handle_channel(wiphy, band, i);
932} 1020}
933 1021
934static bool ignore_reg_update(struct wiphy *wiphy, enum reg_set_by setby) 1022static bool ignore_reg_update(struct wiphy *wiphy,
1023 enum nl80211_reg_initiator initiator)
935{ 1024{
936 if (!last_request) 1025 if (!last_request)
937 return true; 1026 return true;
938 if (setby == REGDOM_SET_BY_CORE && 1027 if (initiator == NL80211_REGDOM_SET_BY_CORE &&
939 wiphy->fw_handles_regulatory) 1028 wiphy->custom_regulatory)
1029 return true;
1030 /*
1031 * wiphy->regd will be set once the device has its own
1032 * desired regulatory domain set
1033 */
1034 if (wiphy->strict_regulatory && !wiphy->regd &&
1035 !is_world_regdom(last_request->alpha2))
940 return true; 1036 return true;
941 return false; 1037 return false;
942} 1038}
943 1039
944static void update_all_wiphy_regulatory(enum reg_set_by setby) 1040static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator)
945{ 1041{
946 struct cfg80211_registered_device *drv; 1042 struct cfg80211_registered_device *drv;
947 1043
948 list_for_each_entry(drv, &cfg80211_drv_list, list) 1044 list_for_each_entry(drv, &cfg80211_drv_list, list)
949 if (!ignore_reg_update(&drv->wiphy, setby)) 1045 wiphy_update_regulatory(&drv->wiphy, initiator);
950 wiphy_update_regulatory(&drv->wiphy, setby); 1046}
1047
1048static void handle_reg_beacon(struct wiphy *wiphy,
1049 unsigned int chan_idx,
1050 struct reg_beacon *reg_beacon)
1051{
1052#ifdef CONFIG_CFG80211_REG_DEBUG
1053#define REG_DEBUG_BEACON_FLAG(desc) \
1054 printk(KERN_DEBUG "cfg80211: Enabling " desc " on " \
1055 "frequency: %d MHz (Ch %d) on %s\n", \
1056 reg_beacon->chan.center_freq, \
1057 ieee80211_frequency_to_channel(reg_beacon->chan.center_freq), \
1058 wiphy_name(wiphy));
1059#else
1060#define REG_DEBUG_BEACON_FLAG(desc) do {} while (0)
1061#endif
1062 struct ieee80211_supported_band *sband;
1063 struct ieee80211_channel *chan;
1064
1065 assert_cfg80211_lock();
1066
1067 sband = wiphy->bands[reg_beacon->chan.band];
1068 chan = &sband->channels[chan_idx];
1069
1070 if (likely(chan->center_freq != reg_beacon->chan.center_freq))
1071 return;
1072
1073 if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) {
1074 chan->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
1075 REG_DEBUG_BEACON_FLAG("active scanning");
1076 }
1077
1078 if (chan->flags & IEEE80211_CHAN_NO_IBSS) {
1079 chan->flags &= ~IEEE80211_CHAN_NO_IBSS;
1080 REG_DEBUG_BEACON_FLAG("beaconing");
1081 }
1082
1083 chan->beacon_found = true;
1084#undef REG_DEBUG_BEACON_FLAG
951} 1085}
952 1086
953void wiphy_update_regulatory(struct wiphy *wiphy, enum reg_set_by setby) 1087/*
1088 * Called when a scan on a wiphy finds a beacon on
1089 * new channel
1090 */
1091static void wiphy_update_new_beacon(struct wiphy *wiphy,
1092 struct reg_beacon *reg_beacon)
1093{
1094 unsigned int i;
1095 struct ieee80211_supported_band *sband;
1096
1097 assert_cfg80211_lock();
1098
1099 if (!wiphy->bands[reg_beacon->chan.band])
1100 return;
1101
1102 sband = wiphy->bands[reg_beacon->chan.band];
1103
1104 for (i = 0; i < sband->n_channels; i++)
1105 handle_reg_beacon(wiphy, i, reg_beacon);
1106}
1107
1108/*
1109 * Called upon reg changes or a new wiphy is added
1110 */
1111static void wiphy_update_beacon_reg(struct wiphy *wiphy)
1112{
1113 unsigned int i;
1114 struct ieee80211_supported_band *sband;
1115 struct reg_beacon *reg_beacon;
1116
1117 assert_cfg80211_lock();
1118
1119 if (list_empty(&reg_beacon_list))
1120 return;
1121
1122 list_for_each_entry(reg_beacon, &reg_beacon_list, list) {
1123 if (!wiphy->bands[reg_beacon->chan.band])
1124 continue;
1125 sband = wiphy->bands[reg_beacon->chan.band];
1126 for (i = 0; i < sband->n_channels; i++)
1127 handle_reg_beacon(wiphy, i, reg_beacon);
1128 }
1129}
1130
1131static bool reg_is_world_roaming(struct wiphy *wiphy)
1132{
1133 if (is_world_regdom(cfg80211_regdomain->alpha2) ||
1134 (wiphy->regd && is_world_regdom(wiphy->regd->alpha2)))
1135 return true;
1136 if (last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE &&
1137 wiphy->custom_regulatory)
1138 return true;
1139 return false;
1140}
1141
1142/* Reap the advantages of previously found beacons */
1143static void reg_process_beacons(struct wiphy *wiphy)
1144{
1145 if (!reg_is_world_roaming(wiphy))
1146 return;
1147 wiphy_update_beacon_reg(wiphy);
1148}
1149
1150void wiphy_update_regulatory(struct wiphy *wiphy,
1151 enum nl80211_reg_initiator initiator)
954{ 1152{
955 enum ieee80211_band band; 1153 enum ieee80211_band band;
1154
1155 if (ignore_reg_update(wiphy, initiator))
1156 goto out;
956 for (band = 0; band < IEEE80211_NUM_BANDS; band++) { 1157 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
957 if (wiphy->bands[band]) 1158 if (wiphy->bands[band])
958 handle_band(wiphy, band); 1159 handle_band(wiphy, band);
959 if (wiphy->reg_notifier)
960 wiphy->reg_notifier(wiphy, setby);
961 } 1160 }
1161out:
1162 reg_process_beacons(wiphy);
1163 if (wiphy->reg_notifier)
1164 wiphy->reg_notifier(wiphy, last_request);
962} 1165}
963 1166
964/* Return value which can be used by ignore_request() to indicate 1167static void handle_channel_custom(struct wiphy *wiphy,
965 * it has been determined we should intersect two regulatory domains */ 1168 enum ieee80211_band band,
1169 unsigned int chan_idx,
1170 const struct ieee80211_regdomain *regd)
1171{
1172 int r;
1173 u32 max_bandwidth = 0;
1174 const struct ieee80211_reg_rule *reg_rule = NULL;
1175 const struct ieee80211_power_rule *power_rule = NULL;
1176 struct ieee80211_supported_band *sband;
1177 struct ieee80211_channel *chan;
1178
1179 sband = wiphy->bands[band];
1180 BUG_ON(chan_idx >= sband->n_channels);
1181 chan = &sband->channels[chan_idx];
1182
1183 r = freq_reg_info_regd(wiphy, MHZ_TO_KHZ(chan->center_freq),
1184 &max_bandwidth, &reg_rule, regd);
1185
1186 if (r) {
1187 chan->flags = IEEE80211_CHAN_DISABLED;
1188 return;
1189 }
1190
1191 power_rule = &reg_rule->power_rule;
1192
1193 chan->flags |= map_regdom_flags(reg_rule->flags);
1194 chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain);
1195 chan->max_bandwidth = KHZ_TO_MHZ(max_bandwidth);
1196 chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp);
1197}
1198
1199static void handle_band_custom(struct wiphy *wiphy, enum ieee80211_band band,
1200 const struct ieee80211_regdomain *regd)
1201{
1202 unsigned int i;
1203 struct ieee80211_supported_band *sband;
1204
1205 BUG_ON(!wiphy->bands[band]);
1206 sband = wiphy->bands[band];
1207
1208 for (i = 0; i < sband->n_channels; i++)
1209 handle_channel_custom(wiphy, band, i, regd);
1210}
1211
1212/* Used by drivers prior to wiphy registration */
1213void wiphy_apply_custom_regulatory(struct wiphy *wiphy,
1214 const struct ieee80211_regdomain *regd)
1215{
1216 enum ieee80211_band band;
1217 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
1218 if (wiphy->bands[band])
1219 handle_band_custom(wiphy, band, regd);
1220 }
1221}
1222EXPORT_SYMBOL(wiphy_apply_custom_regulatory);
1223
1224static int reg_copy_regd(const struct ieee80211_regdomain **dst_regd,
1225 const struct ieee80211_regdomain *src_regd)
1226{
1227 struct ieee80211_regdomain *regd;
1228 int size_of_regd = 0;
1229 unsigned int i;
1230
1231 size_of_regd = sizeof(struct ieee80211_regdomain) +
1232 ((src_regd->n_reg_rules + 1) * sizeof(struct ieee80211_reg_rule));
1233
1234 regd = kzalloc(size_of_regd, GFP_KERNEL);
1235 if (!regd)
1236 return -ENOMEM;
1237
1238 memcpy(regd, src_regd, sizeof(struct ieee80211_regdomain));
1239
1240 for (i = 0; i < src_regd->n_reg_rules; i++)
1241 memcpy(&regd->reg_rules[i], &src_regd->reg_rules[i],
1242 sizeof(struct ieee80211_reg_rule));
1243
1244 *dst_regd = regd;
1245 return 0;
1246}
1247
1248/*
1249 * Return value which can be used by ignore_request() to indicate
1250 * it has been determined we should intersect two regulatory domains
1251 */
966#define REG_INTERSECT 1 1252#define REG_INTERSECT 1
967 1253
968/* This has the logic which determines when a new request 1254/* This has the logic which determines when a new request
969 * should be ignored. */ 1255 * should be ignored. */
970static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by, 1256static int ignore_request(struct wiphy *wiphy,
971 const char *alpha2) 1257 struct regulatory_request *pending_request)
972{ 1258{
1259 struct wiphy *last_wiphy = NULL;
1260
1261 assert_cfg80211_lock();
1262
973 /* All initial requests are respected */ 1263 /* All initial requests are respected */
974 if (!last_request) 1264 if (!last_request)
975 return 0; 1265 return 0;
976 1266
977 switch (set_by) { 1267 switch (pending_request->initiator) {
978 case REGDOM_SET_BY_INIT: 1268 case NL80211_REGDOM_SET_BY_CORE:
979 return -EINVAL; 1269 return -EINVAL;
980 case REGDOM_SET_BY_CORE: 1270 case NL80211_REGDOM_SET_BY_COUNTRY_IE:
981 /* 1271
982 * Always respect new wireless core hints, should only happen 1272 last_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx);
983 * when updating the world regulatory domain at init. 1273
984 */ 1274 if (unlikely(!is_an_alpha2(pending_request->alpha2)))
985 return 0;
986 case REGDOM_SET_BY_COUNTRY_IE:
987 if (unlikely(!is_an_alpha2(alpha2)))
988 return -EINVAL; 1275 return -EINVAL;
989 if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) { 1276 if (last_request->initiator ==
990 if (last_request->wiphy != wiphy) { 1277 NL80211_REGDOM_SET_BY_COUNTRY_IE) {
1278 if (last_wiphy != wiphy) {
991 /* 1279 /*
992 * Two cards with two APs claiming different 1280 * Two cards with two APs claiming different
993 * different Country IE alpha2s. We could 1281 * different Country IE alpha2s. We could
994 * intersect them, but that seems unlikely 1282 * intersect them, but that seems unlikely
995 * to be correct. Reject second one for now. 1283 * to be correct. Reject second one for now.
996 */ 1284 */
997 if (!alpha2_equal(alpha2, 1285 if (regdom_changes(pending_request->alpha2))
998 cfg80211_regdomain->alpha2))
999 return -EOPNOTSUPP; 1286 return -EOPNOTSUPP;
1000 return -EALREADY; 1287 return -EALREADY;
1001 } 1288 }
1002 /* Two consecutive Country IE hints on the same wiphy. 1289 /*
1003 * This should be picked up early by the driver/stack */ 1290 * Two consecutive Country IE hints on the same wiphy.
1004 if (WARN_ON(!alpha2_equal(cfg80211_regdomain->alpha2, 1291 * This should be picked up early by the driver/stack
1005 alpha2))) 1292 */
1293 if (WARN_ON(regdom_changes(pending_request->alpha2)))
1006 return 0; 1294 return 0;
1007 return -EALREADY; 1295 return -EALREADY;
1008 } 1296 }
1009 return REG_INTERSECT; 1297 return REG_INTERSECT;
1010 case REGDOM_SET_BY_DRIVER: 1298 case NL80211_REGDOM_SET_BY_DRIVER:
1011 if (last_request->initiator == REGDOM_SET_BY_DRIVER) 1299 if (last_request->initiator == NL80211_REGDOM_SET_BY_CORE) {
1300 if (is_old_static_regdom(cfg80211_regdomain))
1301 return 0;
1302 if (regdom_changes(pending_request->alpha2))
1303 return 0;
1012 return -EALREADY; 1304 return -EALREADY;
1013 return 0; 1305 }
1014 case REGDOM_SET_BY_USER: 1306
1015 if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) 1307 /*
1308 * This would happen if you unplug and plug your card
1309 * back in or if you add a new device for which the previously
1310 * loaded card also agrees on the regulatory domain.
1311 */
1312 if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
1313 !regdom_changes(pending_request->alpha2))
1314 return -EALREADY;
1315
1316 return REG_INTERSECT;
1317 case NL80211_REGDOM_SET_BY_USER:
1318 if (last_request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)
1016 return REG_INTERSECT; 1319 return REG_INTERSECT;
1017 /* If the user knows better the user should set the regdom 1320 /*
1018 * to their country before the IE is picked up */ 1321 * If the user knows better the user should set the regdom
1019 if (last_request->initiator == REGDOM_SET_BY_USER && 1322 * to their country before the IE is picked up
1323 */
1324 if (last_request->initiator == NL80211_REGDOM_SET_BY_USER &&
1020 last_request->intersect) 1325 last_request->intersect)
1021 return -EOPNOTSUPP; 1326 return -EOPNOTSUPP;
1327 /*
1328 * Process user requests only after previous user/driver/core
1329 * requests have been processed
1330 */
1331 if (last_request->initiator == NL80211_REGDOM_SET_BY_CORE ||
1332 last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER ||
1333 last_request->initiator == NL80211_REGDOM_SET_BY_USER) {
1334 if (regdom_changes(last_request->alpha2))
1335 return -EAGAIN;
1336 }
1337
1338 if (!is_old_static_regdom(cfg80211_regdomain) &&
1339 !regdom_changes(pending_request->alpha2))
1340 return -EALREADY;
1341
1022 return 0; 1342 return 0;
1023 } 1343 }
1024 1344
1025 return -EINVAL; 1345 return -EINVAL;
1026} 1346}
1027 1347
1028/* Caller must hold &cfg80211_drv_mutex */ 1348/**
1029int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by, 1349 * __regulatory_hint - hint to the wireless core a regulatory domain
1030 const char *alpha2, 1350 * @wiphy: if the hint comes from country information from an AP, this
1031 u32 country_ie_checksum, 1351 * is required to be set to the wiphy that received the information
1032 enum environment_cap env) 1352 * @pending_request: the regulatory request currently being processed
1353 *
1354 * The Wireless subsystem can use this function to hint to the wireless core
1355 * what it believes should be the current regulatory domain.
1356 *
1357 * Returns zero if all went fine, %-EALREADY if a regulatory domain had
1358 * already been set or other standard error codes.
1359 *
1360 * Caller must hold &cfg80211_mutex
1361 */
1362static int __regulatory_hint(struct wiphy *wiphy,
1363 struct regulatory_request *pending_request)
1033{ 1364{
1034 struct regulatory_request *request;
1035 bool intersect = false; 1365 bool intersect = false;
1036 int r = 0; 1366 int r = 0;
1037 1367
1038 r = ignore_request(wiphy, set_by, alpha2); 1368 assert_cfg80211_lock();
1369
1370 r = ignore_request(wiphy, pending_request);
1039 1371
1040 if (r == REG_INTERSECT) 1372 if (r == REG_INTERSECT) {
1373 if (pending_request->initiator ==
1374 NL80211_REGDOM_SET_BY_DRIVER) {
1375 r = reg_copy_regd(&wiphy->regd, cfg80211_regdomain);
1376 if (r) {
1377 kfree(pending_request);
1378 return r;
1379 }
1380 }
1041 intersect = true; 1381 intersect = true;
1042 else if (r) 1382 } else if (r) {
1383 /*
1384 * If the regulatory domain being requested by the
1385 * driver has already been set just copy it to the
1386 * wiphy
1387 */
1388 if (r == -EALREADY &&
1389 pending_request->initiator ==
1390 NL80211_REGDOM_SET_BY_DRIVER) {
1391 r = reg_copy_regd(&wiphy->regd, cfg80211_regdomain);
1392 if (r) {
1393 kfree(pending_request);
1394 return r;
1395 }
1396 r = -EALREADY;
1397 goto new_request;
1398 }
1399 kfree(pending_request);
1400 return r;
1401 }
1402
1403new_request:
1404 kfree(last_request);
1405
1406 last_request = pending_request;
1407 last_request->intersect = intersect;
1408
1409 pending_request = NULL;
1410
1411 /* When r == REG_INTERSECT we do need to call CRDA */
1412 if (r < 0) {
1413 /*
1414 * Since CRDA will not be called in this case as we already
1415 * have applied the requested regulatory domain before we just
1416 * inform userspace we have processed the request
1417 */
1418 if (r == -EALREADY)
1419 nl80211_send_reg_change_event(last_request);
1043 return r; 1420 return r;
1421 }
1422
1423 return call_crda(last_request->alpha2);
1424}
1425
1426/* This currently only processes user and driver regulatory hints */
1427static void reg_process_hint(struct regulatory_request *reg_request)
1428{
1429 int r = 0;
1430 struct wiphy *wiphy = NULL;
1431
1432 BUG_ON(!reg_request->alpha2);
1433
1434 mutex_lock(&cfg80211_mutex);
1435
1436 if (wiphy_idx_valid(reg_request->wiphy_idx))
1437 wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx);
1438
1439 if (reg_request->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
1440 !wiphy) {
1441 kfree(reg_request);
1442 goto out;
1443 }
1444
1445 r = __regulatory_hint(wiphy, reg_request);
1446 /* This is required so that the orig_* parameters are saved */
1447 if (r == -EALREADY && wiphy && wiphy->strict_regulatory)
1448 wiphy_update_regulatory(wiphy, reg_request->initiator);
1449out:
1450 mutex_unlock(&cfg80211_mutex);
1451}
1452
1453/* Processes regulatory hints, this is all the NL80211_REGDOM_SET_BY_* */
1454static void reg_process_pending_hints(void)
1455 {
1456 struct regulatory_request *reg_request;
1457
1458 spin_lock(&reg_requests_lock);
1459 while (!list_empty(&reg_requests_list)) {
1460 reg_request = list_first_entry(&reg_requests_list,
1461 struct regulatory_request,
1462 list);
1463 list_del_init(&reg_request->list);
1464
1465 spin_unlock(&reg_requests_lock);
1466 reg_process_hint(reg_request);
1467 spin_lock(&reg_requests_lock);
1468 }
1469 spin_unlock(&reg_requests_lock);
1470}
1471
1472/* Processes beacon hints -- this has nothing to do with country IEs */
1473static void reg_process_pending_beacon_hints(void)
1474{
1475 struct cfg80211_registered_device *drv;
1476 struct reg_beacon *pending_beacon, *tmp;
1477
1478 mutex_lock(&cfg80211_mutex);
1479
1480 /* This goes through the _pending_ beacon list */
1481 spin_lock_bh(&reg_pending_beacons_lock);
1482
1483 if (list_empty(&reg_pending_beacons)) {
1484 spin_unlock_bh(&reg_pending_beacons_lock);
1485 goto out;
1486 }
1487
1488 list_for_each_entry_safe(pending_beacon, tmp,
1489 &reg_pending_beacons, list) {
1490
1491 list_del_init(&pending_beacon->list);
1492
1493 /* Applies the beacon hint to current wiphys */
1494 list_for_each_entry(drv, &cfg80211_drv_list, list)
1495 wiphy_update_new_beacon(&drv->wiphy, pending_beacon);
1496
1497 /* Remembers the beacon hint for new wiphys or reg changes */
1498 list_add_tail(&pending_beacon->list, &reg_beacon_list);
1499 }
1500
1501 spin_unlock_bh(&reg_pending_beacons_lock);
1502out:
1503 mutex_unlock(&cfg80211_mutex);
1504}
1505
1506static void reg_todo(struct work_struct *work)
1507{
1508 reg_process_pending_hints();
1509 reg_process_pending_beacon_hints();
1510}
1511
1512static DECLARE_WORK(reg_work, reg_todo);
1513
1514static void queue_regulatory_request(struct regulatory_request *request)
1515{
1516 spin_lock(&reg_requests_lock);
1517 list_add_tail(&request->list, &reg_requests_list);
1518 spin_unlock(&reg_requests_lock);
1519
1520 schedule_work(&reg_work);
1521}
1522
1523/* Core regulatory hint -- happens once during cfg80211_init() */
1524static int regulatory_hint_core(const char *alpha2)
1525{
1526 struct regulatory_request *request;
1527
1528 BUG_ON(last_request);
1044 1529
1045 request = kzalloc(sizeof(struct regulatory_request), 1530 request = kzalloc(sizeof(struct regulatory_request),
1046 GFP_KERNEL); 1531 GFP_KERNEL);
@@ -1049,47 +1534,84 @@ int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by,
1049 1534
1050 request->alpha2[0] = alpha2[0]; 1535 request->alpha2[0] = alpha2[0];
1051 request->alpha2[1] = alpha2[1]; 1536 request->alpha2[1] = alpha2[1];
1052 request->initiator = set_by; 1537 request->initiator = NL80211_REGDOM_SET_BY_CORE;
1053 request->wiphy = wiphy;
1054 request->intersect = intersect;
1055 request->country_ie_checksum = country_ie_checksum;
1056 request->country_ie_env = env;
1057 1538
1058 kfree(last_request); 1539 queue_regulatory_request(request);
1059 last_request = request; 1540
1060 /* 1541 return 0;
1061 * Note: When CONFIG_WIRELESS_OLD_REGULATORY is enabled 1542}
1062 * AND if CRDA is NOT present nothing will happen, if someone 1543
1063 * wants to bother with 11d with OLD_REG you can add a timer. 1544/* User hints */
1064 * If after x amount of time nothing happens you can call: 1545int regulatory_hint_user(const char *alpha2)
1065 * 1546{
1066 * return set_regdom(country_ie_regdomain); 1547 struct regulatory_request *request;
1067 * 1548
1068 * to intersect with the static rd 1549 BUG_ON(!alpha2);
1069 */ 1550
1070 return call_crda(alpha2); 1551 request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL);
1552 if (!request)
1553 return -ENOMEM;
1554
1555 request->wiphy_idx = WIPHY_IDX_STALE;
1556 request->alpha2[0] = alpha2[0];
1557 request->alpha2[1] = alpha2[1];
1558 request->initiator = NL80211_REGDOM_SET_BY_USER,
1559
1560 queue_regulatory_request(request);
1561
1562 return 0;
1071} 1563}
1072 1564
1073void regulatory_hint(struct wiphy *wiphy, const char *alpha2) 1565/* Driver hints */
1566int regulatory_hint(struct wiphy *wiphy, const char *alpha2)
1074{ 1567{
1568 struct regulatory_request *request;
1569
1075 BUG_ON(!alpha2); 1570 BUG_ON(!alpha2);
1571 BUG_ON(!wiphy);
1076 1572
1077 mutex_lock(&cfg80211_drv_mutex); 1573 request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL);
1078 __regulatory_hint(wiphy, REGDOM_SET_BY_DRIVER, alpha2, 0, ENVIRON_ANY); 1574 if (!request)
1079 mutex_unlock(&cfg80211_drv_mutex); 1575 return -ENOMEM;
1576
1577 request->wiphy_idx = get_wiphy_idx(wiphy);
1578
1579 /* Must have registered wiphy first */
1580 BUG_ON(!wiphy_idx_valid(request->wiphy_idx));
1581
1582 request->alpha2[0] = alpha2[0];
1583 request->alpha2[1] = alpha2[1];
1584 request->initiator = NL80211_REGDOM_SET_BY_DRIVER;
1585
1586 queue_regulatory_request(request);
1587
1588 return 0;
1080} 1589}
1081EXPORT_SYMBOL(regulatory_hint); 1590EXPORT_SYMBOL(regulatory_hint);
1082 1591
1083static bool reg_same_country_ie_hint(struct wiphy *wiphy, 1592static bool reg_same_country_ie_hint(struct wiphy *wiphy,
1084 u32 country_ie_checksum) 1593 u32 country_ie_checksum)
1085{ 1594{
1086 if (!last_request->wiphy) 1595 struct wiphy *request_wiphy;
1596
1597 assert_cfg80211_lock();
1598
1599 if (unlikely(last_request->initiator !=
1600 NL80211_REGDOM_SET_BY_COUNTRY_IE))
1601 return false;
1602
1603 request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx);
1604
1605 if (!request_wiphy)
1087 return false; 1606 return false;
1088 if (likely(last_request->wiphy != wiphy)) 1607
1608 if (likely(request_wiphy != wiphy))
1089 return !country_ie_integrity_changes(country_ie_checksum); 1609 return !country_ie_integrity_changes(country_ie_checksum);
1090 /* We should not have let these through at this point, they 1610 /*
1611 * We should not have let these through at this point, they
1091 * should have been picked up earlier by the first alpha2 check 1612 * should have been picked up earlier by the first alpha2 check
1092 * on the device */ 1613 * on the device
1614 */
1093 if (WARN_ON(!country_ie_integrity_changes(country_ie_checksum))) 1615 if (WARN_ON(!country_ie_integrity_changes(country_ie_checksum)))
1094 return true; 1616 return true;
1095 return false; 1617 return false;
@@ -1103,11 +1625,14 @@ void regulatory_hint_11d(struct wiphy *wiphy,
1103 char alpha2[2]; 1625 char alpha2[2];
1104 u32 checksum = 0; 1626 u32 checksum = 0;
1105 enum environment_cap env = ENVIRON_ANY; 1627 enum environment_cap env = ENVIRON_ANY;
1628 struct regulatory_request *request;
1106 1629
1107 if (!last_request) 1630 mutex_lock(&cfg80211_mutex);
1108 return;
1109 1631
1110 mutex_lock(&cfg80211_drv_mutex); 1632 if (unlikely(!last_request)) {
1633 mutex_unlock(&cfg80211_mutex);
1634 return;
1635 }
1111 1636
1112 /* IE len must be evenly divisible by 2 */ 1637 /* IE len must be evenly divisible by 2 */
1113 if (country_ie_len & 0x01) 1638 if (country_ie_len & 0x01)
@@ -1116,9 +1641,11 @@ void regulatory_hint_11d(struct wiphy *wiphy,
1116 if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) 1641 if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN)
1117 goto out; 1642 goto out;
1118 1643
1119 /* Pending country IE processing, this can happen after we 1644 /*
1645 * Pending country IE processing, this can happen after we
1120 * call CRDA and wait for a response if a beacon was received before 1646 * call CRDA and wait for a response if a beacon was received before
1121 * we were able to process the last regulatory_hint_11d() call */ 1647 * we were able to process the last regulatory_hint_11d() call
1648 */
1122 if (country_ie_regdomain) 1649 if (country_ie_regdomain)
1123 goto out; 1650 goto out;
1124 1651
@@ -1130,33 +1657,46 @@ void regulatory_hint_11d(struct wiphy *wiphy,
1130 else if (country_ie[2] == 'O') 1657 else if (country_ie[2] == 'O')
1131 env = ENVIRON_OUTDOOR; 1658 env = ENVIRON_OUTDOOR;
1132 1659
1133 /* We will run this for *every* beacon processed for the BSSID, so 1660 /*
1661 * We will run this for *every* beacon processed for the BSSID, so
1134 * we optimize an early check to exit out early if we don't have to 1662 * we optimize an early check to exit out early if we don't have to
1135 * do anything */ 1663 * do anything
1136 if (likely(last_request->wiphy)) { 1664 */
1665 if (likely(last_request->initiator ==
1666 NL80211_REGDOM_SET_BY_COUNTRY_IE &&
1667 wiphy_idx_valid(last_request->wiphy_idx))) {
1137 struct cfg80211_registered_device *drv_last_ie; 1668 struct cfg80211_registered_device *drv_last_ie;
1138 1669
1139 drv_last_ie = wiphy_to_dev(last_request->wiphy); 1670 drv_last_ie =
1671 cfg80211_drv_by_wiphy_idx(last_request->wiphy_idx);
1140 1672
1141 /* Lets keep this simple -- we trust the first AP 1673 /*
1142 * after we intersect with CRDA */ 1674 * Lets keep this simple -- we trust the first AP
1143 if (likely(last_request->wiphy == wiphy)) { 1675 * after we intersect with CRDA
1144 /* Ignore IEs coming in on this wiphy with 1676 */
1145 * the same alpha2 and environment cap */ 1677 if (likely(&drv_last_ie->wiphy == wiphy)) {
1678 /*
1679 * Ignore IEs coming in on this wiphy with
1680 * the same alpha2 and environment cap
1681 */
1146 if (likely(alpha2_equal(drv_last_ie->country_ie_alpha2, 1682 if (likely(alpha2_equal(drv_last_ie->country_ie_alpha2,
1147 alpha2) && 1683 alpha2) &&
1148 env == drv_last_ie->env)) { 1684 env == drv_last_ie->env)) {
1149 goto out; 1685 goto out;
1150 } 1686 }
1151 /* the wiphy moved on to another BSSID or the AP 1687 /*
1688 * the wiphy moved on to another BSSID or the AP
1152 * was reconfigured. XXX: We need to deal with the 1689 * was reconfigured. XXX: We need to deal with the
1153 * case where the user suspends and goes to goes 1690 * case where the user suspends and goes to goes
1154 * to another country, and then gets IEs from an 1691 * to another country, and then gets IEs from an
1155 * AP with different settings */ 1692 * AP with different settings
1693 */
1156 goto out; 1694 goto out;
1157 } else { 1695 } else {
1158 /* Ignore IEs coming in on two separate wiphys with 1696 /*
1159 * the same alpha2 and environment cap */ 1697 * Ignore IEs coming in on two separate wiphys with
1698 * the same alpha2 and environment cap
1699 */
1160 if (likely(alpha2_equal(drv_last_ie->country_ie_alpha2, 1700 if (likely(alpha2_equal(drv_last_ie->country_ie_alpha2,
1161 alpha2) && 1701 alpha2) &&
1162 env == drv_last_ie->env)) { 1702 env == drv_last_ie->env)) {
@@ -1171,28 +1711,97 @@ void regulatory_hint_11d(struct wiphy *wiphy,
1171 if (!rd) 1711 if (!rd)
1172 goto out; 1712 goto out;
1173 1713
1174 /* This will not happen right now but we leave it here for the 1714 /*
1715 * This will not happen right now but we leave it here for the
1175 * the future when we want to add suspend/resume support and having 1716 * the future when we want to add suspend/resume support and having
1176 * the user move to another country after doing so, or having the user 1717 * the user move to another country after doing so, or having the user
1177 * move to another AP. Right now we just trust the first AP. This is why 1718 * move to another AP. Right now we just trust the first AP.
1178 * this is marked as likley(). If we hit this before we add this support 1719 *
1179 * we want to be informed of it as it would indicate a mistake in the 1720 * If we hit this before we add this support we want to be informed of
1180 * current design */ 1721 * it as it would indicate a mistake in the current design
1181 if (likely(WARN_ON(reg_same_country_ie_hint(wiphy, checksum)))) 1722 */
1182 goto out; 1723 if (WARN_ON(reg_same_country_ie_hint(wiphy, checksum)))
1724 goto free_rd_out;
1183 1725
1184 /* We keep this around for when CRDA comes back with a response so 1726 request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL);
1185 * we can intersect with that */ 1727 if (!request)
1728 goto free_rd_out;
1729
1730 /*
1731 * We keep this around for when CRDA comes back with a response so
1732 * we can intersect with that
1733 */
1186 country_ie_regdomain = rd; 1734 country_ie_regdomain = rd;
1187 1735
1188 __regulatory_hint(wiphy, REGDOM_SET_BY_COUNTRY_IE, 1736 request->wiphy_idx = get_wiphy_idx(wiphy);
1189 country_ie_regdomain->alpha2, checksum, env); 1737 request->alpha2[0] = rd->alpha2[0];
1738 request->alpha2[1] = rd->alpha2[1];
1739 request->initiator = NL80211_REGDOM_SET_BY_COUNTRY_IE;
1740 request->country_ie_checksum = checksum;
1741 request->country_ie_env = env;
1742
1743 mutex_unlock(&cfg80211_mutex);
1744
1745 queue_regulatory_request(request);
1746
1747 return;
1190 1748
1749free_rd_out:
1750 kfree(rd);
1191out: 1751out:
1192 mutex_unlock(&cfg80211_drv_mutex); 1752 mutex_unlock(&cfg80211_mutex);
1193} 1753}
1194EXPORT_SYMBOL(regulatory_hint_11d); 1754EXPORT_SYMBOL(regulatory_hint_11d);
1195 1755
1756static bool freq_is_chan_12_13_14(u16 freq)
1757{
1758 if (freq == ieee80211_channel_to_frequency(12) ||
1759 freq == ieee80211_channel_to_frequency(13) ||
1760 freq == ieee80211_channel_to_frequency(14))
1761 return true;
1762 return false;
1763}
1764
1765int regulatory_hint_found_beacon(struct wiphy *wiphy,
1766 struct ieee80211_channel *beacon_chan,
1767 gfp_t gfp)
1768{
1769 struct reg_beacon *reg_beacon;
1770
1771 if (likely((beacon_chan->beacon_found ||
1772 (beacon_chan->flags & IEEE80211_CHAN_RADAR) ||
1773 (beacon_chan->band == IEEE80211_BAND_2GHZ &&
1774 !freq_is_chan_12_13_14(beacon_chan->center_freq)))))
1775 return 0;
1776
1777 reg_beacon = kzalloc(sizeof(struct reg_beacon), gfp);
1778 if (!reg_beacon)
1779 return -ENOMEM;
1780
1781#ifdef CONFIG_CFG80211_REG_DEBUG
1782 printk(KERN_DEBUG "cfg80211: Found new beacon on "
1783 "frequency: %d MHz (Ch %d) on %s\n",
1784 beacon_chan->center_freq,
1785 ieee80211_frequency_to_channel(beacon_chan->center_freq),
1786 wiphy_name(wiphy));
1787#endif
1788 memcpy(&reg_beacon->chan, beacon_chan,
1789 sizeof(struct ieee80211_channel));
1790
1791
1792 /*
1793 * Since we can be called from BH or and non-BH context
1794 * we must use spin_lock_bh()
1795 */
1796 spin_lock_bh(&reg_pending_beacons_lock);
1797 list_add_tail(&reg_beacon->list, &reg_pending_beacons);
1798 spin_unlock_bh(&reg_pending_beacons_lock);
1799
1800 schedule_work(&reg_work);
1801
1802 return 0;
1803}
1804
1196static void print_rd_rules(const struct ieee80211_regdomain *rd) 1805static void print_rd_rules(const struct ieee80211_regdomain *rd)
1197{ 1806{
1198 unsigned int i; 1807 unsigned int i;
@@ -1208,8 +1817,10 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd)
1208 freq_range = &reg_rule->freq_range; 1817 freq_range = &reg_rule->freq_range;
1209 power_rule = &reg_rule->power_rule; 1818 power_rule = &reg_rule->power_rule;
1210 1819
1211 /* There may not be documentation for max antenna gain 1820 /*
1212 * in certain regions */ 1821 * There may not be documentation for max antenna gain
1822 * in certain regions
1823 */
1213 if (power_rule->max_antenna_gain) 1824 if (power_rule->max_antenna_gain)
1214 printk(KERN_INFO "\t(%d KHz - %d KHz @ %d KHz), " 1825 printk(KERN_INFO "\t(%d KHz - %d KHz @ %d KHz), "
1215 "(%d mBi, %d mBm)\n", 1826 "(%d mBi, %d mBm)\n",
@@ -1232,13 +1843,13 @@ static void print_regdomain(const struct ieee80211_regdomain *rd)
1232{ 1843{
1233 1844
1234 if (is_intersected_alpha2(rd->alpha2)) { 1845 if (is_intersected_alpha2(rd->alpha2)) {
1235 struct wiphy *wiphy = NULL;
1236 struct cfg80211_registered_device *drv;
1237 1846
1238 if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) { 1847 if (last_request->initiator ==
1239 if (last_request->wiphy) { 1848 NL80211_REGDOM_SET_BY_COUNTRY_IE) {
1240 wiphy = last_request->wiphy; 1849 struct cfg80211_registered_device *drv;
1241 drv = wiphy_to_dev(wiphy); 1850 drv = cfg80211_drv_by_wiphy_idx(
1851 last_request->wiphy_idx);
1852 if (drv) {
1242 printk(KERN_INFO "cfg80211: Current regulatory " 1853 printk(KERN_INFO "cfg80211: Current regulatory "
1243 "domain updated by AP to: %c%c\n", 1854 "domain updated by AP to: %c%c\n",
1244 drv->country_ie_alpha2[0], 1855 drv->country_ie_alpha2[0],
@@ -1248,7 +1859,7 @@ static void print_regdomain(const struct ieee80211_regdomain *rd)
1248 "domain intersected: \n"); 1859 "domain intersected: \n");
1249 } else 1860 } else
1250 printk(KERN_INFO "cfg80211: Current regulatory " 1861 printk(KERN_INFO "cfg80211: Current regulatory "
1251 "intersected: \n"); 1862 "domain intersected: \n");
1252 } else if (is_world_regdom(rd->alpha2)) 1863 } else if (is_world_regdom(rd->alpha2))
1253 printk(KERN_INFO "cfg80211: World regulatory " 1864 printk(KERN_INFO "cfg80211: World regulatory "
1254 "domain updated:\n"); 1865 "domain updated:\n");
@@ -1304,7 +1915,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
1304{ 1915{
1305 const struct ieee80211_regdomain *intersected_rd = NULL; 1916 const struct ieee80211_regdomain *intersected_rd = NULL;
1306 struct cfg80211_registered_device *drv = NULL; 1917 struct cfg80211_registered_device *drv = NULL;
1307 struct wiphy *wiphy = NULL; 1918 struct wiphy *request_wiphy;
1308 /* Some basic sanity checks first */ 1919 /* Some basic sanity checks first */
1309 1920
1310 if (is_world_regdom(rd->alpha2)) { 1921 if (is_world_regdom(rd->alpha2)) {
@@ -1321,23 +1932,27 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
1321 if (!last_request) 1932 if (!last_request)
1322 return -EINVAL; 1933 return -EINVAL;
1323 1934
1324 /* Lets only bother proceeding on the same alpha2 if the current 1935 /*
1936 * Lets only bother proceeding on the same alpha2 if the current
1325 * rd is non static (it means CRDA was present and was used last) 1937 * rd is non static (it means CRDA was present and was used last)
1326 * and the pending request came in from a country IE */ 1938 * and the pending request came in from a country IE
1327 if (last_request->initiator != REGDOM_SET_BY_COUNTRY_IE) { 1939 */
1328 /* If someone else asked us to change the rd lets only bother 1940 if (last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) {
1329 * checking if the alpha2 changes if CRDA was already called */ 1941 /*
1942 * If someone else asked us to change the rd lets only bother
1943 * checking if the alpha2 changes if CRDA was already called
1944 */
1330 if (!is_old_static_regdom(cfg80211_regdomain) && 1945 if (!is_old_static_regdom(cfg80211_regdomain) &&
1331 !regdom_changed(rd->alpha2)) 1946 !regdom_changes(rd->alpha2))
1332 return -EINVAL; 1947 return -EINVAL;
1333 } 1948 }
1334 1949
1335 wiphy = last_request->wiphy; 1950 /*
1336 1951 * Now lets set the regulatory domain, update all driver channels
1337 /* Now lets set the regulatory domain, update all driver channels
1338 * and finally inform them of what we have done, in case they want 1952 * and finally inform them of what we have done, in case they want
1339 * to review or adjust their own settings based on their own 1953 * to review or adjust their own settings based on their own
1340 * internal EEPROM data */ 1954 * internal EEPROM data
1955 */
1341 1956
1342 if (WARN_ON(!reg_is_valid_request(rd->alpha2))) 1957 if (WARN_ON(!reg_is_valid_request(rd->alpha2)))
1343 return -EINVAL; 1958 return -EINVAL;
@@ -1349,7 +1964,28 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
1349 return -EINVAL; 1964 return -EINVAL;
1350 } 1965 }
1351 1966
1967 request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx);
1968
1352 if (!last_request->intersect) { 1969 if (!last_request->intersect) {
1970 int r;
1971
1972 if (last_request->initiator != NL80211_REGDOM_SET_BY_DRIVER) {
1973 reset_regdomains();
1974 cfg80211_regdomain = rd;
1975 return 0;
1976 }
1977
1978 /*
1979 * For a driver hint, lets copy the regulatory domain the
1980 * driver wanted to the wiphy to deal with conflicts
1981 */
1982
1983 BUG_ON(request_wiphy->regd);
1984
1985 r = reg_copy_regd(&request_wiphy->regd, rd);
1986 if (r)
1987 return r;
1988
1353 reset_regdomains(); 1989 reset_regdomains();
1354 cfg80211_regdomain = rd; 1990 cfg80211_regdomain = rd;
1355 return 0; 1991 return 0;
@@ -1357,14 +1993,22 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
1357 1993
1358 /* Intersection requires a bit more work */ 1994 /* Intersection requires a bit more work */
1359 1995
1360 if (last_request->initiator != REGDOM_SET_BY_COUNTRY_IE) { 1996 if (last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) {
1361 1997
1362 intersected_rd = regdom_intersect(rd, cfg80211_regdomain); 1998 intersected_rd = regdom_intersect(rd, cfg80211_regdomain);
1363 if (!intersected_rd) 1999 if (!intersected_rd)
1364 return -EINVAL; 2000 return -EINVAL;
1365 2001
1366 /* We can trash what CRDA provided now */ 2002 /*
1367 kfree(rd); 2003 * We can trash what CRDA provided now.
2004 * However if a driver requested this specific regulatory
2005 * domain we keep it for its private use
2006 */
2007 if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER)
2008 request_wiphy->regd = rd;
2009 else
2010 kfree(rd);
2011
1368 rd = NULL; 2012 rd = NULL;
1369 2013
1370 reset_regdomains(); 2014 reset_regdomains();
@@ -1379,29 +2023,26 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
1379 */ 2023 */
1380 2024
1381 BUG_ON(!country_ie_regdomain); 2025 BUG_ON(!country_ie_regdomain);
2026 BUG_ON(rd == country_ie_regdomain);
1382 2027
1383 if (rd != country_ie_regdomain) { 2028 /*
1384 /* Intersect what CRDA returned and our what we 2029 * Intersect what CRDA returned and our what we
1385 * had built from the Country IE received */ 2030 * had built from the Country IE received
2031 */
1386 2032
1387 intersected_rd = regdom_intersect(rd, country_ie_regdomain); 2033 intersected_rd = regdom_intersect(rd, country_ie_regdomain);
1388 2034
1389 reg_country_ie_process_debug(rd, country_ie_regdomain, 2035 reg_country_ie_process_debug(rd,
1390 intersected_rd); 2036 country_ie_regdomain,
2037 intersected_rd);
1391 2038
1392 kfree(country_ie_regdomain); 2039 kfree(country_ie_regdomain);
1393 country_ie_regdomain = NULL; 2040 country_ie_regdomain = NULL;
1394 } else {
1395 /* This would happen when CRDA was not present and
1396 * OLD_REGULATORY was enabled. We intersect our Country
1397 * IE rd and what was set on cfg80211 originally */
1398 intersected_rd = regdom_intersect(rd, cfg80211_regdomain);
1399 }
1400 2041
1401 if (!intersected_rd) 2042 if (!intersected_rd)
1402 return -EINVAL; 2043 return -EINVAL;
1403 2044
1404 drv = wiphy_to_dev(wiphy); 2045 drv = wiphy_to_dev(request_wiphy);
1405 2046
1406 drv->country_ie_alpha2[0] = rd->alpha2[0]; 2047 drv->country_ie_alpha2[0] = rd->alpha2[0];
1407 drv->country_ie_alpha2[1] = rd->alpha2[1]; 2048 drv->country_ie_alpha2[1] = rd->alpha2[1];
@@ -1419,13 +2060,17 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
1419} 2060}
1420 2061
1421 2062
1422/* Use this call to set the current regulatory domain. Conflicts with 2063/*
2064 * Use this call to set the current regulatory domain. Conflicts with
1423 * multiple drivers can be ironed out later. Caller must've already 2065 * multiple drivers can be ironed out later. Caller must've already
1424 * kmalloc'd the rd structure. Caller must hold cfg80211_drv_mutex */ 2066 * kmalloc'd the rd structure. Caller must hold cfg80211_mutex
2067 */
1425int set_regdom(const struct ieee80211_regdomain *rd) 2068int set_regdom(const struct ieee80211_regdomain *rd)
1426{ 2069{
1427 int r; 2070 int r;
1428 2071
2072 assert_cfg80211_lock();
2073
1429 /* Note that this doesn't update the wiphys, this is done below */ 2074 /* Note that this doesn't update the wiphys, this is done below */
1430 r = __set_regdom(rd); 2075 r = __set_regdom(rd);
1431 if (r) { 2076 if (r) {
@@ -1442,56 +2087,90 @@ int set_regdom(const struct ieee80211_regdomain *rd)
1442 2087
1443 print_regdomain(cfg80211_regdomain); 2088 print_regdomain(cfg80211_regdomain);
1444 2089
2090 nl80211_send_reg_change_event(last_request);
2091
1445 return r; 2092 return r;
1446} 2093}
1447 2094
1448/* Caller must hold cfg80211_drv_mutex */ 2095/* Caller must hold cfg80211_mutex */
1449void reg_device_remove(struct wiphy *wiphy) 2096void reg_device_remove(struct wiphy *wiphy)
1450{ 2097{
1451 if (!last_request || !last_request->wiphy) 2098 struct wiphy *request_wiphy;
2099
2100 assert_cfg80211_lock();
2101
2102 request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx);
2103
2104 kfree(wiphy->regd);
2105 if (!last_request || !request_wiphy)
1452 return; 2106 return;
1453 if (last_request->wiphy != wiphy) 2107 if (request_wiphy != wiphy)
1454 return; 2108 return;
1455 last_request->wiphy = NULL; 2109 last_request->wiphy_idx = WIPHY_IDX_STALE;
1456 last_request->country_ie_env = ENVIRON_ANY; 2110 last_request->country_ie_env = ENVIRON_ANY;
1457} 2111}
1458 2112
1459int regulatory_init(void) 2113int regulatory_init(void)
1460{ 2114{
1461 int err; 2115 int err = 0;
1462 2116
1463 reg_pdev = platform_device_register_simple("regulatory", 0, NULL, 0); 2117 reg_pdev = platform_device_register_simple("regulatory", 0, NULL, 0);
1464 if (IS_ERR(reg_pdev)) 2118 if (IS_ERR(reg_pdev))
1465 return PTR_ERR(reg_pdev); 2119 return PTR_ERR(reg_pdev);
1466 2120
2121 spin_lock_init(&reg_requests_lock);
2122 spin_lock_init(&reg_pending_beacons_lock);
2123
1467#ifdef CONFIG_WIRELESS_OLD_REGULATORY 2124#ifdef CONFIG_WIRELESS_OLD_REGULATORY
1468 cfg80211_regdomain = static_regdom(ieee80211_regdom); 2125 cfg80211_regdomain = static_regdom(ieee80211_regdom);
1469 2126
1470 printk(KERN_INFO "cfg80211: Using static regulatory domain info\n"); 2127 printk(KERN_INFO "cfg80211: Using static regulatory domain info\n");
1471 print_regdomain_info(cfg80211_regdomain); 2128 print_regdomain_info(cfg80211_regdomain);
1472 /* The old code still requests for a new regdomain and if 2129 /*
2130 * The old code still requests for a new regdomain and if
1473 * you have CRDA you get it updated, otherwise you get 2131 * you have CRDA you get it updated, otherwise you get
1474 * stuck with the static values. We ignore "EU" code as 2132 * stuck with the static values. Since "EU" is not a valid
1475 * that is not a valid ISO / IEC 3166 alpha2 */ 2133 * ISO / IEC 3166 alpha2 code we can't expect userpace to
1476 if (ieee80211_regdom[0] != 'E' || ieee80211_regdom[1] != 'U') 2134 * give us a regulatory domain for it. We need last_request
1477 err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, 2135 * iniitalized though so lets just send a request which we
1478 ieee80211_regdom, 0, ENVIRON_ANY); 2136 * know will be ignored... this crap will be removed once
2137 * OLD_REG dies.
2138 */
2139 err = regulatory_hint_core(ieee80211_regdom);
1479#else 2140#else
1480 cfg80211_regdomain = cfg80211_world_regdom; 2141 cfg80211_regdomain = cfg80211_world_regdom;
1481 2142
1482 err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, "00", 0, ENVIRON_ANY); 2143 err = regulatory_hint_core(ieee80211_regdom);
1483 if (err) 2144#endif
1484 printk(KERN_ERR "cfg80211: calling CRDA failed - " 2145 if (err) {
1485 "unable to update world regulatory domain, " 2146 if (err == -ENOMEM)
1486 "using static definition\n"); 2147 return err;
2148 /*
2149 * N.B. kobject_uevent_env() can fail mainly for when we're out
2150 * memory which is handled and propagated appropriately above
2151 * but it can also fail during a netlink_broadcast() or during
2152 * early boot for call_usermodehelper(). For now treat these
2153 * errors as non-fatal.
2154 */
2155 printk(KERN_ERR "cfg80211: kobject_uevent_env() was unable "
2156 "to call CRDA during init");
2157#ifdef CONFIG_CFG80211_REG_DEBUG
2158 /* We want to find out exactly why when debugging */
2159 WARN_ON(err);
1487#endif 2160#endif
2161 }
1488 2162
1489 return 0; 2163 return 0;
1490} 2164}
1491 2165
1492void regulatory_exit(void) 2166void regulatory_exit(void)
1493{ 2167{
1494 mutex_lock(&cfg80211_drv_mutex); 2168 struct regulatory_request *reg_request, *tmp;
2169 struct reg_beacon *reg_beacon, *btmp;
2170
2171 cancel_work_sync(&reg_work);
2172
2173 mutex_lock(&cfg80211_mutex);
1495 2174
1496 reset_regdomains(); 2175 reset_regdomains();
1497 2176
@@ -1502,5 +2181,33 @@ void regulatory_exit(void)
1502 2181
1503 platform_device_unregister(reg_pdev); 2182 platform_device_unregister(reg_pdev);
1504 2183
1505 mutex_unlock(&cfg80211_drv_mutex); 2184 spin_lock_bh(&reg_pending_beacons_lock);
2185 if (!list_empty(&reg_pending_beacons)) {
2186 list_for_each_entry_safe(reg_beacon, btmp,
2187 &reg_pending_beacons, list) {
2188 list_del(&reg_beacon->list);
2189 kfree(reg_beacon);
2190 }
2191 }
2192 spin_unlock_bh(&reg_pending_beacons_lock);
2193
2194 if (!list_empty(&reg_beacon_list)) {
2195 list_for_each_entry_safe(reg_beacon, btmp,
2196 &reg_beacon_list, list) {
2197 list_del(&reg_beacon->list);
2198 kfree(reg_beacon);
2199 }
2200 }
2201
2202 spin_lock(&reg_requests_lock);
2203 if (!list_empty(&reg_requests_list)) {
2204 list_for_each_entry_safe(reg_request, tmp,
2205 &reg_requests_list, list) {
2206 list_del(&reg_request->list);
2207 kfree(reg_request);
2208 }
2209 }
2210 spin_unlock(&reg_requests_lock);
2211
2212 mutex_unlock(&cfg80211_mutex);
1506} 2213}
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index a76ea3ff7cd6..e37829a49dc4 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -1,9 +1,13 @@
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
4extern const struct ieee80211_regdomain *cfg80211_regdomain;
5
4bool is_world_regdom(const char *alpha2); 6bool is_world_regdom(const char *alpha2);
5bool reg_is_valid_request(const char *alpha2); 7bool reg_is_valid_request(const char *alpha2);
6 8
9int regulatory_hint_user(const char *alpha2);
10
7void reg_device_remove(struct wiphy *wiphy); 11void reg_device_remove(struct wiphy *wiphy);
8 12
9int regulatory_init(void); 13int regulatory_init(void);
@@ -11,34 +15,25 @@ void regulatory_exit(void);
11 15
12int set_regdom(const struct ieee80211_regdomain *rd); 16int set_regdom(const struct ieee80211_regdomain *rd);
13 17
14enum environment_cap {
15 ENVIRON_ANY,
16 ENVIRON_INDOOR,
17 ENVIRON_OUTDOOR,
18};
19
20
21/** 18/**
22 * __regulatory_hint - hint to the wireless core a regulatory domain 19 * regulatory_hint_found_beacon - hints a beacon was found on a channel
23 * @wiphy: if the hint comes from country information from an AP, this 20 * @wiphy: the wireless device where the beacon was found on
24 * is required to be set to the wiphy that received the information 21 * @beacon_chan: the channel on which the beacon was found on
25 * @alpha2: the ISO/IEC 3166 alpha2 being claimed the regulatory domain 22 * @gfp: context flags
26 * should be in.
27 * @country_ie_checksum: checksum of processed country IE, set this to 0
28 * if the hint did not come from a country IE
29 * @country_ie_env: the environment the IE told us we are in, %ENVIRON_*
30 *
31 * The Wireless subsystem can use this function to hint to the wireless core
32 * what it believes should be the current regulatory domain by giving it an
33 * ISO/IEC 3166 alpha2 country code it knows its regulatory domain should be
34 * in.
35 * 23 *
36 * Returns zero if all went fine, %-EALREADY if a regulatory domain had 24 * This informs the wireless core that a beacon from an AP was found on
37 * already been set or other standard error codes. 25 * the channel provided. This allows the wireless core to make educated
26 * guesses on regulatory to help with world roaming. This is only used for
27 * world roaming -- when we do not know our current location. This is
28 * only useful on channels 12, 13 and 14 on the 2 GHz band as channels
29 * 1-11 are already enabled by the world regulatory domain; and on
30 * non-radar 5 GHz channels.
38 * 31 *
32 * Drivers do not need to call this, cfg80211 will do it for after a scan
33 * on a newly found BSS.
39 */ 34 */
40extern int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by, 35int regulatory_hint_found_beacon(struct wiphy *wiphy,
41 const char *alpha2, u32 country_ie_checksum, 36 struct ieee80211_channel *beacon_chan,
42 enum environment_cap country_ie_env); 37 gfp_t gfp);
43 38
44#endif /* __NET_WIRELESS_REG_H */ 39#endif /* __NET_WIRELESS_REG_H */
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
new file mode 100644
index 000000000000..2a00e362f5fe
--- /dev/null
+++ b/net/wireless/scan.c
@@ -0,0 +1,891 @@
1/*
2 * cfg80211 scan result handling
3 *
4 * Copyright 2008 Johannes Berg <johannes@sipsolutions.net>
5 */
6#include <linux/kernel.h>
7#include <linux/module.h>
8#include <linux/netdevice.h>
9#include <linux/wireless.h>
10#include <linux/nl80211.h>
11#include <linux/etherdevice.h>
12#include <net/arp.h>
13#include <net/cfg80211.h>
14#include <net/iw_handler.h>
15#include "core.h"
16#include "nl80211.h"
17
18#define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ)
19
20void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
21{
22 struct net_device *dev;
23#ifdef CONFIG_WIRELESS_EXT
24 union iwreq_data wrqu;
25#endif
26
27 dev = dev_get_by_index(&init_net, request->ifidx);
28 if (!dev)
29 goto out;
30
31 WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req);
32 wiphy_to_dev(request->wiphy)->scan_req = NULL;
33
34 if (aborted)
35 nl80211_send_scan_aborted(wiphy_to_dev(request->wiphy), dev);
36 else
37 nl80211_send_scan_done(wiphy_to_dev(request->wiphy), dev);
38
39#ifdef CONFIG_WIRELESS_EXT
40 if (!aborted) {
41 memset(&wrqu, 0, sizeof(wrqu));
42
43 wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
44 }
45#endif
46
47 dev_put(dev);
48
49 out:
50 kfree(request);
51}
52EXPORT_SYMBOL(cfg80211_scan_done);
53
54static void bss_release(struct kref *ref)
55{
56 struct cfg80211_internal_bss *bss;
57
58 bss = container_of(ref, struct cfg80211_internal_bss, ref);
59 if (bss->pub.free_priv)
60 bss->pub.free_priv(&bss->pub);
61 kfree(bss);
62}
63
64/* must hold dev->bss_lock! */
65void cfg80211_bss_age(struct cfg80211_registered_device *dev,
66 unsigned long age_secs)
67{
68 struct cfg80211_internal_bss *bss;
69 unsigned long age_jiffies = msecs_to_jiffies(age_secs * MSEC_PER_SEC);
70
71 list_for_each_entry(bss, &dev->bss_list, list) {
72 bss->ts -= age_jiffies;
73 }
74}
75
76/* must hold dev->bss_lock! */
77void cfg80211_bss_expire(struct cfg80211_registered_device *dev)
78{
79 struct cfg80211_internal_bss *bss, *tmp;
80 bool expired = false;
81
82 list_for_each_entry_safe(bss, tmp, &dev->bss_list, list) {
83 if (bss->hold ||
84 !time_after(jiffies, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE))
85 continue;
86 list_del(&bss->list);
87 rb_erase(&bss->rbn, &dev->bss_tree);
88 kref_put(&bss->ref, bss_release);
89 expired = true;
90 }
91
92 if (expired)
93 dev->bss_generation++;
94}
95
96static u8 *find_ie(u8 num, u8 *ies, size_t len)
97{
98 while (len > 2 && ies[0] != num) {
99 len -= ies[1] + 2;
100 ies += ies[1] + 2;
101 }
102 if (len < 2)
103 return NULL;
104 if (len < 2 + ies[1])
105 return NULL;
106 return ies;
107}
108
109static int cmp_ies(u8 num, u8 *ies1, size_t len1, u8 *ies2, size_t len2)
110{
111 const u8 *ie1 = find_ie(num, ies1, len1);
112 const u8 *ie2 = find_ie(num, ies2, len2);
113 int r;
114
115 if (!ie1 && !ie2)
116 return 0;
117 if (!ie1)
118 return -1;
119
120 r = memcmp(ie1 + 2, ie2 + 2, min(ie1[1], ie2[1]));
121 if (r == 0 && ie1[1] != ie2[1])
122 return ie2[1] - ie1[1];
123 return r;
124}
125
126static bool is_bss(struct cfg80211_bss *a,
127 const u8 *bssid,
128 const u8 *ssid, size_t ssid_len)
129{
130 const u8 *ssidie;
131
132 if (bssid && compare_ether_addr(a->bssid, bssid))
133 return false;
134
135 if (!ssid)
136 return true;
137
138 ssidie = find_ie(WLAN_EID_SSID,
139 a->information_elements,
140 a->len_information_elements);
141 if (!ssidie)
142 return false;
143 if (ssidie[1] != ssid_len)
144 return false;
145 return memcmp(ssidie + 2, ssid, ssid_len) == 0;
146}
147
148static bool is_mesh(struct cfg80211_bss *a,
149 const u8 *meshid, size_t meshidlen,
150 const u8 *meshcfg)
151{
152 const u8 *ie;
153
154 if (!is_zero_ether_addr(a->bssid))
155 return false;
156
157 ie = find_ie(WLAN_EID_MESH_ID,
158 a->information_elements,
159 a->len_information_elements);
160 if (!ie)
161 return false;
162 if (ie[1] != meshidlen)
163 return false;
164 if (memcmp(ie + 2, meshid, meshidlen))
165 return false;
166
167 ie = find_ie(WLAN_EID_MESH_CONFIG,
168 a->information_elements,
169 a->len_information_elements);
170 if (ie[1] != IEEE80211_MESH_CONFIG_LEN)
171 return false;
172
173 /*
174 * Ignore mesh capability (last two bytes of the IE) when
175 * comparing since that may differ between stations taking
176 * part in the same mesh.
177 */
178 return memcmp(ie + 2, meshcfg, IEEE80211_MESH_CONFIG_LEN - 2) == 0;
179}
180
181static int cmp_bss(struct cfg80211_bss *a,
182 struct cfg80211_bss *b)
183{
184 int r;
185
186 if (a->channel != b->channel)
187 return b->channel->center_freq - a->channel->center_freq;
188
189 r = memcmp(a->bssid, b->bssid, ETH_ALEN);
190 if (r)
191 return r;
192
193 if (is_zero_ether_addr(a->bssid)) {
194 r = cmp_ies(WLAN_EID_MESH_ID,
195 a->information_elements,
196 a->len_information_elements,
197 b->information_elements,
198 b->len_information_elements);
199 if (r)
200 return r;
201 return cmp_ies(WLAN_EID_MESH_CONFIG,
202 a->information_elements,
203 a->len_information_elements,
204 b->information_elements,
205 b->len_information_elements);
206 }
207
208 return cmp_ies(WLAN_EID_SSID,
209 a->information_elements,
210 a->len_information_elements,
211 b->information_elements,
212 b->len_information_elements);
213}
214
215struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy,
216 struct ieee80211_channel *channel,
217 const u8 *bssid,
218 const u8 *ssid, size_t ssid_len,
219 u16 capa_mask, u16 capa_val)
220{
221 struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy);
222 struct cfg80211_internal_bss *bss, *res = NULL;
223
224 spin_lock_bh(&dev->bss_lock);
225
226 list_for_each_entry(bss, &dev->bss_list, list) {
227 if ((bss->pub.capability & capa_mask) != capa_val)
228 continue;
229 if (channel && bss->pub.channel != channel)
230 continue;
231 if (is_bss(&bss->pub, bssid, ssid, ssid_len)) {
232 res = bss;
233 kref_get(&res->ref);
234 break;
235 }
236 }
237
238 spin_unlock_bh(&dev->bss_lock);
239 if (!res)
240 return NULL;
241 return &res->pub;
242}
243EXPORT_SYMBOL(cfg80211_get_bss);
244
245struct cfg80211_bss *cfg80211_get_mesh(struct wiphy *wiphy,
246 struct ieee80211_channel *channel,
247 const u8 *meshid, size_t meshidlen,
248 const u8 *meshcfg)
249{
250 struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy);
251 struct cfg80211_internal_bss *bss, *res = NULL;
252
253 spin_lock_bh(&dev->bss_lock);
254
255 list_for_each_entry(bss, &dev->bss_list, list) {
256 if (channel && bss->pub.channel != channel)
257 continue;
258 if (is_mesh(&bss->pub, meshid, meshidlen, meshcfg)) {
259 res = bss;
260 kref_get(&res->ref);
261 break;
262 }
263 }
264
265 spin_unlock_bh(&dev->bss_lock);
266 if (!res)
267 return NULL;
268 return &res->pub;
269}
270EXPORT_SYMBOL(cfg80211_get_mesh);
271
272
273static void rb_insert_bss(struct cfg80211_registered_device *dev,
274 struct cfg80211_internal_bss *bss)
275{
276 struct rb_node **p = &dev->bss_tree.rb_node;
277 struct rb_node *parent = NULL;
278 struct cfg80211_internal_bss *tbss;
279 int cmp;
280
281 while (*p) {
282 parent = *p;
283 tbss = rb_entry(parent, struct cfg80211_internal_bss, rbn);
284
285 cmp = cmp_bss(&bss->pub, &tbss->pub);
286
287 if (WARN_ON(!cmp)) {
288 /* will sort of leak this BSS */
289 return;
290 }
291
292 if (cmp < 0)
293 p = &(*p)->rb_left;
294 else
295 p = &(*p)->rb_right;
296 }
297
298 rb_link_node(&bss->rbn, parent, p);
299 rb_insert_color(&bss->rbn, &dev->bss_tree);
300}
301
302static struct cfg80211_internal_bss *
303rb_find_bss(struct cfg80211_registered_device *dev,
304 struct cfg80211_internal_bss *res)
305{
306 struct rb_node *n = dev->bss_tree.rb_node;
307 struct cfg80211_internal_bss *bss;
308 int r;
309
310 while (n) {
311 bss = rb_entry(n, struct cfg80211_internal_bss, rbn);
312 r = cmp_bss(&res->pub, &bss->pub);
313
314 if (r == 0)
315 return bss;
316 else if (r < 0)
317 n = n->rb_left;
318 else
319 n = n->rb_right;
320 }
321
322 return NULL;
323}
324
325static struct cfg80211_internal_bss *
326cfg80211_bss_update(struct cfg80211_registered_device *dev,
327 struct cfg80211_internal_bss *res,
328 bool overwrite)
329{
330 struct cfg80211_internal_bss *found = NULL;
331 const u8 *meshid, *meshcfg;
332
333 /*
334 * The reference to "res" is donated to this function.
335 */
336
337 if (WARN_ON(!res->pub.channel)) {
338 kref_put(&res->ref, bss_release);
339 return NULL;
340 }
341
342 res->ts = jiffies;
343
344 if (is_zero_ether_addr(res->pub.bssid)) {
345 /* must be mesh, verify */
346 meshid = find_ie(WLAN_EID_MESH_ID, res->pub.information_elements,
347 res->pub.len_information_elements);
348 meshcfg = find_ie(WLAN_EID_MESH_CONFIG,
349 res->pub.information_elements,
350 res->pub.len_information_elements);
351 if (!meshid || !meshcfg ||
352 meshcfg[1] != IEEE80211_MESH_CONFIG_LEN) {
353 /* bogus mesh */
354 kref_put(&res->ref, bss_release);
355 return NULL;
356 }
357 }
358
359 spin_lock_bh(&dev->bss_lock);
360
361 found = rb_find_bss(dev, res);
362
363 if (found && overwrite) {
364 list_replace(&found->list, &res->list);
365 rb_replace_node(&found->rbn, &res->rbn,
366 &dev->bss_tree);
367 kref_put(&found->ref, bss_release);
368 found = res;
369 } else if (found) {
370 kref_get(&found->ref);
371 found->pub.beacon_interval = res->pub.beacon_interval;
372 found->pub.tsf = res->pub.tsf;
373 found->pub.signal = res->pub.signal;
374 found->pub.capability = res->pub.capability;
375 found->ts = res->ts;
376 kref_put(&res->ref, bss_release);
377 } else {
378 /* this "consumes" the reference */
379 list_add_tail(&res->list, &dev->bss_list);
380 rb_insert_bss(dev, res);
381 found = res;
382 }
383
384 dev->bss_generation++;
385 spin_unlock_bh(&dev->bss_lock);
386
387 kref_get(&found->ref);
388 return found;
389}
390
391struct cfg80211_bss *
392cfg80211_inform_bss_frame(struct wiphy *wiphy,
393 struct ieee80211_channel *channel,
394 struct ieee80211_mgmt *mgmt, size_t len,
395 s32 signal, gfp_t gfp)
396{
397 struct cfg80211_internal_bss *res;
398 size_t ielen = len - offsetof(struct ieee80211_mgmt,
399 u.probe_resp.variable);
400 bool overwrite;
401 size_t privsz = wiphy->bss_priv_size;
402
403 if (WARN_ON(wiphy->signal_type == NL80211_BSS_SIGNAL_UNSPEC &&
404 (signal < 0 || signal > 100)))
405 return NULL;
406
407 if (WARN_ON(!mgmt || !wiphy ||
408 len < offsetof(struct ieee80211_mgmt, u.probe_resp.variable)))
409 return NULL;
410
411 res = kzalloc(sizeof(*res) + privsz + ielen, gfp);
412 if (!res)
413 return NULL;
414
415 memcpy(res->pub.bssid, mgmt->bssid, ETH_ALEN);
416 res->pub.channel = channel;
417 res->pub.signal = signal;
418 res->pub.tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp);
419 res->pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int);
420 res->pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info);
421 /* point to after the private area */
422 res->pub.information_elements = (u8 *)res + sizeof(*res) + privsz;
423 memcpy(res->pub.information_elements, mgmt->u.probe_resp.variable, ielen);
424 res->pub.len_information_elements = ielen;
425
426 kref_init(&res->ref);
427
428 overwrite = ieee80211_is_probe_resp(mgmt->frame_control);
429
430 res = cfg80211_bss_update(wiphy_to_dev(wiphy), res, overwrite);
431 if (!res)
432 return NULL;
433
434 if (res->pub.capability & WLAN_CAPABILITY_ESS)
435 regulatory_hint_found_beacon(wiphy, channel, gfp);
436
437 /* cfg80211_bss_update gives us a referenced result */
438 return &res->pub;
439}
440EXPORT_SYMBOL(cfg80211_inform_bss_frame);
441
442void cfg80211_put_bss(struct cfg80211_bss *pub)
443{
444 struct cfg80211_internal_bss *bss;
445
446 if (!pub)
447 return;
448
449 bss = container_of(pub, struct cfg80211_internal_bss, pub);
450 kref_put(&bss->ref, bss_release);
451}
452EXPORT_SYMBOL(cfg80211_put_bss);
453
454void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub)
455{
456 struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy);
457 struct cfg80211_internal_bss *bss;
458
459 if (WARN_ON(!pub))
460 return;
461
462 bss = container_of(pub, struct cfg80211_internal_bss, pub);
463
464 spin_lock_bh(&dev->bss_lock);
465
466 list_del(&bss->list);
467 rb_erase(&bss->rbn, &dev->bss_tree);
468
469 spin_unlock_bh(&dev->bss_lock);
470
471 kref_put(&bss->ref, bss_release);
472}
473EXPORT_SYMBOL(cfg80211_unlink_bss);
474
475void cfg80211_hold_bss(struct cfg80211_bss *pub)
476{
477 struct cfg80211_internal_bss *bss;
478
479 if (!pub)
480 return;
481
482 bss = container_of(pub, struct cfg80211_internal_bss, pub);
483 bss->hold = true;
484}
485EXPORT_SYMBOL(cfg80211_hold_bss);
486
487void cfg80211_unhold_bss(struct cfg80211_bss *pub)
488{
489 struct cfg80211_internal_bss *bss;
490
491 if (!pub)
492 return;
493
494 bss = container_of(pub, struct cfg80211_internal_bss, pub);
495 bss->hold = false;
496}
497EXPORT_SYMBOL(cfg80211_unhold_bss);
498
499#ifdef CONFIG_WIRELESS_EXT
500int cfg80211_wext_siwscan(struct net_device *dev,
501 struct iw_request_info *info,
502 union iwreq_data *wrqu, char *extra)
503{
504 struct cfg80211_registered_device *rdev;
505 struct wiphy *wiphy;
506 struct iw_scan_req *wreq = NULL;
507 struct cfg80211_scan_request *creq;
508 int i, err, n_channels = 0;
509 enum ieee80211_band band;
510
511 if (!netif_running(dev))
512 return -ENETDOWN;
513
514 rdev = cfg80211_get_dev_from_ifindex(dev->ifindex);
515
516 if (IS_ERR(rdev))
517 return PTR_ERR(rdev);
518
519 if (rdev->scan_req) {
520 err = -EBUSY;
521 goto out;
522 }
523
524 wiphy = &rdev->wiphy;
525
526 for (band = 0; band < IEEE80211_NUM_BANDS; band++)
527 if (wiphy->bands[band])
528 n_channels += wiphy->bands[band]->n_channels;
529
530 creq = kzalloc(sizeof(*creq) + sizeof(struct cfg80211_ssid) +
531 n_channels * sizeof(void *),
532 GFP_ATOMIC);
533 if (!creq) {
534 err = -ENOMEM;
535 goto out;
536 }
537
538 creq->wiphy = wiphy;
539 creq->ifidx = dev->ifindex;
540 creq->ssids = (void *)(creq + 1);
541 creq->channels = (void *)(creq->ssids + 1);
542 creq->n_channels = n_channels;
543 creq->n_ssids = 1;
544
545 /* all channels */
546 i = 0;
547 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
548 int j;
549 if (!wiphy->bands[band])
550 continue;
551 for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
552 creq->channels[i] = &wiphy->bands[band]->channels[j];
553 i++;
554 }
555 }
556
557 /* translate scan request */
558 if (wrqu->data.length == sizeof(struct iw_scan_req)) {
559 wreq = (struct iw_scan_req *)extra;
560
561 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
562 if (wreq->essid_len > IEEE80211_MAX_SSID_LEN)
563 return -EINVAL;
564 memcpy(creq->ssids[0].ssid, wreq->essid, wreq->essid_len);
565 creq->ssids[0].ssid_len = wreq->essid_len;
566 }
567 if (wreq->scan_type == IW_SCAN_TYPE_PASSIVE)
568 creq->n_ssids = 0;
569 }
570
571 rdev->scan_req = creq;
572 err = rdev->ops->scan(wiphy, dev, creq);
573 if (err) {
574 rdev->scan_req = NULL;
575 kfree(creq);
576 }
577 out:
578 cfg80211_put_dev(rdev);
579 return err;
580}
581EXPORT_SYMBOL(cfg80211_wext_siwscan);
582
583static void ieee80211_scan_add_ies(struct iw_request_info *info,
584 struct cfg80211_bss *bss,
585 char **current_ev, char *end_buf)
586{
587 u8 *pos, *end, *next;
588 struct iw_event iwe;
589
590 if (!bss->information_elements ||
591 !bss->len_information_elements)
592 return;
593
594 /*
595 * If needed, fragment the IEs buffer (at IE boundaries) into short
596 * enough fragments to fit into IW_GENERIC_IE_MAX octet messages.
597 */
598 pos = bss->information_elements;
599 end = pos + bss->len_information_elements;
600
601 while (end - pos > IW_GENERIC_IE_MAX) {
602 next = pos + 2 + pos[1];
603 while (next + 2 + next[1] - pos < IW_GENERIC_IE_MAX)
604 next = next + 2 + next[1];
605
606 memset(&iwe, 0, sizeof(iwe));
607 iwe.cmd = IWEVGENIE;
608 iwe.u.data.length = next - pos;
609 *current_ev = iwe_stream_add_point(info, *current_ev,
610 end_buf, &iwe, pos);
611
612 pos = next;
613 }
614
615 if (end > pos) {
616 memset(&iwe, 0, sizeof(iwe));
617 iwe.cmd = IWEVGENIE;
618 iwe.u.data.length = end - pos;
619 *current_ev = iwe_stream_add_point(info, *current_ev,
620 end_buf, &iwe, pos);
621 }
622}
623
624static inline unsigned int elapsed_jiffies_msecs(unsigned long start)
625{
626 unsigned long end = jiffies;
627
628 if (end >= start)
629 return jiffies_to_msecs(end - start);
630
631 return jiffies_to_msecs(end + (MAX_JIFFY_OFFSET - start) + 1);
632}
633
634static char *
635ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,
636 struct cfg80211_internal_bss *bss, char *current_ev,
637 char *end_buf)
638{
639 struct iw_event iwe;
640 u8 *buf, *cfg, *p;
641 u8 *ie = bss->pub.information_elements;
642 int rem = bss->pub.len_information_elements, i, sig;
643 bool ismesh = false;
644
645 memset(&iwe, 0, sizeof(iwe));
646 iwe.cmd = SIOCGIWAP;
647 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
648 memcpy(iwe.u.ap_addr.sa_data, bss->pub.bssid, ETH_ALEN);
649 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe,
650 IW_EV_ADDR_LEN);
651
652 memset(&iwe, 0, sizeof(iwe));
653 iwe.cmd = SIOCGIWFREQ;
654 iwe.u.freq.m = ieee80211_frequency_to_channel(bss->pub.channel->center_freq);
655 iwe.u.freq.e = 0;
656 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe,
657 IW_EV_FREQ_LEN);
658
659 memset(&iwe, 0, sizeof(iwe));
660 iwe.cmd = SIOCGIWFREQ;
661 iwe.u.freq.m = bss->pub.channel->center_freq;
662 iwe.u.freq.e = 6;
663 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe,
664 IW_EV_FREQ_LEN);
665
666 if (wiphy->signal_type != CFG80211_SIGNAL_TYPE_NONE) {
667 memset(&iwe, 0, sizeof(iwe));
668 iwe.cmd = IWEVQUAL;
669 iwe.u.qual.updated = IW_QUAL_LEVEL_UPDATED |
670 IW_QUAL_NOISE_INVALID |
671 IW_QUAL_QUAL_UPDATED;
672 switch (wiphy->signal_type) {
673 case CFG80211_SIGNAL_TYPE_MBM:
674 sig = bss->pub.signal / 100;
675 iwe.u.qual.level = sig;
676 iwe.u.qual.updated |= IW_QUAL_DBM;
677 if (sig < -110) /* rather bad */
678 sig = -110;
679 else if (sig > -40) /* perfect */
680 sig = -40;
681 /* will give a range of 0 .. 70 */
682 iwe.u.qual.qual = sig + 110;
683 break;
684 case CFG80211_SIGNAL_TYPE_UNSPEC:
685 iwe.u.qual.level = bss->pub.signal;
686 /* will give range 0 .. 100 */
687 iwe.u.qual.qual = bss->pub.signal;
688 break;
689 default:
690 /* not reached */
691 break;
692 }
693 current_ev = iwe_stream_add_event(info, current_ev, end_buf,
694 &iwe, IW_EV_QUAL_LEN);
695 }
696
697 memset(&iwe, 0, sizeof(iwe));
698 iwe.cmd = SIOCGIWENCODE;
699 if (bss->pub.capability & WLAN_CAPABILITY_PRIVACY)
700 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
701 else
702 iwe.u.data.flags = IW_ENCODE_DISABLED;
703 iwe.u.data.length = 0;
704 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
705 &iwe, "");
706
707 while (rem >= 2) {
708 /* invalid data */
709 if (ie[1] > rem - 2)
710 break;
711
712 switch (ie[0]) {
713 case WLAN_EID_SSID:
714 memset(&iwe, 0, sizeof(iwe));
715 iwe.cmd = SIOCGIWESSID;
716 iwe.u.data.length = ie[1];
717 iwe.u.data.flags = 1;
718 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
719 &iwe, ie + 2);
720 break;
721 case WLAN_EID_MESH_ID:
722 memset(&iwe, 0, sizeof(iwe));
723 iwe.cmd = SIOCGIWESSID;
724 iwe.u.data.length = ie[1];
725 iwe.u.data.flags = 1;
726 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
727 &iwe, ie + 2);
728 break;
729 case WLAN_EID_MESH_CONFIG:
730 ismesh = true;
731 if (ie[1] != IEEE80211_MESH_CONFIG_LEN)
732 break;
733 buf = kmalloc(50, GFP_ATOMIC);
734 if (!buf)
735 break;
736 cfg = ie + 2;
737 memset(&iwe, 0, sizeof(iwe));
738 iwe.cmd = IWEVCUSTOM;
739 sprintf(buf, "Mesh network (version %d)", cfg[0]);
740 iwe.u.data.length = strlen(buf);
741 current_ev = iwe_stream_add_point(info, current_ev,
742 end_buf,
743 &iwe, buf);
744 sprintf(buf, "Path Selection Protocol ID: "
745 "0x%02X%02X%02X%02X", cfg[1], cfg[2], cfg[3],
746 cfg[4]);
747 iwe.u.data.length = strlen(buf);
748 current_ev = iwe_stream_add_point(info, current_ev,
749 end_buf,
750 &iwe, buf);
751 sprintf(buf, "Path Selection Metric ID: "
752 "0x%02X%02X%02X%02X", cfg[5], cfg[6], cfg[7],
753 cfg[8]);
754 iwe.u.data.length = strlen(buf);
755 current_ev = iwe_stream_add_point(info, current_ev,
756 end_buf,
757 &iwe, buf);
758 sprintf(buf, "Congestion Control Mode ID: "
759 "0x%02X%02X%02X%02X", cfg[9], cfg[10],
760 cfg[11], cfg[12]);
761 iwe.u.data.length = strlen(buf);
762 current_ev = iwe_stream_add_point(info, current_ev,
763 end_buf,
764 &iwe, buf);
765 sprintf(buf, "Channel Precedence: "
766 "0x%02X%02X%02X%02X", cfg[13], cfg[14],
767 cfg[15], cfg[16]);
768 iwe.u.data.length = strlen(buf);
769 current_ev = iwe_stream_add_point(info, current_ev,
770 end_buf,
771 &iwe, buf);
772 kfree(buf);
773 break;
774 case WLAN_EID_SUPP_RATES:
775 case WLAN_EID_EXT_SUPP_RATES:
776 /* display all supported rates in readable format */
777 p = current_ev + iwe_stream_lcp_len(info);
778
779 memset(&iwe, 0, sizeof(iwe));
780 iwe.cmd = SIOCGIWRATE;
781 /* Those two flags are ignored... */
782 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
783
784 for (i = 0; i < ie[1]; i++) {
785 iwe.u.bitrate.value =
786 ((ie[i + 2] & 0x7f) * 500000);
787 p = iwe_stream_add_value(info, current_ev, p,
788 end_buf, &iwe, IW_EV_PARAM_LEN);
789 }
790 current_ev = p;
791 break;
792 }
793 rem -= ie[1] + 2;
794 ie += ie[1] + 2;
795 }
796
797 if (bss->pub.capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)
798 || ismesh) {
799 memset(&iwe, 0, sizeof(iwe));
800 iwe.cmd = SIOCGIWMODE;
801 if (ismesh)
802 iwe.u.mode = IW_MODE_MESH;
803 else if (bss->pub.capability & WLAN_CAPABILITY_ESS)
804 iwe.u.mode = IW_MODE_MASTER;
805 else
806 iwe.u.mode = IW_MODE_ADHOC;
807 current_ev = iwe_stream_add_event(info, current_ev, end_buf,
808 &iwe, IW_EV_UINT_LEN);
809 }
810
811 buf = kmalloc(30, GFP_ATOMIC);
812 if (buf) {
813 memset(&iwe, 0, sizeof(iwe));
814 iwe.cmd = IWEVCUSTOM;
815 sprintf(buf, "tsf=%016llx", (unsigned long long)(bss->pub.tsf));
816 iwe.u.data.length = strlen(buf);
817 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
818 &iwe, buf);
819 memset(&iwe, 0, sizeof(iwe));
820 iwe.cmd = IWEVCUSTOM;
821 sprintf(buf, " Last beacon: %ums ago",
822 elapsed_jiffies_msecs(bss->ts));
823 iwe.u.data.length = strlen(buf);
824 current_ev = iwe_stream_add_point(info, current_ev,
825 end_buf, &iwe, buf);
826 kfree(buf);
827 }
828
829 ieee80211_scan_add_ies(info, &bss->pub, &current_ev, end_buf);
830
831 return current_ev;
832}
833
834
835static int ieee80211_scan_results(struct cfg80211_registered_device *dev,
836 struct iw_request_info *info,
837 char *buf, size_t len)
838{
839 char *current_ev = buf;
840 char *end_buf = buf + len;
841 struct cfg80211_internal_bss *bss;
842
843 spin_lock_bh(&dev->bss_lock);
844 cfg80211_bss_expire(dev);
845
846 list_for_each_entry(bss, &dev->bss_list, list) {
847 if (buf + len - current_ev <= IW_EV_ADDR_LEN) {
848 spin_unlock_bh(&dev->bss_lock);
849 return -E2BIG;
850 }
851 current_ev = ieee80211_bss(&dev->wiphy, info, bss,
852 current_ev, end_buf);
853 }
854 spin_unlock_bh(&dev->bss_lock);
855 return current_ev - buf;
856}
857
858
859int cfg80211_wext_giwscan(struct net_device *dev,
860 struct iw_request_info *info,
861 struct iw_point *data, char *extra)
862{
863 struct cfg80211_registered_device *rdev;
864 int res;
865
866 if (!netif_running(dev))
867 return -ENETDOWN;
868
869 rdev = cfg80211_get_dev_from_ifindex(dev->ifindex);
870
871 if (IS_ERR(rdev))
872 return PTR_ERR(rdev);
873
874 if (rdev->scan_req) {
875 res = -EAGAIN;
876 goto out;
877 }
878
879 res = ieee80211_scan_results(rdev, info, extra, data->length);
880 data->length = 0;
881 if (res >= 0) {
882 data->length = res;
883 res = 0;
884 }
885
886 out:
887 cfg80211_put_dev(rdev);
888 return res;
889}
890EXPORT_SYMBOL(cfg80211_wext_giwscan);
891#endif
diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c
index 79a382877641..efe3c5c92b2d 100644
--- a/net/wireless/sysfs.c
+++ b/net/wireless/sysfs.c
@@ -31,7 +31,7 @@ static ssize_t name ## _show(struct device *dev, \
31 return sprintf(buf, fmt "\n", dev_to_rdev(dev)->member); \ 31 return sprintf(buf, fmt "\n", dev_to_rdev(dev)->member); \
32} 32}
33 33
34SHOW_FMT(index, "%d", idx); 34SHOW_FMT(index, "%d", wiphy_idx);
35SHOW_FMT(macaddress, "%pM", wiphy.perm_addr); 35SHOW_FMT(macaddress, "%pM", wiphy.perm_addr);
36 36
37static struct device_attribute ieee80211_dev_attrs[] = { 37static struct device_attribute ieee80211_dev_attrs[] = {
@@ -55,6 +55,41 @@ static int wiphy_uevent(struct device *dev, struct kobj_uevent_env *env)
55} 55}
56#endif 56#endif
57 57
58static int wiphy_suspend(struct device *dev, pm_message_t state)
59{
60 struct cfg80211_registered_device *rdev = dev_to_rdev(dev);
61 int ret = 0;
62
63 rdev->suspend_at = get_seconds();
64
65 if (rdev->ops->suspend) {
66 rtnl_lock();
67 ret = rdev->ops->suspend(&rdev->wiphy);
68 rtnl_unlock();
69 }
70
71 return ret;
72}
73
74static int wiphy_resume(struct device *dev)
75{
76 struct cfg80211_registered_device *rdev = dev_to_rdev(dev);
77 int ret = 0;
78
79 /* Age scan results with time spent in suspend */
80 spin_lock_bh(&rdev->bss_lock);
81 cfg80211_bss_age(rdev, get_seconds() - rdev->suspend_at);
82 spin_unlock_bh(&rdev->bss_lock);
83
84 if (rdev->ops->resume) {
85 rtnl_lock();
86 ret = rdev->ops->resume(&rdev->wiphy);
87 rtnl_unlock();
88 }
89
90 return ret;
91}
92
58struct class ieee80211_class = { 93struct class ieee80211_class = {
59 .name = "ieee80211", 94 .name = "ieee80211",
60 .owner = THIS_MODULE, 95 .owner = THIS_MODULE,
@@ -63,6 +98,8 @@ struct class ieee80211_class = {
63#ifdef CONFIG_HOTPLUG 98#ifdef CONFIG_HOTPLUG
64 .dev_uevent = wiphy_uevent, 99 .dev_uevent = wiphy_uevent,
65#endif 100#endif
101 .suspend = wiphy_suspend,
102 .resume = wiphy_resume,
66}; 103};
67 104
68int wiphy_sysfs_init(void) 105int wiphy_sysfs_init(void)
diff --git a/net/wireless/util.c b/net/wireless/util.c
index e76cc28b0345..487cdd9bcffc 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -9,7 +9,7 @@
9 9
10struct ieee80211_rate * 10struct ieee80211_rate *
11ieee80211_get_response_rate(struct ieee80211_supported_band *sband, 11ieee80211_get_response_rate(struct ieee80211_supported_band *sband,
12 u64 basic_rates, int bitrate) 12 u32 basic_rates, int bitrate)
13{ 13{
14 struct ieee80211_rate *result = &sband->bitrates[0]; 14 struct ieee80211_rate *result = &sband->bitrates[0];
15 int i; 15 int i;
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index 58e489fd4aed..0fd1db6e95bb 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -66,6 +66,7 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
66 struct cfg80211_registered_device *rdev; 66 struct cfg80211_registered_device *rdev;
67 struct vif_params vifparams; 67 struct vif_params vifparams;
68 enum nl80211_iftype type; 68 enum nl80211_iftype type;
69 int ret;
69 70
70 if (!wdev) 71 if (!wdev)
71 return -EOPNOTSUPP; 72 return -EOPNOTSUPP;
@@ -96,10 +97,16 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
96 return -EINVAL; 97 return -EINVAL;
97 } 98 }
98 99
100 if (type == wdev->iftype)
101 return 0;
102
99 memset(&vifparams, 0, sizeof(vifparams)); 103 memset(&vifparams, 0, sizeof(vifparams));
100 104
101 return rdev->ops->change_virtual_intf(wdev->wiphy, dev->ifindex, type, 105 ret = rdev->ops->change_virtual_intf(wdev->wiphy, dev->ifindex, type,
102 NULL, &vifparams); 106 NULL, &vifparams);
107 WARN_ON(!ret && wdev->iftype != type);
108
109 return ret;
103} 110}
104EXPORT_SYMBOL(cfg80211_wext_siwmode); 111EXPORT_SYMBOL(cfg80211_wext_siwmode);
105 112
@@ -137,3 +144,100 @@ int cfg80211_wext_giwmode(struct net_device *dev, struct iw_request_info *info,
137 return 0; 144 return 0;
138} 145}
139EXPORT_SYMBOL(cfg80211_wext_giwmode); 146EXPORT_SYMBOL(cfg80211_wext_giwmode);
147
148
149int cfg80211_wext_giwrange(struct net_device *dev,
150 struct iw_request_info *info,
151 struct iw_point *data, char *extra)
152{
153 struct wireless_dev *wdev = dev->ieee80211_ptr;
154 struct iw_range *range = (struct iw_range *) extra;
155 enum ieee80211_band band;
156 int c = 0;
157
158 if (!wdev)
159 return -EOPNOTSUPP;
160
161 data->length = sizeof(struct iw_range);
162 memset(range, 0, sizeof(struct iw_range));
163
164 range->we_version_compiled = WIRELESS_EXT;
165 range->we_version_source = 21;
166 range->retry_capa = IW_RETRY_LIMIT;
167 range->retry_flags = IW_RETRY_LIMIT;
168 range->min_retry = 0;
169 range->max_retry = 255;
170 range->min_rts = 0;
171 range->max_rts = 2347;
172 range->min_frag = 256;
173 range->max_frag = 2346;
174
175 range->encoding_size[0] = 5;
176 range->encoding_size[1] = 13;
177 range->num_encoding_sizes = 2;
178 range->max_encoding_tokens = 4;
179
180 range->max_qual.updated = IW_QUAL_NOISE_INVALID;
181
182 switch (wdev->wiphy->signal_type) {
183 case CFG80211_SIGNAL_TYPE_NONE:
184 break;
185 case CFG80211_SIGNAL_TYPE_MBM:
186 range->max_qual.level = -110;
187 range->max_qual.qual = 70;
188 range->avg_qual.qual = 35;
189 range->max_qual.updated |= IW_QUAL_DBM;
190 range->max_qual.updated |= IW_QUAL_QUAL_UPDATED;
191 range->max_qual.updated |= IW_QUAL_LEVEL_UPDATED;
192 break;
193 case CFG80211_SIGNAL_TYPE_UNSPEC:
194 range->max_qual.level = 100;
195 range->max_qual.qual = 100;
196 range->avg_qual.qual = 50;
197 range->max_qual.updated |= IW_QUAL_QUAL_UPDATED;
198 range->max_qual.updated |= IW_QUAL_LEVEL_UPDATED;
199 break;
200 }
201
202 range->avg_qual.level = range->max_qual.level / 2;
203 range->avg_qual.noise = range->max_qual.noise / 2;
204 range->avg_qual.updated = range->max_qual.updated;
205
206 range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
207 IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
208
209
210 for (band = 0; band < IEEE80211_NUM_BANDS; band ++) {
211 int i;
212 struct ieee80211_supported_band *sband;
213
214 sband = wdev->wiphy->bands[band];
215
216 if (!sband)
217 continue;
218
219 for (i = 0; i < sband->n_channels && c < IW_MAX_FREQUENCIES; i++) {
220 struct ieee80211_channel *chan = &sband->channels[i];
221
222 if (!(chan->flags & IEEE80211_CHAN_DISABLED)) {
223 range->freq[c].i =
224 ieee80211_frequency_to_channel(
225 chan->center_freq);
226 range->freq[c].m = chan->center_freq;
227 range->freq[c].e = 6;
228 c++;
229 }
230 }
231 }
232 range->num_channels = c;
233 range->num_frequency = c;
234
235 IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
236 IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
237 IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
238
239 range->scan_capa |= IW_SCAN_CAPA_ESSID;
240
241 return 0;
242}
243EXPORT_SYMBOL(cfg80211_wext_giwrange);