00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include <linux/delay.h>
00017 #include <linux/if_ether.h>
00018 #include <linux/skbuff.h>
00019 #include <linux/if_arp.h>
00020 #include <linux/etherdevice.h>
00021 #include <linux/crc32.h>
00022 #include <linux/slab.h>
00023 #include <net/mac80211.h>
00024 #include <asm/unaligned.h>
00025
00026 #include "ieee80211_i.h"
00027 #include "rate.h"
00028 #include "driver-ops.h"
00029
00030 #define IEEE80211_AUTH_TIMEOUT (HZ / 5)
00031 #define IEEE80211_AUTH_MAX_TRIES 3
00032 #define IEEE80211_ASSOC_TIMEOUT (HZ / 5)
00033 #define IEEE80211_ASSOC_MAX_TRIES 3
00034
00035 enum work_action {
00036 WORK_ACT_MISMATCH,
00037 WORK_ACT_NONE,
00038 WORK_ACT_TIMEOUT,
00039 WORK_ACT_DONE,
00040 };
00041
00042
00043
00044 static inline void ASSERT_WORK_MTX(struct ieee80211_local *local)
00045 {
00046 lockdep_assert_held(&local->mtx);
00047 }
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 static void run_again(struct ieee80211_local *local,
00060 unsigned long timeout)
00061 {
00062 ASSERT_WORK_MTX(local);
00063
00064 if (!timer_pending(&local->work_timer) ||
00065 time_before(timeout, local->work_timer.expires))
00066 mod_timer(&local->work_timer, timeout);
00067 }
00068
00069 void free_work(struct ieee80211_work *wk)
00070 {
00071 kfree_rcu(wk, rcu_head);
00072 }
00073
00074 static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len,
00075 struct ieee80211_supported_band *sband,
00076 u32 *rates)
00077 {
00078 int i, j, count;
00079 *rates = 0;
00080 count = 0;
00081 for (i = 0; i < supp_rates_len; i++) {
00082 int rate = (supp_rates[i] & 0x7F) * 5;
00083
00084 for (j = 0; j < sband->n_bitrates; j++)
00085 if (sband->bitrates[j].bitrate == rate) {
00086 *rates |= BIT(j);
00087 count++;
00088 break;
00089 }
00090 }
00091
00092 return count;
00093 }
00094
00095
00096
00097 static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie,
00098 struct ieee80211_supported_band *sband,
00099 struct ieee80211_channel *channel,
00100 enum ieee80211_smps_mode smps)
00101 {
00102 struct ieee80211_ht_info *ht_info;
00103 u8 *pos;
00104 u32 flags = channel->flags;
00105 u16 cap = sband->ht_cap.cap;
00106 __le16 tmp;
00107
00108 if (!sband->ht_cap.ht_supported)
00109 return;
00110
00111 if (!ht_info_ie)
00112 return;
00113
00114 if (ht_info_ie[1] < sizeof(struct ieee80211_ht_info))
00115 return;
00116
00117 ht_info = (struct ieee80211_ht_info *)(ht_info_ie + 2);
00118
00119
00120
00121 switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
00122 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
00123 if (flags & IEEE80211_CHAN_NO_HT40PLUS) {
00124 cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
00125 cap &= ~IEEE80211_HT_CAP_SGI_40;
00126 }
00127 break;
00128 case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
00129 if (flags & IEEE80211_CHAN_NO_HT40MINUS) {
00130 cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
00131 cap &= ~IEEE80211_HT_CAP_SGI_40;
00132 }
00133 break;
00134 }
00135
00136
00137 cap &= ~IEEE80211_HT_CAP_SM_PS;
00138 switch (smps) {
00139 case IEEE80211_SMPS_AUTOMATIC:
00140 case IEEE80211_SMPS_NUM_MODES:
00141 WARN_ON(1);
00142 case IEEE80211_SMPS_OFF:
00143 cap |= WLAN_HT_CAP_SM_PS_DISABLED <<
00144 IEEE80211_HT_CAP_SM_PS_SHIFT;
00145 break;
00146 case IEEE80211_SMPS_STATIC:
00147 cap |= WLAN_HT_CAP_SM_PS_STATIC <<
00148 IEEE80211_HT_CAP_SM_PS_SHIFT;
00149 break;
00150 case IEEE80211_SMPS_DYNAMIC:
00151 cap |= WLAN_HT_CAP_SM_PS_DYNAMIC <<
00152 IEEE80211_HT_CAP_SM_PS_SHIFT;
00153 break;
00154 }
00155
00156
00157
00158 pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
00159 *pos++ = WLAN_EID_HT_CAPABILITY;
00160 *pos++ = sizeof(struct ieee80211_ht_cap);
00161 memset(pos, 0, sizeof(struct ieee80211_ht_cap));
00162
00163
00164 tmp = cpu_to_le16(cap);
00165 memcpy(pos, &tmp, sizeof(u16));
00166 pos += sizeof(u16);
00167
00168
00169 *pos++ = sband->ht_cap.ampdu_factor |
00170 (sband->ht_cap.ampdu_density <<
00171 IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
00172
00173
00174 memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
00175 pos += sizeof(sband->ht_cap.mcs);
00176
00177
00178 pos += sizeof(__le16);
00179
00180
00181 pos += sizeof(__le32);
00182
00183
00184 pos += sizeof(u8);
00185 }
00186
00187 static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
00188 struct ieee80211_work *wk)
00189 {
00190 struct ieee80211_local *local = sdata->local;
00191 struct sk_buff *skb;
00192 struct ieee80211_mgmt *mgmt;
00193 u8 *pos, qos_info;
00194 size_t offset = 0, noffset;
00195 int i, count, rates_len, supp_rates_len;
00196 u16 capab;
00197 struct ieee80211_supported_band *sband;
00198 u32 rates = 0;
00199
00200 sband = local->hw.wiphy->bands[wk->chan->band];
00201
00202 if (wk->assoc.supp_rates_len) {
00203
00204
00205
00206
00207
00208
00209 rates_len = ieee80211_compatible_rates(wk->assoc.supp_rates,
00210 wk->assoc.supp_rates_len,
00211 sband, &rates);
00212 } else {
00213
00214
00215
00216
00217
00218 rates = ~0;
00219 rates_len = sband->n_bitrates;
00220 }
00221
00222 skb = alloc_skb(local->hw.extra_tx_headroom +
00223 sizeof(*mgmt) +
00224 2 + wk->assoc.ssid_len +
00225 4 + rates_len +
00226 4 +
00227 2 + 2 * sband->n_channels +
00228 2 + sizeof(struct ieee80211_ht_cap) +
00229 wk->ie_len +
00230 9,
00231 GFP_KERNEL);
00232 if (!skb)
00233 return;
00234
00235 skb_reserve(skb, local->hw.extra_tx_headroom);
00236
00237 capab = WLAN_CAPABILITY_ESS;
00238
00239 if (sband->band == IEEE80211_BAND_2GHZ) {
00240 if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE))
00241 capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
00242 if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE))
00243 capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
00244 }
00245
00246 if (wk->assoc.capability & WLAN_CAPABILITY_PRIVACY)
00247 capab |= WLAN_CAPABILITY_PRIVACY;
00248
00249 if ((wk->assoc.capability & WLAN_CAPABILITY_SPECTRUM_MGMT) &&
00250 (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT))
00251 capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
00252
00253 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
00254 memset(mgmt, 0, 24);
00255 memcpy(mgmt->da, wk->filter_ta, ETH_ALEN);
00256 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
00257 memcpy(mgmt->bssid, wk->filter_ta, ETH_ALEN);
00258
00259 if (!is_zero_ether_addr(wk->assoc.prev_bssid)) {
00260 skb_put(skb, 10);
00261 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
00262 IEEE80211_STYPE_REASSOC_REQ);
00263 mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab);
00264 mgmt->u.reassoc_req.listen_interval =
00265 cpu_to_le16(local->hw.conf.listen_interval);
00266 memcpy(mgmt->u.reassoc_req.current_ap, wk->assoc.prev_bssid,
00267 ETH_ALEN);
00268 } else {
00269 skb_put(skb, 4);
00270 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
00271 IEEE80211_STYPE_ASSOC_REQ);
00272 mgmt->u.assoc_req.capab_info = cpu_to_le16(capab);
00273 mgmt->u.assoc_req.listen_interval =
00274 cpu_to_le16(local->hw.conf.listen_interval);
00275 }
00276
00277
00278 pos = skb_put(skb, 2 + wk->assoc.ssid_len);
00279 *pos++ = WLAN_EID_SSID;
00280 *pos++ = wk->assoc.ssid_len;
00281 memcpy(pos, wk->assoc.ssid, wk->assoc.ssid_len);
00282
00283
00284 supp_rates_len = rates_len;
00285 if (supp_rates_len > 8)
00286 supp_rates_len = 8;
00287
00288 pos = skb_put(skb, supp_rates_len + 2);
00289 *pos++ = WLAN_EID_SUPP_RATES;
00290 *pos++ = supp_rates_len;
00291
00292 count = 0;
00293 for (i = 0; i < sband->n_bitrates; i++) {
00294 if (BIT(i) & rates) {
00295 int rate = sband->bitrates[i].bitrate;
00296 *pos++ = (u8) (rate / 5);
00297 if (++count == 8)
00298 break;
00299 }
00300 }
00301
00302 if (rates_len > count) {
00303 pos = skb_put(skb, rates_len - count + 2);
00304 *pos++ = WLAN_EID_EXT_SUPP_RATES;
00305 *pos++ = rates_len - count;
00306
00307 for (i++; i < sband->n_bitrates; i++) {
00308 if (BIT(i) & rates) {
00309 int rate = sband->bitrates[i].bitrate;
00310 *pos++ = (u8) (rate / 5);
00311 }
00312 }
00313 }
00314
00315 if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT) {
00316
00317 pos = skb_put(skb, 4);
00318 *pos++ = WLAN_EID_PWR_CAPABILITY;
00319 *pos++ = 2;
00320 *pos++ = 0;
00321 *pos++ = wk->chan->max_power;
00322
00323
00324
00325 pos = skb_put(skb, 2 * sband->n_channels + 2);
00326 *pos++ = WLAN_EID_SUPPORTED_CHANNELS;
00327 *pos++ = 2 * sband->n_channels;
00328 for (i = 0; i < sband->n_channels; i++) {
00329 *pos++ = ieee80211_frequency_to_channel(
00330 sband->channels[i].center_freq);
00331 *pos++ = 1;
00332 }
00333 }
00334
00335
00336 if (wk->ie_len && wk->ie) {
00337 static const u8 before_ht[] = {
00338 WLAN_EID_SSID,
00339 WLAN_EID_SUPP_RATES,
00340 WLAN_EID_EXT_SUPP_RATES,
00341 WLAN_EID_PWR_CAPABILITY,
00342 WLAN_EID_SUPPORTED_CHANNELS,
00343 WLAN_EID_RSN,
00344 WLAN_EID_QOS_CAPA,
00345 WLAN_EID_RRM_ENABLED_CAPABILITIES,
00346 WLAN_EID_MOBILITY_DOMAIN,
00347 WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
00348 };
00349 noffset = ieee80211_ie_split(wk->ie, wk->ie_len,
00350 before_ht, ARRAY_SIZE(before_ht),
00351 offset);
00352 pos = skb_put(skb, noffset - offset);
00353 memcpy(pos, wk->ie + offset, noffset - offset);
00354 offset = noffset;
00355 }
00356
00357 if (wk->assoc.use_11n && wk->assoc.wmm_used &&
00358 local->hw.queues >= 4)
00359 ieee80211_add_ht_ie(skb, wk->assoc.ht_information_ie,
00360 sband, wk->chan, wk->assoc.smps);
00361
00362
00363 if (wk->ie_len && wk->ie) {
00364 noffset = ieee80211_ie_split_vendor(wk->ie, wk->ie_len,
00365 offset);
00366 pos = skb_put(skb, noffset - offset);
00367 memcpy(pos, wk->ie + offset, noffset - offset);
00368 offset = noffset;
00369 }
00370
00371 if (wk->assoc.wmm_used && local->hw.queues >= 4) {
00372 if (wk->assoc.uapsd_used) {
00373 qos_info = local->uapsd_queues;
00374 qos_info |= (local->uapsd_max_sp_len <<
00375 IEEE80211_WMM_IE_STA_QOSINFO_SP_SHIFT);
00376 } else {
00377 qos_info = 0;
00378 }
00379
00380 pos = skb_put(skb, 9);
00381 *pos++ = WLAN_EID_VENDOR_SPECIFIC;
00382 *pos++ = 7;
00383 *pos++ = 0x00;
00384 *pos++ = 0x50;
00385 *pos++ = 0xf2;
00386 *pos++ = 2;
00387 *pos++ = 0;
00388 *pos++ = 1;
00389 *pos++ = qos_info;
00390 }
00391
00392
00393 if (wk->ie_len && wk->ie) {
00394 noffset = wk->ie_len;
00395 pos = skb_put(skb, noffset - offset);
00396 memcpy(pos, wk->ie + offset, noffset - offset);
00397 }
00398
00399 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
00400 ieee80211_tx_skb(sdata, skb);
00401 }
00402
00403 static void ieee80211_remove_auth_bss(struct ieee80211_local *local,
00404 struct ieee80211_work *wk)
00405 {
00406 struct cfg80211_bss *cbss;
00407 u16 capa_val = WLAN_CAPABILITY_ESS;
00408
00409 if (wk->probe_auth.privacy)
00410 capa_val |= WLAN_CAPABILITY_PRIVACY;
00411
00412 cbss = cfg80211_get_bss(local->hw.wiphy, wk->chan, wk->filter_ta,
00413 wk->probe_auth.ssid, wk->probe_auth.ssid_len,
00414 WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_PRIVACY,
00415 capa_val);
00416 if (!cbss)
00417 return;
00418
00419 cfg80211_unlink_bss(local->hw.wiphy, cbss);
00420 cfg80211_put_bss(cbss);
00421 }
00422
00423 static enum work_action __must_check
00424 ieee80211_direct_probe(struct ieee80211_work *wk)
00425 {
00426 struct ieee80211_sub_if_data *sdata = wk->sdata;
00427 struct ieee80211_local *local = sdata->local;
00428
00429 if (!wk->probe_auth.synced) {
00430 int ret = drv_tx_sync(local, sdata, wk->filter_ta,
00431 IEEE80211_TX_SYNC_AUTH);
00432 if (ret)
00433 return WORK_ACT_TIMEOUT;
00434 }
00435 wk->probe_auth.synced = true;
00436
00437 wk->probe_auth.tries++;
00438 if (wk->probe_auth.tries > IEEE80211_AUTH_MAX_TRIES) {
00439 printk(KERN_DEBUG "%s: direct probe to %pM timed out\n",
00440 sdata->name, wk->filter_ta);
00441
00442
00443
00444
00445
00446 ieee80211_remove_auth_bss(local, wk);
00447
00448 return WORK_ACT_TIMEOUT;
00449 }
00450
00451 printk(KERN_DEBUG "%s: direct probe to %pM (try %d/%i)\n",
00452 sdata->name, wk->filter_ta, wk->probe_auth.tries,
00453 IEEE80211_AUTH_MAX_TRIES);
00454
00455
00456
00457
00458
00459 ieee80211_send_probe_req(sdata, NULL, wk->probe_auth.ssid,
00460 wk->probe_auth.ssid_len, NULL, 0,
00461 (u32) -1, true, false);
00462
00463 wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
00464 run_again(local, wk->timeout);
00465
00466 return WORK_ACT_NONE;
00467 }
00468
00469
00470 static enum work_action __must_check
00471 ieee80211_authenticate(struct ieee80211_work *wk)
00472 {
00473 struct ieee80211_sub_if_data *sdata = wk->sdata;
00474 struct ieee80211_local *local = sdata->local;
00475
00476 if (!wk->probe_auth.synced) {
00477 int ret = drv_tx_sync(local, sdata, wk->filter_ta,
00478 IEEE80211_TX_SYNC_AUTH);
00479 if (ret)
00480 return WORK_ACT_TIMEOUT;
00481 }
00482 wk->probe_auth.synced = true;
00483
00484 wk->probe_auth.tries++;
00485 if (wk->probe_auth.tries > IEEE80211_AUTH_MAX_TRIES) {
00486 printk(KERN_DEBUG "%s: authentication with %pM"
00487 " timed out\n", sdata->name, wk->filter_ta);
00488
00489
00490
00491
00492
00493 ieee80211_remove_auth_bss(local, wk);
00494
00495 return WORK_ACT_TIMEOUT;
00496 }
00497
00498 printk(KERN_DEBUG "%s: authenticate with %pM (try %d)\n",
00499 sdata->name, wk->filter_ta, wk->probe_auth.tries);
00500
00501 ieee80211_send_auth(sdata, 1, wk->probe_auth.algorithm, wk->ie,
00502 wk->ie_len, wk->filter_ta, NULL, 0, 0);
00503 wk->probe_auth.transaction = 2;
00504
00505 wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
00506 run_again(local, wk->timeout);
00507
00508 return WORK_ACT_NONE;
00509 }
00510
00511 static enum work_action __must_check
00512 ieee80211_associate(struct ieee80211_work *wk)
00513 {
00514 struct ieee80211_sub_if_data *sdata = wk->sdata;
00515 struct ieee80211_local *local = sdata->local;
00516
00517 if (!wk->assoc.synced) {
00518 int ret = drv_tx_sync(local, sdata, wk->filter_ta,
00519 IEEE80211_TX_SYNC_ASSOC);
00520 if (ret)
00521 return WORK_ACT_TIMEOUT;
00522 }
00523 wk->assoc.synced = true;
00524
00525 wk->assoc.tries++;
00526 if (wk->assoc.tries > IEEE80211_ASSOC_MAX_TRIES) {
00527 printk(KERN_DEBUG "%s: association with %pM"
00528 " timed out\n",
00529 sdata->name, wk->filter_ta);
00530
00531
00532
00533
00534
00535 if (wk->assoc.bss)
00536 cfg80211_unlink_bss(local->hw.wiphy, wk->assoc.bss);
00537
00538 return WORK_ACT_TIMEOUT;
00539 }
00540
00541 printk(KERN_DEBUG "%s: associate with %pM (try %d)\n",
00542 sdata->name, wk->filter_ta, wk->assoc.tries);
00543 ieee80211_send_assoc(sdata, wk);
00544
00545 wk->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT;
00546 run_again(local, wk->timeout);
00547
00548 return WORK_ACT_NONE;
00549 }
00550
00551 static enum work_action __must_check
00552 ieee80211_remain_on_channel_timeout(struct ieee80211_work *wk)
00553 {
00554
00555
00556
00557
00558 if (!wk->started) {
00559 wk->timeout = jiffies + msecs_to_jiffies(wk->remain.duration);
00560
00561 cfg80211_ready_on_channel(wk->sdata->dev, (unsigned long) wk,
00562 wk->chan, wk->chan_type,
00563 wk->remain.duration, GFP_KERNEL);
00564
00565 return WORK_ACT_NONE;
00566 }
00567
00568 return WORK_ACT_TIMEOUT;
00569 }
00570
00571 static enum work_action __must_check
00572 ieee80211_offchannel_tx(struct ieee80211_work *wk)
00573 {
00574 if (!wk->started) {
00575 wk->timeout = jiffies + msecs_to_jiffies(wk->offchan_tx.wait);
00576
00577
00578
00579
00580
00581
00582 ieee80211_tx_skb(wk->sdata, wk->offchan_tx.frame);
00583
00584 return WORK_ACT_NONE;
00585 }
00586
00587 return WORK_ACT_TIMEOUT;
00588 }
00589
00590 static enum work_action __must_check
00591 ieee80211_assoc_beacon_wait(struct ieee80211_work *wk)
00592 {
00593 if (wk->started)
00594 return WORK_ACT_TIMEOUT;
00595
00596
00597
00598
00599
00600 printk(KERN_DEBUG "%s: waiting for beacon from %pM\n",
00601 wk->sdata->name, wk->filter_ta);
00602 wk->timeout = TU_TO_EXP_TIME(wk->assoc.bss->beacon_interval);
00603 return WORK_ACT_NONE;
00604 }
00605
00606 static void ieee80211_auth_challenge(struct ieee80211_work *wk,
00607 struct ieee80211_mgmt *mgmt,
00608 size_t len)
00609 {
00610 struct ieee80211_sub_if_data *sdata = wk->sdata;
00611 u8 *pos;
00612 struct ieee802_11_elems elems;
00613
00614 pos = mgmt->u.auth.variable;
00615 ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
00616 if (!elems.challenge)
00617 return;
00618 ieee80211_send_auth(sdata, 3, wk->probe_auth.algorithm,
00619 elems.challenge - 2, elems.challenge_len + 2,
00620 wk->filter_ta, wk->probe_auth.key,
00621 wk->probe_auth.key_len, wk->probe_auth.key_idx);
00622 wk->probe_auth.transaction = 4;
00623 }
00624
00625 static enum work_action __must_check
00626 ieee80211_rx_mgmt_auth(struct ieee80211_work *wk,
00627 struct ieee80211_mgmt *mgmt, size_t len)
00628 {
00629 u16 auth_alg, auth_transaction, status_code;
00630
00631 if (wk->type != IEEE80211_WORK_AUTH)
00632 return WORK_ACT_MISMATCH;
00633
00634 if (len < 24 + 6)
00635 return WORK_ACT_NONE;
00636
00637 auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg);
00638 auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction);
00639 status_code = le16_to_cpu(mgmt->u.auth.status_code);
00640
00641 if (auth_alg != wk->probe_auth.algorithm ||
00642 auth_transaction != wk->probe_auth.transaction)
00643 return WORK_ACT_NONE;
00644
00645 if (status_code != WLAN_STATUS_SUCCESS) {
00646 printk(KERN_DEBUG "%s: %pM denied authentication (status %d)\n",
00647 wk->sdata->name, mgmt->sa, status_code);
00648 return WORK_ACT_DONE;
00649 }
00650
00651 switch (wk->probe_auth.algorithm) {
00652 case WLAN_AUTH_OPEN:
00653 case WLAN_AUTH_LEAP:
00654 case WLAN_AUTH_FT:
00655 break;
00656 case WLAN_AUTH_SHARED_KEY:
00657 if (wk->probe_auth.transaction != 4) {
00658 ieee80211_auth_challenge(wk, mgmt, len);
00659
00660 return WORK_ACT_NONE;
00661 }
00662 break;
00663 default:
00664 WARN_ON(1);
00665 return WORK_ACT_NONE;
00666 }
00667
00668 printk(KERN_DEBUG "%s: authenticated\n", wk->sdata->name);
00669 return WORK_ACT_DONE;
00670 }
00671
00672 static enum work_action __must_check
00673 ieee80211_rx_mgmt_assoc_resp(struct ieee80211_work *wk,
00674 struct ieee80211_mgmt *mgmt, size_t len,
00675 bool reassoc)
00676 {
00677 struct ieee80211_sub_if_data *sdata = wk->sdata;
00678 struct ieee80211_local *local = sdata->local;
00679 u16 capab_info, status_code, aid;
00680 struct ieee802_11_elems elems;
00681 u8 *pos;
00682
00683 if (wk->type != IEEE80211_WORK_ASSOC)
00684 return WORK_ACT_MISMATCH;
00685
00686
00687
00688
00689
00690
00691 if (len < 24 + 6)
00692 return WORK_ACT_NONE;
00693
00694 capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
00695 status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
00696 aid = le16_to_cpu(mgmt->u.assoc_resp.aid);
00697
00698 printk(KERN_DEBUG "%s: RX %sssocResp from %pM (capab=0x%x "
00699 "status=%d aid=%d)\n",
00700 sdata->name, reassoc ? "Rea" : "A", mgmt->sa,
00701 capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14))));
00702
00703 pos = mgmt->u.assoc_resp.variable;
00704 ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
00705
00706 if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY &&
00707 elems.timeout_int && elems.timeout_int_len == 5 &&
00708 elems.timeout_int[0] == WLAN_TIMEOUT_ASSOC_COMEBACK) {
00709 u32 tu, ms;
00710 tu = get_unaligned_le32(elems.timeout_int + 1);
00711 ms = tu * 1024 / 1000;
00712 printk(KERN_DEBUG "%s: %pM rejected association temporarily; "
00713 "comeback duration %u TU (%u ms)\n",
00714 sdata->name, mgmt->sa, tu, ms);
00715 wk->timeout = jiffies + msecs_to_jiffies(ms);
00716 if (ms > IEEE80211_ASSOC_TIMEOUT)
00717 run_again(local, wk->timeout);
00718 return WORK_ACT_NONE;
00719 }
00720
00721 if (status_code != WLAN_STATUS_SUCCESS)
00722 printk(KERN_DEBUG "%s: %pM denied association (code=%d)\n",
00723 sdata->name, mgmt->sa, status_code);
00724 else
00725 printk(KERN_DEBUG "%s: associated\n", sdata->name);
00726
00727 return WORK_ACT_DONE;
00728 }
00729
00730 static enum work_action __must_check
00731 ieee80211_rx_mgmt_probe_resp(struct ieee80211_work *wk,
00732 struct ieee80211_mgmt *mgmt, size_t len,
00733 struct ieee80211_rx_status *rx_status)
00734 {
00735 struct ieee80211_sub_if_data *sdata = wk->sdata;
00736 struct ieee80211_local *local = sdata->local;
00737 size_t baselen;
00738
00739 ASSERT_WORK_MTX(local);
00740
00741 if (wk->type != IEEE80211_WORK_DIRECT_PROBE)
00742 return WORK_ACT_MISMATCH;
00743
00744 if (len < 24 + 12)
00745 return WORK_ACT_NONE;
00746
00747 baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
00748 if (baselen > len)
00749 return WORK_ACT_NONE;
00750
00751 printk(KERN_DEBUG "%s: direct probe responded\n", sdata->name);
00752 return WORK_ACT_DONE;
00753 }
00754
00755 static enum work_action __must_check
00756 ieee80211_rx_mgmt_beacon(struct ieee80211_work *wk,
00757 struct ieee80211_mgmt *mgmt, size_t len)
00758 {
00759 struct ieee80211_sub_if_data *sdata = wk->sdata;
00760 struct ieee80211_local *local = sdata->local;
00761
00762 ASSERT_WORK_MTX(local);
00763
00764 if (wk->type != IEEE80211_WORK_ASSOC_BEACON_WAIT)
00765 return WORK_ACT_MISMATCH;
00766
00767 if (len < 24 + 12)
00768 return WORK_ACT_NONE;
00769
00770 printk(KERN_DEBUG "%s: beacon received\n", sdata->name);
00771 return WORK_ACT_DONE;
00772 }
00773
00774 static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local,
00775 struct sk_buff *skb)
00776 {
00777 struct ieee80211_rx_status *rx_status;
00778 struct ieee80211_mgmt *mgmt;
00779 struct ieee80211_work *wk;
00780 enum work_action rma = WORK_ACT_NONE;
00781 u16 fc;
00782
00783 rx_status = (struct ieee80211_rx_status *) skb->cb;
00784 mgmt = (struct ieee80211_mgmt *) skb->data;
00785 fc = le16_to_cpu(mgmt->frame_control);
00786
00787 mutex_lock(&local->mtx);
00788
00789 list_for_each_entry(wk, &local->work_list, list) {
00790 const u8 *bssid = NULL;
00791
00792 switch (wk->type) {
00793 case IEEE80211_WORK_DIRECT_PROBE:
00794 case IEEE80211_WORK_AUTH:
00795 case IEEE80211_WORK_ASSOC:
00796 case IEEE80211_WORK_ASSOC_BEACON_WAIT:
00797 bssid = wk->filter_ta;
00798 break;
00799 default:
00800 continue;
00801 }
00802
00803
00804
00805
00806
00807 if (compare_ether_addr(bssid, mgmt->bssid))
00808 continue;
00809
00810 switch (fc & IEEE80211_FCTL_STYPE) {
00811 case IEEE80211_STYPE_BEACON:
00812 rma = ieee80211_rx_mgmt_beacon(wk, mgmt, skb->len);
00813 break;
00814 case IEEE80211_STYPE_PROBE_RESP:
00815 rma = ieee80211_rx_mgmt_probe_resp(wk, mgmt, skb->len,
00816 rx_status);
00817 break;
00818 case IEEE80211_STYPE_AUTH:
00819 rma = ieee80211_rx_mgmt_auth(wk, mgmt, skb->len);
00820 break;
00821 case IEEE80211_STYPE_ASSOC_RESP:
00822 rma = ieee80211_rx_mgmt_assoc_resp(wk, mgmt,
00823 skb->len, false);
00824 break;
00825 case IEEE80211_STYPE_REASSOC_RESP:
00826 rma = ieee80211_rx_mgmt_assoc_resp(wk, mgmt,
00827 skb->len, true);
00828 break;
00829 default:
00830 WARN_ON(1);
00831 rma = WORK_ACT_NONE;
00832 }
00833
00834
00835
00836
00837
00838
00839 if (rma == WORK_ACT_MISMATCH)
00840 continue;
00841
00842
00843
00844
00845
00846
00847 break;
00848 }
00849
00850 switch (rma) {
00851 case WORK_ACT_MISMATCH:
00852
00853 break;
00854 case WORK_ACT_NONE:
00855 break;
00856 case WORK_ACT_DONE:
00857 list_del_rcu(&wk->list);
00858 break;
00859 default:
00860 WARN(1, "unexpected: %d", rma);
00861 }
00862
00863 mutex_unlock(&local->mtx);
00864
00865 if (rma != WORK_ACT_DONE)
00866 goto out;
00867
00868 switch (wk->done(wk, skb)) {
00869 case WORK_DONE_DESTROY:
00870 free_work(wk);
00871 break;
00872 case WORK_DONE_REQUEUE:
00873 synchronize_rcu();
00874 wk->started = false;
00875 mutex_lock(&local->mtx);
00876 list_add_tail(&wk->list, &local->work_list);
00877 mutex_unlock(&local->mtx);
00878 }
00879
00880 out:
00881 kfree_skb(skb);
00882 }
00883
00884 static bool ieee80211_work_ct_coexists(enum nl80211_channel_type wk_ct,
00885 enum nl80211_channel_type oper_ct)
00886 {
00887 switch (wk_ct) {
00888 case NL80211_CHAN_NO_HT:
00889 return true;
00890 case NL80211_CHAN_HT20:
00891 if (oper_ct != NL80211_CHAN_NO_HT)
00892 return true;
00893 return false;
00894 case NL80211_CHAN_HT40MINUS:
00895 case NL80211_CHAN_HT40PLUS:
00896 return (wk_ct == oper_ct);
00897 }
00898 WARN_ON(1);
00899 return false;
00900 }
00901
00902 static void ieee80211_work_timer(unsigned long data)
00903 {
00904 struct ieee80211_local *local = (void *) data;
00905
00906 if (local->quiescing)
00907 return;
00908
00909 ieee80211_queue_work(&local->hw, &local->work_work);
00910 }
00911
00912 static void ieee80211_work_work(struct work_struct *work)
00913 {
00914 struct ieee80211_local *local =
00915 container_of(work, struct ieee80211_local, work_work);
00916 struct sk_buff *skb;
00917 struct ieee80211_work *wk, *tmp;
00918 LIST_HEAD(free_work);
00919 enum work_action rma;
00920 bool remain_off_channel = false;
00921
00922 if (local->scanning)
00923 return;
00924
00925
00926
00927
00928
00929 if (WARN(local->suspended, "work scheduled while going to suspend\n"))
00930 return;
00931
00932
00933 while ((skb = skb_dequeue(&local->work_skb_queue)))
00934 ieee80211_work_rx_queued_mgmt(local, skb);
00935
00936 mutex_lock(&local->mtx);
00937
00938 ieee80211_recalc_idle(local);
00939
00940 list_for_each_entry_safe(wk, tmp, &local->work_list, list) {
00941 bool started = wk->started;
00942
00943
00944 if (!started && local->tmp_channel &&
00945 wk->chan == local->tmp_channel &&
00946 wk->chan_type == local->tmp_channel_type) {
00947 started = true;
00948 wk->timeout = jiffies;
00949 }
00950
00951 if (!started && !local->tmp_channel) {
00952
00953
00954
00955
00956
00957
00958 ieee80211_offchannel_stop_beaconing(local);
00959 ieee80211_offchannel_stop_station(local);
00960
00961 local->tmp_channel = wk->chan;
00962 local->tmp_channel_type = wk->chan_type;
00963 ieee80211_hw_config(local, 0);
00964 started = true;
00965 wk->timeout = jiffies;
00966 }
00967
00968
00969 if (!started)
00970 continue;
00971
00972 if (time_is_after_jiffies(wk->timeout)) {
00973
00974
00975
00976
00977
00978 run_again(local, wk->timeout);
00979 continue;
00980 }
00981
00982 switch (wk->type) {
00983 default:
00984 WARN_ON(1);
00985
00986 rma = WORK_ACT_NONE;
00987 break;
00988 case IEEE80211_WORK_ABORT:
00989 rma = WORK_ACT_TIMEOUT;
00990 break;
00991 case IEEE80211_WORK_DIRECT_PROBE:
00992 rma = ieee80211_direct_probe(wk);
00993 break;
00994 case IEEE80211_WORK_AUTH:
00995 rma = ieee80211_authenticate(wk);
00996 break;
00997 case IEEE80211_WORK_ASSOC:
00998 rma = ieee80211_associate(wk);
00999 break;
01000 case IEEE80211_WORK_REMAIN_ON_CHANNEL:
01001 rma = ieee80211_remain_on_channel_timeout(wk);
01002 break;
01003 case IEEE80211_WORK_OFFCHANNEL_TX:
01004 rma = ieee80211_offchannel_tx(wk);
01005 break;
01006 case IEEE80211_WORK_ASSOC_BEACON_WAIT:
01007 rma = ieee80211_assoc_beacon_wait(wk);
01008 break;
01009 }
01010
01011 wk->started = started;
01012
01013 switch (rma) {
01014 case WORK_ACT_NONE:
01015
01016 run_again(local, wk->timeout);
01017 break;
01018 case WORK_ACT_TIMEOUT:
01019 list_del_rcu(&wk->list);
01020 synchronize_rcu();
01021 list_add(&wk->list, &free_work);
01022 break;
01023 default:
01024 WARN(1, "unexpected: %d", rma);
01025 }
01026 }
01027
01028 list_for_each_entry(wk, &local->work_list, list) {
01029 if (!wk->started)
01030 continue;
01031 if (wk->chan != local->tmp_channel)
01032 continue;
01033 if (!ieee80211_work_ct_coexists(wk->chan_type,
01034 local->tmp_channel_type))
01035 continue;
01036 remain_off_channel = true;
01037 }
01038
01039 if (!remain_off_channel && local->tmp_channel) {
01040 local->tmp_channel = NULL;
01041
01042
01043
01044
01045
01046
01047
01048
01049 ieee80211_hw_config(local, 0);
01050
01051
01052
01053
01054
01055
01056
01057 ieee80211_offchannel_return(local, true);
01058
01059
01060 run_again(local, jiffies + HZ/2);
01061 }
01062
01063 if (list_empty(&local->work_list) && local->scan_req &&
01064 !local->scanning)
01065 ieee80211_queue_delayed_work(&local->hw,
01066 &local->scan_work,
01067 round_jiffies_relative(0));
01068
01069 ieee80211_recalc_idle(local);
01070
01071 mutex_unlock(&local->mtx);
01072
01073 list_for_each_entry_safe(wk, tmp, &free_work, list) {
01074 wk->done(wk, NULL);
01075 list_del(&wk->list);
01076 kfree(wk);
01077 }
01078 }
01079
01080 void ieee80211_add_work(struct ieee80211_work *wk)
01081 {
01082 struct ieee80211_local *local;
01083
01084 if (WARN_ON(!wk->chan))
01085 return;
01086
01087 if (WARN_ON(!wk->sdata))
01088 return;
01089
01090 if (WARN_ON(!wk->done))
01091 return;
01092
01093 if (WARN_ON(!ieee80211_sdata_running(wk->sdata)))
01094 return;
01095
01096 wk->started = false;
01097
01098 local = wk->sdata->local;
01099 mutex_lock(&local->mtx);
01100 list_add_tail(&wk->list, &local->work_list);
01101 mutex_unlock(&local->mtx);
01102
01103 ieee80211_queue_work(&local->hw, &local->work_work);
01104 }
01105
01106 void ieee80211_work_init(struct ieee80211_local *local)
01107 {
01108 INIT_LIST_HEAD(&local->work_list);
01109 setup_timer(&local->work_timer, ieee80211_work_timer,
01110 (unsigned long)local);
01111 INIT_WORK(&local->work_work, ieee80211_work_work);
01112 skb_queue_head_init(&local->work_skb_queue);
01113 }
01114
01115 void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata)
01116 {
01117 struct ieee80211_local *local = sdata->local;
01118 struct ieee80211_work *wk;
01119 bool cleanup = false;
01120
01121 mutex_lock(&local->mtx);
01122 list_for_each_entry(wk, &local->work_list, list) {
01123 if (wk->sdata != sdata)
01124 continue;
01125 cleanup = true;
01126 wk->type = IEEE80211_WORK_ABORT;
01127 wk->started = true;
01128 wk->timeout = jiffies;
01129 }
01130 mutex_unlock(&local->mtx);
01131
01132
01133 if (cleanup)
01134 ieee80211_work_work(&local->work_work);
01135
01136 mutex_lock(&local->mtx);
01137 list_for_each_entry(wk, &local->work_list, list) {
01138 if (wk->sdata != sdata)
01139 continue;
01140 WARN_ON(1);
01141 break;
01142 }
01143 mutex_unlock(&local->mtx);
01144 }
01145
01146 ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata,
01147 struct sk_buff *skb)
01148 {
01149 struct ieee80211_local *local = sdata->local;
01150 struct ieee80211_mgmt *mgmt;
01151 struct ieee80211_work *wk;
01152 u16 fc;
01153
01154 if (skb->len < 24)
01155 return RX_DROP_MONITOR;
01156
01157 mgmt = (struct ieee80211_mgmt *) skb->data;
01158 fc = le16_to_cpu(mgmt->frame_control);
01159
01160 list_for_each_entry_rcu(wk, &local->work_list, list) {
01161 if (sdata != wk->sdata)
01162 continue;
01163 if (compare_ether_addr(wk->filter_ta, mgmt->sa))
01164 continue;
01165 if (compare_ether_addr(wk->filter_ta, mgmt->bssid))
01166 continue;
01167
01168 switch (fc & IEEE80211_FCTL_STYPE) {
01169 case IEEE80211_STYPE_AUTH:
01170 case IEEE80211_STYPE_PROBE_RESP:
01171 case IEEE80211_STYPE_ASSOC_RESP:
01172 case IEEE80211_STYPE_REASSOC_RESP:
01173 case IEEE80211_STYPE_BEACON:
01174 skb_queue_tail(&local->work_skb_queue, skb);
01175 ieee80211_queue_work(&local->hw, &local->work_work);
01176 return RX_QUEUED;
01177 }
01178 }
01179
01180 return RX_CONTINUE;
01181 }
01182
01183 static enum work_done_result ieee80211_remain_done(struct ieee80211_work *wk,
01184 struct sk_buff *skb)
01185 {
01186
01187
01188
01189 cfg80211_remain_on_channel_expired(wk->sdata->dev, (unsigned long) wk,
01190 wk->chan, wk->chan_type,
01191 GFP_KERNEL);
01192
01193 return WORK_DONE_DESTROY;
01194 }
01195
01196 int ieee80211_wk_remain_on_channel(struct ieee80211_sub_if_data *sdata,
01197 struct ieee80211_channel *chan,
01198 enum nl80211_channel_type channel_type,
01199 unsigned int duration, u64 *cookie)
01200 {
01201 struct ieee80211_work *wk;
01202
01203 wk = kzalloc(sizeof(*wk), GFP_KERNEL);
01204 if (!wk)
01205 return -ENOMEM;
01206
01207 wk->type = IEEE80211_WORK_REMAIN_ON_CHANNEL;
01208 wk->chan = chan;
01209 wk->chan_type = channel_type;
01210 wk->sdata = sdata;
01211 wk->done = ieee80211_remain_done;
01212
01213 wk->remain.duration = duration;
01214
01215 *cookie = (unsigned long) wk;
01216
01217 ieee80211_add_work(wk);
01218
01219 return 0;
01220 }
01221
01222 int ieee80211_wk_cancel_remain_on_channel(struct ieee80211_sub_if_data *sdata,
01223 u64 cookie)
01224 {
01225 struct ieee80211_local *local = sdata->local;
01226 struct ieee80211_work *wk, *tmp;
01227 bool found = false;
01228
01229 mutex_lock(&local->mtx);
01230 list_for_each_entry_safe(wk, tmp, &local->work_list, list) {
01231 if ((unsigned long) wk == cookie) {
01232 wk->timeout = jiffies;
01233 found = true;
01234 break;
01235 }
01236 }
01237 mutex_unlock(&local->mtx);
01238
01239 if (!found)
01240 return -ENOENT;
01241
01242 ieee80211_queue_work(&local->hw, &local->work_work);
01243
01244 return 0;
01245 }