Interworking: Add optional use of network selection on normal scans

auto_interworking=1 configuration parameter can be used to request
wpa_supplicant to use Interworking network selection automatically as a
part of the normal (non-Interworking) network selection if the scan
results do not match with enabled networks. This makes scanning work
similarly to the "interworking_select auto" command.

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Jouni Malinen 2012-08-28 16:14:13 +03:00 committed by Jouni Malinen
parent b1f122964e
commit 4d5bda5fca
10 changed files with 88 additions and 2 deletions

View file

@ -24,6 +24,31 @@ standardized in IEEE Std 802.11u-2011 which is now part of the IEEE Std
802.11-2012. 802.11-2012.
wpa_supplicant network selection
--------------------------------
Interworking support added option for configuring credentials that can
work with multiple networks as an alternative to configuration of
network blocks (e.g., per-SSID parameters). When requested to perform
network selection, wpa_supplicant picks the highest priority enabled
network block or credential. If a credential is picked (based on ANQP
information from APs), a temporary network block is created
automatically for the matching network. This temporary network block is
used similarly to the network blocks that can be configured by the user,
but it is not stored into the configuration file and is meant to be used
only for temporary period of time since a new one can be created
whenever needed based on ANQP information and the credential.
By default, wpa_supplicant is not using automatic network selection
unless requested explicitly with the interworking_select command. This
can be changed with the auto_interworking=1 parameter to perform network
selection automatically whenever trying to find a network for connection
and none of the enabled network blocks match with the scan results. This
case works similarly to "interworking_select auto", i.e., wpa_supplicant
will internally determine which network or credential is going to be
used based on configured priorities, scan results, and ANQP information.
wpa_supplicant configuration wpa_supplicant configuration
---------------------------- ----------------------------
@ -65,6 +90,14 @@ hs20=1
# This value controls the Access Network Type value in Probe Request frames. # This value controls the Access Network Type value in Probe Request frames.
#access_network_type=15 #access_network_type=15
# Automatic network selection behavior
# 0 = do not automatically go through Interworking network selection
# (i.e., require explicit interworking_select command for this; default)
# 1 = perform Interworking network selection if one or more
# credentials have been configured and scan did not find a
# matching network block
#auto_interworking=0
Credentials can be pre-configured for automatic network selection: Credentials can be pre-configured for automatic network selection:

View file

@ -3010,6 +3010,7 @@ static const struct global_parse_data global_fields[] = {
{ BIN(wps_nfc_dev_pw), 0 }, { BIN(wps_nfc_dev_pw), 0 },
{ STR(ext_password_backend), CFG_CHANGED_EXT_PW_BACKEND }, { STR(ext_password_backend), CFG_CHANGED_EXT_PW_BACKEND },
{ INT(p2p_go_max_inactivity), 0 }, { INT(p2p_go_max_inactivity), 0 },
{ INT_RANGE(auto_interworking, 0, 1), 0 },
}; };
#undef FUNC #undef FUNC

View file

@ -736,6 +736,17 @@ struct wpa_config {
int p2p_go_max_inactivity; int p2p_go_max_inactivity;
struct hostapd_wmm_ac_params wmm_ac_params[4]; struct hostapd_wmm_ac_params wmm_ac_params[4];
/**
* auto_interworking - Whether to use network selection automatically
*
* 0 = do not automatically go through Interworking network selection
* (i.e., require explicit interworking_select command for this)
* 1 = perform Interworking network selection if one or more
* credentials have been configured and scan did not find a
* matching network block
*/
int auto_interworking;
}; };

View file

@ -916,6 +916,9 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
if (config->p2p_go_max_inactivity != DEFAULT_P2P_GO_MAX_INACTIVITY) if (config->p2p_go_max_inactivity != DEFAULT_P2P_GO_MAX_INACTIVITY)
fprintf(f, "p2p_go_max_inactivity=%d\n", fprintf(f, "p2p_go_max_inactivity=%d\n",
config->p2p_go_max_inactivity); config->p2p_go_max_inactivity);
if (config->auto_interworking)
fprintf(f, "auto_interworking=%d\n",
config->auto_interworking);
} }
#endif /* CONFIG_NO_CONFIG_WRITE */ #endif /* CONFIG_NO_CONFIG_WRITE */

View file

