@@ -2490,6 +2490,7 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
int ap = 0;
bool trigger_6ghz_scan;
bool short_ssid_match_found = false;
+ size_t idx;
#ifndef CONFIG_NO_RANDOM_POOL
size_t i, num;
#endif /* CONFIG_NO_RANDOM_POOL */
@@ -2555,7 +2556,23 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
}
#endif /* CONFIG_NO_RANDOM_POOL */
- wpa_s->last_scan_external = data && data->scan_info.external_scan;
+ if (data) {
+ wpa_s->last_scan_external = data->scan_info.external_scan;
+ wpa_s->last_scan_num_ssids = data->scan_info.num_ssids;
+ for (idx = 0; idx < wpa_s->last_scan_num_ssids; idx++) {
+ /* Copy the SSID and its length */
+ if (data->scan_info.ssids[idx].ssid_len > SSID_MAX_LEN)
+ continue;
+
+ os_memcpy(wpa_s->last_scan_ssids[idx].ssid,
+ data->scan_info.ssids[idx].ssid,
+ data->scan_info.ssids[idx].ssid_len);
+ wpa_s->last_scan_ssids[idx].ssid[data->scan_info.ssids[idx].ssid_len] =
+ '\0';
+ wpa_s->last_scan_ssids[idx].ssid_len =
+ data->scan_info.ssids[idx].ssid_len;
+ }
+ }
if (update_only) {
ret = 1;
@@ -5104,6 +5104,30 @@ void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
}
}
+/**
+ * Checks whether the ssid was discovered in the last scan.
+ * @wpa_s: wpa_supplicant structure for a network interface.
+ * @ssid: wpa_ssid structure for a configured network.
+ * Returns: true if ssid found, false otherwise.
+ */
+static inline bool check_ssid_last_scan(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid)
+{
+ int i;
+
+ if (wpa_s->last_scan_res != NULL &&
+ wpa_s->last_scan_res_used != 0) {
+ for (i = 0; i < wpa_s->last_scan_res_used; i++) {
+ if (os_memcmp(wpa_s->last_scan_res[i]->ssid,
+ ssid->ssid, ssid->ssid_len) == 0) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
/**
* wpa_supplicant_select_network - Attempt association with a network
@@ -5116,7 +5140,10 @@ void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
struct wpa_ssid *other_ssid;
int disconnected = 0;
+ int i;
bool request_new_scan = false;
+ bool ssid_scanned = false;
+
if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
@@ -5162,11 +5189,34 @@ void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
(ssid->mode == WPAS_MODE_MESH ||
ssid->mode == WPAS_MODE_AP) ? ssid : NULL;
- if (ssid->scan_ssid &&
- (wpa_s->no_suitable_network || wpa_s->last_scan_external)) {
- wpa_printf(MSG_DEBUG,
- "Request a new scan for hidden network");
- request_new_scan = true;
+ if (ssid->scan_ssid) {
+ /* Check if the previous scan included the selected network */
+ if (wpa_s->last_scan_num_ssids > 1) {
+ ssid_scanned = false;
+ /* Iterate through the previous scan SSIDs */
+ for (i = 0; i < wpa_s->last_scan_num_ssids; i++) {
+ if (os_memcmp(wpa_s->last_scan_ssids[i].ssid,
+ ssid->ssid, ssid->ssid_len) == 0) {
+ ssid_scanned = true;
+ break;
+ }
+ }
+ }
+
+ if (!ssid_scanned) {
+ /* Check if ssid is found in previous scan */
+ if (check_ssid_last_scan(wpa_s, ssid)) {
+ wpa_printf(MSG_DEBUG,
+ "Hidden network was found in last scan results");
+ } else {
+ request_new_scan = true;
+ wpa_printf(MSG_DEBUG,
+ "Request a new scan for hidden network");
+ }
+ } else {
+ wpa_printf(MSG_DEBUG,
+ "Hidden network was scanned for in last scan");
+ }
} else if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
!ssid->owe_only) {
wpa_printf(MSG_DEBUG,
@@ -668,6 +668,11 @@ struct ml_sta_link_info {
u16 status;
};
+struct last_scan_ssid {
+ u8 ssid[SSID_MAX_LEN + 1];
+ size_t ssid_len;
+};
+
/**
* struct wpa_supplicant - Internal data for wpa_supplicant interface
@@ -806,6 +811,9 @@ struct wpa_supplicant {
size_t last_scan_res_size;
struct os_reltime last_scan;
bool last_scan_external;
+ struct last_scan_ssid last_scan_ssids[WPAS_MAX_SCAN_SSIDS];
+ size_t last_scan_num_ssids;
+
const struct wpa_driver_ops *driver;
int interface_removed; /* whether the network interface has been
This recent patch [1] introduced a redundant scan when selecting a hidden network that was previously scanned and found. This occurs because the code only checks for the condition `(wpa_s->no_suitable_network || wpa_s->last_scan_external)`, which doesn't cover the case where the last scan successfully found the hidden SSID. This patch saves the scanned SSIDs from the last scan and updates the condition to check if the hidden SSID was included. If the hidden SSID is not found in `last_scan_ssids`, the code checks if the SSID was found in earlier scan results. If not, it triggers a new scan. If the SSID is found, a new scan is avoided, resulting in faster connection times. [1] https://w1.fi/cgit/hostap/commit/?id=92374d59d4efea5c8b61ed2ceef141c26bcd7f99 Signed-off-by: Arowa Suliman <arowa@chromium.org> --- wpa_supplicant/events.c | 19 +++++++++- wpa_supplicant/wpa_supplicant.c | 60 ++++++++++++++++++++++++++++--- wpa_supplicant/wpa_supplicant_i.h | 8 +++++ 3 files changed, 81 insertions(+), 6 deletions(-)