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>
This commit is contained in:
parent
163f801ef2
commit
cf28c66bcb
5 changed files with 48 additions and 12 deletions
|
@ -4945,15 +4945,27 @@ static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
|
||||||
#define MAX_ANQP_INFO_ID 100
|
#define MAX_ANQP_INFO_ID 100
|
||||||
u16 id[MAX_ANQP_INFO_ID];
|
u16 id[MAX_ANQP_INFO_ID];
|
||||||
size_t num_id = 0;
|
size_t num_id = 0;
|
||||||
|
u32 subtypes = 0;
|
||||||
|
|
||||||
used = hwaddr_aton2(dst, dst_addr);
|
used = hwaddr_aton2(dst, dst_addr);
|
||||||
if (used < 0)
|
if (used < 0)
|
||||||
return -1;
|
return -1;
|
||||||
pos = dst + used;
|
pos = dst + used;
|
||||||
while (num_id < MAX_ANQP_INFO_ID) {
|
while (num_id < MAX_ANQP_INFO_ID) {
|
||||||
id[num_id] = atoi(pos);
|
if (os_strncmp(pos, "hs20:", 5) == 0) {
|
||||||
if (id[num_id])
|
#ifdef CONFIG_HS20
|
||||||
num_id++;
|
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, ',');
|
pos = os_strchr(pos + 1, ',');
|
||||||
if (pos == NULL)
|
if (pos == NULL)
|
||||||
break;
|
break;
|
||||||
|
@ -4963,7 +4975,7 @@ static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
|
||||||
if (num_id == 0)
|
if (num_id == 0)
|
||||||
return -1;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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,
|
void hs20_put_anqp_req(u32 stypes, const u8 *payload, size_t payload_len,
|
||||||
size_t payload_len)
|
struct wpabuf *buf)
|
||||||
{
|
{
|
||||||
struct wpabuf *buf;
|
|
||||||
u8 *len_pos;
|
u8 *len_pos;
|
||||||
|
|
||||||
buf = gas_anqp_build_initial_req(0, 100 + payload_len);
|
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
return NULL;
|
return;
|
||||||
|
|
||||||
len_pos = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
|
len_pos = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
|
||||||
wpabuf_put_be24(buf, OUI_WFA);
|
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_element_len(buf, len_pos);
|
||||||
|
|
||||||
gas_anqp_set_len(buf);
|
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;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
const u8 *payload, size_t payload_len);
|
||||||
struct wpabuf * hs20_build_anqp_req(u32 stypes, const u8 *payload,
|
struct wpabuf * hs20_build_anqp_req(u32 stypes, const u8 *payload,
|
||||||
size_t payload_len);
|
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,
|
void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s,
|
||||||
const u8 *sa, const u8 *data, size_t slen);
|
const u8 *sa, const u8 *data, size_t slen);
|
||||||
int is_hs20_network(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
|
int is_hs20_network(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
|
||||||
|
|
|
@ -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,
|
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 *buf;
|
||||||
|
struct wpabuf *hs20_buf = NULL;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int freq;
|
int freq;
|
||||||
struct wpa_bss *bss;
|
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)",
|
wpa_printf(MSG_DEBUG, "ANQP: Query Request to " MACSTR " for %u id(s)",
|
||||||
MAC2STR(dst), (unsigned int) num_ids);
|
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)
|
if (buf == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
enum gas_query_result;
|
enum gas_query_result;
|
||||||
|
|
||||||
int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst,
|
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,
|
void anqp_resp_cb(void *ctx, const u8 *dst, u8 dialog_token,
|
||||||
enum gas_query_result result,
|
enum gas_query_result result,
|
||||||
const struct wpabuf *adv_proto,
|
const struct wpabuf *adv_proto,
|
||||||
|
|
Loading…
Reference in a new issue