int dhd_sel_ant_from_file(dhd_pub_t *dhd) { struct file *fp = NULL; int ret = -1; uint32 ant_val = 0; uint32 btc_mode = 0; uint32 rsdb_mode = 0; char *filepath = ANTINFO; char iovbuf[WLC_IOCTL_SMLEN]; uint chip_id = dhd_bus_chip_id(dhd); /* Check if this chip can support MIMO */ if (chip_id != BCM4324_CHIP_ID && chip_id != BCM4350_CHIP_ID && chip_id != BCM4354_CHIP_ID && chip_id != BCM4356_CHIP_ID && chip_id != BCM43569_CHIP_ID && chip_id != BCM4358_CHIP_ID && chip_id != BCM4359_CHIP_ID && chip_id != BCM4355_CHIP_ID) { DHD_ERROR(("[WIFI_SEC] %s: This chipset does not support MIMO\n", __FUNCTION__)); return ret; } /* Read antenna settings from the file */ fp = filp_open(filepath, O_RDONLY, 0); if (IS_ERR(fp)) { DHD_ERROR(("[WIFI_SEC] %s: File [%s] doesn't exist\n", __FUNCTION__, filepath)); return ret; } else { ret = kernel_read(fp, 0, (char *)&ant_val, 4); if (ret < 0) { DHD_ERROR(("[WIFI_SEC] %s: File read error, ret=%d\n", __FUNCTION__, ret)); filp_close(fp, NULL); return ret; } ant_val = bcm_atoi((char *)&ant_val); DHD_ERROR(("[WIFI_SEC]%s: ANT val = %d\n", __FUNCTION__, ant_val)); filp_close(fp, NULL); /* Check value from the file */ if (ant_val < 1 || ant_val > 3) { DHD_ERROR(("[WIFI_SEC] %s: Invalid value %d read from the file %s\n", __FUNCTION__, ant_val, filepath)); return -1; } } /* bt coex mode off */ if (dhd_get_fw_mode(dhd->info) == DHD_FLAG_MFG_MODE) { bcm_mkiovar("btc_mode", (char *)&btc_mode, 4, iovbuf, sizeof(iovbuf)); ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); if (ret) { DHD_ERROR(("[WIFI_SEC] %s: Fail to execute dhd_wl_ioctl_cmd(): " "btc_mode, ret=%d\n", __FUNCTION__, ret)); return ret; } } /* rsdb mode off */ DHD_ERROR(("[WIFI_SEC] %s: %s the RSDB mode!\n", __FUNCTION__, rsdb_mode ? "Enable" : "Disable")); bcm_mkiovar("rsdb_mode", (char *)&rsdb_mode, 4, iovbuf, sizeof(iovbuf)); ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); if (ret) { DHD_ERROR(("[WIFI_SEC] %s: Fail to execute dhd_wl_ioctl_cmd(): " "rsdb_mode, ret=%d\n", __FUNCTION__, ret)); return ret; } /* Select Antenna */ bcm_mkiovar("txchain", (char *)&ant_val, 4, iovbuf, sizeof(iovbuf)); ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); if (ret) { DHD_ERROR(("[WIFI_SEC] %s: Fail to execute dhd_wl_ioctl_cmd(): txchain, ret=%d\n", __FUNCTION__, ret)); return ret; } bcm_mkiovar("rxchain", (char *)&ant_val, 4, iovbuf, sizeof(iovbuf)); ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); if (ret) { DHD_ERROR(("[WIFI_SEC] %s: Fail to execute dhd_wl_ioctl_cmd(): rxchain, ret=%d\n", __FUNCTION__, ret)); return ret; } return 0; }
bool dhd_tcpack_suppress(dhd_pub_t *dhdp, void *pkt) { uint8 *new_ether_hdr; /* Ethernet header of the new packet */ uint16 new_ether_type; /* Ethernet type of the new packet */ uint8 *new_ip_hdr; /* IP header of the new packet */ uint8 *new_tcp_hdr; /* TCP header of the new packet */ uint32 new_ip_hdr_len; /* IP header length of the new packet */ uint32 cur_framelen; uint32 new_tcp_ack_num; /* TCP acknowledge number of the new packet */ uint16 new_ip_total_len; /* Total length of IP packet for the new packet */ uint32 new_tcp_hdr_len; /* TCP header length of the new packet */ tcpack_sup_module_t *tcpack_sup_mod; tcpack_info_t *tcpack_info_tbl; int i; bool ret = FALSE; bool set_dotxinrx = TRUE; unsigned long flags; if (dhdp->tcpack_sup_mode == TCPACK_SUP_OFF) goto exit; new_ether_hdr = PKTDATA(dhdp->osh, pkt); cur_framelen = PKTLEN(dhdp->osh, pkt); if (cur_framelen < TCPACKSZMIN || cur_framelen > TCPACKSZMAX) { DHD_TRACE(("%s %d: Too short or long length %d to be TCP ACK\n", __FUNCTION__, __LINE__, cur_framelen)); goto exit; } new_ether_type = new_ether_hdr[12] << 8 | new_ether_hdr[13]; if (new_ether_type != ETHER_TYPE_IP) { DHD_TRACE(("%s %d: Not a IP packet 0x%x\n", __FUNCTION__, __LINE__, new_ether_type)); goto exit; } DHD_TRACE(("%s %d: IP pkt! 0x%x\n", __FUNCTION__, __LINE__, new_ether_type)); new_ip_hdr = new_ether_hdr + ETHER_HDR_LEN; cur_framelen -= ETHER_HDR_LEN; ASSERT(cur_framelen >= IPV4_MIN_HEADER_LEN); new_ip_hdr_len = IPV4_HLEN(new_ip_hdr); if (IP_VER(new_ip_hdr) != IP_VER_4 || IPV4_PROT(new_ip_hdr) != IP_PROT_TCP) { DHD_TRACE(("%s %d: Not IPv4 nor TCP! ip ver %d, prot %d\n", __FUNCTION__, __LINE__, IP_VER(new_ip_hdr), IPV4_PROT(new_ip_hdr))); goto exit; } new_tcp_hdr = new_ip_hdr + new_ip_hdr_len; cur_framelen -= new_ip_hdr_len; ASSERT(cur_framelen >= TCP_MIN_HEADER_LEN); DHD_TRACE(("%s %d: TCP pkt!\n", __FUNCTION__, __LINE__)); /* is it an ack ? Allow only ACK flag, not to suppress others. */ if (new_tcp_hdr[TCP_FLAGS_OFFSET] != TCP_FLAG_ACK) { DHD_TRACE(("%s %d: Do not touch TCP flag 0x%x\n", __FUNCTION__, __LINE__, new_tcp_hdr[TCP_FLAGS_OFFSET])); goto exit; } new_ip_total_len = ntoh16_ua(&new_ip_hdr[IPV4_PKTLEN_OFFSET]); new_tcp_hdr_len = 4 * TCP_HDRLEN(new_tcp_hdr[TCP_HLEN_OFFSET]); /* This packet has TCP data, so just send */ if (new_ip_total_len > new_ip_hdr_len + new_tcp_hdr_len) { DHD_TRACE(("%s %d: Do nothing for TCP DATA\n", __FUNCTION__, __LINE__)); goto exit; } ASSERT(new_ip_total_len == new_ip_hdr_len + new_tcp_hdr_len); new_tcp_ack_num = ntoh32_ua(&new_tcp_hdr[TCP_ACK_NUM_OFFSET]); DHD_TRACE(("%s %d: TCP ACK with zero DATA length" " IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR" TCP port %d %d\n", __FUNCTION__, __LINE__, IPV4_ADDR_TO_STR(ntoh32_ua(&new_ip_hdr[IPV4_SRC_IP_OFFSET])), IPV4_ADDR_TO_STR(ntoh32_ua(&new_ip_hdr[IPV4_DEST_IP_OFFSET])), ntoh16_ua(&new_tcp_hdr[TCP_SRC_PORT_OFFSET]), ntoh16_ua(&new_tcp_hdr[TCP_DEST_PORT_OFFSET]))); /* Look for tcp_ack_info that has the same ip src/dst addrs and tcp src/dst ports */ flags = dhd_os_tcpacklock(dhdp); #if defined(DEBUG_COUNTER) && defined(DHDTCPACK_SUP_DBG) counter_printlog(&tack_tbl); tack_tbl.cnt[0]++; #endif /* DEBUG_COUNTER && DHDTCPACK_SUP_DBG */ tcpack_sup_mod = dhdp->tcpack_sup_module; tcpack_info_tbl = tcpack_sup_mod->tcpack_info_tbl; if (!tcpack_sup_mod) { DHD_ERROR(("%s %d: tcpack suppress module NULL!!\n", __FUNCTION__, __LINE__)); ret = BCME_ERROR; dhd_os_tcpackunlock(dhdp, flags); goto exit; } if (dhd_tcpdata_psh_acked(dhdp, new_ip_hdr, new_tcp_hdr, new_tcp_ack_num)) { /* This TCPACK is ACK to TCPDATA PSH pkt, so keep set_dotxinrx TRUE */ #if defined(DEBUG_COUNTER) && defined(DHDTCPACK_SUP_DBG) tack_tbl.cnt[5]++; #endif /* DEBUG_COUNTER && DHDTCPACK_SUP_DBG */ } else set_dotxinrx = FALSE; for (i = 0; i < tcpack_sup_mod->tcpack_info_cnt; i++) { void *oldpkt; /* TCPACK packet that is already in txq or DelayQ */ uint8 *old_ether_hdr, *old_ip_hdr, *old_tcp_hdr; uint32 old_ip_hdr_len, old_tcp_hdr_len; uint32 old_tcpack_num; /* TCP ACK number of old TCPACK packet in Q */ if ((oldpkt = tcpack_info_tbl[i].pkt_in_q) == NULL) { DHD_ERROR(("%s %d: Unexpected error!! cur idx %d, ttl cnt %d\n", __FUNCTION__, __LINE__, i, tcpack_sup_mod->tcpack_info_cnt)); break; } if (PKTDATA(dhdp->osh, oldpkt) == NULL) { DHD_ERROR(("%s %d: oldpkt data NULL!! cur idx %d, ttl cnt %d\n", __FUNCTION__, __LINE__, i, tcpack_sup_mod->tcpack_info_cnt)); break; } old_ether_hdr = tcpack_info_tbl[i].pkt_ether_hdr; old_ip_hdr = old_ether_hdr + ETHER_HDR_LEN; old_ip_hdr_len = IPV4_HLEN(old_ip_hdr); old_tcp_hdr = old_ip_hdr + old_ip_hdr_len; old_tcp_hdr_len = 4 * TCP_HDRLEN(old_tcp_hdr[TCP_HLEN_OFFSET]); DHD_TRACE(("%s %d: oldpkt %p[%d], IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR " TCP port %d %d\n", __FUNCTION__, __LINE__, oldpkt, i, IPV4_ADDR_TO_STR(ntoh32_ua(&old_ip_hdr[IPV4_SRC_IP_OFFSET])), IPV4_ADDR_TO_STR(ntoh32_ua(&old_ip_hdr[IPV4_DEST_IP_OFFSET])), ntoh16_ua(&old_tcp_hdr[TCP_SRC_PORT_OFFSET]), ntoh16_ua(&old_tcp_hdr[TCP_DEST_PORT_OFFSET]))); /* If either of IP address or TCP port number does not match, skip. */ if (memcmp(&new_ip_hdr[IPV4_SRC_IP_OFFSET], &old_ip_hdr[IPV4_SRC_IP_OFFSET], IPV4_ADDR_LEN * 2) || memcmp(&new_tcp_hdr[TCP_SRC_PORT_OFFSET], &old_tcp_hdr[TCP_SRC_PORT_OFFSET], TCP_PORT_LEN * 2)) continue; old_tcpack_num = ntoh32_ua(&old_tcp_hdr[TCP_ACK_NUM_OFFSET]); if (IS_TCPSEQ_GT(new_tcp_ack_num, old_tcpack_num)) { /* New packet has higher TCP ACK number, so it replaces the old packet */ if (new_ip_hdr_len == old_ip_hdr_len && new_tcp_hdr_len == old_tcp_hdr_len) { ASSERT(memcmp(new_ether_hdr, old_ether_hdr, ETHER_HDR_LEN) == 0); bcopy(new_ip_hdr, old_ip_hdr, new_ip_total_len); PKTFREE(dhdp->osh, pkt, FALSE); DHD_TRACE(("%s %d: TCP ACK replace %u -> %u\n", __FUNCTION__, __LINE__, old_tcpack_num, new_tcp_ack_num)); #if defined(DEBUG_COUNTER) && defined(DHDTCPACK_SUP_DBG) tack_tbl.cnt[2]++; #endif /* DEBUG_COUNTER && DHDTCPACK_SUP_DBG */ ret = TRUE; } else { #if defined(DEBUG_COUNTER) && defined(DHDTCPACK_SUP_DBG) tack_tbl.cnt[6]++; #endif /* DEBUG_COUNTER && DHDTCPACK_SUP_DBG */ DHD_TRACE(("%s %d: lenth mismatch %d != %d || %d != %d" " ACK %u -> %u\n", __FUNCTION__, __LINE__, new_ip_hdr_len, old_ip_hdr_len, new_tcp_hdr_len, old_tcp_hdr_len, old_tcpack_num, new_tcp_ack_num)); } } else if (new_tcp_ack_num == old_tcpack_num) { set_dotxinrx = TRUE; /* TCPACK retransmission */ #if defined(DEBUG_COUNTER) && defined(DHDTCPACK_SUP_DBG) tack_tbl.cnt[3]++; #endif /* DEBUG_COUNTER && DHDTCPACK_SUP_DBG */ } else { DHD_TRACE(("%s %d: ACK number reverse old %u(0x%p) new %u(0x%p)\n", __FUNCTION__, __LINE__, old_tcpack_num, oldpkt, new_tcp_ack_num, pkt)); } dhd_os_tcpackunlock(dhdp, flags); goto exit; } if (i == tcpack_sup_mod->tcpack_info_cnt && i < TCPACK_INFO_MAXNUM) { /* No TCPACK packet with the same IP addr and TCP port is found * in tcp_ack_info_tbl. So add this packet to the table. */ DHD_TRACE(("%s %d: Add pkt 0x%p(ether_hdr 0x%p) to tbl[%d]\n", __FUNCTION__, __LINE__, pkt, new_ether_hdr, tcpack_sup_mod->tcpack_info_cnt)); tcpack_info_tbl[tcpack_sup_mod->tcpack_info_cnt].pkt_in_q = pkt; tcpack_info_tbl[tcpack_sup_mod->tcpack_info_cnt].pkt_ether_hdr = new_ether_hdr; tcpack_sup_mod->tcpack_info_cnt++; #if defined(DEBUG_COUNTER) && defined(DHDTCPACK_SUP_DBG) tack_tbl.cnt[1]++; #endif /* DEBUG_COUNTER && DHDTCPACK_SUP_DBG */ } else { ASSERT(i == tcpack_sup_mod->tcpack_info_cnt); DHD_TRACE(("%s %d: No empty tcp ack info tbl\n", __FUNCTION__, __LINE__)); } dhd_os_tcpackunlock(dhdp, flags); exit: /* Unless TCPACK_SUP_DELAYTX, dotxinrx is alwasy TRUE, so no need to set here */ if (dhdp->tcpack_sup_mode == TCPACK_SUP_DELAYTX && set_dotxinrx) dhd_bus_set_dotxinrx(dhdp->bus, TRUE); return ret; }
int wl_host_event(struct dhd_info *dhd, int *ifidx, void *pktdata, wl_event_msg_t *event, void **data_ptr) { /* check whether packet is a BRCM event pkt */ bcm_event_t *pvt_data = (bcm_event_t *)pktdata; char *event_data; uint32 type, status; uint16 flags; int evlen; if (bcmp(BRCM_OUI, &pvt_data->bcm_hdr.oui[0], DOT11_OUI_LEN)) { DHD_ERROR(("%s: mismatched OUI, bailing\n", __FUNCTION__)); return (BCME_ERROR); } /* BRCM event pkt may be unaligned - use xxx_ua to load user_subtype. */ if (ntoh16_ua((void *)&pvt_data->bcm_hdr.usr_subtype) != BCMILCP_BCM_SUBTYPE_EVENT) { DHD_ERROR(("%s: mismatched subtype, bailing\n", __FUNCTION__)); return (BCME_ERROR); } *data_ptr = &pvt_data[1]; event_data = *data_ptr; /* memcpy since BRCM event pkt may be unaligned. */ memcpy(event, &pvt_data->event, sizeof(wl_event_msg_t)); type = ntoh32_ua((void *)&event->event_type); flags = ntoh16_ua((void *)&event->flags); status = ntoh32_ua((void *)&event->status); evlen = ntoh32_ua((void *)&event->datalen) + sizeof(bcm_event_t); switch (type) { case WLC_E_IF: { dhd_if_event_t *ifevent = (dhd_if_event_t *)event_data; DHD_TRACE(("%s: if event\n", __FUNCTION__)); if (ifevent->ifidx > 0 && ifevent->ifidx < DHD_MAX_IFS) { if (ifevent->action == WLC_E_IF_ADD) dhd_add_if(dhd, ifevent->ifidx, NULL, event->ifname, pvt_data->eth.ether_dhost, ifevent->flags, ifevent->bssidx); else dhd_del_if(dhd, ifevent->ifidx); } else { DHD_ERROR(("%s: Invalid ifidx %d for %s\n", __FUNCTION__, ifevent->ifidx, event->ifname)); } if (ifevent->action != WLC_E_IF_ADD) { /* send up the if event: btamp user needs it */ *ifidx = dhd_ifname2idx(dhd, event->ifname); } } /* push up to external supp/auth */ dhd_event(dhd, (char *)pvt_data, evlen, *ifidx); break; #ifdef P2P case WLC_E_NDIS_LINK: break; #endif /* fall through */ /* These are what external supplicant/authenticator wants */ case WLC_E_LINK: case WLC_E_ASSOC_IND: case WLC_E_REASSOC_IND: case WLC_E_DISASSOC_IND: case WLC_E_MIC_ERROR: default: /* Fall through: this should get _everything_ */ *ifidx = dhd_ifname2idx(dhd, event->ifname); /* push up to external supp/auth */ dhd_event(dhd, (char *)pvt_data, evlen, *ifidx); DHD_TRACE(("%s: MAC event %d, flags %x, status %x\n", __FUNCTION__, type, flags, status)); /* put it back to WLC_E_NDIS_LINK */ if (type == WLC_E_NDIS_LINK) { uint32 temp; temp = ntoh32_ua((void *)&event->event_type); DHD_TRACE(("Converted to WLC_E_LINK type %d\n", temp)); temp = ntoh32(WLC_E_NDIS_LINK); memcpy((void *)(&pvt_data->event.event_type), &temp, sizeof(pvt_data->event.event_type)); } break; } #ifdef SHOW_EVENTS wl_show_host_event(event, event_data); #endif /* SHOW_EVENTS */ return (BCME_OK); }
static int wl_android_set_pno_setup(struct net_device *dev, char *command, int total_len) { wlc_ssid_t ssids_local[MAX_PFN_LIST_COUNT]; int res = -1; int nssid = 0; cmd_tlv_t *cmd_tlv_temp; char *str_ptr; int tlv_size_left; int pno_time = 0; int pno_repeat = 0; int pno_freq_expo_max = 0; #ifdef PNO_SET_DEBUG int i; char pno_in_example[] = { 'P', 'N', 'O', 'S', 'E', 'T', 'U', 'P', ' ', 'S', '1', '2', '0', 'S', 0x05, 'd', 'l', 'i', 'n', 'k', 'S', 0x04, 'G', 'O', 'O', 'G', 'T', '0', 'B', 'R', '2', 'M', '2', 0x00 }; #endif /* PNO_SET_DEBUG */ DHD_INFO(("%s: command=%s, len=%d\n", __FUNCTION__, command, total_len)); if (total_len < (strlen(CMD_PNOSETUP_SET) + sizeof(cmd_tlv_t))) { DHD_ERROR(("%s argument=%d less min size\n", __FUNCTION__, total_len)); goto exit_proc; } #ifdef PNO_SET_DEBUG memcpy(command, pno_in_example, sizeof(pno_in_example)); for (i = 0; i < sizeof(pno_in_example); i++) printf("%02X ", command[i]); printf("\n"); total_len = sizeof(pno_in_example); #endif str_ptr = command + strlen(CMD_PNOSETUP_SET); tlv_size_left = total_len - strlen(CMD_PNOSETUP_SET); cmd_tlv_temp = (cmd_tlv_t *)str_ptr; memset(ssids_local, 0, sizeof(ssids_local)); if ((cmd_tlv_temp->prefix == PNO_TLV_PREFIX) && (cmd_tlv_temp->version == PNO_TLV_VERSION) && (cmd_tlv_temp->subver == PNO_TLV_SUBVERSION)) { str_ptr += sizeof(cmd_tlv_t); tlv_size_left -= sizeof(cmd_tlv_t); if ((nssid = wl_iw_parse_ssid_list_tlv(&str_ptr, ssids_local, MAX_PFN_LIST_COUNT, &tlv_size_left)) <= 0) { DHD_ERROR(("SSID is not presented or corrupted ret=%d\n", nssid)); goto exit_proc; } else { if ((str_ptr[0] != PNO_TLV_TYPE_TIME) || (tlv_size_left <= 1)) { DHD_ERROR(("%s scan duration corrupted field size %d\n", __FUNCTION__, tlv_size_left)); goto exit_proc; } str_ptr++; pno_time = simple_strtoul(str_ptr, &str_ptr, 16); DHD_INFO(("%s: pno_time=%d\n", __FUNCTION__, pno_time)); if (str_ptr[0] != 0) { if ((str_ptr[0] != PNO_TLV_FREQ_REPEAT)) { DHD_ERROR(("%s pno repeat : corrupted field\n", __FUNCTION__)); goto exit_proc; } str_ptr++; pno_repeat = simple_strtoul(str_ptr, &str_ptr, 16); DHD_INFO(("%s :got pno_repeat=%d\n", __FUNCTION__, pno_repeat)); if (str_ptr[0] != PNO_TLV_FREQ_EXPO_MAX) { DHD_ERROR(("%s FREQ_EXPO_MAX corrupted field size\n", __FUNCTION__)); goto exit_proc; } str_ptr++; pno_freq_expo_max = simple_strtoul(str_ptr, &str_ptr, 16); DHD_INFO(("%s: pno_freq_expo_max=%d\n", __FUNCTION__, pno_freq_expo_max)); } } } else { DHD_ERROR(("%s get wrong TLV command\n", __FUNCTION__)); goto exit_proc; } res = dhd_dev_pno_set(dev, ssids_local, nssid, pno_time, pno_repeat, pno_freq_expo_max); exit_proc: return res; }
int dhd_tcpack_suppress_set(dhd_pub_t *dhdp, uint8 mode) { int ret = BCME_OK; unsigned long flags; flags = dhd_os_tcpacklock(dhdp); if (dhdp->tcpack_sup_mode == mode) { DHD_ERROR(("%s %d: already set to %d\n", __FUNCTION__, __LINE__, mode)); goto exit; } if (mode >= TCPACK_SUP_LAST_MODE || #ifndef BCMSDIO mode == TCPACK_SUP_DELAYTX || #endif /* !BCMSDIO */ FALSE) { DHD_ERROR(("%s %d: Invalid mode %d\n", __FUNCTION__, __LINE__, mode)); ret = BCME_BADARG; goto exit; } DHD_TRACE(("%s: %d -> %d\n", __FUNCTION__, dhdp->tcpack_sup_mode, mode)); #ifdef BCMSDIO /* Old tcpack_sup_mode is TCPACK_SUP_DELAYTX */ if (dhdp->tcpack_sup_mode == TCPACK_SUP_DELAYTX) { tcpack_sup_module_t *tcpack_sup_mod = dhdp->tcpack_sup_module; /* We won't need tdata_psh_info pool and tcpddata_info_tbl anymore */ _tdata_psh_info_pool_deinit(dhdp, tcpack_sup_mod); tcpack_sup_mod->tcpdata_info_cnt = 0; bzero(tcpack_sup_mod->tcpdata_info_tbl, sizeof(tcpdata_info_t) * TCPDATA_INFO_MAXNUM); /* For half duplex bus interface, tx precedes rx by default */ if (dhdp->bus) dhd_bus_set_dotxinrx(dhdp->bus, TRUE); } #endif dhdp->tcpack_sup_mode = mode; if (mode == TCPACK_SUP_OFF) { ASSERT(dhdp->tcpack_sup_module != NULL); /* Clean up timer/data structure for any remaining/pending packet or timer. */ dhd_tcpack_info_tbl_clean(dhdp); MFREE(dhdp->osh, dhdp->tcpack_sup_module, sizeof(tcpack_sup_module_t)); dhdp->tcpack_sup_module = NULL; goto exit; } if (dhdp->tcpack_sup_module == NULL) { tcpack_sup_module_t *tcpack_sup_mod = MALLOC(dhdp->osh, sizeof(tcpack_sup_module_t)); if (tcpack_sup_mod == NULL) { DHD_ERROR(("%s %d: No MEM\n", __FUNCTION__, __LINE__)); dhdp->tcpack_sup_mode = TCPACK_SUP_OFF; ret = BCME_NOMEM; goto exit; } bzero(tcpack_sup_mod, sizeof(tcpack_sup_module_t)); dhdp->tcpack_sup_module = tcpack_sup_mod; } #ifdef BCMSDIO if (mode == TCPACK_SUP_DELAYTX) { ret = _tdata_psh_info_pool_init(dhdp, dhdp->tcpack_sup_module); if (ret != BCME_OK) DHD_ERROR(("%s %d: pool init fail with %d\n", __FUNCTION__, __LINE__, ret)); else if (dhdp->bus) dhd_bus_set_dotxinrx(dhdp->bus, FALSE); } #endif /* BCMSDIO */ if (mode == TCPACK_SUP_HOLD) { int i; tcpack_sup_module_t *tcpack_sup_mod = (tcpack_sup_module_t *)dhdp->tcpack_sup_module; dhdp->tcpack_sup_ratio = TCPACK_SUPP_RATIO; dhdp->tcpack_sup_delay = TCPACK_DELAY_TIME; for (i = 0; i < TCPACK_INFO_MAXNUM; i++) { tcpack_sup_mod->tcpack_info_tbl[i].dhdp = dhdp; init_timer(&tcpack_sup_mod->tcpack_info_tbl[i].timer); tcpack_sup_mod->tcpack_info_tbl[i].timer.data = (ulong)&tcpack_sup_mod->tcpack_info_tbl[i]; tcpack_sup_mod->tcpack_info_tbl[i].timer.function = dhd_tcpack_send; } } exit: dhd_os_tcpackunlock(dhdp, flags); return ret; }
static int wl_android_set_ap_mac_list(struct net_device *dev, int macmode, struct maclist *maclist) { int i, j, match; int ret = 0; char mac_buf[MAX_NUM_OF_ASSOCLIST * sizeof(struct ether_addr) + sizeof(uint)] = {0}; struct maclist *assoc_maclist = (struct maclist *)mac_buf; /* set filtering mode */ if ((ret = wldev_ioctl(dev, WLC_SET_MACMODE, &macmode, sizeof(macmode), true)) != 0) { DHD_ERROR(("%s : WLC_SET_MACMODE error=%d\n", __FUNCTION__, ret)); return ret; } if (macmode != MACLIST_MODE_DISABLED) { /* set the MAC filter list */ if ((ret = wldev_ioctl(dev, WLC_SET_MACLIST, maclist, sizeof(int) + sizeof(struct ether_addr) * maclist->count, true)) != 0) { DHD_ERROR(("%s : WLC_SET_MACLIST error=%d\n", __FUNCTION__, ret)); return ret; } /* get the current list of associated STAs */ assoc_maclist->count = MAX_NUM_OF_ASSOCLIST; if ((ret = wldev_ioctl(dev, WLC_GET_ASSOCLIST, assoc_maclist, sizeof(mac_buf), false)) != 0) { DHD_ERROR(("%s : WLC_GET_ASSOCLIST error=%d\n", __FUNCTION__, ret)); return ret; } /* do we have any STA associated? */ if (assoc_maclist->count) { /* iterate each associated STA */ for (i = 0; i < assoc_maclist->count; i++) { match = 0; /* compare with each entry */ for (j = 0; j < maclist->count; j++) { DHD_INFO(("%s : associated="MACDBG " list="MACDBG "\n", __FUNCTION__, MAC2STRDBG(assoc_maclist->ea[i].octet), MAC2STRDBG(maclist->ea[j].octet))); if (memcmp(assoc_maclist->ea[i].octet, maclist->ea[j].octet, ETHER_ADDR_LEN) == 0) { match = 1; break; } } /* do conditional deauth */ /* "if not in the allow list" or "if in the deny list" */ if ((macmode == MACLIST_MODE_ALLOW && !match) || (macmode == MACLIST_MODE_DENY && match)) { scb_val_t scbval; scbval.val = htod32(1); memcpy(&scbval.ea, &assoc_maclist->ea[i], ETHER_ADDR_LEN); if ((ret = wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scbval, sizeof(scb_val_t), true)) != 0) DHD_ERROR(("%s WLC_SCB_DEAUTHENTICATE error=%d\n", __FUNCTION__, ret)); } } } } return ret; }
void sec_dhd_config_pm(dhd_pub_t *dhd, uint power_mode) { struct file *fp = NULL; char* filepath = "/data/.psm.info"; char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Set PowerSave mode */ fp = filp_open(filepath, O_RDONLY, 0); if(IS_ERR(fp))// the file is not exist { /* Set PowerSave mode */ dhdcdc_set_ioctl(dhd, 0, WLC_SET_PM, (char *)&power_mode, sizeof(power_mode)); fp = filp_open(filepath, O_RDWR | O_CREAT, 0666); if(IS_ERR(fp)||(fp==NULL)) { DHD_ERROR(("[WIFI] %s: File open error\n", filepath)); } else { char buffer[2] = {1}; if(fp->f_mode & FMODE_WRITE) { sprintf(buffer,"1\n"); fp->f_op->write(fp, (const char *)buffer, sizeof(buffer), &fp->f_pos); } } } else { char buffer[1] = {0}; kernel_read(fp, fp->f_pos, buffer, 1); if(strncmp(buffer, "1",1)==0) { /* Set PowerSave mode */ dhdcdc_set_ioctl(dhd, 0, WLC_SET_PM, (char *)&power_mode, sizeof(power_mode)); } else { /*Disable Power save features for CERTIFICATION*/ power_mode = 0; /* Set PowerSave mode */ dhdcdc_set_ioctl(dhd, 0, WLC_SET_PM, (char *)&power_mode, sizeof(power_mode)); /* Disable MPC */ bcm_mkiovar("mpc", (char *)&power_mode, 4, iovbuf, sizeof(iovbuf)); dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf)); fp = filp_open(filepath, O_RDWR | O_CREAT, 0666); if(IS_ERR(fp)||(fp==NULL)) { DHD_ERROR(("[WIFI] %s: File open error\n", filepath)); } else { char buffer[2] = {1}; if(fp->f_mode & FMODE_WRITE) { sprintf(buffer,"1\n"); fp->f_op->write(fp, (const char *)buffer, sizeof(buffer), &fp->f_pos); } } } } if(fp) filp_close(fp, NULL); }
int dhd_write_macaddr(struct ether_addr *mac) { char *filepath_data = MACINFO; char *filepath_efs = MACINFO_EFS; struct file *fp_mac = NULL; char buf[WRMAC_BUF_SIZE] = {0}; mm_segment_t oldfs = {0}; int ret = -1; int retry_count = 0; startwrite: sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X\n", mac->octet[0], mac->octet[1], mac->octet[2], mac->octet[3], mac->octet[4], mac->octet[5]); /* File will be created /data/.mac.info. */ fp_mac = filp_open(filepath_data, O_RDWR | O_CREAT, 0666); if (IS_ERR(fp_mac)) { DHD_ERROR(("[WIFI_SEC] %s: File open error\n", filepath_data)); return -1; } else { oldfs = get_fs(); set_fs(get_ds()); if (fp_mac->f_mode & FMODE_WRITE) { ret = fp_mac->f_op->write(fp_mac, (const char *)buf, sizeof(buf), &fp_mac->f_pos); if (ret < 0) DHD_ERROR(("[WIFI_SEC] Mac address [%s] Failed to" " write into File: %s\n", buf, filepath_data)); else DHD_INFO(("[WIFI_SEC] Mac address [%s] written" " into File: %s\n", buf, filepath_data)); } set_fs(oldfs); filp_close(fp_mac, NULL); } /* check .mac.info file is 0 byte */ fp_mac = filp_open(filepath_data, O_RDONLY, 0); ret = kernel_read(fp_mac, 0, buf, 18); if ((ret == 0) && (retry_count++ < 3)) { filp_close(fp_mac, NULL); goto startwrite; } filp_close(fp_mac, NULL); /* end of /data/.mac.info */ if (filepath_efs == NULL) { DHD_ERROR(("[WIFI_SEC] %s : no efs filepath", __func__)); return 0; } /* File will be created /efs/wifi/.mac.info. */ fp_mac = filp_open(filepath_efs, O_RDWR | O_CREAT, 0666); if (IS_ERR(fp_mac)) { DHD_ERROR(("[WIFI_SEC] %s: File open error\n", filepath_efs)); return -1; } else { oldfs = get_fs(); set_fs(get_ds()); if (fp_mac->f_mode & FMODE_WRITE) { ret = fp_mac->f_op->write(fp_mac, (const char *)buf, sizeof(buf), &fp_mac->f_pos); if (ret < 0) DHD_ERROR(("[WIFI_SEC] Mac address [%s] Failed to" " write into File: %s\n", buf, filepath_efs)); else DHD_INFO(("[WIFI_SEC] Mac address [%s] written" " into File: %s\n", buf, filepath_efs)); } set_fs(oldfs); filp_close(fp_mac, NULL); } /* check .mac.info file is 0 byte */ fp_mac = filp_open(filepath_efs, O_RDONLY, 0); ret = kernel_read(fp_mac, 0, buf, 18); if ((ret == 0) && (retry_count++ < 3)) { filp_close(fp_mac, NULL); goto startwrite; } filp_close(fp_mac, NULL); return 0; }
int dhd_tcpack_suppress_set(dhd_pub_t *dhdp, uint8 mode) { int ret = BCME_OK; dhd_os_tcpacklock(dhdp); if (dhdp->tcpack_sup_mode == mode) { DHD_ERROR(("%s %d: already set to %d\n", __FUNCTION__, __LINE__, mode)); goto exit; } if (mode > TCPACK_SUP_DELAYTX) { DHD_ERROR(("%s %d: Invalid mode %d\n", __FUNCTION__, __LINE__, mode)); ret = BCME_BADARG; goto exit; } DHD_TRACE(("%s: %d -> %d\n", __FUNCTION__, dhdp->tcpack_sup_mode, mode)); /* Old tcpack_sup_mode is TCPACK_SUP_DELAYTX */ if (dhdp->tcpack_sup_mode == TCPACK_SUP_DELAYTX) { tcpack_sup_module_t *tcpack_sup_mod = dhdp->tcpack_sup_module; /* We won't need tdata_psh_info pool and tcpddata_info_tbl anymore */ _tdata_psh_info_pool_deinit(dhdp, tcpack_sup_mod); tcpack_sup_mod->tcpdata_info_cnt = 0; bzero(tcpack_sup_mod->tcpdata_info_tbl, sizeof(tcpdata_info_t) * TCPDATA_INFO_MAXNUM); /* For half duplex bus interface, tx precedes rx by default */ if (dhdp->bus) dhd_bus_set_dotxinrx(dhdp->bus, TRUE); } dhdp->tcpack_sup_mode = mode; if (mode == TCPACK_SUP_OFF) { ASSERT(dhdp->tcpack_sup_module != NULL); MFREE(dhdp->osh, dhdp->tcpack_sup_module, sizeof(tcpack_sup_module_t)); dhdp->tcpack_sup_module = NULL; goto exit; } if (dhdp->tcpack_sup_module == NULL) { tcpack_sup_module_t *tcpack_sup_mod = MALLOC(dhdp->osh, sizeof(tcpack_sup_module_t)); if (tcpack_sup_mod == NULL) { DHD_ERROR(("%s %d: No MEM\n", __FUNCTION__, __LINE__)); dhdp->tcpack_sup_mode = TCPACK_SUP_OFF; ret = BCME_NOMEM; goto exit; } bzero(tcpack_sup_mod, sizeof(tcpack_sup_module_t)); dhdp->tcpack_sup_module = tcpack_sup_mod; } if (mode == TCPACK_SUP_DELAYTX) { ret = _tdata_psh_info_pool_init(dhdp, dhdp->tcpack_sup_module); if (ret != BCME_OK) DHD_ERROR(("%s %d: pool init fail with %d\n", __FUNCTION__, __LINE__, ret)); else if (dhdp->bus) dhd_bus_set_dotxinrx(dhdp->bus, FALSE); } exit: dhd_os_tcpackunlock(dhdp); return ret; }
int dhd_check_module_cid(dhd_pub_t *dhd) { int ret = -1; unsigned char cis_buf[CIS_BUF_SIZE] = {0}; const char *cidfilepath = CIDINFO; cis_rw_t *cish = (cis_rw_t *)&cis_buf[8]; int idx, max; vid_info_t *cur_info; unsigned char *vid_start = NULL; unsigned char vid_length = 0; #ifdef SUPPORT_MULTIPLE_BOARDTYPE board_info_t *cur_b_info = NULL; board_info_t *vendor_b_info = NULL; unsigned char *btype_start; unsigned char boardtype_len = 0; #endif /* SUPPORT_MULTIPLE_BOARDTYPE */ unsigned char cid_info[MAX_VNAME_LEN + MAX_BNAME_LEN]; bool found = FALSE; #if defined(BCM4334_CHIP) || defined(BCM4335_CHIP) const char *revfilepath = REVINFO; #ifdef BCM4334_CHIP int flag_b3; #else char rev_str[10] = {0}; #endif /* BCM4334_CHIP */ #endif /* BCM4334_CHIP || BCM4335_CHIP */ /* Try reading out from CIS */ cish->source = 0; cish->byteoff = 0; cish->nbytes = sizeof(cis_buf); strcpy(cis_buf, "cisdump"); ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, cis_buf, sizeof(cis_buf), 0, 0); if (ret < 0) { DHD_INFO(("[WIFI_SEC] %s: CIS reading failed, ret=%d\n", __FUNCTION__, ret)); return ret; } DHD_ERROR(("[WIFI_SEC] %s: CIS reading success, ret=%d\n", __FUNCTION__, ret)); #ifdef DUMP_CIS dhd_dump_cis(cis_buf, 48); #endif max = sizeof(cis_buf); idx = find_tuple_from_otp(cis_buf, max, CIS_TUPLE_TAG_VENDOR, &vid_length); if (idx > 0) { found = TRUE; vid_start = &cis_buf[idx]; } if (found) { max = sizeof(vid_info) / sizeof(vid_info_t); for (idx = 0; idx < max; idx++) { cur_info = &vid_info[idx]; #if defined(BCM4358_CHIP) if (cur_info->vid_length == 6 && vid_length == 6) { if (cur_info->vid[0] == vid_start[0] && cur_info->vid[3] == vid_start[3] && cur_info->vid[4] == vid_start[4]) goto check_board_type; } #endif /* BCM4358_CHIP */ if ((cur_info->vid_length == vid_length) && (cur_info->vid_length != 0) && (memcmp(cur_info->vid, vid_start, cur_info->vid_length - 1) == 0)) goto check_board_type; } } /* find default nvram, if exist */ DHD_ERROR(("[WIFI_SEC] %s: cannot find CIS TUPLE set as default\n", __FUNCTION__)); max = sizeof(vid_info) / sizeof(vid_info_t); for (idx = 0; idx < max; idx++) { cur_info = &vid_info[idx]; if (cur_info->vid_length == 0) goto write_cid; } DHD_ERROR(("[WIFI_SEC] %s: cannot find default CID\n", __FUNCTION__)); return -1; check_board_type: #ifdef SUPPORT_MULTIPLE_BOARDTYPE max = sizeof(cis_buf) - 4; for (idx = 0; idx < max; idx++) { if (cis_buf[idx] == CIS_TUPLE_TAG_START && cis_buf[idx + 2] == CIS_TUPLE_TAG_BOARDTYPE) { boardtype_len = cis_buf[idx + 1]; btype_start = &cis_buf[idx + 3]; /* Check buffer overflow */ if (&cis_buf[idx + 1] + boardtype_len <= &cis_buf[CIS_BUF_SIZE - 1]) { DHD_INFO(("[WIFI_SEC] %s: board type found.\n", __FUNCTION__)); break; } else { boardtype_len = 0; } } } if (strcmp(cur_info->vname, "semco") == 0) { vendor_b_info = semco_board_info; max = sizeof(semco_board_info) / sizeof(board_info_t); } else if (strcmp(cur_info->vname, "murata") == 0) { vendor_b_info = murata_board_info; max = sizeof(murata_board_info) / sizeof(board_info_t); } else { max = 0; } if (boardtype_len) { for (idx = 0; idx < max; idx++) { cur_b_info = vendor_b_info; if ((cur_b_info->b_len == boardtype_len) && (cur_b_info->b_len != 0) && (memcmp(cur_b_info->btype, btype_start, cur_b_info->b_len - 1) == 0)) { DHD_INFO(("[WIFI_SEC] %s : board type name : %s\n", __FUNCTION__, cur_b_info->bname)); break; } cur_b_info = NULL; vendor_b_info++; } } #endif /* SUPPORT_MULTIPLE_BOARDTYPE */ write_cid: #ifdef SUPPORT_MULTIPLE_BOARDTYPE if (cur_b_info && cur_b_info->b_len > 0) { strcpy(cid_info, cur_info->vname); strcpy(cid_info + strlen(cur_info->vname), cur_b_info->bname); } else #endif /* SUPPORT_MULTIPLE_BOARDTYPE */ strcpy(cid_info, cur_info->vname); DHD_ERROR(("[WIFI_SEC] CIS MATCH FOUND : %s\n", cid_info)); dhd_write_cid_file(cidfilepath, cid_info, strlen(cid_info)+1); #if defined(BCM4334_CHIP) /* Try reading out from OTP to distinguish B2 or B3 */ memset(cis_buf, 0, sizeof(cis_buf)); cish = (cis_rw_t *)&cis_buf[8]; cish->source = 0; cish->byteoff = 0; cish->nbytes = sizeof(cis_buf); strcpy(cis_buf, "otpdump"); ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, cis_buf, sizeof(cis_buf), 0, 0); if (ret < 0) { DHD_ERROR(("[WIFI_SEC] %s: OTP reading failed, err=%d\n", __FUNCTION__, ret)); return ret; } /* otp 33th character is identifier for 4334B3 */ cis_buf[34] = '\0'; flag_b3 = bcm_atoi(&cis_buf[33]); if (flag_b3 & 0x1) { DHD_ERROR(("[WIFI_SEC] REV MATCH FOUND : 4334B3, %c\n", cis_buf[33])); dhd_write_cid_file(revfilepath, "4334B3", 6); } #endif /* BCM4334_CHIP */ #if defined(BCM4335_CHIP) DHD_TRACE(("[WIFI_SEC] %s: BCM4335 Multiple Revision Check\n", __FUNCTION__)); if (concate_revision(dhd->bus, rev_str, rev_str) < 0) { DHD_ERROR(("[WIFI_SEC] %s: fail to concate revision\n", __FUNCTION__)); ret = -1; } else { if (strstr(rev_str, "_a0")) { DHD_ERROR(("[WIFI_SEC] REV MATCH FOUND : 4335A0\n")); dhd_write_cid_file(revfilepath, "BCM4335A0", 9); } else { DHD_ERROR(("[WIFI_SEC] REV MATCH FOUND : 4335B0\n")); dhd_write_cid_file(revfilepath, "BCM4335B0", 9); } } #endif /* BCM4335_CHIP */ return ret; }
int dhd_check_module_mac(dhd_pub_t *dhd, struct ether_addr *mac) { int ret = -1; unsigned char cis_buf[CIS_BUF_SIZE] = {0}; unsigned char mac_buf[20] = {0}; unsigned char otp_mac_buf[20] = {0}; const char *macfilepath = MACINFO_EFS; /* Try reading out from CIS */ cis_rw_t *cish = (cis_rw_t *)&cis_buf[8]; struct file *fp_mac = NULL; cish->source = 0; cish->byteoff = 0; cish->nbytes = sizeof(cis_buf); strcpy(cis_buf, "cisdump"); ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, cis_buf, sizeof(cis_buf), 0, 0); if (ret < 0) { DHD_INFO(("[WIFI_SEC] %s: CIS reading failed, ret=%d\n", __FUNCTION__, ret)); sprintf(otp_mac_buf, "%02X:%02X:%02X:%02X:%02X:%02X\n", mac->octet[0], mac->octet[1], mac->octet[2], mac->octet[3], mac->octet[4], mac->octet[5]); DHD_ERROR(("[WIFI_SEC] %s: Check module mac by legacy FW : " MACDBG "\n", __FUNCTION__, MAC2STRDBG(mac->octet))); } else { int max, idx, macaddr_idx; #ifdef DUMP_CIS dhd_dump_cis(cis_buf, 48); #endif /* Find a new tuple tag */ max = sizeof(cis_buf) - 8; for (idx = 0; idx < max; idx++) { if (cis_buf[idx] == CIS_TUPLE_TAG_START) { if (cis_buf[idx + 2] == CIS_TUPLE_TAG_MACADDR && cis_buf[idx + 1] == 7) { macaddr_idx = idx + 3; /* found MAC Address tuple */ break; } } } if (idx < max) { sprintf(otp_mac_buf, "%02X:%02X:%02X:%02X:%02X:%02X\n", cis_buf[macaddr_idx], cis_buf[macaddr_idx + 1], cis_buf[macaddr_idx + 2], cis_buf[macaddr_idx + 3], cis_buf[macaddr_idx + 4], cis_buf[macaddr_idx + 5]); DHD_ERROR(("[WIFI_SEC] MAC address is taken from OTP\n")); } else { sprintf(otp_mac_buf, "%02X:%02X:%02X:%02X:%02X:%02X\n", mac->octet[0], mac->octet[1], mac->octet[2], mac->octet[3], mac->octet[4], mac->octet[5]); DHD_ERROR(("[WIFI_SEC] %s: Cannot find MAC address info from OTP," " Check module mac by initial value: " MACDBG "\n", __FUNCTION__, MAC2STRDBG(mac->octet))); } } fp_mac = filp_open(macfilepath, O_RDONLY, 0); if (!IS_ERR(fp_mac)) { DHD_ERROR(("[WIFI_SEC] Check Mac address in .mac.info \n")); kernel_read(fp_mac, fp_mac->f_pos, mac_buf, sizeof(mac_buf)); filp_close(fp_mac, NULL); if (strncmp(mac_buf, otp_mac_buf, 17) != 0) { DHD_ERROR(("[WIFI_SEC] file MAC is wrong. Write OTP MAC in .mac.info \n")); dhd_write_mac_file(macfilepath, otp_mac_buf, sizeof(otp_mac_buf)); } } return ret; }
int dhd_read_macaddr(struct dhd_info *dhd, struct ether_addr *mac) { struct file *fp = NULL; char macbuffer[18] = {0}; mm_segment_t oldfs = {0}; char randommac[3] = {0}; char buf[18] = {0}; char *filepath_efs = MACINFO_EFS; int ret = 0; fp = filp_open(filepath_efs, O_RDONLY, 0); if (IS_ERR(fp)) { start_readmac: /* File Doesn't Exist. Create and write mac addr. */ fp = filp_open(filepath_efs, O_RDWR | O_CREAT, 0666); if (IS_ERR(fp)) { DHD_ERROR(("[WIFI_SEC] %s: File open error\n", filepath_efs)); return -1; } oldfs = get_fs(); set_fs(get_ds()); /* Generating the Random Bytes for 3 last octects of the MAC address */ get_random_bytes(randommac, 3); sprintf(macbuffer, "%02X:%02X:%02X:%02X:%02X:%02X\n", 0x00, 0x12, 0x34, randommac[0], randommac[1], randommac[2]); DHD_ERROR(("[WIFI_SEC] The Random Generated MAC ID: %s\n", macbuffer)); if (fp->f_mode & FMODE_WRITE) { ret = fp->f_op->write(fp, (const char *)macbuffer, sizeof(macbuffer), &fp->f_pos); if (ret < 0) DHD_ERROR(("[WIFI_SEC] MAC address [%s] Failed to write into File:" " %s\n", macbuffer, filepath_efs)); else DHD_ERROR(("[WIFI_SEC] MAC address [%s] written into File: %s\n", macbuffer, filepath_efs)); } set_fs(oldfs); /* Reading the MAC Address from .mac.info file ( the existed file or just created file) */ ret = kernel_read(fp, 0, buf, 18); } else { /* Reading the MAC Address from .mac.info file( the existed file or just created file) */ ret = kernel_read(fp, 0, buf, 18); /* to prevent abnormal string display * when mac address is displayed on the screen. */ buf[17] = '\0'; if (strncmp(buf, "00:00:00:00:00:00", 17) < 1) { DHD_ERROR(("[WIFI_SEC] goto start_readmac \r\n")); filp_close(fp, NULL); goto start_readmac; } } if (ret) sscanf(buf, "%02X:%02X:%02X:%02X:%02X:%02X", (unsigned int *)&(mac->octet[0]), (unsigned int *)&(mac->octet[1]), (unsigned int *)&(mac->octet[2]), (unsigned int *)&(mac->octet[3]), (unsigned int *)&(mac->octet[4]), (unsigned int *)&(mac->octet[5])); else DHD_ERROR(("[WIFI_SEC] dhd_bus_start: Reading from the '%s' returns 0 bytes\n", filepath_efs)); if (fp) filp_close(fp, NULL); /* Writing Newly generated MAC ID to the Dongle */ if (_dhd_set_mac_address(dhd, 0, mac) == 0) DHD_INFO(("[WIFI_SEC] dhd_bus_start: MACID is overwritten\n")); else DHD_ERROR(("[WIFI_SEC] dhd_bus_start: _dhd_set_mac_address() failed\n")); return 0; }
uint32 sec_save_wlinfo(char *firm_ver, char *dhd_ver, char *nvram_p) { struct file *fp = NULL; struct file *nvfp = NULL; char *filepath = WIFIVERINFO; int min_len, str_len = 0; int ret = 0; char* nvram_buf; char temp_buf[256]; DHD_TRACE(("[WIFI_SEC] %s: Entered.\n", __FUNCTION__)); DHD_INFO(("[WIFI_SEC] firmware version : %s\n", firm_ver)); DHD_INFO(("[WIFI_SEC] dhd driver version : %s\n", dhd_ver)); DHD_INFO(("[WIFI_SEC] nvram path : %s\n", nvram_p)); memset(version_info, 0, sizeof(version_info)); if (strlen(dhd_ver)) { min_len = min(strlen(dhd_ver), max_len(temp_buf, DHD_PREFIX)); min_len += strlen(DHD_PREFIX) + 3; DHD_INFO(("[WIFI_SEC] DHD ver length : %d\n", min_len)); snprintf(version_info+str_len, min_len, DHD_PREFIX " %s\n", dhd_ver); str_len = strlen(version_info); DHD_INFO(("[WIFI_SEC] Driver version_info len : %d\n", str_len)); DHD_INFO(("[WIFI_SEC] Driver version_info : %s\n", version_info)); } else { DHD_ERROR(("[WIFI_SEC] Driver version is missing.\n")); } if (strlen(firm_ver)) { min_len = min(strlen(firm_ver), max_len(temp_buf, FIRM_PREFIX)); min_len += strlen(FIRM_PREFIX) + 3; DHD_INFO(("[WIFI_SEC] firmware ver length : %d\n", min_len)); snprintf(version_info+str_len, min_len, FIRM_PREFIX " %s\n", firm_ver); str_len = strlen(version_info); DHD_INFO(("[WIFI_SEC] Firmware version_info len : %d\n", str_len)); DHD_INFO(("[WIFI_SEC] Firmware version_info : %s\n", version_info)); } else { DHD_ERROR(("[WIFI_SEC] Firmware version is missing.\n")); } if (nvram_p) { memset(temp_buf, 0, sizeof(temp_buf)); nvfp = filp_open(nvram_p, O_RDONLY, 0); if (IS_ERR(nvfp) || (nvfp == NULL)) { DHD_ERROR(("[WIFI_SEC] %s: Nvarm File open failed.\n", __FUNCTION__)); return -1; } else { ret = kernel_read(nvfp, nvfp->f_pos, temp_buf, sizeof(temp_buf)); filp_close(nvfp, NULL); } if (strlen(temp_buf)) { nvram_buf = temp_buf; bcmstrtok(&nvram_buf, "\n", 0); DHD_INFO(("[WIFI_SEC] nvram tolkening : %s(%zu) \n", temp_buf, strlen(temp_buf))); snprintf(version_info+str_len, tstr_len(temp_buf, NV_PREFIX), NV_PREFIX " %s\n", temp_buf); str_len = strlen(version_info); DHD_INFO(("[WIFI_SEC] NVRAM version_info : %s\n", version_info)); DHD_INFO(("[WIFI_SEC] NVRAM version_info len : %d, nvram len : %zu\n", str_len, strlen(temp_buf))); } else { DHD_ERROR(("[WIFI_SEC] NVRAM info is missing.\n")); } } else { DHD_ERROR(("[WIFI_SEC] Not exist nvram path\n")); } DHD_INFO(("[WIFI_SEC] version_info : %s, strlen : %zu\n", version_info, strlen(version_info))); fp = filp_open(filepath, O_RDONLY, 0); if (IS_ERR(fp) || (fp == NULL)) { DHD_ERROR(("[WIFI_SEC] %s: .wifiver.info File open failed.\n", __FUNCTION__)); } else { memset(version_old_info, 0, sizeof(version_old_info)); ret = kernel_read(fp, fp->f_pos, version_old_info, sizeof(version_info)); filp_close(fp, NULL); DHD_INFO(("[WIFI_SEC] kernel_read ret : %d.\n", ret)); if (strcmp(version_info, version_old_info) == 0) { DHD_ERROR(("[WIFI_SEC] .wifiver.info already saved.\n")); return 0; } } fp = filp_open(filepath, O_RDWR | O_CREAT, 0664); if (IS_ERR(fp) || (fp == NULL)) { DHD_ERROR(("[WIFI_SEC] %s: .wifiver.info File open failed.\n", __FUNCTION__)); } else { ret = write_filesystem(fp, fp->f_pos, version_info, sizeof(version_info)); DHD_INFO(("[WIFI_SEC] sec_save_wlinfo done. ret : %d\n", ret)); DHD_ERROR(("[WIFI_SEC] save .wifiver.info file.\n")); filp_close(fp, NULL); } return ret; }
int sec_get_param_wfa_cert(dhd_pub_t *dhd, int mode, uint* read_val) { struct file *fp = NULL; char *filepath = NULL; int val = 0; if (!dhd || (mode < SET_PARAM_BUS_TXGLOM_MODE) || (mode >= PARAM_LAST_VALUE)) { DHD_ERROR(("[WIFI_SEC] %s: invalid argument\n", __FUNCTION__)); return BCME_ERROR; } switch (mode) { case SET_PARAM_BUS_TXGLOM_MODE: filepath = "/data/.bustxglom.info"; break; case SET_PARAM_ROAMOFF: filepath = "/data/.roamoff.info"; break; #ifdef USE_WL_FRAMEBURST case SET_PARAM_FRAMEBURST: filepath = "/data/.frameburst.info"; break; #endif /* USE_WL_FRAMEBURST */ #ifdef USE_WL_TXBF case SET_PARAM_TXBF: filepath = "/data/.txbf.info"; break; #endif /* USE_WL_TXBF */ #ifdef PROP_TXSTATUS case SET_PARAM_PROPTX: filepath = "/data/.proptx.info"; break; #endif /* PROP_TXSTATUS */ default: DHD_ERROR(("[WIFI_SEC] %s: File to find file name for index=%d\n", __FUNCTION__, mode)); return BCME_ERROR; } fp = filp_open(filepath, O_RDONLY, 0); if (IS_ERR(fp) || (fp == NULL)) { DHD_ERROR(("[WIFI_SEC] %s: File [%s] doesn't exist \n", __FUNCTION__, filepath)); return BCME_ERROR; } else { if (kernel_read(fp, fp->f_pos, (char *)&val, 4) < 0) { filp_close(fp, NULL); /* File operation is failed so we will return error code */ DHD_ERROR(("[WIFI_SEC] %s: read failed, file path=%s\n", __FUNCTION__, filepath)); return BCME_ERROR; } filp_close(fp, NULL); } val = bcm_atoi((char *)&val); switch (mode) { case SET_PARAM_ROAMOFF: #ifdef USE_WL_FRAMEBURST case SET_PARAM_FRAMEBURST: #endif /* USE_WL_FRAMEBURST */ #ifdef USE_WL_TXBF case SET_PARAM_TXBF: #endif /* USE_WL_TXBF */ #ifdef PROP_TXSTATUS case SET_PARAM_PROPTX: #endif /* PROP_TXSTATUS */ if (val < 0 || val > 1) { DHD_ERROR(("[WIFI_SEC] %s: value[%d] is out of range\n", __FUNCTION__, *read_val)); return BCME_ERROR; } break; default: return BCME_ERROR; } *read_val = (uint)val; return BCME_OK; }
static int dhd_cfgvendor_priv_string_handler(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) { const struct bcm_nlmsg_hdr *nlioc = data; struct net_device *ndev = NULL; struct bcm_cfg80211 *cfg; struct sk_buff *reply; void *buf = NULL, *cur; dhd_pub_t *dhd; dhd_ioctl_t ioc = { 0 }; int ret = 0, ret_len, payload, msglen; int maxmsglen = PAGE_SIZE - 0x100; int8 index; WL_TRACE(("entry: cmd = %d\n", nlioc->cmd)); DHD_ERROR(("entry: cmd = %d\n", nlioc->cmd)); cfg = wiphy_priv(wiphy); dhd = cfg->pub; DHD_OS_WAKE_LOCK(dhd); /* send to dongle only if we are not waiting for reload already */ if (dhd->hang_was_sent) { WL_ERR(("HANG was sent up earlier\n")); DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(dhd, DHD_EVENT_TIMEOUT_MS); DHD_OS_WAKE_UNLOCK(dhd); return OSL_ERROR(BCME_DONGLE_DOWN); } len -= sizeof(struct bcm_nlmsg_hdr); ret_len = nlioc->len; if (ret_len > 0 || len > 0) { if (len > DHD_IOCTL_MAXLEN) { WL_ERR(("oversize input buffer %d\n", len)); len = DHD_IOCTL_MAXLEN; } if (ret_len > DHD_IOCTL_MAXLEN) { WL_ERR(("oversize return buffer %d\n", ret_len)); ret_len = DHD_IOCTL_MAXLEN; } payload = max(ret_len, len) + 1; buf = vzalloc(payload); if (!buf) { DHD_OS_WAKE_UNLOCK(dhd); return -ENOMEM; } memcpy(buf, (void *)nlioc + nlioc->offset, len); *(char *)(buf + len) = '\0'; } ndev = wdev_to_wlc_ndev(wdev, cfg); index = dhd_net2idx(dhd->info, ndev); if (index == DHD_BAD_IF) { WL_ERR(("Bad ifidx from wdev:%p\n", wdev)); ret = BCME_ERROR; goto done; } ioc.cmd = nlioc->cmd; ioc.len = nlioc->len; ioc.set = nlioc->set; ioc.driver = nlioc->magic; ret = dhd_ioctl_process(dhd, index, &ioc, buf); if (ret) { WL_TRACE(("dhd_ioctl_process return err %d\n", ret)); ret = OSL_ERROR(ret); goto done; } cur = buf; while (ret_len > 0) { msglen = nlioc->len > maxmsglen ? maxmsglen : ret_len; ret_len -= msglen; payload = msglen + sizeof(msglen); reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload); if (!reply) { WL_ERR(("Failed to allocate reply msg\n")); ret = -ENOMEM; break; } if (nla_put(reply, BCM_NLATTR_DATA, msglen, cur) || nla_put_u16(reply, BCM_NLATTR_LEN, msglen)) { kfree_skb(reply); ret = -ENOBUFS; break; } ret = cfg80211_vendor_cmd_reply(reply); if (ret) { WL_ERR(("testmode reply failed:%d\n", ret)); break; } cur += msglen; } done: vfree(buf); DHD_OS_WAKE_UNLOCK(dhd); return ret; }
inline int dhd_tcpack_check_xmit(dhd_pub_t *dhdp, void *pkt) { uint8 i; tcpack_sup_module_t *tcpack_sup_mod; tcpack_info_t *tcpack_info_tbl; int tbl_cnt; uint pushed_len; int ret = BCME_OK; void *pdata; uint32 pktlen; if (dhdp->tcpack_sup_mode == TCPACK_SUP_OFF) goto exit; pdata = PKTDATA(dhdp->osh, pkt); /* Length of BDC(+WLFC) headers pushed */ pushed_len = BDC_HEADER_LEN + (((struct bdc_header *)pdata)->dataOffset * 4); pktlen = PKTLEN(dhdp->osh, pkt) - pushed_len; if (pktlen < TCPACKSZMIN || pktlen > TCPACKSZMAX) { DHD_TRACE(("%s %d: Too short or long length %d to be TCP ACK\n", __FUNCTION__, __LINE__, pktlen)); goto exit; } dhd_os_tcpacklock(dhdp); tcpack_sup_mod = dhdp->tcpack_sup_module; if (!tcpack_sup_mod) { DHD_ERROR(("%s %d: tcpack suppress module NULL!!\n", __FUNCTION__, __LINE__)); ret = BCME_ERROR; dhd_os_tcpackunlock(dhdp); goto exit; } tbl_cnt = tcpack_sup_mod->tcpack_info_cnt; tcpack_info_tbl = tcpack_sup_mod->tcpack_info_tbl; ASSERT(tbl_cnt <= TCPACK_INFO_MAXNUM); for (i = 0; i < tbl_cnt; i++) { if (tcpack_info_tbl[i].pkt_in_q == pkt) { DHD_TRACE(("%s %d: pkt %p sent out. idx %d, tbl_cnt %d\n", __FUNCTION__, __LINE__, pkt, i, tbl_cnt)); /* This pkt is being transmitted so remove the tcp_ack_info of it. */ if (i < tbl_cnt - 1) { bcopy(&tcpack_info_tbl[tbl_cnt - 1], &tcpack_info_tbl[i], sizeof(tcpack_info_t)); } bzero(&tcpack_info_tbl[tbl_cnt - 1], sizeof(tcpack_info_t)); if (--tcpack_sup_mod->tcpack_info_cnt < 0) { DHD_ERROR(("%s %d: ERROR!!! tcp_ack_info_cnt %d\n", __FUNCTION__, __LINE__, tcpack_sup_mod->tcpack_info_cnt)); ret = BCME_ERROR; } break; } } dhd_os_tcpackunlock(dhdp); exit: return ret; }
int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) { #define PRIVATE_COMMAND_MAX_LEN 8192 int ret = 0; char *command = NULL; int bytes_written = 0; android_wifi_priv_cmd priv_cmd; net_os_wake_lock(net); if (!ifr->ifr_data) { ret = -EINVAL; goto exit; } if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) { ret = -EFAULT; goto exit; } if (priv_cmd.total_len > PRIVATE_COMMAND_MAX_LEN) { DHD_ERROR(("%s: too long priavte command\n", __FUNCTION__)); ret = -EINVAL; } command = kmalloc(priv_cmd.total_len, GFP_KERNEL); if (!command) { DHD_ERROR(("%s: failed to allocate memory\n", __FUNCTION__)); ret = -ENOMEM; goto exit; } if (copy_from_user(command, priv_cmd.buf, priv_cmd.total_len)) { ret = -EFAULT; goto exit; } DHD_INFO(("%s: Android private cmd \"%s\" on %s\n", __FUNCTION__, command, ifr->ifr_name)); if (strnicmp(command, CMD_START, strlen(CMD_START)) == 0) { DHD_INFO(("%s, Received regular START command\n", __FUNCTION__)); bytes_written = wl_android_wifi_on(net); } else if (strnicmp(command, CMD_SETFWPATH, strlen(CMD_SETFWPATH)) == 0) { bytes_written = wl_android_set_fwpath(net, command, priv_cmd.total_len); } if (!g_wifi_on) { DHD_ERROR(("%s: Ignore private cmd \"%s\" - iface %s is down\n", __FUNCTION__, command, ifr->ifr_name)); ret = 0; goto exit; } if (strnicmp(command, CMD_STOP, strlen(CMD_STOP)) == 0) { bytes_written = wl_android_wifi_off(net); } else if (strnicmp(command, CMD_SCAN_ACTIVE, strlen(CMD_SCAN_ACTIVE)) == 0) { /* TBD: SCAN-ACTIVE */ } else if (strnicmp(command, CMD_SCAN_PASSIVE, strlen(CMD_SCAN_PASSIVE)) == 0) { /* TBD: SCAN-PASSIVE */ } else if (strnicmp(command, CMD_RSSI, strlen(CMD_RSSI)) == 0) { bytes_written = wl_android_get_rssi(net, command, priv_cmd.total_len); } else if (strnicmp(command, CMD_LINKSPEED, strlen(CMD_LINKSPEED)) == 0) { bytes_written = wl_android_get_link_speed(net, command, priv_cmd.total_len); } #ifdef PKT_FILTER_SUPPORT else if (strnicmp(command, CMD_RXFILTER_START, strlen(CMD_RXFILTER_START)) == 0) { bytes_written = net_os_enable_packet_filter(net, 1); } else if (strnicmp(command, CMD_RXFILTER_STOP, strlen(CMD_RXFILTER_STOP)) == 0) { bytes_written = net_os_enable_packet_filter(net, 0); } else if (strnicmp(command, CMD_RXFILTER_ADD, strlen(CMD_RXFILTER_ADD)) == 0) { int filter_num = *(command + strlen(CMD_RXFILTER_ADD) + 1) - '0'; bytes_written = net_os_rxfilter_add_remove(net, TRUE, filter_num); } else if (strnicmp(command, CMD_RXFILTER_REMOVE, strlen(CMD_RXFILTER_REMOVE)) == 0) { int filter_num = *(command + strlen(CMD_RXFILTER_REMOVE) + 1) - '0'; bytes_written = net_os_rxfilter_add_remove(net, FALSE, filter_num); } #endif /* PKT_FILTER_SUPPORT */ else if (strnicmp(command, CMD_BTCOEXSCAN_START, strlen(CMD_BTCOEXSCAN_START)) == 0) { /* TBD: BTCOEXSCAN-START */ } else if (strnicmp(command, CMD_BTCOEXSCAN_STOP, strlen(CMD_BTCOEXSCAN_STOP)) == 0) { /* TBD: BTCOEXSCAN-STOP */ } else if (strnicmp(command, CMD_BTCOEXMODE, strlen(CMD_BTCOEXMODE)) == 0) { #ifdef WL_CFG80211 bytes_written = wl_cfg80211_set_btcoex_dhcp(net, command); #else #ifdef PKT_FILTER_SUPPORT uint mode = *(command + strlen(CMD_BTCOEXMODE) + 1) - '0'; if (mode == 1) net_os_enable_packet_filter(net, 0); /* DHCP starts */ else net_os_enable_packet_filter(net, 1); /* DHCP ends */ #endif /* PKT_FILTER_SUPPORT */ #endif /* WL_CFG80211 */ } else if (strnicmp(command, CMD_SETSUSPENDOPT, strlen(CMD_SETSUSPENDOPT)) == 0) { bytes_written = wl_android_set_suspendopt(net, command, priv_cmd.total_len); } else if (strnicmp(command, CMD_SETSUSPENDMODE, strlen(CMD_SETSUSPENDMODE)) == 0) { bytes_written = wl_android_set_suspendmode(net, command, priv_cmd.total_len); } else if (strnicmp(command, CMD_SETBAND, strlen(CMD_SETBAND)) == 0) { uint band = *(command + strlen(CMD_SETBAND) + 1) - '0'; #ifdef WL_HOST_BAND_MGMT if (wl_cfg80211_set_band(net, band) < 0) { bytes_written = -1; goto exit; } if (band == WLC_BAND_AUTO) bytes_written = wldev_set_band(net, band); #else bytes_written = wldev_set_band(net, band); #endif /* WL_HOST_BAND_MGMT */ } else if (strnicmp(command, CMD_GETBAND, strlen(CMD_GETBAND)) == 0) { bytes_written = wl_android_get_band(net, command, priv_cmd.total_len); } #ifdef WL_CFG80211 /* CUSTOMER_SET_COUNTRY feature is define for only GGSM model */ else if (strnicmp(command, CMD_COUNTRY, strlen(CMD_COUNTRY)) == 0) { char *country_code = command + strlen(CMD_COUNTRY) + 1; bytes_written = wldev_set_country(net, country_code); } #endif /* WL_CFG80211 */ #if defined(PNO_SUPPORT) && !defined(WL_SCHED_SCAN) else if (strnicmp(command, CMD_PNOSSIDCLR_SET, strlen(CMD_PNOSSIDCLR_SET)) == 0) { bytes_written = dhd_dev_pno_reset(net); } else if (strnicmp(command, CMD_PNOSETUP_SET, strlen(CMD_PNOSETUP_SET)) == 0) { bytes_written = wl_android_set_pno_setup(net, command, priv_cmd.total_len); } else if (strnicmp(command, CMD_PNOENABLE_SET, strlen(CMD_PNOENABLE_SET)) == 0) { uint pfn_enabled = *(command + strlen(CMD_PNOENABLE_SET) + 1) - '0'; bytes_written = dhd_dev_pno_enable(net, pfn_enabled); } #endif /* PNO_SUPPORT && !WL_SCHED_SCAN */ else if (strnicmp(command, CMD_P2P_DEV_ADDR, strlen(CMD_P2P_DEV_ADDR)) == 0) { bytes_written = wl_android_get_p2p_dev_addr(net, command, priv_cmd.total_len); } else if (strnicmp(command, CMD_P2P_SET_NOA, strlen(CMD_P2P_SET_NOA)) == 0) { int skip = strlen(CMD_P2P_SET_NOA) + 1; bytes_written = wl_cfg80211_set_p2p_noa(net, command + skip, priv_cmd.total_len - skip); } #if !defined WL_ENABLE_P2P_IF else if (strnicmp(command, CMD_P2P_GET_NOA, strlen(CMD_P2P_GET_NOA)) == 0) { bytes_written = wl_cfg80211_get_p2p_noa(net, command, priv_cmd.total_len); } #endif /* WL_ENABLE_P2P_IF */ else if (strnicmp(command, CMD_P2P_SET_PS, strlen(CMD_P2P_SET_PS)) == 0) { int skip = strlen(CMD_P2P_SET_PS) + 1; bytes_written = wl_cfg80211_set_p2p_ps(net, command + skip, priv_cmd.total_len - skip); } #ifdef WL_CFG80211 else if (strnicmp(command, CMD_SET_AP_WPS_P2P_IE, strlen(CMD_SET_AP_WPS_P2P_IE)) == 0) { int skip = strlen(CMD_SET_AP_WPS_P2P_IE) + 3; bytes_written = wl_cfg80211_set_wps_p2p_ie(net, command + skip, priv_cmd.total_len - skip, *(command + skip - 2) - '0'); } #endif /* WL_CFG80211 */ else if (strnicmp(command, CMD_OKC_SET_PMK, strlen(CMD_OKC_SET_PMK)) == 0) bytes_written = wl_android_set_pmk(net, command, priv_cmd.total_len); else if (strnicmp(command, CMD_OKC_ENABLE, strlen(CMD_OKC_ENABLE)) == 0) bytes_written = wl_android_okc_enable(net, command, priv_cmd.total_len); else if (strnicmp(command, CMD_SETROAMMODE, strlen(CMD_SETROAMMODE)) == 0) bytes_written = wl_android_set_roam_mode(net, command, priv_cmd.total_len); else { DHD_ERROR(("Unknown PRIVATE command %s - ignored\n", command)); snprintf(command, 3, "OK"); bytes_written = strlen("OK"); } 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++; } 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__)); ret = -EFAULT; } } else { ret = bytes_written; } exit: net_os_wake_unlock(net); if (command) { kfree(command); } return ret; }
int CheckRDWR_Macaddr( struct dhd_info *dhd, dhd_pub_t *dhdp, struct ether_addr *mac) { struct file *fp_mac = NULL; struct file *fp_nvm = NULL; char macbuffer[18] = {0}; char randommac[3] = {0}; char buf[18] = {0}; char* filepath = "/data/.mac.info"; char* nvfilepath = "/data/.nvmac.info"; char cur_mac[128] = {0}; char dummy_mac[ETHER_ADDR_LEN] = { 0x00, 0x90, 0x4C, 0xC5, 0x12, 0x38 }; char cur_macbuffer[18] = {0}; int ret = -1; g_iMacFlag = MACADDR_NONE; fp_nvm = filp_open(nvfilepath, O_RDONLY, 0); if(IS_ERR(fp_nvm)) { // file is not exist //read MAC Address; //ReadMacAddress_OTP(dhd,cur_mac); //dhd_os_proto_block(dhdp); strcpy(cur_mac, "cur_etheraddr"); //ret = dhdcdc_query_ioctl(dhdp, 0, WLC_GET_VAR, cur_mac, sizeof(cur_mac)); ret = dhd_wl_ioctl_cmd(dhdp, WLC_GET_VAR, cur_mac, sizeof(cur_mac), 0, 0); if (ret < 0) { DHD_ERROR(("Current READ MAC error \r\n")); memset(cur_mac , 0 , ETHER_ADDR_LEN); return -1; } else { DHD_ERROR(("MAC (OTP) : [%02X:%02X:%02X:%02X:%02X:%02X] \r\n" , cur_mac[0], cur_mac[1], cur_mac[2], cur_mac[3], cur_mac[4], cur_mac[5])); } //dhd_os_proto_unblock(dhdp); sprintf(cur_macbuffer,"%02X:%02X:%02X:%02X:%02X:%02X\n", cur_mac[0],cur_mac[1],cur_mac[2],cur_mac[3],cur_mac[4],cur_mac[5]); fp_mac = filp_open(filepath, O_RDONLY, 0); if(IS_ERR(fp_mac)) { // file is not exist if(memcmp(cur_mac,dummy_mac,ETHER_ADDR_LEN) == 0) { // read mac is 00:90:4C:C5:12:38 g_iMacFlag = MACADDR_MOD_RANDOM; } else if(strncmp(buf , "00:00:00:00:00:00" , 17) == 0) { g_iMacFlag = MACADDR_MOD_RANDOM; } else { g_iMacFlag = MACADDR_MOD; } } else { int is_zeromac; ret = kernel_read(fp_mac, 0, buf, 18); filp_close(fp_mac, NULL); buf[17] ='\0'; is_zeromac = strncmp(buf, "00:00:00:00:00:00", 17); DHD_ERROR(("MAC (FILE): [%s] [%d] \r\n" , buf, is_zeromac)); if (is_zeromac == 0) { DHD_ERROR(("Zero MAC detected. Trying Random MAC.\n")); g_iMacFlag = MACADDR_MOD_RANDOM; } else { sscanf(buf,"%02X:%02X:%02X:%02X:%02X:%02X", &(mac->octet[0]), &(mac->octet[1]), &(mac->octet[2]), &(mac->octet[3]), &(mac->octet[4]), &(mac->octet[5])); if(memcmp(cur_mac,mac->octet,ETHER_ADDR_LEN) == 0) { // read mac is same g_iMacFlag = MACADDR_NONE; } else { // change mac.. if (0 == _dhd_set_mac_address(dhd, 0, mac)) { DHD_INFO(("dhd_bus_start: MACID is overwritten\n")); g_iMacFlag = MACADDR_MOD; } else { DHD_ERROR(("dhd_bus_start: _dhd_set_mac_address() failed\n")); g_iMacFlag = MACADDR_NONE; } } } } } else { // COB type. only COB. /* Reading the MAC Address from .nvmac.info file( the existed file or just created file)*/ ret = kernel_read(fp_nvm, 0, buf, 18); buf[17] ='\0'; // to prevent abnormal string display when mac address is displayed on the screen. DHD_ERROR(("Read MAC : [%s] [%d] \r\n" , buf, strncmp(buf , "00:00:00:00:00:00" , 17))); if(strncmp(buf , "00:00:00:00:00:00" , 17) == 0) { filp_close(fp_nvm, NULL); g_iMacFlag = MACADDR_COB_RANDOM; } else { sscanf(buf,"%02X:%02X:%02X:%02X:%02X:%02X", &(mac->octet[0]), &(mac->octet[1]), &(mac->octet[2]), &(mac->octet[3]), &(mac->octet[4]), &(mac->octet[5])); /* Writing Newly generated MAC ID to the Dongle */ if (0 == _dhd_set_mac_address(dhd, 0, mac)) { DHD_INFO(("dhd_bus_start: MACID is overwritten\n")); g_iMacFlag = MACADDR_COB; } else { DHD_ERROR(("dhd_bus_start: _dhd_set_mac_address() failed\n")); } } filp_close(fp_nvm, NULL); } if((g_iMacFlag == MACADDR_COB_RANDOM) || (g_iMacFlag == MACADDR_MOD_RANDOM)) { get_random_bytes(randommac, 3); sprintf(macbuffer,"%02X:%02X:%02X:%02X:%02X:%02X\n", 0x60,0xd0,0xa9,randommac[0],randommac[1],randommac[2]); DHD_ERROR(("[WIFI] The Random Generated MAC ID : %s\n", macbuffer)); sscanf(macbuffer,"%02X:%02X:%02X:%02X:%02X:%02X", &(mac->octet[0]), &(mac->octet[1]), &(mac->octet[2]), &(mac->octet[3]), &(mac->octet[4]), &(mac->octet[5])); if (0 == _dhd_set_mac_address(dhd, 0, mac)) { DHD_INFO(("dhd_bus_start: MACID is overwritten\n")); g_iMacFlag = MACADDR_COB; } else { DHD_ERROR(("dhd_bus_start: _dhd_set_mac_address() failed\n")); } } return 0; }
int dhd_read_macaddr(dhd_info_t *dhd) { struct file *fp = NULL; struct file *fpnv = NULL; char macbuffer[18] = {0}; mm_segment_t oldfs = {0}; char randommac[3] = {0}; char buf[18] = {0}; char* filepath = "/data/.mac.info"; char* nvfilepath = "/data/.nvmac.info"; int ret; //MAC address copied from nv fpnv = filp_open(nvfilepath, O_RDONLY, 0); if (IS_ERR(fpnv)) { start_readmac: fpnv = NULL; fp = filp_open(filepath, O_RDONLY, 0); if (IS_ERR(fp)) { /* File Doesn't Exist. Create and write mac addr.*/ fp = filp_open(filepath, O_RDWR | O_CREAT, 0666); if(IS_ERR(fp)) { DHD_ERROR(("[WIFI] %s: File open error\n", filepath)); return -1; } oldfs = get_fs(); set_fs(get_ds()); /* Generating the Random Bytes for 3 last octects of the MAC address */ get_random_bytes(randommac, 3); sprintf(macbuffer,"%02X:%02X:%02X:%02X:%02X:%02X\n", 0x60,0xd0,0xa9,randommac[0],randommac[1],randommac[2]); DHD_INFO(("[WIFI] The Random Generated MAC ID : %s\n", macbuffer)); printk("[WIFI] The Random Generated MAC ID : %s\n", macbuffer); if(fp->f_mode & FMODE_WRITE) { ret = fp->f_op->write(fp, (const char *)macbuffer, sizeof(macbuffer), &fp->f_pos); if(ret < 0) DHD_ERROR(("[WIFI] Mac address [%s] Failed to write into File: %s\n", macbuffer, filepath)); else DHD_INFO(("[WIFI] Mac address [%s] written into File: %s\n", macbuffer, filepath)); } set_fs(oldfs); } /* Reading the MAC Address from .mac.info file( the existed file or just created file)*/ //rtn_value=kernel_read(fp, fp->f_pos, buf, 18); ret = kernel_read(fp, 0, buf, 18); } else { /* Reading the MAC Address from .nvmac.info file( the existed file or just created file)*/ ret = kernel_read(fpnv, 0, buf, 18); buf[17] ='\0'; // to prevent abnormal string display when mac address is displayed on the screen. printk("Read MAC : [%s] [%d] \r\n" , buf, strncmp(buf , "00:00:00:00:00:00" , 17)); if(strncmp(buf , "00:00:00:00:00:00" , 17) == 0) { filp_close(fpnv, NULL); goto start_readmac; } fp = filp_open(filepath, O_RDONLY, 0); if (IS_ERR(fp)) // If you want to write MAC address to /data/.mac.info once, { fp = filp_open(filepath, O_RDWR | O_CREAT, 0666); if(IS_ERR(fp)) { DHD_ERROR(("[WIFI] %s: File open error\n", filepath)); return -1; } oldfs = get_fs(); set_fs(get_ds()); if(fp->f_mode & FMODE_WRITE) { ret = fp->f_op->write(fp, (const char *)buf, sizeof(buf), &fp->f_pos); if(ret < 0) DHD_ERROR(("[WIFI] Mac address [%s] Failed to write into File: %s\n", buf, filepath)); else DHD_INFO(("[WIFI] Mac address [%s] written into File: %s\n", buf, filepath)); } set_fs(oldfs); } ret = kernel_read(fp, 0, buf, 18); } if(ret) sscanf(buf,"%02X:%02X:%02X:%02X:%02X:%02X", &dhd->pub.mac.octet[0], &dhd->pub.mac.octet[1], &dhd->pub.mac.octet[2], &dhd->pub.mac.octet[3], &dhd->pub.mac.octet[4], &dhd->pub.mac.octet[5]); else DHD_ERROR(("dhd_bus_start: Reading from the '%s' returns 0 bytes\n", filepath)); if (fp) filp_close(fp, NULL); if (fpnv) filp_close(fpnv, NULL); /* Writing Newly generated MAC ID to the Dongle */ if (0 == _dhd_set_mac_address(dhd, 0, &dhd->pub.mac)) DHD_INFO(("dhd_bus_start: MACID is overwritten\n")); else DHD_ERROR(("dhd_bus_start: _dhd_set_mac_address() failed\n")); return 0; }
void dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_mode) { char *argv[8]; int i = 0; const char *str; int buf_len; int str_len; char *arg_save = 0, *arg_org = 0; int rc; char buf[128]; wl_pkt_filter_enable_t enable_parm; wl_pkt_filter_enable_t * pkt_filterp; if (!(arg_save = MALLOC(dhd->osh, strlen(arg) + 1))) { DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__)); goto fail; } arg_org = arg_save; memcpy(arg_save, arg, strlen(arg) + 1); argv[i] = bcmstrtok(&arg_save, " ", 0); i = 0; if (NULL == argv[i]) { DHD_ERROR(("No args provided\n")); goto fail; } str = "pkt_filter_enable"; str_len = strlen(str); strncpy(buf, str, str_len); buf[str_len] = '\0'; buf_len = str_len + 1; pkt_filterp = (wl_pkt_filter_enable_t *)(buf + str_len + 1); /* Parse packet filter id. */ enable_parm.id = htod32(strtoul(argv[i], NULL, 0)); /* Parse enable/disable value. */ enable_parm.enable = htod32(enable); buf_len += sizeof(enable_parm); memcpy((char *)pkt_filterp, &enable_parm, sizeof(enable_parm)); /* Enable/disable the specified filter. */ rc = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, buf_len, TRUE, 0); rc = rc >= 0 ? 0 : rc; if (rc) DHD_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n", __FUNCTION__, arg, rc)); else DHD_TRACE(("%s: successfully added pktfilter %s\n", __FUNCTION__, arg)); /* Contorl the master mode */ bcm_mkiovar("pkt_filter_mode", (char *)&master_mode, 4, buf, sizeof(buf)); rc = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, sizeof(buf), TRUE, 0); rc = rc >= 0 ? 0 : rc; if (rc) DHD_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n", __FUNCTION__, arg, rc)); fail: if (arg_org) MFREE(dhd->osh, arg_org, strlen(arg) + 1); }
static int dhd_rtt_start(dhd_pub_t *dhd) { int err = BCME_OK; int mpc = 0; int nss, mcs, bw; uint32 rspec = 0; int8 eabuf[ETHER_ADDR_STR_LEN]; int8 chanbuf[CHANSPEC_STR_LEN]; bool set_mpc = FALSE; wl_proxd_iovar_t proxd_iovar; wl_proxd_params_iovar_t proxd_params; wl_proxd_params_iovar_t proxd_tune; wl_proxd_params_tof_method_t *tof_params = &proxd_params.u.tof_params; rtt_status_info_t *rtt_status; rtt_target_info_t *rtt_target; NULL_CHECK(dhd, "dhd is NULL", err); rtt_status = GET_RTTSTATE(dhd); NULL_CHECK(rtt_status, "rtt_status is NULL", err); /* turn off mpc in case of non-associted */ if (!dhd_is_associated(dhd, NULL, NULL)) { err = dhd_iovar(dhd, 0, "mpc", (char *)&mpc, sizeof(mpc), 1); if (err < 0) { DHD_ERROR(("%s : failed to set proxd_tune\n", __FUNCTION__)); goto exit; } set_mpc = TRUE; } if (rtt_status->cur_idx >= rtt_status->rtt_config.rtt_target_cnt) { err = BCME_RANGE; goto exit; } DHD_RTT(("%s enter\n", __FUNCTION__)); bzero(&proxd_tune, sizeof(proxd_tune)); bzero(&proxd_params, sizeof(proxd_params)); mutex_lock(&rtt_status->rtt_mutex); /* Get a target information */ rtt_target = &rtt_status->rtt_config.target_info[rtt_status->cur_idx]; mutex_unlock(&rtt_status->rtt_mutex); /* set role */ proxd_iovar.method = PROXD_TOF_METHOD; proxd_iovar.mode = WL_PROXD_MODE_INITIATOR; /* make sure that proxd is stop */ //dhd_iovar(dhd, 0, "proxd_stop", (char *)NULL, 0, 1); err = dhd_iovar(dhd, 0, "proxd", (char *)&proxd_iovar, sizeof(proxd_iovar), 1); if (err < 0 && err != BCME_BUSY) { DHD_ERROR(("%s : failed to set proxd %d\n", __FUNCTION__, err)); goto exit; } /* mac address */ bcopy(&rtt_target->addr, &tof_params->tgt_mac, ETHER_ADDR_LEN); /* frame count */ if (rtt_target->ftm_cnt > RTT_MAX_FRAME_CNT) rtt_target->ftm_cnt = RTT_MAX_FRAME_CNT; if (rtt_target->ftm_cnt) tof_params->ftm_cnt = htol16(rtt_target->ftm_cnt); else tof_params->ftm_cnt = htol16(DEFAULT_FTM_CNT); if (rtt_target->retry_cnt > RTT_MAX_RETRY_CNT) rtt_target->retry_cnt = RTT_MAX_RETRY_CNT; /* retry count */ if (rtt_target->retry_cnt) tof_params->retry_cnt = htol16(rtt_target->retry_cnt); else tof_params->retry_cnt = htol16(DEFAULT_RETRY_CNT); /* chanspec */ tof_params->chanspec = htol16(rtt_target->chanspec); /* set parameter */ DHD_RTT(("Target addr(Idx %d) %s, Channel : %s for RTT (ftm_cnt %d, rety_cnt : %d)\n", rtt_status->cur_idx, bcm_ether_ntoa((const struct ether_addr *)&rtt_target->addr, eabuf), wf_chspec_ntoa(rtt_target->chanspec, chanbuf), rtt_target->ftm_cnt, rtt_target->retry_cnt)); if (rtt_target->type == RTT_ONE_WAY) { proxd_tune.u.tof_tune.flags = htol32(WL_PROXD_FLAG_ONEWAY); /* report RTT results for initiator */ proxd_tune.u.tof_tune.flags |= htol32(WL_PROXD_FLAG_INITIATOR_RPTRTT); proxd_tune.u.tof_tune.vhtack = 0; tof_params->tx_rate = htol16(WL_RATE_6M); tof_params->vht_rate = htol16((WL_RATE_6M >> 16)); } else { /* RTT TWO WAY */
void dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg) { const char *str; wl_pkt_filter_t pkt_filter; wl_pkt_filter_t *pkt_filterp; int buf_len; int str_len; int rc; uint32 mask_size; uint32 pattern_size; char *argv[8], * buf = 0; int i = 0; char *arg_save = 0, *arg_org = 0; #define BUF_SIZE 2048 if (!(arg_save = MALLOC(dhd->osh, strlen(arg) + 1))) { DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__)); goto fail; } arg_org = arg_save; if (!(buf = MALLOC(dhd->osh, BUF_SIZE))) { DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__)); goto fail; } memcpy(arg_save, arg, strlen(arg) + 1); if (strlen(arg) > BUF_SIZE) { DHD_ERROR(("Not enough buffer %d < %d\n", (int)strlen(arg), (int)sizeof(buf))); goto fail; } argv[i] = bcmstrtok(&arg_save, " ", 0); while (argv[i++]) argv[i] = bcmstrtok(&arg_save, " ", 0); i = 0; if (NULL == argv[i]) { DHD_ERROR(("No args provided\n")); goto fail; } str = "pkt_filter_add"; str_len = strlen(str); strncpy(buf, str, str_len); buf[ str_len ] = '\0'; buf_len = str_len + 1; pkt_filterp = (wl_pkt_filter_t *) (buf + str_len + 1); /* Parse packet filter id. */ pkt_filter.id = htod32(strtoul(argv[i], NULL, 0)); if (NULL == argv[++i]) { DHD_ERROR(("Polarity not provided\n")); goto fail; } /* Parse filter polarity. */ pkt_filter.negate_match = htod32(strtoul(argv[i], NULL, 0)); if (NULL == argv[++i]) { DHD_ERROR(("Filter type not provided\n")); goto fail; } /* Parse filter type. */ pkt_filter.type = htod32(strtoul(argv[i], NULL, 0)); if (NULL == argv[++i]) { DHD_ERROR(("Offset not provided\n")); goto fail; } /* Parse pattern filter offset. */ pkt_filter.u.pattern.offset = htod32(strtoul(argv[i], NULL, 0)); if (NULL == argv[++i]) { DHD_ERROR(("Bitmask not provided\n")); goto fail; } /* Parse pattern filter mask. */ mask_size = htod32(wl_pattern_atoh(argv[i], (char *) pkt_filterp->u.pattern.mask_and_pattern)); if (NULL == argv[++i]) { DHD_ERROR(("Pattern not provided\n")); goto fail; } /* Parse pattern filter pattern. */ pattern_size = htod32(wl_pattern_atoh(argv[i], (char *) &pkt_filterp->u.pattern.mask_and_pattern[mask_size])); if (mask_size != pattern_size) { DHD_ERROR(("Mask and pattern not the same size\n")); goto fail; } pkt_filter.u.pattern.size_bytes = mask_size; buf_len += WL_PKT_FILTER_FIXED_LEN; buf_len += (WL_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size); /* Keep-alive attributes are set in local variable (keep_alive_pkt), and ** then memcpy'ed into buffer (keep_alive_pktp) since there is no ** guarantee that the buffer is properly aligned. */ memcpy((char *)pkt_filterp, &pkt_filter, WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN); rc = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, buf_len, TRUE, 0); rc = rc >= 0 ? 0 : rc; if (rc) DHD_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n", __FUNCTION__, arg, rc)); else DHD_TRACE(("%s: successfully added pktfilter %s\n", __FUNCTION__, arg)); fail: if (arg_org) MFREE(dhd->osh, arg_org, strlen(arg) + 1); if (buf) MFREE(dhd->osh, buf, BUF_SIZE); }
bool dhd_tcpack_hold(dhd_pub_t *dhdp, void *pkt, int ifidx) { uint8 *new_ether_hdr; /* Ethernet header of the new packet */ uint16 new_ether_type; /* Ethernet type of the new packet */ uint8 *new_ip_hdr; /* IP header of the new packet */ uint8 *new_tcp_hdr; /* TCP header of the new packet */ uint32 new_ip_hdr_len; /* IP header length of the new packet */ uint32 cur_framelen; uint32 new_tcp_ack_num; /* TCP acknowledge number of the new packet */ uint16 new_ip_total_len; /* Total length of IP packet for the new packet */ uint32 new_tcp_hdr_len; /* TCP header length of the new packet */ tcpack_sup_module_t *tcpack_sup_mod; tcpack_info_t *tcpack_info_tbl; int i, free_slot = TCPACK_INFO_MAXNUM; bool hold = FALSE; unsigned long flags; if (dhdp->tcpack_sup_mode != TCPACK_SUP_HOLD) { goto exit; } if (dhdp->tcpack_sup_ratio == 1) { goto exit; } new_ether_hdr = PKTDATA(dhdp->osh, pkt); cur_framelen = PKTLEN(dhdp->osh, pkt); if (cur_framelen < TCPACKSZMIN || cur_framelen > TCPACKSZMAX) { DHD_TRACE(("%s %d: Too short or long length %d to be TCP ACK\n", __FUNCTION__, __LINE__, cur_framelen)); goto exit; } new_ether_type = new_ether_hdr[12] << 8 | new_ether_hdr[13]; if (new_ether_type != ETHER_TYPE_IP) { DHD_TRACE(("%s %d: Not a IP packet 0x%x\n", __FUNCTION__, __LINE__, new_ether_type)); goto exit; } DHD_TRACE(("%s %d: IP pkt! 0x%x\n", __FUNCTION__, __LINE__, new_ether_type)); new_ip_hdr = new_ether_hdr + ETHER_HDR_LEN; cur_framelen -= ETHER_HDR_LEN; ASSERT(cur_framelen >= IPV4_MIN_HEADER_LEN); new_ip_hdr_len = IPV4_HLEN(new_ip_hdr); if (IP_VER(new_ip_hdr) != IP_VER_4 || IPV4_PROT(new_ip_hdr) != IP_PROT_TCP) { DHD_TRACE(("%s %d: Not IPv4 nor TCP! ip ver %d, prot %d\n", __FUNCTION__, __LINE__, IP_VER(new_ip_hdr), IPV4_PROT(new_ip_hdr))); goto exit; } new_tcp_hdr = new_ip_hdr + new_ip_hdr_len; cur_framelen -= new_ip_hdr_len; ASSERT(cur_framelen >= TCP_MIN_HEADER_LEN); DHD_TRACE(("%s %d: TCP pkt!\n", __FUNCTION__, __LINE__)); /* is it an ack ? Allow only ACK flag, not to suppress others. */ if (new_tcp_hdr[TCP_FLAGS_OFFSET] != TCP_FLAG_ACK) { DHD_TRACE(("%s %d: Do not touch TCP flag 0x%x\n", __FUNCTION__, __LINE__, new_tcp_hdr[TCP_FLAGS_OFFSET])); goto exit; } new_ip_total_len = ntoh16_ua(&new_ip_hdr[IPV4_PKTLEN_OFFSET]); new_tcp_hdr_len = 4 * TCP_HDRLEN(new_tcp_hdr[TCP_HLEN_OFFSET]); /* This packet has TCP data, so just send */ if (new_ip_total_len > new_ip_hdr_len + new_tcp_hdr_len) { DHD_TRACE(("%s %d: Do nothing for TCP DATA\n", __FUNCTION__, __LINE__)); goto exit; } ASSERT(new_ip_total_len == new_ip_hdr_len + new_tcp_hdr_len); new_tcp_ack_num = ntoh32_ua(&new_tcp_hdr[TCP_ACK_NUM_OFFSET]); DHD_TRACE(("%s %d: TCP ACK with zero DATA length" " IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR" TCP port %d %d\n", __FUNCTION__, __LINE__, IPV4_ADDR_TO_STR(ntoh32_ua(&new_ip_hdr[IPV4_SRC_IP_OFFSET])), IPV4_ADDR_TO_STR(ntoh32_ua(&new_ip_hdr[IPV4_DEST_IP_OFFSET])), ntoh16_ua(&new_tcp_hdr[TCP_SRC_PORT_OFFSET]), ntoh16_ua(&new_tcp_hdr[TCP_DEST_PORT_OFFSET]))); /* Look for tcp_ack_info that has the same ip src/dst addrs and tcp src/dst ports */ flags = dhd_os_tcpacklock(dhdp); tcpack_sup_mod = dhdp->tcpack_sup_module; tcpack_info_tbl = tcpack_sup_mod->tcpack_info_tbl; if (!tcpack_sup_mod) { DHD_ERROR(("%s %d: tcpack suppress module NULL!!\n", __FUNCTION__, __LINE__)); dhd_os_tcpackunlock(dhdp, flags); goto exit; } hold = TRUE; for (i = 0; i < TCPACK_INFO_MAXNUM; i++) { void *oldpkt; /* TCPACK packet that is already in txq or DelayQ */ uint8 *old_ether_hdr, *old_ip_hdr, *old_tcp_hdr; uint32 old_ip_hdr_len, old_tcp_hdr_len; uint32 old_tcpack_num; /* TCP ACK number of old TCPACK packet in Q */ if ((oldpkt = tcpack_info_tbl[i].pkt_in_q) == NULL) { if (free_slot == TCPACK_INFO_MAXNUM) { free_slot = i; } continue; } if (PKTDATA(dhdp->osh, oldpkt) == NULL) { DHD_ERROR(("%s %d: oldpkt data NULL!! cur idx %d\n", __FUNCTION__, __LINE__, i)); hold = FALSE; dhd_os_tcpackunlock(dhdp, flags); goto exit; } old_ether_hdr = tcpack_info_tbl[i].pkt_ether_hdr; old_ip_hdr = old_ether_hdr + ETHER_HDR_LEN; old_ip_hdr_len = IPV4_HLEN(old_ip_hdr); old_tcp_hdr = old_ip_hdr + old_ip_hdr_len; old_tcp_hdr_len = 4 * TCP_HDRLEN(old_tcp_hdr[TCP_HLEN_OFFSET]); DHD_TRACE(("%s %d: oldpkt %p[%d], IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR " TCP port %d %d\n", __FUNCTION__, __LINE__, oldpkt, i, IPV4_ADDR_TO_STR(ntoh32_ua(&old_ip_hdr[IPV4_SRC_IP_OFFSET])), IPV4_ADDR_TO_STR(ntoh32_ua(&old_ip_hdr[IPV4_DEST_IP_OFFSET])), ntoh16_ua(&old_tcp_hdr[TCP_SRC_PORT_OFFSET]), ntoh16_ua(&old_tcp_hdr[TCP_DEST_PORT_OFFSET]))); /* If either of IP address or TCP port number does not match, skip. */ if (memcmp(&new_ip_hdr[IPV4_SRC_IP_OFFSET], &old_ip_hdr[IPV4_SRC_IP_OFFSET], IPV4_ADDR_LEN * 2) || memcmp(&new_tcp_hdr[TCP_SRC_PORT_OFFSET], &old_tcp_hdr[TCP_SRC_PORT_OFFSET], TCP_PORT_LEN * 2)) { continue; } old_tcpack_num = ntoh32_ua(&old_tcp_hdr[TCP_ACK_NUM_OFFSET]); if (IS_TCPSEQ_GE(new_tcp_ack_num, old_tcpack_num)) { tcpack_info_tbl[i].supp_cnt++; if (tcpack_info_tbl[i].supp_cnt >= dhdp->tcpack_sup_ratio) { tcpack_info_tbl[i].pkt_in_q = NULL; tcpack_info_tbl[i].pkt_ether_hdr = NULL; tcpack_info_tbl[i].ifidx = 0; tcpack_info_tbl[i].supp_cnt = 0; hold = FALSE; } else { tcpack_info_tbl[i].pkt_in_q = pkt; tcpack_info_tbl[i].pkt_ether_hdr = new_ether_hdr; tcpack_info_tbl[i].ifidx = ifidx; } PKTFREE(dhdp->osh, oldpkt, TRUE); } else { PKTFREE(dhdp->osh, pkt, TRUE); } dhd_os_tcpackunlock(dhdp, flags); if (!hold) { del_timer_sync(&tcpack_info_tbl[i].timer); } goto exit; } if (free_slot < TCPACK_INFO_MAXNUM) { /* No TCPACK packet with the same IP addr and TCP port is found * in tcp_ack_info_tbl. So add this packet to the table. */ DHD_TRACE(("%s %d: Add pkt 0x%p(ether_hdr 0x%p) to tbl[%d]\n", __FUNCTION__, __LINE__, pkt, new_ether_hdr, free_slot)); tcpack_info_tbl[free_slot].pkt_in_q = pkt; tcpack_info_tbl[free_slot].pkt_ether_hdr = new_ether_hdr; tcpack_info_tbl[free_slot].ifidx = ifidx; tcpack_info_tbl[free_slot].supp_cnt = 1; mod_timer(&tcpack_sup_mod->tcpack_info_tbl[free_slot].timer, jiffies + msecs_to_jiffies(dhdp->tcpack_sup_delay)); tcpack_sup_mod->tcpack_info_cnt++; } else { DHD_TRACE(("%s %d: No empty tcp ack info tbl\n", __FUNCTION__, __LINE__)); } dhd_os_tcpackunlock(dhdp, flags); exit: return hold; }
/* * delete disappeared AP from specific scan cache */ int dhd_iscan_delete_bss(/* TBD void *dhdp, */ void *addr) { int i = 0, j = 0, l = 0; iscan_buf_t *iscan_cur; wl_iscan_results_t *list; wl_scan_results_t *results; wl_bss_info_t UNALIGNED *bi, *bi_new, *bi_next; uchar *s_addr = addr; DHD_TRACE(("%s: Entered\n", __FUNCTION__)); dhd_iscan_lock(); DHD_TRACE(("%s: BSS to remove %X:%X:%X:%X:%X:%X\n", __FUNCTION__, s_addr[0], s_addr[1], s_addr[2], s_addr[3], s_addr[4], s_addr[5])); DHD_TRACE(("%s: Scan cache before delete\n", __FUNCTION__)); iscan_cur = dhd_iscan_result_buf(); while (iscan_cur) { list = (wl_iscan_results_t *)iscan_cur->iscan_buf; if (!list) break; results = (wl_scan_results_t *)&list->results; if (!results) break; if (results->version != WL_BSS_INFO_VERSION) { DHD_ERROR(("%s: results->version %d != WL_BSS_INFO_VERSION\n", __FUNCTION__, results->version)); goto done; } bi = results->bss_info; for (i = 0; i < results->count; i++) { if (!bi) break; if (!memcmp(bi->BSSID.octet, addr, ETHER_ADDR_LEN)) { DHD_TRACE(("%s: Del BSS[%2.2d:%2.2d] %X:%X:%X:%X:%X:%X\n", __FUNCTION__, l, i, bi->BSSID.octet[0], bi->BSSID.octet[1], bi->BSSID.octet[2], bi->BSSID.octet[3], bi->BSSID.octet[4], bi->BSSID.octet[5])); bi_new = bi; bi = (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)); for (j = i; j < results->count; j++) { DHD_TRACE(("%s: Moved up BSS[%2.2d:%2.2d]" " %X:%X:%X:%X:%X:%X\n", __FUNCTION__, l, j, bi->BSSID.octet[0], bi->BSSID.octet[1], bi->BSSID.octet[2], bi->BSSID.octet[3], bi->BSSID.octet[4], bi->BSSID.octet[5])); bi_next = (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)); bcopy(bi, bi_new, dtoh32(bi->length)); bi_new = (wl_bss_info_t *)((uintptr)bi_new + dtoh32(bi_new->length)); bi = bi_next; } results->count--; if (results->count == 0) { /* Prune now empty partial scan list */ goto done; } break; } bi = (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)); } iscan_cur = iscan_cur->next; l++; } done: DHD_TRACE(("%s: Scan cache after delete\n", __FUNCTION__)); dhd_iscan_unlock(); return 0; }
static INLINE bool dhd_tcpdata_psh_acked(dhd_pub_t *dhdp, uint8 *ip_hdr, uint8 *tcp_hdr, uint32 tcp_ack_num) { tcpack_sup_module_t *tcpack_sup_mod; int i; tcpdata_info_t *tcpdata_info = NULL; tdata_psh_info_t *tdata_psh_info = NULL; bool ret = FALSE; if (dhdp->tcpack_sup_mode != TCPACK_SUP_DELAYTX) goto exit; tcpack_sup_mod = dhdp->tcpack_sup_module; if (!tcpack_sup_mod) { DHD_ERROR(("%s %d: tcpack suppress module NULL!!\n", __FUNCTION__, __LINE__)); goto exit; } DHD_TRACE(("%s %d: IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR " TCP port %d %d, ack %u\n", __FUNCTION__, __LINE__, IPV4_ADDR_TO_STR(ntoh32_ua(&ip_hdr[IPV4_SRC_IP_OFFSET])), IPV4_ADDR_TO_STR(ntoh32_ua(&ip_hdr[IPV4_DEST_IP_OFFSET])), ntoh16_ua(&tcp_hdr[TCP_SRC_PORT_OFFSET]), ntoh16_ua(&tcp_hdr[TCP_DEST_PORT_OFFSET]), tcp_ack_num)); for (i = 0; i < tcpack_sup_mod->tcpdata_info_cnt; i++) { tcpdata_info_t *tcpdata_info_tmp = &tcpack_sup_mod->tcpdata_info_tbl[i]; DHD_TRACE(("%s %d: data info[%d], IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR " TCP port %d %d\n", __FUNCTION__, __LINE__, i, IPV4_ADDR_TO_STR(ntoh32_ua(tcpdata_info_tmp->src_ip_addr)), IPV4_ADDR_TO_STR(ntoh32_ua(tcpdata_info_tmp->dst_ip_addr)), ntoh16_ua(tcpdata_info_tmp->src_tcp_port), ntoh16_ua(tcpdata_info_tmp->dst_tcp_port))); /* If either IP address or TCP port number does not match, skip. */ if (memcmp(&ip_hdr[IPV4_SRC_IP_OFFSET], tcpdata_info_tmp->dst_ip_addr, IPV4_ADDR_LEN) == 0 && memcmp(&ip_hdr[IPV4_DEST_IP_OFFSET], tcpdata_info_tmp->src_ip_addr, IPV4_ADDR_LEN) == 0 && memcmp(&tcp_hdr[TCP_SRC_PORT_OFFSET], tcpdata_info_tmp->dst_tcp_port, TCP_PORT_LEN) == 0 && memcmp(&tcp_hdr[TCP_DEST_PORT_OFFSET], tcpdata_info_tmp->src_tcp_port, TCP_PORT_LEN) == 0) { tcpdata_info = tcpdata_info_tmp; break; } } if (tcpdata_info == NULL) { DHD_TRACE(("%s %d: no tcpdata_info!\n", __FUNCTION__, __LINE__)); goto exit; } if (tcpdata_info->tdata_psh_info_head == NULL) { DHD_TRACE(("%s %d: No PSH DATA to be acked!\n", __FUNCTION__, __LINE__)); } while ((tdata_psh_info = tcpdata_info->tdata_psh_info_head)) { if (IS_TCPSEQ_GE(tcp_ack_num, tdata_psh_info->end_seq)) { DHD_TRACE(("%s %d: PSH ACKED! %u >= %u\n", __FUNCTION__, __LINE__, tcp_ack_num, tdata_psh_info->end_seq)); tcpdata_info->tdata_psh_info_head = tdata_psh_info->next; tdata_psh_info->next = NULL; _tdata_psh_info_pool_enq(tcpack_sup_mod, tdata_psh_info); ret = TRUE; } else break; } if (tdata_psh_info == NULL) tcpdata_info->tdata_psh_info_tail = NULL; #ifdef DHDTCPACK_SUP_DBG DHD_TRACE(("%s %d: PSH INFO ENQ %d\n", __FUNCTION__, __LINE__, tcpack_sup_mod->psh_info_enq_num)); #endif /* DHDTCPACK_SUP_DBG */ exit: return ret; }
/* Function to execute combined scan */ int dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, uchar scan_fr) { int err = -1; char iovbuf[128]; int k, i; wl_pfn_param_t pfn_param; wl_pfn_t pfn_element; DHD_TRACE(("%s nssid=%d nchan=%d\n", __FUNCTION__, nssid, scan_fr)); if ((!dhd) && (!ssids_local)) { DHD_ERROR(("%s error exit\n", __FUNCTION__)); err = -1; } /* Check for broadcast ssid */ for (k = 0; k < nssid; k++) { if (!ssids_local[k].SSID_len) { DHD_ERROR(("%d: Broadcast SSID is ilegal for PNO setting\n", k)); return err; } } /* #define PNO_DUMP 1 */ #ifdef PNO_DUMP { int j; for (j = 0; j < nssid; j++) { DHD_ERROR(("%d: scan for %s size =%d\n", j, ssids_local[j].SSID, ssids_local[j].SSID_len)); } } #endif /* PNO_DUMP */ /* clean up everything */ if ((err = dhd_pno_clean(dhd)) < 0) { DHD_ERROR(("%s failed error=%d\n", __FUNCTION__, err)); return err; } memset(&pfn_param, 0, sizeof(pfn_param)); memset(&pfn_element, 0, sizeof(pfn_element)); /* set pfn parameters */ pfn_param.version = htod32(PFN_VERSION); pfn_param.flags = htod16((PFN_LIST_ORDER << SORT_CRITERIA_BIT)); /* set up pno scan fr */ if (scan_fr != 0) pfn_param.scan_freq = htod32(scan_fr); bcm_mkiovar("pfn_set", (char *)&pfn_param, sizeof(pfn_param), iovbuf, sizeof(iovbuf)); dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); /* set all pfn ssid */ for (i = 0; i < nssid; i++) { pfn_element.bss_type = htod32(DOT11_BSSTYPE_INFRASTRUCTURE); pfn_element.auth = (DOT11_OPEN_SYSTEM); pfn_element.wpa_auth = htod32(WPA_AUTH_PFN_ANY); pfn_element.wsec = htod32(0); pfn_element.infra = htod32(1); memcpy((char *)pfn_element.ssid.SSID, ssids_local[i].SSID, ssids_local[i].SSID_len); pfn_element.ssid.SSID_len = ssids_local[i].SSID_len; if ((err = bcm_mkiovar("pfn_add", (char *)&pfn_element, sizeof(pfn_element), iovbuf, sizeof(iovbuf))) > 0) { if ((err = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) { DHD_ERROR(("%s failed for i=%d error=%d\n", __FUNCTION__, i, err)); return err; } } else DHD_ERROR(("%s failed err=%d\n", __FUNCTION__, err)); } /* Enable PNO */ /* dhd_pno_enable(dhd, 1); */ return err; }
bool dhd_tcpdata_info_get(dhd_pub_t *dhdp, void *pkt) { uint8 *ether_hdr; /* Ethernet header of the new packet */ uint16 ether_type; /* Ethernet type of the new packet */ uint8 *ip_hdr; /* IP header of the new packet */ uint8 *tcp_hdr; /* TCP header of the new packet */ uint32 ip_hdr_len; /* IP header length of the new packet */ uint32 cur_framelen; uint16 ip_total_len; /* Total length of IP packet for the new packet */ uint32 tcp_hdr_len; /* TCP header length of the new packet */ uint32 tcp_seq_num; /* TCP sequence number of the new packet */ uint16 tcp_data_len; /* TCP DATA length that excludes IP and TCP headers */ uint32 end_tcp_seq_num; /* TCP seq number of the last byte in the new packet */ tcpack_sup_module_t *tcpack_sup_mod; tcpdata_info_t *tcpdata_info = NULL; tdata_psh_info_t *tdata_psh_info; int i; bool ret = FALSE; unsigned long flags; if (dhdp->tcpack_sup_mode != TCPACK_SUP_DELAYTX) goto exit; ether_hdr = PKTDATA(dhdp->osh, pkt); cur_framelen = PKTLEN(dhdp->osh, pkt); ether_type = ether_hdr[12] << 8 | ether_hdr[13]; if (ether_type != ETHER_TYPE_IP) { DHD_TRACE(("%s %d: Not a IP packet 0x%x\n", __FUNCTION__, __LINE__, ether_type)); goto exit; } DHD_TRACE(("%s %d: IP pkt! 0x%x\n", __FUNCTION__, __LINE__, ether_type)); ip_hdr = ether_hdr + ETHER_HDR_LEN; cur_framelen -= ETHER_HDR_LEN; ASSERT(cur_framelen >= IPV4_MIN_HEADER_LEN); ip_hdr_len = IPV4_HLEN(ip_hdr); if (IP_VER(ip_hdr) != IP_VER_4 || IPV4_PROT(ip_hdr) != IP_PROT_TCP) { DHD_TRACE(("%s %d: Not IPv4 nor TCP! ip ver %d, prot %d\n", __FUNCTION__, __LINE__, IP_VER(ip_hdr), IPV4_PROT(ip_hdr))); goto exit; } tcp_hdr = ip_hdr + ip_hdr_len; cur_framelen -= ip_hdr_len; ASSERT(cur_framelen >= TCP_MIN_HEADER_LEN); DHD_TRACE(("%s %d: TCP pkt!\n", __FUNCTION__, __LINE__)); ip_total_len = ntoh16_ua(&ip_hdr[IPV4_PKTLEN_OFFSET]); tcp_hdr_len = 4 * TCP_HDRLEN(tcp_hdr[TCP_HLEN_OFFSET]); /* This packet is mere TCP ACK, so do nothing */ if (ip_total_len == ip_hdr_len + tcp_hdr_len) { DHD_TRACE(("%s %d: Do nothing for no data TCP ACK\n", __FUNCTION__, __LINE__)); goto exit; } ASSERT(ip_total_len > ip_hdr_len + tcp_hdr_len); if ((tcp_hdr[TCP_FLAGS_OFFSET] & TCP_FLAG_PSH) == 0) { DHD_TRACE(("%s %d: Not interested TCP DATA packet\n", __FUNCTION__, __LINE__)); goto exit; } DHD_TRACE(("%s %d: TCP DATA with nonzero DATA length" " IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR" TCP port %d %d, flag 0x%x\n", __FUNCTION__, __LINE__, IPV4_ADDR_TO_STR(ntoh32_ua(&ip_hdr[IPV4_SRC_IP_OFFSET])), IPV4_ADDR_TO_STR(ntoh32_ua(&ip_hdr[IPV4_DEST_IP_OFFSET])), ntoh16_ua(&tcp_hdr[TCP_SRC_PORT_OFFSET]), ntoh16_ua(&tcp_hdr[TCP_DEST_PORT_OFFSET]), tcp_hdr[TCP_FLAGS_OFFSET])); flags = dhd_os_tcpacklock(dhdp); tcpack_sup_mod = dhdp->tcpack_sup_module; if (!tcpack_sup_mod) { DHD_ERROR(("%s %d: tcpack suppress module NULL!!\n", __FUNCTION__, __LINE__)); ret = BCME_ERROR; dhd_os_tcpackunlock(dhdp, flags); goto exit; } /* Look for tcpdata_info that has the same ip src/dst addrs and tcp src/dst ports */ i = 0; while (i < tcpack_sup_mod->tcpdata_info_cnt) { tcpdata_info_t *tdata_info_tmp = &tcpack_sup_mod->tcpdata_info_tbl[i]; uint32 now_in_ms = OSL_SYSUPTIME(); DHD_TRACE(("%s %d: data info[%d], IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR " TCP port %d %d\n", __FUNCTION__, __LINE__, i, IPV4_ADDR_TO_STR(ntoh32_ua(tdata_info_tmp->src_ip_addr)), IPV4_ADDR_TO_STR(ntoh32_ua(tdata_info_tmp->dst_ip_addr)), ntoh16_ua(tdata_info_tmp->src_tcp_port), ntoh16_ua(tdata_info_tmp->dst_tcp_port))); /* If both IP address and TCP port number match, we found it so break. */ if (memcmp(&ip_hdr[IPV4_SRC_IP_OFFSET], tdata_info_tmp->src_ip_addr, IPV4_ADDR_LEN) == 0 && memcmp(&ip_hdr[IPV4_DEST_IP_OFFSET], tdata_info_tmp->dst_ip_addr, IPV4_ADDR_LEN) == 0 && memcmp(&tcp_hdr[TCP_SRC_PORT_OFFSET], tdata_info_tmp->src_tcp_port, TCP_PORT_LEN) == 0 && memcmp(&tcp_hdr[TCP_DEST_PORT_OFFSET], tdata_info_tmp->dst_tcp_port, TCP_PORT_LEN) == 0) { tcpdata_info = tdata_info_tmp; tcpdata_info->last_used_time = now_in_ms; break; } if (now_in_ms - tdata_info_tmp->last_used_time > TCPDATA_INFO_TIMEOUT) { tdata_psh_info_t *tdata_psh_info_tmp; tcpdata_info_t *last_tdata_info; while ((tdata_psh_info_tmp = tdata_info_tmp->tdata_psh_info_head)) { tdata_info_tmp->tdata_psh_info_head = tdata_psh_info_tmp->next; tdata_psh_info_tmp->next = NULL; DHD_TRACE(("%s %d: Clean tdata_psh_info(end_seq %u)!\n", __FUNCTION__, __LINE__, tdata_psh_info_tmp->end_seq)); _tdata_psh_info_pool_enq(tcpack_sup_mod, tdata_psh_info_tmp); } #ifdef DHDTCPACK_SUP_DBG DHD_ERROR(("%s %d: PSH INFO ENQ %d\n", __FUNCTION__, __LINE__, tcpack_sup_mod->psh_info_enq_num)); #endif /* DHDTCPACK_SUP_DBG */ tcpack_sup_mod->tcpdata_info_cnt--; ASSERT(tcpack_sup_mod->tcpdata_info_cnt >= 0); last_tdata_info = &tcpack_sup_mod->tcpdata_info_tbl[tcpack_sup_mod->tcpdata_info_cnt]; if (i < tcpack_sup_mod->tcpdata_info_cnt) { ASSERT(last_tdata_info != tdata_info_tmp); bcopy(last_tdata_info, tdata_info_tmp, sizeof(tcpdata_info_t)); } bzero(last_tdata_info, sizeof(tcpdata_info_t)); DHD_INFO(("%s %d: tcpdata_info(idx %d) is aged out. ttl cnt is now %d\n", __FUNCTION__, __LINE__, i, tcpack_sup_mod->tcpdata_info_cnt)); /* Don't increase "i" here, so that the prev last tcpdata_info is checked */ } else i++; } tcp_seq_num = ntoh32_ua(&tcp_hdr[TCP_SEQ_NUM_OFFSET]); tcp_data_len = ip_total_len - ip_hdr_len - tcp_hdr_len; end_tcp_seq_num = tcp_seq_num + tcp_data_len; if (tcpdata_info == NULL) { ASSERT(i == tcpack_sup_mod->tcpdata_info_cnt); if (i >= TCPDATA_INFO_MAXNUM) { DHD_TRACE(("%s %d: tcp_data_info_tbl FULL! %d %d" " IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR" TCP port %d %d\n", __FUNCTION__, __LINE__, i, tcpack_sup_mod->tcpdata_info_cnt, IPV4_ADDR_TO_STR(ntoh32_ua(&ip_hdr[IPV4_SRC_IP_OFFSET])), IPV4_ADDR_TO_STR(ntoh32_ua(&ip_hdr[IPV4_DEST_IP_OFFSET])), ntoh16_ua(&tcp_hdr[TCP_SRC_PORT_OFFSET]), ntoh16_ua(&tcp_hdr[TCP_DEST_PORT_OFFSET]))); dhd_os_tcpackunlock(dhdp, flags); goto exit; } tcpdata_info = &tcpack_sup_mod->tcpdata_info_tbl[i]; /* No TCP flow with the same IP addr and TCP port is found * in tcp_data_info_tbl. So add this flow to the table. */ DHD_INFO(("%s %d: Add data info to tbl[%d]: IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR " TCP port %d %d\n", __FUNCTION__, __LINE__, tcpack_sup_mod->tcpdata_info_cnt, IPV4_ADDR_TO_STR(ntoh32_ua(&ip_hdr[IPV4_SRC_IP_OFFSET])), IPV4_ADDR_TO_STR(ntoh32_ua(&ip_hdr[IPV4_DEST_IP_OFFSET])), ntoh16_ua(&tcp_hdr[TCP_SRC_PORT_OFFSET]), ntoh16_ua(&tcp_hdr[TCP_DEST_PORT_OFFSET]))); bcopy(&ip_hdr[IPV4_SRC_IP_OFFSET], tcpdata_info->src_ip_addr, IPV4_ADDR_LEN); bcopy(&ip_hdr[IPV4_DEST_IP_OFFSET], tcpdata_info->dst_ip_addr, IPV4_ADDR_LEN); bcopy(&tcp_hdr[TCP_SRC_PORT_OFFSET], tcpdata_info->src_tcp_port, TCP_PORT_LEN); bcopy(&tcp_hdr[TCP_DEST_PORT_OFFSET], tcpdata_info->dst_tcp_port, TCP_PORT_LEN); tcpdata_info->last_used_time = OSL_SYSUPTIME(); tcpack_sup_mod->tcpdata_info_cnt++; } ASSERT(tcpdata_info != NULL); tdata_psh_info = _tdata_psh_info_pool_deq(tcpack_sup_mod); #ifdef DHDTCPACK_SUP_DBG DHD_TRACE(("%s %d: PSH INFO ENQ %d\n", __FUNCTION__, __LINE__, tcpack_sup_mod->psh_info_enq_num)); #endif /* DHDTCPACK_SUP_DBG */ if (tdata_psh_info == NULL) { DHD_ERROR(("%s %d: No more free tdata_psh_info!!\n", __FUNCTION__, __LINE__)); ret = BCME_ERROR; dhd_os_tcpackunlock(dhdp, flags); goto exit; } tdata_psh_info->end_seq = end_tcp_seq_num; #if defined(DEBUG_COUNTER) && defined(DHDTCPACK_SUP_DBG) tack_tbl.cnt[4]++; #endif /* DEBUG_COUNTER && DHDTCPACK_SUP_DBG */ DHD_TRACE(("%s %d: TCP PSH DATA recvd! end seq %u\n", __FUNCTION__, __LINE__, tdata_psh_info->end_seq)); ASSERT(tdata_psh_info->next == NULL); if (tcpdata_info->tdata_psh_info_head == NULL) tcpdata_info->tdata_psh_info_head = tdata_psh_info; else { ASSERT(tcpdata_info->tdata_psh_info_tail); tcpdata_info->tdata_psh_info_tail->next = tdata_psh_info; } tcpdata_info->tdata_psh_info_tail = tdata_psh_info; dhd_os_tcpackunlock(dhdp, flags); exit: return ret; }
/* * SSIDs list parsing from cscan tlv list */ int wl_iw_parse_ssid_list_tlv(char** list_str, wlc_ssid_t* ssid, int max, int *bytes_left) { char* str = *list_str; int idx = 0; if ((list_str == NULL) || (*list_str == NULL) || (*bytes_left < 0)) { DHD_ERROR(("%s error paramters\n", __FUNCTION__)); return -1; } 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; 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; }
static int dhd_wifi_platform_load_sdio(void) { int i; int err = 0; wifi_adapter_info_t *adapter; BCM_REFERENCE(i); BCM_REFERENCE(adapter); /* Sanity check on the module parameters * - Both watchdog and DPC as tasklets are ok * - If both watchdog and DPC are threads, TX must be deferred */ if (!(dhd_watchdog_prio < 0 && dhd_dpc_prio < 0) && !(dhd_watchdog_prio >= 0 && dhd_dpc_prio >= 0 && dhd_deferred_tx)) return -EINVAL; #if defined(BCMLXSDMMC) if (dhd_wifi_platdata == NULL) { DHD_ERROR(("DHD wifi platform data is required for Android build\n")); return -EINVAL; } sema_init(&dhd_registration_sem, 0); /* power up all adapters */ for (i = 0; i < dhd_wifi_platdata->num_adapters; i++) { bool chip_up = FALSE; int retry = POWERUP_MAX_RETRY; struct semaphore dhd_chipup_sem; adapter = &dhd_wifi_platdata->adapters[i]; DHD_ERROR(("Power-up adapter '%s'\n", adapter->name)); DHD_INFO((" - irq %d [flags %d], firmware: %s, nvram: %s\n", adapter->irq_num, adapter->intr_flags, adapter->fw_path, adapter->nv_path)); DHD_INFO((" - bus type %d, bus num %d, slot num %d\n\n", adapter->bus_type, adapter->bus_num, adapter->slot_num)); do { sema_init(&dhd_chipup_sem, 0); err = dhd_bus_reg_sdio_notify(&dhd_chipup_sem); if (err) { DHD_ERROR(("%s dhd_bus_reg_sdio_notify fail(%d)\n\n", __FUNCTION__, err)); return err; } err = wifi_platform_set_power(adapter, TRUE, WIFI_TURNON_DELAY); if (err) { /* WL_REG_ON state unknown, Power off forcely */ wifi_platform_set_power(adapter, FALSE, WIFI_TURNOFF_DELAY); continue; } else { wifi_platform_bus_enumerate(adapter, TRUE); err = 0; } if (down_timeout(&dhd_chipup_sem, msecs_to_jiffies(POWERUP_WAIT_MS)) == 0) { dhd_bus_unreg_sdio_notify(); chip_up = TRUE; break; } DHD_ERROR(("failed to power up %s, %d retry left\n", adapter->name, retry)); dhd_bus_unreg_sdio_notify(); wifi_platform_set_power(adapter, FALSE, WIFI_TURNOFF_DELAY); wifi_platform_bus_enumerate(adapter, FALSE); } while (retry--); if (!chip_up) { DHD_ERROR(("failed to power up %s, max retry reached**\n", adapter->name)); return -ENODEV; } } err = dhd_bus_register(); if (err) { DHD_ERROR(("%s: sdio_register_driver failed\n", __FUNCTION__)); goto fail; } /* * Wait till MMC sdio_register_driver callback called and made driver attach. * It's needed to make sync up exit from dhd insmod and * Kernel MMC sdio device callback registration */ err = down_timeout(&dhd_registration_sem, msecs_to_jiffies(DHD_REGISTRATION_TIMEOUT)); if (err) { DHD_ERROR(("%s: sdio_register_driver timeout or error \n", __FUNCTION__)); dhd_bus_unregister(); goto fail; } return err; fail: /* power down all adapters */ for (i = 0; i < dhd_wifi_platdata->num_adapters; i++) { adapter = &dhd_wifi_platdata->adapters[i]; wifi_platform_set_power(adapter, FALSE, WIFI_TURNOFF_DELAY); wifi_platform_bus_enumerate(adapter, FALSE); } #else /* x86 bring-up PC needs no power-up operations */ err = dhd_bus_register(); #endif return err; }
void sec_control_pm(dhd_pub_t *dhd, uint *power_mode) { struct file *fp = NULL; char *filepath = PSMINFO; char power_val = 0; char iovbuf[WL_EVENTING_MASK_LEN + 12]; int ret = 0; #ifdef DHD_ENABLE_LPC uint32 lpc = 0; #endif /* DHD_ENABLE_LPC */ g_pm_control = FALSE; fp = filp_open(filepath, O_RDONLY, 0); if (IS_ERR(fp) || (fp == NULL)) { /* Enable PowerSave Mode */ dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)power_mode, sizeof(uint), TRUE, 0); DHD_ERROR(("[WIFI_SEC] %s: /data/.psm.info doesn't exist" " so set PM to %d\n", __FUNCTION__, *power_mode)); return; } else { kernel_read(fp, fp->f_pos, &power_val, 1); DHD_ERROR(("[WIFI_SEC] %s: POWER_VAL = %c \r\n", __FUNCTION__, power_val)); if (power_val == '0') { #ifdef ROAM_ENABLE uint roamvar = 1; #endif uint32 ocl_enable = 0; uint32 wl_updown = 1; *power_mode = PM_OFF; /* Disable PowerSave Mode */ dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)power_mode, sizeof(uint), TRUE, 0); /* Turn off MPC in AP mode */ bcm_mkiovar("mpc", (char *)power_mode, 4, iovbuf, sizeof(iovbuf)); dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); g_pm_control = TRUE; #ifdef ROAM_ENABLE /* Roaming off of dongle */ bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf)); dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); #endif #ifdef DHD_ENABLE_LPC /* Set lpc 0 */ bcm_mkiovar("lpc", (char *)&lpc, 4, iovbuf, sizeof(iovbuf)); if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) { DHD_ERROR(("[WIFI_SEC] %s: Set lpc failed %d\n", __FUNCTION__, ret)); } #endif /* DHD_ENABLE_LPC */ /* Disable ocl */ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_UP, (char *)&wl_updown, sizeof(wl_updown), TRUE, 0)) < 0) { DHD_ERROR(("[WIFI_SEC] %s: WLC_UP faield %d\n", __FUNCTION__, ret)); } bcm_mkiovar("ocl_enable", (char *)&ocl_enable, 4, iovbuf, sizeof(iovbuf)); if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) { DHD_ERROR(("[WIFI_SEC] %s: Set ocl_enable %d failed %d\n", __FUNCTION__, ocl_enable, ret)); } else { DHD_ERROR(("[WIFI_SEC] %s: Set ocl_enable %d succeeded %d\n", __FUNCTION__, ocl_enable, ret)); } if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_DOWN, (char *)&wl_updown, sizeof(wl_updown), TRUE, 0)) < 0) { DHD_ERROR(("[WIFI_SEC] %s: WLC_DOWN faield %d\n", __FUNCTION__, ret)); } } else { dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)power_mode, sizeof(uint), TRUE, 0); } } if (fp) filp_close(fp, NULL); }