diff options
Diffstat (limited to 'net/wireless')
-rw-r--r-- | net/wireless/Kconfig | 3 | ||||
-rw-r--r-- | net/wireless/core.c | 97 | ||||
-rw-r--r-- | net/wireless/core.h | 7 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 57 | ||||
-rw-r--r-- | net/wireless/reg.c | 8 | ||||
-rw-r--r-- | net/wireless/scan.c | 3 | ||||
-rw-r--r-- | net/wireless/util.c | 13 | ||||
-rw-r--r-- | net/wireless/wext-compat.c | 83 |
8 files changed, 251 insertions, 20 deletions
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index 45005497c634..4428dd5e911d 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig | |||
@@ -1,5 +1,6 @@ | |||
1 | config CFG80211 | 1 | config CFG80211 |
2 | tristate "Improved wireless configuration API" | 2 | tristate "Improved wireless configuration API" |
3 | depends on RFKILL || !RFKILL | ||
3 | 4 | ||
4 | config CFG80211_REG_DEBUG | 5 | config CFG80211_REG_DEBUG |
5 | bool "cfg80211 regulatory debugging" | 6 | bool "cfg80211 regulatory debugging" |
diff --git a/net/wireless/core.c b/net/wireless/core.c index a5dbea1da476..3b74b88e10a3 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -12,6 +12,7 @@ | |||
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 "nl80211.h" | 18 | #include "nl80211.h" |
@@ -227,6 +228,41 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, | |||
227 | return 0; | 228 | return 0; |
228 | } | 229 | } |
229 | 230 | ||
231 | static 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 | |||
238 | static 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 | |||
258 | static 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 | ||
232 | struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) | 268 | struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) |
@@ -274,6 +310,18 @@ struct wiphy *wiphy_new(const 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 | |||
277 | /* | 325 | /* |
278 | * Initialize wiphy parameters to IEEE 802.11 MIB default values. | 326 | * Initialize wiphy parameters to IEEE 802.11 MIB default values. |
279 | * Fragmentation and RTS threshold are disabled by default with the | 327 | * Fragmentation and RTS threshold are disabled by default with the |
@@ -356,6 +404,10 @@ int wiphy_register(struct wiphy *wiphy) | |||
356 | if (res) | 404 | if (res) |
357 | goto out_unlock; | 405 | goto out_unlock; |
358 | 406 | ||
407 | res = rfkill_register(drv->rfkill); | ||
408 | if (res) | ||
409 | goto out_rm_dev; | ||
410 | |||
359 | list_add(&drv->list, &cfg80211_drv_list); | 411 | list_add(&drv->list, &cfg80211_drv_list); |
360 | 412 | ||
361 | /* add to debugfs */ | 413 | /* add to debugfs */ |
@@ -379,16 +431,41 @@ int wiphy_register(struct wiphy *wiphy) | |||
379 | cfg80211_debugfs_drv_add(drv); | 431 | cfg80211_debugfs_drv_add(drv); |
380 | 432 | ||
381 | res = 0; | 433 | res = 0; |
382 | out_unlock: | 434 | goto out_unlock; |
435 | |||
436 | out_rm_dev: | ||
437 | device_del(&drv->wiphy.dev); | ||
438 | out_unlock: | ||
383 | mutex_unlock(&cfg80211_mutex); | 439 | mutex_unlock(&cfg80211_mutex); |
384 | return res; | 440 | return res; |
385 | } | 441 | } |
386 | EXPORT_SYMBOL(wiphy_register); | 442 | EXPORT_SYMBOL(wiphy_register); |
387 | 443 | ||
444 | void wiphy_rfkill_start_polling(struct wiphy *wiphy) | ||
445 | { | ||
446 | struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy); | ||
447 | |||
448 | if (!drv->ops->rfkill_poll) | ||
449 | return; | ||
450 | drv->rfkill_ops.poll = cfg80211_rfkill_poll; | ||
451 | rfkill_resume_polling(drv->rfkill); | ||
452 | } | ||
453 | EXPORT_SYMBOL(wiphy_rfkill_start_polling); | ||
454 | |||
455 | void wiphy_rfkill_stop_polling(struct wiphy *wiphy) | ||
456 | { | ||
457 | struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy); | ||
458 | |||
459 | rfkill_pause_polling(drv->rfkill); | ||
460 | } | ||
461 | EXPORT_SYMBOL(wiphy_rfkill_stop_polling); | ||
462 | |||
388 | void wiphy_unregister(struct wiphy *wiphy) | 463 | void wiphy_unregister(struct wiphy *wiphy) |
389 | { | 464 | { |
390 | struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy); | 465 | struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy); |
391 | 466 | ||
467 | rfkill_unregister(drv->rfkill); | ||
468 | |||
392 | /* protect the device list */ | 469 | /* protect the device list */ |
393 | mutex_lock(&cfg80211_mutex); | 470 | mutex_lock(&cfg80211_mutex); |
394 | 471 | ||
@@ -425,6 +502,7 @@ EXPORT_SYMBOL(wiphy_unregister); | |||
425 | void cfg80211_dev_free(struct cfg80211_registered_device *drv) | 502 | void cfg80211_dev_free(struct cfg80211_registered_device *drv) |
426 | { | 503 | { |
427 | struct cfg80211_internal_bss *scan, *tmp; | 504 | struct cfg80211_internal_bss *scan, *tmp; |
505 | rfkill_destroy(drv->rfkill); | ||
428 | mutex_destroy(&drv->mtx); | 506 | mutex_destroy(&drv->mtx); |
429 | mutex_destroy(&drv->devlist_mtx); | 507 | mutex_destroy(&drv->devlist_mtx); |
430 | list_for_each_entry_safe(scan, tmp, &drv->bss_list, list) | 508 | list_for_each_entry_safe(scan, tmp, &drv->bss_list, list) |
@@ -438,6 +516,15 @@ void wiphy_free(struct wiphy *wiphy) | |||
438 | } | 516 | } |
439 | EXPORT_SYMBOL(wiphy_free); | 517 | EXPORT_SYMBOL(wiphy_free); |
440 | 518 | ||
519 | void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool blocked) | ||
520 | { | ||
521 | struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy); | ||
522 | |||
523 | if (rfkill_set_hw_state(drv->rfkill, blocked)) | ||
524 | schedule_work(&drv->rfkill_sync); | ||
525 | } | ||
526 | EXPORT_SYMBOL(wiphy_rfkill_set_hw_state); | ||
527 | |||
441 | static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | 528 | static int cfg80211_netdev_notifier_call(struct notifier_block * nb, |
442 | unsigned long state, | 529 | unsigned long state, |
443 | void *ndev) | 530 | void *ndev) |
@@ -446,7 +533,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
446 | struct cfg80211_registered_device *rdev; | 533 | struct cfg80211_registered_device *rdev; |
447 | 534 | ||
448 | if (!dev->ieee80211_ptr) | 535 | if (!dev->ieee80211_ptr) |
449 | return 0; | 536 | return NOTIFY_DONE; |
450 | 537 | ||
451 | rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy); | 538 | rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy); |
452 | 539 | ||
@@ -492,9 +579,13 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
492 | } | 579 | } |
493 | mutex_unlock(&rdev->devlist_mtx); | 580 | mutex_unlock(&rdev->devlist_mtx); |
494 | break; | 581 | break; |
582 | case NETDEV_PRE_UP: | ||
583 | if (rfkill_blocked(rdev->rfkill)) | ||
584 | return notifier_from_errno(-ERFKILL); | ||
585 | break; | ||
495 | } | 586 | } |
496 | 587 | ||
497 | return 0; | 588 | return NOTIFY_DONE; |
498 | } | 589 | } |
499 | 590 | ||
500 | static struct notifier_block cfg80211_netdev_notifier = { | 591 | static struct notifier_block cfg80211_netdev_notifier = { |
diff --git a/net/wireless/core.h b/net/wireless/core.h index ab512bcd8153..bfa340c7abb5 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -11,6 +11,8 @@ | |||
11 | #include <linux/kref.h> | 11 | #include <linux/kref.h> |
12 | #include <linux/rbtree.h> | 12 | #include <linux/rbtree.h> |
13 | #include <linux/debugfs.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/cfg80211.h> | 17 | #include <net/cfg80211.h> |
16 | #include "reg.h" | 18 | #include "reg.h" |
@@ -24,6 +26,11 @@ struct cfg80211_registered_device { | |||
24 | * any call is in progress */ | 26 | * any call is in progress */ |
25 | struct mutex mtx; | 27 | struct mutex mtx; |
26 | 28 | ||
29 | /* rfkill support */ | ||
30 | struct rfkill_ops rfkill_ops; | ||
31 | struct rfkill *rfkill; | ||
32 | struct work_struct rfkill_sync; | ||
33 | |||
27 | /* ISO / IEC 3166 alpha2 for which this device is receiving | 34 | /* ISO / IEC 3166 alpha2 for which this device is receiving |
28 | * country IEs on, this can help disregard country IEs from APs | 35 | * country IEs on, this can help disregard country IEs from APs |
29 | * on the same alpha2 quickly. The alpha2 may differ from | 36 | * on the same alpha2 quickly. The alpha2 may differ from |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 4b4d3c8a1aed..24168560ebae 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -1687,6 +1687,12 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | |||
1687 | if (err) | 1687 | if (err) |
1688 | goto out_rtnl; | 1688 | goto out_rtnl; |
1689 | 1689 | ||
1690 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | ||
1691 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN) { | ||
1692 | err = -EINVAL; | ||
1693 | goto out; | ||
1694 | } | ||
1695 | |||
1690 | err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, ¶ms.vlan); | 1696 | err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, ¶ms.vlan); |
1691 | if (err) | 1697 | if (err) |
1692 | goto out; | 1698 | goto out; |
@@ -1738,7 +1744,11 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
1738 | nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]); | 1744 | nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]); |
1739 | params.listen_interval = | 1745 | params.listen_interval = |
1740 | nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); | 1746 | nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); |
1747 | |||
1741 | params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]); | 1748 | params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]); |
1749 | if (!params.aid || params.aid > IEEE80211_MAX_AID) | ||
1750 | return -EINVAL; | ||
1751 | |||
1742 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) | 1752 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) |
1743 | params.ht_capa = | 1753 | params.ht_capa = |
1744 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); | 1754 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); |
@@ -3559,11 +3569,43 @@ void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev) | |||
3559 | genlmsg_multicast(msg, 0, nl80211_config_mcgrp.id, GFP_KERNEL); | 3569 | genlmsg_multicast(msg, 0, nl80211_config_mcgrp.id, GFP_KERNEL); |
3560 | } | 3570 | } |
3561 | 3571 | ||
3572 | static int nl80211_add_scan_req(struct sk_buff *msg, | ||
3573 | struct cfg80211_registered_device *rdev) | ||
3574 | { | ||
3575 | struct cfg80211_scan_request *req = rdev->scan_req; | ||
3576 | struct nlattr *nest; | ||
3577 | int i; | ||
3578 | |||
3579 | if (WARN_ON(!req)) | ||
3580 | return 0; | ||
3581 | |||
3582 | nest = nla_nest_start(msg, NL80211_ATTR_SCAN_SSIDS); | ||
3583 | if (!nest) | ||
3584 | goto nla_put_failure; | ||
3585 | for (i = 0; i < req->n_ssids; i++) | ||
3586 | NLA_PUT(msg, i, req->ssids[i].ssid_len, req->ssids[i].ssid); | ||
3587 | nla_nest_end(msg, nest); | ||
3588 | |||
3589 | nest = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES); | ||
3590 | if (!nest) | ||
3591 | goto nla_put_failure; | ||
3592 | for (i = 0; i < req->n_channels; i++) | ||
3593 | NLA_PUT_U32(msg, i, req->channels[i]->center_freq); | ||
3594 | nla_nest_end(msg, nest); | ||
3595 | |||
3596 | if (req->ie) | ||
3597 | NLA_PUT(msg, NL80211_ATTR_IE, req->ie_len, req->ie); | ||
3598 | |||
3599 | return 0; | ||
3600 | nla_put_failure: | ||
3601 | return -ENOBUFS; | ||
3602 | } | ||
3603 | |||
3562 | static int nl80211_send_scan_donemsg(struct sk_buff *msg, | 3604 | static int nl80211_send_scan_donemsg(struct sk_buff *msg, |
3563 | struct cfg80211_registered_device *rdev, | 3605 | struct cfg80211_registered_device *rdev, |
3564 | struct net_device *netdev, | 3606 | struct net_device *netdev, |
3565 | u32 pid, u32 seq, int flags, | 3607 | u32 pid, u32 seq, int flags, |
3566 | u32 cmd) | 3608 | u32 cmd) |
3567 | { | 3609 | { |
3568 | void *hdr; | 3610 | void *hdr; |
3569 | 3611 | ||
@@ -3574,7 +3616,8 @@ static int nl80211_send_scan_donemsg(struct sk_buff *msg, | |||
3574 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); | 3616 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); |
3575 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); | 3617 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); |
3576 | 3618 | ||
3577 | /* XXX: we should probably bounce back the request? */ | 3619 | /* ignore errors and send incomplete event anyway */ |
3620 | nl80211_add_scan_req(msg, rdev); | ||
3578 | 3621 | ||
3579 | return genlmsg_end(msg, hdr); | 3622 | return genlmsg_end(msg, hdr); |
3580 | 3623 | ||
@@ -3828,7 +3871,7 @@ void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev, | |||
3828 | struct sk_buff *msg; | 3871 | struct sk_buff *msg; |
3829 | void *hdr; | 3872 | void *hdr; |
3830 | 3873 | ||
3831 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 3874 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); |
3832 | if (!msg) | 3875 | if (!msg) |
3833 | return; | 3876 | return; |
3834 | 3877 | ||
@@ -3852,7 +3895,7 @@ void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev, | |||
3852 | return; | 3895 | return; |
3853 | } | 3896 | } |
3854 | 3897 | ||
3855 | genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, GFP_KERNEL); | 3898 | genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, GFP_ATOMIC); |
3856 | return; | 3899 | return; |
3857 | 3900 | ||
3858 | nla_put_failure: | 3901 | nla_put_failure: |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index f87ac1df2df5..ea4c299fbe3b 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -2171,7 +2171,13 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) | |||
2171 | * the country IE rd with what CRDA believes that country should have | 2171 | * the country IE rd with what CRDA believes that country should have |
2172 | */ | 2172 | */ |
2173 | 2173 | ||
2174 | BUG_ON(!country_ie_regdomain); | 2174 | /* |
2175 | * Userspace could have sent two replies with only | ||
2176 | * one kernel request. By the second reply we would have | ||
2177 | * already processed and consumed the country_ie_regdomain. | ||
2178 | */ | ||
2179 | if (!country_ie_regdomain) | ||
2180 | return -EALREADY; | ||
2175 | BUG_ON(rd == country_ie_regdomain); | 2181 | BUG_ON(rd == country_ie_regdomain); |
2176 | 2182 | ||
2177 | /* | 2183 | /* |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index df59440290e5..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)); |
diff --git a/net/wireless/util.c b/net/wireless/util.c index d072bff463aa..25550692dda6 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -157,26 +157,25 @@ int cfg80211_validate_key_settings(struct key_params *params, int key_idx, | |||
157 | params->cipher != WLAN_CIPHER_SUITE_WEP104) | 157 | params->cipher != WLAN_CIPHER_SUITE_WEP104) |
158 | return -EINVAL; | 158 | return -EINVAL; |
159 | 159 | ||
160 | /* TODO: add definitions for the lengths to linux/ieee80211.h */ | ||
161 | switch (params->cipher) { | 160 | switch (params->cipher) { |
162 | case WLAN_CIPHER_SUITE_WEP40: | 161 | case WLAN_CIPHER_SUITE_WEP40: |
163 | if (params->key_len != 5) | 162 | if (params->key_len != WLAN_KEY_LEN_WEP40) |
164 | return -EINVAL; | 163 | return -EINVAL; |
165 | break; | 164 | break; |
166 | case WLAN_CIPHER_SUITE_TKIP: | 165 | case WLAN_CIPHER_SUITE_TKIP: |
167 | if (params->key_len != 32) | 166 | if (params->key_len != WLAN_KEY_LEN_TKIP) |
168 | return -EINVAL; | 167 | return -EINVAL; |
169 | break; | 168 | break; |
170 | case WLAN_CIPHER_SUITE_CCMP: | 169 | case WLAN_CIPHER_SUITE_CCMP: |
171 | if (params->key_len != 16) | 170 | if (params->key_len != WLAN_KEY_LEN_CCMP) |
172 | return -EINVAL; | 171 | return -EINVAL; |
173 | break; | 172 | break; |
174 | case WLAN_CIPHER_SUITE_WEP104: | 173 | case WLAN_CIPHER_SUITE_WEP104: |
175 | if (params->key_len != 13) | 174 | if (params->key_len != WLAN_KEY_LEN_WEP104) |
176 | return -EINVAL; | 175 | return -EINVAL; |
177 | break; | 176 | break; |
178 | case WLAN_CIPHER_SUITE_AES_CMAC: | 177 | case WLAN_CIPHER_SUITE_AES_CMAC: |
179 | if (params->key_len != 16) | 178 | if (params->key_len != WLAN_KEY_LEN_AES_CMAC) |
180 | return -EINVAL; | 179 | return -EINVAL; |
181 | break; | 180 | break; |
182 | default: | 181 | default: |
@@ -259,7 +258,7 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb) | |||
259 | } | 258 | } |
260 | EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb); | 259 | EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb); |
261 | 260 | ||
262 | int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) | 261 | static int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) |
263 | { | 262 | { |
264 | int ae = meshhdr->flags & MESH_FLAGS_AE; | 263 | int ae = meshhdr->flags & MESH_FLAGS_AE; |
265 | /* 7.1.3.5a.2 */ | 264 | /* 7.1.3.5a.2 */ |
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 711e00a0c9b5..d030c5315672 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c | |||
@@ -744,3 +744,86 @@ int cfg80211_wext_giwencode(struct net_device *dev, | |||
744 | return err; | 744 | return err; |
745 | } | 745 | } |
746 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwencode); | 746 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwencode); |
747 | |||
748 | int 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 | } | ||
799 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwtxpower); | ||
800 | |||
801 | int 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 | } | ||
829 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwtxpower); | ||