Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /******************************************************************************
0003  * rtl871x_recv.c
0004  *
0005  * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
0006  * Linux device driver for RTL8192SU
0007  *
0008  * Modifications for inclusion into the Linux staging tree are
0009  * Copyright(c) 2010 Larry Finger. All rights reserved.
0010  *
0011  * Contact information:
0012  * WLAN FAE <wlanfae@realtek.com>
0013  * Larry Finger <Larry.Finger@lwfinger.net>
0014  *
0015  ******************************************************************************/
0016 
0017 #define _RTL871X_RECV_C_
0018 
0019 #include <linux/ip.h>
0020 #include <linux/slab.h>
0021 #include <linux/if_ether.h>
0022 #include <linux/kmemleak.h>
0023 #include <linux/etherdevice.h>
0024 #include <linux/ieee80211.h>
0025 #include <net/cfg80211.h>
0026 
0027 #include "osdep_service.h"
0028 #include "drv_types.h"
0029 #include "recv_osdep.h"
0030 #include "mlme_osdep.h"
0031 #include "ethernet.h"
0032 #include "usb_ops.h"
0033 #include "wifi.h"
0034 
0035 static const u8 SNAP_ETH_TYPE_IPX[2] = {0x81, 0x37};
0036 
0037 /* Datagram Delivery Protocol */
0038 static const u8 SNAP_ETH_TYPE_APPLETALK_AARP[2] = {0x80, 0xf3};
0039 
0040 void _r8712_init_sta_recv_priv(struct sta_recv_priv *psta_recvpriv)
0041 {
0042     memset((u8 *)psta_recvpriv, 0, sizeof(struct sta_recv_priv));
0043     spin_lock_init(&psta_recvpriv->lock);
0044     _init_queue(&psta_recvpriv->defrag_q);
0045 }
0046 
0047 void _r8712_init_recv_priv(struct recv_priv *precvpriv,
0048                struct _adapter *padapter)
0049 {
0050     sint i;
0051     union recv_frame *precvframe;
0052 
0053     memset((unsigned char *)precvpriv, 0, sizeof(struct  recv_priv));
0054     spin_lock_init(&precvpriv->lock);
0055     _init_queue(&precvpriv->free_recv_queue);
0056     _init_queue(&precvpriv->recv_pending_queue);
0057     precvpriv->adapter = padapter;
0058     precvpriv->free_recvframe_cnt = NR_RECVFRAME;
0059     precvpriv->pallocated_frame_buf = kzalloc(NR_RECVFRAME *
0060                 sizeof(union recv_frame) + RXFRAME_ALIGN_SZ,
0061                 GFP_ATOMIC);
0062     if (!precvpriv->pallocated_frame_buf)
0063         return;
0064     kmemleak_not_leak(precvpriv->pallocated_frame_buf);
0065     precvpriv->precv_frame_buf = precvpriv->pallocated_frame_buf +
0066                     RXFRAME_ALIGN_SZ -
0067                     ((addr_t)(precvpriv->pallocated_frame_buf) &
0068                     (RXFRAME_ALIGN_SZ - 1));
0069     precvframe = (union recv_frame *)precvpriv->precv_frame_buf;
0070     for (i = 0; i < NR_RECVFRAME; i++) {
0071         INIT_LIST_HEAD(&(precvframe->u.list));
0072         list_add_tail(&(precvframe->u.list),
0073                   &(precvpriv->free_recv_queue.queue));
0074         r8712_os_recv_resource_alloc(padapter, precvframe);
0075         precvframe->u.hdr.adapter = padapter;
0076         precvframe++;
0077     }
0078     precvpriv->rx_pending_cnt = 1;
0079     r8712_init_recv_priv(precvpriv, padapter);
0080 }
0081 
0082 void _r8712_free_recv_priv(struct recv_priv *precvpriv)
0083 {
0084     kfree(precvpriv->pallocated_frame_buf);
0085     r8712_free_recv_priv(precvpriv);
0086 }
0087 
0088 union recv_frame *r8712_alloc_recvframe(struct __queue *pfree_recv_queue)
0089 {
0090     unsigned long irqL;
0091     union recv_frame  *precvframe;
0092     struct _adapter *padapter;
0093     struct recv_priv *precvpriv;
0094 
0095     spin_lock_irqsave(&pfree_recv_queue->lock, irqL);
0096     precvframe = list_first_entry_or_null(&pfree_recv_queue->queue,
0097                           union recv_frame, u.hdr.list);
0098     if (precvframe) {
0099         list_del_init(&precvframe->u.hdr.list);
0100         padapter = precvframe->u.hdr.adapter;
0101         if (padapter) {
0102             precvpriv = &padapter->recvpriv;
0103             if (pfree_recv_queue == &precvpriv->free_recv_queue)
0104                 precvpriv->free_recvframe_cnt--;
0105         }
0106     }
0107     spin_unlock_irqrestore(&pfree_recv_queue->lock, irqL);
0108     return precvframe;
0109 }
0110 
0111 /*
0112  * caller : defrag; recvframe_chk_defrag in recv_thread  (passive)
0113  * pframequeue: defrag_queue : will be accessed in recv_thread  (passive)
0114  * using spin_lock to protect
0115  */
0116 void r8712_free_recvframe_queue(struct  __queue *pframequeue,
0117                 struct  __queue *pfree_recv_queue)
0118 {
0119     union   recv_frame *precvframe;
0120     struct list_head *plist, *phead;
0121 
0122     spin_lock(&pframequeue->lock);
0123     phead = &pframequeue->queue;
0124     plist = phead->next;
0125     while (!end_of_queue_search(phead, plist)) {
0126         precvframe = container_of(plist, union recv_frame, u.list);
0127         plist = plist->next;
0128         r8712_free_recvframe(precvframe, pfree_recv_queue);
0129     }
0130     spin_unlock(&pframequeue->lock);
0131 }
0132 
0133 sint r8712_recvframe_chkmic(struct _adapter *adapter,
0134                 union recv_frame *precvframe)
0135 {
0136     sint i, res = _SUCCESS;
0137     u32 datalen;
0138     u8 miccode[8];
0139     u8 bmic_err = false;
0140     u8 *pframe, *payload, *pframemic;
0141     u8   *mickey, idx, *iv;
0142     struct  sta_info *stainfo;
0143     struct  rx_pkt_attrib *prxattrib = &precvframe->u.hdr.attrib;
0144     struct  security_priv *psecuritypriv = &adapter->securitypriv;
0145 
0146     stainfo = r8712_get_stainfo(&adapter->stapriv, &prxattrib->ta[0]);
0147     if (prxattrib->encrypt == _TKIP_) {
0148         /* calculate mic code */
0149         if (stainfo) {
0150             if (is_multicast_ether_addr(prxattrib->ra)) {
0151                 iv = precvframe->u.hdr.rx_data +
0152                      prxattrib->hdrlen;
0153                 idx = iv[3];
0154                 mickey = &psecuritypriv->XGrprxmickey[(((idx >>
0155                      6) & 0x3)) - 1].skey[0];
0156                 if (!psecuritypriv->binstallGrpkey)
0157                     return _FAIL;
0158             } else {
0159                 mickey = &stainfo->tkiprxmickey.skey[0];
0160             }
0161             /*icv_len included the mic code*/
0162             datalen = precvframe->u.hdr.len - prxattrib->hdrlen -
0163                   prxattrib->iv_len - prxattrib->icv_len - 8;
0164             pframe = precvframe->u.hdr.rx_data;
0165             payload = pframe + prxattrib->hdrlen +
0166                   prxattrib->iv_len;
0167             seccalctkipmic(mickey, pframe, payload, datalen,
0168                        &miccode[0],
0169                        (unsigned char)prxattrib->priority);
0170             pframemic = payload + datalen;
0171             bmic_err = false;
0172             for (i = 0; i < 8; i++) {
0173                 if (miccode[i] != *(pframemic + i))
0174                     bmic_err = true;
0175             }
0176             if (bmic_err) {
0177                 if (prxattrib->bdecrypted)
0178                     r8712_handle_tkip_mic_err(adapter,
0179                                   (u8)is_multicast_ether_addr(prxattrib->ra));
0180                 res = _FAIL;
0181             } else {
0182                 /* mic checked ok */
0183                 if (!psecuritypriv->bcheck_grpkey &&
0184                     is_multicast_ether_addr(prxattrib->ra))
0185                     psecuritypriv->bcheck_grpkey = true;
0186             }
0187             recvframe_pull_tail(precvframe, 8);
0188         }
0189     }
0190     return res;
0191 }
0192 
0193 /* decrypt and set the ivlen,icvlen of the recv_frame */
0194 union recv_frame *r8712_decryptor(struct _adapter *padapter,
0195                   union recv_frame *precv_frame)
0196 {
0197     struct rx_pkt_attrib *prxattrib = &precv_frame->u.hdr.attrib;
0198     struct security_priv *psecuritypriv = &padapter->securitypriv;
0199     union recv_frame *return_packet = precv_frame;
0200 
0201     if ((prxattrib->encrypt > 0) && ((prxattrib->bdecrypted == 0) ||
0202                      psecuritypriv->sw_decrypt)) {
0203         psecuritypriv->hw_decrypted = false;
0204         switch (prxattrib->encrypt) {
0205         case _WEP40_:
0206         case _WEP104_:
0207             r8712_wep_decrypt(padapter, (u8 *)precv_frame);
0208             break;
0209         case _TKIP_:
0210             r8712_tkip_decrypt(padapter, (u8 *)precv_frame);
0211             break;
0212         case _AES_:
0213             r8712_aes_decrypt(padapter, (u8 *)precv_frame);
0214             break;
0215         default:
0216                 break;
0217         }
0218     } else if (prxattrib->bdecrypted == 1) {
0219         psecuritypriv->hw_decrypted = true;
0220     }
0221     return return_packet;
0222 }
0223 
0224 /*###set the security information in the recv_frame */
0225 union recv_frame *r8712_portctrl(struct _adapter *adapter,
0226                  union recv_frame *precv_frame)
0227 {
0228     u8 *psta_addr, *ptr;
0229     uint auth_alg;
0230     struct recv_frame_hdr *pfhdr;
0231     struct sta_info *psta;
0232     struct  sta_priv *pstapriv;
0233     union recv_frame *prtnframe;
0234     u16 ether_type;
0235 
0236     pstapriv = &adapter->stapriv;
0237     ptr = precv_frame->u.hdr.rx_data;
0238     pfhdr = &precv_frame->u.hdr;
0239     psta_addr = pfhdr->attrib.ta;
0240     psta = r8712_get_stainfo(pstapriv, psta_addr);
0241     auth_alg = adapter->securitypriv.AuthAlgrthm;
0242     if (auth_alg == 2) {
0243         /* get ether_type */
0244         ptr = ptr + pfhdr->attrib.hdrlen + LLC_HEADER_SIZE;
0245         ether_type = get_unaligned_be16(ptr);
0246 
0247         if (psta && psta->ieee8021x_blocked) {
0248             /* blocked
0249              * only accept EAPOL frame
0250              */
0251             if (ether_type == 0x888e) {
0252                 prtnframe = precv_frame;
0253             } else {
0254                 /*free this frame*/
0255                 r8712_free_recvframe(precv_frame,
0256                              &adapter->recvpriv.free_recv_queue);
0257                 prtnframe = NULL;
0258             }
0259         } else {
0260             /* allowed
0261              * check decryption status, and decrypt the
0262              * frame if needed
0263              */
0264             prtnframe = precv_frame;
0265             /* check is the EAPOL frame or not (Rekey) */
0266             if (ether_type == 0x888e) {
0267                 /* check Rekey */
0268                 prtnframe = precv_frame;
0269             }
0270         }
0271     } else {
0272         prtnframe = precv_frame;
0273     }
0274     return prtnframe;
0275 }
0276 
0277 static sint recv_decache(union recv_frame *precv_frame, u8 bretry,
0278              struct stainfo_rxcache *prxcache)
0279 {
0280     sint tid = precv_frame->u.hdr.attrib.priority;
0281     u16 seq_ctrl = ((precv_frame->u.hdr.attrib.seq_num & 0xffff) << 4) |
0282             (precv_frame->u.hdr.attrib.frag_num & 0xf);
0283 
0284     if (tid > 15)
0285         return _FAIL;
0286     if (seq_ctrl == prxcache->tid_rxseq[tid])
0287         return _FAIL;
0288     prxcache->tid_rxseq[tid] = seq_ctrl;
0289     return _SUCCESS;
0290 }
0291 
0292 static sint sta2sta_data_frame(struct _adapter *adapter,
0293                    union recv_frame *precv_frame,
0294                    struct sta_info **psta)
0295 {
0296     u8 *ptr = precv_frame->u.hdr.rx_data;
0297     sint ret = _SUCCESS;
0298     struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
0299     struct  sta_priv *pstapriv = &adapter->stapriv;
0300     struct  mlme_priv *pmlmepriv = &adapter->mlmepriv;
0301     u8 *mybssid  = get_bssid(pmlmepriv);
0302     u8 *myhwaddr = myid(&adapter->eeprompriv);
0303     u8 *sta_addr = NULL;
0304     bool bmcast = is_multicast_ether_addr(pattrib->dst);
0305 
0306     if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
0307         check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
0308         /* filter packets that SA is myself or multicast or broadcast */
0309         if (!memcmp(myhwaddr, pattrib->src, ETH_ALEN))
0310             return _FAIL;
0311         if ((memcmp(myhwaddr, pattrib->dst, ETH_ALEN)) && (!bmcast))
0312             return _FAIL;
0313         if (is_zero_ether_addr(pattrib->bssid) ||
0314             is_zero_ether_addr(mybssid) ||
0315             (memcmp(pattrib->bssid, mybssid, ETH_ALEN)))
0316             return _FAIL;
0317         sta_addr = pattrib->src;
0318     } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
0319         /* For Station mode, sa and bssid should always be BSSID,
0320          * and DA is my mac-address
0321          */
0322         if (memcmp(pattrib->bssid, pattrib->src, ETH_ALEN))
0323             return _FAIL;
0324         sta_addr = pattrib->bssid;
0325     } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
0326         if (bmcast) {
0327             /* For AP mode, if DA == MCAST, then BSSID should
0328              * be also MCAST
0329              */
0330             if (!is_multicast_ether_addr(pattrib->bssid))
0331                 return _FAIL;
0332         } else { /* not mc-frame */
0333             /* For AP mode, if DA is non-MCAST, then it must be
0334              * BSSID, and bssid == BSSID
0335              */
0336             if (memcmp(pattrib->bssid, pattrib->dst, ETH_ALEN))
0337                 return _FAIL;
0338             sta_addr = pattrib->src;
0339         }
0340     } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
0341         memcpy(pattrib->dst, GetAddr1Ptr(ptr), ETH_ALEN);
0342         memcpy(pattrib->src, GetAddr2Ptr(ptr), ETH_ALEN);
0343         memcpy(pattrib->bssid, GetAddr3Ptr(ptr), ETH_ALEN);
0344         memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
0345         memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
0346         sta_addr = mybssid;
0347     } else {
0348         ret  = _FAIL;
0349     }
0350     if (bmcast)
0351         *psta = r8712_get_bcmc_stainfo(adapter);
0352     else
0353         *psta = r8712_get_stainfo(pstapriv, sta_addr); /* get ap_info */
0354     if (!*psta) {
0355         if (check_fwstate(pmlmepriv, WIFI_MP_STATE))
0356             adapter->mppriv.rx_pktloss++;
0357         return _FAIL;
0358     }
0359     return ret;
0360 }
0361 
0362 static sint ap2sta_data_frame(struct _adapter *adapter,
0363                   union recv_frame *precv_frame,
0364                   struct sta_info **psta)
0365 {
0366     u8 *ptr = precv_frame->u.hdr.rx_data;
0367     struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
0368     struct  sta_priv *pstapriv = &adapter->stapriv;
0369     struct  mlme_priv *pmlmepriv = &adapter->mlmepriv;
0370     u8 *mybssid  = get_bssid(pmlmepriv);
0371     u8 *myhwaddr = myid(&adapter->eeprompriv);
0372     bool bmcast = is_multicast_ether_addr(pattrib->dst);
0373 
0374     if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) &&
0375         check_fwstate(pmlmepriv, _FW_LINKED)) {
0376         /* if NULL-frame, drop packet */
0377         if ((GetFrameSubType(ptr)) == (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC))
0378             return _FAIL;
0379         /* drop QoS-SubType Data, including QoS NULL,
0380          * excluding QoS-Data
0381          */
0382         if ((GetFrameSubType(ptr) & WIFI_QOS_DATA_TYPE) ==
0383              WIFI_QOS_DATA_TYPE) {
0384             if (GetFrameSubType(ptr) & (BIT(4) | BIT(5) | BIT(6)))
0385                 return _FAIL;
0386         }
0387 
0388         /* filter packets that SA is myself or multicast or broadcast */
0389         if (!memcmp(myhwaddr, pattrib->src, ETH_ALEN))
0390             return _FAIL;
0391 
0392         /* da should be for me */
0393         if ((memcmp(myhwaddr, pattrib->dst, ETH_ALEN)) && (!bmcast))
0394             return _FAIL;
0395         /* check BSSID */
0396         if (is_zero_ether_addr(pattrib->bssid) ||
0397             is_zero_ether_addr(mybssid) ||
0398              (memcmp(pattrib->bssid, mybssid, ETH_ALEN)))
0399             return _FAIL;
0400         if (bmcast)
0401             *psta = r8712_get_bcmc_stainfo(adapter);
0402         else
0403             *psta = r8712_get_stainfo(pstapriv, pattrib->bssid);
0404         if (!*psta)
0405             return _FAIL;
0406     } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE) &&
0407            check_fwstate(pmlmepriv, _FW_LINKED)) {
0408         memcpy(pattrib->dst, GetAddr1Ptr(ptr), ETH_ALEN);
0409         memcpy(pattrib->src, GetAddr2Ptr(ptr), ETH_ALEN);
0410         memcpy(pattrib->bssid, GetAddr3Ptr(ptr), ETH_ALEN);
0411         memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
0412         memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
0413         memcpy(pattrib->bssid,  mybssid, ETH_ALEN);
0414         *psta = r8712_get_stainfo(pstapriv, pattrib->bssid);
0415         if (!*psta)
0416             return _FAIL;
0417     } else {
0418         return _FAIL;
0419     }
0420     return _SUCCESS;
0421 }
0422 
0423 static sint sta2ap_data_frame(struct _adapter *adapter,
0424                   union recv_frame *precv_frame,
0425                   struct sta_info **psta)
0426 {
0427     struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
0428     struct  sta_priv *pstapriv = &adapter->stapriv;
0429     struct  mlme_priv *pmlmepriv = &adapter->mlmepriv;
0430     unsigned char *mybssid  = get_bssid(pmlmepriv);
0431 
0432     if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
0433         /* For AP mode, if DA is non-MCAST, then it must be BSSID,
0434          * and bssid == BSSID
0435          * For AP mode, RA=BSSID, TX=STA(SRC_ADDR), A3=DST_ADDR
0436          */
0437         if (memcmp(pattrib->bssid, mybssid, ETH_ALEN))
0438             return _FAIL;
0439         *psta = r8712_get_stainfo(pstapriv, pattrib->src);
0440         if (!*psta)
0441             return _FAIL;
0442     }
0443     return _SUCCESS;
0444 }
0445 
0446 static sint validate_recv_ctrl_frame(struct _adapter *adapter,
0447                      union recv_frame *precv_frame)
0448 {
0449     return _FAIL;
0450 }
0451 
0452 static sint validate_recv_mgnt_frame(struct _adapter *adapter,
0453                      union recv_frame *precv_frame)
0454 {
0455     return _FAIL;
0456 }
0457 
0458 static sint validate_recv_data_frame(struct _adapter *adapter,
0459                      union recv_frame *precv_frame)
0460 {
0461     int res;
0462     u8 bretry;
0463     u8 *psa, *pda, *pbssid;
0464     struct sta_info *psta = NULL;
0465     u8 *ptr = precv_frame->u.hdr.rx_data;
0466     struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
0467     struct security_priv *psecuritypriv = &adapter->securitypriv;
0468 
0469     bretry = GetRetry(ptr);
0470     pda = ieee80211_get_DA((struct ieee80211_hdr *)ptr);
0471     psa = ieee80211_get_SA((struct ieee80211_hdr *)ptr);
0472     pbssid = get_hdr_bssid(ptr);
0473     if (!pbssid)
0474         return _FAIL;
0475     memcpy(pattrib->dst, pda, ETH_ALEN);
0476     memcpy(pattrib->src, psa, ETH_ALEN);
0477     memcpy(pattrib->bssid, pbssid, ETH_ALEN);
0478     switch (pattrib->to_fr_ds) {
0479     case 0:
0480         memcpy(pattrib->ra, pda, ETH_ALEN);
0481         memcpy(pattrib->ta, psa, ETH_ALEN);
0482         res = sta2sta_data_frame(adapter, precv_frame, &psta);
0483         break;
0484     case 1:
0485         memcpy(pattrib->ra, pda, ETH_ALEN);
0486         memcpy(pattrib->ta, pbssid, ETH_ALEN);
0487         res = ap2sta_data_frame(adapter, precv_frame, &psta);
0488         break;
0489     case 2:
0490         memcpy(pattrib->ra, pbssid, ETH_ALEN);
0491         memcpy(pattrib->ta, psa, ETH_ALEN);
0492         res = sta2ap_data_frame(adapter, precv_frame, &psta);
0493         break;
0494     case 3:
0495         memcpy(pattrib->ra, GetAddr1Ptr(ptr), ETH_ALEN);
0496         memcpy(pattrib->ta, GetAddr2Ptr(ptr), ETH_ALEN);
0497         return _FAIL;
0498     default:
0499         return _FAIL;
0500     }
0501     if (res == _FAIL)
0502         return _FAIL;
0503     if (!psta)
0504         return _FAIL;
0505     precv_frame->u.hdr.psta = psta;
0506     pattrib->amsdu = 0;
0507     /* parsing QC field */
0508     if (pattrib->qos == 1) {
0509         pattrib->priority = GetPriority((ptr + 24));
0510         pattrib->ack_policy = GetAckpolicy((ptr + 24));
0511         pattrib->amsdu = GetAMsdu((ptr + 24));
0512         pattrib->hdrlen = pattrib->to_fr_ds == 3 ? 32 : 26;
0513     } else {
0514         pattrib->priority = 0;
0515         pattrib->hdrlen = (pattrib->to_fr_ds == 3) ? 30 : 24;
0516     }
0517 
0518     if (pattrib->order)/*HT-CTRL 11n*/
0519         pattrib->hdrlen += 4;
0520     precv_frame->u.hdr.preorder_ctrl =
0521              &psta->recvreorder_ctrl[pattrib->priority];
0522 
0523     /* decache, drop duplicate recv packets */
0524     if (recv_decache(precv_frame, bretry, &psta->sta_recvpriv.rxcache) ==
0525         _FAIL)
0526         return _FAIL;
0527 
0528     if (pattrib->privacy) {
0529         GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt,
0530                    is_multicast_ether_addr(pattrib->ra));
0531         SET_ICE_IV_LEN(pattrib->iv_len, pattrib->icv_len,
0532                    pattrib->encrypt);
0533     } else {
0534         pattrib->encrypt = 0;
0535         pattrib->iv_len = pattrib->icv_len = 0;
0536     }
0537     return _SUCCESS;
0538 }
0539 
0540 sint r8712_validate_recv_frame(struct _adapter *adapter,
0541                    union recv_frame *precv_frame)
0542 {
0543     /*shall check frame subtype, to / from ds, da, bssid */
0544     /*then call check if rx seq/frag. duplicated.*/
0545 
0546     u8 type;
0547     u8 subtype;
0548     sint retval = _SUCCESS;
0549     struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
0550 
0551     u8 *ptr = precv_frame->u.hdr.rx_data;
0552     u8  ver = (unsigned char)(*ptr) & 0x3;
0553 
0554     /*add version chk*/
0555     if (ver != 0)
0556         return _FAIL;
0557     type =  GetFrameType(ptr);
0558     subtype = GetFrameSubType(ptr); /*bit(7)~bit(2)*/
0559     pattrib->to_fr_ds = get_tofr_ds(ptr);
0560     pattrib->frag_num = GetFragNum(ptr);
0561     pattrib->seq_num = GetSequence(ptr);
0562     pattrib->pw_save = GetPwrMgt(ptr);
0563     pattrib->mfrag = GetMFrag(ptr);
0564     pattrib->mdata = GetMData(ptr);
0565     pattrib->privacy =  GetPrivacy(ptr);
0566     pattrib->order = GetOrder(ptr);
0567     switch (type) {
0568     case IEEE80211_FTYPE_MGMT:
0569         retval = validate_recv_mgnt_frame(adapter, precv_frame);
0570         break;
0571     case IEEE80211_FTYPE_CTL:
0572         retval = validate_recv_ctrl_frame(adapter, precv_frame);
0573         break;
0574     case IEEE80211_FTYPE_DATA:
0575         pattrib->qos = (subtype & BIT(7)) ? 1 : 0;
0576         retval = validate_recv_data_frame(adapter, precv_frame);
0577         break;
0578     default:
0579         return _FAIL;
0580     }
0581     return retval;
0582 }
0583 
0584 int r8712_wlanhdr_to_ethhdr(union recv_frame *precvframe)
0585 {
0586     /*remove the wlanhdr and add the eth_hdr*/
0587     sint    rmv_len;
0588     u16 len;
0589     u8  bsnaphdr;
0590     u8  *psnap_type;
0591     struct ieee80211_snap_hdr *psnap;
0592     struct _adapter *adapter = precvframe->u.hdr.adapter;
0593     struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
0594 
0595     u8 *ptr = precvframe->u.hdr.rx_data; /*point to frame_ctrl field*/
0596     struct rx_pkt_attrib *pattrib = &precvframe->u.hdr.attrib;
0597 
0598     if (pattrib->encrypt)
0599         recvframe_pull_tail(precvframe, pattrib->icv_len);
0600     psnap = (struct ieee80211_snap_hdr *)(ptr + pattrib->hdrlen +
0601          pattrib->iv_len);
0602     psnap_type = ptr + pattrib->hdrlen + pattrib->iv_len + SNAP_SIZE;
0603     /* convert hdr + possible LLC headers into Ethernet header */
0604     if ((!memcmp(psnap, (void *)rfc1042_header, SNAP_SIZE) &&
0605          (memcmp(psnap_type, (void *)SNAP_ETH_TYPE_IPX, 2)) &&
0606         (memcmp(psnap_type, (void *)SNAP_ETH_TYPE_APPLETALK_AARP, 2))) ||
0607          !memcmp(psnap, (void *)bridge_tunnel_header, SNAP_SIZE)) {
0608         /* remove RFC1042 or Bridge-Tunnel encapsulation and
0609          * replace EtherType
0610          */
0611         bsnaphdr = true;
0612     } else {
0613         /* Leave Ethernet header part of hdr and full payload */
0614         bsnaphdr = false;
0615     }
0616     rmv_len = pattrib->hdrlen + pattrib->iv_len +
0617           (bsnaphdr ? SNAP_SIZE : 0);
0618     len = precvframe->u.hdr.len - rmv_len;
0619     if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
0620         ptr += rmv_len;
0621         *ptr = 0x87;
0622         *(ptr + 1) = 0x12;
0623         /* append rx status for mp test packets */
0624         ptr = recvframe_pull(precvframe, (rmv_len -
0625               sizeof(struct ethhdr) + 2) - 24);
0626         if (!ptr)
0627             return -ENOMEM;
0628         memcpy(ptr, get_rxmem(precvframe), 24);
0629         ptr += 24;
0630     } else {
0631         ptr = recvframe_pull(precvframe, (rmv_len -
0632               sizeof(struct ethhdr) + (bsnaphdr ? 2 : 0)));
0633         if (!ptr)
0634             return -ENOMEM;
0635     }
0636 
0637     memcpy(ptr, pattrib->dst, ETH_ALEN);
0638     memcpy(ptr + ETH_ALEN, pattrib->src, ETH_ALEN);
0639     if (!bsnaphdr) {
0640         __be16 be_tmp = htons(len);
0641 
0642         memcpy(ptr + 12, &be_tmp, 2);
0643     }
0644     return 0;
0645 }
0646 
0647 void r8712_recv_entry(union recv_frame *precvframe)
0648 {
0649     struct _adapter *padapter;
0650     struct recv_priv *precvpriv;
0651 
0652     s32 ret = _SUCCESS;
0653 
0654     padapter = precvframe->u.hdr.adapter;
0655     precvpriv = &(padapter->recvpriv);
0656 
0657     padapter->ledpriv.LedControlHandler(padapter, LED_CTL_RX);
0658 
0659     ret = recv_func(padapter, precvframe);
0660     if (ret == _FAIL)
0661         goto _recv_entry_drop;
0662     precvpriv->rx_pkts++;
0663     precvpriv->rx_bytes += (uint)(precvframe->u.hdr.rx_tail -
0664                 precvframe->u.hdr.rx_data);
0665     return;
0666 _recv_entry_drop:
0667     precvpriv->rx_drop++;
0668     padapter->mppriv.rx_pktloss = precvpriv->rx_drop;
0669 }