From 356d1488c4d92d344d309d1e5a06cd663f6cfe91 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 5 Jan 2014 12:25:13 +0200 Subject: [PATCH] Interworking: Add optional freq argument to INTERWORKING_SELECT This can be used to limit which channels are scanned using the specified list of frequency ranges in the same format that the SCAN command uses. Signed-hostap: Jouni Malinen --- wpa_supplicant/ctrl_iface.c | 98 ++++++++++++++++++++++++----------- wpa_supplicant/interworking.c | 5 +- wpa_supplicant/interworking.h | 3 +- 3 files changed, 74 insertions(+), 32 deletions(-) diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 43b3eee4f..155207a4e 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -4664,7 +4664,68 @@ static int p2p_ctrl_remove_client(struct wpa_supplicant *wpa_s, const char *cmd) #endif /* CONFIG_P2P */ +static int * freq_range_to_channel_list(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 NULL; + + os_memset(&ranges, 0, sizeof(ranges)); + if (freq_range_list_parse(&ranges, val) < 0) + return NULL; + + 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); + return freqs; +} + + #ifdef CONFIG_INTERWORKING + +static int ctrl_interworking_select(struct wpa_supplicant *wpa_s, char *param) +{ + int auto_sel = 0; + int *freqs = NULL; + + if (param) { + char *pos; + + auto_sel = os_strstr(param, "auto") != NULL; + + pos = os_strstr(param, "freq="); + if (pos) { + freqs = freq_range_to_channel_list(wpa_s, pos + 5); + if (freqs == NULL) + return -1; + } + + } + + return interworking_select(wpa_s, auto_sel, freqs); +} + + static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst) { u8 bssid[ETH_ALEN]; @@ -5413,37 +5474,12 @@ static void wpas_ctrl_eapol_response(void *eloop_ctx, void *timeout_ctx) 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) + freqs = freq_range_to_channel_list(wpa_s, val); + if (freqs == 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; @@ -5847,9 +5883,11 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, reply_len = -1; } else if (os_strcmp(buf, "STOP_FETCH_ANQP") == 0) { interworking_stop_fetch_anqp(wpa_s); - } else if (os_strncmp(buf, "INTERWORKING_SELECT", 19) == 0) { - if (interworking_select(wpa_s, os_strstr(buf + 19, "auto") != - NULL) < 0) + } else if (os_strcmp(buf, "INTERWORKING_SELECT") == 0) { + if (ctrl_interworking_select(wpa_s, NULL) < 0) + reply_len = -1; + } else if (os_strncmp(buf, "INTERWORKING_SELECT ", 20) == 0) { + if (ctrl_interworking_select(wpa_s, buf + 20) < 0) reply_len = -1; } else if (os_strncmp(buf, "INTERWORKING_CONNECT ", 21) == 0) { if (ctrl_interworking_connect(wpa_s, buf + 21) < 0) diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c index 9f8842bbd..5e7fe5b27 100644 --- a/wpa_supplicant/interworking.c +++ b/wpa_supplicant/interworking.c @@ -2202,7 +2202,8 @@ static void interworking_scan_res_handler(struct wpa_supplicant *wpa_s, } -int interworking_select(struct wpa_supplicant *wpa_s, int auto_select) +int interworking_select(struct wpa_supplicant *wpa_s, int auto_select, + int *freqs) { interworking_stop_fetch_anqp(wpa_s); wpa_s->network_select = 1; @@ -2214,6 +2215,8 @@ int interworking_select(struct wpa_supplicant *wpa_s, int auto_select) wpa_s->scan_res_handler = interworking_scan_res_handler; wpa_s->normal_scans = 0; wpa_s->scan_req = MANUAL_SCAN_REQ; + os_free(wpa_s->manual_scan_freqs); + wpa_s->manual_scan_freqs = freqs; wpa_s->after_wps = 0; wpa_s->known_wps_freq = 0; wpa_supplicant_req_scan(wpa_s, 0, 0); diff --git a/wpa_supplicant/interworking.h b/wpa_supplicant/interworking.h index 4a4af827b..c8e70938c 100644 --- a/wpa_supplicant/interworking.h +++ b/wpa_supplicant/interworking.h @@ -22,7 +22,8 @@ int gas_send_request(struct wpa_supplicant *wpa_s, const u8 *dst, const struct wpabuf *query); int interworking_fetch_anqp(struct wpa_supplicant *wpa_s); void interworking_stop_fetch_anqp(struct wpa_supplicant *wpa_s); -int interworking_select(struct wpa_supplicant *wpa_s, int auto_select); +int interworking_select(struct wpa_supplicant *wpa_s, int auto_select, + int *freqs); int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss); void interworking_start_fetch_anqp(struct wpa_supplicant *wpa_s); int interworking_home_sp_cred(struct wpa_supplicant *wpa_s,