From 1379bfb6c09ee2ad5969db45c27fb675602b4ed0 Mon Sep 17 00:00:00 2001 From: Rajeev Kumar Sirasanagandla Date: Sat, 5 Nov 2016 18:37:04 +0530 Subject: qcacld-2.0: Add support to include selective scan IEs only Add support to include only selective IEs in probe requests in order to improve user's privacy. Change-Id: Ib874af7ec2f5453282ffe0e8fc2e50934460b745 CRs-Fixed: 1086582 --- CORE/HDD/inc/wlan_hdd_cfg.h | 79 ++++++ CORE/HDD/inc/wlan_hdd_main.h | 5 + CORE/HDD/src/wlan_hdd_cfg.c | 317 +++++++++++++++++++++++++ CORE/HDD/src/wlan_hdd_cfg80211.c | 100 +++++++- CORE/HDD/src/wlan_hdd_main.c | 26 +- CORE/MAC/inc/sirApi.h | 39 ++- CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c | 22 +- CORE/SERVICES/WMA/wma.c | 128 +++++++++- CORE/SME/inc/csrApi.h | 4 + CORE/SME/src/csr/csrApiScan.c | 62 ++++- CORE/SME/src/pmc/pmcApi.c | 7 +- 11 files changed, 774 insertions(+), 15 deletions(-) diff --git a/CORE/HDD/inc/wlan_hdd_cfg.h b/CORE/HDD/inc/wlan_hdd_cfg.h index 6207a15..301ded4 100644 --- a/CORE/HDD/inc/wlan_hdd_cfg.h +++ b/CORE/HDD/inc/wlan_hdd_cfg.h @@ -58,6 +58,8 @@ //Number of items that can be configured #define MAX_CFG_INI_ITEMS 1024 +#define MAX_PRB_REQ_VENDOR_OUI_INI_LEN 160 +#define VENDOR_SPECIFIC_IE_BITMAP 0x20000000 #ifdef SAP_AUTH_OFFLOAD /* 802.11 pre-share key length */ @@ -4206,6 +4208,66 @@ FG_BTC_BT_INTERVAL_PAGE_P2P_STA_DEFAULT #define CFG_5G_MAX_RSSI_PENALIZE_MAX (20) #define CFG_5G_MAX_RSSI_PENALIZE_DEFAULT (10) +/* enable/disable probe request whiltelist IE feature */ +#define CFG_PRB_REQ_IE_WHITELIST_NAME "g_enable_probereq_whitelist_ies" +#define CFG_PRB_REQ_IE_WHITELIST_MIN (0) +#define CFG_PRB_REQ_IE_WHITELIST_MAX (1) +#define CFG_PRB_REQ_IE_WHITELIST_DEFAULT (0) +/* + * For IE white listing in Probe Req, following ini parameters from + * g_probe_req_ie_bitmap_0 to g_probe_req_ie_bitmap_7 are used. User needs to + * input this values in hexa decimal format, when bit is set, corresponding ie + * needs to be included in probe request. + */ +#define CFG_PRB_REQ_IE_BIT_MAP0_NAME "g_probe_req_ie_bitmap_0" +#define CFG_PRB_REQ_IE_BIT_MAP0_MIN (0x00000000) +#define CFG_PRB_REQ_IE_BIT_MAP0_MAX (0xFFFFFFFF) +#define CFG_PRB_REQ_IE_BIT_MAP0_DEFAULT (0x00000000) + +#define CFG_PRB_REQ_IE_BIT_MAP1_NAME "g_probe_req_ie_bitmap_1" +#define CFG_PRB_REQ_IE_BIT_MAP1_MIN (0x00000000) +#define CFG_PRB_REQ_IE_BIT_MAP1_MAX (0xFFFFFFFF) +#define CFG_PRB_REQ_IE_BIT_MAP1_DEFAULT (0x00000000) + +#define CFG_PRB_REQ_IE_BIT_MAP2_NAME "g_probe_req_ie_bitmap_2" +#define CFG_PRB_REQ_IE_BIT_MAP2_MIN (0x00000000) +#define CFG_PRB_REQ_IE_BIT_MAP2_MAX (0xFFFFFFFF) +#define CFG_PRB_REQ_IE_BIT_MAP2_DEFAULT (0x00000000) + +#define CFG_PRB_REQ_IE_BIT_MAP3_NAME "g_probe_req_ie_bitmap_3" +#define CFG_PRB_REQ_IE_BIT_MAP3_MIN (0x00000000) +#define CFG_PRB_REQ_IE_BIT_MAP3_MAX (0xFFFFFFFF) +#define CFG_PRB_REQ_IE_BIT_MAP3_DEFAULT (0x00000000) + +#define CFG_PRB_REQ_IE_BIT_MAP4_NAME "g_probe_req_ie_bitmap_4" +#define CFG_PRB_REQ_IE_BIT_MAP4_MIN (0x00000000) +#define CFG_PRB_REQ_IE_BIT_MAP4_MAX (0xFFFFFFFF) +#define CFG_PRB_REQ_IE_BIT_MAP4_DEFAULT (0x00000000) + +#define CFG_PRB_REQ_IE_BIT_MAP5_NAME "g_probe_req_ie_bitmap_5" +#define CFG_PRB_REQ_IE_BIT_MAP5_MIN (0x00000000) +#define CFG_PRB_REQ_IE_BIT_MAP5_MAX (0xFFFFFFFF) +#define CFG_PRB_REQ_IE_BIT_MAP5_DEFAULT (0x00000000) + +#define CFG_PRB_REQ_IE_BIT_MAP6_NAME "g_probe_req_ie_bitmap_6" +#define CFG_PRB_REQ_IE_BIT_MAP6_MIN (0x00000000) +#define CFG_PRB_REQ_IE_BIT_MAP6_MAX (0xFFFFFFFF) +#define CFG_PRB_REQ_IE_BIT_MAP6_DEFAULT (0x00000000) + +#define CFG_PRB_REQ_IE_BIT_MAP7_NAME "g_probe_req_ie_bitmap_7" +#define CFG_PRB_REQ_IE_BIT_MAP7_MIN (0x00000000) +#define CFG_PRB_REQ_IE_BIT_MAP7_MAX (0xFFFFFFFF) +#define CFG_PRB_REQ_IE_BIT_MAP7_DEFAULT (0x00000000) + +/* + * For vendor specific IE, Probe Req OUI types and sub types which are + * to be white listed are specifed in gProbeReqOUIs in the following + * example format - gProbeReqOUIs=AABBCCDD EEFF1122 + */ +#define CFG_PROBE_REQ_OUI_NAME "gProbeReqOUIs" +#define CFG_PROBE_REQ_OUI_DEFAULT "" + + /*--------------------------------------------------------------------------- Type declarations -------------------------------------------------------------------------*/ @@ -5020,6 +5082,20 @@ struct hdd_config { int8_t rssi_penalize_threshold_5g; uint8_t rssi_penalize_factor_5g; uint8_t max_rssi_penalize_5g; + + bool probe_req_ie_whitelist; + /* probe request bit map ies */ + uint32_t probe_req_ie_bitmap_0; + uint32_t probe_req_ie_bitmap_1; + uint32_t probe_req_ie_bitmap_2; + uint32_t probe_req_ie_bitmap_3; + uint32_t probe_req_ie_bitmap_4; + uint32_t probe_req_ie_bitmap_5; + uint32_t probe_req_ie_bitmap_6; + uint32_t probe_req_ie_bitmap_7; + + /* Probe Request multiple vendor OUIs */ + uint8_t probe_req_ouis[MAX_PRB_REQ_VENDOR_OUI_INI_LEN]; }; typedef struct hdd_config hdd_config_t; @@ -5137,6 +5213,9 @@ static __inline unsigned long utilMin( unsigned long a, unsigned long b ) Function declarations and documentation -------------------------------------------------------------------------*/ VOS_STATUS hdd_parse_config_ini(hdd_context_t *pHddCtx); +uint32_t hdd_validate_prb_req_ie_bitmap(hdd_context_t* pHddCtx); +VOS_STATUS hdd_parse_probe_req_ouis(hdd_context_t* pHddCtx); +void hdd_free_probe_req_ouis(hdd_context_t* pHddCtx); VOS_STATUS hdd_update_mac_config(hdd_context_t *pHddCtx); VOS_STATUS hdd_set_sme_config( hdd_context_t *pHddCtx ); VOS_STATUS hdd_set_sme_chan_list(hdd_context_t *hdd_ctx); diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h index 8a70ab5..953aca0 100644 --- a/CORE/HDD/inc/wlan_hdd_main.h +++ b/CORE/HDD/inc/wlan_hdd_main.h @@ -265,6 +265,8 @@ typedef v_U8_t tWlanHddMacAddr[HDD_MAC_ADDR_LEN]; #define HDD_BW_GET_DIFF(_x, _y) (unsigned long)((ULONG_MAX - (_y)) + (_x) + 1) +#define MAX_PROBE_REQ_OUIS 16 + /* * Generic asynchronous request/response support * @@ -1894,6 +1896,9 @@ struct hdd_context_s vos_timer_t tdls_source_timer; struct hdd_scan_chan_info *chan_info; struct mutex chan_info_lock; + + uint32_t no_of_probe_req_ouis; + struct vendor_oui *probe_req_voui; }; /*--------------------------------------------------------------------------- diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c index c00ade7..787ae45 100644 --- a/CORE/HDD/src/wlan_hdd_cfg.c +++ b/CORE/HDD/src/wlan_hdd_cfg.c @@ -4835,6 +4835,74 @@ REG_TABLE_ENTRY g_registry_table[] = CFG_5G_MAX_RSSI_PENALIZE_DEFAULT, CFG_5G_MAX_RSSI_PENALIZE_MIN, CFG_5G_MAX_RSSI_PENALIZE_MAX), + + REG_VARIABLE(CFG_PRB_REQ_IE_WHITELIST_NAME, WLAN_PARAM_Integer, + hdd_config_t, probe_req_ie_whitelist, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_PRB_REQ_IE_WHITELIST_DEFAULT, + CFG_PRB_REQ_IE_WHITELIST_MIN, + CFG_PRB_REQ_IE_WHITELIST_MAX), + + REG_VARIABLE(CFG_PRB_REQ_IE_BIT_MAP0_NAME, WLAN_PARAM_HexInteger, + hdd_config_t, probe_req_ie_bitmap_0, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_PRB_REQ_IE_BIT_MAP0_DEFAULT, + CFG_PRB_REQ_IE_BIT_MAP0_MIN, + CFG_PRB_REQ_IE_BIT_MAP0_MAX), + + REG_VARIABLE(CFG_PRB_REQ_IE_BIT_MAP1_NAME, WLAN_PARAM_HexInteger, + hdd_config_t, probe_req_ie_bitmap_1, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_PRB_REQ_IE_BIT_MAP1_DEFAULT, + CFG_PRB_REQ_IE_BIT_MAP1_MIN, + CFG_PRB_REQ_IE_BIT_MAP1_MAX), + + REG_VARIABLE(CFG_PRB_REQ_IE_BIT_MAP2_NAME, WLAN_PARAM_HexInteger, + hdd_config_t, probe_req_ie_bitmap_2, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_PRB_REQ_IE_BIT_MAP2_DEFAULT, + CFG_PRB_REQ_IE_BIT_MAP2_MIN, + CFG_PRB_REQ_IE_BIT_MAP2_MAX), + + REG_VARIABLE(CFG_PRB_REQ_IE_BIT_MAP3_NAME, WLAN_PARAM_HexInteger, + hdd_config_t, probe_req_ie_bitmap_3, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_PRB_REQ_IE_BIT_MAP3_DEFAULT, + CFG_PRB_REQ_IE_BIT_MAP3_MIN, + CFG_PRB_REQ_IE_BIT_MAP3_MAX), + + REG_VARIABLE(CFG_PRB_REQ_IE_BIT_MAP4_NAME, WLAN_PARAM_HexInteger, + hdd_config_t, probe_req_ie_bitmap_4, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_PRB_REQ_IE_BIT_MAP4_DEFAULT, + CFG_PRB_REQ_IE_BIT_MAP4_MIN, + CFG_PRB_REQ_IE_BIT_MAP4_MAX), + + REG_VARIABLE(CFG_PRB_REQ_IE_BIT_MAP5_NAME, WLAN_PARAM_HexInteger, + hdd_config_t, probe_req_ie_bitmap_5, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_PRB_REQ_IE_BIT_MAP5_DEFAULT, + CFG_PRB_REQ_IE_BIT_MAP5_MIN, + CFG_PRB_REQ_IE_BIT_MAP5_MAX), + + REG_VARIABLE(CFG_PRB_REQ_IE_BIT_MAP6_NAME, WLAN_PARAM_HexInteger, + hdd_config_t, probe_req_ie_bitmap_6, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_PRB_REQ_IE_BIT_MAP6_DEFAULT, + CFG_PRB_REQ_IE_BIT_MAP6_MIN, + CFG_PRB_REQ_IE_BIT_MAP6_MAX), + + REG_VARIABLE(CFG_PRB_REQ_IE_BIT_MAP7_NAME, WLAN_PARAM_HexInteger, + hdd_config_t, probe_req_ie_bitmap_7, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_PRB_REQ_IE_BIT_MAP7_DEFAULT, + CFG_PRB_REQ_IE_BIT_MAP7_MIN, + CFG_PRB_REQ_IE_BIT_MAP7_MAX), + + REG_VARIABLE_STRING(CFG_PROBE_REQ_OUI_NAME, WLAN_PARAM_String, + hdd_config_t, probe_req_ouis, + VAR_FLAGS_OPTIONAL, + (void *)CFG_PROBE_REQ_OUI_DEFAULT), }; @@ -5691,6 +5759,46 @@ void print_hdd_cfg(hdd_context_t *pHddCtx) hddLog(LOG2, "Name = [%s] Value = [%u] ", CFG_TDLS_ENABLE_DEFER_TIMER, pHddCtx->cfg_ini->tdls_enable_defer_time); + + hddLog(LOG2, "Name = [%s] Value = [%x] ", + CFG_PRB_REQ_IE_WHITELIST_NAME, + pHddCtx->cfg_ini->probe_req_ie_whitelist); + + hddLog(LOG2, "Name = [%s] Value = [%x] ", + CFG_PRB_REQ_IE_BIT_MAP0_NAME, + pHddCtx->cfg_ini->probe_req_ie_bitmap_0); + + hddLog(LOG2, "Name = [%s] Value = [%x] ", + CFG_PRB_REQ_IE_BIT_MAP1_NAME, + pHddCtx->cfg_ini->probe_req_ie_bitmap_1); + + hddLog(LOG2, "Name = [%s] Value = [%x] ", + CFG_PRB_REQ_IE_BIT_MAP2_NAME, + pHddCtx->cfg_ini->probe_req_ie_bitmap_2); + + hddLog(LOG2, "Name = [%s] Value = [%x] ", + CFG_PRB_REQ_IE_BIT_MAP3_NAME, + pHddCtx->cfg_ini->probe_req_ie_bitmap_3); + + hddLog(LOG2, "Name = [%s] Value = [%x] ", + CFG_PRB_REQ_IE_BIT_MAP4_NAME, + pHddCtx->cfg_ini->probe_req_ie_bitmap_4); + + hddLog(LOG2, "Name = [%s] Value = [%x] ", + CFG_PRB_REQ_IE_BIT_MAP5_NAME, + pHddCtx->cfg_ini->probe_req_ie_bitmap_5); + + hddLog(LOG2, "Name = [%s] Value = [%x] ", + CFG_PRB_REQ_IE_BIT_MAP6_NAME, + pHddCtx->cfg_ini->probe_req_ie_bitmap_6); + + hddLog(LOG2, "Name = [%s] Value = [%x] ", + CFG_PRB_REQ_IE_BIT_MAP7_NAME, + pHddCtx->cfg_ini->probe_req_ie_bitmap_7); + + hddLog(LOG2, "Name = [%s] Value =[%s]", + CFG_PROBE_REQ_OUI_NAME, + pHddCtx->cfg_ini->probe_req_ouis); } #define CFG_VALUE_MAX_LEN 256 @@ -8187,3 +8295,212 @@ void hdd_set_btc_bt_wlan_interval(hdd_context_t *hdd_ctx) if (VOS_STATUS_SUCCESS != status) hddLog(LOGE, "Fail to set enable bt wlan coex parameters"); } + +/** + * hdd_validate_prb_req_ie_bitmap - validates user input for ie bit map + * @hdd_ctx: the pointer to hdd context + * + * This function checks whether user have entered valid probe request + * ie bitmap and also verifies vendor ouis if vendor specific ie is set + * + * Return: status of verification + * 1 - valid input + * 0 - invalid input + */ +uint32_t hdd_validate_prb_req_ie_bitmap(hdd_context_t* pHddCtx) +{ + if (!(pHddCtx->cfg_ini->probe_req_ie_bitmap_0 || + pHddCtx->cfg_ini->probe_req_ie_bitmap_1 || + pHddCtx->cfg_ini->probe_req_ie_bitmap_2 || + pHddCtx->cfg_ini->probe_req_ie_bitmap_3 || + pHddCtx->cfg_ini->probe_req_ie_bitmap_4 || + pHddCtx->cfg_ini->probe_req_ie_bitmap_5 || + pHddCtx->cfg_ini->probe_req_ie_bitmap_6 || + pHddCtx->cfg_ini->probe_req_ie_bitmap_7)) + return 0; + + /** + * check whether vendor oui IE is set and OUIs are present, each OUI + * is eneterd in the form of string of 8 characters from ini, therefore, + * for atleast one OUI, minimum length is 8 and hence this string length + * is checked for minimum of 8 + */ + if ((pHddCtx->cfg_ini->probe_req_ie_bitmap_6 & + VENDOR_SPECIFIC_IE_BITMAP) && + (strlen(pHddCtx->cfg_ini->probe_req_ouis) < 8)) + return 0; + + /* check whether vendor oui IE is not set but OUIs are present */ + if (!(pHddCtx->cfg_ini->probe_req_ie_bitmap_6 & + VENDOR_SPECIFIC_IE_BITMAP) && + (strlen(pHddCtx->cfg_ini->probe_req_ouis) > 0)) + return 0; + + return 1; +} + +/** + * probe_req_voui_convert_to_hex - converts str of 8 chars into two hex values + * @temp: string to be converted + * @voui: contains the type and subtype values + * + * This function converts the string length of 8 characters into two + * hexa-decimal values, oui_type and oui_subtype, where oui_type is the + * hexa decimal value converted from first 6 characters and oui_subtype is + * hexa decimal value converted from last 2 characters. + * strings which doesn't match with the specified pattern are ignored. + * + * Return: status of conversion + * 1 - if conversion is successful + * 0 - if conversion is failed + */ +static uint32_t hdd_probe_req_voui_convert_to_hex(uint8_t *temp, + struct vendor_oui *voui) +{ + uint32_t hex_value[4]; + uint32_t i = 0; + uint32_t indx = 0; + + memset(hex_value, 0x00, sizeof(hex_value)); + memset(voui, 0x00, sizeof(*voui)); + + /* convert string to hex */ + for (i = 0; i < 8; i++) { + if (temp[i] >= '0' && temp[i] <= '9') { + hex_value[indx] = (temp[i] - '0') << 4; + } else if (temp[i] >= 'A' && temp[i] <= 'F') { + hex_value[indx] = (temp[i] - 'A') + 0xA; + hex_value[indx] = hex_value[indx] << 4; + } else { + /* invalid character in oui */ + return 0; + } + + if (temp[i + 1] >= '0' && temp[i + 1] <= '9') { + hex_value[indx] |= (temp[i + 1] - '0'); + i = i + 1; + indx = indx + 1; + } else if (temp[i + 1] >= 'A' && temp[i + 1] <= 'F') { + hex_value[indx] |= ((temp[i + 1] - 'A') + 0xA); + i = i + 1; + indx = indx + 1; + } else { + /* invalid character in oui */ + return 0; + } + } + + voui->oui_type = (hex_value[0] | (hex_value[1] << 8) | + (hex_value[2] << 16)); + voui->oui_subtype = hex_value[3]; + + hddLog(LOG1, FL("OUI_type = %x and OUI_subtype = %x"), voui->oui_type, + voui->oui_subtype); + return 1; +} + +/** + * hdd_parse_probe_req_ouis - form ouis from ini gProbeReqOUIs + * @hdd_ctx: the pointer to hdd context + * + * This function parses the ini string gProbeReqOUIs which needs to in the + * following format: + * "<8 characters of [0-9] or [A-F]>space<8 characters from [0-9] etc.," + * example: "AABBCCDD 1122EEFF" + * and the logic counts the number of OUIS and allocates the memory + * for every valid OUI and is stored in hdd_context_t + * + * Return: status of parsing + */ +VOS_STATUS hdd_parse_probe_req_ouis(hdd_context_t* pHddCtx) +{ + struct vendor_oui voui[MAX_PROBE_REQ_OUIS]; + uint8_t *str; + uint8_t temp[9]; + uint32_t start = 0, end = 0; + uint32_t oui_indx = 0; + uint32_t i = 0; + + pHddCtx->cfg_ini->probe_req_ouis[MAX_PRB_REQ_VENDOR_OUI_INI_LEN - 1] = + '\0'; + if (!strlen(pHddCtx->cfg_ini->probe_req_ouis)) { + pHddCtx->no_of_probe_req_ouis = 0; + pHddCtx->probe_req_voui = NULL; + hddLog(LOG1, FL("NO OUIS to parse")); + return VOS_STATUS_SUCCESS; + } + + str = (uint8_t *)(pHddCtx->cfg_ini->probe_req_ouis); + + while(str[i] != '\0') { + if (str[i] == ' ') { + if ((end - start) != 8) + { + end = start = 0; + i++; + continue; + } else { + memcpy(temp, &str[i - 8], 8); + i++; + temp[8] = '\0'; + if (hdd_probe_req_voui_convert_to_hex(temp, + &voui[oui_indx]) == 0) { + continue; + } + oui_indx++; + if (oui_indx > MAX_PROBE_REQ_OUIS) { + hddLog(LOGE, "Max no.of OUIS supported " + "is 16. ignoring the rest"); + return VOS_STATUS_SUCCESS; + } + } + start = end = 0; + } else { + i++; + end++; + } + } + + if ((end - start) == 8) { + memcpy(temp, &str[i - 8], 8); + temp[8] = '\0'; + if (hdd_probe_req_voui_convert_to_hex(temp, + &voui[oui_indx]) == 1) + oui_indx++; + } + + if (!oui_indx) + return VOS_STATUS_SUCCESS; + + pHddCtx->probe_req_voui = (struct vendor_oui *)vos_mem_malloc(oui_indx * + sizeof(struct vendor_oui)); + if (pHddCtx->probe_req_voui == NULL) { + hddLog(LOGE,"Not Enough memory for OUI"); + pHddCtx->no_of_probe_req_ouis = 0; + return VOS_STATUS_E_FAILURE; + } + vos_mem_zero(pHddCtx->probe_req_voui, + oui_indx * sizeof(struct vendor_oui)); + pHddCtx->no_of_probe_req_ouis = oui_indx; + vos_mem_copy(pHddCtx->probe_req_voui, voui, + oui_indx * sizeof(struct vendor_oui)); + + return VOS_STATUS_SUCCESS; +} + +/** + * hdd_free_probe_req_ouis - de-allocates the probe req ouis + * @hdd_ctx: the pointer to hdd context + * + * This function de-alloactes the probe req ouis which are + * allocated while parsing of ini string gProbeReqOUIs + * + * Return: None + */ +void hdd_free_probe_req_ouis(hdd_context_t* pHddCtx) +{ + if (!pHddCtx->probe_req_voui) + vos_mem_free(pHddCtx->probe_req_voui); + + pHddCtx->no_of_probe_req_ouis = 0; +} diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index b61bbdb..d51350e 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -1578,6 +1578,49 @@ wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy, } /** + * wlan_hdd_fill_whitelist_ie_attrs - fill the white list members + * @ie_whitelist: enables whitelist + * @probe_req_ie_bitmap: bitmap to be filled + * @num_vendor_oui: pointer to no of ouis + * @voui: pointer to ouis to be filled + * @pHddCtx: pointer to hdd ctx + * + * This function fills the ie bitmap and vendor oui fields with the + * corresponding values present in cfg_ini and PHddCtx + * + * Return: Return none + */ +static void wlan_hdd_fill_whitelist_ie_attrs(bool *ie_whitelist, + uint32_t *probe_req_ie_bitmap, + uint32_t *num_vendor_oui, + struct vendor_oui *voui, + hdd_context_t *pHddCtx) +{ + uint32_t i = 0; + + *ie_whitelist = true; + probe_req_ie_bitmap[0] = pHddCtx->cfg_ini->probe_req_ie_bitmap_0; + probe_req_ie_bitmap[1] = pHddCtx->cfg_ini->probe_req_ie_bitmap_1; + probe_req_ie_bitmap[2] = pHddCtx->cfg_ini->probe_req_ie_bitmap_2; + probe_req_ie_bitmap[3] = pHddCtx->cfg_ini->probe_req_ie_bitmap_3; + probe_req_ie_bitmap[4] = pHddCtx->cfg_ini->probe_req_ie_bitmap_4; + probe_req_ie_bitmap[5] = pHddCtx->cfg_ini->probe_req_ie_bitmap_5; + probe_req_ie_bitmap[6] = pHddCtx->cfg_ini->probe_req_ie_bitmap_6; + probe_req_ie_bitmap[7] = pHddCtx->cfg_ini->probe_req_ie_bitmap_7; + + *num_vendor_oui = 0; + + if ((pHddCtx->no_of_probe_req_ouis != 0) && (voui != NULL)) { + *num_vendor_oui = pHddCtx->no_of_probe_req_ouis; + for (i = 0; i < pHddCtx->no_of_probe_req_ouis; i++) { + voui[i].oui_type = pHddCtx->probe_req_voui[i].oui_type; + voui[i].oui_subtype = + pHddCtx->probe_req_voui[i].oui_subtype; + } + } +} + +/** * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC * @wiphy: pointer to wireless wiphy structure. * @wdev: pointer to wireless_dev structure. @@ -1625,12 +1668,16 @@ __wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy, return -EINVAL; } - pReqMsg = vos_mem_malloc(sizeof(*pReqMsg)); + pReqMsg = vos_mem_malloc(sizeof(*pReqMsg) + + (pHddCtx->no_of_probe_req_ouis) * + (sizeof(struct vendor_oui))); if (!pReqMsg) { hddLog(LOGE, FL("vos_mem_malloc failed")); return -ENOMEM; } - vos_mem_zero(pReqMsg, sizeof(*pReqMsg)); + vos_mem_zero(pReqMsg, sizeof(*pReqMsg) + + (pHddCtx->no_of_probe_req_ouis) * + (sizeof(struct vendor_oui))); /* Parse and fetch oui */ if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) { @@ -1647,7 +1694,15 @@ __wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy, pReqMsg->enb_probe_req_sno_randomization = 1; hddLog(LOG1, FL("Oui (%02x:%02x:%02x), vdev_id = %d"), pReqMsg->oui[0], - pReqMsg->oui[1], pReqMsg->oui[2], pReqMsg->vdev_id); + pReqMsg->oui[1], pReqMsg->oui[2], pReqMsg->vdev_id); + + if (pHddCtx->cfg_ini->probe_req_ie_whitelist) + wlan_hdd_fill_whitelist_ie_attrs(&pReqMsg->ie_whitelist, + pReqMsg->probe_req_ie_bitmap, + &pReqMsg->num_vendor_oui, + (struct vendor_oui *)((uint8_t *)pReqMsg + + sizeof(*pReqMsg)), + pHddCtx); status = sme_SetScanningMacOui(pHddCtx->hHal, pReqMsg); if (!HAL_STATUS_SUCCESS(status)) { @@ -18805,6 +18860,25 @@ int __wlan_hdd_cfg80211_scan( struct wiphy *wiphy, wlan_hdd_update_scan_rand_attrs((void *)&scanRequest, (void *)request, WLAN_HDD_HOST_SCAN); + if (pHddCtx->no_of_probe_req_ouis != 0) { + scanRequest.voui = (struct vendor_oui *)vos_mem_malloc( + pHddCtx->no_of_probe_req_ouis * + sizeof(struct vendor_oui)); + if (!scanRequest.voui) { + hddLog(LOGE, FL("Not enough memory for voui")); + scanRequest.num_vendor_oui = 0; + status = -ENOMEM; + goto free_mem; + } + } + + if (pHddCtx->cfg_ini->probe_req_ie_whitelist) + wlan_hdd_fill_whitelist_ie_attrs(&scanRequest.ie_whitelist, + scanRequest.probe_req_ie_bitmap, + &scanRequest.num_vendor_oui, + scanRequest.voui, + pHddCtx); + vos_runtime_pm_prevent_suspend(pHddCtx->runtime_context.scan); status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, &scanRequest, &scanId, @@ -18846,6 +18920,9 @@ free_mem: if( channelList ) vos_mem_free( channelList ); + if(scanRequest.voui) + vos_mem_free(scanRequest.voui); + EXIT(); return status; } @@ -22819,7 +22896,9 @@ static int __wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy, return -ENOTSUPP; } - pPnoRequest = (tpSirPNOScanReq) vos_mem_malloc(sizeof (tSirPNOScanReq)); + pPnoRequest = (tpSirPNOScanReq) vos_mem_malloc(sizeof(tSirPNOScanReq) + + (pHddCtx->no_of_probe_req_ouis) * + (sizeof(struct vendor_oui))); if (NULL == pPnoRequest) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, @@ -22827,7 +22906,9 @@ static int __wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy, return -ENOMEM; } - memset(pPnoRequest, 0, sizeof (tSirPNOScanReq)); + memset(pPnoRequest, 0, sizeof (tSirPNOScanReq) + + (pHddCtx->no_of_probe_req_ouis) * + (sizeof(struct vendor_oui))); pPnoRequest->enable = 1; /*Enable PNO */ pPnoRequest->ucNetworksCount = request->n_match_sets; if ((!pPnoRequest->ucNetworksCount ) || @@ -22985,6 +23066,15 @@ static int __wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy, wlan_hdd_update_scan_rand_attrs((void *)pPnoRequest, (void *)request, WLAN_HDD_PNO_SCAN); + if (pHddCtx->cfg_ini->probe_req_ie_whitelist) + wlan_hdd_fill_whitelist_ie_attrs(&pPnoRequest->ie_whitelist, + pPnoRequest->probe_req_ie_bitmap, + &pPnoRequest->num_vendor_oui, + (struct vendor_oui *)( + (uint8_t *)pPnoRequest + + sizeof(*pPnoRequest)), + pHddCtx); + status = sme_SetPreferredNetworkList(WLAN_HDD_GET_HAL_CTX(pAdapter), pPnoRequest, pAdapter->sessionId, hdd_cfg80211_sched_scan_done_callback, pAdapter); diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index 9a1922b..b967a67 100644 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -13334,6 +13334,7 @@ free_hdd_ctx: wlan_hdd_deinit_chan_info(pHddCtx); wlan_hdd_deinit_tx_rx_histogram(pHddCtx); + hdd_free_probe_req_ouis(pHddCtx); wiphy_unregister(wiphy) ; wlan_hdd_cfg80211_deinit(wiphy); wiphy_free(wiphy) ; @@ -14926,6 +14927,27 @@ int hdd_wlan_startup(struct device *dev, v_VOID_t *hif_sc) if (!hdd_ipa_is_present(pHddCtx)) hdd_ipa_reset_ipaconfig(pHddCtx, 0); + if (pHddCtx->cfg_ini->probe_req_ie_whitelist) + { + if (hdd_validate_prb_req_ie_bitmap(pHddCtx)) + { + /* parse ini string probe req oui */ + status = hdd_parse_probe_req_ouis(pHddCtx); + if (VOS_STATUS_SUCCESS != status) + { + hddLog(LOGE, FL("Error parsing probe req ouis - Ignoring them" + " disabling white list")); + pHddCtx->cfg_ini->probe_req_ie_whitelist = false; + } + } + else + { + hddLog(LOGE, FL("invalid probe req ie bitmap and ouis," + " disabling white list")); + pHddCtx->cfg_ini->probe_req_ie_whitelist = false; + } + } + if (0 == pHddCtx->cfg_ini->max_go_peers) pHddCtx->cfg_ini->max_go_peers = pHddCtx->cfg_ini->max_sap_peers; @@ -15944,8 +15966,10 @@ err_histogram: err_free_hdd_context: /* wiphy_free() will free the HDD context so remove global reference */ - if (pVosContext) + if (pVosContext) { + hdd_free_probe_req_ouis(pHddCtx); ((VosContextType*)(pVosContext))->pHDDContext = NULL; + } wiphy_free(wiphy) ; //kfree(wdev) ; diff --git a/CORE/MAC/inc/sirApi.h b/CORE/MAC/inc/sirApi.h index 83d53be..36f71b6 100644 --- a/CORE/MAC/inc/sirApi.h +++ b/CORE/MAC/inc/sirApi.h @@ -89,6 +89,7 @@ typedef tANI_U8 tSirVersionString[SIR_VERSION_STRING_LEN]; #define MAXNUM_PERIODIC_TX_PTRNS 6 #define WIFI_SCANNING_MAC_OUI_LENGTH 3 +#define PROBE_REQ_BITMAP_LEN 8 #define MAX_LEN_UDP_RESP_OFFLOAD 128 @@ -945,6 +946,11 @@ typedef struct sSirSmeScanReq uint32_t enable_scan_randomization; uint8_t mac_addr[VOS_MAC_ADDR_SIZE]; uint8_t mac_addr_mask[VOS_MAC_ADDR_SIZE]; + bool ie_whitelist; + uint32_t probe_req_ie_bitmap[PROBE_REQ_BITMAP_LEN]; + uint32_t num_vendor_oui; + uint32_t oui_field_len; + uint32_t oui_field_offset; //channelList MUST be the last field of this structure tSirChannelList channelList; @@ -964,7 +970,10 @@ typedef struct sSirSmeScanReq ----------------------------- <--+ ... variable size uIEFiled up to uIEFieldLen (can be 0) - -----------------------------*/ + ----------------------------- + ... variable size upto num_vendor_oui + struct vendor_oui voui; + */ } tSirSmeScanReq, *tpSirSmeScanReq; typedef struct sSirSmeScanAbortReq @@ -3810,6 +3819,10 @@ typedef struct sSirPNOScanReq { uint32_t enable_pno_scan_randomization; uint8_t mac_addr[VOS_MAC_ADDR_SIZE]; uint8_t mac_addr_mask[VOS_MAC_ADDR_SIZE]; + bool ie_whitelist; + uint32_t probe_req_ie_bitmap[PROBE_REQ_BITMAP_LEN]; + uint32_t num_vendor_oui; + /* followed by one or more struct vendor_oui */ } tSirPNOScanReq, *tpSirPNOScanReq; typedef struct sSirSetRSSIFilterReq @@ -4536,6 +4549,11 @@ typedef struct sSirScanOffloadReq { uint32_t enable_scan_randomization; uint8_t mac_addr[VOS_MAC_ADDR_SIZE]; uint8_t mac_addr_mask[VOS_MAC_ADDR_SIZE]; + bool ie_whitelist; + uint32_t probe_req_ie_bitmap[PROBE_REQ_BITMAP_LEN]; + uint32_t num_vendor_oui; + uint32_t oui_field_len; + uint32_t oui_field_offset; tSirChannelList channelList; /*----------------------------- @@ -4554,7 +4572,10 @@ typedef struct sSirScanOffloadReq { ----------------------------- <--+ ... variable size uIEField up to uIEFieldLen (can be 0) - -----------------------------*/ + ----------------------------- + ... variable size upto num_vendor_oui + struct vendor_oui voui; + ------------------------*/ } tSirScanOffloadReq, *tpSirScanOffloadReq; /** @@ -5823,11 +5844,25 @@ typedef struct tANI_U8 stopReq; } tSirLLStatsClearReq, *tpSirLLStatsClearReq; +/** + * struct vendor_oui - probe request ie vendor oui information + * @oui_type: type of the vendor oui (3 valid octets) + * @oui_subtype: subtype of the vendor oui (1 valid octet) + */ +struct vendor_oui { + uint32_t oui_type; + uint32_t oui_subtype; +}; + typedef struct { tANI_U8 oui[WIFI_SCANNING_MAC_OUI_LENGTH]; uint32_t vdev_id; uint32_t enb_probe_req_sno_randomization; + bool ie_whitelist; + uint32_t probe_req_ie_bitmap[PROBE_REQ_BITMAP_LEN]; + uint32_t num_vendor_oui; + /* Followed by 0 or more struct vendor_oui */ } tSirScanMacOui, *tpSirScanMacOui; enum { diff --git a/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c b/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c index a6a7879..d1629bc 100644 --- a/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c +++ b/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c @@ -1233,7 +1233,7 @@ static eHalStatus limSendHalStartScanOffloadReq(tpAniSirGlobal pMac, /* The tSirScanOffloadReq will reserve the space for first channel, so allocate the memory for (numChannels - 1) and uIEFieldLen */ len = sizeof(tSirScanOffloadReq) + (pScanReq->channelList.numChannels - 1) + - pScanReq->uIEFieldLen; + pScanReq->uIEFieldLen + pScanReq->oui_field_len; if (!pMac->per_band_chainmask_supp) { if (IS_DOT11_MODE_HT(pScanReq->dot11mode)) { @@ -1332,7 +1332,8 @@ static eHalStatus limSendHalStartScanOffloadReq(tpAniSirGlobal pMac, pScanOffloadReq->uIEFieldLen = pScanReq->uIEFieldLen; pScanOffloadReq->uIEFieldOffset = len - addn_ie_len - - pScanOffloadReq->uIEFieldLen; + pScanOffloadReq->uIEFieldLen - + pScanReq->oui_field_len; vos_mem_copy( (tANI_U8 *) pScanOffloadReq + pScanOffloadReq->uIEFieldOffset, (tANI_U8 *) pScanReq + pScanReq->uIEFieldOffset, @@ -1395,6 +1396,23 @@ static eHalStatus limSendHalStartScanOffloadReq(tpAniSirGlobal pMac, VOS_MAC_ADDR_SIZE); } + pScanOffloadReq->oui_field_len = pScanReq->oui_field_len; + pScanOffloadReq->num_vendor_oui = pScanReq->num_vendor_oui; + pScanOffloadReq->ie_whitelist = pScanReq->ie_whitelist; + if (pScanOffloadReq->ie_whitelist) + vos_mem_copy(pScanOffloadReq->probe_req_ie_bitmap, + pScanReq->probe_req_ie_bitmap, + PROBE_REQ_BITMAP_LEN * sizeof(uint32_t)); + pScanOffloadReq->oui_field_offset = sizeof(tSirScanOffloadReq) + + (pScanOffloadReq->channelList.numChannels - 1) + + pScanOffloadReq->uIEFieldLen; + if (pScanOffloadReq->num_vendor_oui != 0) { + vos_mem_copy( + (tANI_U8 *) pScanOffloadReq + pScanOffloadReq->oui_field_offset, + (uint8_t *) pScanReq + pScanReq->oui_field_offset, + pScanReq->oui_field_len); + } + rc = wdaPostCtrlMsg(pMac, &msg); if (rc != eSIR_SUCCESS) { diff --git a/CORE/SERVICES/WMA/wma.c b/CORE/SERVICES/WMA/wma.c index c89f31b..e24b0e6 100644 --- a/CORE/SERVICES/WMA/wma.c +++ b/CORE/SERVICES/WMA/wma.c @@ -9884,6 +9884,8 @@ VOS_STATUS wma_get_buf_start_scan_cmd(tp_wma_handle wma_handle, u_int8_t SSID_num; int i; int len = sizeof(*cmd); + wmi_vendor_oui *voui = NULL; + struct vendor_oui *pvoui = NULL; tpAniSirGlobal pMac = (tpAniSirGlobal )vos_get_context(VOS_MODULE_ID_PE, wma_handle->vos_context); @@ -9908,6 +9910,10 @@ VOS_STATUS wma_get_buf_start_scan_cmd(tp_wma_handle wma_handle, if (scan_req->uIEFieldLen) len += roundup(scan_req->uIEFieldLen, sizeof(u_int32_t)); + len += WMI_TLV_HDR_SIZE; /* Length of TLV for array of wmi_vendor_oui */ + if (scan_req->num_vendor_oui) + len += scan_req->num_vendor_oui * sizeof(wmi_vendor_oui); + /* Allocate the memory */ *buf = wmi_buf_alloc(wma_handle->wmi_handle, len); if (!*buf) { @@ -10010,8 +10016,19 @@ VOS_STATUS wma_get_buf_start_scan_cmd(tp_wma_handle wma_handle, WMI_CHAR_ARRAY_TO_MAC_ADDR(scan_req->mac_addr_mask, &cmd->mac_mask); } + if (scan_req->ie_whitelist) + cmd->scan_ctrl_flags |= + WMI_SCAN_ENABLE_IE_WHTELIST_IN_PROBE_REQ; + WMA_LOGI("scan_ctrl_flags = %x", cmd->scan_ctrl_flags); + if (scan_req->ie_whitelist) { + for (i = 0; i < PROBE_REQ_BITMAP_LEN; i++) + cmd->ie_bitmap[i] = scan_req->probe_req_ie_bitmap[i]; + } + + cmd->num_vendor_oui = scan_req->num_vendor_oui; + if (!scan_req->p2pScanType) { WMA_LOGD("Normal Scan request"); cmd->scan_ctrl_flags |= WMI_SCAN_ADD_CCK_RATES; @@ -10233,6 +10250,29 @@ VOS_STATUS wma_get_buf_start_scan_cmd(tp_wma_handle wma_handle, } buf_ptr += WMI_TLV_HDR_SIZE + ie_len_with_pad; + /* mac randomization */ + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + scan_req->num_vendor_oui * + sizeof(wmi_vendor_oui)); + + buf_ptr += WMI_TLV_HDR_SIZE; + + if (cmd->num_vendor_oui != 0) { + voui = (wmi_vendor_oui *)buf_ptr; + pvoui = (struct vendor_oui *)((u_int8_t *)scan_req + + (scan_req->oui_field_offset)); + for (i = 0; i < cmd->num_vendor_oui; i++) { + WMITLV_SET_HDR(&voui[i].tlv_header, + WMITLV_TAG_STRUC_wmi_vendor_oui, + WMITLV_GET_STRUCT_TLVLEN( + wmi_vendor_oui)); + voui[i].oui_type_subtype = pvoui[i].oui_type | + (pvoui[i].oui_subtype << 24); + } + buf_ptr += cmd->num_vendor_oui * + sizeof(wmi_vendor_oui); + } + *buf_len = len; return VOS_STATUS_SUCCESS; error: @@ -20530,17 +20570,24 @@ static VOS_STATUS wma_pno_start(tp_wma_handle wma, tpSirPNOScanReq pno) u_int8_t *buf_ptr; u_int8_t i; int ret; + wmi_vendor_oui *voui = NULL; + struct vendor_oui *pvoui = NULL; WMA_LOGD("PNO Start"); len = sizeof(*cmd) + WMI_TLV_HDR_SIZE + /* TLV place holder for array of structures nlo_configured_parameters(nlo_list) */ - WMI_TLV_HDR_SIZE; /* TLV place holder for array of uint32 channel_list */ + WMI_TLV_HDR_SIZE + /* TLV place holder for array of uint32 channel_list */ + WMI_TLV_HDR_SIZE + /* TLV of nlo_channel_prediction_cfg */ + WMI_TLV_HDR_SIZE; /* array of wmi_vendor_oui */ len += sizeof(u_int32_t) * MIN(pno->aNetworks[0].ucChannelCount, WMI_NLO_MAX_CHAN); len += sizeof(nlo_configured_parameters) * MIN(pno->ucNetworksCount, WMI_NLO_MAX_SSIDS); + /* Add the fixed length of enlo_candidate_score_params */ + len += sizeof(enlo_candidate_score_params); + len += sizeof(wmi_vendor_oui) * pno->num_vendor_oui; buf = wmi_buf_alloc(wma->wmi_handle, len); if (!buf) { @@ -20578,8 +20625,19 @@ static VOS_STATUS wma_pno_start(tp_wma_handle wma, tpSirPNOScanReq pno) WMI_CHAR_ARRAY_TO_MAC_ADDR(pno->mac_addr, &cmd->mac_addr); WMI_CHAR_ARRAY_TO_MAC_ADDR(pno->mac_addr_mask, &cmd->mac_mask); } + + if (pno->ie_whitelist) + cmd->flags |= WMI_NLO_CONFIG_ENABLE_IE_WHITELIST_IN_PROBE_REQ; + WMA_LOGI("pno flags = %x", cmd->flags); + cmd->num_vendor_oui = pno->num_vendor_oui; + + if (pno->ie_whitelist) { + for (i = 0; i < PROBE_REQ_BITMAP_LEN; i++) + cmd->ie_bitmap[i] = pno->probe_req_ie_bitmap[i]; + } + buf_ptr += sizeof(wmi_nlo_config_cmd_fixed_param); cmd->no_of_ssids = MIN(pno->ucNetworksCount, WMI_NLO_MAX_SSIDS); @@ -20640,6 +20698,37 @@ static VOS_STATUS wma_pno_start(tp_wma_handle wma, tpSirPNOScanReq pno) } buf_ptr += cmd->num_of_channels * sizeof(u_int32_t); + /* + * For pno start, this is not needed but to get the correct offset of + * wmi_vendor_oui, this is needed + */ + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0); + buf_ptr += WMI_TLV_HDR_SIZE; /* zero no.of nlo_channel_prediction_cfg */ + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_STRUC_enlo_candidate_score_param, + WMITLV_GET_STRUCT_TLVLEN(enlo_candidate_score_params)); + buf_ptr += sizeof(enlo_candidate_score_params); + + /* ie white list */ + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + pno->num_vendor_oui * + sizeof(wmi_vendor_oui)); + + buf_ptr += WMI_TLV_HDR_SIZE; + + if (cmd->num_vendor_oui != 0) { + voui = (wmi_vendor_oui *)buf_ptr; + pvoui = (struct vendor_oui *)((uint8_t *)pno + sizeof(*pno)); + for (i = 0; i < cmd->num_vendor_oui; i++) { + WMITLV_SET_HDR(&voui[i].tlv_header, + WMITLV_TAG_STRUC_wmi_vendor_oui, + WMITLV_GET_STRUCT_TLVLEN( + wmi_vendor_oui)); + voui[i].oui_type_subtype = pvoui[i].oui_type | + (pvoui[i].oui_subtype << 24); + } + buf_ptr += cmd->num_vendor_oui * sizeof(wmi_vendor_oui); + } + /* TODO: Discrete firmware doesn't have command/option to configure * App IE which comes from wpa_supplicant as of part PNO start request. */ @@ -29358,13 +29447,17 @@ VOS_STATUS wma_scan_probe_setoui(tp_wma_handle wma, uint32_t len; u_int8_t *buf_ptr; u_int32_t *oui_buf; + uint32_t i = 0; + wmi_vendor_oui *voui = NULL; + struct vendor_oui *pvoui = NULL; if (!wma || !wma->wmi_handle) { WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__); return VOS_STATUS_E_INVAL; } - len = sizeof(*cmd); + len = sizeof(*cmd) + WMI_TLV_HDR_SIZE + + psetoui->num_vendor_oui * sizeof(wmi_vendor_oui); wmi_buf = wmi_buf_alloc(wma->wmi_handle, len); if (!wmi_buf) { WMA_LOGE("%s: wmi_buf_alloc failed", __func__); @@ -29388,8 +29481,39 @@ VOS_STATUS wma_scan_probe_setoui(tp_wma_handle wma, cmd->flags = WMI_SCAN_PROBE_OUI_SPOOFED_MAC_IN_PROBE_REQ; if (psetoui->enb_probe_req_sno_randomization) cmd->flags |= WMI_SCAN_PROBE_OUI_RANDOM_SEQ_NO_IN_PROBE_REQ; + + if (psetoui->ie_whitelist) + cmd->flags |= + WMI_SCAN_PROBE_OUI_ENABLE_IE_WHITELIST_IN_PROBE_REQ; + WMA_LOGI(FL("vdev_id = %d, flags = %x"), cmd->vdev_id, cmd->flags); + cmd->num_vendor_oui = psetoui->num_vendor_oui; + + if (psetoui->ie_whitelist) { + for (i = 0; i < PROBE_REQ_BITMAP_LEN; i++) + cmd->ie_bitmap[i] = psetoui->probe_req_ie_bitmap[i]; + } + + buf_ptr += sizeof(*cmd); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + psetoui->num_vendor_oui * + sizeof(wmi_vendor_oui)); + + buf_ptr += WMI_TLV_HDR_SIZE; + if (cmd->num_vendor_oui != 0) { + voui = (wmi_vendor_oui *)buf_ptr; + pvoui = (struct vendor_oui *)((u_int8_t *)psetoui + + sizeof(*psetoui)); + for (i = 0; i < cmd->num_vendor_oui; i++) { + WMITLV_SET_HDR(&voui[i].tlv_header, + WMITLV_TAG_STRUC_wmi_vendor_oui, + WMITLV_GET_STRUCT_TLVLEN( + wmi_vendor_oui)); + voui[i].oui_type_subtype = pvoui[i].oui_type | + (pvoui[i].oui_subtype << 24); + } + } if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len, WMI_SCAN_PROB_REQ_OUI_CMDID)) { diff --git a/CORE/SME/inc/csrApi.h b/CORE/SME/inc/csrApi.h index 5c03abe..a1606fe 100644 --- a/CORE/SME/inc/csrApi.h +++ b/CORE/SME/inc/csrApi.h @@ -314,6 +314,10 @@ typedef struct tagCsrScanRequest uint32_t enable_scan_randomization; uint8_t mac_addr[VOS_MAC_ADDR_SIZE]; uint8_t mac_addr_mask[VOS_MAC_ADDR_SIZE]; + bool ie_whitelist; + uint32_t probe_req_ie_bitmap[PROBE_REQ_BITMAP_LEN]; + uint32_t num_vendor_oui; + struct vendor_oui *voui; }tCsrScanRequest; typedef struct tagCsrBGScanRequest diff --git a/CORE/SME/src/csr/csrApiScan.c b/CORE/SME/src/csr/csrApiScan.c index 37e5a0f..65a8dc4 100644 --- a/CORE/SME/src/csr/csrApiScan.c +++ b/CORE/SME/src/csr/csrApiScan.c @@ -5827,7 +5827,8 @@ eHalStatus csrSendMBScanReq( tpAniSirGlobal pMac, tANI_U16 sessionId, msgLen = (tANI_U16)(sizeof( tSirSmeScanReq ) - sizeof( pMsg->channelList.channelNumber ) + ( sizeof( pMsg->channelList.channelNumber ) * pScanReq->ChannelInfo.numOfChannels )) + - ( pScanReq->uIEFieldLen ) ; + ( pScanReq->uIEFieldLen ) + + pScanReq->num_vendor_oui * sizeof(struct vendor_oui); pMsg = vos_mem_malloc(msgLen); if ( NULL == pMsg ) @@ -5999,6 +6000,28 @@ eHalStatus csrSendMBScanReq( tpAniSirGlobal pMac, tANI_U16 sessionId, vos_mem_copy(pMsg->mac_addr_mask, pScanReq->mac_addr_mask, VOS_MAC_ADDR_SIZE); } + + pMsg->ie_whitelist = pScanReq->ie_whitelist; + if (pMsg->ie_whitelist) + vos_mem_copy(pMsg->probe_req_ie_bitmap, + pScanReq->probe_req_ie_bitmap, + PROBE_REQ_BITMAP_LEN * sizeof(uint32_t)); + pMsg->num_vendor_oui = pScanReq->num_vendor_oui; + pMsg->oui_field_len = pScanReq->num_vendor_oui * + sizeof(struct vendor_oui); + pMsg->oui_field_offset = (tANI_U16)(sizeof( tSirSmeScanReq ) - + sizeof( pMsg->channelList.channelNumber ) + + (sizeof( pMsg->channelList.channelNumber ) * + pScanReq->ChannelInfo.numOfChannels )) + + pScanReq->uIEFieldLen; + + if (pScanReq->num_vendor_oui != 0) + { + vos_mem_copy((tANI_U8 *)pMsg + pMsg->oui_field_offset, + (uint8_t*)(pScanReq->voui), + pMsg->oui_field_len); + } + }while(0); smsLog(pMac, LOG1, FL("domainIdCurrent %s (%d) scanType %s (%d)" "bssType %s (%d), requestType %s(%d)" @@ -6479,6 +6502,7 @@ eHalStatus csrScanCopyRequest(tpAniSirGlobal pMac, tCsrScanRequest *pDstReq, tCs pDstReq->pIEField = NULL; pDstReq->ChannelInfo.ChannelList = NULL; pDstReq->SSIDs.SSIDList = NULL; + pDstReq->voui = NULL; if(pSrcReq->uIEFieldLen == 0) { @@ -6721,6 +6745,35 @@ eHalStatus csrScanCopyRequest(tpAniSirGlobal pMac, tCsrScanRequest *pDstReq, tCs pDstReq->p2pSearch = pSrcReq->p2pSearch; pDstReq->skipDfsChnlInP2pSearch = pSrcReq->skipDfsChnlInP2pSearch; + if (pSrcReq->num_vendor_oui == 0) + { + pDstReq->num_vendor_oui = 0; + pDstReq->voui = NULL; + } + else + { + pDstReq->voui = vos_mem_malloc(pSrcReq->num_vendor_oui * + sizeof(*pDstReq->voui)); + if (NULL == pDstReq->voui) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + + if (HAL_STATUS_SUCCESS(status)) + { + pDstReq->num_vendor_oui = pSrcReq->num_vendor_oui; + vos_mem_copy(pDstReq->voui, + pSrcReq->voui, + pSrcReq->num_vendor_oui * + sizeof(*pDstReq->voui)); + } + else + { + pDstReq->num_vendor_oui = 0; + smsLog(pMac, LOGE, FL("No memory for voui")); + break; + } + } } }while(0); @@ -6755,6 +6808,13 @@ eHalStatus csrScanFreeRequest(tpAniSirGlobal pMac, tCsrScanRequest *pReq) } pReq->SSIDs.numOfSSIDs = 0; + if(pReq->voui) + { + vos_mem_free(pReq->voui); + pReq->voui = NULL; + } + pReq->num_vendor_oui = 0; + return eHAL_STATUS_SUCCESS; } diff --git a/CORE/SME/src/pmc/pmcApi.c b/CORE/SME/src/pmc/pmcApi.c index c1f7653..45313c1 100644 --- a/CORE/SME/src/pmc/pmcApi.c +++ b/CORE/SME/src/pmc/pmcApi.c @@ -2867,14 +2867,17 @@ eHalStatus pmcSetPreferredNetworkList return eHAL_STATUS_FAILURE; } - pRequestBuf = vos_mem_malloc(sizeof(tSirPNOScanReq)); + pRequestBuf = vos_mem_malloc(sizeof(tSirPNOScanReq) + + (pRequest->num_vendor_oui) * + (sizeof(struct vendor_oui))); if (NULL == pRequestBuf) { VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to allocate memory for PNO request", __func__); return eHAL_STATUS_FAILED_ALLOC; } - vos_mem_copy(pRequestBuf, pRequest, sizeof(tSirPNOScanReq)); + vos_mem_copy(pRequestBuf, pRequest, sizeof(tSirPNOScanReq) + + (pRequest->num_vendor_oui) * (sizeof(struct vendor_oui))); /*Must translate the mode first*/ ucDot11Mode = (tANI_U8) csrTranslateToWNICfgDot11Mode(pMac, -- cgit v1.1