aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/mlme.c776
1 files changed, 387 insertions, 389 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index b1815c1ee6d3..e917e1b72631 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -74,6 +74,27 @@ static u8 *ieee80211_bss_get_ie(struct ieee80211_sta_bss *bss, u8 ie)
74 return NULL; 74 return NULL;
75} 75}
76 76
77static int ieee80211_compatible_rates(struct ieee80211_sta_bss *bss,
78 struct ieee80211_supported_band *sband,
79 u64 *rates)
80{
81 int i, j, count;
82 *rates = 0;
83 count = 0;
84 for (i = 0; i < bss->supp_rates_len; i++) {
85 int rate = (bss->supp_rates[i] & 0x7F) * 5;
86
87 for (j = 0; j < sband->n_bitrates; j++)
88 if (sband->bitrates[j].bitrate == rate) {
89 *rates |= BIT(j);
90 count++;
91 break;
92 }
93 }
94
95 return count;
96}
97
77/* frame sending functions */ 98/* frame sending functions */
78void ieee80211_sta_tx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, 99void ieee80211_sta_tx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
79 int encrypt) 100 int encrypt)
@@ -186,6 +207,364 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
186 ieee80211_sta_tx(sdata, skb, 0); 207 ieee80211_sta_tx(sdata, skb, 0);
187} 208}
188 209
210static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
211 struct ieee80211_if_sta *ifsta)
212{
213 struct ieee80211_local *local = sdata->local;
214 struct sk_buff *skb;
215 struct ieee80211_mgmt *mgmt;
216 u8 *pos, *ies, *ht_add_ie;
217 int i, len, count, rates_len, supp_rates_len;
218 u16 capab;
219 struct ieee80211_sta_bss *bss;
220 int wmm = 0;
221 struct ieee80211_supported_band *sband;
222 u64 rates = 0;
223
224 skb = dev_alloc_skb(local->hw.extra_tx_headroom +
225 sizeof(*mgmt) + 200 + ifsta->extra_ie_len +
226 ifsta->ssid_len);
227 if (!skb) {
228 printk(KERN_DEBUG "%s: failed to allocate buffer for assoc "
229 "frame\n", sdata->dev->name);
230 return;
231 }
232 skb_reserve(skb, local->hw.extra_tx_headroom);
233
234 sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
235
236 capab = ifsta->capab;
237
238 if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ) {
239 if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE))
240 capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
241 if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE))
242 capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
243 }
244
245 bss = ieee80211_rx_bss_get(local, ifsta->bssid,
246 local->hw.conf.channel->center_freq,
247 ifsta->ssid, ifsta->ssid_len);
248 if (bss) {
249 if (bss->capability & WLAN_CAPABILITY_PRIVACY)
250 capab |= WLAN_CAPABILITY_PRIVACY;
251 if (bss->wmm_used)
252 wmm = 1;
253
254 /* get all rates supported by the device and the AP as
255 * some APs don't like getting a superset of their rates
256 * in the association request (e.g. D-Link DAP 1353 in
257 * b-only mode) */
258 rates_len = ieee80211_compatible_rates(bss, sband, &rates);
259
260 if ((bss->capability & WLAN_CAPABILITY_SPECTRUM_MGMT) &&
261 (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT))
262 capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
263
264 ieee80211_rx_bss_put(local, bss);
265 } else {
266 rates = ~0;
267 rates_len = sband->n_bitrates;
268 }
269
270 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
271 memset(mgmt, 0, 24);
272 memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
273 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
274 memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
275
276 if (ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) {
277 skb_put(skb, 10);
278 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
279 IEEE80211_STYPE_REASSOC_REQ);
280 mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab);
281 mgmt->u.reassoc_req.listen_interval =
282 cpu_to_le16(local->hw.conf.listen_interval);
283 memcpy(mgmt->u.reassoc_req.current_ap, ifsta->prev_bssid,
284 ETH_ALEN);
285 } else {
286 skb_put(skb, 4);
287 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
288 IEEE80211_STYPE_ASSOC_REQ);
289 mgmt->u.assoc_req.capab_info = cpu_to_le16(capab);
290 mgmt->u.reassoc_req.listen_interval =
291 cpu_to_le16(local->hw.conf.listen_interval);
292 }
293
294 /* SSID */
295 ies = pos = skb_put(skb, 2 + ifsta->ssid_len);
296 *pos++ = WLAN_EID_SSID;
297 *pos++ = ifsta->ssid_len;
298 memcpy(pos, ifsta->ssid, ifsta->ssid_len);
299
300 /* add all rates which were marked to be used above */
301 supp_rates_len = rates_len;
302 if (supp_rates_len > 8)
303 supp_rates_len = 8;
304
305 len = sband->n_bitrates;
306 pos = skb_put(skb, supp_rates_len + 2);
307 *pos++ = WLAN_EID_SUPP_RATES;
308 *pos++ = supp_rates_len;
309
310 count = 0;
311 for (i = 0; i < sband->n_bitrates; i++) {
312 if (BIT(i) & rates) {
313 int rate = sband->bitrates[i].bitrate;
314 *pos++ = (u8) (rate / 5);
315 if (++count == 8)
316 break;
317 }
318 }
319
320 if (rates_len > count) {
321 pos = skb_put(skb, rates_len - count + 2);
322 *pos++ = WLAN_EID_EXT_SUPP_RATES;
323 *pos++ = rates_len - count;
324
325 for (i++; i < sband->n_bitrates; i++) {
326 if (BIT(i) & rates) {
327 int rate = sband->bitrates[i].bitrate;
328 *pos++ = (u8) (rate / 5);
329 }
330 }
331 }
332
333 if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT) {
334 /* 1. power capabilities */
335 pos = skb_put(skb, 4);
336 *pos++ = WLAN_EID_PWR_CAPABILITY;
337 *pos++ = 2;
338 *pos++ = 0; /* min tx power */
339 *pos++ = local->hw.conf.channel->max_power; /* max tx power */
340
341 /* 2. supported channels */
342 /* TODO: get this in reg domain format */
343 pos = skb_put(skb, 2 * sband->n_channels + 2);
344 *pos++ = WLAN_EID_SUPPORTED_CHANNELS;
345 *pos++ = 2 * sband->n_channels;
346 for (i = 0; i < sband->n_channels; i++) {
347 *pos++ = ieee80211_frequency_to_channel(
348 sband->channels[i].center_freq);
349 *pos++ = 1; /* one channel in the subband*/
350 }
351 }
352
353 if (ifsta->extra_ie) {
354 pos = skb_put(skb, ifsta->extra_ie_len);
355 memcpy(pos, ifsta->extra_ie, ifsta->extra_ie_len);
356 }
357
358 if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
359 pos = skb_put(skb, 9);
360 *pos++ = WLAN_EID_VENDOR_SPECIFIC;
361 *pos++ = 7; /* len */
362 *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */
363 *pos++ = 0x50;
364 *pos++ = 0xf2;
365 *pos++ = 2; /* WME */
366 *pos++ = 0; /* WME info */
367 *pos++ = 1; /* WME ver */
368 *pos++ = 0;
369 }
370
371 /* wmm support is a must to HT */
372 if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED) &&
373 sband->ht_info.ht_supported &&
374 (ht_add_ie = ieee80211_bss_get_ie(bss, WLAN_EID_HT_EXTRA_INFO))) {
375 struct ieee80211_ht_addt_info *ht_add_info =
376 (struct ieee80211_ht_addt_info *)ht_add_ie;
377 u16 cap = sband->ht_info.cap;
378 __le16 tmp;
379 u32 flags = local->hw.conf.channel->flags;
380
381 switch (ht_add_info->ht_param & IEEE80211_HT_IE_CHA_SEC_OFFSET) {
382 case IEEE80211_HT_IE_CHA_SEC_ABOVE:
383 if (flags & IEEE80211_CHAN_NO_FAT_ABOVE) {
384 cap &= ~IEEE80211_HT_CAP_SUP_WIDTH;
385 cap &= ~IEEE80211_HT_CAP_SGI_40;
386 }
387 break;
388 case IEEE80211_HT_IE_CHA_SEC_BELOW:
389 if (flags & IEEE80211_CHAN_NO_FAT_BELOW) {
390 cap &= ~IEEE80211_HT_CAP_SUP_WIDTH;
391 cap &= ~IEEE80211_HT_CAP_SGI_40;
392 }
393 break;
394 }
395
396 tmp = cpu_to_le16(cap);
397 pos = skb_put(skb, sizeof(struct ieee80211_ht_cap)+2);
398 *pos++ = WLAN_EID_HT_CAPABILITY;
399 *pos++ = sizeof(struct ieee80211_ht_cap);
400 memset(pos, 0, sizeof(struct ieee80211_ht_cap));
401 memcpy(pos, &tmp, sizeof(u16));
402 pos += sizeof(u16);
403 /* TODO: needs a define here for << 2 */
404 *pos++ = sband->ht_info.ampdu_factor |
405 (sband->ht_info.ampdu_density << 2);
406 memcpy(pos, sband->ht_info.supp_mcs_set, 16);
407 }
408
409 kfree(ifsta->assocreq_ies);
410 ifsta->assocreq_ies_len = (skb->data + skb->len) - ies;
411 ifsta->assocreq_ies = kmalloc(ifsta->assocreq_ies_len, GFP_KERNEL);
412 if (ifsta->assocreq_ies)
413 memcpy(ifsta->assocreq_ies, ies, ifsta->assocreq_ies_len);
414
415 ieee80211_sta_tx(sdata, skb, 0);
416}
417
418
419static void ieee80211_send_deauth(struct ieee80211_sub_if_data *sdata,
420 struct ieee80211_if_sta *ifsta, u16 reason)
421{
422 struct ieee80211_local *local = sdata->local;
423 struct sk_buff *skb;
424 struct ieee80211_mgmt *mgmt;
425
426 skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt));
427 if (!skb) {
428 printk(KERN_DEBUG "%s: failed to allocate buffer for deauth "
429 "frame\n", sdata->dev->name);
430 return;
431 }
432 skb_reserve(skb, local->hw.extra_tx_headroom);
433
434 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
435 memset(mgmt, 0, 24);
436 memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
437 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
438 memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
439 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
440 IEEE80211_STYPE_DEAUTH);
441 skb_put(skb, 2);
442 mgmt->u.deauth.reason_code = cpu_to_le16(reason);
443
444 ieee80211_sta_tx(sdata, skb, 0);
445}
446
447static void ieee80211_send_disassoc(struct ieee80211_sub_if_data *sdata,
448 struct ieee80211_if_sta *ifsta, u16 reason)
449{
450 struct ieee80211_local *local = sdata->local;
451 struct sk_buff *skb;
452 struct ieee80211_mgmt *mgmt;
453
454 skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt));
455 if (!skb) {
456 printk(KERN_DEBUG "%s: failed to allocate buffer for disassoc "
457 "frame\n", sdata->dev->name);
458 return;
459 }
460 skb_reserve(skb, local->hw.extra_tx_headroom);
461
462 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
463 memset(mgmt, 0, 24);
464 memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
465 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
466 memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
467 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
468 IEEE80211_STYPE_DISASSOC);
469 skb_put(skb, 2);
470 mgmt->u.disassoc.reason_code = cpu_to_le16(reason);
471
472 ieee80211_sta_tx(sdata, skb, 0);
473}
474
475static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid,
476 u8 dialog_token, u16 status, u16 policy,
477 u16 buf_size, u16 timeout)
478{
479 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
480 struct ieee80211_local *local = sdata->local;
481 struct sk_buff *skb;
482 struct ieee80211_mgmt *mgmt;
483 u16 capab;
484
485 skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom);
486
487 if (!skb) {
488 printk(KERN_DEBUG "%s: failed to allocate buffer "
489 "for addba resp frame\n", sdata->dev->name);
490 return;
491 }
492
493 skb_reserve(skb, local->hw.extra_tx_headroom);
494 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
495 memset(mgmt, 0, 24);
496 memcpy(mgmt->da, da, ETH_ALEN);
497 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
498 if (sdata->vif.type == IEEE80211_IF_TYPE_AP)
499 memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN);
500 else
501 memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
502 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
503 IEEE80211_STYPE_ACTION);
504
505 skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_resp));
506 mgmt->u.action.category = WLAN_CATEGORY_BACK;
507 mgmt->u.action.u.addba_resp.action_code = WLAN_ACTION_ADDBA_RESP;
508 mgmt->u.action.u.addba_resp.dialog_token = dialog_token;
509
510 capab = (u16)(policy << 1); /* bit 1 aggregation policy */
511 capab |= (u16)(tid << 2); /* bit 5:2 TID number */
512 capab |= (u16)(buf_size << 6); /* bit 15:6 max size of aggregation */
513
514 mgmt->u.action.u.addba_resp.capab = cpu_to_le16(capab);
515 mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout);
516 mgmt->u.action.u.addba_resp.status = cpu_to_le16(status);
517
518 ieee80211_sta_tx(sdata, skb, 0);
519}
520
521static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_data *sdata,
522 struct ieee80211_msrment_ie *request_ie,
523 const u8 *da, const u8 *bssid,
524 u8 dialog_token)
525{
526 struct ieee80211_local *local = sdata->local;
527 struct sk_buff *skb;
528 struct ieee80211_mgmt *msr_report;
529
530 skb = dev_alloc_skb(sizeof(*msr_report) + local->hw.extra_tx_headroom +
531 sizeof(struct ieee80211_msrment_ie));
532
533 if (!skb) {
534 printk(KERN_ERR "%s: failed to allocate buffer for "
535 "measurement report frame\n", sdata->dev->name);
536 return;
537 }
538
539 skb_reserve(skb, local->hw.extra_tx_headroom);
540 msr_report = (struct ieee80211_mgmt *)skb_put(skb, 24);
541 memset(msr_report, 0, 24);
542 memcpy(msr_report->da, da, ETH_ALEN);
543 memcpy(msr_report->sa, sdata->dev->dev_addr, ETH_ALEN);
544 memcpy(msr_report->bssid, bssid, ETH_ALEN);
545 msr_report->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
546 IEEE80211_STYPE_ACTION);
547
548 skb_put(skb, 1 + sizeof(msr_report->u.action.u.measurement));
549 msr_report->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT;
550 msr_report->u.action.u.measurement.action_code =
551 WLAN_ACTION_SPCT_MSR_RPRT;
552 msr_report->u.action.u.measurement.dialog_token = dialog_token;
553
554 msr_report->u.action.u.measurement.element_id = WLAN_EID_MEASURE_REPORT;
555 msr_report->u.action.u.measurement.length =
556 sizeof(struct ieee80211_msrment_ie);
557
558 memset(&msr_report->u.action.u.measurement.msr_elem, 0,
559 sizeof(struct ieee80211_msrment_ie));
560 msr_report->u.action.u.measurement.msr_elem.token = request_ie->token;
561 msr_report->u.action.u.measurement.msr_elem.mode |=
562 IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED;
563 msr_report->u.action.u.measurement.msr_elem.type = request_ie->type;
564
565 ieee80211_sta_tx(sdata, skb, 0);
566}
567
189/* MLME */ 568/* MLME */
190static void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, 569static void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata,
191 struct ieee80211_sta_bss *bss) 570 struct ieee80211_sta_bss *bss)
@@ -510,300 +889,6 @@ static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata,
510 mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT); 889 mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT);
511} 890}
512 891
513static int ieee80211_compatible_rates(struct ieee80211_sta_bss *bss,
514 struct ieee80211_supported_band *sband,
515 u64 *rates)
516{
517 int i, j, count;
518 *rates = 0;
519 count = 0;
520 for (i = 0; i < bss->supp_rates_len; i++) {
521 int rate = (bss->supp_rates[i] & 0x7F) * 5;
522
523 for (j = 0; j < sband->n_bitrates; j++)
524 if (sband->bitrates[j].bitrate == rate) {
525 *rates |= BIT(j);
526 count++;
527 break;
528 }
529 }
530
531 return count;
532}
533
534static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
535 struct ieee80211_if_sta *ifsta)
536{
537 struct ieee80211_local *local = sdata->local;
538 struct sk_buff *skb;
539 struct ieee80211_mgmt *mgmt;
540 u8 *pos, *ies, *ht_add_ie;
541 int i, len, count, rates_len, supp_rates_len;
542 u16 capab;
543 struct ieee80211_sta_bss *bss;
544 int wmm = 0;
545 struct ieee80211_supported_band *sband;
546 u64 rates = 0;
547
548 skb = dev_alloc_skb(local->hw.extra_tx_headroom +
549 sizeof(*mgmt) + 200 + ifsta->extra_ie_len +
550 ifsta->ssid_len);
551 if (!skb) {
552 printk(KERN_DEBUG "%s: failed to allocate buffer for assoc "
553 "frame\n", sdata->dev->name);
554 return;
555 }
556 skb_reserve(skb, local->hw.extra_tx_headroom);
557
558 sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
559
560 capab = ifsta->capab;
561
562 if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ) {
563 if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE))
564 capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
565 if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE))
566 capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
567 }
568
569 bss = ieee80211_rx_bss_get(local, ifsta->bssid,
570 local->hw.conf.channel->center_freq,
571 ifsta->ssid, ifsta->ssid_len);
572 if (bss) {
573 if (bss->capability & WLAN_CAPABILITY_PRIVACY)
574 capab |= WLAN_CAPABILITY_PRIVACY;
575 if (bss->wmm_used)
576 wmm = 1;
577
578 /* get all rates supported by the device and the AP as
579 * some APs don't like getting a superset of their rates
580 * in the association request (e.g. D-Link DAP 1353 in
581 * b-only mode) */
582 rates_len = ieee80211_compatible_rates(bss, sband, &rates);
583
584 if ((bss->capability & WLAN_CAPABILITY_SPECTRUM_MGMT) &&
585 (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT))
586 capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
587
588 ieee80211_rx_bss_put(local, bss);
589 } else {
590 rates = ~0;
591 rates_len = sband->n_bitrates;
592 }
593
594 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
595 memset(mgmt, 0, 24);
596 memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
597 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
598 memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
599
600 if (ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) {
601 skb_put(skb, 10);
602 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
603 IEEE80211_STYPE_REASSOC_REQ);
604 mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab);
605 mgmt->u.reassoc_req.listen_interval =
606 cpu_to_le16(local->hw.conf.listen_interval);
607 memcpy(mgmt->u.reassoc_req.current_ap, ifsta->prev_bssid,
608 ETH_ALEN);
609 } else {
610 skb_put(skb, 4);
611 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
612 IEEE80211_STYPE_ASSOC_REQ);
613 mgmt->u.assoc_req.capab_info = cpu_to_le16(capab);
614 mgmt->u.reassoc_req.listen_interval =
615 cpu_to_le16(local->hw.conf.listen_interval);
616 }
617
618 /* SSID */
619 ies = pos = skb_put(skb, 2 + ifsta->ssid_len);
620 *pos++ = WLAN_EID_SSID;
621 *pos++ = ifsta->ssid_len;
622 memcpy(pos, ifsta->ssid, ifsta->ssid_len);
623
624 /* add all rates which were marked to be used above */
625 supp_rates_len = rates_len;
626 if (supp_rates_len > 8)
627 supp_rates_len = 8;
628
629 len = sband->n_bitrates;
630 pos = skb_put(skb, supp_rates_len + 2);
631 *pos++ = WLAN_EID_SUPP_RATES;
632 *pos++ = supp_rates_len;
633
634 count = 0;
635 for (i = 0; i < sband->n_bitrates; i++) {
636 if (BIT(i) & rates) {
637 int rate = sband->bitrates[i].bitrate;
638 *pos++ = (u8) (rate / 5);
639 if (++count == 8)
640 break;
641 }
642 }
643
644 if (rates_len > count) {
645 pos = skb_put(skb, rates_len - count + 2);
646 *pos++ = WLAN_EID_EXT_SUPP_RATES;
647 *pos++ = rates_len - count;
648
649 for (i++; i < sband->n_bitrates; i++) {
650 if (BIT(i) & rates) {
651 int rate = sband->bitrates[i].bitrate;
652 *pos++ = (u8) (rate / 5);
653 }
654 }
655 }
656
657 if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT) {
658 /* 1. power capabilities */
659 pos = skb_put(skb, 4);
660 *pos++ = WLAN_EID_PWR_CAPABILITY;
661 *pos++ = 2;
662 *pos++ = 0; /* min tx power */
663 *pos++ = local->hw.conf.channel->max_power; /* max tx power */
664
665 /* 2. supported channels */
666 /* TODO: get this in reg domain format */
667 pos = skb_put(skb, 2 * sband->n_channels + 2);
668 *pos++ = WLAN_EID_SUPPORTED_CHANNELS;
669 *pos++ = 2 * sband->n_channels;
670 for (i = 0; i < sband->n_channels; i++) {
671 *pos++ = ieee80211_frequency_to_channel(
672 sband->channels[i].center_freq);
673 *pos++ = 1; /* one channel in the subband*/
674 }
675 }
676
677 if (ifsta->extra_ie) {
678 pos = skb_put(skb, ifsta->extra_ie_len);
679 memcpy(pos, ifsta->extra_ie, ifsta->extra_ie_len);
680 }
681
682 if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
683 pos = skb_put(skb, 9);
684 *pos++ = WLAN_EID_VENDOR_SPECIFIC;
685 *pos++ = 7; /* len */
686 *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */
687 *pos++ = 0x50;
688 *pos++ = 0xf2;
689 *pos++ = 2; /* WME */
690 *pos++ = 0; /* WME info */
691 *pos++ = 1; /* WME ver */
692 *pos++ = 0;
693 }
694
695 /* wmm support is a must to HT */
696 if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED) &&
697 sband->ht_info.ht_supported &&
698 (ht_add_ie = ieee80211_bss_get_ie(bss, WLAN_EID_HT_EXTRA_INFO))) {
699 struct ieee80211_ht_addt_info *ht_add_info =
700 (struct ieee80211_ht_addt_info *)ht_add_ie;
701 u16 cap = sband->ht_info.cap;
702 __le16 tmp;
703 u32 flags = local->hw.conf.channel->flags;
704
705 switch (ht_add_info->ht_param & IEEE80211_HT_IE_CHA_SEC_OFFSET) {
706 case IEEE80211_HT_IE_CHA_SEC_ABOVE:
707 if (flags & IEEE80211_CHAN_NO_FAT_ABOVE) {
708 cap &= ~IEEE80211_HT_CAP_SUP_WIDTH;
709 cap &= ~IEEE80211_HT_CAP_SGI_40;
710 }
711 break;
712 case IEEE80211_HT_IE_CHA_SEC_BELOW:
713 if (flags & IEEE80211_CHAN_NO_FAT_BELOW) {
714 cap &= ~IEEE80211_HT_CAP_SUP_WIDTH;
715 cap &= ~IEEE80211_HT_CAP_SGI_40;
716 }
717 break;
718 }
719
720 tmp = cpu_to_le16(cap);
721 pos = skb_put(skb, sizeof(struct ieee80211_ht_cap)+2);
722 *pos++ = WLAN_EID_HT_CAPABILITY;
723 *pos++ = sizeof(struct ieee80211_ht_cap);
724 memset(pos, 0, sizeof(struct ieee80211_ht_cap));
725 memcpy(pos, &tmp, sizeof(u16));
726 pos += sizeof(u16);
727 /* TODO: needs a define here for << 2 */
728 *pos++ = sband->ht_info.ampdu_factor |
729 (sband->ht_info.ampdu_density << 2);
730 memcpy(pos, sband->ht_info.supp_mcs_set, 16);
731 }
732
733 kfree(ifsta->assocreq_ies);
734 ifsta->assocreq_ies_len = (skb->data + skb->len) - ies;
735 ifsta->assocreq_ies = kmalloc(ifsta->assocreq_ies_len, GFP_KERNEL);
736 if (ifsta->assocreq_ies)
737 memcpy(ifsta->assocreq_ies, ies, ifsta->assocreq_ies_len);
738
739 ieee80211_sta_tx(sdata, skb, 0);
740}
741
742
743static void ieee80211_send_deauth(struct ieee80211_sub_if_data *sdata,
744 struct ieee80211_if_sta *ifsta, u16 reason)
745{
746 struct ieee80211_local *local = sdata->local;
747 struct sk_buff *skb;
748 struct ieee80211_mgmt *mgmt;
749
750 skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt));
751 if (!skb) {
752 printk(KERN_DEBUG "%s: failed to allocate buffer for deauth "
753 "frame\n", sdata->dev->name);
754 return;
755 }
756 skb_reserve(skb, local->hw.extra_tx_headroom);
757
758 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
759 memset(mgmt, 0, 24);
760 memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
761 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
762 memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
763 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
764 IEEE80211_STYPE_DEAUTH);
765 skb_put(skb, 2);
766 mgmt->u.deauth.reason_code = cpu_to_le16(reason);
767
768 ieee80211_sta_tx(sdata, skb, 0);
769}
770
771static int ieee80211_sta_wep_configured(struct ieee80211_sub_if_data *sdata)
772{
773 if (!sdata || !sdata->default_key ||
774 sdata->default_key->conf.alg != ALG_WEP)
775 return 0;
776 return 1;
777}
778
779static void ieee80211_send_disassoc(struct ieee80211_sub_if_data *sdata,
780 struct ieee80211_if_sta *ifsta, u16 reason)
781{
782 struct ieee80211_local *local = sdata->local;
783 struct sk_buff *skb;
784 struct ieee80211_mgmt *mgmt;
785
786 skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt));
787 if (!skb) {
788 printk(KERN_DEBUG "%s: failed to allocate buffer for disassoc "
789 "frame\n", sdata->dev->name);
790 return;
791 }
792 skb_reserve(skb, local->hw.extra_tx_headroom);
793
794 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
795 memset(mgmt, 0, 24);
796 memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
797 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
798 memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
799 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
800 IEEE80211_STYPE_DISASSOC);
801 skb_put(skb, 2);
802 mgmt->u.disassoc.reason_code = cpu_to_le16(reason);
803
804 ieee80211_sta_tx(sdata, skb, 0);
805}
806
807static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, 892static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
808 struct ieee80211_if_sta *ifsta, bool deauth, 893 struct ieee80211_if_sta *ifsta, bool deauth,
809 bool self_disconnected, u16 reason) 894 bool self_disconnected, u16 reason)
@@ -864,6 +949,14 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
864 sta_info_destroy(sta); 949 sta_info_destroy(sta);
865} 950}
866 951
952static int ieee80211_sta_wep_configured(struct ieee80211_sub_if_data *sdata)
953{
954 if (!sdata || !sdata->default_key ||
955 sdata->default_key->conf.alg != ALG_WEP)
956 return 0;
957 return 1;
958}
959
867static int ieee80211_privacy_mismatch(struct ieee80211_sub_if_data *sdata, 960static int ieee80211_privacy_mismatch(struct ieee80211_sub_if_data *sdata,
868 struct ieee80211_if_sta *ifsta) 961 struct ieee80211_if_sta *ifsta)
869{ 962{
@@ -1009,54 +1102,6 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
1009 elems.challenge_len + 2, 1); 1102 elems.challenge_len + 2, 1);
1010} 1103}
1011 1104
1012static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid,
1013 u8 dialog_token, u16 status, u16 policy,
1014 u16 buf_size, u16 timeout)
1015{
1016 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
1017 struct ieee80211_local *local = sdata->local;
1018 struct sk_buff *skb;
1019 struct ieee80211_mgmt *mgmt;
1020 u16 capab;
1021
1022 skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom);
1023
1024 if (!skb) {
1025 printk(KERN_DEBUG "%s: failed to allocate buffer "
1026 "for addba resp frame\n", sdata->dev->name);
1027 return;
1028 }
1029
1030 skb_reserve(skb, local->hw.extra_tx_headroom);
1031 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
1032 memset(mgmt, 0, 24);
1033 memcpy(mgmt->da, da, ETH_ALEN);
1034 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
1035 if (sdata->vif.type == IEEE80211_IF_TYPE_AP)
1036 memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN);
1037 else
1038 memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
1039 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
1040 IEEE80211_STYPE_ACTION);
1041
1042 skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_resp));
1043 mgmt->u.action.category = WLAN_CATEGORY_BACK;
1044 mgmt->u.action.u.addba_resp.action_code = WLAN_ACTION_ADDBA_RESP;
1045 mgmt->u.action.u.addba_resp.dialog_token = dialog_token;
1046
1047 capab = (u16)(policy << 1); /* bit 1 aggregation policy */
1048 capab |= (u16)(tid << 2); /* bit 5:2 TID number */
1049 capab |= (u16)(buf_size << 6); /* bit 15:6 max size of aggregation */
1050
1051 mgmt->u.action.u.addba_resp.capab = cpu_to_le16(capab);
1052 mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout);
1053 mgmt->u.action.u.addba_resp.status = cpu_to_le16(status);
1054
1055 ieee80211_sta_tx(sdata, skb, 0);
1056
1057 return;
1058}
1059
1060/* 1105/*
1061 * After accepting the AddBA Request we activated a timer, 1106 * After accepting the AddBA Request we activated a timer,
1062 * resetting it after each frame that arrives from the originator. 1107 * resetting it after each frame that arrives from the originator.
@@ -1329,53 +1374,6 @@ static void ieee80211_sta_process_delba(struct ieee80211_sub_if_data *sdata,
1329 rcu_read_unlock(); 1374 rcu_read_unlock();
1330} 1375}
1331 1376
1332static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_data *sdata,
1333 struct ieee80211_msrment_ie *request_ie,
1334 const u8 *da, const u8 *bssid,
1335 u8 dialog_token)
1336{
1337 struct ieee80211_local *local = sdata->local;
1338 struct sk_buff *skb;
1339 struct ieee80211_mgmt *msr_report;
1340
1341 skb = dev_alloc_skb(sizeof(*msr_report) + local->hw.extra_tx_headroom +
1342 sizeof(struct ieee80211_msrment_ie));
1343
1344 if (!skb) {
1345 printk(KERN_ERR "%s: failed to allocate buffer for "
1346 "measurement report frame\n", sdata->dev->name);
1347 return;
1348 }
1349
1350 skb_reserve(skb, local->hw.extra_tx_headroom);
1351 msr_report = (struct ieee80211_mgmt *)skb_put(skb, 24);
1352 memset(msr_report, 0, 24);
1353 memcpy(msr_report->da, da, ETH_ALEN);
1354 memcpy(msr_report->sa, sdata->dev->dev_addr, ETH_ALEN);
1355 memcpy(msr_report->bssid, bssid, ETH_ALEN);
1356 msr_report->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
1357 IEEE80211_STYPE_ACTION);
1358
1359 skb_put(skb, 1 + sizeof(msr_report->u.action.u.measurement));
1360 msr_report->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT;
1361 msr_report->u.action.u.measurement.action_code =
1362 WLAN_ACTION_SPCT_MSR_RPRT;
1363 msr_report->u.action.u.measurement.dialog_token = dialog_token;
1364
1365 msr_report->u.action.u.measurement.element_id = WLAN_EID_MEASURE_REPORT;
1366 msr_report->u.action.u.measurement.length =
1367 sizeof(struct ieee80211_msrment_ie);
1368
1369 memset(&msr_report->u.action.u.measurement.msr_elem, 0,
1370 sizeof(struct ieee80211_msrment_ie));
1371 msr_report->u.action.u.measurement.msr_elem.token = request_ie->token;
1372 msr_report->u.action.u.measurement.msr_elem.mode |=
1373 IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED;
1374 msr_report->u.action.u.measurement.msr_elem.type = request_ie->type;
1375
1376 ieee80211_sta_tx(sdata, skb, 0);
1377}
1378
1379static void ieee80211_sta_process_measurement_req(struct ieee80211_sub_if_data *sdata, 1377static void ieee80211_sta_process_measurement_req(struct ieee80211_sub_if_data *sdata,
1380 struct ieee80211_mgmt *mgmt, 1378 struct ieee80211_mgmt *mgmt,
1381 size_t len) 1379 size_t len)