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