root/drivers/staging/rtl8712/rtl871x_recv.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. _r8712_init_sta_recv_priv
  2. _r8712_init_recv_priv
  3. _r8712_free_recv_priv
  4. r8712_alloc_recvframe
  5. r8712_free_recvframe_queue
  6. r8712_recvframe_chkmic
  7. r8712_decryptor
  8. r8712_portctrl
  9. recv_decache
  10. sta2sta_data_frame
  11. ap2sta_data_frame
  12. sta2ap_data_frame
  13. validate_recv_ctrl_frame
  14. validate_recv_mgnt_frame
  15. validate_recv_data_frame
  16. r8712_validate_recv_frame
  17. r8712_wlanhdr_to_ethhdr
  18. r8712_recv_entry

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

/* [<][>][^][v][top][bottom][index][help] */