From 6891f0e6f4e85408c3bf3be99eb85f767e5a7766 Mon Sep 17 00:00:00 2001 From: Li Jianyun Date: Tue, 1 Jul 2014 23:22:56 +0800 Subject: [PATCH] Allow SCAN command to specify scan_ssid=1 SSIDs The new "scan_id=" parameter can now be used to specify a list of network ids that have scan_ssid=1 to indicate active scanning of the SSID. This adds the listed SSIDs to the scan command to allow manual scan requests to perform active scans for hidden SSIDs. For example, "SCAN scan_id=1,7,11" would run a scan with the SSID fetched from the configured network blocks 1, 7, and 11 (assuming those are set with scan_ssid=1). The SSIDs will be included even from network blocks that are currently disabled. The maximum number of SSIDs added to the request is limited by the driver support. If more than supported values are specified, the command will fail (returns "FAIL"). Signed-off-by: Jouni Malinen --- wpa_supplicant/ctrl_iface.c | 26 ++++++++++++++++++ wpa_supplicant/scan.c | 45 +++++++++++++++++++++++++++++++ wpa_supplicant/wpa_supplicant_i.h | 3 +++ 3 files changed, 74 insertions(+) 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;