struct sta_info *r8712_get_bcmc_stainfo(struct _adapter *padapter) { struct sta_priv *pstapriv = &padapter->stapriv; u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; return r8712_get_stainfo(pstapriv, bc_addr); }
/* *r8712_free_assoc_resources: the caller has to lock pmlmepriv->lock */ void r8712_free_assoc_resources(struct _adapter *adapter) { unsigned long irqL; struct wlan_network *pwlan = NULL; struct mlme_priv *pmlmepriv = &adapter->mlmepriv; struct sta_priv *pstapriv = &adapter->stapriv; struct wlan_network *tgt_network = &pmlmepriv->cur_network; pwlan = r8712_find_network(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress); if (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_AP_STATE)) { struct sta_info *psta; psta = r8712_get_stainfo(&adapter->stapriv, tgt_network->network.MacAddress); spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL); r8712_free_stainfo(adapter, psta); spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL); } if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE)) r8712_free_all_stainfo(adapter); if (pwlan) pwlan->fixed = false; if (((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) && (adapter->stapriv.asoc_sta_count == 1))) free_network_nolock(pmlmepriv, pwlan); }
void r8712_stadel_event_callback(struct _adapter *adapter, u8 *pbuf) { unsigned long irqL, irqL2; struct sta_info *psta; struct wlan_network *pwlan = NULL; struct wlan_bssid_ex *pdev_network = NULL; u8 *pibss = NULL; struct mlme_priv *pmlmepriv = &adapter->mlmepriv; struct stadel_event *pstadel = (struct stadel_event *)pbuf; struct sta_priv *pstapriv = &adapter->stapriv; struct wlan_network *tgt_network = &pmlmepriv->cur_network; spin_lock_irqsave(&pmlmepriv->lock, irqL2); if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) { r8712_ind_disconnect(adapter); r8712_free_assoc_resources(adapter); } if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE)) { psta = r8712_get_stainfo(&adapter->stapriv, pstadel->macaddr); spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL); r8712_free_stainfo(adapter, psta); spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL); if (adapter->stapriv.asoc_sta_count == 1) { /*a sta + bc/mc_stainfo (not Ibss_stainfo) */ pwlan = r8712_find_network(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress); if (pwlan) { pwlan->fixed = false; free_network_nolock(pmlmepriv, pwlan); } /*re-create ibss*/ pdev_network = &(adapter->registrypriv.dev_network); pibss = adapter->registrypriv.dev_network.MacAddress; memcpy(pdev_network, &tgt_network->network, r8712_get_ndis_wlan_bssid_ex_sz(&tgt_network-> network)); memset(&pdev_network->Ssid, 0, sizeof(struct ndis_802_11_ssid)); memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid)); r8712_update_registrypriv_dev_network(adapter); r8712_generate_random_ibss(pibss); if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { _clr_fwstate_(pmlmepriv, WIFI_ADHOC_STATE); set_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE); } } } spin_unlock_irqrestore(&pmlmepriv->lock, irqL2); }
/* * Will enqueue pxmitframe to the proper queue, and indicate it * to xx_pending list..... */ sint r8712_xmit_classifier(struct _adapter *padapter, struct xmit_frame *pxmitframe) { unsigned long irqL0; struct __queue *pstapending; struct sta_info *psta; struct tx_servq *ptxservq; struct pkt_attrib *pattrib = &pxmitframe->attrib; struct sta_priv *pstapriv = &padapter->stapriv; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; sint bmcst = IS_MCAST(pattrib->ra); if (pattrib->psta) { psta = pattrib->psta; } else { if (bmcst) { psta = r8712_get_bcmc_stainfo(padapter); } else { if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) psta = r8712_get_stainfo(pstapriv, get_bssid(pmlmepriv)); else psta = r8712_get_stainfo(pstapriv, pattrib->ra); } } if (psta == NULL) return _FAIL; ptxservq = get_sta_pending(padapter, &pstapending, psta, pattrib->priority); spin_lock_irqsave(&pstapending->lock, irqL0); if (list_empty(&ptxservq->tx_pending)) list_add_tail(&ptxservq->tx_pending, &pstapending->queue); list_add_tail(&pxmitframe->list, &ptxservq->sta_pending.queue); ptxservq->qcnt++; spin_unlock_irqrestore(&pstapending->lock, irqL0); return _SUCCESS; }
void r8712_setstaKey_cmdrsp_callback(struct _adapter *padapter, struct cmd_obj *pcmd) { struct sta_priv *pstapriv = &padapter->stapriv; struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *) (pcmd->rsp); struct sta_info *psta = r8712_get_stainfo(pstapriv, psetstakey_rsp->addr); if (psta == NULL) goto exit; psta->aid = psta->mac_id = psetstakey_rsp->keyid; /*CAM_ID(CAM_ENTRY)*/ exit: r8712_free_cmd_obj(pcmd); }
/* When the Netgear 3500 AP is with WPA2PSK-AES mode, it will send * the ADDBA req frame with start seq control = 0 to wifi client after * the WPA handshake and the seqence number of following data packet * will be 0. In this case, the Rx reorder sequence is not longer than 0 * and the WiFi client will drop the data with seq number 0. * So, the 8712 firmware has to inform driver with receiving the * ADDBA-Req frame so that the driver can reset the * sequence value of Rx reorder contorl. */ void r8712_got_addbareq_event_callback(struct _adapter *adapter, u8 *pbuf) { struct ADDBA_Req_Report_parm *pAddbareq_pram = (struct ADDBA_Req_Report_parm *)pbuf; struct sta_info *psta; struct sta_priv *pstapriv = &adapter->stapriv; struct recv_reorder_ctrl *precvreorder_ctrl = NULL; printk(KERN_INFO "r8712u: [%s] mac = %pM, seq = %d, tid = %d\n", __func__, pAddbareq_pram->MacAddress, pAddbareq_pram->StartSeqNum, pAddbareq_pram->tid); psta = r8712_get_stainfo(pstapriv, pAddbareq_pram->MacAddress); if (psta) { precvreorder_ctrl = &psta->recvreorder_ctrl[pAddbareq_pram->tid]; /* set the indicate_seq to 0xffff so that the rx reorder * can store any following data packet. */ precvreorder_ctrl->indicate_seq = 0xffff; } }
void r8712_stassoc_event_callback(struct _adapter *adapter, u8 *pbuf) { unsigned long irqL; struct sta_info *psta; struct mlme_priv *pmlmepriv = &(adapter->mlmepriv); struct stassoc_event *pstassoc = (struct stassoc_event *)pbuf; /* to do: */ if (r8712_access_ctrl(&adapter->acl_list, pstassoc->macaddr) == false) return; psta = r8712_get_stainfo(&adapter->stapriv, pstassoc->macaddr); if (psta != NULL) { /*the sta have been in sta_info_queue => do nothing *(between drv has received this event before and * fw have not yet to set key to CAM_ENTRY) */ return; } psta = r8712_alloc_stainfo(&adapter->stapriv, pstassoc->macaddr); if (psta == NULL) return; /* to do : init sta_info variable */ psta->qos_option = 0; psta->mac_id = le32_to_cpu((uint)pstassoc->cam_id); /* psta->aid = (uint)pstassoc->cam_id; */ if (adapter->securitypriv.AuthAlgrthm == 2) psta->XPrivacy = adapter->securitypriv.PrivacyAlgrthm; psta->ieee8021x_blocked = false; spin_lock_irqsave(&pmlmepriv->lock, irqL); if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) || (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)) { if (adapter->stapriv.asoc_sta_count == 2) { /* a sta + bc/mc_stainfo (not Ibss_stainfo) */ r8712_indicate_connect(adapter); } } spin_unlock_irqrestore(&pmlmepriv->lock, irqL); }
void r8712_setassocsta_cmdrsp_callback(struct _adapter *padapter, struct cmd_obj *pcmd) { unsigned long irqL; struct sta_priv *pstapriv = &padapter->stapriv; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct set_assocsta_parm *passocsta_parm = (struct set_assocsta_parm *)(pcmd->parmbuf); struct set_assocsta_rsp *passocsta_rsp = (struct set_assocsta_rsp *) (pcmd->rsp); struct sta_info *psta = r8712_get_stainfo(pstapriv, passocsta_parm->addr); if (psta == NULL) return; psta->aid = psta->mac_id = passocsta_rsp->cam_id; spin_lock_irqsave(&pmlmepriv->lock, irqL); if ((check_fwstate(pmlmepriv, WIFI_MP_STATE)) && (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))) pmlmepriv->fw_state ^= _FW_UNDER_LINKING; set_fwstate(pmlmepriv, _FW_LINKED); spin_unlock_irqrestore(&pmlmepriv->lock, irqL); r8712_free_cmd_obj(pcmd); }
void r8712_createbss_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd) { unsigned long irqL; u8 timer_cancelled; struct sta_info *psta = NULL; struct wlan_network *pwlan = NULL; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct ndis_wlan_bssid_ex *pnetwork = (struct ndis_wlan_bssid_ex *) pcmd->parmbuf; struct wlan_network *tgt_network = &(pmlmepriv->cur_network); if (pcmd->res != H2C_SUCCESS) _set_timer(&pmlmepriv->assoc_timer, 1); _cancel_timer(&pmlmepriv->assoc_timer, &timer_cancelled); #ifdef __BIG_ENDIAN /* endian_convert */ pnetwork->Length = le32_to_cpu(pnetwork->Length); pnetwork->Ssid.SsidLength = le32_to_cpu(pnetwork->Ssid.SsidLength); pnetwork->Privacy = le32_to_cpu(pnetwork->Privacy); pnetwork->Rssi = le32_to_cpu(pnetwork->Rssi); pnetwork->NetworkTypeInUse = le32_to_cpu(pnetwork->NetworkTypeInUse); pnetwork->Configuration.ATIMWindow = le32_to_cpu(pnetwork-> Configuration.ATIMWindow); pnetwork->Configuration.DSConfig = le32_to_cpu(pnetwork-> Configuration.DSConfig); pnetwork->Configuration.FHConfig.DwellTime = le32_to_cpu(pnetwork-> Configuration.FHConfig.DwellTime); pnetwork->Configuration.FHConfig.HopPattern = le32_to_cpu(pnetwork-> Configuration.FHConfig.HopPattern); pnetwork->Configuration.FHConfig.HopSet = le32_to_cpu(pnetwork-> Configuration.FHConfig.HopSet); pnetwork->Configuration.FHConfig.Length = le32_to_cpu(pnetwork-> Configuration.FHConfig.Length); pnetwork->Configuration.Length = le32_to_cpu(pnetwork-> Configuration.Length); pnetwork->InfrastructureMode = le32_to_cpu(pnetwork-> InfrastructureMode); pnetwork->IELength = le32_to_cpu(pnetwork->IELength); #endif spin_lock_irqsave(&pmlmepriv->lock, irqL); if ((pmlmepriv->fw_state) & WIFI_AP_STATE) { psta = r8712_get_stainfo(&padapter->stapriv, pnetwork->MacAddress); if (!psta) { psta = r8712_alloc_stainfo(&padapter->stapriv, pnetwork->MacAddress); if (psta == NULL) goto createbss_cmd_fail; } r8712_indicate_connect(padapter); } else { pwlan = _r8712_alloc_network(pmlmepriv); if (pwlan == NULL) { pwlan = r8712_get_oldest_wlan_network( &pmlmepriv->scanned_queue); if (pwlan == NULL) goto createbss_cmd_fail; pwlan->last_scanned = jiffies; } else list_add_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue); pnetwork->Length = r8712_get_ndis_wlan_bssid_ex_sz(pnetwork); memcpy(&(pwlan->network), pnetwork, pnetwork->Length); pwlan->fixed = true; memcpy(&tgt_network->network, pnetwork, (r8712_get_ndis_wlan_bssid_ex_sz(pnetwork))); if (pmlmepriv->fw_state & _FW_UNDER_LINKING) pmlmepriv->fw_state ^= _FW_UNDER_LINKING; /* we will set _FW_LINKED when there is one more sat to * join us (stassoc_event_callback) */ } createbss_cmd_fail: spin_unlock_irqrestore(&pmlmepriv->lock, irqL); r8712_free_cmd_obj(pcmd); }
/*Notes: *pnetwork : returns from r8712_joinbss_event_callback *ptarget_wlan: found from scanned_queue *if join_res > 0, for (fw_state==WIFI_STATION_STATE), we check if * "ptarget_sta" & "ptarget_wlan" exist. *if join_res > 0, for (fw_state==WIFI_ADHOC_STATE), we only check * if "ptarget_wlan" exist. *if join_res > 0, update "cur_network->network" from * "pnetwork->network" if (ptarget_wlan !=NULL). */ void r8712_joinbss_event_callback(struct _adapter *adapter, u8 *pbuf) { unsigned long irqL = 0, irqL2; u8 timer_cancelled; struct sta_info *ptarget_sta = NULL, *pcur_sta = NULL; struct sta_priv *pstapriv = &adapter->stapriv; struct mlme_priv *pmlmepriv = &adapter->mlmepriv; struct wlan_network *cur_network = &pmlmepriv->cur_network; struct wlan_network *pcur_wlan = NULL, *ptarget_wlan = NULL; unsigned int the_same_macaddr = false; struct wlan_network *pnetwork; if (sizeof(struct list_head) == 4 * sizeof(u32)) { pnetwork = (struct wlan_network *) _malloc(sizeof(struct wlan_network)); memcpy((u8 *)pnetwork+16, (u8 *)pbuf + 8, sizeof(struct wlan_network) - 16); } else pnetwork = (struct wlan_network *)pbuf; #ifdef __BIG_ENDIAN /* endian_convert */ pnetwork->join_res = le32_to_cpu(pnetwork->join_res); pnetwork->network_type = le32_to_cpu(pnetwork->network_type); pnetwork->network.Length = le32_to_cpu(pnetwork->network.Length); pnetwork->network.Ssid.SsidLength = le32_to_cpu(pnetwork->network.Ssid.SsidLength); pnetwork->network.Privacy = le32_to_cpu(pnetwork->network.Privacy); pnetwork->network.Rssi = le32_to_cpu(pnetwork->network.Rssi); pnetwork->network.NetworkTypeInUse = le32_to_cpu(pnetwork->network.NetworkTypeInUse); pnetwork->network.Configuration.ATIMWindow = le32_to_cpu(pnetwork->network.Configuration.ATIMWindow); pnetwork->network.Configuration.BeaconPeriod = le32_to_cpu(pnetwork->network.Configuration.BeaconPeriod); pnetwork->network.Configuration.DSConfig = le32_to_cpu(pnetwork->network.Configuration.DSConfig); pnetwork->network.Configuration.FHConfig.DwellTime = le32_to_cpu(pnetwork->network.Configuration.FHConfig. DwellTime); pnetwork->network.Configuration.FHConfig.HopPattern = le32_to_cpu(pnetwork->network.Configuration. FHConfig.HopPattern); pnetwork->network.Configuration.FHConfig.HopSet = le32_to_cpu(pnetwork->network.Configuration.FHConfig.HopSet); pnetwork->network.Configuration.FHConfig.Length = le32_to_cpu(pnetwork->network.Configuration.FHConfig.Length); pnetwork->network.Configuration.Length = le32_to_cpu(pnetwork->network.Configuration.Length); pnetwork->network.InfrastructureMode = le32_to_cpu(pnetwork->network.InfrastructureMode); pnetwork->network.IELength = le32_to_cpu(pnetwork->network.IELength); #endif the_same_macaddr = !memcmp(pnetwork->network.MacAddress, cur_network->network.MacAddress, ETH_ALEN); pnetwork->network.Length = r8712_get_ndis_wlan_bssid_ex_sz(&pnetwork->network); spin_lock_irqsave(&pmlmepriv->lock, irqL); if (pnetwork->network.Length > sizeof(struct wlan_bssid_ex)) goto ignore_joinbss_callback; if (pnetwork->join_res > 0) { if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true) { /*s1. find ptarget_wlan*/ if (check_fwstate(pmlmepriv, _FW_LINKED) == true) { if (the_same_macaddr == true) ptarget_wlan = r8712_find_network(&pmlmepriv-> scanned_queue, cur_network->network.MacAddress); else { pcur_wlan = r8712_find_network(&pmlmepriv-> scanned_queue, cur_network->network.MacAddress); pcur_wlan->fixed = false; pcur_sta = r8712_get_stainfo(pstapriv, cur_network->network.MacAddress); spin_lock_irqsave(&pstapriv-> sta_hash_lock, irqL2); r8712_free_stainfo(adapter, pcur_sta); spin_unlock_irqrestore(&(pstapriv-> sta_hash_lock), irqL2); ptarget_wlan = r8712_find_network(&pmlmepriv-> scanned_queue, pnetwork->network. MacAddress); if (ptarget_wlan) ptarget_wlan->fixed = true; } } else { ptarget_wlan = r8712_find_network(&pmlmepriv-> scanned_queue, pnetwork->network.MacAddress); if (ptarget_wlan) ptarget_wlan->fixed = true; } if (ptarget_wlan == NULL) { if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) pmlmepriv->fw_state ^= _FW_UNDER_LINKING; goto ignore_joinbss_callback; } /*s2. find ptarget_sta & update ptarget_sta*/ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { if (the_same_macaddr == true) { ptarget_sta = r8712_get_stainfo(pstapriv, pnetwork->network.MacAddress); if (ptarget_sta == NULL) ptarget_sta = r8712_alloc_stainfo(pstapriv, pnetwork->network.MacAddress); } else ptarget_sta = r8712_alloc_stainfo(pstapriv, pnetwork->network.MacAddress); if (ptarget_sta) /*update ptarget_sta*/ { ptarget_sta->aid = pnetwork->join_res; ptarget_sta->qos_option = 1; ptarget_sta->mac_id = 5; if (adapter->securitypriv. AuthAlgrthm == 2) { adapter->securitypriv. binstallGrpkey = false; adapter->securitypriv. busetkipkey = false; adapter->securitypriv. bgrpkey_handshake = false; ptarget_sta->ieee8021x_blocked = true; ptarget_sta->XPrivacy = adapter->securitypriv. PrivacyAlgrthm; memset((u8 *)&ptarget_sta-> x_UncstKey, 0, sizeof(union Keytype)); memset((u8 *)&ptarget_sta-> tkiprxmickey, 0, sizeof(union Keytype)); memset((u8 *)&ptarget_sta-> tkiptxmickey, 0, sizeof(union Keytype)); memset((u8 *)&ptarget_sta-> txpn, 0, sizeof(union pn48)); memset((u8 *)&ptarget_sta-> rxpn, 0, sizeof(union pn48)); } } else { if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) pmlmepriv->fw_state ^= _FW_UNDER_LINKING; goto ignore_joinbss_callback; } } /*s3. update cur_network & indicate connect*/ memcpy(&cur_network->network, &pnetwork->network, pnetwork->network.Length); cur_network->aid = pnetwork->join_res; /*update fw_state will clr _FW_UNDER_LINKING*/ switch (pnetwork->network.InfrastructureMode) { case Ndis802_11Infrastructure: pmlmepriv->fw_state = WIFI_STATION_STATE; break; case Ndis802_11IBSS: pmlmepriv->fw_state = WIFI_ADHOC_STATE; break; default: pmlmepriv->fw_state = WIFI_NULL_STATE; break; } r8712_update_protection(adapter, (cur_network->network.IEs) + sizeof(struct NDIS_802_11_FIXED_IEs), (cur_network->network.IELength)); /*TODO: update HT_Capability*/ update_ht_cap(adapter, cur_network->network.IEs, cur_network->network.IELength); /*indicate connect*/ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) r8712_indicate_connect(adapter); _cancel_timer(&pmlmepriv->assoc_timer, &timer_cancelled); } else goto ignore_joinbss_callback; } else { if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true) { _set_timer(&pmlmepriv->assoc_timer, 1); _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); } } ignore_joinbss_callback: spin_unlock_irqrestore(&pmlmepriv->lock, irqL); if (sizeof(struct list_head) == 4 * sizeof(u32)) kfree((u8 *)pnetwork); }
static sint make_wlanhdr(struct _adapter *padapter, u8 *hdr, struct pkt_attrib *pattrib) { u16 *qc; struct ieee80211_hdr *pwlanhdr = (struct ieee80211_hdr *)hdr; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct qos_priv *pqospriv = &pmlmepriv->qospriv; __le16 *fctrl = &pwlanhdr->frame_ctl; memset(hdr, 0, WLANHDR_OFFSET); SetFrameSubType(fctrl, pattrib->subtype); if (pattrib->subtype & WIFI_DATA_TYPE) { if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { /* to_ds = 1, fr_ds = 0; */ SetToDs(fctrl); memcpy(pwlanhdr->addr1, get_bssid(pmlmepriv), ETH_ALEN); memcpy(pwlanhdr->addr2, pattrib->src, ETH_ALEN); memcpy(pwlanhdr->addr3, pattrib->dst, ETH_ALEN); } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { /* to_ds = 0, fr_ds = 1; */ SetFrDs(fctrl); memcpy(pwlanhdr->addr1, pattrib->dst, ETH_ALEN); memcpy(pwlanhdr->addr2, get_bssid(pmlmepriv), ETH_ALEN); memcpy(pwlanhdr->addr3, pattrib->src, ETH_ALEN); } else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { memcpy(pwlanhdr->addr1, pattrib->dst, ETH_ALEN); memcpy(pwlanhdr->addr2, pattrib->src, ETH_ALEN); memcpy(pwlanhdr->addr3, get_bssid(pmlmepriv), ETH_ALEN); } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) { memcpy(pwlanhdr->addr1, pattrib->dst, ETH_ALEN); memcpy(pwlanhdr->addr2, pattrib->src, ETH_ALEN); memcpy(pwlanhdr->addr3, get_bssid(pmlmepriv), ETH_ALEN); } else { return _FAIL; } if (pattrib->encrypt) SetPrivacy(fctrl); if (pqospriv->qos_option) { qc = (unsigned short *)(hdr + pattrib->hdrlen - 2); if (pattrib->priority) SetPriority(qc, pattrib->priority); SetAckpolicy(qc, pattrib->ack_policy); } /* TODO: fill HT Control Field */ /* Update Seq Num will be handled by f/w */ { struct sta_info *psta; sint bmcst = IS_MCAST(pattrib->ra); if (pattrib->psta) { psta = pattrib->psta; } else { if (bmcst) psta = r8712_get_bcmc_stainfo(padapter); else psta = r8712_get_stainfo(&padapter->stapriv, pattrib->ra); } if (psta) { psta->sta_xmitpriv.txseq_tid [pattrib->priority]++; psta->sta_xmitpriv.txseq_tid[pattrib->priority] &= 0xFFF; pattrib->seqnum = psta->sta_xmitpriv. txseq_tid[pattrib->priority]; SetSeqNum(hdr, pattrib->seqnum); } } } return _SUCCESS; }
static sint xmitframe_addmic(struct _adapter *padapter, struct xmit_frame *pxmitframe) { u32 curfragnum, length; u8 *pframe, *payload, mic[8]; struct mic_data micdata; struct sta_info *stainfo; struct qos_priv *pqospriv = &(padapter->mlmepriv.qospriv); struct pkt_attrib *pattrib = &pxmitframe->attrib; struct security_priv *psecuritypriv = &padapter->securitypriv; struct xmit_priv *pxmitpriv = &padapter->xmitpriv; u8 priority[4] = {0x0, 0x0, 0x0, 0x0}; sint bmcst = IS_MCAST(pattrib->ra); if (pattrib->psta) stainfo = pattrib->psta; else stainfo = r8712_get_stainfo(&padapter->stapriv, &pattrib->ra[0]); if (pattrib->encrypt == _TKIP_) { /*encode mic code*/ if (stainfo != NULL) { u8 null_key[16] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; pframe = pxmitframe->buf_addr + TXDESC_OFFSET; if (bmcst) { if (!memcmp(psecuritypriv->XGrptxmickey [psecuritypriv->XGrpKeyid].skey, null_key, 16)) return _FAIL; /*start to calculate the mic code*/ r8712_secmicsetkey(&micdata, psecuritypriv-> XGrptxmickey[psecuritypriv-> XGrpKeyid].skey); } else { if (!memcmp(&stainfo->tkiptxmickey.skey[0], null_key, 16)) return _FAIL; /* start to calculate the mic code */ r8712_secmicsetkey(&micdata, &stainfo->tkiptxmickey.skey[0]); } if (pframe[1] & 1) { /* ToDS==1 */ r8712_secmicappend(&micdata, &pframe[16], 6); /*DA*/ if (pframe[1] & 2) /* From Ds==1 */ r8712_secmicappend(&micdata, &pframe[24], 6); else r8712_secmicappend(&micdata, &pframe[10], 6); } else { /* ToDS==0 */ r8712_secmicappend(&micdata, &pframe[4], 6); /* DA */ if (pframe[1] & 2) /* From Ds==1 */ r8712_secmicappend(&micdata, &pframe[16], 6); else r8712_secmicappend(&micdata, &pframe[10], 6); } if (pqospriv->qos_option == 1) priority[0] = (u8)pxmitframe->attrib.priority; r8712_secmicappend(&micdata, &priority[0], 4); payload = pframe; for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) { payload = (u8 *)RND4((addr_t)(payload)); payload += pattrib->hdrlen + pattrib->iv_len; if ((curfragnum + 1) == pattrib->nr_frags) { length = pattrib->last_txcmdsz - pattrib->hdrlen - pattrib->iv_len - ((psecuritypriv->sw_encrypt) ? pattrib->icv_len : 0); r8712_secmicappend(&micdata, payload, length); payload = payload + length; } else { length = pxmitpriv->frag_len - pattrib->hdrlen - pattrib->iv_len - ((psecuritypriv->sw_encrypt) ? pattrib->icv_len : 0); r8712_secmicappend(&micdata, payload, length); payload = payload + length + pattrib->icv_len; } } r8712_secgetmic(&micdata, &(mic[0])); /* add mic code and add the mic code length in * last_txcmdsz */ memcpy(payload, &(mic[0]), 8); pattrib->last_txcmdsz += 8; payload = payload - pattrib->last_txcmdsz + 8; } } return _SUCCESS; }
sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, struct pkt_attrib *pattrib) { struct pkt_file pktfile; struct sta_info *psta = NULL; struct ethhdr etherhdr; struct tx_cmd txdesc; sint bmcast; struct sta_priv *pstapriv = &padapter->stapriv; struct security_priv *psecuritypriv = &padapter->securitypriv; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct qos_priv *pqospriv = &pmlmepriv->qospriv; _r8712_open_pktfile(pkt, &pktfile); _r8712_pktfile_read(&pktfile, (unsigned char *)ðerhdr, ETH_HLEN); pattrib->ether_type = ntohs(etherhdr.h_proto); /* * If driver xmit ARP packet, driver can set ps mode to initial * setting. It stands for getting DHCP or fix IP. */ if (pattrib->ether_type == 0x0806) { if (padapter->pwrctrlpriv.pwr_mode != padapter->registrypriv.power_mgnt) { del_timer_sync(&pmlmepriv->dhcp_timer); r8712_set_ps_mode(padapter, padapter->registrypriv.power_mgnt, padapter->registrypriv.smart_ps); } } memcpy(pattrib->dst, ðerhdr.h_dest, ETH_ALEN); memcpy(pattrib->src, ðerhdr.h_source, ETH_ALEN); pattrib->pctrl = 0; if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { memcpy(pattrib->ra, pattrib->dst, ETH_ALEN); memcpy(pattrib->ta, pattrib->src, ETH_ALEN); } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN); memcpy(pattrib->ta, pattrib->src, ETH_ALEN); } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { memcpy(pattrib->ra, pattrib->dst, ETH_ALEN); memcpy(pattrib->ta, get_bssid(pmlmepriv), ETH_ALEN); } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) { /*firstly, filter packet not belongs to mp*/ if (pattrib->ether_type != 0x8712) return _FAIL; /* for mp storing the txcmd per packet, * according to the info of txcmd to update pattrib */ /*get MP_TXDESC_SIZE bytes txcmd per packet*/ _r8712_pktfile_read(&pktfile, (u8 *)&txdesc, TXDESC_SIZE); memcpy(pattrib->ra, pattrib->dst, ETH_ALEN); memcpy(pattrib->ta, pattrib->src, ETH_ALEN); pattrib->pctrl = 1; } /* r8712_xmitframe_coalesce() overwrite this!*/ pattrib->pktlen = pktfile.pkt_len; if (pattrib->ether_type == ETH_P_IP) { /* The following is for DHCP and ARP packet, we use cck1M to * tx these packets and let LPS awake some time * to prevent DHCP protocol fail */ u8 tmp[24]; _r8712_pktfile_read(&pktfile, &tmp[0], 24); pattrib->dhcp_pkt = 0; if (pktfile.pkt_len > 282) {/*MINIMUM_DHCP_PACKET_SIZE)*/ if (pattrib->ether_type == ETH_P_IP) {/* IP header*/ if (((tmp[21] == 68) && (tmp[23] == 67)) || ((tmp[21] == 67) && (tmp[23] == 68))) { /* 68 : UDP BOOTP client * 67 : UDP BOOTP server * Use low rate to send DHCP packet. */ pattrib->dhcp_pkt = 1; } } } } bmcast = IS_MCAST(pattrib->ra); /* get sta_info*/ if (bmcast) { psta = r8712_get_bcmc_stainfo(padapter); pattrib->mac_id = 4; } else { if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) { psta = r8712_get_stainfo(pstapriv, get_bssid(pmlmepriv)); pattrib->mac_id = 5; } else { psta = r8712_get_stainfo(pstapriv, pattrib->ra); if (psta == NULL) /* drop the pkt */ return _FAIL; if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) pattrib->mac_id = 5; else pattrib->mac_id = psta->mac_id; } } if (psta) { pattrib->psta = psta; } else { /* if we cannot get psta => drrp the pkt */ return _FAIL; } pattrib->ack_policy = 0; /* get ether_hdr_len */ pattrib->pkt_hdrlen = ETH_HLEN; if (pqospriv->qos_option) { r8712_set_qos(&pktfile, pattrib); } else { pattrib->hdrlen = WLAN_HDR_A3_LEN; pattrib->subtype = WIFI_DATA_TYPE; pattrib->priority = 0; } if (psta->ieee8021x_blocked) { pattrib->encrypt = 0; if ((pattrib->ether_type != 0x888e) && !check_fwstate(pmlmepriv, WIFI_MP_STATE)) return _FAIL; } else { GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, bmcast); } switch (pattrib->encrypt) { case _WEP40_: case _WEP104_: pattrib->iv_len = 4; pattrib->icv_len = 4; break; case _TKIP_: pattrib->iv_len = 8; pattrib->icv_len = 4; if (padapter->securitypriv.busetkipkey == _FAIL) return _FAIL; break; case _AES_: pattrib->iv_len = 8; pattrib->icv_len = 8; break; default: pattrib->iv_len = 0; pattrib->icv_len = 0; break; } if (pattrib->encrypt && (padapter->securitypriv.sw_encrypt || !psecuritypriv->hw_decrypted)) pattrib->bswenc = true; else pattrib->bswenc = false; /* if in MP_STATE, update pkt_attrib from mp_txcmd, and overwrite * some settings above. */ if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) pattrib->priority = (le32_to_cpu(txdesc.txdw1) >> QSEL_SHT) & 0x1f; return _SUCCESS; }