aboutsummaryrefslogtreecommitdiffstats
path: root/wpa_supplicant
diff options
context:
space:
mode:
authorvamsi krishna <vamsin@qti.qualcomm.com>2016-09-09 12:05:50 (GMT)
committerJouni Malinen <j@w1.fi>2016-09-30 19:45:03 (GMT)
commit8f4791749302bb3a89b2baef19fc5e6075ec3845 (patch)
tree8cc755dffeee85f4910a6118fb6fa255e262f8f9 /wpa_supplicant
parent5b71cb552bc0def1149acf2a89a1847606702f22 (diff)
downloadhostap-8f4791749302bb3a89b2baef19fc5e6075ec3845.zip
hostap-8f4791749302bb3a89b2baef19fc5e6075ec3845.tar.gz
hostap-8f4791749302bb3a89b2baef19fc5e6075ec3845.tar.bz2
MBO: Add support to send ANQP request to get cellular preference
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>
Diffstat (limited to 'wpa_supplicant')
-rw-r--r--wpa_supplicant/ctrl_iface.c13
-rw-r--r--wpa_supplicant/interworking.c31
-rw-r--r--wpa_supplicant/interworking.h3
-rw-r--r--wpa_supplicant/mbo.c29
-rw-r--r--wpa_supplicant/wpa_supplicant_i.h2
5 files changed, 69 insertions, 9 deletions
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 1b81797..d814fdf 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -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);
}
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index 697810e..1fb40c7 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -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;
diff --git a/wpa_supplicant/interworking.h b/wpa_supplicant/interworking.h
index 3743dc0..3d22292 100644
--- a/wpa_supplicant/interworking.h
+++ b/wpa_supplicant/interworking.h
@@ -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,
diff --git a/wpa_supplicant/mbo.c b/wpa_supplicant/mbo.c
index 13d764e..7e049be 100644
--- a/wpa_supplicant/mbo.c
+++ b/wpa_supplicant/mbo.c
@@ -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;
+}
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 44f72a6..5d8ac81 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -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