aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/Kconfig11
-rw-r--r--net/wireless/Makefile3
-rw-r--r--net/wireless/core.c148
-rw-r--r--net/wireless/core.h42
-rw-r--r--net/wireless/debugfs.c131
-rw-r--r--net/wireless/debugfs.h14
-rw-r--r--net/wireless/ibss.c369
-rw-r--r--net/wireless/mlme.c50
-rw-r--r--net/wireless/nl80211.c996
-rw-r--r--net/wireless/nl80211.h32
-rw-r--r--net/wireless/reg.c274
-rw-r--r--net/wireless/scan.c66
-rw-r--r--net/wireless/util.c370
-rw-r--r--net/wireless/wext-compat.c600
-rw-r--r--net/wireless/wext.c48
15 files changed, 2841 insertions, 313 deletions
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig
index 3c3bc9e579ed..4428dd5e911d 100644
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -1,5 +1,6 @@
1config CFG80211 1config CFG80211
2 tristate "Improved wireless configuration API" 2 tristate "Improved wireless configuration API"
3 depends on RFKILL || !RFKILL
3 4
4config CFG80211_REG_DEBUG 5config CFG80211_REG_DEBUG
5 bool "cfg80211 regulatory debugging" 6 bool "cfg80211 regulatory debugging"
@@ -10,6 +11,14 @@ config CFG80211_REG_DEBUG
10 11
11 If unsure, say N. 12 If unsure, say N.
12 13
14config CFG80211_DEBUGFS
15 bool "cfg80211 DebugFS entries"
16 depends on CFG80211 && DEBUG_FS
17 ---help---
18 You can enable this if you want to debugfs entries for cfg80211.
19
20 If unsure, say N.
21
13config WIRELESS_OLD_REGULATORY 22config WIRELESS_OLD_REGULATORY
14 bool "Old wireless static regulatory definitions" 23 bool "Old wireless static regulatory definitions"
15 default n 24 default n
diff --git a/net/wireless/Makefile b/net/wireless/Makefile
index 6d1e7b27b752..f78c4832a9ca 100644
--- a/net/wireless/Makefile
+++ b/net/wireless/Makefile
@@ -5,7 +5,8 @@ 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 scan.o nl80211.o mlme.o 8cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o mlme.o ibss.o
9cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o
9cfg80211-$(CONFIG_WIRELESS_EXT) += wext-compat.o 10cfg80211-$(CONFIG_WIRELESS_EXT) += wext-compat.o
10 11
11ccflags-y += -D__CHECK_ENDIAN__ 12ccflags-y += -D__CHECK_ENDIAN__
diff --git a/net/wireless/core.c b/net/wireless/core.c
index d1f556535f6d..d5850292b3df 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * This is the linux wireless configuration interface. 2 * This is the linux wireless configuration interface.
3 * 3 *
4 * Copyright 2006-2008 Johannes Berg <johannes@sipsolutions.net> 4 * Copyright 2006-2009 Johannes Berg <johannes@sipsolutions.net>
5 */ 5 */
6 6
7#include <linux/if.h> 7#include <linux/if.h>
@@ -12,12 +12,13 @@
12#include <linux/debugfs.h> 12#include <linux/debugfs.h>
13#include <linux/notifier.h> 13#include <linux/notifier.h>
14#include <linux/device.h> 14#include <linux/device.h>
15#include <linux/rtnetlink.h>
15#include <net/genetlink.h> 16#include <net/genetlink.h>
16#include <net/cfg80211.h> 17#include <net/cfg80211.h>
17#include <net/wireless.h>
18#include "nl80211.h" 18#include "nl80211.h"
19#include "core.h" 19#include "core.h"
20#include "sysfs.h" 20#include "sysfs.h"
21#include "debugfs.h"
21 22
22/* name for sysfs, %d is appended */ 23/* name for sysfs, %d is appended */
23#define PHY_NAME "phy" 24#define PHY_NAME "phy"
@@ -227,9 +228,44 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
227 return 0; 228 return 0;
228} 229}
229 230
231static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data)
232{
233 struct cfg80211_registered_device *drv = data;
234
235 drv->ops->rfkill_poll(&drv->wiphy);
236}
237
238static int cfg80211_rfkill_set_block(void *data, bool blocked)
239{
240 struct cfg80211_registered_device *drv = data;
241 struct wireless_dev *wdev;
242
243 if (!blocked)
244 return 0;
245
246 rtnl_lock();
247 mutex_lock(&drv->devlist_mtx);
248
249 list_for_each_entry(wdev, &drv->netdev_list, list)
250 dev_close(wdev->netdev);
251
252 mutex_unlock(&drv->devlist_mtx);
253 rtnl_unlock();
254
255 return 0;
256}
257
258static void cfg80211_rfkill_sync_work(struct work_struct *work)
259{
260 struct cfg80211_registered_device *drv;
261
262 drv = container_of(work, struct cfg80211_registered_device, rfkill_sync);
263 cfg80211_rfkill_set_block(drv, rfkill_blocked(drv->rfkill));
264}
265
230/* exported functions */ 266/* exported functions */
231 267
232struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv) 268struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
233{ 269{
234 static int wiphy_counter; 270 static int wiphy_counter;
235 271
@@ -274,6 +310,28 @@ struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv)
274 drv->wiphy.dev.class = &ieee80211_class; 310 drv->wiphy.dev.class = &ieee80211_class;
275 drv->wiphy.dev.platform_data = drv; 311 drv->wiphy.dev.platform_data = drv;
276 312
313 drv->rfkill_ops.set_block = cfg80211_rfkill_set_block;
314 drv->rfkill = rfkill_alloc(dev_name(&drv->wiphy.dev),
315 &drv->wiphy.dev, RFKILL_TYPE_WLAN,
316 &drv->rfkill_ops, drv);
317
318 if (!drv->rfkill) {
319 kfree(drv);
320 return NULL;
321 }
322
323 INIT_WORK(&drv->rfkill_sync, cfg80211_rfkill_sync_work);
324
325 /*
326 * Initialize wiphy parameters to IEEE 802.11 MIB default values.
327 * Fragmentation and RTS threshold are disabled by default with the
328 * special -1 value.
329 */
330 drv->wiphy.retry_short = 7;
331 drv->wiphy.retry_long = 4;
332 drv->wiphy.frag_threshold = (u32) -1;
333 drv->wiphy.rts_threshold = (u32) -1;
334
277 return &drv->wiphy; 335 return &drv->wiphy;
278} 336}
279EXPORT_SYMBOL(wiphy_new); 337EXPORT_SYMBOL(wiphy_new);
@@ -337,17 +395,23 @@ int wiphy_register(struct wiphy *wiphy)
337 /* check and set up bitrates */ 395 /* check and set up bitrates */
338 ieee80211_set_bitrate_flags(wiphy); 396 ieee80211_set_bitrate_flags(wiphy);
339 397
398 res = device_add(&drv->wiphy.dev);
399 if (res)
400 return res;
401
402 res = rfkill_register(drv->rfkill);
403 if (res)
404 goto out_rm_dev;
405
340 mutex_lock(&cfg80211_mutex); 406 mutex_lock(&cfg80211_mutex);
341 407
342 /* set up regulatory info */ 408 /* set up regulatory info */
343 wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE); 409 wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE);
344 410
345 res = device_add(&drv->wiphy.dev);
346 if (res)
347 goto out_unlock;
348
349 list_add(&drv->list, &cfg80211_drv_list); 411 list_add(&drv->list, &cfg80211_drv_list);
350 412
413 mutex_unlock(&cfg80211_mutex);
414
351 /* add to debugfs */ 415 /* add to debugfs */
352 drv->wiphy.debugfsdir = 416 drv->wiphy.debugfsdir =
353 debugfs_create_dir(wiphy_name(&drv->wiphy), 417 debugfs_create_dir(wiphy_name(&drv->wiphy),
@@ -366,17 +430,41 @@ int wiphy_register(struct wiphy *wiphy)
366 nl80211_send_reg_change_event(&request); 430 nl80211_send_reg_change_event(&request);
367 } 431 }
368 432
369 res = 0; 433 cfg80211_debugfs_drv_add(drv);
370out_unlock: 434
371 mutex_unlock(&cfg80211_mutex); 435 return 0;
436
437 out_rm_dev:
438 device_del(&drv->wiphy.dev);
372 return res; 439 return res;
373} 440}
374EXPORT_SYMBOL(wiphy_register); 441EXPORT_SYMBOL(wiphy_register);
375 442
443void wiphy_rfkill_start_polling(struct wiphy *wiphy)
444{
445 struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy);
446
447 if (!drv->ops->rfkill_poll)
448 return;
449 drv->rfkill_ops.poll = cfg80211_rfkill_poll;
450 rfkill_resume_polling(drv->rfkill);
451}
452EXPORT_SYMBOL(wiphy_rfkill_start_polling);
453
454void wiphy_rfkill_stop_polling(struct wiphy *wiphy)
455{
456 struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy);
457
458 rfkill_pause_polling(drv->rfkill);
459}
460EXPORT_SYMBOL(wiphy_rfkill_stop_polling);
461
376void wiphy_unregister(struct wiphy *wiphy) 462void wiphy_unregister(struct wiphy *wiphy)
377{ 463{
378 struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy); 464 struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy);
379 465
466 rfkill_unregister(drv->rfkill);
467
380 /* protect the device list */ 468 /* protect the device list */
381 mutex_lock(&cfg80211_mutex); 469 mutex_lock(&cfg80211_mutex);
382 470
@@ -396,6 +484,8 @@ void wiphy_unregister(struct wiphy *wiphy)
396 /* unlock again before freeing */ 484 /* unlock again before freeing */
397 mutex_unlock(&drv->mtx); 485 mutex_unlock(&drv->mtx);
398 486
487 cfg80211_debugfs_drv_del(drv);
488
399 /* If this device got a regulatory hint tell core its 489 /* If this device got a regulatory hint tell core its
400 * free to listen now to a new shiny device regulatory hint */ 490 * free to listen now to a new shiny device regulatory hint */
401 reg_device_remove(wiphy); 491 reg_device_remove(wiphy);
@@ -411,6 +501,7 @@ EXPORT_SYMBOL(wiphy_unregister);
411void cfg80211_dev_free(struct cfg80211_registered_device *drv) 501void cfg80211_dev_free(struct cfg80211_registered_device *drv)
412{ 502{
413 struct cfg80211_internal_bss *scan, *tmp; 503 struct cfg80211_internal_bss *scan, *tmp;
504 rfkill_destroy(drv->rfkill);
414 mutex_destroy(&drv->mtx); 505 mutex_destroy(&drv->mtx);
415 mutex_destroy(&drv->devlist_mtx); 506 mutex_destroy(&drv->devlist_mtx);
416 list_for_each_entry_safe(scan, tmp, &drv->bss_list, list) 507 list_for_each_entry_safe(scan, tmp, &drv->bss_list, list)
@@ -424,6 +515,15 @@ void wiphy_free(struct wiphy *wiphy)
424} 515}
425EXPORT_SYMBOL(wiphy_free); 516EXPORT_SYMBOL(wiphy_free);
426 517
518void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool blocked)
519{
520 struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy);
521
522 if (rfkill_set_hw_state(drv->rfkill, blocked))
523 schedule_work(&drv->rfkill_sync);
524}
525EXPORT_SYMBOL(wiphy_rfkill_set_hw_state);
526
427static int cfg80211_netdev_notifier_call(struct notifier_block * nb, 527static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
428 unsigned long state, 528 unsigned long state,
429 void *ndev) 529 void *ndev)
@@ -432,7 +532,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
432 struct cfg80211_registered_device *rdev; 532 struct cfg80211_registered_device *rdev;
433 533
434 if (!dev->ieee80211_ptr) 534 if (!dev->ieee80211_ptr)
435 return 0; 535 return NOTIFY_DONE;
436 536
437 rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy); 537 rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy);
438 538
@@ -448,8 +548,28 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
448 "symlink to netdev!\n"); 548 "symlink to netdev!\n");
449 } 549 }
450 dev->ieee80211_ptr->netdev = dev; 550 dev->ieee80211_ptr->netdev = dev;
551#ifdef CONFIG_WIRELESS_EXT
552 dev->ieee80211_ptr->wext.default_key = -1;
553 dev->ieee80211_ptr->wext.default_mgmt_key = -1;
554#endif
451 mutex_unlock(&rdev->devlist_mtx); 555 mutex_unlock(&rdev->devlist_mtx);
452 break; 556 break;
557 case NETDEV_GOING_DOWN:
558 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
559 break;
560 if (!dev->ieee80211_ptr->ssid_len)
561 break;
562 cfg80211_leave_ibss(rdev, dev, true);
563 break;
564 case NETDEV_UP:
565#ifdef CONFIG_WIRELESS_EXT
566 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
567 break;
568 if (!dev->ieee80211_ptr->wext.ibss.ssid_len)
569 break;
570 cfg80211_join_ibss(rdev, dev, &dev->ieee80211_ptr->wext.ibss);
571 break;
572#endif
453 case NETDEV_UNREGISTER: 573 case NETDEV_UNREGISTER:
454 mutex_lock(&rdev->devlist_mtx); 574 mutex_lock(&rdev->devlist_mtx);
455 if (!list_empty(&dev->ieee80211_ptr->list)) { 575 if (!list_empty(&dev->ieee80211_ptr->list)) {
@@ -458,9 +578,13 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
458 } 578 }
459 mutex_unlock(&rdev->devlist_mtx); 579 mutex_unlock(&rdev->devlist_mtx);
460 break; 580 break;
581 case NETDEV_PRE_UP:
582 if (rfkill_blocked(rdev->rfkill))
583 return notifier_from_errno(-ERFKILL);
584 break;
461 } 585 }
462 586
463 return 0; 587 return NOTIFY_DONE;
464} 588}
465 589
466static struct notifier_block cfg80211_netdev_notifier = { 590static struct notifier_block cfg80211_netdev_notifier = {
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 0a592e4295f0..bfa340c7abb5 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * Wireless configuration interface internals. 2 * Wireless configuration interface internals.
3 * 3 *
4 * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net> 4 * Copyright 2006-2009 Johannes Berg <johannes@sipsolutions.net>
5 */ 5 */
6#ifndef __NET_WIRELESS_CORE_H 6#ifndef __NET_WIRELESS_CORE_H
7#define __NET_WIRELESS_CORE_H 7#define __NET_WIRELESS_CORE_H
@@ -10,14 +10,15 @@
10#include <linux/netdevice.h> 10#include <linux/netdevice.h>
11#include <linux/kref.h> 11#include <linux/kref.h>
12#include <linux/rbtree.h> 12#include <linux/rbtree.h>
13#include <linux/mutex.h> 13#include <linux/debugfs.h>
14#include <linux/rfkill.h>
15#include <linux/workqueue.h>
14#include <net/genetlink.h> 16#include <net/genetlink.h>
15#include <net/wireless.h>
16#include <net/cfg80211.h> 17#include <net/cfg80211.h>
17#include "reg.h" 18#include "reg.h"
18 19
19struct cfg80211_registered_device { 20struct cfg80211_registered_device {
20 struct cfg80211_ops *ops; 21 const struct cfg80211_ops *ops;
21 struct list_head list; 22 struct list_head list;
22 /* we hold this mutex during any call so that 23 /* we hold this mutex during any call so that
23 * we cannot do multiple calls at once, and also 24 * we cannot do multiple calls at once, and also
@@ -25,6 +26,11 @@ struct cfg80211_registered_device {
25 * any call is in progress */ 26 * any call is in progress */
26 struct mutex mtx; 27 struct mutex mtx;
27 28
29 /* rfkill support */
30 struct rfkill_ops rfkill_ops;
31 struct rfkill *rfkill;
32 struct work_struct rfkill_sync;
33
28 /* ISO / IEC 3166 alpha2 for which this device is receiving 34 /* ISO / IEC 3166 alpha2 for which this device is receiving
29 * country IEs on, this can help disregard country IEs from APs 35 * country IEs on, this can help disregard country IEs from APs
30 * on the same alpha2 quickly. The alpha2 may differ from 36 * on the same alpha2 quickly. The alpha2 may differ from
@@ -52,6 +58,17 @@ struct cfg80211_registered_device {
52 struct cfg80211_scan_request *scan_req; /* protected by RTNL */ 58 struct cfg80211_scan_request *scan_req; /* protected by RTNL */
53 unsigned long suspend_at; 59 unsigned long suspend_at;
54 60
61#ifdef CONFIG_CFG80211_DEBUGFS
62 /* Debugfs entries */
63 struct wiphy_debugfsdentries {
64 struct dentry *rts_threshold;
65 struct dentry *fragmentation_threshold;
66 struct dentry *short_retry_limit;
67 struct dentry *long_retry_limit;
68 struct dentry *ht40allow_map;
69 } debugfs;
70#endif
71
55 /* must be last because of the way we do wiphy_priv(), 72 /* must be last because of the way we do wiphy_priv(),
56 * and it should at least be aligned to NETDEV_ALIGN */ 73 * and it should at least be aligned to NETDEV_ALIGN */
57 struct wiphy wiphy __attribute__((__aligned__(NETDEV_ALIGN))); 74 struct wiphy wiphy __attribute__((__aligned__(NETDEV_ALIGN)));
@@ -74,10 +91,7 @@ bool wiphy_idx_valid(int wiphy_idx)
74extern struct mutex cfg80211_mutex; 91extern struct mutex cfg80211_mutex;
75extern struct list_head cfg80211_drv_list; 92extern struct list_head cfg80211_drv_list;
76 93
77static inline void assert_cfg80211_lock(void) 94#define assert_cfg80211_lock() WARN_ON(!mutex_is_locked(&cfg80211_mutex))
78{
79 WARN_ON(!mutex_is_locked(&cfg80211_mutex));
80}
81 95
82/* 96/*
83 * You can use this to mark a wiphy_idx as not having an associated wiphy. 97 * You can use this to mark a wiphy_idx as not having an associated wiphy.
@@ -148,4 +162,16 @@ void cfg80211_bss_expire(struct cfg80211_registered_device *dev);
148void cfg80211_bss_age(struct cfg80211_registered_device *dev, 162void cfg80211_bss_age(struct cfg80211_registered_device *dev,
149 unsigned long age_secs); 163 unsigned long age_secs);
150 164
165/* IBSS */
166int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
167 struct net_device *dev,
168 struct cfg80211_ibss_params *params);
169void cfg80211_clear_ibss(struct net_device *dev, bool nowext);
170int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
171 struct net_device *dev, bool nowext);
172
173/* internal helpers */
174int cfg80211_validate_key_settings(struct key_params *params, int key_idx,
175 const u8 *mac_addr);
176
151#endif /* __NET_WIRELESS_CORE_H */ 177#endif /* __NET_WIRELESS_CORE_H */
diff --git a/net/wireless/debugfs.c b/net/wireless/debugfs.c
new file mode 100644
index 000000000000..679ddfcec1ee
--- /dev/null
+++ b/net/wireless/debugfs.c
@@ -0,0 +1,131 @@
1/*
2 * cfg80211 debugfs
3 *
4 * Copyright 2009 Luis R. Rodriguez <lrodriguez@atheros.com>
5 * Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include "core.h"
13#include "debugfs.h"
14
15static int cfg80211_open_file_generic(struct inode *inode, struct file *file)
16{
17 file->private_data = inode->i_private;
18 return 0;
19}
20
21#define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...) \
22static ssize_t name## _read(struct file *file, char __user *userbuf, \
23 size_t count, loff_t *ppos) \
24{ \
25 struct wiphy *wiphy= file->private_data; \
26 char buf[buflen]; \
27 int res; \
28 \
29 res = scnprintf(buf, buflen, fmt "\n", ##value); \
30 return simple_read_from_buffer(userbuf, count, ppos, buf, res); \
31} \
32 \
33static const struct file_operations name## _ops = { \
34 .read = name## _read, \
35 .open = cfg80211_open_file_generic, \
36};
37
38DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d",
39 wiphy->rts_threshold)
40DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d",
41 wiphy->frag_threshold);
42DEBUGFS_READONLY_FILE(short_retry_limit, 20, "%d",
43 wiphy->retry_short)
44DEBUGFS_READONLY_FILE(long_retry_limit, 20, "%d",
45 wiphy->retry_long);
46
47static int ht_print_chan(struct ieee80211_channel *chan,
48 char *buf, int buf_size, int offset)
49{
50 if (WARN_ON(offset > buf_size))
51 return 0;
52
53 if (chan->flags & IEEE80211_CHAN_DISABLED)
54 return snprintf(buf + offset,
55 buf_size - offset,
56 "%d Disabled\n",
57 chan->center_freq);
58
59 return snprintf(buf + offset,
60 buf_size - offset,
61 "%d HT40 %c%c\n",
62 chan->center_freq,
63 (chan->flags & IEEE80211_CHAN_NO_HT40MINUS) ? ' ' : '-',
64 (chan->flags & IEEE80211_CHAN_NO_HT40PLUS) ? ' ' : '+');
65}
66
67static ssize_t ht40allow_map_read(struct file *file,
68 char __user *user_buf,
69 size_t count, loff_t *ppos)
70{
71 struct wiphy *wiphy = file->private_data;
72 char *buf;
73 unsigned int offset = 0, buf_size = PAGE_SIZE, i, r;
74 enum ieee80211_band band;
75 struct ieee80211_supported_band *sband;
76
77 buf = kzalloc(buf_size, GFP_KERNEL);
78 if (!buf)
79 return -ENOMEM;
80
81 mutex_lock(&cfg80211_mutex);
82
83 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
84 sband = wiphy->bands[band];
85 if (!sband)
86 continue;
87 for (i = 0; i < sband->n_channels; i++)
88 offset += ht_print_chan(&sband->channels[i],
89 buf, buf_size, offset);
90 }
91
92 mutex_unlock(&cfg80211_mutex);
93
94 r = simple_read_from_buffer(user_buf, count, ppos, buf, offset);
95
96 kfree(buf);
97
98 return r;
99}
100
101static const struct file_operations ht40allow_map_ops = {
102 .read = ht40allow_map_read,
103 .open = cfg80211_open_file_generic,
104};
105
106#define DEBUGFS_ADD(name) \
107 drv->debugfs.name = debugfs_create_file(#name, S_IRUGO, phyd, \
108 &drv->wiphy, &name## _ops);
109#define DEBUGFS_DEL(name) \
110 debugfs_remove(drv->debugfs.name); \
111 drv->debugfs.name = NULL;
112
113void cfg80211_debugfs_drv_add(struct cfg80211_registered_device *drv)
114{
115 struct dentry *phyd = drv->wiphy.debugfsdir;
116
117 DEBUGFS_ADD(rts_threshold);
118 DEBUGFS_ADD(fragmentation_threshold);
119 DEBUGFS_ADD(short_retry_limit);
120 DEBUGFS_ADD(long_retry_limit);
121 DEBUGFS_ADD(ht40allow_map);
122}
123
124void cfg80211_debugfs_drv_del(struct cfg80211_registered_device *drv)
125{
126 DEBUGFS_DEL(rts_threshold);
127 DEBUGFS_DEL(fragmentation_threshold);
128 DEBUGFS_DEL(short_retry_limit);
129 DEBUGFS_DEL(long_retry_limit);
130 DEBUGFS_DEL(ht40allow_map);
131}
diff --git a/net/wireless/debugfs.h b/net/wireless/debugfs.h
new file mode 100644
index 000000000000..c226983ae66b
--- /dev/null
+++ b/net/wireless/debugfs.h
@@ -0,0 +1,14 @@
1#ifndef __CFG80211_DEBUGFS_H
2#define __CFG80211_DEBUGFS_H
3
4#ifdef CONFIG_CFG80211_DEBUGFS
5void cfg80211_debugfs_drv_add(struct cfg80211_registered_device *drv);
6void cfg80211_debugfs_drv_del(struct cfg80211_registered_device *drv);
7#else
8static inline
9void cfg80211_debugfs_drv_add(struct cfg80211_registered_device *drv) {}
10static inline
11void cfg80211_debugfs_drv_del(struct cfg80211_registered_device *drv) {}
12#endif
13
14#endif /* __CFG80211_DEBUGFS_H */
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
new file mode 100644
index 000000000000..a4a1c3498ff2
--- /dev/null
+++ b/net/wireless/ibss.c
@@ -0,0 +1,369 @@
1/*
2 * Some IBSS support code for cfg80211.
3 *
4 * Copyright 2009 Johannes Berg <johannes@sipsolutions.net>
5 */
6
7#include <linux/etherdevice.h>
8#include <linux/if_arp.h>
9#include <net/cfg80211.h>
10#include "nl80211.h"
11
12
13void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp)
14{
15 struct wireless_dev *wdev = dev->ieee80211_ptr;
16 struct cfg80211_bss *bss;
17#ifdef CONFIG_WIRELESS_EXT
18 union iwreq_data wrqu;
19#endif
20
21 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
22 return;
23
24 if (WARN_ON(!wdev->ssid_len))
25 return;
26
27 if (memcmp(bssid, wdev->bssid, ETH_ALEN) == 0)
28 return;
29
30 bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
31 wdev->ssid, wdev->ssid_len,
32 WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS);
33
34 if (WARN_ON(!bss))
35 return;
36
37 if (wdev->current_bss) {
38 cfg80211_unhold_bss(wdev->current_bss);
39 cfg80211_put_bss(wdev->current_bss);
40 }
41
42 cfg80211_hold_bss(bss);
43 wdev->current_bss = bss;
44 memcpy(wdev->bssid, bssid, ETH_ALEN);
45
46 nl80211_send_ibss_bssid(wiphy_to_dev(wdev->wiphy), dev, bssid, gfp);
47#ifdef CONFIG_WIRELESS_EXT
48 memset(&wrqu, 0, sizeof(wrqu));
49 memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
50 wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
51#endif
52}
53EXPORT_SYMBOL(cfg80211_ibss_joined);
54
55int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
56 struct net_device *dev,
57 struct cfg80211_ibss_params *params)
58{
59 struct wireless_dev *wdev = dev->ieee80211_ptr;
60 int err;
61
62 if (wdev->ssid_len)
63 return -EALREADY;
64
65#ifdef CONFIG_WIRELESS_EXT
66 wdev->wext.ibss.channel = params->channel;
67#endif
68 err = rdev->ops->join_ibss(&rdev->wiphy, dev, params);
69
70 if (err)
71 return err;
72
73 memcpy(wdev->ssid, params->ssid, params->ssid_len);
74 wdev->ssid_len = params->ssid_len;
75
76 return 0;
77}
78
79void cfg80211_clear_ibss(struct net_device *dev, bool nowext)
80{
81 struct wireless_dev *wdev = dev->ieee80211_ptr;
82
83 if (wdev->current_bss) {
84 cfg80211_unhold_bss(wdev->current_bss);
85 cfg80211_put_bss(wdev->current_bss);
86 }
87
88 wdev->current_bss = NULL;
89 wdev->ssid_len = 0;
90 memset(wdev->bssid, 0, ETH_ALEN);
91#ifdef CONFIG_WIRELESS_EXT
92 if (!nowext)
93 wdev->wext.ibss.ssid_len = 0;
94#endif
95}
96
97int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
98 struct net_device *dev, bool nowext)
99{
100 int err;
101
102 err = rdev->ops->leave_ibss(&rdev->wiphy, dev);
103
104 if (err)
105 return err;
106
107 cfg80211_clear_ibss(dev, nowext);
108
109 return 0;
110}
111
112#ifdef CONFIG_WIRELESS_EXT
113static int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
114 struct wireless_dev *wdev)
115{
116 enum ieee80211_band band;
117 int i;
118
119 if (!wdev->wext.ibss.beacon_interval)
120 wdev->wext.ibss.beacon_interval = 100;
121
122 /* try to find an IBSS channel if none requested ... */
123 if (!wdev->wext.ibss.channel) {
124 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
125 struct ieee80211_supported_band *sband;
126 struct ieee80211_channel *chan;
127
128 sband = rdev->wiphy.bands[band];
129 if (!sband)
130 continue;
131
132 for (i = 0; i < sband->n_channels; i++) {
133 chan = &sband->channels[i];
134 if (chan->flags & IEEE80211_CHAN_NO_IBSS)
135 continue;
136 if (chan->flags & IEEE80211_CHAN_DISABLED)
137 continue;
138 wdev->wext.ibss.channel = chan;
139 break;
140 }
141
142 if (wdev->wext.ibss.channel)
143 break;
144 }
145
146 if (!wdev->wext.ibss.channel)
147 return -EINVAL;
148 }
149
150 /* don't join -- SSID is not there */
151 if (!wdev->wext.ibss.ssid_len)
152 return 0;
153
154 if (!netif_running(wdev->netdev))
155 return 0;
156
157 return cfg80211_join_ibss(wiphy_to_dev(wdev->wiphy),
158 wdev->netdev, &wdev->wext.ibss);
159}
160
161int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
162 struct iw_request_info *info,
163 struct iw_freq *freq, char *extra)
164{
165 struct wireless_dev *wdev = dev->ieee80211_ptr;
166 struct ieee80211_channel *chan;
167 int err;
168
169 /* call only for ibss! */
170 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
171 return -EINVAL;
172
173 if (!wiphy_to_dev(wdev->wiphy)->ops->join_ibss)
174 return -EOPNOTSUPP;
175
176 chan = cfg80211_wext_freq(wdev->wiphy, freq);
177 if (chan && IS_ERR(chan))
178 return PTR_ERR(chan);
179
180 if (chan &&
181 (chan->flags & IEEE80211_CHAN_NO_IBSS ||
182 chan->flags & IEEE80211_CHAN_DISABLED))
183 return -EINVAL;
184
185 if (wdev->wext.ibss.channel == chan)
186 return 0;
187
188 if (wdev->ssid_len) {
189 err = cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy),
190 dev, true);
191 if (err)
192 return err;
193 }
194
195 if (chan) {
196 wdev->wext.ibss.channel = chan;
197 wdev->wext.ibss.channel_fixed = true;
198 } else {
199 /* cfg80211_ibss_wext_join will pick one if needed */
200 wdev->wext.ibss.channel_fixed = false;
201 }
202
203 return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev);
204}
205/* temporary symbol - mark GPL - in the future the handler won't be */
206EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwfreq);
207
208int cfg80211_ibss_wext_giwfreq(struct net_device *dev,
209 struct iw_request_info *info,
210 struct iw_freq *freq, char *extra)
211{
212 struct wireless_dev *wdev = dev->ieee80211_ptr;
213 struct ieee80211_channel *chan = NULL;
214
215 /* call only for ibss! */
216 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
217 return -EINVAL;
218
219 if (wdev->current_bss)
220 chan = wdev->current_bss->channel;
221 else if (wdev->wext.ibss.channel)
222 chan = wdev->wext.ibss.channel;
223
224 if (chan) {
225 freq->m = chan->center_freq;
226 freq->e = 6;
227 return 0;
228 }
229
230 /* no channel if not joining */
231 return -EINVAL;
232}
233/* temporary symbol - mark GPL - in the future the handler won't be */
234EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_giwfreq);
235
236int cfg80211_ibss_wext_siwessid(struct net_device *dev,
237 struct iw_request_info *info,
238 struct iw_point *data, char *ssid)
239{
240 struct wireless_dev *wdev = dev->ieee80211_ptr;
241 size_t len = data->length;
242 int err;
243
244 /* call only for ibss! */
245 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
246 return -EINVAL;
247
248 if (!wiphy_to_dev(wdev->wiphy)->ops->join_ibss)
249 return -EOPNOTSUPP;
250
251 if (wdev->ssid_len) {
252 err = cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy),
253 dev, true);
254 if (err)
255 return err;
256 }
257
258 /* iwconfig uses nul termination in SSID.. */
259 if (len > 0 && ssid[len - 1] == '\0')
260 len--;
261
262 wdev->wext.ibss.ssid = wdev->ssid;
263 memcpy(wdev->wext.ibss.ssid, ssid, len);
264 wdev->wext.ibss.ssid_len = len;
265
266 return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev);
267}
268/* temporary symbol - mark GPL - in the future the handler won't be */
269EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwessid);
270
271int cfg80211_ibss_wext_giwessid(struct net_device *dev,
272 struct iw_request_info *info,
273 struct iw_point *data, char *ssid)
274{
275 struct wireless_dev *wdev = dev->ieee80211_ptr;
276
277 /* call only for ibss! */
278 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
279 return -EINVAL;
280
281 data->flags = 0;
282
283 if (wdev->ssid_len) {
284 data->flags = 1;
285 data->length = wdev->ssid_len;
286 memcpy(ssid, wdev->ssid, data->length);
287 } else if (wdev->wext.ibss.ssid && wdev->wext.ibss.ssid_len) {
288 data->flags = 1;
289 data->length = wdev->wext.ibss.ssid_len;
290 memcpy(ssid, wdev->wext.ibss.ssid, data->length);
291 }
292
293 return 0;
294}
295/* temporary symbol - mark GPL - in the future the handler won't be */
296EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_giwessid);
297
298int cfg80211_ibss_wext_siwap(struct net_device *dev,
299 struct iw_request_info *info,
300 struct sockaddr *ap_addr, char *extra)
301{
302 struct wireless_dev *wdev = dev->ieee80211_ptr;
303 u8 *bssid = ap_addr->sa_data;
304 int err;
305
306 /* call only for ibss! */
307 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
308 return -EINVAL;
309
310 if (!wiphy_to_dev(wdev->wiphy)->ops->join_ibss)
311 return -EOPNOTSUPP;
312
313 if (ap_addr->sa_family != ARPHRD_ETHER)
314 return -EINVAL;
315
316 /* automatic mode */
317 if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid))
318 bssid = NULL;
319
320 /* both automatic */
321 if (!bssid && !wdev->wext.ibss.bssid)
322 return 0;
323
324 /* fixed already - and no change */
325 if (wdev->wext.ibss.bssid && bssid &&
326 compare_ether_addr(bssid, wdev->wext.ibss.bssid) == 0)
327 return 0;
328
329 if (wdev->ssid_len) {
330 err = cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy),
331 dev, true);
332 if (err)
333 return err;
334 }
335
336 if (bssid) {
337 memcpy(wdev->wext.bssid, bssid, ETH_ALEN);
338 wdev->wext.ibss.bssid = wdev->wext.bssid;
339 } else
340 wdev->wext.ibss.bssid = NULL;
341
342 return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev);
343}
344/* temporary symbol - mark GPL - in the future the handler won't be */
345EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwap);
346
347int cfg80211_ibss_wext_giwap(struct net_device *dev,
348 struct iw_request_info *info,
349 struct sockaddr *ap_addr, char *extra)
350{
351 struct wireless_dev *wdev = dev->ieee80211_ptr;
352
353 /* call only for ibss! */
354 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
355 return -EINVAL;
356
357 ap_addr->sa_family = ARPHRD_ETHER;
358
359 if (wdev->wext.ibss.bssid) {
360 memcpy(ap_addr->sa_data, wdev->wext.ibss.bssid, ETH_ALEN);
361 return 0;
362 }
363
364 memcpy(ap_addr->sa_data, wdev->bssid, ETH_ALEN);
365 return 0;
366}
367/* temporary symbol - mark GPL - in the future the handler won't be */
368EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_giwap);
369#endif
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index bec5721b6f99..42184361a109 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -28,19 +28,55 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len)
28} 28}
29EXPORT_SYMBOL(cfg80211_send_rx_assoc); 29EXPORT_SYMBOL(cfg80211_send_rx_assoc);
30 30
31void cfg80211_send_rx_deauth(struct net_device *dev, const u8 *buf, size_t len) 31void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len)
32{ 32{
33 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; 33 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
34 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); 34 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
35 nl80211_send_rx_deauth(rdev, dev, buf, len); 35 nl80211_send_deauth(rdev, dev, buf, len);
36} 36}
37EXPORT_SYMBOL(cfg80211_send_rx_deauth); 37EXPORT_SYMBOL(cfg80211_send_deauth);
38 38
39void cfg80211_send_rx_disassoc(struct net_device *dev, const u8 *buf, 39void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len)
40 size_t len)
41{ 40{
42 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; 41 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
43 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); 42 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
44 nl80211_send_rx_disassoc(rdev, dev, buf, len); 43 nl80211_send_disassoc(rdev, dev, buf, len);
45} 44}
46EXPORT_SYMBOL(cfg80211_send_rx_disassoc); 45EXPORT_SYMBOL(cfg80211_send_disassoc);
46
47static void cfg80211_wext_disconnected(struct net_device *dev)
48{
49#ifdef CONFIG_WIRELESS_EXT
50 union iwreq_data wrqu;
51 memset(&wrqu, 0, sizeof(wrqu));
52 wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
53#endif
54}
55
56void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr)
57{
58 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
59 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
60 nl80211_send_auth_timeout(rdev, dev, addr);
61 cfg80211_wext_disconnected(dev);
62}
63EXPORT_SYMBOL(cfg80211_send_auth_timeout);
64
65void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr)
66{
67 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
68 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
69 nl80211_send_assoc_timeout(rdev, dev, addr);
70 cfg80211_wext_disconnected(dev);
71}
72EXPORT_SYMBOL(cfg80211_send_assoc_timeout);
73
74void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
75 enum nl80211_key_type key_type, int key_id,
76 const u8 *tsc)
77{
78 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
79 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
80 nl80211_michael_mic_failure(rdev, dev, addr, key_type, key_id, tsc);
81}
82EXPORT_SYMBOL(cfg80211_michael_mic_failure);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 2456e4ee445e..241bddd0b4f1 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * This is the new netlink-based wireless configuration interface. 2 * This is the new netlink-based wireless configuration interface.
3 * 3 *
4 * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net> 4 * Copyright 2006-2009 Johannes Berg <johannes@sipsolutions.net>
5 */ 5 */
6 6
7#include <linux/if.h> 7#include <linux/if.h>
@@ -57,10 +57,14 @@ static int get_drv_dev_by_info_ifindex(struct nlattr **attrs,
57static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { 57static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
58 [NL80211_ATTR_WIPHY] = { .type = NLA_U32 }, 58 [NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
59 [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING, 59 [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,
60 .len = BUS_ID_SIZE-1 }, 60 .len = 20-1 },
61 [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED }, 61 [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED },
62 [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 }, 62 [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 },
63 [NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 }, 63 [NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 },
64 [NL80211_ATTR_WIPHY_RETRY_SHORT] = { .type = NLA_U8 },
65 [NL80211_ATTR_WIPHY_RETRY_LONG] = { .type = NLA_U8 },
66 [NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 },
67 [NL80211_ATTR_WIPHY_RTS_THRESHOLD] = { .type = NLA_U32 },
64 68
65 [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 }, 69 [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 },
66 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, 70 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
@@ -73,6 +77,7 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
73 [NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 }, 77 [NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 },
74 [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 }, 78 [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 },
75 [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG }, 79 [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG },
80 [NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 },
76 81
77 [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 }, 82 [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 },
78 [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 }, 83 [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 },
@@ -116,8 +121,45 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
116 .len = IEEE80211_MAX_SSID_LEN }, 121 .len = IEEE80211_MAX_SSID_LEN },
117 [NL80211_ATTR_AUTH_TYPE] = { .type = NLA_U32 }, 122 [NL80211_ATTR_AUTH_TYPE] = { .type = NLA_U32 },
118 [NL80211_ATTR_REASON_CODE] = { .type = NLA_U16 }, 123 [NL80211_ATTR_REASON_CODE] = { .type = NLA_U16 },
124 [NL80211_ATTR_FREQ_FIXED] = { .type = NLA_FLAG },
125 [NL80211_ATTR_TIMED_OUT] = { .type = NLA_FLAG },
126 [NL80211_ATTR_USE_MFP] = { .type = NLA_U32 },
127 [NL80211_ATTR_STA_FLAGS2] = {
128 .len = sizeof(struct nl80211_sta_flag_update),
129 },
130 [NL80211_ATTR_CONTROL_PORT] = { .type = NLA_FLAG },
119}; 131};
120 132
133/* IE validation */
134static bool is_valid_ie_attr(const struct nlattr *attr)
135{
136 const u8 *pos;
137 int len;
138
139 if (!attr)
140 return true;
141
142 pos = nla_data(attr);
143 len = nla_len(attr);
144
145 while (len) {
146 u8 elemlen;
147
148 if (len < 2)
149 return false;
150 len -= 2;
151
152 elemlen = pos[1];
153 if (elemlen > len)
154 return false;
155
156 len -= elemlen;
157 pos += 2 + elemlen;
158 }
159
160 return true;
161}
162
121/* message building helper */ 163/* message building helper */
122static inline void *nl80211hdr_put(struct sk_buff *skb, u32 pid, u32 seq, 164static inline void *nl80211hdr_put(struct sk_buff *skb, u32 pid, u32 seq,
123 int flags, u8 cmd) 165 int flags, u8 cmd)
@@ -126,6 +168,30 @@ static inline void *nl80211hdr_put(struct sk_buff *skb, u32 pid, u32 seq,
126 return genlmsg_put(skb, pid, seq, &nl80211_fam, flags, cmd); 168 return genlmsg_put(skb, pid, seq, &nl80211_fam, flags, cmd);
127} 169}
128 170
171static int nl80211_msg_put_channel(struct sk_buff *msg,
172 struct ieee80211_channel *chan)
173{
174 NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_FREQ,
175 chan->center_freq);
176
177 if (chan->flags & IEEE80211_CHAN_DISABLED)
178 NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_DISABLED);
179 if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)
180 NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_PASSIVE_SCAN);
181 if (chan->flags & IEEE80211_CHAN_NO_IBSS)
182 NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_NO_IBSS);
183 if (chan->flags & IEEE80211_CHAN_RADAR)
184 NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_RADAR);
185
186 NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
187 DBM_TO_MBM(chan->max_power));
188
189 return 0;
190
191 nla_put_failure:
192 return -ENOBUFS;
193}
194
129/* netlink command implementations */ 195/* netlink command implementations */
130 196
131static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, 197static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
@@ -149,8 +215,24 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
149 215
150 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx); 216 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx);
151 NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy)); 217 NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy));
218
219 NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT,
220 dev->wiphy.retry_short);
221 NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_RETRY_LONG,
222 dev->wiphy.retry_long);
223 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
224 dev->wiphy.frag_threshold);
225 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD,
226 dev->wiphy.rts_threshold);
227
152 NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS, 228 NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
153 dev->wiphy.max_scan_ssids); 229 dev->wiphy.max_scan_ssids);
230 NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN,
231 dev->wiphy.max_scan_ie_len);
232
233 NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES,
234 sizeof(u32) * dev->wiphy.n_cipher_suites,
235 dev->wiphy.cipher_suites);
154 236
155 nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES); 237 nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES);
156 if (!nl_modes) 238 if (!nl_modes)
@@ -202,20 +284,9 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
202 goto nla_put_failure; 284 goto nla_put_failure;
203 285
204 chan = &dev->wiphy.bands[band]->channels[i]; 286 chan = &dev->wiphy.bands[band]->channels[i];
205 NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_FREQ,
206 chan->center_freq);
207
208 if (chan->flags & IEEE80211_CHAN_DISABLED)
209 NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_DISABLED);
210 if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)
211 NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_PASSIVE_SCAN);
212 if (chan->flags & IEEE80211_CHAN_NO_IBSS)
213 NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_NO_IBSS);
214 if (chan->flags & IEEE80211_CHAN_RADAR)
215 NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_RADAR);
216 287
217 NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER, 288 if (nl80211_msg_put_channel(msg, chan))
218 DBM_TO_MBM(chan->max_power)); 289 goto nla_put_failure;
219 290
220 nla_nest_end(msg, nl_freq); 291 nla_nest_end(msg, nl_freq);
221 } 292 }
@@ -273,6 +344,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
273 CMD(assoc, ASSOCIATE); 344 CMD(assoc, ASSOCIATE);
274 CMD(deauth, DEAUTHENTICATE); 345 CMD(deauth, DEAUTHENTICATE);
275 CMD(disassoc, DISASSOCIATE); 346 CMD(disassoc, DISASSOCIATE);
347 CMD(join_ibss, JOIN_IBSS);
276 348
277#undef CMD 349#undef CMD
278 nla_nest_end(msg, nl_cmds); 350 nla_nest_end(msg, nl_cmds);
@@ -317,7 +389,7 @@ static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
317 if (IS_ERR(dev)) 389 if (IS_ERR(dev))
318 return PTR_ERR(dev); 390 return PTR_ERR(dev);
319 391
320 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 392 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
321 if (!msg) 393 if (!msg)
322 goto out_err; 394 goto out_err;
323 395
@@ -365,6 +437,9 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
365 struct cfg80211_registered_device *rdev; 437 struct cfg80211_registered_device *rdev;
366 int result = 0, rem_txq_params = 0; 438 int result = 0, rem_txq_params = 0;
367 struct nlattr *nl_txq_params; 439 struct nlattr *nl_txq_params;
440 u32 changed;
441 u8 retry_short = 0, retry_long = 0;
442 u32 frag_threshold = 0, rts_threshold = 0;
368 443
369 rtnl_lock(); 444 rtnl_lock();
370 445
@@ -418,7 +493,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
418 enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; 493 enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
419 struct ieee80211_channel *chan; 494 struct ieee80211_channel *chan;
420 struct ieee80211_sta_ht_cap *ht_cap; 495 struct ieee80211_sta_ht_cap *ht_cap;
421 u32 freq, sec_freq; 496 u32 freq;
422 497
423 if (!rdev->ops->set_channel) { 498 if (!rdev->ops->set_channel) {
424 result = -EOPNOTSUPP; 499 result = -EOPNOTSUPP;
@@ -444,33 +519,28 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
444 if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) 519 if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
445 goto bad_res; 520 goto bad_res;
446 521
447 if (channel_type == NL80211_CHAN_HT40MINUS) 522 if (channel_type == NL80211_CHAN_HT40MINUS &&
448 sec_freq = freq - 20; 523 (chan->flags & IEEE80211_CHAN_NO_HT40MINUS))
449 else if (channel_type == NL80211_CHAN_HT40PLUS)
450 sec_freq = freq + 20;
451 else
452 sec_freq = 0;
453
454 ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap;
455
456 /* no HT capabilities */
457 if (channel_type != NL80211_CHAN_NO_HT &&
458 !ht_cap->ht_supported)
459 goto bad_res; 524 goto bad_res;
525 else if (channel_type == NL80211_CHAN_HT40PLUS &&
526 (chan->flags & IEEE80211_CHAN_NO_HT40PLUS))
527 goto bad_res;
528
529 /*
530 * At this point we know if that if HT40 was requested
531 * we are allowed to use it and the extension channel
532 * exists.
533 */
460 534
461 if (sec_freq) { 535 ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap;
462 struct ieee80211_channel *schan;
463 536
464 /* no 40 MHz capabilities */ 537 /* no HT capabilities or intolerant */
538 if (channel_type != NL80211_CHAN_NO_HT) {
539 if (!ht_cap->ht_supported)
540 goto bad_res;
465 if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) || 541 if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
466 (ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT)) 542 (ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT))
467 goto bad_res; 543 goto bad_res;
468
469 schan = ieee80211_get_channel(&rdev->wiphy, sec_freq);
470
471 /* Secondary channel not allowed */
472 if (!schan || schan->flags & IEEE80211_CHAN_DISABLED)
473 goto bad_res;
474 } 544 }
475 545
476 result = rdev->ops->set_channel(&rdev->wiphy, chan, 546 result = rdev->ops->set_channel(&rdev->wiphy, chan,
@@ -479,6 +549,84 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
479 goto bad_res; 549 goto bad_res;
480 } 550 }
481 551
552 changed = 0;
553
554 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) {
555 retry_short = nla_get_u8(
556 info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]);
557 if (retry_short == 0) {
558 result = -EINVAL;
559 goto bad_res;
560 }
561 changed |= WIPHY_PARAM_RETRY_SHORT;
562 }
563
564 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]) {
565 retry_long = nla_get_u8(
566 info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]);
567 if (retry_long == 0) {
568 result = -EINVAL;
569 goto bad_res;
570 }
571 changed |= WIPHY_PARAM_RETRY_LONG;
572 }
573
574 if (info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]) {
575 frag_threshold = nla_get_u32(
576 info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]);
577 if (frag_threshold < 256) {
578 result = -EINVAL;
579 goto bad_res;
580 }
581 if (frag_threshold != (u32) -1) {
582 /*
583 * Fragments (apart from the last one) are required to
584 * have even length. Make the fragmentation code
585 * simpler by stripping LSB should someone try to use
586 * odd threshold value.
587 */
588 frag_threshold &= ~0x1;
589 }
590 changed |= WIPHY_PARAM_FRAG_THRESHOLD;
591 }
592
593 if (info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]) {
594 rts_threshold = nla_get_u32(
595 info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]);
596 changed |= WIPHY_PARAM_RTS_THRESHOLD;
597 }
598
599 if (changed) {
600 u8 old_retry_short, old_retry_long;
601 u32 old_frag_threshold, old_rts_threshold;
602
603 if (!rdev->ops->set_wiphy_params) {
604 result = -EOPNOTSUPP;
605 goto bad_res;
606 }
607
608 old_retry_short = rdev->wiphy.retry_short;
609 old_retry_long = rdev->wiphy.retry_long;
610 old_frag_threshold = rdev->wiphy.frag_threshold;
611 old_rts_threshold = rdev->wiphy.rts_threshold;
612
613 if (changed & WIPHY_PARAM_RETRY_SHORT)
614 rdev->wiphy.retry_short = retry_short;
615 if (changed & WIPHY_PARAM_RETRY_LONG)
616 rdev->wiphy.retry_long = retry_long;
617 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
618 rdev->wiphy.frag_threshold = frag_threshold;
619 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
620 rdev->wiphy.rts_threshold = rts_threshold;
621
622 result = rdev->ops->set_wiphy_params(&rdev->wiphy, changed);
623 if (result) {
624 rdev->wiphy.retry_short = old_retry_short;
625 rdev->wiphy.retry_long = old_retry_long;
626 rdev->wiphy.frag_threshold = old_frag_threshold;
627 rdev->wiphy.rts_threshold = old_rts_threshold;
628 }
629 }
482 630
483 bad_res: 631 bad_res:
484 mutex_unlock(&rdev->mtx); 632 mutex_unlock(&rdev->mtx);
@@ -489,6 +637,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
489 637
490 638
491static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags, 639static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags,
640 struct cfg80211_registered_device *rdev,
492 struct net_device *dev) 641 struct net_device *dev)
493{ 642{
494 void *hdr; 643 void *hdr;
@@ -498,6 +647,7 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags,
498 return -1; 647 return -1;
499 648
500 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); 649 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
650 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
501 NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, dev->name); 651 NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, dev->name);
502 NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, dev->ieee80211_ptr->iftype); 652 NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, dev->ieee80211_ptr->iftype);
503 return genlmsg_end(msg, hdr); 653 return genlmsg_end(msg, hdr);
@@ -532,7 +682,7 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
532 } 682 }
533 if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).pid, 683 if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).pid,
534 cb->nlh->nlmsg_seq, NLM_F_MULTI, 684 cb->nlh->nlmsg_seq, NLM_F_MULTI,
535 wdev->netdev) < 0) { 685 dev, wdev->netdev) < 0) {
536 mutex_unlock(&dev->devlist_mtx); 686 mutex_unlock(&dev->devlist_mtx);
537 goto out; 687 goto out;
538 } 688 }
@@ -562,11 +712,12 @@ static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
562 if (err) 712 if (err)
563 return err; 713 return err;
564 714
565 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 715 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
566 if (!msg) 716 if (!msg)
567 goto out_err; 717 goto out_err;
568 718
569 if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0, netdev) < 0) 719 if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0,
720 dev, netdev) < 0)
570 goto out_free; 721 goto out_free;
571 722
572 dev_put(netdev); 723 dev_put(netdev);
@@ -616,7 +767,7 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
616 struct cfg80211_registered_device *drv; 767 struct cfg80211_registered_device *drv;
617 struct vif_params params; 768 struct vif_params params;
618 int err, ifindex; 769 int err, ifindex;
619 enum nl80211_iftype type; 770 enum nl80211_iftype otype, ntype;
620 struct net_device *dev; 771 struct net_device *dev;
621 u32 _flags, *flags = NULL; 772 u32 _flags, *flags = NULL;
622 bool change = false; 773 bool change = false;
@@ -630,30 +781,27 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
630 goto unlock_rtnl; 781 goto unlock_rtnl;
631 782
632 ifindex = dev->ifindex; 783 ifindex = dev->ifindex;
633 type = dev->ieee80211_ptr->iftype; 784 otype = ntype = dev->ieee80211_ptr->iftype;
634 dev_put(dev); 785 dev_put(dev);
635 786
636 if (info->attrs[NL80211_ATTR_IFTYPE]) { 787 if (info->attrs[NL80211_ATTR_IFTYPE]) {
637 enum nl80211_iftype ntype;
638
639 ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]); 788 ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
640 if (type != ntype) 789 if (otype != ntype)
641 change = true; 790 change = true;
642 type = ntype; 791 if (ntype > NL80211_IFTYPE_MAX) {
643 if (type > NL80211_IFTYPE_MAX) {
644 err = -EINVAL; 792 err = -EINVAL;
645 goto unlock; 793 goto unlock;
646 } 794 }
647 } 795 }
648 796
649 if (!drv->ops->change_virtual_intf || 797 if (!drv->ops->change_virtual_intf ||
650 !(drv->wiphy.interface_modes & (1 << type))) { 798 !(drv->wiphy.interface_modes & (1 << ntype))) {
651 err = -EOPNOTSUPP; 799 err = -EOPNOTSUPP;
652 goto unlock; 800 goto unlock;
653 } 801 }
654 802
655 if (info->attrs[NL80211_ATTR_MESH_ID]) { 803 if (info->attrs[NL80211_ATTR_MESH_ID]) {
656 if (type != NL80211_IFTYPE_MESH_POINT) { 804 if (ntype != NL80211_IFTYPE_MESH_POINT) {
657 err = -EINVAL; 805 err = -EINVAL;
658 goto unlock; 806 goto unlock;
659 } 807 }
@@ -663,7 +811,7 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
663 } 811 }
664 812
665 if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) { 813 if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) {
666 if (type != NL80211_IFTYPE_MONITOR) { 814 if (ntype != NL80211_IFTYPE_MONITOR) {
667 err = -EINVAL; 815 err = -EINVAL;
668 goto unlock; 816 goto unlock;
669 } 817 }
@@ -678,12 +826,17 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
678 826
679 if (change) 827 if (change)
680 err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, 828 err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex,
681 type, flags, &params); 829 ntype, flags, &params);
682 else 830 else
683 err = 0; 831 err = 0;
684 832
685 dev = __dev_get_by_index(&init_net, ifindex); 833 dev = __dev_get_by_index(&init_net, ifindex);
686 WARN_ON(!dev || (!err && dev->ieee80211_ptr->iftype != type)); 834 WARN_ON(!dev || (!err && dev->ieee80211_ptr->iftype != ntype));
835
836 if (dev && !err && (ntype != otype)) {
837 if (otype == NL80211_IFTYPE_ADHOC)
838 cfg80211_clear_ibss(dev, false);
839 }
687 840
688 unlock: 841 unlock:
689 cfg80211_put_dev(drv); 842 cfg80211_put_dev(drv);
@@ -832,7 +985,7 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
832 goto out; 985 goto out;
833 } 986 }
834 987
835 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 988 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
836 if (!msg) { 989 if (!msg) {
837 err = -ENOMEM; 990 err = -ENOMEM;
838 goto out; 991 goto out;
@@ -920,6 +1073,14 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
920 } 1073 }
921 1074
922 err = func(&drv->wiphy, dev, key_idx); 1075 err = func(&drv->wiphy, dev, key_idx);
1076#ifdef CONFIG_WIRELESS_EXT
1077 if (!err) {
1078 if (func == drv->ops->set_default_key)
1079 dev->ieee80211_ptr->wext.default_key = key_idx;
1080 else
1081 dev->ieee80211_ptr->wext.default_mgmt_key = key_idx;
1082 }
1083#endif
923 1084
924 out: 1085 out:
925 cfg80211_put_dev(drv); 1086 cfg80211_put_dev(drv);
@@ -934,7 +1095,7 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
934static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info) 1095static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
935{ 1096{
936 struct cfg80211_registered_device *drv; 1097 struct cfg80211_registered_device *drv;
937 int err; 1098 int err, i;
938 struct net_device *dev; 1099 struct net_device *dev;
939 struct key_params params; 1100 struct key_params params;
940 u8 key_idx = 0; 1101 u8 key_idx = 0;
@@ -950,6 +1111,11 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
950 params.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]); 1111 params.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]);
951 } 1112 }
952 1113
1114 if (info->attrs[NL80211_ATTR_KEY_SEQ]) {
1115 params.seq = nla_data(info->attrs[NL80211_ATTR_KEY_SEQ]);
1116 params.seq_len = nla_len(info->attrs[NL80211_ATTR_KEY_SEQ]);
1117 }
1118
953 if (info->attrs[NL80211_ATTR_KEY_IDX]) 1119 if (info->attrs[NL80211_ATTR_KEY_IDX])
954 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); 1120 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
955 1121
@@ -958,51 +1124,23 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
958 if (info->attrs[NL80211_ATTR_MAC]) 1124 if (info->attrs[NL80211_ATTR_MAC])
959 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 1125 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
960 1126
961 if (key_idx > 5) 1127 if (cfg80211_validate_key_settings(&params, key_idx, mac_addr))
962 return -EINVAL; 1128 return -EINVAL;
963 1129
964 /*
965 * Disallow pairwise keys with non-zero index unless it's WEP
966 * (because current deployments use pairwise WEP keys with
967 * non-zero indizes but 802.11i clearly specifies to use zero)
968 */
969 if (mac_addr && key_idx &&
970 params.cipher != WLAN_CIPHER_SUITE_WEP40 &&
971 params.cipher != WLAN_CIPHER_SUITE_WEP104)
972 return -EINVAL;
973
974 /* TODO: add definitions for the lengths to linux/ieee80211.h */
975 switch (params.cipher) {
976 case WLAN_CIPHER_SUITE_WEP40:
977 if (params.key_len != 5)
978 return -EINVAL;
979 break;
980 case WLAN_CIPHER_SUITE_TKIP:
981 if (params.key_len != 32)
982 return -EINVAL;
983 break;
984 case WLAN_CIPHER_SUITE_CCMP:
985 if (params.key_len != 16)
986 return -EINVAL;
987 break;
988 case WLAN_CIPHER_SUITE_WEP104:
989 if (params.key_len != 13)
990 return -EINVAL;
991 break;
992 case WLAN_CIPHER_SUITE_AES_CMAC:
993 if (params.key_len != 16)
994 return -EINVAL;
995 break;
996 default:
997 return -EINVAL;
998 }
999
1000 rtnl_lock(); 1130 rtnl_lock();
1001 1131
1002 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 1132 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1003 if (err) 1133 if (err)
1004 goto unlock_rtnl; 1134 goto unlock_rtnl;
1005 1135
1136 for (i = 0; i < drv->wiphy.n_cipher_suites; i++)
1137 if (params.cipher == drv->wiphy.cipher_suites[i])
1138 break;
1139 if (i == drv->wiphy.n_cipher_suites) {
1140 err = -EINVAL;
1141 goto out;
1142 }
1143
1006 if (!drv->ops->add_key) { 1144 if (!drv->ops->add_key) {
1007 err = -EOPNOTSUPP; 1145 err = -EOPNOTSUPP;
1008 goto out; 1146 goto out;
@@ -1049,6 +1187,15 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
1049 1187
1050 err = drv->ops->del_key(&drv->wiphy, dev, key_idx, mac_addr); 1188 err = drv->ops->del_key(&drv->wiphy, dev, key_idx, mac_addr);
1051 1189
1190#ifdef CONFIG_WIRELESS_EXT
1191 if (!err) {
1192 if (key_idx == dev->ieee80211_ptr->wext.default_key)
1193 dev->ieee80211_ptr->wext.default_key = -1;
1194 else if (key_idx == dev->ieee80211_ptr->wext.default_mgmt_key)
1195 dev->ieee80211_ptr->wext.default_mgmt_key = -1;
1196 }
1197#endif
1198
1052 out: 1199 out:
1053 cfg80211_put_dev(drv); 1200 cfg80211_put_dev(drv);
1054 dev_put(dev); 1201 dev_put(dev);
@@ -1069,6 +1216,9 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
1069 struct beacon_parameters params; 1216 struct beacon_parameters params;
1070 int haveinfo = 0; 1217 int haveinfo = 0;
1071 1218
1219 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_BEACON_TAIL]))
1220 return -EINVAL;
1221
1072 rtnl_lock(); 1222 rtnl_lock();
1073 1223
1074 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 1224 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
@@ -1186,15 +1336,36 @@ static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = {
1186 [NL80211_STA_FLAG_AUTHORIZED] = { .type = NLA_FLAG }, 1336 [NL80211_STA_FLAG_AUTHORIZED] = { .type = NLA_FLAG },
1187 [NL80211_STA_FLAG_SHORT_PREAMBLE] = { .type = NLA_FLAG }, 1337 [NL80211_STA_FLAG_SHORT_PREAMBLE] = { .type = NLA_FLAG },
1188 [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG }, 1338 [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG },
1339 [NL80211_STA_FLAG_MFP] = { .type = NLA_FLAG },
1189}; 1340};
1190 1341
1191static int parse_station_flags(struct nlattr *nla, u32 *staflags) 1342static int parse_station_flags(struct genl_info *info,
1343 struct station_parameters *params)
1192{ 1344{
1193 struct nlattr *flags[NL80211_STA_FLAG_MAX + 1]; 1345 struct nlattr *flags[NL80211_STA_FLAG_MAX + 1];
1346 struct nlattr *nla;
1194 int flag; 1347 int flag;
1195 1348
1196 *staflags = 0; 1349 /*
1350 * Try parsing the new attribute first so userspace
1351 * can specify both for older kernels.
1352 */
1353 nla = info->attrs[NL80211_ATTR_STA_FLAGS2];
1354 if (nla) {
1355 struct nl80211_sta_flag_update *sta_flags;
1356
1357 sta_flags = nla_data(nla);
1358 params->sta_flags_mask = sta_flags->mask;
1359 params->sta_flags_set = sta_flags->set;
1360 if ((params->sta_flags_mask |
1361 params->sta_flags_set) & BIT(__NL80211_STA_FLAG_INVALID))
1362 return -EINVAL;
1363 return 0;
1364 }
1365
1366 /* if present, parse the old attribute */
1197 1367
1368 nla = info->attrs[NL80211_ATTR_STA_FLAGS];
1198 if (!nla) 1369 if (!nla)
1199 return 0; 1370 return 0;
1200 1371
@@ -1202,11 +1373,12 @@ static int parse_station_flags(struct nlattr *nla, u32 *staflags)
1202 nla, sta_flags_policy)) 1373 nla, sta_flags_policy))
1203 return -EINVAL; 1374 return -EINVAL;
1204 1375
1205 *staflags = STATION_FLAG_CHANGED; 1376 params->sta_flags_mask = (1 << __NL80211_STA_FLAG_AFTER_LAST) - 1;
1377 params->sta_flags_mask &= ~1;
1206 1378
1207 for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++) 1379 for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++)
1208 if (flags[flag]) 1380 if (flags[flag])
1209 *staflags |= (1<<flag); 1381 params->sta_flags_set |= (1<<flag);
1210 1382
1211 return 0; 1383 return 0;
1212} 1384}
@@ -1424,7 +1596,7 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
1424 if (err) 1596 if (err)
1425 goto out; 1597 goto out;
1426 1598
1427 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 1599 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1428 if (!msg) 1600 if (!msg)
1429 goto out; 1601 goto out;
1430 1602
@@ -1502,8 +1674,7 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
1502 params.ht_capa = 1674 params.ht_capa =
1503 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); 1675 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
1504 1676
1505 if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS], 1677 if (parse_station_flags(info, &params))
1506 &params.station_flags))
1507 return -EINVAL; 1678 return -EINVAL;
1508 1679
1509 if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) 1680 if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
@@ -1520,6 +1691,51 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
1520 if (err) 1691 if (err)
1521 goto out; 1692 goto out;
1522 1693
1694 /* validate settings */
1695 err = 0;
1696
1697 switch (dev->ieee80211_ptr->iftype) {
1698 case NL80211_IFTYPE_AP:
1699 case NL80211_IFTYPE_AP_VLAN:
1700 /* disallow mesh-specific things */
1701 if (params.plink_action)
1702 err = -EINVAL;
1703 break;
1704 case NL80211_IFTYPE_STATION:
1705 /* disallow everything but AUTHORIZED flag */
1706 if (params.plink_action)
1707 err = -EINVAL;
1708 if (params.vlan)
1709 err = -EINVAL;
1710 if (params.supported_rates)
1711 err = -EINVAL;
1712 if (params.ht_capa)
1713 err = -EINVAL;
1714 if (params.listen_interval >= 0)
1715 err = -EINVAL;
1716 if (params.sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED))
1717 err = -EINVAL;
1718 break;
1719 case NL80211_IFTYPE_MESH_POINT:
1720 /* disallow things mesh doesn't support */
1721 if (params.vlan)
1722 err = -EINVAL;
1723 if (params.ht_capa)
1724 err = -EINVAL;
1725 if (params.listen_interval >= 0)
1726 err = -EINVAL;
1727 if (params.supported_rates)
1728 err = -EINVAL;
1729 if (params.sta_flags_mask)
1730 err = -EINVAL;
1731 break;
1732 default:
1733 err = -EINVAL;
1734 }
1735
1736 if (err)
1737 goto out;
1738
1523 if (!drv->ops->change_station) { 1739 if (!drv->ops->change_station) {
1524 err = -EOPNOTSUPP; 1740 err = -EOPNOTSUPP;
1525 goto out; 1741 goto out;
@@ -1551,9 +1767,6 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
1551 if (!info->attrs[NL80211_ATTR_MAC]) 1767 if (!info->attrs[NL80211_ATTR_MAC])
1552 return -EINVAL; 1768 return -EINVAL;
1553 1769
1554 if (!info->attrs[NL80211_ATTR_STA_AID])
1555 return -EINVAL;
1556
1557 if (!info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]) 1770 if (!info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
1558 return -EINVAL; 1771 return -EINVAL;
1559 1772
@@ -1567,13 +1780,18 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
1567 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]); 1780 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
1568 params.listen_interval = 1781 params.listen_interval =
1569 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); 1782 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
1570 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]); 1783
1784 if (info->attrs[NL80211_ATTR_STA_AID]) {
1785 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
1786 if (!params.aid || params.aid > IEEE80211_MAX_AID)
1787 return -EINVAL;
1788 }
1789
1571 if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) 1790 if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
1572 params.ht_capa = 1791 params.ht_capa =
1573 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); 1792 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
1574 1793
1575 if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS], 1794 if (parse_station_flags(info, &params))
1576 &params.station_flags))
1577 return -EINVAL; 1795 return -EINVAL;
1578 1796
1579 rtnl_lock(); 1797 rtnl_lock();
@@ -1586,6 +1804,38 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
1586 if (err) 1804 if (err)
1587 goto out; 1805 goto out;
1588 1806
1807 /* validate settings */
1808 err = 0;
1809
1810 switch (dev->ieee80211_ptr->iftype) {
1811 case NL80211_IFTYPE_AP:
1812 case NL80211_IFTYPE_AP_VLAN:
1813 /* all ok but must have AID */
1814 if (!params.aid)
1815 err = -EINVAL;
1816 break;
1817 case NL80211_IFTYPE_MESH_POINT:
1818 /* disallow things mesh doesn't support */
1819 if (params.vlan)
1820 err = -EINVAL;
1821 if (params.aid)
1822 err = -EINVAL;
1823 if (params.ht_capa)
1824 err = -EINVAL;
1825 if (params.listen_interval >= 0)
1826 err = -EINVAL;
1827 if (params.supported_rates)
1828 err = -EINVAL;
1829 if (params.sta_flags_mask)
1830 err = -EINVAL;
1831 break;
1832 default:
1833 err = -EINVAL;
1834 }
1835
1836 if (err)
1837 goto out;
1838
1589 if (!drv->ops->add_station) { 1839 if (!drv->ops->add_station) {
1590 err = -EOPNOTSUPP; 1840 err = -EOPNOTSUPP;
1591 goto out; 1841 goto out;
@@ -1625,6 +1875,13 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
1625 if (err) 1875 if (err)
1626 goto out_rtnl; 1876 goto out_rtnl;
1627 1877
1878 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
1879 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
1880 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) {
1881 err = -EINVAL;
1882 goto out;
1883 }
1884
1628 if (!drv->ops->del_station) { 1885 if (!drv->ops->del_station) {
1629 err = -EOPNOTSUPP; 1886 err = -EOPNOTSUPP;
1630 goto out; 1887 goto out;
@@ -1808,7 +2065,7 @@ static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
1808 if (err) 2065 if (err)
1809 goto out; 2066 goto out;
1810 2067
1811 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 2068 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1812 if (!msg) 2069 if (!msg)
1813 goto out; 2070 goto out;
1814 2071
@@ -2124,7 +2381,7 @@ static int nl80211_get_mesh_params(struct sk_buff *skb,
2124 goto out; 2381 goto out;
2125 2382
2126 /* Draw up a netlink message to send back */ 2383 /* Draw up a netlink message to send back */
2127 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 2384 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2128 if (!msg) { 2385 if (!msg) {
2129 err = -ENOBUFS; 2386 err = -ENOBUFS;
2130 goto out; 2387 goto out;
@@ -2302,7 +2559,7 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
2302 if (!cfg80211_regdomain) 2559 if (!cfg80211_regdomain)
2303 goto out; 2560 goto out;
2304 2561
2305 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 2562 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2306 if (!msg) { 2563 if (!msg) {
2307 err = -ENOBUFS; 2564 err = -ENOBUFS;
2308 goto out; 2565 goto out;
@@ -2385,18 +2642,24 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
2385 rem_reg_rules) { 2642 rem_reg_rules) {
2386 num_rules++; 2643 num_rules++;
2387 if (num_rules > NL80211_MAX_SUPP_REG_RULES) 2644 if (num_rules > NL80211_MAX_SUPP_REG_RULES)
2388 goto bad_reg; 2645 return -EINVAL;
2389 } 2646 }
2390 2647
2391 if (!reg_is_valid_request(alpha2)) 2648 mutex_lock(&cfg80211_mutex);
2392 return -EINVAL; 2649
2650 if (!reg_is_valid_request(alpha2)) {
2651 r = -EINVAL;
2652 goto bad_reg;
2653 }
2393 2654
2394 size_of_regd = sizeof(struct ieee80211_regdomain) + 2655 size_of_regd = sizeof(struct ieee80211_regdomain) +
2395 (num_rules * sizeof(struct ieee80211_reg_rule)); 2656 (num_rules * sizeof(struct ieee80211_reg_rule));
2396 2657
2397 rd = kzalloc(size_of_regd, GFP_KERNEL); 2658 rd = kzalloc(size_of_regd, GFP_KERNEL);
2398 if (!rd) 2659 if (!rd) {
2399 return -ENOMEM; 2660 r = -ENOMEM;
2661 goto bad_reg;
2662 }
2400 2663
2401 rd->n_reg_rules = num_rules; 2664 rd->n_reg_rules = num_rules;
2402 rd->alpha2[0] = alpha2[0]; 2665 rd->alpha2[0] = alpha2[0];
@@ -2413,20 +2676,24 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
2413 2676
2414 rule_idx++; 2677 rule_idx++;
2415 2678
2416 if (rule_idx > NL80211_MAX_SUPP_REG_RULES) 2679 if (rule_idx > NL80211_MAX_SUPP_REG_RULES) {
2680 r = -EINVAL;
2417 goto bad_reg; 2681 goto bad_reg;
2682 }
2418 } 2683 }
2419 2684
2420 BUG_ON(rule_idx != num_rules); 2685 BUG_ON(rule_idx != num_rules);
2421 2686
2422 mutex_lock(&cfg80211_mutex);
2423 r = set_regdom(rd); 2687 r = set_regdom(rd);
2688
2424 mutex_unlock(&cfg80211_mutex); 2689 mutex_unlock(&cfg80211_mutex);
2690
2425 return r; 2691 return r;
2426 2692
2427 bad_reg: 2693 bad_reg:
2694 mutex_unlock(&cfg80211_mutex);
2428 kfree(rd); 2695 kfree(rd);
2429 return -EINVAL; 2696 return r;
2430} 2697}
2431 2698
2432static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) 2699static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
@@ -2442,6 +2709,9 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
2442 enum ieee80211_band band; 2709 enum ieee80211_band band;
2443 size_t ie_len; 2710 size_t ie_len;
2444 2711
2712 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
2713 return -EINVAL;
2714
2445 rtnl_lock(); 2715 rtnl_lock();
2446 2716
2447 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 2717 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
@@ -2492,6 +2762,11 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
2492 else 2762 else
2493 ie_len = 0; 2763 ie_len = 0;
2494 2764
2765 if (ie_len > wiphy->max_scan_ie_len) {
2766 err = -EINVAL;
2767 goto out;
2768 }
2769
2495 request = kzalloc(sizeof(*request) 2770 request = kzalloc(sizeof(*request)
2496 + sizeof(*ssid) * n_ssids 2771 + sizeof(*ssid) * n_ssids
2497 + sizeof(channel) * n_channels 2772 + sizeof(channel) * n_channels
@@ -2554,7 +2829,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
2554 2829
2555 if (info->attrs[NL80211_ATTR_IE]) { 2830 if (info->attrs[NL80211_ATTR_IE]) {
2556 request->ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); 2831 request->ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
2557 memcpy(request->ie, nla_data(info->attrs[NL80211_ATTR_IE]), 2832 memcpy((void *)request->ie,
2833 nla_data(info->attrs[NL80211_ATTR_IE]),
2558 request->ie_len); 2834 request->ie_len);
2559 } 2835 }
2560 2836
@@ -2710,6 +2986,15 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
2710 struct wiphy *wiphy; 2986 struct wiphy *wiphy;
2711 int err; 2987 int err;
2712 2988
2989 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
2990 return -EINVAL;
2991
2992 if (!info->attrs[NL80211_ATTR_MAC])
2993 return -EINVAL;
2994
2995 if (!info->attrs[NL80211_ATTR_AUTH_TYPE])
2996 return -EINVAL;
2997
2713 rtnl_lock(); 2998 rtnl_lock();
2714 2999
2715 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 3000 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
@@ -2731,11 +3016,6 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
2731 goto out; 3016 goto out;
2732 } 3017 }
2733 3018
2734 if (!info->attrs[NL80211_ATTR_MAC]) {
2735 err = -EINVAL;
2736 goto out;
2737 }
2738
2739 wiphy = &drv->wiphy; 3019 wiphy = &drv->wiphy;
2740 memset(&req, 0, sizeof(req)); 3020 memset(&req, 0, sizeof(req));
2741 3021
@@ -2761,13 +3041,10 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
2761 req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); 3041 req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
2762 } 3042 }
2763 3043
2764 if (info->attrs[NL80211_ATTR_AUTH_TYPE]) { 3044 req.auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
2765 req.auth_type = 3045 if (!nl80211_valid_auth_type(req.auth_type)) {
2766 nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]); 3046 err = -EINVAL;
2767 if (!nl80211_valid_auth_type(req.auth_type)) { 3047 goto out;
2768 err = -EINVAL;
2769 goto out;
2770 }
2771 } 3048 }
2772 3049
2773 err = drv->ops->auth(&drv->wiphy, dev, &req); 3050 err = drv->ops->auth(&drv->wiphy, dev, &req);
@@ -2788,6 +3065,13 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
2788 struct wiphy *wiphy; 3065 struct wiphy *wiphy;
2789 int err; 3066 int err;
2790 3067
3068 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
3069 return -EINVAL;
3070
3071 if (!info->attrs[NL80211_ATTR_MAC] ||
3072 !info->attrs[NL80211_ATTR_SSID])
3073 return -EINVAL;
3074
2791 rtnl_lock(); 3075 rtnl_lock();
2792 3076
2793 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 3077 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
@@ -2809,12 +3093,6 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
2809 goto out; 3093 goto out;
2810 } 3094 }
2811 3095
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; 3096 wiphy = &drv->wiphy;
2819 memset(&req, 0, sizeof(req)); 3097 memset(&req, 0, sizeof(req));
2820 3098
@@ -2838,6 +3116,19 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
2838 req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); 3116 req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
2839 } 3117 }
2840 3118
3119 if (info->attrs[NL80211_ATTR_USE_MFP]) {
3120 enum nl80211_mfp use_mfp =
3121 nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]);
3122 if (use_mfp == NL80211_MFP_REQUIRED)
3123 req.use_mfp = true;
3124 else if (use_mfp != NL80211_MFP_NO) {
3125 err = -EINVAL;
3126 goto out;
3127 }
3128 }
3129
3130 req.control_port = info->attrs[NL80211_ATTR_CONTROL_PORT];
3131
2841 err = drv->ops->assoc(&drv->wiphy, dev, &req); 3132 err = drv->ops->assoc(&drv->wiphy, dev, &req);
2842 3133
2843out: 3134out:
@@ -2856,6 +3147,15 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
2856 struct wiphy *wiphy; 3147 struct wiphy *wiphy;
2857 int err; 3148 int err;
2858 3149
3150 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
3151 return -EINVAL;
3152
3153 if (!info->attrs[NL80211_ATTR_MAC])
3154 return -EINVAL;
3155
3156 if (!info->attrs[NL80211_ATTR_REASON_CODE])
3157 return -EINVAL;
3158
2859 rtnl_lock(); 3159 rtnl_lock();
2860 3160
2861 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 3161 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
@@ -2877,24 +3177,16 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
2877 goto out; 3177 goto out;
2878 } 3178 }
2879 3179
2880 if (!info->attrs[NL80211_ATTR_MAC]) {
2881 err = -EINVAL;
2882 goto out;
2883 }
2884
2885 wiphy = &drv->wiphy; 3180 wiphy = &drv->wiphy;
2886 memset(&req, 0, sizeof(req)); 3181 memset(&req, 0, sizeof(req));
2887 3182
2888 req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 3183 req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
2889 3184
2890 if (info->attrs[NL80211_ATTR_REASON_CODE]) { 3185 req.reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
2891 req.reason_code = 3186 if (req.reason_code == 0) {
2892 nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]); 3187 /* Reason Code 0 is reserved */
2893 if (req.reason_code == 0) { 3188 err = -EINVAL;
2894 /* Reason Code 0 is reserved */ 3189 goto out;
2895 err = -EINVAL;
2896 goto out;
2897 }
2898 } 3190 }
2899 3191
2900 if (info->attrs[NL80211_ATTR_IE]) { 3192 if (info->attrs[NL80211_ATTR_IE]) {
@@ -2920,6 +3212,15 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
2920 struct wiphy *wiphy; 3212 struct wiphy *wiphy;
2921 int err; 3213 int err;
2922 3214
3215 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
3216 return -EINVAL;
3217
3218 if (!info->attrs[NL80211_ATTR_MAC])
3219 return -EINVAL;
3220
3221 if (!info->attrs[NL80211_ATTR_REASON_CODE])
3222 return -EINVAL;
3223
2923 rtnl_lock(); 3224 rtnl_lock();
2924 3225
2925 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 3226 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
@@ -2941,24 +3242,16 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
2941 goto out; 3242 goto out;
2942 } 3243 }
2943 3244
2944 if (!info->attrs[NL80211_ATTR_MAC]) {
2945 err = -EINVAL;
2946 goto out;
2947 }
2948
2949 wiphy = &drv->wiphy; 3245 wiphy = &drv->wiphy;
2950 memset(&req, 0, sizeof(req)); 3246 memset(&req, 0, sizeof(req));
2951 3247
2952 req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 3248 req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
2953 3249
2954 if (info->attrs[NL80211_ATTR_REASON_CODE]) { 3250 req.reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
2955 req.reason_code = 3251 if (req.reason_code == 0) {
2956 nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]); 3252 /* Reason Code 0 is reserved */
2957 if (req.reason_code == 0) { 3253 err = -EINVAL;
2958 /* Reason Code 0 is reserved */ 3254 goto out;
2959 err = -EINVAL;
2960 goto out;
2961 }
2962 } 3255 }
2963 3256
2964 if (info->attrs[NL80211_ATTR_IE]) { 3257 if (info->attrs[NL80211_ATTR_IE]) {
@@ -2976,6 +3269,124 @@ unlock_rtnl:
2976 return err; 3269 return err;
2977} 3270}
2978 3271
3272static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
3273{
3274 struct cfg80211_registered_device *drv;
3275 struct net_device *dev;
3276 struct cfg80211_ibss_params ibss;
3277 struct wiphy *wiphy;
3278 int err;
3279
3280 memset(&ibss, 0, sizeof(ibss));
3281
3282 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
3283 return -EINVAL;
3284
3285 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
3286 !info->attrs[NL80211_ATTR_SSID] ||
3287 !nla_len(info->attrs[NL80211_ATTR_SSID]))
3288 return -EINVAL;
3289
3290 ibss.beacon_interval = 100;
3291
3292 if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
3293 ibss.beacon_interval =
3294 nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
3295 if (ibss.beacon_interval < 1 || ibss.beacon_interval > 10000)
3296 return -EINVAL;
3297 }
3298
3299 rtnl_lock();
3300
3301 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
3302 if (err)
3303 goto unlock_rtnl;
3304
3305 if (!drv->ops->join_ibss) {
3306 err = -EOPNOTSUPP;
3307 goto out;
3308 }
3309
3310 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) {
3311 err = -EOPNOTSUPP;
3312 goto out;
3313 }
3314
3315 if (!netif_running(dev)) {
3316 err = -ENETDOWN;
3317 goto out;
3318 }
3319
3320 wiphy = &drv->wiphy;
3321
3322 if (info->attrs[NL80211_ATTR_MAC])
3323 ibss.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
3324 ibss.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
3325 ibss.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
3326
3327 if (info->attrs[NL80211_ATTR_IE]) {
3328 ibss.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
3329 ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
3330 }
3331
3332 ibss.channel = ieee80211_get_channel(wiphy,
3333 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
3334 if (!ibss.channel ||
3335 ibss.channel->flags & IEEE80211_CHAN_NO_IBSS ||
3336 ibss.channel->flags & IEEE80211_CHAN_DISABLED) {
3337 err = -EINVAL;
3338 goto out;
3339 }
3340
3341 ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
3342
3343 err = cfg80211_join_ibss(drv, dev, &ibss);
3344
3345out:
3346 cfg80211_put_dev(drv);
3347 dev_put(dev);
3348unlock_rtnl:
3349 rtnl_unlock();
3350 return err;
3351}
3352
3353static int nl80211_leave_ibss(struct sk_buff *skb, struct genl_info *info)
3354{
3355 struct cfg80211_registered_device *drv;
3356 struct net_device *dev;
3357 int err;
3358
3359 rtnl_lock();
3360
3361 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
3362 if (err)
3363 goto unlock_rtnl;
3364
3365 if (!drv->ops->leave_ibss) {
3366 err = -EOPNOTSUPP;
3367 goto out;
3368 }
3369
3370 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) {
3371 err = -EOPNOTSUPP;
3372 goto out;
3373 }
3374
3375 if (!netif_running(dev)) {
3376 err = -ENETDOWN;
3377 goto out;
3378 }
3379
3380 err = cfg80211_leave_ibss(drv, dev, false);
3381
3382out:
3383 cfg80211_put_dev(drv);
3384 dev_put(dev);
3385unlock_rtnl:
3386 rtnl_unlock();
3387 return err;
3388}
3389
2979static struct genl_ops nl80211_ops[] = { 3390static struct genl_ops nl80211_ops[] = {
2980 { 3391 {
2981 .cmd = NL80211_CMD_GET_WIPHY, 3392 .cmd = NL80211_CMD_GET_WIPHY,
@@ -3177,6 +3588,18 @@ static struct genl_ops nl80211_ops[] = {
3177 .policy = nl80211_policy, 3588 .policy = nl80211_policy,
3178 .flags = GENL_ADMIN_PERM, 3589 .flags = GENL_ADMIN_PERM,
3179 }, 3590 },
3591 {
3592 .cmd = NL80211_CMD_JOIN_IBSS,
3593 .doit = nl80211_join_ibss,
3594 .policy = nl80211_policy,
3595 .flags = GENL_ADMIN_PERM,
3596 },
3597 {
3598 .cmd = NL80211_CMD_LEAVE_IBSS,
3599 .doit = nl80211_leave_ibss,
3600 .policy = nl80211_policy,
3601 .flags = GENL_ADMIN_PERM,
3602 },
3180}; 3603};
3181static struct genl_multicast_group nl80211_mlme_mcgrp = { 3604static struct genl_multicast_group nl80211_mlme_mcgrp = {
3182 .name = "mlme", 3605 .name = "mlme",
@@ -3199,7 +3622,7 @@ void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev)
3199{ 3622{
3200 struct sk_buff *msg; 3623 struct sk_buff *msg;
3201 3624
3202 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 3625 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3203 if (!msg) 3626 if (!msg)
3204 return; 3627 return;
3205 3628
@@ -3211,11 +3634,43 @@ void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev)
3211 genlmsg_multicast(msg, 0, nl80211_config_mcgrp.id, GFP_KERNEL); 3634 genlmsg_multicast(msg, 0, nl80211_config_mcgrp.id, GFP_KERNEL);
3212} 3635}
3213 3636
3637static int nl80211_add_scan_req(struct sk_buff *msg,
3638 struct cfg80211_registered_device *rdev)
3639{
3640 struct cfg80211_scan_request *req = rdev->scan_req;
3641 struct nlattr *nest;
3642 int i;
3643
3644 if (WARN_ON(!req))
3645 return 0;
3646
3647 nest = nla_nest_start(msg, NL80211_ATTR_SCAN_SSIDS);
3648 if (!nest)
3649 goto nla_put_failure;
3650 for (i = 0; i < req->n_ssids; i++)
3651 NLA_PUT(msg, i, req->ssids[i].ssid_len, req->ssids[i].ssid);
3652 nla_nest_end(msg, nest);
3653
3654 nest = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES);
3655 if (!nest)
3656 goto nla_put_failure;
3657 for (i = 0; i < req->n_channels; i++)
3658 NLA_PUT_U32(msg, i, req->channels[i]->center_freq);
3659 nla_nest_end(msg, nest);
3660
3661 if (req->ie)
3662 NLA_PUT(msg, NL80211_ATTR_IE, req->ie_len, req->ie);
3663
3664 return 0;
3665 nla_put_failure:
3666 return -ENOBUFS;
3667}
3668
3214static int nl80211_send_scan_donemsg(struct sk_buff *msg, 3669static int nl80211_send_scan_donemsg(struct sk_buff *msg,
3215 struct cfg80211_registered_device *rdev, 3670 struct cfg80211_registered_device *rdev,
3216 struct net_device *netdev, 3671 struct net_device *netdev,
3217 u32 pid, u32 seq, int flags, 3672 u32 pid, u32 seq, int flags,
3218 u32 cmd) 3673 u32 cmd)
3219{ 3674{
3220 void *hdr; 3675 void *hdr;
3221 3676
@@ -3226,7 +3681,8 @@ static int nl80211_send_scan_donemsg(struct sk_buff *msg,
3226 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); 3681 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
3227 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); 3682 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
3228 3683
3229 /* XXX: we should probably bounce back the request? */ 3684 /* ignore errors and send incomplete event anyway */
3685 nl80211_add_scan_req(msg, rdev);
3230 3686
3231 return genlmsg_end(msg, hdr); 3687 return genlmsg_end(msg, hdr);
3232 3688
@@ -3240,7 +3696,7 @@ void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
3240{ 3696{
3241 struct sk_buff *msg; 3697 struct sk_buff *msg;
3242 3698
3243 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 3699 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3244 if (!msg) 3700 if (!msg)
3245 return; 3701 return;
3246 3702
@@ -3258,7 +3714,7 @@ void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
3258{ 3714{
3259 struct sk_buff *msg; 3715 struct sk_buff *msg;
3260 3716
3261 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 3717 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3262 if (!msg) 3718 if (!msg)
3263 return; 3719 return;
3264 3720
@@ -3280,7 +3736,7 @@ void nl80211_send_reg_change_event(struct regulatory_request *request)
3280 struct sk_buff *msg; 3736 struct sk_buff *msg;
3281 void *hdr; 3737 void *hdr;
3282 3738
3283 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 3739 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3284 if (!msg) 3740 if (!msg)
3285 return; 3741 return;
3286 3742
@@ -3334,7 +3790,7 @@ static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev,
3334 struct sk_buff *msg; 3790 struct sk_buff *msg;
3335 void *hdr; 3791 void *hdr;
3336 3792
3337 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); 3793 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
3338 if (!msg) 3794 if (!msg)
3339 return; 3795 return;
3340 3796
@@ -3375,38 +3831,208 @@ void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
3375 nl80211_send_mlme_event(rdev, netdev, buf, len, NL80211_CMD_ASSOCIATE); 3831 nl80211_send_mlme_event(rdev, netdev, buf, len, NL80211_CMD_ASSOCIATE);
3376} 3832}
3377 3833
3378void nl80211_send_rx_deauth(struct cfg80211_registered_device *rdev, 3834void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
3379 struct net_device *netdev, const u8 *buf, 3835 struct net_device *netdev, const u8 *buf, size_t len)
3380 size_t len)
3381{ 3836{
3382 nl80211_send_mlme_event(rdev, netdev, buf, len, 3837 nl80211_send_mlme_event(rdev, netdev, buf, len,
3383 NL80211_CMD_DEAUTHENTICATE); 3838 NL80211_CMD_DEAUTHENTICATE);
3384} 3839}
3385 3840
3386void nl80211_send_rx_disassoc(struct cfg80211_registered_device *rdev, 3841void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
3387 struct net_device *netdev, const u8 *buf, 3842 struct net_device *netdev, const u8 *buf,
3388 size_t len) 3843 size_t len)
3389{ 3844{
3390 nl80211_send_mlme_event(rdev, netdev, buf, len, 3845 nl80211_send_mlme_event(rdev, netdev, buf, len,
3391 NL80211_CMD_DISASSOCIATE); 3846 NL80211_CMD_DISASSOCIATE);
3392} 3847}
3393 3848
3849static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev,
3850 struct net_device *netdev, int cmd,
3851 const u8 *addr)
3852{
3853 struct sk_buff *msg;
3854 void *hdr;
3855
3856 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
3857 if (!msg)
3858 return;
3859
3860 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
3861 if (!hdr) {
3862 nlmsg_free(msg);
3863 return;
3864 }
3865
3866 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
3867 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
3868 NLA_PUT_FLAG(msg, NL80211_ATTR_TIMED_OUT);
3869 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
3870
3871 if (genlmsg_end(msg, hdr) < 0) {
3872 nlmsg_free(msg);
3873 return;
3874 }
3875
3876 genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, GFP_ATOMIC);
3877 return;
3878
3879 nla_put_failure:
3880 genlmsg_cancel(msg, hdr);
3881 nlmsg_free(msg);
3882}
3883
3884void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev,
3885 struct net_device *netdev, const u8 *addr)
3886{
3887 nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_AUTHENTICATE,
3888 addr);
3889}
3890
3891void nl80211_send_assoc_timeout(struct cfg80211_registered_device *rdev,
3892 struct net_device *netdev, const u8 *addr)
3893{
3894 nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_ASSOCIATE, addr);
3895}
3896
3897void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
3898 struct net_device *netdev, const u8 *bssid,
3899 gfp_t gfp)
3900{
3901 struct sk_buff *msg;
3902 void *hdr;
3903
3904 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
3905 if (!msg)
3906 return;
3907
3908 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_JOIN_IBSS);
3909 if (!hdr) {
3910 nlmsg_free(msg);
3911 return;
3912 }
3913
3914 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
3915 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
3916 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid);
3917
3918 if (genlmsg_end(msg, hdr) < 0) {
3919 nlmsg_free(msg);
3920 return;
3921 }
3922
3923 genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp);
3924 return;
3925
3926 nla_put_failure:
3927 genlmsg_cancel(msg, hdr);
3928 nlmsg_free(msg);
3929}
3930
3931void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
3932 struct net_device *netdev, const u8 *addr,
3933 enum nl80211_key_type key_type, int key_id,
3934 const u8 *tsc)
3935{
3936 struct sk_buff *msg;
3937 void *hdr;
3938
3939 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
3940 if (!msg)
3941 return;
3942
3943 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_MICHAEL_MIC_FAILURE);
3944 if (!hdr) {
3945 nlmsg_free(msg);
3946 return;
3947 }
3948
3949 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
3950 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
3951 if (addr)
3952 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
3953 NLA_PUT_U32(msg, NL80211_ATTR_KEY_TYPE, key_type);
3954 NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_id);
3955 if (tsc)
3956 NLA_PUT(msg, NL80211_ATTR_KEY_SEQ, 6, tsc);
3957
3958 if (genlmsg_end(msg, hdr) < 0) {
3959 nlmsg_free(msg);
3960 return;
3961 }
3962
3963 genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, GFP_ATOMIC);
3964 return;
3965
3966 nla_put_failure:
3967 genlmsg_cancel(msg, hdr);
3968 nlmsg_free(msg);
3969}
3970
3971void nl80211_send_beacon_hint_event(struct wiphy *wiphy,
3972 struct ieee80211_channel *channel_before,
3973 struct ieee80211_channel *channel_after)
3974{
3975 struct sk_buff *msg;
3976 void *hdr;
3977 struct nlattr *nl_freq;
3978
3979 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
3980 if (!msg)
3981 return;
3982
3983 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_REG_BEACON_HINT);
3984 if (!hdr) {
3985 nlmsg_free(msg);
3986 return;
3987 }
3988
3989 /*
3990 * Since we are applying the beacon hint to a wiphy we know its
3991 * wiphy_idx is valid
3992 */
3993 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy));
3994
3995 /* Before */
3996 nl_freq = nla_nest_start(msg, NL80211_ATTR_FREQ_BEFORE);
3997 if (!nl_freq)
3998 goto nla_put_failure;
3999 if (nl80211_msg_put_channel(msg, channel_before))
4000 goto nla_put_failure;
4001 nla_nest_end(msg, nl_freq);
4002
4003 /* After */
4004 nl_freq = nla_nest_start(msg, NL80211_ATTR_FREQ_AFTER);
4005 if (!nl_freq)
4006 goto nla_put_failure;
4007 if (nl80211_msg_put_channel(msg, channel_after))
4008 goto nla_put_failure;
4009 nla_nest_end(msg, nl_freq);
4010
4011 if (genlmsg_end(msg, hdr) < 0) {
4012 nlmsg_free(msg);
4013 return;
4014 }
4015
4016 genlmsg_multicast(msg, 0, nl80211_regulatory_mcgrp.id, GFP_ATOMIC);
4017
4018 return;
4019
4020nla_put_failure:
4021 genlmsg_cancel(msg, hdr);
4022 nlmsg_free(msg);
4023}
4024
3394/* initialisation/exit functions */ 4025/* initialisation/exit functions */
3395 4026
3396int nl80211_init(void) 4027int nl80211_init(void)
3397{ 4028{
3398 int err, i; 4029 int err;
3399 4030
3400 err = genl_register_family(&nl80211_fam); 4031 err = genl_register_family_with_ops(&nl80211_fam,
4032 nl80211_ops, ARRAY_SIZE(nl80211_ops));
3401 if (err) 4033 if (err)
3402 return err; 4034 return err;
3403 4035
3404 for (i = 0; i < ARRAY_SIZE(nl80211_ops); i++) {
3405 err = genl_register_ops(&nl80211_fam, &nl80211_ops[i]);
3406 if (err)
3407 goto err_out;
3408 }
3409
3410 err = genl_register_mc_group(&nl80211_fam, &nl80211_config_mcgrp); 4036 err = genl_register_mc_group(&nl80211_fam, &nl80211_config_mcgrp);
3411 if (err) 4037 if (err)
3412 goto err_out; 4038 goto err_out;
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h
index b77af4ab80be..5c12ad13499b 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -17,11 +17,31 @@ extern void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev,
17extern void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev, 17extern void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
18 struct net_device *netdev, 18 struct net_device *netdev,
19 const u8 *buf, size_t len); 19 const u8 *buf, size_t len);
20extern void nl80211_send_rx_deauth(struct cfg80211_registered_device *rdev, 20extern void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
21 struct net_device *netdev, 21 struct net_device *netdev,
22 const u8 *buf, size_t len); 22 const u8 *buf, size_t len);
23extern void nl80211_send_rx_disassoc(struct cfg80211_registered_device *rdev, 23extern void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
24 struct net_device *netdev, 24 struct net_device *netdev,
25 const u8 *buf, size_t len); 25 const u8 *buf, size_t len);
26extern void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev,
27 struct net_device *netdev,
28 const u8 *addr);
29extern void nl80211_send_assoc_timeout(struct cfg80211_registered_device *rdev,
30 struct net_device *netdev,
31 const u8 *addr);
32extern void
33nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
34 struct net_device *netdev, const u8 *addr,
35 enum nl80211_key_type key_type,
36 int key_id, const u8 *tsc);
37
38extern void
39nl80211_send_beacon_hint_event(struct wiphy *wiphy,
40 struct ieee80211_channel *channel_before,
41 struct ieee80211_channel *channel_after);
42
43void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
44 struct net_device *netdev, const u8 *bssid,
45 gfp_t gfp);
26 46
27#endif /* __NET_WIRELESS_NL80211_H */ 47#endif /* __NET_WIRELESS_NL80211_H */
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 487cb627ddba..5e14371cda70 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -37,7 +37,6 @@
37#include <linux/random.h> 37#include <linux/random.h>
38#include <linux/nl80211.h> 38#include <linux/nl80211.h>
39#include <linux/platform_device.h> 39#include <linux/platform_device.h>
40#include <net/wireless.h>
41#include <net/cfg80211.h> 40#include <net/cfg80211.h>
42#include "core.h" 41#include "core.h"
43#include "reg.h" 42#include "reg.h"
@@ -49,12 +48,6 @@ static struct regulatory_request *last_request;
49/* To trigger userspace events */ 48/* To trigger userspace events */
50static struct platform_device *reg_pdev; 49static struct platform_device *reg_pdev;
51 50
52/* Keep the ordering from large to small */
53static u32 supported_bandwidths[] = {
54 MHZ_TO_KHZ(40),
55 MHZ_TO_KHZ(20),
56};
57
58/* 51/*
59 * Central wireless core regulatory domains, we only need two, 52 * Central wireless core regulatory domains, we only need two,
60 * the current one and a world regulatory domain in case we have no 53 * the current one and a world regulatory domain in case we have no
@@ -389,6 +382,8 @@ static int call_crda(const char *alpha2)
389/* Used by nl80211 before kmalloc'ing our regulatory domain */ 382/* Used by nl80211 before kmalloc'ing our regulatory domain */
390bool reg_is_valid_request(const char *alpha2) 383bool reg_is_valid_request(const char *alpha2)
391{ 384{
385 assert_cfg80211_lock();
386
392 if (!last_request) 387 if (!last_request)
393 return false; 388 return false;
394 389
@@ -436,19 +431,20 @@ static bool is_valid_rd(const struct ieee80211_regdomain *rd)
436 return true; 431 return true;
437} 432}
438 433
439/* Returns value in KHz */ 434static bool reg_does_bw_fit(const struct ieee80211_freq_range *freq_range,
440static u32 freq_max_bandwidth(const struct ieee80211_freq_range *freq_range, 435 u32 center_freq_khz,
441 u32 freq) 436 u32 bw_khz)
442{ 437{
443 unsigned int i; 438 u32 start_freq_khz, end_freq_khz;
444 for (i = 0; i < ARRAY_SIZE(supported_bandwidths); i++) { 439
445 u32 start_freq_khz = freq - supported_bandwidths[i]/2; 440 start_freq_khz = center_freq_khz - (bw_khz/2);
446 u32 end_freq_khz = freq + supported_bandwidths[i]/2; 441 end_freq_khz = center_freq_khz + (bw_khz/2);
447 if (start_freq_khz >= freq_range->start_freq_khz && 442
448 end_freq_khz <= freq_range->end_freq_khz) 443 if (start_freq_khz >= freq_range->start_freq_khz &&
449 return supported_bandwidths[i]; 444 end_freq_khz <= freq_range->end_freq_khz)
450 } 445 return true;
451 return 0; 446
447 return false;
452} 448}
453 449
454/** 450/**
@@ -848,14 +844,17 @@ static u32 map_regdom_flags(u32 rd_flags)
848 844
849static int freq_reg_info_regd(struct wiphy *wiphy, 845static int freq_reg_info_regd(struct wiphy *wiphy,
850 u32 center_freq, 846 u32 center_freq,
851 u32 *bandwidth, 847 u32 desired_bw_khz,
852 const struct ieee80211_reg_rule **reg_rule, 848 const struct ieee80211_reg_rule **reg_rule,
853 const struct ieee80211_regdomain *custom_regd) 849 const struct ieee80211_regdomain *custom_regd)
854{ 850{
855 int i; 851 int i;
856 bool band_rule_found = false; 852 bool band_rule_found = false;
857 const struct ieee80211_regdomain *regd; 853 const struct ieee80211_regdomain *regd;
858 u32 max_bandwidth = 0; 854 bool bw_fits = false;
855
856 if (!desired_bw_khz)
857 desired_bw_khz = MHZ_TO_KHZ(20);
859 858
860 regd = custom_regd ? custom_regd : cfg80211_regdomain; 859 regd = custom_regd ? custom_regd : cfg80211_regdomain;
861 860
@@ -888,38 +887,54 @@ static int freq_reg_info_regd(struct wiphy *wiphy,
888 if (!band_rule_found) 887 if (!band_rule_found)
889 band_rule_found = freq_in_rule_band(fr, center_freq); 888 band_rule_found = freq_in_rule_band(fr, center_freq);
890 889
891 max_bandwidth = freq_max_bandwidth(fr, center_freq); 890 bw_fits = reg_does_bw_fit(fr,
891 center_freq,
892 desired_bw_khz);
892 893
893 if (max_bandwidth && *bandwidth <= max_bandwidth) { 894 if (band_rule_found && bw_fits) {
894 *reg_rule = rr; 895 *reg_rule = rr;
895 *bandwidth = max_bandwidth; 896 return 0;
896 break;
897 } 897 }
898 } 898 }
899 899
900 if (!band_rule_found) 900 if (!band_rule_found)
901 return -ERANGE; 901 return -ERANGE;
902 902
903 return !max_bandwidth; 903 return -EINVAL;
904} 904}
905EXPORT_SYMBOL(freq_reg_info); 905EXPORT_SYMBOL(freq_reg_info);
906 906
907int freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 *bandwidth, 907int freq_reg_info(struct wiphy *wiphy,
908 const struct ieee80211_reg_rule **reg_rule) 908 u32 center_freq,
909 u32 desired_bw_khz,
910 const struct ieee80211_reg_rule **reg_rule)
909{ 911{
910 assert_cfg80211_lock(); 912 assert_cfg80211_lock();
911 return freq_reg_info_regd(wiphy, center_freq, 913 return freq_reg_info_regd(wiphy,
912 bandwidth, reg_rule, NULL); 914 center_freq,
915 desired_bw_khz,
916 reg_rule,
917 NULL);
913} 918}
914 919
920/*
921 * Note that right now we assume the desired channel bandwidth
922 * is always 20 MHz for each individual channel (HT40 uses 20 MHz
923 * per channel, the primary and the extension channel). To support
924 * smaller custom bandwidths such as 5 MHz or 10 MHz we'll need a
925 * new ieee80211_channel.target_bw and re run the regulatory check
926 * on the wiphy with the target_bw specified. Then we can simply use
927 * that below for the desired_bw_khz below.
928 */
915static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, 929static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
916 unsigned int chan_idx) 930 unsigned int chan_idx)
917{ 931{
918 int r; 932 int r;
919 u32 flags; 933 u32 flags, bw_flags = 0;
920 u32 max_bandwidth = 0; 934 u32 desired_bw_khz = MHZ_TO_KHZ(20);
921 const struct ieee80211_reg_rule *reg_rule = NULL; 935 const struct ieee80211_reg_rule *reg_rule = NULL;
922 const struct ieee80211_power_rule *power_rule = NULL; 936 const struct ieee80211_power_rule *power_rule = NULL;
937 const struct ieee80211_freq_range *freq_range = NULL;
923 struct ieee80211_supported_band *sband; 938 struct ieee80211_supported_band *sband;
924 struct ieee80211_channel *chan; 939 struct ieee80211_channel *chan;
925 struct wiphy *request_wiphy = NULL; 940 struct wiphy *request_wiphy = NULL;
@@ -934,8 +949,10 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
934 949
935 flags = chan->orig_flags; 950 flags = chan->orig_flags;
936 951
937 r = freq_reg_info(wiphy, MHZ_TO_KHZ(chan->center_freq), 952 r = freq_reg_info(wiphy,
938 &max_bandwidth, &reg_rule); 953 MHZ_TO_KHZ(chan->center_freq),
954 desired_bw_khz,
955 &reg_rule);
939 956
940 if (r) { 957 if (r) {
941 /* 958 /*
@@ -978,6 +995,10 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
978 } 995 }
979 996
980 power_rule = &reg_rule->power_rule; 997 power_rule = &reg_rule->power_rule;
998 freq_range = &reg_rule->freq_range;
999
1000 if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40))
1001 bw_flags = IEEE80211_CHAN_NO_HT40;
981 1002
982 if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && 1003 if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
983 request_wiphy && request_wiphy == wiphy && 1004 request_wiphy && request_wiphy == wiphy &&
@@ -988,19 +1009,19 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
988 * settings 1009 * settings
989 */ 1010 */
990 chan->flags = chan->orig_flags = 1011 chan->flags = chan->orig_flags =
991 map_regdom_flags(reg_rule->flags); 1012 map_regdom_flags(reg_rule->flags) | bw_flags;
992 chan->max_antenna_gain = chan->orig_mag = 1013 chan->max_antenna_gain = chan->orig_mag =
993 (int) MBI_TO_DBI(power_rule->max_antenna_gain); 1014 (int) MBI_TO_DBI(power_rule->max_antenna_gain);
994 chan->max_bandwidth = KHZ_TO_MHZ(max_bandwidth); 1015 chan->max_bandwidth = KHZ_TO_MHZ(desired_bw_khz);
995 chan->max_power = chan->orig_mpwr = 1016 chan->max_power = chan->orig_mpwr =
996 (int) MBM_TO_DBM(power_rule->max_eirp); 1017 (int) MBM_TO_DBM(power_rule->max_eirp);
997 return; 1018 return;
998 } 1019 }
999 1020
1000 chan->flags = flags | map_regdom_flags(reg_rule->flags); 1021 chan->flags = flags | bw_flags | map_regdom_flags(reg_rule->flags);
1001 chan->max_antenna_gain = min(chan->orig_mag, 1022 chan->max_antenna_gain = min(chan->orig_mag,
1002 (int) MBI_TO_DBI(power_rule->max_antenna_gain)); 1023 (int) MBI_TO_DBI(power_rule->max_antenna_gain));
1003 chan->max_bandwidth = KHZ_TO_MHZ(max_bandwidth); 1024 chan->max_bandwidth = KHZ_TO_MHZ(desired_bw_khz);
1004 if (chan->orig_mpwr) 1025 if (chan->orig_mpwr)
1005 chan->max_power = min(chan->orig_mpwr, 1026 chan->max_power = min(chan->orig_mpwr,
1006 (int) MBM_TO_DBM(power_rule->max_eirp)); 1027 (int) MBM_TO_DBM(power_rule->max_eirp));
@@ -1050,18 +1071,10 @@ static void handle_reg_beacon(struct wiphy *wiphy,
1050 unsigned int chan_idx, 1071 unsigned int chan_idx,
1051 struct reg_beacon *reg_beacon) 1072 struct reg_beacon *reg_beacon)
1052{ 1073{
1053#ifdef CONFIG_CFG80211_REG_DEBUG
1054#define REG_DEBUG_BEACON_FLAG(desc) \
1055 printk(KERN_DEBUG "cfg80211: Enabling " desc " on " \
1056 "frequency: %d MHz (Ch %d) on %s\n", \
1057 reg_beacon->chan.center_freq, \
1058 ieee80211_frequency_to_channel(reg_beacon->chan.center_freq), \
1059 wiphy_name(wiphy));
1060#else
1061#define REG_DEBUG_BEACON_FLAG(desc) do {} while (0)
1062#endif
1063 struct ieee80211_supported_band *sband; 1074 struct ieee80211_supported_band *sband;
1064 struct ieee80211_channel *chan; 1075 struct ieee80211_channel *chan;
1076 bool channel_changed = false;
1077 struct ieee80211_channel chan_before;
1065 1078
1066 assert_cfg80211_lock(); 1079 assert_cfg80211_lock();
1067 1080
@@ -1071,18 +1084,28 @@ static void handle_reg_beacon(struct wiphy *wiphy,
1071 if (likely(chan->center_freq != reg_beacon->chan.center_freq)) 1084 if (likely(chan->center_freq != reg_beacon->chan.center_freq))
1072 return; 1085 return;
1073 1086
1074 if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) { 1087 if (chan->beacon_found)
1088 return;
1089
1090 chan->beacon_found = true;
1091
1092 chan_before.center_freq = chan->center_freq;
1093 chan_before.flags = chan->flags;
1094
1095 if ((chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) &&
1096 !(chan->orig_flags & IEEE80211_CHAN_PASSIVE_SCAN)) {
1075 chan->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; 1097 chan->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
1076 REG_DEBUG_BEACON_FLAG("active scanning"); 1098 channel_changed = true;
1077 } 1099 }
1078 1100
1079 if (chan->flags & IEEE80211_CHAN_NO_IBSS) { 1101 if ((chan->flags & IEEE80211_CHAN_NO_IBSS) &&
1102 !(chan->orig_flags & IEEE80211_CHAN_NO_IBSS)) {
1080 chan->flags &= ~IEEE80211_CHAN_NO_IBSS; 1103 chan->flags &= ~IEEE80211_CHAN_NO_IBSS;
1081 REG_DEBUG_BEACON_FLAG("beaconing"); 1104 channel_changed = true;
1082 } 1105 }
1083 1106
1084 chan->beacon_found = true; 1107 if (channel_changed)
1085#undef REG_DEBUG_BEACON_FLAG 1108 nl80211_send_beacon_hint_event(wiphy, &chan_before, chan);
1086} 1109}
1087 1110
1088/* 1111/*
@@ -1155,6 +1178,93 @@ static void reg_process_beacons(struct wiphy *wiphy)
1155 wiphy_update_beacon_reg(wiphy); 1178 wiphy_update_beacon_reg(wiphy);
1156} 1179}
1157 1180
1181static bool is_ht40_not_allowed(struct ieee80211_channel *chan)
1182{
1183 if (!chan)
1184 return true;
1185 if (chan->flags & IEEE80211_CHAN_DISABLED)
1186 return true;
1187 /* This would happen when regulatory rules disallow HT40 completely */
1188 if (IEEE80211_CHAN_NO_HT40 == (chan->flags & (IEEE80211_CHAN_NO_HT40)))
1189 return true;
1190 return false;
1191}
1192
1193static void reg_process_ht_flags_channel(struct wiphy *wiphy,
1194 enum ieee80211_band band,
1195 unsigned int chan_idx)
1196{
1197 struct ieee80211_supported_band *sband;
1198 struct ieee80211_channel *channel;
1199 struct ieee80211_channel *channel_before = NULL, *channel_after = NULL;
1200 unsigned int i;
1201
1202 assert_cfg80211_lock();
1203
1204 sband = wiphy->bands[band];
1205 BUG_ON(chan_idx >= sband->n_channels);
1206 channel = &sband->channels[chan_idx];
1207
1208 if (is_ht40_not_allowed(channel)) {
1209 channel->flags |= IEEE80211_CHAN_NO_HT40;
1210 return;
1211 }
1212
1213 /*
1214 * We need to ensure the extension channels exist to
1215 * be able to use HT40- or HT40+, this finds them (or not)
1216 */
1217 for (i = 0; i < sband->n_channels; i++) {
1218 struct ieee80211_channel *c = &sband->channels[i];
1219 if (c->center_freq == (channel->center_freq - 20))
1220 channel_before = c;
1221 if (c->center_freq == (channel->center_freq + 20))
1222 channel_after = c;
1223 }
1224
1225 /*
1226 * Please note that this assumes target bandwidth is 20 MHz,
1227 * if that ever changes we also need to change the below logic
1228 * to include that as well.
1229 */
1230 if (is_ht40_not_allowed(channel_before))
1231 channel->flags |= IEEE80211_CHAN_NO_HT40MINUS;
1232 else
1233 channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS;
1234
1235 if (is_ht40_not_allowed(channel_after))
1236 channel->flags |= IEEE80211_CHAN_NO_HT40PLUS;
1237 else
1238 channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS;
1239}
1240
1241static void reg_process_ht_flags_band(struct wiphy *wiphy,
1242 enum ieee80211_band band)
1243{
1244 unsigned int i;
1245 struct ieee80211_supported_band *sband;
1246
1247 BUG_ON(!wiphy->bands[band]);
1248 sband = wiphy->bands[band];
1249
1250 for (i = 0; i < sband->n_channels; i++)
1251 reg_process_ht_flags_channel(wiphy, band, i);
1252}
1253
1254static void reg_process_ht_flags(struct wiphy *wiphy)
1255{
1256 enum ieee80211_band band;
1257
1258 if (!wiphy)
1259 return;
1260
1261 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
1262 if (wiphy->bands[band])
1263 reg_process_ht_flags_band(wiphy, band);
1264 }
1265
1266}
1267
1158void wiphy_update_regulatory(struct wiphy *wiphy, 1268void wiphy_update_regulatory(struct wiphy *wiphy,
1159 enum nl80211_reg_initiator initiator) 1269 enum nl80211_reg_initiator initiator)
1160{ 1270{
@@ -1168,6 +1278,7 @@ void wiphy_update_regulatory(struct wiphy *wiphy,
1168 } 1278 }
1169out: 1279out:
1170 reg_process_beacons(wiphy); 1280 reg_process_beacons(wiphy);
1281 reg_process_ht_flags(wiphy);
1171 if (wiphy->reg_notifier) 1282 if (wiphy->reg_notifier)
1172 wiphy->reg_notifier(wiphy, last_request); 1283 wiphy->reg_notifier(wiphy, last_request);
1173} 1284}
@@ -1178,9 +1289,11 @@ static void handle_channel_custom(struct wiphy *wiphy,
1178 const struct ieee80211_regdomain *regd) 1289 const struct ieee80211_regdomain *regd)
1179{ 1290{
1180 int r; 1291 int r;
1181 u32 max_bandwidth = 0; 1292 u32 desired_bw_khz = MHZ_TO_KHZ(20);
1293 u32 bw_flags = 0;
1182 const struct ieee80211_reg_rule *reg_rule = NULL; 1294 const struct ieee80211_reg_rule *reg_rule = NULL;
1183 const struct ieee80211_power_rule *power_rule = NULL; 1295 const struct ieee80211_power_rule *power_rule = NULL;
1296 const struct ieee80211_freq_range *freq_range = NULL;
1184 struct ieee80211_supported_band *sband; 1297 struct ieee80211_supported_band *sband;
1185 struct ieee80211_channel *chan; 1298 struct ieee80211_channel *chan;
1186 1299
@@ -1190,8 +1303,11 @@ static void handle_channel_custom(struct wiphy *wiphy,
1190 BUG_ON(chan_idx >= sband->n_channels); 1303 BUG_ON(chan_idx >= sband->n_channels);
1191 chan = &sband->channels[chan_idx]; 1304 chan = &sband->channels[chan_idx];
1192 1305
1193 r = freq_reg_info_regd(wiphy, MHZ_TO_KHZ(chan->center_freq), 1306 r = freq_reg_info_regd(wiphy,
1194 &max_bandwidth, &reg_rule, regd); 1307 MHZ_TO_KHZ(chan->center_freq),
1308 desired_bw_khz,
1309 &reg_rule,
1310 regd);
1195 1311
1196 if (r) { 1312 if (r) {
1197 chan->flags = IEEE80211_CHAN_DISABLED; 1313 chan->flags = IEEE80211_CHAN_DISABLED;
@@ -1199,10 +1315,14 @@ static void handle_channel_custom(struct wiphy *wiphy,
1199 } 1315 }
1200 1316
1201 power_rule = &reg_rule->power_rule; 1317 power_rule = &reg_rule->power_rule;
1318 freq_range = &reg_rule->freq_range;
1319
1320 if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40))
1321 bw_flags = IEEE80211_CHAN_NO_HT40;
1202 1322
1203 chan->flags |= map_regdom_flags(reg_rule->flags); 1323 chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags;
1204 chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain); 1324 chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain);
1205 chan->max_bandwidth = KHZ_TO_MHZ(max_bandwidth); 1325 chan->max_bandwidth = KHZ_TO_MHZ(desired_bw_khz);
1206 chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp); 1326 chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp);
1207} 1327}
1208 1328
@@ -1224,13 +1344,22 @@ void wiphy_apply_custom_regulatory(struct wiphy *wiphy,
1224 const struct ieee80211_regdomain *regd) 1344 const struct ieee80211_regdomain *regd)
1225{ 1345{
1226 enum ieee80211_band band; 1346 enum ieee80211_band band;
1347 unsigned int bands_set = 0;
1227 1348
1228 mutex_lock(&cfg80211_mutex); 1349 mutex_lock(&cfg80211_mutex);
1229 for (band = 0; band < IEEE80211_NUM_BANDS; band++) { 1350 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
1230 if (wiphy->bands[band]) 1351 if (!wiphy->bands[band])
1231 handle_band_custom(wiphy, band, regd); 1352 continue;
1353 handle_band_custom(wiphy, band, regd);
1354 bands_set++;
1232 } 1355 }
1233 mutex_unlock(&cfg80211_mutex); 1356 mutex_unlock(&cfg80211_mutex);
1357
1358 /*
1359 * no point in calling this if it won't have any effect
1360 * on your device's supportd bands.
1361 */
1362 WARN_ON(!bands_set);
1234} 1363}
1235EXPORT_SYMBOL(wiphy_apply_custom_regulatory); 1364EXPORT_SYMBOL(wiphy_apply_custom_regulatory);
1236 1365
@@ -2000,7 +2129,12 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
2000 * driver wanted to the wiphy to deal with conflicts 2129 * driver wanted to the wiphy to deal with conflicts
2001 */ 2130 */
2002 2131
2003 BUG_ON(request_wiphy->regd); 2132 /*
2133 * Userspace could have sent two replies with only
2134 * one kernel request.
2135 */
2136 if (request_wiphy->regd)
2137 return -EALREADY;
2004 2138
2005 r = reg_copy_regd(&request_wiphy->regd, rd); 2139 r = reg_copy_regd(&request_wiphy->regd, rd);
2006 if (r) 2140 if (r)
@@ -2042,7 +2176,13 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
2042 * the country IE rd with what CRDA believes that country should have 2176 * the country IE rd with what CRDA believes that country should have
2043 */ 2177 */
2044 2178
2045 BUG_ON(!country_ie_regdomain); 2179 /*
2180 * Userspace could have sent two replies with only
2181 * one kernel request. By the second reply we would have
2182 * already processed and consumed the country_ie_regdomain.
2183 */
2184 if (!country_ie_regdomain)
2185 return -EALREADY;
2046 BUG_ON(rd == country_ie_regdomain); 2186 BUG_ON(rd == country_ie_regdomain);
2047 2187
2048 /* 2188 /*
@@ -2119,14 +2259,14 @@ void reg_device_remove(struct wiphy *wiphy)
2119 2259
2120 assert_cfg80211_lock(); 2260 assert_cfg80211_lock();
2121 2261
2262 kfree(wiphy->regd);
2263
2122 if (last_request) 2264 if (last_request)
2123 request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); 2265 request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx);
2124 2266
2125 kfree(wiphy->regd); 2267 if (!request_wiphy || request_wiphy != wiphy)
2126 if (!last_request || !request_wiphy)
2127 return;
2128 if (request_wiphy != wiphy)
2129 return; 2268 return;
2269
2130 last_request->wiphy_idx = WIPHY_IDX_STALE; 2270 last_request->wiphy_idx = WIPHY_IDX_STALE;
2131 last_request->country_ie_env = ENVIRON_ANY; 2271 last_request->country_ie_env = ENVIRON_ANY;
2132} 2272}
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 1f260c40b6ca..e95b638b919f 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -29,13 +29,14 @@ void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
29 goto out; 29 goto out;
30 30
31 WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req); 31 WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req);
32 wiphy_to_dev(request->wiphy)->scan_req = NULL;
33 32
34 if (aborted) 33 if (aborted)
35 nl80211_send_scan_aborted(wiphy_to_dev(request->wiphy), dev); 34 nl80211_send_scan_aborted(wiphy_to_dev(request->wiphy), dev);
36 else 35 else
37 nl80211_send_scan_done(wiphy_to_dev(request->wiphy), dev); 36 nl80211_send_scan_done(wiphy_to_dev(request->wiphy), dev);
38 37
38 wiphy_to_dev(request->wiphy)->scan_req = NULL;
39
39#ifdef CONFIG_WIRELESS_EXT 40#ifdef CONFIG_WIRELESS_EXT
40 if (!aborted) { 41 if (!aborted) {
41 memset(&wrqu, 0, sizeof(wrqu)); 42 memset(&wrqu, 0, sizeof(wrqu));
@@ -377,18 +378,16 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
377 size_t used = dev->wiphy.bss_priv_size + sizeof(*res); 378 size_t used = dev->wiphy.bss_priv_size + sizeof(*res);
378 size_t ielen = res->pub.len_information_elements; 379 size_t ielen = res->pub.len_information_elements;
379 380
380 if (ksize(found) >= used + ielen) { 381 if (!found->ies_allocated && ksize(found) >= used + ielen) {
381 memcpy(found->pub.information_elements, 382 memcpy(found->pub.information_elements,
382 res->pub.information_elements, ielen); 383 res->pub.information_elements, ielen);
383 found->pub.len_information_elements = ielen; 384 found->pub.len_information_elements = ielen;
384 } else { 385 } else {
385 u8 *ies = found->pub.information_elements; 386 u8 *ies = found->pub.information_elements;
386 387
387 if (found->ies_allocated) { 388 if (found->ies_allocated)
388 if (ksize(ies) < ielen) 389 ies = krealloc(ies, ielen, GFP_ATOMIC);
389 ies = krealloc(ies, ielen, 390 else
390 GFP_ATOMIC);
391 } else
392 ies = kmalloc(ielen, GFP_ATOMIC); 391 ies = kmalloc(ielen, GFP_ATOMIC);
393 392
394 if (ies) { 393 if (ies) {
@@ -415,6 +414,55 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
415 return found; 414 return found;
416} 415}
417 416
417struct cfg80211_bss*
418cfg80211_inform_bss(struct wiphy *wiphy,
419 struct ieee80211_channel *channel,
420 const u8 *bssid,
421 u64 timestamp, u16 capability, u16 beacon_interval,
422 const u8 *ie, size_t ielen,
423 s32 signal, gfp_t gfp)
424{
425 struct cfg80211_internal_bss *res;
426 size_t privsz;
427
428 if (WARN_ON(!wiphy))
429 return NULL;
430
431 privsz = wiphy->bss_priv_size;
432
433 if (WARN_ON(wiphy->signal_type == NL80211_BSS_SIGNAL_UNSPEC &&
434 (signal < 0 || signal > 100)))
435 return NULL;
436
437 res = kzalloc(sizeof(*res) + privsz + ielen, gfp);
438 if (!res)
439 return NULL;
440
441 memcpy(res->pub.bssid, bssid, ETH_ALEN);
442 res->pub.channel = channel;
443 res->pub.signal = signal;
444 res->pub.tsf = timestamp;
445 res->pub.beacon_interval = beacon_interval;
446 res->pub.capability = capability;
447 /* point to after the private area */
448 res->pub.information_elements = (u8 *)res + sizeof(*res) + privsz;
449 memcpy(res->pub.information_elements, ie, ielen);
450 res->pub.len_information_elements = ielen;
451
452 kref_init(&res->ref);
453
454 res = cfg80211_bss_update(wiphy_to_dev(wiphy), res, 0);
455 if (!res)
456 return NULL;
457
458 if (res->pub.capability & WLAN_CAPABILITY_ESS)
459 regulatory_hint_found_beacon(wiphy, channel, gfp);
460
461 /* cfg80211_bss_update gives us a referenced result */
462 return &res->pub;
463}
464EXPORT_SYMBOL(cfg80211_inform_bss);
465
418struct cfg80211_bss * 466struct cfg80211_bss *
419cfg80211_inform_bss_frame(struct wiphy *wiphy, 467cfg80211_inform_bss_frame(struct wiphy *wiphy,
420 struct ieee80211_channel *channel, 468 struct ieee80211_channel *channel,
@@ -605,7 +653,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
605 cfg80211_put_dev(rdev); 653 cfg80211_put_dev(rdev);
606 return err; 654 return err;
607} 655}
608EXPORT_SYMBOL(cfg80211_wext_siwscan); 656EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan);
609 657
610static void ieee80211_scan_add_ies(struct iw_request_info *info, 658static void ieee80211_scan_add_ies(struct iw_request_info *info,
611 struct cfg80211_bss *bss, 659 struct cfg80211_bss *bss,
@@ -914,5 +962,5 @@ int cfg80211_wext_giwscan(struct net_device *dev,
914 cfg80211_put_dev(rdev); 962 cfg80211_put_dev(rdev);
915 return res; 963 return res;
916} 964}
917EXPORT_SYMBOL(cfg80211_wext_giwscan); 965EXPORT_SYMBOL_GPL(cfg80211_wext_giwscan);
918#endif 966#endif
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 487cdd9bcffc..25550692dda6 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1,10 +1,12 @@
1/* 1/*
2 * Wireless utility functions 2 * Wireless utility functions
3 * 3 *
4 * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> 4 * Copyright 2007-2009 Johannes Berg <johannes@sipsolutions.net>
5 */ 5 */
6#include <net/wireless.h> 6#include <linux/bitops.h>
7#include <asm/bitops.h> 7#include <linux/etherdevice.h>
8#include <net/cfg80211.h>
9#include <net/ip.h>
8#include "core.h" 10#include "core.h"
9 11
10struct ieee80211_rate * 12struct ieee80211_rate *
@@ -138,3 +140,365 @@ void ieee80211_set_bitrate_flags(struct wiphy *wiphy)
138 if (wiphy->bands[band]) 140 if (wiphy->bands[band])
139 set_mandatory_flags_band(wiphy->bands[band], band); 141 set_mandatory_flags_band(wiphy->bands[band], band);
140} 142}
143
144int cfg80211_validate_key_settings(struct key_params *params, int key_idx,
145 const u8 *mac_addr)
146{
147 if (key_idx > 5)
148 return -EINVAL;
149
150 /*
151 * Disallow pairwise keys with non-zero index unless it's WEP
152 * (because current deployments use pairwise WEP keys with
153 * non-zero indizes but 802.11i clearly specifies to use zero)
154 */
155 if (mac_addr && key_idx &&
156 params->cipher != WLAN_CIPHER_SUITE_WEP40 &&
157 params->cipher != WLAN_CIPHER_SUITE_WEP104)
158 return -EINVAL;
159
160 switch (params->cipher) {
161 case WLAN_CIPHER_SUITE_WEP40:
162 if (params->key_len != WLAN_KEY_LEN_WEP40)
163 return -EINVAL;
164 break;
165 case WLAN_CIPHER_SUITE_TKIP:
166 if (params->key_len != WLAN_KEY_LEN_TKIP)
167 return -EINVAL;
168 break;
169 case WLAN_CIPHER_SUITE_CCMP:
170 if (params->key_len != WLAN_KEY_LEN_CCMP)
171 return -EINVAL;
172 break;
173 case WLAN_CIPHER_SUITE_WEP104:
174 if (params->key_len != WLAN_KEY_LEN_WEP104)
175 return -EINVAL;
176 break;
177 case WLAN_CIPHER_SUITE_AES_CMAC:
178 if (params->key_len != WLAN_KEY_LEN_AES_CMAC)
179 return -EINVAL;
180 break;
181 default:
182 return -EINVAL;
183 }
184
185 if (params->seq) {
186 switch (params->cipher) {
187 case WLAN_CIPHER_SUITE_WEP40:
188 case WLAN_CIPHER_SUITE_WEP104:
189 /* These ciphers do not use key sequence */
190 return -EINVAL;
191 case WLAN_CIPHER_SUITE_TKIP:
192 case WLAN_CIPHER_SUITE_CCMP:
193 case WLAN_CIPHER_SUITE_AES_CMAC:
194 if (params->seq_len != 6)
195 return -EINVAL;
196 break;
197 }
198 }
199
200 return 0;
201}
202
203/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
204/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
205const unsigned char rfc1042_header[] __aligned(2) =
206 { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
207EXPORT_SYMBOL(rfc1042_header);
208
209/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
210const unsigned char bridge_tunnel_header[] __aligned(2) =
211 { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
212EXPORT_SYMBOL(bridge_tunnel_header);
213
214unsigned int ieee80211_hdrlen(__le16 fc)
215{
216 unsigned int hdrlen = 24;
217
218 if (ieee80211_is_data(fc)) {
219 if (ieee80211_has_a4(fc))
220 hdrlen = 30;
221 if (ieee80211_is_data_qos(fc))
222 hdrlen += IEEE80211_QOS_CTL_LEN;
223 goto out;
224 }
225
226 if (ieee80211_is_ctl(fc)) {
227 /*
228 * ACK and CTS are 10 bytes, all others 16. To see how
229 * to get this condition consider
230 * subtype mask: 0b0000000011110000 (0x00F0)
231 * ACK subtype: 0b0000000011010000 (0x00D0)
232 * CTS subtype: 0b0000000011000000 (0x00C0)
233 * bits that matter: ^^^ (0x00E0)
234 * value of those: 0b0000000011000000 (0x00C0)
235 */
236 if ((fc & cpu_to_le16(0x00E0)) == cpu_to_le16(0x00C0))
237 hdrlen = 10;
238 else
239 hdrlen = 16;
240 }
241out:
242 return hdrlen;
243}
244EXPORT_SYMBOL(ieee80211_hdrlen);
245
246unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb)
247{
248 const struct ieee80211_hdr *hdr =
249 (const struct ieee80211_hdr *)skb->data;
250 unsigned int hdrlen;
251
252 if (unlikely(skb->len < 10))
253 return 0;
254 hdrlen = ieee80211_hdrlen(hdr->frame_control);
255 if (unlikely(hdrlen > skb->len))
256 return 0;
257 return hdrlen;
258}
259EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb);
260
261static int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
262{
263 int ae = meshhdr->flags & MESH_FLAGS_AE;
264 /* 7.1.3.5a.2 */
265 switch (ae) {
266 case 0:
267 return 6;
268 case 1:
269 return 12;
270 case 2:
271 return 18;
272 case 3:
273 return 24;
274 default:
275 return 6;
276 }
277}
278
279int ieee80211_data_to_8023(struct sk_buff *skb, u8 *addr,
280 enum nl80211_iftype iftype)
281{
282 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
283 u16 hdrlen, ethertype;
284 u8 *payload;
285 u8 dst[ETH_ALEN];
286 u8 src[ETH_ALEN] __aligned(2);
287
288 if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
289 return -1;
290
291 hdrlen = ieee80211_hdrlen(hdr->frame_control);
292
293 /* convert IEEE 802.11 header + possible LLC headers into Ethernet
294 * header
295 * IEEE 802.11 address fields:
296 * ToDS FromDS Addr1 Addr2 Addr3 Addr4
297 * 0 0 DA SA BSSID n/a
298 * 0 1 DA BSSID SA n/a
299 * 1 0 BSSID SA DA n/a
300 * 1 1 RA TA DA SA
301 */
302 memcpy(dst, ieee80211_get_DA(hdr), ETH_ALEN);
303 memcpy(src, ieee80211_get_SA(hdr), ETH_ALEN);
304
305 switch (hdr->frame_control &
306 cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) {
307 case cpu_to_le16(IEEE80211_FCTL_TODS):
308 if (unlikely(iftype != NL80211_IFTYPE_AP &&
309 iftype != NL80211_IFTYPE_AP_VLAN))
310 return -1;
311 break;
312 case cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS):
313 if (unlikely(iftype != NL80211_IFTYPE_WDS &&
314 iftype != NL80211_IFTYPE_MESH_POINT))
315 return -1;
316 if (iftype == NL80211_IFTYPE_MESH_POINT) {
317 struct ieee80211s_hdr *meshdr =
318 (struct ieee80211s_hdr *) (skb->data + hdrlen);
319 hdrlen += ieee80211_get_mesh_hdrlen(meshdr);
320 if (meshdr->flags & MESH_FLAGS_AE_A5_A6) {
321 memcpy(dst, meshdr->eaddr1, ETH_ALEN);
322 memcpy(src, meshdr->eaddr2, ETH_ALEN);
323 }
324 }
325 break;
326 case cpu_to_le16(IEEE80211_FCTL_FROMDS):
327 if (iftype != NL80211_IFTYPE_STATION ||
328 (is_multicast_ether_addr(dst) &&
329 !compare_ether_addr(src, addr)))
330 return -1;
331 break;
332 case cpu_to_le16(0):
333 if (iftype != NL80211_IFTYPE_ADHOC)
334 return -1;
335 break;
336 }
337
338 if (unlikely(skb->len - hdrlen < 8))
339 return -1;
340
341 payload = skb->data + hdrlen;
342 ethertype = (payload[6] << 8) | payload[7];
343
344 if (likely((compare_ether_addr(payload, rfc1042_header) == 0 &&
345 ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
346 compare_ether_addr(payload, bridge_tunnel_header) == 0)) {
347 /* remove RFC1042 or Bridge-Tunnel encapsulation and
348 * replace EtherType */
349 skb_pull(skb, hdrlen + 6);
350 memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
351 memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
352 } else {
353 struct ethhdr *ehdr;
354 __be16 len;
355
356 skb_pull(skb, hdrlen);
357 len = htons(skb->len);
358 ehdr = (struct ethhdr *) skb_push(skb, sizeof(struct ethhdr));
359 memcpy(ehdr->h_dest, dst, ETH_ALEN);
360 memcpy(ehdr->h_source, src, ETH_ALEN);
361 ehdr->h_proto = len;
362 }
363 return 0;
364}
365EXPORT_SYMBOL(ieee80211_data_to_8023);
366
367int ieee80211_data_from_8023(struct sk_buff *skb, u8 *addr,
368 enum nl80211_iftype iftype, u8 *bssid, bool qos)
369{
370 struct ieee80211_hdr hdr;
371 u16 hdrlen, ethertype;
372 __le16 fc;
373 const u8 *encaps_data;
374 int encaps_len, skip_header_bytes;
375 int nh_pos, h_pos;
376 int head_need;
377
378 if (unlikely(skb->len < ETH_HLEN))
379 return -EINVAL;
380
381 nh_pos = skb_network_header(skb) - skb->data;
382 h_pos = skb_transport_header(skb) - skb->data;
383
384 /* convert Ethernet header to proper 802.11 header (based on
385 * operation mode) */
386 ethertype = (skb->data[12] << 8) | skb->data[13];
387 fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA);
388
389 switch (iftype) {
390 case NL80211_IFTYPE_AP:
391 case NL80211_IFTYPE_AP_VLAN:
392 fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
393 /* DA BSSID SA */
394 memcpy(hdr.addr1, skb->data, ETH_ALEN);
395 memcpy(hdr.addr2, addr, ETH_ALEN);
396 memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN);
397 hdrlen = 24;
398 break;
399 case NL80211_IFTYPE_STATION:
400 fc |= cpu_to_le16(IEEE80211_FCTL_TODS);
401 /* BSSID SA DA */
402 memcpy(hdr.addr1, bssid, ETH_ALEN);
403 memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
404 memcpy(hdr.addr3, skb->data, ETH_ALEN);
405 hdrlen = 24;
406 break;
407 case NL80211_IFTYPE_ADHOC:
408 /* DA SA BSSID */
409 memcpy(hdr.addr1, skb->data, ETH_ALEN);
410 memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
411 memcpy(hdr.addr3, bssid, ETH_ALEN);
412 hdrlen = 24;
413 break;
414 default:
415 return -EOPNOTSUPP;
416 }
417
418 if (qos) {
419 fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
420 hdrlen += 2;
421 }
422
423 hdr.frame_control = fc;
424 hdr.duration_id = 0;
425 hdr.seq_ctrl = 0;
426
427 skip_header_bytes = ETH_HLEN;
428 if (ethertype == ETH_P_AARP || ethertype == ETH_P_IPX) {
429 encaps_data = bridge_tunnel_header;
430 encaps_len = sizeof(bridge_tunnel_header);
431 skip_header_bytes -= 2;
432 } else if (ethertype > 0x600) {
433 encaps_data = rfc1042_header;
434 encaps_len = sizeof(rfc1042_header);
435 skip_header_bytes -= 2;
436 } else {
437 encaps_data = NULL;
438 encaps_len = 0;
439 }
440
441 skb_pull(skb, skip_header_bytes);
442 nh_pos -= skip_header_bytes;
443 h_pos -= skip_header_bytes;
444
445 head_need = hdrlen + encaps_len - skb_headroom(skb);
446
447 if (head_need > 0 || skb_cloned(skb)) {
448 head_need = max(head_need, 0);
449 if (head_need)
450 skb_orphan(skb);
451
452 if (pskb_expand_head(skb, head_need, 0, GFP_ATOMIC)) {
453 printk(KERN_ERR "failed to reallocate Tx buffer\n");
454 return -ENOMEM;
455 }
456 skb->truesize += head_need;
457 }
458
459 if (encaps_data) {
460 memcpy(skb_push(skb, encaps_len), encaps_data, encaps_len);
461 nh_pos += encaps_len;
462 h_pos += encaps_len;
463 }
464
465 memcpy(skb_push(skb, hdrlen), &hdr, hdrlen);
466
467 nh_pos += hdrlen;
468 h_pos += hdrlen;
469
470 /* Update skb pointers to various headers since this modified frame
471 * is going to go through Linux networking code that may potentially
472 * need things like pointer to IP header. */
473 skb_set_mac_header(skb, 0);
474 skb_set_network_header(skb, nh_pos);
475 skb_set_transport_header(skb, h_pos);
476
477 return 0;
478}
479EXPORT_SYMBOL(ieee80211_data_from_8023);
480
481/* Given a data frame determine the 802.1p/1d tag to use. */
482unsigned int cfg80211_classify8021d(struct sk_buff *skb)
483{
484 unsigned int dscp;
485
486 /* skb->priority values from 256->263 are magic values to
487 * directly indicate a specific 802.1d priority. This is used
488 * to allow 802.1d priority to be passed directly in from VLAN
489 * tags, etc.
490 */
491 if (skb->priority >= 256 && skb->priority <= 263)
492 return skb->priority - 256;
493
494 switch (skb->protocol) {
495 case htons(ETH_P_IP):
496 dscp = ip_hdr(skb)->tos & 0xfc;
497 break;
498 default:
499 return 0;
500 }
501
502 return dscp >> 5;
503}
504EXPORT_SYMBOL(cfg80211_classify8021d);
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index 0fd1db6e95bb..d030c5315672 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -5,13 +5,14 @@
5 * into cfg80211, when that happens all the exports here go away and 5 * into cfg80211, when that happens all the exports here go away and
6 * we directly assign the wireless handlers of wireless interfaces. 6 * we directly assign the wireless handlers of wireless interfaces.
7 * 7 *
8 * Copyright 2008 Johannes Berg <johannes@sipsolutions.net> 8 * Copyright 2008-2009 Johannes Berg <johannes@sipsolutions.net>
9 */ 9 */
10 10
11#include <linux/wireless.h> 11#include <linux/wireless.h>
12#include <linux/nl80211.h> 12#include <linux/nl80211.h>
13#include <linux/if_arp.h>
14#include <linux/etherdevice.h>
13#include <net/iw_handler.h> 15#include <net/iw_handler.h>
14#include <net/wireless.h>
15#include <net/cfg80211.h> 16#include <net/cfg80211.h>
16#include "core.h" 17#include "core.h"
17 18
@@ -57,7 +58,7 @@ int cfg80211_wext_giwname(struct net_device *dev,
57 58
58 return 0; 59 return 0;
59} 60}
60EXPORT_SYMBOL(cfg80211_wext_giwname); 61EXPORT_SYMBOL_GPL(cfg80211_wext_giwname);
61 62
62int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info, 63int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
63 u32 *mode, char *extra) 64 u32 *mode, char *extra)
@@ -108,7 +109,7 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
108 109
109 return ret; 110 return ret;
110} 111}
111EXPORT_SYMBOL(cfg80211_wext_siwmode); 112EXPORT_SYMBOL_GPL(cfg80211_wext_siwmode);
112 113
113int cfg80211_wext_giwmode(struct net_device *dev, struct iw_request_info *info, 114int cfg80211_wext_giwmode(struct net_device *dev, struct iw_request_info *info,
114 u32 *mode, char *extra) 115 u32 *mode, char *extra)
@@ -143,7 +144,7 @@ int cfg80211_wext_giwmode(struct net_device *dev, struct iw_request_info *info,
143 } 144 }
144 return 0; 145 return 0;
145} 146}
146EXPORT_SYMBOL(cfg80211_wext_giwmode); 147EXPORT_SYMBOL_GPL(cfg80211_wext_giwmode);
147 148
148 149
149int cfg80211_wext_giwrange(struct net_device *dev, 150int cfg80211_wext_giwrange(struct net_device *dev,
@@ -206,7 +207,6 @@ int cfg80211_wext_giwrange(struct net_device *dev,
206 range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | 207 range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
207 IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; 208 IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
208 209
209
210 for (band = 0; band < IEEE80211_NUM_BANDS; band ++) { 210 for (band = 0; band < IEEE80211_NUM_BANDS; band ++) {
211 int i; 211 int i;
212 struct ieee80211_supported_band *sband; 212 struct ieee80211_supported_band *sband;
@@ -240,4 +240,590 @@ int cfg80211_wext_giwrange(struct net_device *dev,
240 240
241 return 0; 241 return 0;
242} 242}
243EXPORT_SYMBOL(cfg80211_wext_giwrange); 243EXPORT_SYMBOL_GPL(cfg80211_wext_giwrange);
244
245int cfg80211_wext_siwmlme(struct net_device *dev,
246 struct iw_request_info *info,
247 struct iw_point *data, char *extra)
248{
249 struct wireless_dev *wdev = dev->ieee80211_ptr;
250 struct iw_mlme *mlme = (struct iw_mlme *)extra;
251 struct cfg80211_registered_device *rdev;
252 union {
253 struct cfg80211_disassoc_request disassoc;
254 struct cfg80211_deauth_request deauth;
255 } cmd;
256
257 if (!wdev)
258 return -EOPNOTSUPP;
259
260 rdev = wiphy_to_dev(wdev->wiphy);
261
262 if (wdev->iftype != NL80211_IFTYPE_STATION)
263 return -EINVAL;
264
265 if (mlme->addr.sa_family != ARPHRD_ETHER)
266 return -EINVAL;
267
268 memset(&cmd, 0, sizeof(cmd));
269
270 switch (mlme->cmd) {
271 case IW_MLME_DEAUTH:
272 if (!rdev->ops->deauth)
273 return -EOPNOTSUPP;
274 cmd.deauth.peer_addr = mlme->addr.sa_data;
275 cmd.deauth.reason_code = mlme->reason_code;
276 return rdev->ops->deauth(wdev->wiphy, dev, &cmd.deauth);
277 case IW_MLME_DISASSOC:
278 if (!rdev->ops->disassoc)
279 return -EOPNOTSUPP;
280 cmd.disassoc.peer_addr = mlme->addr.sa_data;
281 cmd.disassoc.reason_code = mlme->reason_code;
282 return rdev->ops->disassoc(wdev->wiphy, dev, &cmd.disassoc);
283 default:
284 return -EOPNOTSUPP;
285 }
286}
287EXPORT_SYMBOL_GPL(cfg80211_wext_siwmlme);
288
289
290/**
291 * cfg80211_wext_freq - get wext frequency for non-"auto"
292 * @wiphy: the wiphy
293 * @freq: the wext freq encoding
294 *
295 * Returns a channel, %NULL for auto, or an ERR_PTR for errors!
296 */
297struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy,
298 struct iw_freq *freq)
299{
300 struct ieee80211_channel *chan;
301 int f;
302
303 /*
304 * Parse frequency - return NULL for auto and
305 * -EINVAL for impossible things.
306 */
307 if (freq->e == 0) {
308 if (freq->m < 0)
309 return NULL;
310 f = ieee80211_channel_to_frequency(freq->m);
311 } else {
312 int i, div = 1000000;
313 for (i = 0; i < freq->e; i++)
314 div /= 10;
315 if (div <= 0)
316 return ERR_PTR(-EINVAL);
317 f = freq->m / div;
318 }
319
320 /*
321 * Look up channel struct and return -EINVAL when
322 * it cannot be found.
323 */
324 chan = ieee80211_get_channel(wiphy, f);
325 if (!chan)
326 return ERR_PTR(-EINVAL);
327 return chan;
328}
329EXPORT_SYMBOL_GPL(cfg80211_wext_freq);
330
331int cfg80211_wext_siwrts(struct net_device *dev,
332 struct iw_request_info *info,
333 struct iw_param *rts, char *extra)
334{
335 struct wireless_dev *wdev = dev->ieee80211_ptr;
336 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
337 u32 orts = wdev->wiphy->rts_threshold;
338 int err;
339
340 if (rts->disabled || !rts->fixed)
341 wdev->wiphy->rts_threshold = (u32) -1;
342 else if (rts->value < 0)
343 return -EINVAL;
344 else
345 wdev->wiphy->rts_threshold = rts->value;
346
347 err = rdev->ops->set_wiphy_params(wdev->wiphy,
348 WIPHY_PARAM_RTS_THRESHOLD);
349 if (err)
350 wdev->wiphy->rts_threshold = orts;
351
352 return err;
353}
354EXPORT_SYMBOL_GPL(cfg80211_wext_siwrts);
355
356int cfg80211_wext_giwrts(struct net_device *dev,
357 struct iw_request_info *info,
358 struct iw_param *rts, char *extra)
359{
360 struct wireless_dev *wdev = dev->ieee80211_ptr;
361
362 rts->value = wdev->wiphy->rts_threshold;
363 rts->disabled = rts->value == (u32) -1;
364 rts->fixed = 1;
365
366 return 0;
367}
368EXPORT_SYMBOL_GPL(cfg80211_wext_giwrts);
369
370int cfg80211_wext_siwfrag(struct net_device *dev,
371 struct iw_request_info *info,
372 struct iw_param *frag, char *extra)
373{
374 struct wireless_dev *wdev = dev->ieee80211_ptr;
375 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
376 u32 ofrag = wdev->wiphy->frag_threshold;
377 int err;
378
379 if (frag->disabled || !frag->fixed)
380 wdev->wiphy->frag_threshold = (u32) -1;
381 else if (frag->value < 256)
382 return -EINVAL;
383 else {
384 /* Fragment length must be even, so strip LSB. */
385 wdev->wiphy->frag_threshold = frag->value & ~0x1;
386 }
387
388 err = rdev->ops->set_wiphy_params(wdev->wiphy,
389 WIPHY_PARAM_FRAG_THRESHOLD);
390 if (err)
391 wdev->wiphy->frag_threshold = ofrag;
392
393 return err;
394}
395EXPORT_SYMBOL_GPL(cfg80211_wext_siwfrag);
396
397int cfg80211_wext_giwfrag(struct net_device *dev,
398 struct iw_request_info *info,
399 struct iw_param *frag, char *extra)
400{
401 struct wireless_dev *wdev = dev->ieee80211_ptr;
402
403 frag->value = wdev->wiphy->frag_threshold;
404 frag->disabled = frag->value == (u32) -1;
405 frag->fixed = 1;
406
407 return 0;
408}
409EXPORT_SYMBOL_GPL(cfg80211_wext_giwfrag);
410
411int cfg80211_wext_siwretry(struct net_device *dev,
412 struct iw_request_info *info,
413 struct iw_param *retry, char *extra)
414{
415 struct wireless_dev *wdev = dev->ieee80211_ptr;
416 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
417 u32 changed = 0;
418 u8 olong = wdev->wiphy->retry_long;
419 u8 oshort = wdev->wiphy->retry_short;
420 int err;
421
422 if (retry->disabled ||
423 (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
424 return -EINVAL;
425
426 if (retry->flags & IW_RETRY_LONG) {
427 wdev->wiphy->retry_long = retry->value;
428 changed |= WIPHY_PARAM_RETRY_LONG;
429 } else if (retry->flags & IW_RETRY_SHORT) {
430 wdev->wiphy->retry_short = retry->value;
431 changed |= WIPHY_PARAM_RETRY_SHORT;
432 } else {
433 wdev->wiphy->retry_short = retry->value;
434 wdev->wiphy->retry_long = retry->value;
435 changed |= WIPHY_PARAM_RETRY_LONG;
436 changed |= WIPHY_PARAM_RETRY_SHORT;
437 }
438
439 if (!changed)
440 return 0;
441
442 err = rdev->ops->set_wiphy_params(wdev->wiphy, changed);
443 if (err) {
444 wdev->wiphy->retry_short = oshort;
445 wdev->wiphy->retry_long = olong;
446 }
447
448 return err;
449}
450EXPORT_SYMBOL_GPL(cfg80211_wext_siwretry);
451
452int cfg80211_wext_giwretry(struct net_device *dev,
453 struct iw_request_info *info,
454 struct iw_param *retry, char *extra)
455{
456 struct wireless_dev *wdev = dev->ieee80211_ptr;
457
458 retry->disabled = 0;
459
460 if (retry->flags == 0 || (retry->flags & IW_RETRY_SHORT)) {
461 /*
462 * First return short value, iwconfig will ask long value
463 * later if needed
464 */
465 retry->flags |= IW_RETRY_LIMIT;
466 retry->value = wdev->wiphy->retry_short;
467 if (wdev->wiphy->retry_long != wdev->wiphy->retry_short)
468 retry->flags |= IW_RETRY_LONG;
469
470 return 0;
471 }
472
473 if (retry->flags & IW_RETRY_LONG) {
474 retry->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
475 retry->value = wdev->wiphy->retry_long;
476 }
477
478 return 0;
479}
480EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry);
481
482static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
483 struct net_device *dev, const u8 *addr,
484 bool remove, bool tx_key, int idx,
485 struct key_params *params)
486{
487 struct wireless_dev *wdev = dev->ieee80211_ptr;
488 int err;
489
490 if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
491 if (!rdev->ops->set_default_mgmt_key)
492 return -EOPNOTSUPP;
493
494 if (idx < 4 || idx > 5)
495 return -EINVAL;
496 } else if (idx < 0 || idx > 3)
497 return -EINVAL;
498
499 if (remove) {
500 err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr);
501 if (!err) {
502 if (idx == wdev->wext.default_key)
503 wdev->wext.default_key = -1;
504 else if (idx == wdev->wext.default_mgmt_key)
505 wdev->wext.default_mgmt_key = -1;
506 }
507 /*
508 * Applications using wireless extensions expect to be
509 * able to delete keys that don't exist, so allow that.
510 */
511 if (err == -ENOENT)
512 return 0;
513
514 return err;
515 } else {
516 if (addr)
517 tx_key = false;
518
519 if (cfg80211_validate_key_settings(params, idx, addr))
520 return -EINVAL;
521
522 err = rdev->ops->add_key(&rdev->wiphy, dev, idx, addr, params);
523 if (err)
524 return err;
525
526 if (tx_key || (!addr && wdev->wext.default_key == -1)) {
527 err = rdev->ops->set_default_key(&rdev->wiphy,
528 dev, idx);
529 if (!err)
530 wdev->wext.default_key = idx;
531 return err;
532 }
533
534 if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC &&
535 (tx_key || (!addr && wdev->wext.default_mgmt_key == -1))) {
536 err = rdev->ops->set_default_mgmt_key(&rdev->wiphy,
537 dev, idx);
538 if (!err)
539 wdev->wext.default_mgmt_key = idx;
540 return err;
541 }
542
543 return 0;
544 }
545}
546
547int cfg80211_wext_siwencode(struct net_device *dev,
548 struct iw_request_info *info,
549 struct iw_point *erq, char *keybuf)
550{
551 struct wireless_dev *wdev = dev->ieee80211_ptr;
552 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
553 int idx, err;
554 bool remove = false;
555 struct key_params params;
556
557 /* no use -- only MFP (set_default_mgmt_key) is optional */
558 if (!rdev->ops->del_key ||
559 !rdev->ops->add_key ||
560 !rdev->ops->set_default_key)
561 return -EOPNOTSUPP;
562
563 idx = erq->flags & IW_ENCODE_INDEX;
564 if (idx == 0) {
565 idx = wdev->wext.default_key;
566 if (idx < 0)
567 idx = 0;
568 } else if (idx < 1 || idx > 4)
569 return -EINVAL;
570 else
571 idx--;
572
573 if (erq->flags & IW_ENCODE_DISABLED)
574 remove = true;
575 else if (erq->length == 0) {
576 /* No key data - just set the default TX key index */
577 err = rdev->ops->set_default_key(&rdev->wiphy, dev, idx);
578 if (!err)
579 wdev->wext.default_key = idx;
580 return err;
581 }
582
583 memset(&params, 0, sizeof(params));
584 params.key = keybuf;
585 params.key_len = erq->length;
586 if (erq->length == 5)
587 params.cipher = WLAN_CIPHER_SUITE_WEP40;
588 else if (erq->length == 13)
589 params.cipher = WLAN_CIPHER_SUITE_WEP104;
590 else if (!remove)
591 return -EINVAL;
592
593 return cfg80211_set_encryption(rdev, dev, NULL, remove,
594 wdev->wext.default_key == -1,
595 idx, &params);
596}
597EXPORT_SYMBOL_GPL(cfg80211_wext_siwencode);
598
599int cfg80211_wext_siwencodeext(struct net_device *dev,
600 struct iw_request_info *info,
601 struct iw_point *erq, char *extra)
602{
603 struct wireless_dev *wdev = dev->ieee80211_ptr;
604 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
605 struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
606 const u8 *addr;
607 int idx;
608 bool remove = false;
609 struct key_params params;
610 u32 cipher;
611
612 /* no use -- only MFP (set_default_mgmt_key) is optional */
613 if (!rdev->ops->del_key ||
614 !rdev->ops->add_key ||
615 !rdev->ops->set_default_key)
616 return -EOPNOTSUPP;
617
618 switch (ext->alg) {
619 case IW_ENCODE_ALG_NONE:
620 remove = true;
621 cipher = 0;
622 break;
623 case IW_ENCODE_ALG_WEP:
624 if (ext->key_len == 5)
625 cipher = WLAN_CIPHER_SUITE_WEP40;
626 else if (ext->key_len == 13)
627 cipher = WLAN_CIPHER_SUITE_WEP104;
628 else
629 return -EINVAL;
630 break;
631 case IW_ENCODE_ALG_TKIP:
632 cipher = WLAN_CIPHER_SUITE_TKIP;
633 break;
634 case IW_ENCODE_ALG_CCMP:
635 cipher = WLAN_CIPHER_SUITE_CCMP;
636 break;
637 case IW_ENCODE_ALG_AES_CMAC:
638 cipher = WLAN_CIPHER_SUITE_AES_CMAC;
639 break;
640 default:
641 return -EOPNOTSUPP;
642 }
643
644 if (erq->flags & IW_ENCODE_DISABLED)
645 remove = true;
646
647 idx = erq->flags & IW_ENCODE_INDEX;
648 if (cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
649 if (idx < 4 || idx > 5) {
650 idx = wdev->wext.default_mgmt_key;
651 if (idx < 0)
652 return -EINVAL;
653 } else
654 idx--;
655 } else {
656 if (idx < 1 || idx > 4) {
657 idx = wdev->wext.default_key;
658 if (idx < 0)
659 return -EINVAL;
660 } else
661 idx--;
662 }
663
664 addr = ext->addr.sa_data;
665 if (is_broadcast_ether_addr(addr))
666 addr = NULL;
667
668 memset(&params, 0, sizeof(params));
669 params.key = ext->key;
670 params.key_len = ext->key_len;
671 params.cipher = cipher;
672
673 if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
674 params.seq = ext->rx_seq;
675 params.seq_len = 6;
676 }
677
678 return cfg80211_set_encryption(
679 rdev, dev, addr, remove,
680 ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
681 idx, &params);
682}
683EXPORT_SYMBOL_GPL(cfg80211_wext_siwencodeext);
684
685struct giwencode_cookie {
686 size_t buflen;
687 char *keybuf;
688};
689
690static void giwencode_get_key_cb(void *cookie, struct key_params *params)
691{
692 struct giwencode_cookie *data = cookie;
693
694 if (!params->key) {
695 data->buflen = 0;
696 return;
697 }
698
699 data->buflen = min_t(size_t, data->buflen, params->key_len);
700 memcpy(data->keybuf, params->key, data->buflen);
701}
702
703int cfg80211_wext_giwencode(struct net_device *dev,
704 struct iw_request_info *info,
705 struct iw_point *erq, char *keybuf)
706{
707 struct wireless_dev *wdev = dev->ieee80211_ptr;
708 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
709 int idx, err;
710 struct giwencode_cookie data = {
711 .keybuf = keybuf,
712 .buflen = erq->length,
713 };
714
715 if (!rdev->ops->get_key)
716 return -EOPNOTSUPP;
717
718 idx = erq->flags & IW_ENCODE_INDEX;
719 if (idx == 0) {
720 idx = wdev->wext.default_key;
721 if (idx < 0)
722 idx = 0;
723 } else if (idx < 1 || idx > 4)
724 return -EINVAL;
725 else
726 idx--;
727
728 erq->flags = idx + 1;
729
730 err = rdev->ops->get_key(&rdev->wiphy, dev, idx, NULL, &data,
731 giwencode_get_key_cb);
732 if (!err) {
733 erq->length = data.buflen;
734 erq->flags |= IW_ENCODE_ENABLED;
735 return 0;
736 }
737
738 if (err == -ENOENT) {
739 erq->flags |= IW_ENCODE_DISABLED;
740 erq->length = 0;
741 return 0;
742 }
743
744 return err;
745}
746EXPORT_SYMBOL_GPL(cfg80211_wext_giwencode);
747
748int cfg80211_wext_siwtxpower(struct net_device *dev,
749 struct iw_request_info *info,
750 union iwreq_data *data, char *extra)
751{
752 struct wireless_dev *wdev = dev->ieee80211_ptr;
753 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
754 enum tx_power_setting type;
755 int dbm = 0;
756
757 if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
758 return -EINVAL;
759 if (data->txpower.flags & IW_TXPOW_RANGE)
760 return -EINVAL;
761
762 if (!rdev->ops->set_tx_power)
763 return -EOPNOTSUPP;
764
765 /* only change when not disabling */
766 if (!data->txpower.disabled) {
767 rfkill_set_sw_state(rdev->rfkill, false);
768
769 if (data->txpower.fixed) {
770 /*
771 * wext doesn't support negative values, see
772 * below where it's for automatic
773 */
774 if (data->txpower.value < 0)
775 return -EINVAL;
776 dbm = data->txpower.value;
777 type = TX_POWER_FIXED;
778 /* TODO: do regulatory check! */
779 } else {
780 /*
781 * Automatic power level setting, max being the value
782 * passed in from userland.
783 */
784 if (data->txpower.value < 0) {
785 type = TX_POWER_AUTOMATIC;
786 } else {
787 dbm = data->txpower.value;
788 type = TX_POWER_LIMITED;
789 }
790 }
791 } else {
792 rfkill_set_sw_state(rdev->rfkill, true);
793 schedule_work(&rdev->rfkill_sync);
794 return 0;
795 }
796
797 return rdev->ops->set_tx_power(wdev->wiphy, type, dbm);;
798}
799EXPORT_SYMBOL_GPL(cfg80211_wext_siwtxpower);
800
801int cfg80211_wext_giwtxpower(struct net_device *dev,
802 struct iw_request_info *info,
803 union iwreq_data *data, char *extra)
804{
805 struct wireless_dev *wdev = dev->ieee80211_ptr;
806 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
807 int err, val;
808
809 if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
810 return -EINVAL;
811 if (data->txpower.flags & IW_TXPOW_RANGE)
812 return -EINVAL;
813
814 if (!rdev->ops->get_tx_power)
815 return -EOPNOTSUPP;
816
817 err = rdev->ops->get_tx_power(wdev->wiphy, &val);
818 if (err)
819 return err;
820
821 /* well... oh well */
822 data->txpower.fixed = 1;
823 data->txpower.disabled = rfkill_blocked(rdev->rfkill);
824 data->txpower.value = val;
825 data->txpower.flags = IW_TXPOW_DBM;
826
827 return 0;
828}
829EXPORT_SYMBOL_GPL(cfg80211_wext_giwtxpower);
diff --git a/net/wireless/wext.c b/net/wireless/wext.c
index 0e59f9ae9b81..252c2010c2e2 100644
--- a/net/wireless/wext.c
+++ b/net/wireless/wext.c
@@ -636,8 +636,10 @@ static void wireless_seq_printf_stats(struct seq_file *seq,
636/* 636/*
637 * Print info for /proc/net/wireless (print all entries) 637 * Print info for /proc/net/wireless (print all entries)
638 */ 638 */
639static int wireless_seq_show(struct seq_file *seq, void *v) 639static int wireless_dev_seq_show(struct seq_file *seq, void *v)
640{ 640{
641 might_sleep();
642
641 if (v == SEQ_START_TOKEN) 643 if (v == SEQ_START_TOKEN)
642 seq_printf(seq, "Inter-| sta-| Quality | Discarded " 644 seq_printf(seq, "Inter-| sta-| Quality | Discarded "
643 "packets | Missed | WE\n" 645 "packets | Missed | WE\n"
@@ -649,14 +651,46 @@ static int wireless_seq_show(struct seq_file *seq, void *v)
649 return 0; 651 return 0;
650} 652}
651 653
654static void *wireless_dev_seq_start(struct seq_file *seq, loff_t *pos)
655{
656 struct net *net = seq_file_net(seq);
657 loff_t off;
658 struct net_device *dev;
659
660 rtnl_lock();
661 if (!*pos)
662 return SEQ_START_TOKEN;
663
664 off = 1;
665 for_each_netdev(net, dev)
666 if (off++ == *pos)
667 return dev;
668 return NULL;
669}
670
671static void *wireless_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
672{
673 struct net *net = seq_file_net(seq);
674
675 ++*pos;
676
677 return v == SEQ_START_TOKEN ?
678 first_net_device(net) : next_net_device(v);
679}
680
681static void wireless_dev_seq_stop(struct seq_file *seq, void *v)
682{
683 rtnl_unlock();
684}
685
652static const struct seq_operations wireless_seq_ops = { 686static const struct seq_operations wireless_seq_ops = {
653 .start = dev_seq_start, 687 .start = wireless_dev_seq_start,
654 .next = dev_seq_next, 688 .next = wireless_dev_seq_next,
655 .stop = dev_seq_stop, 689 .stop = wireless_dev_seq_stop,
656 .show = wireless_seq_show, 690 .show = wireless_dev_seq_show,
657}; 691};
658 692
659static int wireless_seq_open(struct inode *inode, struct file *file) 693static int seq_open_wireless(struct inode *inode, struct file *file)
660{ 694{
661 return seq_open_net(inode, file, &wireless_seq_ops, 695 return seq_open_net(inode, file, &wireless_seq_ops,
662 sizeof(struct seq_net_private)); 696 sizeof(struct seq_net_private));
@@ -664,7 +698,7 @@ static int wireless_seq_open(struct inode *inode, struct file *file)
664 698
665static const struct file_operations wireless_seq_fops = { 699static const struct file_operations wireless_seq_fops = {
666 .owner = THIS_MODULE, 700 .owner = THIS_MODULE,
667 .open = wireless_seq_open, 701 .open = seq_open_wireless,
668 .read = seq_read, 702 .read = seq_read,
669 .llseek = seq_lseek, 703 .llseek = seq_lseek,
670 .release = seq_release_net, 704 .release = seq_release_net,