DivestOS/Patches/Linux_CVEs/CVE-2017-11022/qcacld-2.0/0001.patch
2017-11-07 18:55:10 -05:00

1218 lines
45 KiB
Diff

From 1379bfb6c09ee2ad5969db45c27fb675602b4ed0 Mon Sep 17 00:00:00 2001
From: Rajeev Kumar Sirasanagandla <rsirasan@codeaurora.org>
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