PageRenderTime 59ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 1ms

/drivers/staging/rtl8712/rtl871x_recv.c

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