@ -41,6 +41,7 @@
#include "bss.h" #include "bss.h"
#include "scan.h" #include "scan.h"
#include "offchannel.h" #include "offchannel.h"
#include "interworking.h"
static int wpas_temp_disabled(struct wpa_supplicant *wpa_s, static int wpas_temp_disabled(struct wpa_supplicant *wpa_s,
@ -1204,6 +1205,19 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
return 0; return 0;
} }
#endif /* CONFIG_P2P */ #endif /* CONFIG_P2P */
#ifdef CONFIG_INTERWORKING
if (wpa_s->conf->auto_interworking &&
wpa_s->conf->interworking &&
wpa_s->conf->cred) {
wpa_dbg(wpa_s, MSG_DEBUG, "Interworking: "
"start ANQP fetch since no matching "
"networks found");
wpa_s->network_select = 1;
wpa_s->auto_network_select = 1;
interworking_start_fetch_anqp(wpa_s);
return 0;
}
#endif /* CONFIG_INTERWORKING */
if (wpa_supplicant_req_sched_scan(wpa_s)) if (wpa_supplicant_req_sched_scan(wpa_s))
wpa_supplicant_req_new_scan(wpa_s, timeout_sec, wpa_supplicant_req_new_scan(wpa_s, timeout_sec,
timeout_usec); timeout_usec);

View file

@ -1411,7 +1411,9 @@ static void interworking_select_network(struct wpa_supplicant *wpa_s)
type = "unknown"; type = "unknown";
wpa_msg(wpa_s, MSG_INFO, INTERWORKING_AP MACSTR " type=%s", wpa_msg(wpa_s, MSG_INFO, INTERWORKING_AP MACSTR " type=%s",
MAC2STR(bss->bssid), type); MAC2STR(bss->bssid), type);
if (wpa_s->auto_select) { if (wpa_s->auto_select ||
(wpa_s->conf->auto_interworking &&
wpa_s->auto_network_select)) {
if (selected == NULL || if (selected == NULL ||
cred->priority > selected_prio) { cred->priority > selected_prio) {
selected = bss; selected = bss;
@ -1446,6 +1448,14 @@ static void interworking_select_network(struct wpa_supplicant *wpa_s)
return; return;
} }
if (wpa_s->auto_network_select) {
wpa_printf(MSG_DEBUG, "Interworking: Continue "
"scanning after ANQP fetch");
wpa_supplicant_req_scan(wpa_s, wpa_s->scan_interval,
0);
return;
}
wpa_msg(wpa_s, MSG_INFO, INTERWORKING_NO_MATCH "No network " wpa_msg(wpa_s, MSG_INFO, INTERWORKING_NO_MATCH "No network "
"with matching credentials found"); "with matching credentials found");
} }
@ -1490,7 +1500,7 @@ static void interworking_next_anqp_fetch(struct wpa_supplicant *wpa_s)
} }
static void interworking_start_fetch_anqp(struct wpa_supplicant *wpa_s) void interworking_start_fetch_anqp(struct wpa_supplicant *wpa_s)
{ {
struct wpa_bss *bss; struct wpa_bss *bss;
@ -1748,6 +1758,7 @@ int interworking_select(struct wpa_supplicant *wpa_s, int auto_select)
{ {
interworking_stop_fetch_anqp(wpa_s); interworking_stop_fetch_anqp(wpa_s);
wpa_s->network_select = 1; wpa_s->network_select = 1;
wpa_s->auto_network_select = 0;
wpa_s->auto_select = !!auto_select; wpa_s->auto_select = !!auto_select;
wpa_printf(MSG_DEBUG, "Interworking: Start scan for network " wpa_printf(MSG_DEBUG, "Interworking: Start scan for network "
"selection"); "selection");

View file

@ -24,5 +24,6 @@ int interworking_fetch_anqp(struct wpa_supplicant *wpa_s);
void interworking_stop_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 interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss); int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss);
void interworking_start_fetch_anqp(struct wpa_supplicant *wpa_s);
#endif /* INTERWORKING_H */ #endif /* INTERWORKING_H */

View file

@ -89,6 +89,9 @@ int wpa_supplicant_enabled_networks(struct wpa_supplicant *wpa_s)
count++; count++;
ssid = ssid->next; ssid = ssid->next;
} }
if (wpa_s->conf->cred && wpa_s->conf->interworking &&
wpa_s->conf->auto_interworking)
count++;
return count; return count;
} }

View file

@ -277,6 +277,14 @@ fast_reauth=1
# is enabled. # is enabled.
# hessid=00:11:22:33:44:55 # hessid=00:11:22:33:44:55
# Automatic network selection behavior
# 0 = do not automatically go through Interworking network selection
# (i.e., require explicit interworking_select command for this; default)
# 1 = perform Interworking network selection if one or more
# credentials have been configured and scan did not find a
# matching network block
#auto_interworking=0
# credential block # credential block
# #
# Each credential used for automatic network selection is configured as a set # Each credential used for automatic network selection is configured as a set

View file

@ -570,6 +570,7 @@ struct wpa_supplicant {
unsigned int fetch_anqp_in_progress:1; unsigned int fetch_anqp_in_progress:1;
unsigned int network_select:1; unsigned int network_select:1;
unsigned int auto_select:1; unsigned int auto_select:1;
unsigned int auto_network_select:1;
#endif /* CONFIG_INTERWORKING */ #endif /* CONFIG_INTERWORKING */
unsigned int drv_capa_known; unsigned int drv_capa_known;