diff --git a/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h b/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h index fbfefc450b14..8e0ce7c36348 100644 --- a/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h +++ b/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h @@ -69,6 +69,13 @@ /* Extender vendor specific IE */ #define QCA_OUI_EXTENDER_TYPE 0x03 +#define ADAPTIVE_11R_OUI 0x964000 +#define ADAPTIVE_11R_OUI_TYPE 0x2C + +#define OUI_LENGTH 4 +#define OUI_TYPE_BITS 24 +#define MAX_ADAPTIVE_11R_IE_LEN 8 + /* Temporary vendor specific IE for 11n pre-standard interoperability */ #define VENDOR_HT_OUI 0x00904c #define VENDOR_HT_CAP_ID 51 @@ -1434,6 +1441,21 @@ is_extender_oui(uint8_t *frm) ((QCA_OUI_EXTENDER_TYPE << 24) | QCA_OUI)); } +/** + * is_adaptive_11r_oui() - Function to check if vendor IE is ADAPTIVE 11R OUI + * @frm: vendor IE pointer + * + * API to check if vendor IE is ADAPTIVE 11R OUI + * + * Return: true if its ADAPTIVE 11r OUI + */ +static inline bool +is_adaptive_11r_oui(uint8_t *frm) +{ + return (frm[1] > OUI_LENGTH) && (LE_READ_4(frm + 2) == + ((ADAPTIVE_11R_OUI_TYPE << OUI_TYPE_BITS) | ADAPTIVE_11R_OUI)); +} + /** * wlan_parse_rsn_ie() - parse rsn ie * @rsn_ie: rsn ie ptr diff --git a/umac/scan/core/src/wlan_scan_filter.c b/umac/scan/core/src/wlan_scan_filter.c index a9853821cfa6..abf9dbd4c407 100644 --- a/umac/scan/core/src/wlan_scan_filter.c +++ b/umac/scan/core/src/wlan_scan_filter.c @@ -382,16 +382,18 @@ scm_is_rsn_mcast_cipher_match(struct wlan_rsn_ie *rsn, * Return: true if RSN security else false */ static bool scm_is_rsn_security(struct scan_filter *filter, - struct scan_cache_entry *db_entry, - struct security_info *security) + struct scan_cache_entry *db_entry, + struct security_info *security) { int i; uint8_t cipher_type; bool match_any_akm, match = false; enum wlan_auth_type neg_auth = WLAN_NUM_OF_SUPPORT_AUTH_TYPE; + enum wlan_auth_type filter_akm; enum wlan_enc_type neg_mccipher = WLAN_ENCRYPT_TYPE_NONE; struct wlan_rsn_ie rsn = {0}; QDF_STATUS status; + bool is_adaptive_11r; if (!security) return false; @@ -425,11 +427,15 @@ static bool scm_is_rsn_security(struct scan_filter *filter, return false; } + is_adaptive_11r = (db_entry->adaptive_11r_ap && + filter->enable_adaptive_11r); + /* Initializing with false as it has true value already */ match = false; for (i = 0; i < filter->num_of_auth; i++) { - if (filter->auth_type[i] == WLAN_AUTH_TYPE_ANY) + filter_akm = filter->auth_type[i]; + if (filter_akm == WLAN_AUTH_TYPE_ANY) match_any_akm = true; else match_any_akm = false; @@ -440,8 +446,8 @@ static bool scm_is_rsn_security(struct scan_filter *filter, if (scm_is_cipher_match(rsn.akm_suites, rsn.akm_suite_count, WLAN_RSN_SEL(WLAN_AKM_FILS_FT_SHA384))) { - if (match_any_akm || (WLAN_AUTH_TYPE_FT_FILS_SHA384 == - filter->auth_type[i])) { + if (match_any_akm || + (filter_akm == WLAN_AUTH_TYPE_FT_FILS_SHA384)) { neg_auth = WLAN_AUTH_TYPE_FT_FILS_SHA384; match = true; break; @@ -450,8 +456,8 @@ static bool scm_is_rsn_security(struct scan_filter *filter, if (scm_is_cipher_match(rsn.akm_suites, rsn.akm_suite_count, WLAN_RSN_SEL(WLAN_AKM_FILS_FT_SHA256))) { - if (match_any_akm || (WLAN_AUTH_TYPE_FT_FILS_SHA256 == - filter->auth_type[i])) { + if (match_any_akm || + (filter_akm == WLAN_AUTH_TYPE_FT_FILS_SHA256)) { neg_auth = WLAN_AUTH_TYPE_FT_FILS_SHA256; match = true; break; @@ -460,8 +466,8 @@ static bool scm_is_rsn_security(struct scan_filter *filter, if (scm_is_cipher_match(rsn.akm_suites, rsn.akm_suite_count, WLAN_RSN_SEL(WLAN_AKM_FILS_SHA384))) { - if (match_any_akm || (WLAN_AUTH_TYPE_FILS_SHA384 == - filter->auth_type[i])) { + if (match_any_akm || + (filter_akm == WLAN_AUTH_TYPE_FILS_SHA384)) { neg_auth = WLAN_AUTH_TYPE_FILS_SHA384; match = true; break; @@ -470,8 +476,8 @@ static bool scm_is_rsn_security(struct scan_filter *filter, if (scm_is_cipher_match(rsn.akm_suites, rsn.akm_suite_count, WLAN_RSN_SEL(WLAN_AKM_FILS_SHA256))) { - if (match_any_akm || (WLAN_AUTH_TYPE_FILS_SHA256 == - filter->auth_type[i])) { + if (match_any_akm || + (filter_akm == WLAN_AUTH_TYPE_FILS_SHA256)) { neg_auth = WLAN_AUTH_TYPE_FILS_SHA256; match = true; break; @@ -481,8 +487,8 @@ static bool scm_is_rsn_security(struct scan_filter *filter, if (scm_is_cipher_match(rsn.akm_suites, rsn.akm_suite_count, WLAN_RSN_SEL(WLAN_AKM_SAE))) { - if (match_any_akm || (WLAN_AUTH_TYPE_SAE == - filter->auth_type[i])) { + if (match_any_akm || + (filter_akm == WLAN_AUTH_TYPE_SAE)) { neg_auth = WLAN_AUTH_TYPE_SAE; match = true; break; @@ -491,8 +497,8 @@ static bool scm_is_rsn_security(struct scan_filter *filter, if (scm_is_cipher_match(rsn.akm_suites, rsn.akm_suite_count, WLAN_RSN_DPP_AKM)) { - if (match_any_akm || (WLAN_AUTH_TYPE_DPP_RSN == - filter->auth_type[i])) { + if (match_any_akm || + (filter_akm == WLAN_AUTH_TYPE_DPP_RSN)) { neg_auth = WLAN_AUTH_TYPE_DPP_RSN; match = true; break; @@ -502,7 +508,7 @@ static bool scm_is_rsn_security(struct scan_filter *filter, rsn.akm_suite_count, WLAN_RSN_OSEN_AKM)) { if (match_any_akm || - WLAN_AUTH_TYPE_OSEN == filter->auth_type[i]) { + (filter_akm == WLAN_AUTH_TYPE_OSEN)) { neg_auth = WLAN_AUTH_TYPE_OSEN; match = true; break; @@ -511,8 +517,8 @@ static bool scm_is_rsn_security(struct scan_filter *filter, if (scm_is_cipher_match(rsn.akm_suites, rsn.akm_suite_count, WLAN_RSN_SEL(WLAN_AKM_OWE))) { - if (match_any_akm || (WLAN_AUTH_TYPE_OWE == - filter->auth_type[i])) { + if (match_any_akm || + (filter_akm == WLAN_AUTH_TYPE_OWE)) { neg_auth = WLAN_AUTH_TYPE_OWE; match = true; break; @@ -521,8 +527,8 @@ static bool scm_is_rsn_security(struct scan_filter *filter, if (scm_is_cipher_match(rsn.akm_suites, rsn.akm_suite_count, WLAN_RSN_SEL(WLAN_AKM_FT_IEEE8021X))) { - if (match_any_akm || (WLAN_AUTH_TYPE_FT_RSN == - filter->auth_type[i])) { + if (match_any_akm || + (filter_akm == WLAN_AUTH_TYPE_FT_RSN)) { neg_auth = WLAN_AUTH_TYPE_FT_RSN; match = true; break; @@ -532,8 +538,8 @@ static bool scm_is_rsn_security(struct scan_filter *filter, if (scm_is_cipher_match(rsn.akm_suites, rsn.akm_suite_count, WLAN_RSN_SEL(WLAN_AKM_FT_PSK))) { - if (match_any_akm || (WLAN_AUTH_TYPE_FT_RSN_PSK == - filter->auth_type[i])) { + if (match_any_akm || + (filter_akm == WLAN_AUTH_TYPE_FT_RSN_PSK)) { neg_auth = WLAN_AUTH_TYPE_FT_RSN_PSK; match = true; break; @@ -543,8 +549,8 @@ static bool scm_is_rsn_security(struct scan_filter *filter, if (scm_is_cipher_match(rsn.akm_suites, rsn.akm_suite_count, WLAN_RSN_CCKM_AKM)) { - if (match_any_akm || (WLAN_AUTH_TYPE_CCKM_RSN == - filter->auth_type[i])) { + if (match_any_akm || + (filter_akm == WLAN_AUTH_TYPE_CCKM_RSN)) { neg_auth = WLAN_AUTH_TYPE_CCKM_RSN; match = true; break; @@ -554,8 +560,15 @@ static bool scm_is_rsn_security(struct scan_filter *filter, if (scm_is_cipher_match(rsn.akm_suites, rsn.akm_suite_count, WLAN_RSN_SEL(WLAN_AKM_IEEE8021X))) { - if (match_any_akm || (WLAN_AUTH_TYPE_RSN == - filter->auth_type[i])) { + if (is_adaptive_11r && + (filter_akm == WLAN_AUTH_TYPE_FT_RSN)) { + neg_auth = WLAN_AUTH_TYPE_FT_RSN; + match = true; + break; + } + + if (match_any_akm || + (WLAN_AUTH_TYPE_RSN == filter_akm)) { neg_auth = WLAN_AUTH_TYPE_RSN; match = true; break; @@ -565,8 +578,15 @@ static bool scm_is_rsn_security(struct scan_filter *filter, if (scm_is_cipher_match(rsn.akm_suites, rsn.akm_suite_count, WLAN_RSN_SEL(WLAN_AKM_PSK))) { - if (match_any_akm || (WLAN_AUTH_TYPE_RSN_PSK == - filter->auth_type[i])) { + if (is_adaptive_11r && + (filter_akm == WLAN_AUTH_TYPE_FT_RSN_PSK)) { + neg_auth = WLAN_AUTH_TYPE_FT_RSN_PSK; + match = true; + break; + } + + if (match_any_akm || + (filter_akm == WLAN_AUTH_TYPE_RSN_PSK)) { neg_auth = WLAN_AUTH_TYPE_RSN_PSK; match = true; break; @@ -576,10 +596,16 @@ static bool scm_is_rsn_security(struct scan_filter *filter, if (scm_is_cipher_match(rsn.akm_suites, rsn.akm_suite_count, WLAN_RSN_SEL(WLAN_AKM_SHA256_PSK))) { - if (match_any_akm || (WLAN_AUTH_TYPE_RSN_PSK_SHA256 == - filter->auth_type[i])) { - neg_auth = - WLAN_AUTH_TYPE_RSN_PSK_SHA256; + if (is_adaptive_11r && + (filter_akm == WLAN_AUTH_TYPE_FT_RSN_PSK)) { + neg_auth = WLAN_AUTH_TYPE_FT_RSN_PSK; + match = true; + break; + } + + if (match_any_akm || + (filter_akm == WLAN_AUTH_TYPE_RSN_PSK_SHA256)) { + neg_auth = WLAN_AUTH_TYPE_RSN_PSK_SHA256; match = true; break; } @@ -588,10 +614,16 @@ static bool scm_is_rsn_security(struct scan_filter *filter, if (scm_is_cipher_match(rsn.akm_suites, rsn.akm_suite_count, WLAN_RSN_SEL(WLAN_AKM_SHA256_IEEE8021X))) { - if (match_any_akm || (WLAN_AUTH_TYPE_RSN_8021X_SHA256 == - filter->auth_type[i])) { - neg_auth = - WLAN_AUTH_TYPE_RSN_8021X_SHA256; + if (is_adaptive_11r && + (filter_akm == WLAN_AUTH_TYPE_FT_RSN)) { + neg_auth = WLAN_AUTH_TYPE_FT_RSN; + match = true; + break; + } + + if (match_any_akm || + (filter_akm == WLAN_AUTH_TYPE_RSN_8021X_SHA256)) { + neg_auth = WLAN_AUTH_TYPE_RSN_8021X_SHA256; match = true; break; } @@ -600,8 +632,7 @@ static bool scm_is_rsn_security(struct scan_filter *filter, rsn.akm_suite_count, WLAN_RSN_SEL(WLAN_AKM_SUITEB_EAP_SHA256))) { if (match_any_akm || - (WLAN_AUTH_TYPE_SUITEB_EAP_SHA256 == - filter->auth_type[i])) { + (filter_akm == WLAN_AUTH_TYPE_SUITEB_EAP_SHA256)) { neg_auth = WLAN_AUTH_TYPE_SUITEB_EAP_SHA256; match = true; break; @@ -611,8 +642,7 @@ static bool scm_is_rsn_security(struct scan_filter *filter, rsn.akm_suite_count, WLAN_RSN_SEL(WLAN_AKM_SUITEB_EAP_SHA384))) { if (match_any_akm || - (WLAN_AUTH_TYPE_SUITEB_EAP_SHA384 == - filter->auth_type[i])) { + (filter_akm == WLAN_AUTH_TYPE_SUITEB_EAP_SHA384)) { neg_auth = WLAN_AUTH_TYPE_SUITEB_EAP_SHA384; match = true; break; @@ -621,8 +651,8 @@ static bool scm_is_rsn_security(struct scan_filter *filter, if (scm_is_cipher_match(rsn.akm_suites, rsn.akm_suite_count, WLAN_RSN_SEL(WLAN_AKM_FT_SAE))) { - if (match_any_akm || (WLAN_AUTH_TYPE_FT_SAE == - filter->auth_type[i])) { + if (match_any_akm || + (filter_akm == WLAN_AUTH_TYPE_FT_SAE)) { neg_auth = WLAN_AUTH_TYPE_FT_SAE; match = true; break; @@ -633,8 +663,8 @@ static bool scm_is_rsn_security(struct scan_filter *filter, WLAN_RSN_SEL( WLAN_AKM_FT_SUITEB_EAP_SHA384))) { if (match_any_akm || - (WLAN_AUTH_TYPE_FT_SUITEB_EAP_SHA384 == - filter->auth_type[i])) { + (filter_akm == + WLAN_AUTH_TYPE_FT_SUITEB_EAP_SHA384)) { neg_auth = WLAN_AUTH_TYPE_FT_SUITEB_EAP_SHA384; match = true; break; @@ -923,8 +953,8 @@ static bool scm_is_wapi_security(struct scan_filter *filter, * Return: true if any security else false */ static bool scm_is_def_security(struct scan_filter *filter, - struct scan_cache_entry *db_entry, - struct security_info *security) + struct scan_cache_entry *db_entry, + struct security_info *security) { /* It is allowed to match anything. Try the more secured ones first. */ @@ -1045,8 +1075,8 @@ static bool scm_is_fils_config_match(struct scan_filter *filter, * Return: true if security match else false */ static bool scm_is_security_match(struct scan_filter *filter, - struct scan_cache_entry *db_entry, - struct security_info *security) + struct scan_cache_entry *db_entry, + struct security_info *security) { int i; bool match = false; @@ -1078,8 +1108,8 @@ static bool scm_is_security_match(struct scan_filter *filter, case WLAN_ENCRYPT_TYPE_AES_GCMP: case WLAN_ENCRYPT_TYPE_AES_GCMP_256: /* First check if there is a RSN match */ - match = scm_is_rsn_security(filter, - db_entry, &local_security); + match = scm_is_rsn_security(filter, db_entry, + &local_security); /* If not RSN, then check WPA match */ if (!match) match = scm_is_wpa_security(filter, @@ -1091,23 +1121,22 @@ static bool scm_is_security_match(struct scan_filter *filter, break; case WLAN_ENCRYPT_TYPE_ANY: default: - match = scm_is_def_security(filter, - db_entry, &local_security); + match = scm_is_def_security(filter, db_entry, + &local_security); break; } } if (match && security) - qdf_mem_copy(security, - &local_security, sizeof(*security)); + qdf_mem_copy(security, &local_security, sizeof(*security)); return match; } bool scm_filter_match(struct wlan_objmgr_psoc *psoc, - struct scan_cache_entry *db_entry, - struct scan_filter *filter, - struct security_info *security) + struct scan_cache_entry *db_entry, + struct scan_filter *filter, + struct security_info *security) { int i; bool match = false; @@ -1191,15 +1220,13 @@ bool scm_filter_match(struct wlan_objmgr_psoc *psoc, /* TODO match phyMode */ if (!filter->ignore_auth_enc_type && - !scm_is_security_match(filter, - db_entry, security)) { + !scm_is_security_match(filter, db_entry, security)) { scm_debug("%pM : Ignore as security profile didn't match", db_entry->bssid.bytes); return false; } - if (!util_is_bss_type_match(filter->bss_type, - db_entry->cap_info)) { + if (!util_is_bss_type_match(filter->bss_type, db_entry->cap_info)) { scm_debug("%pM : Ignore as bss type didn't match cap_info %x bss_type %d", db_entry->bssid.bytes, db_entry->cap_info.value, filter->bss_type); diff --git a/umac/scan/dispatcher/inc/wlan_scan_public_structs.h b/umac/scan/dispatcher/inc/wlan_scan_public_structs.h index b740b9591095..52d46e695243 100644 --- a/umac/scan/dispatcher/inc/wlan_scan_public_structs.h +++ b/umac/scan/dispatcher/inc/wlan_scan_public_structs.h @@ -158,6 +158,7 @@ struct element_info { * @fils_indication: pointer to FILS indication ie * @esp: pointer to ESP indication ie * @mbo_oce: pointer to mbo/oce indication ie + * @adaptive_11r: pointer to adaptive 11r IE */ struct ie_list { uint8_t *tim; @@ -206,6 +207,7 @@ struct ie_list { uint8_t *mbo_oce; uint8_t *muedca; uint8_t *extender; + uint8_t *adaptive_11r; }; enum scan_entry_connection_state { @@ -299,6 +301,7 @@ struct scan_mbssid_info { * @qbss_chan_load: Qbss channel load * @nss: supported NSS information * @is_p2p_ssid: is P2P entry + * @adaptive_11r_ap: flag to check if AP supports adaptive 11r * @scan_entry_time: boottime in microsec when last beacon/probe is received * @rssi_timestamp: boottime in microsec when RSSI was updated * @hidden_ssid_timestamp: boottime in microsec when hidden @@ -340,6 +343,7 @@ struct scan_cache_entry { uint8_t qbss_chan_load; uint8_t nss; bool is_p2p; + bool adaptive_11r_ap; qdf_time_t scan_entry_time; qdf_time_t rssi_timestamp; qdf_time_t hidden_ssid_timestamp; @@ -523,6 +527,7 @@ struct fils_filter_info { /** * @bss_scoring_required :- flag to bypass scoring filtered results + * @enable_adaptive_11r: flag to check if adaptive 11r ini is enabled * @age_threshold: If set return entry which are newer than the age_threshold * @p2p_results: If only p2p entries is required * @rrm_measurement_filter: For measurement reports.if set, only SSID, BSSID @@ -560,6 +565,7 @@ struct fils_filter_info { */ struct scan_filter { bool bss_scoring_required; + bool enable_adaptive_11r; uint32_t age_threshold; uint32_t p2p_results; uint32_t rrm_measurement_filter; diff --git a/umac/scan/dispatcher/inc/wlan_scan_utils_api.h b/umac/scan/dispatcher/inc/wlan_scan_utils_api.h index d66d0cb30656..720135556e04 100644 --- a/umac/scan/dispatcher/inc/wlan_scan_utils_api.h +++ b/umac/scan/dispatcher/inc/wlan_scan_utils_api.h @@ -673,6 +673,7 @@ util_scan_copy_beacon_data(struct scan_cache_entry *new_entry, ie_lst->esp = conv_ptr(ie_lst->esp, old_ptr, new_ptr); ie_lst->mbo_oce = conv_ptr(ie_lst->mbo_oce, old_ptr, new_ptr); ie_lst->extender = conv_ptr(ie_lst->extender, old_ptr, new_ptr); + ie_lst->adaptive_11r = conv_ptr(ie_lst->adaptive_11r, old_ptr, new_ptr); return QDF_STATUS_SUCCESS; } @@ -809,6 +810,20 @@ util_scan_entry_rsn(struct scan_cache_entry *scan_entry) return scan_entry->ie_list.rsn; } +/** + * util_scan_entry_adaptive_11r()- function to read adaptive 11r Vendor IE + * @scan_entry: scan entry + * + * API, function to read adaptive 11r IE + * + * Return: apaptive 11r ie or NULL if ie is not present + */ +static inline uint8_t* +util_scan_entry_adaptive_11r(struct scan_cache_entry *scan_entry) +{ + return scan_entry->ie_list.adaptive_11r; +} + /** * util_scan_get_rsn_len()- function to read rsn IE length if present * @scan_entry: scan entry diff --git a/umac/scan/dispatcher/src/wlan_scan_utils_api.c b/umac/scan/dispatcher/src/wlan_scan_utils_api.c index e9049fe2e83a..75da0cc2d8e7 100644 --- a/umac/scan/dispatcher/src/wlan_scan_utils_api.c +++ b/umac/scan/dispatcher/src/wlan_scan_utils_api.c @@ -471,6 +471,13 @@ util_scan_parse_vendor_ie(struct scan_cache_entry *scan_params, scan_params->ie_list.mbo_oce = (uint8_t *)ie; } else if (is_extender_oui((uint8_t *)ie)) { scan_params->ie_list.extender = (uint8_t *)ie; + } else if (is_adaptive_11r_oui((uint8_t *)ie)) { + if ((ie->ie_len < OUI_LENGTH) || + (ie->ie_len > MAX_ADAPTIVE_11R_IE_LEN)) + return QDF_STATUS_E_INVAL; + + scan_params->ie_list.adaptive_11r = (uint8_t *)ie + + sizeof(struct ie_header); } return QDF_STATUS_SUCCESS; } @@ -977,6 +984,36 @@ util_scan_add_hidden_ssid(struct wlan_objmgr_pdev *pdev, qdf_nbuf_t bcnbuf) return QDF_STATUS_SUCCESS; } #endif /* WLAN_DFS_CHAN_HIDDEN_SSID */ + +#ifdef WLAN_ADAPTIVE_11R +/** + * scm_fill_adaptive_11r_cap() - Check if the AP supports adaptive 11r + * @scan_entry: Pointer to the scan entry + * + * Return: true if adaptive 11r is advertised else false + */ +static void scm_fill_adaptive_11r_cap(struct scan_cache_entry *scan_entry) +{ + uint8_t *ie; + uint8_t data; + bool adaptive_11r; + + ie = util_scan_entry_adaptive_11r(scan_entry); + if (!ie) + return; + + data = *(ie + OUI_LENGTH); + adaptive_11r = (data & 0x1) ? true : false; + + scan_entry->adaptive_11r_ap = adaptive_11r; +} +#else +static void scm_fill_adaptive_11r_cap(struct scan_cache_entry *scan_entry) +{ + scan_entry->adaptive_11r_ap = false; +} +#endif + static QDF_STATUS util_scan_gen_scan_entry(struct wlan_objmgr_pdev *pdev, uint8_t *frame, qdf_size_t frame_len, @@ -1114,6 +1151,8 @@ util_scan_gen_scan_entry(struct wlan_objmgr_pdev *pdev, scan_entry->phy_mode = util_scan_get_phymode_2g(scan_entry); scan_entry->nss = util_scan_scm_calc_nss_supported_by_ap(scan_entry); + scm_fill_adaptive_11r_cap(scan_entry); + util_scan_scm_update_bss_with_esp_data(scan_entry); qbss_load = (struct qbss_load_ie *) util_scan_entry_qbssload(scan_entry);