aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--wpa_supplicant/bss.c58
-rw-r--r--wpa_supplicant/bss.h36
-rw-r--r--wpa_supplicant/ctrl_iface.c23
-rw-r--r--wpa_supplicant/hs20_supplicant.c28
-rw-r--r--wpa_supplicant/interworking.c79
5 files changed, 138 insertions, 86 deletions
diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c
index 503aaa9..a999868 100644
--- a/wpa_supplicant/bss.c
+++ b/wpa_supplicant/bss.c
@@ -35,6 +35,48 @@
#define WPA_BSS_IES_CHANGED_FLAG BIT(8)
+struct wpa_bss_anqp * wpa_bss_anqp_alloc(void)
+{
+ struct wpa_bss_anqp *anqp;
+ anqp = os_zalloc(sizeof(*anqp));
+ if (anqp == NULL)
+ return NULL;
+ anqp->users = 1;
+ return anqp;
+}
+
+
+static void wpa_bss_anqp_free(struct wpa_bss_anqp *anqp)
+{
+ if (anqp == NULL)
+ return;
+
+ anqp->users--;
+ if (anqp->users > 0) {
+ /* Another BSS entry holds a pointer to this ANQP info */
+ return;
+ }
+
+#ifdef CONFIG_INTERWORKING
+ wpabuf_free(anqp->venue_name);
+ wpabuf_free(anqp->network_auth_type);
+ wpabuf_free(anqp->roaming_consortium);
+ wpabuf_free(anqp->ip_addr_type_availability);
+ wpabuf_free(anqp->nai_realm);
+ wpabuf_free(anqp->anqp_3gpp);
+ wpabuf_free(anqp->domain_name);
+#endif /* CONFIG_INTERWORKING */
+#ifdef CONFIG_HS20
+ wpabuf_free(anqp->hs20_operator_friendly_name);
+ wpabuf_free(anqp->hs20_wan_metrics);
+ wpabuf_free(anqp->hs20_connection_capability);
+ wpabuf_free(anqp->hs20_operating_class);
+#endif /* CONFIG_HS20 */
+
+ os_free(anqp);
+}
+
+
static void wpa_bss_remove(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
const char *reason)
{
@@ -58,21 +100,7 @@ static void wpa_bss_remove(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
" SSID '%s' due to %s", bss->id, MAC2STR(bss->bssid),
wpa_ssid_txt(bss->ssid, bss->ssid_len), reason);
wpas_notify_bss_removed(wpa_s, bss->bssid, bss->id);
-#ifdef CONFIG_INTERWORKING
- wpabuf_free(bss->anqp_venue_name);
- wpabuf_free(bss->anqp_network_auth_type);
- wpabuf_free(bss->anqp_roaming_consortium);
- wpabuf_free(bss->anqp_ip_addr_type_availability);
- wpabuf_free(bss->anqp_nai_realm);
- wpabuf_free(bss->anqp_3gpp);
- wpabuf_free(bss->anqp_domain_name);
-#endif /* CONFIG_INTERWORKING */
-#ifdef CONFIG_HS20
- wpabuf_free(bss->hs20_operator_friendly_name);
- wpabuf_free(bss->hs20_wan_metrics);
- wpabuf_free(bss->hs20_connection_capability);
- wpabuf_free(bss->hs20_operating_class);
-#endif /* CONFIG_HS20 */
+ wpa_bss_anqp_free(bss->anqp);
os_free(bss);
}
diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h
index ef9e5c3..31ae3da 100644
--- a/wpa_supplicant/bss.h
+++ b/wpa_supplicant/bss.h
@@ -19,6 +19,25 @@ struct wpa_scan_res;
#define WPA_BSS_ASSOCIATED BIT(5)
#define WPA_BSS_ANQP_FETCH_TRIED BIT(6)
+struct wpa_bss_anqp {
+ unsigned int users;
+#ifdef CONFIG_INTERWORKING
+ struct wpabuf *venue_name;
+ struct wpabuf *network_auth_type;
+ struct wpabuf *roaming_consortium;
+ struct wpabuf *ip_addr_type_availability;
+ struct wpabuf *nai_realm;
+ struct wpabuf *anqp_3gpp;
+ struct wpabuf *domain_name;
+#endif /* CONFIG_INTERWORKING */
+#ifdef CONFIG_HS20
+ struct wpabuf *hs20_operator_friendly_name;
+ struct wpabuf *hs20_wan_metrics;
+ struct wpabuf *hs20_connection_capability;
+ struct wpabuf *hs20_operating_class;
+#endif /* CONFIG_HS20 */
+};
+
/**
* struct wpa_bss - BSS table
* @list: List entry for struct wpa_supplicant::bss
@@ -60,21 +79,7 @@ struct wpa_bss {
int level;
u64 tsf;
struct os_time last_update;
-#ifdef CONFIG_INTERWORKING
- struct wpabuf *anqp_venue_name;
- struct wpabuf *anqp_network_auth_type;
- struct wpabuf *anqp_roaming_consortium;
- struct wpabuf *anqp_ip_addr_type_availability;
- struct wpabuf *anqp_nai_realm;
- struct wpabuf *anqp_3gpp;
- struct wpabuf *anqp_domain_name;
-#endif /* CONFIG_INTERWORKING */
-#ifdef CONFIG_HS20
- struct wpabuf *hs20_operator_friendly_name;
- struct wpabuf *hs20_wan_metrics;
- struct wpabuf *hs20_connection_capability;
- struct wpabuf *hs20_operating_class;
-#endif /* CONFIG_HS20 */
+ struct wpa_bss_anqp *anqp;
size_t ie_len;
size_t beacon_ie_len;
/* followed by ie_len octets of IEs */
@@ -105,5 +110,6 @@ struct wpabuf * wpa_bss_get_vendor_ie_multi_beacon(const struct wpa_bss *bss,
u32 vendor_type);
int wpa_bss_get_max_rate(const struct wpa_bss *bss);
int wpa_bss_get_bit_rates(const struct wpa_bss *bss, u8 **rates);
+struct wpa_bss_anqp * wpa_bss_anqp_alloc(void);
#endif /* BSS_H */
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index df5ecd3..ba2edff 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -2772,27 +2772,28 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
#endif /* CONFIG_WIFI_DISPLAY */
#ifdef CONFIG_INTERWORKING
- if (mask & WPA_BSS_MASK_INTERNETW) {
+ if ((mask & WPA_BSS_MASK_INTERNETW) && bss->anqp) {
+ struct wpa_bss_anqp *anqp = bss->anqp;
pos = anqp_add_hex(pos, end, "anqp_venue_name",
- bss->anqp_venue_name);
+ anqp->venue_name);
pos = anqp_add_hex(pos, end, "anqp_network_auth_type",
- bss->anqp_network_auth_type);
+ anqp->network_auth_type);
pos = anqp_add_hex(pos, end, "anqp_roaming_consortium",
- bss->anqp_roaming_consortium);
+ anqp->roaming_consortium);
pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability",
- bss->anqp_ip_addr_type_availability);
+ anqp->ip_addr_type_availability);
pos = anqp_add_hex(pos, end, "anqp_nai_realm",
- bss->anqp_nai_realm);
- pos = anqp_add_hex(pos, end, "anqp_3gpp", bss->anqp_3gpp);
+ anqp->nai_realm);
+ pos = anqp_add_hex(pos, end, "anqp_3gpp", anqp->anqp_3gpp);
pos = anqp_add_hex(pos, end, "anqp_domain_name",
- bss->anqp_domain_name);
+ anqp->domain_name);
#ifdef CONFIG_HS20
pos = anqp_add_hex(pos, end, "hs20_operator_friendly_name",
- bss->hs20_operator_friendly_name);
+ anqp->hs20_operator_friendly_name);
pos = anqp_add_hex(pos, end, "hs20_wan_metrics",
- bss->hs20_wan_metrics);
+ anqp->hs20_wan_metrics);
pos = anqp_add_hex(pos, end, "hs20_connection_capability",
- bss->hs20_connection_capability);
+ anqp->hs20_connection_capability);
#endif /* CONFIG_HS20 */
}
#endif /* CONFIG_INTERWORKING */
diff --git a/wpa_supplicant/hs20_supplicant.c b/wpa_supplicant/hs20_supplicant.c
index 2afa16c..0eb6119 100644
--- a/wpa_supplicant/hs20_supplicant.c
+++ b/wpa_supplicant/hs20_supplicant.c
@@ -110,10 +110,14 @@ void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s,
const u8 *pos = data;
u8 subtype;
struct wpa_bss *bss = wpa_bss_get_bssid(wpa_s, sa);
+ struct wpa_bss_anqp *anqp = NULL;
if (slen < 2)
return;
+ if (bss)
+ anqp = bss->anqp;
+
subtype = *pos++;
slen--;
@@ -130,9 +134,9 @@ void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s,
wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR
" Operator Friendly Name", MAC2STR(sa));
wpa_hexdump_ascii(MSG_DEBUG, "oper friendly name", pos, slen);
- if (bss) {
- wpabuf_free(bss->hs20_operator_friendly_name);
- bss->hs20_operator_friendly_name =
+ if (anqp) {
+ wpabuf_free(anqp->hs20_operator_friendly_name);
+ anqp->hs20_operator_friendly_name =
wpabuf_alloc_copy(pos, slen);
}
break;
@@ -140,18 +144,18 @@ void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s,
wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR
" WAN Metrics", MAC2STR(sa));
wpa_hexdump_ascii(MSG_DEBUG, "WAN Metrics", pos, slen);
- if (bss) {
- wpabuf_free(bss->hs20_wan_metrics);
- bss->hs20_wan_metrics = wpabuf_alloc_copy(pos, slen);
+ if (anqp) {
+ wpabuf_free(anqp->hs20_wan_metrics);
+ anqp->hs20_wan_metrics = wpabuf_alloc_copy(pos, slen);
}
break;
case HS20_STYPE_CONNECTION_CAPABILITY:
wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR
" Connection Capability", MAC2STR(sa));
wpa_hexdump_ascii(MSG_DEBUG, "conn capability", pos, slen);
- if (bss) {
- wpabuf_free(bss->hs20_connection_capability);
- bss->hs20_connection_capability =
+ if (anqp) {
+ wpabuf_free(anqp->hs20_connection_capability);
+ anqp->hs20_connection_capability =
wpabuf_alloc_copy(pos, slen);
}
break;
@@ -159,9 +163,9 @@ void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s,
wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR
" Operating Class", MAC2STR(sa));
wpa_hexdump_ascii(MSG_DEBUG, "Operating Class", pos, slen);
- if (bss) {
- wpabuf_free(bss->hs20_operating_class);
- bss->hs20_operating_class =
+ if (anqp) {
+ wpabuf_free(anqp->hs20_operating_class);
+ anqp->hs20_operating_class =
wpabuf_alloc_copy(pos, slen);
}
break;
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index 20c7731..bbcfe4d 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -737,7 +737,7 @@ static int interworking_connect_3gpp(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid;
const u8 *ie;
- if (bss->anqp_3gpp == NULL)
+ if (bss->anqp == NULL || bss->anqp->anqp_3gpp == NULL)
return -1;
for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
@@ -768,7 +768,7 @@ static int interworking_connect_3gpp(struct wpa_supplicant *wpa_s,
#ifdef PCSC_FUNCS
compare:
#endif /* PCSC_FUNCS */
- if (plmn_id_match(bss->anqp_3gpp, imsi, mnc_len))
+ if (plmn_id_match(bss->anqp->anqp_3gpp, imsi, mnc_len))
break;
}
if (cred == NULL)
@@ -923,7 +923,8 @@ static struct wpa_cred * interworking_credentials_available_roaming_consortium(
ie = wpa_bss_get_ie(bss, WLAN_EID_ROAMING_CONSORTIUM);
- if (ie == NULL && bss->anqp_roaming_consortium == NULL)
+ if (ie == NULL &&
+ (bss->anqp == NULL || bss->anqp->roaming_consortium == NULL))
return NULL;
if (wpa_s->conf->cred == NULL)
@@ -933,7 +934,10 @@ static struct wpa_cred * interworking_credentials_available_roaming_consortium(
if (cred->roaming_consortium_len == 0)
continue;
- if (!roaming_consortium_match(ie, bss->anqp_roaming_consortium,
+ if (!roaming_consortium_match(ie,
+ bss->anqp ?
+ bss->anqp->roaming_consortium :
+ NULL,
cred->roaming_consortium,
cred->roaming_consortium_len))
continue;
@@ -1123,7 +1127,8 @@ int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
return interworking_connect_roaming_consortium(wpa_s, cred,
bss, ie);
- realm = nai_realm_parse(bss->anqp_nai_realm, &count);
+ realm = nai_realm_parse(bss->anqp ? bss->anqp->nai_realm : NULL,
+ &count);
if (realm == NULL) {
wpa_printf(MSG_DEBUG, "Interworking: Could not parse NAI "
"Realm list from " MACSTR, MAC2STR(bss->bssid));
@@ -1250,7 +1255,7 @@ static struct wpa_cred * interworking_credentials_available_3gpp(
int ret;
#ifdef INTERWORKING_3GPP
- if (bss->anqp_3gpp == NULL)
+ if (bss->anqp == NULL || bss->anqp->anqp_3gpp == NULL)
return NULL;
for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
@@ -1283,7 +1288,7 @@ static struct wpa_cred * interworking_credentials_available_3gpp(
#endif /* PCSC_FUNCS */
wpa_printf(MSG_DEBUG, "Interworking: Parsing 3GPP info from "
MACSTR, MAC2STR(bss->bssid));
- ret = plmn_id_match(bss->anqp_3gpp, imsi, mnc_len);
+ ret = plmn_id_match(bss->anqp->anqp_3gpp, imsi, mnc_len);
wpa_printf(MSG_DEBUG, "PLMN match %sfound", ret ? "" : "not ");
if (ret) {
if (selected == NULL ||
@@ -1303,7 +1308,7 @@ static struct wpa_cred * interworking_credentials_available_realm(
struct nai_realm *realm;
u16 count, i;
- if (bss->anqp_nai_realm == NULL)
+ if (bss->anqp == NULL || bss->anqp->nai_realm == NULL)
return NULL;
if (wpa_s->conf->cred == NULL)
@@ -1311,7 +1316,7 @@ static struct wpa_cred * interworking_credentials_available_realm(
wpa_printf(MSG_DEBUG, "Interworking: Parsing NAI Realm list from "
MACSTR, MAC2STR(bss->bssid));
- realm = nai_realm_parse(bss->anqp_nai_realm, &count);
+ realm = nai_realm_parse(bss->anqp->nai_realm, &count);
if (realm == NULL) {
wpa_printf(MSG_DEBUG, "Interworking: Could not parse NAI "
"Realm list from " MACSTR, MAC2STR(bss->bssid));
@@ -1492,7 +1497,8 @@ static void interworking_select_network(struct wpa_supplicant *wpa_s)
continue;
}
count++;
- res = interworking_home_sp(wpa_s, bss->anqp_domain_name);
+ res = interworking_home_sp(wpa_s, bss->anqp ?
+ bss->anqp->domain_name : NULL);
if (res > 0)
type = "home";
else if (res == 0)
@@ -1572,6 +1578,11 @@ static void interworking_next_anqp_fetch(struct wpa_supplicant *wpa_s)
continue; /* AP does not support Interworking */
if (!(bss->flags & WPA_BSS_ANQP_FETCH_TRIED)) {
+ if (bss->anqp == NULL) {
+ bss->anqp = wpa_bss_anqp_alloc();
+ if (bss->anqp == NULL)
+ break;
+ }
found++;
bss->flags |= WPA_BSS_ANQP_FETCH_TRIED;
wpa_msg(wpa_s, MSG_INFO, "Starting ANQP fetch for "
@@ -1667,10 +1678,14 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
{
const u8 *pos = data;
struct wpa_bss *bss = wpa_bss_get_bssid(wpa_s, sa);
+ struct wpa_bss_anqp *anqp = NULL;
#ifdef CONFIG_HS20
u8 type;
#endif /* CONFIG_HS20 */
+ if (bss)
+ anqp = bss->anqp;
+
switch (info_id) {
case ANQP_CAPABILITY_LIST:
wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
@@ -1680,9 +1695,9 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
" Venue Name", MAC2STR(sa));
wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Venue Name", pos, slen);
- if (bss) {
- wpabuf_free(bss->anqp_venue_name);
- bss->anqp_venue_name = wpabuf_alloc_copy(pos, slen);
+ if (anqp) {
+ wpabuf_free(anqp->venue_name);
+ anqp->venue_name = wpabuf_alloc_copy(pos, slen);
}
break;
case ANQP_NETWORK_AUTH_TYPE:
@@ -1691,10 +1706,9 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
MAC2STR(sa));
wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Network Authentication "
"Type", pos, slen);
- if (bss) {
- wpabuf_free(bss->anqp_network_auth_type);
- bss->anqp_network_auth_type =
- wpabuf_alloc_copy(pos, slen);
+ if (anqp) {
+ wpabuf_free(anqp->network_auth_type);
+ anqp->network_auth_type = wpabuf_alloc_copy(pos, slen);
}
break;
case ANQP_ROAMING_CONSORTIUM:
@@ -1702,10 +1716,9 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
" Roaming Consortium list", MAC2STR(sa));
wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Roaming Consortium",
pos, slen);
- if (bss) {
- wpabuf_free(bss->anqp_roaming_consortium);
- bss->anqp_roaming_consortium =
- wpabuf_alloc_copy(pos, slen);
+ if (anqp) {
+ wpabuf_free(anqp->roaming_consortium);
+ anqp->roaming_consortium = wpabuf_alloc_copy(pos, slen);
}
break;
case ANQP_IP_ADDR_TYPE_AVAILABILITY:
@@ -1714,9 +1727,9 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
MAC2STR(sa));
wpa_hexdump(MSG_MSGDUMP, "ANQP: IP Address Availability",
pos, slen);
- if (bss) {
- wpabuf_free(bss->anqp_ip_addr_type_availability);
- bss->anqp_ip_addr_type_availability =
+ if (anqp) {
+ wpabuf_free(anqp->ip_addr_type_availability);
+ anqp->ip_addr_type_availability =
wpabuf_alloc_copy(pos, slen);
}
break;
@@ -1724,9 +1737,9 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
" NAI Realm list", MAC2STR(sa));
wpa_hexdump_ascii(MSG_DEBUG, "ANQP: NAI Realm", pos, slen);
- if (bss) {
- wpabuf_free(bss->anqp_nai_realm);
- bss->anqp_nai_realm = wpabuf_alloc_copy(pos, slen);
+ if (anqp) {
+ wpabuf_free(anqp->nai_realm);
+ anqp->nai_realm = wpabuf_alloc_copy(pos, slen);
}
break;
case ANQP_3GPP_CELLULAR_NETWORK:
@@ -1734,18 +1747,18 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
" 3GPP Cellular Network information", MAC2STR(sa));
wpa_hexdump_ascii(MSG_DEBUG, "ANQP: 3GPP Cellular Network",
pos, slen);
- if (bss) {
- wpabuf_free(bss->anqp_3gpp);
- bss->anqp_3gpp = wpabuf_alloc_copy(pos, slen);
+ if (anqp) {
+ wpabuf_free(anqp->anqp_3gpp);
+ anqp->anqp_3gpp = wpabuf_alloc_copy(pos, slen);
}
break;
case ANQP_DOMAIN_NAME:
wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
" Domain Name list", MAC2STR(sa));
wpa_hexdump_ascii(MSG_MSGDUMP, "ANQP: Domain Name", pos, slen);
- if (bss) {
- wpabuf_free(bss->anqp_domain_name);
- bss->anqp_domain_name = wpabuf_alloc_copy(pos, slen);
+ if (anqp) {
+ wpabuf_free(anqp->domain_name);
+ anqp->domain_name = wpabuf_alloc_copy(pos, slen);
}
break;
case ANQP_VENDOR_SPECIFIC: