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:
parent
b1f122964e
commit
4d5bda5fca
10 changed files with 88 additions and 2 deletions
|
@ -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:
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue