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 } 674