aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2016-10-20 03:30:50 -0600
committerLinux Build Service Account <lnxbuild@localhost>2016-10-20 03:30:50 -0600
commitcfe716c6c89a26ab47523a1c5152d3068e288b25 (patch)
tree86a1ab3f6245a234949c68222b7a9bf07f4f131f
parent703a0fd394ec0b6f8c5618cf2560ecb152bc3424 (diff)
parentb02c29b98f540189b0d02cf0b0f7c12f590cd5b8 (diff)
downloadandroid_external_wpa_supplicant_8-cfe716c6c89a26ab47523a1c5152d3068e288b25.tar.gz
android_external_wpa_supplicant_8-cfe716c6c89a26ab47523a1c5152d3068e288b25.tar.bz2
android_external_wpa_supplicant_8-cfe716c6c89a26ab47523a1c5152d3068e288b25.zip
Promotion of wlan-aosp-service.lnx.2.0-00011.
CRs Change ID Subject -------------------------------------------------------------------------------------------------------------- 1070010 Ic242de6aa946ced65dd2c954af29b763a8af3757 MBO: Add support to send ANQP request to get cellular pr 1070010 I0b470892c535fd061b3b3f72c83dd3fe453d14c2 MBO: Do not add reason_detail in non_pref_chan attr (STA 1070010 I8afc22e53dc35ebc527b86390dc69470a6174e80 MBO: Remove unused assignment 1070010 I62855a556e6e04ae05a39ec7731075f74ffcbd73 WNM: Add testing option to reject BSS Transition Managem 1070010 I0c16d8d63b755d5169ddc8c5c7e96d8388f35d37 MBO: Improve supported operating class generation 1070010 Ic4e0d0309f44cfdc73f0e9406867caffb20eb706 MBO: Add support to ignore association disallowed set by 1070010 Ic68560fff749ccef6e3a2ab6efed8fa6440d0e4e MBO: Mark verify_channel() static Change-Id: I21dabc828bd1cbdffb76ab64b37648cd3f891e70 CRs-Fixed: 1070010
-rw-r--r--src/common/ieee802_11_defs.h4
-rw-r--r--wpa_supplicant/ctrl_iface.c19
-rw-r--r--wpa_supplicant/events.c7
-rw-r--r--wpa_supplicant/interworking.c31
-rw-r--r--wpa_supplicant/interworking.h3
-rw-r--r--wpa_supplicant/mbo.c127
-rw-r--r--wpa_supplicant/wnm_sta.c13
-rw-r--r--wpa_supplicant/wpa_supplicant.conf6
-rw-r--r--wpa_supplicant/wpa_supplicant_i.h5
9 files changed, 170 insertions, 45 deletions
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index e1a8ef78..6912320c 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -1116,6 +1116,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
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 6154afee..e7671a9c 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -484,6 +484,10 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
wpa_s->test_failure = atoi(value);
} else if (os_strcasecmp(cmd, "p2p_go_csa_on_inv") == 0) {
wpa_s->p2p_go_csa_on_inv = !!atoi(value);
+ } else if (os_strcasecmp(cmd, "ignore_assoc_disallow") == 0) {
+ wpa_s->ignore_assoc_disallow = !!atoi(value);
+ } else if (os_strcasecmp(cmd, "reject_btm_req_reason") == 0) {
+ wpa_s->reject_btm_req_reason = atoi(value);
#endif /* CONFIG_TESTING_OPTIONS */
#ifndef CONFIG_NO_CONFIG_BLOBS
} else if (os_strcmp(cmd, "blob") == 0) {
@@ -6384,6 +6388,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)
@@ -6401,6 +6406,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])
@@ -6415,7 +6429,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);
}
@@ -7179,6 +7194,8 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
wpa_s->extra_roc_dur = 0;
wpa_s->test_failure = WPAS_TEST_FAILURE_NONE;
wpa_s->p2p_go_csa_on_inv = 0;
+ wpa_s->ignore_assoc_disallow = 0;
+ wpa_s->reject_btm_req_reason = 0;
wpa_sm_set_test_assoc_ie(wpa_s->wpa, NULL);
#endif /* CONFIG_TESTING_OPTIONS */
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index fed9aca6..22685319 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -1078,6 +1078,10 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
continue;
}
#ifdef CONFIG_MBO
+#ifdef CONFIG_TESTING_OPTIONS
+ if (wpa_s->ignore_assoc_disallow)
+ goto skip_assoc_disallow;
+#endif /* CONFIG_TESTING_OPTIONS */
assoc_disallow = wpas_mbo_get_bss_attr(
bss, MBO_ATTR_ID_ASSOC_DISALLOW);
if (assoc_disallow && assoc_disallow[1] >= 1) {
@@ -1092,6 +1096,9 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
" skip - MBO retry delay has not passed yet");
continue;
}
+#ifdef CONFIG_TESTING_OPTIONS
+ skip_assoc_disallow:
+#endif /* CONFIG_TESTING_OPTIONS */
#endif /* CONFIG_MBO */
/* Matching configuration found */
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index 589ee57b..ef8747e0 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -2702,10 +2702,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;
@@ -2728,15 +2729,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 3743dc00..3d222926 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 1154ab6d..7e049be3 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"
@@ -68,14 +69,13 @@ static void wpas_mbo_non_pref_chan_attr_body(struct wpa_supplicant *wpa_s,
wpabuf_put_u8(mbo, wpa_s->non_pref_chan[start].preference);
wpabuf_put_u8(mbo, wpa_s->non_pref_chan[start].reason);
- wpabuf_put_u8(mbo, wpa_s->non_pref_chan[start].reason_detail);
}
static void wpas_mbo_non_pref_chan_attr(struct wpa_supplicant *wpa_s,
struct wpabuf *mbo, u8 start, u8 end)
{
- size_t size = end - start + 4;
+ size_t size = end - start + 3;
if (size + 2 > wpabuf_tailroom(mbo))
return;
@@ -100,7 +100,7 @@ static void wpas_mbo_non_pref_chan_subelement(struct wpa_supplicant *wpa_s,
struct wpabuf *mbo, u8 start,
u8 end)
{
- size_t size = end - start + 8;
+ size_t size = end - start + 7;
if (size + 2 > wpabuf_tailroom(mbo))
return;
@@ -131,7 +131,6 @@ static void wpas_mbo_non_pref_chan_attrs(struct wpa_supplicant *wpa_s,
if (!non_pref ||
non_pref->oper_class != start_pref->oper_class ||
non_pref->reason != start_pref->reason ||
- non_pref->reason_detail != start_pref->reason_detail ||
non_pref->preference != start_pref->preference) {
if (subelement)
wpas_mbo_non_pref_chan_subelement(wpa_s, mbo,
@@ -250,9 +249,9 @@ static int wpa_non_pref_chan_is_eq(struct wpa_mbo_non_pref_channel *a,
*
* In MBO IE non-preferred channel subelement we can put many channels in an
* attribute if they are in the same operating class and have the same
- * preference, reason, and reason detail. To make it easy for the functions that
- * build the IE attributes and WNM Request subelements, save the channels sorted
- * by their oper_class, reason, and reason_detail.
+ * preference and reason. To make it easy for the functions that build
+ * the IE attributes and WNM Request subelements, save the channels sorted
+ * by their oper_class and reason.
*/
static int wpa_non_pref_chan_cmp(const void *_a, const void *_b)
{
@@ -262,8 +261,6 @@ static int wpa_non_pref_chan_cmp(const void *_a, const void *_b)
return a->oper_class - b->oper_class;
if (a->reason != b->reason)
return a->reason - b->reason;
- if (a->reason_detail != b->reason_detail)
- return a->reason_detail - b->reason_detail;
return a->preference - b->preference;
}
@@ -298,7 +295,6 @@ int wpas_mbo_update_non_pref_chan(struct wpa_supplicant *wpa_s,
unsigned int _chan;
unsigned int _preference;
unsigned int _reason;
- unsigned int _reason_detail;
if (num == size) {
size = size ? size * 2 : 1;
@@ -314,13 +310,11 @@ int wpas_mbo_update_non_pref_chan(struct wpa_supplicant *wpa_s,
chan = &chans[num];
- ret = sscanf(token, "%u:%u:%u:%u:%u", &_oper_class,
- &_chan, &_preference, &_reason,
- &_reason_detail);
- if ((ret != 4 && ret != 5) ||
+ ret = sscanf(token, "%u:%u:%u:%u", &_oper_class,
+ &_chan, &_preference, &_reason);
+ if (ret != 4 ||
_oper_class > 255 || _chan > 255 ||
- _preference > 255 || _reason > 65535 ||
- (ret == 5 && _reason_detail > 255)) {
+ _preference > 255 || _reason > 65535 ) {
wpa_printf(MSG_ERROR, "Invalid non-pref chan input %s",
token);
goto fail;
@@ -329,7 +323,6 @@ int wpas_mbo_update_non_pref_chan(struct wpa_supplicant *wpa_s,
chan->chan = _chan;
chan->preference = _preference;
chan->reason = _reason;
- chan->reason_detail = ret == 4 ? 0 : _reason_detail;
if (wpas_mbo_validate_non_pref_chan(chan->oper_class,
chan->chan, chan->reason)) {
@@ -517,8 +510,8 @@ static enum chan_allowed verify_160mhz(struct hostapd_hw_modes *mode,
}
-enum chan_allowed verify_channel(struct hostapd_hw_modes *mode, u8 channel,
- u8 bw)
+static enum chan_allowed verify_channel(struct hostapd_hw_modes *mode,
+ u8 channel, u8 bw)
{
unsigned int flag = 0;
enum chan_allowed res, res2;
@@ -533,9 +526,26 @@ enum chan_allowed verify_channel(struct hostapd_hw_modes *mode, u8 channel,
return NOT_ALLOWED;
res2 = allow_channel(mode, channel + 4, NULL);
} else if (bw == BW80) {
- res2 = verify_80mhz(mode, channel);
+ /*
+ * channel is a center channel and as such, not necessarily a
+ * valid 20 MHz channels. Override earlier allow_channel()
+ * result and use only the 80 MHz specific version.
+ */
+ res2 = res = verify_80mhz(mode, channel);
} else if (bw == BW160) {
- res2 = verify_160mhz(mode, channel);
+ /*
+ * channel is a center channel and as such, not necessarily a
+ * valid 20 MHz channels. Override earlier allow_channel()
+ * result and use only the 160 MHz specific version.
+ */
+ res2 = res = verify_160mhz(mode, channel);
+ } else if (bw == BW80P80) {
+ /*
+ * channel is a center channel and as such, not necessarily a
+ * valid 20 MHz channels. Override earlier allow_channel()
+ * result and use only the 80 MHz specific version.
+ */
+ res2 = res = verify_80mhz(mode, channel);
}
if (res == NOT_ALLOWED || res2 == NOT_ALLOWED)
@@ -551,38 +561,63 @@ static int wpas_op_class_supported(struct wpa_supplicant *wpa_s,
int chan;
size_t i;
struct hostapd_hw_modes *mode;
+ int found;
mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, op_class->mode);
if (!mode)
return 0;
- if (op_class->op_class == 128 || op_class->op_class == 130) {
+ if (op_class->op_class == 128) {
u8 channels[] = { 42, 58, 106, 122, 138, 155 };
for (i = 0; i < ARRAY_SIZE(channels); i++) {
if (verify_channel(mode, channels[i], op_class->bw) ==
- NOT_ALLOWED)
- return 0;
+ ALLOWED)
+ return 1;
}
- return 1;
+ return 0;
}
if (op_class->op_class == 129) {
- if (verify_channel(mode, 50, op_class->bw) == NOT_ALLOWED ||
- verify_channel(mode, 114, op_class->bw) == NOT_ALLOWED)
- return 0;
+ /* Check if either 160 MHz channels is allowed */
+ return verify_channel(mode, 50, op_class->bw) == ALLOWED ||
+ verify_channel(mode, 114, op_class->bw) == ALLOWED;
+ }
+
+ if (op_class->op_class == 130) {
+ /* Need at least two non-contiguous 80 MHz segments */
+ found = 0;
+
+ if (verify_channel(mode, 42, op_class->bw) == ALLOWED ||
+ verify_channel(mode, 58, op_class->bw) == ALLOWED)
+ found++;
+ if (verify_channel(mode, 106, op_class->bw) == ALLOWED ||
+ verify_channel(mode, 122, op_class->bw) == ALLOWED ||
+ verify_channel(mode, 138, op_class->bw) == ALLOWED)
+ found++;
+ if (verify_channel(mode, 106, op_class->bw) == ALLOWED &&
+ verify_channel(mode, 138, op_class->bw) == ALLOWED)
+ found++;
+ if (verify_channel(mode, 155, op_class->bw) == ALLOWED)
+ found++;
+
+ if (found >= 2)
+ return 1;
- return 1;
+ return 0;
}
+ found = 0;
for (chan = op_class->min_chan; chan <= op_class->max_chan;
chan += op_class->inc) {
- if (verify_channel(mode, chan, op_class->bw) == NOT_ALLOWED)
- return 0;
+ if (verify_channel(mode, chan, op_class->bw) == ALLOWED) {
+ found = 1;
+ break;
+ }
}
- return 1;
+ return found;
}
@@ -771,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/wnm_sta.c b/wpa_supplicant/wnm_sta.c
index 520b0095..dc20ee00 100644
--- a/wpa_supplicant/wnm_sta.c
+++ b/wpa_supplicant/wnm_sta.c
@@ -1159,6 +1159,19 @@ static void ieee802_11_rx_bss_trans_mgmt_req(struct wpa_supplicant *wpa_s,
wpa_s->wnm_dialog_token, wpa_s->wnm_mode,
wpa_s->wnm_dissoc_timer, valid_int);
+#if defined(CONFIG_MBO) && defined(CONFIG_TESTING_OPTIONS)
+ if (wpa_s->reject_btm_req_reason) {
+ wpa_printf(MSG_INFO,
+ "WNM: Testing - reject BSS Transition Management Request: reject_btm_req_reason=%d",
+ wpa_s->reject_btm_req_reason);
+ wnm_send_bss_transition_mgmt_resp(wpa_s,
+ wpa_s->wnm_dialog_token,
+ wpa_s->reject_btm_req_reason,
+ 0, NULL);
+ return;
+ }
+#endif /* CONFIG_MBO && CONFIG_TESTING_OPTIONS */
+
pos += 5;
if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED) {
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index ff3aa841..b72608a9 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -649,11 +649,11 @@ fast_reauth=1
# Multi Band Operation (MBO) non-preferred channels
# A space delimited list of non-preferred channels where each channel is a colon
-# delimited list of values. Reason detail is optional.
+# delimited list of values.
# Format:
-# non_pref_chan=<oper_class>:<chan>:<preference>:<reason>[:reason_detail]
+# non_pref_chan=<oper_class>:<chan>:<preference>:<reason>
# Example:
-# non_pref_chan="81:5:10:2:0 81:1:0:2:0 81:9:0:2"
+# non_pref_chan="81:5:10:2 81:1:0:2 81:9:0:2"
# MBO Cellular Data Capabilities
# 1 = Cellular data connection available
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index b07255ef..af5d6590 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -1028,7 +1028,9 @@ struct wpa_supplicant {
struct l2_packet_data *l2_test;
unsigned int extra_roc_dur;
enum wpa_supplicant_test_failure test_failure;
+ unsigned int reject_btm_req_reason;
unsigned int p2p_go_csa_on_inv:1;
+ unsigned int ignore_assoc_disallow:1;
#endif /* CONFIG_TESTING_OPTIONS */
struct wmm_ac_assoc_data *wmm_ac_assoc_info;
@@ -1052,7 +1054,6 @@ struct wpa_supplicant {
enum mbo_non_pref_chan_reason reason;
u8 oper_class;
u8 chan;
- u8 reason_detail;
u8 preference;
} *non_pref_chan;
size_t non_pref_chan_num;
@@ -1193,6 +1194,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