Maintain list of BSS entries in last scan result order
authorJouni Malinen <j@w1.fi>
Sun, 2 Sep 2012 16:53:15 +0000 (19:53 +0300)
committerJouni Malinen <j@w1.fi>
Sun, 2 Sep 2012 16:53:15 +0000 (19:53 +0300)
This allows last results to be used even after they have been freed
since the information is copied to the BSS entries anyway and this new
array provides the order in which scan results were processed.

Signed-hostap: Jouni Malinen <j@w1.fi>

wpa_supplicant/bss.c
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant_i.h

index 580a82a..434fb08 100644 (file)
 static void wpa_bss_remove(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
                           const char *reason)
 {
+       if (wpa_s->last_scan_res) {
+               unsigned int i;
+               for (i = 0; i < wpa_s->last_scan_res_used; i++) {
+                       if (wpa_s->last_scan_res[i] == bss) {
+                               os_memmove(&wpa_s->last_scan_res[i],
+                                          &wpa_s->last_scan_res[i + 1],
+                                          (wpa_s->last_scan_res_used - i - 1)
+                                          * sizeof(struct wpa_bss *));
+                               wpa_s->last_scan_res_used--;
+                               break;
+                       }
+               }
+       }
        dl_list_del(&bss->list);
        dl_list_del(&bss->list_id);
        wpa_s->num_bss--;
@@ -169,15 +182,15 @@ static int wpa_bss_remove_oldest(struct wpa_supplicant *wpa_s)
 }
 
 
-static void wpa_bss_add(struct wpa_supplicant *wpa_s,
-                       const u8 *ssid, size_t ssid_len,
-                       struct wpa_scan_res *res)
+static struct wpa_bss * wpa_bss_add(struct wpa_supplicant *wpa_s,
+                                   const u8 *ssid, size_t ssid_len,
+                                   struct wpa_scan_res *res)
 {
        struct wpa_bss *bss;
 
        bss = os_zalloc(sizeof(*bss) + res->ie_len + res->beacon_ie_len);
        if (bss == NULL)
-               return;
+               return NULL;
        bss->id = wpa_s->bss_next_id++;
        bss->last_update_idx = wpa_s->bss_update_idx;
        wpa_bss_copy_res(bss, res);
@@ -201,6 +214,7 @@ static void wpa_bss_add(struct wpa_supplicant *wpa_s,
                           "not get here!", (int) wpa_s->num_bss);
                wpa_s->conf->bss_max_count = wpa_s->num_bss;
        }
+       return bss;
 }
 
 
@@ -376,6 +390,7 @@ void wpa_bss_update_start(struct wpa_supplicant *wpa_s)
        wpa_s->bss_update_idx++;
        wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Start scan result update %u",
                wpa_s->bss_update_idx);
+       wpa_s->last_scan_res_used = 0;
 }
 
 
@@ -418,9 +433,28 @@ void wpa_bss_update_scan_res(struct wpa_supplicant *wpa_s,
         * (to save memory) */
        bss = wpa_bss_get(wpa_s, res->bssid, ssid + 2, ssid[1]);
        if (bss == NULL)
-               wpa_bss_add(wpa_s, ssid + 2, ssid[1], res);
+               bss = wpa_bss_add(wpa_s, ssid + 2, ssid[1], res);
        else
                wpa_bss_update(wpa_s, bss, res);
+
+       if (bss == NULL)
+               return;
+       if (wpa_s->last_scan_res_used >= wpa_s->last_scan_res_size) {
+               struct wpa_bss **n;
+               unsigned int siz;
+               if (wpa_s->last_scan_res_size == 0)
+                       siz = 32;
+               else
+                       siz = wpa_s->last_scan_res_size * 2;
+               n = os_realloc_array(wpa_s->last_scan_res, siz,
+                                    sizeof(struct wpa_bss *));
+               if (n == NULL)
+                       return;
+               wpa_s->last_scan_res = n;
+               wpa_s->last_scan_res_size = siz;
+       }
+
+       wpa_s->last_scan_res[wpa_s->last_scan_res_used++] = bss;
 }
 
 
@@ -470,9 +504,26 @@ void wpa_bss_update_end(struct wpa_supplicant *wpa_s, struct scan_info *info,
 {
        struct wpa_bss *bss, *n;
 
+       wpa_s->last_scan_full = 0;
+       os_get_time(&wpa_s->last_scan);
        if (!new_scan)
                return; /* do not expire entries without new scan */
 
+       if (info && !info->aborted && !info->freqs) {
+               size_t i;
+               if (info->num_ssids == 0) {
+                       wpa_s->last_scan_full = 1;
+               } else {
+                       for (i = 0; i < info->num_ssids; i++) {
+                               if (info->ssids[i].ssid == NULL ||
+                                   info->ssids[i].ssid_len == 0) {
+                                       wpa_s->last_scan_full = 1;
+                                       break;
+                               }
+                       }
+               }
+       }
+
        dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) {
                if (wpa_bss_in_use(wpa_s, bss))
                        continue;
@@ -485,6 +536,11 @@ void wpa_bss_update_end(struct wpa_supplicant *wpa_s, struct scan_info *info,
                        wpa_bss_remove(wpa_s, bss, "no match in scan");
                }
        }
+
+       wpa_printf(MSG_DEBUG, "BSS: last_scan_res_used=%u/%u "
+                  "last_scan_full=%d",
+                  wpa_s->last_scan_res_used, wpa_s->last_scan_res_size,
+                  wpa_s->last_scan_full);
 }
 
 
index 820cd5e..fdd322e 100644 (file)
@@ -476,6 +476,9 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
        wpa_s->ext_pw = NULL;
 
        wpabuf_free(wpa_s->last_gas_resp);
+
+       os_free(wpa_s->last_scan_res);
+       wpa_s->last_scan_res = NULL;
 }
 
 
index fb8dba8..42055ec 100644 (file)
@@ -347,6 +347,16 @@ struct wpa_supplicant {
        unsigned int bss_update_idx;
        unsigned int bss_next_id;
 
+        /*
+         * Pointers to BSS entries in the order they were in the last scan
+         * results.
+         */
+       struct wpa_bss **last_scan_res;
+       unsigned int last_scan_res_used;
+       unsigned int last_scan_res_size;
+       int last_scan_full;
+       struct os_time last_scan;
+
        struct wpa_driver_ops *driver;
        int interface_removed; /* whether the network interface has been
                                * removed */