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:
Jouni Malinen 2012-02-16 16:32:00 +02:00 committed by Jouni Malinen
parent 95bc2ea63d
commit 00bf219ddb
3 changed files with 62 additions and 5 deletions

View file

@ -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 }

View file

@ -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;
};

View file

@ -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) {