aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c144
1 files changed, 97 insertions, 47 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index bdaab1391d4e..6b75cb6c6300 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -350,14 +350,12 @@ static void ieee80211_sta_wmm_params(struct net_device *dev,
350 } 350 }
351} 351}
352 352
353 353static u32 ieee80211_handle_protect_preamb(struct ieee80211_sub_if_data *sdata,
354static u32 ieee80211_handle_erp_ie(struct ieee80211_sub_if_data *sdata, 354 bool use_protection,
355 u8 erp_value) 355 bool use_short_preamble)
356{ 356{
357 struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf; 357 struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf;
358 struct ieee80211_if_sta *ifsta = &sdata->u.sta; 358 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
359 bool use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0;
360 bool use_short_preamble = (erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0;
361 DECLARE_MAC_BUF(mac); 359 DECLARE_MAC_BUF(mac);
362 u32 changed = 0; 360 u32 changed = 0;
363 361
@@ -388,6 +386,32 @@ static u32 ieee80211_handle_erp_ie(struct ieee80211_sub_if_data *sdata,
388 return changed; 386 return changed;
389} 387}
390 388
389static u32 ieee80211_handle_erp_ie(struct ieee80211_sub_if_data *sdata,
390 u8 erp_value)
391{
392 bool use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0;
393 bool use_short_preamble = (erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0;
394
395 return ieee80211_handle_protect_preamb(sdata,
396 use_protection, use_short_preamble);
397}
398
399static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
400 struct ieee80211_sta_bss *bss)
401{
402 u32 changed = 0;
403
404 if (bss->has_erp_value)
405 changed |= ieee80211_handle_erp_ie(sdata, bss->erp_value);
406 else {
407 u16 capab = bss->capability;
408 changed |= ieee80211_handle_protect_preamb(sdata, false,
409 (capab & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0);
410 }
411
412 return changed;
413}
414
391int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie, 415int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie,
392 struct ieee80211_ht_info *ht_info) 416 struct ieee80211_ht_info *ht_info)
393{ 417{
@@ -511,9 +535,7 @@ static void ieee80211_set_associated(struct net_device *dev,
511 sdata->bss_conf.beacon_int = bss->beacon_int; 535 sdata->bss_conf.beacon_int = bss->beacon_int;
512 sdata->bss_conf.timestamp = bss->timestamp; 536 sdata->bss_conf.timestamp = bss->timestamp;
513 537
514 if (bss->has_erp_value) 538 changed |= ieee80211_handle_bss_capability(sdata, bss);
515 changed |= ieee80211_handle_erp_ie(
516 sdata, bss->erp_value);
517 539
518 ieee80211_rx_bss_put(dev, bss); 540 ieee80211_rx_bss_put(dev, bss);
519 } 541 }
@@ -2566,22 +2588,29 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
2566#endif 2588#endif
2567 } 2589 }
2568 2590
2569 bss->band = rx_status->band;
2570
2571 if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
2572 bss->probe_resp && beacon) {
2573 /* STA mode:
2574 * Do not allow beacon to override data from Probe Response. */
2575 ieee80211_rx_bss_put(dev, bss);
2576 return;
2577 }
2578
2579 /* save the ERP value so that it is available at association time */ 2591 /* save the ERP value so that it is available at association time */
2580 if (elems.erp_info && elems.erp_info_len >= 1) { 2592 if (elems.erp_info && elems.erp_info_len >= 1) {
2581 bss->erp_value = elems.erp_info[0]; 2593 bss->erp_value = elems.erp_info[0];
2582 bss->has_erp_value = 1; 2594 bss->has_erp_value = 1;
2583 } 2595 }
2584 2596
2597 if (elems.ht_cap_elem &&
2598 (!bss->ht_ie || bss->ht_ie_len != elems.ht_cap_elem_len ||
2599 memcmp(bss->ht_ie, elems.ht_cap_elem, elems.ht_cap_elem_len))) {
2600 kfree(bss->ht_ie);
2601 bss->ht_ie = kmalloc(elems.ht_cap_elem_len + 2, GFP_ATOMIC);
2602 if (bss->ht_ie) {
2603 memcpy(bss->ht_ie, elems.ht_cap_elem - 2,
2604 elems.ht_cap_elem_len + 2);
2605 bss->ht_ie_len = elems.ht_cap_elem_len + 2;
2606 } else
2607 bss->ht_ie_len = 0;
2608 } else if (!elems.ht_cap_elem && bss->ht_ie) {
2609 kfree(bss->ht_ie);
2610 bss->ht_ie = NULL;
2611 bss->ht_ie_len = 0;
2612 }
2613
2585 bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); 2614 bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int);
2586 bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); 2615 bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info);
2587 2616
@@ -2603,6 +2632,26 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
2603 bss->supp_rates_len += clen; 2632 bss->supp_rates_len += clen;
2604 } 2633 }
2605 2634
2635 bss->band = rx_status->band;
2636
2637 bss->timestamp = beacon_timestamp;
2638 bss->last_update = jiffies;
2639 bss->rssi = rx_status->ssi;
2640 bss->signal = rx_status->signal;
2641 bss->noise = rx_status->noise;
2642 if (!beacon && !bss->probe_resp)
2643 bss->probe_resp = true;
2644
2645 /*
2646 * In STA mode, the remaining parameters should not be overridden
2647 * by beacons because they're not necessarily accurate there.
2648 */
2649 if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
2650 bss->probe_resp && beacon) {
2651 ieee80211_rx_bss_put(dev, bss);
2652 return;
2653 }
2654
2606 if (elems.wpa && 2655 if (elems.wpa &&
2607 (!bss->wpa_ie || bss->wpa_ie_len != elems.wpa_len || 2656 (!bss->wpa_ie || bss->wpa_ie_len != elems.wpa_len ||
2608 memcmp(bss->wpa_ie, elems.wpa, elems.wpa_len))) { 2657 memcmp(bss->wpa_ie, elems.wpa, elems.wpa_len))) {
@@ -2635,6 +2684,20 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
2635 bss->rsn_ie_len = 0; 2684 bss->rsn_ie_len = 0;
2636 } 2685 }
2637 2686
2687 /*
2688 * Cf.
2689 * http://www.wipo.int/pctdb/en/wo.jsp?wo=2007047181&IA=WO2007047181&DISPLAY=DESC
2690 *
2691 * quoting:
2692 *
2693 * In particular, "Wi-Fi CERTIFIED for WMM - Support for Multimedia
2694 * Applications with Quality of Service in Wi-Fi Networks," Wi- Fi
2695 * Alliance (September 1, 2004) is incorporated by reference herein.
2696 * The inclusion of the WMM Parameters in probe responses and
2697 * association responses is mandatory for WMM enabled networks. The
2698 * inclusion of the WMM Parameters in beacons, however, is optional.
2699 */
2700
2638 if (elems.wmm_param && 2701 if (elems.wmm_param &&
2639 (!bss->wmm_ie || bss->wmm_ie_len != elems.wmm_param_len || 2702 (!bss->wmm_ie || bss->wmm_ie_len != elems.wmm_param_len ||
2640 memcmp(bss->wmm_ie, elems.wmm_param, elems.wmm_param_len))) { 2703 memcmp(bss->wmm_ie, elems.wmm_param, elems.wmm_param_len))) {
@@ -2651,30 +2714,6 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
2651 bss->wmm_ie = NULL; 2714 bss->wmm_ie = NULL;
2652 bss->wmm_ie_len = 0; 2715 bss->wmm_ie_len = 0;
2653 } 2716 }
2654 if (elems.ht_cap_elem &&
2655 (!bss->ht_ie || bss->ht_ie_len != elems.ht_cap_elem_len ||
2656 memcmp(bss->ht_ie, elems.ht_cap_elem, elems.ht_cap_elem_len))) {
2657 kfree(bss->ht_ie);
2658 bss->ht_ie = kmalloc(elems.ht_cap_elem_len + 2, GFP_ATOMIC);
2659 if (bss->ht_ie) {
2660 memcpy(bss->ht_ie, elems.ht_cap_elem - 2,
2661 elems.ht_cap_elem_len + 2);
2662 bss->ht_ie_len = elems.ht_cap_elem_len + 2;
2663 } else
2664 bss->ht_ie_len = 0;
2665 } else if (!elems.ht_cap_elem && bss->ht_ie) {
2666 kfree(bss->ht_ie);
2667 bss->ht_ie = NULL;
2668 bss->ht_ie_len = 0;
2669 }
2670
2671 bss->timestamp = beacon_timestamp;
2672 bss->last_update = jiffies;
2673 bss->rssi = rx_status->ssi;
2674 bss->signal = rx_status->signal;
2675 bss->noise = rx_status->noise;
2676 if (!beacon)
2677 bss->probe_resp++;
2678 2717
2679 /* check if we need to merge IBSS */ 2718 /* check if we need to merge IBSS */
2680 if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && beacon && 2719 if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && beacon &&
@@ -2775,8 +2814,24 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
2775 2814
2776 ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems); 2815 ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
2777 2816
2817 if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
2818 ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,
2819 elems.wmm_param_len);
2820 }
2821
2822 /* Do not send changes to driver if we are scanning. This removes
2823 * requirement that driver's bss_info_changed function needs to be
2824 * atomic. */
2825 if (local->sta_sw_scanning || local->sta_hw_scanning)
2826 return;
2827
2778 if (elems.erp_info && elems.erp_info_len >= 1) 2828 if (elems.erp_info && elems.erp_info_len >= 1)
2779 changed |= ieee80211_handle_erp_ie(sdata, elems.erp_info[0]); 2829 changed |= ieee80211_handle_erp_ie(sdata, elems.erp_info[0]);
2830 else {
2831 u16 capab = le16_to_cpu(mgmt->u.beacon.capab_info);
2832 changed |= ieee80211_handle_protect_preamb(sdata, false,
2833 (capab & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0);
2834 }
2780 2835
2781 if (elems.ht_cap_elem && elems.ht_info_elem && 2836 if (elems.ht_cap_elem && elems.ht_info_elem &&
2782 elems.wmm_param && conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { 2837 elems.wmm_param && conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
@@ -2789,11 +2844,6 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
2789 &bss_info); 2844 &bss_info);
2790 } 2845 }
2791 2846
2792 if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
2793 ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,
2794 elems.wmm_param_len);
2795 }
2796
2797 ieee80211_bss_info_change_notify(sdata, changed); 2847 ieee80211_bss_info_change_notify(sdata, changed);
2798} 2848}
2799 2849