From 2316cb358c854a013bc27ac76c63d0e1ed663475 Mon Sep 17 00:00:00 2001 From: Avraham Stern Date: Thu, 9 Mar 2017 15:19:58 +0200 Subject: [PATCH] MBO: Add option to add MBO query list to ANQP query MBO techspec v0.0_r27 changed the MBO ANQP-element format. The MBO element in ANQP query should now include an MBO Query List element that contains a list of MBO elements to query. Add API to add the MBO Query List to an ANQP query. Format: ANQP_GET [,]...[,mbo:...] Example for querying neighbor report with MBO cellular data connection preference: ANQP_GET 272,mbo:2 Signed-off-by: Avraham Stern --- src/common/ieee802_11_defs.h | 6 ++++-- wpa_supplicant/ctrl_iface.c | 9 +++++---- wpa_supplicant/interworking.c | 6 +++--- wpa_supplicant/interworking.h | 2 +- wpa_supplicant/mbo.c | 15 ++++++++++++--- wpa_supplicant/wpa_supplicant_i.h | 2 +- 6 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index eecabd945..afe2651a8 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -1419,9 +1419,11 @@ enum wfa_wnm_notif_subelem_id { WFA_WNM_NOTIF_SUBELEM_CELL_DATA_CAPA = 3, }; -/* MBO v0.0_r25, 4.3: MBO ANQP-elements */ +/* MBO v0.0_r27, 4.3: MBO ANQP-elements */ #define MBO_ANQP_OUI_TYPE 0x12 -#define MBO_ANQP_SUBTYPE_CELL_CONN_PREF 1 +#define MBO_ANQP_SUBTYPE_QUERY_LIST 1 +#define MBO_ANQP_SUBTYPE_CELL_CONN_PREF 2 +#define MAX_MBO_ANQP_SUBTYPE MBO_ANQP_SUBTYPE_CELL_CONN_PREF /* Wi-Fi Direct (P2P) */ diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 14dcdcd9c..5aa3542bc 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -6712,7 +6712,7 @@ static int get_anqp(struct wpa_supplicant *wpa_s, char *dst) u16 id[MAX_ANQP_INFO_ID]; size_t num_id = 0; u32 subtypes = 0; - int get_cell_pref = 0; + u32 mbo_subtypes = 0; used = hwaddr_aton2(dst, dst_addr); if (used < 0) @@ -6733,9 +6733,10 @@ static int get_anqp(struct wpa_supplicant *wpa_s, char *dst) } else if (os_strncmp(pos, "mbo:", 4) == 0) { #ifdef CONFIG_MBO int num = atoi(pos + 4); - if (num != MBO_ANQP_SUBTYPE_CELL_CONN_PREF) + + if (num <= 0 || num > MAX_MBO_ANQP_SUBTYPE) return -1; - get_cell_pref = 1; + mbo_subtypes |= BIT(num); #else /* CONFIG_MBO */ return -1; #endif /* CONFIG_MBO */ @@ -6754,7 +6755,7 @@ static int get_anqp(struct wpa_supplicant *wpa_s, char *dst) return -1; return anqp_send_req(wpa_s, dst_addr, id, num_id, subtypes, - get_cell_pref); + mbo_subtypes); } diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c index 30b9c88a7..24bbeff33 100644 --- a/wpa_supplicant/interworking.c +++ b/wpa_supplicant/interworking.c @@ -2694,7 +2694,7 @@ 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, u32 subtypes, - int get_cell_pref) + u32 mbo_subtypes) { struct wpabuf *buf; struct wpabuf *extra_buf = NULL; @@ -2728,10 +2728,10 @@ int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, #endif /* CONFIG_HS20 */ #ifdef CONFIG_MBO - if (get_cell_pref) { + if (mbo_subtypes) { struct wpabuf *mbo; - mbo = mbo_build_anqp_buf(wpa_s, bss); + mbo = mbo_build_anqp_buf(wpa_s, bss, mbo_subtypes); if (mbo) { if (wpabuf_resize(&extra_buf, wpabuf_len(mbo))) { wpabuf_free(extra_buf); diff --git a/wpa_supplicant/interworking.h b/wpa_supplicant/interworking.h index 3d2229261..37ee2e904 100644 --- a/wpa_supplicant/interworking.h +++ b/wpa_supplicant/interworking.h @@ -13,7 +13,7 @@ enum gas_query_result; int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, u16 info_ids[], size_t num_ids, u32 subtypes, - int get_cell_pref); + u32 mbo_subtypes); void anqp_resp_cb(void *ctx, const u8 *dst, u8 dialog_token, enum gas_query_result result, const struct wpabuf *adv_proto, diff --git a/wpa_supplicant/mbo.c b/wpa_supplicant/mbo.c index 5488f446a..5348b9a96 100644 --- a/wpa_supplicant/mbo.c +++ b/wpa_supplicant/mbo.c @@ -515,10 +515,11 @@ void wpas_mbo_update_cell_capa(struct wpa_supplicant *wpa_s, u8 mbo_cell_capa) struct wpabuf * mbo_build_anqp_buf(struct wpa_supplicant *wpa_s, - struct wpa_bss *bss) + struct wpa_bss *bss, u32 mbo_subtypes) { struct wpabuf *anqp_buf; u8 *len_pos; + u8 i; if (!wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE)) { wpa_printf(MSG_INFO, "MBO: " MACSTR @@ -527,7 +528,8 @@ struct wpabuf * mbo_build_anqp_buf(struct wpa_supplicant *wpa_s, return NULL; } - anqp_buf = wpabuf_alloc(10); + /* Allocate size for the maximum case - all MBO subtypes are set */ + anqp_buf = wpabuf_alloc(9 + MAX_MBO_ANQP_SUBTYPE); if (!anqp_buf) return NULL; @@ -535,7 +537,14 @@ struct wpabuf * mbo_build_anqp_buf(struct wpa_supplicant *wpa_s, wpabuf_put_be24(anqp_buf, OUI_WFA); wpabuf_put_u8(anqp_buf, MBO_ANQP_OUI_TYPE); - wpabuf_put_u8(anqp_buf, MBO_ANQP_SUBTYPE_CELL_CONN_PREF); + wpabuf_put_u8(anqp_buf, MBO_ANQP_SUBTYPE_QUERY_LIST); + + /* The first valid MBO subtype is 1 */ + for (i = 1; i <= MAX_MBO_ANQP_SUBTYPE; i++) { + if (mbo_subtypes & BIT(i)) + wpabuf_put_u8(anqp_buf, i); + } + gas_anqp_set_element_len(anqp_buf, len_pos); return anqp_buf; diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 87065cf9e..08df4cca1 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1294,7 +1294,7 @@ size_t wpas_mbo_ie_bss_trans_reject(struct wpa_supplicant *wpa_s, u8 *pos, enum mbo_transition_reject_reason reason); void wpas_mbo_update_cell_capa(struct wpa_supplicant *wpa_s, u8 mbo_cell_capa); struct wpabuf * mbo_build_anqp_buf(struct wpa_supplicant *wpa_s, - struct wpa_bss *bss); + struct wpa_bss *bss, u32 mbo_subtypes); /* op_classes.c */ enum chan_allowed {