aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-09-09 04:57:09 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-09-11 15:53:38 -0400
commit9ac19a9084001695479a6d6dd67443cc5fb1df2f (patch)
tree404a4a2b16235bb575dc366c2cc87b9f65d79cc5
parentb079ada7dd11cf82c3157a51c205c3d88321c704 (diff)
mac80211: reorder frame code in mlme
This reorders all frame sending functions to be at the top of the file. When reading the file, I tend to be looking at either the frame code or the state machine, and having them mixed in the file is confusing. When all frame sending is at the top the remainder of the file is more readable, in my opinion. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-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)