]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
HS 2.0: Extend ANQP_GET to accept Hotspot 2.0 subtypes
authorDmitry Shmidt <dimitrysh@google.com>
Tue, 25 Mar 2014 00:36:13 +0000 (17:36 -0700)
committerJouni Malinen <j@w1.fi>
Tue, 25 Mar 2014 16:33:21 +0000 (18:33 +0200)
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>
wpa_supplicant/ctrl_iface.c
wpa_supplicant/hs20_supplicant.c
wpa_supplicant/hs20_supplicant.h
wpa_supplicant/interworking.c
wpa_supplicant/interworking.h

index 19ac27c2ef1921523d2075c3ac98970c77702786..925ece1289fca668134c7a44219004c753fc6f67 100644 (file)
@@ -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);
 }
 
 
index b342d5d898b3f5daacecd3f24e1ef12984f00ccf..c242c3319acb8060135828ce8ebeee9a5f93948f 100644 (file)
@@ -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;
 }
index 88e506209ef17f4f45e6753e037438ec7fd3a8db..f6c4d4432066d0238994b2e60e8cb6c9667a4e39 100644 (file)
@@ -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,
index e3ad9314f06072e0d296f57d5d1ea1bc29a35092..71163c39746bec6271941e30f5f8883f67c8438a 100644 (file)
@@ -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;
 
index bb0ceb813f3459b876af326e04e911feacf583aa..38ef745fad45fba2b77cbf099ea3a30ac80cd72f 100644 (file)
@@ -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,