From: Jouni Malinen Date: Thu, 11 Dec 2014 23:12:15 +0000 (+0200) Subject: Fix SCAN control interface command error cases X-Git-Tag: hostap_2_4~819 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=43a66ecba3f1ad41ab36f82d9e979ca5cef919d5;p=thirdparty%2Fhostap.git 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 --- diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 2713d115c..74fab9fdc 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -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); }