Maintain list of BSS entries in last scan result order
[mech_eap.git] / wpa_supplicant / bss.c
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);
 }