bgscan learn: Probe one new channel at a time to find APs

This allows APs to be found from channels that have not previously
been observed to contain APs for this ESS.
This commit is contained in:
Jouni Malinen 2010-07-10 18:09:41 -07:00
parent fc480e88bf
commit 2e2a8d073d

View file

@ -41,6 +41,8 @@ struct bgscan_learn_data {
struct os_time last_bgscan;
char *fname;
struct dl_list bss;
int *supp_freqs;
int probe_idx;
};
@ -168,13 +170,47 @@ static int * bgscan_learn_get_freqs(struct bgscan_learn_data *data,
}
static int * bgscan_learn_get_probe_freq(struct bgscan_learn_data *data,
int *freqs, size_t count)
{
int idx, *n;
if (data->supp_freqs == NULL)
return freqs;
idx = data->probe_idx + 1;
while (idx != data->probe_idx) {
if (data->supp_freqs[idx] == 0)
idx = 0;
if (!in_array(freqs, data->supp_freqs[idx])) {
wpa_printf(MSG_DEBUG, "bgscan learn: Probe new freq "
"%u", data->supp_freqs[idx]);
data->probe_idx = idx;
n = os_realloc(freqs, (count + 2) * sizeof(int));
if (n == NULL)
return freqs;
freqs = n;
freqs[count] = data->supp_freqs[idx];
count++;
freqs[count] = 0;
break;
}
idx++;
}
return freqs;
}
static void bgscan_learn_timeout(void *eloop_ctx, void *timeout_ctx)
{
struct bgscan_learn_data *data = eloop_ctx;
struct wpa_supplicant *wpa_s = data->wpa_s;
struct wpa_driver_scan_params params;
int *freqs = NULL;
size_t count;
size_t count, i;
char msg[100], *pos;
os_memset(&params, 0, sizeof(params));
params.num_ssids = 1;
@ -186,10 +222,21 @@ static void bgscan_learn_timeout(void *eloop_ctx, void *timeout_ctx)
freqs = bgscan_learn_get_freqs(data, &count);
wpa_printf(MSG_DEBUG, "bgscan learn: BSSes in this ESS have "
"been seen on %u channels", (unsigned int) count);
/*
* TODO: add other frequencies (rotate through one or couple at
* a time, etc., to find APs from new channels)
*/
freqs = bgscan_learn_get_probe_freq(data, freqs, count);
msg[0] = '\0';
pos = msg;
for (i = 0; freqs && freqs[i]; i++) {
int ret;
ret = os_snprintf(pos, msg + sizeof(msg) - pos, " %d",
freqs[i]);
if (ret < 0 || ret >= msg + sizeof(msg) - pos)
break;
pos += ret;
}
pos[0] = '\0';
wpa_printf(MSG_DEBUG, "bgscan learn: Scanning frequencies:%s",
msg);
params.freqs = freqs;
}
@ -237,6 +284,39 @@ static int bgscan_learn_get_params(struct bgscan_learn_data *data,
}
static int * bgscan_learn_get_supp_freqs(struct wpa_supplicant *wpa_s)
{
struct hostapd_hw_modes *modes;
u16 num_modes, flags;
int i, j, *freqs = NULL, *n;
size_t count = 0;
modes = wpa_drv_get_hw_feature_data(wpa_s, &num_modes, &flags);
if (!modes)
return NULL;
for (i = 0; i < num_modes; i++) {
for (j = 0; j < modes[i].num_channels; j++) {
if (modes[i].channels[j].flag & HOSTAPD_CHAN_DISABLED)
continue;
n = os_realloc(freqs, (count + 2) * sizeof(int));
if (!n)
continue;
freqs = n;
freqs[count] = modes[i].channels[j].freq;
count++;
freqs[count] = 0;
}
os_free(modes[i].channels);
os_free(modes[i].rates);
}
os_free(modes);
return freqs;
}
static void * bgscan_learn_init(struct wpa_supplicant *wpa_s,
const char *params,
const struct wpa_ssid *ssid)
@ -276,6 +356,7 @@ static void * bgscan_learn_init(struct wpa_supplicant *wpa_s,
"signal strength monitoring");
}
data->supp_freqs = bgscan_learn_get_supp_freqs(wpa_s);
data->scan_interval = data->short_interval;
eloop_register_timeout(data->scan_interval, 0, bgscan_learn_timeout,
data, NULL);
@ -298,6 +379,7 @@ static void bgscan_learn_deinit(void *priv)
dl_list_del(&bss->list);
os_free(bss);
}
os_free(data->supp_freqs);
os_free(data);
}