aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c259
1 files changed, 180 insertions, 79 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 841b8450b3de..7ecda9d59d8a 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -30,7 +30,7 @@
30#define IEEE80211_ASSOC_TIMEOUT (HZ / 5) 30#define IEEE80211_ASSOC_TIMEOUT (HZ / 5)
31#define IEEE80211_ASSOC_MAX_TRIES 3 31#define IEEE80211_ASSOC_MAX_TRIES 3
32#define IEEE80211_MONITORING_INTERVAL (2 * HZ) 32#define IEEE80211_MONITORING_INTERVAL (2 * HZ)
33#define IEEE80211_PROBE_INTERVAL (60 * HZ) 33#define IEEE80211_PROBE_IDLE_TIME (60 * HZ)
34#define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ) 34#define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ)
35 35
36/* utils */ 36/* utils */
@@ -82,38 +82,23 @@ static int ieee80211_compatible_rates(struct ieee80211_bss *bss,
82 82
83/* frame sending functions */ 83/* frame sending functions */
84 84
85static void add_extra_ies(struct sk_buff *skb, u8 *ies, size_t ies_len)
86{
87 if (ies)
88 memcpy(skb_put(skb, ies_len), ies, ies_len);
89}
90
91static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) 85static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
92{ 86{
93 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 87 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
94 struct ieee80211_local *local = sdata->local; 88 struct ieee80211_local *local = sdata->local;
95 struct sk_buff *skb; 89 struct sk_buff *skb;
96 struct ieee80211_mgmt *mgmt; 90 struct ieee80211_mgmt *mgmt;
97 u8 *pos, *ies, *ht_ie, *e_ies; 91 u8 *pos, *ies, *ht_ie;
98 int i, len, count, rates_len, supp_rates_len; 92 int i, len, count, rates_len, supp_rates_len;
99 u16 capab; 93 u16 capab;
100 struct ieee80211_bss *bss; 94 struct ieee80211_bss *bss;
101 int wmm = 0; 95 int wmm = 0;
102 struct ieee80211_supported_band *sband; 96 struct ieee80211_supported_band *sband;
103 u32 rates = 0; 97 u32 rates = 0;
104 size_t e_ies_len;
105
106 if (ifmgd->flags & IEEE80211_IBSS_PREV_BSSID_SET) {
107 e_ies = sdata->u.mgd.ie_reassocreq;
108 e_ies_len = sdata->u.mgd.ie_reassocreq_len;
109 } else {
110 e_ies = sdata->u.mgd.ie_assocreq;
111 e_ies_len = sdata->u.mgd.ie_assocreq_len;
112 }
113 98
114 skb = dev_alloc_skb(local->hw.extra_tx_headroom + 99 skb = dev_alloc_skb(local->hw.extra_tx_headroom +
115 sizeof(*mgmt) + 200 + ifmgd->extra_ie_len + 100 sizeof(*mgmt) + 200 + ifmgd->extra_ie_len +
116 ifmgd->ssid_len + e_ies_len); 101 ifmgd->ssid_len);
117 if (!skb) { 102 if (!skb) {
118 printk(KERN_DEBUG "%s: failed to allocate buffer for assoc " 103 printk(KERN_DEBUG "%s: failed to allocate buffer for assoc "
119 "frame\n", sdata->dev->name); 104 "frame\n", sdata->dev->name);
@@ -304,8 +289,6 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
304 memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); 289 memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
305 } 290 }
306 291
307 add_extra_ies(skb, e_ies, e_ies_len);
308
309 kfree(ifmgd->assocreq_ies); 292 kfree(ifmgd->assocreq_ies);
310 ifmgd->assocreq_ies_len = (skb->data + skb->len) - ies; 293 ifmgd->assocreq_ies_len = (skb->data + skb->len) - ies;
311 ifmgd->assocreq_ies = kmalloc(ifmgd->assocreq_ies_len, GFP_KERNEL); 294 ifmgd->assocreq_ies = kmalloc(ifmgd->assocreq_ies_len, GFP_KERNEL);
@@ -323,19 +306,8 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
323 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 306 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
324 struct sk_buff *skb; 307 struct sk_buff *skb;
325 struct ieee80211_mgmt *mgmt; 308 struct ieee80211_mgmt *mgmt;
326 u8 *ies;
327 size_t ies_len;
328
329 if (stype == IEEE80211_STYPE_DEAUTH) {
330 ies = sdata->u.mgd.ie_deauth;
331 ies_len = sdata->u.mgd.ie_deauth_len;
332 } else {
333 ies = sdata->u.mgd.ie_disassoc;
334 ies_len = sdata->u.mgd.ie_disassoc_len;
335 }
336 309
337 skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 310 skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt));
338 ies_len);
339 if (!skb) { 311 if (!skb) {
340 printk(KERN_DEBUG "%s: failed to allocate buffer for " 312 printk(KERN_DEBUG "%s: failed to allocate buffer for "
341 "deauth/disassoc frame\n", sdata->dev->name); 313 "deauth/disassoc frame\n", sdata->dev->name);
@@ -353,8 +325,6 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
353 /* u.deauth.reason_code == u.disassoc.reason_code */ 325 /* u.deauth.reason_code == u.disassoc.reason_code */
354 mgmt->u.deauth.reason_code = cpu_to_le16(reason); 326 mgmt->u.deauth.reason_code = cpu_to_le16(reason);
355 327
356 add_extra_ies(skb, ies, ies_len);
357
358 ieee80211_tx_skb(sdata, skb, ifmgd->flags & IEEE80211_STA_MFP_ENABLED); 328 ieee80211_tx_skb(sdata, skb, ifmgd->flags & IEEE80211_STA_MFP_ENABLED);
359} 329}
360 330
@@ -640,6 +610,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
640 bss_info_changed |= ieee80211_handle_bss_capability(sdata, 610 bss_info_changed |= ieee80211_handle_bss_capability(sdata,
641 bss->cbss.capability, bss->has_erp_value, bss->erp_value); 611 bss->cbss.capability, bss->has_erp_value, bss->erp_value);
642 612
613 cfg80211_hold_bss(&bss->cbss);
614
643 ieee80211_rx_bss_put(local, bss); 615 ieee80211_rx_bss_put(local, bss);
644 } 616 }
645 617
@@ -682,6 +654,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
682static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata) 654static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata)
683{ 655{
684 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 656 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
657 struct ieee80211_local *local = sdata->local;
685 658
686 ifmgd->direct_probe_tries++; 659 ifmgd->direct_probe_tries++;
687 if (ifmgd->direct_probe_tries > IEEE80211_AUTH_MAX_TRIES) { 660 if (ifmgd->direct_probe_tries > IEEE80211_AUTH_MAX_TRIES) {
@@ -697,6 +670,13 @@ static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata)
697 ieee80211_rx_bss_remove(sdata, ifmgd->bssid, 670 ieee80211_rx_bss_remove(sdata, ifmgd->bssid,
698 sdata->local->hw.conf.channel->center_freq, 671 sdata->local->hw.conf.channel->center_freq,
699 ifmgd->ssid, ifmgd->ssid_len); 672 ifmgd->ssid, ifmgd->ssid_len);
673
674 /*
675 * We might have a pending scan which had no chance to run yet
676 * due to state == IEEE80211_STA_MLME_DIRECT_PROBE.
677 * Hence, queue the STAs work again
678 */
679 queue_work(local->hw.workqueue, &ifmgd->work);
700 return; 680 return;
701 } 681 }
702 682
@@ -721,6 +701,9 @@ static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata)
721static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata) 701static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata)
722{ 702{
723 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 703 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
704 struct ieee80211_local *local = sdata->local;
705 u8 *ies;
706 size_t ies_len;
724 707
725 ifmgd->auth_tries++; 708 ifmgd->auth_tries++;
726 if (ifmgd->auth_tries > IEEE80211_AUTH_MAX_TRIES) { 709 if (ifmgd->auth_tries > IEEE80211_AUTH_MAX_TRIES) {
@@ -732,6 +715,13 @@ static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata)
732 ieee80211_rx_bss_remove(sdata, ifmgd->bssid, 715 ieee80211_rx_bss_remove(sdata, ifmgd->bssid,
733 sdata->local->hw.conf.channel->center_freq, 716 sdata->local->hw.conf.channel->center_freq,
734 ifmgd->ssid, ifmgd->ssid_len); 717 ifmgd->ssid, ifmgd->ssid_len);
718
719 /*
720 * We might have a pending scan which had no chance to run yet
721 * due to state == IEEE80211_STA_MLME_AUTHENTICATE.
722 * Hence, queue the STAs work again
723 */
724 queue_work(local->hw.workqueue, &ifmgd->work);
735 return; 725 return;
736 } 726 }
737 727
@@ -739,7 +729,14 @@ static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata)
739 printk(KERN_DEBUG "%s: authenticate with AP %pM\n", 729 printk(KERN_DEBUG "%s: authenticate with AP %pM\n",
740 sdata->dev->name, ifmgd->bssid); 730 sdata->dev->name, ifmgd->bssid);
741 731
742 ieee80211_send_auth(sdata, 1, ifmgd->auth_alg, NULL, 0, 732 if (ifmgd->flags & IEEE80211_STA_EXT_SME) {
733 ies = ifmgd->sme_auth_ie;
734 ies_len = ifmgd->sme_auth_ie_len;
735 } else {
736 ies = NULL;
737 ies_len = 0;
738 }
739 ieee80211_send_auth(sdata, 1, ifmgd->auth_alg, ies, ies_len,
743 ifmgd->bssid, 0); 740 ifmgd->bssid, 0);
744 ifmgd->auth_transaction = 2; 741 ifmgd->auth_transaction = 2;
745 742
@@ -756,6 +753,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
756{ 753{
757 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 754 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
758 struct ieee80211_local *local = sdata->local; 755 struct ieee80211_local *local = sdata->local;
756 struct ieee80211_conf *conf = &local_to_hw(local)->conf;
757 struct ieee80211_bss *bss;
759 struct sta_info *sta; 758 struct sta_info *sta;
760 u32 changed = 0, config_changed = 0; 759 u32 changed = 0, config_changed = 0;
761 760
@@ -779,6 +778,15 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
779 778
780 ieee80211_sta_tear_down_BA_sessions(sta); 779 ieee80211_sta_tear_down_BA_sessions(sta);
781 780
781 bss = ieee80211_rx_bss_get(local, ifmgd->bssid,
782 conf->channel->center_freq,
783 ifmgd->ssid, ifmgd->ssid_len);
784
785 if (bss) {
786 cfg80211_unhold_bss(&bss->cbss);
787 ieee80211_rx_bss_put(local, bss);
788 }
789
782 if (self_disconnected) { 790 if (self_disconnected) {
783 if (deauth) 791 if (deauth)
784 ieee80211_send_deauth_disassoc(sdata, 792 ieee80211_send_deauth_disassoc(sdata,
@@ -854,7 +862,7 @@ static int ieee80211_privacy_mismatch(struct ieee80211_sub_if_data *sdata)
854 int wep_privacy; 862 int wep_privacy;
855 int privacy_invoked; 863 int privacy_invoked;
856 864
857 if (!ifmgd || (ifmgd->flags & IEEE80211_STA_MIXED_CELL)) 865 if (!ifmgd || (ifmgd->flags & IEEE80211_STA_EXT_SME))
858 return 0; 866 return 0;
859 867
860 bss = ieee80211_rx_bss_get(local, ifmgd->bssid, 868 bss = ieee80211_rx_bss_get(local, ifmgd->bssid,
@@ -878,6 +886,7 @@ static int ieee80211_privacy_mismatch(struct ieee80211_sub_if_data *sdata)
878static void ieee80211_associate(struct ieee80211_sub_if_data *sdata) 886static void ieee80211_associate(struct ieee80211_sub_if_data *sdata)
879{ 887{
880 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 888 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
889 struct ieee80211_local *local = sdata->local;
881 890
882 ifmgd->assoc_tries++; 891 ifmgd->assoc_tries++;
883 if (ifmgd->assoc_tries > IEEE80211_ASSOC_MAX_TRIES) { 892 if (ifmgd->assoc_tries > IEEE80211_ASSOC_MAX_TRIES) {
@@ -889,6 +898,12 @@ static void ieee80211_associate(struct ieee80211_sub_if_data *sdata)
889 ieee80211_rx_bss_remove(sdata, ifmgd->bssid, 898 ieee80211_rx_bss_remove(sdata, ifmgd->bssid,
890 sdata->local->hw.conf.channel->center_freq, 899 sdata->local->hw.conf.channel->center_freq,
891 ifmgd->ssid, ifmgd->ssid_len); 900 ifmgd->ssid, ifmgd->ssid_len);
901 /*
902 * We might have a pending scan which had no chance to run yet
903 * due to state == IEEE80211_STA_MLME_ASSOCIATE.
904 * Hence, queue the STAs work again
905 */
906 queue_work(local->hw.workqueue, &ifmgd->work);
892 return; 907 return;
893 } 908 }
894 909
@@ -907,13 +922,55 @@ static void ieee80211_associate(struct ieee80211_sub_if_data *sdata)
907 mod_timer(&ifmgd->timer, jiffies + IEEE80211_ASSOC_TIMEOUT); 922 mod_timer(&ifmgd->timer, jiffies + IEEE80211_ASSOC_TIMEOUT);
908} 923}
909 924
925void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
926 struct ieee80211_hdr *hdr)
927{
928 /*
929 * We can postpone the mgd.timer whenever receiving unicast frames
930 * from AP because we know that the connection is working both ways
931 * at that time. But multicast frames (and hence also beacons) must
932 * be ignored here, because we need to trigger the timer during
933 * data idle periods for sending the periodical probe request to
934 * the AP.
935 */
936 if (!is_multicast_ether_addr(hdr->addr1))
937 mod_timer(&sdata->u.mgd.timer,
938 jiffies + IEEE80211_MONITORING_INTERVAL);
939}
940
941void ieee80211_beacon_loss_work(struct work_struct *work)
942{
943 struct ieee80211_sub_if_data *sdata =
944 container_of(work, struct ieee80211_sub_if_data,
945 u.mgd.beacon_loss_work);
946 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
947
948 printk(KERN_DEBUG "%s: driver reports beacon loss from AP %pM "
949 "- sending probe request\n", sdata->dev->name,
950 sdata->u.mgd.bssid);
951
952 ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL;
953 ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid,
954 ifmgd->ssid_len, NULL, 0);
955
956 mod_timer(&ifmgd->timer, jiffies + IEEE80211_MONITORING_INTERVAL);
957}
958
959void ieee80211_beacon_loss(struct ieee80211_vif *vif)
960{
961 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
962
963 queue_work(sdata->local->hw.workqueue,
964 &sdata->u.mgd.beacon_loss_work);
965}
966EXPORT_SYMBOL(ieee80211_beacon_loss);
910 967
911static void ieee80211_associated(struct ieee80211_sub_if_data *sdata) 968static void ieee80211_associated(struct ieee80211_sub_if_data *sdata)
912{ 969{
913 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 970 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
914 struct ieee80211_local *local = sdata->local; 971 struct ieee80211_local *local = sdata->local;
915 struct sta_info *sta; 972 struct sta_info *sta;
916 int disassoc; 973 bool disassoc = false;
917 974
918 /* TODO: start monitoring current AP signal quality and number of 975 /* TODO: start monitoring current AP signal quality and number of
919 * missed beacons. Scan other channels every now and then and search 976 * missed beacons. Scan other channels every now and then and search
@@ -928,36 +985,45 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata)
928 if (!sta) { 985 if (!sta) {
929 printk(KERN_DEBUG "%s: No STA entry for own AP %pM\n", 986 printk(KERN_DEBUG "%s: No STA entry for own AP %pM\n",
930 sdata->dev->name, ifmgd->bssid); 987 sdata->dev->name, ifmgd->bssid);
931 disassoc = 1; 988 disassoc = true;
932 } else { 989 goto unlock;
933 disassoc = 0;
934 if (time_after(jiffies,
935 sta->last_rx + IEEE80211_MONITORING_INTERVAL)) {
936 if (ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) {
937 printk(KERN_DEBUG "%s: No ProbeResp from "
938 "current AP %pM - assume out of "
939 "range\n",
940 sdata->dev->name, ifmgd->bssid);
941 disassoc = 1;
942 } else
943 ieee80211_send_probe_req(sdata, ifmgd->bssid,
944 ifmgd->ssid,
945 ifmgd->ssid_len,
946 NULL, 0);
947 ifmgd->flags ^= IEEE80211_STA_PROBEREQ_POLL;
948 } else {
949 ifmgd->flags &= ~IEEE80211_STA_PROBEREQ_POLL;
950 if (time_after(jiffies, ifmgd->last_probe +
951 IEEE80211_PROBE_INTERVAL)) {
952 ifmgd->last_probe = jiffies;
953 ieee80211_send_probe_req(sdata, ifmgd->bssid,
954 ifmgd->ssid,
955 ifmgd->ssid_len,
956 NULL, 0);
957 }
958 }
959 } 990 }
960 991
992 if ((ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) &&
993 time_after(jiffies, sta->last_rx + IEEE80211_MONITORING_INTERVAL)) {
994 printk(KERN_DEBUG "%s: no probe response from AP %pM "
995 "- disassociating\n",
996 sdata->dev->name, ifmgd->bssid);
997 disassoc = true;
998 ifmgd->flags &= ~IEEE80211_STA_PROBEREQ_POLL;
999 goto unlock;
1000 }
1001
1002 /*
1003 * Beacon filtering is only enabled with power save and then the
1004 * stack should not check for beacon loss.
1005 */
1006 if (!((local->hw.flags & IEEE80211_HW_BEACON_FILTER) &&
1007 (local->hw.conf.flags & IEEE80211_CONF_PS)) &&
1008 time_after(jiffies,
1009 ifmgd->last_beacon + IEEE80211_MONITORING_INTERVAL)) {
1010 printk(KERN_DEBUG "%s: beacon loss from AP %pM "
1011 "- sending probe request\n",
1012 sdata->dev->name, ifmgd->bssid);
1013 ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL;
1014 ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid,
1015 ifmgd->ssid_len, NULL, 0);
1016 goto unlock;
1017
1018 }
1019
1020 if (time_after(jiffies, sta->last_rx + IEEE80211_PROBE_IDLE_TIME)) {
1021 ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL;
1022 ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid,
1023 ifmgd->ssid_len, NULL, 0);
1024 }
1025
1026 unlock:
961 rcu_read_unlock(); 1027 rcu_read_unlock();
962 1028
963 if (disassoc) 1029 if (disassoc)
@@ -975,7 +1041,11 @@ static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata)
975 1041
976 printk(KERN_DEBUG "%s: authenticated\n", sdata->dev->name); 1042 printk(KERN_DEBUG "%s: authenticated\n", sdata->dev->name);
977 ifmgd->flags |= IEEE80211_STA_AUTHENTICATED; 1043 ifmgd->flags |= IEEE80211_STA_AUTHENTICATED;
978 ieee80211_associate(sdata); 1044 if (ifmgd->flags & IEEE80211_STA_EXT_SME) {
1045 /* Wait for SME to request association */
1046 ifmgd->state = IEEE80211_STA_MLME_DISABLED;
1047 } else
1048 ieee80211_associate(sdata);
979} 1049}
980 1050
981 1051
@@ -1061,12 +1131,15 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
1061 switch (ifmgd->auth_alg) { 1131 switch (ifmgd->auth_alg) {
1062 case WLAN_AUTH_OPEN: 1132 case WLAN_AUTH_OPEN:
1063 case WLAN_AUTH_LEAP: 1133 case WLAN_AUTH_LEAP:
1134 case WLAN_AUTH_FT:
1064 ieee80211_auth_completed(sdata); 1135 ieee80211_auth_completed(sdata);
1136 cfg80211_send_rx_auth(sdata->dev, (u8 *) mgmt, len);
1065 break; 1137 break;
1066 case WLAN_AUTH_SHARED_KEY: 1138 case WLAN_AUTH_SHARED_KEY:
1067 if (ifmgd->auth_transaction == 4) 1139 if (ifmgd->auth_transaction == 4) {
1068 ieee80211_auth_completed(sdata); 1140 ieee80211_auth_completed(sdata);
1069 else 1141 cfg80211_send_rx_auth(sdata->dev, (u8 *) mgmt, len);
1142 } else
1070 ieee80211_auth_challenge(sdata, mgmt, len); 1143 ieee80211_auth_challenge(sdata, mgmt, len);
1071 break; 1144 break;
1072 } 1145 }
@@ -1092,9 +1165,10 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
1092 printk(KERN_DEBUG "%s: deauthenticated (Reason: %u)\n", 1165 printk(KERN_DEBUG "%s: deauthenticated (Reason: %u)\n",
1093 sdata->dev->name, reason_code); 1166 sdata->dev->name, reason_code);
1094 1167
1095 if (ifmgd->state == IEEE80211_STA_MLME_AUTHENTICATE || 1168 if (!(ifmgd->flags & IEEE80211_STA_EXT_SME) &&
1096 ifmgd->state == IEEE80211_STA_MLME_ASSOCIATE || 1169 (ifmgd->state == IEEE80211_STA_MLME_AUTHENTICATE ||
1097 ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED) { 1170 ifmgd->state == IEEE80211_STA_MLME_ASSOCIATE ||
1171 ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED)) {
1098 ifmgd->state = IEEE80211_STA_MLME_DIRECT_PROBE; 1172 ifmgd->state = IEEE80211_STA_MLME_DIRECT_PROBE;
1099 mod_timer(&ifmgd->timer, jiffies + 1173 mod_timer(&ifmgd->timer, jiffies +
1100 IEEE80211_RETRY_AUTH_INTERVAL); 1174 IEEE80211_RETRY_AUTH_INTERVAL);
@@ -1102,6 +1176,7 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
1102 1176
1103 ieee80211_set_disassoc(sdata, true, false, 0); 1177 ieee80211_set_disassoc(sdata, true, false, 0);
1104 ifmgd->flags &= ~IEEE80211_STA_AUTHENTICATED; 1178 ifmgd->flags &= ~IEEE80211_STA_AUTHENTICATED;
1179 cfg80211_send_rx_deauth(sdata->dev, (u8 *) mgmt, len);
1105} 1180}
1106 1181
1107 1182
@@ -1124,13 +1199,15 @@ static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
1124 printk(KERN_DEBUG "%s: disassociated (Reason: %u)\n", 1199 printk(KERN_DEBUG "%s: disassociated (Reason: %u)\n",
1125 sdata->dev->name, reason_code); 1200 sdata->dev->name, reason_code);
1126 1201
1127 if (ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED) { 1202 if (!(ifmgd->flags & IEEE80211_STA_EXT_SME) &&
1203 ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED) {
1128 ifmgd->state = IEEE80211_STA_MLME_ASSOCIATE; 1204 ifmgd->state = IEEE80211_STA_MLME_ASSOCIATE;
1129 mod_timer(&ifmgd->timer, jiffies + 1205 mod_timer(&ifmgd->timer, jiffies +
1130 IEEE80211_RETRY_AUTH_INTERVAL); 1206 IEEE80211_RETRY_AUTH_INTERVAL);
1131 } 1207 }
1132 1208
1133 ieee80211_set_disassoc(sdata, false, false, reason_code); 1209 ieee80211_set_disassoc(sdata, false, false, reason_code);
1210 cfg80211_send_rx_disassoc(sdata->dev, (u8 *) mgmt, len);
1134} 1211}
1135 1212
1136 1213
@@ -1346,7 +1423,14 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
1346 bss_conf->assoc_capability = capab_info; 1423 bss_conf->assoc_capability = capab_info;
1347 ieee80211_set_associated(sdata, changed); 1424 ieee80211_set_associated(sdata, changed);
1348 1425
1426 /*
1427 * initialise the time of last beacon to be the association time,
1428 * otherwise beacon loss check will trigger immediately
1429 */
1430 ifmgd->last_beacon = jiffies;
1431
1349 ieee80211_associated(sdata); 1432 ieee80211_associated(sdata);
1433 cfg80211_send_rx_assoc(sdata->dev, (u8 *) mgmt, len);
1350} 1434}
1351 1435
1352 1436
@@ -1393,9 +1477,12 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
1393 size_t len, 1477 size_t len,
1394 struct ieee80211_rx_status *rx_status) 1478 struct ieee80211_rx_status *rx_status)
1395{ 1479{
1480 struct ieee80211_if_managed *ifmgd;
1396 size_t baselen; 1481 size_t baselen;
1397 struct ieee802_11_elems elems; 1482 struct ieee802_11_elems elems;
1398 1483
1484 ifmgd = &sdata->u.mgd;
1485
1399 if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN)) 1486 if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN))
1400 return; /* ignore ProbeResp to foreign address */ 1487 return; /* ignore ProbeResp to foreign address */
1401 1488
@@ -1410,11 +1497,14 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
1410 1497
1411 /* direct probe may be part of the association flow */ 1498 /* direct probe may be part of the association flow */
1412 if (test_and_clear_bit(IEEE80211_STA_REQ_DIRECT_PROBE, 1499 if (test_and_clear_bit(IEEE80211_STA_REQ_DIRECT_PROBE,
1413 &sdata->u.mgd.request)) { 1500 &ifmgd->request)) {
1414 printk(KERN_DEBUG "%s direct probe responded\n", 1501 printk(KERN_DEBUG "%s direct probe responded\n",
1415 sdata->dev->name); 1502 sdata->dev->name);
1416 ieee80211_authenticate(sdata); 1503 ieee80211_authenticate(sdata);
1417 } 1504 }
1505
1506 if (ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL)
1507 ifmgd->flags &= ~IEEE80211_STA_PROBEREQ_POLL;
1418} 1508}
1419 1509
1420static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, 1510static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
@@ -1636,6 +1726,8 @@ static void ieee80211_sta_reset_auth(struct ieee80211_sub_if_data *sdata)
1636 ifmgd->auth_alg = WLAN_AUTH_SHARED_KEY; 1726 ifmgd->auth_alg = WLAN_AUTH_SHARED_KEY;
1637 else if (ifmgd->auth_algs & IEEE80211_AUTH_ALG_LEAP) 1727 else if (ifmgd->auth_algs & IEEE80211_AUTH_ALG_LEAP)
1638 ifmgd->auth_alg = WLAN_AUTH_LEAP; 1728 ifmgd->auth_alg = WLAN_AUTH_LEAP;
1729 else if (ifmgd->auth_algs & IEEE80211_AUTH_ALG_FT)
1730 ifmgd->auth_alg = WLAN_AUTH_FT;
1639 else 1731 else
1640 ifmgd->auth_alg = WLAN_AUTH_OPEN; 1732 ifmgd->auth_alg = WLAN_AUTH_OPEN;
1641 ifmgd->auth_transaction = -1; 1733 ifmgd->auth_transaction = -1;
@@ -1659,7 +1751,8 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata)
1659 u16 capa_val = WLAN_CAPABILITY_ESS; 1751 u16 capa_val = WLAN_CAPABILITY_ESS;
1660 struct ieee80211_channel *chan = local->oper_channel; 1752 struct ieee80211_channel *chan = local->oper_channel;
1661 1753
1662 if (ifmgd->flags & (IEEE80211_STA_AUTO_SSID_SEL | 1754 if (!(ifmgd->flags & IEEE80211_STA_EXT_SME) &&
1755 ifmgd->flags & (IEEE80211_STA_AUTO_SSID_SEL |
1663 IEEE80211_STA_AUTO_BSSID_SEL | 1756 IEEE80211_STA_AUTO_BSSID_SEL |
1664 IEEE80211_STA_AUTO_CHANNEL_SEL)) { 1757 IEEE80211_STA_AUTO_CHANNEL_SEL)) {
1665 capa_mask |= WLAN_CAPABILITY_PRIVACY; 1758 capa_mask |= WLAN_CAPABILITY_PRIVACY;
@@ -1822,6 +1915,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
1822 ifmgd = &sdata->u.mgd; 1915 ifmgd = &sdata->u.mgd;
1823 INIT_WORK(&ifmgd->work, ieee80211_sta_work); 1916 INIT_WORK(&ifmgd->work, ieee80211_sta_work);
1824 INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work); 1917 INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work);
1918 INIT_WORK(&ifmgd->beacon_loss_work, ieee80211_beacon_loss_work);
1825 setup_timer(&ifmgd->timer, ieee80211_sta_timer, 1919 setup_timer(&ifmgd->timer, ieee80211_sta_timer,
1826 (unsigned long) sdata); 1920 (unsigned long) sdata);
1827 setup_timer(&ifmgd->chswitch_timer, ieee80211_chswitch_timer, 1921 setup_timer(&ifmgd->chswitch_timer, ieee80211_chswitch_timer,
@@ -1834,7 +1928,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
1834 ifmgd->flags |= IEEE80211_STA_CREATE_IBSS | 1928 ifmgd->flags |= IEEE80211_STA_CREATE_IBSS |
1835 IEEE80211_STA_AUTO_BSSID_SEL | 1929 IEEE80211_STA_AUTO_BSSID_SEL |
1836 IEEE80211_STA_AUTO_CHANNEL_SEL; 1930 IEEE80211_STA_AUTO_CHANNEL_SEL;
1837 if (ieee80211_num_regular_queues(&sdata->local->hw) >= 4) 1931 if (sdata->local->hw.queues >= 4)
1838 ifmgd->flags |= IEEE80211_STA_WMM_ENABLED; 1932 ifmgd->flags |= IEEE80211_STA_WMM_ENABLED;
1839} 1933}
1840 1934
@@ -1856,7 +1950,11 @@ void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata)
1856 ieee80211_set_disassoc(sdata, true, true, 1950 ieee80211_set_disassoc(sdata, true, true,
1857 WLAN_REASON_DEAUTH_LEAVING); 1951 WLAN_REASON_DEAUTH_LEAVING);
1858 1952
1859 set_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request); 1953 if (!(ifmgd->flags & IEEE80211_STA_EXT_SME) ||
1954 ifmgd->state != IEEE80211_STA_MLME_ASSOCIATE)
1955 set_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request);
1956 else if (ifmgd->flags & IEEE80211_STA_EXT_SME)
1957 set_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request);
1860 queue_work(local->hw.workqueue, &ifmgd->work); 1958 queue_work(local->hw.workqueue, &ifmgd->work);
1861 } 1959 }
1862} 1960}
@@ -1865,8 +1963,6 @@ int ieee80211_sta_commit(struct ieee80211_sub_if_data *sdata)
1865{ 1963{
1866 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 1964 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1867 1965
1868 ifmgd->flags &= ~IEEE80211_STA_PREV_BSSID_SET;
1869
1870 if (ifmgd->ssid_len) 1966 if (ifmgd->ssid_len)
1871 ifmgd->flags |= IEEE80211_STA_SSID_SET; 1967 ifmgd->flags |= IEEE80211_STA_SSID_SET;
1872 else 1968 else
@@ -1885,6 +1981,10 @@ int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size
1885 ifmgd = &sdata->u.mgd; 1981 ifmgd = &sdata->u.mgd;
1886 1982
1887 if (ifmgd->ssid_len != len || memcmp(ifmgd->ssid, ssid, len) != 0) { 1983 if (ifmgd->ssid_len != len || memcmp(ifmgd->ssid, ssid, len) != 0) {
1984 /*
1985 * Do not use reassociation if SSID is changed (different ESS).
1986 */
1987 ifmgd->flags &= ~IEEE80211_STA_PREV_BSSID_SET;
1888 memset(ifmgd->ssid, 0, sizeof(ifmgd->ssid)); 1988 memset(ifmgd->ssid, 0, sizeof(ifmgd->ssid));
1889 memcpy(ifmgd->ssid, ssid, len); 1989 memcpy(ifmgd->ssid, ssid, len);
1890 ifmgd->ssid_len = len; 1990 ifmgd->ssid_len = len;
@@ -1923,7 +2023,8 @@ int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid)
1923 return ieee80211_sta_commit(sdata); 2023 return ieee80211_sta_commit(sdata);
1924} 2024}
1925 2025
1926int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, char *ie, size_t len) 2026int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata,
2027 const char *ie, size_t len)
1927{ 2028{
1928 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 2029 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1929 2030