aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2013-12-25 20:04:52 +0200
committerSteve Kondik <shade@chemlab.org>2014-06-12 14:08:00 -0700
commit8aa9fe0efeb787d4694320c61be8e9fc225b3681 (patch)
tree45cb08a8b64a6e07d2bfce64613c531756de8139
parent09750ccb085162a73c708bc9ca2a6cdcd23669e9 (diff)
downloadandroid_external_wpa_supplicant_8-8aa9fe0efeb787d4694320c61be8e9fc225b3681.tar.gz
android_external_wpa_supplicant_8-8aa9fe0efeb787d4694320c61be8e9fc225b3681.tar.bz2
android_external_wpa_supplicant_8-8aa9fe0efeb787d4694320c61be8e9fc225b3681.zip
Allow channel list to be specified for SCAN command
The new freq=<frequency ranges> parameter to the SCAN command can be used to request a scan to be performed on the specified set of channels instead of on all channels. For example, "wpa_cli scan freq=2400-2500,5180" would scan channels 1-14 and 36. Only the channels that the driver indicates as enabled and that are within the specified ranges are included in the request. Git-commit: fee5234284345f7c27db7e726ed729b7317ee5b8 Git-repo : git://w1.fi/srv/git/hostap.git CRs-fixed:593066 Signed-hostap: Jouni Malinen <j@w1.fi> Change-Id: I924cfe107d2bfd8c8ebb09dd22ca24ff1e95a95a
-rw-r--r--wpa_supplicant/ctrl_iface.c118
-rw-r--r--wpa_supplicant/scan.c14
-rw-r--r--wpa_supplicant/wpa_supplicant.c3
-rw-r--r--wpa_supplicant/wpa_supplicant_i.h1
4 files changed, 108 insertions, 28 deletions
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 194dc92c..fdffda85 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -5246,6 +5246,92 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
}
+static int set_scan_freqs(struct wpa_supplicant *wpa_s, char *val)
+{
+ struct wpa_freq_range_list ranges;
+ int *freqs = NULL;
+ struct hostapd_hw_modes *mode;
+ u16 i;
+
+ if (wpa_s->hw.modes == NULL)
+ return -1;
+
+ os_memset(&ranges, 0, sizeof(ranges));
+ if (freq_range_list_parse(&ranges, val) < 0)
+ return -1;
+
+ for (i = 0; i < wpa_s->hw.num_modes; i++) {
+ int j;
+
+ mode = &wpa_s->hw.modes[i];
+ for (j = 0; j < mode->num_channels; j++) {
+ unsigned int freq;
+
+ if (mode->channels[j].flag & HOSTAPD_CHAN_DISABLED)
+ continue;
+
+ freq = mode->channels[j].freq;
+ if (!freq_range_list_includes(&ranges, freq))
+ continue;
+
+ int_array_add_unique(&freqs, freq);
+ }
+ }
+
+ os_free(ranges.range);
+ os_free(wpa_s->manual_scan_freqs);
+ wpa_s->manual_scan_freqs = freqs;
+
+ return 0;
+}
+
+
+static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params,
+ char *reply, int reply_size, int *reply_len)
+{
+ char *pos;
+
+ if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+ *reply_len = -1;
+ return;
+ }
+
+ if (params) {
+ if (os_strncasecmp(params, "TYPE=ONLY", 9) == 0)
+ wpa_s->scan_res_handler = scan_only_handler;
+
+ pos = os_strstr(params, "freq=");
+ if (pos && set_scan_freqs(wpa_s, pos + 5) < 0) {
+ *reply_len = -1;
+ return;
+ }
+ } 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 (!wpa_s->sched_scanning && !wpa_s->scanning &&
+ ((wpa_s->wpa_state <= WPA_SCANNING) ||
+ (wpa_s->wpa_state == WPA_COMPLETED))) {
+ wpa_s->normal_scans = 0;
+ wpa_s->scan_req = MANUAL_SCAN_REQ;
+ wpa_s->after_wps = 0;
+ wpa_s->known_wps_freq = 0;
+ wpa_supplicant_req_scan(wpa_s, 0, 0);
+ } else if (wpa_s->sched_scanning) {
+ 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;
+ wpa_supplicant_req_scan(wpa_s, 0, 0);
+ } else {
+ wpa_printf(MSG_DEBUG, "Ongoing scan action - reject new request");
+ *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
+ }
+}
+
+
char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
char *buf, size_t *resp_len)
{
@@ -5619,34 +5705,10 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
wpa_supplicant_cancel_scan(wpa_s);
wpa_supplicant_deauthenticate(wpa_s,
WLAN_REASON_DEAUTH_LEAVING);
- } else if (os_strcmp(buf, "SCAN") == 0 ||
- os_strncmp(buf, "SCAN ", 5) == 0) {
- if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
- reply_len = -1;
- else {
- if (os_strlen(buf) > 4 &&
- os_strncasecmp(buf + 5, "TYPE=ONLY", 9) == 0)
- wpa_s->scan_res_handler = scan_only_handler;
- if (!wpa_s->sched_scanning && !wpa_s->scanning &&
- ((wpa_s->wpa_state <= WPA_SCANNING) ||
- (wpa_s->wpa_state == WPA_COMPLETED))) {
- wpa_s->normal_scans = 0;
- wpa_s->scan_req = MANUAL_SCAN_REQ;
- wpa_supplicant_req_scan(wpa_s, 0, 0);
- } else if (wpa_s->sched_scanning) {
- 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;
- wpa_supplicant_req_scan(wpa_s, 0, 0);
- } else {
- wpa_printf(MSG_DEBUG, "Ongoing scan action - "
- "reject new request");
- reply_len = os_snprintf(reply, reply_size,
- "FAIL-BUSY\n");
- }
- }
+ } else if (os_strcmp(buf, "SCAN") == 0) {
+ wpas_ctrl_scan(wpa_s, NULL, reply, reply_size, &reply_len);
+ } else if (os_strncmp(buf, "SCAN ", 5) == 0) {
+ wpas_ctrl_scan(wpa_s, buf + 5, reply, reply_size, &reply_len);
} else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
reply_len = wpa_supplicant_ctrl_iface_scan_results(
wpa_s, reply, reply_size);
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index 00fd8652..28cfe570 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -702,6 +702,13 @@ ssid_list_set:
wpa_supplicant_optimize_freqs(wpa_s, &params);
extra_ie = wpa_supplicant_extra_ies(wpa_s);
+ if (wpa_s->last_scan_req == MANUAL_SCAN_REQ && params.freqs == NULL &&
+ wpa_s->manual_scan_freqs) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "Limit manual scan to specified channels");
+ params.freqs = wpa_s->manual_scan_freqs;
+ wpa_s->manual_scan_freqs = NULL;
+ }
+
if (params.freqs == NULL && wpa_s->next_scan_freqs) {
wpa_dbg(wpa_s, MSG_DEBUG, "Optimize scan based on previously "
"generated frequency list");
@@ -790,6 +797,13 @@ scan:
ret = wpa_supplicant_trigger_scan(wpa_s, scan_params);
+ if (ret && wpa_s->last_scan_req == MANUAL_SCAN_REQ && params.freqs &&
+ !wpa_s->manual_scan_freqs) {
+ /* Restore manual_scan_freqs for the next attempt */
+ wpa_s->manual_scan_freqs = params.freqs;
+ params.freqs = NULL;
+ }
+
wpabuf_free(extra_ie);
os_free(params.freqs);
os_free(params.filter_ssids);
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 2e9cbfb9..78eccff9 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -459,6 +459,9 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
os_free(wpa_s->next_scan_freqs);
wpa_s->next_scan_freqs = NULL;
+ os_free(wpa_s->manual_scan_freqs);
+ wpa_s->manual_scan_freqs = NULL;
+
gas_query_deinit(wpa_s->gas);
wpa_s->gas = NULL;
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 32955b59..e110d3c5 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -473,6 +473,7 @@ struct wpa_supplicant {
unsigned int own_scan_requested:1;
unsigned int own_scan_running:1;
unsigned int external_scan_running:1;
+ int *manual_scan_freqs;
int scan_interval; /* time in sec between scans to find suitable AP */
int normal_scans; /* normal scans run before sched_scan */
int scan_for_connection; /* whether the scan request was triggered for