aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-01-20 07:55:27 -0500
committerJohn W. Linville <linville@tuxdriver.com>2012-02-06 14:50:37 -0500
commit66e67e418908442389d3a9e6509985f01cbaf9b0 (patch)
tree01fad87d0d47f5887497c569d98cee20fa1f0f29 /net/mac80211/mlme.c
parent4c0c0b75e0c35ddb8f61c06bcbffede63ab4f4a2 (diff)
mac80211: redesign auth/assoc
This is the second part of the auth/assoc redesign, the mac80211 part. This moves the auth/assoc code out of the work abstraction and into the MLME, so that we don't flip channels all the time etc. The only downside is that when we are associated, we need to drop the association in order to create a connection to another AP, but for most drivers this is actually desirable and the ability to do was never used by any applications. If we want to implement resource reservation with FT-OTA, we'd probably best do it with explicit R-O-C in wpa_s. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c1340
1 files changed, 985 insertions, 355 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 082fcda57786..52133dab9297 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -30,6 +30,12 @@
30#include "rate.h" 30#include "rate.h"
31#include "led.h" 31#include "led.h"
32 32
33#define IEEE80211_AUTH_TIMEOUT (HZ / 5)
34#define IEEE80211_AUTH_MAX_TRIES 3
35#define IEEE80211_AUTH_WAIT_ASSOC (HZ * 5)
36#define IEEE80211_ASSOC_TIMEOUT (HZ / 5)
37#define IEEE80211_ASSOC_MAX_TRIES 3
38
33static int max_nullfunc_tries = 2; 39static int max_nullfunc_tries = 2;
34module_param(max_nullfunc_tries, int, 0644); 40module_param(max_nullfunc_tries, int, 0644);
35MODULE_PARM_DESC(max_nullfunc_tries, 41MODULE_PARM_DESC(max_nullfunc_tries,
@@ -97,6 +103,15 @@ enum rx_mgmt_action {
97 103
98 /* caller must call cfg80211_send_disassoc() */ 104 /* caller must call cfg80211_send_disassoc() */
99 RX_MGMT_CFG80211_DISASSOC, 105 RX_MGMT_CFG80211_DISASSOC,
106
107 /* caller must call cfg80211_send_rx_auth() */
108 RX_MGMT_CFG80211_RX_AUTH,
109
110 /* caller must call cfg80211_send_rx_assoc() */
111 RX_MGMT_CFG80211_RX_ASSOC,
112
113 /* caller must call cfg80211_send_assoc_timeout() */
114 RX_MGMT_CFG80211_ASSOC_TIMEOUT,
100}; 115};
101 116
102/* utils */ 117/* utils */
@@ -115,8 +130,7 @@ static inline void ASSERT_MGD_MTX(struct ieee80211_if_managed *ifmgd)
115 * has happened -- the work that runs from this timer will 130 * has happened -- the work that runs from this timer will
116 * do that. 131 * do that.
117 */ 132 */
118static void run_again(struct ieee80211_if_managed *ifmgd, 133static void run_again(struct ieee80211_if_managed *ifmgd, unsigned long timeout)
119 unsigned long timeout)
120{ 134{
121 ASSERT_MGD_MTX(ifmgd); 135 ASSERT_MGD_MTX(ifmgd);
122 136
@@ -284,6 +298,319 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
284 298
285/* frame sending functions */ 299/* frame sending functions */
286 300
301static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len,
302 struct ieee80211_supported_band *sband,
303 u32 *rates)
304{
305 int i, j, count;
306 *rates = 0;
307 count = 0;
308 for (i = 0; i < supp_rates_len; i++) {
309 int rate = (supp_rates[i] & 0x7F) * 5;
310
311 for (j = 0; j < sband->n_bitrates; j++)
312 if (sband->bitrates[j].bitrate == rate) {
313 *rates |= BIT(j);
314 count++;
315 break;
316 }
317 }
318
319 return count;
320}
321
322static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata,
323 struct sk_buff *skb, const u8 *ht_info_ie,
324 struct ieee80211_supported_band *sband,
325 struct ieee80211_channel *channel,
326 enum ieee80211_smps_mode smps)
327{
328 struct ieee80211_ht_info *ht_info;
329 u8 *pos;
330 u32 flags = channel->flags;
331 u16 cap;
332 struct ieee80211_sta_ht_cap ht_cap;
333
334 BUILD_BUG_ON(sizeof(ht_cap) != sizeof(sband->ht_cap));
335
336 if (!sband->ht_cap.ht_supported)
337 return;
338
339 if (!ht_info_ie)
340 return;
341
342 if (ht_info_ie[1] < sizeof(struct ieee80211_ht_info))
343 return;
344
345 memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap));
346 ieee80211_apply_htcap_overrides(sdata, &ht_cap);
347
348 ht_info = (struct ieee80211_ht_info *)(ht_info_ie + 2);
349
350 /* determine capability flags */
351 cap = ht_cap.cap;
352
353 switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
354 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
355 if (flags & IEEE80211_CHAN_NO_HT40PLUS) {
356 cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
357 cap &= ~IEEE80211_HT_CAP_SGI_40;
358 }
359 break;
360 case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
361 if (flags & IEEE80211_CHAN_NO_HT40MINUS) {
362 cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
363 cap &= ~IEEE80211_HT_CAP_SGI_40;
364 }
365 break;
366 }
367
368 /* set SM PS mode properly */
369 cap &= ~IEEE80211_HT_CAP_SM_PS;
370 switch (smps) {
371 case IEEE80211_SMPS_AUTOMATIC:
372 case IEEE80211_SMPS_NUM_MODES:
373 WARN_ON(1);
374 case IEEE80211_SMPS_OFF:
375 cap |= WLAN_HT_CAP_SM_PS_DISABLED <<
376 IEEE80211_HT_CAP_SM_PS_SHIFT;
377 break;
378 case IEEE80211_SMPS_STATIC:
379 cap |= WLAN_HT_CAP_SM_PS_STATIC <<
380 IEEE80211_HT_CAP_SM_PS_SHIFT;
381 break;
382 case IEEE80211_SMPS_DYNAMIC:
383 cap |= WLAN_HT_CAP_SM_PS_DYNAMIC <<
384 IEEE80211_HT_CAP_SM_PS_SHIFT;
385 break;
386 }
387
388 /* reserve and fill IE */
389 pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
390 ieee80211_ie_build_ht_cap(pos, &ht_cap, cap);
391}
392
393static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
394{
395 struct ieee80211_local *local = sdata->local;
396 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
397 struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data;
398 struct sk_buff *skb;
399 struct ieee80211_mgmt *mgmt;
400 u8 *pos, qos_info;
401 size_t offset = 0, noffset;
402 int i, count, rates_len, supp_rates_len;
403 u16 capab;
404 struct ieee80211_supported_band *sband;
405 u32 rates = 0;
406 struct ieee80211_bss *bss = (void *)assoc_data->bss->priv;
407
408 lockdep_assert_held(&ifmgd->mtx);
409
410 sband = local->hw.wiphy->bands[local->oper_channel->band];
411
412 if (assoc_data->supp_rates_len) {
413 /*
414 * Get all rates supported by the device and the AP as
415 * some APs don't like getting a superset of their rates
416 * in the association request (e.g. D-Link DAP 1353 in
417 * b-only mode)...
418 */
419 rates_len = ieee80211_compatible_rates(assoc_data->supp_rates,
420 assoc_data->supp_rates_len,
421 sband, &rates);
422 } else {
423 /*
424 * In case AP not provide any supported rates information
425 * before association, we send information element(s) with
426 * all rates that we support.
427 */
428 rates = ~0;
429 rates_len = sband->n_bitrates;
430 }
431
432 skb = alloc_skb(local->hw.extra_tx_headroom +
433 sizeof(*mgmt) + /* bit too much but doesn't matter */
434 2 + assoc_data->ssid_len + /* SSID */
435 4 + rates_len + /* (extended) rates */
436 4 + /* power capability */
437 2 + 2 * sband->n_channels + /* supported channels */
438 2 + sizeof(struct ieee80211_ht_cap) + /* HT */
439 assoc_data->ie_len + /* extra IEs */
440 9, /* WMM */
441 GFP_KERNEL);
442 if (!skb)
443 return;
444
445 skb_reserve(skb, local->hw.extra_tx_headroom);
446
447 capab = WLAN_CAPABILITY_ESS;
448
449 if (sband->band == IEEE80211_BAND_2GHZ) {
450 if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE))
451 capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
452 if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE))
453 capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
454 }
455
456 if (assoc_data->capability & WLAN_CAPABILITY_PRIVACY)
457 capab |= WLAN_CAPABILITY_PRIVACY;
458
459 if ((assoc_data->capability & WLAN_CAPABILITY_SPECTRUM_MGMT) &&
460 (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT))
461 capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
462
463 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
464 memset(mgmt, 0, 24);
465 memcpy(mgmt->da, assoc_data->bss->bssid, ETH_ALEN);
466 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
467 memcpy(mgmt->bssid, assoc_data->bss->bssid, ETH_ALEN);
468
469 if (!is_zero_ether_addr(assoc_data->prev_bssid)) {
470 skb_put(skb, 10);
471 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
472 IEEE80211_STYPE_REASSOC_REQ);
473 mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab);
474 mgmt->u.reassoc_req.listen_interval =
475 cpu_to_le16(local->hw.conf.listen_interval);
476 memcpy(mgmt->u.reassoc_req.current_ap, assoc_data->prev_bssid,
477 ETH_ALEN);
478 } else {
479 skb_put(skb, 4);
480 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
481 IEEE80211_STYPE_ASSOC_REQ);
482 mgmt->u.assoc_req.capab_info = cpu_to_le16(capab);
483 mgmt->u.assoc_req.listen_interval =
484 cpu_to_le16(local->hw.conf.listen_interval);
485 }
486
487 /* SSID */
488 pos = skb_put(skb, 2 + assoc_data->ssid_len);
489 *pos++ = WLAN_EID_SSID;
490 *pos++ = assoc_data->ssid_len;
491 memcpy(pos, assoc_data->ssid, assoc_data->ssid_len);
492
493 /* add all rates which were marked to be used above */
494 supp_rates_len = rates_len;
495 if (supp_rates_len > 8)
496 supp_rates_len = 8;
497
498 pos = skb_put(skb, supp_rates_len + 2);
499 *pos++ = WLAN_EID_SUPP_RATES;
500 *pos++ = supp_rates_len;
501
502 count = 0;
503 for (i = 0; i < sband->n_bitrates; i++) {
504 if (BIT(i) & rates) {
505 int rate = sband->bitrates[i].bitrate;
506 *pos++ = (u8) (rate / 5);
507 if (++count == 8)
508 break;
509 }
510 }
511
512 if (rates_len > count) {
513 pos = skb_put(skb, rates_len - count + 2);
514 *pos++ = WLAN_EID_EXT_SUPP_RATES;
515 *pos++ = rates_len - count;
516
517 for (i++; i < sband->n_bitrates; i++) {
518 if (BIT(i) & rates) {
519 int rate = sband->bitrates[i].bitrate;
520 *pos++ = (u8) (rate / 5);
521 }
522 }
523 }
524
525 if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT) {
526 /* 1. power capabilities */
527 pos = skb_put(skb, 4);
528 *pos++ = WLAN_EID_PWR_CAPABILITY;
529 *pos++ = 2;
530 *pos++ = 0; /* min tx power */
531 *pos++ = local->oper_channel->max_power; /* max tx power */
532
533 /* 2. supported channels */
534 /* TODO: get this in reg domain format */
535 pos = skb_put(skb, 2 * sband->n_channels + 2);
536 *pos++ = WLAN_EID_SUPPORTED_CHANNELS;
537 *pos++ = 2 * sband->n_channels;
538 for (i = 0; i < sband->n_channels; i++) {
539 *pos++ = ieee80211_frequency_to_channel(
540 sband->channels[i].center_freq);
541 *pos++ = 1; /* one channel in the subband*/
542 }
543 }
544
545 /* if present, add any custom IEs that go before HT */
546 if (assoc_data->ie_len && assoc_data->ie) {
547 static const u8 before_ht[] = {
548 WLAN_EID_SSID,
549 WLAN_EID_SUPP_RATES,
550 WLAN_EID_EXT_SUPP_RATES,
551 WLAN_EID_PWR_CAPABILITY,
552 WLAN_EID_SUPPORTED_CHANNELS,
553 WLAN_EID_RSN,
554 WLAN_EID_QOS_CAPA,
555 WLAN_EID_RRM_ENABLED_CAPABILITIES,
556 WLAN_EID_MOBILITY_DOMAIN,
557 WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
558 };
559 noffset = ieee80211_ie_split(assoc_data->ie, assoc_data->ie_len,
560 before_ht, ARRAY_SIZE(before_ht),
561 offset);
562 pos = skb_put(skb, noffset - offset);
563 memcpy(pos, assoc_data->ie + offset, noffset - offset);
564 offset = noffset;
565 }
566
567 if (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N) &&
568 bss->wmm_used && local->hw.queues >= 4)
569 ieee80211_add_ht_ie(sdata, skb, assoc_data->ht_information_ie,
570 sband, local->oper_channel, ifmgd->ap_smps);
571
572 /* if present, add any custom non-vendor IEs that go after HT */
573 if (assoc_data->ie_len && assoc_data->ie) {
574 noffset = ieee80211_ie_split_vendor(assoc_data->ie,
575 assoc_data->ie_len,
576 offset);
577 pos = skb_put(skb, noffset - offset);
578 memcpy(pos, assoc_data->ie + offset, noffset - offset);
579 offset = noffset;
580 }
581
582 if (assoc_data->wmm_used && local->hw.queues >= 4) {
583 if (assoc_data->uapsd_used) {
584 qos_info = local->uapsd_queues;
585 qos_info |= (local->uapsd_max_sp_len <<
586 IEEE80211_WMM_IE_STA_QOSINFO_SP_SHIFT);
587 } else {
588 qos_info = 0;
589 }
590
591 pos = skb_put(skb, 9);
592 *pos++ = WLAN_EID_VENDOR_SPECIFIC;
593 *pos++ = 7; /* len */
594 *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */
595 *pos++ = 0x50;
596 *pos++ = 0xf2;
597 *pos++ = 2; /* WME */
598 *pos++ = 0; /* WME info */
599 *pos++ = 1; /* WME ver */
600 *pos++ = qos_info;
601 }
602
603 /* add any remaining custom (i.e. vendor specific here) IEs */
604 if (assoc_data->ie_len && assoc_data->ie) {
605 noffset = assoc_data->ie_len;
606 pos = skb_put(skb, noffset - offset);
607 memcpy(pos, assoc_data->ie + offset, noffset - offset);
608 }
609
610 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
611 ieee80211_tx_skb(sdata, skb);
612}
613
287static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, 614static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
288 const u8 *bssid, u16 stype, u16 reason, 615 const u8 *bssid, u16 stype, u16 reason,
289 void *cookie, bool send_frame) 616 void *cookie, bool send_frame)
@@ -1423,6 +1750,135 @@ void ieee80211_connection_loss(struct ieee80211_vif *vif)
1423EXPORT_SYMBOL(ieee80211_connection_loss); 1750EXPORT_SYMBOL(ieee80211_connection_loss);
1424 1751
1425 1752
1753static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata,
1754 bool assoc)
1755{
1756 struct ieee80211_mgd_auth_data *auth_data = sdata->u.mgd.auth_data;
1757
1758 lockdep_assert_held(&sdata->u.mgd.mtx);
1759
1760 if (auth_data->synced)
1761 drv_finish_tx_sync(sdata->local, sdata,
1762 auth_data->bss->bssid,
1763 IEEE80211_TX_SYNC_AUTH);
1764
1765 if (!assoc) {
1766 sta_info_destroy_addr(sdata, auth_data->bss->bssid);
1767
1768 memset(sdata->u.mgd.bssid, 0, ETH_ALEN);
1769 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
1770 }
1771
1772 cfg80211_put_bss(auth_data->bss);
1773 kfree(auth_data);
1774 sdata->u.mgd.auth_data = NULL;
1775}
1776
1777static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
1778 struct ieee80211_mgmt *mgmt, size_t len)
1779{
1780 struct ieee80211_mgd_auth_data *auth_data = sdata->u.mgd.auth_data;
1781 u8 *pos;
1782 struct ieee802_11_elems elems;
1783
1784 pos = mgmt->u.auth.variable;
1785 ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
1786 if (!elems.challenge)
1787 return;
1788 auth_data->expected_transaction = 4;
1789 ieee80211_send_auth(sdata, 3, auth_data->algorithm,
1790 elems.challenge - 2, elems.challenge_len + 2,
1791 auth_data->bss->bssid, auth_data->bss->bssid,
1792 auth_data->key, auth_data->key_len,
1793 auth_data->key_idx);
1794}
1795
1796static enum rx_mgmt_action __must_check
1797ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
1798 struct ieee80211_mgmt *mgmt, size_t len)
1799{
1800 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1801 u8 bssid[ETH_ALEN];
1802 u16 auth_alg, auth_transaction, status_code;
1803 struct sta_info *sta;
1804
1805 lockdep_assert_held(&ifmgd->mtx);
1806
1807 if (len < 24 + 6)
1808 return RX_MGMT_NONE;
1809
1810 if (!ifmgd->auth_data || ifmgd->auth_data->done)
1811 return RX_MGMT_NONE;
1812
1813 memcpy(bssid, ifmgd->auth_data->bss->bssid, ETH_ALEN);
1814
1815 if (memcmp(bssid, mgmt->bssid, ETH_ALEN))
1816 return RX_MGMT_NONE;
1817
1818 auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg);
1819 auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction);
1820 status_code = le16_to_cpu(mgmt->u.auth.status_code);
1821
1822 if (auth_alg != ifmgd->auth_data->algorithm ||
1823 auth_transaction != ifmgd->auth_data->expected_transaction)
1824 return RX_MGMT_NONE;
1825
1826 if (status_code != WLAN_STATUS_SUCCESS) {
1827 printk(KERN_DEBUG "%s: %pM denied authentication (status %d)\n",
1828 sdata->name, mgmt->sa, status_code);
1829 goto out;
1830 }
1831
1832 switch (ifmgd->auth_data->algorithm) {
1833 case WLAN_AUTH_OPEN:
1834 case WLAN_AUTH_LEAP:
1835 case WLAN_AUTH_FT:
1836 break;
1837 case WLAN_AUTH_SHARED_KEY:
1838 if (ifmgd->auth_data->expected_transaction != 4) {
1839 ieee80211_auth_challenge(sdata, mgmt, len);
1840 /* need another frame */
1841 return RX_MGMT_NONE;
1842 }
1843 break;
1844 default:
1845 WARN_ONCE(1, "invalid auth alg %d",
1846 ifmgd->auth_data->algorithm);
1847 return RX_MGMT_NONE;
1848 }
1849
1850 printk(KERN_DEBUG "%s: authenticated\n", sdata->name);
1851 out:
1852 if (ifmgd->auth_data->synced)
1853 drv_finish_tx_sync(sdata->local, sdata, bssid,
1854 IEEE80211_TX_SYNC_AUTH);
1855 ifmgd->auth_data->synced = false;
1856 ifmgd->auth_data->done = true;
1857 ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC;
1858 run_again(ifmgd, ifmgd->auth_data->timeout);
1859
1860 /* move station state to auth */
1861 mutex_lock(&sdata->local->sta_mtx);
1862 sta = sta_info_get(sdata, bssid);
1863 if (!sta) {
1864 WARN_ONCE(1, "%s: STA %pM not found", sdata->name, bssid);
1865 goto out_err;
1866 }
1867 if (sta_info_move_state(sta, IEEE80211_STA_AUTH)) {
1868 printk(KERN_DEBUG "%s: failed moving %pM to auth\n",
1869 sdata->name, bssid);
1870 goto out_err;
1871 }
1872 mutex_unlock(&sdata->local->sta_mtx);
1873
1874 return RX_MGMT_CFG80211_RX_AUTH;
1875 out_err:
1876 mutex_unlock(&sdata->local->sta_mtx);
1877 /* ignore frame -- wait for timeout */
1878 return RX_MGMT_NONE;
1879}
1880
1881
1426static enum rx_mgmt_action __must_check 1882static enum rx_mgmt_action __must_check
1427ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, 1883ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
1428 struct ieee80211_mgmt *mgmt, size_t len) 1884 struct ieee80211_mgmt *mgmt, size_t len)
@@ -1431,10 +1887,14 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
1431 const u8 *bssid = NULL; 1887 const u8 *bssid = NULL;
1432 u16 reason_code; 1888 u16 reason_code;
1433 1889
1890 lockdep_assert_held(&ifmgd->mtx);
1891
1434 if (len < 24 + 2) 1892 if (len < 24 + 2)
1435 return RX_MGMT_NONE; 1893 return RX_MGMT_NONE;
1436 1894
1437 ASSERT_MGD_MTX(ifmgd); 1895 if (!ifmgd->associated ||
1896 memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN))
1897 return RX_MGMT_NONE;
1438 1898
1439 bssid = ifmgd->associated->bssid; 1899 bssid = ifmgd->associated->bssid;
1440 1900
@@ -1459,15 +1919,13 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
1459 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 1919 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1460 u16 reason_code; 1920 u16 reason_code;
1461 1921
1462 if (len < 24 + 2) 1922 lockdep_assert_held(&ifmgd->mtx);
1463 return RX_MGMT_NONE;
1464
1465 ASSERT_MGD_MTX(ifmgd);
1466 1923
1467 if (WARN_ON(!ifmgd->associated)) 1924 if (len < 24 + 2)
1468 return RX_MGMT_NONE; 1925 return RX_MGMT_NONE;
1469 1926
1470 if (WARN_ON(memcmp(ifmgd->associated->bssid, mgmt->sa, ETH_ALEN))) 1927 if (!ifmgd->associated ||
1928 memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN))
1471 return RX_MGMT_NONE; 1929 return RX_MGMT_NONE;
1472 1930
1473 reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); 1931 reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
@@ -1524,15 +1982,37 @@ static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
1524 } 1982 }
1525} 1983}
1526 1984
1527static bool ieee80211_assoc_success(struct ieee80211_work *wk, 1985static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
1986 bool assoc)
1987{
1988 struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data;
1989
1990 lockdep_assert_held(&sdata->u.mgd.mtx);
1991
1992 if (assoc_data->synced)
1993 drv_finish_tx_sync(sdata->local, sdata,
1994 assoc_data->bss->bssid,
1995 IEEE80211_TX_SYNC_ASSOC);
1996
1997 if (!assoc) {
1998 sta_info_destroy_addr(sdata, assoc_data->bss->bssid);
1999
2000 memset(sdata->u.mgd.bssid, 0, ETH_ALEN);
2001 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
2002 }
2003
2004 kfree(assoc_data);
2005 sdata->u.mgd.assoc_data = NULL;
2006}
2007
2008static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
2009 struct cfg80211_bss *cbss,
1528 struct ieee80211_mgmt *mgmt, size_t len) 2010 struct ieee80211_mgmt *mgmt, size_t len)
1529{ 2011{
1530 struct ieee80211_sub_if_data *sdata = wk->sdata;
1531 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 2012 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1532 struct ieee80211_local *local = sdata->local; 2013 struct ieee80211_local *local = sdata->local;
1533 struct ieee80211_supported_band *sband; 2014 struct ieee80211_supported_band *sband;
1534 struct sta_info *sta; 2015 struct sta_info *sta;
1535 struct cfg80211_bss *cbss = wk->assoc.bss;
1536 u8 *pos; 2016 u8 *pos;
1537 u32 rates, basic_rates; 2017 u32 rates, basic_rates;
1538 u16 capab_info, aid; 2018 u16 capab_info, aid;
@@ -1589,7 +2069,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
1589 2069
1590 rates = 0; 2070 rates = 0;
1591 basic_rates = 0; 2071 basic_rates = 0;
1592 sband = local->hw.wiphy->bands[wk->chan->band]; 2072 sband = local->hw.wiphy->bands[local->oper_channel->band];
1593 2073
1594 ieee80211_get_rates(sband, elems.supp_rates, elems.supp_rates_len, 2074 ieee80211_get_rates(sband, elems.supp_rates, elems.supp_rates_len,
1595 &rates, &basic_rates, &have_higher_than_11mbit, 2075 &rates, &basic_rates, &have_higher_than_11mbit,
@@ -1610,11 +2090,11 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
1610 basic_rates = BIT(min_rate_index); 2090 basic_rates = BIT(min_rate_index);
1611 } 2091 }
1612 2092
1613 sta->sta.supp_rates[wk->chan->band] = rates; 2093 sta->sta.supp_rates[local->oper_channel->band] = rates;
1614 sdata->vif.bss_conf.basic_rates = basic_rates; 2094 sdata->vif.bss_conf.basic_rates = basic_rates;
1615 2095
1616 /* cf. IEEE 802.11 9.2.12 */ 2096 /* cf. IEEE 802.11 9.2.12 */
1617 if (wk->chan->band == IEEE80211_BAND_2GHZ && 2097 if (local->oper_channel->band == IEEE80211_BAND_2GHZ &&
1618 have_higher_than_11mbit) 2098 have_higher_than_11mbit)
1619 sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; 2099 sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE;
1620 else 2100 else
@@ -1664,8 +2144,6 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
1664 else 2144 else
1665 ieee80211_set_wmm_default(sdata); 2145 ieee80211_set_wmm_default(sdata);
1666 2146
1667 local->oper_channel = wk->chan;
1668
1669 if (elems.ht_info_elem && elems.wmm_param && 2147 if (elems.ht_info_elem && elems.wmm_param &&
1670 (sdata->local->hw.queues >= 4) && 2148 (sdata->local->hw.queues >= 4) &&
1671 !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) 2149 !(ifmgd->flags & IEEE80211_STA_DISABLE_11N))
@@ -1696,7 +2174,82 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
1696 return true; 2174 return true;
1697} 2175}
1698 2176
2177static enum rx_mgmt_action __must_check
2178ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
2179 struct ieee80211_mgmt *mgmt, size_t len,
2180 struct cfg80211_bss **bss)
2181{
2182 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2183 struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data;
2184 u16 capab_info, status_code, aid;
2185 struct ieee802_11_elems elems;
2186 u8 *pos;
2187 bool reassoc;
2188
2189 lockdep_assert_held(&ifmgd->mtx);
2190
2191 if (!assoc_data)
2192 return RX_MGMT_NONE;
2193 if (memcmp(assoc_data->bss->bssid, mgmt->bssid, ETH_ALEN))
2194 return RX_MGMT_NONE;
2195
2196 /*
2197 * AssocResp and ReassocResp have identical structure, so process both
2198 * of them in this function.
2199 */
2200
2201 if (len < 24 + 6)
2202 return RX_MGMT_NONE;
2203
2204 reassoc = ieee80211_is_reassoc_req(mgmt->frame_control);
2205 capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
2206 status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
2207 aid = le16_to_cpu(mgmt->u.assoc_resp.aid);
2208
2209 printk(KERN_DEBUG "%s: RX %sssocResp from %pM (capab=0x%x "
2210 "status=%d aid=%d)\n",
2211 sdata->name, reassoc ? "Rea" : "A", mgmt->sa,
2212 capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14))));
2213
2214 pos = mgmt->u.assoc_resp.variable;
2215 ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
2216
2217 if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY &&
2218 elems.timeout_int && elems.timeout_int_len == 5 &&
2219 elems.timeout_int[0] == WLAN_TIMEOUT_ASSOC_COMEBACK) {
2220 u32 tu, ms;
2221 tu = get_unaligned_le32(elems.timeout_int + 1);
2222 ms = tu * 1024 / 1000;
2223 printk(KERN_DEBUG "%s: %pM rejected association temporarily; "
2224 "comeback duration %u TU (%u ms)\n",
2225 sdata->name, mgmt->sa, tu, ms);
2226 assoc_data->timeout = jiffies + msecs_to_jiffies(ms);
2227 if (ms > IEEE80211_ASSOC_TIMEOUT)
2228 run_again(ifmgd, assoc_data->timeout);
2229 return RX_MGMT_NONE;
2230 }
2231
2232 *bss = assoc_data->bss;
2233
2234 if (status_code != WLAN_STATUS_SUCCESS) {
2235 printk(KERN_DEBUG "%s: %pM denied association (code=%d)\n",
2236 sdata->name, mgmt->sa, status_code);
2237 ieee80211_destroy_assoc_data(sdata, false);
2238 } else {
2239 printk(KERN_DEBUG "%s: associated\n", sdata->name);
2240
2241 ieee80211_destroy_assoc_data(sdata, true);
1699 2242
2243 if (!ieee80211_assoc_success(sdata, *bss, mgmt, len)) {
2244 /* oops -- internal error -- send timeout for now */
2245 sta_info_destroy_addr(sdata, mgmt->bssid);
2246 cfg80211_put_bss(*bss);
2247 return RX_MGMT_CFG80211_ASSOC_TIMEOUT;
2248 }
2249 }
2250
2251 return RX_MGMT_CFG80211_RX_ASSOC;
2252}
1700static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, 2253static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
1701 struct ieee80211_mgmt *mgmt, 2254 struct ieee80211_mgmt *mgmt,
1702 size_t len, 2255 size_t len,
@@ -1710,7 +2263,9 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
1710 struct ieee80211_channel *channel; 2263 struct ieee80211_channel *channel;
1711 bool need_ps = false; 2264 bool need_ps = false;
1712 2265
1713 if (sdata->u.mgd.associated) { 2266 if (sdata->u.mgd.associated &&
2267 memcmp(mgmt->bssid, sdata->u.mgd.associated->bssid,
2268 ETH_ALEN) == 0) {
1714 bss = (void *)sdata->u.mgd.associated->priv; 2269 bss = (void *)sdata->u.mgd.associated->priv;
1715 /* not previously set so we may need to recalc */ 2270 /* not previously set so we may need to recalc */
1716 need_ps = !bss->dtim_period; 2271 need_ps = !bss->dtim_period;
@@ -1780,6 +2335,15 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
1780 if (ifmgd->associated && 2335 if (ifmgd->associated &&
1781 memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN) == 0) 2336 memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN) == 0)
1782 ieee80211_reset_ap_probe(sdata); 2337 ieee80211_reset_ap_probe(sdata);
2338
2339 if (ifmgd->auth_data && !ifmgd->auth_data->bss->proberesp_ies &&
2340 memcmp(mgmt->bssid, ifmgd->auth_data->bss->bssid, ETH_ALEN) == 0) {
2341 /* got probe response, continue with auth */
2342 printk(KERN_DEBUG "%s: direct probe responded\n", sdata->name);
2343 ifmgd->auth_data->tries = 0;
2344 ifmgd->auth_data->timeout = jiffies;
2345 run_again(ifmgd, ifmgd->auth_data->timeout);
2346 }
1783} 2347}
1784 2348
1785/* 2349/*
@@ -1819,7 +2383,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
1819 u32 ncrc; 2383 u32 ncrc;
1820 u8 *bssid; 2384 u8 *bssid;
1821 2385
1822 ASSERT_MGD_MTX(ifmgd); 2386 lockdep_assert_held(&ifmgd->mtx);
1823 2387
1824 /* Process beacon from the current BSS */ 2388 /* Process beacon from the current BSS */
1825 baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt; 2389 baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
@@ -1829,21 +2393,25 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
1829 if (rx_status->freq != local->hw.conf.channel->center_freq) 2393 if (rx_status->freq != local->hw.conf.channel->center_freq)
1830 return; 2394 return;
1831 2395
1832 /* 2396 if (ifmgd->assoc_data && !ifmgd->assoc_data->have_beacon &&
1833 * We might have received a number of frames, among them a 2397 memcmp(mgmt->bssid, ifmgd->assoc_data->bss->bssid, ETH_ALEN) == 0) {
1834 * disassoc frame and a beacon... 2398 ieee802_11_parse_elems(mgmt->u.beacon.variable,
1835 */ 2399 len - baselen, &elems);
1836 if (!ifmgd->associated)
1837 return;
1838 2400
1839 bssid = ifmgd->associated->bssid; 2401 ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems,
2402 false);
2403 ifmgd->assoc_data->have_beacon = true;
2404 ifmgd->assoc_data->sent_assoc = false;
2405 /* continue assoc process */
2406 ifmgd->assoc_data->timeout = jiffies;
2407 run_again(ifmgd, ifmgd->assoc_data->timeout);
2408 return;
2409 }
1840 2410
1841 /* 2411 if (!ifmgd->associated ||
1842 * And in theory even frames from a different AP we were just 2412 memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN))
1843 * associated to a split-second ago!
1844 */
1845 if (memcmp(bssid, mgmt->bssid, ETH_ALEN) != 0)
1846 return; 2413 return;
2414 bssid = ifmgd->associated->bssid;
1847 2415
1848 /* Track average RSSI from the Beacon frames of the current AP */ 2416 /* Track average RSSI from the Beacon frames of the current AP */
1849 ifmgd->last_beacon_signal = rx_status->signal; 2417 ifmgd->last_beacon_signal = rx_status->signal;
@@ -2027,6 +2595,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
2027 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 2595 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2028 struct ieee80211_rx_status *rx_status; 2596 struct ieee80211_rx_status *rx_status;
2029 struct ieee80211_mgmt *mgmt; 2597 struct ieee80211_mgmt *mgmt;
2598 struct cfg80211_bss *bss = NULL;
2030 enum rx_mgmt_action rma = RX_MGMT_NONE; 2599 enum rx_mgmt_action rma = RX_MGMT_NONE;
2031 u16 fc; 2600 u16 fc;
2032 2601
@@ -2036,92 +2605,59 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
2036 2605
2037 mutex_lock(&ifmgd->mtx); 2606 mutex_lock(&ifmgd->mtx);
2038 2607
2039 if (ifmgd->associated && 2608 switch (fc & IEEE80211_FCTL_STYPE) {
2040 memcmp(ifmgd->associated->bssid, mgmt->bssid, ETH_ALEN) == 0) { 2609 case IEEE80211_STYPE_BEACON:
2041 switch (fc & IEEE80211_FCTL_STYPE) { 2610 ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, rx_status);
2042 case IEEE80211_STYPE_BEACON: 2611 break;
2043 ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, 2612 case IEEE80211_STYPE_PROBE_RESP:
2044 rx_status); 2613 ieee80211_rx_mgmt_probe_resp(sdata, skb);
2045 break; 2614 break;
2046 case IEEE80211_STYPE_PROBE_RESP: 2615 case IEEE80211_STYPE_AUTH:
2047 ieee80211_rx_mgmt_probe_resp(sdata, skb); 2616 rma = ieee80211_rx_mgmt_auth(sdata, mgmt, skb->len);
2048 break; 2617 break;
2049 case IEEE80211_STYPE_DEAUTH: 2618 case IEEE80211_STYPE_DEAUTH:
2050 rma = ieee80211_rx_mgmt_deauth(sdata, mgmt, skb->len); 2619 rma = ieee80211_rx_mgmt_deauth(sdata, mgmt, skb->len);
2051 break; 2620 break;
2052 case IEEE80211_STYPE_DISASSOC: 2621 case IEEE80211_STYPE_DISASSOC:
2053 rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len); 2622 rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len);
2054 break; 2623 break;
2055 case IEEE80211_STYPE_ACTION: 2624 case IEEE80211_STYPE_ASSOC_RESP:
2056 switch (mgmt->u.action.category) { 2625 case IEEE80211_STYPE_REASSOC_RESP:
2057 case WLAN_CATEGORY_SPECTRUM_MGMT: 2626 rma = ieee80211_rx_mgmt_assoc_resp(sdata, mgmt, skb->len, &bss);
2058 ieee80211_sta_process_chanswitch(sdata, 2627 break;
2059 &mgmt->u.action.u.chan_switch.sw_elem, 2628 case IEEE80211_STYPE_ACTION:
2060 (void *)ifmgd->associated->priv, 2629 switch (mgmt->u.action.category) {
2061 rx_status->mactime); 2630 case WLAN_CATEGORY_SPECTRUM_MGMT:
2062 break; 2631 ieee80211_sta_process_chanswitch(sdata,
2063 } 2632 &mgmt->u.action.u.chan_switch.sw_elem,
2064 } 2633 (void *)ifmgd->associated->priv,
2065 mutex_unlock(&ifmgd->mtx); 2634 rx_status->mactime);
2066
2067 switch (rma) {
2068 case RX_MGMT_NONE:
2069 /* no action */
2070 break;
2071 case RX_MGMT_CFG80211_DEAUTH:
2072 cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);
2073 break;
2074 case RX_MGMT_CFG80211_DISASSOC:
2075 cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len);
2076 break; 2635 break;
2077 default:
2078 WARN(1, "unexpected: %d", rma);
2079 } 2636 }
2080 return;
2081 } 2637 }
2082
2083 mutex_unlock(&ifmgd->mtx); 2638 mutex_unlock(&ifmgd->mtx);
2084 2639
2085 if (skb->len >= 24 + 2 /* mgmt + deauth reason */ && 2640 switch (rma) {
2086 (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_DEAUTH) { 2641 case RX_MGMT_NONE:
2087 struct ieee80211_local *local = sdata->local; 2642 /* no action */
2088 struct ieee80211_work *wk; 2643 break;
2089 2644 case RX_MGMT_CFG80211_DEAUTH:
2090 mutex_lock(&local->mtx);
2091 list_for_each_entry(wk, &local->work_list, list) {
2092 if (wk->sdata != sdata)
2093 continue;
2094
2095 if (wk->type != IEEE80211_WORK_ASSOC &&
2096 wk->type != IEEE80211_WORK_ASSOC_BEACON_WAIT)
2097 continue;
2098
2099 if (memcmp(mgmt->bssid, wk->filter_ta, ETH_ALEN))
2100 continue;
2101 if (memcmp(mgmt->sa, wk->filter_ta, ETH_ALEN))
2102 continue;
2103
2104 /*
2105 * Printing the message only here means we can't
2106 * spuriously print it, but it also means that it
2107 * won't be printed when the frame comes in before
2108 * we even tried to associate or in similar cases.
2109 *
2110 * Ultimately, I suspect cfg80211 should print the
2111 * messages instead.
2112 */
2113 printk(KERN_DEBUG
2114 "%s: deauthenticated from %pM (Reason: %u)\n",
2115 sdata->name, mgmt->bssid,
2116 le16_to_cpu(mgmt->u.deauth.reason_code));
2117
2118 list_del_rcu(&wk->list);
2119 free_work(wk);
2120 break;
2121 }
2122 mutex_unlock(&local->mtx);
2123
2124 cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len); 2645 cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);
2646 break;
2647 case RX_MGMT_CFG80211_DISASSOC:
2648 cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len);
2649 break;
2650 case RX_MGMT_CFG80211_RX_AUTH:
2651 cfg80211_send_rx_auth(sdata->dev, (u8 *)mgmt, skb->len);
2652 break;
2653 case RX_MGMT_CFG80211_RX_ASSOC:
2654 cfg80211_send_rx_assoc(sdata->dev, bss, (u8 *)mgmt, skb->len);
2655 break;
2656 case RX_MGMT_CFG80211_ASSOC_TIMEOUT:
2657 cfg80211_send_assoc_timeout(sdata->dev, mgmt->bssid);
2658 break;
2659 default:
2660 WARN(1, "unexpected: %d", rma);
2125 } 2661 }
2126} 2662}
2127 2663
@@ -2166,14 +2702,160 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
2166 mutex_lock(&ifmgd->mtx); 2702 mutex_lock(&ifmgd->mtx);
2167} 2703}
2168 2704
2705static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
2706{
2707 struct ieee80211_local *local = sdata->local;
2708 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2709 struct ieee80211_mgd_auth_data *auth_data = ifmgd->auth_data;
2710
2711 lockdep_assert_held(&ifmgd->mtx);
2712
2713 if (WARN_ON_ONCE(!auth_data))
2714 return -EINVAL;
2715
2716 if (!auth_data->synced) {
2717 int ret = drv_tx_sync(local, sdata, auth_data->bss->bssid,
2718 IEEE80211_TX_SYNC_AUTH);
2719 if (ret)
2720 return ret;
2721 }
2722 auth_data->synced = true;
2723
2724 auth_data->tries++;
2725
2726 if (auth_data->tries > IEEE80211_AUTH_MAX_TRIES) {
2727 printk(KERN_DEBUG "%s: authentication with %pM timed out\n",
2728 sdata->name, auth_data->bss->bssid);
2729
2730 /*
2731 * Most likely AP is not in the range so remove the
2732 * bss struct for that AP.
2733 */
2734 cfg80211_unlink_bss(local->hw.wiphy, auth_data->bss);
2735
2736 return -ETIMEDOUT;
2737 }
2738
2739 if (auth_data->bss->proberesp_ies) {
2740 printk(KERN_DEBUG "%s: send auth to %pM (try %d/%d)\n",
2741 sdata->name, auth_data->bss->bssid, auth_data->tries,
2742 IEEE80211_AUTH_MAX_TRIES);
2743
2744 auth_data->expected_transaction = 2;
2745 ieee80211_send_auth(sdata, 1, auth_data->algorithm,
2746 auth_data->ie, auth_data->ie_len,
2747 auth_data->bss->bssid,
2748 auth_data->bss->bssid, NULL, 0, 0);
2749 } else {
2750 const u8 *ssidie;
2751
2752 printk(KERN_DEBUG "%s: direct probe to %pM (try %d/%i)\n",
2753 sdata->name, auth_data->bss->bssid, auth_data->tries,
2754 IEEE80211_AUTH_MAX_TRIES);
2755
2756 ssidie = ieee80211_bss_get_ie(auth_data->bss, WLAN_EID_SSID);
2757 if (!ssidie)
2758 return -EINVAL;
2759 /*
2760 * Direct probe is sent to broadcast address as some APs
2761 * will not answer to direct packet in unassociated state.
2762 */
2763 ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1],
2764 NULL, 0, (u32) -1, true, false);
2765 }
2766
2767 auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
2768 run_again(ifmgd, auth_data->timeout);
2769
2770 return 0;
2771}
2772
2773static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata)
2774{
2775 struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data;
2776 struct ieee80211_local *local = sdata->local;
2777
2778 lockdep_assert_held(&sdata->u.mgd.mtx);
2779
2780 if (!assoc_data->synced) {
2781 int ret = drv_tx_sync(local, sdata, assoc_data->bss->bssid,
2782 IEEE80211_TX_SYNC_ASSOC);
2783 if (ret)
2784 return ret;
2785 }
2786 assoc_data->synced = true;
2787
2788 assoc_data->tries++;
2789 if (assoc_data->tries > IEEE80211_ASSOC_MAX_TRIES) {
2790 printk(KERN_DEBUG "%s: association with %pM timed out\n",
2791 sdata->name, assoc_data->bss->bssid);
2792
2793 /*
2794 * Most likely AP is not in the range so remove the
2795 * bss struct for that AP.
2796 */
2797 cfg80211_unlink_bss(local->hw.wiphy, assoc_data->bss);
2798
2799 return -ETIMEDOUT;
2800 }
2801
2802 printk(KERN_DEBUG "%s: associate with %pM (try %d/%d)\n",
2803 sdata->name, assoc_data->bss->bssid, assoc_data->tries,
2804 IEEE80211_ASSOC_MAX_TRIES);
2805 ieee80211_send_assoc(sdata);
2806
2807 assoc_data->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT;
2808 run_again(&sdata->u.mgd, assoc_data->timeout);
2809
2810 return 0;
2811}
2812
2169void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) 2813void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
2170{ 2814{
2171 struct ieee80211_local *local = sdata->local; 2815 struct ieee80211_local *local = sdata->local;
2172 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 2816 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2173 2817
2174 /* then process the rest of the work */
2175 mutex_lock(&ifmgd->mtx); 2818 mutex_lock(&ifmgd->mtx);
2176 2819
2820 if (ifmgd->auth_data &&
2821 time_after(jiffies, ifmgd->auth_data->timeout)) {
2822 if (ifmgd->auth_data->done) {
2823 /*
2824 * ok ... we waited for assoc but userspace didn't,
2825 * so let's just kill the auth data
2826 */
2827 ieee80211_destroy_auth_data(sdata, false);
2828 } else if (ieee80211_probe_auth(sdata)) {
2829 u8 bssid[ETH_ALEN];
2830
2831 memcpy(bssid, ifmgd->auth_data->bss->bssid, ETH_ALEN);
2832
2833 ieee80211_destroy_auth_data(sdata, false);
2834
2835 mutex_unlock(&ifmgd->mtx);
2836 cfg80211_send_auth_timeout(sdata->dev, bssid);
2837 mutex_lock(&ifmgd->mtx);
2838 }
2839 } else if (ifmgd->auth_data)
2840 run_again(ifmgd, ifmgd->auth_data->timeout);
2841
2842 if (ifmgd->assoc_data &&
2843 time_after(jiffies, ifmgd->assoc_data->timeout)) {
2844 if (!ifmgd->assoc_data->have_beacon ||
2845 ieee80211_do_assoc(sdata)) {
2846 u8 bssid[ETH_ALEN];
2847
2848 memcpy(bssid, ifmgd->assoc_data->bss->bssid, ETH_ALEN);
2849
2850 ieee80211_destroy_assoc_data(sdata, false);
2851
2852 mutex_unlock(&ifmgd->mtx);
2853 cfg80211_send_assoc_timeout(sdata->dev, bssid);
2854 mutex_lock(&ifmgd->mtx);
2855 }
2856 } else if (ifmgd->assoc_data)
2857 run_again(ifmgd, ifmgd->assoc_data->timeout);
2858
2177 if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL | 2859 if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL |
2178 IEEE80211_STA_CONNECTION_POLL) && 2860 IEEE80211_STA_CONNECTION_POLL) &&
2179 ifmgd->associated) { 2861 ifmgd->associated) {
@@ -2249,6 +2931,10 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
2249 } 2931 }
2250 2932
2251 mutex_unlock(&ifmgd->mtx); 2933 mutex_unlock(&ifmgd->mtx);
2934
2935 mutex_lock(&local->mtx);
2936 ieee80211_recalc_idle(local);
2937 mutex_unlock(&local->mtx);
2252} 2938}
2253 2939
2254static void ieee80211_sta_bcn_mon_timer(unsigned long data) 2940static void ieee80211_sta_bcn_mon_timer(unsigned long data)
@@ -2421,50 +3107,24 @@ int ieee80211_max_network_latency(struct notifier_block *nb,
2421} 3107}
2422 3108
2423/* config hooks */ 3109/* config hooks */
2424static enum work_done_result
2425ieee80211_probe_auth_done(struct ieee80211_work *wk,
2426 struct sk_buff *skb)
2427{
2428 struct ieee80211_local *local = wk->sdata->local;
2429
2430 if (!skb) {
2431 cfg80211_send_auth_timeout(wk->sdata->dev, wk->filter_ta);
2432 goto destroy;
2433 }
2434
2435 if (wk->type == IEEE80211_WORK_AUTH) {
2436 cfg80211_send_rx_auth(wk->sdata->dev, skb->data, skb->len);
2437 goto destroy;
2438 }
2439
2440 mutex_lock(&wk->sdata->u.mgd.mtx);
2441 ieee80211_rx_mgmt_probe_resp(wk->sdata, skb);
2442 mutex_unlock(&wk->sdata->u.mgd.mtx);
2443
2444 wk->type = IEEE80211_WORK_AUTH;
2445 wk->probe_auth.tries = 0;
2446 return WORK_DONE_REQUEUE;
2447 destroy:
2448 if (wk->probe_auth.synced)
2449 drv_finish_tx_sync(local, wk->sdata, wk->filter_ta,
2450 IEEE80211_TX_SYNC_AUTH);
2451
2452 return WORK_DONE_DESTROY;
2453}
2454
2455int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, 3110int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
2456 struct cfg80211_auth_request *req) 3111 struct cfg80211_auth_request *req)
2457{ 3112{
2458 const u8 *ssid; 3113 struct ieee80211_local *local = sdata->local;
2459 struct ieee80211_work *wk; 3114 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
3115 struct ieee80211_mgd_auth_data *auth_data;
3116 struct sta_info *sta;
2460 u16 auth_alg; 3117 u16 auth_alg;
3118 int err;
3119
3120 /* prepare auth data structure */
2461 3121
2462 switch (req->auth_type) { 3122 switch (req->auth_type) {
2463 case NL80211_AUTHTYPE_OPEN_SYSTEM: 3123 case NL80211_AUTHTYPE_OPEN_SYSTEM:
2464 auth_alg = WLAN_AUTH_OPEN; 3124 auth_alg = WLAN_AUTH_OPEN;
2465 break; 3125 break;
2466 case NL80211_AUTHTYPE_SHARED_KEY: 3126 case NL80211_AUTHTYPE_SHARED_KEY:
2467 if (IS_ERR(sdata->local->wep_tx_tfm)) 3127 if (IS_ERR(local->wep_tx_tfm))
2468 return -EOPNOTSUPP; 3128 return -EOPNOTSUPP;
2469 auth_alg = WLAN_AUTH_SHARED_KEY; 3129 auth_alg = WLAN_AUTH_SHARED_KEY;
2470 break; 3130 break;
@@ -2478,169 +3138,142 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
2478 return -EOPNOTSUPP; 3138 return -EOPNOTSUPP;
2479 } 3139 }
2480 3140
2481 wk = kzalloc(sizeof(*wk) + req->ie_len, GFP_KERNEL); 3141 auth_data = kzalloc(sizeof(*auth_data) + req->ie_len, GFP_KERNEL);
2482 if (!wk) 3142 if (!auth_data)
2483 return -ENOMEM; 3143 return -ENOMEM;
2484 3144
2485 memcpy(wk->filter_ta, req->bss->bssid, ETH_ALEN); 3145 auth_data->bss = req->bss;
2486 3146
2487 if (req->ie && req->ie_len) { 3147 if (req->ie && req->ie_len) {
2488 memcpy(wk->ie, req->ie, req->ie_len); 3148 memcpy(auth_data->ie, req->ie, req->ie_len);
2489 wk->ie_len = req->ie_len; 3149 auth_data->ie_len = req->ie_len;
2490 } 3150 }
2491 3151
2492 if (req->key && req->key_len) { 3152 if (req->key && req->key_len) {
2493 wk->probe_auth.key_len = req->key_len; 3153 auth_data->key_len = req->key_len;
2494 wk->probe_auth.key_idx = req->key_idx; 3154 auth_data->key_idx = req->key_idx;
2495 memcpy(wk->probe_auth.key, req->key, req->key_len); 3155 memcpy(auth_data->key, req->key, req->key_len);
2496 } 3156 }
2497 3157
2498 ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); 3158 auth_data->algorithm = auth_alg;
2499 memcpy(wk->probe_auth.ssid, ssid + 2, ssid[1]);
2500 wk->probe_auth.ssid_len = ssid[1];
2501
2502 wk->probe_auth.algorithm = auth_alg;
2503 wk->probe_auth.privacy = req->bss->capability & WLAN_CAPABILITY_PRIVACY;
2504
2505 /* if we already have a probe, don't probe again */
2506 if (req->bss->proberesp_ies)
2507 wk->type = IEEE80211_WORK_AUTH;
2508 else
2509 wk->type = IEEE80211_WORK_DIRECT_PROBE;
2510 wk->chan = req->bss->channel;
2511 wk->chan_type = NL80211_CHAN_NO_HT;
2512 wk->sdata = sdata;
2513 wk->done = ieee80211_probe_auth_done;
2514
2515 ieee80211_add_work(wk);
2516 return 0;
2517}
2518 3159
2519/* create and insert a dummy station entry */ 3160 /* try to authenticate/probe */
2520static int ieee80211_pre_assoc(struct ieee80211_sub_if_data *sdata,
2521 u8 *bssid) {
2522 struct sta_info *sta;
2523 int err;
2524 3161
2525 sta = sta_info_alloc(sdata, bssid, GFP_KERNEL); 3162 mutex_lock(&ifmgd->mtx);
2526 if (!sta)
2527 return -ENOMEM;
2528 3163
2529 err = sta_info_insert(sta); 3164 if ((ifmgd->auth_data && !ifmgd->auth_data->done) ||
2530 sta = NULL; 3165 ifmgd->assoc_data) {
2531 if (err) { 3166 err = -EBUSY;
2532 printk(KERN_DEBUG "%s: failed to insert STA entry for" 3167 goto err_free;
2533 " the AP (error %d)\n", sdata->name, err);
2534 return err;
2535 } 3168 }
2536 3169
2537 return 0; 3170 if (ifmgd->auth_data)
2538} 3171 ieee80211_destroy_auth_data(sdata, false);
2539 3172
2540static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk, 3173 /* prep auth_data so we don't go into idle on disassoc */
2541 struct sk_buff *skb) 3174 ifmgd->auth_data = auth_data;
2542{
2543 struct ieee80211_local *local = wk->sdata->local;
2544 struct ieee80211_mgmt *mgmt;
2545 struct ieee80211_rx_status *rx_status;
2546 struct ieee802_11_elems elems;
2547 struct cfg80211_bss *cbss = wk->assoc.bss;
2548 u16 status;
2549 3175
2550 if (!skb) { 3176 if (ifmgd->associated)
2551 sta_info_destroy_addr(wk->sdata, cbss->bssid); 3177 ieee80211_set_disassoc(sdata, true, false);
2552 cfg80211_send_assoc_timeout(wk->sdata->dev, wk->filter_ta);
2553 goto destroy;
2554 }
2555 3178
2556 if (wk->type == IEEE80211_WORK_ASSOC_BEACON_WAIT) { 3179 printk(KERN_DEBUG "%s: authenticate with %pM\n",
2557 mutex_lock(&wk->sdata->u.mgd.mtx); 3180 sdata->name, req->bss->bssid);
2558 rx_status = (void *) skb->cb;
2559 ieee802_11_parse_elems(skb->data + 24 + 12, skb->len - 24 - 12, &elems);
2560 ieee80211_rx_bss_info(wk->sdata, (void *)skb->data, skb->len, rx_status,
2561 &elems, true);
2562 mutex_unlock(&wk->sdata->u.mgd.mtx);
2563 3181
2564 wk->type = IEEE80211_WORK_ASSOC; 3182 mutex_lock(&local->mtx);
2565 /* not really done yet */ 3183 ieee80211_recalc_idle(sdata->local);
2566 return WORK_DONE_REQUEUE; 3184 mutex_unlock(&local->mtx);
2567 }
2568 3185
2569 mgmt = (void *)skb->data; 3186 /* switch to the right channel */
2570 status = le16_to_cpu(mgmt->u.assoc_resp.status_code); 3187 local->oper_channel = req->bss->channel;
3188 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
2571 3189
2572 if (status == WLAN_STATUS_SUCCESS) { 3190 /* set BSSID */
2573 if (wk->assoc.synced) 3191 memcpy(ifmgd->bssid, req->bss->bssid, ETH_ALEN);
2574 drv_finish_tx_sync(local, wk->sdata, wk->filter_ta, 3192 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
2575 IEEE80211_TX_SYNC_ASSOC);
2576 3193
2577 mutex_lock(&wk->sdata->u.mgd.mtx); 3194 /* add station entry */
2578 if (!ieee80211_assoc_success(wk, mgmt, skb->len)) { 3195 sta = sta_info_alloc(sdata, req->bss->bssid, GFP_KERNEL);
2579 mutex_unlock(&wk->sdata->u.mgd.mtx); 3196 if (!sta) {
2580 /* oops -- internal error -- send timeout for now */ 3197 err = -ENOMEM;
2581 sta_info_destroy_addr(wk->sdata, cbss->bssid); 3198 goto err_clear;
2582 cfg80211_send_assoc_timeout(wk->sdata->dev, 3199 }
2583 wk->filter_ta);
2584 return WORK_DONE_DESTROY;
2585 }
2586 3200
2587 mutex_unlock(&wk->sdata->u.mgd.mtx); 3201 err = sta_info_insert(sta);
2588 } else { 3202 if (err) {
2589 /* assoc failed - destroy the dummy station entry */ 3203 printk(KERN_DEBUG
2590 sta_info_destroy_addr(wk->sdata, cbss->bssid); 3204 "%s: failed to insert STA entry for the AP %pM (error %d)\n",
3205 sdata->name, req->bss->bssid, err);
3206 goto err_clear;
2591 } 3207 }
2592 3208
2593 cfg80211_send_rx_assoc(wk->sdata->dev, cbss, skb->data, skb->len); 3209 err = ieee80211_probe_auth(sdata);
2594 destroy: 3210 if (err) {
2595 if (wk->assoc.synced) 3211 if (auth_data->synced)
2596 drv_finish_tx_sync(local, wk->sdata, wk->filter_ta, 3212 drv_finish_tx_sync(local, sdata, req->bss->bssid,
2597 IEEE80211_TX_SYNC_ASSOC); 3213 IEEE80211_TX_SYNC_AUTH);
3214 sta_info_destroy_addr(sdata, req->bss->bssid);
3215 goto err_clear;
3216 }
3217
3218 /* hold our own reference */
3219 cfg80211_ref_bss(auth_data->bss);
3220 err = 0;
3221 goto out_unlock;
3222
3223 err_clear:
3224 ifmgd->auth_data = NULL;
3225 err_free:
3226 kfree(auth_data);
3227 out_unlock:
3228 mutex_unlock(&ifmgd->mtx);
2598 3229
2599 return WORK_DONE_DESTROY; 3230 return err;
2600} 3231}
2601 3232
2602int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, 3233int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
2603 struct cfg80211_assoc_request *req) 3234 struct cfg80211_assoc_request *req)
2604{ 3235{
3236 struct ieee80211_local *local = sdata->local;
2605 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 3237 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2606 struct ieee80211_bss *bss = (void *)req->bss->priv; 3238 struct ieee80211_bss *bss = (void *)req->bss->priv;
2607 struct ieee80211_work *wk; 3239 struct ieee80211_mgd_assoc_data *assoc_data;
2608 const u8 *ssid; 3240 struct sta_info *sta;
3241 const u8 *ssidie;
2609 int i, err; 3242 int i, err;
2610 3243
3244 ssidie = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID);
3245 if (!ssidie)
3246 return -EINVAL;
3247
3248 assoc_data = kzalloc(sizeof(*assoc_data) + req->ie_len, GFP_KERNEL);
3249 if (!assoc_data)
3250 return -ENOMEM;
3251
2611 mutex_lock(&ifmgd->mtx); 3252 mutex_lock(&ifmgd->mtx);
2612 if (ifmgd->associated) {
2613 if (!req->prev_bssid ||
2614 memcmp(req->prev_bssid, ifmgd->associated->bssid,
2615 ETH_ALEN)) {
2616 /*
2617 * We are already associated and the request was not a
2618 * reassociation request from the current BSS, so
2619 * reject it.
2620 */
2621 mutex_unlock(&ifmgd->mtx);
2622 return -EALREADY;
2623 }
2624 3253
2625 /* Trying to reassociate - clear previous association state */ 3254 if (ifmgd->associated)
2626 ieee80211_set_disassoc(sdata, true, false); 3255 ieee80211_set_disassoc(sdata, true, false);
3256
3257 if (ifmgd->auth_data && !ifmgd->auth_data->done) {
3258 err = -EBUSY;
3259 goto err_free;
2627 } 3260 }
2628 mutex_unlock(&ifmgd->mtx);
2629 3261
2630 wk = kzalloc(sizeof(*wk) + req->ie_len, GFP_KERNEL); 3262 if (ifmgd->assoc_data) {
2631 if (!wk) 3263 err = -EBUSY;
2632 return -ENOMEM; 3264 goto err_free;
3265 }
2633 3266
2634 /* 3267 if (ifmgd->auth_data) {
2635 * create a dummy station info entry in order 3268 bool match;
2636 * to start accepting incoming EAPOL packets from the station 3269
2637 */ 3270 /* keep sta info, bssid if matching */
2638 err = ieee80211_pre_assoc(sdata, req->bss->bssid); 3271 match = memcmp(ifmgd->bssid, req->bss->bssid, ETH_ALEN) == 0;
2639 if (err) { 3272 ieee80211_destroy_auth_data(sdata, match);
2640 kfree(wk);
2641 return err;
2642 } 3273 }
2643 3274
3275 /* prepare assoc data */
3276
2644 ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N; 3277 ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N;
2645 ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; 3278 ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED;
2646 3279
@@ -2652,7 +3285,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
2652 req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) 3285 req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104)
2653 ifmgd->flags |= IEEE80211_STA_DISABLE_11N; 3286 ifmgd->flags |= IEEE80211_STA_DISABLE_11N;
2654 3287
2655
2656 if (req->flags & ASSOC_REQ_DISABLE_HT) 3288 if (req->flags & ASSOC_REQ_DISABLE_HT)
2657 ifmgd->flags |= IEEE80211_STA_DISABLE_11N; 3289 ifmgd->flags |= IEEE80211_STA_DISABLE_11N;
2658 3290
@@ -2661,16 +3293,12 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
2661 sizeof(ifmgd->ht_capa_mask)); 3293 sizeof(ifmgd->ht_capa_mask));
2662 3294
2663 if (req->ie && req->ie_len) { 3295 if (req->ie && req->ie_len) {
2664 memcpy(wk->ie, req->ie, req->ie_len); 3296 memcpy(assoc_data->ie, req->ie, req->ie_len);
2665 wk->ie_len = req->ie_len; 3297 assoc_data->ie_len = req->ie_len;
2666 } else 3298 }
2667 wk->ie_len = 0;
2668
2669 wk->assoc.bss = req->bss;
2670 3299
2671 memcpy(wk->filter_ta, req->bss->bssid, ETH_ALEN); 3300 assoc_data->bss = req->bss;
2672 3301
2673 /* new association always uses requested smps mode */
2674 if (ifmgd->req_smps == IEEE80211_SMPS_AUTOMATIC) { 3302 if (ifmgd->req_smps == IEEE80211_SMPS_AUTOMATIC) {
2675 if (ifmgd->powersave) 3303 if (ifmgd->powersave)
2676 ifmgd->ap_smps = IEEE80211_SMPS_DYNAMIC; 3304 ifmgd->ap_smps = IEEE80211_SMPS_DYNAMIC;
@@ -2679,7 +3307,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
2679 } else 3307 } else
2680 ifmgd->ap_smps = ifmgd->req_smps; 3308 ifmgd->ap_smps = ifmgd->req_smps;
2681 3309
2682 wk->assoc.smps = ifmgd->ap_smps;
2683 /* 3310 /*
2684 * IEEE802.11n does not allow TKIP/WEP as pairwise ciphers in HT mode. 3311 * IEEE802.11n does not allow TKIP/WEP as pairwise ciphers in HT mode.
2685 * We still associate in non-HT mode (11a/b/g) if any one of these 3312 * We still associate in non-HT mode (11a/b/g) if any one of these
@@ -2687,39 +3314,27 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
2687 * We can set this to true for non-11n hardware, that'll be checked 3314 * We can set this to true for non-11n hardware, that'll be checked
2688 * separately along with the peer capabilities. 3315 * separately along with the peer capabilities.
2689 */ 3316 */
2690 wk->assoc.use_11n = !(ifmgd->flags & IEEE80211_STA_DISABLE_11N); 3317 assoc_data->capability = req->bss->capability;
2691 wk->assoc.capability = req->bss->capability; 3318 assoc_data->wmm_used = bss->wmm_used;
2692 wk->assoc.wmm_used = bss->wmm_used; 3319 assoc_data->supp_rates = bss->supp_rates;
2693 wk->assoc.supp_rates = bss->supp_rates; 3320 assoc_data->supp_rates_len = bss->supp_rates_len;
2694 wk->assoc.supp_rates_len = bss->supp_rates_len; 3321 assoc_data->ht_information_ie =
2695 wk->assoc.ht_information_ie =
2696 ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_INFORMATION); 3322 ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_INFORMATION);
2697 3323
2698 if (bss->wmm_used && bss->uapsd_supported && 3324 if (bss->wmm_used && bss->uapsd_supported &&
2699 (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) { 3325 (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) {
2700 wk->assoc.uapsd_used = true; 3326 assoc_data->uapsd_used = true;
2701 ifmgd->flags |= IEEE80211_STA_UAPSD_ENABLED; 3327 ifmgd->flags |= IEEE80211_STA_UAPSD_ENABLED;
2702 } else { 3328 } else {
2703 wk->assoc.uapsd_used = false; 3329 assoc_data->uapsd_used = false;
2704 ifmgd->flags &= ~IEEE80211_STA_UAPSD_ENABLED; 3330 ifmgd->flags &= ~IEEE80211_STA_UAPSD_ENABLED;
2705 } 3331 }
2706 3332
2707 ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); 3333 memcpy(assoc_data->ssid, ssidie + 2, ssidie[1]);
2708 memcpy(wk->assoc.ssid, ssid + 2, ssid[1]); 3334 assoc_data->ssid_len = ssidie[1];
2709 wk->assoc.ssid_len = ssid[1];
2710 3335
2711 if (req->prev_bssid) 3336 if (req->prev_bssid)
2712 memcpy(wk->assoc.prev_bssid, req->prev_bssid, ETH_ALEN); 3337 memcpy(assoc_data->prev_bssid, req->prev_bssid, ETH_ALEN);
2713
2714 wk->chan = req->bss->channel;
2715 wk->chan_type = NL80211_CHAN_NO_HT;
2716 wk->sdata = sdata;
2717 wk->done = ieee80211_assoc_done;
2718 if (!bss->dtim_period &&
2719 sdata->local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD)
2720 wk->type = IEEE80211_WORK_ASSOC_BEACON_WAIT;
2721 else
2722 wk->type = IEEE80211_WORK_ASSOC;
2723 3338
2724 if (req->use_mfp) { 3339 if (req->use_mfp) {
2725 ifmgd->mfp = IEEE80211_MFP_REQUIRED; 3340 ifmgd->mfp = IEEE80211_MFP_REQUIRED;
@@ -2737,15 +3352,79 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
2737 sdata->control_port_protocol = req->crypto.control_port_ethertype; 3352 sdata->control_port_protocol = req->crypto.control_port_ethertype;
2738 sdata->control_port_no_encrypt = req->crypto.control_port_no_encrypt; 3353 sdata->control_port_no_encrypt = req->crypto.control_port_no_encrypt;
2739 3354
2740 ieee80211_add_work(wk); 3355 /* kick off associate process */
2741 return 0; 3356
3357 ifmgd->assoc_data = assoc_data;
3358
3359 mutex_lock(&local->mtx);
3360 ieee80211_recalc_idle(sdata->local);
3361 mutex_unlock(&local->mtx);
3362
3363 /* switch to the right channel */
3364 local->oper_channel = req->bss->channel;
3365 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
3366
3367 rcu_read_lock();
3368 sta = sta_info_get(sdata, req->bss->bssid);
3369 rcu_read_unlock();
3370
3371 if (!sta) {
3372 /* set BSSID */
3373 memcpy(ifmgd->bssid, req->bss->bssid, ETH_ALEN);
3374 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
3375
3376 sta = sta_info_alloc(sdata, req->bss->bssid, GFP_KERNEL);
3377 if (!sta) {
3378 err = -ENOMEM;
3379 goto err_clear;
3380 }
3381
3382 sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
3383
3384 err = sta_info_insert(sta);
3385 sta = NULL;
3386 if (err) {
3387 printk(KERN_DEBUG
3388 "%s: failed to insert STA entry for the AP (error %d)\n",
3389 sdata->name, err);
3390 goto err_clear;
3391 }
3392 } else
3393 WARN_ON_ONCE(memcmp(ifmgd->bssid, req->bss->bssid, ETH_ALEN));
3394
3395 if (!bss->dtim_period &&
3396 sdata->local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) {
3397 /*
3398 * Wait up to one beacon interval ...
3399 * should this be more if we miss one?
3400 */
3401 printk(KERN_DEBUG "%s: waiting for beacon from %pM\n",
3402 sdata->name, ifmgd->bssid);
3403 assoc_data->timeout = jiffies +
3404 TU_TO_EXP_TIME(req->bss->beacon_interval);
3405 } else {
3406 assoc_data->have_beacon = true;
3407 assoc_data->sent_assoc = false;
3408 assoc_data->timeout = jiffies;
3409 }
3410 run_again(ifmgd, assoc_data->timeout);
3411
3412 err = 0;
3413 goto out;
3414 err_clear:
3415 ifmgd->assoc_data = NULL;
3416 err_free:
3417 kfree(assoc_data);
3418 out:
3419 mutex_unlock(&ifmgd->mtx);
3420
3421 return err;
2742} 3422}
2743 3423
2744int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, 3424int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
2745 struct cfg80211_deauth_request *req, 3425 struct cfg80211_deauth_request *req,
2746 void *cookie) 3426 void *cookie)
2747{ 3427{
2748 struct ieee80211_local *local = sdata->local;
2749 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 3428 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2750 bool assoc_bss = false; 3429 bool assoc_bss = false;
2751 3430
@@ -2754,62 +3433,13 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
2754 if (ifmgd->associated && 3433 if (ifmgd->associated &&
2755 memcmp(ifmgd->associated->bssid, req->bssid, ETH_ALEN) == 0) { 3434 memcmp(ifmgd->associated->bssid, req->bssid, ETH_ALEN) == 0) {
2756 ieee80211_set_disassoc(sdata, false, true); 3435 ieee80211_set_disassoc(sdata, false, true);
2757 mutex_unlock(&ifmgd->mtx);
2758 assoc_bss = true; 3436 assoc_bss = true;
2759 } else { 3437 } else if (ifmgd->auth_data) {
2760 bool not_auth_yet = false; 3438 ieee80211_destroy_auth_data(sdata, false);
2761 struct ieee80211_work *tmp, *wk = NULL;
2762
2763 mutex_unlock(&ifmgd->mtx); 3439 mutex_unlock(&ifmgd->mtx);
2764 3440 return 0;
2765 mutex_lock(&local->mtx);
2766 list_for_each_entry(tmp, &local->work_list, list) {
2767 if (tmp->sdata != sdata)
2768 continue;
2769
2770 if (tmp->type != IEEE80211_WORK_DIRECT_PROBE &&
2771 tmp->type != IEEE80211_WORK_AUTH &&
2772 tmp->type != IEEE80211_WORK_ASSOC &&
2773 tmp->type != IEEE80211_WORK_ASSOC_BEACON_WAIT)
2774 continue;
2775
2776 if (memcmp(req->bssid, tmp->filter_ta, ETH_ALEN))
2777 continue;
2778
2779 not_auth_yet = tmp->type == IEEE80211_WORK_DIRECT_PROBE;
2780 list_del_rcu(&tmp->list);
2781 synchronize_rcu();
2782 wk = tmp;
2783 break;
2784 }
2785 mutex_unlock(&local->mtx);
2786
2787 if (wk && wk->type == IEEE80211_WORK_ASSOC) {
2788 /* clean up dummy sta & TX sync */
2789 sta_info_destroy_addr(wk->sdata, wk->filter_ta);
2790 if (wk->assoc.synced)
2791 drv_finish_tx_sync(local, wk->sdata,
2792 wk->filter_ta,
2793 IEEE80211_TX_SYNC_ASSOC);
2794 } else if (wk && wk->type == IEEE80211_WORK_AUTH) {
2795 if (wk->probe_auth.synced)
2796 drv_finish_tx_sync(local, wk->sdata,
2797 wk->filter_ta,
2798 IEEE80211_TX_SYNC_AUTH);
2799 }
2800 kfree(wk);
2801
2802 /*
2803 * If somebody requests authentication and we haven't
2804 * sent out an auth frame yet there's no need to send
2805 * out a deauth frame either. If the state was PROBE,
2806 * then this is the case. If it's AUTH we have sent a
2807 * frame, and if it's IDLE we have completed the auth
2808 * process already.
2809 */
2810 if (not_auth_yet)
2811 return 0;
2812 } 3441 }
3442 mutex_unlock(&ifmgd->mtx);
2813 3443
2814 printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n", 3444 printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n",
2815 sdata->name, req->bssid, req->reason_code); 3445 sdata->name, req->bssid, req->reason_code);