From cf28c66bcb8883e6be921d6406a534e4a5b45b96 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Mon, 24 Mar 2014 17:36:13 -0700 Subject: [PATCH] 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 [,]... [,hs20:][...,hs20:] For example: ANQP_GET 00:11:22:33:44:55:66 258,268,hs20:3,hs20:4 Signed-off-by: Dmitry Shmidt --- wpa_supplicant/ctrl_iface.c | 20 ++++++++++++++++---- wpa_supplicant/hs20_supplicant.c | 21 ++++++++++++++++----- wpa_supplicant/hs20_supplicant.h | 2 ++ wpa_supplicant/interworking.c | 15 +++++++++++++-- wpa_supplicant/interworking.h | 2 +- 5 files changed, 48 insertions(+), 12 deletions(-) diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 19ac27c2e..925ece128 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 b342d5d89..c242c3319 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 88e506209..f6c4d4432 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 e3ad9314f..71163c397 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 bb0ceb813..38ef745fa 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,