Fix SCAN control interface command error cases

Update the scan parameters in wpa_s only in case the scan command is
going to be executed. In other words, do not change the parameters for
an ongoing scan (the SCAN command is rejected with FAIL-BUSY) or if any
of the parameters is invalid.

Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2014-12-12 01:12:15 +02:00
parent 530b519f78
commit 43a66ecba3

View File

@ -6217,31 +6217,17 @@ static void wpas_ctrl_eapol_response(void *eloop_ctx, void *timeout_ctx)
}
static int set_scan_freqs(struct wpa_supplicant *wpa_s, char *val)
{
int *freqs = NULL;
freqs = freq_range_to_channel_list(wpa_s, val);
if (freqs == NULL)
return -1;
os_free(wpa_s->manual_scan_freqs);
wpa_s->manual_scan_freqs = freqs;
return 0;
}
static int scan_id_list_parse(struct wpa_supplicant *wpa_s, const char *value)
static int scan_id_list_parse(struct wpa_supplicant *wpa_s, const char *value,
unsigned int *scan_id_count, int scan_id[])
{
const char *pos = value;
while (pos) {
if (*pos == ' ' || *pos == '\0')
break;
if (wpa_s->scan_id_count == MAX_SCAN_ID)
if (*scan_id_count == MAX_SCAN_ID)
return -1;
wpa_s->scan_id[wpa_s->scan_id_count++] = atoi(pos);
scan_id[(*scan_id_count)++] = atoi(pos);
pos = os_strchr(pos, ',');
if (pos)
pos++;
@ -6255,54 +6241,75 @@ static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params,
char *reply, int reply_size, int *reply_len)
{
char *pos;
unsigned int manual_scan_passive = 0;
unsigned int manual_scan_use_id = 0;
unsigned int manual_scan_only_new = 0;
unsigned int scan_only = 0;
unsigned int scan_id_count = 0;
int scan_id[MAX_SCAN_ID];
void (*scan_res_handler)(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res);
int *manual_scan_freqs = NULL;
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
*reply_len = -1;
return;
}
wpa_s->manual_scan_passive = 0;
wpa_s->manual_scan_use_id = 0;
wpa_s->manual_scan_only_new = 0;
wpa_s->scan_id_count = 0;
if (params) {
if (os_strncasecmp(params, "TYPE=ONLY", 9) == 0)
wpa_s->scan_res_handler = scan_only_handler;
scan_only = 1;
pos = os_strstr(params, "freq=");
if (pos && set_scan_freqs(wpa_s, pos + 5) < 0) {
*reply_len = -1;
return;
if (pos) {
manual_scan_freqs = freq_range_to_channel_list(wpa_s,
pos + 5);
if (manual_scan_freqs == NULL) {
*reply_len = -1;
goto done;
}
}
pos = os_strstr(params, "passive=");
if (pos)
wpa_s->manual_scan_passive = !!atoi(pos + 8);
manual_scan_passive = !!atoi(pos + 8);
pos = os_strstr(params, "use_id=");
if (pos)
wpa_s->manual_scan_use_id = atoi(pos + 7);
manual_scan_use_id = atoi(pos + 7);
pos = os_strstr(params, "only_new=1");
if (pos)
wpa_s->manual_scan_only_new = 1;
manual_scan_only_new = 1;
pos = os_strstr(params, "scan_id=");
if (pos && scan_id_list_parse(wpa_s, pos + 8) < 0) {
if (pos && scan_id_list_parse(wpa_s, pos + 8, &scan_id_count,
scan_id) < 0) {
*reply_len = -1;
return;
goto done;
}
} else {
os_free(wpa_s->manual_scan_freqs);
wpa_s->manual_scan_freqs = NULL;
if (wpa_s->scan_res_handler == scan_only_handler)
wpa_s->scan_res_handler = NULL;
}
if (scan_only)
scan_res_handler = scan_only_handler;
else if (wpa_s->scan_res_handler == scan_only_handler)
scan_res_handler = NULL;
else
scan_res_handler = wpa_s->scan_res_handler;
if (!wpa_s->sched_scanning && !wpa_s->scanning &&
((wpa_s->wpa_state <= WPA_SCANNING) ||
(wpa_s->wpa_state == WPA_COMPLETED))) {
wpa_s->manual_scan_passive = manual_scan_passive;
wpa_s->manual_scan_use_id = manual_scan_use_id;
wpa_s->manual_scan_only_new = manual_scan_only_new;
wpa_s->scan_id_count = scan_id_count;
os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int));
wpa_s->scan_res_handler = scan_res_handler;
os_free(wpa_s->manual_scan_freqs);
wpa_s->manual_scan_freqs = manual_scan_freqs;
manual_scan_freqs = NULL;
wpa_s->normal_scans = 0;
wpa_s->scan_req = MANUAL_SCAN_REQ;
wpa_s->after_wps = 0;
@ -6316,6 +6323,16 @@ static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params,
wpa_s->manual_scan_id);
}
} else if (wpa_s->sched_scanning) {
wpa_s->manual_scan_passive = manual_scan_passive;
wpa_s->manual_scan_use_id = manual_scan_use_id;
wpa_s->manual_scan_only_new = manual_scan_only_new;
wpa_s->scan_id_count = scan_id_count;
os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int));
wpa_s->scan_res_handler = scan_res_handler;
os_free(wpa_s->manual_scan_freqs);
wpa_s->manual_scan_freqs = manual_scan_freqs;
manual_scan_freqs = NULL;
wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to allow requested full scan to proceed");
wpa_supplicant_cancel_sched_scan(wpa_s);
wpa_s->scan_req = MANUAL_SCAN_REQ;
@ -6331,6 +6348,9 @@ static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params,
wpa_printf(MSG_DEBUG, "Ongoing scan action - reject new request");
*reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
}
done:
os_free(manual_scan_freqs);
}