aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/scan.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/scan.c')
-rw-r--r--net/mac80211/scan.c160
1 files changed, 91 insertions, 69 deletions
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 95413413f98c..0cf066700623 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -8,6 +8,7 @@
* Copyright 2007, Michael Wu <flamingice@sourmilk.net>
* Copyright 2013-2015 Intel Mobile Communications GmbH
* Copyright 2016-2017 Intel Deutschland GmbH
+ * Copyright (C) 2018-2019 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -57,62 +58,14 @@ static bool is_uapsd_supported(struct ieee802_11_elems *elems)
return qos_info & IEEE80211_WMM_IE_AP_QOSINFO_UAPSD;
}
-struct ieee80211_bss *
-ieee80211_bss_info_update(struct ieee80211_local *local,
- struct ieee80211_rx_status *rx_status,
- struct ieee80211_mgmt *mgmt, size_t len,
- struct ieee802_11_elems *elems,
- struct ieee80211_channel *channel)
+static void
+ieee80211_update_bss_from_elems(struct ieee80211_local *local,
+ struct ieee80211_bss *bss,
+ struct ieee802_11_elems *elems,
+ struct ieee80211_rx_status *rx_status,
+ bool beacon)
{
- bool beacon = ieee80211_is_beacon(mgmt->frame_control);
- struct cfg80211_bss *cbss;
- struct ieee80211_bss *bss;
int clen, srlen;
- struct cfg80211_inform_bss bss_meta = {
- .boottime_ns = rx_status->boottime_ns,
- };
- bool signal_valid;
- struct ieee80211_sub_if_data *scan_sdata;
-
- if (rx_status->flag & RX_FLAG_NO_SIGNAL_VAL)
- bss_meta.signal = 0; /* invalid signal indication */
- else if (ieee80211_hw_check(&local->hw, SIGNAL_DBM))
- bss_meta.signal = rx_status->signal * 100;
- else if (ieee80211_hw_check(&local->hw, SIGNAL_UNSPEC))
- bss_meta.signal = (rx_status->signal * 100) / local->hw.max_signal;
-
- bss_meta.scan_width = NL80211_BSS_CHAN_WIDTH_20;
- if (rx_status->bw == RATE_INFO_BW_5)
- bss_meta.scan_width = NL80211_BSS_CHAN_WIDTH_5;
- else if (rx_status->bw == RATE_INFO_BW_10)
- bss_meta.scan_width = NL80211_BSS_CHAN_WIDTH_10;
-
- bss_meta.chan = channel;
-
- rcu_read_lock();
- scan_sdata = rcu_dereference(local->scan_sdata);
- if (scan_sdata && scan_sdata->vif.type == NL80211_IFTYPE_STATION &&
- scan_sdata->vif.bss_conf.assoc &&
- ieee80211_have_rx_timestamp(rx_status)) {
- bss_meta.parent_tsf =
- ieee80211_calculate_rx_timestamp(local, rx_status,
- len + FCS_LEN, 24);
- ether_addr_copy(bss_meta.parent_bssid,
- scan_sdata->vif.bss_conf.bssid);
- }
- rcu_read_unlock();
-
- cbss = cfg80211_inform_bss_frame_data(local->hw.wiphy, &bss_meta,
- mgmt, len, GFP_ATOMIC);
- if (!cbss)
- return NULL;
- /* In case the signal is invalid update the status */
- signal_valid = abs(channel->center_freq - cbss->channel->center_freq)
- <= local->hw.wiphy->max_adj_channel_rssi_comp;
- if (!signal_valid)
- rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
-
- bss = (void *)cbss->priv;
if (beacon)
bss->device_ts_beacon = rx_status->device_timestamp;
@@ -182,6 +135,89 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
bss->beacon_rate =
&sband->bitrates[rx_status->rate_idx];
}
+}
+
+struct ieee80211_bss *
+ieee80211_bss_info_update(struct ieee80211_local *local,
+ struct ieee80211_rx_status *rx_status,
+ struct ieee80211_mgmt *mgmt, size_t len,
+ struct ieee80211_channel *channel)
+{
+ bool beacon = ieee80211_is_beacon(mgmt->frame_control);
+ struct cfg80211_bss *cbss, *non_tx_cbss;
+ struct ieee80211_bss *bss, *non_tx_bss;
+ struct cfg80211_inform_bss bss_meta = {
+ .boottime_ns = rx_status->boottime_ns,
+ };
+ bool signal_valid;
+ struct ieee80211_sub_if_data *scan_sdata;
+ struct ieee802_11_elems elems;
+ size_t baselen;
+ u8 *elements;
+
+ if (rx_status->flag & RX_FLAG_NO_SIGNAL_VAL)
+ bss_meta.signal = 0; /* invalid signal indication */
+ else if (ieee80211_hw_check(&local->hw, SIGNAL_DBM))
+ bss_meta.signal = rx_status->signal * 100;
+ else if (ieee80211_hw_check(&local->hw, SIGNAL_UNSPEC))
+ bss_meta.signal = (rx_status->signal * 100) / local->hw.max_signal;
+
+ bss_meta.scan_width = NL80211_BSS_CHAN_WIDTH_20;
+ if (rx_status->bw == RATE_INFO_BW_5)
+ bss_meta.scan_width = NL80211_BSS_CHAN_WIDTH_5;
+ else if (rx_status->bw == RATE_INFO_BW_10)
+ bss_meta.scan_width = NL80211_BSS_CHAN_WIDTH_10;
+
+ bss_meta.chan = channel;
+
+ rcu_read_lock();
+ scan_sdata = rcu_dereference(local->scan_sdata);
+ if (scan_sdata && scan_sdata->vif.type == NL80211_IFTYPE_STATION &&
+ scan_sdata->vif.bss_conf.assoc &&
+ ieee80211_have_rx_timestamp(rx_status)) {
+ bss_meta.parent_tsf =
+ ieee80211_calculate_rx_timestamp(local, rx_status,
+ len + FCS_LEN, 24);
+ ether_addr_copy(bss_meta.parent_bssid,
+ scan_sdata->vif.bss_conf.bssid);
+ }
+ rcu_read_unlock();
+
+ cbss = cfg80211_inform_bss_frame_data(local->hw.wiphy, &bss_meta,
+ mgmt, len, GFP_ATOMIC);
+ if (!cbss)
+ return NULL;
+
+ if (ieee80211_is_probe_resp(mgmt->frame_control)) {
+ elements = mgmt->u.probe_resp.variable;
+ baselen = offsetof(struct ieee80211_mgmt,
+ u.probe_resp.variable);
+ } else {
+ baselen = offsetof(struct ieee80211_mgmt, u.beacon.variable);
+ elements = mgmt->u.beacon.variable;
+ }
+
+ if (baselen > len)
+ return NULL;
+
+ ieee802_11_parse_elems(elements, len - baselen, false, &elems,
+ mgmt->bssid, cbss->bssid);
+
+ /* In case the signal is invalid update the status */
+ signal_valid = abs(channel->center_freq - cbss->channel->center_freq)
+ <= local->hw.wiphy->max_adj_channel_rssi_comp;
+ if (!signal_valid)
+ rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
+
+ bss = (void *)cbss->priv;
+ ieee80211_update_bss_from_elems(local, bss, &elems, rx_status, beacon);
+
+ list_for_each_entry(non_tx_cbss, &cbss->nontrans_list, nontrans_list) {
+ non_tx_bss = (void *)non_tx_cbss->priv;
+
+ ieee80211_update_bss_from_elems(local, non_tx_bss, &elems,
+ rx_status, beacon);
+ }
return bss;
}
@@ -206,10 +242,7 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
struct ieee80211_sub_if_data *sdata1, *sdata2;
struct ieee80211_mgmt *mgmt = (void *)skb->data;
struct ieee80211_bss *bss;
- u8 *elements;
struct ieee80211_channel *channel;
- size_t baselen;
- struct ieee802_11_elems elems;
if (skb->len < 24 ||
(!ieee80211_is_probe_resp(mgmt->frame_control) &&
@@ -244,26 +277,15 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
!ieee80211_scan_accept_presp(sdata2, sched_scan_req_flags,
mgmt->da))
return;
-
- elements = mgmt->u.probe_resp.variable;
- baselen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
- } else {
- baselen = offsetof(struct ieee80211_mgmt, u.beacon.variable);
- elements = mgmt->u.beacon.variable;
}
- if (baselen > skb->len)
- return;
-
- ieee802_11_parse_elems(elements, skb->len - baselen, false, &elems);
-
channel = ieee80211_get_channel(local->hw.wiphy, rx_status->freq);
if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
return;
bss = ieee80211_bss_info_update(local, rx_status,
- mgmt, skb->len, &elems,
+ mgmt, skb->len,
channel);
if (bss)
ieee80211_rx_bss_put(local, bss);