diff options
| author | Linux Build Service Account <lnxbuild@localhost> | 2016-10-20 03:30:50 -0600 |
|---|---|---|
| committer | Linux Build Service Account <lnxbuild@localhost> | 2016-10-20 03:30:50 -0600 |
| commit | cfe716c6c89a26ab47523a1c5152d3068e288b25 (patch) | |
| tree | 86a1ab3f6245a234949c68222b7a9bf07f4f131f | |
| parent | 703a0fd394ec0b6f8c5618cf2560ecb152bc3424 (diff) | |
| parent | b02c29b98f540189b0d02cf0b0f7c12f590cd5b8 (diff) | |
| download | android_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.h | 4 | ||||
| -rw-r--r-- | wpa_supplicant/ctrl_iface.c | 19 | ||||
| -rw-r--r-- | wpa_supplicant/events.c | 7 | ||||
| -rw-r--r-- | wpa_supplicant/interworking.c | 31 | ||||
| -rw-r--r-- | wpa_supplicant/interworking.h | 3 | ||||
| -rw-r--r-- | wpa_supplicant/mbo.c | 127 | ||||
| -rw-r--r-- | wpa_supplicant/wnm_sta.c | 13 | ||||
| -rw-r--r-- | wpa_supplicant/wpa_supplicant.conf | 6 | ||||
| -rw-r--r-- | wpa_supplicant/wpa_supplicant_i.h | 5 |
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 |
