From 1f8a9dbac1d16ca4172ddca87a53553792891c29 Mon Sep 17 00:00:00 2001 From: jrior001 Date: Sun, 16 Jul 2017 22:42:20 -0400 Subject: [PATCH] moorefield: bcmdhd update from 4.21.40.327 source release Change-Id: I2218d0aa5a65837bef013c01df5c4ff85c05173c --- drivers/net/wireless/bcmdhd/Kconfig | 8 - drivers/net/wireless/bcmdhd/dhd_common.c | 218 +---------- drivers/net/wireless/bcmdhd/dhd_custom_gpio.c | 22 +- drivers/net/wireless/bcmdhd/dhd_ip.h | 4 +- drivers/net/wireless/bcmdhd/dhd_linux.c | 93 +---- drivers/net/wireless/bcmdhd/dhd_linux.h | 5 +- drivers/net/wireless/bcmdhd/dhd_msgbuf.c | 27 +- drivers/net/wireless/bcmdhd/dhd_pcie.c | 1 - drivers/net/wireless/bcmdhd/dhd_pno.c | 10 +- drivers/net/wireless/bcmdhd/dhd_pno.h | 9 +- drivers/net/wireless/bcmdhd/dhd_wlfc.c | 4 +- drivers/net/wireless/bcmdhd/wl_android.c | 58 ++- drivers/net/wireless/bcmdhd/wl_cfg80211.c | 10 +- drivers/net/wireless/bcmdhd/wl_cfgvendor.c | 362 +++++++++++++----- drivers/net/wireless/bcmdhd/wl_cfgvendor.h | 14 + drivers/net/wireless/bcmdhd/wl_iw.c | 8 + 16 files changed, 404 insertions(+), 449 deletions(-) diff --git a/drivers/net/wireless/bcmdhd/Kconfig b/drivers/net/wireless/bcmdhd/Kconfig index 00371565..bf84d97b 100755 --- a/drivers/net/wireless/bcmdhd/Kconfig +++ b/drivers/net/wireless/bcmdhd/Kconfig @@ -45,14 +45,6 @@ config BCMDHD_NVRAM_PATH ---help--- Path to the calibration file. -config BCMDHD_WEXT - bool "Enable WEXT support" - depends on BCMDHD && CFG80211 = n - select WIRELESS_EXT - select WEXT_PRIV - help - Enables WEXT support - config DHD_USE_STATIC_BUF bool "Enable memory preallocation" depends on BCMDHD diff --git a/drivers/net/wireless/bcmdhd/dhd_common.c b/drivers/net/wireless/bcmdhd/dhd_common.c index 39cb3610..ef9bca10 100755 --- a/drivers/net/wireless/bcmdhd/dhd_common.c +++ b/drivers/net/wireless/bcmdhd/dhd_common.c @@ -82,8 +82,6 @@ int dhd_msg_level = DHD_ERROR_VAL | DHD_MSGTRACE_VAL | DHD_FWLOG_VAL; #else #endif /* WL_WLC_SHIM */ -#include - #ifdef SOFTAP char fw_path2[MOD_PARAM_PATHLEN]; extern bool softap_enabled; @@ -129,7 +127,17 @@ const char dhd_version[] = "\nDongle Host Driver, version " EPI_VERSION_STR "\nC void dhd_set_timer(void *bus, uint wdtick); - +#define CSCAN_COMMAND "CSCAN " +#define CSCAN_TLV_PREFIX 'S' +#define CSCAN_TLV_VERSION 1 +#define CSCAN_TLV_SUBVERSION 0 +#define CSCAN_TLV_TYPE_SSID_IE 'S' +#define CSCAN_TLV_TYPE_CHANNEL_IE 'C' +#define CSCAN_TLV_TYPE_NPROBE_IE 'N' +#define CSCAN_TLV_TYPE_ACTIVE_IE 'A' +#define CSCAN_TLV_TYPE_PASSIVE_IE 'P' +#define CSCAN_TLV_TYPE_HOME_IE 'H' +#define CSCAN_TLV_TYPE_STYPE_IE 'T' /* IOVar table */ enum { @@ -3160,6 +3168,7 @@ int dhd_keep_alive_onoff(dhd_pub_t *dhd) /* * data parsing from ComboScan tlv list */ +#ifdef WL_WIRELESS_EXT int wl_iw_parse_data_tlv(char** list_str, void *dst, int dst_size, const char token, int input_size, int *bytes_left) @@ -3206,208 +3215,7 @@ wl_iw_parse_data_tlv(char** list_str, void *dst, int dst_size, const char token, } return 1; } - -/* - * channel list parsing from cscan tlv list -*/ -int -wl_iw_parse_channel_list_tlv(char** list_str, uint16* channel_list, - int channel_num, int *bytes_left) -{ - char* str; - int idx = 0; - - if ((list_str == NULL) || (*list_str == NULL) ||(bytes_left == NULL) || (*bytes_left < 0)) { - DHD_ERROR(("%s error paramters\n", __FUNCTION__)); - return -1; - } - str = *list_str; - - while (*bytes_left > 0) { - - if (str[0] != CSCAN_TLV_TYPE_CHANNEL_IE) { - *list_str = str; - DHD_TRACE(("End channel=%d left_parse=%d %d\n", idx, *bytes_left, str[0])); - return idx; - } - /* Get proper CSCAN_TLV_TYPE_CHANNEL_IE */ - *bytes_left -= 1; - str += 1; - - if (str[0] == 0) { - /* All channels */ - channel_list[idx] = 0x0; - } - else { - channel_list[idx] = (uint16)str[0]; - DHD_TRACE(("%s channel=%d \n", __FUNCTION__, channel_list[idx])); - } - *bytes_left -= 1; - str += 1; - - if (idx++ > 255) { - DHD_ERROR(("%s Too many channels \n", __FUNCTION__)); - return -1; - } - } - - *list_str = str; - return idx; -} - -/* - * SSIDs list parsing from cscan tlv list - */ -int -wl_iw_parse_ssid_list_tlv(char** list_str, wlc_ssid_ext_t* ssid, int max, int *bytes_left) -{ - char* str; - int idx = 0; - - if ((list_str == NULL) || (*list_str == NULL) || (*bytes_left < 0)) { - DHD_ERROR(("%s error paramters\n", __FUNCTION__)); - return -1; - } - str = *list_str; - while (*bytes_left > 0) { - - if (str[0] != CSCAN_TLV_TYPE_SSID_IE) { - *list_str = str; - DHD_TRACE(("nssid=%d left_parse=%d %d\n", idx, *bytes_left, str[0])); - return idx; - } - - /* Get proper CSCAN_TLV_TYPE_SSID_IE */ - *bytes_left -= 1; - str += 1; - - if (str[0] == 0) { - /* Broadcast SSID */ - ssid[idx].SSID_len = 0; - memset((char*)ssid[idx].SSID, 0x0, DOT11_MAX_SSID_LEN); - *bytes_left -= 1; - str += 1; - - DHD_TRACE(("BROADCAST SCAN left=%d\n", *bytes_left)); - } - else if (str[0] <= DOT11_MAX_SSID_LEN) { - /* Get proper SSID size */ - ssid[idx].SSID_len = str[0]; - *bytes_left -= 1; - str += 1; - - /* Get SSID */ - if (ssid[idx].SSID_len > *bytes_left) { - DHD_ERROR(("%s out of memory range len=%d but left=%d\n", - __FUNCTION__, ssid[idx].SSID_len, *bytes_left)); - return -1; - } - - memcpy((char*)ssid[idx].SSID, str, ssid[idx].SSID_len); - - *bytes_left -= ssid[idx].SSID_len; - str += ssid[idx].SSID_len; - ssid[idx].hidden = TRUE; - - DHD_TRACE(("%s :size=%d left=%d\n", - (char*)ssid[idx].SSID, ssid[idx].SSID_len, *bytes_left)); - } - else { - DHD_ERROR(("### SSID size more that %d\n", str[0])); - return -1; - } - - if (idx++ > max) { - DHD_ERROR(("%s number of SSIDs more that %d\n", __FUNCTION__, idx)); - return -1; - } - } - - *list_str = str; - return idx; -} - -/* Parse a comma-separated list from list_str into ssid array, starting - * at index idx. Max specifies size of the ssid array. Parses ssids - * and returns updated idx; if idx >= max not all fit, the excess have - * not been copied. Returns -1 on empty string, or on ssid too long. - */ -int -wl_iw_parse_ssid_list(char** list_str, wlc_ssid_t* ssid, int idx, int max) -{ - char* str, *ptr; - - if ((list_str == NULL) || (*list_str == NULL)) - return -1; - - for (str = *list_str; str != NULL; str = ptr) { - - /* check for next TAG */ - if (!strncmp(str, GET_CHANNEL, strlen(GET_CHANNEL))) { - *list_str = str + strlen(GET_CHANNEL); - return idx; - } - - if ((ptr = strchr(str, ',')) != NULL) { - *ptr++ = '\0'; - } - - if (strlen(str) > DOT11_MAX_SSID_LEN) { - DHD_ERROR(("ssid <%s> exceeds %d\n", str, DOT11_MAX_SSID_LEN)); - return -1; - } - - if (strlen(str) == 0) - ssid[idx].SSID_len = 0; - - if (idx < max) { - bzero(ssid[idx].SSID, sizeof(ssid[idx].SSID)); - strncpy((char*)ssid[idx].SSID, str, sizeof(ssid[idx].SSID) - 1); - ssid[idx].SSID_len = strlen(str); - } - idx++; - } - return idx; -} - -/* - * Parse channel list from iwpriv CSCAN - */ -int -wl_iw_parse_channel_list(char** list_str, uint16* channel_list, int channel_num) -{ - int num; - int val; - char* str; - char* endptr = NULL; - - if ((list_str == NULL)||(*list_str == NULL)) - return -1; - - str = *list_str; - num = 0; - while (strncmp(str, GET_NPROBE, strlen(GET_NPROBE))) { - val = (int)strtoul(str, &endptr, 0); - if (endptr == str) { - printf("could not parse channel number starting at" - " substring \"%s\" in list:\n%s\n", - str, *list_str); - return -1; - } - str = endptr + strspn(endptr, " ,"); - - if (num == channel_num) { - DHD_ERROR(("too many channels (more than %d) in channel list:\n%s\n", - channel_num, *list_str)); - return -1; - } - - channel_list[num++] = (uint16)val; - } - *list_str = str; - return num; -} - +#endif /* WL_WIRELESS_EXT */ /* Given filename and download type, returns a buffer pointer and length * for download to f/w. Type can be FW or NVRAM. diff --git a/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c b/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c index 6e9fd115..362e4008 100755 --- a/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c +++ b/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c @@ -18,9 +18,9 @@ #include #include -#if defined(WL_WIRELESS_EXT) -#include -#endif +//#if defined(WL_WIRELESS_EXT) +//#include +//#endif #define WL_ERROR(x) printf x #define WL_TRACE(x) @@ -170,13 +170,19 @@ dhd_custom_get_mac_address(void *adapter, unsigned char *buf) } #endif /* GET_CUSTOM_MAC_ENABLE */ -#if !defined(WL_WIRELESS_EXT) struct cntry_locales_custom { - char iso_abbrev[WLC_CNTRY_BUF_SZ]; /* ISO 3166-1 country abbreviation */ - char custom_locale[WLC_CNTRY_BUF_SZ]; /* Custom firmware locale */ - int32 custom_locale_rev; /* Custom local revisin default -1 */ + char iso_abbrev[WLC_CNTRY_BUF_SZ]; + char custom_locale[WLC_CNTRY_BUF_SZ]; + int32 custom_locale_rev; }; -#endif /* WL_WIRELESS_EXT */ + +//#if !defined(WL_WIRELESS_EXT) +//struct cntry_locales_custom { +// char iso_abbrev[WLC_CNTRY_BUF_SZ]; /* ISO 3166-1 country abbreviation */ +// char custom_locale[WLC_CNTRY_BUF_SZ]; /* Custom firmware locale */ +// int32 custom_locale_rev; /* Custom local revisin default -1 */ +//}; +//#endif /* WL_WIRELESS_EXT */ /* Customized Locale table : OPTIONAL feature */ const struct cntry_locales_custom translate_custom_table[] = { diff --git a/drivers/net/wireless/bcmdhd/dhd_ip.h b/drivers/net/wireless/bcmdhd/dhd_ip.h index 15b95a60..9a7e3966 100755 --- a/drivers/net/wireless/bcmdhd/dhd_ip.h +++ b/drivers/net/wireless/bcmdhd/dhd_ip.h @@ -36,8 +36,8 @@ extern pkt_frag_t pkt_frag_info(osl_t *osh, void *p); #define TCPACKSZMAX (TCPACKSZMIN + 100) /* Max number of TCP streams that have own src/dst IP addrs and TCP ports */ -#define TCPACK_INFO_MAXNUM 32 -#define TCPDATA_INFO_MAXNUM 32 +#define TCPACK_INFO_MAXNUM 4 +#define TCPDATA_INFO_MAXNUM 4 #define TCPDATA_PSH_INFO_MAXNUM (8 * TCPDATA_INFO_MAXNUM) #define TCPDATA_INFO_TIMEOUT 5000 /* Remove tcpdata_info if inactive for this time (in ms) */ diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 940f0611..1c28aef1 100755 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -184,6 +184,7 @@ static bool tput_latest_performance_mode = false; inline static void tput_set_performance_mode(bool en) { + //do nothing when tput_check_interval_s=0(disable tput monitor) if(!tput_check_interval_s) return; @@ -385,12 +386,6 @@ print_tainted() } #endif /* LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 15) */ -/* Linux wireless extension support */ -#if defined(WL_WIRELESS_EXT) -#include -extern wl_iw_extra_params_t g_wl_iw_params; -#endif /* defined(WL_WIRELESS_EXT) */ - #if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) #include #endif /* defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) */ @@ -556,9 +551,6 @@ typedef struct dhd_dump { /* Local private structure (extension of pub) */ typedef struct dhd_info { -#if defined(WL_WIRELESS_EXT) - wl_iw_t iw; /* wireless extensions state (must be first) */ -#endif /* defined(WL_WIRELESS_EXT) */ dhd_pub_t pub; dhd_if_t *iflist[DHD_MAX_IFS]; /* for supporting multiple interfaces */ @@ -1451,10 +1443,6 @@ int dhd_monitor_init(void *dhd_pub); int dhd_monitor_uninit(void); -#if defined(WL_WIRELESS_EXT) -struct iw_statistics *dhd_get_wireless_stats(struct net_device *dev); -#endif /* defined(WL_WIRELESS_EXT) */ - static void dhd_dpc(ulong data); /* forward decl */ extern int dhd_wait_pend8021x(struct net_device *dev); @@ -5673,15 +5661,6 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd) goto exit; } -#if defined(WL_WIRELESS_EXT) - /* linux wireless extensions */ - if ((cmd >= SIOCIWFIRST) && (cmd <= SIOCIWLAST)) { - /* may recurse, do NOT lock */ - ret = wl_iw_ioctl(net, ifr, cmd); - goto exit; - } -#endif /* defined(WL_WIRELESS_EXT) */ - #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) if (cmd == SIOCETHTOOL) { ret = dhd_ethtool(dhd, (void*)ifr->ifr_data); @@ -7053,16 +7032,6 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) dhd_monitor_init(&dhd->pub); dhd_state |= DHD_ATTACH_STATE_CFG80211; #endif -#if defined(WL_WIRELESS_EXT) - /* Attach and link in the iw */ - if (!(dhd_state & DHD_ATTACH_STATE_CFG80211)) { - if (wl_iw_attach(net, (void *)&dhd->pub) != 0) { - DHD_ERROR(("wl_iw_attach failed\n")); - goto fail; - } - dhd_state |= DHD_ATTACH_STATE_WL_ATTACH; - } -#endif /* defined(WL_WIRELESS_EXT) */ #ifdef SHOW_LOGTRACE dhd_init_logstrs_array(&dhd->event_data); @@ -9413,15 +9382,6 @@ dhd_register_if(dhd_pub_t *dhdp, int ifidx, bool need_rtnl_lock) net->ethtool_ops = &dhd_ethtool_ops; #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */ -#if defined(WL_WIRELESS_EXT) -#if WIRELESS_EXT < 19 - net->get_wireless_stats = dhd_get_wireless_stats; -#endif /* WIRELESS_EXT < 19 */ -#if WIRELESS_EXT > 12 - net->wireless_handlers = (struct iw_handler_def *)&wl_iw_handler_def; -#endif /* WIRELESS_EXT > 12 */ -#endif /* defined(WL_WIRELESS_EXT) */ - dhd->pub.rxsz = DBUS_RX_BUFFER_SIZE_DHD(net); memcpy(net->dev_addr, temp_addr, ETHER_ADDR_LEN); @@ -9444,9 +9404,6 @@ dhd_register_if(dhd_pub_t *dhdp, int ifidx, bool need_rtnl_lock) printf("Register interface [%s] MAC: "MACDBG"\n\n", net->name, MAC2STRDBG(net->dev_addr)); -#if defined(SOFTAP) && defined(WL_WIRELESS_EXT) && !defined(WL_CFG80211) - wl_iw_iscan_set_scan_broadcast_prep(net, 1); -#endif #if 1 && (defined(BCMPCIE) || (defined(BCMLXSDMMC) && (LINUX_VERSION_CODE >= \ KERNEL_VERSION(2, 6, 27)))) @@ -9600,13 +9557,6 @@ void dhd_detach(dhd_pub_t *dhdp) } #endif /* CONFIG_HAS_EARLYSUSPEND && DHD_USE_EARLYSUSPEND */ -#if defined(WL_WIRELESS_EXT) - if (dhd->dhd_state & DHD_ATTACH_STATE_WL_ATTACH) { - /* Detatch and unlink in the iw */ - wl_iw_detach(); - } -#endif /* defined(WL_WIRELESS_EXT) */ - /* delete all interfaces, start with virtual */ if (dhd->dhd_state & DHD_ATTACH_STATE_ADD_IF) { int i = 1; @@ -10383,26 +10333,6 @@ void dhd_os_prefree(dhd_pub_t *dhdpub, void *addr, uint size) { } -#if defined(WL_WIRELESS_EXT) -struct iw_statistics * -dhd_get_wireless_stats(struct net_device *dev) -{ - int res = 0; - dhd_info_t *dhd = DHD_DEV_INFO(dev); - - if (!dhd->pub.up) { - return NULL; - } - - res = wl_iw_get_wireless_stats(dev, &dhd->iw.wstats); - - if (res == 0) - return &dhd->iw.wstats; - else - return NULL; -} -#endif /* defined(WL_WIRELESS_EXT) */ - static int dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata, uint16 pktlen, wl_event_msg_t *event, void **data) @@ -10420,21 +10350,9 @@ dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata, uint16 pktlen, if (bcmerror != BCME_OK) return (bcmerror); - -#if defined(WL_WIRELESS_EXT) - if (event->bsscfgidx == 0) { - /* - * Wireless ext is on primary interface only - */ - - ASSERT(dhd->iflist[*ifidx] != NULL); - ASSERT(dhd->iflist[*ifidx]->net != NULL); - - if (dhd->iflist[*ifidx]->net) { - wl_iw_event(dhd->iflist[*ifidx]->net, event, *data); - } - } -#endif /* defined(WL_WIRELESS_EXT) */ + + if ((dhd->iflist[*ifidx] == NULL) || (dhd->iflist[*ifidx]->net == NULL)) + return BCME_ERROR; #ifdef WL_CFG80211 ASSERT(dhd->iflist[*ifidx] != NULL); @@ -11233,9 +11151,6 @@ static void dhd_hang_process(void *dhd_info, void *event_info, u8 event) rtnl_lock(); dev_close(dev); rtnl_unlock(); -#if defined(WL_WIRELESS_EXT) - wl_iw_send_priv_event(dev, "HANG"); -#endif #if defined(WL_CFG80211) wl_cfg80211_hang(dev, WLAN_REASON_UNSPECIFIED); #endif diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.h b/drivers/net/wireless/bcmdhd/dhd_linux.h index 73d83142..17828942 100755 --- a/drivers/net/wireless/bcmdhd/dhd_linux.h +++ b/drivers/net/wireless/bcmdhd/dhd_linux.h @@ -25,10 +25,7 @@ #ifdef DHD_WMF #include #endif -/* Linux wireless extension support */ -#if defined(WL_WIRELESS_EXT) -#include -#endif /* defined(WL_WIRELESS_EXT) */ + #if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) #include #endif /* defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) */ diff --git a/drivers/net/wireless/bcmdhd/dhd_msgbuf.c b/drivers/net/wireless/bcmdhd/dhd_msgbuf.c index 6ea552f2..64eba29b 100755 --- a/drivers/net/wireless/bcmdhd/dhd_msgbuf.c +++ b/drivers/net/wireless/bcmdhd/dhd_msgbuf.c @@ -4513,20 +4513,33 @@ static int dhd_msgbuf_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len, uint8 action) { int ret = 0; + uint copylen = 0; DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - /* Respond "bcmerror" and "bcmerrorstr" with local cache */ if (cmd == WLC_GET_VAR && buf) { - if (!strcmp((char *)buf, "bcmerrorstr")) - { - strncpy((char *)buf, bcmerrorstr(dhd->dongle_error), BCME_STRLEN); + if (!len || !*(uint8 *)buf) { + DHD_ERROR(("%s(): Zero length bailing\n", __FUNCTION__)); + ret = BCME_BADARG; goto done; } - else if (!strcmp((char *)buf, "bcmerror")) - { - *(int *)buf = dhd->dongle_error; + + /* Respond "bcmerror" and "bcmerrorstr" with local cache */ + copylen = MIN(len, BCME_STRLEN); + + if ((len >= strlen("bcmerrorstr")) && + (!strcmp((char *)buf, "bcmerrorstr"))) { + + strncpy((char *)buf, bcmerrorstr(dhd->dongle_error), copylen); + *(uint8 *)((uint8 *)buf + (copylen - 1)) = '\0'; + + goto done; + } else if ((len >= strlen("bcmerror")) && + !strcmp((char *)buf, "bcmerror")) { + + *(uint32 *)(uint32 *)buf = dhd->dongle_error; + goto done; } } diff --git a/drivers/net/wireless/bcmdhd/dhd_pcie.c b/drivers/net/wireless/bcmdhd/dhd_pcie.c index 01ad1624..be028a64 100755 --- a/drivers/net/wireless/bcmdhd/dhd_pcie.c +++ b/drivers/net/wireless/bcmdhd/dhd_pcie.c @@ -2846,7 +2846,6 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag) DHD_GENERAL_UNLOCK(bus->dhd, flags); } else { if (bus->intr) { - dhdpcie_bus_intr_disable(bus); dhdpcie_free_irq(bus); } #ifdef BCMPCIE_OOB_HOST_WAKE diff --git a/drivers/net/wireless/bcmdhd/dhd_pno.c b/drivers/net/wireless/bcmdhd/dhd_pno.c index 2d2e2ddd..a6bace51 100755 --- a/drivers/net/wireless/bcmdhd/dhd_pno.c +++ b/drivers/net/wireless/bcmdhd/dhd_pno.c @@ -3556,9 +3556,15 @@ dhd_handle_swc_evt(dhd_pub_t *dhd, const void *event_data, int *send_evt_bytes) return ptr; } - memcpy(change_array, results->list, + if ((params->results_rxed_so_far + results->pkt_count) <= results->total_count) { + memcpy(change_array, results->list, sizeof(wl_pfn_significant_net_t) * results->pkt_count); - params->results_rxed_so_far += results->pkt_count; + params->results_rxed_so_far += results->pkt_count; + } else { + /* In case of spurious event or invalid data send hang event */ + dhd->hang_reason = HANG_REASON_INVALID_EVENT_OR_DATA; + dhd_os_send_hang_message(dhd); + } if (params->results_rxed_so_far == results->total_count) { params->results_rxed_so_far = 0; diff --git a/drivers/net/wireless/bcmdhd/dhd_pno.h b/drivers/net/wireless/bcmdhd/dhd_pno.h index 5e75dfb0..e194ac3c 100755 --- a/drivers/net/wireless/bcmdhd/dhd_pno.h +++ b/drivers/net/wireless/bcmdhd/dhd_pno.h @@ -47,7 +47,10 @@ #ifdef GSCAN_SUPPORT -#define GSCAN_MAX_CH_BUCKETS 8 +#define GSCAN_MAX_CH_BUCKETS 8 +#define GSCAN_MAX_CHANNELS_IN_BUCKET 32 +#define GSCAN_MAX_AP_CACHE_PER_SCAN 32 +#define GSCAN_MAX_AP_CACHE 320 #define GSCAN_BG_BAND_MASK (1 << 0) #define GSCAN_A_BAND_MASK (1 << 1) #define GSCAN_DFS_MASK (1 << 2) @@ -252,7 +255,9 @@ typedef struct dhd_pno_gscan_channel_bucket { uint16 band; uint8 report_flag; uint8 num_channels; - uint16 chan_list[GSCAN_MAX_CH_BUCKETS]; + uint16 repeat; + uint16 bucket_max_multiple; + uint16 chan_list[GSCAN_MAX_CHANNELS_IN_BUCKET]; } dhd_pno_gscan_channel_bucket_t; typedef struct dhd_pno_swc_evt_param { diff --git a/drivers/net/wireless/bcmdhd/dhd_wlfc.c b/drivers/net/wireless/bcmdhd/dhd_wlfc.c index f229181c..fac2146e 100755 --- a/drivers/net/wireless/bcmdhd/dhd_wlfc.c +++ b/drivers/net/wireless/bcmdhd/dhd_wlfc.c @@ -2802,8 +2802,8 @@ _dhd_wlfc_packet_request(dhd_pub_t *dhd, uint8* value) static void _dhd_wlfc_reorderinfo_indicate(uint8 *val, uint8 len, uchar *info_buf, uint *info_len) { - if (info_len) { - if (info_buf && (len <= WLHOST_REORDERDATA_TOTLEN)) { + if (info_buf && (len <= WLHOST_REORDERDATA_TOTLEN)) { + if (info_buf) { bcopy(val, info_buf, len); *info_len = len; } else { diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c index dd799d8a..2749334f 100755 --- a/drivers/net/wireless/bcmdhd/wl_android.c +++ b/drivers/net/wireless/bcmdhd/wl_android.c @@ -438,11 +438,19 @@ static int wl_android_get_rssi(struct net_device *net, char *command, int total_ return -1; if ((ssid.SSID_len == 0) || (ssid.SSID_len > DOT11_MAX_SSID_LEN)) { DHD_ERROR(("%s: wldev_get_ssid failed\n", __FUNCTION__)); + } else if (total_len <= ssid.SSID_len) { + return -ENOMEM; } else { memcpy(command, ssid.SSID, ssid.SSID_len); bytes_written = ssid.SSID_len; } - bytes_written += snprintf(&command[bytes_written], total_len, " rssi %d", scbval.val); + if ((total_len - bytes_written) < (strlen(" rssi -XXX") + 1)) + return -ENOMEM; + + bytes_written += scnprintf(&command[bytes_written], total_len - bytes_written, + " rssi %d", scbval.val); + command[bytes_written] = '\0'; + DHD_TRACE(("%s: command result is %s (%d)\n", __FUNCTION__, command, bytes_written)); return bytes_written; } @@ -775,8 +783,9 @@ wls_parse_batching_cmd(struct net_device *dev, char *command, int total_len) " <> params\n", __FUNCTION__)); goto exit; } - while ((token2 = strsep(&pos2, - PNO_PARAM_CHANNEL_DELIMETER)) != NULL) { + + while ((token2 = strsep(&pos2, PNO_PARAM_CHANNEL_DELIMETER)) + != NULL) { if (token2 == NULL || !*token2) break; if (*token2 == '\0') @@ -787,13 +796,20 @@ wls_parse_batching_cmd(struct net_device *dev, char *command, int total_len) DHD_PNO(("band : %s\n", (*token2 == 'A')? "A" : "B")); } else { + if ((batch_params.nchan >= WL_NUMCHANNELS) || + (i >= WL_NUMCHANNELS)) { + DHD_ERROR(("Too many nchan %d\n", + batch_params.nchan)); + err = BCME_BUFTOOSHORT; + goto exit; + } batch_params.chan_list[i++] = - simple_strtol(token2, NULL, 0); + simple_strtol(token2, NULL, 0); batch_params.nchan++; - DHD_PNO(("channel :%d\n", - batch_params.chan_list[i-1])); + DHD_PNO(("channel: %d\n", + batch_params.chan_list[i-1])); } - } + } } else if (!strncmp(param, PNO_PARAM_RTT, strlen(PNO_PARAM_RTT))) { batch_params.rtt = simple_strtol(value, NULL, 0); DHD_PNO(("rtt : %d\n", batch_params.rtt)); @@ -2748,10 +2764,13 @@ wl_android_set_rps_cpus(struct net_device *dev, char *command, int total_len) int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) { #define PRIVATE_COMMAND_MAX_LEN 8192 +#define PRIVATE_COMMAND_DEF_LEN 4096 + int ret = 0; char *command = NULL; int bytes_written = 0; android_wifi_priv_cmd priv_cmd; + int buf_size = 0; net_os_wake_lock(net); @@ -2760,11 +2779,6 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) goto exit; } - if (!capable(CAP_NET_ADMIN)) { - ret = -EPERM; - goto exit; - } - #ifdef CONFIG_COMPAT if (is_compat_task()) { compat_android_wifi_priv_cmd compat_priv_cmd; @@ -2786,11 +2800,15 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) } } if ((priv_cmd.total_len > PRIVATE_COMMAND_MAX_LEN) || (priv_cmd.total_len < 0)) { - DHD_ERROR(("%s: too long priavte command\n", __FUNCTION__)); + DHD_ERROR(("%s: buf length invalid:%d\n", __FUNCTION__, + priv_cmd.total_len)); ret = -EINVAL; goto exit; } - command = kmalloc((priv_cmd.total_len + 1), GFP_KERNEL); + + buf_size = max(priv_cmd.total_len, PRIVATE_COMMAND_DEF_LEN); + command = kmalloc((buf_size + 1), GFP_KERNEL); + if (!command) { DHD_ERROR(("%s: failed to allocate memory\n", __FUNCTION__)); @@ -3180,19 +3198,19 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) else { DHD_ERROR(("Unknown PRIVATE command %s - ignored\n", command)); - snprintf(command, 3, "OK"); - bytes_written = strlen("OK"); + bytes_written = scnprintf(command, sizeof("FAIL"), "FAIL"); } if (bytes_written >= 0) { if ((bytes_written == 0) && (priv_cmd.total_len > 0)) command[0] = '\0'; if (bytes_written >= priv_cmd.total_len) { - DHD_ERROR(("%s: bytes_written = %d\n", __FUNCTION__, bytes_written)); - bytes_written = priv_cmd.total_len; - } else { - bytes_written++; + DHD_ERROR(("%s: err. bytes_written:%d >= buf_size:%d \n", + __FUNCTION__, bytes_written, buf_size)); + ret = BCME_BUFTOOSHORT; + goto exit; } + bytes_written++; priv_cmd.used_len = bytes_written; if (copy_to_user(priv_cmd.buf, command, bytes_written)) { DHD_ERROR(("%s: failed to copy data to user buffer\n", __FUNCTION__)); diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index fb3d99f6..ead450a4 100755 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -2575,7 +2575,7 @@ wl_run_escan(struct bcm_cfg80211 *cfg, struct net_device *ndev, err = -EINVAL; goto exit; } - + for (i = 0; i < num_chans; i++) { #ifdef WL_HOST_BAND_MGMT @@ -11113,7 +11113,7 @@ wl_notify_pfn_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, WL_ERR(("Data is NULL!\n")); return 0; } - + WL_DBG((">>> PNO Event\n")); ndev = cfgdev_to_wlc_ndev(cfgdev, cfg); @@ -16457,6 +16457,12 @@ wl_cfg80211_add_iw_ie(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bss if (ie_id != DOT11_MNG_INTERWORKING_ID) return BCME_UNSUPPORTED; + /* access network options (1 octet) is the mandatory field */ + if (!data || data_len == 0 || data_len > IW_IES_MAX_BUF_LEN) { + WL_ERR(("wrong data_len:%d\n", data_len)); + return BCME_BADARG; + } + /* Validate the pktflag parameter */ if ((pktflag & ~(VNDR_IE_BEACON_FLAG | VNDR_IE_PRBRSP_FLAG | VNDR_IE_ASSOCRSP_FLAG | VNDR_IE_AUTHRSP_FLAG | diff --git a/drivers/net/wireless/bcmdhd/wl_cfgvendor.c b/drivers/net/wireless/bcmdhd/wl_cfgvendor.c index 52a25cd6..00cfa68e 100755 --- a/drivers/net/wireless/bcmdhd/wl_cfgvendor.c +++ b/drivers/net/wireless/bcmdhd/wl_cfgvendor.c @@ -527,16 +527,106 @@ wl_cfgvendor_enable_full_scan_result(struct wiphy *wiphy, } static int -wl_cfgvendor_set_scan_cfg(struct wiphy *wiphy, - struct wireless_dev *wdev, const void *data, int len) +wl_cfgvendor_set_scan_cfg_bucket(const struct nlattr *prev, + gscan_scan_params_t *scan_param, int num) +{ + struct dhd_pno_gscan_channel_bucket *ch_bucket; + int k = 0; + int type, err = 0, rem; + const struct nlattr *cur, *next; + + nla_for_each_nested(cur, prev, rem) { + type = nla_type(cur); + ch_bucket = scan_param->channel_bucket; + switch (type) { + case GSCAN_ATTRIBUTE_BUCKET_ID: + break; + case GSCAN_ATTRIBUTE_BUCKET_PERIOD: + if (nla_len(cur) != sizeof(uint32)) { + err = -EINVAL; + goto exit; + } + + ch_bucket[num].bucket_freq_multiple = + nla_get_u32(cur) / MSEC_PER_SEC; + break; + case GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS: + if (nla_len(cur) != sizeof(uint32)) { + err = -EINVAL; + goto exit; + } + ch_bucket[num].num_channels = nla_get_u32(cur); + if (ch_bucket[num].num_channels > + GSCAN_MAX_CHANNELS_IN_BUCKET) { + WL_ERR(("channel range:%d,bucket:%d\n", + ch_bucket[num].num_channels, + num)); + err = -EINVAL; + goto exit; + } + break; + case GSCAN_ATTRIBUTE_BUCKET_CHANNELS: + nla_for_each_nested(next, cur, rem) { + if (k >= GSCAN_MAX_CHANNELS_IN_BUCKET) + break; + if (nla_len(next) != sizeof(uint32)) { + err = -EINVAL; + goto exit; + } + ch_bucket[num].chan_list[k] = nla_get_u32(next); + k++; + } + break; + case GSCAN_ATTRIBUTE_BUCKETS_BAND: + if (nla_len(cur) != sizeof(uint32)) { + err = -EINVAL; + goto exit; + } + ch_bucket[num].band = (uint16)nla_get_u32(cur); + break; + case GSCAN_ATTRIBUTE_REPORT_EVENTS: + if (nla_len(cur) != sizeof(uint32)) { + err = -EINVAL; + goto exit; + } + ch_bucket[num].report_flag = (uint8)nla_get_u32(cur); + break; + case GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT: + if (nla_len(cur) != sizeof(uint32)) { + err = -EINVAL; + goto exit; + } + ch_bucket[num].repeat = (uint16)nla_get_u32(cur); + break; + case GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD: + if (nla_len(cur) != sizeof(uint32)) { + err = -EINVAL; + goto exit; + } + ch_bucket[num].bucket_max_multiple = + nla_get_u32(cur) / MSEC_PER_SEC; + break; + default: + WL_ERR(("unknown attr type:%d\n", type)); + err = -EINVAL; + goto exit; + } + } + +exit: + return err; +} + +static int +wl_cfgvendor_set_scan_cfg(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int len) { int err = 0; struct bcm_cfg80211 *cfg = wiphy_priv(wiphy); gscan_scan_params_t *scan_param; int j = 0; - int type, tmp, tmp1, tmp2, k = 0; - const struct nlattr *iter, *iter1, *iter2; - struct dhd_pno_gscan_channel_bucket *ch_bucket; + int type, tmp; + const struct nlattr *iter; scan_param = kzalloc(sizeof(gscan_scan_params_t), GFP_KERNEL); if (!scan_param) { @@ -556,10 +646,25 @@ wl_cfgvendor_set_scan_cfg(struct wiphy *wiphy, switch (type) { case GSCAN_ATTRIBUTE_BASE_PERIOD: - scan_param->scan_fr = nla_get_u32(iter)/1000; + if (nla_len(iter) != sizeof(uint32)) { + err = -EINVAL; + goto exit; + } + scan_param->scan_fr = nla_get_u32(iter)/MSEC_PER_SEC; break; case GSCAN_ATTRIBUTE_NUM_BUCKETS: + if (nla_len(iter) != sizeof(uint32)) { + err = -EINVAL; + goto exit; + } scan_param->nchannel_buckets = nla_get_u32(iter); + if (scan_param->nchannel_buckets >= + GSCAN_MAX_CH_BUCKETS) { + WL_ERR(("ncha_buck out of range %d\n", + scan_param->nchannel_buckets)); + err = -EINVAL; + goto exit; + } break; case GSCAN_ATTRIBUTE_CH_BUCKET_1: case GSCAN_ATTRIBUTE_CH_BUCKET_2: @@ -568,60 +673,29 @@ wl_cfgvendor_set_scan_cfg(struct wiphy *wiphy, case GSCAN_ATTRIBUTE_CH_BUCKET_5: case GSCAN_ATTRIBUTE_CH_BUCKET_6: case GSCAN_ATTRIBUTE_CH_BUCKET_7: - nla_for_each_nested(iter1, iter, tmp1) { - type = nla_type(iter1); - ch_bucket = - scan_param->channel_bucket; - - switch (type) { - case GSCAN_ATTRIBUTE_BUCKET_ID: - break; - case GSCAN_ATTRIBUTE_BUCKET_PERIOD: - ch_bucket[j].bucket_freq_multiple = - nla_get_u32(iter1)/1000; - break; - case GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS: - ch_bucket[j].num_channels = - nla_get_u32(iter1); - break; - case GSCAN_ATTRIBUTE_BUCKET_CHANNELS: - nla_for_each_nested(iter2, iter1, tmp2) { - if (k >= PFN_SWC_RSSI_WINDOW_MAX) - break; - ch_bucket[j].chan_list[k] = - nla_get_u32(iter2); - k++; - } - k = 0; - break; - case GSCAN_ATTRIBUTE_BUCKETS_BAND: - ch_bucket[j].band = (uint16) - nla_get_u32(iter1); - break; - case GSCAN_ATTRIBUTE_REPORT_EVENTS: - ch_bucket[j].report_flag = (uint8) - nla_get_u32(iter1); - break; - default: - WL_ERR(("bucket attribute type error %d\n", - type)); - break; - } + err = wl_cfgvendor_set_scan_cfg_bucket(iter, scan_param, j); + if (err < 0) { + WL_ERR(("set_scan_cfg_buck error:%d\n", err)); + goto exit; } j++; break; default: WL_ERR(("Unknown type %d\n", type)); - break; + err = -EINVAL; + goto exit; } } - if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg), - DHD_PNO_SCAN_CFG_ID, scan_param, 0) < 0) { + err = dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg), + DHD_PNO_SCAN_CFG_ID, scan_param, FALSE); + + if (err < 0) { WL_ERR(("Could not set GSCAN scan cfg\n")); err = -EINVAL; } +exit: kfree(scan_param); return err; @@ -635,13 +709,21 @@ wl_cfgvendor_hotlist_cfg(struct wiphy *wiphy, struct bcm_cfg80211 *cfg = wiphy_priv(wiphy); gscan_hotlist_scan_params_t *hotlist_params; int tmp, tmp1, tmp2, type, j = 0, dummy; - const struct nlattr *outer, *inner, *iter; + const struct nlattr *outer, *inner = NULL, *iter; uint8 flush = 0; struct bssid_t *pbssid; - hotlist_params = (gscan_hotlist_scan_params_t *)kzalloc(len, GFP_KERNEL); + if (len < sizeof(*hotlist_params) || len >= WLC_IOCTL_MAXLEN) { + WL_ERR(("buffer length :%d wrong - bail out.\n", len)); + return -EINVAL; + } + + hotlist_params = kzalloc(sizeof(*hotlist_params) + + (sizeof(struct bssid_t) * (PFN_SWC_MAX_NUM_APS - 1)), + GFP_KERNEL); + if (!hotlist_params) { - WL_ERR(("Cannot Malloc mem to parse config commands size - %d bytes \n", len)); + WL_ERR(("Cannot Malloc memory.\n")); return -ENOMEM; } @@ -650,51 +732,111 @@ wl_cfgvendor_hotlist_cfg(struct wiphy *wiphy, nla_for_each_attr(iter, data, len, tmp2) { type = nla_type(iter); switch (type) { - case GSCAN_ATTRIBUTE_HOTLIST_BSSIDS: - pbssid = hotlist_params->bssid; - nla_for_each_nested(outer, iter, tmp) { - nla_for_each_nested(inner, outer, tmp1) { - type = nla_type(inner); - - switch (type) { - case GSCAN_ATTRIBUTE_BSSID: - memcpy(&(pbssid[j].macaddr), - nla_data(inner), ETHER_ADDR_LEN); - break; - case GSCAN_ATTRIBUTE_RSSI_LOW: - pbssid[j].rssi_reporting_threshold = - (int8) nla_get_u8(inner); - break; - case GSCAN_ATTRIBUTE_RSSI_HIGH: - dummy = (int8) nla_get_u8(inner); - break; - default: - WL_ERR(("ATTR unknown %d\n", - type)); - break; + case GSCAN_ATTRIBUTE_HOTLIST_BSSID_COUNT: + if (nla_len(iter) != sizeof(uint32)) { + WL_DBG(("type:%d length:%d not matching.\n", + type, nla_len(inner))); + err = -EINVAL; + goto exit; + } + hotlist_params->nbssid = (uint16)nla_get_u32(iter); + if ((hotlist_params->nbssid == 0) || + (hotlist_params->nbssid > PFN_SWC_MAX_NUM_APS)) { + WL_ERR(("nbssid:%d exceed limit.\n", + hotlist_params->nbssid)); + err = -EINVAL; + goto exit; + } + break; + case GSCAN_ATTRIBUTE_HOTLIST_BSSIDS: + if (hotlist_params->nbssid == 0) { + WL_ERR(("nbssid not retrieved.\n")); + err = -EINVAL; + goto exit; + } + pbssid = hotlist_params->bssid; + nla_for_each_nested(outer, iter, tmp) { + nla_for_each_nested(inner, outer, tmp1) { + if (j >= hotlist_params->nbssid) + break; + type = nla_type(inner); + + switch (type) { + case GSCAN_ATTRIBUTE_BSSID: + if (nla_len(inner) != sizeof(pbssid[j].macaddr)) { + WL_ERR(("type:%d length:%d not matching.\n", + type, nla_len(inner))); + err = -EINVAL; + goto exit; } + memcpy( + &(pbssid[j].macaddr), + nla_data(inner), + sizeof(pbssid[j].macaddr)); + break; + case GSCAN_ATTRIBUTE_RSSI_LOW: + if (nla_len(inner) != sizeof(uint8)) { + WL_ERR(("type:%d length:%d not matching.\n", + type, nla_len(inner))); + err = -EINVAL; + goto exit; + } + pbssid[j].rssi_reporting_threshold = + (int8)nla_get_u8(inner); + break; + case GSCAN_ATTRIBUTE_RSSI_HIGH: + if (nla_len(inner) != sizeof(uint8)) { + WL_ERR(("type:%d length:%d not matching.\n", + type, nla_len(inner))); + err = -EINVAL; + goto exit; + } + dummy = (int8)nla_get_u8(inner); + break; + default: + WL_ERR(("ATTR unknown %d\n", type)); + err = -EINVAL; + goto exit; } - j++; } - hotlist_params->nbssid = j; - break; - case GSCAN_ATTRIBUTE_HOTLIST_FLUSH: - flush = nla_get_u8(iter); - break; - case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE: - hotlist_params->lost_ap_window = nla_get_u32(iter); - break; - default: - WL_ERR(("Unknown type %d\n", type)); - break; + j++; } - + if (j != hotlist_params->nbssid) { + WL_ERR(("bssid_cnt:%d != nbssid:%d.\n", j, + hotlist_params->nbssid)); + err = -EINVAL; + goto exit; + } + break; + case GSCAN_ATTRIBUTE_HOTLIST_FLUSH: + if (nla_len(iter) != sizeof(uint8)) { + WL_ERR(("type:%d length:%d not matching.\n", + type, nla_len(inner))); + err = -EINVAL; + goto exit; + } + flush = nla_get_u8(iter); + break; + case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE: + if (nla_len(iter) != sizeof(uint32)) { + WL_ERR(("type:%d length:%d not matching.\n", + type, nla_len(inner))); + err = -EINVAL; + goto exit; + } + hotlist_params->lost_ap_window = (uint16)nla_get_u32(iter); + break; + default: + WL_ERR(("Unknown type %d\n", type)); + err = -EINVAL; + goto exit; + } } if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg), DHD_PNO_GEOFENCE_SCAN_CFG_ID, hotlist_params, flush) < 0) { - WL_ERR(("Could not set GSCAN HOTLIST cfg\n")); + WL_ERR(("Could not set GSCAN HOTLIST cfg error: %d\n", err)); err = -EINVAL; goto exit; } @@ -898,6 +1040,7 @@ static int wl_cfgvendor_rtt_set_config(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) { int err = 0, rem, rem1, rem2, type; + int target_cnt; rtt_config_params_t rtt_param; rtt_target_info_t* rtt_target = NULL; const struct nlattr *iter, *iter1, *iter2; @@ -914,19 +1057,33 @@ wl_cfgvendor_rtt_set_config(struct wiphy *wiphy, struct wireless_dev *wdev, goto exit; } memset(&rtt_param, 0, sizeof(rtt_param)); + if (len <= 0) { + WL_ERR(("Length of the nlattr is not valid len : %d\n", len)); + err = BCME_ERROR; + goto exit; + } nla_for_each_attr(iter, data, len, rem) { type = nla_type(iter); switch (type) { case RTT_ATTRIBUTE_TARGET_CNT: - rtt_param.rtt_target_cnt = nla_get_u8(iter); - if (rtt_param.rtt_target_cnt > RTT_MAX_TARGET_CNT) { - WL_ERR(("exceed max target count : %d\n", - rtt_param.rtt_target_cnt)); + target_cnt = nla_get_u8(iter); + if ((target_cnt <= 0) || (target_cnt > RTT_MAX_TARGET_CNT)) { + WL_ERR(("target_cnt is not valid : %d\n", + target_cnt)); err = BCME_RANGE; goto exit; } + rtt_param.rtt_target_cnt = target_cnt; break; case RTT_ATTRIBUTE_TARGET_INFO: + /* Added this variable for safe check to avoid crash + * incase the caller did not respect the order + */ + if (rtt_param.target_info == NULL) { + WL_ERR(("rtt_target_info is NULL\n")); + err = BCME_NOMEM; + goto exit; + } rtt_target = rtt_param.target_info; nla_for_each_nested(iter1, iter, rem1) { nla_for_each_nested(iter2, iter1, rem2) { @@ -1021,22 +1178,31 @@ wl_cfgvendor_rtt_cancel_config(struct wiphy *wiphy, struct wireless_dev *wdev, struct ether_addr *mac_list = NULL, *mac_addr = NULL; struct bcm_cfg80211 *cfg = wiphy_priv(wiphy); + if (len <= 0) { + WL_ERR(("Length of nlattr is not valid len : %d\n", len)); + err = -EINVAL; + goto exit; + } nla_for_each_attr(iter, data, len, rem) { type = nla_type(iter); switch (type) { case RTT_ATTRIBUTE_TARGET_CNT: if (mac_list != NULL) { WL_ERR(("mac_list is not NULL\n")); + err = -EINVAL; goto exit; } target_cnt = nla_get_u8(iter); - mac_list = (struct ether_addr *)kzalloc(target_cnt * ETHER_ADDR_LEN, - GFP_KERNEL); - if (mac_list == NULL) { - WL_ERR(("failed to allocate mem for mac list\n")); - goto exit; + if ((target_cnt > 0) && (target_cnt < RTT_MAX_TARGET_CNT)) { + mac_list = (struct ether_addr *)kzalloc(target_cnt * ETHER_ADDR_LEN, + GFP_KERNEL); + if (mac_list == NULL) { + WL_ERR(("failed to allocate mem for mac list\n")); + err = -EINVAL; + goto exit; + } + mac_addr = &mac_list[0]; } - mac_addr = &mac_list[0]; break; case RTT_ATTRIBUTE_TARGET_MAC: if (mac_addr) { @@ -1044,11 +1210,13 @@ wl_cfgvendor_rtt_cancel_config(struct wiphy *wiphy, struct wireless_dev *wdev, target_cnt_chk++; if (target_cnt_chk > target_cnt) { WL_ERR(("over target count\n")); + err = -EINVAL; goto exit; } break; } else { WL_ERR(("mac_list is NULL\n")); + err = -EINVAL; goto exit; } } diff --git a/drivers/net/wireless/bcmdhd/wl_cfgvendor.h b/drivers/net/wireless/bcmdhd/wl_cfgvendor.h index b74f5168..8c26696a 100755 --- a/drivers/net/wireless/bcmdhd/wl_cfgvendor.h +++ b/drivers/net/wireless/bcmdhd/wl_cfgvendor.h @@ -42,6 +42,14 @@ #define GSCAN_ATTR_SET4 40 #define GSCAN_ATTR_SET5 50 #define GSCAN_ATTR_SET6 60 +#define GSCAN_ATTR_SET7 70 +#define GSCAN_ATTR_SET8 80 +#define GSCAN_ATTR_SET9 90 +#define GSCAN_ATTR_SET10 100 +#define GSCAN_ATTR_SET11 110 +#define GSCAN_ATTR_SET12 120 +#define GSCAN_ATTR_SET13 130 + typedef enum { /* don't use 0 as a valid subcommand */ @@ -142,6 +150,7 @@ enum gscan_attributes { GSCAN_ATTRIBUTE_RSSI_HIGH, GSCAN_ATTRIBUTE_HOSTLIST_BSSID_ELEM, GSCAN_ATTRIBUTE_HOTLIST_FLUSH, + GSCAN_ATTRIBUTE_HOTLIST_BSSID_COUNT, /* remaining reserved for additional attributes */ GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE = GSCAN_ATTR_SET6, @@ -149,6 +158,11 @@ enum gscan_attributes { GSCAN_ATTRIBUTE_MIN_BREACHING, GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS, GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, + + /* Adaptive scan attributes */ + GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT = GSCAN_ATTR_SET12, + GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD, + GSCAN_ATTRIBUTE_MAX }; diff --git a/drivers/net/wireless/bcmdhd/wl_iw.c b/drivers/net/wireless/bcmdhd/wl_iw.c index 3fc34d39..80f9e170 100755 --- a/drivers/net/wireless/bcmdhd/wl_iw.c +++ b/drivers/net/wireless/bcmdhd/wl_iw.c @@ -1780,9 +1780,17 @@ wl_iw_get_essid( ssid.SSID_len = dtoh32(ssid.SSID_len); + /* Max SSID length check */ + if (ssid.SSID_len > IW_ESSID_MAX_SIZE) { + ssid.SSID_len = IW_ESSID_MAX_SIZE; + } + /* Get the current SSID */ memcpy(extra, ssid.SSID, ssid.SSID_len); + /* NULL terminating as length of extra buffer is IW_ESSID_MAX_SIZE ie 32 */ + extra[IW_ESSID_MAX_SIZE] = '\0'; + dwrq->length = ssid.SSID_len; dwrq->flags = 1; /* active */