@@ -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) */
@@ -6712,7 +6712,8 @@ 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;
+ u8 mbo_elems[MAX_MBO_ANQP_SUBTYPE];
+ int num_mbo_elems = 0;
used = hwaddr_aton2(dst, dst_addr);
if (used < 0)
@@ -6732,10 +6733,22 @@ static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
#endif /* CONFIG_HS20 */
} else if (os_strncmp(pos, "mbo:", 4) == 0) {
#ifdef CONFIG_MBO
- int num = atoi(pos + 4);
- if (num != MBO_ANQP_SUBTYPE_CELL_CONN_PREF)
- return -1;
- get_cell_pref = 1;
+ const char *mbo_pos = pos + 4;
+
+ while (mbo_pos &&
+ num_mbo_elems <= MAX_MBO_ANQP_SUBTYPE) {
+ mbo_elems[num_mbo_elems] = atoi(mbo_pos);
+ if (mbo_elems[num_mbo_elems] >
+ MAX_MBO_ANQP_SUBTYPE) {
+ wpa_printf(MSG_DEBUG,
+ "Invalid MBO ANQP element subtype: %u",
+ mbo_elems[num_mbo_elems]);
+ return -1;
+ }
+
+ num_mbo_elems++;
+ mbo_pos = os_strchr(mbo_pos, ':');
+ }
#else /* CONFIG_MBO */
return -1;
#endif /* CONFIG_MBO */
@@ -6753,8 +6766,8 @@ 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, subtypes,
- get_cell_pref);
+ return anqp_send_req(wpa_s, dst_addr, id, num_id, subtypes, mbo_elems,
+ num_mbo_elems);
}
@@ -2693,8 +2693,8 @@ 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)
+ u16 info_ids[], size_t num_ids, u32 subtypes, u8 *mbo_elems,
+ int num_mbo_elems)
{
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 (num_mbo_elems) {
struct wpabuf *mbo;
- mbo = mbo_build_anqp_buf(wpa_s, bss);
+ mbo = mbo_build_anqp_buf(wpa_s, bss, mbo_elems, num_mbo_elems);
if (mbo) {
if (wpabuf_resize(&extra_buf, wpabuf_len(mbo))) {
wpabuf_free(extra_buf);
@@ -12,8 +12,8 @@
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);
+ u16 info_ids[], size_t num_ids, u32 subtypes, u8 *mbo_elems,
+ int num_mbo_elems);
void anqp_resp_cb(void *ctx, const u8 *dst, u8 dialog_token,
enum gas_query_result result,
const struct wpabuf *adv_proto,
@@ -514,7 +514,8 @@ 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, u8 *mbo_elems,
+ int num_elems)
{
struct wpabuf *anqp_buf;
u8 *len_pos;
@@ -526,7 +527,7 @@ struct wpabuf * mbo_build_anqp_buf(struct wpa_supplicant *wpa_s,
return NULL;
}
- anqp_buf = wpabuf_alloc(10);
+ anqp_buf = wpabuf_alloc(9 + num_elems);
if (!anqp_buf)
return NULL;
@@ -534,7 +535,9 @@ 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);
+ wpabuf_put_data(anqp_buf, mbo_elems, num_elems);
+
gas_anqp_set_element_len(anqp_buf, len_pos);
return anqp_buf;
@@ -1290,7 +1290,8 @@ 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, u8 *mbo_elems,
+ int num_mbo_elems);
/* op_classes.c */
enum chan_allowed {