Browse Source

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 <j@w1.fi>
Jouni Malinen 11 years ago
parent
commit
356d1488c4
3 changed files with 74 additions and 32 deletions
  1. 68 30
      wpa_supplicant/ctrl_iface.c
  2. 4 1
      wpa_supplicant/interworking.c
  3. 2 1
      wpa_supplicant/interworking.h

+ 68 - 30
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)
-		return -1;
 
-	os_memset(&ranges, 0, sizeof(ranges));
-	if (freq_range_list_parse(&ranges, val) < 0)
+	freqs = freq_range_to_channel_list(wpa_s, val);
+	if (freqs == NULL)
 		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)

+ 4 - 1
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);

+ 2 - 1
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,