diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 2de784509..aceaa02b1 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -1826,6 +1826,7 @@ void wpa_config_free(struct wpa_config *config) os_free(config->pssid); os_free(config->p2p_pref_chan); os_free(config->autoscan); + os_free(config->freq_list); wpabuf_free(config->wps_nfc_dh_pubkey); wpabuf_free(config->wps_nfc_dh_privkey); wpabuf_free(config->wps_nfc_dev_pw); @@ -2733,6 +2734,21 @@ static int wpa_global_config_parse_bin(const struct global_parse_data *data, } +static int wpa_config_process_freq_list(const struct global_parse_data *data, + struct wpa_config *config, int line, + const char *value) +{ + int *freqs; + + freqs = wpa_config_parse_int_array(value); + if (freqs == NULL) + return -1; + os_free(config->freq_list); + config->freq_list = freqs; + return 0; +} + + static int wpa_config_process_country(const struct global_parse_data *data, struct wpa_config *config, int line, const char *pos) @@ -3088,6 +3104,7 @@ static const struct global_parse_data global_fields[] = { { INT(beacon_int), 0 }, { FUNC(ap_vendor_elements), 0 }, { INT_RANGE(ignore_old_scan_res, 0, 1), 0 }, + { FUNC(freq_list), 0 }, }; #undef FUNC diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index 4a175ce99..cdaaa8948 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -644,6 +644,14 @@ struct wpa_config { */ unsigned int max_num_sta; + /** + * freq_list - Array of allowed scan frequencies or %NULL for all + * + * This is an optional zero-terminated array of frequencies in + * megahertz (MHz) to allow for narrowing scanning range. + */ + int *freq_list; + /** * changed_parameters - Bitmap of changed parameters since last update */ diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index 8604ae8a4..ed6b3f2b5 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -1015,6 +1015,16 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config) if (config->ignore_old_scan_res) fprintf(f, "ignore_old_scan_res=%d\n", config->ignore_old_scan_res); + + if (config->freq_list && config->freq_list[0]) { + int i; + fprintf(f, "freq_list="); + for (i = 0; config->freq_list[i]; i++) { + fprintf(f, "%s%u", i > 0 ? " " : "", + config->freq_list[i]); + } + fprintf(f, "\n"); + } } #endif /* CONFIG_NO_CONFIG_WRITE */ diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index 6e2bb812e..8d4c7f1a7 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -749,6 +749,13 @@ ssid_list_set: os_free(wpa_s->next_scan_freqs); wpa_s->next_scan_freqs = NULL; + /* See if user specified frequencies. If so, scan only those. */ + if (wpa_s->conf->freq_list && !params.freqs) { + wpa_dbg(wpa_s, MSG_DEBUG, + "Optimize scan based on conf->freq_list"); + int_array_concat(¶ms.freqs, wpa_s->conf->freq_list); + } + params.filter_ssids = wpa_supplicant_build_filter_ssids( wpa_s->conf, ¶ms.num_filter_ssids); if (extra_ie) { diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index 0935a0624..87dd3970a 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -524,6 +524,9 @@ fast_reauth=1 # set, scan results that do not match any of the specified frequencies are not # considered when selecting a BSS. # +# This can also be set on the outside of the network block. In this case, +# it limits the frequencies that will be scanned. +# # bgscan: Background scanning # wpa_supplicant behavior for background scanning can be specified by # configuring a bgscan module. These modules are responsible for requesting @@ -1231,3 +1234,10 @@ SGVsbG8gV29ybGQhCg== network={ key_mgmt=NONE } + + +# Example config file that will only scan on channel 36. +freq_list=5180 +network={ + key_mgmt=NONE +}