summaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
authorSara Sharon <sara.sharon@intel.com>2019-01-16 11:22:56 -0500
committerJohannes Berg <johannes.berg@intel.com>2019-02-08 07:56:37 -0500
commit78ac51f81532c1e361a31ac112c1fea470ea9036 (patch)
tree902a6460da1d4ee980bba2220151b931b520a6a9 /net/mac80211/mlme.c
parent0cd01efb03396c5368b1a32eed0ccb2aa453bdc8 (diff)
mac80211: support multi-bssid
Add support for multi-bssid. This includes: - Parsing multi-bssid element - Overriding DTIM values - Taking into account in various places the inner BSSID instead of transmitter BSSID - Save aside some multi-bssid properties needed by drivers Signed-off-by: Sara Sharon <sara.sharon@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c125
1 files changed, 88 insertions, 37 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 1f41f760bd22..64b6ddb67456 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3308,6 +3308,14 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
3308 /* TODO: OPEN: what happens if BSS color disable is set? */ 3308 /* TODO: OPEN: what happens if BSS color disable is set? */
3309 } 3309 }
3310 3310
3311 if (cbss->transmitted_bss) {
3312 bss_conf->nontransmitted = true;
3313 ether_addr_copy(bss_conf->transmitter_bssid,
3314 cbss->transmitted_bss->bssid);
3315 bss_conf->bssid_indicator = cbss->max_bssid_indicator;
3316 bss_conf->bssid_index = cbss->bssid_index;
3317 }
3318
3311 /* 3319 /*
3312 * Some APs, e.g. Netgear WNDR3700, report invalid HT operation data 3320 * Some APs, e.g. Netgear WNDR3700, report invalid HT operation data
3313 * in their association response, so ignore that data for our own 3321 * in their association response, so ignore that data for our own
@@ -3692,6 +3700,16 @@ static void ieee80211_handle_beacon_sig(struct ieee80211_sub_if_data *sdata,
3692 } 3700 }
3693} 3701}
3694 3702
3703static bool ieee80211_rx_our_beacon(const u8 *tx_bssid,
3704 struct cfg80211_bss *bss)
3705{
3706 if (ether_addr_equal(tx_bssid, bss->bssid))
3707 return true;
3708 if (!bss->transmitted_bss)
3709 return false;
3710 return ether_addr_equal(tx_bssid, bss->transmitted_bss->bssid);
3711}
3712
3695static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, 3713static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
3696 struct ieee80211_mgmt *mgmt, size_t len, 3714 struct ieee80211_mgmt *mgmt, size_t len,
3697 struct ieee80211_rx_status *rx_status) 3715 struct ieee80211_rx_status *rx_status)
@@ -3733,17 +3751,16 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
3733 rcu_read_unlock(); 3751 rcu_read_unlock();
3734 3752
3735 if (ifmgd->assoc_data && ifmgd->assoc_data->need_beacon && 3753 if (ifmgd->assoc_data && ifmgd->assoc_data->need_beacon &&
3736 ether_addr_equal(mgmt->bssid, ifmgd->assoc_data->bss->bssid)) { 3754 ieee80211_rx_our_beacon(mgmt->bssid, ifmgd->assoc_data->bss)) {
3737 ieee802_11_parse_elems(mgmt->u.beacon.variable, 3755 ieee802_11_parse_elems(mgmt->u.beacon.variable,
3738 len - baselen, false, &elems, 3756 len - baselen, false, &elems,
3739 mgmt->bssid, 3757 mgmt->bssid,
3740 ifmgd->assoc_data->bss->bssid); 3758 ifmgd->assoc_data->bss->bssid);
3741 3759
3742 ieee80211_rx_bss_info(sdata, mgmt, len, rx_status); 3760 ieee80211_rx_bss_info(sdata, mgmt, len, rx_status);
3743 if (elems.tim && !elems.parse_error) { 3761
3744 const struct ieee80211_tim_ie *tim_ie = elems.tim; 3762 if (elems.dtim_period)
3745 ifmgd->dtim_period = tim_ie->dtim_period; 3763 ifmgd->dtim_period = elems.dtim_period;
3746 }
3747 ifmgd->have_beacon = true; 3764 ifmgd->have_beacon = true;
3748 ifmgd->assoc_data->need_beacon = false; 3765 ifmgd->assoc_data->need_beacon = false;
3749 if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY)) { 3766 if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY)) {
@@ -3751,12 +3768,17 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
3751 le64_to_cpu(mgmt->u.beacon.timestamp); 3768 le64_to_cpu(mgmt->u.beacon.timestamp);
3752 sdata->vif.bss_conf.sync_device_ts = 3769 sdata->vif.bss_conf.sync_device_ts =
3753 rx_status->device_timestamp; 3770 rx_status->device_timestamp;
3754 if (elems.tim) 3771 sdata->vif.bss_conf.sync_dtim_count = elems.dtim_count;
3755 sdata->vif.bss_conf.sync_dtim_count =
3756 elems.tim->dtim_count;
3757 else
3758 sdata->vif.bss_conf.sync_dtim_count = 0;
3759 } 3772 }
3773
3774 if (elems.mbssid_config_ie)
3775 bss_conf->profile_periodicity =
3776 elems.mbssid_config_ie->profile_periodicity;
3777
3778 if (elems.ext_capab_len >= 11 &&
3779 (elems.ext_capab[10] & WLAN_EXT_CAPA11_EMA_SUPPORT))
3780 bss_conf->ema_ap = true;
3781
3760 /* continue assoc process */ 3782 /* continue assoc process */
3761 ifmgd->assoc_data->timeout = jiffies; 3783 ifmgd->assoc_data->timeout = jiffies;
3762 ifmgd->assoc_data->timeout_started = true; 3784 ifmgd->assoc_data->timeout_started = true;
@@ -3765,7 +3787,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
3765 } 3787 }
3766 3788
3767 if (!ifmgd->associated || 3789 if (!ifmgd->associated ||
3768 !ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid)) 3790 !ieee80211_rx_our_beacon(mgmt->bssid, ifmgd->associated))
3769 return; 3791 return;
3770 bssid = ifmgd->associated->bssid; 3792 bssid = ifmgd->associated->bssid;
3771 3793
@@ -3861,11 +3883,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
3861 le64_to_cpu(mgmt->u.beacon.timestamp); 3883 le64_to_cpu(mgmt->u.beacon.timestamp);
3862 sdata->vif.bss_conf.sync_device_ts = 3884 sdata->vif.bss_conf.sync_device_ts =
3863 rx_status->device_timestamp; 3885 rx_status->device_timestamp;
3864 if (elems.tim) 3886 sdata->vif.bss_conf.sync_dtim_count = elems.dtim_count;
3865 sdata->vif.bss_conf.sync_dtim_count =
3866 elems.tim->dtim_count;
3867 else
3868 sdata->vif.bss_conf.sync_dtim_count = 0;
3869 } 3887 }
3870 3888
3871 if (ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid) 3889 if (ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid)
@@ -3891,10 +3909,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
3891 */ 3909 */
3892 if (!ifmgd->have_beacon) { 3910 if (!ifmgd->have_beacon) {
3893 /* a few bogus AP send dtim_period = 0 or no TIM IE */ 3911 /* a few bogus AP send dtim_period = 0 or no TIM IE */
3894 if (elems.tim) 3912 bss_conf->dtim_period = elems.dtim_period ?: 1;
3895 bss_conf->dtim_period = elems.tim->dtim_period ?: 1;
3896 else
3897 bss_conf->dtim_period = 1;
3898 3913
3899 changed |= BSS_CHANGED_BEACON_INFO; 3914 changed |= BSS_CHANGED_BEACON_INFO;
3900 ifmgd->have_beacon = true; 3915 ifmgd->have_beacon = true;
@@ -4761,6 +4776,40 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
4761 return ret; 4776 return ret;
4762} 4777}
4763 4778
4779static bool ieee80211_get_dtim(const struct cfg80211_bss_ies *ies,
4780 u8 *dtim_count, u8 *dtim_period)
4781{
4782 const u8 *tim_ie = cfg80211_find_ie(WLAN_EID_TIM, ies->data, ies->len);
4783 const u8 *idx_ie = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX, ies->data,
4784 ies->len);
4785 const struct ieee80211_tim_ie *tim = NULL;
4786 const struct ieee80211_bssid_index *idx;
4787 bool valid = tim_ie && tim_ie[1] >= 2;
4788
4789 if (valid)
4790 tim = (void *)(tim_ie + 2);
4791
4792 if (dtim_count)
4793 *dtim_count = valid ? tim->dtim_count : 0;
4794
4795 if (dtim_period)
4796 *dtim_period = valid ? tim->dtim_period : 0;
4797
4798 /* Check if value is overridden by non-transmitted profile */
4799 if (!idx_ie || idx_ie[1] < 3)
4800 return valid;
4801
4802 idx = (void *)(idx_ie + 2);
4803
4804 if (dtim_count)
4805 *dtim_count = idx->dtim_count;
4806
4807 if (dtim_period)
4808 *dtim_period = idx->dtim_period;
4809
4810 return true;
4811}
4812
4764static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, 4813static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
4765 struct cfg80211_bss *cbss, bool assoc, 4814 struct cfg80211_bss *cbss, bool assoc,
4766 bool override) 4815 bool override)
@@ -4852,17 +4901,13 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
4852 rcu_read_lock(); 4901 rcu_read_lock();
4853 ies = rcu_dereference(cbss->beacon_ies); 4902 ies = rcu_dereference(cbss->beacon_ies);
4854 if (ies) { 4903 if (ies) {
4855 const u8 *tim_ie;
4856
4857 sdata->vif.bss_conf.sync_tsf = ies->tsf; 4904 sdata->vif.bss_conf.sync_tsf = ies->tsf;
4858 sdata->vif.bss_conf.sync_device_ts = 4905 sdata->vif.bss_conf.sync_device_ts =
4859 bss->device_ts_beacon; 4906 bss->device_ts_beacon;
4860 tim_ie = cfg80211_find_ie(WLAN_EID_TIM, 4907
4861 ies->data, ies->len); 4908 ieee80211_get_dtim(ies,
4862 if (tim_ie && tim_ie[1] >= 2) 4909 &sdata->vif.bss_conf.sync_dtim_count,
4863 sdata->vif.bss_conf.sync_dtim_count = tim_ie[2]; 4910 NULL);
4864 else
4865 sdata->vif.bss_conf.sync_dtim_count = 0;
4866 } else if (!ieee80211_hw_check(&sdata->local->hw, 4911 } else if (!ieee80211_hw_check(&sdata->local->hw,
4867 TIMING_BEACON_ONLY)) { 4912 TIMING_BEACON_ONLY)) {
4868 ies = rcu_dereference(cbss->proberesp_ies); 4913 ies = rcu_dereference(cbss->proberesp_ies);
@@ -5332,17 +5377,12 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
5332 assoc_data->timeout_started = true; 5377 assoc_data->timeout_started = true;
5333 assoc_data->need_beacon = true; 5378 assoc_data->need_beacon = true;
5334 } else if (beacon_ies) { 5379 } else if (beacon_ies) {
5335 const u8 *tim_ie = cfg80211_find_ie(WLAN_EID_TIM, 5380 const u8 *ie;
5336 beacon_ies->data,
5337 beacon_ies->len);
5338 u8 dtim_count = 0; 5381 u8 dtim_count = 0;
5339 5382
5340 if (tim_ie && tim_ie[1] >= sizeof(struct ieee80211_tim_ie)) { 5383 ieee80211_get_dtim(beacon_ies, &dtim_count,
5341 const struct ieee80211_tim_ie *tim; 5384 &ifmgd->dtim_period);
5342 tim = (void *)(tim_ie + 2); 5385
5343 ifmgd->dtim_period = tim->dtim_period;
5344 dtim_count = tim->dtim_count;
5345 }
5346 ifmgd->have_beacon = true; 5386 ifmgd->have_beacon = true;
5347 assoc_data->timeout = jiffies; 5387 assoc_data->timeout = jiffies;
5348 assoc_data->timeout_started = true; 5388 assoc_data->timeout_started = true;
@@ -5353,6 +5393,17 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
5353 bss->device_ts_beacon; 5393 bss->device_ts_beacon;
5354 sdata->vif.bss_conf.sync_dtim_count = dtim_count; 5394 sdata->vif.bss_conf.sync_dtim_count = dtim_count;
5355 } 5395 }
5396
5397 ie = cfg80211_find_ext_ie(WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION,
5398 beacon_ies->data, beacon_ies->len);
5399 if (ie && ie[1] >= 3)
5400 sdata->vif.bss_conf.profile_periodicity = ie[4];
5401
5402 ie = cfg80211_find_ie(WLAN_EID_EXT_CAPABILITY,
5403 beacon_ies->data, beacon_ies->len);
5404 if (ie && ie[1] >= 11 &&
5405 (ie[10] & WLAN_EXT_CAPA11_EMA_SUPPORT))
5406 sdata->vif.bss_conf.ema_ap = true;
5356 } else { 5407 } else {
5357 assoc_data->timeout = jiffies; 5408 assoc_data->timeout = jiffies;
5358 assoc_data->timeout_started = true; 5409 assoc_data->timeout_started = true;