aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/ibss.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/ibss.c')
-rw-r--r--net/mac80211/ibss.c171
1 files changed, 86 insertions, 85 deletions
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index b2cc1fda6cfd..c691780725a7 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -43,6 +43,8 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata,
43{ 43{
44 u16 auth_alg, auth_transaction, status_code; 44 u16 auth_alg, auth_transaction, status_code;
45 45
46 lockdep_assert_held(&sdata->u.ibss.mtx);
47
46 if (len < 24 + 6) 48 if (len < 24 + 6)
47 return; 49 return;
48 50
@@ -78,6 +80,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
78 u32 bss_change; 80 u32 bss_change;
79 u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; 81 u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
80 82
83 lockdep_assert_held(&ifibss->mtx);
84
81 /* Reset own TSF to allow time synchronization work. */ 85 /* Reset own TSF to allow time synchronization work. */
82 drv_reset_tsf(local); 86 drv_reset_tsf(local);
83 87
@@ -172,11 +176,13 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
172 rcu_assign_pointer(ifibss->presp, skb); 176 rcu_assign_pointer(ifibss->presp, skb);
173 177
174 sdata->vif.bss_conf.beacon_int = beacon_int; 178 sdata->vif.bss_conf.beacon_int = beacon_int;
179 sdata->vif.bss_conf.basic_rates = basic_rates;
175 bss_change = BSS_CHANGED_BEACON_INT; 180 bss_change = BSS_CHANGED_BEACON_INT;
176 bss_change |= ieee80211_reset_erp_info(sdata); 181 bss_change |= ieee80211_reset_erp_info(sdata);
177 bss_change |= BSS_CHANGED_BSSID; 182 bss_change |= BSS_CHANGED_BSSID;
178 bss_change |= BSS_CHANGED_BEACON; 183 bss_change |= BSS_CHANGED_BEACON;
179 bss_change |= BSS_CHANGED_BEACON_ENABLED; 184 bss_change |= BSS_CHANGED_BEACON_ENABLED;
185 bss_change |= BSS_CHANGED_BASIC_RATES;
180 bss_change |= BSS_CHANGED_IBSS; 186 bss_change |= BSS_CHANGED_IBSS;
181 sdata->vif.bss_conf.ibss_joined = true; 187 sdata->vif.bss_conf.ibss_joined = true;
182 ieee80211_bss_info_change_notify(sdata, bss_change); 188 ieee80211_bss_info_change_notify(sdata, bss_change);
@@ -203,6 +209,8 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
203 int i, j; 209 int i, j;
204 u16 beacon_int = cbss->beacon_interval; 210 u16 beacon_int = cbss->beacon_interval;
205 211
212 lockdep_assert_held(&sdata->u.ibss.mtx);
213
206 if (beacon_int < 10) 214 if (beacon_int < 10)
207 beacon_int = 10; 215 beacon_int = 10;
208 216
@@ -447,6 +455,8 @@ static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata)
447 int active = 0; 455 int active = 0;
448 struct sta_info *sta; 456 struct sta_info *sta;
449 457
458 lockdep_assert_held(&sdata->u.ibss.mtx);
459
450 rcu_read_lock(); 460 rcu_read_lock();
451 461
452 list_for_each_entry_rcu(sta, &local->sta_list, list) { 462 list_for_each_entry_rcu(sta, &local->sta_list, list) {
@@ -471,6 +481,8 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
471{ 481{
472 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 482 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
473 483
484 lockdep_assert_held(&ifibss->mtx);
485
474 mod_timer(&ifibss->timer, 486 mod_timer(&ifibss->timer,
475 round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL)); 487 round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL));
476 488
@@ -503,6 +515,8 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
503 u16 capability; 515 u16 capability;
504 int i; 516 int i;
505 517
518 lockdep_assert_held(&ifibss->mtx);
519
506 if (ifibss->fixed_bssid) { 520 if (ifibss->fixed_bssid) {
507 memcpy(bssid, ifibss->bssid, ETH_ALEN); 521 memcpy(bssid, ifibss->bssid, ETH_ALEN);
508 } else { 522 } else {
@@ -529,7 +543,7 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
529 sdata->drop_unencrypted = 0; 543 sdata->drop_unencrypted = 0;
530 544
531 __ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int, 545 __ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int,
532 ifibss->channel, 3, /* first two are basic */ 546 ifibss->channel, ifibss->basic_rates,
533 capability, 0); 547 capability, 0);
534} 548}
535 549
@@ -547,6 +561,8 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
547 int active_ibss; 561 int active_ibss;
548 u16 capability; 562 u16 capability;
549 563
564 lockdep_assert_held(&ifibss->mtx);
565
550 active_ibss = ieee80211_sta_active_ibss(sdata); 566 active_ibss = ieee80211_sta_active_ibss(sdata);
551#ifdef CONFIG_MAC80211_IBSS_DEBUG 567#ifdef CONFIG_MAC80211_IBSS_DEBUG
552 printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n", 568 printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n",
@@ -635,6 +651,8 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
635 struct ieee80211_mgmt *resp; 651 struct ieee80211_mgmt *resp;
636 u8 *pos, *end; 652 u8 *pos, *end;
637 653
654 lockdep_assert_held(&ifibss->mtx);
655
638 if (ifibss->state != IEEE80211_IBSS_MLME_JOINED || 656 if (ifibss->state != IEEE80211_IBSS_MLME_JOINED ||
639 len < 24 + 2 || !ifibss->presp) 657 len < 24 + 2 || !ifibss->presp)
640 return; 658 return;
@@ -727,8 +745,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
727 ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, true); 745 ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, true);
728} 746}
729 747
730static void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, 748void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
731 struct sk_buff *skb) 749 struct sk_buff *skb)
732{ 750{
733 struct ieee80211_rx_status *rx_status; 751 struct ieee80211_rx_status *rx_status;
734 struct ieee80211_mgmt *mgmt; 752 struct ieee80211_mgmt *mgmt;
@@ -738,6 +756,8 @@ static void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
738 mgmt = (struct ieee80211_mgmt *) skb->data; 756 mgmt = (struct ieee80211_mgmt *) skb->data;
739 fc = le16_to_cpu(mgmt->frame_control); 757 fc = le16_to_cpu(mgmt->frame_control);
740 758
759 mutex_lock(&sdata->u.ibss.mtx);
760
741 switch (fc & IEEE80211_FCTL_STYPE) { 761 switch (fc & IEEE80211_FCTL_STYPE) {
742 case IEEE80211_STYPE_PROBE_REQ: 762 case IEEE80211_STYPE_PROBE_REQ:
743 ieee80211_rx_mgmt_probe_req(sdata, mgmt, skb->len); 763 ieee80211_rx_mgmt_probe_req(sdata, mgmt, skb->len);
@@ -755,35 +775,22 @@ static void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
755 break; 775 break;
756 } 776 }
757 777
758 kfree_skb(skb); 778 mutex_unlock(&sdata->u.ibss.mtx);
759} 779}
760 780
761static void ieee80211_ibss_work(struct work_struct *work) 781void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata)
762{ 782{
763 struct ieee80211_sub_if_data *sdata = 783 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
764 container_of(work, struct ieee80211_sub_if_data, u.ibss.work);
765 struct ieee80211_local *local = sdata->local;
766 struct ieee80211_if_ibss *ifibss;
767 struct sk_buff *skb;
768
769 if (WARN_ON(local->suspended))
770 return;
771
772 if (!ieee80211_sdata_running(sdata))
773 return;
774
775 if (local->scanning)
776 return;
777
778 if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_ADHOC))
779 return;
780 ifibss = &sdata->u.ibss;
781 784
782 while ((skb = skb_dequeue(&ifibss->skb_queue))) 785 mutex_lock(&ifibss->mtx);
783 ieee80211_ibss_rx_queued_mgmt(sdata, skb);
784 786
785 if (!test_and_clear_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request)) 787 /*
786 return; 788 * Work could be scheduled after scan or similar
789 * when we aren't even joined (or trying) with a
790 * network.
791 */
792 if (!ifibss->ssid_len)
793 goto out;
787 794
788 switch (ifibss->state) { 795 switch (ifibss->state) {
789 case IEEE80211_IBSS_MLME_SEARCH: 796 case IEEE80211_IBSS_MLME_SEARCH:
@@ -796,6 +803,9 @@ static void ieee80211_ibss_work(struct work_struct *work)
796 WARN_ON(1); 803 WARN_ON(1);
797 break; 804 break;
798 } 805 }
806
807 out:
808 mutex_unlock(&ifibss->mtx);
799} 809}
800 810
801static void ieee80211_ibss_timer(unsigned long data) 811static void ieee80211_ibss_timer(unsigned long data)
@@ -810,8 +820,7 @@ static void ieee80211_ibss_timer(unsigned long data)
810 return; 820 return;
811 } 821 }
812 822
813 set_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request); 823 ieee80211_queue_work(&local->hw, &sdata->work);
814 ieee80211_queue_work(&local->hw, &ifibss->work);
815} 824}
816 825
817#ifdef CONFIG_PM 826#ifdef CONFIG_PM
@@ -819,7 +828,6 @@ void ieee80211_ibss_quiesce(struct ieee80211_sub_if_data *sdata)
819{ 828{
820 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 829 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
821 830
822 cancel_work_sync(&ifibss->work);
823 if (del_timer_sync(&ifibss->timer)) 831 if (del_timer_sync(&ifibss->timer))
824 ifibss->timer_running = true; 832 ifibss->timer_running = true;
825} 833}
@@ -839,10 +847,9 @@ void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata)
839{ 847{
840 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 848 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
841 849
842 INIT_WORK(&ifibss->work, ieee80211_ibss_work);
843 setup_timer(&ifibss->timer, ieee80211_ibss_timer, 850 setup_timer(&ifibss->timer, ieee80211_ibss_timer,
844 (unsigned long) sdata); 851 (unsigned long) sdata);
845 skb_queue_head_init(&ifibss->skb_queue); 852 mutex_init(&ifibss->mtx);
846} 853}
847 854
848/* scan finished notification */ 855/* scan finished notification */
@@ -856,45 +863,28 @@ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local)
856 continue; 863 continue;
857 if (sdata->vif.type != NL80211_IFTYPE_ADHOC) 864 if (sdata->vif.type != NL80211_IFTYPE_ADHOC)
858 continue; 865 continue;
859 if (!sdata->u.ibss.ssid_len)
860 continue;
861 sdata->u.ibss.last_scan_completed = jiffies; 866 sdata->u.ibss.last_scan_completed = jiffies;
862 mod_timer(&sdata->u.ibss.timer, 0); 867 ieee80211_queue_work(&local->hw, &sdata->work);
863 } 868 }
864 mutex_unlock(&local->iflist_mtx); 869 mutex_unlock(&local->iflist_mtx);
865} 870}
866 871
867ieee80211_rx_result
868ieee80211_ibss_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
869{
870 struct ieee80211_local *local = sdata->local;
871 struct ieee80211_mgmt *mgmt;
872 u16 fc;
873
874 if (skb->len < 24)
875 return RX_DROP_MONITOR;
876
877 mgmt = (struct ieee80211_mgmt *) skb->data;
878 fc = le16_to_cpu(mgmt->frame_control);
879
880 switch (fc & IEEE80211_FCTL_STYPE) {
881 case IEEE80211_STYPE_PROBE_RESP:
882 case IEEE80211_STYPE_BEACON:
883 case IEEE80211_STYPE_PROBE_REQ:
884 case IEEE80211_STYPE_AUTH:
885 skb_queue_tail(&sdata->u.ibss.skb_queue, skb);
886 ieee80211_queue_work(&local->hw, &sdata->u.ibss.work);
887 return RX_QUEUED;
888 }
889
890 return RX_DROP_MONITOR;
891}
892
893int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, 872int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
894 struct cfg80211_ibss_params *params) 873 struct cfg80211_ibss_params *params)
895{ 874{
896 struct sk_buff *skb; 875 struct sk_buff *skb;
897 876
877 skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom +
878 36 /* bitrates */ +
879 34 /* SSID */ +
880 3 /* DS params */ +
881 4 /* IBSS params */ +
882 params->ie_len);
883 if (!skb)
884 return -ENOMEM;
885
886 mutex_lock(&sdata->u.ibss.mtx);
887
898 if (params->bssid) { 888 if (params->bssid) {
899 memcpy(sdata->u.ibss.bssid, params->bssid, ETH_ALEN); 889 memcpy(sdata->u.ibss.bssid, params->bssid, ETH_ALEN);
900 sdata->u.ibss.fixed_bssid = true; 890 sdata->u.ibss.fixed_bssid = true;
@@ -902,6 +892,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
902 sdata->u.ibss.fixed_bssid = false; 892 sdata->u.ibss.fixed_bssid = false;
903 893
904 sdata->u.ibss.privacy = params->privacy; 894 sdata->u.ibss.privacy = params->privacy;
895 sdata->u.ibss.basic_rates = params->basic_rates;
905 896
906 sdata->vif.bss_conf.beacon_int = params->beacon_interval; 897 sdata->vif.bss_conf.beacon_int = params->beacon_interval;
907 898
@@ -922,34 +913,18 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
922 sdata->u.ibss.ie_len = params->ie_len; 913 sdata->u.ibss.ie_len = params->ie_len;
923 } 914 }
924 915
925 skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom +
926 36 /* bitrates */ +
927 34 /* SSID */ +
928 3 /* DS params */ +
929 4 /* IBSS params */ +
930 params->ie_len);
931 if (!skb)
932 return -ENOMEM;
933
934 sdata->u.ibss.skb = skb; 916 sdata->u.ibss.skb = skb;
935 sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH; 917 sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH;
936 sdata->u.ibss.ibss_join_req = jiffies; 918 sdata->u.ibss.ibss_join_req = jiffies;
937 919
938 memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN); 920 memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN);
939
940 /*
941 * The ssid_len setting below is used to see whether
942 * we are active, and we need all other settings
943 * before that may get visible.
944 */
945 mb();
946
947 sdata->u.ibss.ssid_len = params->ssid_len; 921 sdata->u.ibss.ssid_len = params->ssid_len;
948 922
949 ieee80211_recalc_idle(sdata->local); 923 ieee80211_recalc_idle(sdata->local);
950 924
951 set_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request); 925 ieee80211_queue_work(&sdata->local->hw, &sdata->work);
952 ieee80211_queue_work(&sdata->local->hw, &sdata->u.ibss.work); 926
927 mutex_unlock(&sdata->u.ibss.mtx);
953 928
954 return 0; 929 return 0;
955} 930}
@@ -957,11 +932,33 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
957int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) 932int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
958{ 933{
959 struct sk_buff *skb; 934 struct sk_buff *skb;
935 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
936 struct ieee80211_local *local = sdata->local;
937 struct cfg80211_bss *cbss;
938 u16 capability;
939 int active_ibss;
960 940
961 del_timer_sync(&sdata->u.ibss.timer); 941 mutex_lock(&sdata->u.ibss.mtx);
962 clear_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request); 942
963 cancel_work_sync(&sdata->u.ibss.work); 943 active_ibss = ieee80211_sta_active_ibss(sdata);
964 clear_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request); 944
945 if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) {
946 capability = WLAN_CAPABILITY_IBSS;
947
948 if (ifibss->privacy)
949 capability |= WLAN_CAPABILITY_PRIVACY;
950
951 cbss = cfg80211_get_bss(local->hw.wiphy, ifibss->channel,
952 ifibss->bssid, ifibss->ssid,
953 ifibss->ssid_len, WLAN_CAPABILITY_IBSS |
954 WLAN_CAPABILITY_PRIVACY,
955 capability);
956
957 if (cbss) {
958 cfg80211_unlink_bss(local->hw.wiphy, cbss);
959 cfg80211_put_bss(cbss);
960 }
961 }
965 962
966 sta_info_flush(sdata->local, sdata); 963 sta_info_flush(sdata->local, sdata);
967 964
@@ -975,10 +972,14 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
975 synchronize_rcu(); 972 synchronize_rcu();
976 kfree_skb(skb); 973 kfree_skb(skb);
977 974
978 skb_queue_purge(&sdata->u.ibss.skb_queue); 975 skb_queue_purge(&sdata->skb_queue);
979 memset(sdata->u.ibss.bssid, 0, ETH_ALEN); 976 memset(sdata->u.ibss.bssid, 0, ETH_ALEN);
980 sdata->u.ibss.ssid_len = 0; 977 sdata->u.ibss.ssid_len = 0;
981 978
979 del_timer_sync(&sdata->u.ibss.timer);
980
981 mutex_unlock(&sdata->u.ibss.mtx);
982
982 ieee80211_recalc_idle(sdata->local); 983 ieee80211_recalc_idle(sdata->local);
983 984
984 return 0; 985 return 0;