Interworking: Support unknown ANQP-elements in BSS table
This allows wpa_supplicant to expose internally unknown ANQP-elements in the BSS command. For example, "ANQP_GET <BSSID> 265" can be used to fetch the AP Geospatial Location ANQP-element and if the AP has this information, the "BSS <BSSID>" command will include the response as "anqp[265]=<hexdump>". Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
aeeb0bca71
commit
8c4a1026b8
4 changed files with 69 additions and 0 deletions
|
@ -60,6 +60,9 @@ struct wpa_bss_anqp * wpa_bss_anqp_alloc(void)
|
|||
anqp = os_zalloc(sizeof(*anqp));
|
||||
if (anqp == NULL)
|
||||
return NULL;
|
||||
#ifdef CONFIG_INTERWORKING
|
||||
dl_list_init(&anqp->anqp_elems);
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
anqp->users = 1;
|
||||
return anqp;
|
||||
}
|
||||
|
@ -80,6 +83,7 @@ static struct wpa_bss_anqp * wpa_bss_anqp_clone(struct wpa_bss_anqp *anqp)
|
|||
|
||||
#define ANQP_DUP(f) if (anqp->f) n->f = wpabuf_dup(anqp->f)
|
||||
#ifdef CONFIG_INTERWORKING
|
||||
dl_list_init(&n->anqp_elems);
|
||||
ANQP_DUP(capability_list);
|
||||
ANQP_DUP(venue_name);
|
||||
ANQP_DUP(network_auth_type);
|
||||
|
@ -141,6 +145,10 @@ int wpa_bss_anqp_unshare_alloc(struct wpa_bss *bss)
|
|||
*/
|
||||
static void wpa_bss_anqp_free(struct wpa_bss_anqp *anqp)
|
||||
{
|
||||
#ifdef CONFIG_INTERWORKING
|
||||
struct wpa_bss_anqp_elem *elem;
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
|
||||
if (anqp == NULL)
|
||||
return;
|
||||
|
||||
|
@ -159,6 +167,13 @@ static void wpa_bss_anqp_free(struct wpa_bss_anqp *anqp)
|
|||
wpabuf_free(anqp->nai_realm);
|
||||
wpabuf_free(anqp->anqp_3gpp);
|
||||
wpabuf_free(anqp->domain_name);
|
||||
|
||||
while ((elem = dl_list_first(&anqp->anqp_elems,
|
||||
struct wpa_bss_anqp_elem, list))) {
|
||||
dl_list_del(&elem->list);
|
||||
wpabuf_free(elem->payload);
|
||||
os_free(elem);
|
||||
}
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
#ifdef CONFIG_HS20
|
||||
wpabuf_free(anqp->hs20_capability_list);
|
||||
|
|
|
@ -19,6 +19,12 @@ struct wpa_scan_res;
|
|||
#define WPA_BSS_ASSOCIATED BIT(5)
|
||||
#define WPA_BSS_ANQP_FETCH_TRIED BIT(6)
|
||||
|
||||
struct wpa_bss_anqp_elem {
|
||||
struct dl_list list;
|
||||
u16 infoid;
|
||||
struct wpabuf *payload;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct wpa_bss_anqp - ANQP data for a BSS entry (struct wpa_bss)
|
||||
*/
|
||||
|
@ -34,6 +40,7 @@ struct wpa_bss_anqp {
|
|||
struct wpabuf *nai_realm;
|
||||
struct wpabuf *anqp_3gpp;
|
||||
struct wpabuf *domain_name;
|
||||
struct dl_list anqp_elems; /* list of struct wpa_bss_anqp_elem */
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
#ifdef CONFIG_HS20
|
||||
struct wpabuf *hs20_capability_list;
|
||||
|
|
|
@ -4231,6 +4231,8 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
|
|||
#ifdef CONFIG_INTERWORKING
|
||||
if ((mask & WPA_BSS_MASK_INTERNETW) && bss->anqp) {
|
||||
struct wpa_bss_anqp *anqp = bss->anqp;
|
||||
struct wpa_bss_anqp_elem *elem;
|
||||
|
||||
pos = anqp_add_hex(pos, end, "anqp_capability_list",
|
||||
anqp->capability_list);
|
||||
pos = anqp_add_hex(pos, end, "anqp_venue_name",
|
||||
|
@ -4260,6 +4262,15 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
|
|||
pos = anqp_add_hex(pos, end, "hs20_osu_providers_list",
|
||||
anqp->hs20_osu_providers_list);
|
||||
#endif /* CONFIG_HS20 */
|
||||
|
||||
dl_list_for_each(elem, &anqp->anqp_elems,
|
||||
struct wpa_bss_anqp_elem, list) {
|
||||
char title[20];
|
||||
|
||||
os_snprintf(title, sizeof(title), "anqp[%u]",
|
||||
elem->infoid);
|
||||
pos = anqp_add_hex(pos, end, title, elem->payload);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
|
||||
|
|
|
@ -2716,6 +2716,41 @@ int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst,
|
|||
}
|
||||
|
||||
|
||||
static void anqp_add_extra(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_bss_anqp *anqp, u16 info_id,
|
||||
const u8 *data, size_t slen)
|
||||
{
|
||||
struct wpa_bss_anqp_elem *tmp, *elem = NULL;
|
||||
|
||||
if (!anqp)
|
||||
return;
|
||||
|
||||
dl_list_for_each(tmp, &anqp->anqp_elems, struct wpa_bss_anqp_elem,
|
||||
list) {
|
||||
if (tmp->infoid == info_id) {
|
||||
elem = tmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!elem) {
|
||||
elem = os_zalloc(sizeof(*elem));
|
||||
if (!elem)
|
||||
return;
|
||||
elem->infoid = info_id;
|
||||
dl_list_add(&anqp->anqp_elems, &elem->list);
|
||||
} else {
|
||||
wpabuf_free(elem->payload);
|
||||
}
|
||||
|
||||
elem->payload = wpabuf_alloc_copy(data, slen);
|
||||
if (!elem->payload) {
|
||||
dl_list_del(&elem->list);
|
||||
os_free(elem);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_bss *bss, const u8 *sa,
|
||||
u16 info_id,
|
||||
|
@ -2849,6 +2884,7 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
|
|||
default:
|
||||
wpa_msg(wpa_s, MSG_DEBUG,
|
||||
"Interworking: Unsupported ANQP Info ID %u", info_id);
|
||||
anqp_add_extra(wpa_s, anqp, info_id, data, slen);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue