aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <jouni@qca.qualcomm.com>2015-10-07 13:10:38 (GMT)
committerJouni Malinen <j@w1.fi>2015-10-07 14:07:21 (GMT)
commit8c4a1026b83b7bfb14c1f69d2b9a7c4be6c0758e (patch)
tree17acc3d6f58b490d9c3c67290202fed8d8f6a313
parentaeeb0bca712c5063c78c5294a4a669d975f35fa4 (diff)
downloadhostap-8c4a1026b83b7bfb14c1f69d2b9a7c4be6c0758e.zip
hostap-8c4a1026b83b7bfb14c1f69d2b9a7c4be6c0758e.tar.gz
hostap-8c4a1026b83b7bfb14c1f69d2b9a7c4be6c0758e.tar.bz2
Interworking: Support unknown ANQP-elements in BSS table
This allows wpa_supplicant to expose internally unknown ANQP-elements in the BSS command. For example, "ANQP_GET <BSSID> 265" can be used to fetch the AP Geospatial Location ANQP-element and if the AP has this information, the "BSS <BSSID>" command will include the response as "anqp[265]=<hexdump>". Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
-rw-r--r--wpa_supplicant/bss.c15
-rw-r--r--wpa_supplicant/bss.h7
-rw-r--r--wpa_supplicant/ctrl_iface.c11
-rw-r--r--wpa_supplicant/interworking.c36
4 files changed, 69 insertions, 0 deletions
diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c
index 1051ee3..704ee7e 100644
--- a/wpa_supplicant/bss.c
+++ b/wpa_supplicant/bss.c
@@ -60,6 +60,9 @@ struct wpa_bss_anqp * wpa_bss_anqp_alloc(void)
anqp = os_zalloc(sizeof(*anqp));
if (anqp == NULL)
return NULL;
+#ifdef CONFIG_INTERWORKING
+ dl_list_init(&anqp->anqp_elems);
+#endif /* CONFIG_INTERWORKING */
anqp->users = 1;
return anqp;
}
@@ -80,6 +83,7 @@ static struct wpa_bss_anqp * wpa_bss_anqp_clone(struct wpa_bss_anqp *anqp)
#define ANQP_DUP(f) if (anqp->f) n->f = wpabuf_dup(anqp->f)
#ifdef CONFIG_INTERWORKING
+ dl_list_init(&n->anqp_elems);
ANQP_DUP(capability_list);
ANQP_DUP(venue_name);
ANQP_DUP(network_auth_type);
@@ -141,6 +145,10 @@ int wpa_bss_anqp_unshare_alloc(struct wpa_bss *bss)
*/
static void wpa_bss_anqp_free(struct wpa_bss_anqp *anqp)
{
+#ifdef CONFIG_INTERWORKING
+ struct wpa_bss_anqp_elem *elem;
+#endif /* CONFIG_INTERWORKING */
+
if (anqp == NULL)
return;
@@ -159,6 +167,13 @@ static void wpa_bss_anqp_free(struct wpa_bss_anqp *anqp)
wpabuf_free(anqp->nai_realm);
wpabuf_free(anqp->anqp_3gpp);
wpabuf_free(anqp->domain_name);
+
+ while ((elem = dl_list_first(&anqp->anqp_elems,
+ struct wpa_bss_anqp_elem, list))) {
+ dl_list_del(&elem->list);
+ wpabuf_free(elem->payload);
+ os_free(elem);
+ }
#endif /* CONFIG_INTERWORKING */
#ifdef CONFIG_HS20
wpabuf_free(anqp->hs20_capability_list);
diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h
index b215380..4a782af 100644
--- a/wpa_supplicant/bss.h
+++ b/wpa_supplicant/bss.h
@@ -19,6 +19,12 @@ struct wpa_scan_res;
#define WPA_BSS_ASSOCIATED BIT(5)
#define WPA_BSS_ANQP_FETCH_TRIED BIT(6)
+struct wpa_bss_anqp_elem {
+ struct dl_list list;
+ u16 infoid;
+ struct wpabuf *payload;
+};
+
/**
* struct wpa_bss_anqp - ANQP data for a BSS entry (struct wpa_bss)
*/
@@ -34,6 +40,7 @@ struct wpa_bss_anqp {
struct wpabuf *nai_realm;
struct wpabuf *anqp_3gpp;
struct wpabuf *domain_name;
+ struct dl_list anqp_elems; /* list of struct wpa_bss_anqp_elem */
#endif /* CONFIG_INTERWORKING */
#ifdef CONFIG_HS20
struct wpabuf *hs20_capability_list;
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 02d0cc2..c8868b2 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -4231,6 +4231,8 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
#ifdef CONFIG_INTERWORKING
if ((mask & WPA_BSS_MASK_INTERNETW) && bss->anqp) {
struct wpa_bss_anqp *anqp = bss->anqp;
+ struct wpa_bss_anqp_elem *elem;
+
pos = anqp_add_hex(pos, end, "anqp_capability_list",
anqp->capability_list);
pos = anqp_add_hex(pos, end, "anqp_venue_name",
@@ -4260,6 +4262,15 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
pos = anqp_add_hex(pos, end, "hs20_osu_providers_list",
anqp->hs20_osu_providers_list);
#endif /* CONFIG_HS20 */
+
+ dl_list_for_each(elem, &anqp->anqp_elems,
+ struct wpa_bss_anqp_elem, list) {
+ char title[20];
+
+ os_snprintf(title, sizeof(title), "anqp[%u]",
+ elem->infoid);
+ pos = anqp_add_hex(pos, end, title, elem->payload);
+ }
}
#endif /* CONFIG_INTERWORKING */
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index fd47c17..9a6ab47 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -2716,6 +2716,41 @@ int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst,
}
+static void anqp_add_extra(struct wpa_supplicant *wpa_s,
+ struct wpa_bss_anqp *anqp, u16 info_id,
+ const u8 *data, size_t slen)
+{
+ struct wpa_bss_anqp_elem *tmp, *elem = NULL;
+
+ if (!anqp)
+ return;
+
+ dl_list_for_each(tmp, &anqp->anqp_elems, struct wpa_bss_anqp_elem,
+ list) {
+ if (tmp->infoid == info_id) {
+ elem = tmp;
+ break;
+ }
+ }
+
+ if (!elem) {
+ elem = os_zalloc(sizeof(*elem));
+ if (!elem)
+ return;
+ elem->infoid = info_id;
+ dl_list_add(&anqp->anqp_elems, &elem->list);
+ } else {
+ wpabuf_free(elem->payload);
+ }
+
+ elem->payload = wpabuf_alloc_copy(data, slen);
+ if (!elem->payload) {
+ dl_list_del(&elem->list);
+ os_free(elem);
+ }
+}
+
+
static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
struct wpa_bss *bss, const u8 *sa,
u16 info_id,
@@ -2849,6 +2884,7 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
default:
wpa_msg(wpa_s, MSG_DEBUG,
"Interworking: Unsupported ANQP Info ID %u", info_id);
+ anqp_add_extra(wpa_s, anqp, info_id, data, slen);
break;
}
}