Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
rtl871x_recv.c
Go to the documentation of this file.
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 <[email protected]>
25  * Larry Finger <[email protected]>
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 
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 = _malloc(NR_RECVFRAME *
76  sizeof(union recv_frame) +
78  if (precvpriv->pallocated_frame_buf == NULL)
79  return _FAIL;
82  sizeof(union recv_frame) + RXFRAME_ALIGN_SZ);
83  precvpriv->precv_frame_buf = precvpriv->pallocated_frame_buf +
85  ((addr_t)(precvpriv->pallocated_frame_buf) &
86  (RXFRAME_ALIGN_SZ-1));
87  precvframe = (union recv_frame *)precvpriv->precv_frame_buf;
88  for (i = 0; i < NR_RECVFRAME; i++) {
89  _init_listhead(&(precvframe->u.list));
90  list_insert_tail(&(precvframe->u.list),
91  &(precvpriv->free_recv_queue.queue));
92  r8712_os_recv_resource_alloc(padapter, precvframe);
93  precvframe->u.hdr.adapter = padapter;
94  precvframe++;
95  }
96  precvpriv->rx_pending_cnt = 1;
97  return r8712_init_recv_priv(precvpriv, padapter);
98 }
99 
100 void _r8712_free_recv_priv(struct recv_priv *precvpriv)
101 {
102  kfree(precvpriv->pallocated_frame_buf);
103  r8712_free_recv_priv(precvpriv);
104 }
105 
106 union recv_frame *r8712_alloc_recvframe(struct __queue *pfree_recv_queue)
107 {
108  unsigned long irqL;
109  union recv_frame *precvframe;
110  struct list_head *plist, *phead;
111  struct _adapter *padapter;
112  struct recv_priv *precvpriv;
113 
114  spin_lock_irqsave(&pfree_recv_queue->lock, irqL);
115  if (_queue_empty(pfree_recv_queue) == true)
116  precvframe = NULL;
117  else {
118  phead = get_list_head(pfree_recv_queue);
119  plist = get_next(phead);
120  precvframe = LIST_CONTAINOR(plist, union recv_frame, u);
121  list_delete(&precvframe->u.hdr.list);
122  padapter = precvframe->u.hdr.adapter;
123  if (padapter != NULL) {
124  precvpriv = &padapter->recvpriv;
125  if (pfree_recv_queue == &precvpriv->free_recv_queue)
126  precvpriv->free_recvframe_cnt--;
127  }
128  }
129  spin_unlock_irqrestore(&pfree_recv_queue->lock, irqL);
130  return precvframe;
131 }
132 
133 /*
134 caller : defrag; recvframe_chk_defrag in recv_thread (passive)
135 pframequeue: defrag_queue : will be accessed in recv_thread (passive)
136 
137 using spin_lock to protect
138 
139 */
140 
141 void r8712_free_recvframe_queue(struct __queue *pframequeue,
142  struct __queue *pfree_recv_queue)
143 {
144  union recv_frame *precvframe;
145  struct list_head *plist, *phead;
146 
147  spin_lock(&pframequeue->lock);
148  phead = get_list_head(pframequeue);
149  plist = get_next(phead);
150  while (end_of_queue_search(phead, plist) == false) {
151  precvframe = LIST_CONTAINOR(plist, union recv_frame, u);
152  plist = get_next(plist);
153  r8712_free_recvframe(precvframe, pfree_recv_queue);
154  }
155  spin_unlock(&pframequeue->lock);
156 }
157 
159  union recv_frame *precvframe)
160 {
161  sint i, res = _SUCCESS;
162  u32 datalen;
163  u8 miccode[8];
164  u8 bmic_err = false;
165  u8 *pframe, *payload, *pframemic;
166  u8 *mickey, idx, *iv;
167  struct sta_info *stainfo;
168  struct rx_pkt_attrib *prxattrib = &precvframe->u.hdr.attrib;
169  struct security_priv *psecuritypriv = &adapter->securitypriv;
170 
171  stainfo = r8712_get_stainfo(&adapter->stapriv, &prxattrib->ta[0]);
172  if (prxattrib->encrypt == _TKIP_) {
173  /* calculate mic code */
174  if (stainfo != NULL) {
175  if (IS_MCAST(prxattrib->ra)) {
176  iv = precvframe->u.hdr.rx_data +
177  prxattrib->hdrlen;
178  idx = iv[3];
179  mickey = &psecuritypriv->XGrprxmickey[(((idx >>
180  6) & 0x3)) - 1].skey[0];
181  if (psecuritypriv->binstallGrpkey == false)
182  return _FAIL;
183  } else
184  mickey = &stainfo->tkiprxmickey.skey[0];
185  /*icv_len included the mic code*/
186  datalen = precvframe->u.hdr.len - prxattrib->hdrlen -
187  prxattrib->iv_len - prxattrib->icv_len - 8;
188  pframe = precvframe->u.hdr.rx_data;
189  payload = pframe + prxattrib->hdrlen +
190  prxattrib->iv_len;
191  seccalctkipmic(mickey, pframe, payload, datalen,
192  &miccode[0],
193  (unsigned char)prxattrib->priority);
194  pframemic = payload + datalen;
195  bmic_err = false;
196  for (i = 0; i < 8; i++) {
197  if (miccode[i] != *(pframemic + i))
198  bmic_err = true;
199  }
200  if (bmic_err == true) {
201  if (prxattrib->bdecrypted == true)
203  (u8)IS_MCAST(prxattrib->ra));
204  res = _FAIL;
205  } else {
206  /* mic checked ok */
207  if ((psecuritypriv->bcheck_grpkey ==
208  false) && (IS_MCAST(prxattrib->ra) ==
209  true))
210  psecuritypriv->bcheck_grpkey = true;
211  }
212  recvframe_pull_tail(precvframe, 8);
213  }
214  }
215  return res;
216 }
217 
218 /* decrypt and set the ivlen,icvlen of the recv_frame */
219 union recv_frame *r8712_decryptor(struct _adapter *padapter,
220  union recv_frame *precv_frame)
221 {
222  struct rx_pkt_attrib *prxattrib = &precv_frame->u.hdr.attrib;
223  struct security_priv *psecuritypriv = &padapter->securitypriv;
224  union recv_frame *return_packet = precv_frame;
225 
226  if ((prxattrib->encrypt > 0) && ((prxattrib->bdecrypted == 0) ||
227  (psecuritypriv->sw_decrypt == true))) {
228  psecuritypriv->hw_decrypted = false;
229  switch (prxattrib->encrypt) {
230  case _WEP40_:
231  case _WEP104_:
232  r8712_wep_decrypt(padapter, (u8 *)precv_frame);
233  break;
234  case _TKIP_:
235  r8712_tkip_decrypt(padapter, (u8 *)precv_frame);
236  break;
237  case _AES_:
238  r8712_aes_decrypt(padapter, (u8 *)precv_frame);
239  break;
240  default:
241  break;
242  }
243  } else if (prxattrib->bdecrypted == 1)
244  psecuritypriv->hw_decrypted = true;
245  return return_packet;
246 }
247 /*###set the security information in the recv_frame */
249  union recv_frame *precv_frame)
250 {
251  u8 *psta_addr, *ptr;
252  uint auth_alg;
253  struct recv_frame_hdr *pfhdr;
254  struct sta_info *psta;
255  struct sta_priv *pstapriv;
256  union recv_frame *prtnframe;
257  u16 ether_type = 0;
258 
259  pstapriv = &adapter->stapriv;
260  ptr = get_recvframe_data(precv_frame);
261  pfhdr = &precv_frame->u.hdr;
262  psta_addr = pfhdr->attrib.ta;
263  psta = r8712_get_stainfo(pstapriv, psta_addr);
264  auth_alg = adapter->securitypriv.AuthAlgrthm;
265  if (auth_alg == 2) {
266  if ((psta != NULL) && (psta->ieee8021x_blocked)) {
267  /* blocked
268  * only accept EAPOL frame */
269  prtnframe = precv_frame;
270  /*get ether_type */
271  ptr = ptr + pfhdr->attrib.hdrlen +
272  pfhdr->attrib.iv_len + LLC_HEADER_SIZE;
273  memcpy(&ether_type, ptr, 2);
274  ether_type = ntohs((unsigned short)ether_type);
275  if (ether_type == 0x888e)
276  prtnframe = precv_frame;
277  else {
278  /*free this frame*/
279  r8712_free_recvframe(precv_frame,
280  &adapter->recvpriv.free_recv_queue);
281  prtnframe = NULL;
282  }
283  } else {
284  /* allowed
285  * check decryption status, and decrypt the
286  * frame if needed */
287  prtnframe = precv_frame;
288  /* check is the EAPOL frame or not (Rekey) */
289  if (ether_type == 0x888e) {
290  /* check Rekey */
291  prtnframe = precv_frame;
292  }
293  }
294  } else
295  prtnframe = precv_frame;
296  return prtnframe;
297 }
298 
299 static sint recv_decache(union recv_frame *precv_frame, u8 bretry,
300  struct stainfo_rxcache *prxcache)
301 {
302  sint tid = precv_frame->u.hdr.attrib.priority;
303  u16 seq_ctrl = ((precv_frame->u.hdr.attrib.seq_num&0xffff) << 4) |
304  (precv_frame->u.hdr.attrib.frag_num & 0xf);
305 
306  if (tid > 15)
307  return _FAIL;
308  if (seq_ctrl == prxcache->tid_rxseq[tid])
309  return _FAIL;
310  prxcache->tid_rxseq[tid] = seq_ctrl;
311  return _SUCCESS;
312 }
313 
314 static sint sta2sta_data_frame(struct _adapter *adapter,
315  union recv_frame *precv_frame,
316  struct sta_info **psta)
317 {
318  u8 *ptr = precv_frame->u.hdr.rx_data;
319  sint ret = _SUCCESS;
320  struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
321  struct sta_priv *pstapriv = &adapter->stapriv;
322  struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
323  u8 *mybssid = get_bssid(pmlmepriv);
324  u8 *myhwaddr = myid(&adapter->eeprompriv);
325  u8 *sta_addr = NULL;
326  sint bmcast = IS_MCAST(pattrib->dst);
327 
328  if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) ||
329  (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)) {
330  /* filter packets that SA is myself or multicast or broadcast */
331  if (!memcmp(myhwaddr, pattrib->src, ETH_ALEN))
332  return _FAIL;
333  if ((memcmp(myhwaddr, pattrib->dst, ETH_ALEN)) && (!bmcast))
334  return _FAIL;
335  if (is_zero_ether_addr(pattrib->bssid) ||
336  is_zero_ether_addr(mybssid) ||
337  (memcmp(pattrib->bssid, mybssid, ETH_ALEN)))
338  return _FAIL;
339  sta_addr = pattrib->src;
340  } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
341  /* For Station mode, sa and bssid should always be BSSID,
342  * and DA is my mac-address */
343  if (memcmp(pattrib->bssid, pattrib->src, ETH_ALEN))
344  return _FAIL;
345  sta_addr = pattrib->bssid;
346  } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
347  if (bmcast) {
348  /* For AP mode, if DA == MCAST, then BSSID should
349  * be also MCAST */
350  if (!IS_MCAST(pattrib->bssid))
351  return _FAIL;
352  } else { /* not mc-frame */
353  /* For AP mode, if DA is non-MCAST, then it must be
354  * BSSID, and bssid == BSSID */
355  if (memcmp(pattrib->bssid, pattrib->dst, ETH_ALEN))
356  return _FAIL;
357  sta_addr = pattrib->src;
358  }
359  } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) {
360  memcpy(pattrib->dst, GetAddr1Ptr(ptr), ETH_ALEN);
361  memcpy(pattrib->src, GetAddr2Ptr(ptr), ETH_ALEN);
362  memcpy(pattrib->bssid, GetAddr3Ptr(ptr), ETH_ALEN);
363  memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
364  memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
365  sta_addr = mybssid;
366  } else
367  ret = _FAIL;
368  if (bmcast)
369  *psta = r8712_get_bcmc_stainfo(adapter);
370  else
371  *psta = r8712_get_stainfo(pstapriv, sta_addr); /* get ap_info */
372  if (*psta == NULL) {
373  if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == true)
374  adapter->mppriv.rx_pktloss++;
375  return _FAIL;
376  }
377  return ret;
378 }
379 
380 static sint ap2sta_data_frame(struct _adapter *adapter,
381  union recv_frame *precv_frame,
382  struct sta_info **psta)
383 {
384  u8 *ptr = precv_frame->u.hdr.rx_data;
385  struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
386  struct sta_priv *pstapriv = &adapter->stapriv;
387  struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
388  u8 *mybssid = get_bssid(pmlmepriv);
389  u8 *myhwaddr = myid(&adapter->eeprompriv);
390  sint bmcast = IS_MCAST(pattrib->dst);
391 
392  if ((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
393  && (check_fwstate(pmlmepriv, _FW_LINKED) == true)) {
394  /* if NULL-frame, drop packet */
395  if ((GetFrameSubType(ptr)) == WIFI_DATA_NULL)
396  return _FAIL;
397  /* drop QoS-SubType Data, including QoS NULL,
398  * excluding QoS-Data */
399  if ((GetFrameSubType(ptr) & WIFI_QOS_DATA_TYPE) ==
400  WIFI_QOS_DATA_TYPE) {
401  if (GetFrameSubType(ptr) & (BIT(4) | BIT(5) | BIT(6)))
402  return _FAIL;
403  }
404 
405  /* filter packets that SA is myself or multicast or broadcast */
406  if (!memcmp(myhwaddr, pattrib->src, ETH_ALEN))
407  return _FAIL;
408 
409  /* da should be for me */
410  if ((memcmp(myhwaddr, pattrib->dst, ETH_ALEN)) && (!bmcast))
411  return _FAIL;
412  /* check BSSID */
413  if (is_zero_ether_addr(pattrib->bssid) ||
414  is_zero_ether_addr(mybssid) ||
415  (memcmp(pattrib->bssid, mybssid, ETH_ALEN)))
416  return _FAIL;
417  if (bmcast)
418  *psta = r8712_get_bcmc_stainfo(adapter);
419  else
420  *psta = r8712_get_stainfo(pstapriv, pattrib->bssid);
421  if (*psta == NULL)
422  return _FAIL;
423  } else if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) &&
424  (check_fwstate(pmlmepriv, _FW_LINKED) == true)) {
425  memcpy(pattrib->dst, GetAddr1Ptr(ptr), ETH_ALEN);
426  memcpy(pattrib->src, GetAddr2Ptr(ptr), ETH_ALEN);
427  memcpy(pattrib->bssid, GetAddr3Ptr(ptr), ETH_ALEN);
428  memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
429  memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
430  memcpy(pattrib->bssid, mybssid, ETH_ALEN);
431  *psta = r8712_get_stainfo(pstapriv, pattrib->bssid);
432  if (*psta == NULL)
433  return _FAIL;
434  } else
435  return _FAIL;
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) == true) {
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  if (memcmp(pattrib->bssid, mybssid, ETH_ALEN))
453  return _FAIL;
454  *psta = r8712_get_stainfo(pstapriv, pattrib->src);
455  if (*psta == NULL)
456  return _FAIL;
457  }
458  return _SUCCESS;
459 }
460 
461 static sint validate_recv_ctrl_frame(struct _adapter *adapter,
462  union recv_frame *precv_frame)
463 {
464  return _FAIL;
465 }
466 
467 static sint validate_recv_mgnt_frame(struct _adapter *adapter,
468  union recv_frame *precv_frame)
469 {
470  return _FAIL;
471 }
472 
473 
474 static sint validate_recv_data_frame(struct _adapter *adapter,
475  union recv_frame *precv_frame)
476 {
477  int res;
478  u8 bretry;
479  u8 *psa, *pda, *pbssid;
480  struct sta_info *psta = NULL;
481  u8 *ptr = precv_frame->u.hdr.rx_data;
482  struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
483  struct security_priv *psecuritypriv = &adapter->securitypriv;
484 
485  bretry = GetRetry(ptr);
486  pda = get_da(ptr);
487  psa = get_sa(ptr);
488  pbssid = get_hdr_bssid(ptr);
489  if (pbssid == NULL)
490  return _FAIL;
491  memcpy(pattrib->dst, pda, ETH_ALEN);
492  memcpy(pattrib->src, psa, ETH_ALEN);
493  memcpy(pattrib->bssid, pbssid, ETH_ALEN);
494  switch (pattrib->to_fr_ds) {
495  case 0:
496  memcpy(pattrib->ra, pda, ETH_ALEN);
497  memcpy(pattrib->ta, psa, ETH_ALEN);
498  res = sta2sta_data_frame(adapter, precv_frame, &psta);
499  break;
500  case 1:
501  memcpy(pattrib->ra, pda, ETH_ALEN);
502  memcpy(pattrib->ta, pbssid, ETH_ALEN);
503  res = ap2sta_data_frame(adapter, precv_frame, &psta);
504  break;
505  case 2:
506  memcpy(pattrib->ra, pbssid, ETH_ALEN);
507  memcpy(pattrib->ta, psa, ETH_ALEN);
508  res = sta2ap_data_frame(adapter, precv_frame, &psta);
509  break;
510  case 3:
511  memcpy(pattrib->ra, GetAddr1Ptr(ptr), ETH_ALEN);
512  memcpy(pattrib->ta, GetAddr2Ptr(ptr), ETH_ALEN);
513  return _FAIL;
514  default:
515  return _FAIL;
516  }
517  if (res == _FAIL)
518  return _FAIL;
519  if (psta == NULL)
520  return _FAIL;
521  else
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 
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 
602 {
603  /*remove the wlanhdr and add the eth_hdr*/
604  sint rmv_len;
605  u16 eth_type, len;
606  u8 bsnaphdr;
607  u8 *psnap_type;
608  struct ieee80211_snap_hdr *psnap;
609 
610  sint ret = _SUCCESS;
611  struct _adapter *adapter = precvframe->u.hdr.adapter;
612  struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
613 
614  u8 *ptr = get_recvframe_data(precvframe); /*point to frame_ctrl field*/
615  struct rx_pkt_attrib *pattrib = &precvframe->u.hdr.attrib;
616 
617  if (pattrib->encrypt)
618  recvframe_pull_tail(precvframe, pattrib->icv_len);
619  psnap = (struct ieee80211_snap_hdr *)(ptr + pattrib->hdrlen +
620  pattrib->iv_len);
621  psnap_type = ptr + pattrib->hdrlen + pattrib->iv_len + SNAP_SIZE;
622  /* convert hdr + possible LLC headers into Ethernet header */
623  if ((!memcmp(psnap, (void *)rfc1042_header, SNAP_SIZE) &&
624  (memcmp(psnap_type, (void *)SNAP_ETH_TYPE_IPX, 2)) &&
625  (memcmp(psnap_type, (void *)SNAP_ETH_TYPE_APPLETALK_AARP, 2))) ||
626  !memcmp(psnap, (void *)bridge_tunnel_header, SNAP_SIZE)) {
627  /* remove RFC1042 or Bridge-Tunnel encapsulation and
628  * replace EtherType */
629  bsnaphdr = true;
630  } else {
631  /* Leave Ethernet header part of hdr and full payload */
632  bsnaphdr = false;
633  }
634  rmv_len = pattrib->hdrlen + pattrib->iv_len +
635  (bsnaphdr ? SNAP_SIZE : 0);
636  len = precvframe->u.hdr.len - rmv_len;
637  if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == true)) {
638  ptr += rmv_len;
639  *ptr = 0x87;
640  *(ptr+1) = 0x12;
641  eth_type = 0x8712;
642  /* append rx status for mp test packets */
643  ptr = recvframe_pull(precvframe, (rmv_len -
644  sizeof(struct ethhdr) + 2) - 24);
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 
651  memcpy(ptr, pattrib->dst, ETH_ALEN);
652  memcpy(ptr+ETH_ALEN, pattrib->src, ETH_ALEN);
653  if (!bsnaphdr) {
654  len = htons(len);
655  memcpy(ptr + 12, &len, 2);
656  }
657  return ret;
658 }
659 
660 s32 r8712_recv_entry(union recv_frame *precvframe)
661 {
662  struct _adapter *padapter;
663  struct recv_priv *precvpriv;
664  struct mlme_priv *pmlmepriv;
665  struct recv_stat *prxstat;
666  struct dvobj_priv *pdev;
667  u8 *phead, *pdata, *ptail, *pend;
668 
669  struct __queue *pfree_recv_queue, *ppending_recv_queue;
670  s32 ret = _SUCCESS;
671  struct intf_hdl *pintfhdl;
672 
673  padapter = precvframe->u.hdr.adapter;
674  pintfhdl = &padapter->pio_queue->intf;
675  pmlmepriv = &padapter->mlmepriv;
676  precvpriv = &(padapter->recvpriv);
677  pdev = &padapter->dvobjpriv;
678  pfree_recv_queue = &(precvpriv->free_recv_queue);
679  ppending_recv_queue = &(precvpriv->recv_pending_queue);
680  phead = precvframe->u.hdr.rx_head;
681  pdata = precvframe->u.hdr.rx_data;
682  ptail = precvframe->u.hdr.rx_tail;
683  pend = precvframe->u.hdr.rx_end;
684  prxstat = (struct recv_stat *)phead;
685 
686  padapter->ledpriv.LedControlHandler(padapter, LED_CTL_RX);
687 
688  ret = recv_func(padapter, precvframe);
689  if (ret == _FAIL)
690  goto _recv_entry_drop;
691  precvpriv->rx_pkts++;
692  precvpriv->rx_bytes += (uint)(precvframe->u.hdr.rx_tail -
693  precvframe->u.hdr.rx_data);
694  return ret;
695 _recv_entry_drop:
696  precvpriv->rx_drop++;
697  padapter->mppriv.rx_pktloss = precvpriv->rx_drop;
698  return ret;
699 }