u8 eap_get_phase2_type(const char *name) { u8 type = eap_get_type(name); if (eap_allowed_phase2_type(type)) return type; return EAP_TYPE_NONE; }
static void eapol_auth_tx_req(struct eapol_state_machine *sm) { if (sm->eap_if->eapReqData == NULL || wpabuf_len(sm->eap_if->eapReqData) < sizeof(struct eap_hdr)) { eapol_auth_logger(sm->eapol, sm->addr, EAPOL_LOGGER_DEBUG, "TxReq called, but there is no EAP request " "from authentication server"); return; } if (sm->flags & EAPOL_SM_WAIT_START) { wpa_printf(MSG_DEBUG, "EAPOL: Drop EAPOL TX to " MACSTR " while waiting for EAPOL-Start", MAC2STR(sm->addr)); return; } sm->last_eap_id = eap_get_id(sm->eap_if->eapReqData); eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_DEBUG, "Sending EAP Packet (identifier %d)", sm->last_eap_id); sm->eapol->cb.eapol_send(sm->eapol->conf.ctx, sm->sta, IEEE802_1X_TYPE_EAP_PACKET, wpabuf_head(sm->eap_if->eapReqData), wpabuf_len(sm->eap_if->eapReqData)); sm->dot1xAuthEapolFramesTx++; if (eap_get_type(sm->eap_if->eapReqData) == EAP_TYPE_IDENTITY) sm->dot1xAuthEapolReqIdFramesTx++; else sm->dot1xAuthEapolReqFramesTx++; }
static int eap_peap_decrypt(struct eap_sm *sm, struct eap_peap_data *data, struct eap_method_ret *ret, const struct eap_hdr *req, const struct wpabuf *in_data, struct wpabuf **out_data) { struct wpabuf *in_decrypted = NULL; int res, skip_change = 0; struct eap_hdr *hdr, *rhdr; struct wpabuf *resp = NULL; size_t len; wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for" " Phase 2", (unsigned long) wpabuf_len(in_data)); if (data->pending_phase2_req) { wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 request - " "skip decryption and use old data"); /* Clear TLS reassembly state. */ eap_peer_tls_reset_input(&data->ssl); in_decrypted = data->pending_phase2_req; data->pending_phase2_req = NULL; skip_change = 1; goto continue_req; } if (wpabuf_len(in_data) == 0 && sm->workaround && data->phase2_success) { /* * Cisco ACS seems to be using TLS ACK to terminate * EAP-PEAPv0/GTC. Try to reply with TLS ACK. */ wpa_printf(MSG_DEBUG, "EAP-PEAP: Received TLS ACK, but " "expected data - acknowledge with TLS ACK since " "Phase 2 has been completed"); ret->decision = DECISION_COND_SUCC; ret->methodState = METHOD_DONE; return 1; } else if (wpabuf_len(in_data) == 0) { /* Received TLS ACK - requesting more fragments */ return eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_PEAP, data->peap_version, req->identifier, NULL, out_data); } res = eap_peer_tls_decrypt(sm, &data->ssl, in_data, &in_decrypted); if (res) return res; continue_req: wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP", in_decrypted); hdr = wpabuf_mhead(in_decrypted); if (wpabuf_len(in_decrypted) == 5 && hdr->code == EAP_CODE_REQUEST && be_to_host16(hdr->length) == 5 && eap_get_type(in_decrypted) == EAP_TYPE_IDENTITY) { /* At least FreeRADIUS seems to send full EAP header with * EAP Request Identity */ skip_change = 1; } if (wpabuf_len(in_decrypted) >= 5 && hdr->code == EAP_CODE_REQUEST && eap_get_type(in_decrypted) == EAP_TYPE_TLV) { skip_change = 1; } if (data->peap_version == 0 && !skip_change) { struct eap_hdr *nhdr; struct wpabuf *nmsg = wpabuf_alloc(sizeof(struct eap_hdr) + wpabuf_len(in_decrypted)); if (nmsg == NULL) { wpabuf_free(in_decrypted); return 0; } nhdr = wpabuf_put(nmsg, sizeof(*nhdr)); wpabuf_put_buf(nmsg, in_decrypted); nhdr->code = req->code; nhdr->identifier = req->identifier; nhdr->length = host_to_be16(sizeof(struct eap_hdr) + wpabuf_len(in_decrypted)); wpabuf_free(in_decrypted); in_decrypted = nmsg; } if (data->peap_version >= 2) { struct eap_tlv_hdr *tlv; struct wpabuf *nmsg; if (wpabuf_len(in_decrypted) < sizeof(*tlv) + sizeof(*hdr)) { wpa_printf(MSG_INFO, "EAP-PEAPv2: Too short Phase 2 " "EAP TLV"); wpabuf_free(in_decrypted); return 0; } tlv = wpabuf_mhead(in_decrypted); if ((be_to_host16(tlv->tlv_type) & 0x3fff) != EAP_TLV_EAP_PAYLOAD_TLV) { wpa_printf(MSG_INFO, "EAP-PEAPv2: Not an EAP TLV"); wpabuf_free(in_decrypted); return 0; } if (sizeof(*tlv) + be_to_host16(tlv->length) > wpabuf_len(in_decrypted)) { wpa_printf(MSG_INFO, "EAP-PEAPv2: Invalid EAP TLV " "length"); wpabuf_free(in_decrypted); return 0; } hdr = (struct eap_hdr *) (tlv + 1); if (be_to_host16(hdr->length) > be_to_host16(tlv->length)) { wpa_printf(MSG_INFO, "EAP-PEAPv2: No room for full " "EAP packet in EAP TLV"); wpabuf_free(in_decrypted); return 0; } nmsg = wpabuf_alloc(be_to_host16(hdr->length)); if (nmsg == NULL) { wpabuf_free(in_decrypted); return 0; } wpabuf_put_data(nmsg, hdr, be_to_host16(hdr->length)); wpabuf_free(in_decrypted); in_decrypted = nmsg; } hdr = wpabuf_mhead(in_decrypted); if (wpabuf_len(in_decrypted) < sizeof(*hdr)) { wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 " "EAP frame (len=%lu)", (unsigned long) wpabuf_len(in_decrypted)); wpabuf_free(in_decrypted); return 0; } len = be_to_host16(hdr->length); if (len > wpabuf_len(in_decrypted)) { wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in " "Phase 2 EAP frame (len=%lu hdr->length=%lu)", (unsigned long) wpabuf_len(in_decrypted), (unsigned long) len); wpabuf_free(in_decrypted); return 0; } if (len < wpabuf_len(in_decrypted)) { wpa_printf(MSG_INFO, "EAP-PEAP: Odd.. Phase 2 EAP header has " "shorter length than full decrypted data " "(%lu < %lu)", (unsigned long) len, (unsigned long) wpabuf_len(in_decrypted)); } wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d " "identifier=%d length=%lu", hdr->code, hdr->identifier, (unsigned long) len); switch (hdr->code) { case EAP_CODE_REQUEST: if (eap_peap_phase2_request(sm, data, ret, in_decrypted, &resp)) { wpabuf_free(in_decrypted); wpa_printf(MSG_INFO, "EAP-PEAP: Phase2 Request " "processing failed"); return 0; } break; case EAP_CODE_SUCCESS: wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Success"); if (data->peap_version == 1) { /* EAP-Success within TLS tunnel is used to indicate * shutdown of the TLS channel. The authentication has * been completed. */ if (data->phase2_eap_started && !data->phase2_eap_success) { wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 " "Success used to indicate success, " "but Phase 2 EAP was not yet " "completed successfully"); ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; wpabuf_free(in_decrypted); return 0; } wpa_printf(MSG_DEBUG, "EAP-PEAP: Version 1 - " "EAP-Success within TLS tunnel - " "authentication completed"); ret->decision = DECISION_UNCOND_SUCC; ret->methodState = METHOD_DONE; data->phase2_success = 1; if (data->peap_outer_success == 2) { wpabuf_free(in_decrypted); wpa_printf(MSG_DEBUG, "EAP-PEAP: Use TLS ACK " "to finish authentication"); return 1; } else if (data->peap_outer_success == 1) { /* Reply with EAP-Success within the TLS * channel to complete the authentication. */ resp = wpabuf_alloc(sizeof(struct eap_hdr)); if (resp) { rhdr = wpabuf_put(resp, sizeof(*rhdr)); rhdr->code = EAP_CODE_SUCCESS; rhdr->identifier = hdr->identifier; rhdr->length = host_to_be16(sizeof(*rhdr)); } } else { /* No EAP-Success expected for Phase 1 (outer, * unencrypted auth), so force EAP state * machine to SUCCESS state. */ sm->peap_done = TRUE; } } else { /* FIX: ? */ } break; case EAP_CODE_FAILURE: wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure"); ret->decision = DECISION_FAIL; ret->methodState = METHOD_MAY_CONT; ret->allowNotifications = FALSE; /* Reply with EAP-Failure within the TLS channel to complete * failure reporting. */ resp = wpabuf_alloc(sizeof(struct eap_hdr)); if (resp) { rhdr = wpabuf_put(resp, sizeof(*rhdr)); rhdr->code = EAP_CODE_FAILURE; rhdr->identifier = hdr->identifier; rhdr->length = host_to_be16(sizeof(*rhdr)); } break; default: wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in " "Phase 2 EAP header", hdr->code); break; } wpabuf_free(in_decrypted); if (resp) { int skip_change2 = 0; struct wpabuf *rmsg, buf; wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data", resp); /* PEAP version changes */ if (data->peap_version >= 2) { resp = eap_peapv2_tlv_eap_payload(resp); if (resp == NULL) return -1; } if (wpabuf_len(resp) >= 5 && wpabuf_head_u8(resp)[0] == EAP_CODE_RESPONSE && eap_get_type(resp) == EAP_TYPE_TLV) skip_change2 = 1; rmsg = resp; if (data->peap_version == 0 && !skip_change2) { wpabuf_set(&buf, wpabuf_head_u8(resp) + sizeof(struct eap_hdr), wpabuf_len(resp) - sizeof(struct eap_hdr)); rmsg = &buf; } if (eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_PEAP, data->peap_version, req->identifier, rmsg, out_data)) { wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt " "a Phase 2 frame"); } wpabuf_free(resp); } return 0; }
int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev) { struct rtllib_device *ieee = (struct rtllib_device *)netdev_priv_rsl(dev); struct rtllib_txb *txb = NULL; struct rtllib_hdr_3addrqos *frag_hdr; int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size; unsigned long flags; struct net_device_stats *stats = &ieee->stats; int ether_type = 0, encrypt; int bytes, fc, qos_ctl = 0, hdr_len; struct sk_buff *skb_frag; struct rtllib_hdr_3addrqos header = { /* Ensure zero initialized */ .duration_id = 0, .seq_ctl = 0, .qos_ctl = 0 }; u8 dest[ETH_ALEN], src[ETH_ALEN]; int qos_actived = ieee->current_network.qos_data.active; struct rtllib_crypt_data* crypt = NULL; cb_desc *tcb_desc; u8 bIsMulticast = false; #if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) struct sta_info *p_sta = NULL; #endif u8 IsAmsdu = false; #ifdef ENABLE_AMSDU u8 queue_index = WME_AC_BE; cb_desc *tcb_desc_skb; u8 bIsSptAmsdu = false; #endif bool bdhcp =false; #ifndef _RTL8192_EXT_PATCH_ //PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(ieee->PowerSaveControl));//added by amy for Leisure PS 090402 #endif spin_lock_irqsave(&ieee->lock, flags); /* If there is no driver handler to take the TXB, dont' bother * creating it... */ if ((!ieee->hard_start_xmit && !(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE))|| ((!ieee->softmac_data_hard_start_xmit && (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) { printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name); goto success; } if(likely(ieee->raw_tx == 0)){ if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) { printk(KERN_WARNING "%s: skb too small (%d).\n", ieee->dev->name, skb->len); goto success; } /* Save source and destination addresses */ memcpy(dest, skb->data, ETH_ALEN); memcpy(src, skb->data+ETH_ALEN, ETH_ALEN); #ifdef ENABLE_AMSDU if(ieee->iw_mode == IW_MODE_ADHOC) { p_sta = GetStaInfo(ieee, dest); if(p_sta) { if(p_sta->htinfo.bEnableHT) bIsSptAmsdu = true; } }else if(ieee->iw_mode == IW_MODE_INFRA) { bIsSptAmsdu = true; }else bIsSptAmsdu = true; bIsSptAmsdu = (bIsSptAmsdu && ieee->pHTInfo->bCurrent_AMSDU_Support && qos_actived); //u8 *a = skb->data; //u8 *b = (u8*)skb->data + ETH_ALEN; //printk("\n&&&&&&&skb=%p len=%d dst:"MAC_FMT" src:"MAC_FMT"\n",skb,skb->len,MAC_ARG(a),MAC_ARG(b)); tcb_desc_skb = (pcb_desc)(skb->cb + MAX_DEV_ADDR_SIZE); //YJ,move,081104 if(bIsSptAmsdu) { if(!tcb_desc_skb->bFromAggrQ) //Normal MSDU { if(qos_actived) { queue_index = UP2AC(skb->priority); } else { queue_index = WME_AC_BE; } //printk("Normal MSDU,queue_idx=%d nic_enough=%d queue_len=%d\n", queue_index, ieee->check_nic_enough_desc(ieee->dev,queue_index), skb_queue_len(&ieee->skb_aggQ[queue_index])); if ((skb_queue_len(&ieee->skb_aggQ[queue_index]) != 0)|| #if defined RTL8192SE || defined RTL8192CE (ieee->get_nic_desc_num(ieee->dev,queue_index)) > 1|| #else (!ieee->check_nic_enough_desc(ieee->dev,queue_index))|| #endif (ieee->queue_stop) || (ieee->amsdu_in_process)) //YJ,add,090409 { /* insert the skb packet to the Aggregation queue */ //printk("!!!!!!!!!!%s(): intert to aggr queue\n", __FUNCTION__); skb_queue_tail(&ieee->skb_aggQ[queue_index], skb); spin_unlock_irqrestore(&ieee->lock, flags); return 0; } } else //AMSDU { //printk("AMSDU!!!!!!!!!!!!!\n"); if(tcb_desc_skb->bAMSDU) IsAmsdu = true; //YJ,add,090409 ieee->amsdu_in_process = false; } } #endif memset(skb->cb, 0, sizeof(skb->cb)); ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto); // 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 if (skb->len > 282){//MINIMUM_DHCP_PACKET_SIZE) { if (ETH_P_IP == ether_type) {// IP header const struct iphdr *ip = (struct iphdr *)((u8 *)skb->data+14); if (IPPROTO_UDP == ip->protocol) {//FIXME windows is 11 but here UDP in linux kernel is 17. struct udphdr *udp = (struct udphdr *)((u8 *)ip + (ip->ihl << 2)); //if(((ntohs(udp->source) == 68) && (ntohs(udp->dest) == 67)) || /// ((ntohs(udp->source) == 67) && (ntohs(udp->dest) == 68))) { if(((((u8 *)udp)[1] == 68) && (((u8 *)udp)[3] == 67)) || ((((u8 *)udp)[1] == 67) && (((u8 *)udp)[3] == 68))) { // 68 : UDP BOOTP client // 67 : UDP BOOTP server printk("===>DHCP Protocol start tx DHCP pkt src port:%d, dest port:%d!!\n", ((u8 *)udp)[1],((u8 *)udp)[3]); // Use low rate to send DHCP packet. //if(pMgntInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom) //{ // tcb_desc->DataRate = MgntQuery_TxRateExcludeCCKRates(ieee);//0xc;//ofdm 6m // tcb_desc->bTxDisableRateFallBack = false; //} //else //pTcb->DataRate = Adapter->MgntInfo.LowestBasicRate; //RTPRINT(FDM, WA_IOT, ("DHCP TranslateHeader(), pTcb->DataRate = 0x%x\n", pTcb->DataRate)); bdhcp = true; #ifdef _RTL8192_EXT_PATCH_ ieee->LPSDelayCnt = 100;//pPSC->LPSAwakeIntvl*2; //AMY,090701 #else ieee->LPSDelayCnt = 100;//pPSC->LPSAwakeIntvl*2; #endif } } }else if(ETH_P_ARP == ether_type){// IP ARP packet printk("=================>DHCP Protocol start tx ARP pkt!!\n"); bdhcp = true; ieee->LPSDelayCnt = ieee->current_network.tim.tim_count; //if(pMgntInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom) //{ // tcb_desc->DataRate = MgntQuery_TxRateExcludeCCKRates(Adapter->MgntInfo.mBrates);//0xc;//ofdm 6m // tcb_desc->bTxDisableRateFallBack = FALSE; //} //else // tcb_desc->DataRate = Adapter->MgntInfo.LowestBasicRate; //RTPRINT(FDM, WA_IOT, ("ARP TranslateHeader(), pTcb->DataRate = 0x%x\n", pTcb->DataRate)); } } skb->priority = rtllib_classify(skb, IsAmsdu); #ifdef _RTL8192_EXT_PATCH_ crypt = ieee->sta_crypt[ieee->tx_keyidx]; #else crypt = ieee->crypt[ieee->tx_keyidx]; #endif encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) && ieee->host_encrypt && crypt && crypt->ops; if (!encrypt && ieee->ieee802_1x && ieee->drop_unencrypted && ether_type != ETH_P_PAE) { stats->tx_dropped++; goto success; } #ifdef CONFIG_RTLLIB_DEBUG if (crypt && !encrypt && ether_type == ETH_P_PAE) { struct eapol *eap = (struct eapol *)(skb->data + sizeof(struct ethhdr) - SNAP_SIZE - sizeof(u16)); RTLLIB_DEBUG_EAP("TX: IEEE 802.11 EAPOL frame: %s\n", eap_get_type(eap->type)); } #endif /* Advance the SKB to the start of the payload */ skb_pull(skb, sizeof(struct ethhdr)); /* Determine total amount of storage required for TXB packets */ #ifdef ENABLE_AMSDU if(!IsAmsdu) bytes = skb->len + SNAP_SIZE + sizeof(u16); else bytes = skb->len; #else bytes = skb->len + SNAP_SIZE + sizeof(u16); #endif if (encrypt) fc = RTLLIB_FTYPE_DATA | RTLLIB_FCTL_WEP; else fc = RTLLIB_FTYPE_DATA; //if(ieee->current_network.QoS_Enable) if(qos_actived) fc |= RTLLIB_STYPE_QOS_DATA; else fc |= RTLLIB_STYPE_DATA; #ifdef _RTL8192_EXT_PATCH_ if ((ieee->iw_mode == IW_MODE_INFRA) //|| ((ieee->iw_mode == IW_MODE_MESH) && (ieee->only_mesh == 0))) //YJ,test,090610 || (ieee->iw_mode == IW_MODE_MESH) ) #else if (ieee->iw_mode == IW_MODE_INFRA) #endif { fc |= RTLLIB_FCTL_TODS; /* To DS: Addr1 = BSSID, Addr2 = SA, Addr3 = DA */ memcpy(&header.addr1, ieee->current_network.bssid, ETH_ALEN); memcpy(&header.addr2, &src, ETH_ALEN); if(IsAmsdu) memcpy(&header.addr3, ieee->current_network.bssid, ETH_ALEN); else memcpy(&header.addr3, &dest, ETH_ALEN); } else if (ieee->iw_mode == IW_MODE_ADHOC) { /* not From/To DS: Addr1 = DA, Addr2 = SA, Addr3 = BSSID */ memcpy(&header.addr1, dest, ETH_ALEN); memcpy(&header.addr2, src, ETH_ALEN); memcpy(&header.addr3, ieee->current_network.bssid, ETH_ALEN); } bIsMulticast = is_broadcast_ether_addr(header.addr1) ||is_multicast_ether_addr(header.addr1); header.frame_ctl = cpu_to_le16(fc); /* Determine fragmentation size based on destination (multicast * and broadcast are not fragmented) */ if (bIsMulticast) { frag_size = MAX_FRAG_THRESHOLD; qos_ctl |= QOS_CTL_NOTCONTAIN_ACK; } else { #ifdef ENABLE_AMSDU if(bIsSptAmsdu) { if(ieee->iw_mode == IW_MODE_ADHOC) { if(p_sta) frag_size = p_sta->htinfo.AMSDU_MaxSize; else frag_size = ieee->pHTInfo->nAMSDU_MaxSize; } else frag_size = ieee->pHTInfo->nAMSDU_MaxSize; qos_ctl = 0; } else #endif { frag_size = ieee->fts;//default:392 qos_ctl = 0; } } if(qos_actived) { hdr_len = RTLLIB_3ADDR_LEN + 2; /* in case we are a client verify acm is not set for this ac */ while (unlikely(ieee->wmm_acm & (0x01 << skb->priority))) { printk("skb->priority = %x\n", skb->priority); if (wme_downgrade_ac(skb)) { break; } printk("converted skb->priority = %x\n", skb->priority); } qos_ctl |= skb->priority; //set in the rtllib_classify #ifdef ENABLE_AMSDU if(IsAmsdu) { qos_ctl |= QOS_CTL_AMSDU_PRESENT; } header.qos_ctl = cpu_to_le16(qos_ctl); #else header.qos_ctl = cpu_to_le16(qos_ctl & RTLLIB_QOS_TID); #endif } else { hdr_len = RTLLIB_3ADDR_LEN; } /* Determine amount of payload per fragment. Regardless of if * this stack is providing the full 802.11 header, one will * eventually be affixed to this fragment -- so we must account for * it when determining the amount of payload space. */ bytes_per_frag = frag_size - hdr_len; if (ieee->config & (CFG_RTLLIB_COMPUTE_FCS | CFG_RTLLIB_RESERVE_FCS)) bytes_per_frag -= RTLLIB_FCS_LEN; /* Each fragment may need to have room for encryptiong pre/postfix */ if (encrypt){ bytes_per_frag -= crypt->ops->extra_prefix_len + crypt->ops->extra_postfix_len; } /* Number of fragments is the total bytes_per_frag / * payload_per_fragment */ nr_frags = bytes / bytes_per_frag; bytes_last_frag = bytes % bytes_per_frag; if (bytes_last_frag) nr_frags++; else bytes_last_frag = bytes_per_frag; /* When we allocate the TXB we allocate enough space for the reserve * and full fragment bytes (bytes_per_frag doesn't include prefix, * postfix, header, FCS, etc.) */ txb = rtllib_alloc_txb(nr_frags, frag_size + ieee->tx_headroom, GFP_ATOMIC); if (unlikely(!txb)) { printk(KERN_WARNING "%s: Could not allocate TXB\n", ieee->dev->name); goto failed; } txb->encrypted = encrypt; txb->payload_size = bytes; //if (ieee->current_network.QoS_Enable) if(qos_actived) { txb->queue_index = UP2AC(skb->priority); } else { txb->queue_index = WME_AC_BE;; } for (i = 0; i < nr_frags; i++) { skb_frag = txb->fragments[i]; tcb_desc = (cb_desc *)(skb_frag->cb + MAX_DEV_ADDR_SIZE); #ifdef _RTL8192_EXT_PATCH_ tcb_desc->mesh_pkt = 0;//AMY added 090226 if(ieee->iw_mode == IW_MODE_ADHOC) tcb_desc->badhoc = 1; else tcb_desc->badhoc = 0; #endif if(qos_actived){ skb_frag->priority = skb->priority;//UP2AC(skb->priority); tcb_desc->queue_index = UP2AC(skb->priority); } else { skb_frag->priority = WME_AC_BE; tcb_desc->queue_index = WME_AC_BE; } skb_reserve(skb_frag, ieee->tx_headroom); if (encrypt){ if (ieee->hwsec_active) tcb_desc->bHwSec = 1; else tcb_desc->bHwSec = 0; skb_reserve(skb_frag, crypt->ops->extra_prefix_len); } else { tcb_desc->bHwSec = 0; } frag_hdr = (struct rtllib_hdr_3addrqos *)skb_put(skb_frag, hdr_len); memcpy(frag_hdr, &header, hdr_len); /* If this is not the last fragment, then add the MOREFRAGS * bit to the frame control */ if (i != nr_frags - 1) { frag_hdr->frame_ctl = cpu_to_le16( fc | RTLLIB_FCTL_MOREFRAGS); bytes = bytes_per_frag; } else { /* The last fragment takes the remaining length */ bytes = bytes_last_frag; } //if(ieee->current_network.QoS_Enable) if((qos_actived) && (!bIsMulticast)) { // add 1 only indicate to corresponding seq number control 2006/7/12 //frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[UP2AC(skb->priority)+1]<<4 | i); frag_hdr->seq_ctl = rtllib_query_seqnum(ieee, skb_frag, header.addr1); frag_hdr->seq_ctl = cpu_to_le16(frag_hdr->seq_ctl<<4 | i); } else { frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4 | i); } /* Put a SNAP header on the first fragment */ #ifdef ENABLE_AMSDU if ((i == 0) && (!IsAmsdu)) #else if (i == 0) #endif { rtllib_put_snap( skb_put(skb_frag, SNAP_SIZE + sizeof(u16)), ether_type); bytes -= SNAP_SIZE + sizeof(u16); } memcpy(skb_put(skb_frag, bytes), skb->data, bytes); /* Advance the SKB... */ skb_pull(skb, bytes); /* Encryption routine will move the header forward in order * to insert the IV between the header and the payload */ if (encrypt){ #ifdef _RTL8192_EXT_PATCH_ rtllib_encrypt_fragment(ieee, skb_frag, hdr_len, 0); #else rtllib_encrypt_fragment(ieee, skb_frag, hdr_len); #endif } if (ieee->config & (CFG_RTLLIB_COMPUTE_FCS | CFG_RTLLIB_RESERVE_FCS)) skb_put(skb_frag, 4); } if((qos_actived) && (!bIsMulticast)) { if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF) ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0; else ieee->seq_ctrl[UP2AC(skb->priority) + 1]++; } else { if (ieee->seq_ctrl[0] == 0xFFF) ieee->seq_ctrl[0] = 0; else ieee->seq_ctrl[0]++; } }else{ if (unlikely(skb->len < sizeof(struct rtllib_hdr_3addr))) { printk(KERN_WARNING "%s: skb too small (%d).\n", ieee->dev->name, skb->len); goto success; } txb = rtllib_alloc_txb(1, skb->len, GFP_ATOMIC); if(!txb){ printk(KERN_WARNING "%s: Could not allocate TXB\n", ieee->dev->name); goto failed; } txb->encrypted = 0; txb->payload_size = skb->len; memcpy(skb_put(txb->fragments[0],skb->len), skb->data, skb->len); } success: //WB add to fill data tcb_desc here. only first fragment is considered, need to change, and you may remove to other place. if (txb) { #if 1 cb_desc *tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE); tcb_desc->bTxEnableFwCalcDur = 1; tcb_desc->priority = skb->priority; if(ether_type == ETH_P_PAE) { if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom) { tcb_desc->data_rate = MgntQuery_TxRateExcludeCCKRates(ieee);//0xc;//ofdm 6m tcb_desc->bTxDisableRateFallBack = false; }else{ tcb_desc->data_rate = ieee->basic_rate; tcb_desc->bTxDisableRateFallBack = 1; } printk("EAPOL TranslateHeader(), pTcb->DataRate = 0x%x\n", tcb_desc->data_rate); tcb_desc->RATRIndex = 7; tcb_desc->bTxUseDriverAssingedRate = 1; } else { if (is_multicast_ether_addr(header.addr1)) tcb_desc->bMulticast = 1; if (is_broadcast_ether_addr(header.addr1)) tcb_desc->bBroadcast = 1; #if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) if ( tcb_desc->bMulticast || tcb_desc->bBroadcast){ rtllib_txrate_selectmode(ieee, tcb_desc, 7); tcb_desc->data_rate = ieee->basic_rate; } else { if(ieee->iw_mode == IW_MODE_ADHOC) { u8 is_peer_shortGI_40M = 0; u8 is_peer_shortGI_20M = 0; u8 is_peer_BW_40M = 0; p_sta = GetStaInfo(ieee, header.addr1); if(NULL == p_sta) { rtllib_txrate_selectmode(ieee, tcb_desc, 7); tcb_desc->data_rate = ieee->rate; } else { rtllib_txrate_selectmode(ieee, tcb_desc, p_sta->ratr_index); tcb_desc->data_rate = CURRENT_RATE(p_sta->wireless_mode, p_sta->CurDataRate, p_sta->htinfo.HTHighestOperaRate); is_peer_shortGI_40M = p_sta->htinfo.bCurShortGI40MHz; is_peer_shortGI_20M = p_sta->htinfo.bCurShortGI20MHz; is_peer_BW_40M = p_sta->htinfo.bCurTxBW40MHz; } rtllib_qurey_ShortPreambleMode(ieee, tcb_desc); rtllib_tx_query_agg_cap(ieee, txb->fragments[0], tcb_desc); rtllib_ibss_query_HTCapShortGI(ieee, tcb_desc,is_peer_shortGI_40M,is_peer_shortGI_20M); rtllib_ibss_query_BandwidthMode(ieee, tcb_desc,is_peer_BW_40M); rtllib_query_protectionmode(ieee, tcb_desc, txb->fragments[0]); //CB_DESC_DUMP(tcb_desc, __FUNCTION__); } else { rtllib_txrate_selectmode(ieee, tcb_desc, 0); tcb_desc->data_rate = CURRENT_RATE(ieee->mode, ieee->rate, ieee->HTCurrentOperaRate); if(bdhcp == true){ // Use low rate to send DHCP packet. if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom) { tcb_desc->data_rate = MGN_1M;//MgntQuery_TxRateExcludeCCKRates(ieee);//0xc;//ofdm 6m tcb_desc->bTxDisableRateFallBack = false; }else{ tcb_desc->data_rate = MGN_1M; tcb_desc->bTxDisableRateFallBack = 1; } tcb_desc->RATRIndex = 7; tcb_desc->bTxUseDriverAssingedRate = 1; tcb_desc->bdhcp = 1; } rtllib_qurey_ShortPreambleMode(ieee, tcb_desc); rtllib_tx_query_agg_cap(ieee, txb->fragments[0], tcb_desc); rtllib_query_HTCapShortGI(ieee, tcb_desc); rtllib_query_BandwidthMode(ieee, tcb_desc); rtllib_query_protectionmode(ieee, tcb_desc, txb->fragments[0]); } } #else rtllib_txrate_selectmode(ieee, tcb_desc); if ( tcb_desc->bMulticast || tcb_desc->bBroadcast) tcb_desc->data_rate = ieee->basic_rate; else //tcb_desc->data_rate = CURRENT_RATE(ieee->current_network.mode, ieee->rate, ieee->HTCurrentOperaRate); tcb_desc->data_rate = CURRENT_RATE(ieee->mode, ieee->rate, ieee->HTCurrentOperaRate); if(bdhcp == true){ // Use low rate to send DHCP packet. if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom) { tcb_desc->data_rate = MgntQuery_TxRateExcludeCCKRates(ieee);//0xc;//ofdm 6m tcb_desc->bTxDisableRateFallBack = false; }else{ tcb_desc->data_rate = MGN_1M; tcb_desc->bTxDisableRateFallBack = 1; } //printk("DHCP TranslateHeader(), pTcb->DataRate = 0x%x\n", tcb_desc->data_rate); tcb_desc->RATRIndex = 7; tcb_desc->bTxUseDriverAssingedRate = 1; //tcb_desc->bTxEnableFwCalcDur = 1; } rtllib_qurey_ShortPreambleMode(ieee, tcb_desc); rtllib_tx_query_agg_cap(ieee, txb->fragments[0], tcb_desc); rtllib_query_HTCapShortGI(ieee, tcb_desc); rtllib_query_BandwidthMode(ieee, tcb_desc); rtllib_query_protectionmode(ieee, tcb_desc, txb->fragments[0]); #endif } // rtllib_query_seqnum(ieee, txb->fragments[0], header.addr1); // RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA, txb->fragments[0]->data, txb->fragments[0]->len); //RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA, tcb_desc, sizeof(cb_desc)); #endif } spin_unlock_irqrestore(&ieee->lock, flags); dev_kfree_skb_any(skb); if (txb) { if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE){ rtllib_softmac_xmit(txb, ieee); }else{ if ((*ieee->hard_start_xmit)(txb, dev) == 0) { stats->tx_packets++; stats->tx_bytes += txb->payload_size; return 0; } rtllib_txb_free(txb); } } return 0; failed: spin_unlock_irqrestore(&ieee->lock, flags); netif_stop_queue(dev); stats->tx_errors++; return 1; } int rtllib_xmit(struct sk_buff *skb, struct net_device *dev) { memset(skb->cb, 0, sizeof(skb->cb)); return rtllib_xmit_inter(skb, dev); }
int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) { struct ieee80211_device *ieee = netdev_priv(dev); struct ieee80211_txb *txb = NULL; struct ieee80211_hdr_3addrqos *frag_hdr; int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size; unsigned long flags; struct net_device_stats *stats = &ieee->stats; int ether_type = 0, encrypt; int bytes, fc, qos_ctl = 0, hdr_len; struct sk_buff *skb_frag; struct ieee80211_hdr_3addrqos header = { /* Ensure zero initialized */ .duration_id = 0, .seq_ctl = 0, .qos_ctl = 0 }; u8 dest[ETH_ALEN], src[ETH_ALEN]; int qos_actived = ieee->current_network.qos_data.active; struct ieee80211_crypt_data* crypt; cb_desc *tcb_desc; spin_lock_irqsave(&ieee->lock, flags); /* If there is no driver handler to take the TXB, dont' bother * creating it... */ if ((!ieee->hard_start_xmit && !(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE))|| ((!ieee->softmac_data_hard_start_xmit && (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) { // printk(KERN_WARNING "%s: No xmit handler.\n", ; goto success; } if(likely(ieee->raw_tx == 0)){ if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) { // printk(KERN_WARNING "%s: skb too small (%d).\n", ; goto success; } memset(skb->cb, 0, sizeof(skb->cb)); ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto); crypt = ieee->crypt[ieee->tx_keyidx]; encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) && ieee->host_encrypt && crypt && crypt->ops; if (!encrypt && ieee->ieee802_1x && ieee->drop_unencrypted && ether_type != ETH_P_PAE) { stats->tx_dropped++; goto success; } #ifdef CONFIG_IEEE80211_DEBUG if (crypt && !encrypt && ether_type == ETH_P_PAE) { struct eapol *eap = (struct eapol *)(skb->data + sizeof(struct ethhdr) - SNAP_SIZE - sizeof(u16)); IEEE80211_DEBUG_EAP("TX: IEEE 802.11 EAPOL frame: %s\n", eap_get_type(eap->type)); } #endif /* Save source and destination addresses */ memcpy(&dest, skb->data, ETH_ALEN); memcpy(&src, skb->data+ETH_ALEN, ETH_ALEN); /* Advance the SKB to the start of the payload */ skb_pull(skb, sizeof(struct ethhdr)); /* Determine total amount of storage required for TXB packets */ bytes = skb->len + SNAP_SIZE + sizeof(u16); if (encrypt) fc = IEEE80211_FTYPE_DATA | IEEE80211_FCTL_WEP; else fc = IEEE80211_FTYPE_DATA; //if(ieee->current_network.QoS_Enable) if(qos_actived) fc |= IEEE80211_STYPE_QOS_DATA; else fc |= IEEE80211_STYPE_DATA; if (ieee->iw_mode == IW_MODE_INFRA) { fc |= IEEE80211_FCTL_TODS; /* To DS: Addr1 = BSSID, Addr2 = SA, Addr3 = DA */ memcpy(&header.addr1, ieee->current_network.bssid, ETH_ALEN); memcpy(&header.addr2, &src, ETH_ALEN); memcpy(&header.addr3, &dest, ETH_ALEN); } else if (ieee->iw_mode == IW_MODE_ADHOC) { /* not From/To DS: Addr1 = DA, Addr2 = SA, Addr3 = BSSID */ memcpy(&header.addr1, dest, ETH_ALEN); memcpy(&header.addr2, src, ETH_ALEN); memcpy(&header.addr3, ieee->current_network.bssid, ETH_ALEN); } header.frame_ctl = cpu_to_le16(fc); /* Determine fragmentation size based on destination (multicast * and broadcast are not fragmented) */ if (is_multicast_ether_addr(header.addr1) || is_broadcast_ether_addr(header.addr1)) { frag_size = MAX_FRAG_THRESHOLD; qos_ctl |= QOS_CTL_NOTCONTAIN_ACK; } else { frag_size = ieee->fts;//default:392 qos_ctl = 0; } //if (ieee->current_network.QoS_Enable) if(qos_actived) { hdr_len = IEEE80211_3ADDR_LEN + 2; skb->priority = ieee80211_classify(skb, &ieee->current_network); qos_ctl |= skb->priority; //set in the ieee80211_classify header.qos_ctl = cpu_to_le16(qos_ctl & IEEE80211_QOS_TID); } else { hdr_len = IEEE80211_3ADDR_LEN; } /* Determine amount of payload per fragment. Regardless of if * this stack is providing the full 802.11 header, one will * eventually be affixed to this fragment -- so we must account for * it when determining the amount of payload space. */ bytes_per_frag = frag_size - hdr_len; if (ieee->config & (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) bytes_per_frag -= IEEE80211_FCS_LEN; /* Each fragment may need to have room for encryptiong pre/postfix */ if (encrypt) bytes_per_frag -= crypt->ops->extra_prefix_len + crypt->ops->extra_postfix_len; /* Number of fragments is the total bytes_per_frag / * payload_per_fragment */ nr_frags = bytes / bytes_per_frag; bytes_last_frag = bytes % bytes_per_frag; if (bytes_last_frag) nr_frags++; else bytes_last_frag = bytes_per_frag; /* When we allocate the TXB we allocate enough space for the reserve * and full fragment bytes (bytes_per_frag doesn't include prefix, * postfix, header, FCS, etc.) */ txb = ieee80211_alloc_txb(nr_frags, frag_size + ieee->tx_headroom, GFP_ATOMIC); if (unlikely(!txb)) { // printk(KERN_WARNING "%s: Could not allocate TXB\n", ; goto failed; } txb->encrypted = encrypt; txb->payload_size = bytes; //if (ieee->current_network.QoS_Enable) if(qos_actived) { txb->queue_index = UP2AC(skb->priority); } else { txb->queue_index = WME_AC_BK; } for (i = 0; i < nr_frags; i++) { skb_frag = txb->fragments[i]; tcb_desc = (cb_desc *)(skb_frag->cb + MAX_DEV_ADDR_SIZE); if(qos_actived){ skb_frag->priority = skb->priority;//UP2AC(skb->priority); tcb_desc->queue_index = UP2AC(skb->priority); } else { skb_frag->priority = WME_AC_BK; tcb_desc->queue_index = WME_AC_BK; } skb_reserve(skb_frag, ieee->tx_headroom); if (encrypt){ if (ieee->hwsec_active) tcb_desc->bHwSec = 1; else tcb_desc->bHwSec = 0; skb_reserve(skb_frag, crypt->ops->extra_prefix_len); } else { tcb_desc->bHwSec = 0; } frag_hdr = (struct ieee80211_hdr_3addrqos *)skb_put(skb_frag, hdr_len); memcpy(frag_hdr, &header, hdr_len); /* If this is not the last fragment, then add the MOREFRAGS * bit to the frame control */ if (i != nr_frags - 1) { frag_hdr->frame_ctl = cpu_to_le16( fc | IEEE80211_FCTL_MOREFRAGS); bytes = bytes_per_frag; } else { /* The last fragment takes the remaining length */ bytes = bytes_last_frag; } //if(ieee->current_network.QoS_Enable) if(qos_actived) { // add 1 only indicate to corresponding seq number control 2006/7/12 frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[UP2AC(skb->priority)+1]<<4 | i); } else { frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4 | i); } /* Put a SNAP header on the first fragment */ if (i == 0) { ieee80211_put_snap( skb_put(skb_frag, SNAP_SIZE + sizeof(u16)), ether_type); bytes -= SNAP_SIZE + sizeof(u16); } memcpy(skb_put(skb_frag, bytes), skb->data, bytes); /* Advance the SKB... */ skb_pull(skb, bytes); /* Encryption routine will move the header forward in order * to insert the IV between the header and the payload */ if (encrypt) ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len); if (ieee->config & (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) skb_put(skb_frag, 4); } if(qos_actived) { if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF) ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0; else ieee->seq_ctrl[UP2AC(skb->priority) + 1]++; } else { if (ieee->seq_ctrl[0] == 0xFFF) ieee->seq_ctrl[0] = 0; else ieee->seq_ctrl[0]++; } }else{ if (unlikely(skb->len < sizeof(struct ieee80211_hdr_3addr))) { // printk(KERN_WARNING "%s: skb too small (%d).\n", ; goto success; } txb = ieee80211_alloc_txb(1, skb->len, GFP_ATOMIC); if(!txb){ // printk(KERN_WARNING "%s: Could not allocate TXB\n", ; goto failed; } txb->encrypted = 0; txb->payload_size = skb->len; memcpy(skb_put(txb->fragments[0],skb->len), skb->data, skb->len); } success: //WB add to fill data tcb_desc here. only first fragment is considered, need to change, and you may remove to other place. if (txb) { cb_desc *tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE); tcb_desc->bTxEnableFwCalcDur = 1; if (is_multicast_ether_addr(header.addr1)) tcb_desc->bMulticast = 1; if (is_broadcast_ether_addr(header.addr1)) tcb_desc->bBroadcast = 1; ieee80211_txrate_selectmode(ieee, tcb_desc); if ( tcb_desc->bMulticast || tcb_desc->bBroadcast) tcb_desc->data_rate = ieee->basic_rate; else //tcb_desc->data_rate = CURRENT_RATE(ieee->current_network.mode, ieee->rate, ieee->HTCurrentOperaRate); tcb_desc->data_rate = CURRENT_RATE(ieee->mode, ieee->rate, ieee->HTCurrentOperaRate); ieee80211_qurey_ShortPreambleMode(ieee, tcb_desc); ieee80211_tx_query_agg_cap(ieee, txb->fragments[0], tcb_desc); ieee80211_query_HTCapShortGI(ieee, tcb_desc); ieee80211_query_BandwidthMode(ieee, tcb_desc); ieee80211_query_protectionmode(ieee, tcb_desc, txb->fragments[0]); ieee80211_query_seqnum(ieee, txb->fragments[0], header.addr1); // IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, txb->fragments[0]->data, txb->fragments[0]->len); //IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, tcb_desc, sizeof(cb_desc)); } spin_unlock_irqrestore(&ieee->lock, flags); dev_kfree_skb_any(skb); if (txb) { if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE){ ieee80211_softmac_xmit(txb, ieee); }else{ if ((*ieee->hard_start_xmit)(txb, dev) == 0) { stats->tx_packets++; stats->tx_bytes += txb->payload_size; return 0; } ieee80211_txb_free(txb); } } return 0; failed: spin_unlock_irqrestore(&ieee->lock, flags); netif_stop_queue(dev); stats->tx_errors++; return 1; } EXPORT_SYMBOL(ieee80211_txb_free);
int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev) { struct rtllib_device *ieee = (struct rtllib_device *)netdev_priv_rsl(dev); struct rtllib_txb *txb = NULL; struct rtllib_hdr_3addrqos *frag_hdr; int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size; unsigned long flags; struct net_device_stats *stats = &ieee->stats; int ether_type = 0, encrypt; int bytes, fc, qos_ctl = 0, hdr_len; struct sk_buff *skb_frag; struct rtllib_hdr_3addrqos header = { /* Ensure zero initialized */ .duration_id = 0, .seq_ctl = 0, .qos_ctl = 0 }; u8 dest[ETH_ALEN], src[ETH_ALEN]; int qos_actived = ieee->current_network.qos_data.active; struct rtllib_crypt_data* crypt = NULL; cb_desc *tcb_desc; u8 bIsMulticast = false; #if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) || defined RTL8192CE struct sta_info *p_sta = NULL; #endif u8 IsAmsdu = false; cb_desc *tcb_desc_skb; #ifdef ENABLE_AMSDU u8 queue_index = WME_AC_BE; u8 bIsSptAmsdu = false; #endif bool bdhcp =false; #ifndef _RTL8192_EXT_PATCH_ #endif #ifdef RTL8192S_WAPI_SUPPORT static u8 zero14[14] = {0}; #endif u8 bEosp = false; spin_lock_irqsave(&ieee->lock, flags); /* If there is no driver handler to take the TXB, dont' bother * creating it... */ if ((!ieee->hard_start_xmit && !(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE))|| ((!ieee->softmac_data_hard_start_xmit && (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) { printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name); goto success; } if(likely(ieee->raw_tx == 0)){ if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) { printk(KERN_WARNING "%s: skb too small (%d).\n", ieee->dev->name, skb->len); goto success; } #ifdef RTL8192S_WAPI_SUPPORT if(memcmp(skb->data, zero14, sizeof(zero14))==0){ if(WapiSendWaiPacket(ieee, skb)< 0) goto failed; else{ spin_unlock_irqrestore(&ieee->lock, flags); return 0; } } #endif /* Save source and destination addresses */ memcpy(dest, skb->data, ETH_ALEN); memcpy(src, skb->data+ETH_ALEN, ETH_ALEN); tcb_desc_skb = (pcb_desc)(skb->cb + MAX_DEV_ADDR_SIZE); #ifdef ENABLE_AMSDU if (ieee->iw_mode == IW_MODE_ADHOC) { p_sta = GetStaInfo(ieee, dest); if(p_sta) { if(p_sta->htinfo.bEnableHT) bIsSptAmsdu = true; } }else if(ieee->iw_mode == IW_MODE_INFRA #ifdef ASL || ieee->iw_mode == IW_MODE_APSTA #endif ) { bIsSptAmsdu = true; }else bIsSptAmsdu = true; bIsSptAmsdu = (bIsSptAmsdu && ieee->pHTInfo->bCurrent_AMSDU_Support && qos_actived); if(bIsSptAmsdu) { if(!tcb_desc_skb->bFromAggrQ) { if (qos_actived) { queue_index = UP2AC(skb->priority); } else { queue_index = WME_AC_BE; } if ((skb_queue_len(&ieee->skb_aggQ[queue_index]) != 0)|| #if defined RTL8192SE || defined RTL8192CE (ieee->get_nic_desc_num(ieee->dev,queue_index)) > 1|| #else (!ieee->check_nic_enough_desc(ieee->dev,queue_index))|| #endif (ieee->queue_stop) || (ieee->amsdu_in_process)) { /* insert the skb packet to the Aggregation queue */ skb_queue_tail(&ieee->skb_aggQ[queue_index], skb); spin_unlock_irqrestore(&ieee->lock, flags); return 0; } } else { if(tcb_desc_skb->bAMSDU) IsAmsdu = true; ieee->amsdu_in_process = false; } } #endif ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto); if(ieee->iw_mode == IW_MODE_MONITOR) { txb = rtllib_alloc_txb(1, skb->len, GFP_ATOMIC); if (unlikely(!txb)) { printk(KERN_WARNING "%s: Could not allocate TXB\n", ieee->dev->name); goto failed; } txb->encrypted = 0; txb->payload_size = skb->len; memcpy(skb_put(txb->fragments[0],skb->len), skb->data, skb->len); goto success; } if (skb->len > 282){ if (ETH_P_IP == ether_type) { const struct iphdr *ip = (struct iphdr *)((u8 *)skb->data+14); if (IPPROTO_UDP == ip->protocol) { struct udphdr *udp = (struct udphdr *)((u8 *)ip + (ip->ihl << 2)); if(((((u8 *)udp)[1] == 68) && (((u8 *)udp)[3] == 67)) || ((((u8 *)udp)[1] == 67) && (((u8 *)udp)[3] == 68))) { printk("DHCP pkt src port:%d, dest port:%d!!\n", ((u8 *)udp)[1],((u8 *)udp)[3]); bdhcp = true; #ifdef _RTL8192_EXT_PATCH_ ieee->LPSDelayCnt = 200; #else ieee->LPSDelayCnt = 200; #endif } } }else if(ETH_P_ARP == ether_type){ printk("=================>DHCP Protocol start tx ARP pkt!!\n"); bdhcp = true; ieee->LPSDelayCnt = ieee->current_network.tim.tim_count; } } skb->priority = rtllib_classify(skb, IsAmsdu); if (qos_actived) { /* in case we are a client verify acm is not set for this ac */ while (unlikely(ieee->wmm_acm & (0x01 << skb->priority))) { printk("skb->priority = %x\n", skb->priority); if (wme_downgrade_ac(skb)) { break; } printk("converted skb->priority = %x\n", skb->priority); } } memset(skb->cb, 0, sizeof(skb->cb)); #ifdef RTL8192S_WAPI_SUPPORT if(ieee->WapiSupport && ieee->wapiInfo.bWapiEnable){ crypt = NULL; encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) && ieee->host_encrypt && ieee->WapiSupport && ieee->wapiInfo.bWapiEnable; } else{ #endif #if defined(_RTL8192_EXT_PATCH_) || defined(ASL) crypt = ieee->sta_crypt[ieee->tx_keyidx]; #else crypt = ieee->crypt[ieee->tx_keyidx]; #endif encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) && ieee->host_encrypt && crypt && crypt->ops; #ifdef RTL8192S_WAPI_SUPPORT } #endif if (!encrypt && ieee->ieee802_1x && ieee->drop_unencrypted && ether_type != ETH_P_PAE) { stats->tx_dropped++; goto success; } #ifdef CONFIG_RTLLIB_DEBUG if (crypt && !encrypt && ether_type == ETH_P_PAE) { struct eapol *eap = (struct eapol *)(skb->data + sizeof(struct ethhdr) - SNAP_SIZE - sizeof(u16)); RTLLIB_DEBUG_EAP("TX: IEEE 802.11 EAPOL frame: %s\n", eap_get_type(eap->type)); } #endif /* Advance the SKB to the start of the payload */ skb_pull(skb, sizeof(struct ethhdr)); /* Determine total amount of storage required for TXB packets */ #ifdef ENABLE_AMSDU if(!IsAmsdu) bytes = skb->len + SNAP_SIZE + sizeof(u16); else bytes = skb->len; #else bytes = skb->len + SNAP_SIZE + sizeof(u16); #endif if (encrypt) fc = RTLLIB_FTYPE_DATA | RTLLIB_FCTL_WEP; else fc = RTLLIB_FTYPE_DATA; if(qos_actived) fc |= RTLLIB_STYPE_QOS_DATA; else fc |= RTLLIB_STYPE_DATA; #ifdef _RTL8192_EXT_PATCH_ if ((ieee->iw_mode == IW_MODE_INFRA) || (ieee->iw_mode == IW_MODE_MESH) ) #else #ifdef ASL if ((ieee->iw_mode == IW_MODE_INFRA) || (ieee->iw_mode == IW_MODE_APSTA)) #else if (ieee->iw_mode == IW_MODE_INFRA) #endif #endif { fc |= RTLLIB_FCTL_TODS; /* To DS: Addr1 = BSSID, Addr2 = SA, Addr3 = DA */ memcpy(&header.addr1, ieee->current_network.bssid, ETH_ALEN); memcpy(&header.addr2, &src, ETH_ALEN); if(IsAmsdu) memcpy(&header.addr3, ieee->current_network.bssid, ETH_ALEN); else memcpy(&header.addr3, &dest, ETH_ALEN); } else if (ieee->iw_mode == IW_MODE_ADHOC) { /* not From/To DS: Addr1 = DA, Addr2 = SA, Addr3 = BSSID */ memcpy(&header.addr1, dest, ETH_ALEN); memcpy(&header.addr2, src, ETH_ALEN); memcpy(&header.addr3, ieee->current_network.bssid, ETH_ALEN); } bIsMulticast = is_broadcast_ether_addr(header.addr1) ||is_multicast_ether_addr(header.addr1); header.frame_ctl = cpu_to_le16(fc); /* Determine fragmentation size based on destination (multicast * and broadcast are not fragmented) */ if (bIsMulticast) { frag_size = MAX_FRAG_THRESHOLD; qos_ctl |= QOS_CTL_NOTCONTAIN_ACK; } else { #ifdef ENABLE_AMSDU if(bIsSptAmsdu) { if(ieee->iw_mode == IW_MODE_ADHOC) { if(p_sta) frag_size = p_sta->htinfo.AMSDU_MaxSize; else frag_size = ieee->pHTInfo->nAMSDU_MaxSize; } else frag_size = ieee->pHTInfo->nAMSDU_MaxSize; qos_ctl = 0; } else #endif { frag_size = ieee->fts; qos_ctl = 0; } } if(qos_actived) { hdr_len = RTLLIB_3ADDR_LEN + 2; qos_ctl |= skb->priority; qos_ctl |= (bEosp?1:0)<<4; #ifdef ENABLE_AMSDU if(IsAmsdu) { qos_ctl |= QOS_CTL_AMSDU_PRESENT; } header.qos_ctl = cpu_to_le16(qos_ctl); #else header.qos_ctl = cpu_to_le16(qos_ctl & RTLLIB_QOS_TID); #endif } else { hdr_len = RTLLIB_3ADDR_LEN; } /* Determine amount of payload per fragment. Regardless of if * this stack is providing the full 802.11 header, one will * eventually be affixed to this fragment -- so we must account for * it when determining the amount of payload space. */ bytes_per_frag = frag_size - hdr_len; if (ieee->config & (CFG_RTLLIB_COMPUTE_FCS | CFG_RTLLIB_RESERVE_FCS)) bytes_per_frag -= RTLLIB_FCS_LEN; /* Each fragment may need to have room for encryptiong pre/postfix */ if (encrypt) { #ifdef RTL8192S_WAPI_SUPPORT if(ieee->WapiSupport && ieee->wapiInfo.bWapiEnable) bytes_per_frag -= ieee->wapiInfo.extra_prefix_len + ieee->wapiInfo.extra_postfix_len; else #endif bytes_per_frag -= crypt->ops->extra_prefix_len + crypt->ops->extra_postfix_len; } /* Number of fragments is the total bytes_per_frag / * payload_per_fragment */ nr_frags = bytes / bytes_per_frag; bytes_last_frag = bytes % bytes_per_frag; if (bytes_last_frag) nr_frags++; else bytes_last_frag = bytes_per_frag; /* When we allocate the TXB we allocate enough space for the reserve * and full fragment bytes (bytes_per_frag doesn't include prefix, * postfix, header, FCS, etc.) */ txb = rtllib_alloc_txb(nr_frags, frag_size + ieee->tx_headroom, GFP_ATOMIC); if (unlikely(!txb)) { printk(KERN_WARNING "%s: Could not allocate TXB\n", ieee->dev->name); goto failed; } txb->encrypted = encrypt; txb->payload_size = bytes; if(qos_actived) { txb->queue_index = UP2AC(skb->priority); } else { txb->queue_index = WME_AC_BE;; } for (i = 0; i < nr_frags; i++) { skb_frag = txb->fragments[i]; tcb_desc = (cb_desc *)(skb_frag->cb + MAX_DEV_ADDR_SIZE); #ifdef _RTL8192_EXT_PATCH_ tcb_desc->mesh_pkt = 0; #endif if(ieee->iw_mode == IW_MODE_ADHOC) tcb_desc->badhoc = 1; else tcb_desc->badhoc = 0; if(qos_actived){ skb_frag->priority = skb->priority; tcb_desc->queue_index = UP2AC(skb->priority); } else { skb_frag->priority = WME_AC_BE; tcb_desc->queue_index = WME_AC_BE; } skb_reserve(skb_frag, ieee->tx_headroom); if (encrypt){ if (ieee->hwsec_active) tcb_desc->bHwSec = 1; else tcb_desc->bHwSec = 0; #ifdef RTL8192S_WAPI_SUPPORT if(ieee->WapiSupport && ieee->wapiInfo.bWapiEnable) skb_reserve(skb_frag, ieee->wapiInfo.extra_prefix_len); else #endif skb_reserve(skb_frag, crypt->ops->extra_prefix_len); } else { tcb_desc->bHwSec = 0; } frag_hdr = (struct rtllib_hdr_3addrqos *)skb_put(skb_frag, hdr_len); memcpy(frag_hdr, &header, hdr_len); /* If this is not the last fragment, then add the MOREFRAGS * bit to the frame control */ if (i != nr_frags - 1) { frag_hdr->frame_ctl = cpu_to_le16( fc | RTLLIB_FCTL_MOREFRAGS); bytes = bytes_per_frag; } else { /* The last fragment takes the remaining length */ bytes = bytes_last_frag; } if((qos_actived) && (!bIsMulticast)) { frag_hdr->seq_ctl = rtllib_query_seqnum(ieee, skb_frag, header.addr1); frag_hdr->seq_ctl = cpu_to_le16(frag_hdr->seq_ctl<<4 | i); } else { frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4 | i); } /* Put a SNAP header on the first fragment */ #ifdef ENABLE_AMSDU if ((i == 0) && (!IsAmsdu)) #else if (i == 0) #endif { rtllib_put_snap( skb_put(skb_frag, SNAP_SIZE + sizeof(u16)), ether_type); bytes -= SNAP_SIZE + sizeof(u16); } memcpy(skb_put(skb_frag, bytes), skb->data, bytes); /* Advance the SKB... */ skb_pull(skb, bytes); /* Encryption routine will move the header forward in order * to insert the IV between the header and the payload */ if (encrypt) { #ifdef RTL8192S_WAPI_SUPPORT if(ieee->WapiSupport && ieee->wapiInfo.bWapiEnable){ if(SecSMS4HeaderFillIV(ieee, skb_frag) == 0){ SecSWSMS4Encryption(ieee, skb_frag); } else { spin_unlock_irqrestore(&ieee->lock, flags); dev_kfree_skb_any(skb); rtllib_txb_free(txb); return 0; } } else #endif { #if defined(_RTL8192_EXT_PATCH_) || defined(ASL) rtllib_encrypt_fragment(ieee, skb_frag, hdr_len, 0, 0); #else rtllib_encrypt_fragment(ieee, skb_frag, hdr_len); #endif } } if (ieee->config & (CFG_RTLLIB_COMPUTE_FCS | CFG_RTLLIB_RESERVE_FCS)) skb_put(skb_frag, 4); } if ((!qos_actived) || (bIsMulticast)) { if (ieee->seq_ctrl[0] == 0xFFF) ieee->seq_ctrl[0] = 0; else ieee->seq_ctrl[0]++; } }else{ if (unlikely(skb->len < sizeof(struct rtllib_hdr_3addr))) { printk(KERN_WARNING "%s: skb too small (%d).\n", ieee->dev->name, skb->len); goto success; } txb = rtllib_alloc_txb(1, skb->len, GFP_ATOMIC); if(!txb){ printk(KERN_WARNING "%s: Could not allocate TXB\n", ieee->dev->name); goto failed; } txb->encrypted = 0; txb->payload_size = skb->len; memcpy(skb_put(txb->fragments[0],skb->len), skb->data, skb->len); } success: if (txb) { #if 1 cb_desc *tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE); tcb_desc->bTxEnableFwCalcDur = 1; tcb_desc->priority = skb->priority; if(ether_type == ETH_P_PAE) { if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom) { #ifdef ASL tcb_desc->data_rate = MgntQuery_TxRateExcludeCCKRates(ieee,0); #else tcb_desc->data_rate = MgntQuery_TxRateExcludeCCKRates(ieee); #endif tcb_desc->bTxDisableRateFallBack = false; }else{ tcb_desc->data_rate = ieee->basic_rate; tcb_desc->bTxDisableRateFallBack = 1; } tcb_desc->RATRIndex = 7; tcb_desc->bTxUseDriverAssingedRate = 1; } else { if (is_multicast_ether_addr(header.addr1)) tcb_desc->bMulticast = 1; if (is_broadcast_ether_addr(header.addr1)) tcb_desc->bBroadcast = 1; #if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) || defined RTL8192CE if ( tcb_desc->bMulticast || tcb_desc->bBroadcast){ rtllib_txrate_selectmode(ieee, tcb_desc, p_sta); tcb_desc->data_rate = ieee->basic_rate; } else { if(ieee->iw_mode == IW_MODE_ADHOC) { u8 is_peer_shortGI_40M = 0; u8 is_peer_shortGI_20M = 0; u8 is_peer_BW_40M = 0; p_sta = GetStaInfo(ieee, header.addr1); if(NULL == p_sta) { rtllib_txrate_selectmode(ieee, tcb_desc, p_sta); tcb_desc->data_rate = ieee->rate; } else { rtllib_txrate_selectmode(ieee, tcb_desc, p_sta); tcb_desc->data_rate = CURRENT_RATE(p_sta->wireless_mode, p_sta->CurDataRate, p_sta->htinfo.HTHighestOperaRate); is_peer_shortGI_40M = p_sta->htinfo.bCurShortGI40MHz; is_peer_shortGI_20M = p_sta->htinfo.bCurShortGI20MHz; is_peer_BW_40M = p_sta->htinfo.bCurTxBW40MHz; } rtllib_qurey_ShortPreambleMode(ieee, tcb_desc); rtllib_tx_query_agg_cap(ieee, txb->fragments[0], tcb_desc); rtllib_entry_query_HTCapShortGI(ieee, tcb_desc,is_peer_shortGI_40M,is_peer_shortGI_20M); rtllib_entry_query_BandwidthMode(ieee, tcb_desc,is_peer_BW_40M); rtllib_query_protectionmode(ieee, tcb_desc, txb->fragments[0]); } else { rtllib_txrate_selectmode(ieee, tcb_desc, p_sta); tcb_desc->data_rate = CURRENT_RATE(ieee->mode, ieee->rate, ieee->HTCurrentOperaRate); if(bdhcp == true){ if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom) { tcb_desc->data_rate = MGN_1M; tcb_desc->bTxDisableRateFallBack = false; }else{ tcb_desc->data_rate = MGN_1M; tcb_desc->bTxDisableRateFallBack = 1; } tcb_desc->RATRIndex = 7; tcb_desc->bTxUseDriverAssingedRate = 1; tcb_desc->bdhcp = 1; } rtllib_qurey_ShortPreambleMode(ieee, tcb_desc); rtllib_tx_query_agg_cap(ieee, txb->fragments[0], tcb_desc); rtllib_query_HTCapShortGI(ieee, tcb_desc); rtllib_query_BandwidthMode(ieee, tcb_desc); rtllib_query_protectionmode(ieee, tcb_desc, txb->fragments[0]); #ifdef _RTL8192_EXT_PATCH_ ieee->LinkDetectInfo.NumTxUnicastOkInPeriod ++; #endif } } #else rtllib_txrate_selectmode(ieee, tcb_desc); if ( tcb_desc->bMulticast || tcb_desc->bBroadcast) tcb_desc->data_rate = ieee->basic_rate; else tcb_desc->data_rate = CURRENT_RATE(ieee->mode, ieee->rate, ieee->HTCurrentOperaRate); if(bdhcp == true){ if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom) { #ifdef ASL tcb_desc->data_rate = MgntQuery_TxRateExcludeCCKRates(ieee,0); #else tcb_desc->data_rate = MgntQuery_TxRateExcludeCCKRates(ieee); #endif tcb_desc->bTxDisableRateFallBack = false; }else{ tcb_desc->data_rate = MGN_1M; tcb_desc->bTxDisableRateFallBack = 1; } tcb_desc->RATRIndex = 7; tcb_desc->bTxUseDriverAssingedRate = 1; tcb_desc->bdhcp = 1; } rtllib_qurey_ShortPreambleMode(ieee, tcb_desc); rtllib_tx_query_agg_cap(ieee, txb->fragments[0], tcb_desc); rtllib_query_HTCapShortGI(ieee, tcb_desc); rtllib_query_BandwidthMode(ieee, tcb_desc); rtllib_query_protectionmode(ieee, tcb_desc, txb->fragments[0]); #endif } #endif } spin_unlock_irqrestore(&ieee->lock, flags); dev_kfree_skb_any(skb); if (txb) { if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE){ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)) dev->stats.tx_packets++; dev->stats.tx_bytes += txb->payload_size; #endif rtllib_softmac_xmit(txb, ieee); }else{ if ((*ieee->hard_start_xmit)(txb, dev) == 0) { stats->tx_packets++; stats->tx_bytes += txb->payload_size; return 0; } rtllib_txb_free(txb); } } return 0; failed: spin_unlock_irqrestore(&ieee->lock, flags); netif_stop_queue(dev); stats->tx_errors++; return 1; } int rtllib_xmit(struct sk_buff *skb, struct net_device *dev) { memset(skb->cb, 0, sizeof(skb->cb)); return rtllib_xmit_inter(skb, dev); }
int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev) { struct rtllib_device *ieee = (struct rtllib_device *) netdev_priv_rsl(dev); struct rtllib_txb *txb = NULL; struct rtllib_hdr_3addrqos *frag_hdr; int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size; unsigned long flags; struct net_device_stats *stats = &ieee->stats; int ether_type = 0, encrypt; int bytes, fc, qos_ctl = 0, hdr_len; struct sk_buff *skb_frag; struct rtllib_hdr_3addrqos header = { /* Ensure zero initialized */ .duration_id = 0, .seq_ctl = 0, .qos_ctl = 0 }; u8 dest[ETH_ALEN], src[ETH_ALEN]; int qos_actived = ieee->current_network.qos_data.active; struct lib80211_crypt_data *crypt = NULL; struct cb_desc *tcb_desc; u8 bIsMulticast = false; u8 IsAmsdu = false; bool bdhcp = false; spin_lock_irqsave(&ieee->lock, flags); /* If there is no driver handler to take the TXB, don't bother * creating it... */ if ((!ieee->hard_start_xmit && !(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)) || ((!ieee->softmac_data_hard_start_xmit && (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) { printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name); goto success; } if (likely(ieee->raw_tx == 0)) { if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) { printk(KERN_WARNING "%s: skb too small (%d).\n", ieee->dev->name, skb->len); goto success; } /* Save source and destination addresses */ memcpy(dest, skb->data, ETH_ALEN); memcpy(src, skb->data+ETH_ALEN, ETH_ALEN); memset(skb->cb, 0, sizeof(skb->cb)); ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto); if (ieee->iw_mode == IW_MODE_MONITOR) { txb = rtllib_alloc_txb(1, skb->len, GFP_ATOMIC); if (unlikely(!txb)) { printk(KERN_WARNING "%s: Could not allocate " "TXB\n", ieee->dev->name); goto failed; } txb->encrypted = 0; txb->payload_size = cpu_to_le16(skb->len); memcpy(skb_put(txb->fragments[0], skb->len), skb->data, skb->len); goto success; } if (skb->len > 282) { if (ETH_P_IP == ether_type) { const struct iphdr *ip = (struct iphdr *) ((u8 *)skb->data+14); if (IPPROTO_UDP == ip->protocol) { struct udphdr *udp; udp = (struct udphdr *)((u8 *)ip + (ip->ihl << 2)); if (((((u8 *)udp)[1] == 68) && (((u8 *)udp)[3] == 67)) || ((((u8 *)udp)[1] == 67) && (((u8 *)udp)[3] == 68))) { bdhcp = true; ieee->LPSDelayCnt = 200; } } } else if (ETH_P_ARP == ether_type) { printk(KERN_INFO "=================>DHCP " "Protocol start tx ARP pkt!!\n"); bdhcp = true; ieee->LPSDelayCnt = ieee->current_network.tim.tim_count; } } skb->priority = rtllib_classify(skb, IsAmsdu); crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx]; encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) && ieee->host_encrypt && crypt && crypt->ops; if (!encrypt && ieee->ieee802_1x && ieee->drop_unencrypted && ether_type != ETH_P_PAE) { stats->tx_dropped++; goto success; } if (crypt && !encrypt && ether_type == ETH_P_PAE) { struct eapol *eap = (struct eapol *)(skb->data + sizeof(struct ethhdr) - SNAP_SIZE - sizeof(u16)); RTLLIB_DEBUG_EAP("TX: IEEE 802.11 EAPOL frame: %s\n", eap_get_type(eap->type)); } /* Advance the SKB to the start of the payload */ skb_pull(skb, sizeof(struct ethhdr)); /* Determine total amount of storage required for TXB packets */ bytes = skb->len + SNAP_SIZE + sizeof(u16); if (encrypt) fc = RTLLIB_FTYPE_DATA | RTLLIB_FCTL_WEP; else fc = RTLLIB_FTYPE_DATA; if (qos_actived) fc |= RTLLIB_STYPE_QOS_DATA; else fc |= RTLLIB_STYPE_DATA; if (ieee->iw_mode == IW_MODE_INFRA) { fc |= RTLLIB_FCTL_TODS; /* To DS: Addr1 = BSSID, Addr2 = SA, Addr3 = DA */ memcpy(&header.addr1, ieee->current_network.bssid, ETH_ALEN); memcpy(&header.addr2, &src, ETH_ALEN); if (IsAmsdu) memcpy(&header.addr3, ieee->current_network.bssid, ETH_ALEN); else memcpy(&header.addr3, &dest, ETH_ALEN); } else if (ieee->iw_mode == IW_MODE_ADHOC) { /* not From/To DS: Addr1 = DA, Addr2 = SA, Addr3 = BSSID */ memcpy(&header.addr1, dest, ETH_ALEN); memcpy(&header.addr2, src, ETH_ALEN); memcpy(&header.addr3, ieee->current_network.bssid, ETH_ALEN); } bIsMulticast = is_multicast_ether_addr(header.addr1); header.frame_ctl = cpu_to_le16(fc); /* Determine fragmentation size based on destination (multicast * and broadcast are not fragmented) */ if (bIsMulticast) { frag_size = MAX_FRAG_THRESHOLD; qos_ctl |= QOS_CTL_NOTCONTAIN_ACK; } else { frag_size = ieee->fts; qos_ctl = 0; } if (qos_actived) { hdr_len = RTLLIB_3ADDR_LEN + 2; /* in case we are a client verify acm is not set for this ac */ while (unlikely(ieee->wmm_acm & (0x01 << skb->priority))) { printk(KERN_INFO "skb->priority = %x\n", skb->priority); if (wme_downgrade_ac(skb)) break; printk(KERN_INFO "converted skb->priority = %x\n", skb->priority); } qos_ctl |= skb->priority; header.qos_ctl = cpu_to_le16(qos_ctl & RTLLIB_QOS_TID); } else { hdr_len = RTLLIB_3ADDR_LEN; } /* Determine amount of payload per fragment. Regardless of if * this stack is providing the full 802.11 header, one will * eventually be affixed to this fragment -- so we must account * for it when determining the amount of payload space. */ bytes_per_frag = frag_size - hdr_len; if (ieee->config & (CFG_RTLLIB_COMPUTE_FCS | CFG_RTLLIB_RESERVE_FCS)) bytes_per_frag -= RTLLIB_FCS_LEN; /* Each fragment may need to have room for encrypting * pre/postfix */ if (encrypt) { bytes_per_frag -= crypt->ops->extra_mpdu_prefix_len + crypt->ops->extra_mpdu_postfix_len + crypt->ops->extra_msdu_prefix_len + crypt->ops->extra_msdu_postfix_len; } /* Number of fragments is the total bytes_per_frag / * payload_per_fragment */ nr_frags = bytes / bytes_per_frag; bytes_last_frag = bytes % bytes_per_frag; if (bytes_last_frag) nr_frags++; else bytes_last_frag = bytes_per_frag; /* When we allocate the TXB we allocate enough space for the * reserve and full fragment bytes (bytes_per_frag doesn't * include prefix, postfix, header, FCS, etc.) */ txb = rtllib_alloc_txb(nr_frags, frag_size + ieee->tx_headroom, GFP_ATOMIC); if (unlikely(!txb)) { printk(KERN_WARNING "%s: Could not allocate TXB\n", ieee->dev->name); goto failed; } txb->encrypted = encrypt; txb->payload_size = cpu_to_le16(bytes); if (qos_actived) txb->queue_index = UP2AC(skb->priority); else txb->queue_index = WME_AC_BE; for (i = 0; i < nr_frags; i++) { skb_frag = txb->fragments[i]; tcb_desc = (struct cb_desc *)(skb_frag->cb + MAX_DEV_ADDR_SIZE); if (qos_actived) { skb_frag->priority = skb->priority; tcb_desc->queue_index = UP2AC(skb->priority); } else { skb_frag->priority = WME_AC_BE; tcb_desc->queue_index = WME_AC_BE; } skb_reserve(skb_frag, ieee->tx_headroom); if (encrypt) { if (ieee->hwsec_active) tcb_desc->bHwSec = 1; else tcb_desc->bHwSec = 0; skb_reserve(skb_frag, crypt->ops->extra_mpdu_prefix_len + crypt->ops->extra_msdu_prefix_len); } else { tcb_desc->bHwSec = 0; } frag_hdr = (struct rtllib_hdr_3addrqos *) skb_put(skb_frag, hdr_len); memcpy(frag_hdr, &header, hdr_len); /* If this is not the last fragment, then add the * MOREFRAGS bit to the frame control */ if (i != nr_frags - 1) { frag_hdr->frame_ctl = cpu_to_le16( fc | RTLLIB_FCTL_MOREFRAGS); bytes = bytes_per_frag; } else { /* The last fragment has the remaining length */ bytes = bytes_last_frag; } if ((qos_actived) && (!bIsMulticast)) { frag_hdr->seq_ctl = cpu_to_le16(rtllib_query_seqnum(ieee, skb_frag, header.addr1)); frag_hdr->seq_ctl = cpu_to_le16(le16_to_cpu(frag_hdr->seq_ctl)<<4 | i); } else { frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4 | i); } /* Put a SNAP header on the first fragment */ if (i == 0) { rtllib_put_snap( skb_put(skb_frag, SNAP_SIZE + sizeof(u16)), ether_type); bytes -= SNAP_SIZE + sizeof(u16); } memcpy(skb_put(skb_frag, bytes), skb->data, bytes); /* Advance the SKB... */ skb_pull(skb, bytes); /* Encryption routine will move the header forward in * order to insert the IV between the header and the * payload */ if (encrypt) rtllib_encrypt_fragment(ieee, skb_frag, hdr_len); if (ieee->config & (CFG_RTLLIB_COMPUTE_FCS | CFG_RTLLIB_RESERVE_FCS)) skb_put(skb_frag, 4); } if ((qos_actived) && (!bIsMulticast)) { if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF) ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0; else ieee->seq_ctrl[UP2AC(skb->priority) + 1]++; } else { if (ieee->seq_ctrl[0] == 0xFFF) ieee->seq_ctrl[0] = 0; else ieee->seq_ctrl[0]++; } } else { if (unlikely(skb->len < sizeof(struct rtllib_hdr_3addr))) { printk(KERN_WARNING "%s: skb too small (%d).\n", ieee->dev->name, skb->len); goto success; } txb = rtllib_alloc_txb(1, skb->len, GFP_ATOMIC); if (!txb) { printk(KERN_WARNING "%s: Could not allocate TXB\n", ieee->dev->name); goto failed; } txb->encrypted = 0; txb->payload_size = cpu_to_le16(skb->len); memcpy(skb_put(txb->fragments[0], skb->len), skb->data, skb->len); } success: if (txb) { struct cb_desc *tcb_desc = (struct cb_desc *) (txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE); tcb_desc->bTxEnableFwCalcDur = 1; tcb_desc->priority = skb->priority; if (ether_type == ETH_P_PAE) { if (ieee->pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom) { tcb_desc->data_rate = MgntQuery_TxRateExcludeCCKRates(ieee); tcb_desc->bTxDisableRateFallBack = false; } else { tcb_desc->data_rate = ieee->basic_rate; tcb_desc->bTxDisableRateFallBack = 1; } tcb_desc->RATRIndex = 7; tcb_desc->bTxUseDriverAssingedRate = 1; } else { if (is_multicast_ether_addr(header.addr1)) tcb_desc->bMulticast = 1; if (is_broadcast_ether_addr(header.addr1)) tcb_desc->bBroadcast = 1; rtllib_txrate_selectmode(ieee, tcb_desc); if (tcb_desc->bMulticast || tcb_desc->bBroadcast) tcb_desc->data_rate = ieee->basic_rate; else tcb_desc->data_rate = CURRENT_RATE(ieee->mode, ieee->rate, ieee->HTCurrentOperaRate); if (bdhcp) { if (ieee->pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom) { tcb_desc->data_rate = MgntQuery_TxRateExcludeCCKRates(ieee); tcb_desc->bTxDisableRateFallBack = false; } else { tcb_desc->data_rate = MGN_1M; tcb_desc->bTxDisableRateFallBack = 1; } tcb_desc->RATRIndex = 7; tcb_desc->bTxUseDriverAssingedRate = 1; tcb_desc->bdhcp = 1; } rtllib_qurey_ShortPreambleMode(ieee, tcb_desc); rtllib_tx_query_agg_cap(ieee, txb->fragments[0], tcb_desc); rtllib_query_HTCapShortGI(ieee, tcb_desc); rtllib_query_BandwidthMode(ieee, tcb_desc); rtllib_query_protectionmode(ieee, tcb_desc, txb->fragments[0]); } } spin_unlock_irqrestore(&ieee->lock, flags); dev_kfree_skb_any(skb); if (txb) { if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE) { dev->stats.tx_packets++; dev->stats.tx_bytes += le16_to_cpu(txb->payload_size); rtllib_softmac_xmit(txb, ieee); } else { if ((*ieee->hard_start_xmit)(txb, dev) == 0) { stats->tx_packets++; stats->tx_bytes += le16_to_cpu(txb->payload_size); return 0; } rtllib_txb_free(txb); } } return 0; failed: spin_unlock_irqrestore(&ieee->lock, flags); netif_stop_queue(dev); stats->tx_errors++; return 1; } int rtllib_xmit(struct sk_buff *skb, struct net_device *dev) { memset(skb->cb, 0, sizeof(skb->cb)); return rtllib_xmit_inter(skb, dev); }
static int wpa_config_parse_eap(struct parse_data *data, int line, const char *value) { int last, errors = 0; char *start, *end, *buf; u8 *methods = NULL, *tmp; size_t num_methods = 0; buf = strdup(value); if (buf == NULL) return -1; start = buf; while (*start != '\0') { while (*start == ' ' || *start == '\t') start++; if (*start == '\0') break; end = start; while (*end != ' ' && *end != '\t' && *end != '\0') end++; last = *end == '\0'; *end = '\0'; tmp = methods; methods = realloc(methods, num_methods + 1); if (methods == NULL) { free(tmp); return -1; } methods[num_methods] = eap_get_type(start); if (methods[num_methods] == EAP_TYPE_NONE) { wpa_printf(MSG_ERROR, "Line %d: unknown EAP method " "'%s'", line, start); wpa_printf(MSG_ERROR, "You may need to add support for" " this EAP method during wpa_supplicant\n" "build time configuration.\n" "See README for more information."); errors++; } else if (methods[num_methods] == EAP_TYPE_LEAP) data->ssid->leap++; else data->ssid->non_leap++; num_methods++; if (last) break; start = end + 1; } free(buf); tmp = methods; methods = realloc(methods, num_methods + 1); if (methods == NULL) { free(tmp); return -1; } methods[num_methods] = EAP_TYPE_NONE; num_methods++; wpa_hexdump(MSG_MSGDUMP, "eap methods", methods, num_methods); data->ssid->eap_methods = methods; return errors ? -1 : 0; }
/* SKBs are added to the ieee->tx_queue. */ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) { #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) struct ieee80211_device *ieee = netdev_priv(dev); #else struct ieee80211_device *ieee = (struct ieee80211_device *)dev->priv; #endif struct ieee80211_txb *txb = NULL; struct ieee80211_hdr *frag_hdr; int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size; unsigned long flags; struct net_device_stats *stats = &ieee->stats; int ether_type, encrypt; int bytes, fc, hdr_len; struct sk_buff *skb_frag; struct ieee80211_hdr header = { /* Ensure zero initialized */ .duration_id = 0, .seq_ctl = 0 }; u8 dest[ETH_ALEN], src[ETH_ALEN]; int pend; struct ieee80211_crypt_data* crypt; spin_lock_irqsave(&ieee->lock, flags); /* If there is no driver handler to take the TXB, dont' bother * creating it... */ if ((!ieee->hard_start_xmit && !(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE))|| ((!ieee->softmac_data_hard_start_xmit && (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) { printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name); goto success; } if(likely(ieee->raw_tx == 0)){ if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) { printk(KERN_WARNING "%s: skb too small (%d).\n", ieee->dev->name, skb->len); goto success; } ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto); crypt = ieee->crypt[ieee->tx_keyidx]; encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) && ieee->host_encrypt && crypt && crypt->ops; if (!encrypt && ieee->ieee802_1x && ieee->drop_unencrypted && ether_type != ETH_P_PAE) { stats->tx_dropped++; goto success; } #ifdef CONFIG_IEEE80211_DEBUG if (crypt && !encrypt && ether_type == ETH_P_PAE) { struct eapol *eap = (struct eapol *)(skb->data + sizeof(struct ethhdr) - SNAP_SIZE - sizeof(u16)); IEEE80211_DEBUG_EAP("TX: IEEE 802.11 EAPOL frame: %s\n", eap_get_type(eap->type)); } #endif /* Save source and destination addresses */ memcpy(&dest, skb->data, ETH_ALEN); memcpy(&src, skb->data+ETH_ALEN, ETH_ALEN); /* Advance the SKB to the start of the payload */ skb_pull(skb, sizeof(struct ethhdr)); /* Determine total amount of storage required for TXB packets */ bytes = skb->len + SNAP_SIZE + sizeof(u16); if (encrypt) fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA | IEEE80211_FCTL_WEP; else fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA; if (ieee->iw_mode == IW_MODE_INFRA) { fc |= IEEE80211_FCTL_TODS; /* To DS: Addr1 = BSSID, Addr2 = SA, Addr3 = DA */ memcpy(&header.addr1, ieee->current_network.bssid, ETH_ALEN); memcpy(&header.addr2, &src, ETH_ALEN); memcpy(&header.addr3, &dest, ETH_ALEN); } else if (ieee->iw_mode == IW_MODE_ADHOC) { /* not From/To DS: Addr1 = DA, Addr2 = SA, Addr3 = BSSID */ memcpy(&header.addr1, dest, ETH_ALEN); memcpy(&header.addr2, src, ETH_ALEN); memcpy(&header.addr3, ieee->current_network.bssid, ETH_ALEN); } header.frame_ctl = cpu_to_le16(fc); hdr_len = IEEE80211_3ADDR_LEN; /* Determine fragmentation size based on destination (multicast * and broadcast are not fragmented) */ if (is_multicast_ether_addr(dest) || is_broadcast_ether_addr(dest)) frag_size = MAX_FRAG_THRESHOLD; else frag_size = ieee->fts; /* Determine amount of payload per fragment. Regardless of if * this stack is providing the full 802.11 header, one will * eventually be affixed to this fragment -- so we must account for * it when determining the amount of payload space. */ bytes_per_frag = frag_size - IEEE80211_3ADDR_LEN; if (ieee->config & (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) bytes_per_frag -= IEEE80211_FCS_LEN; /* Each fragment may need to have room for encryptiong pre/postfix */ if (encrypt) bytes_per_frag -= crypt->ops->extra_prefix_len + crypt->ops->extra_postfix_len; /* Number of fragments is the total bytes_per_frag / * payload_per_fragment */ nr_frags = bytes / bytes_per_frag; bytes_last_frag = bytes % bytes_per_frag; if (bytes_last_frag) nr_frags++; else bytes_last_frag = bytes_per_frag; /* When we allocate the TXB we allocate enough space for the reserve * and full fragment bytes (bytes_per_frag doesn't include prefix, * postfix, header, FCS, etc.) */ pend = atomic_read(&ieee->tx_pending_txb); if(pend > (MAX_TX_SKB - 1)) { goto failed; } else { atomic_inc(&ieee->tx_pending_txb); } txb = ieee->alloc_txb[ieee->tx_skb_index]; ieee->tx_skb_index = (ieee->tx_skb_index + 1) % MAX_TX_SKB; if (unlikely(!txb)) { printk(KERN_WARNING "%s: Could not allocate TXB\n", ieee->dev->name); goto failed; } for(i = 0; i < txb->nr_frags; i++) { txb->fragments[i]->len = 0; txb->fragments[i]->data = txb->fragments[i]->head + 16; txb->fragments[i]->tail = txb->fragments[i]->data; } #if 1 txb->nr_frags = nr_frags; txb->frag_size = frag_size; #endif txb->encrypted = encrypt; txb->payload_size = bytes; for (i = 0; i < nr_frags; i++) { skb_frag = txb->fragments[i]; if (encrypt) skb_reserve(skb_frag, crypt->ops->extra_prefix_len); frag_hdr = (struct ieee80211_hdr *)skb_put(skb_frag, hdr_len); memcpy(frag_hdr, &header, hdr_len); /* If this is not the last fragment, then add the MOREFRAGS * bit to the frame control */ if (i != nr_frags - 1) { frag_hdr->frame_ctl = cpu_to_le16( fc | IEEE80211_FCTL_MOREFRAGS); bytes = bytes_per_frag; } else { /* The last fragment takes the remaining length */ bytes = bytes_last_frag; } frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl<<4 | i); /* Put a SNAP header on the first fragment */ if (i == 0) { ieee80211_put_snap( skb_put(skb_frag, SNAP_SIZE + sizeof(u16)), ether_type); bytes -= SNAP_SIZE + sizeof(u16); } memcpy(skb_put(skb_frag, bytes), skb->data, bytes); /* Advance the SKB... */ skb_pull(skb, bytes); /* Encryption routine will move the header forward in order * to insert the IV between the header and the payload */ if (encrypt) ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len); if (ieee->config & (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) skb_put(skb_frag, 4); } if (ieee->seq_ctrl == 0xFFF) ieee->seq_ctrl = 0; else ieee->seq_ctrl++; }else{ if (unlikely(skb->len < sizeof(struct ieee80211_hdr_3addr))) { printk(KERN_WARNING "%s: skb too small (%d).\n", ieee->dev->name, skb->len); goto success; } txb = ieee80211_alloc_txb(1, skb->len, GFP_ATOMIC); if(!txb){ printk(KERN_WARNING "%s: Could not allocate TXB\n", ieee->dev->name); goto failed; } txb->encrypted = 0; txb->payload_size = skb->len; memcpy(skb_put(txb->fragments[0],skb->len), skb->data, skb->len); } success: spin_unlock_irqrestore(&ieee->lock, flags); dev_kfree_skb_any(skb); if (txb) { if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE){ ieee80211_softmac_xmit(txb, ieee); }else{ if ((*ieee->hard_start_xmit)(txb, dev) == 0) { stats->tx_packets++; stats->tx_bytes += txb->payload_size; return 0; } ieee80211_txb_free(txb, txb->nr_frags); } } return 0; failed: spin_unlock_irqrestore(&ieee->lock, flags); netif_stop_queue(dev); stats->tx_errors++; return 1; } #ifndef BUILT_IN_IEEE80211 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) EXPORT_SYMBOL(ieee80211_txb_free); EXPORT_SYMBOL(ieee80211_alloc_txb); #else EXPORT_SYMBOL_NOVERS(ieee80211_txb_free); EXPORT_SYMBOL_NOVERS(ieee80211_alloc_txb);
static int hostapd_config_read_eap_user(const char *fname, struct hostapd_config *conf) { FILE *f; char buf[512], *pos, *start, *pos2; int line = 0, ret = 0, num_methods; struct hostapd_eap_user *user, *tail = NULL; if (!fname) return 0; f = fopen(fname, "r"); if (!f) { printf("EAP user file '%s' not found.\n", fname); return -1; } /* Lines: "user" METHOD,METHOD2 "password" (password optional) */ while (fgets(buf, sizeof(buf), f)) { line++; if (buf[0] == '#') continue; pos = buf; while (*pos != '\0') { if (*pos == '\n') { *pos = '\0'; break; } pos++; } if (buf[0] == '\0') continue; user = NULL; if (buf[0] != '"' && buf[0] != '*') { printf("Invalid EAP identity (no \" in start) on " "line %d in '%s'\n", line, fname); goto failed; } user = malloc(sizeof(*user)); if (user == NULL) { printf("EAP user allocation failed\n"); goto failed; } memset(user, 0, sizeof(*user)); user->force_version = -1; if (buf[0] == '*') { pos = buf; } else { pos = buf + 1; start = pos; while (*pos != '"' && *pos != '\0') pos++; if (*pos == '\0') { printf("Invalid EAP identity (no \" in end) on" " line %d in '%s'\n", line, fname); goto failed; } user->identity = malloc(pos - start); if (user->identity == NULL) { printf("Failed to allocate memory for EAP " "identity\n"); goto failed; } memcpy(user->identity, start, pos - start); user->identity_len = pos - start; } pos++; while (*pos == ' ' || *pos == '\t') pos++; if (*pos == '\0') { printf("No EAP method on line %d in '%s'\n", line, fname); goto failed; } start = pos; while (*pos != ' ' && *pos != '\t' && *pos != '\0') pos++; if (*pos == '\0') { pos = NULL; } else { *pos = '\0'; pos++; } num_methods = 0; while (*start) { char *pos2 = strchr(start, ','); if (pos2) { *pos2++ = '\0'; } user->methods[num_methods] = eap_get_type(start); if (user->methods[num_methods] == EAP_TYPE_NONE) { printf("Unsupported EAP type '%s' on line %d " "in '%s'\n", start, line, fname); goto failed; } num_methods++; if (num_methods >= EAP_USER_MAX_METHODS) break; if (pos2 == NULL) break; start = pos2; } if (num_methods == 0) { printf("No EAP types configured on line %d in '%s'\n", line, fname); goto failed; } if (pos == NULL) goto done; while (*pos == ' ' || *pos == '\t') pos++; if (*pos == '\0') goto done; if (strncmp(pos, "[ver=0]", 7) == 0) { user->force_version = 0; goto done; } if (strncmp(pos, "[ver=1]", 7) == 0) { user->force_version = 1; goto done; } if (strncmp(pos, "[2]", 3) == 0) { user->phase2 = 1; goto done; } if (*pos == '"') { pos++; start = pos; while (*pos != '"' && *pos != '\0') pos++; if (*pos == '\0') { printf("Invalid EAP password (no \" in end) " "on line %d in '%s'\n", line, fname); goto failed; } user->password = malloc(pos - start); if (user->password == NULL) { printf("Failed to allocate memory for EAP " "password\n"); goto failed; } memcpy(user->password, start, pos - start); user->password_len = pos - start; pos++; } else { pos2 = pos; while (*pos2 != '\0' && *pos2 != ' ' && *pos2 != '\t' && *pos2 != '#') pos2++; if ((pos2 - pos) & 1) { printf("Invalid hex password on line %d in " "'%s'\n", line, fname); goto failed; } user->password = malloc((pos2 - pos) / 2); if (user->password == NULL) { printf("Failed to allocate memory for EAP " "password\n"); goto failed; } if (hexstr2bin(pos, user->password, (pos2 - pos) / 2) < 0) { printf("Invalid hex password on line %d in " "'%s'\n", line, fname); goto failed; } user->password_len = (pos2 - pos) / 2; pos = pos2; } while (*pos == ' ' || *pos == '\t') pos++; if (strncmp(pos, "[2]", 3) == 0) { user->phase2 = 1; } done: if (tail == NULL) { tail = conf->eap_user = user; } else { tail->next = user; tail = user; } continue; failed: if (user) { free(user->identity); free(user); } ret = -1; break; } fclose(f); return ret; }
int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) struct ieee80211_device *ieee = netdev_priv(dev); #else struct ieee80211_device *ieee = (struct ieee80211_device *)dev->priv; #endif struct ieee80211_txb *txb = NULL; struct ieee80211_hdr_3addrqos *frag_hdr; int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size; unsigned long flags; struct net_device_stats *stats = &ieee->stats; int ether_type = 0, encrypt; int bytes, fc, qos_ctl = 0, hdr_len; struct sk_buff *skb_frag; struct ieee80211_hdr_3addrqos header = { .duration_id = 0, .seq_ctl = 0, .qos_ctl = 0 }; u8 dest[ETH_ALEN], src[ETH_ALEN]; int qos_actived = ieee->current_network.qos_data.active; struct ieee80211_crypt_data* crypt; cb_desc *tcb_desc; spin_lock_irqsave(&ieee->lock, flags); if ((!ieee->hard_start_xmit && !(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE))|| ((!ieee->softmac_data_hard_start_xmit && (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) { printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name); goto success; } if(likely(ieee->raw_tx == 0)){ if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) { printk(KERN_WARNING "%s: skb too small (%d).\n", ieee->dev->name, skb->len); goto success; } memset(skb->cb, 0, sizeof(skb->cb)); ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto); crypt = ieee->crypt[ieee->tx_keyidx]; encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) && ieee->host_encrypt && crypt && crypt->ops; if (!encrypt && ieee->ieee802_1x && ieee->drop_unencrypted && ether_type != ETH_P_PAE) { stats->tx_dropped++; goto success; } #ifdef CONFIG_IEEE80211_DEBUG if (crypt && !encrypt && ether_type == ETH_P_PAE) { struct eapol *eap = (struct eapol *)(skb->data + sizeof(struct ethhdr) - SNAP_SIZE - sizeof(u16)); IEEE80211_DEBUG_EAP("TX: IEEE 802.11 EAPOL frame: %s\n", eap_get_type(eap->type)); } #endif memcpy(&dest, skb->data, ETH_ALEN); memcpy(&src, skb->data+ETH_ALEN, ETH_ALEN); skb_pull(skb, sizeof(struct ethhdr)); bytes = skb->len + SNAP_SIZE + sizeof(u16); if (encrypt) fc = IEEE80211_FTYPE_DATA | IEEE80211_FCTL_WEP; else fc = IEEE80211_FTYPE_DATA; if(qos_actived) fc |= IEEE80211_STYPE_QOS_DATA; else fc |= IEEE80211_STYPE_DATA; if (ieee->iw_mode == IW_MODE_INFRA) { fc |= IEEE80211_FCTL_TODS; memcpy(&header.addr1, ieee->current_network.bssid, ETH_ALEN); memcpy(&header.addr2, &src, ETH_ALEN); memcpy(&header.addr3, &dest, ETH_ALEN); } else if (ieee->iw_mode == IW_MODE_ADHOC) { memcpy(&header.addr1, dest, ETH_ALEN); memcpy(&header.addr2, src, ETH_ALEN); memcpy(&header.addr3, ieee->current_network.bssid, ETH_ALEN); } header.frame_ctl = cpu_to_le16(fc); if (is_multicast_ether_addr(header.addr1) || is_broadcast_ether_addr(header.addr1)) { frag_size = MAX_FRAG_THRESHOLD; qos_ctl |= QOS_CTL_NOTCONTAIN_ACK; } else { frag_size = ieee->fts; qos_ctl = 0; } if(qos_actived) { hdr_len = IEEE80211_3ADDR_LEN + 2; skb->priority = ieee80211_classify(skb, &ieee->current_network); qos_ctl |= skb->priority; header.qos_ctl = cpu_to_le16(qos_ctl & IEEE80211_QOS_TID); } else { hdr_len = IEEE80211_3ADDR_LEN; } bytes_per_frag = frag_size - hdr_len; if (ieee->config & (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) bytes_per_frag -= IEEE80211_FCS_LEN; if (encrypt) bytes_per_frag -= crypt->ops->extra_prefix_len + crypt->ops->extra_postfix_len; nr_frags = bytes / bytes_per_frag; bytes_last_frag = bytes % bytes_per_frag; if (bytes_last_frag) nr_frags++; else bytes_last_frag = bytes_per_frag; txb = ieee80211_alloc_txb(nr_frags, frag_size + ieee->tx_headroom, GFP_ATOMIC); if (unlikely(!txb)) { printk(KERN_WARNING "%s: Could not allocate TXB\n", ieee->dev->name); goto failed; } txb->encrypted = encrypt; txb->payload_size = bytes; if(qos_actived) { txb->queue_index = UP2AC(skb->priority); } else { txb->queue_index = WME_AC_BK;; } for (i = 0; i < nr_frags; i++) { skb_frag = txb->fragments[i]; tcb_desc = (cb_desc *)(skb_frag->cb + MAX_DEV_ADDR_SIZE); if(qos_actived){ skb_frag->priority = skb->priority; tcb_desc->queue_index = UP2AC(skb->priority); } else { skb_frag->priority = WME_AC_BK; tcb_desc->queue_index = WME_AC_BK; } skb_reserve(skb_frag, ieee->tx_headroom); if (encrypt){ if (ieee->hwsec_active) tcb_desc->bHwSec = 1; else tcb_desc->bHwSec = 0; skb_reserve(skb_frag, crypt->ops->extra_prefix_len); } else { tcb_desc->bHwSec = 0; } frag_hdr = (struct ieee80211_hdr_3addrqos *)skb_put(skb_frag, hdr_len); memcpy(frag_hdr, &header, hdr_len); if (i != nr_frags - 1) { frag_hdr->frame_ctl = cpu_to_le16( fc | IEEE80211_FCTL_MOREFRAGS); bytes = bytes_per_frag; } else { bytes = bytes_last_frag; } if(qos_actived) { frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[UP2AC(skb->priority)+1]<<4 | i); } else { frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4 | i); } if (i == 0) { ieee80211_put_snap( skb_put(skb_frag, SNAP_SIZE + sizeof(u16)), ether_type); bytes -= SNAP_SIZE + sizeof(u16); } memcpy(skb_put(skb_frag, bytes), skb->data, bytes); skb_pull(skb, bytes); if (encrypt) ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len); if (ieee->config & (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) skb_put(skb_frag, 4); } if(qos_actived) { if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF) ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0; else ieee->seq_ctrl[UP2AC(skb->priority) + 1]++; } else { if (ieee->seq_ctrl[0] == 0xFFF) ieee->seq_ctrl[0] = 0; else ieee->seq_ctrl[0]++; } }else{ if (unlikely(skb->len < sizeof(struct ieee80211_hdr_3addr))) { printk(KERN_WARNING "%s: skb too small (%d).\n", ieee->dev->name, skb->len); goto success; } txb = ieee80211_alloc_txb(1, skb->len, GFP_ATOMIC); if(!txb){ printk(KERN_WARNING "%s: Could not allocate TXB\n", ieee->dev->name); goto failed; } txb->encrypted = 0; txb->payload_size = skb->len; memcpy(skb_put(txb->fragments[0],skb->len), skb->data, skb->len); } success: if (txb) { #if 1 cb_desc *tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE); tcb_desc->bTxEnableFwCalcDur = 1; if (is_multicast_ether_addr(header.addr1)) tcb_desc->bMulticast = 1; if (is_broadcast_ether_addr(header.addr1)) tcb_desc->bBroadcast = 1; ieee80211_txrate_selectmode(ieee, tcb_desc); if ( tcb_desc->bMulticast || tcb_desc->bBroadcast) tcb_desc->data_rate = ieee->basic_rate; else tcb_desc->data_rate = CURRENT_RATE(ieee->mode, ieee->rate, ieee->HTCurrentOperaRate); ieee80211_qurey_ShortPreambleMode(ieee, tcb_desc); ieee80211_tx_query_agg_cap(ieee, txb->fragments[0], tcb_desc); ieee80211_query_HTCapShortGI(ieee, tcb_desc); ieee80211_query_BandwidthMode(ieee, tcb_desc); ieee80211_query_protectionmode(ieee, tcb_desc, txb->fragments[0]); ieee80211_query_seqnum(ieee, txb->fragments[0], header.addr1); #endif } spin_unlock_irqrestore(&ieee->lock, flags); dev_kfree_skb_any(skb); if (txb) { if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE){ ieee80211_softmac_xmit(txb, ieee); }else{ if ((*ieee->hard_start_xmit)(txb, dev) == 0) { stats->tx_packets++; stats->tx_bytes += txb->payload_size; return 0; } ieee80211_txb_free(txb); } } return 0; failed: spin_unlock_irqrestore(&ieee->lock, flags); netif_stop_queue(dev); stats->tx_errors++; return 1; }
int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev) { struct ieee80211_device *ieee = netdev_priv(dev); struct ieee80211_txb *txb = NULL; struct ieee80211_hdr_3addrqos *frag_hdr; int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size; unsigned long flags; struct net_device_stats *stats = &ieee->stats; int ether_type = 0, encrypt; int bytes, fc, qos_ctl = 0, hdr_len; struct sk_buff *skb_frag; struct ieee80211_hdr_3addrqos header = { /* Ensure zero initialized */ .duration_id = 0, .seq_ctl = 0, .qos_ctl = 0 }; u8 dest[ETH_ALEN], src[ETH_ALEN]; int qos_actived = ieee->current_network.qos_data.active; struct ieee80211_crypt_data* crypt; bool bdhcp =false; cb_desc *tcb_desc; spin_lock_irqsave(&ieee->lock, flags); /* If there is no driver handler to take the TXB, dont' bother * creating it... */ if ((!ieee->hard_start_xmit && !(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE))|| ((!ieee->softmac_data_hard_start_xmit && (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) { printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name); goto success; } if(likely(ieee->raw_tx == 0)){ if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) { printk(KERN_WARNING "%s: skb too small (%d).\n", ieee->dev->name, skb->len); goto success; } memset(skb->cb, 0, sizeof(skb->cb)); ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto); crypt = ieee->crypt[ieee->tx_keyidx]; encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) && ieee->host_encrypt && crypt && crypt->ops; if (!encrypt && ieee->ieee802_1x && ieee->drop_unencrypted && ether_type != ETH_P_PAE) { stats->tx_dropped++; goto success; } #ifdef CONFIG_IEEE80211_DEBUG if (crypt && !encrypt && ether_type == ETH_P_PAE) { struct eapol *eap = (struct eapol *)(skb->data + sizeof(struct ethhdr) - SNAP_SIZE - sizeof(u16)); IEEE80211_DEBUG_EAP("TX: IEEE 802.11 EAPOL frame: %s\n", eap_get_type(eap->type)); } #endif // 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 if (skb->len > 282){//MINIMUM_DHCP_PACKET_SIZE) { if (ETH_P_IP == ether_type) {// IP header const struct iphdr *ip = (struct iphdr *)((u8 *)skb->data+14); if (IPPROTO_UDP == ip->protocol) {//FIXME windows is 11 but here UDP in linux kernel is 17. struct udphdr *udp = (struct udphdr *)((u8 *)ip + (ip->ihl << 2)); //if(((ntohs(udp->source) == 68) && (ntohs(udp->dest) == 67)) || /// ((ntohs(udp->source) == 67) && (ntohs(udp->dest) == 68))) { if(((((u8 *)udp)[1] == 68) && (((u8 *)udp)[3] == 67)) || ((((u8 *)udp)[1] == 67) && (((u8 *)udp)[3] == 68))) { // 68 : UDP BOOTP client // 67 : UDP BOOTP server printk("DHCP pkt src port:%d, dest port:%d!!\n", ((u8 *)udp)[1],((u8 *)udp)[3]); // Use low rate to send DHCP packet. //if(pMgntInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom) //{ // tcb_desc->DataRate = MgntQuery_TxRateExcludeCCKRates(ieee);//0xc;//ofdm 6m // tcb_desc->bTxDisableRateFallBack = false; //} //else //pTcb->DataRate = Adapter->MgntInfo.LowestBasicRate; //RTPRINT(FDM, WA_IOT, ("DHCP TranslateHeader(), pTcb->DataRate = 0x%x\n", pTcb->DataRate)); bdhcp = true; #ifdef _RTL8192_EXT_PATCH_ ieee->LPSDelayCnt = 100;//pPSC->LPSAwakeIntvl*2; //AMY,090701 #else ieee->LPSDelayCnt = 100;//pPSC->LPSAwakeIntvl*2; #endif } } }else if(ETH_P_ARP == ether_type){// IP ARP packet printk("=================>DHCP Protocol start tx ARP pkt!!\n"); bdhcp = true; ieee->LPSDelayCnt = ieee->current_network.tim.tim_count; //if(pMgntInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom) //{ // tcb_desc->DataRate = MgntQuery_TxRateExcludeCCKRates(Adapter->MgntInfo.mBrates);//0xc;//ofdm 6m // tcb_desc->bTxDisableRateFallBack = FALSE; //} //else // tcb_desc->DataRate = Adapter->MgntInfo.LowestBasicRate; //RTPRINT(FDM, WA_IOT, ("ARP TranslateHeader(), pTcb->DataRate = 0x%x\n", pTcb->DataRate)); } } /* Save source and destination addresses */ memcpy(&dest, skb->data, ETH_ALEN); memcpy(&src, skb->data+ETH_ALEN, ETH_ALEN); /* Advance the SKB to the start of the payload */ skb_pull(skb, sizeof(struct ethhdr)); /* Determine total amount of storage required for TXB packets */ bytes = skb->len + SNAP_SIZE + sizeof(u16); if (encrypt) fc = IEEE80211_FTYPE_DATA | IEEE80211_FCTL_WEP; else fc = IEEE80211_FTYPE_DATA; //if(ieee->current_network.QoS_Enable) if(qos_actived) fc |= IEEE80211_STYPE_QOS_DATA; else fc |= IEEE80211_STYPE_DATA; if (ieee->iw_mode == IW_MODE_INFRA) { fc |= IEEE80211_FCTL_TODS; /* To DS: Addr1 = BSSID, Addr2 = SA, Addr3 = DA */ memcpy(&header.addr1, ieee->current_network.bssid, ETH_ALEN); memcpy(&header.addr2, &src, ETH_ALEN); memcpy(&header.addr3, &dest, ETH_ALEN); } else if (ieee->iw_mode == IW_MODE_ADHOC) { /* not From/To DS: Addr1 = DA, Addr2 = SA, Addr3 = BSSID */ memcpy(&header.addr1, dest, ETH_ALEN); memcpy(&header.addr2, src, ETH_ALEN); memcpy(&header.addr3, ieee->current_network.bssid, ETH_ALEN); } header.frame_ctl = cpu_to_le16(fc); /* Determine fragmentation size based on destination (multicast * and broadcast are not fragmented) */ if (is_multicast_ether_addr(header.addr1) || is_broadcast_ether_addr(header.addr1)) { frag_size = MAX_FRAG_THRESHOLD; qos_ctl |= QOS_CTL_NOTCONTAIN_ACK; } else { frag_size = ieee->fts;//default:392 qos_ctl = 0; } //if (ieee->current_network.QoS_Enable) if(qos_actived) { hdr_len = IEEE80211_3ADDR_LEN + 2; skb->priority = ieee80211_classify(skb, &ieee->current_network); qos_ctl |= skb->priority; //set in the ieee80211_classify header.qos_ctl = cpu_to_le16(qos_ctl & IEEE80211_QOS_TID); } else { hdr_len = IEEE80211_3ADDR_LEN; } /* Determine amount of payload per fragment. Regardless of if * this stack is providing the full 802.11 header, one will * eventually be affixed to this fragment -- so we must account for * it when determining the amount of payload space. */ bytes_per_frag = frag_size - hdr_len; if (ieee->config & (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) bytes_per_frag -= IEEE80211_FCS_LEN; /* Each fragment may need to have room for encryptiong pre/postfix */ if (encrypt) bytes_per_frag -= crypt->ops->extra_prefix_len + crypt->ops->extra_postfix_len; /* Number of fragments is the total bytes_per_frag / * payload_per_fragment */ nr_frags = bytes / bytes_per_frag; bytes_last_frag = bytes % bytes_per_frag; if (bytes_last_frag) nr_frags++; else bytes_last_frag = bytes_per_frag; /* When we allocate the TXB we allocate enough space for the reserve * and full fragment bytes (bytes_per_frag doesn't include prefix, * postfix, header, FCS, etc.) */ txb = ieee80211_alloc_txb(nr_frags, frag_size + ieee->tx_headroom, GFP_ATOMIC); if (unlikely(!txb)) { printk(KERN_WARNING "%s: Could not allocate TXB\n", ieee->dev->name); goto failed; } txb->encrypted = encrypt; txb->payload_size = bytes; //if (ieee->current_network.QoS_Enable) if(qos_actived) { txb->queue_index = UP2AC(skb->priority); } else { txb->queue_index = WME_AC_BK; } for (i = 0; i < nr_frags; i++) { skb_frag = txb->fragments[i]; tcb_desc = (cb_desc *)(skb_frag->cb + MAX_DEV_ADDR_SIZE); if(qos_actived){ skb_frag->priority = skb->priority;//UP2AC(skb->priority); tcb_desc->queue_index = UP2AC(skb->priority); } else { skb_frag->priority = WME_AC_BK; tcb_desc->queue_index = WME_AC_BK; } skb_reserve(skb_frag, ieee->tx_headroom); if (encrypt){ if (ieee->hwsec_active) tcb_desc->bHwSec = 1; else tcb_desc->bHwSec = 0; skb_reserve(skb_frag, crypt->ops->extra_prefix_len); } else { tcb_desc->bHwSec = 0; } frag_hdr = (struct ieee80211_hdr_3addrqos *)skb_put(skb_frag, hdr_len); memcpy(frag_hdr, &header, hdr_len); /* If this is not the last fragment, then add the MOREFRAGS * bit to the frame control */ if (i != nr_frags - 1) { frag_hdr->frame_ctl = cpu_to_le16( fc | IEEE80211_FCTL_MOREFRAGS); bytes = bytes_per_frag; } else { /* The last fragment takes the remaining length */ bytes = bytes_last_frag; } //if(ieee->current_network.QoS_Enable) if(qos_actived) { // add 1 only indicate to corresponding seq number control 2006/7/12 frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[UP2AC(skb->priority)+1]<<4 | i); } else { frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4 | i); } /* Put a SNAP header on the first fragment */ if (i == 0) { ieee80211_put_snap( skb_put(skb_frag, SNAP_SIZE + sizeof(u16)), ether_type); bytes -= SNAP_SIZE + sizeof(u16); } memcpy(skb_put(skb_frag, bytes), skb->data, bytes); /* Advance the SKB... */ skb_pull(skb, bytes); /* Encryption routine will move the header forward in order * to insert the IV between the header and the payload */ if (encrypt) ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len); if (ieee->config & (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) skb_put(skb_frag, 4); } if(qos_actived) { if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF) ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0; else ieee->seq_ctrl[UP2AC(skb->priority) + 1]++; } else { if (ieee->seq_ctrl[0] == 0xFFF) ieee->seq_ctrl[0] = 0; else ieee->seq_ctrl[0]++; } }else{ if (unlikely(skb->len < sizeof(struct ieee80211_hdr_3addr))) { printk(KERN_WARNING "%s: skb too small (%d).\n", ieee->dev->name, skb->len); goto success; } txb = ieee80211_alloc_txb(1, skb->len, GFP_ATOMIC); if(!txb){ printk(KERN_WARNING "%s: Could not allocate TXB\n", ieee->dev->name); goto failed; } txb->encrypted = 0; txb->payload_size = skb->len; memcpy(skb_put(txb->fragments[0],skb->len), skb->data, skb->len); } success: //WB add to fill data tcb_desc here. only first fragment is considered, need to change, and you may remove to other place. if (txb) { #if 1 cb_desc *tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE); tcb_desc->bTxEnableFwCalcDur = 1; if (is_multicast_ether_addr(header.addr1)) tcb_desc->bMulticast = 1; if (is_broadcast_ether_addr(header.addr1)) tcb_desc->bBroadcast = 1; ieee80211_txrate_selectmode(ieee, tcb_desc); if ( tcb_desc->bMulticast || tcb_desc->bBroadcast) tcb_desc->data_rate = ieee->basic_rate; else //tcb_desc->data_rate = CURRENT_RATE(ieee->current_network.mode, ieee->rate, ieee->HTCurrentOperaRate); tcb_desc->data_rate = CURRENT_RATE(ieee->mode, ieee->rate, ieee->HTCurrentOperaRate); if(bdhcp == true){ // Use low rate to send DHCP packet. //if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom) { // tcb_desc->data_rate = MGN_1M;//MgntQuery_TxRateExcludeCCKRates(ieee);//0xc;//ofdm 6m // tcb_desc->bTxDisableRateFallBack = false; //} //else { tcb_desc->data_rate = MGN_1M; tcb_desc->bTxDisableRateFallBack = 1; } tcb_desc->RATRIndex = 7; tcb_desc->bTxUseDriverAssingedRate = 1; tcb_desc->bdhcp = 1; } ieee80211_qurey_ShortPreambleMode(ieee, tcb_desc); ieee80211_tx_query_agg_cap(ieee, txb->fragments[0], tcb_desc); ieee80211_query_HTCapShortGI(ieee, tcb_desc); ieee80211_query_BandwidthMode(ieee, tcb_desc); ieee80211_query_protectionmode(ieee, tcb_desc, txb->fragments[0]); ieee80211_query_seqnum(ieee, txb->fragments[0], header.addr1); // IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, txb->fragments[0]->data, txb->fragments[0]->len); //IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, tcb_desc, sizeof(cb_desc)); #endif } spin_unlock_irqrestore(&ieee->lock, flags); dev_kfree_skb_any(skb); if (txb) { if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE){ ieee80211_softmac_xmit(txb, ieee); }else{ if ((*ieee->hard_start_xmit)(txb, dev) == 0) { stats->tx_packets++; stats->tx_bytes += txb->payload_size; return 0; } ieee80211_txb_free(txb); } } return 0; failed: spin_unlock_irqrestore(&ieee->lock, flags); netif_stop_queue(dev); stats->tx_errors++; return 1; }