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