diff options
author | David S. Miller <davem@davemloft.net> | 2009-07-30 22:26:55 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-07-30 22:26:55 -0400 |
commit | 2f6d7c1b34403b97fa57473edcb6749d1db5ace3 (patch) | |
tree | 97da33c077b08b72a361ff5a4542b86d190b0164 /net | |
parent | df597efb5737063497f1a4f7c996cc9aec294230 (diff) | |
parent | 1e4247d457c6a42e4a05cb7dfa4e6ea1fa65c112 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'net')
-rw-r--r-- | net/core/dev.c | 1 | ||||
-rw-r--r-- | net/mac80211/Kconfig | 1 | ||||
-rw-r--r-- | net/mac80211/Makefile | 1 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 14 | ||||
-rw-r--r-- | net/mac80211/ibss.c | 2 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 45 | ||||
-rw-r--r-- | net/mac80211/iface.c | 22 | ||||
-rw-r--r-- | net/mac80211/main.c | 3 | ||||
-rw-r--r-- | net/mac80211/mesh.c | 2 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 35 | ||||
-rw-r--r-- | net/mac80211/rx.c | 21 | ||||
-rw-r--r-- | net/mac80211/scan.c | 304 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 13 | ||||
-rw-r--r-- | net/mac80211/tx.c | 109 | ||||
-rw-r--r-- | net/mac80211/util.c | 13 | ||||
-rw-r--r-- | net/mac80211/wext.c | 235 | ||||
-rw-r--r-- | net/wireless/core.c | 78 | ||||
-rw-r--r-- | net/wireless/core.h | 8 | ||||
-rw-r--r-- | net/wireless/ibss.c | 13 | ||||
-rw-r--r-- | net/wireless/mlme.c | 8 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 206 | ||||
-rw-r--r-- | net/wireless/scan.c | 25 | ||||
-rw-r--r-- | net/wireless/sme.c | 5 | ||||
-rw-r--r-- | net/wireless/wext-compat.c | 180 | ||||
-rw-r--r-- | net/wireless/wext-compat.h | 50 | ||||
-rw-r--r-- | net/wireless/wext-sme.c | 13 |
26 files changed, 846 insertions, 561 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index d6c657ee413d..71347668c506 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -5344,6 +5344,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char | |||
5344 | out: | 5344 | out: |
5345 | return err; | 5345 | return err; |
5346 | } | 5346 | } |
5347 | EXPORT_SYMBOL_GPL(dev_change_net_namespace); | ||
5347 | 5348 | ||
5348 | static int dev_cpu_callback(struct notifier_block *nfb, | 5349 | static int dev_cpu_callback(struct notifier_block *nfb, |
5349 | unsigned long action, | 5350 | unsigned long action, |
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index 19a4c66e143e..7dd77b6d4c9a 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig | |||
@@ -6,7 +6,6 @@ config MAC80211 | |||
6 | select CRYPTO_ARC4 | 6 | select CRYPTO_ARC4 |
7 | select CRYPTO_AES | 7 | select CRYPTO_AES |
8 | select CRC32 | 8 | select CRC32 |
9 | select WIRELESS_EXT | ||
10 | ---help--- | 9 | ---help--- |
11 | This option enables the hardware independent IEEE 802.11 | 10 | This option enables the hardware independent IEEE 802.11 |
12 | networking stack. | 11 | networking stack. |
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index 91284a74ff91..9f3cf7129324 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile | |||
@@ -3,7 +3,6 @@ obj-$(CONFIG_MAC80211) += mac80211.o | |||
3 | # mac80211 objects | 3 | # mac80211 objects |
4 | mac80211-y := \ | 4 | mac80211-y := \ |
5 | main.o \ | 5 | main.o \ |
6 | wext.o \ | ||
7 | sta_info.o \ | 6 | sta_info.o \ |
8 | wep.o \ | 7 | wep.o \ |
9 | wpa.o \ | 8 | wpa.o \ |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 52928ad90570..4bbf5007799b 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -57,19 +57,9 @@ static int ieee80211_add_iface(struct wiphy *wiphy, char *name, | |||
57 | return 0; | 57 | return 0; |
58 | } | 58 | } |
59 | 59 | ||
60 | static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex) | 60 | static int ieee80211_del_iface(struct wiphy *wiphy, struct net_device *dev) |
61 | { | 61 | { |
62 | struct net_device *dev; | 62 | ieee80211_if_remove(IEEE80211_DEV_TO_SUB_IF(dev)); |
63 | struct ieee80211_sub_if_data *sdata; | ||
64 | |||
65 | /* we're under RTNL */ | ||
66 | dev = __dev_get_by_index(&init_net, ifindex); | ||
67 | if (!dev) | ||
68 | return -ENODEV; | ||
69 | |||
70 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
71 | |||
72 | ieee80211_if_remove(sdata); | ||
73 | 63 | ||
74 | return 0; | 64 | return 0; |
75 | } | 65 | } |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 8e2220000e5c..6e3cca65c460 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -742,7 +742,7 @@ static void ieee80211_ibss_work(struct work_struct *work) | |||
742 | if (!netif_running(sdata->dev)) | 742 | if (!netif_running(sdata->dev)) |
743 | return; | 743 | return; |
744 | 744 | ||
745 | if (local->sw_scanning || local->hw_scanning) | 745 | if (local->scanning) |
746 | return; | 746 | return; |
747 | 747 | ||
748 | if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_ADHOC)) | 748 | if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_ADHOC)) |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 6a0177137dd5..aec6853cb435 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <linux/spinlock.h> | 24 | #include <linux/spinlock.h> |
25 | #include <linux/etherdevice.h> | 25 | #include <linux/etherdevice.h> |
26 | #include <net/cfg80211.h> | 26 | #include <net/cfg80211.h> |
27 | #include <net/iw_handler.h> | ||
28 | #include <net/mac80211.h> | 27 | #include <net/mac80211.h> |
29 | #include "key.h" | 28 | #include "key.h" |
30 | #include "sta_info.h" | 29 | #include "sta_info.h" |
@@ -570,6 +569,43 @@ enum queue_stop_reason { | |||
570 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD, | 569 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD, |
571 | }; | 570 | }; |
572 | 571 | ||
572 | /** | ||
573 | * mac80211 scan flags - currently active scan mode | ||
574 | * | ||
575 | * @SCAN_SW_SCANNING: We're currently in the process of scanning but may as | ||
576 | * well be on the operating channel | ||
577 | * @SCAN_HW_SCANNING: The hardware is scanning for us, we have no way to | ||
578 | * determine if we are on the operating channel or not | ||
579 | * @SCAN_OFF_CHANNEL: We're off our operating channel for scanning, | ||
580 | * gets only set in conjunction with SCAN_SW_SCANNING | ||
581 | */ | ||
582 | enum { | ||
583 | SCAN_SW_SCANNING, | ||
584 | SCAN_HW_SCANNING, | ||
585 | SCAN_OFF_CHANNEL, | ||
586 | }; | ||
587 | |||
588 | /** | ||
589 | * enum mac80211_scan_state - scan state machine states | ||
590 | * | ||
591 | * @SCAN_DECISION: Main entry point to the scan state machine, this state | ||
592 | * determines if we should keep on scanning or switch back to the | ||
593 | * operating channel | ||
594 | * @SCAN_SET_CHANNEL: Set the next channel to be scanned | ||
595 | * @SCAN_SEND_PROBE: Send probe requests and wait for probe responses | ||
596 | * @SCAN_LEAVE_OPER_CHANNEL: Leave the operating channel, notify the AP | ||
597 | * about us leaving the channel and stop all associated STA interfaces | ||
598 | * @SCAN_ENTER_OPER_CHANNEL: Enter the operating channel again, notify the | ||
599 | * AP about us being back and restart all associated STA interfaces | ||
600 | */ | ||
601 | enum mac80211_scan_state { | ||
602 | SCAN_DECISION, | ||
603 | SCAN_SET_CHANNEL, | ||
604 | SCAN_SEND_PROBE, | ||
605 | SCAN_LEAVE_OPER_CHANNEL, | ||
606 | SCAN_ENTER_OPER_CHANNEL, | ||
607 | }; | ||
608 | |||
573 | struct ieee80211_local { | 609 | struct ieee80211_local { |
574 | /* embed the driver visible part. | 610 | /* embed the driver visible part. |
575 | * don't cast (use the static inlines below), but we keep | 611 | * don't cast (use the static inlines below), but we keep |
@@ -668,7 +704,7 @@ struct ieee80211_local { | |||
668 | 704 | ||
669 | /* Scanning and BSS list */ | 705 | /* Scanning and BSS list */ |
670 | struct mutex scan_mtx; | 706 | struct mutex scan_mtx; |
671 | bool sw_scanning, hw_scanning; | 707 | unsigned long scanning; |
672 | struct cfg80211_ssid scan_ssid; | 708 | struct cfg80211_ssid scan_ssid; |
673 | struct cfg80211_scan_request int_scan_req; | 709 | struct cfg80211_scan_request int_scan_req; |
674 | struct cfg80211_scan_request *scan_req; | 710 | struct cfg80211_scan_request *scan_req; |
@@ -678,7 +714,7 @@ struct ieee80211_local { | |||
678 | int scan_channel_idx; | 714 | int scan_channel_idx; |
679 | int scan_ies_len; | 715 | int scan_ies_len; |
680 | 716 | ||
681 | enum { SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state; | 717 | enum mac80211_scan_state next_scan_state; |
682 | struct delayed_work scan_work; | 718 | struct delayed_work scan_work; |
683 | struct ieee80211_sub_if_data *scan_sdata; | 719 | struct ieee80211_sub_if_data *scan_sdata; |
684 | enum nl80211_channel_type oper_channel_type; | 720 | enum nl80211_channel_type oper_channel_type; |
@@ -914,9 +950,6 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
914 | void ieee80211_configure_filter(struct ieee80211_local *local); | 950 | void ieee80211_configure_filter(struct ieee80211_local *local); |
915 | u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata); | 951 | u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata); |
916 | 952 | ||
917 | /* wireless extensions */ | ||
918 | extern const struct iw_handler_def ieee80211_iw_handler_def; | ||
919 | |||
920 | /* STA code */ | 953 | /* STA code */ |
921 | void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata); | 954 | void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata); |
922 | int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | 955 | int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 2f797a86ced5..6c655b6547fb 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -335,7 +335,10 @@ static int ieee80211_stop(struct net_device *dev) | |||
335 | struct ieee80211_local *local = sdata->local; | 335 | struct ieee80211_local *local = sdata->local; |
336 | struct ieee80211_if_init_conf conf; | 336 | struct ieee80211_if_init_conf conf; |
337 | struct sta_info *sta; | 337 | struct sta_info *sta; |
338 | unsigned long flags; | ||
339 | struct sk_buff *skb, *tmp; | ||
338 | u32 hw_reconf_flags = 0; | 340 | u32 hw_reconf_flags = 0; |
341 | int i; | ||
339 | 342 | ||
340 | /* | 343 | /* |
341 | * Stop TX on this interface first. | 344 | * Stop TX on this interface first. |
@@ -515,7 +518,7 @@ static int ieee80211_stop(struct net_device *dev) | |||
515 | * the scan_sdata is NULL already don't send out a | 518 | * the scan_sdata is NULL already don't send out a |
516 | * scan event to userspace -- the scan is incomplete. | 519 | * scan event to userspace -- the scan is incomplete. |
517 | */ | 520 | */ |
518 | if (local->sw_scanning) | 521 | if (test_bit(SCAN_SW_SCANNING, &local->scanning)) |
519 | ieee80211_scan_completed(&local->hw, true); | 522 | ieee80211_scan_completed(&local->hw, true); |
520 | } | 523 | } |
521 | 524 | ||
@@ -551,6 +554,18 @@ static int ieee80211_stop(struct net_device *dev) | |||
551 | if (hw_reconf_flags) | 554 | if (hw_reconf_flags) |
552 | ieee80211_hw_config(local, hw_reconf_flags); | 555 | ieee80211_hw_config(local, hw_reconf_flags); |
553 | 556 | ||
557 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | ||
558 | for (i = 0; i < IEEE80211_MAX_QUEUES; i++) { | ||
559 | skb_queue_walk_safe(&local->pending[i], skb, tmp) { | ||
560 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
561 | if (info->control.vif == &sdata->vif) { | ||
562 | __skb_unlink(skb, &local->pending[i]); | ||
563 | dev_kfree_skb_irq(skb); | ||
564 | } | ||
565 | } | ||
566 | } | ||
567 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | ||
568 | |||
554 | return 0; | 569 | return 0; |
555 | } | 570 | } |
556 | 571 | ||
@@ -669,7 +684,6 @@ static void ieee80211_if_setup(struct net_device *dev) | |||
669 | { | 684 | { |
670 | ether_setup(dev); | 685 | ether_setup(dev); |
671 | dev->netdev_ops = &ieee80211_dataif_ops; | 686 | dev->netdev_ops = &ieee80211_dataif_ops; |
672 | dev->wireless_handlers = &ieee80211_iw_handler_def; | ||
673 | dev->destructor = free_netdev; | 687 | dev->destructor = free_netdev; |
674 | } | 688 | } |
675 | 689 | ||
@@ -772,6 +786,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
772 | name, ieee80211_if_setup); | 786 | name, ieee80211_if_setup); |
773 | if (!ndev) | 787 | if (!ndev) |
774 | return -ENOMEM; | 788 | return -ENOMEM; |
789 | dev_net_set(ndev, wiphy_net(local->hw.wiphy)); | ||
775 | 790 | ||
776 | ndev->needed_headroom = local->tx_headroom + | 791 | ndev->needed_headroom = local->tx_headroom + |
777 | 4*6 /* four MAC addresses */ | 792 | 4*6 /* four MAC addresses */ |
@@ -788,7 +803,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
788 | 803 | ||
789 | memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN); | 804 | memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN); |
790 | SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy)); | 805 | SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy)); |
791 | ndev->features |= NETIF_F_NETNS_LOCAL; | ||
792 | 806 | ||
793 | /* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */ | 807 | /* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */ |
794 | sdata = netdev_priv(ndev); | 808 | sdata = netdev_priv(ndev); |
@@ -905,7 +919,7 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | |||
905 | struct ieee80211_sub_if_data *sdata; | 919 | struct ieee80211_sub_if_data *sdata; |
906 | int count = 0; | 920 | int count = 0; |
907 | 921 | ||
908 | if (local->hw_scanning || local->sw_scanning) | 922 | if (local->scanning) |
909 | return ieee80211_idle_off(local, "scanning"); | 923 | return ieee80211_idle_off(local, "scanning"); |
910 | 924 | ||
911 | list_for_each_entry(sdata, &local->interfaces, list) { | 925 | list_for_each_entry(sdata, &local->interfaces, list) { |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 3234f3751d22..c1a799194fff 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -198,7 +198,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
198 | } | 198 | } |
199 | 199 | ||
200 | if (changed & BSS_CHANGED_BEACON_ENABLED) { | 200 | if (changed & BSS_CHANGED_BEACON_ENABLED) { |
201 | if (local->sw_scanning) { | 201 | if (test_bit(SCAN_SW_SCANNING, &local->scanning)) { |
202 | sdata->vif.bss_conf.enable_beacon = false; | 202 | sdata->vif.bss_conf.enable_beacon = false; |
203 | } else { | 203 | } else { |
204 | /* | 204 | /* |
@@ -620,6 +620,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
620 | if (!wiphy) | 620 | if (!wiphy) |
621 | return NULL; | 621 | return NULL; |
622 | 622 | ||
623 | wiphy->netnsok = true; | ||
623 | wiphy->privid = mac80211_wiphy_privid; | 624 | wiphy->privid = mac80211_wiphy_privid; |
624 | 625 | ||
625 | /* Yes, putting cfg80211_bss into ieee80211_bss is a hack */ | 626 | /* Yes, putting cfg80211_bss into ieee80211_bss is a hack */ |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 8a97b1423088..9a3826978b1c 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -597,7 +597,7 @@ static void ieee80211_mesh_work(struct work_struct *work) | |||
597 | if (!netif_running(sdata->dev)) | 597 | if (!netif_running(sdata->dev)) |
598 | return; | 598 | return; |
599 | 599 | ||
600 | if (local->sw_scanning || local->hw_scanning) | 600 | if (local->scanning) |
601 | return; | 601 | return; |
602 | 602 | ||
603 | while ((skb = skb_dequeue(&ifmsh->skb_queue))) | 603 | while ((skb = skb_dequeue(&ifmsh->skb_queue))) |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 0b3551da8f43..ee83125ed179 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -581,7 +581,7 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
581 | if (!ifmgd->associated) | 581 | if (!ifmgd->associated) |
582 | return; | 582 | return; |
583 | 583 | ||
584 | if (sdata->local->sw_scanning || sdata->local->hw_scanning) | 584 | if (sdata->local->scanning) |
585 | return; | 585 | return; |
586 | 586 | ||
587 | /* Disregard subsequent beacons if we are already running a timer | 587 | /* Disregard subsequent beacons if we are already running a timer |
@@ -639,7 +639,7 @@ static void ieee80211_enable_ps(struct ieee80211_local *local, | |||
639 | * If we are scanning right now then the parameters will | 639 | * If we are scanning right now then the parameters will |
640 | * take effect when scan finishes. | 640 | * take effect when scan finishes. |
641 | */ | 641 | */ |
642 | if (local->hw_scanning || local->sw_scanning) | 642 | if (local->scanning) |
643 | return; | 643 | return; |
644 | 644 | ||
645 | if (conf->dynamic_ps_timeout > 0 && | 645 | if (conf->dynamic_ps_timeout > 0 && |
@@ -1166,6 +1166,9 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, | |||
1166 | if (!netif_running(sdata->dev)) | 1166 | if (!netif_running(sdata->dev)) |
1167 | return; | 1167 | return; |
1168 | 1168 | ||
1169 | if (sdata->local->scanning) | ||
1170 | return; | ||
1171 | |||
1169 | mutex_lock(&ifmgd->mtx); | 1172 | mutex_lock(&ifmgd->mtx); |
1170 | 1173 | ||
1171 | if (!ifmgd->associated) | 1174 | if (!ifmgd->associated) |
@@ -2000,6 +2003,9 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
2000 | case RX_MGMT_CFG80211_ASSOC: | 2003 | case RX_MGMT_CFG80211_ASSOC: |
2001 | cfg80211_send_rx_assoc(sdata->dev, (u8 *) mgmt, skb->len); | 2004 | cfg80211_send_rx_assoc(sdata->dev, (u8 *) mgmt, skb->len); |
2002 | break; | 2005 | break; |
2006 | case RX_MGMT_CFG80211_DEAUTH: | ||
2007 | cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len, NULL); | ||
2008 | break; | ||
2003 | default: | 2009 | default: |
2004 | WARN(1, "unexpected: %d", rma); | 2010 | WARN(1, "unexpected: %d", rma); |
2005 | } | 2011 | } |
@@ -2038,7 +2044,7 @@ static void ieee80211_sta_work(struct work_struct *work) | |||
2038 | if (!netif_running(sdata->dev)) | 2044 | if (!netif_running(sdata->dev)) |
2039 | return; | 2045 | return; |
2040 | 2046 | ||
2041 | if (local->sw_scanning || local->hw_scanning) | 2047 | if (local->scanning) |
2042 | return; | 2048 | return; |
2043 | 2049 | ||
2044 | if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) | 2050 | if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) |
@@ -2213,9 +2219,6 @@ static void ieee80211_sta_monitor_work(struct work_struct *work) | |||
2213 | container_of(work, struct ieee80211_sub_if_data, | 2219 | container_of(work, struct ieee80211_sub_if_data, |
2214 | u.mgd.monitor_work); | 2220 | u.mgd.monitor_work); |
2215 | 2221 | ||
2216 | if (sdata->local->sw_scanning || sdata->local->hw_scanning) | ||
2217 | return; | ||
2218 | |||
2219 | ieee80211_mgd_probe_ap(sdata, false); | 2222 | ieee80211_mgd_probe_ap(sdata, false); |
2220 | } | 2223 | } |
2221 | 2224 | ||
@@ -2377,6 +2380,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | |||
2377 | 2380 | ||
2378 | wk->state = IEEE80211_MGD_STATE_PROBE; | 2381 | wk->state = IEEE80211_MGD_STATE_PROBE; |
2379 | wk->auth_alg = auth_alg; | 2382 | wk->auth_alg = auth_alg; |
2383 | wk->timeout = jiffies; /* run right away */ | ||
2380 | 2384 | ||
2381 | /* | 2385 | /* |
2382 | * XXX: if still associated need to tell AP that we're going | 2386 | * XXX: if still associated need to tell AP that we're going |
@@ -2448,6 +2452,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
2448 | 2452 | ||
2449 | wk->state = IEEE80211_MGD_STATE_ASSOC; | 2453 | wk->state = IEEE80211_MGD_STATE_ASSOC; |
2450 | wk->tries = 0; | 2454 | wk->tries = 0; |
2455 | wk->timeout = jiffies; /* run right away */ | ||
2451 | 2456 | ||
2452 | if (req->use_mfp) { | 2457 | if (req->use_mfp) { |
2453 | ifmgd->mfp = IEEE80211_MFP_REQUIRED; | 2458 | ifmgd->mfp = IEEE80211_MFP_REQUIRED; |
@@ -2496,8 +2501,13 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
2496 | } | 2501 | } |
2497 | } | 2502 | } |
2498 | 2503 | ||
2499 | /* cfg80211 should catch this... */ | 2504 | /* |
2500 | if (WARN_ON(!bssid)) { | 2505 | * cfg80211 should catch this ... but it's racy since |
2506 | * we can receive a deauth frame, process it, hand it | ||
2507 | * to cfg80211 while that's in a locked section already | ||
2508 | * trying to tell us that the user wants to disconnect. | ||
2509 | */ | ||
2510 | if (!bssid) { | ||
2501 | mutex_unlock(&ifmgd->mtx); | 2511 | mutex_unlock(&ifmgd->mtx); |
2502 | return -ENOLINK; | 2512 | return -ENOLINK; |
2503 | } | 2513 | } |
@@ -2522,8 +2532,13 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | |||
2522 | 2532 | ||
2523 | mutex_lock(&ifmgd->mtx); | 2533 | mutex_lock(&ifmgd->mtx); |
2524 | 2534 | ||
2525 | /* cfg80211 should catch that */ | 2535 | /* |
2526 | if (WARN_ON(&ifmgd->associated->cbss != req->bss)) { | 2536 | * cfg80211 should catch this ... but it's racy since |
2537 | * we can receive a disassoc frame, process it, hand it | ||
2538 | * to cfg80211 while that's in a locked section already | ||
2539 | * trying to tell us that the user wants to disconnect. | ||
2540 | */ | ||
2541 | if (&ifmgd->associated->cbss != req->bss) { | ||
2527 | mutex_unlock(&ifmgd->mtx); | 2542 | mutex_unlock(&ifmgd->mtx); |
2528 | return -ENOLINK; | 2543 | return -ENOLINK; |
2529 | } | 2544 | } |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index b6ddde3848fb..25a669c86e14 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -418,10 +418,11 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx) | |||
418 | struct ieee80211_local *local = rx->local; | 418 | struct ieee80211_local *local = rx->local; |
419 | struct sk_buff *skb = rx->skb; | 419 | struct sk_buff *skb = rx->skb; |
420 | 420 | ||
421 | if (unlikely(local->hw_scanning)) | 421 | if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning))) |
422 | return ieee80211_scan_rx(rx->sdata, skb); | 422 | return ieee80211_scan_rx(rx->sdata, skb); |
423 | 423 | ||
424 | if (unlikely(local->sw_scanning)) { | 424 | if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning) && |
425 | (rx->flags & IEEE80211_RX_IN_SCAN))) { | ||
425 | /* drop all the other packets during a software scan anyway */ | 426 | /* drop all the other packets during a software scan anyway */ |
426 | if (ieee80211_scan_rx(rx->sdata, skb) != RX_QUEUED) | 427 | if (ieee80211_scan_rx(rx->sdata, skb) != RX_QUEUED) |
427 | dev_kfree_skb(skb); | 428 | dev_kfree_skb(skb); |
@@ -782,7 +783,7 @@ static void ap_sta_ps_start(struct sta_info *sta) | |||
782 | struct ieee80211_local *local = sdata->local; | 783 | struct ieee80211_local *local = sdata->local; |
783 | 784 | ||
784 | atomic_inc(&sdata->bss->num_sta_ps); | 785 | atomic_inc(&sdata->bss->num_sta_ps); |
785 | set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL); | 786 | set_sta_flags(sta, WLAN_STA_PS); |
786 | drv_sta_notify(local, &sdata->vif, STA_NOTIFY_SLEEP, &sta->sta); | 787 | drv_sta_notify(local, &sdata->vif, STA_NOTIFY_SLEEP, &sta->sta); |
787 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 788 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
788 | printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n", | 789 | printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n", |
@@ -798,7 +799,7 @@ static int ap_sta_ps_end(struct sta_info *sta) | |||
798 | 799 | ||
799 | atomic_dec(&sdata->bss->num_sta_ps); | 800 | atomic_dec(&sdata->bss->num_sta_ps); |
800 | 801 | ||
801 | clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL); | 802 | clear_sta_flags(sta, WLAN_STA_PS); |
802 | drv_sta_notify(local, &sdata->vif, STA_NOTIFY_AWAKE, &sta->sta); | 803 | drv_sta_notify(local, &sdata->vif, STA_NOTIFY_AWAKE, &sta->sta); |
803 | 804 | ||
804 | if (!skb_queue_empty(&sta->ps_tx_buf)) | 805 | if (!skb_queue_empty(&sta->ps_tx_buf)) |
@@ -1116,14 +1117,15 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx) | |||
1116 | skb_queue_empty(&rx->sta->ps_tx_buf); | 1117 | skb_queue_empty(&rx->sta->ps_tx_buf); |
1117 | 1118 | ||
1118 | if (skb) { | 1119 | if (skb) { |
1120 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
1119 | struct ieee80211_hdr *hdr = | 1121 | struct ieee80211_hdr *hdr = |
1120 | (struct ieee80211_hdr *) skb->data; | 1122 | (struct ieee80211_hdr *) skb->data; |
1121 | 1123 | ||
1122 | /* | 1124 | /* |
1123 | * Tell TX path to send one frame even though the STA may | 1125 | * Tell TX path to send this frame even though the STA may |
1124 | * still remain is PS mode after this frame exchange. | 1126 | * still remain is PS mode after this frame exchange. |
1125 | */ | 1127 | */ |
1126 | set_sta_flags(rx->sta, WLAN_STA_PSPOLL); | 1128 | info->flags |= IEEE80211_TX_CTL_PSPOLL_RESPONSE; |
1127 | 1129 | ||
1128 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 1130 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
1129 | printk(KERN_DEBUG "STA %pM aid %d: PS Poll (entries after %d)\n", | 1131 | printk(KERN_DEBUG "STA %pM aid %d: PS Poll (entries after %d)\n", |
@@ -1138,7 +1140,7 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx) | |||
1138 | else | 1140 | else |
1139 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); | 1141 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); |
1140 | 1142 | ||
1141 | dev_queue_xmit(skb); | 1143 | ieee80211_add_pending_skb(rx->local, skb); |
1142 | 1144 | ||
1143 | if (no_pending_pkts) | 1145 | if (no_pending_pkts) |
1144 | sta_info_clear_tim_bit(rx->sta); | 1146 | sta_info_clear_tim_bit(rx->sta); |
@@ -1539,7 +1541,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1539 | info = IEEE80211_SKB_CB(fwd_skb); | 1541 | info = IEEE80211_SKB_CB(fwd_skb); |
1540 | memset(info, 0, sizeof(*info)); | 1542 | memset(info, 0, sizeof(*info)); |
1541 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | 1543 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; |
1542 | fwd_skb->iif = rx->dev->ifindex; | 1544 | info->control.vif = &rx->sdata->vif; |
1543 | ieee80211_select_queue(local, fwd_skb); | 1545 | ieee80211_select_queue(local, fwd_skb); |
1544 | if (is_multicast_ether_addr(fwd_hdr->addr3)) | 1546 | if (is_multicast_ether_addr(fwd_hdr->addr3)) |
1545 | memcpy(fwd_hdr->addr1, fwd_hdr->addr3, | 1547 | memcpy(fwd_hdr->addr1, fwd_hdr->addr3, |
@@ -2136,7 +2138,8 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2136 | return; | 2138 | return; |
2137 | } | 2139 | } |
2138 | 2140 | ||
2139 | if (unlikely(local->sw_scanning || local->hw_scanning)) | 2141 | if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) || |
2142 | test_bit(SCAN_OFF_CHANNEL, &local->scanning))) | ||
2140 | rx.flags |= IEEE80211_RX_IN_SCAN; | 2143 | rx.flags |= IEEE80211_RX_IN_SCAN; |
2141 | 2144 | ||
2142 | ieee80211_parse_qos(&rx); | 2145 | ieee80211_parse_qos(&rx); |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 74820656dc89..45731000eb8d 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include <linux/if_arp.h> | 18 | #include <linux/if_arp.h> |
19 | #include <linux/rtnetlink.h> | 19 | #include <linux/rtnetlink.h> |
20 | #include <net/mac80211.h> | 20 | #include <net/mac80211.h> |
21 | #include <net/iw_handler.h> | ||
22 | 21 | ||
23 | #include "ieee80211_i.h" | 22 | #include "ieee80211_i.h" |
24 | #include "driver-ops.h" | 23 | #include "driver-ops.h" |
@@ -265,7 +264,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
265 | 264 | ||
266 | mutex_lock(&local->scan_mtx); | 265 | mutex_lock(&local->scan_mtx); |
267 | 266 | ||
268 | if (WARN_ON(!local->hw_scanning && !local->sw_scanning)) { | 267 | if (WARN_ON(!local->scanning)) { |
269 | mutex_unlock(&local->scan_mtx); | 268 | mutex_unlock(&local->scan_mtx); |
270 | return; | 269 | return; |
271 | } | 270 | } |
@@ -275,16 +274,15 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
275 | return; | 274 | return; |
276 | } | 275 | } |
277 | 276 | ||
278 | if (local->hw_scanning) | 277 | if (test_bit(SCAN_HW_SCANNING, &local->scanning)) |
279 | ieee80211_restore_scan_ies(local); | 278 | ieee80211_restore_scan_ies(local); |
280 | 279 | ||
281 | if (local->scan_req != &local->int_scan_req) | 280 | if (local->scan_req != &local->int_scan_req) |
282 | cfg80211_scan_done(local->scan_req, aborted); | 281 | cfg80211_scan_done(local->scan_req, aborted); |
283 | local->scan_req = NULL; | 282 | local->scan_req = NULL; |
284 | 283 | ||
285 | was_hw_scan = local->hw_scanning; | 284 | was_hw_scan = test_bit(SCAN_HW_SCANNING, &local->scanning); |
286 | local->hw_scanning = false; | 285 | local->scanning = 0; |
287 | local->sw_scanning = false; | ||
288 | local->scan_channel = NULL; | 286 | local->scan_channel = NULL; |
289 | 287 | ||
290 | /* we only have to protect scan_req and hw/sw scan */ | 288 | /* we only have to protect scan_req and hw/sw scan */ |
@@ -366,17 +364,16 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) | |||
366 | ieee80211_bss_info_change_notify( | 364 | ieee80211_bss_info_change_notify( |
367 | sdata, BSS_CHANGED_BEACON_ENABLED); | 365 | sdata, BSS_CHANGED_BEACON_ENABLED); |
368 | 366 | ||
369 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 367 | /* |
370 | if (sdata->u.mgd.associated) { | 368 | * only handle non-STA interfaces here, STA interfaces |
371 | netif_tx_stop_all_queues(sdata->dev); | 369 | * are handled in the scan state machine |
372 | ieee80211_scan_ps_enable(sdata); | 370 | */ |
373 | } | 371 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
374 | } else | ||
375 | netif_tx_stop_all_queues(sdata->dev); | 372 | netif_tx_stop_all_queues(sdata->dev); |
376 | } | 373 | } |
377 | mutex_unlock(&local->iflist_mtx); | 374 | mutex_unlock(&local->iflist_mtx); |
378 | 375 | ||
379 | local->scan_state = SCAN_SET_CHANNEL; | 376 | local->next_scan_state = SCAN_DECISION; |
380 | local->scan_channel_idx = 0; | 377 | local->scan_channel_idx = 0; |
381 | 378 | ||
382 | spin_lock_bh(&local->filter_lock); | 379 | spin_lock_bh(&local->filter_lock); |
@@ -434,9 +431,9 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
434 | } | 431 | } |
435 | 432 | ||
436 | if (local->ops->hw_scan) | 433 | if (local->ops->hw_scan) |
437 | local->hw_scanning = true; | 434 | __set_bit(SCAN_HW_SCANNING, &local->scanning); |
438 | else | 435 | else |
439 | local->sw_scanning = true; | 436 | __set_bit(SCAN_SW_SCANNING, &local->scanning); |
440 | /* | 437 | /* |
441 | * Kicking off the scan need not be protected, | 438 | * Kicking off the scan need not be protected, |
442 | * only the scan variable stuff, since now | 439 | * only the scan variable stuff, since now |
@@ -459,11 +456,9 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
459 | mutex_lock(&local->scan_mtx); | 456 | mutex_lock(&local->scan_mtx); |
460 | 457 | ||
461 | if (rc) { | 458 | if (rc) { |
462 | if (local->ops->hw_scan) { | 459 | if (local->ops->hw_scan) |
463 | local->hw_scanning = false; | ||
464 | ieee80211_restore_scan_ies(local); | 460 | ieee80211_restore_scan_ies(local); |
465 | } else | 461 | local->scanning = 0; |
466 | local->sw_scanning = false; | ||
467 | 462 | ||
468 | ieee80211_recalc_idle(local); | 463 | ieee80211_recalc_idle(local); |
469 | 464 | ||
@@ -474,13 +469,195 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
474 | return rc; | 469 | return rc; |
475 | } | 470 | } |
476 | 471 | ||
472 | static int ieee80211_scan_state_decision(struct ieee80211_local *local, | ||
473 | unsigned long *next_delay) | ||
474 | { | ||
475 | bool associated = false; | ||
476 | struct ieee80211_sub_if_data *sdata; | ||
477 | |||
478 | /* if no more bands/channels left, complete scan and advance to the idle state */ | ||
479 | if (local->scan_channel_idx >= local->scan_req->n_channels) { | ||
480 | ieee80211_scan_completed(&local->hw, false); | ||
481 | return 1; | ||
482 | } | ||
483 | |||
484 | /* check if at least one STA interface is associated */ | ||
485 | mutex_lock(&local->iflist_mtx); | ||
486 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
487 | if (!netif_running(sdata->dev)) | ||
488 | continue; | ||
489 | |||
490 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
491 | if (sdata->u.mgd.associated) { | ||
492 | associated = true; | ||
493 | break; | ||
494 | } | ||
495 | } | ||
496 | } | ||
497 | mutex_unlock(&local->iflist_mtx); | ||
498 | |||
499 | if (local->scan_channel) { | ||
500 | /* | ||
501 | * we're currently scanning a different channel, let's | ||
502 | * switch back to the operating channel now if at least | ||
503 | * one interface is associated. Otherwise just scan the | ||
504 | * next channel | ||
505 | */ | ||
506 | if (associated) | ||
507 | local->next_scan_state = SCAN_ENTER_OPER_CHANNEL; | ||
508 | else | ||
509 | local->next_scan_state = SCAN_SET_CHANNEL; | ||
510 | } else { | ||
511 | /* | ||
512 | * we're on the operating channel currently, let's | ||
513 | * leave that channel now to scan another one | ||
514 | */ | ||
515 | local->next_scan_state = SCAN_LEAVE_OPER_CHANNEL; | ||
516 | } | ||
517 | |||
518 | *next_delay = 0; | ||
519 | return 0; | ||
520 | } | ||
521 | |||
522 | static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local, | ||
523 | unsigned long *next_delay) | ||
524 | { | ||
525 | struct ieee80211_sub_if_data *sdata; | ||
526 | |||
527 | /* | ||
528 | * notify the AP about us leaving the channel and stop all STA interfaces | ||
529 | */ | ||
530 | mutex_lock(&local->iflist_mtx); | ||
531 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
532 | if (!netif_running(sdata->dev)) | ||
533 | continue; | ||
534 | |||
535 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
536 | netif_tx_stop_all_queues(sdata->dev); | ||
537 | if (sdata->u.mgd.associated) | ||
538 | ieee80211_scan_ps_enable(sdata); | ||
539 | } | ||
540 | } | ||
541 | mutex_unlock(&local->iflist_mtx); | ||
542 | |||
543 | __set_bit(SCAN_OFF_CHANNEL, &local->scanning); | ||
544 | |||
545 | /* advance to the next channel to be scanned */ | ||
546 | *next_delay = HZ / 10; | ||
547 | local->next_scan_state = SCAN_SET_CHANNEL; | ||
548 | } | ||
549 | |||
550 | static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *local, | ||
551 | unsigned long *next_delay) | ||
552 | { | ||
553 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; | ||
554 | |||
555 | /* switch back to the operating channel */ | ||
556 | local->scan_channel = NULL; | ||
557 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | ||
558 | |||
559 | /* | ||
560 | * notify the AP about us being back and restart all STA interfaces | ||
561 | */ | ||
562 | mutex_lock(&local->iflist_mtx); | ||
563 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
564 | if (!netif_running(sdata->dev)) | ||
565 | continue; | ||
566 | |||
567 | /* Tell AP we're back */ | ||
568 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
569 | if (sdata->u.mgd.associated) | ||
570 | ieee80211_scan_ps_disable(sdata); | ||
571 | netif_tx_wake_all_queues(sdata->dev); | ||
572 | } | ||
573 | } | ||
574 | mutex_unlock(&local->iflist_mtx); | ||
575 | |||
576 | __clear_bit(SCAN_OFF_CHANNEL, &local->scanning); | ||
577 | |||
578 | *next_delay = HZ / 5; | ||
579 | local->next_scan_state = SCAN_DECISION; | ||
580 | } | ||
581 | |||
582 | static void ieee80211_scan_state_set_channel(struct ieee80211_local *local, | ||
583 | unsigned long *next_delay) | ||
584 | { | ||
585 | int skip; | ||
586 | struct ieee80211_channel *chan; | ||
587 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; | ||
588 | |||
589 | skip = 0; | ||
590 | chan = local->scan_req->channels[local->scan_channel_idx]; | ||
591 | |||
592 | if (chan->flags & IEEE80211_CHAN_DISABLED || | ||
593 | (sdata->vif.type == NL80211_IFTYPE_ADHOC && | ||
594 | chan->flags & IEEE80211_CHAN_NO_IBSS)) | ||
595 | skip = 1; | ||
596 | |||
597 | if (!skip) { | ||
598 | local->scan_channel = chan; | ||
599 | if (ieee80211_hw_config(local, | ||
600 | IEEE80211_CONF_CHANGE_CHANNEL)) | ||
601 | skip = 1; | ||
602 | } | ||
603 | |||
604 | /* advance state machine to next channel/band */ | ||
605 | local->scan_channel_idx++; | ||
606 | |||
607 | if (skip) { | ||
608 | /* if we skip this channel return to the decision state */ | ||
609 | local->next_scan_state = SCAN_DECISION; | ||
610 | return; | ||
611 | } | ||
612 | |||
613 | /* | ||
614 | * Probe delay is used to update the NAV, cf. 11.1.3.2.2 | ||
615 | * (which unfortunately doesn't say _why_ step a) is done, | ||
616 | * but it waits for the probe delay or until a frame is | ||
617 | * received - and the received frame would update the NAV). | ||
618 | * For now, we do not support waiting until a frame is | ||
619 | * received. | ||
620 | * | ||
621 | * In any case, it is not necessary for a passive scan. | ||
622 | */ | ||
623 | if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN || | ||
624 | !local->scan_req->n_ssids) { | ||
625 | *next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; | ||
626 | local->next_scan_state = SCAN_DECISION; | ||
627 | return; | ||
628 | } | ||
629 | |||
630 | /* active scan, send probes */ | ||
631 | *next_delay = IEEE80211_PROBE_DELAY; | ||
632 | local->next_scan_state = SCAN_SEND_PROBE; | ||
633 | } | ||
634 | |||
635 | static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, | ||
636 | unsigned long *next_delay) | ||
637 | { | ||
638 | int i; | ||
639 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; | ||
640 | |||
641 | for (i = 0; i < local->scan_req->n_ssids; i++) | ||
642 | ieee80211_send_probe_req( | ||
643 | sdata, NULL, | ||
644 | local->scan_req->ssids[i].ssid, | ||
645 | local->scan_req->ssids[i].ssid_len, | ||
646 | local->scan_req->ie, local->scan_req->ie_len); | ||
647 | |||
648 | /* | ||
649 | * After sending probe requests, wait for probe responses | ||
650 | * on the channel. | ||
651 | */ | ||
652 | *next_delay = IEEE80211_CHANNEL_TIME; | ||
653 | local->next_scan_state = SCAN_DECISION; | ||
654 | } | ||
655 | |||
477 | void ieee80211_scan_work(struct work_struct *work) | 656 | void ieee80211_scan_work(struct work_struct *work) |
478 | { | 657 | { |
479 | struct ieee80211_local *local = | 658 | struct ieee80211_local *local = |
480 | container_of(work, struct ieee80211_local, scan_work.work); | 659 | container_of(work, struct ieee80211_local, scan_work.work); |
481 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; | 660 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; |
482 | struct ieee80211_channel *chan; | ||
483 | int skip, i; | ||
484 | unsigned long next_delay = 0; | 661 | unsigned long next_delay = 0; |
485 | 662 | ||
486 | mutex_lock(&local->scan_mtx); | 663 | mutex_lock(&local->scan_mtx); |
@@ -489,7 +666,7 @@ void ieee80211_scan_work(struct work_struct *work) | |||
489 | return; | 666 | return; |
490 | } | 667 | } |
491 | 668 | ||
492 | if (local->scan_req && !(local->sw_scanning || local->hw_scanning)) { | 669 | if (local->scan_req && !local->scanning) { |
493 | struct cfg80211_scan_request *req = local->scan_req; | 670 | struct cfg80211_scan_request *req = local->scan_req; |
494 | int rc; | 671 | int rc; |
495 | 672 | ||
@@ -513,69 +690,30 @@ void ieee80211_scan_work(struct work_struct *work) | |||
513 | return; | 690 | return; |
514 | } | 691 | } |
515 | 692 | ||
516 | switch (local->scan_state) { | 693 | /* |
517 | case SCAN_SET_CHANNEL: | 694 | * as long as no delay is required advance immediately |
518 | /* if no more bands/channels left, complete scan */ | 695 | * without scheduling a new work |
519 | if (local->scan_channel_idx >= local->scan_req->n_channels) { | 696 | */ |
520 | ieee80211_scan_completed(&local->hw, false); | 697 | do { |
521 | return; | 698 | switch (local->next_scan_state) { |
522 | } | 699 | case SCAN_DECISION: |
523 | skip = 0; | 700 | if (ieee80211_scan_state_decision(local, &next_delay)) |
524 | chan = local->scan_req->channels[local->scan_channel_idx]; | 701 | return; |
525 | |||
526 | if (chan->flags & IEEE80211_CHAN_DISABLED || | ||
527 | (sdata->vif.type == NL80211_IFTYPE_ADHOC && | ||
528 | chan->flags & IEEE80211_CHAN_NO_IBSS)) | ||
529 | skip = 1; | ||
530 | |||
531 | if (!skip) { | ||
532 | local->scan_channel = chan; | ||
533 | if (ieee80211_hw_config(local, | ||
534 | IEEE80211_CONF_CHANGE_CHANNEL)) | ||
535 | skip = 1; | ||
536 | } | ||
537 | |||
538 | /* advance state machine to next channel/band */ | ||
539 | local->scan_channel_idx++; | ||
540 | |||
541 | if (skip) | ||
542 | break; | 702 | break; |
543 | 703 | case SCAN_SET_CHANNEL: | |
544 | /* | 704 | ieee80211_scan_state_set_channel(local, &next_delay); |
545 | * Probe delay is used to update the NAV, cf. 11.1.3.2.2 | 705 | break; |
546 | * (which unfortunately doesn't say _why_ step a) is done, | 706 | case SCAN_SEND_PROBE: |
547 | * but it waits for the probe delay or until a frame is | 707 | ieee80211_scan_state_send_probe(local, &next_delay); |
548 | * received - and the received frame would update the NAV). | 708 | break; |
549 | * For now, we do not support waiting until a frame is | 709 | case SCAN_LEAVE_OPER_CHANNEL: |
550 | * received. | 710 | ieee80211_scan_state_leave_oper_channel(local, &next_delay); |
551 | * | 711 | break; |
552 | * In any case, it is not necessary for a passive scan. | 712 | case SCAN_ENTER_OPER_CHANNEL: |
553 | */ | 713 | ieee80211_scan_state_enter_oper_channel(local, &next_delay); |
554 | if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN || | ||
555 | !local->scan_req->n_ssids) { | ||
556 | next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; | ||
557 | break; | 714 | break; |
558 | } | 715 | } |
559 | 716 | } while (next_delay == 0); | |
560 | next_delay = IEEE80211_PROBE_DELAY; | ||
561 | local->scan_state = SCAN_SEND_PROBE; | ||
562 | break; | ||
563 | case SCAN_SEND_PROBE: | ||
564 | for (i = 0; i < local->scan_req->n_ssids; i++) | ||
565 | ieee80211_send_probe_req( | ||
566 | sdata, NULL, | ||
567 | local->scan_req->ssids[i].ssid, | ||
568 | local->scan_req->ssids[i].ssid_len, | ||
569 | local->scan_req->ie, local->scan_req->ie_len); | ||
570 | |||
571 | /* | ||
572 | * After sending probe requests, wait for probe responses | ||
573 | * on the channel. | ||
574 | */ | ||
575 | next_delay = IEEE80211_CHANNEL_TIME; | ||
576 | local->scan_state = SCAN_SET_CHANNEL; | ||
577 | break; | ||
578 | } | ||
579 | 717 | ||
580 | queue_delayed_work(local->hw.workqueue, &local->scan_work, | 718 | queue_delayed_work(local->hw.workqueue, &local->scan_work, |
581 | next_delay); | 719 | next_delay); |
@@ -625,7 +763,7 @@ void ieee80211_scan_cancel(struct ieee80211_local *local) | |||
625 | * queued -- mostly at suspend under RTNL. | 763 | * queued -- mostly at suspend under RTNL. |
626 | */ | 764 | */ |
627 | mutex_lock(&local->scan_mtx); | 765 | mutex_lock(&local->scan_mtx); |
628 | swscan = local->sw_scanning; | 766 | swscan = test_bit(SCAN_SW_SCANNING, &local->scanning); |
629 | mutex_unlock(&local->scan_mtx); | 767 | mutex_unlock(&local->scan_mtx); |
630 | 768 | ||
631 | if (swscan) | 769 | if (swscan) |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 4ecf10a9bd00..ccc3adf962c7 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -30,7 +30,6 @@ | |||
30 | * @WLAN_STA_ASSOC_AP: We're associated to that station, it is an AP. | 30 | * @WLAN_STA_ASSOC_AP: We're associated to that station, it is an AP. |
31 | * @WLAN_STA_WME: Station is a QoS-STA. | 31 | * @WLAN_STA_WME: Station is a QoS-STA. |
32 | * @WLAN_STA_WDS: Station is one of our WDS peers. | 32 | * @WLAN_STA_WDS: Station is one of our WDS peers. |
33 | * @WLAN_STA_PSPOLL: Station has just PS-polled us. | ||
34 | * @WLAN_STA_CLEAR_PS_FILT: Clear PS filter in hardware (using the | 33 | * @WLAN_STA_CLEAR_PS_FILT: Clear PS filter in hardware (using the |
35 | * IEEE80211_TX_CTL_CLEAR_PS_FILT control flag) when the next | 34 | * IEEE80211_TX_CTL_CLEAR_PS_FILT control flag) when the next |
36 | * frame to this station is transmitted. | 35 | * frame to this station is transmitted. |
@@ -47,7 +46,6 @@ enum ieee80211_sta_info_flags { | |||
47 | WLAN_STA_ASSOC_AP = 1<<5, | 46 | WLAN_STA_ASSOC_AP = 1<<5, |
48 | WLAN_STA_WME = 1<<6, | 47 | WLAN_STA_WME = 1<<6, |
49 | WLAN_STA_WDS = 1<<7, | 48 | WLAN_STA_WDS = 1<<7, |
50 | WLAN_STA_PSPOLL = 1<<8, | ||
51 | WLAN_STA_CLEAR_PS_FILT = 1<<9, | 49 | WLAN_STA_CLEAR_PS_FILT = 1<<9, |
52 | WLAN_STA_MFP = 1<<10, | 50 | WLAN_STA_MFP = 1<<10, |
53 | WLAN_STA_SUSPEND = 1<<11 | 51 | WLAN_STA_SUSPEND = 1<<11 |
@@ -359,17 +357,6 @@ static inline void clear_sta_flags(struct sta_info *sta, const u32 flags) | |||
359 | spin_unlock_irqrestore(&sta->flaglock, irqfl); | 357 | spin_unlock_irqrestore(&sta->flaglock, irqfl); |
360 | } | 358 | } |
361 | 359 | ||
362 | static inline void set_and_clear_sta_flags(struct sta_info *sta, | ||
363 | const u32 set, const u32 clear) | ||
364 | { | ||
365 | unsigned long irqfl; | ||
366 | |||
367 | spin_lock_irqsave(&sta->flaglock, irqfl); | ||
368 | sta->flags |= set; | ||
369 | sta->flags &= ~clear; | ||
370 | spin_unlock_irqrestore(&sta->flaglock, irqfl); | ||
371 | } | ||
372 | |||
373 | static inline u32 test_sta_flags(struct sta_info *sta, const u32 flags) | 360 | static inline u32 test_sta_flags(struct sta_info *sta, const u32 flags) |
374 | { | 361 | { |
375 | u32 ret; | 362 | u32 ret; |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 2572509d5568..4e1b2ba122cd 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -192,7 +192,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) | |||
192 | if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) | 192 | if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) |
193 | return TX_CONTINUE; | 193 | return TX_CONTINUE; |
194 | 194 | ||
195 | if (unlikely(tx->local->sw_scanning) && | 195 | if (unlikely(test_bit(SCAN_OFF_CHANNEL, &tx->local->scanning)) && |
196 | !ieee80211_is_probe_req(hdr->frame_control) && | 196 | !ieee80211_is_probe_req(hdr->frame_control) && |
197 | !ieee80211_is_nullfunc(hdr->frame_control)) | 197 | !ieee80211_is_nullfunc(hdr->frame_control)) |
198 | /* | 198 | /* |
@@ -373,7 +373,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
373 | staflags = get_sta_flags(sta); | 373 | staflags = get_sta_flags(sta); |
374 | 374 | ||
375 | if (unlikely((staflags & WLAN_STA_PS) && | 375 | if (unlikely((staflags & WLAN_STA_PS) && |
376 | !(staflags & WLAN_STA_PSPOLL))) { | 376 | !(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE))) { |
377 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 377 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
378 | printk(KERN_DEBUG "STA %pM aid %d: PS buffer (entries " | 378 | printk(KERN_DEBUG "STA %pM aid %d: PS buffer (entries " |
379 | "before %d)\n", | 379 | "before %d)\n", |
@@ -400,6 +400,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
400 | sta_info_set_tim_bit(sta); | 400 | sta_info_set_tim_bit(sta); |
401 | 401 | ||
402 | info->control.jiffies = jiffies; | 402 | info->control.jiffies = jiffies; |
403 | info->control.vif = &tx->sdata->vif; | ||
403 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | 404 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; |
404 | skb_queue_tail(&sta->ps_tx_buf, tx->skb); | 405 | skb_queue_tail(&sta->ps_tx_buf, tx->skb); |
405 | return TX_QUEUED; | 406 | return TX_QUEUED; |
@@ -411,24 +412,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
411 | sta->sta.addr); | 412 | sta->sta.addr); |
412 | } | 413 | } |
413 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 414 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
414 | if (test_and_clear_sta_flags(sta, WLAN_STA_PSPOLL)) { | ||
415 | /* | ||
416 | * The sleeping station with pending data is now snoozing. | ||
417 | * It queried us for its buffered frames and will go back | ||
418 | * to deep sleep once it got everything. | ||
419 | * | ||
420 | * inform the driver, in case the hardware does powersave | ||
421 | * frame filtering and keeps a station blacklist on its own | ||
422 | * (e.g: p54), so that frames can be delivered unimpeded. | ||
423 | * | ||
424 | * Note: It should be safe to disable the filter now. | ||
425 | * As, it is really unlikely that we still have any pending | ||
426 | * frame for this station in the hw's buffers/fifos left, | ||
427 | * that is not rejected with a unsuccessful tx_status yet. | ||
428 | */ | ||
429 | 415 | ||
430 | info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; | ||
431 | } | ||
432 | return TX_CONTINUE; | 416 | return TX_CONTINUE; |
433 | } | 417 | } |
434 | 418 | ||
@@ -551,7 +535,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
551 | * Lets not bother rate control if we're associated and cannot | 535 | * Lets not bother rate control if we're associated and cannot |
552 | * talk to the sta. This should not happen. | 536 | * talk to the sta. This should not happen. |
553 | */ | 537 | */ |
554 | if (WARN((tx->local->sw_scanning) && | 538 | if (WARN(test_bit(SCAN_SW_SCANNING, &tx->local->scanning) && |
555 | (sta_flags & WLAN_STA_ASSOC) && | 539 | (sta_flags & WLAN_STA_ASSOC) && |
556 | !rate_usable_index_exists(sband, &tx->sta->sta), | 540 | !rate_usable_index_exists(sband, &tx->sta->sta), |
557 | "%s: Dropped data frame as no usable bitrate found while " | 541 | "%s: Dropped data frame as no usable bitrate found while " |
@@ -696,7 +680,7 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) | |||
696 | * number, if we have no matching interface then we | 680 | * number, if we have no matching interface then we |
697 | * neither assign one ourselves nor ask the driver to. | 681 | * neither assign one ourselves nor ask the driver to. |
698 | */ | 682 | */ |
699 | if (unlikely(!info->control.vif)) | 683 | if (unlikely(info->control.vif->type == NL80211_IFTYPE_MONITOR)) |
700 | return TX_CONTINUE; | 684 | return TX_CONTINUE; |
701 | 685 | ||
702 | if (unlikely(ieee80211_is_ctl(hdr->frame_control))) | 686 | if (unlikely(ieee80211_is_ctl(hdr->frame_control))) |
@@ -1092,6 +1076,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, | |||
1092 | } else if (*state != HT_AGG_STATE_IDLE) { | 1076 | } else if (*state != HT_AGG_STATE_IDLE) { |
1093 | /* in progress */ | 1077 | /* in progress */ |
1094 | queued = true; | 1078 | queued = true; |
1079 | info->control.vif = &sdata->vif; | ||
1095 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | 1080 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; |
1096 | __skb_queue_tail(&tid_tx->pending, skb); | 1081 | __skb_queue_tail(&tid_tx->pending, skb); |
1097 | } | 1082 | } |
@@ -1143,6 +1128,7 @@ static int __ieee80211_tx(struct ieee80211_local *local, | |||
1143 | { | 1128 | { |
1144 | struct sk_buff *skb = *skbp, *next; | 1129 | struct sk_buff *skb = *skbp, *next; |
1145 | struct ieee80211_tx_info *info; | 1130 | struct ieee80211_tx_info *info; |
1131 | struct ieee80211_sub_if_data *sdata; | ||
1146 | unsigned long flags; | 1132 | unsigned long flags; |
1147 | int ret, len; | 1133 | int ret, len; |
1148 | bool fragm = false; | 1134 | bool fragm = false; |
@@ -1167,13 +1153,32 @@ static int __ieee80211_tx(struct ieee80211_local *local, | |||
1167 | 1153 | ||
1168 | next = skb->next; | 1154 | next = skb->next; |
1169 | len = skb->len; | 1155 | len = skb->len; |
1156 | |||
1157 | sdata = vif_to_sdata(info->control.vif); | ||
1158 | |||
1159 | switch (sdata->vif.type) { | ||
1160 | case NL80211_IFTYPE_MONITOR: | ||
1161 | info->control.vif = NULL; | ||
1162 | break; | ||
1163 | case NL80211_IFTYPE_AP_VLAN: | ||
1164 | info->control.vif = &container_of(sdata->bss, | ||
1165 | struct ieee80211_sub_if_data, u.ap)->vif; | ||
1166 | break; | ||
1167 | default: | ||
1168 | /* keep */ | ||
1169 | break; | ||
1170 | } | ||
1171 | |||
1170 | ret = drv_tx(local, skb); | 1172 | ret = drv_tx(local, skb); |
1171 | if (WARN_ON(ret != NETDEV_TX_OK && skb->len != len)) { | 1173 | if (WARN_ON(ret != NETDEV_TX_OK && skb->len != len)) { |
1172 | dev_kfree_skb(skb); | 1174 | dev_kfree_skb(skb); |
1173 | ret = NETDEV_TX_OK; | 1175 | ret = NETDEV_TX_OK; |
1174 | } | 1176 | } |
1175 | if (ret != NETDEV_TX_OK) | 1177 | if (ret != NETDEV_TX_OK) { |
1178 | info->control.vif = &sdata->vif; | ||
1176 | return IEEE80211_TX_AGAIN; | 1179 | return IEEE80211_TX_AGAIN; |
1180 | } | ||
1181 | |||
1177 | *skbp = skb = next; | 1182 | *skbp = skb = next; |
1178 | ieee80211_led_tx(local, 1); | 1183 | ieee80211_led_tx(local, 1); |
1179 | fragm = true; | 1184 | fragm = true; |
@@ -1386,17 +1391,12 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, | |||
1386 | struct ieee80211_sub_if_data *tmp_sdata; | 1391 | struct ieee80211_sub_if_data *tmp_sdata; |
1387 | int headroom; | 1392 | int headroom; |
1388 | bool may_encrypt; | 1393 | bool may_encrypt; |
1389 | enum { | ||
1390 | NOT_MONITOR, | ||
1391 | FOUND_SDATA, | ||
1392 | UNKNOWN_ADDRESS, | ||
1393 | } monitor_iface = NOT_MONITOR; | ||
1394 | 1394 | ||
1395 | dev_hold(sdata->dev); | 1395 | dev_hold(sdata->dev); |
1396 | 1396 | ||
1397 | if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && | 1397 | if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && |
1398 | local->hw.conf.dynamic_ps_timeout > 0 && | 1398 | local->hw.conf.dynamic_ps_timeout > 0 && |
1399 | !local->sw_scanning && !local->hw_scanning && local->ps_sdata) { | 1399 | !(local->scanning) && local->ps_sdata) { |
1400 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { | 1400 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { |
1401 | ieee80211_stop_queues_by_reason(&local->hw, | 1401 | ieee80211_stop_queues_by_reason(&local->hw, |
1402 | IEEE80211_QUEUE_STOP_REASON_PS); | 1402 | IEEE80211_QUEUE_STOP_REASON_PS); |
@@ -1424,7 +1424,6 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, | |||
1424 | u16 len_rthdr; | 1424 | u16 len_rthdr; |
1425 | 1425 | ||
1426 | info->flags |= IEEE80211_TX_CTL_INJECTED; | 1426 | info->flags |= IEEE80211_TX_CTL_INJECTED; |
1427 | monitor_iface = UNKNOWN_ADDRESS; | ||
1428 | 1427 | ||
1429 | len_rthdr = ieee80211_get_radiotap_len(skb->data); | 1428 | len_rthdr = ieee80211_get_radiotap_len(skb->data); |
1430 | hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr); | 1429 | hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr); |
@@ -1454,7 +1453,6 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, | |||
1454 | dev_hold(tmp_sdata->dev); | 1453 | dev_hold(tmp_sdata->dev); |
1455 | dev_put(sdata->dev); | 1454 | dev_put(sdata->dev); |
1456 | sdata = tmp_sdata; | 1455 | sdata = tmp_sdata; |
1457 | monitor_iface = FOUND_SDATA; | ||
1458 | break; | 1456 | break; |
1459 | } | 1457 | } |
1460 | } | 1458 | } |
@@ -1476,13 +1474,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, | |||
1476 | return; | 1474 | return; |
1477 | } | 1475 | } |
1478 | 1476 | ||
1479 | tmp_sdata = sdata; | 1477 | info->control.vif = &sdata->vif; |
1480 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
1481 | tmp_sdata = container_of(sdata->bss, | ||
1482 | struct ieee80211_sub_if_data, | ||
1483 | u.ap); | ||
1484 | if (likely(monitor_iface != UNKNOWN_ADDRESS)) | ||
1485 | info->control.vif = &tmp_sdata->vif; | ||
1486 | 1478 | ||
1487 | ieee80211_select_queue(local, skb); | 1479 | ieee80211_select_queue(local, skb); |
1488 | ieee80211_tx(sdata, skb, false); | 1480 | ieee80211_tx(sdata, skb, false); |
@@ -1534,9 +1526,6 @@ int ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
1534 | if (unlikely(skb->len < len_rthdr)) | 1526 | if (unlikely(skb->len < len_rthdr)) |
1535 | goto fail; /* skb too short for claimed rt header extent */ | 1527 | goto fail; /* skb too short for claimed rt header extent */ |
1536 | 1528 | ||
1537 | /* needed because we set skb device to master */ | ||
1538 | skb->iif = dev->ifindex; | ||
1539 | |||
1540 | /* | 1529 | /* |
1541 | * fix up the pointers accounting for the radiotap | 1530 | * fix up the pointers accounting for the radiotap |
1542 | * header still being in there. We are being given | 1531 | * header still being in there. We are being given |
@@ -1810,8 +1799,6 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1810 | nh_pos += hdrlen; | 1799 | nh_pos += hdrlen; |
1811 | h_pos += hdrlen; | 1800 | h_pos += hdrlen; |
1812 | 1801 | ||
1813 | skb->iif = dev->ifindex; | ||
1814 | |||
1815 | dev->stats.tx_packets++; | 1802 | dev->stats.tx_packets++; |
1816 | dev->stats.tx_bytes += skb->len; | 1803 | dev->stats.tx_bytes += skb->len; |
1817 | 1804 | ||
@@ -1856,32 +1843,13 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local, | |||
1856 | struct ieee80211_sub_if_data *sdata; | 1843 | struct ieee80211_sub_if_data *sdata; |
1857 | struct sta_info *sta; | 1844 | struct sta_info *sta; |
1858 | struct ieee80211_hdr *hdr; | 1845 | struct ieee80211_hdr *hdr; |
1859 | struct net_device *dev; | ||
1860 | int ret; | 1846 | int ret; |
1861 | bool result = true; | 1847 | bool result = true; |
1862 | 1848 | ||
1863 | /* does interface still exist? */ | 1849 | sdata = vif_to_sdata(info->control.vif); |
1864 | dev = dev_get_by_index(&init_net, skb->iif); | ||
1865 | if (!dev) { | ||
1866 | dev_kfree_skb(skb); | ||
1867 | return true; | ||
1868 | } | ||
1869 | |||
1870 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1871 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
1872 | sdata = container_of(sdata->bss, | ||
1873 | struct ieee80211_sub_if_data, | ||
1874 | u.ap); | ||
1875 | |||
1876 | if (unlikely(info->control.vif && info->control.vif != &sdata->vif)) { | ||
1877 | dev_kfree_skb(skb); | ||
1878 | result = true; | ||
1879 | goto out; | ||
1880 | } | ||
1881 | 1850 | ||
1882 | if (info->flags & IEEE80211_TX_INTFL_NEED_TXPROCESSING) { | 1851 | if (info->flags & IEEE80211_TX_INTFL_NEED_TXPROCESSING) { |
1883 | /* do not use sdata, it may have been changed above */ | 1852 | ieee80211_tx(sdata, skb, true); |
1884 | ieee80211_tx(IEEE80211_DEV_TO_SUB_IF(dev), skb, true); | ||
1885 | } else { | 1853 | } else { |
1886 | hdr = (struct ieee80211_hdr *)skb->data; | 1854 | hdr = (struct ieee80211_hdr *)skb->data; |
1887 | sta = sta_info_get(local, hdr->addr1); | 1855 | sta = sta_info_get(local, hdr->addr1); |
@@ -1891,9 +1859,6 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local, | |||
1891 | result = false; | 1859 | result = false; |
1892 | } | 1860 | } |
1893 | 1861 | ||
1894 | out: | ||
1895 | dev_put(dev); | ||
1896 | |||
1897 | return result; | 1862 | return result; |
1898 | } | 1863 | } |
1899 | 1864 | ||
@@ -1921,10 +1886,21 @@ void ieee80211_tx_pending(unsigned long data) | |||
1921 | 1886 | ||
1922 | while (!skb_queue_empty(&local->pending[i])) { | 1887 | while (!skb_queue_empty(&local->pending[i])) { |
1923 | struct sk_buff *skb = __skb_dequeue(&local->pending[i]); | 1888 | struct sk_buff *skb = __skb_dequeue(&local->pending[i]); |
1889 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
1890 | struct ieee80211_sub_if_data *sdata; | ||
1891 | |||
1892 | if (WARN_ON(!info->control.vif)) { | ||
1893 | kfree_skb(skb); | ||
1894 | continue; | ||
1895 | } | ||
1896 | |||
1897 | sdata = vif_to_sdata(info->control.vif); | ||
1898 | dev_hold(sdata->dev); | ||
1924 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, | 1899 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, |
1925 | flags); | 1900 | flags); |
1926 | 1901 | ||
1927 | txok = ieee80211_tx_pending_skb(local, skb); | 1902 | txok = ieee80211_tx_pending_skb(local, skb); |
1903 | dev_put(sdata->dev); | ||
1928 | if (!txok) | 1904 | if (!txok) |
1929 | __skb_queue_head(&local->pending[i], skb); | 1905 | __skb_queue_head(&local->pending[i], skb); |
1930 | spin_lock_irqsave(&local->queue_stop_reason_lock, | 1906 | spin_lock_irqsave(&local->queue_stop_reason_lock, |
@@ -2234,7 +2210,6 @@ void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | |||
2234 | skb_set_network_header(skb, 0); | 2210 | skb_set_network_header(skb, 0); |
2235 | skb_set_transport_header(skb, 0); | 2211 | skb_set_transport_header(skb, 0); |
2236 | 2212 | ||
2237 | skb->iif = sdata->dev->ifindex; | ||
2238 | if (!encrypt) | 2213 | if (!encrypt) |
2239 | info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 2214 | info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
2240 | 2215 | ||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 7fc55846d601..8502936e5314 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -336,6 +336,12 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local, | |||
336 | struct ieee80211_hw *hw = &local->hw; | 336 | struct ieee80211_hw *hw = &local->hw; |
337 | unsigned long flags; | 337 | unsigned long flags; |
338 | int queue = skb_get_queue_mapping(skb); | 338 | int queue = skb_get_queue_mapping(skb); |
339 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
340 | |||
341 | if (WARN_ON(!info->control.vif)) { | ||
342 | kfree(skb); | ||
343 | return; | ||
344 | } | ||
339 | 345 | ||
340 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | 346 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
341 | __ieee80211_stop_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD); | 347 | __ieee80211_stop_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD); |
@@ -358,6 +364,13 @@ int ieee80211_add_pending_skbs(struct ieee80211_local *local, | |||
358 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD); | 364 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD); |
359 | 365 | ||
360 | while ((skb = skb_dequeue(skbs))) { | 366 | while ((skb = skb_dequeue(skbs))) { |
367 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
368 | |||
369 | if (WARN_ON(!info->control.vif)) { | ||
370 | kfree(skb); | ||
371 | continue; | ||
372 | } | ||
373 | |||
361 | ret++; | 374 | ret++; |
362 | queue = skb_get_queue_mapping(skb); | 375 | queue = skb_get_queue_mapping(skb); |
363 | __skb_queue_tail(&local->pending[queue], skb); | 376 | __skb_queue_tail(&local->pending[queue], skb); |
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c deleted file mode 100644 index 5acb8140ee58..000000000000 --- a/net/mac80211/wext.c +++ /dev/null | |||
@@ -1,235 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright 2002-2005, Instant802 Networks, Inc. | ||
3 | * Copyright 2005-2006, Devicescape Software, Inc. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | */ | ||
9 | |||
10 | #include <linux/module.h> | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/netdevice.h> | ||
13 | #include <linux/types.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/skbuff.h> | ||
16 | #include <linux/etherdevice.h> | ||
17 | #include <linux/if_arp.h> | ||
18 | #include <linux/wireless.h> | ||
19 | #include <net/iw_handler.h> | ||
20 | #include <asm/uaccess.h> | ||
21 | |||
22 | #include <net/mac80211.h> | ||
23 | #include "ieee80211_i.h" | ||
24 | #include "led.h" | ||
25 | #include "rate.h" | ||
26 | #include "wpa.h" | ||
27 | #include "aes_ccm.h" | ||
28 | |||
29 | |||
30 | static int ieee80211_ioctl_siwfreq(struct net_device *dev, | ||
31 | struct iw_request_info *info, | ||
32 | struct iw_freq *freq, char *extra) | ||
33 | { | ||
34 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
35 | struct ieee80211_local *local = sdata->local; | ||
36 | struct ieee80211_channel *chan; | ||
37 | |||
38 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | ||
39 | return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra); | ||
40 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) | ||
41 | return cfg80211_mgd_wext_siwfreq(dev, info, freq, extra); | ||
42 | |||
43 | /* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */ | ||
44 | if (freq->e == 0) { | ||
45 | if (freq->m < 0) | ||
46 | return -EINVAL; | ||
47 | else | ||
48 | chan = ieee80211_get_channel(local->hw.wiphy, | ||
49 | ieee80211_channel_to_frequency(freq->m)); | ||
50 | } else { | ||
51 | int i, div = 1000000; | ||
52 | for (i = 0; i < freq->e; i++) | ||
53 | div /= 10; | ||
54 | if (div <= 0) | ||
55 | return -EINVAL; | ||
56 | chan = ieee80211_get_channel(local->hw.wiphy, freq->m / div); | ||
57 | } | ||
58 | |||
59 | if (!chan) | ||
60 | return -EINVAL; | ||
61 | |||
62 | if (chan->flags & IEEE80211_CHAN_DISABLED) | ||
63 | return -EINVAL; | ||
64 | |||
65 | /* | ||
66 | * no change except maybe auto -> fixed, ignore the HT | ||
67 | * setting so you can fix a channel you're on already | ||
68 | */ | ||
69 | if (local->oper_channel == chan) | ||
70 | return 0; | ||
71 | |||
72 | local->oper_channel = chan; | ||
73 | local->oper_channel_type = NL80211_CHAN_NO_HT; | ||
74 | ieee80211_hw_config(local, 0); | ||
75 | |||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | |||
80 | static int ieee80211_ioctl_giwfreq(struct net_device *dev, | ||
81 | struct iw_request_info *info, | ||
82 | struct iw_freq *freq, char *extra) | ||
83 | { | ||
84 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
85 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
86 | |||
87 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | ||
88 | return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra); | ||
89 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) | ||
90 | return cfg80211_mgd_wext_giwfreq(dev, info, freq, extra); | ||
91 | |||
92 | freq->m = local->oper_channel->center_freq; | ||
93 | freq->e = 6; | ||
94 | |||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | |||
99 | static int ieee80211_ioctl_siwessid(struct net_device *dev, | ||
100 | struct iw_request_info *info, | ||
101 | struct iw_point *data, char *ssid) | ||
102 | { | ||
103 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
104 | |||
105 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | ||
106 | return cfg80211_ibss_wext_siwessid(dev, info, data, ssid); | ||
107 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) | ||
108 | return cfg80211_mgd_wext_siwessid(dev, info, data, ssid); | ||
109 | |||
110 | return -EOPNOTSUPP; | ||
111 | } | ||
112 | |||
113 | |||
114 | static int ieee80211_ioctl_giwessid(struct net_device *dev, | ||
115 | struct iw_request_info *info, | ||
116 | struct iw_point *data, char *ssid) | ||
117 | { | ||
118 | struct ieee80211_sub_if_data *sdata; | ||
119 | |||
120 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
121 | |||
122 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | ||
123 | return cfg80211_ibss_wext_giwessid(dev, info, data, ssid); | ||
124 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) | ||
125 | return cfg80211_mgd_wext_giwessid(dev, info, data, ssid); | ||
126 | |||
127 | return -EOPNOTSUPP; | ||
128 | } | ||
129 | |||
130 | |||
131 | static int ieee80211_ioctl_siwap(struct net_device *dev, | ||
132 | struct iw_request_info *info, | ||
133 | struct sockaddr *ap_addr, char *extra) | ||
134 | { | ||
135 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
136 | |||
137 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | ||
138 | return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra); | ||
139 | |||
140 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | ||
141 | return cfg80211_mgd_wext_siwap(dev, info, ap_addr, extra); | ||
142 | |||
143 | if (sdata->vif.type == NL80211_IFTYPE_WDS) | ||
144 | return cfg80211_wds_wext_siwap(dev, info, ap_addr, extra); | ||
145 | return -EOPNOTSUPP; | ||
146 | } | ||
147 | |||
148 | |||
149 | static int ieee80211_ioctl_giwap(struct net_device *dev, | ||
150 | struct iw_request_info *info, | ||
151 | struct sockaddr *ap_addr, char *extra) | ||
152 | { | ||
153 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
154 | |||
155 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | ||
156 | return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra); | ||
157 | |||
158 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | ||
159 | return cfg80211_mgd_wext_giwap(dev, info, ap_addr, extra); | ||
160 | |||
161 | if (sdata->vif.type == NL80211_IFTYPE_WDS) | ||
162 | return cfg80211_wds_wext_giwap(dev, info, ap_addr, extra); | ||
163 | |||
164 | return -EOPNOTSUPP; | ||
165 | } | ||
166 | |||
167 | |||
168 | /* Structures to export the Wireless Handlers */ | ||
169 | |||
170 | static const iw_handler ieee80211_handler[] = | ||
171 | { | ||
172 | (iw_handler) NULL, /* SIOCSIWCOMMIT */ | ||
173 | (iw_handler) cfg80211_wext_giwname, /* SIOCGIWNAME */ | ||
174 | (iw_handler) NULL, /* SIOCSIWNWID */ | ||
175 | (iw_handler) NULL, /* SIOCGIWNWID */ | ||
176 | (iw_handler) ieee80211_ioctl_siwfreq, /* SIOCSIWFREQ */ | ||
177 | (iw_handler) ieee80211_ioctl_giwfreq, /* SIOCGIWFREQ */ | ||
178 | (iw_handler) cfg80211_wext_siwmode, /* SIOCSIWMODE */ | ||
179 | (iw_handler) cfg80211_wext_giwmode, /* SIOCGIWMODE */ | ||
180 | (iw_handler) NULL, /* SIOCSIWSENS */ | ||
181 | (iw_handler) NULL, /* SIOCGIWSENS */ | ||
182 | (iw_handler) NULL /* not used */, /* SIOCSIWRANGE */ | ||
183 | (iw_handler) cfg80211_wext_giwrange, /* SIOCGIWRANGE */ | ||
184 | (iw_handler) NULL /* not used */, /* SIOCSIWPRIV */ | ||
185 | (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */ | ||
186 | (iw_handler) NULL /* not used */, /* SIOCSIWSTATS */ | ||
187 | (iw_handler) NULL /* kernel code */, /* SIOCGIWSTATS */ | ||
188 | (iw_handler) NULL, /* SIOCSIWSPY */ | ||
189 | (iw_handler) NULL, /* SIOCGIWSPY */ | ||
190 | (iw_handler) NULL, /* SIOCSIWTHRSPY */ | ||
191 | (iw_handler) NULL, /* SIOCGIWTHRSPY */ | ||
192 | (iw_handler) ieee80211_ioctl_siwap, /* SIOCSIWAP */ | ||
193 | (iw_handler) ieee80211_ioctl_giwap, /* SIOCGIWAP */ | ||
194 | (iw_handler) cfg80211_wext_siwmlme, /* SIOCSIWMLME */ | ||
195 | (iw_handler) NULL, /* SIOCGIWAPLIST */ | ||
196 | (iw_handler) cfg80211_wext_siwscan, /* SIOCSIWSCAN */ | ||
197 | (iw_handler) cfg80211_wext_giwscan, /* SIOCGIWSCAN */ | ||
198 | (iw_handler) ieee80211_ioctl_siwessid, /* SIOCSIWESSID */ | ||
199 | (iw_handler) ieee80211_ioctl_giwessid, /* SIOCGIWESSID */ | ||
200 | (iw_handler) NULL, /* SIOCSIWNICKN */ | ||
201 | (iw_handler) NULL, /* SIOCGIWNICKN */ | ||
202 | (iw_handler) NULL, /* -- hole -- */ | ||
203 | (iw_handler) NULL, /* -- hole -- */ | ||
204 | (iw_handler) cfg80211_wext_siwrate, /* SIOCSIWRATE */ | ||
205 | (iw_handler) cfg80211_wext_giwrate, /* SIOCGIWRATE */ | ||
206 | (iw_handler) cfg80211_wext_siwrts, /* SIOCSIWRTS */ | ||
207 | (iw_handler) cfg80211_wext_giwrts, /* SIOCGIWRTS */ | ||
208 | (iw_handler) cfg80211_wext_siwfrag, /* SIOCSIWFRAG */ | ||
209 | (iw_handler) cfg80211_wext_giwfrag, /* SIOCGIWFRAG */ | ||
210 | (iw_handler) cfg80211_wext_siwtxpower, /* SIOCSIWTXPOW */ | ||
211 | (iw_handler) cfg80211_wext_giwtxpower, /* SIOCGIWTXPOW */ | ||
212 | (iw_handler) cfg80211_wext_siwretry, /* SIOCSIWRETRY */ | ||
213 | (iw_handler) cfg80211_wext_giwretry, /* SIOCGIWRETRY */ | ||
214 | (iw_handler) cfg80211_wext_siwencode, /* SIOCSIWENCODE */ | ||
215 | (iw_handler) cfg80211_wext_giwencode, /* SIOCGIWENCODE */ | ||
216 | (iw_handler) cfg80211_wext_siwpower, /* SIOCSIWPOWER */ | ||
217 | (iw_handler) cfg80211_wext_giwpower, /* SIOCGIWPOWER */ | ||
218 | (iw_handler) NULL, /* -- hole -- */ | ||
219 | (iw_handler) NULL, /* -- hole -- */ | ||
220 | (iw_handler) cfg80211_wext_siwgenie, /* SIOCSIWGENIE */ | ||
221 | (iw_handler) NULL, /* SIOCGIWGENIE */ | ||
222 | (iw_handler) cfg80211_wext_siwauth, /* SIOCSIWAUTH */ | ||
223 | (iw_handler) cfg80211_wext_giwauth, /* SIOCGIWAUTH */ | ||
224 | (iw_handler) cfg80211_wext_siwencodeext, /* SIOCSIWENCODEEXT */ | ||
225 | (iw_handler) NULL, /* SIOCGIWENCODEEXT */ | ||
226 | (iw_handler) NULL, /* SIOCSIWPMKSA */ | ||
227 | (iw_handler) NULL, /* -- hole -- */ | ||
228 | }; | ||
229 | |||
230 | const struct iw_handler_def ieee80211_iw_handler_def = | ||
231 | { | ||
232 | .num_standard = ARRAY_SIZE(ieee80211_handler), | ||
233 | .standard = (iw_handler *) ieee80211_handler, | ||
234 | .get_wireless_stats = cfg80211_wireless_stats, | ||
235 | }; | ||
diff --git a/net/wireless/core.c b/net/wireless/core.c index 6891cd0e38d5..f9fee65dc06a 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include "core.h" | 19 | #include "core.h" |
20 | #include "sysfs.h" | 20 | #include "sysfs.h" |
21 | #include "debugfs.h" | 21 | #include "debugfs.h" |
22 | #include "wext-compat.h" | ||
22 | 23 | ||
23 | /* name for sysfs, %d is appended */ | 24 | /* name for sysfs, %d is appended */ |
24 | #define PHY_NAME "phy" | 25 | #define PHY_NAME "phy" |
@@ -106,7 +107,7 @@ __cfg80211_rdev_from_info(struct genl_info *info) | |||
106 | 107 | ||
107 | if (info->attrs[NL80211_ATTR_IFINDEX]) { | 108 | if (info->attrs[NL80211_ATTR_IFINDEX]) { |
108 | ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]); | 109 | ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]); |
109 | dev = dev_get_by_index(&init_net, ifindex); | 110 | dev = dev_get_by_index(genl_info_net(info), ifindex); |
110 | if (dev) { | 111 | if (dev) { |
111 | if (dev->ieee80211_ptr) | 112 | if (dev->ieee80211_ptr) |
112 | byifidx = | 113 | byifidx = |
@@ -151,13 +152,13 @@ cfg80211_get_dev_from_info(struct genl_info *info) | |||
151 | } | 152 | } |
152 | 153 | ||
153 | struct cfg80211_registered_device * | 154 | struct cfg80211_registered_device * |
154 | cfg80211_get_dev_from_ifindex(int ifindex) | 155 | cfg80211_get_dev_from_ifindex(struct net *net, int ifindex) |
155 | { | 156 | { |
156 | struct cfg80211_registered_device *rdev = ERR_PTR(-ENODEV); | 157 | struct cfg80211_registered_device *rdev = ERR_PTR(-ENODEV); |
157 | struct net_device *dev; | 158 | struct net_device *dev; |
158 | 159 | ||
159 | mutex_lock(&cfg80211_mutex); | 160 | mutex_lock(&cfg80211_mutex); |
160 | dev = dev_get_by_index(&init_net, ifindex); | 161 | dev = dev_get_by_index(net, ifindex); |
161 | if (!dev) | 162 | if (!dev) |
162 | goto out; | 163 | goto out; |
163 | if (dev->ieee80211_ptr) { | 164 | if (dev->ieee80211_ptr) { |
@@ -222,6 +223,42 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, | |||
222 | return 0; | 223 | return 0; |
223 | } | 224 | } |
224 | 225 | ||
226 | int cfg80211_switch_netns(struct cfg80211_registered_device *rdev, | ||
227 | struct net *net) | ||
228 | { | ||
229 | struct wireless_dev *wdev; | ||
230 | int err = 0; | ||
231 | |||
232 | if (!rdev->wiphy.netnsok) | ||
233 | return -EOPNOTSUPP; | ||
234 | |||
235 | list_for_each_entry(wdev, &rdev->netdev_list, list) { | ||
236 | wdev->netdev->features &= ~NETIF_F_NETNS_LOCAL; | ||
237 | err = dev_change_net_namespace(wdev->netdev, net, "wlan%d"); | ||
238 | if (err) | ||
239 | break; | ||
240 | wdev->netdev->features |= NETIF_F_NETNS_LOCAL; | ||
241 | } | ||
242 | |||
243 | if (err) { | ||
244 | /* failed -- clean up to old netns */ | ||
245 | net = wiphy_net(&rdev->wiphy); | ||
246 | |||
247 | list_for_each_entry_continue_reverse(wdev, &rdev->netdev_list, | ||
248 | list) { | ||
249 | wdev->netdev->features &= ~NETIF_F_NETNS_LOCAL; | ||
250 | err = dev_change_net_namespace(wdev->netdev, net, | ||
251 | "wlan%d"); | ||
252 | WARN_ON(err); | ||
253 | wdev->netdev->features |= NETIF_F_NETNS_LOCAL; | ||
254 | } | ||
255 | } | ||
256 | |||
257 | wiphy_net_set(&rdev->wiphy, net); | ||
258 | |||
259 | return err; | ||
260 | } | ||
261 | |||
225 | static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data) | 262 | static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data) |
226 | { | 263 | { |
227 | struct cfg80211_registered_device *rdev = data; | 264 | struct cfg80211_registered_device *rdev = data; |
@@ -375,6 +412,8 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) | |||
375 | rdev->wiphy.dev.class = &ieee80211_class; | 412 | rdev->wiphy.dev.class = &ieee80211_class; |
376 | rdev->wiphy.dev.platform_data = rdev; | 413 | rdev->wiphy.dev.platform_data = rdev; |
377 | 414 | ||
415 | wiphy_net_set(&rdev->wiphy, &init_net); | ||
416 | |||
378 | rdev->rfkill_ops.set_block = cfg80211_rfkill_set_block; | 417 | rdev->rfkill_ops.set_block = cfg80211_rfkill_set_block; |
379 | rdev->rfkill = rfkill_alloc(dev_name(&rdev->wiphy.dev), | 418 | rdev->rfkill = rfkill_alloc(dev_name(&rdev->wiphy.dev), |
380 | &rdev->wiphy.dev, RFKILL_TYPE_WLAN, | 419 | &rdev->wiphy.dev, RFKILL_TYPE_WLAN, |
@@ -615,6 +654,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
615 | spin_lock_init(&wdev->event_lock); | 654 | spin_lock_init(&wdev->event_lock); |
616 | mutex_lock(&rdev->devlist_mtx); | 655 | mutex_lock(&rdev->devlist_mtx); |
617 | list_add(&wdev->list, &rdev->netdev_list); | 656 | list_add(&wdev->list, &rdev->netdev_list); |
657 | /* can only change netns with wiphy */ | ||
658 | dev->features |= NETIF_F_NETNS_LOCAL; | ||
659 | |||
618 | if (sysfs_create_link(&dev->dev.kobj, &rdev->wiphy.dev.kobj, | 660 | if (sysfs_create_link(&dev->dev.kobj, &rdev->wiphy.dev.kobj, |
619 | "phy80211")) { | 661 | "phy80211")) { |
620 | printk(KERN_ERR "wireless: failed to add phy80211 " | 662 | printk(KERN_ERR "wireless: failed to add phy80211 " |
@@ -624,6 +666,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
624 | wdev->sme_state = CFG80211_SME_IDLE; | 666 | wdev->sme_state = CFG80211_SME_IDLE; |
625 | mutex_unlock(&rdev->devlist_mtx); | 667 | mutex_unlock(&rdev->devlist_mtx); |
626 | #ifdef CONFIG_WIRELESS_EXT | 668 | #ifdef CONFIG_WIRELESS_EXT |
669 | if (!dev->wireless_handlers) | ||
670 | dev->wireless_handlers = &cfg80211_wext_handler; | ||
627 | wdev->wext.default_key = -1; | 671 | wdev->wext.default_key = -1; |
628 | wdev->wext.default_mgmt_key = -1; | 672 | wdev->wext.default_mgmt_key = -1; |
629 | wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; | 673 | wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; |
@@ -705,10 +749,32 @@ static struct notifier_block cfg80211_netdev_notifier = { | |||
705 | .notifier_call = cfg80211_netdev_notifier_call, | 749 | .notifier_call = cfg80211_netdev_notifier_call, |
706 | }; | 750 | }; |
707 | 751 | ||
708 | static int cfg80211_init(void) | 752 | static void __net_exit cfg80211_pernet_exit(struct net *net) |
753 | { | ||
754 | struct cfg80211_registered_device *rdev; | ||
755 | |||
756 | rtnl_lock(); | ||
757 | mutex_lock(&cfg80211_mutex); | ||
758 | list_for_each_entry(rdev, &cfg80211_rdev_list, list) { | ||
759 | if (net_eq(wiphy_net(&rdev->wiphy), net)) | ||
760 | WARN_ON(cfg80211_switch_netns(rdev, &init_net)); | ||
761 | } | ||
762 | mutex_unlock(&cfg80211_mutex); | ||
763 | rtnl_unlock(); | ||
764 | } | ||
765 | |||
766 | static struct pernet_operations cfg80211_pernet_ops = { | ||
767 | .exit = cfg80211_pernet_exit, | ||
768 | }; | ||
769 | |||
770 | static int __init cfg80211_init(void) | ||
709 | { | 771 | { |
710 | int err; | 772 | int err; |
711 | 773 | ||
774 | err = register_pernet_device(&cfg80211_pernet_ops); | ||
775 | if (err) | ||
776 | goto out_fail_pernet; | ||
777 | |||
712 | err = wiphy_sysfs_init(); | 778 | err = wiphy_sysfs_init(); |
713 | if (err) | 779 | if (err) |
714 | goto out_fail_sysfs; | 780 | goto out_fail_sysfs; |
@@ -736,9 +802,10 @@ out_fail_nl80211: | |||
736 | out_fail_notifier: | 802 | out_fail_notifier: |
737 | wiphy_sysfs_exit(); | 803 | wiphy_sysfs_exit(); |
738 | out_fail_sysfs: | 804 | out_fail_sysfs: |
805 | unregister_pernet_device(&cfg80211_pernet_ops); | ||
806 | out_fail_pernet: | ||
739 | return err; | 807 | return err; |
740 | } | 808 | } |
741 | |||
742 | subsys_initcall(cfg80211_init); | 809 | subsys_initcall(cfg80211_init); |
743 | 810 | ||
744 | static void cfg80211_exit(void) | 811 | static void cfg80211_exit(void) |
@@ -748,5 +815,6 @@ static void cfg80211_exit(void) | |||
748 | unregister_netdevice_notifier(&cfg80211_netdev_notifier); | 815 | unregister_netdevice_notifier(&cfg80211_netdev_notifier); |
749 | wiphy_sysfs_exit(); | 816 | wiphy_sysfs_exit(); |
750 | regulatory_exit(); | 817 | regulatory_exit(); |
818 | unregister_pernet_device(&cfg80211_pernet_ops); | ||
751 | } | 819 | } |
752 | module_exit(cfg80211_exit); | 820 | module_exit(cfg80211_exit); |
diff --git a/net/wireless/core.h b/net/wireless/core.h index 2ec8ddbe57de..6d903c1d721d 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -66,6 +66,9 @@ struct cfg80211_registered_device { | |||
66 | struct work_struct conn_work; | 66 | struct work_struct conn_work; |
67 | struct work_struct event_work; | 67 | struct work_struct event_work; |
68 | 68 | ||
69 | /* current channel */ | ||
70 | struct ieee80211_channel *channel; | ||
71 | |||
69 | #ifdef CONFIG_CFG80211_DEBUGFS | 72 | #ifdef CONFIG_CFG80211_DEBUGFS |
70 | /* Debugfs entries */ | 73 | /* Debugfs entries */ |
71 | struct wiphy_debugfsdentries { | 74 | struct wiphy_debugfsdentries { |
@@ -170,7 +173,10 @@ struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx); | |||
170 | 173 | ||
171 | /* identical to cfg80211_get_dev_from_info but only operate on ifindex */ | 174 | /* identical to cfg80211_get_dev_from_info but only operate on ifindex */ |
172 | extern struct cfg80211_registered_device * | 175 | extern struct cfg80211_registered_device * |
173 | cfg80211_get_dev_from_ifindex(int ifindex); | 176 | cfg80211_get_dev_from_ifindex(struct net *net, int ifindex); |
177 | |||
178 | int cfg80211_switch_netns(struct cfg80211_registered_device *rdev, | ||
179 | struct net *net); | ||
174 | 180 | ||
175 | static inline void cfg80211_lock_rdev(struct cfg80211_registered_device *rdev) | 181 | static inline void cfg80211_lock_rdev(struct cfg80211_registered_device *rdev) |
176 | { | 182 | { |
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index 8b65e212ae49..4d7a084b35e2 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <linux/etherdevice.h> | 7 | #include <linux/etherdevice.h> |
8 | #include <linux/if_arp.h> | 8 | #include <linux/if_arp.h> |
9 | #include <net/cfg80211.h> | 9 | #include <net/cfg80211.h> |
10 | #include "wext-compat.h" | ||
10 | #include "nl80211.h" | 11 | #include "nl80211.h" |
11 | 12 | ||
12 | 13 | ||
@@ -312,8 +313,6 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev, | |||
312 | 313 | ||
313 | return err; | 314 | return err; |
314 | } | 315 | } |
315 | /* temporary symbol - mark GPL - in the future the handler won't be */ | ||
316 | EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwfreq); | ||
317 | 316 | ||
318 | int cfg80211_ibss_wext_giwfreq(struct net_device *dev, | 317 | int cfg80211_ibss_wext_giwfreq(struct net_device *dev, |
319 | struct iw_request_info *info, | 318 | struct iw_request_info *info, |
@@ -342,8 +341,6 @@ int cfg80211_ibss_wext_giwfreq(struct net_device *dev, | |||
342 | /* no channel if not joining */ | 341 | /* no channel if not joining */ |
343 | return -EINVAL; | 342 | return -EINVAL; |
344 | } | 343 | } |
345 | /* temporary symbol - mark GPL - in the future the handler won't be */ | ||
346 | EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_giwfreq); | ||
347 | 344 | ||
348 | int cfg80211_ibss_wext_siwessid(struct net_device *dev, | 345 | int cfg80211_ibss_wext_siwessid(struct net_device *dev, |
349 | struct iw_request_info *info, | 346 | struct iw_request_info *info, |
@@ -384,8 +381,6 @@ int cfg80211_ibss_wext_siwessid(struct net_device *dev, | |||
384 | 381 | ||
385 | return err; | 382 | return err; |
386 | } | 383 | } |
387 | /* temporary symbol - mark GPL - in the future the handler won't be */ | ||
388 | EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwessid); | ||
389 | 384 | ||
390 | int cfg80211_ibss_wext_giwessid(struct net_device *dev, | 385 | int cfg80211_ibss_wext_giwessid(struct net_device *dev, |
391 | struct iw_request_info *info, | 386 | struct iw_request_info *info, |
@@ -413,8 +408,6 @@ int cfg80211_ibss_wext_giwessid(struct net_device *dev, | |||
413 | 408 | ||
414 | return 0; | 409 | return 0; |
415 | } | 410 | } |
416 | /* temporary symbol - mark GPL - in the future the handler won't be */ | ||
417 | EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_giwessid); | ||
418 | 411 | ||
419 | int cfg80211_ibss_wext_siwap(struct net_device *dev, | 412 | int cfg80211_ibss_wext_siwap(struct net_device *dev, |
420 | struct iw_request_info *info, | 413 | struct iw_request_info *info, |
@@ -469,8 +462,6 @@ int cfg80211_ibss_wext_siwap(struct net_device *dev, | |||
469 | 462 | ||
470 | return err; | 463 | return err; |
471 | } | 464 | } |
472 | /* temporary symbol - mark GPL - in the future the handler won't be */ | ||
473 | EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwap); | ||
474 | 465 | ||
475 | int cfg80211_ibss_wext_giwap(struct net_device *dev, | 466 | int cfg80211_ibss_wext_giwap(struct net_device *dev, |
476 | struct iw_request_info *info, | 467 | struct iw_request_info *info, |
@@ -496,6 +487,4 @@ int cfg80211_ibss_wext_giwap(struct net_device *dev, | |||
496 | 487 | ||
497 | return 0; | 488 | return 0; |
498 | } | 489 | } |
499 | /* temporary symbol - mark GPL - in the future the handler won't be */ | ||
500 | EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_giwap); | ||
501 | #endif | 490 | #endif |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 5b9b22120824..097a87d7bae1 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -8,7 +8,9 @@ | |||
8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
9 | #include <linux/netdevice.h> | 9 | #include <linux/netdevice.h> |
10 | #include <linux/nl80211.h> | 10 | #include <linux/nl80211.h> |
11 | #include <linux/wireless.h> | ||
11 | #include <net/cfg80211.h> | 12 | #include <net/cfg80211.h> |
13 | #include <net/iw_handler.h> | ||
12 | #include "core.h" | 14 | #include "core.h" |
13 | #include "nl80211.h" | 15 | #include "nl80211.h" |
14 | 16 | ||
@@ -545,6 +547,12 @@ static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, | |||
545 | 547 | ||
546 | ASSERT_WDEV_LOCK(wdev); | 548 | ASSERT_WDEV_LOCK(wdev); |
547 | 549 | ||
550 | if (wdev->sme_state != CFG80211_SME_CONNECTED) | ||
551 | return -ENOTCONN; | ||
552 | |||
553 | if (WARN_ON(!wdev->current_bss)) | ||
554 | return -ENOTCONN; | ||
555 | |||
548 | memset(&req, 0, sizeof(req)); | 556 | memset(&req, 0, sizeof(req)); |
549 | req.reason_code = reason; | 557 | req.reason_code = reason; |
550 | req.ie = ie; | 558 | req.ie = ie; |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index da450ef1fc7e..0cd548267d4a 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -14,8 +14,10 @@ | |||
14 | #include <linux/rtnetlink.h> | 14 | #include <linux/rtnetlink.h> |
15 | #include <linux/netlink.h> | 15 | #include <linux/netlink.h> |
16 | #include <linux/etherdevice.h> | 16 | #include <linux/etherdevice.h> |
17 | #include <net/net_namespace.h> | ||
17 | #include <net/genetlink.h> | 18 | #include <net/genetlink.h> |
18 | #include <net/cfg80211.h> | 19 | #include <net/cfg80211.h> |
20 | #include <net/sock.h> | ||
19 | #include "core.h" | 21 | #include "core.h" |
20 | #include "nl80211.h" | 22 | #include "nl80211.h" |
21 | #include "reg.h" | 23 | #include "reg.h" |
@@ -27,24 +29,26 @@ static struct genl_family nl80211_fam = { | |||
27 | .hdrsize = 0, /* no private header */ | 29 | .hdrsize = 0, /* no private header */ |
28 | .version = 1, /* no particular meaning now */ | 30 | .version = 1, /* no particular meaning now */ |
29 | .maxattr = NL80211_ATTR_MAX, | 31 | .maxattr = NL80211_ATTR_MAX, |
32 | .netnsok = true, | ||
30 | }; | 33 | }; |
31 | 34 | ||
32 | /* internal helper: get rdev and dev */ | 35 | /* internal helper: get rdev and dev */ |
33 | static int get_rdev_dev_by_info_ifindex(struct nlattr **attrs, | 36 | static int get_rdev_dev_by_info_ifindex(struct genl_info *info, |
34 | struct cfg80211_registered_device **rdev, | 37 | struct cfg80211_registered_device **rdev, |
35 | struct net_device **dev) | 38 | struct net_device **dev) |
36 | { | 39 | { |
40 | struct nlattr **attrs = info->attrs; | ||
37 | int ifindex; | 41 | int ifindex; |
38 | 42 | ||
39 | if (!attrs[NL80211_ATTR_IFINDEX]) | 43 | if (!attrs[NL80211_ATTR_IFINDEX]) |
40 | return -EINVAL; | 44 | return -EINVAL; |
41 | 45 | ||
42 | ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]); | 46 | ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]); |
43 | *dev = dev_get_by_index(&init_net, ifindex); | 47 | *dev = dev_get_by_index(genl_info_net(info), ifindex); |
44 | if (!*dev) | 48 | if (!*dev) |
45 | return -ENODEV; | 49 | return -ENODEV; |
46 | 50 | ||
47 | *rdev = cfg80211_get_dev_from_ifindex(ifindex); | 51 | *rdev = cfg80211_get_dev_from_ifindex(genl_info_net(info), ifindex); |
48 | if (IS_ERR(*rdev)) { | 52 | if (IS_ERR(*rdev)) { |
49 | dev_put(*dev); | 53 | dev_put(*dev); |
50 | return PTR_ERR(*rdev); | 54 | return PTR_ERR(*rdev); |
@@ -133,6 +137,7 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { | |||
133 | [NL80211_ATTR_PRIVACY] = { .type = NLA_FLAG }, | 137 | [NL80211_ATTR_PRIVACY] = { .type = NLA_FLAG }, |
134 | [NL80211_ATTR_CIPHER_SUITE_GROUP] = { .type = NLA_U32 }, | 138 | [NL80211_ATTR_CIPHER_SUITE_GROUP] = { .type = NLA_U32 }, |
135 | [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 }, | 139 | [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 }, |
140 | [NL80211_ATTR_PID] = { .type = NLA_U32 }, | ||
136 | }; | 141 | }; |
137 | 142 | ||
138 | /* policy for the attributes */ | 143 | /* policy for the attributes */ |
@@ -532,6 +537,10 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
532 | CMD(deauth, DEAUTHENTICATE); | 537 | CMD(deauth, DEAUTHENTICATE); |
533 | CMD(disassoc, DISASSOCIATE); | 538 | CMD(disassoc, DISASSOCIATE); |
534 | CMD(join_ibss, JOIN_IBSS); | 539 | CMD(join_ibss, JOIN_IBSS); |
540 | if (dev->wiphy.netnsok) { | ||
541 | i++; | ||
542 | NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); | ||
543 | } | ||
535 | 544 | ||
536 | #undef CMD | 545 | #undef CMD |
537 | 546 | ||
@@ -562,6 +571,8 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) | |||
562 | 571 | ||
563 | mutex_lock(&cfg80211_mutex); | 572 | mutex_lock(&cfg80211_mutex); |
564 | list_for_each_entry(dev, &cfg80211_rdev_list, list) { | 573 | list_for_each_entry(dev, &cfg80211_rdev_list, list) { |
574 | if (!net_eq(wiphy_net(&dev->wiphy), sock_net(skb->sk))) | ||
575 | continue; | ||
565 | if (++idx <= start) | 576 | if (++idx <= start) |
566 | continue; | 577 | continue; |
567 | if (nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).pid, | 578 | if (nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).pid, |
@@ -746,6 +757,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
746 | channel_type); | 757 | channel_type); |
747 | if (result) | 758 | if (result) |
748 | goto bad_res; | 759 | goto bad_res; |
760 | |||
761 | rdev->channel = chan; | ||
749 | } | 762 | } |
750 | 763 | ||
751 | changed = 0; | 764 | changed = 0; |
@@ -867,6 +880,8 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback * | |||
867 | 880 | ||
868 | mutex_lock(&cfg80211_mutex); | 881 | mutex_lock(&cfg80211_mutex); |
869 | list_for_each_entry(dev, &cfg80211_rdev_list, list) { | 882 | list_for_each_entry(dev, &cfg80211_rdev_list, list) { |
883 | if (!net_eq(wiphy_net(&dev->wiphy), sock_net(skb->sk))) | ||
884 | continue; | ||
870 | if (wp_idx < wp_start) { | 885 | if (wp_idx < wp_start) { |
871 | wp_idx++; | 886 | wp_idx++; |
872 | continue; | 887 | continue; |
@@ -907,7 +922,7 @@ static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info) | |||
907 | struct net_device *netdev; | 922 | struct net_device *netdev; |
908 | int err; | 923 | int err; |
909 | 924 | ||
910 | err = get_rdev_dev_by_info_ifindex(info->attrs, &dev, &netdev); | 925 | err = get_rdev_dev_by_info_ifindex(info, &dev, &netdev); |
911 | if (err) | 926 | if (err) |
912 | return err; | 927 | return err; |
913 | 928 | ||
@@ -975,7 +990,7 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) | |||
975 | 990 | ||
976 | rtnl_lock(); | 991 | rtnl_lock(); |
977 | 992 | ||
978 | err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); | 993 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); |
979 | if (err) | 994 | if (err) |
980 | goto unlock_rtnl; | 995 | goto unlock_rtnl; |
981 | 996 | ||
@@ -1098,26 +1113,25 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) | |||
1098 | static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info) | 1113 | static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info) |
1099 | { | 1114 | { |
1100 | struct cfg80211_registered_device *rdev; | 1115 | struct cfg80211_registered_device *rdev; |
1101 | int ifindex, err; | 1116 | int err; |
1102 | struct net_device *dev; | 1117 | struct net_device *dev; |
1103 | 1118 | ||
1104 | rtnl_lock(); | 1119 | rtnl_lock(); |
1105 | 1120 | ||
1106 | err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); | 1121 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); |
1107 | if (err) | 1122 | if (err) |
1108 | goto unlock_rtnl; | 1123 | goto unlock_rtnl; |
1109 | ifindex = dev->ifindex; | ||
1110 | dev_put(dev); | ||
1111 | 1124 | ||
1112 | if (!rdev->ops->del_virtual_intf) { | 1125 | if (!rdev->ops->del_virtual_intf) { |
1113 | err = -EOPNOTSUPP; | 1126 | err = -EOPNOTSUPP; |
1114 | goto out; | 1127 | goto out; |
1115 | } | 1128 | } |
1116 | 1129 | ||
1117 | err = rdev->ops->del_virtual_intf(&rdev->wiphy, ifindex); | 1130 | err = rdev->ops->del_virtual_intf(&rdev->wiphy, dev); |
1118 | 1131 | ||
1119 | out: | 1132 | out: |
1120 | cfg80211_unlock_rdev(rdev); | 1133 | cfg80211_unlock_rdev(rdev); |
1134 | dev_put(dev); | ||
1121 | unlock_rtnl: | 1135 | unlock_rtnl: |
1122 | rtnl_unlock(); | 1136 | rtnl_unlock(); |
1123 | return err; | 1137 | return err; |
@@ -1195,7 +1209,7 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) | |||
1195 | 1209 | ||
1196 | rtnl_lock(); | 1210 | rtnl_lock(); |
1197 | 1211 | ||
1198 | err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); | 1212 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); |
1199 | if (err) | 1213 | if (err) |
1200 | goto unlock_rtnl; | 1214 | goto unlock_rtnl; |
1201 | 1215 | ||
@@ -1274,7 +1288,7 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) | |||
1274 | 1288 | ||
1275 | rtnl_lock(); | 1289 | rtnl_lock(); |
1276 | 1290 | ||
1277 | err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); | 1291 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); |
1278 | if (err) | 1292 | if (err) |
1279 | goto unlock_rtnl; | 1293 | goto unlock_rtnl; |
1280 | 1294 | ||
@@ -1333,7 +1347,7 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info) | |||
1333 | 1347 | ||
1334 | rtnl_lock(); | 1348 | rtnl_lock(); |
1335 | 1349 | ||
1336 | err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); | 1350 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); |
1337 | if (err) | 1351 | if (err) |
1338 | goto unlock_rtnl; | 1352 | goto unlock_rtnl; |
1339 | 1353 | ||
@@ -1380,7 +1394,7 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) | |||
1380 | 1394 | ||
1381 | rtnl_lock(); | 1395 | rtnl_lock(); |
1382 | 1396 | ||
1383 | err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); | 1397 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); |
1384 | if (err) | 1398 | if (err) |
1385 | goto unlock_rtnl; | 1399 | goto unlock_rtnl; |
1386 | 1400 | ||
@@ -1429,7 +1443,7 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) | |||
1429 | 1443 | ||
1430 | rtnl_lock(); | 1444 | rtnl_lock(); |
1431 | 1445 | ||
1432 | err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); | 1446 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); |
1433 | if (err) | 1447 | if (err) |
1434 | goto unlock_rtnl; | 1448 | goto unlock_rtnl; |
1435 | 1449 | ||
@@ -1516,7 +1530,7 @@ static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info) | |||
1516 | 1530 | ||
1517 | rtnl_lock(); | 1531 | rtnl_lock(); |
1518 | 1532 | ||
1519 | err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); | 1533 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); |
1520 | if (err) | 1534 | if (err) |
1521 | goto unlock_rtnl; | 1535 | goto unlock_rtnl; |
1522 | 1536 | ||
@@ -1726,13 +1740,13 @@ static int nl80211_dump_station(struct sk_buff *skb, | |||
1726 | 1740 | ||
1727 | rtnl_lock(); | 1741 | rtnl_lock(); |
1728 | 1742 | ||
1729 | netdev = __dev_get_by_index(&init_net, ifidx); | 1743 | netdev = __dev_get_by_index(sock_net(skb->sk), ifidx); |
1730 | if (!netdev) { | 1744 | if (!netdev) { |
1731 | err = -ENODEV; | 1745 | err = -ENODEV; |
1732 | goto out_rtnl; | 1746 | goto out_rtnl; |
1733 | } | 1747 | } |
1734 | 1748 | ||
1735 | dev = cfg80211_get_dev_from_ifindex(ifidx); | 1749 | dev = cfg80211_get_dev_from_ifindex(sock_net(skb->sk), ifidx); |
1736 | if (IS_ERR(dev)) { | 1750 | if (IS_ERR(dev)) { |
1737 | err = PTR_ERR(dev); | 1751 | err = PTR_ERR(dev); |
1738 | goto out_rtnl; | 1752 | goto out_rtnl; |
@@ -1791,7 +1805,7 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info) | |||
1791 | 1805 | ||
1792 | rtnl_lock(); | 1806 | rtnl_lock(); |
1793 | 1807 | ||
1794 | err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); | 1808 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); |
1795 | if (err) | 1809 | if (err) |
1796 | goto out_rtnl; | 1810 | goto out_rtnl; |
1797 | 1811 | ||
@@ -1829,14 +1843,16 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info) | |||
1829 | /* | 1843 | /* |
1830 | * Get vlan interface making sure it is on the right wiphy. | 1844 | * Get vlan interface making sure it is on the right wiphy. |
1831 | */ | 1845 | */ |
1832 | static int get_vlan(struct nlattr *vlanattr, | 1846 | static int get_vlan(struct genl_info *info, |
1833 | struct cfg80211_registered_device *rdev, | 1847 | struct cfg80211_registered_device *rdev, |
1834 | struct net_device **vlan) | 1848 | struct net_device **vlan) |
1835 | { | 1849 | { |
1850 | struct nlattr *vlanattr = info->attrs[NL80211_ATTR_STA_VLAN]; | ||
1836 | *vlan = NULL; | 1851 | *vlan = NULL; |
1837 | 1852 | ||
1838 | if (vlanattr) { | 1853 | if (vlanattr) { |
1839 | *vlan = dev_get_by_index(&init_net, nla_get_u32(vlanattr)); | 1854 | *vlan = dev_get_by_index(genl_info_net(info), |
1855 | nla_get_u32(vlanattr)); | ||
1840 | if (!*vlan) | 1856 | if (!*vlan) |
1841 | return -ENODEV; | 1857 | return -ENODEV; |
1842 | if (!(*vlan)->ieee80211_ptr) | 1858 | if (!(*vlan)->ieee80211_ptr) |
@@ -1891,11 +1907,11 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | |||
1891 | 1907 | ||
1892 | rtnl_lock(); | 1908 | rtnl_lock(); |
1893 | 1909 | ||
1894 | err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); | 1910 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); |
1895 | if (err) | 1911 | if (err) |
1896 | goto out_rtnl; | 1912 | goto out_rtnl; |
1897 | 1913 | ||
1898 | err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], rdev, ¶ms.vlan); | 1914 | err = get_vlan(info, rdev, ¶ms.vlan); |
1899 | if (err) | 1915 | if (err) |
1900 | goto out; | 1916 | goto out; |
1901 | 1917 | ||
@@ -2004,11 +2020,11 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
2004 | 2020 | ||
2005 | rtnl_lock(); | 2021 | rtnl_lock(); |
2006 | 2022 | ||
2007 | err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); | 2023 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); |
2008 | if (err) | 2024 | if (err) |
2009 | goto out_rtnl; | 2025 | goto out_rtnl; |
2010 | 2026 | ||
2011 | err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], rdev, ¶ms.vlan); | 2027 | err = get_vlan(info, rdev, ¶ms.vlan); |
2012 | if (err) | 2028 | if (err) |
2013 | goto out; | 2029 | goto out; |
2014 | 2030 | ||
@@ -2079,7 +2095,7 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info) | |||
2079 | 2095 | ||
2080 | rtnl_lock(); | 2096 | rtnl_lock(); |
2081 | 2097 | ||
2082 | err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); | 2098 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); |
2083 | if (err) | 2099 | if (err) |
2084 | goto out_rtnl; | 2100 | goto out_rtnl; |
2085 | 2101 | ||
@@ -2185,13 +2201,13 @@ static int nl80211_dump_mpath(struct sk_buff *skb, | |||
2185 | 2201 | ||
2186 | rtnl_lock(); | 2202 | rtnl_lock(); |
2187 | 2203 | ||
2188 | netdev = __dev_get_by_index(&init_net, ifidx); | 2204 | netdev = __dev_get_by_index(sock_net(skb->sk), ifidx); |
2189 | if (!netdev) { | 2205 | if (!netdev) { |
2190 | err = -ENODEV; | 2206 | err = -ENODEV; |
2191 | goto out_rtnl; | 2207 | goto out_rtnl; |
2192 | } | 2208 | } |
2193 | 2209 | ||
2194 | dev = cfg80211_get_dev_from_ifindex(ifidx); | 2210 | dev = cfg80211_get_dev_from_ifindex(sock_net(skb->sk), ifidx); |
2195 | if (IS_ERR(dev)) { | 2211 | if (IS_ERR(dev)) { |
2196 | err = PTR_ERR(dev); | 2212 | err = PTR_ERR(dev); |
2197 | goto out_rtnl; | 2213 | goto out_rtnl; |
@@ -2255,7 +2271,7 @@ static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info) | |||
2255 | 2271 | ||
2256 | rtnl_lock(); | 2272 | rtnl_lock(); |
2257 | 2273 | ||
2258 | err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); | 2274 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); |
2259 | if (err) | 2275 | if (err) |
2260 | goto out_rtnl; | 2276 | goto out_rtnl; |
2261 | 2277 | ||
@@ -2314,7 +2330,7 @@ static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info) | |||
2314 | 2330 | ||
2315 | rtnl_lock(); | 2331 | rtnl_lock(); |
2316 | 2332 | ||
2317 | err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); | 2333 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); |
2318 | if (err) | 2334 | if (err) |
2319 | goto out_rtnl; | 2335 | goto out_rtnl; |
2320 | 2336 | ||
@@ -2362,7 +2378,7 @@ static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info) | |||
2362 | 2378 | ||
2363 | rtnl_lock(); | 2379 | rtnl_lock(); |
2364 | 2380 | ||
2365 | err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); | 2381 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); |
2366 | if (err) | 2382 | if (err) |
2367 | goto out_rtnl; | 2383 | goto out_rtnl; |
2368 | 2384 | ||
@@ -2404,7 +2420,7 @@ static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info) | |||
2404 | 2420 | ||
2405 | rtnl_lock(); | 2421 | rtnl_lock(); |
2406 | 2422 | ||
2407 | err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); | 2423 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); |
2408 | if (err) | 2424 | if (err) |
2409 | goto out_rtnl; | 2425 | goto out_rtnl; |
2410 | 2426 | ||
@@ -2455,7 +2471,7 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) | |||
2455 | 2471 | ||
2456 | rtnl_lock(); | 2472 | rtnl_lock(); |
2457 | 2473 | ||
2458 | err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); | 2474 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); |
2459 | if (err) | 2475 | if (err) |
2460 | goto out_rtnl; | 2476 | goto out_rtnl; |
2461 | 2477 | ||
@@ -2574,7 +2590,7 @@ static int nl80211_get_mesh_params(struct sk_buff *skb, | |||
2574 | rtnl_lock(); | 2590 | rtnl_lock(); |
2575 | 2591 | ||
2576 | /* Look up our device */ | 2592 | /* Look up our device */ |
2577 | err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); | 2593 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); |
2578 | if (err) | 2594 | if (err) |
2579 | goto out_rtnl; | 2595 | goto out_rtnl; |
2580 | 2596 | ||
@@ -2691,7 +2707,7 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info) | |||
2691 | 2707 | ||
2692 | rtnl_lock(); | 2708 | rtnl_lock(); |
2693 | 2709 | ||
2694 | err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); | 2710 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); |
2695 | if (err) | 2711 | if (err) |
2696 | goto out_rtnl; | 2712 | goto out_rtnl; |
2697 | 2713 | ||
@@ -2947,7 +2963,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
2947 | 2963 | ||
2948 | rtnl_lock(); | 2964 | rtnl_lock(); |
2949 | 2965 | ||
2950 | err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); | 2966 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); |
2951 | if (err) | 2967 | if (err) |
2952 | goto out_rtnl; | 2968 | goto out_rtnl; |
2953 | 2969 | ||
@@ -3069,14 +3085,16 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
3069 | request->ie_len); | 3085 | request->ie_len); |
3070 | } | 3086 | } |
3071 | 3087 | ||
3072 | request->ifidx = dev->ifindex; | 3088 | request->dev = dev; |
3073 | request->wiphy = &rdev->wiphy; | 3089 | request->wiphy = &rdev->wiphy; |
3074 | 3090 | ||
3075 | rdev->scan_req = request; | 3091 | rdev->scan_req = request; |
3076 | err = rdev->ops->scan(&rdev->wiphy, dev, request); | 3092 | err = rdev->ops->scan(&rdev->wiphy, dev, request); |
3077 | 3093 | ||
3078 | if (!err) | 3094 | if (!err) { |
3079 | nl80211_send_scan_start(rdev, dev); | 3095 | nl80211_send_scan_start(rdev, dev); |
3096 | dev_hold(dev); | ||
3097 | } | ||
3080 | 3098 | ||
3081 | out_free: | 3099 | out_free: |
3082 | if (err) { | 3100 | if (err) { |
@@ -3198,11 +3216,11 @@ static int nl80211_dump_scan(struct sk_buff *skb, | |||
3198 | cb->args[0] = ifidx; | 3216 | cb->args[0] = ifidx; |
3199 | } | 3217 | } |
3200 | 3218 | ||
3201 | dev = dev_get_by_index(&init_net, ifidx); | 3219 | dev = dev_get_by_index(sock_net(skb->sk), ifidx); |
3202 | if (!dev) | 3220 | if (!dev) |
3203 | return -ENODEV; | 3221 | return -ENODEV; |
3204 | 3222 | ||
3205 | rdev = cfg80211_get_dev_from_ifindex(ifidx); | 3223 | rdev = cfg80211_get_dev_from_ifindex(sock_net(skb->sk), ifidx); |
3206 | if (IS_ERR(rdev)) { | 3224 | if (IS_ERR(rdev)) { |
3207 | err = PTR_ERR(rdev); | 3225 | err = PTR_ERR(rdev); |
3208 | goto out_put_netdev; | 3226 | goto out_put_netdev; |
@@ -3312,7 +3330,7 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) | |||
3312 | 3330 | ||
3313 | rtnl_lock(); | 3331 | rtnl_lock(); |
3314 | 3332 | ||
3315 | err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); | 3333 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); |
3316 | if (err) | 3334 | if (err) |
3317 | goto unlock_rtnl; | 3335 | goto unlock_rtnl; |
3318 | 3336 | ||
@@ -3369,6 +3387,8 @@ static int nl80211_crypto_settings(struct genl_info *info, | |||
3369 | struct cfg80211_crypto_settings *settings, | 3387 | struct cfg80211_crypto_settings *settings, |
3370 | int cipher_limit) | 3388 | int cipher_limit) |
3371 | { | 3389 | { |
3390 | memset(settings, 0, sizeof(*settings)); | ||
3391 | |||
3372 | settings->control_port = info->attrs[NL80211_ATTR_CONTROL_PORT]; | 3392 | settings->control_port = info->attrs[NL80211_ATTR_CONTROL_PORT]; |
3373 | 3393 | ||
3374 | if (info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]) { | 3394 | if (info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]) { |
@@ -3448,7 +3468,7 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) | |||
3448 | 3468 | ||
3449 | rtnl_lock(); | 3469 | rtnl_lock(); |
3450 | 3470 | ||
3451 | err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); | 3471 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); |
3452 | if (err) | 3472 | if (err) |
3453 | goto unlock_rtnl; | 3473 | goto unlock_rtnl; |
3454 | 3474 | ||
@@ -3531,7 +3551,7 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info) | |||
3531 | 3551 | ||
3532 | rtnl_lock(); | 3552 | rtnl_lock(); |
3533 | 3553 | ||
3534 | err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); | 3554 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); |
3535 | if (err) | 3555 | if (err) |
3536 | goto unlock_rtnl; | 3556 | goto unlock_rtnl; |
3537 | 3557 | ||
@@ -3593,7 +3613,7 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) | |||
3593 | 3613 | ||
3594 | rtnl_lock(); | 3614 | rtnl_lock(); |
3595 | 3615 | ||
3596 | err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); | 3616 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); |
3597 | if (err) | 3617 | if (err) |
3598 | goto unlock_rtnl; | 3618 | goto unlock_rtnl; |
3599 | 3619 | ||
@@ -3666,7 +3686,7 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) | |||
3666 | 3686 | ||
3667 | rtnl_lock(); | 3687 | rtnl_lock(); |
3668 | 3688 | ||
3669 | err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); | 3689 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); |
3670 | if (err) | 3690 | if (err) |
3671 | goto unlock_rtnl; | 3691 | goto unlock_rtnl; |
3672 | 3692 | ||
@@ -3739,7 +3759,7 @@ static int nl80211_leave_ibss(struct sk_buff *skb, struct genl_info *info) | |||
3739 | 3759 | ||
3740 | rtnl_lock(); | 3760 | rtnl_lock(); |
3741 | 3761 | ||
3742 | err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); | 3762 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); |
3743 | if (err) | 3763 | if (err) |
3744 | goto unlock_rtnl; | 3764 | goto unlock_rtnl; |
3745 | 3765 | ||
@@ -3924,7 +3944,7 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) | |||
3924 | return err; | 3944 | return err; |
3925 | rtnl_lock(); | 3945 | rtnl_lock(); |
3926 | 3946 | ||
3927 | err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); | 3947 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); |
3928 | if (err) | 3948 | if (err) |
3929 | goto unlock_rtnl; | 3949 | goto unlock_rtnl; |
3930 | 3950 | ||
@@ -4000,7 +4020,7 @@ static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info) | |||
4000 | 4020 | ||
4001 | rtnl_lock(); | 4021 | rtnl_lock(); |
4002 | 4022 | ||
4003 | err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); | 4023 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); |
4004 | if (err) | 4024 | if (err) |
4005 | goto unlock_rtnl; | 4025 | goto unlock_rtnl; |
4006 | 4026 | ||
@@ -4024,6 +4044,47 @@ unlock_rtnl: | |||
4024 | return err; | 4044 | return err; |
4025 | } | 4045 | } |
4026 | 4046 | ||
4047 | static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info) | ||
4048 | { | ||
4049 | struct cfg80211_registered_device *rdev; | ||
4050 | struct net *net; | ||
4051 | int err; | ||
4052 | u32 pid; | ||
4053 | |||
4054 | if (!info->attrs[NL80211_ATTR_PID]) | ||
4055 | return -EINVAL; | ||
4056 | |||
4057 | pid = nla_get_u32(info->attrs[NL80211_ATTR_PID]); | ||
4058 | |||
4059 | rtnl_lock(); | ||
4060 | |||
4061 | rdev = cfg80211_get_dev_from_info(info); | ||
4062 | if (IS_ERR(rdev)) { | ||
4063 | err = PTR_ERR(rdev); | ||
4064 | goto out; | ||
4065 | } | ||
4066 | |||
4067 | net = get_net_ns_by_pid(pid); | ||
4068 | if (IS_ERR(net)) { | ||
4069 | err = PTR_ERR(net); | ||
4070 | goto out; | ||
4071 | } | ||
4072 | |||
4073 | err = 0; | ||
4074 | |||
4075 | /* check if anything to do */ | ||
4076 | if (net_eq(wiphy_net(&rdev->wiphy), net)) | ||
4077 | goto out_put_net; | ||
4078 | |||
4079 | err = cfg80211_switch_netns(rdev, net); | ||
4080 | out_put_net: | ||
4081 | put_net(net); | ||
4082 | out: | ||
4083 | cfg80211_unlock_rdev(rdev); | ||
4084 | rtnl_unlock(); | ||
4085 | return err; | ||
4086 | } | ||
4087 | |||
4027 | static struct genl_ops nl80211_ops[] = { | 4088 | static struct genl_ops nl80211_ops[] = { |
4028 | { | 4089 | { |
4029 | .cmd = NL80211_CMD_GET_WIPHY, | 4090 | .cmd = NL80211_CMD_GET_WIPHY, |
@@ -4257,6 +4318,12 @@ static struct genl_ops nl80211_ops[] = { | |||
4257 | .policy = nl80211_policy, | 4318 | .policy = nl80211_policy, |
4258 | .flags = GENL_ADMIN_PERM, | 4319 | .flags = GENL_ADMIN_PERM, |
4259 | }, | 4320 | }, |
4321 | { | ||
4322 | .cmd = NL80211_CMD_SET_WIPHY_NETNS, | ||
4323 | .doit = nl80211_wiphy_netns, | ||
4324 | .policy = nl80211_policy, | ||
4325 | .flags = GENL_ADMIN_PERM, | ||
4326 | }, | ||
4260 | }; | 4327 | }; |
4261 | static struct genl_multicast_group nl80211_mlme_mcgrp = { | 4328 | static struct genl_multicast_group nl80211_mlme_mcgrp = { |
4262 | .name = "mlme", | 4329 | .name = "mlme", |
@@ -4288,7 +4355,8 @@ void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev) | |||
4288 | return; | 4355 | return; |
4289 | } | 4356 | } |
4290 | 4357 | ||
4291 | genlmsg_multicast(msg, 0, nl80211_config_mcgrp.id, GFP_KERNEL); | 4358 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, |
4359 | nl80211_config_mcgrp.id, GFP_KERNEL); | ||
4292 | } | 4360 | } |
4293 | 4361 | ||
4294 | static int nl80211_add_scan_req(struct sk_buff *msg, | 4362 | static int nl80211_add_scan_req(struct sk_buff *msg, |
@@ -4365,7 +4433,8 @@ void nl80211_send_scan_start(struct cfg80211_registered_device *rdev, | |||
4365 | return; | 4433 | return; |
4366 | } | 4434 | } |
4367 | 4435 | ||
4368 | genlmsg_multicast(msg, 0, nl80211_scan_mcgrp.id, GFP_KERNEL); | 4436 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, |
4437 | nl80211_scan_mcgrp.id, GFP_KERNEL); | ||
4369 | } | 4438 | } |
4370 | 4439 | ||
4371 | void nl80211_send_scan_done(struct cfg80211_registered_device *rdev, | 4440 | void nl80211_send_scan_done(struct cfg80211_registered_device *rdev, |
@@ -4383,7 +4452,8 @@ void nl80211_send_scan_done(struct cfg80211_registered_device *rdev, | |||
4383 | return; | 4452 | return; |
4384 | } | 4453 | } |
4385 | 4454 | ||
4386 | genlmsg_multicast(msg, 0, nl80211_scan_mcgrp.id, GFP_KERNEL); | 4455 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, |
4456 | nl80211_scan_mcgrp.id, GFP_KERNEL); | ||
4387 | } | 4457 | } |
4388 | 4458 | ||
4389 | void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, | 4459 | void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, |
@@ -4401,7 +4471,8 @@ void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, | |||
4401 | return; | 4471 | return; |
4402 | } | 4472 | } |
4403 | 4473 | ||
4404 | genlmsg_multicast(msg, 0, nl80211_scan_mcgrp.id, GFP_KERNEL); | 4474 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, |
4475 | nl80211_scan_mcgrp.id, GFP_KERNEL); | ||
4405 | } | 4476 | } |
4406 | 4477 | ||
4407 | /* | 4478 | /* |
@@ -4450,7 +4521,10 @@ void nl80211_send_reg_change_event(struct regulatory_request *request) | |||
4450 | return; | 4521 | return; |
4451 | } | 4522 | } |
4452 | 4523 | ||
4453 | genlmsg_multicast(msg, 0, nl80211_regulatory_mcgrp.id, GFP_KERNEL); | 4524 | rcu_read_lock(); |
4525 | genlmsg_multicast_allns(msg, 0, nl80211_regulatory_mcgrp.id, | ||
4526 | GFP_ATOMIC); | ||
4527 | rcu_read_unlock(); | ||
4454 | 4528 | ||
4455 | return; | 4529 | return; |
4456 | 4530 | ||
@@ -4486,7 +4560,8 @@ static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev, | |||
4486 | return; | 4560 | return; |
4487 | } | 4561 | } |
4488 | 4562 | ||
4489 | genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp); | 4563 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, |
4564 | nl80211_mlme_mcgrp.id, gfp); | ||
4490 | return; | 4565 | return; |
4491 | 4566 | ||
4492 | nla_put_failure: | 4567 | nla_put_failure: |
@@ -4553,7 +4628,8 @@ static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev, | |||
4553 | return; | 4628 | return; |
4554 | } | 4629 | } |
4555 | 4630 | ||
4556 | genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp); | 4631 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, |
4632 | nl80211_mlme_mcgrp.id, gfp); | ||
4557 | return; | 4633 | return; |
4558 | 4634 | ||
4559 | nla_put_failure: | 4635 | nla_put_failure: |
@@ -4611,7 +4687,8 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev, | |||
4611 | return; | 4687 | return; |
4612 | } | 4688 | } |
4613 | 4689 | ||
4614 | genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp); | 4690 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, |
4691 | nl80211_mlme_mcgrp.id, gfp); | ||
4615 | return; | 4692 | return; |
4616 | 4693 | ||
4617 | nla_put_failure: | 4694 | nla_put_failure: |
@@ -4651,7 +4728,8 @@ void nl80211_send_roamed(struct cfg80211_registered_device *rdev, | |||
4651 | return; | 4728 | return; |
4652 | } | 4729 | } |
4653 | 4730 | ||
4654 | genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp); | 4731 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, |
4732 | nl80211_mlme_mcgrp.id, gfp); | ||
4655 | return; | 4733 | return; |
4656 | 4734 | ||
4657 | nla_put_failure: | 4735 | nla_put_failure: |
@@ -4691,7 +4769,8 @@ void nl80211_send_disconnected(struct cfg80211_registered_device *rdev, | |||
4691 | return; | 4769 | return; |
4692 | } | 4770 | } |
4693 | 4771 | ||
4694 | genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, GFP_KERNEL); | 4772 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, |
4773 | nl80211_mlme_mcgrp.id, GFP_KERNEL); | ||
4695 | return; | 4774 | return; |
4696 | 4775 | ||
4697 | nla_put_failure: | 4776 | nla_put_failure: |
@@ -4726,7 +4805,8 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev, | |||
4726 | return; | 4805 | return; |
4727 | } | 4806 | } |
4728 | 4807 | ||
4729 | genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp); | 4808 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, |
4809 | nl80211_mlme_mcgrp.id, gfp); | ||
4730 | return; | 4810 | return; |
4731 | 4811 | ||
4732 | nla_put_failure: | 4812 | nla_put_failure: |
@@ -4766,7 +4846,8 @@ void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev, | |||
4766 | return; | 4846 | return; |
4767 | } | 4847 | } |
4768 | 4848 | ||
4769 | genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp); | 4849 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, |
4850 | nl80211_mlme_mcgrp.id, gfp); | ||
4770 | return; | 4851 | return; |
4771 | 4852 | ||
4772 | nla_put_failure: | 4853 | nla_put_failure: |
@@ -4819,7 +4900,10 @@ void nl80211_send_beacon_hint_event(struct wiphy *wiphy, | |||
4819 | return; | 4900 | return; |
4820 | } | 4901 | } |
4821 | 4902 | ||
4822 | genlmsg_multicast(msg, 0, nl80211_regulatory_mcgrp.id, GFP_ATOMIC); | 4903 | rcu_read_lock(); |
4904 | genlmsg_multicast_allns(msg, 0, nl80211_regulatory_mcgrp.id, | ||
4905 | GFP_ATOMIC); | ||
4906 | rcu_read_unlock(); | ||
4823 | 4907 | ||
4824 | return; | 4908 | return; |
4825 | 4909 | ||
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index decc59fe0ee8..67714d7ed5b4 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -14,8 +14,9 @@ | |||
14 | #include <net/iw_handler.h> | 14 | #include <net/iw_handler.h> |
15 | #include "core.h" | 15 | #include "core.h" |
16 | #include "nl80211.h" | 16 | #include "nl80211.h" |
17 | #include "wext-compat.h" | ||
17 | 18 | ||
18 | #define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ) | 19 | #define IEEE80211_SCAN_RESULT_EXPIRE (15 * HZ) |
19 | 20 | ||
20 | void __cfg80211_scan_done(struct work_struct *wk) | 21 | void __cfg80211_scan_done(struct work_struct *wk) |
21 | { | 22 | { |
@@ -32,9 +33,7 @@ void __cfg80211_scan_done(struct work_struct *wk) | |||
32 | mutex_lock(&rdev->mtx); | 33 | mutex_lock(&rdev->mtx); |
33 | request = rdev->scan_req; | 34 | request = rdev->scan_req; |
34 | 35 | ||
35 | dev = dev_get_by_index(&init_net, request->ifidx); | 36 | dev = request->dev; |
36 | if (!dev) | ||
37 | goto out; | ||
38 | 37 | ||
39 | /* | 38 | /* |
40 | * This must be before sending the other events! | 39 | * This must be before sending the other events! |
@@ -58,7 +57,6 @@ void __cfg80211_scan_done(struct work_struct *wk) | |||
58 | 57 | ||
59 | dev_put(dev); | 58 | dev_put(dev); |
60 | 59 | ||
61 | out: | ||
62 | cfg80211_unlock_rdev(rdev); | 60 | cfg80211_unlock_rdev(rdev); |
63 | wiphy_to_dev(request->wiphy)->scan_req = NULL; | 61 | wiphy_to_dev(request->wiphy)->scan_req = NULL; |
64 | kfree(request); | 62 | kfree(request); |
@@ -66,17 +64,10 @@ void __cfg80211_scan_done(struct work_struct *wk) | |||
66 | 64 | ||
67 | void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted) | 65 | void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted) |
68 | { | 66 | { |
69 | struct net_device *dev = dev_get_by_index(&init_net, request->ifidx); | ||
70 | if (WARN_ON(!dev)) { | ||
71 | kfree(request); | ||
72 | return; | ||
73 | } | ||
74 | |||
75 | WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req); | 67 | WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req); |
76 | 68 | ||
77 | request->aborted = aborted; | 69 | request->aborted = aborted; |
78 | schedule_work(&wiphy_to_dev(request->wiphy)->scan_done_wk); | 70 | schedule_work(&wiphy_to_dev(request->wiphy)->scan_done_wk); |
79 | dev_put(dev); | ||
80 | } | 71 | } |
81 | EXPORT_SYMBOL(cfg80211_scan_done); | 72 | EXPORT_SYMBOL(cfg80211_scan_done); |
82 | 73 | ||
@@ -592,7 +583,7 @@ int cfg80211_wext_siwscan(struct net_device *dev, | |||
592 | if (!netif_running(dev)) | 583 | if (!netif_running(dev)) |
593 | return -ENETDOWN; | 584 | return -ENETDOWN; |
594 | 585 | ||
595 | rdev = cfg80211_get_dev_from_ifindex(dev->ifindex); | 586 | rdev = cfg80211_get_dev_from_ifindex(dev_net(dev), dev->ifindex); |
596 | 587 | ||
597 | if (IS_ERR(rdev)) | 588 | if (IS_ERR(rdev)) |
598 | return PTR_ERR(rdev); | 589 | return PTR_ERR(rdev); |
@@ -617,7 +608,7 @@ int cfg80211_wext_siwscan(struct net_device *dev, | |||
617 | } | 608 | } |
618 | 609 | ||
619 | creq->wiphy = wiphy; | 610 | creq->wiphy = wiphy; |
620 | creq->ifidx = dev->ifindex; | 611 | creq->dev = dev; |
621 | creq->ssids = (void *)(creq + 1); | 612 | creq->ssids = (void *)(creq + 1); |
622 | creq->channels = (void *)(creq->ssids + 1); | 613 | creq->channels = (void *)(creq->ssids + 1); |
623 | creq->n_channels = n_channels; | 614 | creq->n_channels = n_channels; |
@@ -654,8 +645,10 @@ int cfg80211_wext_siwscan(struct net_device *dev, | |||
654 | if (err) { | 645 | if (err) { |
655 | rdev->scan_req = NULL; | 646 | rdev->scan_req = NULL; |
656 | kfree(creq); | 647 | kfree(creq); |
657 | } else | 648 | } else { |
658 | nl80211_send_scan_start(rdev, dev); | 649 | nl80211_send_scan_start(rdev, dev); |
650 | dev_hold(dev); | ||
651 | } | ||
659 | out: | 652 | out: |
660 | cfg80211_unlock_rdev(rdev); | 653 | cfg80211_unlock_rdev(rdev); |
661 | return err; | 654 | return err; |
@@ -948,7 +941,7 @@ int cfg80211_wext_giwscan(struct net_device *dev, | |||
948 | if (!netif_running(dev)) | 941 | if (!netif_running(dev)) |
949 | return -ENETDOWN; | 942 | return -ENETDOWN; |
950 | 943 | ||
951 | rdev = cfg80211_get_dev_from_ifindex(dev->ifindex); | 944 | rdev = cfg80211_get_dev_from_ifindex(dev_net(dev), dev->ifindex); |
952 | 945 | ||
953 | if (IS_ERR(rdev)) | 946 | if (IS_ERR(rdev)) |
954 | return PTR_ERR(rdev); | 947 | return PTR_ERR(rdev); |
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 82de2d9795f4..d2b5d4ce0a00 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -8,6 +8,8 @@ | |||
8 | #include <linux/etherdevice.h> | 8 | #include <linux/etherdevice.h> |
9 | #include <linux/if_arp.h> | 9 | #include <linux/if_arp.h> |
10 | #include <linux/workqueue.h> | 10 | #include <linux/workqueue.h> |
11 | #include <linux/wireless.h> | ||
12 | #include <net/iw_handler.h> | ||
11 | #include <net/cfg80211.h> | 13 | #include <net/cfg80211.h> |
12 | #include <net/rtnetlink.h> | 14 | #include <net/rtnetlink.h> |
13 | #include "nl80211.h" | 15 | #include "nl80211.h" |
@@ -86,7 +88,7 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev) | |||
86 | wdev->conn->params.ssid_len); | 88 | wdev->conn->params.ssid_len); |
87 | request->ssids[0].ssid_len = wdev->conn->params.ssid_len; | 89 | request->ssids[0].ssid_len = wdev->conn->params.ssid_len; |
88 | 90 | ||
89 | request->ifidx = wdev->netdev->ifindex; | 91 | request->dev = wdev->netdev; |
90 | request->wiphy = &rdev->wiphy; | 92 | request->wiphy = &rdev->wiphy; |
91 | 93 | ||
92 | rdev->scan_req = request; | 94 | rdev->scan_req = request; |
@@ -95,6 +97,7 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev) | |||
95 | if (!err) { | 97 | if (!err) { |
96 | wdev->conn->state = CFG80211_CONN_SCANNING; | 98 | wdev->conn->state = CFG80211_CONN_SCANNING; |
97 | nl80211_send_scan_start(rdev, wdev->netdev); | 99 | nl80211_send_scan_start(rdev, wdev->netdev); |
100 | dev_hold(wdev->netdev); | ||
98 | } else { | 101 | } else { |
99 | rdev->scan_req = NULL; | 102 | rdev->scan_req = NULL; |
100 | kfree(request); | 103 | kfree(request); |
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index c7351a98e660..e4e90e249bab 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/etherdevice.h> | 14 | #include <linux/etherdevice.h> |
15 | #include <net/iw_handler.h> | 15 | #include <net/iw_handler.h> |
16 | #include <net/cfg80211.h> | 16 | #include <net/cfg80211.h> |
17 | #include "wext-compat.h" | ||
17 | #include "core.h" | 18 | #include "core.h" |
18 | 19 | ||
19 | int cfg80211_wext_giwname(struct net_device *dev, | 20 | int cfg80211_wext_giwname(struct net_device *dev, |
@@ -300,7 +301,6 @@ struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy, | |||
300 | return ERR_PTR(-EINVAL); | 301 | return ERR_PTR(-EINVAL); |
301 | return chan; | 302 | return chan; |
302 | } | 303 | } |
303 | EXPORT_SYMBOL_GPL(cfg80211_wext_freq); | ||
304 | 304 | ||
305 | int cfg80211_wext_siwrts(struct net_device *dev, | 305 | int cfg80211_wext_siwrts(struct net_device *dev, |
306 | struct iw_request_info *info, | 306 | struct iw_request_info *info, |
@@ -759,6 +759,58 @@ int cfg80211_wext_giwencode(struct net_device *dev, | |||
759 | } | 759 | } |
760 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwencode); | 760 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwencode); |
761 | 761 | ||
762 | int cfg80211_wext_siwfreq(struct net_device *dev, | ||
763 | struct iw_request_info *info, | ||
764 | struct iw_freq *freq, char *extra) | ||
765 | { | ||
766 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
767 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | ||
768 | struct ieee80211_channel *chan; | ||
769 | int err; | ||
770 | |||
771 | switch (wdev->iftype) { | ||
772 | case NL80211_IFTYPE_STATION: | ||
773 | return cfg80211_mgd_wext_siwfreq(dev, info, freq, extra); | ||
774 | case NL80211_IFTYPE_ADHOC: | ||
775 | return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra); | ||
776 | default: | ||
777 | chan = cfg80211_wext_freq(wdev->wiphy, freq); | ||
778 | if (!chan) | ||
779 | return -EINVAL; | ||
780 | if (IS_ERR(chan)) | ||
781 | return PTR_ERR(chan); | ||
782 | err = rdev->ops->set_channel(wdev->wiphy, chan, | ||
783 | NL80211_CHAN_NO_HT); | ||
784 | if (err) | ||
785 | return err; | ||
786 | rdev->channel = chan; | ||
787 | return 0; | ||
788 | } | ||
789 | } | ||
790 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwfreq); | ||
791 | |||
792 | int cfg80211_wext_giwfreq(struct net_device *dev, | ||
793 | struct iw_request_info *info, | ||
794 | struct iw_freq *freq, char *extra) | ||
795 | { | ||
796 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
797 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | ||
798 | |||
799 | switch (wdev->iftype) { | ||
800 | case NL80211_IFTYPE_STATION: | ||
801 | return cfg80211_mgd_wext_giwfreq(dev, info, freq, extra); | ||
802 | case NL80211_IFTYPE_ADHOC: | ||
803 | return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra); | ||
804 | default: | ||
805 | if (!rdev->channel) | ||
806 | return -EINVAL; | ||
807 | freq->m = rdev->channel->center_freq; | ||
808 | freq->e = 6; | ||
809 | return 0; | ||
810 | } | ||
811 | } | ||
812 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwfreq); | ||
813 | |||
762 | int cfg80211_wext_siwtxpower(struct net_device *dev, | 814 | int cfg80211_wext_siwtxpower(struct net_device *dev, |
763 | struct iw_request_info *info, | 815 | struct iw_request_info *info, |
764 | union iwreq_data *data, char *extra) | 816 | union iwreq_data *data, char *extra) |
@@ -1097,9 +1149,9 @@ int cfg80211_wext_giwpower(struct net_device *dev, | |||
1097 | } | 1149 | } |
1098 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwpower); | 1150 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwpower); |
1099 | 1151 | ||
1100 | int cfg80211_wds_wext_siwap(struct net_device *dev, | 1152 | static int cfg80211_wds_wext_siwap(struct net_device *dev, |
1101 | struct iw_request_info *info, | 1153 | struct iw_request_info *info, |
1102 | struct sockaddr *addr, char *extra) | 1154 | struct sockaddr *addr, char *extra) |
1103 | { | 1155 | { |
1104 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 1156 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
1105 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | 1157 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); |
@@ -1125,11 +1177,10 @@ int cfg80211_wds_wext_siwap(struct net_device *dev, | |||
1125 | 1177 | ||
1126 | return 0; | 1178 | return 0; |
1127 | } | 1179 | } |
1128 | EXPORT_SYMBOL_GPL(cfg80211_wds_wext_siwap); | ||
1129 | 1180 | ||
1130 | int cfg80211_wds_wext_giwap(struct net_device *dev, | 1181 | static int cfg80211_wds_wext_giwap(struct net_device *dev, |
1131 | struct iw_request_info *info, | 1182 | struct iw_request_info *info, |
1132 | struct sockaddr *addr, char *extra) | 1183 | struct sockaddr *addr, char *extra) |
1133 | { | 1184 | { |
1134 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 1185 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
1135 | 1186 | ||
@@ -1141,7 +1192,6 @@ int cfg80211_wds_wext_giwap(struct net_device *dev, | |||
1141 | 1192 | ||
1142 | return 0; | 1193 | return 0; |
1143 | } | 1194 | } |
1144 | EXPORT_SYMBOL_GPL(cfg80211_wds_wext_giwap); | ||
1145 | 1195 | ||
1146 | int cfg80211_wext_siwrate(struct net_device *dev, | 1196 | int cfg80211_wext_siwrate(struct net_device *dev, |
1147 | struct iw_request_info *info, | 1197 | struct iw_request_info *info, |
@@ -1275,3 +1325,115 @@ struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev) | |||
1275 | return &wstats; | 1325 | return &wstats; |
1276 | } | 1326 | } |
1277 | EXPORT_SYMBOL_GPL(cfg80211_wireless_stats); | 1327 | EXPORT_SYMBOL_GPL(cfg80211_wireless_stats); |
1328 | |||
1329 | int cfg80211_wext_siwap(struct net_device *dev, | ||
1330 | struct iw_request_info *info, | ||
1331 | struct sockaddr *ap_addr, char *extra) | ||
1332 | { | ||
1333 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
1334 | |||
1335 | switch (wdev->iftype) { | ||
1336 | case NL80211_IFTYPE_ADHOC: | ||
1337 | return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra); | ||
1338 | case NL80211_IFTYPE_STATION: | ||
1339 | return cfg80211_mgd_wext_siwap(dev, info, ap_addr, extra); | ||
1340 | case NL80211_IFTYPE_WDS: | ||
1341 | return cfg80211_wds_wext_siwap(dev, info, ap_addr, extra); | ||
1342 | default: | ||
1343 | return -EOPNOTSUPP; | ||
1344 | } | ||
1345 | } | ||
1346 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwap); | ||
1347 | |||
1348 | int cfg80211_wext_giwap(struct net_device *dev, | ||
1349 | struct iw_request_info *info, | ||
1350 | struct sockaddr *ap_addr, char *extra) | ||
1351 | { | ||
1352 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
1353 | |||
1354 | switch (wdev->iftype) { | ||
1355 | case NL80211_IFTYPE_ADHOC: | ||
1356 | return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra); | ||
1357 | case NL80211_IFTYPE_STATION: | ||
1358 | return cfg80211_mgd_wext_giwap(dev, info, ap_addr, extra); | ||
1359 | case NL80211_IFTYPE_WDS: | ||
1360 | return cfg80211_wds_wext_giwap(dev, info, ap_addr, extra); | ||
1361 | default: | ||
1362 | return -EOPNOTSUPP; | ||
1363 | } | ||
1364 | } | ||
1365 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwap); | ||
1366 | |||
1367 | int cfg80211_wext_siwessid(struct net_device *dev, | ||
1368 | struct iw_request_info *info, | ||
1369 | struct iw_point *data, char *ssid) | ||
1370 | { | ||
1371 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
1372 | |||
1373 | switch (wdev->iftype) { | ||
1374 | case NL80211_IFTYPE_ADHOC: | ||
1375 | return cfg80211_ibss_wext_siwessid(dev, info, data, ssid); | ||
1376 | case NL80211_IFTYPE_STATION: | ||
1377 | return cfg80211_mgd_wext_siwessid(dev, info, data, ssid); | ||
1378 | default: | ||
1379 | return -EOPNOTSUPP; | ||
1380 | } | ||
1381 | } | ||
1382 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwessid); | ||
1383 | |||
1384 | int cfg80211_wext_giwessid(struct net_device *dev, | ||
1385 | struct iw_request_info *info, | ||
1386 | struct iw_point *data, char *ssid) | ||
1387 | { | ||
1388 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
1389 | |||
1390 | switch (wdev->iftype) { | ||
1391 | case NL80211_IFTYPE_ADHOC: | ||
1392 | return cfg80211_ibss_wext_giwessid(dev, info, data, ssid); | ||
1393 | case NL80211_IFTYPE_STATION: | ||
1394 | return cfg80211_mgd_wext_giwessid(dev, info, data, ssid); | ||
1395 | default: | ||
1396 | return -EOPNOTSUPP; | ||
1397 | } | ||
1398 | } | ||
1399 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwessid); | ||
1400 | |||
1401 | static const iw_handler cfg80211_handlers[] = { | ||
1402 | [IW_IOCTL_IDX(SIOCGIWNAME)] = (iw_handler) cfg80211_wext_giwname, | ||
1403 | [IW_IOCTL_IDX(SIOCSIWFREQ)] = (iw_handler) cfg80211_wext_siwfreq, | ||
1404 | [IW_IOCTL_IDX(SIOCGIWFREQ)] = (iw_handler) cfg80211_wext_giwfreq, | ||
1405 | [IW_IOCTL_IDX(SIOCSIWMODE)] = (iw_handler) cfg80211_wext_siwmode, | ||
1406 | [IW_IOCTL_IDX(SIOCGIWMODE)] = (iw_handler) cfg80211_wext_giwmode, | ||
1407 | [IW_IOCTL_IDX(SIOCGIWRANGE)] = (iw_handler) cfg80211_wext_giwrange, | ||
1408 | [IW_IOCTL_IDX(SIOCSIWAP)] = (iw_handler) cfg80211_wext_siwap, | ||
1409 | [IW_IOCTL_IDX(SIOCGIWAP)] = (iw_handler) cfg80211_wext_giwap, | ||
1410 | [IW_IOCTL_IDX(SIOCSIWMLME)] = (iw_handler) cfg80211_wext_siwmlme, | ||
1411 | [IW_IOCTL_IDX(SIOCSIWSCAN)] = (iw_handler) cfg80211_wext_siwscan, | ||
1412 | [IW_IOCTL_IDX(SIOCGIWSCAN)] = (iw_handler) cfg80211_wext_giwscan, | ||
1413 | [IW_IOCTL_IDX(SIOCSIWESSID)] = (iw_handler) cfg80211_wext_siwessid, | ||
1414 | [IW_IOCTL_IDX(SIOCGIWESSID)] = (iw_handler) cfg80211_wext_giwessid, | ||
1415 | [IW_IOCTL_IDX(SIOCSIWRATE)] = (iw_handler) cfg80211_wext_siwrate, | ||
1416 | [IW_IOCTL_IDX(SIOCGIWRATE)] = (iw_handler) cfg80211_wext_giwrate, | ||
1417 | [IW_IOCTL_IDX(SIOCSIWRTS)] = (iw_handler) cfg80211_wext_siwrts, | ||
1418 | [IW_IOCTL_IDX(SIOCGIWRTS)] = (iw_handler) cfg80211_wext_giwrts, | ||
1419 | [IW_IOCTL_IDX(SIOCSIWFRAG)] = (iw_handler) cfg80211_wext_siwfrag, | ||
1420 | [IW_IOCTL_IDX(SIOCGIWFRAG)] = (iw_handler) cfg80211_wext_giwfrag, | ||
1421 | [IW_IOCTL_IDX(SIOCSIWTXPOW)] = (iw_handler) cfg80211_wext_siwtxpower, | ||
1422 | [IW_IOCTL_IDX(SIOCGIWTXPOW)] = (iw_handler) cfg80211_wext_giwtxpower, | ||
1423 | [IW_IOCTL_IDX(SIOCSIWRETRY)] = (iw_handler) cfg80211_wext_siwretry, | ||
1424 | [IW_IOCTL_IDX(SIOCGIWRETRY)] = (iw_handler) cfg80211_wext_giwretry, | ||
1425 | [IW_IOCTL_IDX(SIOCSIWENCODE)] = (iw_handler) cfg80211_wext_siwencode, | ||
1426 | [IW_IOCTL_IDX(SIOCGIWENCODE)] = (iw_handler) cfg80211_wext_giwencode, | ||
1427 | [IW_IOCTL_IDX(SIOCSIWPOWER)] = (iw_handler) cfg80211_wext_siwpower, | ||
1428 | [IW_IOCTL_IDX(SIOCGIWPOWER)] = (iw_handler) cfg80211_wext_giwpower, | ||
1429 | [IW_IOCTL_IDX(SIOCSIWGENIE)] = (iw_handler) cfg80211_wext_siwgenie, | ||
1430 | [IW_IOCTL_IDX(SIOCSIWAUTH)] = (iw_handler) cfg80211_wext_siwauth, | ||
1431 | [IW_IOCTL_IDX(SIOCGIWAUTH)] = (iw_handler) cfg80211_wext_giwauth, | ||
1432 | [IW_IOCTL_IDX(SIOCSIWENCODEEXT)]= (iw_handler) cfg80211_wext_siwencodeext, | ||
1433 | }; | ||
1434 | |||
1435 | const struct iw_handler_def cfg80211_wext_handler = { | ||
1436 | .num_standard = ARRAY_SIZE(cfg80211_handlers), | ||
1437 | .standard = cfg80211_handlers, | ||
1438 | .get_wireless_stats = cfg80211_wireless_stats, | ||
1439 | }; | ||
diff --git a/net/wireless/wext-compat.h b/net/wireless/wext-compat.h new file mode 100644 index 000000000000..9a3774749589 --- /dev/null +++ b/net/wireless/wext-compat.h | |||
@@ -0,0 +1,50 @@ | |||
1 | #ifndef __WEXT_COMPAT | ||
2 | #define __WEXT_COMPAT | ||
3 | |||
4 | #include <net/iw_handler.h> | ||
5 | #include <linux/wireless.h> | ||
6 | |||
7 | int cfg80211_ibss_wext_siwfreq(struct net_device *dev, | ||
8 | struct iw_request_info *info, | ||
9 | struct iw_freq *freq, char *extra); | ||
10 | int cfg80211_ibss_wext_giwfreq(struct net_device *dev, | ||
11 | struct iw_request_info *info, | ||
12 | struct iw_freq *freq, char *extra); | ||
13 | int cfg80211_ibss_wext_siwap(struct net_device *dev, | ||
14 | struct iw_request_info *info, | ||
15 | struct sockaddr *ap_addr, char *extra); | ||
16 | int cfg80211_ibss_wext_giwap(struct net_device *dev, | ||
17 | struct iw_request_info *info, | ||
18 | struct sockaddr *ap_addr, char *extra); | ||
19 | int cfg80211_ibss_wext_siwessid(struct net_device *dev, | ||
20 | struct iw_request_info *info, | ||
21 | struct iw_point *data, char *ssid); | ||
22 | int cfg80211_ibss_wext_giwessid(struct net_device *dev, | ||
23 | struct iw_request_info *info, | ||
24 | struct iw_point *data, char *ssid); | ||
25 | |||
26 | int cfg80211_mgd_wext_siwfreq(struct net_device *dev, | ||
27 | struct iw_request_info *info, | ||
28 | struct iw_freq *freq, char *extra); | ||
29 | int cfg80211_mgd_wext_giwfreq(struct net_device *dev, | ||
30 | struct iw_request_info *info, | ||
31 | struct iw_freq *freq, char *extra); | ||
32 | int cfg80211_mgd_wext_siwap(struct net_device *dev, | ||
33 | struct iw_request_info *info, | ||
34 | struct sockaddr *ap_addr, char *extra); | ||
35 | int cfg80211_mgd_wext_giwap(struct net_device *dev, | ||
36 | struct iw_request_info *info, | ||
37 | struct sockaddr *ap_addr, char *extra); | ||
38 | int cfg80211_mgd_wext_siwessid(struct net_device *dev, | ||
39 | struct iw_request_info *info, | ||
40 | struct iw_point *data, char *ssid); | ||
41 | int cfg80211_mgd_wext_giwessid(struct net_device *dev, | ||
42 | struct iw_request_info *info, | ||
43 | struct iw_point *data, char *ssid); | ||
44 | |||
45 | struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy, | ||
46 | struct iw_freq *freq); | ||
47 | |||
48 | |||
49 | extern const struct iw_handler_def cfg80211_wext_handler; | ||
50 | #endif /* __WEXT_COMPAT */ | ||
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c index 4c689fd865b0..7bacbd1c2af6 100644 --- a/net/wireless/wext-sme.c +++ b/net/wireless/wext-sme.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <linux/etherdevice.h> | 8 | #include <linux/etherdevice.h> |
9 | #include <linux/if_arp.h> | 9 | #include <linux/if_arp.h> |
10 | #include <net/cfg80211.h> | 10 | #include <net/cfg80211.h> |
11 | #include "wext-compat.h" | ||
11 | #include "nl80211.h" | 12 | #include "nl80211.h" |
12 | 13 | ||
13 | int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev, | 14 | int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev, |
@@ -108,8 +109,6 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev, | |||
108 | cfg80211_unlock_rdev(rdev); | 109 | cfg80211_unlock_rdev(rdev); |
109 | return err; | 110 | return err; |
110 | } | 111 | } |
111 | /* temporary symbol - mark GPL - in the future the handler won't be */ | ||
112 | EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_siwfreq); | ||
113 | 112 | ||
114 | int cfg80211_mgd_wext_giwfreq(struct net_device *dev, | 113 | int cfg80211_mgd_wext_giwfreq(struct net_device *dev, |
115 | struct iw_request_info *info, | 114 | struct iw_request_info *info, |
@@ -138,8 +137,6 @@ int cfg80211_mgd_wext_giwfreq(struct net_device *dev, | |||
138 | /* no channel if not joining */ | 137 | /* no channel if not joining */ |
139 | return -EINVAL; | 138 | return -EINVAL; |
140 | } | 139 | } |
141 | /* temporary symbol - mark GPL - in the future the handler won't be */ | ||
142 | EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_giwfreq); | ||
143 | 140 | ||
144 | int cfg80211_mgd_wext_siwessid(struct net_device *dev, | 141 | int cfg80211_mgd_wext_siwessid(struct net_device *dev, |
145 | struct iw_request_info *info, | 142 | struct iw_request_info *info, |
@@ -195,8 +192,6 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev, | |||
195 | cfg80211_unlock_rdev(wiphy_to_dev(wdev->wiphy)); | 192 | cfg80211_unlock_rdev(wiphy_to_dev(wdev->wiphy)); |
196 | return err; | 193 | return err; |
197 | } | 194 | } |
198 | /* temporary symbol - mark GPL - in the future the handler won't be */ | ||
199 | EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_siwessid); | ||
200 | 195 | ||
201 | int cfg80211_mgd_wext_giwessid(struct net_device *dev, | 196 | int cfg80211_mgd_wext_giwessid(struct net_device *dev, |
202 | struct iw_request_info *info, | 197 | struct iw_request_info *info, |
@@ -221,8 +216,6 @@ int cfg80211_mgd_wext_giwessid(struct net_device *dev, | |||
221 | 216 | ||
222 | return 0; | 217 | return 0; |
223 | } | 218 | } |
224 | /* temporary symbol - mark GPL - in the future the handler won't be */ | ||
225 | EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_giwessid); | ||
226 | 219 | ||
227 | int cfg80211_mgd_wext_siwap(struct net_device *dev, | 220 | int cfg80211_mgd_wext_siwap(struct net_device *dev, |
228 | struct iw_request_info *info, | 221 | struct iw_request_info *info, |
@@ -276,8 +269,6 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev, | |||
276 | cfg80211_unlock_rdev(wiphy_to_dev(wdev->wiphy)); | 269 | cfg80211_unlock_rdev(wiphy_to_dev(wdev->wiphy)); |
277 | return err; | 270 | return err; |
278 | } | 271 | } |
279 | /* temporary symbol - mark GPL - in the future the handler won't be */ | ||
280 | EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_siwap); | ||
281 | 272 | ||
282 | int cfg80211_mgd_wext_giwap(struct net_device *dev, | 273 | int cfg80211_mgd_wext_giwap(struct net_device *dev, |
283 | struct iw_request_info *info, | 274 | struct iw_request_info *info, |
@@ -302,8 +293,6 @@ int cfg80211_mgd_wext_giwap(struct net_device *dev, | |||
302 | 293 | ||
303 | return 0; | 294 | return 0; |
304 | } | 295 | } |
305 | /* temporary symbol - mark GPL - in the future the handler won't be */ | ||
306 | EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_giwap); | ||
307 | 296 | ||
308 | int cfg80211_wext_siwgenie(struct net_device *dev, | 297 | int cfg80211_wext_siwgenie(struct net_device *dev, |
309 | struct iw_request_info *info, | 298 | struct iw_request_info *info, |