From 8134a0daa58d701f87f3ceda0eb1c1b8378e4b9b Mon Sep 17 00:00:00 2001 From: Greg Goldman Date: Fri, 5 Nov 2010 15:39:20 -0700 Subject: [PATCH] net: wireless: bcm4329: Update to version 4.218.248-12 - Fix crash during Specific Scan handling - Fix potential insmod crash by increase Registration Timeout to 12 sec - Added max time restriction to PNO scan timer - New IWPRIV "AP_STA_DISASSOC" to disassoc STAs in SoftAP mode - Add new setting to SoftAP "AP_SET_CFG" to enable Hidden SSID - Fixs bugs for SoftAP AP_SET_MAC_FLTR iwpriv commnd - Add STAs rssi filed to SoftAP "AP_GET_STA_LIST" IWPRIV commnd Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcm4329/dhd_linux.c | 81 ++-- .../net/wireless/bcm4329/include/epivers.h | 10 +- drivers/net/wireless/bcm4329/wl_iw.c | 368 ++++++++++++------ drivers/net/wireless/bcm4329/wl_iw.h | 23 +- 4 files changed, 314 insertions(+), 168 deletions(-) diff --git a/drivers/net/wireless/bcm4329/dhd_linux.c b/drivers/net/wireless/bcm4329/dhd_linux.c index e95e3b1e0f08..cef803fc179e 100644 --- a/drivers/net/wireless/bcm4329/dhd_linux.c +++ b/drivers/net/wireless/bcm4329/dhd_linux.c @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_linux.c,v 1.65.4.9.2.12.2.104.4.27 2010/10/29 02:31:24 Exp $ + * $Id: dhd_linux.c,v 1.65.4.9.2.12.2.104.4.29 2010/11/04 01:14:41 Exp $ */ #ifdef CONFIG_WIFI_CONTROL_FUNC @@ -280,10 +280,10 @@ typedef struct dhd_info { int wl_count; int wl_packet; - int hang_was_sent; - - struct mutex wl_start_lock; - + int hang_was_sent; /* flag that message was send at least once */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) + struct mutex wl_start_lock; /* mutex when START called to prevent any other Linux calls */ +#endif /* Thread to issue ioctl for multicast */ long sysioc_pid; struct semaphore sysioc_sem; @@ -307,7 +307,7 @@ char nvram_path[MOD_PARAM_PATHLEN]; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) struct semaphore dhd_registration_sem; -#define DHD_REGISTRATION_TIMEOUT 8000 /* msec : allowed time to finished dhd registration */ +#define DHD_REGISTRATION_TIMEOUT 12000 /* msec : allowed time to finished dhd registration */ #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ /* load firmware and/or nvram values from the filesystem */ module_param_string(firmware_path, firmware_path, MOD_PARAM_PATHLEN, 0); @@ -2057,8 +2057,9 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) wake_lock_init(&dhd->wl_wifi, WAKE_LOCK_SUSPEND, "wlan_wake"); wake_lock_init(&dhd->wl_rxwake, WAKE_LOCK_SUSPEND, "wlan_rx_wake"); #endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) mutex_init(&dhd->wl_start_lock); - +#endif /* Link to info module */ dhd->pub.info = dhd; @@ -2926,7 +2927,7 @@ dhd_dev_reset(struct net_device *dev, uint8 flag) /* Turning on watchdog back */ if (!flag) dhd_os_wd_timer(&dhd->pub, dhd_watchdog_ms); - DHD_ERROR(("%s: WLAN OFF DONE:\n", __FUNCTION__)); + DHD_ERROR(("%s: WLAN OFF DONE\n", __FUNCTION__)); return ret; } @@ -3039,6 +3040,40 @@ dhd_dev_get_pno_status(struct net_device *dev) #endif /* PNO_SUPPORT */ +int net_os_send_hang_message(struct net_device *dev) +{ + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); + int ret = 0; + + if (dhd) { + if (!dhd->hang_was_sent) { + dhd->hang_was_sent = 1; + ret = wl_iw_send_priv_event(dev, "HANG"); + } + } + return ret; +} + +void dhd_os_start_lock(dhd_pub_t *pub) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) + dhd_info_t *dhd = (dhd_info_t *)(pub->info); + + if (dhd) + mutex_lock(&dhd->wl_start_lock); +#endif +} + +void dhd_os_start_unlock(dhd_pub_t *pub) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) + dhd_info_t *dhd = (dhd_info_t *)(pub->info); + + if (dhd) + mutex_unlock(&dhd->wl_start_lock); +#endif +} + static int dhd_get_pend_8021x_cnt(dhd_info_t *dhd) { @@ -3220,33 +3255,3 @@ int net_os_wake_unlock(struct net_device *dev) ret = dhd_os_wake_unlock(&dhd->pub); return ret; } - -int net_os_send_hang_message(struct net_device *dev) -{ - dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); - int ret = 0; - - if (dhd) { - if (!dhd->hang_was_sent) { - dhd->hang_was_sent = 1; - ret = wl_iw_send_priv_event(dev, "HANG"); - } - } - return ret; -} - -void dhd_os_start_lock(dhd_pub_t *pub) -{ - dhd_info_t *dhd = (dhd_info_t *)(pub->info); - - if (dhd) - mutex_lock(&dhd->wl_start_lock); -} - -void dhd_os_start_unlock(dhd_pub_t *pub) -{ - dhd_info_t *dhd = (dhd_info_t *)(pub->info); - - if (dhd) - mutex_unlock(&dhd->wl_start_lock); -} diff --git a/drivers/net/wireless/bcm4329/include/epivers.h b/drivers/net/wireless/bcm4329/include/epivers.h index 002aff6897de..9e6942b5ab3e 100644 --- a/drivers/net/wireless/bcm4329/include/epivers.h +++ b/drivers/net/wireless/bcm4329/include/epivers.h @@ -33,16 +33,16 @@ #define EPI_RC_NUMBER 248 -#define EPI_INCREMENTAL_NUMBER 11 +#define EPI_INCREMENTAL_NUMBER 12 #define EPI_BUILD_NUMBER 0 -#define EPI_VERSION 4, 218, 248, 11 +#define EPI_VERSION 4, 218, 248, 12 -#define EPI_VERSION_NUM 0x04daf80b +#define EPI_VERSION_NUM 0x04daf80c -#define EPI_VERSION_STR "4.218.248.11" -#define EPI_ROUTER_VERSION_STR "4.219.248.11" +#define EPI_VERSION_STR "4.218.248.12" +#define EPI_ROUTER_VERSION_STR "4.219.248.12" #endif diff --git a/drivers/net/wireless/bcm4329/wl_iw.c b/drivers/net/wireless/bcm4329/wl_iw.c index 21ccb4b52566..0c34a6375c69 100644 --- a/drivers/net/wireless/bcm4329/wl_iw.c +++ b/drivers/net/wireless/bcm4329/wl_iw.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wl_iw.c,v 1.51.4.9.2.6.4.142.4.28 2010/10/19 22:55:15 Exp $ + * $Id: wl_iw.c,v 1.51.4.9.2.6.4.142.4.45 2010/11/04 21:08:09 Exp $ */ @@ -101,7 +101,7 @@ bool ap_fw_loaded = FALSE; struct net_device *ap_net_dev = NULL; struct semaphore ap_eth_sema; static int wl_iw_set_ap_security(struct net_device *dev, struct ap_profile *ap); -static int wl_iw_softap_deassoc_stations(struct net_device *dev); +static int wl_iw_softap_deassoc_stations(struct net_device *dev, u8 *mac); #endif #define WL_IW_IOCTL_CALL(func_call) \ @@ -1448,8 +1448,8 @@ wl_iw_send_priv_event( int wl_control_wl_start(struct net_device *dev) { - wl_iw_t *iw; int ret = 0; + wl_iw_t *iw; WL_TRACE(("Enter %s \n", __FUNCTION__)); @@ -1459,6 +1459,11 @@ wl_control_wl_start(struct net_device *dev) } iw = *(wl_iw_t **)netdev_priv(dev); + + if (!iw) { + WL_ERROR(("%s: wl is null\n", __FUNCTION__)); + return -1; + } dhd_os_start_lock(iw->pub); if (g_onoff == G_WLAN_SET_OFF) { @@ -1491,8 +1496,8 @@ wl_iw_control_wl_off( struct iw_request_info *info ) { - wl_iw_t *iw; int ret = 0; + wl_iw_t *iw; WL_TRACE(("Enter %s\n", __FUNCTION__)); @@ -1502,6 +1507,10 @@ wl_iw_control_wl_off( } iw = *(wl_iw_t **)netdev_priv(dev); + if (!iw) { + WL_ERROR(("%s: dev is null\n", __FUNCTION__)); + return -1; + } dhd_os_start_lock(iw->pub); #ifdef SOFTAP @@ -1587,7 +1596,7 @@ wl_iw_control_wl_on( static struct ap_profile my_ap; static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap); static int get_assoc_sta_list(struct net_device *dev, char *buf, int len); -static int set_ap_mac_list(struct net_device *dev, char *buf); +static int set_ap_mac_list(struct net_device *dev, void *buf); #define PTYPE_STRING 0 #define PTYPE_INTDEC 1 @@ -1669,9 +1678,11 @@ int init_ap_profile_from_string(char *param_str, struct ap_profile *ap_cfg) ret |= get_parmeter_from_string(&str_ptr, "CHANNEL=", PTYPE_INTDEC, &ap_cfg->channel, 5); - ret |= get_parmeter_from_string(&str_ptr, "PREAMBLE=", PTYPE_INTDEC, &ap_cfg->preamble, 5); + get_parmeter_from_string(&str_ptr, "PREAMBLE=", PTYPE_INTDEC, &ap_cfg->preamble, 5); - ret |= get_parmeter_from_string(&str_ptr, "MAX_SCB=", PTYPE_INTDEC, &ap_cfg->max_scb, 5); + get_parmeter_from_string(&str_ptr, "MAX_SCB=", PTYPE_INTDEC, &ap_cfg->max_scb, 5); + + get_parmeter_from_string(&str_ptr, "HIDDEN=", PTYPE_INTDEC, &ap_cfg->closednet, 5); return ret; } @@ -1688,7 +1699,8 @@ static int iwpriv_set_ap_config(struct net_device *dev, char *extra = NULL; struct ap_profile *ap_cfg = &my_ap; - WL_TRACE(("> Got IWPRIV SET_AP IOCTL: info->cmd:%x, info->flags:%x, u.data:%p, u.len:%d\n", + WL_TRACE(("%s: info->cmd:%x, info->flags:%x, u.data:%p, u.len:%d\n", + __FUNCTION__, info->cmd, info->flags, wrqu->data.pointer, wrqu->data.length)); @@ -1742,52 +1754,86 @@ static int iwpriv_get_assoc_list(struct net_device *dev, char mac_buf[256]; struct maclist *sta_maclist = (struct maclist *)mac_buf; - char mac_lst[256]; + char mac_lst[384]; char *p_mac_str; + char *p_mac_str_end; + + if ((!dev) || (!extra)) { + return -EINVAL; + } + + net_os_wake_lock(dev); WL_TRACE(("\n %s: IWPRIV IOCTL: cmd:%hx, flags:%hx, extra:%p, iwp.len:%d, \ iwp.len:%p, iwp.flags:%x \n", __FUNCTION__, info->cmd, info->flags, \ extra, p_iwrq->data.length, p_iwrq->data.pointer, p_iwrq->data.flags)); - WL_SOFTAP(("extra:%s\n", extra)); - print_buf((u8 *)p_iwrq, 16, 0); - memset(sta_maclist, 0, sizeof(mac_buf)); sta_maclist->count = 8; - WL_TRACE((" net device:%s, buf_sz:%d\n", dev->name, sizeof(mac_buf))); - get_assoc_sta_list(dev, mac_buf, 256); - WL_TRACE((" got %d stations\n", sta_maclist->count)); + WL_SOFTAP(("%s: net device:%s, buf_sz:%d\n", + __FUNCTION__, dev->name, sizeof(mac_buf))); + + if ((ret = get_assoc_sta_list(dev, mac_buf, sizeof(mac_buf))) < 0) { + WL_ERROR(("%s: sta list ioctl error:%d\n", + __FUNCTION__, ret)); + goto func_exit; + } + + WL_SOFTAP(("%s: got %d stations\n", __FUNCTION__, + sta_maclist->count)); memset(mac_lst, 0, sizeof(mac_lst)); p_mac_str = mac_lst; + p_mac_str_end = &mac_lst[sizeof(mac_lst)-1]; for (i = 0; i < 8; i++) { struct ether_addr *id = &sta_maclist->ea[i]; + if (!ETHER_ISNULLADDR(id->octet)) { + scb_val_t scb_val; + int rssi = 0; - WL_SOFTAP(("dhd_drv>> sta_mac[%d] :", i)); - print_buf((unsigned char *)&sta_maclist->ea[i], 6, 0); + bzero(&scb_val, sizeof(scb_val_t)); - p_mac_str += snprintf(p_mac_str, MAX_WX_STRING, - "Mac[%d]=%02X:%02X:%02X:%02X:%02X:%02X\n", i, + if ((p_mac_str_end - p_mac_str) <= 36) { + WL_ERROR(("%s: mac list buf is < 36 for item[%i] item\n", + __FUNCTION__, i)); + break; + } + + p_mac_str += snprintf(p_mac_str, MAX_WX_STRING, + "\nMac[%d]=%02X:%02X:%02X:%02X:%02X:%02X,", i, id->octet[0], id->octet[1], id->octet[2], id->octet[3], id->octet[4], id->octet[5]); + bcopy(id->octet, &scb_val.ea, 6); + ret = dev_wlc_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t)); + if (ret < 0) { + snprintf(p_mac_str, MAX_WX_STRING, "RSSI:ERR"); + WL_ERROR(("%s: RSSI ioctl error:%d\n", + __FUNCTION__, ret)); + break; + } + + rssi = dtoh32(scb_val.val); + p_mac_str += snprintf(p_mac_str, MAX_WX_STRING, + "RSSI:%d", rssi); + } } - p_iwrq->data.length = strlen(mac_lst); + p_iwrq->data.length = strlen(mac_lst) + 1; - WL_TRACE(("u.pointer:%p\n", p_iwrq->data.pointer)); - WL_TRACE(("resulting str:\n%s \n len:%d\n\n", mac_lst, p_iwrq->data.length)); + WL_SOFTAP(("%s: data to user:\n%s\n usr_ptr:%p\n", __FUNCTION__, + mac_lst, p_iwrq->data.pointer)); if (p_iwrq->data.length) { - if (copy_to_user(p_iwrq->data.pointer, mac_lst, p_iwrq->data.length)) { - WL_ERROR(("%s: Can't copy to user\n", __FUNCTION__)); - return -EFAULT; - } + bcopy(mac_lst, extra, p_iwrq->data.length); } +func_exit: + net_os_wake_unlock(dev); + WL_TRACE(("Exited %s \n", __FUNCTION__)); return ret; } @@ -1795,19 +1841,20 @@ static int iwpriv_get_assoc_list(struct net_device *dev, #ifdef SOFTAP +#define MAC_FILT_MAX 8 static int iwpriv_set_mac_filters(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *ext) { - int i, ret = -1; - char *extra = NULL; - u8 macfilt[8][6]; + char * extra = NULL; int mac_cnt = 0; - char sub_cmd[16]; + int mac_mode = 0; + struct ether_addr *p_ea; + struct mac_list_set mflist_set; - WL_TRACE((">>> Got IWPRIV SET_MAC_FILTER IOCTL: info->cmd:%x, \ + WL_SOFTAP((">>> Got IWPRIV SET_MAC_FILTER IOCTL: info->cmd:%x, \ info->flags:%x, u.data:%p, u.len:%d\n", info->cmd, info->flags, wrqu->data.pointer, wrqu->data.length)); @@ -1827,25 +1874,21 @@ static int iwpriv_set_mac_filters(struct net_device *dev, extra[wrqu->data.length] = 0; WL_SOFTAP((" Got parameter string in iw_point:\n %s \n", extra)); - memset(macfilt, 0, sizeof(macfilt)); - memset(sub_cmd, 0, sizeof(sub_cmd)); + memset(&mflist_set, 0, sizeof(mflist_set)); str_ptr = extra; - if (get_parmeter_from_string(&str_ptr, "ASCII_CMD=", PTYPE_STRING, sub_cmd, 15) != 0) { + if (get_parmeter_from_string(&str_ptr, "MAC_MODE=", + PTYPE_INTDEC, &mac_mode, 4) != 0) { + WL_ERROR(("ERROR: 'MAC_MODE=' token is missing\n")); goto exit_proc; } -#define MAC_FILT_MAX 8 - - if (strncmp(sub_cmd, "MAC_FLT_W", strlen("MAC_FLT_W"))) { - WL_ERROR(("ERROR: sub_cmd:%s != 'MAC_FLT_W'!\n", sub_cmd)); - goto exit_proc; - } + p_ea = &mflist_set.mac_list.ea[0]; if (get_parmeter_from_string(&str_ptr, "MAC_CNT=", PTYPE_INTDEC, &mac_cnt, 4) != 0) { - WL_ERROR(("ERROR: MAC_CNT param is missing \n")); + WL_ERROR(("ERROR: 'MAC_CNT=' token param is missing \n")); goto exit_proc; } @@ -1854,19 +1897,23 @@ static int iwpriv_set_mac_filters(struct net_device *dev, goto exit_proc; } - for (i = 0; i < mac_cnt; i++) { + for (i=0; i < mac_cnt; i++) if (get_parmeter_from_string(&str_ptr, "MAC=", - PTYPE_STR_HEX, macfilt[i], 12) != 0) { + PTYPE_STR_HEX, &p_ea[i], 12) != 0) { WL_ERROR(("ERROR: MAC_filter[%d] is missing !\n", i)); goto exit_proc; } - } + WL_SOFTAP(("MAC_MODE=:%d, MAC_CNT=%d, MACs:..\n", mac_mode, mac_cnt)); for (i = 0; i < mac_cnt; i++) { - WL_SOFTAP(("mac_filt[%d]:", i)); - print_buf(macfilt[i], 6, 0); + WL_SOFTAP(("mac_filt[%d]:", i)); + print_buf(&p_ea[i], 6, 0); } + mflist_set.mode = mac_mode; + mflist_set.mac_list.count = mac_cnt; + set_ap_mac_list(dev, &mflist_set); + wrqu->data.pointer = NULL; wrqu->data.length = 0; ret = 0; @@ -1882,8 +1929,44 @@ static int iwpriv_set_mac_filters(struct net_device *dev, } #endif + +#ifdef SOFTAP +static int iwpriv_set_ap_sta_disassoc(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *ext) +{ + int res = 0; + char sta_mac[6] = {0, 0, 0, 0, 0, 0}; + char cmd_buf[256]; + char *str_ptr = cmd_buf; + + WL_SOFTAP((">>%s called\n args: info->cmd:%x," + " info->flags:%x, u.data.p:%p, u.data.len:%d\n", + __FUNCTION__, info->cmd, info->flags, + wrqu->data.pointer, wrqu->data.length)); + + if (wrqu->data.length != 0) { + + if (copy_from_user(cmd_buf, wrqu->data.pointer, wrqu->data.length)) { + return -EFAULT; + } + + if (get_parmeter_from_string(&str_ptr, + "MAC=", PTYPE_STR_HEX, sta_mac, 12) == 0) { + res = wl_iw_softap_deassoc_stations(dev, sta_mac); + } else { + WL_ERROR(("ERROR: STA_MAC= token not found\n")); + } + } + + return res; +} #endif +#endif + + #if WIRELESS_EXT < 13 struct iw_request_info { @@ -3114,7 +3197,7 @@ __u16 *merged_len) mutex_lock(&wl_cache_lock); node = g_ss_cache_ctrl.m_cache_head; for (;node;) { - list_merge = (wl_scan_results_t *)node; + list_merge = (wl_scan_results_t *)&node->buflen; WL_TRACE(("%s: Cached Specific APs list=%d\n", __FUNCTION__, list_merge->count)); if (buflen_from_user - *merged_len > 0) { *merged_len += (__u16) wl_iw_get_scan_prep(list_merge, info, @@ -5607,8 +5690,12 @@ static int iwpriv_set_cscan(struct net_device *dev, struct iw_request_info *info return -1; } + if (iscan->iscan_ex_param_size > WLC_IOCTL_MAXLEN) { + WL_ERROR(("%s wrong ex_param_size %d", \ + __FUNCTION__, iscan->iscan_ex_param_size)); + return -1; + } memset(iscan->iscan_ex_params_p, 0, iscan->iscan_ex_param_size); - ASSERT(iscan->iscan_ex_param_size < WLC_IOCTL_MAXLEN); wl_iw_iscan_prep(&iscan->iscan_ex_params_p->params, NULL); @@ -6001,15 +6088,14 @@ static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap) #ifdef AP_ONLY if (ap_cfg_running) { - wl_iw_softap_deassoc_stations(dev); + wl_iw_softap_deassoc_stations(dev, NULL); ap_cfg_running = FALSE; } -#endif +#endif if (ap_cfg_running == FALSE) { #ifndef AP_ONLY - sema_init(&ap_eth_sema, 0); mpc = 0; @@ -6042,7 +6128,10 @@ static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap) iolen = wl_bssiovar_mkbuf("apsta", bsscfg_index, &apsta_var, sizeof(apsta_var)+4, buf, sizeof(buf), &mkvar_err); - ASSERT(iolen); + + if (iolen <= 0) + goto fail; + if ((res = dev_wlc_ioctl(dev, WLC_SET_VAR, buf, iolen)) < 0) { WL_ERROR(("%s fail to set apsta \n", __FUNCTION__)); goto fail; @@ -6050,6 +6139,15 @@ static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap) WL_TRACE(("\n>in %s: apsta set result: %d \n", __FUNCTION__, res)); #endif + iolen = wl_bssiovar_mkbuf("closednet", + bsscfg_index, &ap->closednet, sizeof(ap->closednet)+4, + buf, sizeof(buf), &mkvar_err); + ASSERT(iolen); + if ((res = dev_wlc_ioctl(dev, WLC_SET_VAR, buf, iolen)) < 0) { + WL_ERROR(("%s failed to set 'closednet'for apsta \n", __FUNCTION__)); + goto fail; + } + updown = 1; if ((res = dev_wlc_ioctl(dev, WLC_UP, &updown, sizeof(updown))) < 0) { WL_ERROR(("%s fail to set apsta \n", __FUNCTION__)); @@ -6063,7 +6161,7 @@ static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap) goto fail; } - res = wl_iw_softap_deassoc_stations(ap_net_dev); + res = wl_iw_softap_deassoc_stations(ap_net_dev, NULL); if ((res = dev_iw_write_cfg1_bss_var(dev, 0)) < 0) { @@ -6167,8 +6265,9 @@ static int wl_iw_set_ap_security(struct net_device *dev, struct ap_profile *ap) WL_SOFTAP(("wl_iw: set ap profile:\n")); WL_SOFTAP((" ssid = '%s'\n", ap->ssid)); WL_SOFTAP((" security = '%s'\n", ap->sec)); - if (ap->key[0] != '\0') + if (ap->key[0] != '\0') { WL_SOFTAP((" key = '%s'\n", ap->key)); + } WL_SOFTAP((" channel = %d\n", ap->channel)); WL_SOFTAP((" max scb = %d\n", ap->max_scb)); @@ -6269,6 +6368,7 @@ static int wl_iw_set_ap_security(struct net_device *dev, struct ap_profile *ap) if (key_len < WSEC_MAX_PSK_LEN) { unsigned char output[2*SHA1HashSize]; char key_str_buf[WSEC_MAX_PSK_LEN+1]; + bzero(output, 2*SHA1HashSize); WL_SOFTAP(("%s: do passhash...\n", __FUNCTION__)); @@ -6324,7 +6424,6 @@ int get_parmeter_from_string( int parm_str_len; char *param_str_begin; char *param_str_end; - char *orig_str = *str_ptr; if ((*str_ptr) && !strncmp(*str_ptr, token, strlen(token))) { @@ -6381,27 +6480,36 @@ int get_parmeter_from_string( return 0; } else { - WL_ERROR(("\n %s: ERROR: can't find token:%s in str:%s \n", - __FUNCTION__, token, orig_str)); + WL_ERROR(("\n %s: No token:%s in str:%s\n", + __FUNCTION__, token, *str_ptr)); return -1; } } - -static int wl_iw_softap_deassoc_stations(struct net_device *dev) +static int wl_iw_softap_deassoc_stations(struct net_device *dev, u8 *mac) { int i; int res = 0; char mac_buf[128] = {0}; - struct maclist *assoc_maclist = (struct maclist *)mac_buf; + char z_mac[6] = {0, 0, 0, 0, 0, 0}; + char *sta_mac; + struct maclist *assoc_maclist = (struct maclist *) mac_buf; + bool deauth_all = false; + + if (mac == NULL) { + deauth_all = true; + sta_mac = z_mac; + } else { + sta_mac = mac; + } memset(assoc_maclist, 0, sizeof(mac_buf)); assoc_maclist->count = 8; res = dev_wlc_ioctl(dev, WLC_GET_ASSOCLIST, assoc_maclist, 128); if (res != 0) { - WL_SOFTAP((" Error:%d in :%s, Couldn't get ASSOC List\n", res, __FUNCTION__)); + WL_SOFTAP(("%s: Error:%d Couldn't get ASSOC List\n", __FUNCTION__, res)); return res; } @@ -6412,18 +6520,19 @@ static int wl_iw_softap_deassoc_stations(struct net_device *dev) scbval.val = htod32(1); bcopy(&assoc_maclist->ea[i], &scbval.ea, ETHER_ADDR_LEN); - WL_SOFTAP(("deauth STA:%d \n", i)); - res |= dev_wlc_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, + if (deauth_all || (memcmp(&scbval.ea, sta_mac, ETHER_ADDR_LEN) == 0)) { + WL_SOFTAP(("%s, deauth STA:%d \n", __FUNCTION__, i)); + res |= dev_wlc_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scbval, sizeof(scb_val_t)); + } } } else { WL_SOFTAP((" STA ASSOC list is empty\n")); } - if (res != 0) - WL_SOFTAP((" Error:%d in :%s\n", res, __FUNCTION__)); - else if (assoc_maclist->count) { - + if (res != 0) { + WL_ERROR(("%s: Error:%d\n", __FUNCTION__, res)); + } else if (assoc_maclist->count) { bcm_mdelay(200); } return res; @@ -6448,9 +6557,9 @@ static int iwpriv_softap_stop(struct net_device *dev, if ((ap_cfg_running == TRUE)) { #ifdef AP_ONLY - wl_iw_softap_deassoc_stations(dev); + wl_iw_softap_deassoc_stations(dev, NULL); #else - wl_iw_softap_deassoc_stations(ap_net_dev); + wl_iw_softap_deassoc_stations(ap_net_dev, NULL); if ((res = dev_iw_write_cfg1_bss_var(dev, 2)) < 0) WL_ERROR(("%s failed to del BSS err = %d", __FUNCTION__, res)); @@ -6604,84 +6713,105 @@ iwpriv_en_ap_bss( static int get_assoc_sta_list(struct net_device *dev, char *buf, int len) { - WL_TRACE(("calling dev_wlc_ioctl(dev:%p, cmd:%d, buf:%p, len:%d)\n", - dev, WLC_GET_ASSOCLIST, buf, len)); + WL_TRACE(("%s: dev_wlc_ioctl(dev:%p, cmd:%d, buf:%p, len:%d)\n", + __FUNCTION__, dev, WLC_GET_ASSOCLIST, buf, len)); - dev_wlc_ioctl(dev, WLC_GET_ASSOCLIST, buf, len); + return dev_wlc_ioctl(dev, WLC_GET_ASSOCLIST, buf, len); - return 0; } +void check_error(int res, const char *msg, const char *func, int line) +{ + if (res != 0) + WL_ERROR(("%s, %d function:%s, line:%d\n", msg, res, func, line)); +} + static int -set_ap_mac_list(struct net_device *dev, char *buf) +set_ap_mac_list(struct net_device *dev, void *buf) { struct mac_list_set *mac_list_set = (struct mac_list_set *)buf; - struct maclist *white_maclist = (struct maclist *)&mac_list_set->white_list; - struct maclist *black_maclist = (struct maclist *)&mac_list_set->black_list; - int mac_mode = mac_list_set->mode; + struct maclist *maclist = (struct maclist *)&mac_list_set->mac_list; int length; int i; + int mac_mode = mac_list_set->mode; + int ioc_res = 0; + ap_macmode = mac_list_set->mode; - ap_macmode = mac_mode; if (mac_mode == MACLIST_MODE_DISABLED) { bzero(&ap_black_list, sizeof(struct mflist)); - dev_wlc_ioctl(dev, WLC_SET_MACMODE, &mac_mode, sizeof(mac_mode)); + ioc_res = dev_wlc_ioctl(dev, WLC_SET_MACMODE, &mac_mode, sizeof(mac_mode)); + WL_SOFTAP(("%s: MAC filtering disabled\n", __FUNCTION__)); } else { + scb_val_t scbval; char mac_buf[256] = {0}; struct maclist *assoc_maclist = (struct maclist *) mac_buf; + bool deny_if_matched = (mac_mode == MACLIST_MODE_DENY); - mac_mode = MACLIST_MODE_ALLOW; - - dev_wlc_ioctl(dev, WLC_SET_MACMODE, &mac_mode, sizeof(mac_mode)); + bcopy(maclist, &ap_black_list, sizeof(ap_black_list)); - length = sizeof(white_maclist->count)+white_maclist->count*ETHER_ADDR_LEN; - dev_wlc_ioctl(dev, WLC_SET_MACLIST, white_maclist, length); - WL_SOFTAP(("White List, length %d:\n", length)); - for (i = 0; i < white_maclist->count; i++) - WL_SOFTAP(("mac %d: %02X:%02X:%02X:%02X:%02X:%02X\n", - i, white_maclist->ea[i].octet[0], white_maclist->ea[i].octet[1], - white_maclist->ea[i].octet[2], - white_maclist->ea[i].octet[3], white_maclist->ea[i].octet[4], - white_maclist->ea[i].octet[5])); + ioc_res = dev_wlc_ioctl(dev, WLC_SET_MACMODE, &mac_mode, sizeof(mac_mode)); + check_error(ioc_res, "ioctl ERROR:", __FUNCTION__, __LINE__); - bcopy(black_maclist, &ap_black_list, sizeof(ap_black_list)); + length = sizeof(maclist->count) + maclist->count*ETHER_ADDR_LEN; + dev_wlc_ioctl(dev, WLC_SET_MACLIST, maclist, length); - WL_SOFTAP(("Black List, size %d:\n", sizeof(ap_black_list))); - for (i = 0; i < ap_black_list.count; i++) + WL_SOFTAP(("%s: applied MAC List, mode:%d, length %d:\n", + __FUNCTION__, mac_mode, length)); + for (i = 0; i < maclist->count; i++) WL_SOFTAP(("mac %d: %02X:%02X:%02X:%02X:%02X:%02X\n", - i, ap_black_list.ea[i].octet[0], ap_black_list.ea[i].octet[1], - ap_black_list.ea[i].octet[2], - ap_black_list.ea[i].octet[3], - ap_black_list.ea[i].octet[4], ap_black_list.ea[i].octet[5])); + i, maclist->ea[i].octet[0], maclist->ea[i].octet[1], \ + maclist->ea[i].octet[2], \ + maclist->ea[i].octet[3], maclist->ea[i].octet[4], \ + maclist->ea[i].octet[5])); + + assoc_maclist->count = 8; + ioc_res = dev_wlc_ioctl(dev, WLC_GET_ASSOCLIST, assoc_maclist, 256); + check_error(ioc_res, "ioctl ERROR:", __FUNCTION__, __LINE__); + WL_SOFTAP((" Cur assoc clients:%d\n", assoc_maclist->count)); - dev_wlc_ioctl(dev, WLC_GET_ASSOCLIST, assoc_maclist, 256); if (assoc_maclist->count) { int j; + for (i = 0; i < assoc_maclist->count; i++) { - for (j = 0; j < white_maclist->count; j++) { - if (!bcmp(&assoc_maclist->ea[i], &white_maclist->ea[j], + + WL_SOFTAP(("\ncheking assoc STA:")); + print_buf(&assoc_maclist->ea[i], 6, 0); + + for (j = 0; j < maclist->count; j++) { + + if (!bcmp(&assoc_maclist->ea[i], &maclist->ea[j], \ ETHER_ADDR_LEN)) { - WL_SOFTAP(("match allow, let it be\n")); + + if (deny_if_matched) { + WL_SOFTAP(("black match," + " do deauth/disassoc \n")); + scbval.val = htod32(1); + bcopy(&assoc_maclist->ea[i], &scbval.ea, \ + ETHER_ADDR_LEN); + ioc_res = dev_wlc_ioctl(dev, + WLC_SCB_DEAUTHENTICATE_FOR_REASON, + &scbval, sizeof(scb_val_t)); + check_error(ioc_res, + "ioctl ERROR:", + __FUNCTION__, __LINE__); + } else { + WL_SOFTAP(("white match, let it be\n")); + } break; } } - if (j == white_maclist->count) { - WL_SOFTAP(("match black, deauth it\n")); - scbval.val = htod32(1); - bcopy(&assoc_maclist->ea[i], &scbval.ea, - ETHER_ADDR_LEN); - dev_wlc_ioctl(dev, - WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scbval, - sizeof(scb_val_t)); - } } + } else { + WL_SOFTAP(("No ASSOC CLIENTS\n")); } - } - return 0; + } + + WL_SOFTAP(("%s iocres:%d\n", __FUNCTION__, ioc_res)); + return ioc_res; } #endif @@ -6996,6 +7126,9 @@ static const iw_handler wl_iw_priv_handler[] = { NULL, (iw_handler)iwpriv_fw_reload, + + NULL, + (iw_handler)iwpriv_set_ap_sta_disassoc, #endif #if defined(CSCAN) @@ -7058,8 +7191,8 @@ static const struct iw_priv_args wl_iw_priv_args[] = { { WL_AP_STA_LIST, - 0, IW_PRIV_TYPE_CHAR | 0, + IW_PRIV_TYPE_CHAR | 1024, "AP_GET_STA_LIST" }, @@ -7097,6 +7230,13 @@ static const struct iw_priv_args wl_iw_priv_args[] = { IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 0, "WL_FW_RELOAD" }, + + { + WL_AP_STA_DISASSOC, + IW_PRIV_TYPE_CHAR | 256, + IW_PRIV_TYPE_CHAR | 0, + "AP_STA_DISASSOC" + }, #endif #if defined(CSCAN) { diff --git a/drivers/net/wireless/bcm4329/wl_iw.h b/drivers/net/wireless/bcm4329/wl_iw.h index 3b45792979af..9fedc839cfb0 100644 --- a/drivers/net/wireless/bcm4329/wl_iw.h +++ b/drivers/net/wireless/bcm4329/wl_iw.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wl_iw.h,v 1.5.34.1.6.36.4.1 2010/09/10 19:24:30 Exp $ + * $Id: wl_iw.h,v 1.5.34.1.6.36.4.12 2010/11/03 03:15:49 Exp $ */ @@ -87,8 +87,9 @@ typedef struct wl_iw_extra_params { #define AP_LPB_CMD (SIOCIWFIRSTPRIV+23) #define WL_AP_STOP (SIOCIWFIRSTPRIV+25) #define WL_FW_RELOAD (SIOCIWFIRSTPRIV+27) -#define WL_COMBO_SCAN (SIOCIWFIRSTPRIV+29) -#define WL_AP_SPARE3 (SIOCIWFIRSTPRIV+31) +#define WL_AP_STA_DISASSOC (SIOCIWFIRSTPRIV+29) +#define WL_COMBO_SCAN (SIOCIWFIRSTPRIV+31) + #define G_SCAN_RESULTS (8*1024) #define WE_ADD_EVENT_FIX 0x80 #define G_WLAN_SET_ON 0 @@ -116,19 +117,18 @@ typedef struct wl_iw { dhd_pub_t * pub; } wl_iw_t; -#define WLC_IW_SS_CACHE_MAXLEN 512 +#define WLC_IW_SS_CACHE_MAXLEN 2048 #define WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN 32 #define WLC_IW_BSS_INFO_MAXLEN \ (WLC_IW_SS_CACHE_MAXLEN - WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN) typedef struct wl_iw_ss_cache { + struct wl_iw_ss_cache *next; + int dirty; uint32 buflen; uint32 version; uint32 count; wl_bss_info_t bss_info[1]; - char dummy[WLC_IW_BSS_INFO_MAXLEN - sizeof(wl_bss_info_t)]; - int dirty; - struct wl_iw_ss_cache *next; } wl_iw_ss_cache_t; typedef struct wl_iw_ss_cache_ctrl { @@ -140,6 +140,7 @@ typedef struct wl_iw_ss_cache_ctrl { uint m_cons_br_scan_cnt; struct timer_list *m_timer; } wl_iw_ss_cache_ctrl_t; + typedef enum broadcast_first_scan { BROADCAST_SCAN_FIRST_IDLE = 0, BROADCAST_SCAN_FIRST_STARTED, @@ -158,12 +159,13 @@ struct ap_profile { uint32 channel; uint32 preamble; uint32 max_scb; + uint32 closednet; }; #define MACLIST_MODE_DISABLED 0 -#define MACLIST_MODE_ENABLED 1 -#define MACLIST_MODE_ALLOW 2 +#define MACLIST_MODE_DENY 1 +#define MACLIST_MODE_ALLOW 2 struct mflist { uint count; struct ether_addr ea[16]; @@ -171,8 +173,7 @@ struct mflist { struct mac_list_set { uint32 mode; - struct mflist white_list; - struct mflist black_list; + struct mflist mac_list; }; #endif -- 2.34.1