mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-12-22 21:22:37 +01:00
scan: add scan API specifically for OWE transition networks
Specifically OWE networks with multiple open/hidden BSS's are troublesome to scan for with the current APIs. The scan parameters are limited to a single SSID and even if that was changed we have the potential of hitting the max SSID's per scan limit. In all, it puts the burden onto the caller to sort out the SSIDs/frequencies to scan for. Rather than requiring station to handle this a new scan API was added, scan_owe_hidden() which takes a list of open BSS's and will automatically scan for the SSIDs in the OWE transition IE for each. It is slightly optimized to first check if all the hidden SSID's are the same. This is the most likely case (e.g. single pair or single network) and a single scan command can be used. Otherwise individual scan commands are queued for each SSID/frequency combo.
This commit is contained in:
parent
c235c9fa54
commit
a6c4972290
139
src/scan.c
139
src/scan.c
@ -583,6 +583,27 @@ static const struct wiphy_radio_work_item_ops work_ops = {
|
|||||||
.destroy = scan_request_free,
|
.destroy = scan_request_free,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct scan_request *scan_request_new(struct scan_context *sc,
|
||||||
|
bool passive,
|
||||||
|
scan_trigger_func_t trigger,
|
||||||
|
scan_notify_func_t notify,
|
||||||
|
void *userdata,
|
||||||
|
scan_destroy_func_t destroy)
|
||||||
|
{
|
||||||
|
struct scan_request *sr;
|
||||||
|
|
||||||
|
sr = l_new(struct scan_request, 1);
|
||||||
|
sr->sc = sc;
|
||||||
|
sr->trigger = trigger;
|
||||||
|
sr->callback = notify;
|
||||||
|
sr->userdata = userdata;
|
||||||
|
sr->destroy = destroy;
|
||||||
|
sr->passive = passive;
|
||||||
|
sr->cmds = l_queue_new();
|
||||||
|
|
||||||
|
return sr;
|
||||||
|
}
|
||||||
|
|
||||||
static uint32_t scan_common(uint64_t wdev_id, bool passive,
|
static uint32_t scan_common(uint64_t wdev_id, bool passive,
|
||||||
const struct scan_parameters *params,
|
const struct scan_parameters *params,
|
||||||
scan_trigger_func_t trigger,
|
scan_trigger_func_t trigger,
|
||||||
@ -597,14 +618,7 @@ static uint32_t scan_common(uint64_t wdev_id, bool passive,
|
|||||||
if (!sc)
|
if (!sc)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
sr = l_new(struct scan_request, 1);
|
sr = scan_request_new(sc, passive, trigger, notify, userdata, destroy);
|
||||||
sr->sc = sc;
|
|
||||||
sr->trigger = trigger;
|
|
||||||
sr->callback = notify;
|
|
||||||
sr->userdata = userdata;
|
|
||||||
sr->destroy = destroy;
|
|
||||||
sr->passive = passive;
|
|
||||||
sr->cmds = l_queue_new();
|
|
||||||
|
|
||||||
scan_cmds_add(sr->cmds, sc, passive, params);
|
scan_cmds_add(sr->cmds, sc, passive, params);
|
||||||
|
|
||||||
@ -656,6 +670,115 @@ uint32_t scan_active_full(uint64_t wdev_id,
|
|||||||
trigger, notify, userdata, destroy);
|
trigger, notify, userdata, destroy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void add_owe_scan_cmd(struct scan_context *sc, struct scan_request *sr,
|
||||||
|
bool ignore_flush,
|
||||||
|
struct scan_freq_set *freqs,
|
||||||
|
const struct scan_bss *bss)
|
||||||
|
{
|
||||||
|
struct l_genl_msg *cmd;
|
||||||
|
struct scan_parameters params = {};
|
||||||
|
struct scan_freq_set *tmp;
|
||||||
|
|
||||||
|
if (!freqs) {
|
||||||
|
tmp = scan_freq_set_new();
|
||||||
|
scan_freq_set_add(tmp, bss->frequency);
|
||||||
|
params.freqs = tmp;
|
||||||
|
} else
|
||||||
|
params.freqs = freqs;
|
||||||
|
|
||||||
|
params.ssid = bss->owe_trans_ssid;
|
||||||
|
params.ssid_len = bss->owe_trans_ssid_len;
|
||||||
|
params.flush = true;
|
||||||
|
|
||||||
|
cmd = scan_build_cmd(sc, ignore_flush, false, ¶ms);
|
||||||
|
|
||||||
|
l_genl_msg_enter_nested(cmd, NL80211_ATTR_SCAN_SSIDS);
|
||||||
|
l_genl_msg_append_attr(cmd, 0, params.ssid_len, params.ssid);
|
||||||
|
l_genl_msg_leave_nested(cmd);
|
||||||
|
|
||||||
|
l_queue_push_tail(sr->cmds, cmd);
|
||||||
|
|
||||||
|
if (!freqs)
|
||||||
|
scan_freq_set_free(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t scan_owe_hidden(uint64_t wdev_id, struct l_queue *list,
|
||||||
|
scan_trigger_func_t trigger, scan_notify_func_t notify,
|
||||||
|
void *userdata, scan_destroy_func_t destroy)
|
||||||
|
{
|
||||||
|
struct scan_context *sc;
|
||||||
|
struct scan_request *sr;
|
||||||
|
struct scan_freq_set *freqs;
|
||||||
|
const struct l_queue_entry *entry;
|
||||||
|
const uint8_t *ssid = NULL;
|
||||||
|
size_t ssid_len;
|
||||||
|
bool same_ssid = true;
|
||||||
|
struct scan_bss *bss;
|
||||||
|
bool ignore_flush = false;
|
||||||
|
|
||||||
|
sc = l_queue_find(scan_contexts, scan_context_match, &wdev_id);
|
||||||
|
|
||||||
|
if (!sc)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
sr = scan_request_new(sc, false, trigger, notify, userdata, destroy);
|
||||||
|
|
||||||
|
freqs = scan_freq_set_new();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Start building up a frequency list if all SSIDs are the same. This
|
||||||
|
* is hopefully the common case and will allow a single scan command.
|
||||||
|
*/
|
||||||
|
for (entry = l_queue_get_entries(list); entry; entry = entry->next) {
|
||||||
|
bss = entry->data;
|
||||||
|
|
||||||
|
scan_freq_set_add(freqs, bss->frequency);
|
||||||
|
|
||||||
|
/* First */
|
||||||
|
if (!ssid) {
|
||||||
|
ssid = bss->owe_trans_ssid;
|
||||||
|
ssid_len = bss->owe_trans_ssid_len;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ssid_len == bss->owe_trans_ssid_len &&
|
||||||
|
!memcmp(ssid, bss->owe_trans_ssid,
|
||||||
|
bss->owe_trans_ssid_len))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
same_ssid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (same_ssid) {
|
||||||
|
bss = l_queue_peek_head(list);
|
||||||
|
|
||||||
|
add_owe_scan_cmd(sc, sr, ignore_flush, freqs, bss);
|
||||||
|
|
||||||
|
scan_freq_set_free(freqs);
|
||||||
|
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
scan_freq_set_free(freqs);
|
||||||
|
|
||||||
|
/* SSIDs differed, use separate scan commands. */
|
||||||
|
for (entry = l_queue_get_entries(list); entry; entry = entry->next) {
|
||||||
|
bss = entry->data;
|
||||||
|
|
||||||
|
add_owe_scan_cmd(sc, sr, ignore_flush, NULL, bss);
|
||||||
|
|
||||||
|
/* Ignore flush on all subsequent commands */
|
||||||
|
if (!ignore_flush)
|
||||||
|
ignore_flush = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
l_queue_push_tail(sc->requests, sr);
|
||||||
|
|
||||||
|
return wiphy_radio_work_insert(sc->wiphy, &sr->work, 2, &work_ops);
|
||||||
|
}
|
||||||
|
|
||||||
bool scan_cancel(uint64_t wdev_id, uint32_t id)
|
bool scan_cancel(uint64_t wdev_id, uint32_t id)
|
||||||
{
|
{
|
||||||
struct scan_context *sc;
|
struct scan_context *sc;
|
||||||
|
@ -147,6 +147,9 @@ uint32_t scan_active_full(uint64_t wdev_id,
|
|||||||
const struct scan_parameters *params,
|
const struct scan_parameters *params,
|
||||||
scan_trigger_func_t trigger, scan_notify_func_t notify,
|
scan_trigger_func_t trigger, scan_notify_func_t notify,
|
||||||
void *userdata, scan_destroy_func_t destroy);
|
void *userdata, scan_destroy_func_t destroy);
|
||||||
|
uint32_t scan_owe_hidden(uint64_t wdev_id, struct l_queue *list,
|
||||||
|
scan_trigger_func_t trigger, scan_notify_func_t notify,
|
||||||
|
void *userdata, scan_destroy_func_t destroy);
|
||||||
bool scan_cancel(uint64_t wdev_id, uint32_t id);
|
bool scan_cancel(uint64_t wdev_id, uint32_t id);
|
||||||
|
|
||||||
void scan_periodic_start(uint64_t wdev_id, scan_trigger_func_t trigger,
|
void scan_periodic_start(uint64_t wdev_id, scan_trigger_func_t trigger,
|
||||||
|
Loading…
Reference in New Issue
Block a user