diff mbox series

wpa_supplicant_select_network: check last scan ssids

Message ID 20241007163329.3060529-1-arowa@google.com
State New
Headers show
Series wpa_supplicant_select_network: check last scan ssids | expand

Commit Message

Arowa Suliman Oct. 7, 2024, 4:32 p.m. UTC
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`, it triggers a new scan
(`request_new_scan = true`).

[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   | 40 +++++++++++++++++++++++++++----
 wpa_supplicant/wpa_supplicant_i.h |  8 +++++++
 3 files changed, 61 insertions(+), 6 deletions(-)
diff mbox series

Patch

diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 7947b6f08..0557926b4 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -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;
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 031268a41..8bbbe2d07 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -5116,7 +5116,12 @@  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;
+	const char *current_ssid_name;
+	const char *prev_ssid_name;
+
 
 	if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
 		if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
@@ -5162,11 +5167,36 @@  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) {
+				current_ssid_name = wpa_ssid_txt(ssid->ssid, ssid->ssid_len);
+				ssid_scanned = false;
+				/* Iterate through the previous scan SSIDs */
+				for (i = 0; i < wpa_s->last_scan_num_ssids; i++) {
+					prev_ssid_name = wpa_ssid_txt(
+						wpa_s->last_scan_ssids[i].ssid,
+						wpa_s->last_scan_ssids[i].ssid_len);
+					if (os_strcmp(current_ssid_name, prev_ssid_name) == 0) {
+						ssid_scanned = true;
+						break;
+					}
+				}
+				if (!ssid_scanned) {
+					/* SSID not found in previous scan, request a new scan */
+					request_new_scan = true;
+				}
+			} else {
+				/* No previous scan or wildcard scan, request a new scan */
+				request_new_scan = true;
+			}
+
+			if (request_new_scan) {
+				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,
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 1f41c149e..b9f7e398b 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -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