mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-12-22 04:32:37 +01:00
scan: add hidden networks into the scan requests
To support an auto-connect for the hidden networks and having a limited number of SSIDs that can be appended into a probe request, introduced a concept of a command batch. Now, scan request may consist of a series of commands. The commands in the batch are triggered sequentially. Once we are notified about the results from a previous command, a consequent command in the batch is triggered. The collective results are reported once the batch is complete. On a command failure, the batch processing is canceled and scan request is removed
This commit is contained in:
parent
87108984bc
commit
c33deb7a0a
194
src/scan.c
194
src/scan.c
@ -38,6 +38,8 @@
|
|||||||
#include "src/wiphy.h"
|
#include "src/wiphy.h"
|
||||||
#include "src/netdev.h"
|
#include "src/netdev.h"
|
||||||
#include "src/ie.h"
|
#include "src/ie.h"
|
||||||
|
#include "src/common.h"
|
||||||
|
#include "src/network.h"
|
||||||
#include "src/scan.h"
|
#include "src/scan.h"
|
||||||
|
|
||||||
#define SCAN_MAX_INTERVAL 320
|
#define SCAN_MAX_INTERVAL 320
|
||||||
@ -68,7 +70,7 @@ struct scan_request {
|
|||||||
scan_destroy_func_t destroy;
|
scan_destroy_func_t destroy;
|
||||||
bool passive:1; /* Active or Passive scan? */
|
bool passive:1; /* Active or Passive scan? */
|
||||||
bool triggered:1;
|
bool triggered:1;
|
||||||
struct l_genl_msg *start_cmd;
|
struct l_queue *cmds;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct scan_context {
|
struct scan_context {
|
||||||
@ -106,12 +108,20 @@ static bool scan_request_match(const void *a, const void *b)
|
|||||||
return sr->id == id;
|
return sr->id == id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void scan_cmd_free(void *data)
|
||||||
|
{
|
||||||
|
struct l_genl_msg *cmd = data;
|
||||||
|
|
||||||
|
l_genl_msg_unref(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
static void scan_request_free(void *data)
|
static void scan_request_free(void *data)
|
||||||
{
|
{
|
||||||
struct scan_request *sr = data;
|
struct scan_request *sr = data;
|
||||||
|
|
||||||
l_genl_msg_unref(sr->start_cmd);
|
l_queue_destroy(sr->cmds, scan_cmd_free);
|
||||||
free(sr);
|
|
||||||
|
l_free(sr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct scan_context *scan_context_new(uint32_t ifindex)
|
static struct scan_context *scan_context_new(uint32_t ifindex)
|
||||||
@ -274,7 +284,8 @@ static void scan_freq_count(uint32_t freq, void *user_data)
|
|||||||
*count += 1;
|
*count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct l_genl_msg *scan_build_cmd(struct scan_context *sc, bool passive,
|
static struct l_genl_msg *scan_build_cmd(struct scan_context *sc,
|
||||||
|
bool ignore_flush_flag,
|
||||||
const struct scan_parameters *params)
|
const struct scan_parameters *params)
|
||||||
{
|
{
|
||||||
struct l_genl_msg *msg;
|
struct l_genl_msg *msg;
|
||||||
@ -288,21 +299,9 @@ static struct l_genl_msg *scan_build_cmd(struct scan_context *sc, bool passive,
|
|||||||
msg = l_genl_msg_new_sized(NL80211_CMD_TRIGGER_SCAN,
|
msg = l_genl_msg_new_sized(NL80211_CMD_TRIGGER_SCAN,
|
||||||
64 + params->extra_ie_size +
|
64 + params->extra_ie_size +
|
||||||
4 * n_channels);
|
4 * n_channels);
|
||||||
|
|
||||||
l_genl_msg_append_attr(msg, NL80211_ATTR_IFINDEX, 4, &sc->ifindex);
|
l_genl_msg_append_attr(msg, NL80211_ATTR_IFINDEX, 4, &sc->ifindex);
|
||||||
|
|
||||||
if (!passive) {
|
|
||||||
l_genl_msg_enter_nested(msg, NL80211_ATTR_SCAN_SSIDS);
|
|
||||||
|
|
||||||
if (params->ssid)
|
|
||||||
l_genl_msg_append_attr(msg, NL80211_ATTR_SSID,
|
|
||||||
strlen(params->ssid),
|
|
||||||
params->ssid);
|
|
||||||
else
|
|
||||||
l_genl_msg_append_attr(msg, NL80211_ATTR_SSID, 0, NULL);
|
|
||||||
|
|
||||||
l_genl_msg_leave_nested(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (params->extra_ie && params->extra_ie_size)
|
if (params->extra_ie && params->extra_ie_size)
|
||||||
l_genl_msg_append_attr(msg, NL80211_ATTR_IE,
|
l_genl_msg_append_attr(msg, NL80211_ATTR_IE,
|
||||||
params->extra_ie_size,
|
params->extra_ie_size,
|
||||||
@ -311,7 +310,7 @@ static struct l_genl_msg *scan_build_cmd(struct scan_context *sc, bool passive,
|
|||||||
if (params->freqs)
|
if (params->freqs)
|
||||||
scan_build_attr_scan_frequencies(msg, params->freqs);
|
scan_build_attr_scan_frequencies(msg, params->freqs);
|
||||||
|
|
||||||
if (params->flush)
|
if (params->flush && !ignore_flush_flag)
|
||||||
flags |= NL80211_SCAN_FLAG_FLUSH;
|
flags |= NL80211_SCAN_FLAG_FLUSH;
|
||||||
|
|
||||||
if (flags)
|
if (flags)
|
||||||
@ -320,6 +319,98 @@ static struct l_genl_msg *scan_build_cmd(struct scan_context *sc, bool passive,
|
|||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void scan_cmds_add(struct l_queue *cmds, struct scan_context *sc,
|
||||||
|
bool passive,
|
||||||
|
const struct scan_parameters *params)
|
||||||
|
{
|
||||||
|
const struct l_queue *networks;
|
||||||
|
struct l_genl_msg *cmd;
|
||||||
|
uint8_t max_ssids_per_scan;
|
||||||
|
uint8_t num_ssids_can_append;
|
||||||
|
const struct l_queue_entry *entry;
|
||||||
|
|
||||||
|
cmd = scan_build_cmd(sc, false, params);
|
||||||
|
|
||||||
|
if (passive) {
|
||||||
|
/* passive scan */
|
||||||
|
l_queue_push_tail(cmds, cmd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
l_genl_msg_enter_nested(cmd, NL80211_ATTR_SCAN_SSIDS);
|
||||||
|
|
||||||
|
if (params->ssid) {
|
||||||
|
/* direct probe request scan */
|
||||||
|
l_genl_msg_append_attr(cmd, NL80211_ATTR_SSID,
|
||||||
|
strlen(params->ssid), params->ssid);
|
||||||
|
l_genl_msg_leave_nested(cmd);
|
||||||
|
|
||||||
|
l_queue_push_tail(cmds, cmd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
num_ssids_can_append = max_ssids_per_scan =
|
||||||
|
wiphy_get_max_num_ssids_per_scan(sc->wiphy);
|
||||||
|
networks = network_info_get_known();
|
||||||
|
|
||||||
|
for (entry = l_queue_get_entries((void *) networks); entry;
|
||||||
|
entry = entry->next) {
|
||||||
|
const struct network_info *network = entry->data;
|
||||||
|
|
||||||
|
if (!network->is_hidden)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
l_genl_msg_append_attr(cmd, NL80211_ATTR_SSID,
|
||||||
|
strlen(network->ssid), network->ssid);
|
||||||
|
num_ssids_can_append--;
|
||||||
|
|
||||||
|
if (!num_ssids_can_append) {
|
||||||
|
l_genl_msg_leave_nested(cmd);
|
||||||
|
l_queue_push_tail(cmds, cmd);
|
||||||
|
|
||||||
|
num_ssids_can_append = max_ssids_per_scan;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a consecutive scan trigger in the batch of
|
||||||
|
* scans. The 'flush' flag is ignored, this allows to
|
||||||
|
* get the results of all scans in the batch after the
|
||||||
|
* last scan is finished.
|
||||||
|
*/
|
||||||
|
cmd = scan_build_cmd(sc, true, params);
|
||||||
|
l_genl_msg_enter_nested(cmd, NL80211_ATTR_SCAN_SSIDS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
l_genl_msg_append_attr(cmd, NL80211_ATTR_SSID, 0, NULL);
|
||||||
|
l_genl_msg_leave_nested(cmd);
|
||||||
|
l_queue_push_tail(cmds, cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool scan_request_send_first_cmd(struct scan_context *sc,
|
||||||
|
struct scan_request *sr)
|
||||||
|
{
|
||||||
|
struct l_genl_msg *cmd = l_queue_pop_head(sr->cmds);
|
||||||
|
if (!cmd)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
sc->start_cmd_id = scan_send_start(&cmd, scan_triggered, sc);
|
||||||
|
|
||||||
|
if (sc->start_cmd_id)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
scan_cmd_free(cmd);
|
||||||
|
error:
|
||||||
|
if (sr->trigger)
|
||||||
|
sr->trigger(-EIO, sr->userdata);
|
||||||
|
|
||||||
|
if (sr->destroy)
|
||||||
|
sr->destroy(sr->userdata);
|
||||||
|
|
||||||
|
scan_request_free(sr);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static uint32_t scan_common(uint32_t ifindex, bool passive,
|
static uint32_t scan_common(uint32_t ifindex, bool passive,
|
||||||
const struct scan_parameters *params,
|
const struct scan_parameters *params,
|
||||||
scan_trigger_func_t trigger,
|
scan_trigger_func_t trigger,
|
||||||
@ -342,10 +433,9 @@ static uint32_t scan_common(uint32_t ifindex, bool passive,
|
|||||||
sr->destroy = destroy;
|
sr->destroy = destroy;
|
||||||
sr->passive = passive;
|
sr->passive = passive;
|
||||||
sr->id = ++next_scan_request_id;
|
sr->id = ++next_scan_request_id;
|
||||||
|
sr->cmds = l_queue_new();
|
||||||
|
|
||||||
sr->start_cmd = scan_build_cmd(sc, passive, params);
|
scan_cmds_add(sr->cmds, sc, passive, params);
|
||||||
if (!sr->start_cmd)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
if (l_queue_length(sc->requests) > 0)
|
if (l_queue_length(sc->requests) > 0)
|
||||||
goto done;
|
goto done;
|
||||||
@ -353,13 +443,9 @@ static uint32_t scan_common(uint32_t ifindex, bool passive,
|
|||||||
if (sc->state != SCAN_STATE_NOT_RUNNING || sc->start_cmd_id)
|
if (sc->state != SCAN_STATE_NOT_RUNNING || sc->start_cmd_id)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
sc->start_cmd_id = scan_send_start(&sr->start_cmd, scan_triggered, sc);
|
if (scan_request_send_first_cmd(sc, sr))
|
||||||
if (sc->start_cmd_id > 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
error:
|
|
||||||
scan_request_free(sr);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
done:
|
done:
|
||||||
l_queue_push_tail(sc->requests, sr);
|
l_queue_push_tail(sc->requests, sr);
|
||||||
@ -415,8 +501,8 @@ bool scan_cancel(uint32_t ifindex, uint32_t id)
|
|||||||
if (!sr)
|
if (!sr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (sr->id == id) {
|
||||||
/* If we already sent the trigger command, cancel the scan */
|
/* If we already sent the trigger command, cancel the scan */
|
||||||
if (sr->id == id && !sr->start_cmd) {
|
|
||||||
if (!sr->triggered && sc->start_cmd_id) {
|
if (!sr->triggered && sc->start_cmd_id) {
|
||||||
l_genl_family_cancel(nl80211, sc->start_cmd_id);
|
l_genl_family_cancel(nl80211, sc->start_cmd_id);
|
||||||
sc->start_cmd_id = 0;
|
sc->start_cmd_id = 0;
|
||||||
@ -614,20 +700,10 @@ static bool start_next_scan_request(struct scan_context *sc)
|
|||||||
while (!l_queue_isempty(sc->requests)) {
|
while (!l_queue_isempty(sc->requests)) {
|
||||||
sr = l_queue_peek_head(sc->requests);
|
sr = l_queue_peek_head(sc->requests);
|
||||||
|
|
||||||
sc->start_cmd_id = scan_send_start(&sr->start_cmd,
|
if (scan_request_send_first_cmd(sc, sr))
|
||||||
scan_triggered, sc);
|
|
||||||
|
|
||||||
if (sc->start_cmd_id)
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (sr->trigger)
|
l_queue_pop_head(sc->requests);
|
||||||
sr->trigger(-EIO, sr->userdata);
|
|
||||||
|
|
||||||
if (sr->destroy)
|
|
||||||
sr->destroy(sr->userdata);
|
|
||||||
|
|
||||||
sr = l_queue_pop_head(sc->requests);
|
|
||||||
scan_request_free(sr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sc->sp.retry) {
|
if (sc->sp.retry) {
|
||||||
@ -1078,6 +1154,43 @@ static void scan_parse_new_scan_results(struct l_genl_msg *msg,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool scan_send_next_cmd(struct scan_context *sc)
|
||||||
|
{
|
||||||
|
struct scan_request *sr = l_queue_peek_head(sc->requests);
|
||||||
|
struct l_genl_msg *cmd;
|
||||||
|
|
||||||
|
if (sr && sr->triggered) {
|
||||||
|
cmd = l_queue_pop_head(sr->cmds);
|
||||||
|
if (!cmd)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
sr->triggered = false;
|
||||||
|
|
||||||
|
sc->start_cmd_id = scan_send_start(&cmd, scan_triggered, sc);
|
||||||
|
if (sc->start_cmd_id)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
scan_cmd_free(cmd);
|
||||||
|
|
||||||
|
if (sr->trigger)
|
||||||
|
sr->trigger(-EIO, sr->userdata);
|
||||||
|
|
||||||
|
if (sr->destroy)
|
||||||
|
sr->destroy(sr->userdata);
|
||||||
|
|
||||||
|
sr = l_queue_pop_head(sc->requests);
|
||||||
|
scan_request_free(sr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The request is destroyed, return 'true' to stop further
|
||||||
|
* processing.
|
||||||
|
*/
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static void scan_notify(struct l_genl_msg *msg, void *user_data)
|
static void scan_notify(struct l_genl_msg *msg, void *user_data)
|
||||||
{
|
{
|
||||||
struct l_genl_attr attr;
|
struct l_genl_attr attr;
|
||||||
@ -1146,6 +1259,9 @@ static void scan_notify(struct l_genl_msg *msg, void *user_data)
|
|||||||
struct l_genl_msg *scan_msg;
|
struct l_genl_msg *scan_msg;
|
||||||
struct scan_results *results;
|
struct scan_results *results;
|
||||||
|
|
||||||
|
if (scan_send_next_cmd(sc))
|
||||||
|
return;
|
||||||
|
|
||||||
results = l_new(struct scan_results, 1);
|
results = l_new(struct scan_results, 1);
|
||||||
results->wiphy = attr_wiphy;
|
results->wiphy = attr_wiphy;
|
||||||
results->ifindex = attr_ifindex;
|
results->ifindex = attr_ifindex;
|
||||||
|
Loading…
Reference in New Issue
Block a user