MBO: Add support to send ANQP request to get cellular preference
authorvamsi krishna <vamsin@qti.qualcomm.com>
Fri, 9 Sep 2016 12:05:50 +0000 (17:35 +0530)
committerJouni Malinen <j@w1.fi>
Fri, 30 Sep 2016 19:45:03 +0000 (22:45 +0300)
This extends ANQP_GET command to support querying MBO cellular
preference also. The cellular preference can be requested along with
neigbor report by appending mbo:1 to the command arguments.

For example:
ANQP_GET <bssid> 272,mbo:1

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
src/common/ieee802_11_defs.h
wpa_supplicant/ctrl_iface.c
wpa_supplicant/interworking.c
wpa_supplicant/interworking.h
wpa_supplicant/mbo.c
wpa_supplicant/wpa_supplicant_i.h

index 02d2ad7..d453aec 100644 (file)
@@ -1180,6 +1180,10 @@ enum wfa_wnm_notif_subelem_id {
        WFA_WNM_NOTIF_SUBELEM_CELL_DATA_CAPA = 3,
 };
 
+/* MBO v0.0_r25, 4.3: MBO ANQP-elements */
+#define MBO_ANQP_OUI_TYPE 0x12
+#define MBO_ANQP_SUBTYPE_CELL_CONN_PREF 1
+
 /* Wi-Fi Direct (P2P) */
 
 #define P2P_OUI_TYPE 9
index 1b81797..d814fdf 100644 (file)
@@ -6383,6 +6383,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;
 
        used = hwaddr_aton2(dst, dst_addr);
        if (used < 0)
@@ -6400,6 +6401,15 @@ static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
 #else /* CONFIG_HS20 */
                        return -1;
 #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;
+#else /* CONFIG_MBO */
+                       return -1;
+#endif /* CONFIG_MBO */
                } else {
                        id[num_id] = atoi(pos);
                        if (id[num_id])
@@ -6414,7 +6424,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);
+       return anqp_send_req(wpa_s, dst_addr, id, num_id, subtypes,
+                            get_cell_pref);
 }
 
 
index 697810e..1fb40c7 100644 (file)
@@ -2692,10 +2692,11 @@ 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)
+                 u16 info_ids[], size_t num_ids, u32 subtypes,
+                 int get_cell_pref)
 {
        struct wpabuf *buf;
-       struct wpabuf *hs20_buf = NULL;
+       struct wpabuf *extra_buf = NULL;
        int ret = 0;
        int freq;
        struct wpa_bss *bss;
@@ -2718,15 +2719,31 @@ int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst,
 
 #ifdef CONFIG_HS20
        if (subtypes != 0) {
-               hs20_buf = wpabuf_alloc(100);
-               if (hs20_buf == NULL)
+               extra_buf = wpabuf_alloc(100);
+               if (extra_buf == NULL)
                        return -1;
-               hs20_put_anqp_req(subtypes, NULL, 0, hs20_buf);
+               hs20_put_anqp_req(subtypes, NULL, 0, extra_buf);
        }
 #endif /* CONFIG_HS20 */
 
-       buf = anqp_build_req(info_ids, num_ids, hs20_buf);
-       wpabuf_free(hs20_buf);
+#ifdef CONFIG_MBO
+       if (get_cell_pref) {
+               struct wpabuf *mbo;
+
+               mbo = mbo_build_anqp_buf(wpa_s, bss);
+               if (mbo) {
+                       if (wpabuf_resize(&extra_buf, wpabuf_len(mbo))) {
+                               wpabuf_free(extra_buf);
+                               return -1;
+                       }
+                       wpabuf_put_buf(extra_buf, mbo);
+                       wpabuf_free(mbo);
+               }
+       }
+#endif /* CONFIG_MBO */
+
+       buf = anqp_build_req(info_ids, num_ids, extra_buf);
+       wpabuf_free(extra_buf);
        if (buf == NULL)
                return -1;
 
index 3743dc0..3d22292 100644 (file)
@@ -12,7 +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);
+                 u16 info_ids[], size_t num_ids, u32 subtypes,
+                 int get_cell_pref);
 void anqp_resp_cb(void *ctx, const u8 *dst, u8 dialog_token,
                  enum gas_query_result result,
                  const struct wpabuf *adv_proto,
index 13d764e..7e049be 100644 (file)
@@ -14,6 +14,7 @@
 
 #include "utils/common.h"
 #include "common/ieee802_11_defs.h"
+#include "common/gas.h"
 #include "config.h"
 #include "wpa_supplicant_i.h"
 #include "driver_i.h"
@@ -805,3 +806,31 @@ void wpas_mbo_update_cell_capa(struct wpa_supplicant *wpa_s, u8 mbo_cell_capa)
        wpas_mbo_send_wnm_notification(wpa_s, cell_capa, 7);
        wpa_supplicant_set_default_scan_ies(wpa_s);
 }
+
+
+struct wpabuf * mbo_build_anqp_buf(struct wpa_supplicant *wpa_s,
+                                  struct wpa_bss *bss)
+{
+       struct wpabuf *anqp_buf;
+       u8 *len_pos;
+
+       if (!wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE)) {
+               wpa_printf(MSG_INFO, "MBO: " MACSTR
+                          " does not support MBO - cannot request MBO ANQP elements from it",
+                          MAC2STR(bss->bssid));
+               return NULL;
+       }
+
+       anqp_buf = wpabuf_alloc(10);
+       if (!anqp_buf)
+               return NULL;
+
+       len_pos = gas_anqp_add_element(anqp_buf, ANQP_VENDOR_SPECIFIC);
+       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);
+       gas_anqp_set_element_len(anqp_buf, len_pos);
+
+       return anqp_buf;
+}
index 44f72a6..5d8ac81 100644 (file)
@@ -1204,6 +1204,8 @@ size_t wpas_mbo_ie_bss_trans_reject(struct wpa_supplicant *wpa_s, u8 *pos,
                                    size_t len,
                                    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);
 
 /**
  * wpa_supplicant_ctrl_iface_ctrl_rsp_handle - Handle a control response