diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 4aa602d66..faf683c9c 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -6982,6 +6982,8 @@ static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params, void (*scan_res_handler)(struct wpa_supplicant *wpa_s, struct wpa_scan_results *scan_res); int *manual_scan_freqs = NULL; + struct wpa_ssid_value *ssid = NULL, *ns; + unsigned int ssid_count = 0; if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) { *reply_len = -1; @@ -7036,6 +7038,60 @@ static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params, *reply_len = -1; goto done; } + + pos = params; + while (pos && *pos != '\0') { + if (os_strncmp(pos, "ssid ", 5) == 0) { + char *end; + + pos += 5; + end = pos; + while (*end) { + if (*end == '\0' || *end == ' ') + break; + end++; + } + + ns = os_realloc_array( + ssid, ssid_count + 1, + sizeof(struct wpa_ssid_value)); + if (ns == NULL) { + *reply_len = -1; + goto done; + } + ssid = ns; + + if ((end - pos) & 0x01 || + end - pos > 2 * SSID_MAX_LEN || + hexstr2bin(pos, ssid[ssid_count].ssid, + (end - pos) / 2) < 0) { + wpa_printf(MSG_DEBUG, + "Invalid SSID value '%s'", + pos); + *reply_len = -1; + goto done; + } + ssid[ssid_count].ssid_len = (end - pos) / 2; + wpa_hexdump_ascii(MSG_DEBUG, "scan SSID", + ssid[ssid_count].ssid, + ssid[ssid_count].ssid_len); + ssid_count++; + pos = end; + } + + pos = os_strchr(pos, ' '); + if (pos) + pos++; + } + } + + wpa_s->num_ssids_from_scan_req = ssid_count; + os_free(wpa_s->ssids_from_scan_req); + if (ssid_count) { + wpa_s->ssids_from_scan_req = ssid; + ssid = NULL; + } else { + wpa_s->ssids_from_scan_req = NULL; } if (scan_only) @@ -7099,6 +7155,7 @@ static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params, done: os_free(manual_scan_freqs); + os_free(ssid); } diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index 3c6b2c7fb..e81465c5b 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -614,6 +614,37 @@ static void wpa_set_scan_ssids(struct wpa_supplicant *wpa_s, } +static int wpa_set_ssids_from_scan_req(struct wpa_supplicant *wpa_s, + struct wpa_driver_scan_params *params, + size_t max_ssids) +{ + unsigned int i; + + if (wpa_s->ssids_from_scan_req == NULL || + wpa_s->num_ssids_from_scan_req == 0) + return 0; + + if (wpa_s->num_ssids_from_scan_req > max_ssids) { + wpa_s->num_ssids_from_scan_req = max_ssids; + wpa_printf(MSG_DEBUG, "Over max scan SSIDs from scan req: %u", + (unsigned int) max_ssids); + } + + for (i = 0; i < wpa_s->num_ssids_from_scan_req; i++) { + params->ssids[i].ssid = wpa_s->ssids_from_scan_req[i].ssid; + params->ssids[i].ssid_len = + wpa_s->ssids_from_scan_req[i].ssid_len; + wpa_hexdump_ascii(MSG_DEBUG, "specific SSID", + params->ssids[i].ssid, + params->ssids[i].ssid_len); + } + + params->num_ssids = wpa_s->num_ssids_from_scan_req; + wpa_s->num_ssids_from_scan_req = 0; + return 1; +} + + static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) { struct wpa_supplicant *wpa_s = eloop_ctx; @@ -726,6 +757,12 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) goto scan; } + if (wpa_s->last_scan_req == MANUAL_SCAN_REQ && + wpa_set_ssids_from_scan_req(wpa_s, ¶ms, max_ssids)) { + wpa_printf(MSG_DEBUG, "Use specific SSIDs from SCAN command"); + goto ssid_list_set; + } + #ifdef CONFIG_P2P if ((wpa_s->p2p_in_provisioning || wpa_s->show_group_started) && wpa_s->go_params && !wpa_s->conf->passive_scan) { @@ -891,10 +928,8 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) wpa_dbg(wpa_s, MSG_DEBUG, "Starting AP scan for wildcard " "SSID"); } -#ifdef CONFIG_P2P -ssid_list_set: -#endif /* CONFIG_P2P */ +ssid_list_set: wpa_supplicant_optimize_freqs(wpa_s, ¶ms); extra_ie = wpa_supplicant_extra_ies(wpa_s); diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 48bded6e1..11ac73550 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -4336,6 +4336,8 @@ static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s, wpa_s->conf = NULL; } + os_free(wpa_s->ssids_from_scan_req); + os_free(wpa_s); } diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index ffda53dfe..bc6425d66 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -609,6 +609,9 @@ struct wpa_supplicant { int scan_id[MAX_SCAN_ID]; unsigned int scan_id_count; + struct wpa_ssid_value *ssids_from_scan_req; + unsigned int num_ssids_from_scan_req; + u64 drv_flags; unsigned int drv_enc; unsigned int drv_smps_modes;