wifi: cfg80211: hide scan internals

Hide the internal scan fields from mac80211 and drivers, the
'notified' variable is for internal tracking, and the 'info'
is output that's passed to cfg80211_scan_done() and stored
only for delayed userspace notification.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Reviewed-by: Benjamin Berg <benjamin.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20250609213231.6a62e41858e2.I004f66e9c087cc6e6ae4a24951cf470961ee9466@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Johannes Berg
2025-06-09 21:35:19 +03:00
parent 6f9e701c16
commit f0df91b6a7
8 changed files with 196 additions and 179 deletions

View File

@@ -2748,8 +2748,6 @@ struct cfg80211_scan_6ghz_params {
* @wiphy: the wiphy this was for
* @scan_start: time (in jiffies) when the scan started
* @wdev: the wireless device to scan for
* @info: (internal) information about completed scan
* @notified: (internal) scan request was notified as done or aborted
* @no_cck: used to send probe requests at non CCK rate in 2GHz band
* @mac_addr: MAC address used with randomisation
* @mac_addr_mask: MAC address mask used with randomisation, bits that
@@ -2780,12 +2778,8 @@ struct cfg80211_scan_request {
u8 mac_addr[ETH_ALEN] __aligned(2);
u8 mac_addr_mask[ETH_ALEN] __aligned(2);
u8 bssid[ETH_ALEN] __aligned(2);
/* internal */
struct wiphy *wiphy;
unsigned long scan_start;
struct cfg80211_scan_info info;
bool notified;
bool no_cck;
bool scan_6ghz;
u32 n_6ghz_params;

View File

@@ -239,7 +239,7 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
rdev->opencount--;
if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
if (rdev->scan_req && rdev->scan_req->req.wdev == wdev) {
if (WARN_ON(!rdev->scan_req->notified &&
(!rdev->int_scan_req ||
!rdev->int_scan_req->notified)))
@@ -1574,7 +1574,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
case NETDEV_DOWN:
wiphy_lock(&rdev->wiphy);
cfg80211_update_iface_num(rdev, wdev->iftype, -1);
if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
if (rdev->scan_req && rdev->scan_req->req.wdev == wdev) {
if (WARN_ON(!rdev->scan_req->notified &&
(!rdev->int_scan_req ||
!rdev->int_scan_req->notified)))

View File

@@ -21,6 +21,13 @@
#define WIPHY_IDX_INVALID -1
struct cfg80211_scan_request_int {
struct cfg80211_scan_info info;
bool notified;
/* must be last - variable members */
struct cfg80211_scan_request req;
};
struct cfg80211_registered_device {
const struct cfg80211_ops *ops;
struct list_head list;
@@ -70,8 +77,8 @@ struct cfg80211_registered_device {
struct rb_root bss_tree;
u32 bss_generation;
u32 bss_entries;
struct cfg80211_scan_request *scan_req; /* protected by RTNL */
struct cfg80211_scan_request *int_scan_req;
struct cfg80211_scan_request_int *scan_req; /* protected by RTNL */
struct cfg80211_scan_request_int *int_scan_req;
struct sk_buff *scan_msg;
struct list_head sched_scan_req_list;
time64_t suspend_at;

View File

@@ -9831,12 +9831,12 @@ nl80211_check_scan_flags(struct wiphy *wiphy, struct wireless_dev *wdev,
mac_addr = req->mac_addr;
mac_addr_mask = req->mac_addr_mask;
} else {
struct cfg80211_scan_request *req = request;
struct cfg80211_scan_request_int *req = request;
randomness_flag = NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
flags = &req->flags;
mac_addr = req->mac_addr;
mac_addr_mask = req->mac_addr_mask;
flags = &req->req.flags;
mac_addr = req->req.mac_addr;
mac_addr_mask = req->req.mac_addr_mask;
}
*flags = nla_get_u32(attrs[NL80211_ATTR_SCAN_FLAGS]);
@@ -9891,7 +9891,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
struct wireless_dev *wdev = info->user_ptr[1];
struct cfg80211_scan_request *request;
struct cfg80211_scan_request_int *request;
struct nlattr *scan_freqs = NULL;
bool scan_freqs_khz = false;
struct nlattr *attr;
@@ -9943,21 +9943,21 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
if (ie_len > wiphy->max_scan_ie_len)
return -EINVAL;
size = struct_size(request, channels, n_channels);
size = struct_size(request, req.channels, n_channels);
ssids_offset = size;
size = size_add(size, array_size(sizeof(*request->ssids), n_ssids));
size = size_add(size, array_size(sizeof(*request->req.ssids), n_ssids));
ie_offset = size;
size = size_add(size, ie_len);
request = kzalloc(size, GFP_KERNEL);
if (!request)
return -ENOMEM;
request->n_channels = n_channels;
request->req.n_channels = n_channels;
if (n_ssids)
request->ssids = (void *)request + ssids_offset;
request->n_ssids = n_ssids;
request->req.ssids = (void *)request + ssids_offset;
request->req.n_ssids = n_ssids;
if (ie_len)
request->ie = (void *)request + ie_offset;
request->req.ie = (void *)request + ie_offset;
i = 0;
if (scan_freqs) {
@@ -9980,7 +9980,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
!cfg80211_wdev_channel_allowed(wdev, chan))
continue;
request->channels[i] = chan;
request->req.channels[i] = chan;
i++;
}
} else {
@@ -10001,7 +10001,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
!cfg80211_wdev_channel_allowed(wdev, chan))
continue;
request->channels[i] = chan;
request->req.channels[i] = chan;
i++;
}
}
@@ -10012,10 +10012,10 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
goto out_free;
}
request->n_channels = i;
request->req.n_channels = i;
for (i = 0; i < request->n_channels; i++) {
struct ieee80211_channel *chan = request->channels[i];
for (i = 0; i < request->req.n_channels; i++) {
struct ieee80211_channel *chan = request->req.channels[i];
/* if we can go off-channel to the target channel we're good */
if (cfg80211_off_channel_oper_allowed(wdev, chan))
@@ -10034,22 +10034,23 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
err = -EINVAL;
goto out_free;
}
request->ssids[i].ssid_len = nla_len(attr);
memcpy(request->ssids[i].ssid, nla_data(attr), nla_len(attr));
request->req.ssids[i].ssid_len = nla_len(attr);
memcpy(request->req.ssids[i].ssid,
nla_data(attr), nla_len(attr));
i++;
}
}
if (info->attrs[NL80211_ATTR_IE]) {
request->ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
memcpy((void *)request->ie,
request->req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
memcpy((void *)request->req.ie,
nla_data(info->attrs[NL80211_ATTR_IE]),
request->ie_len);
request->req.ie_len);
}
for (i = 0; i < NUM_NL80211_BANDS; i++)
if (wiphy->bands[i])
request->rates[i] =
request->req.rates[i] =
(1 << wiphy->bands[i]->n_bitrates) - 1;
if (info->attrs[NL80211_ATTR_SCAN_SUPP_RATES]) {
@@ -10069,16 +10070,16 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
err = ieee80211_get_ratemask(wiphy->bands[band],
nla_data(attr),
nla_len(attr),
&request->rates[band]);
&request->req.rates[band]);
if (err)
goto out_free;
}
}
if (info->attrs[NL80211_ATTR_MEASUREMENT_DURATION]) {
request->duration =
request->req.duration =
nla_get_u16(info->attrs[NL80211_ATTR_MEASUREMENT_DURATION]);
request->duration_mandatory =
request->req.duration_mandatory =
nla_get_flag(info->attrs[NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY]);
}
@@ -10087,7 +10088,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
if (err)
goto out_free;
request->no_cck =
request->req.no_cck =
nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
/* Initial implementation used NL80211_ATTR_MAC to set the specific
@@ -10100,19 +10101,21 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
* (NL80211_ATTR_SCAN_FLAGS is used to enable random MAC address use).
*/
if (info->attrs[NL80211_ATTR_BSSID])
memcpy(request->bssid,
memcpy(request->req.bssid,
nla_data(info->attrs[NL80211_ATTR_BSSID]), ETH_ALEN);
else if (!(request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) &&
else if (!(request->req.flags & NL80211_SCAN_FLAG_RANDOM_ADDR) &&
info->attrs[NL80211_ATTR_MAC])
memcpy(request->bssid, nla_data(info->attrs[NL80211_ATTR_MAC]),
memcpy(request->req.bssid,
nla_data(info->attrs[NL80211_ATTR_MAC]),
ETH_ALEN);
else
eth_broadcast_addr(request->bssid);
eth_broadcast_addr(request->req.bssid);
request->tsf_report_link_id = nl80211_link_id_or_invalid(info->attrs);
request->wdev = wdev;
request->wiphy = &rdev->wiphy;
request->scan_start = jiffies;
request->req.tsf_report_link_id =
nl80211_link_id_or_invalid(info->attrs);
request->req.wdev = wdev;
request->req.wiphy = &rdev->wiphy;
request->req.scan_start = jiffies;
rdev->scan_req = request;
err = cfg80211_scan(rdev);
@@ -18414,7 +18417,7 @@ void nl80211_notify_iface(struct cfg80211_registered_device *rdev,
static int nl80211_add_scan_req(struct sk_buff *msg,
struct cfg80211_registered_device *rdev)
{
struct cfg80211_scan_request *req = rdev->scan_req;
struct cfg80211_scan_request_int *req = rdev->scan_req;
struct nlattr *nest;
int i;
struct cfg80211_scan_info *info;
@@ -18425,19 +18428,20 @@ static int nl80211_add_scan_req(struct sk_buff *msg,
nest = nla_nest_start_noflag(msg, NL80211_ATTR_SCAN_SSIDS);
if (!nest)
goto nla_put_failure;
for (i = 0; i < req->n_ssids; i++) {
if (nla_put(msg, i, req->ssids[i].ssid_len, req->ssids[i].ssid))
for (i = 0; i < req->req.n_ssids; i++) {
if (nla_put(msg, i, req->req.ssids[i].ssid_len,
req->req.ssids[i].ssid))
goto nla_put_failure;
}
nla_nest_end(msg, nest);
if (req->flags & NL80211_SCAN_FLAG_FREQ_KHZ) {
if (req->req.flags & NL80211_SCAN_FLAG_FREQ_KHZ) {
nest = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQ_KHZ);
if (!nest)
goto nla_put_failure;
for (i = 0; i < req->n_channels; i++) {
for (i = 0; i < req->req.n_channels; i++) {
if (nla_put_u32(msg, i,
ieee80211_channel_to_khz(req->channels[i])))
ieee80211_channel_to_khz(req->req.channels[i])))
goto nla_put_failure;
}
nla_nest_end(msg, nest);
@@ -18446,19 +18450,20 @@ static int nl80211_add_scan_req(struct sk_buff *msg,
NL80211_ATTR_SCAN_FREQUENCIES);
if (!nest)
goto nla_put_failure;
for (i = 0; i < req->n_channels; i++) {
if (nla_put_u32(msg, i, req->channels[i]->center_freq))
for (i = 0; i < req->req.n_channels; i++) {
if (nla_put_u32(msg, i,
req->req.channels[i]->center_freq))
goto nla_put_failure;
}
nla_nest_end(msg, nest);
}
if (req->ie &&
nla_put(msg, NL80211_ATTR_IE, req->ie_len, req->ie))
if (req->req.ie &&
nla_put(msg, NL80211_ATTR_IE, req->req.ie_len, req->req.ie))
goto nla_put_failure;
if (req->flags &&
nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, req->flags))
if (req->req.flags &&
nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, req->req.flags))
goto nla_put_failure;
info = rdev->int_scan_req ? &rdev->int_scan_req->info :

View File

@@ -456,15 +456,15 @@ rdev_set_monitor_channel(struct cfg80211_registered_device *rdev,
}
static inline int rdev_scan(struct cfg80211_registered_device *rdev,
struct cfg80211_scan_request *request)
struct cfg80211_scan_request_int *request)
{
int ret;
if (WARN_ON_ONCE(!request->n_ssids && request->ssids))
if (WARN_ON_ONCE(!request->req.n_ssids && request->req.ssids))
return -EINVAL;
trace_rdev_scan(&rdev->wiphy, request);
ret = rdev->ops->scan(&rdev->wiphy, request);
ret = rdev->ops->scan(&rdev->wiphy, &request->req);
trace_rdev_return_int(&rdev->wiphy, ret);
return ret;
}

View File

@@ -782,9 +782,9 @@ cfg80211_parse_colocated_ap(const struct cfg80211_bss_ies *ies,
}
EXPORT_SYMBOL_IF_CFG80211_KUNIT(cfg80211_parse_colocated_ap);
static void cfg80211_scan_req_add_chan(struct cfg80211_scan_request *request,
struct ieee80211_channel *chan,
bool add_to_6ghz)
static void cfg80211_scan_req_add_chan(struct cfg80211_scan_request *request,
struct ieee80211_channel *chan,
bool add_to_6ghz)
{
int i;
u32 n_channels = request->n_channels;
@@ -843,25 +843,25 @@ static int cfg80211_scan_6ghz(struct cfg80211_registered_device *rdev)
u8 i;
struct cfg80211_colocated_ap *ap;
int n_channels, count = 0, err;
struct cfg80211_scan_request *request, *rdev_req = rdev->scan_req;
struct cfg80211_scan_request_int *request, *rdev_req = rdev->scan_req;
LIST_HEAD(coloc_ap_list);
bool need_scan_psc = true;
const struct ieee80211_sband_iftype_data *iftd;
size_t size, offs_ssids, offs_6ghz_params, offs_ies;
rdev_req->scan_6ghz = true;
rdev_req->req.scan_6ghz = true;
if (!rdev->wiphy.bands[NL80211_BAND_6GHZ])
return -EOPNOTSUPP;
iftd = ieee80211_get_sband_iftype_data(rdev->wiphy.bands[NL80211_BAND_6GHZ],
rdev_req->wdev->iftype);
rdev_req->req.wdev->iftype);
if (!iftd || !iftd->he_cap.has_he)
return -EOPNOTSUPP;
n_channels = rdev->wiphy.bands[NL80211_BAND_6GHZ]->n_channels;
if (rdev_req->flags & NL80211_SCAN_FLAG_COLOCATED_6GHZ) {
if (rdev_req->req.flags & NL80211_SCAN_FLAG_COLOCATED_6GHZ) {
struct cfg80211_internal_bss *intbss;
spin_lock_bh(&rdev->bss_lock);
@@ -883,8 +883,8 @@ static int cfg80211_scan_6ghz(struct cfg80211_registered_device *rdev)
* This is relevant for ML probe requests when the lower
* band APs have not been discovered.
*/
if (is_broadcast_ether_addr(rdev_req->bssid) ||
!ether_addr_equal(rdev_req->bssid, res->bssid) ||
if (is_broadcast_ether_addr(rdev_req->req.bssid) ||
!ether_addr_equal(rdev_req->req.bssid, res->bssid) ||
res->channel->band != NL80211_BAND_6GHZ)
continue;
@@ -911,13 +911,13 @@ static int cfg80211_scan_6ghz(struct cfg80211_registered_device *rdev)
spin_unlock_bh(&rdev->bss_lock);
}
size = struct_size(request, channels, n_channels);
size = struct_size(request, req.channels, n_channels);
offs_ssids = size;
size += sizeof(*request->ssids) * rdev_req->n_ssids;
size += sizeof(*request->req.ssids) * rdev_req->req.n_ssids;
offs_6ghz_params = size;
size += sizeof(*request->scan_6ghz_params) * count;
size += sizeof(*request->req.scan_6ghz_params) * count;
offs_ies = size;
size += rdev_req->ie_len;
size += rdev_req->req.ie_len;
request = kzalloc(size, GFP_KERNEL);
if (!request) {
@@ -926,26 +926,26 @@ static int cfg80211_scan_6ghz(struct cfg80211_registered_device *rdev)
}
*request = *rdev_req;
request->n_channels = 0;
request->n_6ghz_params = 0;
if (rdev_req->n_ssids) {
request->req.n_channels = 0;
request->req.n_6ghz_params = 0;
if (rdev_req->req.n_ssids) {
/*
* Add the ssids from the parent scan request to the new
* scan request, so the driver would be able to use them
* in its probe requests to discover hidden APs on PSC
* channels.
*/
request->ssids = (void *)request + offs_ssids;
memcpy(request->ssids, rdev_req->ssids,
sizeof(*request->ssids) * request->n_ssids);
request->req.ssids = (void *)request + offs_ssids;
memcpy(request->req.ssids, rdev_req->req.ssids,
sizeof(*request->req.ssids) * request->req.n_ssids);
}
request->scan_6ghz_params = (void *)request + offs_6ghz_params;
request->req.scan_6ghz_params = (void *)request + offs_6ghz_params;
if (rdev_req->ie_len) {
if (rdev_req->req.ie_len) {
void *ie = (void *)request + offs_ies;
memcpy(ie, rdev_req->ie, rdev_req->ie_len);
request->ie = ie;
memcpy(ie, rdev_req->req.ie, rdev_req->req.ie_len);
request->req.ie = ie;
}
/*
@@ -953,10 +953,12 @@ static int cfg80211_scan_6ghz(struct cfg80211_registered_device *rdev)
* and at least one of the reported co-located APs with same SSID
* indicating that all APs in the same ESS are co-located
*/
if (count && request->n_ssids == 1 && request->ssids[0].ssid_len) {
if (count &&
request->req.n_ssids == 1 &&
request->req.ssids[0].ssid_len) {
list_for_each_entry(ap, &coloc_ap_list, list) {
if (ap->colocated_ess &&
cfg80211_find_ssid_match(ap, request)) {
cfg80211_find_ssid_match(ap, &request->req)) {
need_scan_psc = false;
break;
}
@@ -968,51 +970,52 @@ static int cfg80211_scan_6ghz(struct cfg80211_registered_device *rdev)
* regardless of the collocated APs (PSC channels or all channels
* in case that NL80211_SCAN_FLAG_COLOCATED_6GHZ is not set)
*/
for (i = 0; i < rdev_req->n_channels; i++) {
if (rdev_req->channels[i]->band == NL80211_BAND_6GHZ &&
for (i = 0; i < rdev_req->req.n_channels; i++) {
if (rdev_req->req.channels[i]->band == NL80211_BAND_6GHZ &&
((need_scan_psc &&
cfg80211_channel_is_psc(rdev_req->channels[i])) ||
!(rdev_req->flags & NL80211_SCAN_FLAG_COLOCATED_6GHZ))) {
cfg80211_scan_req_add_chan(request,
rdev_req->channels[i],
cfg80211_channel_is_psc(rdev_req->req.channels[i])) ||
!(rdev_req->req.flags & NL80211_SCAN_FLAG_COLOCATED_6GHZ))) {
cfg80211_scan_req_add_chan(&request->req,
rdev_req->req.channels[i],
false);
}
}
if (!(rdev_req->flags & NL80211_SCAN_FLAG_COLOCATED_6GHZ))
if (!(rdev_req->req.flags & NL80211_SCAN_FLAG_COLOCATED_6GHZ))
goto skip;
list_for_each_entry(ap, &coloc_ap_list, list) {
bool found = false;
struct cfg80211_scan_6ghz_params *scan_6ghz_params =
&request->scan_6ghz_params[request->n_6ghz_params];
&request->req.scan_6ghz_params[request->req.n_6ghz_params];
struct ieee80211_channel *chan =
ieee80211_get_channel(&rdev->wiphy, ap->center_freq);
if (!chan || chan->flags & IEEE80211_CHAN_DISABLED ||
!cfg80211_wdev_channel_allowed(rdev_req->wdev, chan))
!cfg80211_wdev_channel_allowed(rdev_req->req.wdev, chan))
continue;
for (i = 0; i < rdev_req->n_channels; i++) {
if (rdev_req->channels[i] == chan)
for (i = 0; i < rdev_req->req.n_channels; i++) {
if (rdev_req->req.channels[i] == chan)
found = true;
}
if (!found)
continue;
if (request->n_ssids > 0 &&
!cfg80211_find_ssid_match(ap, request))
if (request->req.n_ssids > 0 &&
!cfg80211_find_ssid_match(ap, &request->req))
continue;
if (!is_broadcast_ether_addr(request->bssid) &&
!ether_addr_equal(request->bssid, ap->bssid))
if (!is_broadcast_ether_addr(request->req.bssid) &&
!ether_addr_equal(request->req.bssid, ap->bssid))
continue;
if (!request->n_ssids && ap->multi_bss && !ap->transmitted_bssid)
if (!request->req.n_ssids && ap->multi_bss &&
!ap->transmitted_bssid)
continue;
cfg80211_scan_req_add_chan(request, chan, true);
cfg80211_scan_req_add_chan(&request->req, chan, true);
memcpy(scan_6ghz_params->bssid, ap->bssid, ETH_ALEN);
scan_6ghz_params->short_ssid = ap->short_ssid;
scan_6ghz_params->short_ssid_valid = ap->short_ssid_valid;
@@ -1028,14 +1031,14 @@ static int cfg80211_scan_6ghz(struct cfg80211_registered_device *rdev)
if (cfg80211_channel_is_psc(chan) && !need_scan_psc)
scan_6ghz_params->psc_no_listen = true;
request->n_6ghz_params++;
request->req.n_6ghz_params++;
}
skip:
cfg80211_free_coloc_ap_list(&coloc_ap_list);
if (request->n_channels) {
struct cfg80211_scan_request *old = rdev->int_scan_req;
if (request->req.n_channels) {
struct cfg80211_scan_request_int *old = rdev->int_scan_req;
rdev->int_scan_req = request;
@@ -1063,35 +1066,36 @@ skip:
int cfg80211_scan(struct cfg80211_registered_device *rdev)
{
struct cfg80211_scan_request *request;
struct cfg80211_scan_request *rdev_req = rdev->scan_req;
struct cfg80211_scan_request_int *request;
struct cfg80211_scan_request_int *rdev_req = rdev->scan_req;
u32 n_channels = 0, idx, i;
if (!(rdev->wiphy.flags & WIPHY_FLAG_SPLIT_SCAN_6GHZ))
return rdev_scan(rdev, rdev_req);
for (i = 0; i < rdev_req->n_channels; i++) {
if (rdev_req->channels[i]->band != NL80211_BAND_6GHZ)
for (i = 0; i < rdev_req->req.n_channels; i++) {
if (rdev_req->req.channels[i]->band != NL80211_BAND_6GHZ)
n_channels++;
}
if (!n_channels)
return cfg80211_scan_6ghz(rdev);
request = kzalloc(struct_size(request, channels, n_channels),
request = kzalloc(struct_size(request, req.channels, n_channels),
GFP_KERNEL);
if (!request)
return -ENOMEM;
*request = *rdev_req;
request->n_channels = n_channels;
request->req.n_channels = n_channels;
for (i = idx = 0; i < rdev_req->n_channels; i++) {
if (rdev_req->channels[i]->band != NL80211_BAND_6GHZ)
request->channels[idx++] = rdev_req->channels[i];
for (i = idx = 0; i < rdev_req->req.n_channels; i++) {
if (rdev_req->req.channels[i]->band != NL80211_BAND_6GHZ)
request->req.channels[idx++] =
rdev_req->req.channels[i];
}
rdev_req->scan_6ghz = false;
rdev_req->req.scan_6ghz = false;
rdev->int_scan_req = request;
return rdev_scan(rdev, request);
}
@@ -1099,7 +1103,7 @@ int cfg80211_scan(struct cfg80211_registered_device *rdev)
void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev,
bool send_message)
{
struct cfg80211_scan_request *request, *rdev_req;
struct cfg80211_scan_request_int *request, *rdev_req;
struct wireless_dev *wdev;
struct sk_buff *msg;
#ifdef CONFIG_CFG80211_WEXT
@@ -1118,12 +1122,12 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev,
if (!rdev_req)
return;
wdev = rdev_req->wdev;
wdev = rdev_req->req.wdev;
request = rdev->int_scan_req ? rdev->int_scan_req : rdev_req;
if (wdev_running(wdev) &&
(rdev->wiphy.flags & WIPHY_FLAG_SPLIT_SCAN_6GHZ) &&
!rdev_req->scan_6ghz && !request->info.aborted &&
!rdev_req->req.scan_6ghz && !request->info.aborted &&
!cfg80211_scan_6ghz(rdev))
return;
@@ -1136,10 +1140,10 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev,
cfg80211_sme_scan_done(wdev->netdev);
if (!request->info.aborted &&
request->flags & NL80211_SCAN_FLAG_FLUSH) {
request->req.flags & NL80211_SCAN_FLAG_FLUSH) {
/* flush entries from previous scans */
spin_lock_bh(&rdev->bss_lock);
__cfg80211_bss_expire(rdev, request->scan_start);
__cfg80211_bss_expire(rdev, request->req.scan_start);
spin_unlock_bh(&rdev->bss_lock);
}
@@ -1175,13 +1179,16 @@ void __cfg80211_scan_done(struct wiphy *wiphy, struct wiphy_work *wk)
void cfg80211_scan_done(struct cfg80211_scan_request *request,
struct cfg80211_scan_info *info)
{
struct cfg80211_scan_info old_info = request->info;
struct cfg80211_scan_request_int *intreq =
container_of(request, struct cfg80211_scan_request_int, req);
struct cfg80211_registered_device *rdev = wiphy_to_rdev(request->wiphy);
struct cfg80211_scan_info old_info = intreq->info;
trace_cfg80211_scan_done(request, info);
WARN_ON(request != wiphy_to_rdev(request->wiphy)->scan_req &&
request != wiphy_to_rdev(request->wiphy)->int_scan_req);
trace_cfg80211_scan_done(intreq, info);
WARN_ON(intreq != rdev->scan_req &&
intreq != rdev->int_scan_req);
request->info = *info;
intreq->info = *info;
/*
* In case the scan is split, the scan_start_tsf and tsf_bssid should
@@ -1189,14 +1196,13 @@ void cfg80211_scan_done(struct cfg80211_scan_request *request,
* be non zero.
*/
if (request->scan_6ghz && old_info.scan_start_tsf) {
request->info.scan_start_tsf = old_info.scan_start_tsf;
memcpy(request->info.tsf_bssid, old_info.tsf_bssid,
sizeof(request->info.tsf_bssid));
intreq->info.scan_start_tsf = old_info.scan_start_tsf;
memcpy(intreq->info.tsf_bssid, old_info.tsf_bssid,
sizeof(intreq->info.tsf_bssid));
}
request->notified = true;
wiphy_work_queue(request->wiphy,
&wiphy_to_rdev(request->wiphy)->scan_done_wk);
intreq->notified = true;
wiphy_work_queue(request->wiphy, &rdev->scan_done_wk);
}
EXPORT_SYMBOL(cfg80211_scan_done);
@@ -3496,7 +3502,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
struct cfg80211_registered_device *rdev;
struct wiphy *wiphy;
struct iw_scan_req *wreq = NULL;
struct cfg80211_scan_request *creq;
struct cfg80211_scan_request_int *creq;
int i, err, n_channels = 0;
enum nl80211_band band;
@@ -3526,19 +3532,20 @@ int cfg80211_wext_siwscan(struct net_device *dev,
n_channels = ieee80211_get_num_supported_channels(wiphy);
}
creq = kzalloc(struct_size(creq, channels, n_channels) +
creq = kzalloc(struct_size(creq, req.channels, n_channels) +
sizeof(struct cfg80211_ssid),
GFP_ATOMIC);
if (!creq)
return -ENOMEM;
creq->wiphy = wiphy;
creq->wdev = dev->ieee80211_ptr;
creq->req.wiphy = wiphy;
creq->req.wdev = dev->ieee80211_ptr;
/* SSIDs come after channels */
creq->ssids = (void *)creq + struct_size(creq, channels, n_channels);
creq->n_channels = n_channels;
creq->n_ssids = 1;
creq->scan_start = jiffies;
creq->req.ssids = (void *)creq +
struct_size(creq, req.channels, n_channels);
creq->req.n_channels = n_channels;
creq->req.n_ssids = 1;
creq->req.scan_start = jiffies;
/* translate "Scan on frequencies" request */
i = 0;
@@ -3554,7 +3561,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
/* ignore disabled channels */
chan = &wiphy->bands[band]->channels[j];
if (chan->flags & IEEE80211_CHAN_DISABLED ||
!cfg80211_wdev_channel_allowed(creq->wdev, chan))
!cfg80211_wdev_channel_allowed(creq->req.wdev, chan))
continue;
/* If we have a wireless request structure and the
@@ -3577,7 +3584,8 @@ int cfg80211_wext_siwscan(struct net_device *dev,
}
wext_freq_found:
creq->channels[i] = &wiphy->bands[band]->channels[j];
creq->req.channels[i] =
&wiphy->bands[band]->channels[j];
i++;
wext_freq_not_found: ;
}
@@ -3588,28 +3596,30 @@ int cfg80211_wext_siwscan(struct net_device *dev,
goto out;
}
/* Set real number of channels specified in creq->channels[] */
creq->n_channels = i;
/* Set real number of channels specified in creq->req.channels[] */
creq->req.n_channels = i;
/* translate "Scan for SSID" request */
if (wreq) {
if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
if (wreq->essid_len > IEEE80211_MAX_SSID_LEN)
return -EINVAL;
memcpy(creq->ssids[0].ssid, wreq->essid, wreq->essid_len);
creq->ssids[0].ssid_len = wreq->essid_len;
memcpy(creq->req.ssids[0].ssid, wreq->essid,
wreq->essid_len);
creq->req.ssids[0].ssid_len = wreq->essid_len;
}
if (wreq->scan_type == IW_SCAN_TYPE_PASSIVE) {
creq->ssids = NULL;
creq->n_ssids = 0;
creq->req.ssids = NULL;
creq->req.n_ssids = 0;
}
}
for (i = 0; i < NUM_NL80211_BANDS; i++)
if (wiphy->bands[i])
creq->rates[i] = (1 << wiphy->bands[i]->n_bitrates) - 1;
creq->req.rates[i] =
(1 << wiphy->bands[i]->n_bitrates) - 1;
eth_broadcast_addr(creq->bssid);
eth_broadcast_addr(creq->req.bssid);
scoped_guard(wiphy, &rdev->wiphy) {
rdev->scan_req = creq;

View File

@@ -5,7 +5,7 @@
* (for nl80211's connect() and wext)
*
* Copyright 2009 Johannes Berg <johannes@sipsolutions.net>
* Copyright (C) 2009, 2020, 2022-2024 Intel Corporation. All rights reserved.
* Copyright (C) 2009, 2020, 2022-2025 Intel Corporation. All rights reserved.
* Copyright 2017 Intel Deutschland GmbH
*/
@@ -64,7 +64,7 @@ static void cfg80211_sme_free(struct wireless_dev *wdev)
static int cfg80211_conn_scan(struct wireless_dev *wdev)
{
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
struct cfg80211_scan_request *request;
struct cfg80211_scan_request_int *request;
int n_channels, err;
lockdep_assert_wiphy(wdev->wiphy);
@@ -77,13 +77,13 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
else
n_channels = ieee80211_get_num_supported_channels(wdev->wiphy);
request = kzalloc(sizeof(*request) + sizeof(request->ssids[0]) +
sizeof(request->channels[0]) * n_channels,
request = kzalloc(sizeof(*request) + sizeof(request->req.ssids[0]) +
sizeof(request->req.channels[0]) * n_channels,
GFP_KERNEL);
if (!request)
return -ENOMEM;
request->n_channels = n_channels;
request->req.n_channels = n_channels;
if (wdev->conn->params.channel) {
enum nl80211_band band = wdev->conn->params.channel->band;
struct ieee80211_supported_band *sband =
@@ -93,8 +93,8 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
kfree(request);
return -EINVAL;
}
request->channels[0] = wdev->conn->params.channel;
request->rates[band] = (1 << sband->n_bitrates) - 1;
request->req.channels[0] = wdev->conn->params.channel;
request->req.rates[band] = (1 << sband->n_bitrates) - 1;
} else {
int i = 0, j;
enum nl80211_band band;
@@ -109,26 +109,26 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
channel = &bands->channels[j];
if (channel->flags & IEEE80211_CHAN_DISABLED)
continue;
request->channels[i++] = channel;
request->req.channels[i++] = channel;
}
request->rates[band] = (1 << bands->n_bitrates) - 1;
request->req.rates[band] = (1 << bands->n_bitrates) - 1;
}
n_channels = i;
}
request->n_channels = n_channels;
request->ssids = (void *)request +
struct_size(request, channels, n_channels);
request->n_ssids = 1;
request->req.n_channels = n_channels;
request->req.ssids = (void *)request +
struct_size(request, req.channels, n_channels);
request->req.n_ssids = 1;
memcpy(request->ssids[0].ssid, wdev->conn->params.ssid,
wdev->conn->params.ssid_len);
request->ssids[0].ssid_len = wdev->conn->params.ssid_len;
memcpy(request->req.ssids[0].ssid, wdev->conn->params.ssid,
wdev->conn->params.ssid_len);
request->req.ssids[0].ssid_len = wdev->conn->params.ssid_len;
eth_broadcast_addr(request->bssid);
eth_broadcast_addr(request->req.bssid);
request->wdev = wdev;
request->wiphy = &rdev->wiphy;
request->scan_start = jiffies;
request->req.wdev = wdev;
request->req.wiphy = &rdev->wiphy;
request->req.scan_start = jiffies;
rdev->scan_req = request;

View File

@@ -373,7 +373,8 @@ TRACE_EVENT(rdev_return_int,
);
TRACE_EVENT(rdev_scan,
TP_PROTO(struct wiphy *wiphy, struct cfg80211_scan_request *request),
TP_PROTO(struct wiphy *wiphy,
struct cfg80211_scan_request_int *request),
TP_ARGS(wiphy, request),
TP_STRUCT__entry(
WIPHY_ENTRY
@@ -3716,12 +3717,12 @@ TRACE_EVENT(cfg80211_tdls_oper_request,
);
TRACE_EVENT(cfg80211_scan_done,
TP_PROTO(struct cfg80211_scan_request *request,
TP_PROTO(struct cfg80211_scan_request_int *request,
struct cfg80211_scan_info *info),
TP_ARGS(request, info),
TP_STRUCT__entry(
__field(u32, n_channels)
__dynamic_array(u8, ie, request ? request->ie_len : 0)
__dynamic_array(u8, ie, request ? request->req.ie_len : 0)
__array(u32, rates, NUM_NL80211_BANDS)
__field(u32, wdev_id)
MAC_ENTRY(wiphy_mac)
@@ -3732,16 +3733,16 @@ TRACE_EVENT(cfg80211_scan_done,
),
TP_fast_assign(
if (request) {
memcpy(__get_dynamic_array(ie), request->ie,
request->ie_len);
memcpy(__entry->rates, request->rates,
memcpy(__get_dynamic_array(ie), request->req.ie,
request->req.ie_len);
memcpy(__entry->rates, request->req.rates,
NUM_NL80211_BANDS);
__entry->wdev_id = request->wdev ?
request->wdev->identifier : 0;
if (request->wiphy)
__entry->wdev_id = request->req.wdev ?
request->req.wdev->identifier : 0;
if (request->req.wiphy)
MAC_ASSIGN(wiphy_mac,
request->wiphy->perm_addr);
__entry->no_cck = request->no_cck;
request->req.wiphy->perm_addr);
__entry->no_cck = request->req.no_cck;
}
if (info) {
__entry->aborted = info->aborted;