aboutsummaryrefslogtreecommitdiffstats
path: root/wpa_supplicant
diff options
context:
space:
mode:
authorDmitry Shmidt <dimitrysh@google.com>2014-03-25 00:36:13 (GMT)
committerJouni Malinen <j@w1.fi>2014-03-25 16:33:21 (GMT)
commitcf28c66bcb8883e6be921d6406a534e4a5b45b96 (patch)
treebee8efd6c819bbf3cd5d29806e6890222834e3ce /wpa_supplicant
parent163f801ef23cd486aab5065c90dd71ad4cbb5fcd (diff)
downloadhostap-cf28c66bcb8883e6be921d6406a534e4a5b45b96.zip
hostap-cf28c66bcb8883e6be921d6406a534e4a5b45b96.tar.gz
hostap-cf28c66bcb8883e6be921d6406a534e4a5b45b96.tar.bz2
HS 2.0: Extend ANQP_GET to accept Hotspot 2.0 subtypes
This allows a single ANQP query to be used to fetch both IEEE 802.11 defined ANQP elements and Hotspot 2.0 vendor specific elements. ANQP_GET <addr> <info id>[,<info id>]... [,hs20:<subtype>][...,hs20:<subtype>] For example: ANQP_GET 00:11:22:33:44:55:66 258,268,hs20:3,hs20:4 Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
Diffstat (limited to 'wpa_supplicant')
-rw-r--r--wpa_supplicant/ctrl_iface.c20
-rw-r--r--wpa_supplicant/hs20_supplicant.c21
-rw-r--r--wpa_supplicant/hs20_supplicant.h2
-rw-r--r--wpa_supplicant/interworking.c15
-rw-r--r--wpa_supplicant/interworking.h2
5 files changed, 48 insertions, 12 deletions
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 19ac27c..925ece1 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -4945,15 +4945,27 @@ static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
#define MAX_ANQP_INFO_ID 100
u16 id[MAX_ANQP_INFO_ID];
size_t num_id = 0;
+ u32 subtypes = 0;
used = hwaddr_aton2(dst, dst_addr);
if (used < 0)
return -1;
pos = dst + used;
while (num_id < MAX_ANQP_INFO_ID) {
- id[num_id] = atoi(pos);
- if (id[num_id])
- num_id++;
+ if (os_strncmp(pos, "hs20:", 5) == 0) {
+#ifdef CONFIG_HS20
+ int num = atoi(pos + 5);
+ if (num <= 0 || num > 31)
+ return -1;
+ subtypes |= BIT(num);
+#else /* CONFIG_HS20 */
+ return -1;
+#endif /* CONFIG_HS20 */
+ } else {
+ id[num_id] = atoi(pos);
+ if (id[num_id])
+ num_id++;
+ }
pos = os_strchr(pos + 1, ',');
if (pos == NULL)
break;
@@ -4963,7 +4975,7 @@ static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
if (num_id == 0)
return -1;
- return anqp_send_req(wpa_s, dst_addr, id, num_id);
+ return anqp_send_req(wpa_s, dst_addr, id, num_id, subtypes);
}
diff --git a/wpa_supplicant/hs20_supplicant.c b/wpa_supplicant/hs20_supplicant.c
index b342d5d..c242c33 100644
--- a/wpa_supplicant/hs20_supplicant.c
+++ b/wpa_supplicant/hs20_supplicant.c
@@ -121,15 +121,13 @@ int hs20_get_pps_mo_id(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
}
-struct wpabuf * hs20_build_anqp_req(u32 stypes, const u8 *payload,
- size_t payload_len)
+void hs20_put_anqp_req(u32 stypes, const u8 *payload, size_t payload_len,
+ struct wpabuf *buf)
{
- struct wpabuf *buf;
u8 *len_pos;
- buf = gas_anqp_build_initial_req(0, 100 + payload_len);
if (buf == NULL)
- return NULL;
+ return;
len_pos = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
wpabuf_put_be24(buf, OUI_WFA);
@@ -156,6 +154,19 @@ struct wpabuf * hs20_build_anqp_req(u32 stypes, const u8 *payload,
gas_anqp_set_element_len(buf, len_pos);
gas_anqp_set_len(buf);
+}
+
+
+struct wpabuf * hs20_build_anqp_req(u32 stypes, const u8 *payload,
+ size_t payload_len)
+{
+ struct wpabuf *buf;
+
+ buf = gas_anqp_build_initial_req(0, 100 + payload_len);
+ if (buf == NULL)
+ return NULL;
+
+ hs20_put_anqp_req(stypes, payload, payload_len, buf);
return buf;
}
diff --git a/wpa_supplicant/hs20_supplicant.h b/wpa_supplicant/hs20_supplicant.h
index 88e5062..f6c4d44 100644
--- a/wpa_supplicant/hs20_supplicant.h
+++ b/wpa_supplicant/hs20_supplicant.h
@@ -14,6 +14,8 @@ int hs20_anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, u32 stypes,
const u8 *payload, size_t payload_len);
struct wpabuf * hs20_build_anqp_req(u32 stypes, const u8 *payload,
size_t payload_len);
+void hs20_put_anqp_req(u32 stypes, const u8 *payload, size_t payload_len,
+ struct wpabuf *buf);
void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s,
const u8 *sa, const u8 *data, size_t slen);
int is_hs20_network(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index e3ad931..71163c3 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -2531,9 +2531,10 @@ void interworking_stop_fetch_anqp(struct wpa_supplicant *wpa_s)
int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst,
- u16 info_ids[], size_t num_ids)
+ u16 info_ids[], size_t num_ids, u32 subtypes)
{
struct wpabuf *buf;
+ struct wpabuf *hs20_buf = NULL;
int ret = 0;
int freq;
struct wpa_bss *bss;
@@ -2551,7 +2552,17 @@ int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst,
wpa_printf(MSG_DEBUG, "ANQP: Query Request to " MACSTR " for %u id(s)",
MAC2STR(dst), (unsigned int) num_ids);
- buf = anqp_build_req(info_ids, num_ids, NULL);
+#ifdef CONFIG_HS20
+ if (subtypes != 0) {
+ hs20_buf = wpabuf_alloc(100);
+ if (hs20_buf == NULL)
+ return -1;
+ hs20_put_anqp_req(subtypes, NULL, 0, hs20_buf);
+ }
+#endif /* CONFIG_HS20 */
+
+ buf = anqp_build_req(info_ids, num_ids, hs20_buf);
+ wpabuf_free(hs20_buf);
if (buf == NULL)
return -1;
diff --git a/wpa_supplicant/interworking.h b/wpa_supplicant/interworking.h
index bb0ceb8..38ef745 100644
--- a/wpa_supplicant/interworking.h
+++ b/wpa_supplicant/interworking.h
@@ -12,7 +12,7 @@
enum gas_query_result;
int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst,
- u16 info_ids[], size_t num_ids);
+ u16 info_ids[], size_t num_ids, u32 subtypes);
void anqp_resp_cb(void *ctx, const u8 *dst, u8 dialog_token,
enum gas_query_result result,
const struct wpabuf *adv_proto,