diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index a509bfb4c..244fd2d0e 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -5986,6 +5986,25 @@ static int set_scan_freqs(struct wpa_supplicant *wpa_s, char *val) } +static int scan_id_list_parse(struct wpa_supplicant *wpa_s, const char *value) +{ + const char *pos = value; + + while (pos) { + if (*pos == ' ' || *pos == '\0') + break; + if (wpa_s->scan_id_count == MAX_SCAN_ID) + return -1; + wpa_s->scan_id[wpa_s->scan_id_count++] = atoi(pos); + pos = os_strchr(pos, ','); + if (pos) + pos++; + } + + return 0; +} + + static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params, char *reply, int reply_size, int *reply_len) { @@ -5999,6 +6018,7 @@ static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params, 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) @@ -6021,6 +6041,12 @@ static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params, pos = os_strstr(params, "only_new=1"); if (pos) wpa_s->manual_scan_only_new = 1; + + pos = os_strstr(params, "scan_id="); + if (pos && scan_id_list_parse(wpa_s, pos + 8) < 0) { + *reply_len = -1; + return; + } } else { os_free(wpa_s->manual_scan_freqs); wpa_s->manual_scan_freqs = NULL; diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index a2b996ff9..b13713c78 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -548,6 +548,47 @@ static void wpa_setband_scan_freqs(struct wpa_supplicant *wpa_s, } +static void wpa_set_scan_ssids(struct wpa_supplicant *wpa_s, + struct wpa_driver_scan_params *params, + size_t max_ssids) +{ + unsigned int i; + struct wpa_ssid *ssid; + + for (i = 0; i < wpa_s->scan_id_count; i++) { + unsigned int j; + + ssid = wpa_config_get_network(wpa_s->conf, wpa_s->scan_id[i]); + if (!ssid || !ssid->scan_ssid) + continue; + + for (j = 0; j < params->num_ssids; j++) { + if (params->ssids[j].ssid_len == ssid->ssid_len && + params->ssids[j].ssid && + os_memcmp(params->ssids[j].ssid, ssid->ssid, + ssid->ssid_len) == 0) + break; + } + if (j < params->num_ssids) + continue; /* already in the list */ + + if (params->num_ssids + 1 > max_ssids) { + wpa_printf(MSG_DEBUG, + "Over max scan SSIDs for manual request"); + break; + } + + wpa_printf(MSG_DEBUG, "Scan SSID (manual request): %s", + wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); + params->ssids[params->num_ssids].ssid = ssid->ssid; + params->ssids[params->num_ssids].ssid_len = ssid->ssid_len; + params->num_ssids++; + } + + wpa_s->scan_id_count = 0; +} + + static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) { struct wpa_supplicant *wpa_s = eloop_ctx; @@ -758,6 +799,10 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) ssid = wpa_s->conf->ssid; } + if (wpa_s->scan_id_count && + wpa_s->last_scan_req == MANUAL_SCAN_REQ) + wpa_set_scan_ssids(wpa_s, ¶ms, max_ssids); + for (tssid = wpa_s->conf->ssid; tssid; tssid = tssid->next) { if (wpas_network_disabled(wpa_s, tssid)) continue; diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 1cb4e161d..8a9ca979f 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -568,6 +568,9 @@ struct wpa_supplicant { int normal_scans; /* normal scans run before sched_scan */ int scan_for_connection; /* whether the scan request was triggered for * finding a connection */ +#define MAX_SCAN_ID 16 + int scan_id[MAX_SCAN_ID]; + unsigned int scan_id_count; unsigned int drv_flags; unsigned int drv_enc;