aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--net/mac80211/Makefile4
-rw-r--r--net/mac80211/cfg.c6
-rw-r--r--net/mac80211/ieee80211_i.h77
-rw-r--r--net/mac80211/iface.c4
-rw-r--r--net/mac80211/main.c10
-rw-r--r--net/mac80211/mlme.c1340
-rw-r--r--net/mac80211/rx.c9
-rw-r--r--net/mac80211/work.c815
8 files changed, 1038 insertions, 1227 deletions
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
index d540c3b160f3..1be7a454aa77 100644
--- a/net/mac80211/Makefile
+++ b/net/mac80211/Makefile
@@ -9,7 +9,7 @@ mac80211-y := \
9 scan.o offchannel.o \ 9 scan.o offchannel.o \
10 ht.o agg-tx.o agg-rx.o \ 10 ht.o agg-tx.o agg-rx.o \
11 ibss.o \ 11 ibss.o \
12 mlme.o work.o \ 12 work.o \
13 iface.o \ 13 iface.o \
14 rate.o \ 14 rate.o \
15 michael.o \ 15 michael.o \
@@ -25,7 +25,7 @@ mac80211-y := \
25 wme.o \ 25 wme.o \
26 event.o \ 26 event.o \
27 chan.o \ 27 chan.o \
28 driver-trace.o 28 driver-trace.o mlme.o
29 29
30mac80211-$(CONFIG_MAC80211_LEDS) += led.o 30mac80211-$(CONFIG_MAC80211_LEDS) += led.o
31mac80211-$(CONFIG_MAC80211_DEBUGFS) += \ 31mac80211-$(CONFIG_MAC80211_DEBUGFS) += \
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index d15ba0d0de94..c3de921c8cfd 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2028,7 +2028,7 @@ ieee80211_offchan_tx_done(struct ieee80211_work *wk, struct sk_buff *skb)
2028 if (wk->offchan_tx.wait && !wk->offchan_tx.status) 2028 if (wk->offchan_tx.wait && !wk->offchan_tx.status)
2029 cfg80211_mgmt_tx_status(wk->sdata->dev, 2029 cfg80211_mgmt_tx_status(wk->sdata->dev,
2030 (unsigned long) wk->offchan_tx.frame, 2030 (unsigned long) wk->offchan_tx.frame,
2031 wk->ie, wk->ie_len, false, GFP_KERNEL); 2031 wk->data, wk->data_len, false, GFP_KERNEL);
2032 2032
2033 return WORK_DONE_DESTROY; 2033 return WORK_DONE_DESTROY;
2034} 2034}
@@ -2179,8 +2179,8 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
2179 wk->done = ieee80211_offchan_tx_done; 2179 wk->done = ieee80211_offchan_tx_done;
2180 wk->offchan_tx.frame = skb; 2180 wk->offchan_tx.frame = skb;
2181 wk->offchan_tx.wait = wait; 2181 wk->offchan_tx.wait = wait;
2182 wk->ie_len = len; 2182 wk->data_len = len;
2183 memcpy(wk->ie, buf, len); 2183 memcpy(wk->data, buf, len);
2184 2184
2185 ieee80211_add_work(wk); 2185 ieee80211_add_work(wk);
2186 return 0; 2186 return 0;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index d47e8c110b16..a146b1177cb0 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -280,10 +280,6 @@ struct mesh_preq_queue {
280 280
281enum ieee80211_work_type { 281enum ieee80211_work_type {
282 IEEE80211_WORK_ABORT, 282 IEEE80211_WORK_ABORT,
283 IEEE80211_WORK_DIRECT_PROBE,
284 IEEE80211_WORK_AUTH,
285 IEEE80211_WORK_ASSOC_BEACON_WAIT,
286 IEEE80211_WORK_ASSOC,
287 IEEE80211_WORK_REMAIN_ON_CHANNEL, 283 IEEE80211_WORK_REMAIN_ON_CHANNEL,
288 IEEE80211_WORK_OFFCHANNEL_TX, 284 IEEE80211_WORK_OFFCHANNEL_TX,
289}; 285};
@@ -316,36 +312,10 @@ struct ieee80211_work {
316 unsigned long timeout; 312 unsigned long timeout;
317 enum ieee80211_work_type type; 313 enum ieee80211_work_type type;
318 314
319 u8 filter_ta[ETH_ALEN];
320
321 bool started; 315 bool started;
322 316
323 union { 317 union {
324 struct { 318 struct {
325 int tries;
326 u16 algorithm, transaction;
327 u8 ssid[IEEE80211_MAX_SSID_LEN];
328 u8 ssid_len;
329 u8 key[WLAN_KEY_LEN_WEP104];
330 u8 key_len, key_idx;
331 bool privacy;
332 bool synced;
333 } probe_auth;
334 struct {
335 struct cfg80211_bss *bss;
336 const u8 *supp_rates;
337 const u8 *ht_information_ie;
338 enum ieee80211_smps_mode smps;
339 int tries;
340 u16 capability;
341 u8 prev_bssid[ETH_ALEN];
342 u8 ssid[IEEE80211_MAX_SSID_LEN];
343 u8 ssid_len;
344 u8 supp_rates_len;
345 bool wmm_used, use_11n, uapsd_used;
346 bool synced;
347 } assoc;
348 struct {
349 u32 duration; 319 u32 duration;
350 } remain; 320 } remain;
351 struct { 321 struct {
@@ -355,9 +325,8 @@ struct ieee80211_work {
355 } offchan_tx; 325 } offchan_tx;
356 }; 326 };
357 327
358 int ie_len; 328 size_t data_len;
359 /* must be last */ 329 u8 data[];
360 u8 ie[0];
361}; 330};
362 331
363/* flags used in struct ieee80211_if_managed.flags */ 332/* flags used in struct ieee80211_if_managed.flags */
@@ -373,6 +342,43 @@ enum ieee80211_sta_flags {
373 IEEE80211_STA_RESET_SIGNAL_AVE = BIT(9), 342 IEEE80211_STA_RESET_SIGNAL_AVE = BIT(9),
374}; 343};
375 344
345struct ieee80211_mgd_auth_data {
346 struct cfg80211_bss *bss;
347 unsigned long timeout;
348 int tries;
349 u16 algorithm, expected_transaction;
350
351 u8 key[WLAN_KEY_LEN_WEP104];
352 u8 key_len, key_idx;
353 bool synced;
354 bool done;
355
356 size_t ie_len;
357 u8 ie[];
358};
359
360struct ieee80211_mgd_assoc_data {
361 struct cfg80211_bss *bss;
362 const u8 *supp_rates;
363 const u8 *ht_information_ie;
364
365 unsigned long timeout;
366 int tries;
367
368 u16 capability;
369 u8 prev_bssid[ETH_ALEN];
370 u8 ssid[IEEE80211_MAX_SSID_LEN];
371 u8 ssid_len;
372 u8 supp_rates_len;
373 bool wmm_used, uapsd_used;
374 bool have_beacon;
375 bool sent_assoc;
376 bool synced;
377
378 size_t ie_len;
379 u8 ie[];
380};
381
376struct ieee80211_if_managed { 382struct ieee80211_if_managed {
377 struct timer_list timer; 383 struct timer_list timer;
378 struct timer_list conn_mon_timer; 384 struct timer_list conn_mon_timer;
@@ -389,6 +395,8 @@ struct ieee80211_if_managed {
389 395
390 struct mutex mtx; 396 struct mutex mtx;
391 struct cfg80211_bss *associated; 397 struct cfg80211_bss *associated;
398 struct ieee80211_mgd_auth_data *auth_data;
399 struct ieee80211_mgd_assoc_data *assoc_data;
392 400
393 u8 bssid[ETH_ALEN]; 401 u8 bssid[ETH_ALEN];
394 402
@@ -770,7 +778,6 @@ struct ieee80211_local {
770 struct list_head work_list; 778 struct list_head work_list;
771 struct timer_list work_timer; 779 struct timer_list work_timer;
772 struct work_struct work_work; 780 struct work_struct work_work;
773 struct sk_buff_head work_skb_queue;
774 781
775 /* 782 /*
776 * private workqueue to mac80211. mac80211 makes this accessible 783 * private workqueue to mac80211. mac80211 makes this accessible
@@ -1437,8 +1444,6 @@ void ieee80211_work_init(struct ieee80211_local *local);
1437void ieee80211_add_work(struct ieee80211_work *wk); 1444void ieee80211_add_work(struct ieee80211_work *wk);
1438void free_work(struct ieee80211_work *wk); 1445void free_work(struct ieee80211_work *wk);
1439void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata); 1446void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata);
1440ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata,
1441 struct sk_buff *skb);
1442int ieee80211_wk_remain_on_channel(struct ieee80211_sub_if_data *sdata, 1447int ieee80211_wk_remain_on_channel(struct ieee80211_sub_if_data *sdata,
1443 struct ieee80211_channel *chan, 1448 struct ieee80211_channel *chan,
1444 enum nl80211_channel_type channel_type, 1449 enum nl80211_channel_type channel_type,
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 2efd595b2f7a..19f0818eba78 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1310,7 +1310,9 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local)
1310 1310
1311 /* do not count disabled managed interfaces */ 1311 /* do not count disabled managed interfaces */
1312 if (sdata->vif.type == NL80211_IFTYPE_STATION && 1312 if (sdata->vif.type == NL80211_IFTYPE_STATION &&
1313 !sdata->u.mgd.associated) { 1313 !sdata->u.mgd.associated &&
1314 !sdata->u.mgd.auth_data &&
1315 !sdata->u.mgd.assoc_data) {
1314 sdata->vif.bss_conf.idle = true; 1316 sdata->vif.bss_conf.idle = true;
1315 continue; 1317 continue;
1316 } 1318 }
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index f4fc540aac17..362e89d6d467 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -199,15 +199,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
199 return; 199 return;
200 200
201 if (sdata->vif.type == NL80211_IFTYPE_STATION) { 201 if (sdata->vif.type == NL80211_IFTYPE_STATION) {
202 /* 202 sdata->vif.bss_conf.bssid = sdata->u.mgd.bssid;
203 * While not associated, claim a BSSID of all-zeroes
204 * so that drivers don't do any weird things with the
205 * BSSID at that time.
206 */
207 if (sdata->vif.bss_conf.assoc)
208 sdata->vif.bss_conf.bssid = sdata->u.mgd.bssid;
209 else
210 sdata->vif.bss_conf.bssid = zero;
211 } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) 203 } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
212 sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid; 204 sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid;
213 else if (sdata->vif.type == NL80211_IFTYPE_AP) 205 else if (sdata->vif.type == NL80211_IFTYPE_AP)
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);
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 8d6fa674f53e..2b5b1194dfc2 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2484,14 +2484,9 @@ static ieee80211_rx_result debug_noinline
2484ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) 2484ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
2485{ 2485{
2486 struct ieee80211_sub_if_data *sdata = rx->sdata; 2486 struct ieee80211_sub_if_data *sdata = rx->sdata;
2487 ieee80211_rx_result rxs;
2488 struct ieee80211_mgmt *mgmt = (void *)rx->skb->data; 2487 struct ieee80211_mgmt *mgmt = (void *)rx->skb->data;
2489 __le16 stype; 2488 __le16 stype;
2490 2489
2491 rxs = ieee80211_work_rx_mgmt(rx->sdata, rx->skb);
2492 if (rxs != RX_CONTINUE)
2493 return rxs;
2494
2495 stype = mgmt->frame_control & cpu_to_le16(IEEE80211_FCTL_STYPE); 2490 stype = mgmt->frame_control & cpu_to_le16(IEEE80211_FCTL_STYPE);
2496 2491
2497 if (!ieee80211_vif_is_mesh(&sdata->vif) && 2492 if (!ieee80211_vif_is_mesh(&sdata->vif) &&
@@ -2500,10 +2495,13 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
2500 return RX_DROP_MONITOR; 2495 return RX_DROP_MONITOR;
2501 2496
2502 switch (stype) { 2497 switch (stype) {
2498 case cpu_to_le16(IEEE80211_STYPE_AUTH):
2503 case cpu_to_le16(IEEE80211_STYPE_BEACON): 2499 case cpu_to_le16(IEEE80211_STYPE_BEACON):
2504 case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP): 2500 case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP):
2505 /* process for all: mesh, mlme, ibss */ 2501 /* process for all: mesh, mlme, ibss */
2506 break; 2502 break;
2503 case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP):
2504 case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP):
2507 case cpu_to_le16(IEEE80211_STYPE_DEAUTH): 2505 case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
2508 case cpu_to_le16(IEEE80211_STYPE_DISASSOC): 2506 case cpu_to_le16(IEEE80211_STYPE_DISASSOC):
2509 if (is_multicast_ether_addr(mgmt->da) && 2507 if (is_multicast_ether_addr(mgmt->da) &&
@@ -2515,7 +2513,6 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
2515 return RX_DROP_MONITOR; 2513 return RX_DROP_MONITOR;
2516 break; 2514 break;
2517 case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ): 2515 case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ):
2518 case cpu_to_le16(IEEE80211_STYPE_AUTH):
2519 /* process only for ibss */ 2516 /* process only for ibss */
2520 if (sdata->vif.type != NL80211_IFTYPE_ADHOC) 2517 if (sdata->vif.type != NL80211_IFTYPE_ADHOC)
2521 return RX_DROP_MONITOR; 2518 return RX_DROP_MONITOR;
diff --git a/net/mac80211/work.c b/net/mac80211/work.c
index 0a1a176fbe91..c6e230efa049 100644
--- a/net/mac80211/work.c
+++ b/net/mac80211/work.c
@@ -27,16 +27,9 @@
27#include "rate.h" 27#include "rate.h"
28#include "driver-ops.h" 28#include "driver-ops.h"
29 29
30#define IEEE80211_AUTH_TIMEOUT (HZ / 5)
31#define IEEE80211_AUTH_MAX_TRIES 3
32#define IEEE80211_ASSOC_TIMEOUT (HZ / 5)
33#define IEEE80211_ASSOC_MAX_TRIES 3
34
35enum work_action { 30enum work_action {
36 WORK_ACT_MISMATCH,
37 WORK_ACT_NONE, 31 WORK_ACT_NONE,
38 WORK_ACT_TIMEOUT, 32 WORK_ACT_TIMEOUT,
39 WORK_ACT_DONE,
40}; 33};
41 34
42 35
@@ -71,465 +64,6 @@ void free_work(struct ieee80211_work *wk)
71 kfree_rcu(wk, rcu_head); 64 kfree_rcu(wk, rcu_head);
72} 65}
73 66
74static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len,
75 struct ieee80211_supported_band *sband,
76 u32 *rates)
77{
78 int i, j, count;
79 *rates = 0;
80 count = 0;
81 for (i = 0; i < supp_rates_len; i++) {
82 int rate = (supp_rates[i] & 0x7F) * 5;
83
84 for (j = 0; j < sband->n_bitrates; j++)
85 if (sband->bitrates[j].bitrate == rate) {
86 *rates |= BIT(j);
87 count++;
88 break;
89 }
90 }
91
92 return count;
93}
94
95/* frame sending functions */
96
97static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata,
98 struct sk_buff *skb, const u8 *ht_info_ie,
99 struct ieee80211_supported_band *sband,
100 struct ieee80211_channel *channel,
101 enum ieee80211_smps_mode smps)
102{
103 struct ieee80211_ht_info *ht_info;
104 u8 *pos;
105 u32 flags = channel->flags;
106 u16 cap;
107 struct ieee80211_sta_ht_cap ht_cap;
108
109 BUILD_BUG_ON(sizeof(ht_cap) != sizeof(sband->ht_cap));
110
111 if (!sband->ht_cap.ht_supported)
112 return;
113
114 if (!ht_info_ie)
115 return;
116
117 if (ht_info_ie[1] < sizeof(struct ieee80211_ht_info))
118 return;
119
120 memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap));
121 ieee80211_apply_htcap_overrides(sdata, &ht_cap);
122
123 ht_info = (struct ieee80211_ht_info *)(ht_info_ie + 2);
124
125 /* determine capability flags */
126 cap = ht_cap.cap;
127
128 switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
129 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
130 if (flags & IEEE80211_CHAN_NO_HT40PLUS) {
131 cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
132 cap &= ~IEEE80211_HT_CAP_SGI_40;
133 }
134 break;
135 case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
136 if (flags & IEEE80211_CHAN_NO_HT40MINUS) {
137 cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
138 cap &= ~IEEE80211_HT_CAP_SGI_40;
139 }
140 break;
141 }
142
143 /* set SM PS mode properly */
144 cap &= ~IEEE80211_HT_CAP_SM_PS;
145 switch (smps) {
146 case IEEE80211_SMPS_AUTOMATIC:
147 case IEEE80211_SMPS_NUM_MODES:
148 WARN_ON(1);
149 case IEEE80211_SMPS_OFF:
150 cap |= WLAN_HT_CAP_SM_PS_DISABLED <<
151 IEEE80211_HT_CAP_SM_PS_SHIFT;
152 break;
153 case IEEE80211_SMPS_STATIC:
154 cap |= WLAN_HT_CAP_SM_PS_STATIC <<
155 IEEE80211_HT_CAP_SM_PS_SHIFT;
156 break;
157 case IEEE80211_SMPS_DYNAMIC:
158 cap |= WLAN_HT_CAP_SM_PS_DYNAMIC <<
159 IEEE80211_HT_CAP_SM_PS_SHIFT;
160 break;
161 }
162
163 /* reserve and fill IE */
164 pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
165 ieee80211_ie_build_ht_cap(pos, &ht_cap, cap);
166}
167
168static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
169 struct ieee80211_work *wk)
170{
171 struct ieee80211_local *local = sdata->local;
172 struct sk_buff *skb;
173 struct ieee80211_mgmt *mgmt;
174 u8 *pos, qos_info;
175 size_t offset = 0, noffset;
176 int i, count, rates_len, supp_rates_len;
177 u16 capab;
178 struct ieee80211_supported_band *sband;
179 u32 rates = 0;
180
181 sband = local->hw.wiphy->bands[wk->chan->band];
182
183 if (wk->assoc.supp_rates_len) {
184 /*
185 * Get all rates supported by the device and the AP as
186 * some APs don't like getting a superset of their rates
187 * in the association request (e.g. D-Link DAP 1353 in
188 * b-only mode)...
189 */
190 rates_len = ieee80211_compatible_rates(wk->assoc.supp_rates,
191 wk->assoc.supp_rates_len,
192 sband, &rates);
193 } else {
194 /*
195 * In case AP not provide any supported rates information
196 * before association, we send information element(s) with
197 * all rates that we support.
198 */
199 rates = ~0;
200 rates_len = sband->n_bitrates;
201 }
202
203 skb = alloc_skb(local->hw.extra_tx_headroom +
204 sizeof(*mgmt) + /* bit too much but doesn't matter */
205 2 + wk->assoc.ssid_len + /* SSID */
206 4 + rates_len + /* (extended) rates */
207 4 + /* power capability */
208 2 + 2 * sband->n_channels + /* supported channels */
209 2 + sizeof(struct ieee80211_ht_cap) + /* HT */
210 wk->ie_len + /* extra IEs */
211 9, /* WMM */
212 GFP_KERNEL);
213 if (!skb)
214 return;
215
216 skb_reserve(skb, local->hw.extra_tx_headroom);
217
218 capab = WLAN_CAPABILITY_ESS;
219
220 if (sband->band == IEEE80211_BAND_2GHZ) {
221 if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE))
222 capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
223 if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE))
224 capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
225 }
226
227 if (wk->assoc.capability & WLAN_CAPABILITY_PRIVACY)
228 capab |= WLAN_CAPABILITY_PRIVACY;
229
230 if ((wk->assoc.capability & WLAN_CAPABILITY_SPECTRUM_MGMT) &&
231 (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT))
232 capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
233
234 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
235 memset(mgmt, 0, 24);
236 memcpy(mgmt->da, wk->filter_ta, ETH_ALEN);
237 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
238 memcpy(mgmt->bssid, wk->filter_ta, ETH_ALEN);
239
240 if (!is_zero_ether_addr(wk->assoc.prev_bssid)) {
241 skb_put(skb, 10);
242 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
243 IEEE80211_STYPE_REASSOC_REQ);
244 mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab);
245 mgmt->u.reassoc_req.listen_interval =
246 cpu_to_le16(local->hw.conf.listen_interval);
247 memcpy(mgmt->u.reassoc_req.current_ap, wk->assoc.prev_bssid,
248 ETH_ALEN);
249 } else {
250 skb_put(skb, 4);
251 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
252 IEEE80211_STYPE_ASSOC_REQ);
253 mgmt->u.assoc_req.capab_info = cpu_to_le16(capab);
254 mgmt->u.assoc_req.listen_interval =
255 cpu_to_le16(local->hw.conf.listen_interval);
256 }
257
258 /* SSID */
259 pos = skb_put(skb, 2 + wk->assoc.ssid_len);
260 *pos++ = WLAN_EID_SSID;
261 *pos++ = wk->assoc.ssid_len;
262 memcpy(pos, wk->assoc.ssid, wk->assoc.ssid_len);
263
264 /* add all rates which were marked to be used above */
265 supp_rates_len = rates_len;
266 if (supp_rates_len > 8)
267 supp_rates_len = 8;
268
269 pos = skb_put(skb, supp_rates_len + 2);
270 *pos++ = WLAN_EID_SUPP_RATES;
271 *pos++ = supp_rates_len;
272
273 count = 0;
274 for (i = 0; i < sband->n_bitrates; i++) {
275 if (BIT(i) & rates) {
276 int rate = sband->bitrates[i].bitrate;
277 *pos++ = (u8) (rate / 5);
278 if (++count == 8)
279 break;
280 }
281 }
282
283 if (rates_len > count) {
284 pos = skb_put(skb, rates_len - count + 2);
285 *pos++ = WLAN_EID_EXT_SUPP_RATES;
286 *pos++ = rates_len - count;
287
288 for (i++; i < sband->n_bitrates; i++) {
289 if (BIT(i) & rates) {
290 int rate = sband->bitrates[i].bitrate;
291 *pos++ = (u8) (rate / 5);
292 }
293 }
294 }
295
296 if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT) {
297 /* 1. power capabilities */
298 pos = skb_put(skb, 4);
299 *pos++ = WLAN_EID_PWR_CAPABILITY;
300 *pos++ = 2;
301 *pos++ = 0; /* min tx power */
302 *pos++ = wk->chan->max_power; /* max tx power */
303
304 /* 2. supported channels */
305 /* TODO: get this in reg domain format */
306 pos = skb_put(skb, 2 * sband->n_channels + 2);
307 *pos++ = WLAN_EID_SUPPORTED_CHANNELS;
308 *pos++ = 2 * sband->n_channels;
309 for (i = 0; i < sband->n_channels; i++) {
310 *pos++ = ieee80211_frequency_to_channel(
311 sband->channels[i].center_freq);
312 *pos++ = 1; /* one channel in the subband*/
313 }
314 }
315
316 /* if present, add any custom IEs that go before HT */
317 if (wk->ie_len && wk->ie) {
318 static const u8 before_ht[] = {
319 WLAN_EID_SSID,
320 WLAN_EID_SUPP_RATES,
321 WLAN_EID_EXT_SUPP_RATES,
322 WLAN_EID_PWR_CAPABILITY,
323 WLAN_EID_SUPPORTED_CHANNELS,
324 WLAN_EID_RSN,
325 WLAN_EID_QOS_CAPA,
326 WLAN_EID_RRM_ENABLED_CAPABILITIES,
327 WLAN_EID_MOBILITY_DOMAIN,
328 WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
329 };
330 noffset = ieee80211_ie_split(wk->ie, wk->ie_len,
331 before_ht, ARRAY_SIZE(before_ht),
332 offset);
333 pos = skb_put(skb, noffset - offset);
334 memcpy(pos, wk->ie + offset, noffset - offset);
335 offset = noffset;
336 }
337
338 if (wk->assoc.use_11n && wk->assoc.wmm_used &&
339 local->hw.queues >= 4)
340 ieee80211_add_ht_ie(sdata, skb, wk->assoc.ht_information_ie,
341 sband, wk->chan, wk->assoc.smps);
342
343 /* if present, add any custom non-vendor IEs that go after HT */
344 if (wk->ie_len && wk->ie) {
345 noffset = ieee80211_ie_split_vendor(wk->ie, wk->ie_len,
346 offset);
347 pos = skb_put(skb, noffset - offset);
348 memcpy(pos, wk->ie + offset, noffset - offset);
349 offset = noffset;
350 }
351
352 if (wk->assoc.wmm_used && local->hw.queues >= 4) {
353 if (wk->assoc.uapsd_used) {
354 qos_info = local->uapsd_queues;
355 qos_info |= (local->uapsd_max_sp_len <<
356 IEEE80211_WMM_IE_STA_QOSINFO_SP_SHIFT);
357 } else {
358 qos_info = 0;
359 }
360
361 pos = skb_put(skb, 9);
362 *pos++ = WLAN_EID_VENDOR_SPECIFIC;
363 *pos++ = 7; /* len */
364 *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */
365 *pos++ = 0x50;
366 *pos++ = 0xf2;
367 *pos++ = 2; /* WME */
368 *pos++ = 0; /* WME info */
369 *pos++ = 1; /* WME ver */
370 *pos++ = qos_info;
371 }
372
373 /* add any remaining custom (i.e. vendor specific here) IEs */
374 if (wk->ie_len && wk->ie) {
375 noffset = wk->ie_len;
376 pos = skb_put(skb, noffset - offset);
377 memcpy(pos, wk->ie + offset, noffset - offset);
378 }
379
380 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
381 ieee80211_tx_skb(sdata, skb);
382}
383
384static void ieee80211_remove_auth_bss(struct ieee80211_local *local,
385 struct ieee80211_work *wk)
386{
387 struct cfg80211_bss *cbss;
388 u16 capa_val = WLAN_CAPABILITY_ESS;
389
390 if (wk->probe_auth.privacy)
391 capa_val |= WLAN_CAPABILITY_PRIVACY;
392
393 cbss = cfg80211_get_bss(local->hw.wiphy, wk->chan, wk->filter_ta,
394 wk->probe_auth.ssid, wk->probe_auth.ssid_len,
395 WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_PRIVACY,
396 capa_val);
397 if (!cbss)
398 return;
399
400 cfg80211_unlink_bss(local->hw.wiphy, cbss);
401 cfg80211_put_bss(cbss);
402}
403
404static enum work_action __must_check
405ieee80211_direct_probe(struct ieee80211_work *wk)
406{
407 struct ieee80211_sub_if_data *sdata = wk->sdata;
408 struct ieee80211_local *local = sdata->local;
409
410 if (!wk->probe_auth.synced) {
411 int ret = drv_tx_sync(local, sdata, wk->filter_ta,
412 IEEE80211_TX_SYNC_AUTH);
413 if (ret)
414 return WORK_ACT_TIMEOUT;
415 }
416 wk->probe_auth.synced = true;
417
418 wk->probe_auth.tries++;
419 if (wk->probe_auth.tries > IEEE80211_AUTH_MAX_TRIES) {
420 printk(KERN_DEBUG "%s: direct probe to %pM timed out\n",
421 sdata->name, wk->filter_ta);
422
423 /*
424 * Most likely AP is not in the range so remove the
425 * bss struct for that AP.
426 */
427 ieee80211_remove_auth_bss(local, wk);
428
429 return WORK_ACT_TIMEOUT;
430 }
431
432 printk(KERN_DEBUG "%s: direct probe to %pM (try %d/%i)\n",
433 sdata->name, wk->filter_ta, wk->probe_auth.tries,
434 IEEE80211_AUTH_MAX_TRIES);
435
436 /*
437 * Direct probe is sent to broadcast address as some APs
438 * will not answer to direct packet in unassociated state.
439 */
440 ieee80211_send_probe_req(sdata, NULL, wk->probe_auth.ssid,
441 wk->probe_auth.ssid_len, NULL, 0,
442 (u32) -1, true, false);
443
444 wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
445 run_again(local, wk->timeout);
446
447 return WORK_ACT_NONE;
448}
449
450
451static enum work_action __must_check
452ieee80211_authenticate(struct ieee80211_work *wk)
453{
454 struct ieee80211_sub_if_data *sdata = wk->sdata;
455 struct ieee80211_local *local = sdata->local;
456
457 if (!wk->probe_auth.synced) {
458 int ret = drv_tx_sync(local, sdata, wk->filter_ta,
459 IEEE80211_TX_SYNC_AUTH);
460 if (ret)
461 return WORK_ACT_TIMEOUT;
462 }
463 wk->probe_auth.synced = true;
464
465 wk->probe_auth.tries++;
466 if (wk->probe_auth.tries > IEEE80211_AUTH_MAX_TRIES) {
467 printk(KERN_DEBUG "%s: authentication with %pM"
468 " timed out\n", sdata->name, wk->filter_ta);
469
470 /*
471 * Most likely AP is not in the range so remove the
472 * bss struct for that AP.
473 */
474 ieee80211_remove_auth_bss(local, wk);
475
476 return WORK_ACT_TIMEOUT;
477 }
478
479 printk(KERN_DEBUG "%s: authenticate with %pM (try %d)\n",
480 sdata->name, wk->filter_ta, wk->probe_auth.tries);
481
482 ieee80211_send_auth(sdata, 1, wk->probe_auth.algorithm, wk->ie,
483 wk->ie_len, wk->filter_ta, wk->filter_ta, NULL, 0,
484 0);
485 wk->probe_auth.transaction = 2;
486
487 wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
488 run_again(local, wk->timeout);
489
490 return WORK_ACT_NONE;
491}
492
493static enum work_action __must_check
494ieee80211_associate(struct ieee80211_work *wk)
495{
496 struct ieee80211_sub_if_data *sdata = wk->sdata;
497 struct ieee80211_local *local = sdata->local;
498
499 if (!wk->assoc.synced) {
500 int ret = drv_tx_sync(local, sdata, wk->filter_ta,
501 IEEE80211_TX_SYNC_ASSOC);
502 if (ret)
503 return WORK_ACT_TIMEOUT;
504 }
505 wk->assoc.synced = true;
506
507 wk->assoc.tries++;
508 if (wk->assoc.tries > IEEE80211_ASSOC_MAX_TRIES) {
509 printk(KERN_DEBUG "%s: association with %pM"
510 " timed out\n",
511 sdata->name, wk->filter_ta);
512
513 /*
514 * Most likely AP is not in the range so remove the
515 * bss struct for that AP.
516 */
517 if (wk->assoc.bss)
518 cfg80211_unlink_bss(local->hw.wiphy, wk->assoc.bss);
519
520 return WORK_ACT_TIMEOUT;
521 }
522
523 printk(KERN_DEBUG "%s: associate with %pM (try %d)\n",
524 sdata->name, wk->filter_ta, wk->assoc.tries);
525 ieee80211_send_assoc(sdata, wk);
526
527 wk->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT;
528 run_again(local, wk->timeout);
529
530 return WORK_ACT_NONE;
531}
532
533static enum work_action __must_check 67static enum work_action __must_check
534ieee80211_remain_on_channel_timeout(struct ieee80211_work *wk) 68ieee80211_remain_on_channel_timeout(struct ieee80211_work *wk)
535{ 69{
@@ -569,300 +103,6 @@ ieee80211_offchannel_tx(struct ieee80211_work *wk)
569 return WORK_ACT_TIMEOUT; 103 return WORK_ACT_TIMEOUT;
570} 104}
571 105
572static enum work_action __must_check
573ieee80211_assoc_beacon_wait(struct ieee80211_work *wk)
574{
575 if (wk->started)
576 return WORK_ACT_TIMEOUT;
577
578 /*
579 * Wait up to one beacon interval ...
580 * should this be more if we miss one?
581 */
582 printk(KERN_DEBUG "%s: waiting for beacon from %pM\n",
583 wk->sdata->name, wk->filter_ta);
584 wk->timeout = TU_TO_EXP_TIME(wk->assoc.bss->beacon_interval);
585 return WORK_ACT_NONE;
586}
587
588static void ieee80211_auth_challenge(struct ieee80211_work *wk,
589 struct ieee80211_mgmt *mgmt,
590 size_t len)
591{
592 struct ieee80211_sub_if_data *sdata = wk->sdata;
593 u8 *pos;
594 struct ieee802_11_elems elems;
595
596 pos = mgmt->u.auth.variable;
597 ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
598 if (!elems.challenge)
599 return;
600 ieee80211_send_auth(sdata, 3, wk->probe_auth.algorithm,
601 elems.challenge - 2, elems.challenge_len + 2,
602 wk->filter_ta, wk->filter_ta, wk->probe_auth.key,
603 wk->probe_auth.key_len, wk->probe_auth.key_idx);
604 wk->probe_auth.transaction = 4;
605}
606
607static enum work_action __must_check
608ieee80211_rx_mgmt_auth(struct ieee80211_work *wk,
609 struct ieee80211_mgmt *mgmt, size_t len)
610{
611 u16 auth_alg, auth_transaction, status_code;
612
613 if (wk->type != IEEE80211_WORK_AUTH)
614 return WORK_ACT_MISMATCH;
615
616 if (len < 24 + 6)
617 return WORK_ACT_NONE;
618
619 auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg);
620 auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction);
621 status_code = le16_to_cpu(mgmt->u.auth.status_code);
622
623 if (auth_alg != wk->probe_auth.algorithm ||
624 auth_transaction != wk->probe_auth.transaction)
625 return WORK_ACT_NONE;
626
627 if (status_code != WLAN_STATUS_SUCCESS) {
628 printk(KERN_DEBUG "%s: %pM denied authentication (status %d)\n",
629 wk->sdata->name, mgmt->sa, status_code);
630 return WORK_ACT_DONE;
631 }
632
633 switch (wk->probe_auth.algorithm) {
634 case WLAN_AUTH_OPEN:
635 case WLAN_AUTH_LEAP:
636 case WLAN_AUTH_FT:
637 break;
638 case WLAN_AUTH_SHARED_KEY:
639 if (wk->probe_auth.transaction != 4) {
640 ieee80211_auth_challenge(wk, mgmt, len);
641 /* need another frame */
642 return WORK_ACT_NONE;
643 }
644 break;
645 default:
646 WARN_ON(1);
647 return WORK_ACT_NONE;
648 }
649
650 printk(KERN_DEBUG "%s: authenticated\n", wk->sdata->name);
651 return WORK_ACT_DONE;
652}
653
654static enum work_action __must_check
655ieee80211_rx_mgmt_assoc_resp(struct ieee80211_work *wk,
656 struct ieee80211_mgmt *mgmt, size_t len,
657 bool reassoc)
658{
659 struct ieee80211_sub_if_data *sdata = wk->sdata;
660 struct ieee80211_local *local = sdata->local;
661 u16 capab_info, status_code, aid;
662 struct ieee802_11_elems elems;
663 u8 *pos;
664
665 if (wk->type != IEEE80211_WORK_ASSOC)
666 return WORK_ACT_MISMATCH;
667
668 /*
669 * AssocResp and ReassocResp have identical structure, so process both
670 * of them in this function.
671 */
672
673 if (len < 24 + 6)
674 return WORK_ACT_NONE;
675
676 capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
677 status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
678 aid = le16_to_cpu(mgmt->u.assoc_resp.aid);
679
680 printk(KERN_DEBUG "%s: RX %sssocResp from %pM (capab=0x%x "
681 "status=%d aid=%d)\n",
682 sdata->name, reassoc ? "Rea" : "A", mgmt->sa,
683 capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14))));
684
685 pos = mgmt->u.assoc_resp.variable;
686 ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
687
688 if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY &&
689 elems.timeout_int && elems.timeout_int_len == 5 &&
690 elems.timeout_int[0] == WLAN_TIMEOUT_ASSOC_COMEBACK) {
691 u32 tu, ms;
692 tu = get_unaligned_le32(elems.timeout_int + 1);
693 ms = tu * 1024 / 1000;
694 printk(KERN_DEBUG "%s: %pM rejected association temporarily; "
695 "comeback duration %u TU (%u ms)\n",
696 sdata->name, mgmt->sa, tu, ms);
697 wk->timeout = jiffies + msecs_to_jiffies(ms);
698 if (ms > IEEE80211_ASSOC_TIMEOUT)
699 run_again(local, wk->timeout);
700 return WORK_ACT_NONE;
701 }
702
703 if (status_code != WLAN_STATUS_SUCCESS)
704 printk(KERN_DEBUG "%s: %pM denied association (code=%d)\n",
705 sdata->name, mgmt->sa, status_code);
706 else
707 printk(KERN_DEBUG "%s: associated\n", sdata->name);
708
709 return WORK_ACT_DONE;
710}
711
712static enum work_action __must_check
713ieee80211_rx_mgmt_probe_resp(struct ieee80211_work *wk,
714 struct ieee80211_mgmt *mgmt, size_t len,
715 struct ieee80211_rx_status *rx_status)
716{
717 struct ieee80211_sub_if_data *sdata = wk->sdata;
718 struct ieee80211_local *local = sdata->local;
719 size_t baselen;
720
721 ASSERT_WORK_MTX(local);
722
723 if (wk->type != IEEE80211_WORK_DIRECT_PROBE)
724 return WORK_ACT_MISMATCH;
725
726 if (len < 24 + 12)
727 return WORK_ACT_NONE;
728
729 baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
730 if (baselen > len)
731 return WORK_ACT_NONE;
732
733 printk(KERN_DEBUG "%s: direct probe responded\n", sdata->name);
734 return WORK_ACT_DONE;
735}
736
737static enum work_action __must_check
738ieee80211_rx_mgmt_beacon(struct ieee80211_work *wk,
739 struct ieee80211_mgmt *mgmt, size_t len)
740{
741 struct ieee80211_sub_if_data *sdata = wk->sdata;
742 struct ieee80211_local *local = sdata->local;
743
744 ASSERT_WORK_MTX(local);
745
746 if (wk->type != IEEE80211_WORK_ASSOC_BEACON_WAIT)
747 return WORK_ACT_MISMATCH;
748
749 if (len < 24 + 12)
750 return WORK_ACT_NONE;
751
752 printk(KERN_DEBUG "%s: beacon received\n", sdata->name);
753 return WORK_ACT_DONE;
754}
755
756static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local,
757 struct sk_buff *skb)
758{
759 struct ieee80211_rx_status *rx_status;
760 struct ieee80211_mgmt *mgmt;
761 struct ieee80211_work *wk;
762 enum work_action rma = WORK_ACT_NONE;
763 u16 fc;
764
765 rx_status = (struct ieee80211_rx_status *) skb->cb;
766 mgmt = (struct ieee80211_mgmt *) skb->data;
767 fc = le16_to_cpu(mgmt->frame_control);
768
769 mutex_lock(&local->mtx);
770
771 list_for_each_entry(wk, &local->work_list, list) {
772 const u8 *bssid = NULL;
773
774 switch (wk->type) {
775 case IEEE80211_WORK_DIRECT_PROBE:
776 case IEEE80211_WORK_AUTH:
777 case IEEE80211_WORK_ASSOC:
778 case IEEE80211_WORK_ASSOC_BEACON_WAIT:
779 bssid = wk->filter_ta;
780 break;
781 default:
782 continue;
783 }
784
785 /*
786 * Before queuing, we already verified mgmt->sa,
787 * so this is needed just for matching.
788 */
789 if (compare_ether_addr(bssid, mgmt->bssid))
790 continue;
791
792 switch (fc & IEEE80211_FCTL_STYPE) {
793 case IEEE80211_STYPE_BEACON:
794 rma = ieee80211_rx_mgmt_beacon(wk, mgmt, skb->len);
795 break;
796 case IEEE80211_STYPE_PROBE_RESP:
797 rma = ieee80211_rx_mgmt_probe_resp(wk, mgmt, skb->len,
798 rx_status);
799 break;
800 case IEEE80211_STYPE_AUTH:
801 rma = ieee80211_rx_mgmt_auth(wk, mgmt, skb->len);
802 break;
803 case IEEE80211_STYPE_ASSOC_RESP:
804 rma = ieee80211_rx_mgmt_assoc_resp(wk, mgmt,
805 skb->len, false);
806 break;
807 case IEEE80211_STYPE_REASSOC_RESP:
808 rma = ieee80211_rx_mgmt_assoc_resp(wk, mgmt,
809 skb->len, true);
810 break;
811 default:
812 WARN_ON(1);
813 rma = WORK_ACT_NONE;
814 }
815
816 /*
817 * We've either received an unexpected frame, or we have
818 * multiple work items and need to match the frame to the
819 * right one.
820 */
821 if (rma == WORK_ACT_MISMATCH)
822 continue;
823
824 /*
825 * We've processed this frame for that work, so it can't
826 * belong to another work struct.
827 * NB: this is also required for correctness for 'rma'!
828 */
829 break;
830 }
831
832 switch (rma) {
833 case WORK_ACT_MISMATCH:
834 /* ignore this unmatched frame */
835 break;
836 case WORK_ACT_NONE:
837 break;
838 case WORK_ACT_DONE:
839 list_del_rcu(&wk->list);
840 break;
841 default:
842 WARN(1, "unexpected: %d", rma);
843 }
844
845 mutex_unlock(&local->mtx);
846
847 if (rma != WORK_ACT_DONE)
848 goto out;
849
850 switch (wk->done(wk, skb)) {
851 case WORK_DONE_DESTROY:
852 free_work(wk);
853 break;
854 case WORK_DONE_REQUEUE:
855 synchronize_rcu();
856 wk->started = false; /* restart */
857 mutex_lock(&local->mtx);
858 list_add_tail(&wk->list, &local->work_list);
859 mutex_unlock(&local->mtx);
860 }
861
862 out:
863 kfree_skb(skb);
864}
865
866static void ieee80211_work_timer(unsigned long data) 106static void ieee80211_work_timer(unsigned long data)
867{ 107{
868 struct ieee80211_local *local = (void *) data; 108 struct ieee80211_local *local = (void *) data;
@@ -877,7 +117,6 @@ static void ieee80211_work_work(struct work_struct *work)
877{ 117{
878 struct ieee80211_local *local = 118 struct ieee80211_local *local =
879 container_of(work, struct ieee80211_local, work_work); 119 container_of(work, struct ieee80211_local, work_work);
880 struct sk_buff *skb;
881 struct ieee80211_work *wk, *tmp; 120 struct ieee80211_work *wk, *tmp;
882 LIST_HEAD(free_work); 121 LIST_HEAD(free_work);
883 enum work_action rma; 122 enum work_action rma;
@@ -893,10 +132,6 @@ static void ieee80211_work_work(struct work_struct *work)
893 if (WARN(local->suspended, "work scheduled while going to suspend\n")) 132 if (WARN(local->suspended, "work scheduled while going to suspend\n"))
894 return; 133 return;
895 134
896 /* first process frames to avoid timing out while a frame is pending */
897 while ((skb = skb_dequeue(&local->work_skb_queue)))
898 ieee80211_work_rx_queued_mgmt(local, skb);
899
900 mutex_lock(&local->mtx); 135 mutex_lock(&local->mtx);
901 136
902 ieee80211_recalc_idle(local); 137 ieee80211_recalc_idle(local);
@@ -947,24 +182,12 @@ static void ieee80211_work_work(struct work_struct *work)
947 case IEEE80211_WORK_ABORT: 182 case IEEE80211_WORK_ABORT:
948 rma = WORK_ACT_TIMEOUT; 183 rma = WORK_ACT_TIMEOUT;
949 break; 184 break;
950 case IEEE80211_WORK_DIRECT_PROBE:
951 rma = ieee80211_direct_probe(wk);
952 break;
953 case IEEE80211_WORK_AUTH:
954 rma = ieee80211_authenticate(wk);
955 break;
956 case IEEE80211_WORK_ASSOC:
957 rma = ieee80211_associate(wk);
958 break;
959 case IEEE80211_WORK_REMAIN_ON_CHANNEL: 185 case IEEE80211_WORK_REMAIN_ON_CHANNEL:
960 rma = ieee80211_remain_on_channel_timeout(wk); 186 rma = ieee80211_remain_on_channel_timeout(wk);
961 break; 187 break;
962 case IEEE80211_WORK_OFFCHANNEL_TX: 188 case IEEE80211_WORK_OFFCHANNEL_TX:
963 rma = ieee80211_offchannel_tx(wk); 189 rma = ieee80211_offchannel_tx(wk);
964 break; 190 break;
965 case IEEE80211_WORK_ASSOC_BEACON_WAIT:
966 rma = ieee80211_assoc_beacon_wait(wk);
967 break;
968 } 191 }
969 192
970 wk->started = started; 193 wk->started = started;
@@ -1052,7 +275,6 @@ void ieee80211_work_init(struct ieee80211_local *local)
1052 setup_timer(&local->work_timer, ieee80211_work_timer, 275 setup_timer(&local->work_timer, ieee80211_work_timer,
1053 (unsigned long)local); 276 (unsigned long)local);
1054 INIT_WORK(&local->work_work, ieee80211_work_work); 277 INIT_WORK(&local->work_work, ieee80211_work_work);
1055 skb_queue_head_init(&local->work_skb_queue);
1056} 278}
1057 279
1058void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata) 280void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata)
@@ -1086,43 +308,6 @@ void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata)
1086 mutex_unlock(&local->mtx); 308 mutex_unlock(&local->mtx);
1087} 309}
1088 310
1089ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata,
1090 struct sk_buff *skb)
1091{
1092 struct ieee80211_local *local = sdata->local;
1093 struct ieee80211_mgmt *mgmt;
1094 struct ieee80211_work *wk;
1095 u16 fc;
1096
1097 if (skb->len < 24)
1098 return RX_DROP_MONITOR;
1099
1100 mgmt = (struct ieee80211_mgmt *) skb->data;
1101 fc = le16_to_cpu(mgmt->frame_control);
1102
1103 list_for_each_entry_rcu(wk, &local->work_list, list) {
1104 if (sdata != wk->sdata)
1105 continue;
1106 if (compare_ether_addr(wk->filter_ta, mgmt->sa))
1107 continue;
1108 if (compare_ether_addr(wk->filter_ta, mgmt->bssid))
1109 continue;
1110
1111 switch (fc & IEEE80211_FCTL_STYPE) {
1112 case IEEE80211_STYPE_AUTH:
1113 case IEEE80211_STYPE_PROBE_RESP:
1114 case IEEE80211_STYPE_ASSOC_RESP:
1115 case IEEE80211_STYPE_REASSOC_RESP:
1116 case IEEE80211_STYPE_BEACON:
1117 skb_queue_tail(&local->work_skb_queue, skb);
1118 ieee80211_queue_work(&local->hw, &local->work_work);
1119 return RX_QUEUED;
1120 }
1121 }
1122
1123 return RX_CONTINUE;
1124}
1125
1126static enum work_done_result ieee80211_remain_done(struct ieee80211_work *wk, 311static enum work_done_result ieee80211_remain_done(struct ieee80211_work *wk,
1127 struct sk_buff *skb) 312 struct sk_buff *skb)
1128{ 313{