aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-07-06 21:45:17 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-07-10 15:02:30 -0400
commit77fdaa12cea26c204cc12c312fe40bc0f3dcdfd8 (patch)
treec28fdd28f2ca2783783adb4b5e13b7ba57a223a3 /net/mac80211/mlme.c
parenta7c1cfc9616ee76213a6d4fd4c17f13fdc92ddce (diff)
mac80211: rework MLME for multiple authentications
Sit tight. This shakes up the world as you know it. Let go of your spaghetti tongs, they will no longer be required, the horrible statemachine in net/mac80211/mlme.c is no more... With the cfg80211 SME mac80211 now has much less to keep track of, but, on the other hand, for FT it needs to be able to keep track of at least one authentication being in progress while associated. So convert from a single state machine to having small ones for all the different things we need to do. For real FT it will still need work wrt. PS, but this should be a good step. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c1332
1 files changed, 700 insertions, 632 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 29575eea3ed1..108e8c9c60fd 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -27,20 +27,51 @@
27#include "rate.h" 27#include "rate.h"
28#include "led.h" 28#include "led.h"
29 29
30#define IEEE80211_ASSOC_SCANS_MAX_TRIES 2
31#define IEEE80211_AUTH_TIMEOUT (HZ / 5) 30#define IEEE80211_AUTH_TIMEOUT (HZ / 5)
32#define IEEE80211_AUTH_MAX_TRIES 3 31#define IEEE80211_AUTH_MAX_TRIES 3
33#define IEEE80211_ASSOC_TIMEOUT (HZ / 5) 32#define IEEE80211_ASSOC_TIMEOUT (HZ / 5)
34#define IEEE80211_ASSOC_MAX_TRIES 3 33#define IEEE80211_ASSOC_MAX_TRIES 3
35#define IEEE80211_MONITORING_INTERVAL (2 * HZ) 34#define IEEE80211_MONITORING_INTERVAL (2 * HZ)
36#define IEEE80211_PROBE_WAIT (HZ / 5) 35#define IEEE80211_PROBE_WAIT (HZ / 5)
37#define IEEE80211_PROBE_IDLE_TIME (60 * HZ)
38#define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ)
39 36
40#define TMR_RUNNING_TIMER 0 37#define TMR_RUNNING_TIMER 0
41#define TMR_RUNNING_CHANSW 1 38#define TMR_RUNNING_CHANSW 1
42 39
40/*
41 * All cfg80211 functions have to be called outside a locked
42 * section so that they can acquire a lock themselves... This
43 * is much simpler than queuing up things in cfg80211, but we
44 * do need some indirection for that here.
45 */
46enum rx_mgmt_action {
47 /* no action required */
48 RX_MGMT_NONE,
49
50 /* caller must call cfg80211_send_rx_auth() */
51 RX_MGMT_CFG80211_AUTH,
52
53 /* caller must call cfg80211_send_rx_assoc() */
54 RX_MGMT_CFG80211_ASSOC,
55
56 /* caller must call cfg80211_send_deauth() */
57 RX_MGMT_CFG80211_DEAUTH,
58
59 /* caller must call cfg80211_send_disassoc() */
60 RX_MGMT_CFG80211_DISASSOC,
61
62 /* caller must call cfg80211_auth_timeout() & free work */
63 RX_MGMT_CFG80211_AUTH_TO,
64
65 /* caller must call cfg80211_assoc_timeout() & free work */
66 RX_MGMT_CFG80211_ASSOC_TO,
67};
68
43/* utils */ 69/* utils */
70static inline void ASSERT_MGD_MTX(struct ieee80211_if_managed *ifmgd)
71{
72 WARN_ON(!mutex_is_locked(&ifmgd->mtx));
73}
74
44static int ecw2cw(int ecw) 75static int ecw2cw(int ecw)
45{ 76{
46 return (1 << ecw) - 1; 77 return (1 << ecw) - 1;
@@ -74,11 +105,10 @@ static int ieee80211_compatible_rates(struct ieee80211_bss *bss,
74 */ 105 */
75static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, 106static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
76 struct ieee80211_ht_info *hti, 107 struct ieee80211_ht_info *hti,
77 u16 ap_ht_cap_flags) 108 const u8 *bssid, u16 ap_ht_cap_flags)
78{ 109{
79 struct ieee80211_local *local = sdata->local; 110 struct ieee80211_local *local = sdata->local;
80 struct ieee80211_supported_band *sband; 111 struct ieee80211_supported_band *sband;
81 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
82 struct sta_info *sta; 112 struct sta_info *sta;
83 u32 changed = 0; 113 u32 changed = 0;
84 u16 ht_opmode; 114 u16 ht_opmode;
@@ -127,12 +157,10 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
127 ieee80211_hw_config(local, 0); 157 ieee80211_hw_config(local, 0);
128 158
129 rcu_read_lock(); 159 rcu_read_lock();
130 160 sta = sta_info_get(local, bssid);
131 sta = sta_info_get(local, ifmgd->bssid);
132 if (sta) 161 if (sta)
133 rate_control_rate_update(local, sband, sta, 162 rate_control_rate_update(local, sband, sta,
134 IEEE80211_RC_HT_CHANGED); 163 IEEE80211_RC_HT_CHANGED);
135
136 rcu_read_unlock(); 164 rcu_read_unlock();
137 } 165 }
138 166
@@ -155,7 +183,8 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
155 183
156/* frame sending functions */ 184/* frame sending functions */
157 185
158static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) 186static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
187 struct ieee80211_mgd_work *wk)
159{ 188{
160 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 189 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
161 struct ieee80211_local *local = sdata->local; 190 struct ieee80211_local *local = sdata->local;
@@ -165,14 +194,13 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
165 const u8 *ies, *ht_ie; 194 const u8 *ies, *ht_ie;
166 int i, len, count, rates_len, supp_rates_len; 195 int i, len, count, rates_len, supp_rates_len;
167 u16 capab; 196 u16 capab;
168 struct ieee80211_bss *bss;
169 int wmm = 0; 197 int wmm = 0;
170 struct ieee80211_supported_band *sband; 198 struct ieee80211_supported_band *sband;
171 u32 rates = 0; 199 u32 rates = 0;
172 200
173 skb = dev_alloc_skb(local->hw.extra_tx_headroom + 201 skb = dev_alloc_skb(local->hw.extra_tx_headroom +
174 sizeof(*mgmt) + 200 + ifmgd->extra_ie_len + 202 sizeof(*mgmt) + 200 + wk->ie_len +
175 ifmgd->ssid_len); 203 wk->ssid_len);
176 if (!skb) { 204 if (!skb) {
177 printk(KERN_DEBUG "%s: failed to allocate buffer for assoc " 205 printk(KERN_DEBUG "%s: failed to allocate buffer for assoc "
178 "frame\n", sdata->dev->name); 206 "frame\n", sdata->dev->name);
@@ -191,45 +219,35 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
191 capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; 219 capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
192 } 220 }
193 221
194 bss = ieee80211_rx_bss_get(local, ifmgd->bssid, 222 if (wk->bss->cbss.capability & WLAN_CAPABILITY_PRIVACY)
195 local->hw.conf.channel->center_freq, 223 capab |= WLAN_CAPABILITY_PRIVACY;
196 ifmgd->ssid, ifmgd->ssid_len); 224 if (wk->bss->wmm_used)
197 if (bss) { 225 wmm = 1;
198 if (bss->cbss.capability & WLAN_CAPABILITY_PRIVACY)
199 capab |= WLAN_CAPABILITY_PRIVACY;
200 if (bss->wmm_used)
201 wmm = 1;
202 226
203 /* get all rates supported by the device and the AP as 227 /* get all rates supported by the device and the AP as
204 * some APs don't like getting a superset of their rates 228 * some APs don't like getting a superset of their rates
205 * in the association request (e.g. D-Link DAP 1353 in 229 * in the association request (e.g. D-Link DAP 1353 in
206 * b-only mode) */ 230 * b-only mode) */
207 rates_len = ieee80211_compatible_rates(bss, sband, &rates); 231 rates_len = ieee80211_compatible_rates(wk->bss, sband, &rates);
208 232
209 if ((bss->cbss.capability & WLAN_CAPABILITY_SPECTRUM_MGMT) && 233 if ((wk->bss->cbss.capability & WLAN_CAPABILITY_SPECTRUM_MGMT) &&
210 (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT)) 234 (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT))
211 capab |= WLAN_CAPABILITY_SPECTRUM_MGMT; 235 capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
212
213 ieee80211_rx_bss_put(local, bss);
214 } else {
215 rates = ~0;
216 rates_len = sband->n_bitrates;
217 }
218 236
219 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); 237 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
220 memset(mgmt, 0, 24); 238 memset(mgmt, 0, 24);
221 memcpy(mgmt->da, ifmgd->bssid, ETH_ALEN); 239 memcpy(mgmt->da, wk->bss->cbss.bssid, ETH_ALEN);
222 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); 240 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
223 memcpy(mgmt->bssid, ifmgd->bssid, ETH_ALEN); 241 memcpy(mgmt->bssid, wk->bss->cbss.bssid, ETH_ALEN);
224 242
225 if (ifmgd->flags & IEEE80211_STA_PREV_BSSID_SET) { 243 if (!is_zero_ether_addr(wk->prev_bssid)) {
226 skb_put(skb, 10); 244 skb_put(skb, 10);
227 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 245 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
228 IEEE80211_STYPE_REASSOC_REQ); 246 IEEE80211_STYPE_REASSOC_REQ);
229 mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab); 247 mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab);
230 mgmt->u.reassoc_req.listen_interval = 248 mgmt->u.reassoc_req.listen_interval =
231 cpu_to_le16(local->hw.conf.listen_interval); 249 cpu_to_le16(local->hw.conf.listen_interval);
232 memcpy(mgmt->u.reassoc_req.current_ap, ifmgd->prev_bssid, 250 memcpy(mgmt->u.reassoc_req.current_ap, wk->prev_bssid,
233 ETH_ALEN); 251 ETH_ALEN);
234 } else { 252 } else {
235 skb_put(skb, 4); 253 skb_put(skb, 4);
@@ -241,10 +259,10 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
241 } 259 }
242 260
243 /* SSID */ 261 /* SSID */
244 ies = pos = skb_put(skb, 2 + ifmgd->ssid_len); 262 ies = pos = skb_put(skb, 2 + wk->ssid_len);
245 *pos++ = WLAN_EID_SSID; 263 *pos++ = WLAN_EID_SSID;
246 *pos++ = ifmgd->ssid_len; 264 *pos++ = wk->ssid_len;
247 memcpy(pos, ifmgd->ssid, ifmgd->ssid_len); 265 memcpy(pos, wk->ssid, wk->ssid_len);
248 266
249 /* add all rates which were marked to be used above */ 267 /* add all rates which were marked to be used above */
250 supp_rates_len = rates_len; 268 supp_rates_len = rates_len;
@@ -299,9 +317,9 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
299 } 317 }
300 } 318 }
301 319
302 if (ifmgd->extra_ie) { 320 if (wk->ie_len && wk->ie) {
303 pos = skb_put(skb, ifmgd->extra_ie_len); 321 pos = skb_put(skb, wk->ie_len);
304 memcpy(pos, ifmgd->extra_ie, ifmgd->extra_ie_len); 322 memcpy(pos, wk->ie, wk->ie_len);
305 } 323 }
306 324
307 if (wmm && (ifmgd->flags & IEEE80211_STA_WMM_ENABLED)) { 325 if (wmm && (ifmgd->flags & IEEE80211_STA_WMM_ENABLED)) {
@@ -326,7 +344,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
326 */ 344 */
327 if (wmm && (ifmgd->flags & IEEE80211_STA_WMM_ENABLED) && 345 if (wmm && (ifmgd->flags & IEEE80211_STA_WMM_ENABLED) &&
328 sband->ht_cap.ht_supported && 346 sband->ht_cap.ht_supported &&
329 (ht_ie = ieee80211_bss_get_ie(&bss->cbss, WLAN_EID_HT_INFORMATION)) && 347 (ht_ie = ieee80211_bss_get_ie(&wk->bss->cbss, WLAN_EID_HT_INFORMATION)) &&
330 ht_ie[1] >= sizeof(struct ieee80211_ht_info) && 348 ht_ie[1] >= sizeof(struct ieee80211_ht_info) &&
331 (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N))) { 349 (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N))) {
332 struct ieee80211_ht_info *ht_info = 350 struct ieee80211_ht_info *ht_info =
@@ -363,18 +381,12 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
363 memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); 381 memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
364 } 382 }
365 383
366 kfree(ifmgd->assocreq_ies);
367 ifmgd->assocreq_ies_len = (skb->data + skb->len) - ies;
368 ifmgd->assocreq_ies = kmalloc(ifmgd->assocreq_ies_len, GFP_KERNEL);
369 if (ifmgd->assocreq_ies)
370 memcpy(ifmgd->assocreq_ies, ies, ifmgd->assocreq_ies_len);
371
372 ieee80211_tx_skb(sdata, skb, 0); 384 ieee80211_tx_skb(sdata, skb, 0);
373} 385}
374 386
375 387
376static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, 388static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
377 u16 stype, u16 reason) 389 const u8 *bssid, u16 stype, u16 reason)
378{ 390{
379 struct ieee80211_local *local = sdata->local; 391 struct ieee80211_local *local = sdata->local;
380 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 392 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
@@ -391,9 +403,9 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
391 403
392 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); 404 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
393 memset(mgmt, 0, 24); 405 memset(mgmt, 0, 24);
394 memcpy(mgmt->da, ifmgd->bssid, ETH_ALEN); 406 memcpy(mgmt->da, bssid, ETH_ALEN);
395 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); 407 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
396 memcpy(mgmt->bssid, ifmgd->bssid, ETH_ALEN); 408 memcpy(mgmt->bssid, bssid, ETH_ALEN);
397 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype); 409 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype);
398 skb_put(skb, 2); 410 skb_put(skb, 2);
399 /* u.deauth.reason_code == u.disassoc.reason_code */ 411 /* u.deauth.reason_code == u.disassoc.reason_code */
@@ -477,28 +489,26 @@ static void ieee80211_chswitch_work(struct work_struct *work)
477{ 489{
478 struct ieee80211_sub_if_data *sdata = 490 struct ieee80211_sub_if_data *sdata =
479 container_of(work, struct ieee80211_sub_if_data, u.mgd.chswitch_work); 491 container_of(work, struct ieee80211_sub_if_data, u.mgd.chswitch_work);
480 struct ieee80211_bss *bss;
481 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 492 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
482 493
483 if (!netif_running(sdata->dev)) 494 if (!netif_running(sdata->dev))
484 return; 495 return;
485 496
486 bss = ieee80211_rx_bss_get(sdata->local, ifmgd->bssid, 497 mutex_lock(&ifmgd->mtx);
487 sdata->local->hw.conf.channel->center_freq, 498 if (!ifmgd->associated)
488 ifmgd->ssid, ifmgd->ssid_len); 499 goto out;
489 if (!bss)
490 goto exit;
491 500
492 sdata->local->oper_channel = sdata->local->csa_channel; 501 sdata->local->oper_channel = sdata->local->csa_channel;
502 ieee80211_hw_config(sdata->local, IEEE80211_CONF_CHANGE_CHANNEL);
503
493 /* XXX: shouldn't really modify cfg80211-owned data! */ 504 /* XXX: shouldn't really modify cfg80211-owned data! */
494 if (!ieee80211_hw_config(sdata->local, IEEE80211_CONF_CHANGE_CHANNEL)) 505 ifmgd->associated->cbss.channel = sdata->local->oper_channel;
495 bss->cbss.channel = sdata->local->oper_channel;
496 506
497 ieee80211_rx_bss_put(sdata->local, bss);
498exit:
499 ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
500 ieee80211_wake_queues_by_reason(&sdata->local->hw, 507 ieee80211_wake_queues_by_reason(&sdata->local->hw,
501 IEEE80211_QUEUE_STOP_REASON_CSA); 508 IEEE80211_QUEUE_STOP_REASON_CSA);
509 out:
510 ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
511 mutex_unlock(&ifmgd->mtx);
502} 512}
503 513
504static void ieee80211_chswitch_timer(unsigned long data) 514static void ieee80211_chswitch_timer(unsigned long data)
@@ -523,7 +533,9 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
523 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 533 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
524 int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num); 534 int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num);
525 535
526 if (ifmgd->state != IEEE80211_STA_MLME_ASSOCIATED) 536 ASSERT_MGD_MTX(ifmgd);
537
538 if (!ifmgd->associated)
527 return; 539 return;
528 540
529 if (sdata->local->sw_scanning || sdata->local->hw_scanning) 541 if (sdata->local->sw_scanning || sdata->local->hw_scanning)
@@ -634,7 +646,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
634 } 646 }
635 647
636 if (count == 1 && found->u.mgd.powersave && 648 if (count == 1 && found->u.mgd.powersave &&
637 (found->u.mgd.flags & IEEE80211_STA_ASSOCIATED) && 649 found->u.mgd.associated && list_empty(&found->u.mgd.work_list) &&
638 !(found->u.mgd.flags & IEEE80211_STA_PROBEREQ_POLL)) { 650 !(found->u.mgd.flags & IEEE80211_STA_PROBEREQ_POLL)) {
639 s32 beaconint_us; 651 s32 beaconint_us;
640 652
@@ -789,9 +801,6 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
789 u16 capab, bool erp_valid, u8 erp) 801 u16 capab, bool erp_valid, u8 erp)
790{ 802{
791 struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; 803 struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
792#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
793 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
794#endif
795 u32 changed = 0; 804 u32 changed = 0;
796 bool use_protection; 805 bool use_protection;
797 bool use_short_preamble; 806 bool use_short_preamble;
@@ -808,42 +817,16 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
808 use_short_slot = !!(capab & WLAN_CAPABILITY_SHORT_SLOT_TIME); 817 use_short_slot = !!(capab & WLAN_CAPABILITY_SHORT_SLOT_TIME);
809 818
810 if (use_protection != bss_conf->use_cts_prot) { 819 if (use_protection != bss_conf->use_cts_prot) {
811#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
812 if (net_ratelimit()) {
813 printk(KERN_DEBUG "%s: CTS protection %s (BSSID=%pM)\n",
814 sdata->dev->name,
815 use_protection ? "enabled" : "disabled",
816 ifmgd->bssid);
817 }
818#endif
819 bss_conf->use_cts_prot = use_protection; 820 bss_conf->use_cts_prot = use_protection;
820 changed |= BSS_CHANGED_ERP_CTS_PROT; 821 changed |= BSS_CHANGED_ERP_CTS_PROT;
821 } 822 }
822 823
823 if (use_short_preamble != bss_conf->use_short_preamble) { 824 if (use_short_preamble != bss_conf->use_short_preamble) {
824#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
825 if (net_ratelimit()) {
826 printk(KERN_DEBUG "%s: switched to %s barker preamble"
827 " (BSSID=%pM)\n",
828 sdata->dev->name,
829 use_short_preamble ? "short" : "long",
830 ifmgd->bssid);
831 }
832#endif
833 bss_conf->use_short_preamble = use_short_preamble; 825 bss_conf->use_short_preamble = use_short_preamble;
834 changed |= BSS_CHANGED_ERP_PREAMBLE; 826 changed |= BSS_CHANGED_ERP_PREAMBLE;
835 } 827 }
836 828
837 if (use_short_slot != bss_conf->use_short_slot) { 829 if (use_short_slot != bss_conf->use_short_slot) {
838#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
839 if (net_ratelimit()) {
840 printk(KERN_DEBUG "%s: switched to %s slot time"
841 " (BSSID=%pM)\n",
842 sdata->dev->name,
843 use_short_slot ? "short" : "long",
844 ifmgd->bssid);
845 }
846#endif
847 bss_conf->use_short_slot = use_short_slot; 830 bss_conf->use_short_slot = use_short_slot;
848 changed |= BSS_CHANGED_ERP_SLOT; 831 changed |= BSS_CHANGED_ERP_SLOT;
849 } 832 }
@@ -852,32 +835,23 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
852} 835}
853 836
854static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, 837static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
838 struct ieee80211_bss *bss,
855 u32 bss_info_changed) 839 u32 bss_info_changed)
856{ 840{
857 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
858 struct ieee80211_local *local = sdata->local; 841 struct ieee80211_local *local = sdata->local;
859 struct ieee80211_conf *conf = &local_to_hw(local)->conf;
860
861 struct ieee80211_bss *bss;
862 842
863 bss_info_changed |= BSS_CHANGED_ASSOC; 843 bss_info_changed |= BSS_CHANGED_ASSOC;
864 ifmgd->flags |= IEEE80211_STA_ASSOCIATED; 844 /* set timing information */
845 sdata->vif.bss_conf.beacon_int = bss->cbss.beacon_interval;
846 sdata->vif.bss_conf.timestamp = bss->cbss.tsf;
847 sdata->vif.bss_conf.dtim_period = bss->dtim_period;
865 848
866 bss = ieee80211_rx_bss_get(local, ifmgd->bssid, 849 bss_info_changed |= BSS_CHANGED_BEACON_INT;
867 conf->channel->center_freq, 850 bss_info_changed |= ieee80211_handle_bss_capability(sdata,
868 ifmgd->ssid, ifmgd->ssid_len); 851 bss->cbss.capability, bss->has_erp_value, bss->erp_value);
869 if (bss) {
870 /* set timing information */
871 sdata->vif.bss_conf.beacon_int = bss->cbss.beacon_interval;
872 sdata->vif.bss_conf.timestamp = bss->cbss.tsf;
873 sdata->vif.bss_conf.dtim_period = bss->dtim_period;
874 852
875 bss_info_changed |= BSS_CHANGED_BEACON_INT; 853 sdata->u.mgd.associated = bss;
876 bss_info_changed |= ieee80211_handle_bss_capability(sdata, 854 memcpy(sdata->u.mgd.bssid, bss->cbss.bssid, ETH_ALEN);
877 bss->cbss.capability, bss->has_erp_value, bss->erp_value);
878
879 ieee80211_rx_bss_put(local, bss);
880 }
881 855
882 ieee80211_led_assoc(local, 1); 856 ieee80211_led_assoc(local, 1);
883 857
@@ -905,152 +879,133 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
905 netif_carrier_on(sdata->dev); 879 netif_carrier_on(sdata->dev);
906} 880}
907 881
908static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata) 882static enum rx_mgmt_action __must_check
883ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata,
884 struct ieee80211_mgd_work *wk)
909{ 885{
910 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 886 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
911 struct ieee80211_local *local = sdata->local; 887 struct ieee80211_local *local = sdata->local;
912 888
913 ifmgd->direct_probe_tries++; 889 wk->tries++;
914 if (ifmgd->direct_probe_tries > IEEE80211_AUTH_MAX_TRIES) { 890 if (wk->tries > IEEE80211_AUTH_MAX_TRIES) {
915 printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n", 891 printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n",
916 sdata->dev->name, ifmgd->bssid); 892 sdata->dev->name, wk->bss->cbss.bssid);
917 ifmgd->state = IEEE80211_STA_MLME_DISABLED;
918 ieee80211_recalc_idle(local);
919 cfg80211_send_auth_timeout(sdata->dev, ifmgd->bssid,
920 GFP_KERNEL);
921 893
922 /* 894 /*
923 * Most likely AP is not in the range so remove the 895 * Most likely AP is not in the range so remove the
924 * bss information associated to the AP 896 * bss struct for that AP.
925 */ 897 */
926 ieee80211_rx_bss_remove(sdata, ifmgd->bssid, 898 cfg80211_unlink_bss(local->hw.wiphy, &wk->bss->cbss);
927 sdata->local->hw.conf.channel->center_freq,
928 ifmgd->ssid, ifmgd->ssid_len);
929 899
930 /* 900 /*
931 * We might have a pending scan which had no chance to run yet 901 * We might have a pending scan which had no chance to run yet
932 * due to state == IEEE80211_STA_MLME_DIRECT_PROBE. 902 * due to work needing to be done. Hence, queue the STAs work
933 * Hence, queue the STAs work again 903 * again for that.
934 */ 904 */
935 queue_work(local->hw.workqueue, &ifmgd->work); 905 queue_work(local->hw.workqueue, &ifmgd->work);
936 return; 906 return RX_MGMT_CFG80211_AUTH_TO;
937 } 907 }
938 908
939 printk(KERN_DEBUG "%s: direct probe to AP %pM try %d\n", 909 printk(KERN_DEBUG "%s: direct probe to AP %pM (try %d)\n",
940 sdata->dev->name, ifmgd->bssid, 910 sdata->dev->name, wk->bss->cbss.bssid,
941 ifmgd->direct_probe_tries); 911 wk->tries);
942 912
943 ifmgd->state = IEEE80211_STA_MLME_DIRECT_PROBE; 913 /*
944 914 * Direct probe is sent to broadcast address as some APs
945 /* Direct probe is sent to broadcast address as some APs
946 * will not answer to direct packet in unassociated state. 915 * will not answer to direct packet in unassociated state.
947 */ 916 */
948 ieee80211_send_probe_req(sdata, NULL, 917 ieee80211_send_probe_req(sdata, NULL, wk->ssid, wk->ssid_len, NULL, 0);
949 ifmgd->ssid, ifmgd->ssid_len, NULL, 0); 918
919 wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
920 mod_timer(&ifmgd->timer, wk->timeout);
950 921
951 mod_timer(&ifmgd->timer, jiffies + IEEE80211_AUTH_TIMEOUT); 922 return RX_MGMT_NONE;
952} 923}
953 924
954 925
955static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata) 926static enum rx_mgmt_action __must_check
927ieee80211_authenticate(struct ieee80211_sub_if_data *sdata,
928 struct ieee80211_mgd_work *wk)
956{ 929{
957 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 930 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
958 struct ieee80211_local *local = sdata->local; 931 struct ieee80211_local *local = sdata->local;
959 932
960 ifmgd->auth_tries++; 933 wk->tries++;
961 if (ifmgd->auth_tries > IEEE80211_AUTH_MAX_TRIES) { 934 if (wk->tries > IEEE80211_AUTH_MAX_TRIES) {
962 printk(KERN_DEBUG "%s: authentication with AP %pM" 935 printk(KERN_DEBUG "%s: authentication with AP %pM"
963 " timed out\n", 936 " timed out\n",
964 sdata->dev->name, ifmgd->bssid); 937 sdata->dev->name, wk->bss->cbss.bssid);
965 ifmgd->state = IEEE80211_STA_MLME_DISABLED; 938
966 ieee80211_recalc_idle(local); 939 /*
967 cfg80211_send_auth_timeout(sdata->dev, ifmgd->bssid, 940 * Most likely AP is not in the range so remove the
968 GFP_KERNEL); 941 * bss struct for that AP.
969 ieee80211_rx_bss_remove(sdata, ifmgd->bssid, 942 */
970 sdata->local->hw.conf.channel->center_freq, 943 cfg80211_unlink_bss(local->hw.wiphy, &wk->bss->cbss);
971 ifmgd->ssid, ifmgd->ssid_len);
972 944
973 /* 945 /*
974 * We might have a pending scan which had no chance to run yet 946 * We might have a pending scan which had no chance to run yet
975 * due to state == IEEE80211_STA_MLME_AUTHENTICATE. 947 * due to work needing to be done. Hence, queue the STAs work
976 * Hence, queue the STAs work again 948 * again for that.
977 */ 949 */
978 queue_work(local->hw.workqueue, &ifmgd->work); 950 queue_work(local->hw.workqueue, &ifmgd->work);
979 return; 951 return RX_MGMT_CFG80211_AUTH_TO;
980 } 952 }
981 953
982 ifmgd->state = IEEE80211_STA_MLME_AUTHENTICATE; 954 printk(KERN_DEBUG "%s: authenticate with AP %pM (try %d)\n",
983 printk(KERN_DEBUG "%s: authenticate with AP %pM\n", 955 sdata->dev->name, wk->bss->cbss.bssid, wk->tries);
984 sdata->dev->name, ifmgd->bssid); 956
957 ieee80211_send_auth(sdata, 1, wk->auth_alg, wk->ie, wk->ie_len,
958 wk->bss->cbss.bssid, 0);
959 wk->auth_transaction = 2;
985 960
986 ieee80211_send_auth(sdata, 1, ifmgd->auth_alg, ifmgd->sme_auth_ie, 961 wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
987 ifmgd->sme_auth_ie_len, ifmgd->bssid, 0); 962 mod_timer(&ifmgd->timer, wk->timeout);
988 ifmgd->auth_transaction = 2;
989 963
990 mod_timer(&ifmgd->timer, jiffies + IEEE80211_AUTH_TIMEOUT); 964 return RX_MGMT_NONE;
991} 965}
992 966
993/*
994 * The disassoc 'reason' argument can be either our own reason
995 * if self disconnected or a reason code from the AP.
996 */
997static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, 967static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
998 bool deauth, bool self_disconnected, 968 const u8 *bssid, bool deauth)
999 u16 reason)
1000{ 969{
1001 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 970 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1002 struct ieee80211_local *local = sdata->local; 971 struct ieee80211_local *local = sdata->local;
1003 struct ieee80211_conf *conf = &local_to_hw(local)->conf;
1004 struct ieee80211_bss *bss;
1005 struct sta_info *sta; 972 struct sta_info *sta;
1006 u32 changed = 0, config_changed = 0; 973 u32 changed = 0, config_changed = 0;
1007 974
1008 if (deauth) { 975 ASSERT_MGD_MTX(ifmgd);
1009 ifmgd->direct_probe_tries = 0; 976
1010 ifmgd->auth_tries = 0; 977 ifmgd->associated = NULL;
1011 } 978 memset(ifmgd->bssid, 0, ETH_ALEN);
1012 ifmgd->assoc_scan_tries = 0; 979
1013 ifmgd->assoc_tries = 0; 980 /*
981 * we need to commit the associated = NULL change because the
982 * scan code uses that to determine whether this iface should
983 * go to/wake up from powersave or not -- and could otherwise
984 * wake the queues erroneously.
985 */
986 smp_mb();
987
988 /*
989 * Thus, we can only afterwards stop the queues -- to account
990 * for the case where another CPU is finishing a scan at this
991 * time -- we don't want the scan code to enable queues.
992 */
1014 993
1015 netif_tx_stop_all_queues(sdata->dev); 994 netif_tx_stop_all_queues(sdata->dev);
1016 netif_carrier_off(sdata->dev); 995 netif_carrier_off(sdata->dev);
1017 996
1018 rcu_read_lock(); 997 rcu_read_lock();
1019 sta = sta_info_get(local, ifmgd->bssid); 998 sta = sta_info_get(local, bssid);
1020 if (sta) 999 if (sta)
1021 ieee80211_sta_tear_down_BA_sessions(sta); 1000 ieee80211_sta_tear_down_BA_sessions(sta);
1022 rcu_read_unlock(); 1001 rcu_read_unlock();
1023 1002
1024 bss = ieee80211_rx_bss_get(local, ifmgd->bssid,
1025 conf->channel->center_freq,
1026 ifmgd->ssid, ifmgd->ssid_len);
1027
1028 if (bss)
1029 ieee80211_rx_bss_put(local, bss);
1030
1031 if (self_disconnected) {
1032 if (deauth)
1033 ieee80211_send_deauth_disassoc(sdata,
1034 IEEE80211_STYPE_DEAUTH, reason);
1035 else
1036 ieee80211_send_deauth_disassoc(sdata,
1037 IEEE80211_STYPE_DISASSOC, reason);
1038 }
1039
1040 ifmgd->flags &= ~IEEE80211_STA_ASSOCIATED;
1041 changed |= ieee80211_reset_erp_info(sdata); 1003 changed |= ieee80211_reset_erp_info(sdata);
1042 1004
1043 ieee80211_led_assoc(local, 0); 1005 ieee80211_led_assoc(local, 0);
1044 changed |= BSS_CHANGED_ASSOC; 1006 changed |= BSS_CHANGED_ASSOC;
1045 sdata->vif.bss_conf.assoc = false; 1007 sdata->vif.bss_conf.assoc = false;
1046 1008
1047 if (self_disconnected || reason == WLAN_REASON_DISASSOC_STA_HAS_LEFT) {
1048 ifmgd->state = IEEE80211_STA_MLME_DISABLED;
1049 ieee80211_rx_bss_remove(sdata, ifmgd->bssid,
1050 sdata->local->hw.conf.channel->center_freq,
1051 ifmgd->ssid, ifmgd->ssid_len);
1052 }
1053
1054 ieee80211_set_wmm_default(sdata); 1009 ieee80211_set_wmm_default(sdata);
1055 1010
1056 ieee80211_recalc_idle(local); 1011 ieee80211_recalc_idle(local);
@@ -1079,7 +1034,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1079 1034
1080 rcu_read_lock(); 1035 rcu_read_lock();
1081 1036
1082 sta = sta_info_get(local, ifmgd->bssid); 1037 sta = sta_info_get(local, bssid);
1083 if (!sta) { 1038 if (!sta) {
1084 rcu_read_unlock(); 1039 rcu_read_unlock();
1085 return; 1040 return;
@@ -1092,38 +1047,42 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1092 sta_info_destroy(sta); 1047 sta_info_destroy(sta);
1093} 1048}
1094 1049
1095static void ieee80211_associate(struct ieee80211_sub_if_data *sdata) 1050static enum rx_mgmt_action __must_check
1051ieee80211_associate(struct ieee80211_sub_if_data *sdata,
1052 struct ieee80211_mgd_work *wk)
1096{ 1053{
1097 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 1054 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1098 struct ieee80211_local *local = sdata->local; 1055 struct ieee80211_local *local = sdata->local;
1099 1056
1100 ifmgd->assoc_tries++; 1057 wk->tries++;
1101 if (ifmgd->assoc_tries > IEEE80211_ASSOC_MAX_TRIES) { 1058 if (wk->tries > IEEE80211_ASSOC_MAX_TRIES) {
1102 printk(KERN_DEBUG "%s: association with AP %pM" 1059 printk(KERN_DEBUG "%s: association with AP %pM"
1103 " timed out\n", 1060 " timed out\n",
1104 sdata->dev->name, ifmgd->bssid); 1061 sdata->dev->name, wk->bss->cbss.bssid);
1105 ifmgd->state = IEEE80211_STA_MLME_DISABLED; 1062
1106 ieee80211_recalc_idle(local); 1063 /*
1107 cfg80211_send_assoc_timeout(sdata->dev, ifmgd->bssid, 1064 * Most likely AP is not in the range so remove the
1108 GFP_KERNEL); 1065 * bss struct for that AP.
1109 ieee80211_rx_bss_remove(sdata, ifmgd->bssid, 1066 */
1110 sdata->local->hw.conf.channel->center_freq, 1067 cfg80211_unlink_bss(local->hw.wiphy, &wk->bss->cbss);
1111 ifmgd->ssid, ifmgd->ssid_len); 1068
1112 /* 1069 /*
1113 * We might have a pending scan which had no chance to run yet 1070 * We might have a pending scan which had no chance to run yet
1114 * due to state == IEEE80211_STA_MLME_ASSOCIATE. 1071 * due to work needing to be done. Hence, queue the STAs work
1115 * Hence, queue the STAs work again 1072 * again for that.
1116 */ 1073 */
1117 queue_work(local->hw.workqueue, &ifmgd->work); 1074 queue_work(local->hw.workqueue, &ifmgd->work);
1118 return; 1075 return RX_MGMT_CFG80211_ASSOC_TO;
1119 } 1076 }
1120 1077
1121 ifmgd->state = IEEE80211_STA_MLME_ASSOCIATE; 1078 printk(KERN_DEBUG "%s: associate with AP %pM (try %d)\n",
1122 printk(KERN_DEBUG "%s: associate with AP %pM\n", 1079 sdata->dev->name, wk->bss->cbss.bssid, wk->tries);
1123 sdata->dev->name, ifmgd->bssid); 1080 ieee80211_send_assoc(sdata, wk);
1124 ieee80211_send_assoc(sdata); 1081
1082 wk->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT;
1083 mod_timer(&ifmgd->timer, wk->timeout);
1125 1084
1126 mod_timer(&ifmgd->timer, jiffies + IEEE80211_ASSOC_TIMEOUT); 1085 return RX_MGMT_NONE;
1127} 1086}
1128 1087
1129void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, 1088void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
@@ -1148,6 +1107,7 @@ void ieee80211_beacon_loss_work(struct work_struct *work)
1148 container_of(work, struct ieee80211_sub_if_data, 1107 container_of(work, struct ieee80211_sub_if_data,
1149 u.mgd.beacon_loss_work); 1108 u.mgd.beacon_loss_work);
1150 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 1109 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1110 const u8 *ssid;
1151 1111
1152 /* 1112 /*
1153 * The driver has already reported this event and we have 1113 * The driver has already reported this event and we have
@@ -1160,12 +1120,15 @@ void ieee80211_beacon_loss_work(struct work_struct *work)
1160 if (ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) 1120 if (ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL)
1161 return; 1121 return;
1162 1122
1123 mutex_lock(&ifmgd->mtx);
1124
1125 if (!ifmgd->associated)
1126 goto out;
1127
1163#ifdef CONFIG_MAC80211_VERBOSE_DEBUG 1128#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
1164 if (net_ratelimit()) { 1129 if (net_ratelimit())
1165 printk(KERN_DEBUG "%s: driver reports beacon loss from AP %pM " 1130 printk(KERN_DEBUG "%s: driver reports beacon loss from AP "
1166 "- sending probe request\n", sdata->dev->name, 1131 "- sending probe request\n", sdata->dev->name);
1167 sdata->u.mgd.bssid);
1168 }
1169#endif 1132#endif
1170 1133
1171 ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL; 1134 ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL;
@@ -1174,10 +1137,13 @@ void ieee80211_beacon_loss_work(struct work_struct *work)
1174 ieee80211_recalc_ps(sdata->local, -1); 1137 ieee80211_recalc_ps(sdata->local, -1);
1175 mutex_unlock(&sdata->local->iflist_mtx); 1138 mutex_unlock(&sdata->local->iflist_mtx);
1176 1139
1177 ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid, 1140 ssid = ieee80211_bss_get_ie(&ifmgd->associated->cbss, WLAN_EID_SSID);
1178 ifmgd->ssid_len, NULL, 0); 1141 ieee80211_send_probe_req(sdata, ifmgd->associated->cbss.bssid,
1142 ssid + 2, ssid[1], NULL, 0);
1179 1143
1180 mod_timer(&ifmgd->timer, jiffies + IEEE80211_PROBE_WAIT); 1144 mod_timer(&ifmgd->timer, jiffies + IEEE80211_PROBE_WAIT);
1145 out:
1146 mutex_unlock(&ifmgd->mtx);
1181} 1147}
1182 1148
1183void ieee80211_beacon_loss(struct ieee80211_vif *vif) 1149void ieee80211_beacon_loss(struct ieee80211_vif *vif)
@@ -1189,102 +1155,16 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif)
1189} 1155}
1190EXPORT_SYMBOL(ieee80211_beacon_loss); 1156EXPORT_SYMBOL(ieee80211_beacon_loss);
1191 1157
1192static void ieee80211_associated(struct ieee80211_sub_if_data *sdata) 1158static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata,
1159 struct ieee80211_mgd_work *wk)
1193{ 1160{
1194 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 1161 wk->state = IEEE80211_MGD_STATE_IDLE;
1195 struct ieee80211_local *local = sdata->local;
1196 struct sta_info *sta;
1197 unsigned long last_rx;
1198 bool disassoc = false;
1199
1200 /* TODO: start monitoring current AP signal quality and number of
1201 * missed beacons. Scan other channels every now and then and search
1202 * for better APs. */
1203 /* TODO: remove expired BSSes */
1204
1205 ifmgd->state = IEEE80211_STA_MLME_ASSOCIATED;
1206
1207 rcu_read_lock();
1208
1209 sta = sta_info_get(local, ifmgd->bssid);
1210 if (!sta) {
1211 printk(KERN_DEBUG "%s: No STA entry for own AP %pM\n",
1212 sdata->dev->name, ifmgd->bssid);
1213 disassoc = true;
1214 rcu_read_unlock();
1215 goto out;
1216 }
1217
1218 last_rx = sta->last_rx;
1219 rcu_read_unlock();
1220
1221 if ((ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) &&
1222 time_after(jiffies, last_rx + IEEE80211_PROBE_WAIT)) {
1223 printk(KERN_DEBUG "%s: no probe response from AP %pM "
1224 "- disassociating\n",
1225 sdata->dev->name, ifmgd->bssid);
1226 disassoc = true;
1227 ifmgd->flags &= ~IEEE80211_STA_PROBEREQ_POLL;
1228 goto out;
1229 }
1230
1231 /*
1232 * Beacon filtering is only enabled with power save and then the
1233 * stack should not check for beacon loss.
1234 */
1235 if (!((local->hw.flags & IEEE80211_HW_BEACON_FILTER) &&
1236 (local->hw.conf.flags & IEEE80211_CONF_PS)) &&
1237 time_after(jiffies,
1238 ifmgd->last_beacon + IEEE80211_MONITORING_INTERVAL)) {
1239#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
1240 if (net_ratelimit()) {
1241 printk(KERN_DEBUG "%s: beacon loss from AP %pM "
1242 "- sending probe request\n",
1243 sdata->dev->name, ifmgd->bssid);
1244 }
1245#endif
1246 ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL;
1247 mutex_lock(&local->iflist_mtx);
1248 ieee80211_recalc_ps(local, -1);
1249 mutex_unlock(&local->iflist_mtx);
1250 ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid,
1251 ifmgd->ssid_len, NULL, 0);
1252 mod_timer(&ifmgd->timer, jiffies + IEEE80211_PROBE_WAIT);
1253 goto out;
1254 }
1255
1256 if (time_after(jiffies, last_rx + IEEE80211_PROBE_IDLE_TIME)) {
1257 ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL;
1258 mutex_lock(&local->iflist_mtx);
1259 ieee80211_recalc_ps(local, -1);
1260 mutex_unlock(&local->iflist_mtx);
1261 ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid,
1262 ifmgd->ssid_len, NULL, 0);
1263 }
1264
1265 out:
1266 if (!disassoc)
1267 mod_timer(&ifmgd->timer,
1268 jiffies + IEEE80211_MONITORING_INTERVAL);
1269 else
1270 ieee80211_set_disassoc(sdata, true, true,
1271 WLAN_REASON_PREV_AUTH_NOT_VALID);
1272}
1273
1274
1275static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata)
1276{
1277 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1278
1279 printk(KERN_DEBUG "%s: authenticated\n", sdata->dev->name); 1162 printk(KERN_DEBUG "%s: authenticated\n", sdata->dev->name);
1280 ifmgd->flags |= IEEE80211_STA_AUTHENTICATED;
1281 /* Wait for SME to request association */
1282 ifmgd->state = IEEE80211_STA_MLME_DISABLED;
1283 ieee80211_recalc_idle(sdata->local);
1284} 1163}
1285 1164
1286 1165
1287static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, 1166static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
1167 struct ieee80211_mgd_work *wk,
1288 struct ieee80211_mgmt *mgmt, 1168 struct ieee80211_mgmt *mgmt,
1289 size_t len) 1169 size_t len)
1290{ 1170{
@@ -1295,120 +1175,132 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
1295 ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); 1175 ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
1296 if (!elems.challenge) 1176 if (!elems.challenge)
1297 return; 1177 return;
1298 ieee80211_send_auth(sdata, 3, sdata->u.mgd.auth_alg, 1178 ieee80211_send_auth(sdata, 3, wk->auth_alg,
1299 elems.challenge - 2, elems.challenge_len + 2, 1179 elems.challenge - 2, elems.challenge_len + 2,
1300 sdata->u.mgd.bssid, 1); 1180 wk->bss->cbss.bssid, 1);
1301 sdata->u.mgd.auth_transaction = 4; 1181 wk->auth_transaction = 4;
1302} 1182}
1303 1183
1304static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, 1184static enum rx_mgmt_action __must_check
1305 struct ieee80211_mgmt *mgmt, 1185ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
1306 size_t len) 1186 struct ieee80211_mgd_work *wk,
1187 struct ieee80211_mgmt *mgmt, size_t len)
1307{ 1188{
1308 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1309 u16 auth_alg, auth_transaction, status_code; 1189 u16 auth_alg, auth_transaction, status_code;
1310 1190
1311 if (ifmgd->state != IEEE80211_STA_MLME_AUTHENTICATE) 1191 if (wk->state != IEEE80211_MGD_STATE_AUTH)
1312 return; 1192 return RX_MGMT_NONE;
1313 1193
1314 if (len < 24 + 6) 1194 if (len < 24 + 6)
1315 return; 1195 return RX_MGMT_NONE;
1316 1196
1317 if (memcmp(ifmgd->bssid, mgmt->sa, ETH_ALEN) != 0) 1197 if (memcmp(wk->bss->cbss.bssid, mgmt->sa, ETH_ALEN) != 0)
1318 return; 1198 return RX_MGMT_NONE;
1319 1199
1320 if (memcmp(ifmgd->bssid, mgmt->bssid, ETH_ALEN) != 0) 1200 if (memcmp(wk->bss->cbss.bssid, mgmt->bssid, ETH_ALEN) != 0)
1321 return; 1201 return RX_MGMT_NONE;
1322 1202
1323 auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg); 1203 auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg);
1324 auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); 1204 auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction);
1325 status_code = le16_to_cpu(mgmt->u.auth.status_code); 1205 status_code = le16_to_cpu(mgmt->u.auth.status_code);
1326 1206
1327 if (auth_alg != ifmgd->auth_alg || 1207 if (auth_alg != wk->auth_alg ||
1328 auth_transaction != ifmgd->auth_transaction) 1208 auth_transaction != wk->auth_transaction)
1329 return; 1209 return RX_MGMT_NONE;
1330 1210
1331 if (status_code != WLAN_STATUS_SUCCESS) { 1211 if (status_code != WLAN_STATUS_SUCCESS) {
1332 cfg80211_send_rx_auth(sdata->dev, (u8 *) mgmt, len, 1212 list_del(&wk->list);
1333 GFP_KERNEL); 1213 kfree(wk);
1334 ifmgd->state = IEEE80211_STA_MLME_DISABLED; 1214 return RX_MGMT_CFG80211_AUTH;
1335 ieee80211_recalc_idle(sdata->local);
1336 return;
1337 } 1215 }
1338 1216
1339 switch (ifmgd->auth_alg) { 1217 switch (wk->auth_alg) {
1340 case WLAN_AUTH_OPEN: 1218 case WLAN_AUTH_OPEN:
1341 case WLAN_AUTH_LEAP: 1219 case WLAN_AUTH_LEAP:
1342 case WLAN_AUTH_FT: 1220 case WLAN_AUTH_FT:
1343 ieee80211_auth_completed(sdata); 1221 ieee80211_auth_completed(sdata, wk);
1344 cfg80211_send_rx_auth(sdata->dev, (u8 *) mgmt, len, 1222 return RX_MGMT_CFG80211_AUTH;
1345 GFP_KERNEL);
1346 break;
1347 case WLAN_AUTH_SHARED_KEY: 1223 case WLAN_AUTH_SHARED_KEY:
1348 if (ifmgd->auth_transaction == 4) { 1224 if (wk->auth_transaction == 4) {
1349 ieee80211_auth_completed(sdata); 1225 ieee80211_auth_completed(sdata, wk);
1350 cfg80211_send_rx_auth(sdata->dev, (u8 *) mgmt, len, 1226 return RX_MGMT_CFG80211_AUTH;
1351 GFP_KERNEL);
1352 } else 1227 } else
1353 ieee80211_auth_challenge(sdata, mgmt, len); 1228 ieee80211_auth_challenge(sdata, wk, mgmt, len);
1354 break; 1229 break;
1355 } 1230 }
1231
1232 return RX_MGMT_NONE;
1356} 1233}
1357 1234
1358 1235
1359static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, 1236static enum rx_mgmt_action __must_check
1360 struct ieee80211_mgmt *mgmt, 1237ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
1361 size_t len) 1238 struct ieee80211_mgd_work *wk,
1239 struct ieee80211_mgmt *mgmt, size_t len)
1362{ 1240{
1363 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 1241 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1242 const u8 *bssid = NULL;
1364 u16 reason_code; 1243 u16 reason_code;
1365 1244
1366 if (len < 24 + 2) 1245 if (len < 24 + 2)
1367 return; 1246 return RX_MGMT_NONE;
1368 1247
1369 if (memcmp(ifmgd->bssid, mgmt->sa, ETH_ALEN)) 1248 ASSERT_MGD_MTX(ifmgd);
1370 return; 1249
1250 if (wk)
1251 bssid = wk->bss->cbss.bssid;
1252 else
1253 bssid = ifmgd->associated->cbss.bssid;
1371 1254
1372 reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); 1255 reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
1373 1256
1374 if (ifmgd->flags & IEEE80211_STA_AUTHENTICATED) 1257 printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n",
1375 printk(KERN_DEBUG "%s: deauthenticated (Reason: %u)\n", 1258 sdata->dev->name, bssid, reason_code);
1376 sdata->dev->name, reason_code); 1259
1260 if (!wk) {
1261 ieee80211_set_disassoc(sdata, bssid, true);
1262 } else {
1263 list_del(&wk->list);
1264 kfree(wk);
1265 }
1377 1266
1378 ieee80211_set_disassoc(sdata, true, false, 0); 1267 return RX_MGMT_CFG80211_DEAUTH;
1379 ifmgd->flags &= ~IEEE80211_STA_AUTHENTICATED;
1380 cfg80211_send_deauth(sdata->dev, (u8 *) mgmt, len, GFP_KERNEL);
1381} 1268}
1382 1269
1383 1270
1384static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, 1271static enum rx_mgmt_action __must_check
1385 struct ieee80211_mgmt *mgmt, 1272ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
1386 size_t len) 1273 struct ieee80211_mgmt *mgmt, size_t len)
1387{ 1274{
1388 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 1275 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1389 u16 reason_code; 1276 u16 reason_code;
1390 1277
1391 if (len < 24 + 2) 1278 if (len < 24 + 2)
1392 return; 1279 return RX_MGMT_NONE;
1393 1280
1394 if (memcmp(ifmgd->bssid, mgmt->sa, ETH_ALEN)) 1281 ASSERT_MGD_MTX(ifmgd);
1395 return; 1282
1283 if (WARN_ON(!ifmgd->associated))
1284 return RX_MGMT_NONE;
1285
1286 if (WARN_ON(memcmp(ifmgd->associated->cbss.bssid, mgmt->sa, ETH_ALEN)))
1287 return RX_MGMT_NONE;
1396 1288
1397 reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); 1289 reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
1398 1290
1399 if (ifmgd->flags & IEEE80211_STA_ASSOCIATED) 1291 printk(KERN_DEBUG "%s: disassociated (Reason: %u)\n",
1400 printk(KERN_DEBUG "%s: disassociated (Reason: %u)\n", 1292 sdata->dev->name, reason_code);
1401 sdata->dev->name, reason_code);
1402 1293
1403 ieee80211_set_disassoc(sdata, false, false, reason_code); 1294 ieee80211_set_disassoc(sdata, ifmgd->associated->cbss.bssid, false);
1404 cfg80211_send_disassoc(sdata->dev, (u8 *) mgmt, len, GFP_KERNEL); 1295 return RX_MGMT_CFG80211_DISASSOC;
1405} 1296}
1406 1297
1407 1298
1408static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, 1299static enum rx_mgmt_action __must_check
1409 struct ieee80211_mgmt *mgmt, 1300ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
1410 size_t len, 1301 struct ieee80211_mgd_work *wk,
1411 int reassoc) 1302 struct ieee80211_mgmt *mgmt, size_t len,
1303 bool reassoc)
1412{ 1304{
1413 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 1305 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1414 struct ieee80211_local *local = sdata->local; 1306 struct ieee80211_local *local = sdata->local;
@@ -1424,17 +1316,16 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
1424 bool have_higher_than_11mbit = false, newsta = false; 1316 bool have_higher_than_11mbit = false, newsta = false;
1425 u16 ap_ht_cap_flags; 1317 u16 ap_ht_cap_flags;
1426 1318
1427 /* AssocResp and ReassocResp have identical structure, so process both 1319 /*
1428 * of them in this function. */ 1320 * AssocResp and ReassocResp have identical structure, so process both
1429 1321 * of them in this function.
1430 if (ifmgd->state != IEEE80211_STA_MLME_ASSOCIATE) 1322 */
1431 return;
1432 1323
1433 if (len < 24 + 6) 1324 if (len < 24 + 6)
1434 return; 1325 return RX_MGMT_NONE;
1435 1326
1436 if (memcmp(ifmgd->bssid, mgmt->sa, ETH_ALEN) != 0) 1327 if (memcmp(wk->bss->cbss.bssid, mgmt->sa, ETH_ALEN) != 0)
1437 return; 1328 return RX_MGMT_NONE;
1438 1329
1439 capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); 1330 capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
1440 status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); 1331 status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
@@ -1457,21 +1348,19 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
1457 printk(KERN_DEBUG "%s: AP rejected association temporarily; " 1348 printk(KERN_DEBUG "%s: AP rejected association temporarily; "
1458 "comeback duration %u TU (%u ms)\n", 1349 "comeback duration %u TU (%u ms)\n",
1459 sdata->dev->name, tu, ms); 1350 sdata->dev->name, tu, ms);
1351 wk->timeout = jiffies + msecs_to_jiffies(ms);
1460 if (ms > IEEE80211_ASSOC_TIMEOUT) 1352 if (ms > IEEE80211_ASSOC_TIMEOUT)
1461 mod_timer(&ifmgd->timer, 1353 mod_timer(&ifmgd->timer,
1462 jiffies + msecs_to_jiffies(ms)); 1354 jiffies + msecs_to_jiffies(ms));
1463 return; 1355 return RX_MGMT_NONE;
1464 } 1356 }
1465 1357
1466 if (status_code != WLAN_STATUS_SUCCESS) { 1358 if (status_code != WLAN_STATUS_SUCCESS) {
1467 printk(KERN_DEBUG "%s: AP denied association (code=%d)\n", 1359 printk(KERN_DEBUG "%s: AP denied association (code=%d)\n",
1468 sdata->dev->name, status_code); 1360 sdata->dev->name, status_code);
1469 cfg80211_send_rx_assoc(sdata->dev, (u8 *) mgmt, len, 1361 list_del(&wk->list);
1470 GFP_KERNEL); 1362 kfree(wk);
1471 /* Wait for SME to decide what to do next */ 1363 return RX_MGMT_CFG80211_ASSOC;
1472 ifmgd->state = IEEE80211_STA_MLME_DISABLED;
1473 ieee80211_recalc_idle(local);
1474 return;
1475 } 1364 }
1476 1365
1477 if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) 1366 if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
@@ -1482,50 +1371,38 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
1482 if (!elems.supp_rates) { 1371 if (!elems.supp_rates) {
1483 printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n", 1372 printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n",
1484 sdata->dev->name); 1373 sdata->dev->name);
1485 return; 1374 return RX_MGMT_NONE;
1486 } 1375 }
1487 1376
1488 printk(KERN_DEBUG "%s: associated\n", sdata->dev->name); 1377 printk(KERN_DEBUG "%s: associated\n", sdata->dev->name);
1489 ifmgd->aid = aid; 1378 ifmgd->aid = aid;
1490 1379
1491 kfree(ifmgd->assocresp_ies);
1492 ifmgd->assocresp_ies_len = len - (pos - (u8 *) mgmt);
1493 ifmgd->assocresp_ies = kmalloc(ifmgd->assocresp_ies_len, GFP_KERNEL);
1494 if (ifmgd->assocresp_ies)
1495 memcpy(ifmgd->assocresp_ies, pos, ifmgd->assocresp_ies_len);
1496
1497 rcu_read_lock(); 1380 rcu_read_lock();
1498 1381
1499 /* Add STA entry for the AP */ 1382 /* Add STA entry for the AP */
1500 sta = sta_info_get(local, ifmgd->bssid); 1383 sta = sta_info_get(local, wk->bss->cbss.bssid);
1501 if (!sta) { 1384 if (!sta) {
1502 newsta = true; 1385 newsta = true;
1503 1386
1504 sta = sta_info_alloc(sdata, ifmgd->bssid, GFP_ATOMIC); 1387 rcu_read_unlock();
1388
1389 sta = sta_info_alloc(sdata, wk->bss->cbss.bssid, GFP_KERNEL);
1505 if (!sta) { 1390 if (!sta) {
1506 printk(KERN_DEBUG "%s: failed to alloc STA entry for" 1391 printk(KERN_DEBUG "%s: failed to alloc STA entry for"
1507 " the AP\n", sdata->dev->name); 1392 " the AP\n", sdata->dev->name);
1508 rcu_read_unlock(); 1393 return RX_MGMT_NONE;
1509 return;
1510 } 1394 }
1511 1395
1512 /* update new sta with its last rx activity */ 1396 /* update new sta with its last rx activity */
1513 sta->last_rx = jiffies; 1397 sta->last_rx = jiffies;
1514 }
1515 1398
1516 /* 1399 set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC |
1517 * FIXME: Do we really need to update the sta_info's information here? 1400 WLAN_STA_ASSOC_AP);
1518 * We already know about the AP (we found it in our list) so it 1401 if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT))
1519 * should already be filled with the right info, no? 1402 set_sta_flags(sta, WLAN_STA_AUTHORIZED);
1520 * As is stands, all this is racy because typically we assume
1521 * the information that is filled in here (except flags) doesn't
1522 * change while a STA structure is alive. As such, it should move
1523 * to between the sta_info_alloc() and sta_info_insert() above.
1524 */
1525 1403
1526 set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP); 1404 rcu_read_lock();
1527 if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) 1405 }
1528 set_sta_flags(sta, WLAN_STA_AUTHORIZED);
1529 1406
1530 rates = 0; 1407 rates = 0;
1531 basic_rates = 0; 1408 basic_rates = 0;
@@ -1595,7 +1472,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
1595 printk(KERN_DEBUG "%s: failed to insert STA entry for" 1472 printk(KERN_DEBUG "%s: failed to insert STA entry for"
1596 " the AP (error %d)\n", sdata->dev->name, err); 1473 " the AP (error %d)\n", sdata->dev->name, err);
1597 rcu_read_unlock(); 1474 rcu_read_unlock();
1598 return; 1475 return RX_MGMT_NONE;
1599 } 1476 }
1600 } 1477 }
1601 1478
@@ -1611,13 +1488,14 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
1611 (ifmgd->flags & IEEE80211_STA_WMM_ENABLED) && 1488 (ifmgd->flags & IEEE80211_STA_WMM_ENABLED) &&
1612 !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) 1489 !(ifmgd->flags & IEEE80211_STA_DISABLE_11N))
1613 changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem, 1490 changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem,
1491 wk->bss->cbss.bssid,
1614 ap_ht_cap_flags); 1492 ap_ht_cap_flags);
1615 1493
1616 /* set AID and assoc capability, 1494 /* set AID and assoc capability,
1617 * ieee80211_set_associated() will tell the driver */ 1495 * ieee80211_set_associated() will tell the driver */
1618 bss_conf->aid = aid; 1496 bss_conf->aid = aid;
1619 bss_conf->assoc_capability = capab_info; 1497 bss_conf->assoc_capability = capab_info;
1620 ieee80211_set_associated(sdata, changed); 1498 ieee80211_set_associated(sdata, wk->bss, changed);
1621 1499
1622 /* 1500 /*
1623 * initialise the time of last beacon to be the association time, 1501 * initialise the time of last beacon to be the association time,
@@ -1625,8 +1503,9 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
1625 */ 1503 */
1626 ifmgd->last_beacon = jiffies; 1504 ifmgd->last_beacon = jiffies;
1627 1505
1628 ieee80211_associated(sdata); 1506 list_del(&wk->list);
1629 cfg80211_send_rx_assoc(sdata->dev, (u8 *) mgmt, len, GFP_KERNEL); 1507 kfree(wk);
1508 return RX_MGMT_CFG80211_ASSOC;
1630} 1509}
1631 1510
1632 1511
@@ -1654,23 +1533,25 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
1654 1533
1655 bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems, 1534 bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems,
1656 channel, beacon); 1535 channel, beacon);
1657 if (!bss) 1536 if (bss)
1537 ieee80211_rx_bss_put(local, bss);
1538
1539 if (!sdata->u.mgd.associated)
1658 return; 1540 return;
1659 1541
1660 if (elems->ch_switch_elem && (elems->ch_switch_elem_len == 3) && 1542 if (elems->ch_switch_elem && (elems->ch_switch_elem_len == 3) &&
1661 (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN) == 0)) { 1543 (memcmp(mgmt->bssid, sdata->u.mgd.associated->cbss.bssid,
1544 ETH_ALEN) == 0)) {
1662 struct ieee80211_channel_sw_ie *sw_elem = 1545 struct ieee80211_channel_sw_ie *sw_elem =
1663 (struct ieee80211_channel_sw_ie *)elems->ch_switch_elem; 1546 (struct ieee80211_channel_sw_ie *)elems->ch_switch_elem;
1664 ieee80211_sta_process_chanswitch(sdata, sw_elem, bss); 1547 ieee80211_sta_process_chanswitch(sdata, sw_elem, bss);
1665 } 1548 }
1666
1667 ieee80211_rx_bss_put(local, bss);
1668} 1549}
1669 1550
1670 1551
1671static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, 1552static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
1672 struct ieee80211_mgmt *mgmt, 1553 struct ieee80211_mgd_work *wk,
1673 size_t len, 1554 struct ieee80211_mgmt *mgmt, size_t len,
1674 struct ieee80211_rx_status *rx_status) 1555 struct ieee80211_rx_status *rx_status)
1675{ 1556{
1676 struct ieee80211_if_managed *ifmgd; 1557 struct ieee80211_if_managed *ifmgd;
@@ -1679,6 +1560,8 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
1679 1560
1680 ifmgd = &sdata->u.mgd; 1561 ifmgd = &sdata->u.mgd;
1681 1562
1563 ASSERT_MGD_MTX(ifmgd);
1564
1682 if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN)) 1565 if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN))
1683 return; /* ignore ProbeResp to foreign address */ 1566 return; /* ignore ProbeResp to foreign address */
1684 1567
@@ -1692,13 +1575,17 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
1692 ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false); 1575 ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false);
1693 1576
1694 /* direct probe may be part of the association flow */ 1577 /* direct probe may be part of the association flow */
1695 if (ifmgd->state == IEEE80211_STA_MLME_DIRECT_PROBE) { 1578 if (wk && wk->state == IEEE80211_MGD_STATE_PROBE) {
1696 printk(KERN_DEBUG "%s direct probe responded\n", 1579 printk(KERN_DEBUG "%s direct probe responded\n",
1697 sdata->dev->name); 1580 sdata->dev->name);
1698 ieee80211_authenticate(sdata); 1581 wk->tries = 0;
1582 wk->state = IEEE80211_MGD_STATE_AUTH;
1583 WARN_ON(ieee80211_authenticate(sdata, wk) != RX_MGMT_NONE);
1699 } 1584 }
1700 1585
1701 if (ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) { 1586 if (ifmgd->associated &&
1587 memcmp(mgmt->bssid, ifmgd->associated->cbss.bssid, ETH_ALEN) == 0 &&
1588 ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) {
1702 ifmgd->flags &= ~IEEE80211_STA_PROBEREQ_POLL; 1589 ifmgd->flags &= ~IEEE80211_STA_PROBEREQ_POLL;
1703 mutex_lock(&sdata->local->iflist_mtx); 1590 mutex_lock(&sdata->local->iflist_mtx);
1704 ieee80211_recalc_ps(sdata->local, -1); 1591 ieee80211_recalc_ps(sdata->local, -1);
@@ -1740,6 +1627,9 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
1740 bool erp_valid, directed_tim = false; 1627 bool erp_valid, directed_tim = false;
1741 u8 erp_value = 0; 1628 u8 erp_value = 0;
1742 u32 ncrc; 1629 u32 ncrc;
1630 u8 *bssid;
1631
1632 ASSERT_MGD_MTX(ifmgd);
1743 1633
1744 /* Process beacon from the current BSS */ 1634 /* Process beacon from the current BSS */
1745 baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt; 1635 baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
@@ -1749,8 +1639,12 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
1749 if (rx_status->freq != local->hw.conf.channel->center_freq) 1639 if (rx_status->freq != local->hw.conf.channel->center_freq)
1750 return; 1640 return;
1751 1641
1752 if (!(ifmgd->flags & IEEE80211_STA_ASSOCIATED) || 1642 if (WARN_ON(!ifmgd->associated))
1753 memcmp(ifmgd->bssid, mgmt->bssid, ETH_ALEN) != 0) 1643 return;
1644
1645 bssid = ifmgd->associated->cbss.bssid;
1646
1647 if (WARN_ON(memcmp(bssid, mgmt->bssid, ETH_ALEN) != 0))
1754 return; 1648 return;
1755 1649
1756 if (ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) { 1650 if (ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) {
@@ -1829,8 +1723,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
1829 1723
1830 rcu_read_lock(); 1724 rcu_read_lock();
1831 1725
1832 sta = sta_info_get(local, ifmgd->bssid); 1726 sta = sta_info_get(local, bssid);
1833 if (!sta) { 1727 if (WARN_ON(!sta)) {
1834 rcu_read_unlock(); 1728 rcu_read_unlock();
1835 return; 1729 return;
1836 } 1730 }
@@ -1845,7 +1739,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
1845 rcu_read_unlock(); 1739 rcu_read_unlock();
1846 1740
1847 changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem, 1741 changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem,
1848 ap_ht_cap_flags); 1742 bssid, ap_ht_cap_flags);
1849 } 1743 }
1850 1744
1851 if (elems.country_elem) { 1745 if (elems.country_elem) {
@@ -1887,6 +1781,7 @@ ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata,
1887 case IEEE80211_STYPE_REASSOC_RESP: 1781 case IEEE80211_STYPE_REASSOC_RESP:
1888 case IEEE80211_STYPE_DEAUTH: 1782 case IEEE80211_STYPE_DEAUTH:
1889 case IEEE80211_STYPE_DISASSOC: 1783 case IEEE80211_STYPE_DISASSOC:
1784 case IEEE80211_STYPE_ACTION:
1890 skb_queue_tail(&sdata->u.mgd.skb_queue, skb); 1785 skb_queue_tail(&sdata->u.mgd.skb_queue, skb);
1891 queue_work(local->hw.workqueue, &sdata->u.mgd.work); 1786 queue_work(local->hw.workqueue, &sdata->u.mgd.work);
1892 return RX_QUEUED; 1787 return RX_QUEUED;
@@ -1898,40 +1793,118 @@ ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata,
1898static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, 1793static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
1899 struct sk_buff *skb) 1794 struct sk_buff *skb)
1900{ 1795{
1796 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1901 struct ieee80211_rx_status *rx_status; 1797 struct ieee80211_rx_status *rx_status;
1902 struct ieee80211_mgmt *mgmt; 1798 struct ieee80211_mgmt *mgmt;
1799 struct ieee80211_mgd_work *wk;
1800 enum rx_mgmt_action rma = RX_MGMT_NONE;
1903 u16 fc; 1801 u16 fc;
1904 1802
1905 rx_status = (struct ieee80211_rx_status *) skb->cb; 1803 rx_status = (struct ieee80211_rx_status *) skb->cb;
1906 mgmt = (struct ieee80211_mgmt *) skb->data; 1804 mgmt = (struct ieee80211_mgmt *) skb->data;
1907 fc = le16_to_cpu(mgmt->frame_control); 1805 fc = le16_to_cpu(mgmt->frame_control);
1908 1806
1909 switch (fc & IEEE80211_FCTL_STYPE) { 1807 mutex_lock(&ifmgd->mtx);
1910 case IEEE80211_STYPE_PROBE_RESP: 1808
1911 ieee80211_rx_mgmt_probe_resp(sdata, mgmt, skb->len, 1809 if (ifmgd->associated &&
1912 rx_status); 1810 memcmp(ifmgd->associated->cbss.bssid, mgmt->bssid,
1913 break; 1811 ETH_ALEN) == 0) {
1914 case IEEE80211_STYPE_BEACON: 1812 switch (fc & IEEE80211_FCTL_STYPE) {
1915 ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, 1813 case IEEE80211_STYPE_BEACON:
1916 rx_status); 1814 ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len,
1917 break; 1815 rx_status);
1918 case IEEE80211_STYPE_AUTH: 1816 break;
1919 ieee80211_rx_mgmt_auth(sdata, mgmt, skb->len); 1817 case IEEE80211_STYPE_PROBE_RESP:
1920 break; 1818 ieee80211_rx_mgmt_probe_resp(sdata, NULL, mgmt,
1921 case IEEE80211_STYPE_ASSOC_RESP: 1819 skb->len, rx_status);
1922 ieee80211_rx_mgmt_assoc_resp(sdata, mgmt, skb->len, 0); 1820 break;
1821 case IEEE80211_STYPE_DEAUTH:
1822 rma = ieee80211_rx_mgmt_deauth(sdata, NULL,
1823 mgmt, skb->len);
1824 break;
1825 case IEEE80211_STYPE_DISASSOC:
1826 rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len);
1827 break;
1828 case IEEE80211_STYPE_ACTION:
1829 /* XXX: differentiate, can only happen for CSA now! */
1830 ieee80211_sta_process_chanswitch(sdata,
1831 &mgmt->u.action.u.chan_switch.sw_elem,
1832 ifmgd->associated);
1833 break;
1834 }
1835 mutex_unlock(&ifmgd->mtx);
1836
1837 switch (rma) {
1838 case RX_MGMT_NONE:
1839 /* no action */
1840 break;
1841 case RX_MGMT_CFG80211_DEAUTH:
1842 cfg80211_send_deauth(sdata->dev, (u8 *) mgmt,
1843 skb->len, GFP_KERNEL);
1844 break;
1845 case RX_MGMT_CFG80211_DISASSOC:
1846 cfg80211_send_disassoc(sdata->dev, (u8 *) mgmt,
1847 skb->len, GFP_KERNEL);
1848 break;
1849 default:
1850 WARN(1, "unexpected: %d", rma);
1851 }
1852 goto out;
1853 }
1854
1855 list_for_each_entry(wk, &ifmgd->work_list, list) {
1856 if (memcmp(wk->bss->cbss.bssid, mgmt->bssid, ETH_ALEN) != 0)
1857 continue;
1858
1859 switch (fc & IEEE80211_FCTL_STYPE) {
1860 case IEEE80211_STYPE_PROBE_RESP:
1861 ieee80211_rx_mgmt_probe_resp(sdata, wk, mgmt, skb->len,
1862 rx_status);
1863 break;
1864 case IEEE80211_STYPE_AUTH:
1865 rma = ieee80211_rx_mgmt_auth(sdata, wk, mgmt, skb->len);
1866 break;
1867 case IEEE80211_STYPE_ASSOC_RESP:
1868 rma = ieee80211_rx_mgmt_assoc_resp(sdata, wk, mgmt,
1869 skb->len, false);
1870 break;
1871 case IEEE80211_STYPE_REASSOC_RESP:
1872 rma = ieee80211_rx_mgmt_assoc_resp(sdata, wk, mgmt,
1873 skb->len, true);
1874 break;
1875 case IEEE80211_STYPE_DEAUTH:
1876 rma = ieee80211_rx_mgmt_deauth(sdata, wk, mgmt,
1877 skb->len);
1878 break;
1879 }
1880 /*
1881 * We've processed this frame for that work, so it can't
1882 * belong to another work struct.
1883 * NB: this is also required for correctness because the
1884 * called functions can free 'wk', and for 'rma'!
1885 */
1923 break; 1886 break;
1924 case IEEE80211_STYPE_REASSOC_RESP: 1887 }
1925 ieee80211_rx_mgmt_assoc_resp(sdata, mgmt, skb->len, 1); 1888
1889 mutex_unlock(&ifmgd->mtx);
1890
1891 switch (rma) {
1892 case RX_MGMT_NONE:
1893 /* no action */
1926 break; 1894 break;
1927 case IEEE80211_STYPE_DEAUTH: 1895 case RX_MGMT_CFG80211_AUTH:
1928 ieee80211_rx_mgmt_deauth(sdata, mgmt, skb->len); 1896 cfg80211_send_rx_auth(sdata->dev, (u8 *) mgmt, skb->len,
1897 GFP_KERNEL);
1929 break; 1898 break;
1930 case IEEE80211_STYPE_DISASSOC: 1899 case RX_MGMT_CFG80211_ASSOC:
1931 ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len); 1900 cfg80211_send_rx_assoc(sdata->dev, (u8 *) mgmt, skb->len,
1901 GFP_KERNEL);
1932 break; 1902 break;
1903 default:
1904 WARN(1, "unexpected: %d", rma);
1933 } 1905 }
1934 1906
1907 out:
1935 kfree_skb(skb); 1908 kfree_skb(skb);
1936} 1909}
1937 1910
@@ -1947,89 +1920,9 @@ static void ieee80211_sta_timer(unsigned long data)
1947 return; 1920 return;
1948 } 1921 }
1949 1922
1950 set_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request);
1951 queue_work(local->hw.workqueue, &ifmgd->work); 1923 queue_work(local->hw.workqueue, &ifmgd->work);
1952} 1924}
1953 1925
1954static void ieee80211_sta_reset_auth(struct ieee80211_sub_if_data *sdata)
1955{
1956 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1957 struct ieee80211_local *local = sdata->local;
1958
1959 /* Reset own TSF to allow time synchronization work. */
1960 drv_reset_tsf(local);
1961
1962 ifmgd->wmm_last_param_set = -1; /* allow any WMM update */
1963 ifmgd->auth_transaction = -1;
1964 ifmgd->flags &= ~IEEE80211_STA_ASSOCIATED;
1965 ifmgd->assoc_scan_tries = 0;
1966 ifmgd->direct_probe_tries = 0;
1967 ifmgd->auth_tries = 0;
1968 ifmgd->assoc_tries = 0;
1969 netif_tx_stop_all_queues(sdata->dev);
1970 netif_carrier_off(sdata->dev);
1971}
1972
1973static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata)
1974{
1975 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1976 struct ieee80211_local *local = sdata->local;
1977 struct ieee80211_bss *bss;
1978 u8 *bssid = ifmgd->bssid, *ssid = ifmgd->ssid;
1979 u8 ssid_len = ifmgd->ssid_len;
1980 u16 capa_mask = WLAN_CAPABILITY_ESS;
1981 u16 capa_val = WLAN_CAPABILITY_ESS;
1982 struct ieee80211_channel *chan = local->oper_channel;
1983
1984 bss = (void *)cfg80211_get_bss(local->hw.wiphy, chan,
1985 bssid, ssid, ssid_len,
1986 capa_mask, capa_val);
1987
1988 if (bss) {
1989 local->oper_channel = bss->cbss.channel;
1990 local->oper_channel_type = NL80211_CHAN_NO_HT;
1991 ieee80211_hw_config(local, 0);
1992
1993 ieee80211_sta_def_wmm_params(sdata, bss->supp_rates_len,
1994 bss->supp_rates);
1995 if (sdata->u.mgd.mfp == IEEE80211_MFP_REQUIRED)
1996 sdata->u.mgd.flags |= IEEE80211_STA_MFP_ENABLED;
1997 else
1998 sdata->u.mgd.flags &= ~IEEE80211_STA_MFP_ENABLED;
1999
2000 /* Send out direct probe if no probe resp was received or
2001 * the one we have is outdated
2002 */
2003 if (!bss->last_probe_resp ||
2004 time_after(jiffies, bss->last_probe_resp
2005 + IEEE80211_SCAN_RESULT_EXPIRE))
2006 ifmgd->state = IEEE80211_STA_MLME_DIRECT_PROBE;
2007 else
2008 ifmgd->state = IEEE80211_STA_MLME_AUTHENTICATE;
2009
2010 ieee80211_rx_bss_put(local, bss);
2011 ieee80211_sta_reset_auth(sdata);
2012 return 0;
2013 } else {
2014 if (ifmgd->assoc_scan_tries < IEEE80211_ASSOC_SCANS_MAX_TRIES) {
2015
2016 ifmgd->assoc_scan_tries++;
2017
2018 ieee80211_request_internal_scan(sdata, ifmgd->ssid,
2019 ssid_len);
2020
2021 ifmgd->state = IEEE80211_STA_MLME_AUTHENTICATE;
2022 set_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request);
2023 } else {
2024 ifmgd->assoc_scan_tries = 0;
2025 ifmgd->state = IEEE80211_STA_MLME_DISABLED;
2026 ieee80211_recalc_idle(local);
2027 }
2028 }
2029 return -1;
2030}
2031
2032
2033static void ieee80211_sta_work(struct work_struct *work) 1926static void ieee80211_sta_work(struct work_struct *work)
2034{ 1927{
2035 struct ieee80211_sub_if_data *sdata = 1928 struct ieee80211_sub_if_data *sdata =
@@ -2037,6 +1930,10 @@ static void ieee80211_sta_work(struct work_struct *work)
2037 struct ieee80211_local *local = sdata->local; 1930 struct ieee80211_local *local = sdata->local;
2038 struct ieee80211_if_managed *ifmgd; 1931 struct ieee80211_if_managed *ifmgd;
2039 struct sk_buff *skb; 1932 struct sk_buff *skb;
1933 struct ieee80211_mgd_work *wk, *tmp;
1934 LIST_HEAD(free_work);
1935 enum rx_mgmt_action rma;
1936 bool anybusy = false;
2040 1937
2041 if (!netif_running(sdata->dev)) 1938 if (!netif_running(sdata->dev))
2042 return; 1939 return;
@@ -2059,46 +1956,93 @@ static void ieee80211_sta_work(struct work_struct *work)
2059 1956
2060 ifmgd = &sdata->u.mgd; 1957 ifmgd = &sdata->u.mgd;
2061 1958
1959 /* first process frames to avoid timing out while a frame is pending */
2062 while ((skb = skb_dequeue(&ifmgd->skb_queue))) 1960 while ((skb = skb_dequeue(&ifmgd->skb_queue)))
2063 ieee80211_sta_rx_queued_mgmt(sdata, skb); 1961 ieee80211_sta_rx_queued_mgmt(sdata, skb);
2064 1962
2065 if (ifmgd->state != IEEE80211_STA_MLME_DIRECT_PROBE && 1963 /* then process the rest of the work */
2066 ifmgd->state != IEEE80211_STA_MLME_AUTHENTICATE && 1964 mutex_lock(&ifmgd->mtx);
2067 ifmgd->state != IEEE80211_STA_MLME_ASSOCIATE && 1965
2068 test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request)) { 1966 list_for_each_entry(wk, &ifmgd->work_list, list) {
2069 queue_delayed_work(local->hw.workqueue, &local->scan_work, 1967 if (wk->state != IEEE80211_MGD_STATE_IDLE) {
2070 round_jiffies_relative(0)); 1968 anybusy = true;
2071 return; 1969 break;
1970 }
2072 } 1971 }
2073 1972
2074 if (test_and_clear_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request)) { 1973 ieee80211_recalc_idle(local);
2075 if (ieee80211_sta_config_auth(sdata)) 1974
2076 return; 1975 if (!anybusy) {
2077 clear_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request); 1976 mutex_unlock(&ifmgd->mtx);
2078 } else if (!test_and_clear_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request)) 1977
1978 if (test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request))
1979 queue_delayed_work(local->hw.workqueue,
1980 &local->scan_work,
1981 round_jiffies_relative(0));
2079 return; 1982 return;
1983 }
2080 1984
2081 ieee80211_recalc_idle(local); 1985 list_for_each_entry_safe(wk, tmp, &ifmgd->work_list, list) {
1986 if (time_before(jiffies, wk->timeout))
1987 continue;
2082 1988
2083 switch (ifmgd->state) { 1989 switch (wk->state) {
2084 case IEEE80211_STA_MLME_DISABLED: 1990 default:
2085 break; 1991 WARN_ON(1);
2086 case IEEE80211_STA_MLME_DIRECT_PROBE: 1992 /* fall through */
2087 ieee80211_direct_probe(sdata); 1993 case IEEE80211_MGD_STATE_IDLE:
2088 break; 1994 /* nothing */
2089 case IEEE80211_STA_MLME_AUTHENTICATE: 1995 rma = RX_MGMT_NONE;
2090 ieee80211_authenticate(sdata); 1996 break;
2091 break; 1997 case IEEE80211_MGD_STATE_PROBE:
2092 case IEEE80211_STA_MLME_ASSOCIATE: 1998 rma = ieee80211_direct_probe(sdata, wk);
2093 ieee80211_associate(sdata); 1999 break;
2094 break; 2000 case IEEE80211_MGD_STATE_AUTH:
2095 case IEEE80211_STA_MLME_ASSOCIATED: 2001 rma = ieee80211_authenticate(sdata, wk);
2096 ieee80211_associated(sdata); 2002 break;
2097 break; 2003 case IEEE80211_MGD_STATE_ASSOC:
2098 default: 2004 rma = ieee80211_associate(sdata, wk);
2099 WARN_ON(1); 2005 break;
2100 break; 2006 }
2007
2008 switch (rma) {
2009 case RX_MGMT_NONE:
2010 /* no action required */
2011 break;
2012 case RX_MGMT_CFG80211_AUTH_TO:
2013 case RX_MGMT_CFG80211_ASSOC_TO:
2014 list_del(&wk->list);
2015 list_add(&wk->list, &free_work);
2016 wk->tries = rma; /* small abuse but only local */
2017 break;
2018 default:
2019 WARN(1, "unexpected: %d", rma);
2020 }
2021 }
2022
2023 mutex_unlock(&ifmgd->mtx);
2024
2025 list_for_each_entry_safe(wk, tmp, &free_work, list) {
2026 switch (wk->tries) {
2027 case RX_MGMT_CFG80211_AUTH_TO:
2028 cfg80211_send_auth_timeout(sdata->dev,
2029 wk->bss->cbss.bssid,
2030 GFP_KERNEL);
2031 break;
2032 case RX_MGMT_CFG80211_ASSOC_TO:
2033 cfg80211_send_auth_timeout(sdata->dev,
2034 wk->bss->cbss.bssid,
2035 GFP_KERNEL);
2036 break;
2037 default:
2038 WARN(1, "unexpected: %d", wk->tries);
2039 }
2040
2041 list_del(&wk->list);
2042 kfree(wk);
2101 } 2043 }
2044
2045 ieee80211_recalc_idle(local);
2102} 2046}
2103 2047
2104static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) 2048static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
@@ -2110,7 +2054,6 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
2110 */ 2054 */
2111 sdata->u.mgd.last_beacon = jiffies; 2055 sdata->u.mgd.last_beacon = jiffies;
2112 2056
2113
2114 queue_work(sdata->local->hw.workqueue, 2057 queue_work(sdata->local->hw.workqueue,
2115 &sdata->u.mgd.work); 2058 &sdata->u.mgd.work);
2116 } 2059 }
@@ -2152,7 +2095,6 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
2152void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) 2095void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
2153{ 2096{
2154 struct ieee80211_if_managed *ifmgd; 2097 struct ieee80211_if_managed *ifmgd;
2155 u32 hw_flags;
2156 2098
2157 ifmgd = &sdata->u.mgd; 2099 ifmgd = &sdata->u.mgd;
2158 INIT_WORK(&ifmgd->work, ieee80211_sta_work); 2100 INIT_WORK(&ifmgd->work, ieee80211_sta_work);
@@ -2164,113 +2106,239 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
2164 (unsigned long) sdata); 2106 (unsigned long) sdata);
2165 skb_queue_head_init(&ifmgd->skb_queue); 2107 skb_queue_head_init(&ifmgd->skb_queue);
2166 2108
2109 INIT_LIST_HEAD(&ifmgd->work_list);
2110
2167 ifmgd->capab = WLAN_CAPABILITY_ESS; 2111 ifmgd->capab = WLAN_CAPABILITY_ESS;
2168 ifmgd->flags = 0; 2112 ifmgd->flags = 0;
2169 if (sdata->local->hw.queues >= 4) 2113 if (sdata->local->hw.queues >= 4)
2170 ifmgd->flags |= IEEE80211_STA_WMM_ENABLED; 2114 ifmgd->flags |= IEEE80211_STA_WMM_ENABLED;
2171 2115
2172 hw_flags = sdata->local->hw.flags; 2116 mutex_init(&ifmgd->mtx);
2173} 2117}
2174 2118
2175/* configuration hooks */ 2119/* scan finished notification */
2176void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata) 2120void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local)
2177{ 2121{
2178 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 2122 struct ieee80211_sub_if_data *sdata = local->scan_sdata;
2179 struct ieee80211_local *local = sdata->local;
2180 2123
2181 if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) 2124 /* Restart STA timers */
2182 return; 2125 rcu_read_lock();
2126 list_for_each_entry_rcu(sdata, &local->interfaces, list)
2127 ieee80211_restart_sta_timer(sdata);
2128 rcu_read_unlock();
2129}
2183 2130
2184 if (WARN_ON(ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED)) 2131int ieee80211_max_network_latency(struct notifier_block *nb,
2185 ieee80211_set_disassoc(sdata, true, true, 2132 unsigned long data, void *dummy)
2186 WLAN_REASON_DEAUTH_LEAVING); 2133{
2134 s32 latency_usec = (s32) data;
2135 struct ieee80211_local *local =
2136 container_of(nb, struct ieee80211_local,
2137 network_latency_notifier);
2187 2138
2188 if (WARN_ON(ifmgd->ssid_len == 0)) { 2139 mutex_lock(&local->iflist_mtx);
2189 /* 2140 ieee80211_recalc_ps(local, latency_usec);
2190 * Only allow association to be started if a valid SSID 2141 mutex_unlock(&local->iflist_mtx);
2191 * is configured.
2192 */
2193 return;
2194 }
2195 2142
2196 set_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request); 2143 return 0;
2197 queue_work(local->hw.workqueue, &ifmgd->work);
2198} 2144}
2199 2145
2200int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, 2146/* config hooks */
2201 const char *ie, size_t len) 2147int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
2148 struct cfg80211_auth_request *req)
2202{ 2149{
2203 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 2150 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2151 const u8 *ssid;
2152 struct ieee80211_mgd_work *wk;
2153 u16 auth_alg;
2204 2154
2205 if (len == 0 && ifmgd->extra_ie_len == 0) 2155 switch (req->auth_type) {
2206 return -EALREADY; 2156 case NL80211_AUTHTYPE_OPEN_SYSTEM:
2207 2157 auth_alg = WLAN_AUTH_OPEN;
2208 if (len == ifmgd->extra_ie_len && ifmgd->extra_ie && 2158 break;
2209 memcmp(ifmgd->extra_ie, ie, len) == 0) 2159 case NL80211_AUTHTYPE_SHARED_KEY:
2210 return -EALREADY; 2160 auth_alg = WLAN_AUTH_SHARED_KEY;
2211 2161 break;
2212 kfree(ifmgd->extra_ie); 2162 case NL80211_AUTHTYPE_FT:
2213 if (len == 0) { 2163 auth_alg = WLAN_AUTH_FT;
2214 ifmgd->extra_ie = NULL; 2164 break;
2215 ifmgd->extra_ie_len = 0; 2165 case NL80211_AUTHTYPE_NETWORK_EAP:
2216 return 0; 2166 auth_alg = WLAN_AUTH_LEAP;
2167 break;
2168 default:
2169 return -EOPNOTSUPP;
2217 } 2170 }
2218 ifmgd->extra_ie = kmalloc(len, GFP_KERNEL); 2171
2219 if (!ifmgd->extra_ie) { 2172 wk = kzalloc(sizeof(*wk) + req->ie_len, GFP_KERNEL);
2220 ifmgd->extra_ie_len = 0; 2173 if (!wk)
2221 return -ENOMEM; 2174 return -ENOMEM;
2175
2176 wk->bss = (void *)req->bss;
2177
2178 if (req->ie && req->ie_len) {
2179 memcpy(wk->ie, req->ie, req->ie_len);
2180 wk->ie_len = req->ie_len;
2222 } 2181 }
2223 memcpy(ifmgd->extra_ie, ie, len); 2182
2224 ifmgd->extra_ie_len = len; 2183 ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID);
2184 memcpy(wk->ssid, ssid + 2, ssid[1]);
2185 wk->ssid_len = ssid[1];
2186
2187 wk->state = IEEE80211_MGD_STATE_PROBE;
2188 wk->auth_alg = auth_alg;
2189
2190 /*
2191 * XXX: if still associated need to tell AP that we're going
2192 * to sleep and then change channel etc.
2193 */
2194 sdata->local->oper_channel = req->bss->channel;
2195 ieee80211_hw_config(sdata->local, 0);
2196
2197 mutex_lock(&ifmgd->mtx);
2198 list_add(&wk->list, &sdata->u.mgd.work_list);
2199 mutex_unlock(&ifmgd->mtx);
2200
2201 queue_work(sdata->local->hw.workqueue, &sdata->u.mgd.work);
2225 return 0; 2202 return 0;
2226} 2203}
2227 2204
2228int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason) 2205int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
2206 struct cfg80211_assoc_request *req)
2229{ 2207{
2230 printk(KERN_DEBUG "%s: deauthenticating by local choice (reason=%d)\n", 2208 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2231 sdata->dev->name, reason); 2209 struct ieee80211_mgd_work *wk, *found = NULL;
2210 int i, err;
2232 2211
2233 ieee80211_set_disassoc(sdata, true, true, reason); 2212 mutex_lock(&ifmgd->mtx);
2234 return 0; 2213
2214 list_for_each_entry(wk, &ifmgd->work_list, list) {
2215 if (&wk->bss->cbss == req->bss &&
2216 wk->state == IEEE80211_MGD_STATE_IDLE) {
2217 found = wk;
2218 break;
2219 }
2220 }
2221
2222 if (!found) {
2223 err = -ENOLINK;
2224 goto out;
2225 }
2226
2227 list_del(&found->list);
2228
2229 wk = krealloc(found, sizeof(*wk) + req->ie_len, GFP_KERNEL);
2230 if (!wk) {
2231 list_add(&found->list, &ifmgd->work_list);
2232 err = -ENOMEM;
2233 goto out;
2234 }
2235
2236 list_add(&wk->list, &ifmgd->work_list);
2237
2238 ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N;
2239
2240 for (i = 0; i < req->crypto.n_ciphers_pairwise; i++)
2241 if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 ||
2242 req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP ||
2243 req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104)
2244 ifmgd->flags |= IEEE80211_STA_DISABLE_11N;
2245
2246 sdata->local->oper_channel = req->bss->channel;
2247 ieee80211_hw_config(sdata->local, 0);
2248
2249 if (req->ie && req->ie_len) {
2250 memcpy(wk->ie, req->ie, req->ie_len);
2251 wk->ie_len = req->ie_len;
2252 } else
2253 wk->ie_len = 0;
2254
2255 if (req->prev_bssid)
2256 memcpy(wk->prev_bssid, req->prev_bssid, ETH_ALEN);
2257
2258 wk->state = IEEE80211_MGD_STATE_ASSOC;
2259 wk->tries = 0;
2260
2261 if (req->use_mfp) {
2262 ifmgd->mfp = IEEE80211_MFP_REQUIRED;
2263 ifmgd->flags |= IEEE80211_STA_MFP_ENABLED;
2264 } else {
2265 ifmgd->mfp = IEEE80211_MFP_DISABLED;
2266 ifmgd->flags &= ~IEEE80211_STA_MFP_ENABLED;
2267 }
2268
2269 if (req->crypto.control_port)
2270 ifmgd->flags |= IEEE80211_STA_CONTROL_PORT;
2271 else
2272 ifmgd->flags &= ~IEEE80211_STA_CONTROL_PORT;
2273
2274 queue_work(sdata->local->hw.workqueue, &sdata->u.mgd.work);
2275
2276 err = 0;
2277
2278 out:
2279 mutex_unlock(&ifmgd->mtx);
2280 return err;
2235} 2281}
2236 2282
2237int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason) 2283int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
2284 struct cfg80211_deauth_request *req)
2238{ 2285{
2239 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 2286 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2287 struct ieee80211_mgd_work *wk;
2288 const u8 *bssid = NULL;
2240 2289
2241 printk(KERN_DEBUG "%s: disassociating by local choice (reason=%d)\n", 2290 printk(KERN_DEBUG "%s: deauthenticating by local choice (reason=%d)\n",
2242 sdata->dev->name, reason); 2291 sdata->dev->name, req->reason_code);
2292
2293 mutex_lock(&ifmgd->mtx);
2294
2295 if (ifmgd->associated && &ifmgd->associated->cbss == req->bss) {
2296 bssid = req->bss->bssid;
2297 ieee80211_set_disassoc(sdata, bssid, true);
2298 } else list_for_each_entry(wk, &ifmgd->work_list, list) {
2299 if (&wk->bss->cbss == req->bss) {
2300 bssid = req->bss->bssid;
2301 list_del(&wk->list);
2302 kfree(wk);
2303 break;
2304 }
2305 }
2243 2306
2244 if (!(ifmgd->flags & IEEE80211_STA_ASSOCIATED)) 2307 /* cfg80211 should catch this... */
2308 if (WARN_ON(!bssid)) {
2309 mutex_unlock(&ifmgd->mtx);
2245 return -ENOLINK; 2310 return -ENOLINK;
2311 }
2312
2313 mutex_unlock(&ifmgd->mtx);
2314
2315 ieee80211_send_deauth_disassoc(sdata, bssid,
2316 IEEE80211_STYPE_DEAUTH, req->reason_code);
2246 2317
2247 ieee80211_set_disassoc(sdata, false, true, reason);
2248 return 0; 2318 return 0;
2249} 2319}
2250 2320
2251/* scan finished notification */ 2321int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
2252void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) 2322 struct cfg80211_disassoc_request *req)
2253{ 2323{
2254 struct ieee80211_sub_if_data *sdata = local->scan_sdata; 2324 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2255 2325
2256 /* Restart STA timers */ 2326 printk(KERN_DEBUG "%s: disassociating by local choice (reason=%d)\n",
2257 rcu_read_lock(); 2327 sdata->dev->name, req->reason_code);
2258 list_for_each_entry_rcu(sdata, &local->interfaces, list)
2259 ieee80211_restart_sta_timer(sdata);
2260 rcu_read_unlock();
2261}
2262 2328
2263int ieee80211_max_network_latency(struct notifier_block *nb, 2329 mutex_lock(&ifmgd->mtx);
2264 unsigned long data, void *dummy)
2265{
2266 s32 latency_usec = (s32) data;
2267 struct ieee80211_local *local =
2268 container_of(nb, struct ieee80211_local,
2269 network_latency_notifier);
2270 2330
2271 mutex_lock(&local->iflist_mtx); 2331 /* cfg80211 should catch that */
2272 ieee80211_recalc_ps(local, latency_usec); 2332 if (WARN_ON(&ifmgd->associated->cbss != req->bss)) {
2273 mutex_unlock(&local->iflist_mtx); 2333 mutex_unlock(&ifmgd->mtx);
2334 return -ENOLINK;
2335 }
2336
2337 ieee80211_set_disassoc(sdata, req->bss->bssid, false);
2338
2339 mutex_unlock(&ifmgd->mtx);
2274 2340
2341 ieee80211_send_deauth_disassoc(sdata, req->bss->bssid,
2342 IEEE80211_STYPE_DISASSOC, req->reason_code);
2275 return 0; 2343 return 0;
2276} 2344}