]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Check last scan SSIDs before triggering new scan for hidden network
authorArowa Suliman <arowa@chromium.org>
Tue, 5 Nov 2024 05:36:11 +0000 (05:36 +0000)
committerJouni Malinen <j@w1.fi>
Fri, 27 Dec 2024 10:29:23 +0000 (12:29 +0200)
Commit 92374d59d4ef ("Enhance select_network() to trigger new scans in
some cases") 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.

Save 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.

Signed-off-by: Arowa Suliman <arowa@chromium.org>
wpa_supplicant/events.c
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant_i.h

index 279838afa2bf9fdef626831b0eecc9d921f9d990..77bc3c7a9cd00396817e5cd8b8fc7b5844a915de 100644 (file)
@@ -2560,7 +2560,27 @@ 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) {
+               size_t idx;
+
+               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 (idx >= WPAS_MAX_SCAN_SSIDS ||
+                           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_len =
+                               data->scan_info.ssids[idx].ssid_len;
+               }
+       } else {
+               wpa_s->last_scan_external = false;
+               wpa_s->last_scan_num_ssids = 0;
+       }
 
        if (update_only) {
                ret = 1;
index cfa66da08bbbc3b61b99dd273751a453c4af6eba..5267ffb300edcdc1cb30b50a8f803b98f65e818d 100644 (file)
@@ -5278,6 +5278,51 @@ void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
 }
 
 
+static bool ssid_in_last_scan(struct wpa_supplicant *wpa_s,
+                             struct wpa_ssid *ssid)
+{
+       size_t i;
+
+       /* Check if the previous scan included the selected network */
+       if (wpa_s->last_scan_num_ssids <= 1 ||
+           !ssid->ssid || ssid->ssid_len == 0)
+               return 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)
+                       return true;
+       }
+
+       return false;
+}
+
+
+/**
+ * Checks whether an 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 bool ssid_in_last_scan_res(struct wpa_supplicant *wpa_s,
+                                 struct wpa_ssid *ssid)
+{
+       size_t i;
+
+       if (!wpa_s->last_scan_res || !ssid->ssid || ssid->ssid_len == 0)
+               return false;
+
+       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
  * @wpa_s: wpa_supplicant structure for a network interface
@@ -5335,13 +5380,22 @@ 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;
-               } else if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
-                          !ssid->owe_only) {
+               if (ssid->scan_ssid) {
+                       if (ssid_in_last_scan(wpa_s, ssid)) {
+                               wpa_printf(MSG_DEBUG,
+                                          "Hidden network was scanned for in last scan");
+                       } else if (ssid_in_last_scan_res(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");
+                       }
+               }
+
+               if (!request_new_scan && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
+                   !ssid->owe_only) {
                        wpa_printf(MSG_DEBUG,
                                   "Request a new scan for OWE transition SSID");
                        request_new_scan = true;
index 38ad4857ca285f9ccbdc00fd5bd7afb8bc948e96..726f7caec981238d9dd25d229a7a8800759d0c18 100644 (file)
@@ -676,6 +676,11 @@ enum local_hw_capab {
        CAPAB_EHT,
 };
 
+struct last_scan_ssid {
+       u8 ssid[SSID_MAX_LEN];
+       size_t ssid_len;
+};
+
 /**
  * struct wpa_supplicant - Internal data for wpa_supplicant interface
  *
@@ -813,6 +818,8 @@ 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