Interworking: Add support for home vs. visited SP determination
Use Domain Name List (ANQP) and the new home_domain configuration parameter to figure out whether a network is operated by the home service provider and if so, prefer it over networks that would require roaming. Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
95bc2ea63d
commit
00bf219ddb
3 changed files with 62 additions and 5 deletions
|
@ -1825,6 +1825,7 @@ void wpa_config_free(struct wpa_config *config)
|
|||
os_free(config->home_ca_cert);
|
||||
os_free(config->home_imsi);
|
||||
os_free(config->home_milenage);
|
||||
os_free(config->home_domain);
|
||||
os_free(config);
|
||||
}
|
||||
|
||||
|
@ -2594,6 +2595,7 @@ static const struct global_parse_data global_fields[] = {
|
|||
{ STR(home_ca_cert), 0 },
|
||||
{ STR(home_imsi), 0 },
|
||||
{ STR(home_milenage), 0 },
|
||||
{ STR(home_domain), 0 },
|
||||
{ INT_RANGE(interworking, 0, 1), 0 },
|
||||
{ FUNC(hessid), 0 },
|
||||
{ INT_RANGE(access_network_type, 0, 15), 0 }
|
||||
|
|
|
@ -478,6 +478,14 @@ struct wpa_config {
|
|||
* <Ki>:<OPc>:<SQN> format
|
||||
*/
|
||||
char *home_milenage;
|
||||
|
||||
/**
|
||||
* home_domain - Home service provider FQDN
|
||||
*
|
||||
* This is used to compare against the Domain Name List to figure out
|
||||
* whether the AP is operated by the Home SP.
|
||||
*/
|
||||
char *home_domain;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -830,10 +830,41 @@ static int interworking_credentials_available(struct wpa_supplicant *wpa_s,
|
|||
}
|
||||
|
||||
|
||||
static int interworking_home_sp(struct wpa_supplicant *wpa_s,
|
||||
struct wpabuf *domain_names)
|
||||
{
|
||||
const u8 *pos, *end;
|
||||
size_t len;
|
||||
|
||||
if (wpa_s->conf->home_domain == NULL || domain_names == NULL)
|
||||
return -1;
|
||||
|
||||
len = os_strlen(wpa_s->conf->home_domain);
|
||||
pos = wpabuf_head(domain_names);
|
||||
end = pos + wpabuf_len(domain_names);
|
||||
|
||||
while (pos + 1 < end) {
|
||||
if (pos + 1 + pos[0] > end)
|
||||
break;
|
||||
|
||||
if (pos[0] == len &&
|
||||
os_strncasecmp(wpa_s->conf->home_domain,
|
||||
(const char *) (pos + 1), len) == 0)
|
||||
return 1;
|
||||
|
||||
pos += 1 + pos[0];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void interworking_select_network(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
struct wpa_bss *bss, *selected = NULL;
|
||||
struct wpa_bss *bss, *selected = NULL, *selected_home = NULL;
|
||||
unsigned int count = 0;
|
||||
const char *type;
|
||||
int res;
|
||||
|
||||
wpa_s->network_select = 0;
|
||||
|
||||
|
@ -841,10 +872,26 @@ static void interworking_select_network(struct wpa_supplicant *wpa_s)
|
|||
if (!interworking_credentials_available(wpa_s, bss))
|
||||
continue;
|
||||
count++;
|
||||
wpa_msg(wpa_s, MSG_INFO, INTERWORKING_AP MACSTR,
|
||||
MAC2STR(bss->bssid));
|
||||
if (selected == NULL && wpa_s->auto_select)
|
||||
selected = bss;
|
||||
res = interworking_home_sp(wpa_s, bss->anqp_domain_name);
|
||||
if (res > 0)
|
||||
type = "home";
|
||||
else if (res == 0)
|
||||
type = "roaming";
|
||||
else
|
||||
type = "unknown";
|
||||
wpa_msg(wpa_s, MSG_INFO, INTERWORKING_AP MACSTR " type=%s",
|
||||
MAC2STR(bss->bssid), type);
|
||||
if (wpa_s->auto_select) {
|
||||
if (selected == NULL)
|
||||
selected = bss;
|
||||
if (selected_home == NULL && res > 0)
|
||||
selected_home = bss;
|
||||
}
|
||||
}
|
||||
|
||||
if (selected_home && selected_home != selected) {
|
||||
/* Prefer network operated by the Home SP */
|
||||
selected = selected_home;
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
|
|
Loading…
Reference in a new issue