Maintain list of BSS entries in last scan result order

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>
This commit is contained in:
Jouni Malinen 2012-09-02 19:53:15 +03:00
parent 20ed5e40ba
commit a297201df1
3 changed files with 74 additions and 5 deletions

View file

@ -38,6 +38,19 @@
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);
}

View 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;
}

View 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 */