mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-11-25 17:59:25 +01:00
anqp: move ANQP parsers into anqputil
This allows monitor to use the ANQP parser utils without depending on netdev.
This commit is contained in:
parent
6efc94ff5a
commit
2c19085ccd
@ -207,6 +207,7 @@ src_iwd_SOURCES = src/main.c linux/nl80211.h src/iwd.h src/missing.h \
|
||||
src/rtnlutil.h src/rtnlutil.c \
|
||||
src/auth-proto.h \
|
||||
src/anqp.h src/anqp.c \
|
||||
src/anqputil.h src/anqputil.c \
|
||||
src/netconfig.h src/netconfig.c\
|
||||
src/resolve.h src/resolve.c\
|
||||
src/hotspot.h src/hotspot.c \
|
||||
|
171
src/anqp.c
171
src/anqp.c
@ -59,177 +59,6 @@ static uint8_t anqp_token = 0;
|
||||
static uint32_t netdev_watch;
|
||||
static uint32_t unicast_watch;
|
||||
|
||||
void anqp_iter_init(struct anqp_iter *iter, const unsigned char *anqp,
|
||||
unsigned int len)
|
||||
{
|
||||
iter->anqp = anqp;
|
||||
iter->max = len;
|
||||
iter->pos = 0;
|
||||
}
|
||||
|
||||
bool anqp_iter_next(struct anqp_iter *iter, uint16_t *id, uint16_t *len,
|
||||
const void **data)
|
||||
{
|
||||
const unsigned char *anqp = iter->anqp + iter->pos;
|
||||
const unsigned char *end = iter->anqp + iter->max;
|
||||
|
||||
if (iter->pos + 4 >= iter->max)
|
||||
return false;
|
||||
|
||||
if (anqp + l_get_le16(anqp + 2) > end)
|
||||
return false;
|
||||
|
||||
*id = l_get_le16(anqp);
|
||||
anqp += 2;
|
||||
|
||||
*len = l_get_le16(anqp);
|
||||
anqp += 2;
|
||||
|
||||
*data = anqp;
|
||||
|
||||
iter->id = *id;
|
||||
iter->len = *len;
|
||||
iter->data = *data;
|
||||
|
||||
iter->pos = anqp + *len - iter->anqp;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool anqp_hs20_parse_osu_provider_nai(const unsigned char *anqp,
|
||||
unsigned int len, const char **nai_out)
|
||||
{
|
||||
uint8_t nai_len;
|
||||
static char nai[256] = { 0 };
|
||||
|
||||
if (len < 1)
|
||||
return false;
|
||||
|
||||
nai_len = *anqp++;
|
||||
len--;
|
||||
|
||||
if (len < nai_len)
|
||||
return false;
|
||||
|
||||
memcpy(nai, anqp, nai_len);
|
||||
|
||||
*nai_out = nai;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool anqp_iter_is_hs20(const struct anqp_iter *iter, uint8_t *stype,
|
||||
unsigned int *len, const unsigned char **data)
|
||||
{
|
||||
const unsigned char *anqp = iter->data;
|
||||
unsigned int anqp_len = iter->len;
|
||||
uint8_t type;
|
||||
|
||||
if (iter->len < 6)
|
||||
return false;
|
||||
|
||||
if (memcmp(anqp, wifi_alliance_oui, 3))
|
||||
return false;
|
||||
|
||||
anqp += 3;
|
||||
anqp_len -= 3;
|
||||
|
||||
type = *anqp++;
|
||||
anqp_len--;
|
||||
|
||||
if (type != 0x11)
|
||||
return false;
|
||||
|
||||
*stype = *anqp++;
|
||||
anqp_len--;
|
||||
|
||||
/* reserved byte */
|
||||
anqp++;
|
||||
anqp_len--;
|
||||
|
||||
*data = anqp;
|
||||
*len = anqp_len;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
char **anqp_parse_nai_realms(const unsigned char *anqp, unsigned int len)
|
||||
{
|
||||
char **realms = NULL;
|
||||
uint16_t count;
|
||||
|
||||
if (len < 2)
|
||||
return false;
|
||||
|
||||
count = l_get_le16(anqp);
|
||||
|
||||
anqp += 2;
|
||||
len -= 2;
|
||||
|
||||
l_debug("");
|
||||
|
||||
while (count--) {
|
||||
uint16_t realm_len;
|
||||
uint8_t encoding;
|
||||
uint8_t nai_len;
|
||||
char nai_realm[256] = { 0 };
|
||||
|
||||
/*
|
||||
* The method list is a variable field, so the only way to
|
||||
* reliably increment anqp is by realm_len at the very end since
|
||||
* we dont know how many bytes parse_eap advanced (it does
|
||||
* internal length checking so it should not overflow). We
|
||||
* cant incrementally advance anqp/len, hence the hardcoded
|
||||
* length and pointer adjustments.
|
||||
*/
|
||||
|
||||
if (len < 4)
|
||||
goto failed;
|
||||
|
||||
realm_len = l_get_le16(anqp);
|
||||
anqp += 2;
|
||||
len -= 2;
|
||||
|
||||
encoding = anqp[0];
|
||||
|
||||
nai_len = anqp[1];
|
||||
|
||||
if (len - 2 < nai_len)
|
||||
goto failed;
|
||||
|
||||
memcpy(nai_realm, anqp + 2, nai_len);
|
||||
|
||||
/*
|
||||
* TODO: Verify NAI encoding in accordance with RFC 4282 ?
|
||||
*
|
||||
* The encoding in RFC 4282 seems to only limit which characters
|
||||
* can be used in an NAI. Since these come in from public
|
||||
* action frames it could have been spoofed, but ultimately if
|
||||
* its bogus the AP won't allow us to connect.
|
||||
*/
|
||||
if (!util_is_bit_set(encoding, 0))
|
||||
l_warn("Not verifying NAI encoding");
|
||||
else if (!l_utf8_validate(nai_realm, nai_len, NULL)) {
|
||||
l_warn("NAI is not UTF-8");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
realms = l_strv_append(realms, nai_realm);
|
||||
|
||||
if (len < realm_len)
|
||||
goto failed;
|
||||
|
||||
anqp += realm_len;
|
||||
len -= realm_len;
|
||||
}
|
||||
|
||||
return realms;
|
||||
|
||||
failed:
|
||||
l_strv_free(realms);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void anqp_destroy(void *user_data)
|
||||
{
|
||||
struct anqp_request *request = user_data;
|
||||
|
83
src/anqp.h
83
src/anqp.h
@ -20,10 +20,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <unistd.h>
|
||||
|
||||
struct scan_bss;
|
||||
|
||||
enum anqp_result {
|
||||
@ -38,85 +34,6 @@ typedef void (*anqp_response_func_t)(enum anqp_result result,
|
||||
const void *anqp, size_t len,
|
||||
void *user_data);
|
||||
|
||||
/* IEEE 802.11-2016 Section 9.4.5 ANQP elements */
|
||||
enum anqp_element {
|
||||
/* 0-255 reserved */
|
||||
ANQP_QUERY_LIST = 256,
|
||||
ANQP_CAPABILITY_LIST = 257,
|
||||
ANQP_VENUE_NAME = 258,
|
||||
ANQP_EMERGENCY_CALL_NUMBER = 259,
|
||||
ANQP_NETWORK_AUTH_TYPE = 260,
|
||||
ANQP_ROAMING_CONSORTIUM = 261,
|
||||
ANQP_IP_ADDRESS_TYPE_AVAILABILITY = 262,
|
||||
ANQP_NAI_REALM = 263,
|
||||
ANQP_3GPP_CELLULAR_NETWORK = 264,
|
||||
ANQP_AP_GEOSPATIAL_LOCATION = 265,
|
||||
ANQP_AP_CIVIC_LOCATION = 266,
|
||||
ANQP_AP_LOCATION_PUBLIC_ID = 267,
|
||||
ANQP_DOMAIN_NAME = 268,
|
||||
ANQP_EMERGENCY_ALERT_ID_URI = 269,
|
||||
ANQP_TDLS_CAPABILITY = 270,
|
||||
ANQP_EMERGENCY_NAI = 271,
|
||||
ANQP_NEIGHBOR_REPORT = 272,
|
||||
/* 273-276 reserved */
|
||||
ANQP_VENUE_URI = 277,
|
||||
ANQP_ADVICE_OF_CHARGE = 278,
|
||||
ANQP_LOCAL_CONTENT = 279,
|
||||
ANQP_NETWORK_AUTH_TYPE_WITH_TIMESTAMP = 280,
|
||||
/* 281-56796 reserved */
|
||||
ANQP_VENDOR_SPECIFIC = 56797,
|
||||
/* 56798-65535 reserved */
|
||||
};
|
||||
|
||||
/* WiFi Alliance Hotspot 2.0 Spec - Section 4 Hotspot 2.0 ANQP-elements */
|
||||
enum anqp_hs20_element {
|
||||
ANQP_HS20_QUERY_LIST = 1,
|
||||
ANQP_HS20_CAPABILITY_LIST = 2,
|
||||
ANQP_HS20_OPERATOR_FRIENDLY_NAME = 3,
|
||||
ANQP_HS20_WLAN_METRICS = 4,
|
||||
ANQP_HS20_CONNECTION_CAPABILITY = 5,
|
||||
ANQP_HS20_NAI_HOME_REALM_QUERY = 6,
|
||||
ANQP_HS20_OPERATING_CLASS_INDICATION = 7,
|
||||
ANQP_HS20_OSU_PROVIDERS_LIST = 8,
|
||||
/* 9 reserved */
|
||||
ANQP_HS20_ICON_REQUST = 10,
|
||||
ANQP_HS20_ICON_BINARY_FILE = 11,
|
||||
ANQP_HS20_OPERATOR_ICON_METADATA = 12,
|
||||
ANQP_HS20_OSU_PROVIDERS_NAI_LIST = 13,
|
||||
/* 14 - 255 reserved */
|
||||
};
|
||||
|
||||
/* IEEE 802.11-2016 Table 9-275 Authentication Parameter types */
|
||||
enum anqp_auth_parameter_type {
|
||||
ANQP_AP_EXPANDED_EAP_METHOD = 1,
|
||||
ANQP_AP_NON_INNER_AUTH_EAP = 2,
|
||||
ANQP_AP_INNER_AUTH_EAP = 3,
|
||||
ANQP_AP_EXPANDED_INNER_EAP_METHOD = 4,
|
||||
ANQP_AP_CREDENTIAL = 5,
|
||||
ANQP_AP_TUNNELED_EAP_CREDENTIAL = 6,
|
||||
ANQP_AP_VENDOR_SPECIFIC = 221,
|
||||
};
|
||||
|
||||
struct anqp_iter {
|
||||
unsigned int max;
|
||||
unsigned int pos;
|
||||
const unsigned char *anqp;
|
||||
|
||||
unsigned int id;
|
||||
unsigned int len;
|
||||
const unsigned char *data;
|
||||
};
|
||||
|
||||
void anqp_iter_init(struct anqp_iter *iter, const unsigned char *anqp,
|
||||
unsigned int len);
|
||||
bool anqp_iter_next(struct anqp_iter *iter, uint16_t *id, uint16_t *len,
|
||||
const void **data);
|
||||
bool anqp_iter_is_hs20(const struct anqp_iter *iter, uint8_t *stype,
|
||||
unsigned int *len, const unsigned char **data);
|
||||
bool anqp_hs20_parse_osu_provider_nai(const unsigned char *anqp,
|
||||
unsigned int len, const char **nai_out);
|
||||
char **anqp_parse_nai_realms(const unsigned char *anqp, unsigned int len);
|
||||
|
||||
uint32_t anqp_request(uint32_t ifindex, const uint8_t *addr,
|
||||
struct scan_bss *bss, const uint8_t *anqp, size_t len,
|
||||
anqp_response_func_t cb, void *user_data,
|
||||
|
202
src/anqputil.c
Normal file
202
src/anqputil.c
Normal file
@ -0,0 +1,202 @@
|
||||
/*
|
||||
*
|
||||
* Wireless daemon for Linux
|
||||
*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <ell/ell.h>
|
||||
|
||||
#include "anqputil.h"
|
||||
#include "ie.h"
|
||||
#include "util.h"
|
||||
|
||||
void anqp_iter_init(struct anqp_iter *iter, const unsigned char *anqp,
|
||||
unsigned int len)
|
||||
{
|
||||
iter->anqp = anqp;
|
||||
iter->max = len;
|
||||
iter->pos = 0;
|
||||
}
|
||||
|
||||
bool anqp_iter_next(struct anqp_iter *iter, uint16_t *id, uint16_t *len,
|
||||
const void **data)
|
||||
{
|
||||
const unsigned char *anqp = iter->anqp + iter->pos;
|
||||
const unsigned char *end = iter->anqp + iter->max;
|
||||
|
||||
if (iter->pos + 4 >= iter->max)
|
||||
return false;
|
||||
|
||||
if (anqp + l_get_le16(anqp + 2) > end)
|
||||
return false;
|
||||
|
||||
*id = l_get_le16(anqp);
|
||||
anqp += 2;
|
||||
|
||||
*len = l_get_le16(anqp);
|
||||
anqp += 2;
|
||||
|
||||
*data = anqp;
|
||||
|
||||
iter->id = *id;
|
||||
iter->len = *len;
|
||||
iter->data = *data;
|
||||
|
||||
iter->pos = anqp + *len - iter->anqp;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool anqp_hs20_parse_osu_provider_nai(const unsigned char *anqp,
|
||||
unsigned int len, const char **nai_out)
|
||||
{
|
||||
uint8_t nai_len;
|
||||
static char nai[256] = { 0 };
|
||||
|
||||
if (len < 1)
|
||||
return false;
|
||||
|
||||
nai_len = *anqp++;
|
||||
len--;
|
||||
|
||||
if (len < nai_len)
|
||||
return false;
|
||||
|
||||
memcpy(nai, anqp, nai_len);
|
||||
|
||||
*nai_out = nai;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool anqp_iter_is_hs20(const struct anqp_iter *iter, uint8_t *stype,
|
||||
unsigned int *len, const unsigned char **data)
|
||||
{
|
||||
const unsigned char *anqp = iter->data;
|
||||
unsigned int anqp_len = iter->len;
|
||||
uint8_t type;
|
||||
|
||||
if (iter->len < 6)
|
||||
return false;
|
||||
|
||||
if (memcmp(anqp, wifi_alliance_oui, 3))
|
||||
return false;
|
||||
|
||||
anqp += 3;
|
||||
anqp_len -= 3;
|
||||
|
||||
type = *anqp++;
|
||||
anqp_len--;
|
||||
|
||||
if (type != 0x11)
|
||||
return false;
|
||||
|
||||
*stype = *anqp++;
|
||||
anqp_len--;
|
||||
|
||||
/* reserved byte */
|
||||
anqp++;
|
||||
anqp_len--;
|
||||
|
||||
*data = anqp;
|
||||
*len = anqp_len;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
char **anqp_parse_nai_realms(const unsigned char *anqp, unsigned int len)
|
||||
{
|
||||
char **realms = NULL;
|
||||
uint16_t count;
|
||||
|
||||
if (len < 2)
|
||||
return false;
|
||||
|
||||
count = l_get_le16(anqp);
|
||||
|
||||
anqp += 2;
|
||||
len -= 2;
|
||||
|
||||
l_debug("");
|
||||
|
||||
while (count--) {
|
||||
uint16_t realm_len;
|
||||
uint8_t encoding;
|
||||
uint8_t nai_len;
|
||||
char nai_realm[256] = { 0 };
|
||||
|
||||
/*
|
||||
* The method list is a variable field, so the only way to
|
||||
* reliably increment anqp is by realm_len at the very end since
|
||||
* we dont know how many bytes parse_eap advanced (it does
|
||||
* internal length checking so it should not overflow). We
|
||||
* cant incrementally advance anqp/len, hence the hardcoded
|
||||
* length and pointer adjustments.
|
||||
*/
|
||||
|
||||
if (len < 4)
|
||||
goto failed;
|
||||
|
||||
realm_len = l_get_le16(anqp);
|
||||
anqp += 2;
|
||||
len -= 2;
|
||||
|
||||
encoding = anqp[0];
|
||||
|
||||
nai_len = anqp[1];
|
||||
|
||||
if (len - 2 < nai_len)
|
||||
goto failed;
|
||||
|
||||
memcpy(nai_realm, anqp + 2, nai_len);
|
||||
|
||||
/*
|
||||
* TODO: Verify NAI encoding in accordance with RFC 4282 ?
|
||||
*
|
||||
* The encoding in RFC 4282 seems to only limit which characters
|
||||
* can be used in an NAI. Since these come in from public
|
||||
* action frames it could have been spoofed, but ultimately if
|
||||
* its bogus the AP won't allow us to connect.
|
||||
*/
|
||||
if (!util_is_bit_set(encoding, 0))
|
||||
l_warn("Not verifying NAI encoding");
|
||||
else if (!l_utf8_validate(nai_realm, nai_len, NULL)) {
|
||||
l_warn("NAI is not UTF-8");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
realms = l_strv_append(realms, nai_realm);
|
||||
|
||||
if (len < realm_len)
|
||||
goto failed;
|
||||
|
||||
anqp += realm_len;
|
||||
len -= realm_len;
|
||||
}
|
||||
|
||||
return realms;
|
||||
|
||||
failed:
|
||||
l_strv_free(realms);
|
||||
return NULL;
|
||||
}
|
103
src/anqputil.h
Normal file
103
src/anqputil.h
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
*
|
||||
* Wireless daemon for Linux
|
||||
*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* IEEE 802.11-2016 Section 9.4.5 ANQP elements */
|
||||
enum anqp_element {
|
||||
/* 0-255 reserved */
|
||||
ANQP_QUERY_LIST = 256,
|
||||
ANQP_CAPABILITY_LIST = 257,
|
||||
ANQP_VENUE_NAME = 258,
|
||||
ANQP_EMERGENCY_CALL_NUMBER = 259,
|
||||
ANQP_NETWORK_AUTH_TYPE = 260,
|
||||
ANQP_ROAMING_CONSORTIUM = 261,
|
||||
ANQP_IP_ADDRESS_TYPE_AVAILABILITY = 262,
|
||||
ANQP_NAI_REALM = 263,
|
||||
ANQP_3GPP_CELLULAR_NETWORK = 264,
|
||||
ANQP_AP_GEOSPATIAL_LOCATION = 265,
|
||||
ANQP_AP_CIVIC_LOCATION = 266,
|
||||
ANQP_AP_LOCATION_PUBLIC_ID = 267,
|
||||
ANQP_DOMAIN_NAME = 268,
|
||||
ANQP_EMERGENCY_ALERT_ID_URI = 269,
|
||||
ANQP_TDLS_CAPABILITY = 270,
|
||||
ANQP_EMERGENCY_NAI = 271,
|
||||
ANQP_NEIGHBOR_REPORT = 272,
|
||||
/* 273-276 reserved */
|
||||
ANQP_VENUE_URI = 277,
|
||||
ANQP_ADVICE_OF_CHARGE = 278,
|
||||
ANQP_LOCAL_CONTENT = 279,
|
||||
ANQP_NETWORK_AUTH_TYPE_WITH_TIMESTAMP = 280,
|
||||
/* 281-56796 reserved */
|
||||
ANQP_VENDOR_SPECIFIC = 56797,
|
||||
/* 56798-65535 reserved */
|
||||
};
|
||||
|
||||
/* WiFi Alliance Hotspot 2.0 Spec - Section 4 Hotspot 2.0 ANQP-elements */
|
||||
enum anqp_hs20_element {
|
||||
ANQP_HS20_QUERY_LIST = 1,
|
||||
ANQP_HS20_CAPABILITY_LIST = 2,
|
||||
ANQP_HS20_OPERATOR_FRIENDLY_NAME = 3,
|
||||
ANQP_HS20_WLAN_METRICS = 4,
|
||||
ANQP_HS20_CONNECTION_CAPABILITY = 5,
|
||||
ANQP_HS20_NAI_HOME_REALM_QUERY = 6,
|
||||
ANQP_HS20_OPERATING_CLASS_INDICATION = 7,
|
||||
ANQP_HS20_OSU_PROVIDERS_LIST = 8,
|
||||
/* 9 reserved */
|
||||
ANQP_HS20_ICON_REQUST = 10,
|
||||
ANQP_HS20_ICON_BINARY_FILE = 11,
|
||||
ANQP_HS20_OPERATOR_ICON_METADATA = 12,
|
||||
ANQP_HS20_OSU_PROVIDERS_NAI_LIST = 13,
|
||||
/* 14 - 255 reserved */
|
||||
};
|
||||
|
||||
/* IEEE 802.11-2016 Table 9-275 Authentication Parameter types */
|
||||
enum anqp_auth_parameter_type {
|
||||
ANQP_AP_EXPANDED_EAP_METHOD = 1,
|
||||
ANQP_AP_NON_INNER_AUTH_EAP = 2,
|
||||
ANQP_AP_INNER_AUTH_EAP = 3,
|
||||
ANQP_AP_EXPANDED_INNER_EAP_METHOD = 4,
|
||||
ANQP_AP_CREDENTIAL = 5,
|
||||
ANQP_AP_TUNNELED_EAP_CREDENTIAL = 6,
|
||||
ANQP_AP_VENDOR_SPECIFIC = 221,
|
||||
};
|
||||
|
||||
struct anqp_iter {
|
||||
unsigned int max;
|
||||
unsigned int pos;
|
||||
const unsigned char *anqp;
|
||||
|
||||
unsigned int id;
|
||||
unsigned int len;
|
||||
const unsigned char *data;
|
||||
};
|
||||
|
||||
void anqp_iter_init(struct anqp_iter *iter, const unsigned char *anqp,
|
||||
unsigned int len);
|
||||
bool anqp_iter_next(struct anqp_iter *iter, uint16_t *id, uint16_t *len,
|
||||
const void **data);
|
||||
bool anqp_iter_is_hs20(const struct anqp_iter *iter, uint8_t *stype,
|
||||
unsigned int *len, const unsigned char **data);
|
||||
bool anqp_hs20_parse_osu_provider_nai(const unsigned char *anqp,
|
||||
unsigned int len, const char **nai_out);
|
||||
char **anqp_parse_nai_realms(const unsigned char *anqp, unsigned int len);
|
@ -52,6 +52,7 @@
|
||||
#include "src/erp.h"
|
||||
#include "src/netconfig.h"
|
||||
#include "src/anqp.h"
|
||||
#include "src/anqputil.h"
|
||||
#include "src/hotspot.h"
|
||||
|
||||
static struct l_queue *station_list;
|
||||
|
Loading…
Reference in New Issue
Block a user