linux/drivers/staging/rtl8712/rtl871x_recv.c
<<
>>
Prefs
   1/******************************************************************************
   2 * rtl871x_recv.c
   3 *
   4 * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
   5 * Linux device driver for RTL8192SU
   6 *
   7 * This program is free software; you can redistribute it and/or modify it
   8 * under the terms of version 2 of the GNU General Public License as
   9 * published by the Free Software Foundation.
  10 *
  11 * This program is distributed in the hope that it will be useful, but WITHOUT
  12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  14 * more details.
  15 *
  16 * You should have received a copy of the GNU General Public License along with
  17 * this program; if not, write to the Free Software Foundation, Inc.,
  18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  19 *
  20 * Modifications for inclusion into the Linux staging tree are
  21 * Copyright(c) 2010 Larry Finger. All rights reserved.
  22 *
  23 * Contact information:
  24 * WLAN FAE <wlanfae@realtek.com>
  25 * Larry Finger <Larry.Finger@lwfinger.net>
  26 *
  27 ******************************************************************************/
  28
  29#define _RTL871X_RECV_C_
  30
  31#include <linux/ip.h>
  32#include <linux/slab.h>
  33#include <linux/if_ether.h>
  34#include <linux/kmemleak.h>
  35#include <linux/etherdevice.h>
  36
  37#include "osdep_service.h"
  38#include "drv_types.h"
  39#include "recv_osdep.h"
  40#include "mlme_osdep.h"
  41#include "ethernet.h"
  42#include "usb_ops.h"
  43#include "wifi.h"
  44
  45static const u8 SNAP_ETH_TYPE_IPX[2] = {0x81, 0x37};
  46
  47/* Datagram Delivery Protocol */
  48static const u8 SNAP_ETH_TYPE_APPLETALK_AARP[2] = {0x80, 0xf3};
  49
  50/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
  51static const u8 bridge_tunnel_header[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8};
  52
  53/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
  54static const u8 rfc1042_header[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
  55
  56void _r8712_init_sta_recv_priv(struct sta_recv_priv *psta_recvpriv)
  57{
  58        memset((u8 *)psta_recvpriv, 0, sizeof(struct sta_recv_priv));
  59        spin_lock_init(&psta_recvpriv->lock);
  60        _init_queue(&psta_recvpriv->defrag_q);
  61}
  62
  63sint _r8712_init_recv_priv(struct recv_priv *precvpriv,
  64                           struct _adapter *padapter)
  65{
  66        sint i;
  67        union recv_frame *precvframe;
  68
  69         memset((unsigned char *)precvpriv, 0, sizeof(struct  recv_priv));
  70        spin_lock_init(&precvpriv->lock);
  71        _init_queue(&precvpriv->free_recv_queue);
  72        _init_queue(&precvpriv->recv_pending_queue);
  73        precvpriv->adapter = padapter;
  74        precvpriv->free_recvframe_cnt = NR_RECVFRAME;
  75        precvpriv->pallocated_frame_buf = kzalloc(NR_RECVFRAME *
  76                                sizeof(union recv_frame) + RXFRAME_ALIGN_SZ,
  77                                GFP_ATOMIC);
  78        if (precvpriv->pallocated_frame_buf == NULL)
  79                return _FAIL;
  80        kmemleak_not_leak(precvpriv->pallocated_frame_buf);
  81        precvpriv->precv_frame_buf = precvpriv->pallocated_frame_buf +
  82                                    RXFRAME_ALIGN_SZ -
  83                                    ((addr_t)(precvpriv->pallocated_frame_buf) &
  84                                    (RXFRAME_ALIGN_SZ - 1));
  85        precvframe = (union recv_frame *)precvpriv->precv_frame_buf;
  86        for (i = 0; i < NR_RECVFRAME; i++) {
  87                INIT_LIST_HEAD(&(precvframe->u.list));
  88                list_add_tail(&(precvframe->u.list),
  89                                 &(precvpriv->free_recv_queue.queue));
  90                r8712_os_recv_resource_alloc(padapter, precvframe);
  91                precvframe->u.hdr.adapter = padapter;
  92                precvframe++;
  93        }
  94        precvpriv->rx_pending_cnt = 1;
  95        return r8712_init_recv_priv(precvpriv, padapter);
  96}
  97
  98void _r8712_free_recv_priv(struct recv_priv *precvpriv)
  99{
 100        kfree(precvpriv->pallocated_frame_buf);
 101        r8712_free_recv_priv(precvpriv);
 102}
 103
 104union recv_frame *r8712_alloc_recvframe(struct __queue *pfree_recv_queue)
 105{
 106        unsigned long irqL;
 107        union recv_frame  *precvframe;
 108        struct _adapter *padapter;
 109        struct recv_priv *precvpriv;
 110
 111        spin_lock_irqsave(&pfree_recv_queue->lock, irqL);
 112        precvframe = list_first_entry_or_null(&pfree_recv_queue->queue,
 113                                              union recv_frame, u.hdr.list);
 114        if (precvframe) {
 115                list_del_init(&precvframe->u.hdr.list);
 116                padapter = precvframe->u.hdr.adapter;
 117                if (padapter != NULL) {
 118                        precvpriv = &padapter->recvpriv;
 119                        if (pfree_recv_queue == &precvpriv->free_recv_queue)
 120                                precvpriv->free_recvframe_cnt--;
 121                }
 122        }
 123        spin_unlock_irqrestore(&pfree_recv_queue->lock, irqL);
 124        return precvframe;
 125}
 126
 127/*
 128 * caller : defrag; recvframe_chk_defrag in recv_thread  (passive)
 129 * pframequeue: defrag_queue : will be accessed in recv_thread  (passive)
 130 * using spin_lock to protect
 131 */
 132void r8712_free_recvframe_queue(struct  __queue *pframequeue,
 133                                struct  __queue *pfree_recv_queue)
 134{
 135        union   recv_frame *precvframe;
 136        struct list_head *plist, *phead;
 137
 138        spin_lock(&pframequeue->lock);
 139        phead = &pframequeue->queue;
 140        plist = phead->next;
 141        while (!end_of_queue_search(phead, plist)) {
 142                precvframe = container_of(plist, union recv_frame, u.list);
 143                plist = plist->next;
 144                r8712_free_recvframe(precvframe, pfree_recv_queue);
 145        }
 146        spin_unlock(&pframequeue->lock);
 147}
 148
 149sint r8712_recvframe_chkmic(struct _adapter *adapter,
 150                            union recv_frame *precvframe)
 151{
 152        sint i, res = _SUCCESS;
 153        u32     datalen;
 154        u8 miccode[8];
 155        u8 bmic_err = false;
 156        u8 *pframe, *payload, *pframemic;
 157        u8   *mickey, idx, *iv;
 158        struct  sta_info *stainfo;
 159        struct  rx_pkt_attrib *prxattrib = &precvframe->u.hdr.attrib;
 160        struct  security_priv *psecuritypriv = &adapter->securitypriv;
 161
 162        stainfo = r8712_get_stainfo(&adapter->stapriv, &prxattrib->ta[0]);
 163        if (prxattrib->encrypt == _TKIP_) {
 164                /* calculate mic code */
 165                if (stainfo != NULL) {
 166                        if (IS_MCAST(prxattrib->ra)) {
 167                                iv = precvframe->u.hdr.rx_data +
 168                                     prxattrib->hdrlen;
 169                                idx = iv[3];
 170                                mickey = &psecuritypriv->XGrprxmickey[(((idx >>
 171                                         6) & 0x3)) - 1].skey[0];
 172                                if (!psecuritypriv->binstallGrpkey)
 173                                        return _FAIL;
 174                        } else {
 175                                mickey = &stainfo->tkiprxmickey.skey[0];
 176                        }
 177                        /*icv_len included the mic code*/
 178                        datalen = precvframe->u.hdr.len - prxattrib->hdrlen -
 179                                  prxattrib->iv_len - prxattrib->icv_len - 8;
 180                        pframe = precvframe->u.hdr.rx_data;
 181                        payload = pframe + prxattrib->hdrlen +
 182                                  prxattrib->iv_len;
 183                        seccalctkipmic(mickey, pframe, payload, datalen,
 184                                       &miccode[0],
 185                                       (unsigned char)prxattrib->priority);
 186                        pframemic = payload + datalen;
 187                        bmic_err = false;
 188                        for (i = 0; i < 8; i++) {
 189                                if (miccode[i] != *(pframemic + i))
 190                                        bmic_err = true;
 191                        }
 192                        if (bmic_err) {
 193                                if (prxattrib->bdecrypted)
 194                                        r8712_handle_tkip_mic_err(adapter,
 195                                                (u8)IS_MCAST(prxattrib->ra));
 196                                res = _FAIL;
 197                        } else {
 198                                /* mic checked ok */
 199                                if (!psecuritypriv->bcheck_grpkey &&
 200                                    IS_MCAST(prxattrib->ra))
 201                                        psecuritypriv->bcheck_grpkey = true;
 202                        }
 203                        recvframe_pull_tail(precvframe, 8);
 204                }
 205        }
 206        return res;
 207}
 208
 209/* decrypt and set the ivlen,icvlen of the recv_frame */
 210union recv_frame *r8712_decryptor(struct _adapter *padapter,
 211                            union recv_frame *precv_frame)
 212{
 213        struct rx_pkt_attrib *prxattrib = &precv_frame->u.hdr.attrib;
 214        struct security_priv *psecuritypriv = &padapter->securitypriv;
 215        union recv_frame *return_packet = precv_frame;
 216
 217        if ((prxattrib->encrypt > 0) && ((prxattrib->bdecrypted == 0) ||
 218            psecuritypriv->sw_decrypt)) {
 219                psecuritypriv->hw_decrypted = false;
 220                switch (prxattrib->encrypt) {
 221                case _WEP40_:
 222                case _WEP104_:
 223                        r8712_wep_decrypt(padapter, (u8 *)precv_frame);
 224                        break;
 225                case _TKIP_:
 226                        r8712_tkip_decrypt(padapter, (u8 *)precv_frame);
 227                        break;
 228                case _AES_:
 229                        r8712_aes_decrypt(padapter, (u8 *)precv_frame);
 230                        break;
 231                default:
 232                                break;
 233                }
 234        } else if (prxattrib->bdecrypted == 1) {
 235                psecuritypriv->hw_decrypted = true;
 236        }
 237        return return_packet;
 238}
 239/*###set the security information in the recv_frame */
 240union recv_frame *r8712_portctrl(struct _adapter *adapter,
 241                                 union recv_frame *precv_frame)
 242{
 243        u8 *psta_addr, *ptr;
 244        uint auth_alg;
 245        struct recv_frame_hdr *pfhdr;
 246        struct sta_info *psta;
 247        struct  sta_priv *pstapriv;
 248        union recv_frame *prtnframe;
 249        u16 ether_type;
 250
 251        pstapriv = &adapter->stapriv;
 252        ptr = get_recvframe_data(precv_frame);
 253        pfhdr = &precv_frame->u.hdr;
 254        psta_addr = pfhdr->attrib.ta;
 255        psta = r8712_get_stainfo(pstapriv, psta_addr);
 256        auth_alg = adapter->securitypriv.AuthAlgrthm;
 257        if (auth_alg == 2) {
 258                /* get ether_type */
 259                ptr = ptr + pfhdr->attrib.hdrlen + LLC_HEADER_SIZE;
 260                memcpy(&ether_type, ptr, 2);
 261                be16_to_cpus(&ether_type);
 262
 263                if ((psta != NULL) && (psta->ieee8021x_blocked)) {
 264                        /* blocked
 265                         * only accept EAPOL frame
 266                         */
 267                        if (ether_type == 0x888e) {
 268                                prtnframe = precv_frame;
 269                        } else {
 270                                /*free this frame*/
 271                                r8712_free_recvframe(precv_frame,
 272                                         &adapter->recvpriv.free_recv_queue);
 273                                prtnframe = NULL;
 274                        }
 275                } else {
 276                        /* allowed
 277                         * check decryption status, and decrypt the
 278                         * frame if needed
 279                         */
 280                        prtnframe = precv_frame;
 281                        /* check is the EAPOL frame or not (Rekey) */
 282                        if (ether_type == 0x888e) {
 283                                /* check Rekey */
 284                                prtnframe = precv_frame;
 285                        }
 286                }
 287        } else {
 288                prtnframe = precv_frame;
 289        }
 290        return prtnframe;
 291}
 292
 293static sint recv_decache(union recv_frame *precv_frame, u8 bretry,
 294                  struct stainfo_rxcache *prxcache)
 295{
 296        sint tid = precv_frame->u.hdr.attrib.priority;
 297        u16 seq_ctrl = ((precv_frame->u.hdr.attrib.seq_num & 0xffff) << 4) |
 298                        (precv_frame->u.hdr.attrib.frag_num & 0xf);
 299
 300        if (tid > 15)
 301                return _FAIL;
 302        if (seq_ctrl == prxcache->tid_rxseq[tid])
 303                return _FAIL;
 304        prxcache->tid_rxseq[tid] = seq_ctrl;
 305        return _SUCCESS;
 306}
 307
 308static sint sta2sta_data_frame(struct _adapter *adapter,
 309                               union recv_frame *precv_frame,
 310                               struct sta_info **psta)
 311{
 312        u8 *ptr = precv_frame->u.hdr.rx_data;
 313        sint ret = _SUCCESS;
 314        struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
 315        struct  sta_priv *pstapriv = &adapter->stapriv;
 316        struct  mlme_priv *pmlmepriv = &adapter->mlmepriv;
 317        u8 *mybssid  = get_bssid(pmlmepriv);
 318        u8 *myhwaddr = myid(&adapter->eeprompriv);
 319        u8 *sta_addr = NULL;
 320        sint bmcast = IS_MCAST(pattrib->dst);
 321
 322        if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
 323            check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
 324                /* filter packets that SA is myself or multicast or broadcast */
 325                if (!memcmp(myhwaddr, pattrib->src, ETH_ALEN))
 326                        return _FAIL;
 327                if ((memcmp(myhwaddr, pattrib->dst, ETH_ALEN)) && (!bmcast))
 328                        return _FAIL;
 329                if (is_zero_ether_addr(pattrib->bssid) ||
 330                    is_zero_ether_addr(mybssid) ||
 331                    (memcmp(pattrib->bssid, mybssid, ETH_ALEN)))
 332                        return _FAIL;
 333                sta_addr = pattrib->src;
 334        } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
 335                /* For Station mode, sa and bssid should always be BSSID,
 336                 * and DA is my mac-address
 337                 */
 338                if (memcmp(pattrib->bssid, pattrib->src, ETH_ALEN))
 339                        return _FAIL;
 340               sta_addr = pattrib->bssid;
 341        } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
 342                if (bmcast) {
 343                        /* For AP mode, if DA == MCAST, then BSSID should
 344                         * be also MCAST
 345                         */
 346                        if (!IS_MCAST(pattrib->bssid))
 347                                return _FAIL;
 348                } else { /* not mc-frame */
 349                        /* For AP mode, if DA is non-MCAST, then it must be
 350                         * BSSID, and bssid == BSSID
 351                         */
 352                        if (memcmp(pattrib->bssid, pattrib->dst, ETH_ALEN))
 353                                return _FAIL;
 354                        sta_addr = pattrib->src;
 355                }
 356        } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
 357                memcpy(pattrib->dst, GetAddr1Ptr(ptr), ETH_ALEN);
 358                memcpy(pattrib->src, GetAddr2Ptr(ptr), ETH_ALEN);
 359                memcpy(pattrib->bssid, GetAddr3Ptr(ptr), ETH_ALEN);
 360                memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
 361                memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
 362                sta_addr = mybssid;
 363        } else {
 364                ret  = _FAIL;
 365        }
 366        if (bmcast)
 367                *psta = r8712_get_bcmc_stainfo(adapter);
 368        else
 369                *psta = r8712_get_stainfo(pstapriv, sta_addr); /* get ap_info */
 370        if (*psta == NULL) {
 371                if (check_fwstate(pmlmepriv, WIFI_MP_STATE))
 372                        adapter->mppriv.rx_pktloss++;
 373                return _FAIL;
 374        }
 375        return ret;
 376}
 377
 378static sint ap2sta_data_frame(struct _adapter *adapter,
 379                              union recv_frame *precv_frame,
 380                              struct sta_info **psta)
 381{
 382        u8 *ptr = precv_frame->u.hdr.rx_data;
 383        struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
 384        struct  sta_priv *pstapriv = &adapter->stapriv;
 385        struct  mlme_priv *pmlmepriv = &adapter->mlmepriv;
 386        u8 *mybssid  = get_bssid(pmlmepriv);
 387        u8 *myhwaddr = myid(&adapter->eeprompriv);
 388        sint bmcast = IS_MCAST(pattrib->dst);
 389
 390        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) &&
 391            check_fwstate(pmlmepriv, _FW_LINKED)) {
 392                /* if NULL-frame, drop packet */
 393                if ((GetFrameSubType(ptr)) == WIFI_DATA_NULL)
 394                        return _FAIL;
 395                /* drop QoS-SubType Data, including QoS NULL,
 396                 * excluding QoS-Data
 397                 */
 398                if ((GetFrameSubType(ptr) & WIFI_QOS_DATA_TYPE) ==
 399                     WIFI_QOS_DATA_TYPE) {
 400                        if (GetFrameSubType(ptr) & (BIT(4) | BIT(5) | BIT(6)))
 401                                return _FAIL;
 402                }
 403
 404                /* filter packets that SA is myself or multicast or broadcast */
 405                if (!memcmp(myhwaddr, pattrib->src, ETH_ALEN))
 406                        return _FAIL;
 407
 408                /* da should be for me */
 409                if ((memcmp(myhwaddr, pattrib->dst, ETH_ALEN)) && (!bmcast))
 410                        return _FAIL;
 411                /* check BSSID */
 412                if (is_zero_ether_addr(pattrib->bssid) ||
 413                     is_zero_ether_addr(mybssid) ||
 414                     (memcmp(pattrib->bssid, mybssid, ETH_ALEN)))
 415                        return _FAIL;
 416                if (bmcast)
 417                        *psta = r8712_get_bcmc_stainfo(adapter);
 418                else
 419                       *psta = r8712_get_stainfo(pstapriv, pattrib->bssid);
 420                if (*psta == NULL)
 421                        return _FAIL;
 422        } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE) &&
 423                   check_fwstate(pmlmepriv, _FW_LINKED)) {
 424                memcpy(pattrib->dst, GetAddr1Ptr(ptr), ETH_ALEN);
 425                memcpy(pattrib->src, GetAddr2Ptr(ptr), ETH_ALEN);
 426                memcpy(pattrib->bssid, GetAddr3Ptr(ptr), ETH_ALEN);
 427                memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
 428                memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
 429                memcpy(pattrib->bssid,  mybssid, ETH_ALEN);
 430                *psta = r8712_get_stainfo(pstapriv, pattrib->bssid);
 431                if (*psta == NULL)
 432                        return _FAIL;
 433        } else {
 434                return _FAIL;
 435        }
 436        return _SUCCESS;
 437}
 438
 439static sint sta2ap_data_frame(struct _adapter *adapter,
 440                              union recv_frame *precv_frame,
 441                              struct sta_info **psta)
 442{
 443        struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
 444        struct  sta_priv *pstapriv = &adapter->stapriv;
 445        struct  mlme_priv *pmlmepriv = &adapter->mlmepriv;
 446        unsigned char *mybssid  = get_bssid(pmlmepriv);
 447
 448        if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
 449                /* For AP mode, if DA is non-MCAST, then it must be BSSID,
 450                 * and bssid == BSSID
 451                 * For AP mode, RA=BSSID, TX=STA(SRC_ADDR), A3=DST_ADDR
 452                 */
 453                if (memcmp(pattrib->bssid, mybssid, ETH_ALEN))
 454                        return _FAIL;
 455                *psta = r8712_get_stainfo(pstapriv, pattrib->src);
 456                if (*psta == NULL)
 457                        return _FAIL;
 458        }
 459        return _SUCCESS;
 460}
 461
 462static sint validate_recv_ctrl_frame(struct _adapter *adapter,
 463                              union recv_frame *precv_frame)
 464{
 465        return _FAIL;
 466}
 467
 468static sint validate_recv_mgnt_frame(struct _adapter *adapter,
 469                              union recv_frame *precv_frame)
 470{
 471        return _FAIL;
 472}
 473
 474
 475static sint validate_recv_data_frame(struct _adapter *adapter,
 476                              union recv_frame *precv_frame)
 477{
 478        int res;
 479        u8 bretry;
 480        u8 *psa, *pda, *pbssid;
 481        struct sta_info *psta = NULL;
 482        u8 *ptr = precv_frame->u.hdr.rx_data;
 483        struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
 484        struct security_priv *psecuritypriv = &adapter->securitypriv;
 485
 486        bretry = GetRetry(ptr);
 487        pda = get_da(ptr);
 488        psa = get_sa(ptr);
 489        pbssid = get_hdr_bssid(ptr);
 490        if (pbssid == NULL)
 491                return _FAIL;
 492        memcpy(pattrib->dst, pda, ETH_ALEN);
 493        memcpy(pattrib->src, psa, ETH_ALEN);
 494        memcpy(pattrib->bssid, pbssid, ETH_ALEN);
 495        switch (pattrib->to_fr_ds) {
 496        case 0:
 497                memcpy(pattrib->ra, pda, ETH_ALEN);
 498                memcpy(pattrib->ta, psa, ETH_ALEN);
 499                res = sta2sta_data_frame(adapter, precv_frame, &psta);
 500                break;
 501        case 1:
 502                memcpy(pattrib->ra, pda, ETH_ALEN);
 503                memcpy(pattrib->ta, pbssid, ETH_ALEN);
 504                res = ap2sta_data_frame(adapter, precv_frame, &psta);
 505                break;
 506        case 2:
 507                memcpy(pattrib->ra, pbssid, ETH_ALEN);
 508                memcpy(pattrib->ta, psa, ETH_ALEN);
 509                res = sta2ap_data_frame(adapter, precv_frame, &psta);
 510                break;
 511        case 3:
 512                memcpy(pattrib->ra, GetAddr1Ptr(ptr), ETH_ALEN);
 513                memcpy(pattrib->ta, GetAddr2Ptr(ptr), ETH_ALEN);
 514                return _FAIL;
 515        default:
 516                return _FAIL;
 517        }
 518        if (res == _FAIL)
 519                return _FAIL;
 520        if (psta == NULL)
 521                return _FAIL;
 522        precv_frame->u.hdr.psta = psta;
 523        pattrib->amsdu = 0;
 524        /* parsing QC field */
 525        if (pattrib->qos == 1) {
 526                pattrib->priority = GetPriority((ptr + 24));
 527                pattrib->ack_policy = GetAckpolicy((ptr + 24));
 528                pattrib->amsdu = GetAMsdu((ptr + 24));
 529                pattrib->hdrlen = pattrib->to_fr_ds == 3 ? 32 : 26;
 530        } else {
 531                pattrib->priority = 0;
 532                pattrib->hdrlen = (pattrib->to_fr_ds == 3) ? 30 : 24;
 533        }
 534
 535        if (pattrib->order)/*HT-CTRL 11n*/
 536                pattrib->hdrlen += 4;
 537        precv_frame->u.hdr.preorder_ctrl =
 538                         &psta->recvreorder_ctrl[pattrib->priority];
 539
 540        /* decache, drop duplicate recv packets */
 541        if (recv_decache(precv_frame, bretry, &psta->sta_recvpriv.rxcache) ==
 542            _FAIL)
 543                return _FAIL;
 544
 545        if (pattrib->privacy) {
 546                GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt,
 547                               IS_MCAST(pattrib->ra));
 548                SET_ICE_IV_LEN(pattrib->iv_len, pattrib->icv_len,
 549                               pattrib->encrypt);
 550        } else {
 551                pattrib->encrypt = 0;
 552                pattrib->iv_len = pattrib->icv_len = 0;
 553        }
 554        return _SUCCESS;
 555}
 556
 557sint r8712_validate_recv_frame(struct _adapter *adapter,
 558                               union recv_frame *precv_frame)
 559{
 560        /*shall check frame subtype, to / from ds, da, bssid */
 561        /*then call check if rx seq/frag. duplicated.*/
 562
 563        u8 type;
 564        u8 subtype;
 565        sint retval = _SUCCESS;
 566        struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
 567
 568        u8 *ptr = precv_frame->u.hdr.rx_data;
 569        u8  ver = (unsigned char)(*ptr) & 0x3;
 570
 571        /*add version chk*/
 572        if (ver != 0)
 573                return _FAIL;
 574        type =  GetFrameType(ptr);
 575        subtype = GetFrameSubType(ptr); /*bit(7)~bit(2)*/
 576        pattrib->to_fr_ds = get_tofr_ds(ptr);
 577        pattrib->frag_num = GetFragNum(ptr);
 578        pattrib->seq_num = GetSequence(ptr);
 579        pattrib->pw_save = GetPwrMgt(ptr);
 580        pattrib->mfrag = GetMFrag(ptr);
 581        pattrib->mdata = GetMData(ptr);
 582        pattrib->privacy =  GetPrivacy(ptr);
 583        pattrib->order = GetOrder(ptr);
 584        switch (type) {
 585        case WIFI_MGT_TYPE: /*mgnt*/
 586                retval = validate_recv_mgnt_frame(adapter, precv_frame);
 587                break;
 588        case WIFI_CTRL_TYPE:/*ctrl*/
 589                retval = validate_recv_ctrl_frame(adapter, precv_frame);
 590                break;
 591        case WIFI_DATA_TYPE: /*data*/
 592                pattrib->qos = (subtype & BIT(7)) ? 1 : 0;
 593                retval = validate_recv_data_frame(adapter, precv_frame);
 594                break;
 595        default:
 596                return _FAIL;
 597        }
 598        return retval;
 599}
 600
 601sint r8712_wlanhdr_to_ethhdr(union recv_frame *precvframe)
 602{
 603        /*remove the wlanhdr and add the eth_hdr*/
 604        sint    rmv_len;
 605        u16     len;
 606        u8      bsnaphdr;
 607        u8      *psnap_type;
 608        struct ieee80211_snap_hdr *psnap;
 609        struct _adapter *adapter = precvframe->u.hdr.adapter;
 610        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
 611
 612        u8 *ptr = get_recvframe_data(precvframe); /*point to frame_ctrl field*/
 613        struct rx_pkt_attrib *pattrib = &precvframe->u.hdr.attrib;
 614
 615        if (pattrib->encrypt)
 616                recvframe_pull_tail(precvframe, pattrib->icv_len);
 617        psnap = (struct ieee80211_snap_hdr *)(ptr + pattrib->hdrlen +
 618                 pattrib->iv_len);
 619        psnap_type = ptr + pattrib->hdrlen + pattrib->iv_len + SNAP_SIZE;
 620        /* convert hdr + possible LLC headers into Ethernet header */
 621        if ((!memcmp(psnap, (void *)rfc1042_header, SNAP_SIZE) &&
 622            (memcmp(psnap_type, (void *)SNAP_ETH_TYPE_IPX, 2)) &&
 623            (memcmp(psnap_type, (void *)SNAP_ETH_TYPE_APPLETALK_AARP, 2))) ||
 624             !memcmp(psnap, (void *)bridge_tunnel_header, SNAP_SIZE)) {
 625                /* remove RFC1042 or Bridge-Tunnel encapsulation and
 626                 * replace EtherType
 627                 */
 628                bsnaphdr = true;
 629        } else {
 630                /* Leave Ethernet header part of hdr and full payload */
 631                bsnaphdr = false;
 632        }
 633        rmv_len = pattrib->hdrlen + pattrib->iv_len +
 634                  (bsnaphdr ? SNAP_SIZE : 0);
 635        len = precvframe->u.hdr.len - rmv_len;
 636        if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
 637                ptr += rmv_len;
 638                *ptr = 0x87;
 639                *(ptr + 1) = 0x12;
 640                /* append rx status for mp test packets */
 641                ptr = recvframe_pull(precvframe, (rmv_len -
 642                      sizeof(struct ethhdr) + 2) - 24);
 643                if (!ptr)
 644                        return _FAIL;
 645                memcpy(ptr, get_rxmem(precvframe), 24);
 646                ptr += 24;
 647        } else {
 648                ptr = recvframe_pull(precvframe, (rmv_len -
 649                      sizeof(struct ethhdr) + (bsnaphdr ? 2 : 0)));
 650                if (!ptr)
 651                        return _FAIL;
 652        }
 653
 654        memcpy(ptr, pattrib->dst, ETH_ALEN);
 655        memcpy(ptr + ETH_ALEN, pattrib->src, ETH_ALEN);
 656        if (!bsnaphdr) {
 657                __be16 be_tmp = htons(len);
 658
 659                memcpy(ptr + 12, &be_tmp, 2);
 660        }
 661        return _SUCCESS;
 662}
 663
 664s32 r8712_recv_entry(union recv_frame *precvframe)
 665{
 666        struct _adapter *padapter;
 667        struct recv_priv *precvpriv;
 668
 669        s32 ret = _SUCCESS;
 670
 671        padapter = precvframe->u.hdr.adapter;
 672        precvpriv = &(padapter->recvpriv);
 673
 674        padapter->ledpriv.LedControlHandler(padapter, LED_CTL_RX);
 675
 676        ret = recv_func(padapter, precvframe);
 677        if (ret == _FAIL)
 678                goto _recv_entry_drop;
 679        precvpriv->rx_pkts++;
 680        precvpriv->rx_bytes += (uint)(precvframe->u.hdr.rx_tail -
 681                                precvframe->u.hdr.rx_data);
 682        return ret;
 683_recv_entry_drop:
 684        precvpriv->rx_drop++;
 685        padapter->mppriv.rx_pktloss = precvpriv->rx_drop;
 686        return ret;
 687}
 688