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