Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ieee80211_rx.c
Go to the documentation of this file.
1 /*
2  * Original code based Host AP (software wireless LAN access point) driver
3  * for Intersil Prism2/2.5/3 - hostap.o module, common routines
4  *
5  * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
7  * Copyright (c) 2002-2003, Jouni Malinen <[email protected]>
8  * Copyright (c) 2004, Intel Corporation
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation. See README and COPYING for
13  * more details.
14  ******************************************************************************
15 
16  Few modifications for Realtek's Wi-Fi drivers by
17  Andrea Merello <[email protected]>
18 
19  A special thanks goes to Realtek for their support !
20 
21 ******************************************************************************/
22 
23 
24 #include <linux/compiler.h>
25 //#include <linux/config.h>
26 #include <linux/errno.h>
27 #include <linux/if_arp.h>
28 #include <linux/in6.h>
29 #include <linux/in.h>
30 #include <linux/ip.h>
31 #include <linux/kernel.h>
32 #include <linux/module.h>
33 #include <linux/netdevice.h>
34 #include <linux/pci.h>
35 #include <linux/proc_fs.h>
36 #include <linux/skbuff.h>
37 #include <linux/slab.h>
38 #include <linux/tcp.h>
39 #include <linux/types.h>
40 #include <linux/wireless.h>
41 #include <linux/etherdevice.h>
42 #include <asm/uaccess.h>
43 #include <linux/ctype.h>
44 
45 #include "ieee80211.h"
46 #include "dot11d.h"
47 static inline void ieee80211_monitor_rx(struct ieee80211_device *ieee,
48  struct sk_buff *skb,
50 {
51  struct ieee80211_hdr_4addr *hdr =
52  (struct ieee80211_hdr_4addr *)skb->data;
53  u16 fc = le16_to_cpu(hdr->frame_ctl);
54 
55  skb->dev = ieee->dev;
56  skb_reset_mac_header(skb);
60  memset(skb->cb, 0, sizeof(skb->cb));
61  netif_rx(skb);
62 }
63 
64 
65 /* Called only as a tasklet (software IRQ) */
66 static struct ieee80211_frag_entry *
67 ieee80211_frag_cache_find(struct ieee80211_device *ieee, unsigned int seq,
68  unsigned int frag, u8 tid,u8 *src, u8 *dst)
69 {
71  int i;
72 
73  for (i = 0; i < IEEE80211_FRAG_CACHE_LEN; i++) {
74  entry = &ieee->frag_cache[tid][i];
75  if (entry->skb != NULL &&
76  time_after(jiffies, entry->first_frag_time + 2 * HZ)) {
78  "expiring fragment cache entry "
79  "seq=%u last_frag=%u\n",
80  entry->seq, entry->last_frag);
81  dev_kfree_skb_any(entry->skb);
82  entry->skb = NULL;
83  }
84 
85  if (entry->skb != NULL && entry->seq == seq &&
86  (entry->last_frag + 1 == frag || frag == -1) &&
87  memcmp(entry->src_addr, src, ETH_ALEN) == 0 &&
88  memcmp(entry->dst_addr, dst, ETH_ALEN) == 0)
89  return entry;
90  }
91 
92  return NULL;
93 }
94 
95 /* Called only as a tasklet (software IRQ) */
96 static struct sk_buff *
97 ieee80211_frag_cache_get(struct ieee80211_device *ieee,
98  struct ieee80211_hdr_4addr *hdr)
99 {
100  struct sk_buff *skb = NULL;
101  u16 fc = le16_to_cpu(hdr->frame_ctl);
102  u16 sc = le16_to_cpu(hdr->seq_ctl);
103  unsigned int frag = WLAN_GET_SEQ_FRAG(sc);
104  unsigned int seq = WLAN_GET_SEQ_SEQ(sc);
105  struct ieee80211_frag_entry *entry;
106  struct ieee80211_hdr_3addrqos *hdr_3addrqos;
107  struct ieee80211_hdr_4addrqos *hdr_4addrqos;
108  u8 tid;
109 
110  if (((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS)&&IEEE80211_QOS_HAS_SEQ(fc)) {
111  hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)hdr;
112  tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QOS_TID;
113  tid = UP2AC(tid);
114  tid ++;
115  } else if (IEEE80211_QOS_HAS_SEQ(fc)) {
116  hdr_3addrqos = (struct ieee80211_hdr_3addrqos *)hdr;
117  tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QOS_TID;
118  tid = UP2AC(tid);
119  tid ++;
120  } else {
121  tid = 0;
122  }
123 
124  if (frag == 0) {
125  /* Reserve enough space to fit maximum frame length */
126  skb = dev_alloc_skb(ieee->dev->mtu +
127  sizeof(struct ieee80211_hdr_4addr) +
128  8 /* LLC */ +
129  2 /* alignment */ +
130  8 /* WEP */ +
131  ETH_ALEN /* WDS */ +
132  (IEEE80211_QOS_HAS_SEQ(fc)?2:0) /* QOS Control */);
133  if (skb == NULL)
134  return NULL;
135 
136  entry = &ieee->frag_cache[tid][ieee->frag_next_idx[tid]];
137  ieee->frag_next_idx[tid]++;
138  if (ieee->frag_next_idx[tid] >= IEEE80211_FRAG_CACHE_LEN)
139  ieee->frag_next_idx[tid] = 0;
140 
141  if (entry->skb != NULL)
142  dev_kfree_skb_any(entry->skb);
143 
144  entry->first_frag_time = jiffies;
145  entry->seq = seq;
146  entry->last_frag = frag;
147  entry->skb = skb;
148  memcpy(entry->src_addr, hdr->addr2, ETH_ALEN);
149  memcpy(entry->dst_addr, hdr->addr1, ETH_ALEN);
150  } else {
151  /* received a fragment of a frame for which the head fragment
152  * should have already been received */
153  entry = ieee80211_frag_cache_find(ieee, seq, frag, tid,hdr->addr2,
154  hdr->addr1);
155  if (entry != NULL) {
156  entry->last_frag = frag;
157  skb = entry->skb;
158  }
159  }
160 
161  return skb;
162 }
163 
164 
165 /* Called only as a tasklet (software IRQ) */
166 static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee,
167  struct ieee80211_hdr_4addr *hdr)
168 {
169  u16 fc = le16_to_cpu(hdr->frame_ctl);
170  u16 sc = le16_to_cpu(hdr->seq_ctl);
171  unsigned int seq = WLAN_GET_SEQ_SEQ(sc);
172  struct ieee80211_frag_entry *entry;
173  struct ieee80211_hdr_3addrqos *hdr_3addrqos;
174  struct ieee80211_hdr_4addrqos *hdr_4addrqos;
175  u8 tid;
176 
177  if(((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS)&&IEEE80211_QOS_HAS_SEQ(fc)) {
178  hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)hdr;
179  tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QOS_TID;
180  tid = UP2AC(tid);
181  tid ++;
182  } else if (IEEE80211_QOS_HAS_SEQ(fc)) {
183  hdr_3addrqos = (struct ieee80211_hdr_3addrqos *)hdr;
184  tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QOS_TID;
185  tid = UP2AC(tid);
186  tid ++;
187  } else {
188  tid = 0;
189  }
190 
191  entry = ieee80211_frag_cache_find(ieee, seq, -1, tid,hdr->addr2,
192  hdr->addr1);
193 
194  if (entry == NULL) {
196  "could not invalidate fragment cache "
197  "entry (seq=%u)\n", seq);
198  return -1;
199  }
200 
201  entry->skb = NULL;
202  return 0;
203 }
204 
205 
206 
207 /* ieee80211_rx_frame_mgtmt
208  *
209  * Responsible for handling management control frames
210  *
211  * Called by ieee80211_rx */
212 static inline int
213 ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb,
214  struct ieee80211_rx_stats *rx_stats, u16 type,
215  u16 stype)
216 {
217  struct ieee80211_hdr_4addr *hdr;
218 
219  // cheat the the hdr type
220  hdr = (struct ieee80211_hdr_4addr *)skb->data;
221 
222  /* On the struct stats definition there is written that
223  * this is not mandatory.... but seems that the probe
224  * response parser uses it
225  */
226  rx_stats->len = skb->len;
227  ieee80211_rx_mgt(ieee, (struct ieee80211_hdr_4addr *)skb->data,
228  rx_stats);
229 
230  if((ieee->state == IEEE80211_LINKED)&&(memcmp(hdr->addr3,ieee->current_network.bssid,ETH_ALEN))) {
231  dev_kfree_skb_any(skb);
232  return 0;
233  }
234 
235  ieee80211_rx_frame_softmac(ieee, skb, rx_stats, type, stype);
236 
237  dev_kfree_skb_any(skb);
238 
239  return 0;
240 
241 }
242 
243 
244 
245 /* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
246 /* Ethernet-II snap header (RFC1042 for most EtherTypes) */
247 static unsigned char rfc1042_header[] =
248 { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
249 /* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
250 static unsigned char bridge_tunnel_header[] =
251 { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
252 /* No encapsulation header if EtherType < 0x600 (=length) */
253 
254 /* Called by ieee80211_rx_frame_decrypt */
255 static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee,
256  struct sk_buff *skb, size_t hdrlen)
257 {
258  struct net_device *dev = ieee->dev;
259  u16 fc, ethertype;
260  struct ieee80211_hdr_4addr *hdr;
261  u8 *pos;
262 
263  if (skb->len < 24)
264  return 0;
265 
266  hdr = (struct ieee80211_hdr_4addr *)skb->data;
267  fc = le16_to_cpu(hdr->frame_ctl);
268 
269  /* check that the frame is unicast frame to us */
272  memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0 &&
273  memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0) {
274  /* ToDS frame with own addr BSSID and DA */
275  } else if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
277  memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) {
278  /* FromDS frame with own addr as DA */
279  } else
280  return 0;
281 
282  if (skb->len < 24 + 8)
283  return 0;
284 
285  /* check for port access entity Ethernet type */
286 // pos = skb->data + 24;
287  pos = skb->data + hdrlen;
288  ethertype = (pos[6] << 8) | pos[7];
289  if (ethertype == ETH_P_PAE)
290  return 1;
291 
292  return 0;
293 }
294 
295 /* Called only as a tasklet (software IRQ), by ieee80211_rx */
296 static inline int
297 ieee80211_rx_frame_decrypt(struct ieee80211_device* ieee, struct sk_buff *skb,
298  struct ieee80211_crypt_data *crypt)
299 {
300  struct ieee80211_hdr_4addr *hdr;
301  int res, hdrlen;
302 
303  if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL)
304  return 0;
305 
306  hdr = (struct ieee80211_hdr_4addr *)skb->data;
308 
309 #ifdef CONFIG_IEEE80211_CRYPT_TKIP
310  if (ieee->tkip_countermeasures &&
311  strcmp(crypt->ops->name, "TKIP") == 0) {
312  if (net_ratelimit()) {
313  printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
314  "received packet from %pM\n",
315  ieee->dev->name, hdr->addr2);
316  }
317  return -1;
318  }
319 #endif
320 
321  atomic_inc(&crypt->refcnt);
322  res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
323  atomic_dec(&crypt->refcnt);
324  if (res < 0) {
326  "decryption failed (SA=%pM"
327  ") res=%d\n", hdr->addr2, res);
328  if (res == -2)
329  IEEE80211_DEBUG_DROP("Decryption failed ICV "
330  "mismatch (key %d)\n",
331  skb->data[hdrlen + 3] >> 6);
332  ieee->ieee_stats.rx_discards_undecryptable++;
333  return -1;
334  }
335 
336  return res;
337 }
338 
339 
340 /* Called only as a tasklet (software IRQ), by ieee80211_rx */
341 static inline int
342 ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device* ieee, struct sk_buff *skb,
343  int keyidx, struct ieee80211_crypt_data *crypt)
344 {
345  struct ieee80211_hdr_4addr *hdr;
346  int res, hdrlen;
347 
348  if (crypt == NULL || crypt->ops->decrypt_msdu == NULL)
349  return 0;
350 
351  hdr = (struct ieee80211_hdr_4addr *)skb->data;
353 
354  atomic_inc(&crypt->refcnt);
355  res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv);
356  atomic_dec(&crypt->refcnt);
357  if (res < 0) {
358  printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed"
359  " (SA=%pM keyidx=%d)\n",
360  ieee->dev->name, hdr->addr2, keyidx);
361  return -1;
362  }
363 
364  return 0;
365 }
366 
367 
368 /* this function is stolen from ipw2200 driver*/
369 #define IEEE_PACKET_RETRY_TIME (5*HZ)
370 static int is_duplicate_packet(struct ieee80211_device *ieee,
371  struct ieee80211_hdr_4addr *header)
372 {
373  u16 fc = le16_to_cpu(header->frame_ctl);
374  u16 sc = le16_to_cpu(header->seq_ctl);
375  u16 seq = WLAN_GET_SEQ_SEQ(sc);
376  u16 frag = WLAN_GET_SEQ_FRAG(sc);
377  u16 *last_seq, *last_frag;
378  unsigned long *last_time;
379  struct ieee80211_hdr_3addrqos *hdr_3addrqos;
380  struct ieee80211_hdr_4addrqos *hdr_4addrqos;
381  u8 tid;
382 
383  //TO2DS and QoS
384  if(((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS)&&IEEE80211_QOS_HAS_SEQ(fc)) {
385  hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)header;
386  tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QOS_TID;
387  tid = UP2AC(tid);
388  tid ++;
389  } else if(IEEE80211_QOS_HAS_SEQ(fc)) { //QoS
390  hdr_3addrqos = (struct ieee80211_hdr_3addrqos *)header;
391  tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QOS_TID;
392  tid = UP2AC(tid);
393  tid ++;
394  } else { // no QoS
395  tid = 0;
396  }
397  switch (ieee->iw_mode) {
398  case IW_MODE_ADHOC:
399  {
400  struct list_head *p;
401  struct ieee_ibss_seq *entry = NULL;
402  u8 *mac = header->addr2;
403  int index = mac[5] % IEEE_IBSS_MAC_HASH_SIZE;
404  //for (pos = (head)->next; pos != (head); pos = pos->next)
405  __list_for_each(p, &ieee->ibss_mac_hash[index]) {
406  entry = list_entry(p, struct ieee_ibss_seq, list);
407  if (!memcmp(entry->mac, mac, ETH_ALEN))
408  break;
409  }
410  // if (memcmp(entry->mac, mac, ETH_ALEN)){
411  if (p == &ieee->ibss_mac_hash[index]) {
412  entry = kmalloc(sizeof(struct ieee_ibss_seq), GFP_ATOMIC);
413  if (!entry) {
414  printk(KERN_WARNING "Cannot malloc new mac entry\n");
415  return 0;
416  }
417  memcpy(entry->mac, mac, ETH_ALEN);
418  entry->seq_num[tid] = seq;
419  entry->frag_num[tid] = frag;
420  entry->packet_time[tid] = jiffies;
421  list_add(&entry->list, &ieee->ibss_mac_hash[index]);
422  return 0;
423  }
424  last_seq = &entry->seq_num[tid];
425  last_frag = &entry->frag_num[tid];
426  last_time = &entry->packet_time[tid];
427  break;
428  }
429 
430  case IW_MODE_INFRA:
431  last_seq = &ieee->last_rxseq_num[tid];
432  last_frag = &ieee->last_rxfrag_num[tid];
433  last_time = &ieee->last_packet_time[tid];
434 
435  break;
436  default:
437  return 0;
438  }
439 
440 // if(tid != 0) {
441 // printk(KERN_WARNING ":)))))))))))%x %x %x, fc(%x)\n", tid, *last_seq, seq, header->frame_ctl);
442 // }
443  if ((*last_seq == seq) &&
444  time_after(*last_time + IEEE_PACKET_RETRY_TIME, jiffies)) {
445  if (*last_frag == frag){
446  //printk(KERN_WARNING "[1] go drop!\n");
447  goto drop;
448 
449  }
450  if (*last_frag + 1 != frag)
451  /* out-of-order fragment */
452  //printk(KERN_WARNING "[2] go drop!\n");
453  goto drop;
454  } else
455  *last_seq = seq;
456 
457  *last_frag = frag;
458  *last_time = jiffies;
459  return 0;
460 
461 drop:
462 // BUG_ON(!(fc & IEEE80211_FCTL_RETRY));
463 // printk("DUP\n");
464 
465  return 1;
466 }
467 
468 
469 /* All received frames are sent to this function. @skb contains the frame in
470  * IEEE 802.11 format, i.e., in the format it was sent over air.
471  * This function is called only as a tasklet (software IRQ). */
472 int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
473  struct ieee80211_rx_stats *rx_stats)
474 {
475  struct net_device *dev = ieee->dev;
476  //struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
477  struct ieee80211_hdr_4addr *hdr;
478 
479  size_t hdrlen;
480  u16 fc, type, stype, sc;
481  struct net_device_stats *stats;
482  unsigned int frag;
483  u8 *payload;
484  u16 ethertype;
485  u8 dst[ETH_ALEN];
486  u8 src[ETH_ALEN];
487  u8 bssid[ETH_ALEN];
488  struct ieee80211_crypt_data *crypt = NULL;
489  int keyidx = 0;
490 
491  // cheat the the hdr type
492  hdr = (struct ieee80211_hdr_4addr *)skb->data;
493  stats = &ieee->stats;
494 
495  if (skb->len < 10) {
496  printk(KERN_INFO "%s: SKB length < 10\n",
497  dev->name);
498  goto rx_dropped;
499  }
500 
501  fc = le16_to_cpu(hdr->frame_ctl);
502  type = WLAN_FC_GET_TYPE(fc);
503  stype = WLAN_FC_GET_STYPE(fc);
504  sc = le16_to_cpu(hdr->seq_ctl);
505 
506  frag = WLAN_GET_SEQ_FRAG(sc);
507 
508 //YJ,add,080828,for keep alive
509  if((fc & IEEE80211_FCTL_TODS) != IEEE80211_FCTL_TODS)
510  {
511  if(!memcmp(hdr->addr1,dev->dev_addr, ETH_ALEN))
512  {
513  ieee->NumRxUnicast++;
514  }
515  }
516  else
517  {
518  if(!memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN))
519  {
520  ieee->NumRxUnicast++;
521  }
522  }
523 //YJ,add,080828,for keep alive,end
524 
525  hdrlen = ieee80211_get_hdrlen(fc);
526 
527 
528  if (ieee->iw_mode == IW_MODE_MONITOR) {
529  ieee80211_monitor_rx(ieee, skb, rx_stats);
530  stats->rx_packets++;
531  stats->rx_bytes += skb->len;
532  return 1;
533  }
534 
535  if (ieee->host_decrypt) {
536  int idx = 0;
537  if (skb->len >= hdrlen + 3)
538  idx = skb->data[hdrlen + 3] >> 6;
539  crypt = ieee->crypt[idx];
540 
541  /* allow NULL decrypt to indicate an station specific override
542  * for default encryption */
543  if (crypt && (crypt->ops == NULL ||
544  crypt->ops->decrypt_mpdu == NULL))
545  crypt = NULL;
546 
547  if (!crypt && (fc & IEEE80211_FCTL_WEP)) {
548  /* This seems to be triggered by some (multicast?)
549  * frames from other than current BSS, so just drop the
550  * frames silently instead of filling system log with
551  * these reports. */
552  IEEE80211_DEBUG_DROP("Decryption failed (not set)"
553  " (SA=%pM)\n",
554  hdr->addr2);
555  ieee->ieee_stats.rx_discards_undecryptable++;
556  goto rx_dropped;
557  }
558  }
559 
560  if (skb->len < IEEE80211_DATA_HDR3_LEN)
561  goto rx_dropped;
562 
563  // if QoS enabled, should check the sequence for each of the AC
564  if (is_duplicate_packet(ieee, hdr))
565  goto rx_dropped;
566 
567 
568  if (type == IEEE80211_FTYPE_MGMT) {
569  if (ieee80211_rx_frame_mgmt(ieee, skb, rx_stats, type, stype))
570  goto rx_dropped;
571  else
572  goto rx_exit;
573  }
574 
575  /* Data frame - extract src/dst addresses */
576  switch (fc & (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
578  memcpy(dst, hdr->addr1, ETH_ALEN);
579  memcpy(src, hdr->addr3, ETH_ALEN);
580  memcpy(bssid,hdr->addr2,ETH_ALEN);
581  break;
582  case IEEE80211_FCTL_TODS:
583  memcpy(dst, hdr->addr3, ETH_ALEN);
584  memcpy(src, hdr->addr2, ETH_ALEN);
585  memcpy(bssid,hdr->addr1,ETH_ALEN);
586  break;
587  case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS:
588  if (skb->len < IEEE80211_DATA_HDR4_LEN)
589  goto rx_dropped;
590  memcpy(dst, hdr->addr3, ETH_ALEN);
591  memcpy(src, hdr->addr4, ETH_ALEN);
592  memcpy(bssid, ieee->current_network.bssid, ETH_ALEN);
593  break;
594  case 0:
595  memcpy(dst, hdr->addr1, ETH_ALEN);
596  memcpy(src, hdr->addr2, ETH_ALEN);
597  memcpy(bssid,hdr->addr3,ETH_ALEN);
598  break;
599  }
600 
601 
602  dev->last_rx = jiffies;
603 
604 
605  /* Nullfunc frames may have PS-bit set, so they must be passed to
606  * hostap_handle_sta_rx() before being dropped here. */
607  if (stype != IEEE80211_STYPE_DATA &&
608  stype != IEEE80211_STYPE_DATA_CFACK &&
609  stype != IEEE80211_STYPE_DATA_CFPOLL &&
611  stype != IEEE80211_STYPE_QOS_DATA//add by David,2006.8.4
612  ) {
613  if (stype != IEEE80211_STYPE_NULLFUNC)
615  "RX: dropped data frame "
616  "with no data (type=0x%02x, "
617  "subtype=0x%02x, len=%d)\n",
618  type, stype, skb->len);
619  goto rx_dropped;
620  }
621  if(memcmp(bssid,ieee->current_network.bssid,ETH_ALEN)) {
622  goto rx_dropped;
623  }
624 
625  ieee->NumRxDataInPeriod++;
626  ieee->NumRxOkTotal++;
627  /* skb: hdr + (possibly fragmented, possibly encrypted) payload */
628 
629  if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) &&
630  (keyidx = ieee80211_rx_frame_decrypt(ieee, skb, crypt)) < 0)
631  goto rx_dropped;
632 
633  hdr = (struct ieee80211_hdr_4addr *)skb->data;
634 
635  /* skb: hdr + (possibly fragmented) plaintext payload */
636  // PR: FIXME: hostap has additional conditions in the "if" below:
637  // ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) &&
638  if ((frag != 0 || (fc & IEEE80211_FCTL_MOREFRAGS))) {
639  int flen;
640  struct sk_buff *frag_skb = ieee80211_frag_cache_get(ieee, hdr);
641  IEEE80211_DEBUG_FRAG("Rx Fragment received (%u)\n", frag);
642 
643  if (!frag_skb) {
645  "Rx cannot get skb from fragment "
646  "cache (morefrag=%d seq=%u frag=%u)\n",
647  (fc & IEEE80211_FCTL_MOREFRAGS) != 0,
648  WLAN_GET_SEQ_SEQ(sc), frag);
649  goto rx_dropped;
650  }
651  flen = skb->len;
652  if (frag != 0)
653  flen -= hdrlen;
654 
655  if (frag_skb->tail + flen > frag_skb->end) {
656  printk(KERN_WARNING "%s: host decrypted and "
657  "reassembled frame did not fit skb\n",
658  dev->name);
659  ieee80211_frag_cache_invalidate(ieee, hdr);
660  goto rx_dropped;
661  }
662 
663  if (frag == 0) {
664  /* copy first fragment (including full headers) into
665  * beginning of the fragment cache skb */
666  memcpy(skb_put(frag_skb, flen), skb->data, flen);
667  } else {
668  /* append frame payload to the end of the fragment
669  * cache skb */
670  memcpy(skb_put(frag_skb, flen), skb->data + hdrlen,
671  flen);
672  }
673  dev_kfree_skb_any(skb);
674  skb = NULL;
675 
676  if (fc & IEEE80211_FCTL_MOREFRAGS) {
677  /* more fragments expected - leave the skb in fragment
678  * cache for now; it will be delivered to upper layers
679  * after all fragments have been received */
680  goto rx_exit;
681  }
682 
683  /* this was the last fragment and the frame will be
684  * delivered, so remove skb from fragment cache */
685  skb = frag_skb;
686  hdr = (struct ieee80211_hdr_4addr *)skb->data;
687  ieee80211_frag_cache_invalidate(ieee, hdr);
688  }
689 
690  /* skb: hdr + (possible reassembled) full MSDU payload; possibly still
691  * encrypted/authenticated */
692  if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) &&
693  ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt))
694  goto rx_dropped;
695 
696  hdr = (struct ieee80211_hdr_4addr *)skb->data;
697  if (crypt && !(fc & IEEE80211_FCTL_WEP) && !ieee->open_wep) {
698  if (/*ieee->ieee802_1x &&*/
699  ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
700 
701 #ifdef CONFIG_IEEE80211_DEBUG
702  /* pass unencrypted EAPOL frames even if encryption is
703  * configured */
704  struct eapol *eap = (struct eapol *)(skb->data +
705  24);
706  IEEE80211_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n",
707  eap_get_type(eap->type));
708 #endif
709  } else {
711  "encryption configured, but RX "
712  "frame not encrypted (SA=%pM)\n",
713  hdr->addr2);
714  goto rx_dropped;
715  }
716  }
717 
718 #ifdef CONFIG_IEEE80211_DEBUG
719  if (crypt && !(fc & IEEE80211_FCTL_WEP) &&
720  ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
721  struct eapol *eap = (struct eapol *)(skb->data +
722  24);
723  IEEE80211_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n",
724  eap_get_type(eap->type));
725  }
726 #endif
727 
728  if (crypt && !(fc & IEEE80211_FCTL_WEP) && !ieee->open_wep &&
729  !ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
731  "dropped unencrypted RX data "
732  "frame from %pM"
733  " (drop_unencrypted=1)\n",
734  hdr->addr2);
735  goto rx_dropped;
736  }
737 /*
738  if(ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
739  printk(KERN_WARNING "RX: IEEE802.1X EPAOL frame!\n");
740  }
741 */
742  /* skb: hdr + (possible reassembled) full plaintext payload */
743  payload = skb->data + hdrlen;
744  ethertype = (payload[6] << 8) | payload[7];
745 
746 
747  /* convert hdr + possible LLC headers into Ethernet header */
748  if (skb->len - hdrlen >= 8 &&
749  ((memcmp(payload, rfc1042_header, SNAP_SIZE) == 0 &&
750  ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
751  memcmp(payload, bridge_tunnel_header, SNAP_SIZE) == 0)) {
752  /* remove RFC1042 or Bridge-Tunnel encapsulation and
753  * replace EtherType */
754  skb_pull(skb, hdrlen + SNAP_SIZE);
755  memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
756  memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
757  } else {
758  u16 len;
759  /* Leave Ethernet header part of hdr and full payload */
760  skb_pull(skb, hdrlen);
761  len = htons(skb->len);
762  memcpy(skb_push(skb, 2), &len, 2);
763  memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
764  memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
765  }
766 
767 
768  stats->rx_packets++;
769  stats->rx_bytes += skb->len;
770 
771  if (skb) {
772  skb->protocol = eth_type_trans(skb, dev);
773  memset(skb->cb, 0, sizeof(skb->cb));
774  skb->dev = dev;
775  skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */
776  ieee->last_rx_ps_time = jiffies;
777  netif_rx(skb);
778  }
779 
780  rx_exit:
781  return 1;
782 
783  rx_dropped:
784  stats->rx_dropped++;
785 
786  /* Returning 0 indicates to caller that we have not handled the SKB--
787  * so it is still allocated and can be used again by underlying
788  * hardware as a DMA target */
789  return 0;
790 }
791 
792 #define MGMT_FRAME_FIXED_PART_LENGTH 0x24
793 
794 static inline int ieee80211_is_ofdm_rate(u8 rate)
795 {
796  switch (rate & ~IEEE80211_BASIC_RATE_MASK) {
805  return 1;
806  }
807  return 0;
808 }
809 
810 static inline int ieee80211_SignalStrengthTranslate(
811  int CurrSS
812  )
813 {
814  int RetSS;
815 
816  // Step 1. Scale mapping.
817  if(CurrSS >= 71 && CurrSS <= 100)
818  {
819  RetSS = 90 + ((CurrSS - 70) / 3);
820  }
821  else if(CurrSS >= 41 && CurrSS <= 70)
822  {
823  RetSS = 78 + ((CurrSS - 40) / 3);
824  }
825  else if(CurrSS >= 31 && CurrSS <= 40)
826  {
827  RetSS = 66 + (CurrSS - 30);
828  }
829  else if(CurrSS >= 21 && CurrSS <= 30)
830  {
831  RetSS = 54 + (CurrSS - 20);
832  }
833  else if(CurrSS >= 5 && CurrSS <= 20)
834  {
835  RetSS = 42 + (((CurrSS - 5) * 2) / 3);
836  }
837  else if(CurrSS == 4)
838  {
839  RetSS = 36;
840  }
841  else if(CurrSS == 3)
842  {
843  RetSS = 27;
844  }
845  else if(CurrSS == 2)
846  {
847  RetSS = 18;
848  }
849  else if(CurrSS == 1)
850  {
851  RetSS = 9;
852  }
853  else
854  {
855  RetSS = CurrSS;
856  }
857  //RT_TRACE(COMP_DBG, DBG_LOUD, ("##### After Mapping: LastSS: %d, CurrSS: %d, RetSS: %d\n", LastSS, CurrSS, RetSS));
858 
859  // Step 2. Smoothing.
860 
861  //RT_TRACE(COMP_DBG, DBG_LOUD, ("$$$$$ After Smoothing: LastSS: %d, CurrSS: %d, RetSS: %d\n", LastSS, CurrSS, RetSS));
862 
863  return RetSS;
864 }
865 
866 static inline void ieee80211_extract_country_ie(
867  struct ieee80211_device *ieee,
869  struct ieee80211_network *network,
870  u8 * addr2
871 )
872 {
873  if(IS_DOT11D_ENABLE(ieee))
874  {
875  if(info_element->len!= 0)
876  {
877  memcpy(network->CountryIeBuf, info_element->data, info_element->len);
878  network->CountryIeLen = info_element->len;
879 
880  if(!IS_COUNTRY_IE_VALID(ieee))
881  {
882  Dot11d_UpdateCountryIe(ieee, addr2, info_element->len, info_element->data);
883  }
884  }
885 
886  //
887  // 070305, rcnjko: I update country IE watch dog here because
888  // some AP (e.g. Cisco 1242) don't include country IE in their
889  // probe response frame.
890  //
891  if(IS_EQUAL_CIE_SRC(ieee, addr2) )
892  {
893  UPDATE_CIE_WATCHDOG(ieee);
894  }
895  }
896 
897 }
898 
899 int
901  unsigned char SignalStrengthIndex // 0-100 index.
902  )
903 {
904  unsigned char SignalPower; // in dBm.
905 
906  // Translate to dBm (x=0.5y-95).
907  SignalPower = (int)SignalStrengthIndex * 7 / 10;
908  SignalPower -= 95;
909 
910  return SignalPower;
911 }
913  struct ieee80211_device *ieee,
915  struct ieee80211_network *network,
916  struct ieee80211_rx_stats *stats)
917 {
918 #ifdef CONFIG_IEEE80211_DEBUG
919  char rates_str[64];
920  char *p;
921 #endif
923  u16 left;
924  u8 i;
925  short offset;
926  u8 curRate = 0,hOpRate = 0,curRate_ex = 0;
927 
928  /* Pull out fixed field data */
929  memcpy(network->bssid, beacon->header.addr3, ETH_ALEN);
930  network->capability = beacon->capability;
931  network->last_scanned = jiffies;
932  network->time_stamp[0] = beacon->time_stamp[0];
933  network->time_stamp[1] = beacon->time_stamp[1];
934  network->beacon_interval = beacon->beacon_interval;
935  /* Where to pull this? beacon->listen_interval;*/
936  network->listen_interval = 0x0A;
937  network->rates_len = network->rates_ex_len = 0;
938  network->last_associate = 0;
939  network->ssid_len = 0;
940  network->flags = 0;
941  network->atim_window = 0;
942  network->QoS_Enable = 0;
943 //by amy 080312
944  network->HighestOperaRate = 0;
945 //by amy 080312
946  network->Turbo_Enable = 0;
947  network->CountryIeLen = 0;
948  memset(network->CountryIeBuf, 0, MAX_IE_LEN);
949 
950  if (stats->freq == IEEE80211_52GHZ_BAND) {
951  /* for A band (No DS info) */
952  network->channel = stats->received_channel;
953  } else
954  network->flags |= NETWORK_HAS_CCK;
955 
956  network->wpa_ie_len = 0;
957  network->rsn_ie_len = 0;
958 
959  info_element = &beacon->info_element;
960  left = stats->len - ((void *)info_element - (void *)beacon);
961  while (left >= sizeof(struct ieee80211_info_element_hdr)) {
962  if (sizeof(struct ieee80211_info_element_hdr) + info_element->len > left) {
963  IEEE80211_DEBUG_SCAN("SCAN: parse failed: info_element->len + 2 > left : info_element->len+2=%d left=%d.\n",
964  info_element->len + sizeof(struct ieee80211_info_element),
965  left);
966  return 1;
967  }
968 
969  switch (info_element->id) {
970  case MFIE_TYPE_SSID:
971  if (ieee80211_is_empty_essid(info_element->data,
972  info_element->len)) {
973  network->flags |= NETWORK_EMPTY_ESSID;
974  break;
975  }
976 
977  network->ssid_len = min(info_element->len,
979  memcpy(network->ssid, info_element->data, network->ssid_len);
980  if (network->ssid_len < IW_ESSID_MAX_SIZE)
981  memset(network->ssid + network->ssid_len, 0,
982  IW_ESSID_MAX_SIZE - network->ssid_len);
983 
984  IEEE80211_DEBUG_SCAN("MFIE_TYPE_SSID: '%s' len=%d.\n",
985  network->ssid, network->ssid_len);
986  break;
987 
988  case MFIE_TYPE_RATES:
989 #ifdef CONFIG_IEEE80211_DEBUG
990  p = rates_str;
991 #endif
992  network->rates_len = min(info_element->len, MAX_RATES_LENGTH);
993  for (i = 0; i < network->rates_len; i++) {
994  network->rates[i] = info_element->data[i];
995  curRate = network->rates[i] & 0x7f;
996  if( hOpRate < curRate )
997  hOpRate = curRate;
998 #ifdef CONFIG_IEEE80211_DEBUG
999  p += snprintf(p, sizeof(rates_str) - (p - rates_str), "%02X ", network->rates[i]);
1000 #endif
1001  if (ieee80211_is_ofdm_rate(info_element->data[i])) {
1002  network->flags |= NETWORK_HAS_OFDM;
1003  if (info_element->data[i] &
1005  network->flags &=
1006  ~NETWORK_HAS_CCK;
1007  }
1008  }
1009 
1010  IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES: '%s' (%d)\n",
1011  rates_str, network->rates_len);
1012  break;
1013 
1014  case MFIE_TYPE_RATES_EX:
1015 #ifdef CONFIG_IEEE80211_DEBUG
1016  p = rates_str;
1017 #endif
1018  network->rates_ex_len = min(info_element->len, MAX_RATES_EX_LENGTH);
1019  for (i = 0; i < network->rates_ex_len; i++) {
1020  network->rates_ex[i] = info_element->data[i];
1021  curRate_ex = network->rates_ex[i] & 0x7f;
1022  if( hOpRate < curRate_ex )
1023  hOpRate = curRate_ex;
1024 #ifdef CONFIG_IEEE80211_DEBUG
1025  p += snprintf(p, sizeof(rates_str) - (p - rates_str), "%02X ", network->rates[i]);
1026 #endif
1027  if (ieee80211_is_ofdm_rate(info_element->data[i])) {
1028  network->flags |= NETWORK_HAS_OFDM;
1029  if (info_element->data[i] &
1031  network->flags &=
1032  ~NETWORK_HAS_CCK;
1033  }
1034  }
1035 
1036  IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES_EX: '%s' (%d)\n",
1037  rates_str, network->rates_ex_len);
1038  break;
1039 
1040  case MFIE_TYPE_DS_SET:
1041  IEEE80211_DEBUG_SCAN("MFIE_TYPE_DS_SET: %d\n",
1042  info_element->data[0]);
1043  if (stats->freq == IEEE80211_24GHZ_BAND)
1044  network->channel = info_element->data[0];
1045  break;
1046 
1047  case MFIE_TYPE_FH_SET:
1048  IEEE80211_DEBUG_SCAN("MFIE_TYPE_FH_SET: ignored\n");
1049  break;
1050 
1051  case MFIE_TYPE_CF_SET:
1052  IEEE80211_DEBUG_SCAN("MFIE_TYPE_CF_SET: ignored\n");
1053  break;
1054 
1055  case MFIE_TYPE_TIM:
1056 
1057  if(info_element->len < 4)
1058  break;
1059 
1060  network->dtim_period = info_element->data[1];
1061 
1062  if(ieee->state != IEEE80211_LINKED)
1063  break;
1064 
1065  network->last_dtim_sta_time[0] = jiffies;
1066  network->last_dtim_sta_time[1] = stats->mac_time[1];
1067 
1068  network->dtim_data = IEEE80211_DTIM_VALID;
1069 
1070  if(info_element->data[0] != 0)
1071  break;
1072 
1073  if(info_element->data[2] & 1)
1074  network->dtim_data |= IEEE80211_DTIM_MBCAST;
1075 
1076  offset = (info_element->data[2] >> 1)*2;
1077 
1078  //printk("offset1:%x aid:%x\n",offset, ieee->assoc_id);
1079 
1080  /* add and modified for ps 2008.1.22 */
1081  if(ieee->assoc_id < 8*offset ||
1082  ieee->assoc_id > 8*(offset + info_element->len -3)) {
1083  break;
1084  }
1085 
1086  offset = (ieee->assoc_id/8) - offset;// + ((aid % 8)? 0 : 1) ;
1087 
1088  // printk("offset:%x data:%x, ucast:%d\n", offset,
1089  // info_element->data[3+offset] ,
1090  // info_element->data[3+offset] & (1<<(ieee->assoc_id%8)));
1091 
1092  if(info_element->data[3+offset] & (1<<(ieee->assoc_id%8))) {
1093  network->dtim_data |= IEEE80211_DTIM_UCAST;
1094  }
1095  break;
1096 
1097  case MFIE_TYPE_IBSS_SET:
1098  IEEE80211_DEBUG_SCAN("MFIE_TYPE_IBSS_SET: ignored\n");
1099  break;
1100 
1101  case MFIE_TYPE_CHALLENGE:
1102  IEEE80211_DEBUG_SCAN("MFIE_TYPE_CHALLENGE: ignored\n");
1103  break;
1104 
1105  case MFIE_TYPE_GENERIC:
1106  //nic is 87B
1107  IEEE80211_DEBUG_SCAN("MFIE_TYPE_GENERIC: %d bytes\n",
1108  info_element->len);
1109  if (info_element->len >= 4 &&
1110  info_element->data[0] == 0x00 &&
1111  info_element->data[1] == 0x50 &&
1112  info_element->data[2] == 0xf2 &&
1113  info_element->data[3] == 0x01) {
1114  network->wpa_ie_len = min(info_element->len + 2,
1115  MAX_WPA_IE_LEN);
1116  memcpy(network->wpa_ie, info_element,
1117  network->wpa_ie_len);
1118  }
1119 
1120  if (info_element->len == 7 &&
1121  info_element->data[0] == 0x00 &&
1122  info_element->data[1] == 0xe0 &&
1123  info_element->data[2] == 0x4c &&
1124  info_element->data[3] == 0x01 &&
1125  info_element->data[4] == 0x02) {
1126  network->Turbo_Enable = 1;
1127  }
1128  if (1 == stats->nic_type) {//nic 87
1129  break;
1130  }
1131 
1132  if (info_element->len >= 5 &&
1133  info_element->data[0] == 0x00 &&
1134  info_element->data[1] == 0x50 &&
1135  info_element->data[2] == 0xf2 &&
1136  info_element->data[3] == 0x02 &&
1137  info_element->data[4] == 0x00) {
1138  //printk(KERN_WARNING "wmm info updated: %x\n", info_element->data[6]);
1139  //WMM Information Element
1140  network->wmm_info = info_element->data[6];
1141  network->QoS_Enable = 1;
1142  }
1143 
1144  if (info_element->len >= 8 &&
1145  info_element->data[0] == 0x00 &&
1146  info_element->data[1] == 0x50 &&
1147  info_element->data[2] == 0xf2 &&
1148  info_element->data[3] == 0x02 &&
1149  info_element->data[4] == 0x01) {
1150  // Not care about version at present.
1151  //WMM Information Element
1152  //printk(KERN_WARNING "wmm info&param updated: %x\n", info_element->data[6]);
1153  network->wmm_info = info_element->data[6];
1154  //WMM Parameter Element
1155  memcpy(network->wmm_param, (u8 *)(info_element->data + 8),(info_element->len - 8));
1156  network->QoS_Enable = 1;
1157  }
1158  break;
1159 
1160  case MFIE_TYPE_RSN:
1161  IEEE80211_DEBUG_SCAN("MFIE_TYPE_RSN: %d bytes\n",
1162  info_element->len);
1163  network->rsn_ie_len = min(info_element->len + 2,
1164  MAX_WPA_IE_LEN);
1165  memcpy(network->rsn_ie, info_element,
1166  network->rsn_ie_len);
1167  break;
1168  case MFIE_TYPE_COUNTRY:
1169  IEEE80211_DEBUG_SCAN("MFIE_TYPE_COUNTRY: %d bytes\n",
1170  info_element->len);
1171 // printk("=====>Receive <%s> Country IE\n",network->ssid);
1172  ieee80211_extract_country_ie(ieee, info_element, network, beacon->header.addr2);
1173  break;
1174  default:
1175  IEEE80211_DEBUG_SCAN("unsupported IE %d\n",
1176  info_element->id);
1177  break;
1178  }
1179 
1180  left -= sizeof(struct ieee80211_info_element_hdr) +
1181  info_element->len;
1182  info_element = (struct ieee80211_info_element *)
1183  &info_element->data[info_element->len];
1184  }
1185 //by amy 080312
1186  network->HighestOperaRate = hOpRate;
1187 //by amy 080312
1188  network->mode = 0;
1189  if (stats->freq == IEEE80211_52GHZ_BAND)
1190  network->mode = IEEE_A;
1191  else {
1192  if (network->flags & NETWORK_HAS_OFDM)
1193  network->mode |= IEEE_G;
1194  if (network->flags & NETWORK_HAS_CCK)
1195  network->mode |= IEEE_B;
1196  }
1197 
1198  if (network->mode == 0) {
1199  IEEE80211_DEBUG_SCAN("Filtered out '%s (%pM)' "
1200  "network.\n",
1201  escape_essid(network->ssid,
1202  network->ssid_len),
1203  network->bssid);
1204  return 1;
1205  }
1206 
1207  if (ieee80211_is_empty_essid(network->ssid, network->ssid_len))
1208  network->flags |= NETWORK_EMPTY_ESSID;
1209 
1211  //stats->noise = stats->signal - stats->noise;
1212  stats->noise = ieee80211_TranslateToDbm(100 - stats->signalstrength) - 25;
1213  memcpy(&network->stats, stats, sizeof(network->stats));
1214 
1215  return 0;
1216 }
1217 
1218 static inline int is_same_network(struct ieee80211_network *src,
1219  struct ieee80211_network *dst,
1220  struct ieee80211_device * ieee)
1221 {
1222  /* A network is only a duplicate if the channel, BSSID, ESSID
1223  * and the capability field (in particular IBSS and BSS) all match.
1224  * We treat all <hidden> with the same BSSID and channel
1225  * as one network */
1226  return (((src->ssid_len == dst->ssid_len) || (ieee->iw_mode == IW_MODE_INFRA)) && //YJ,mod,080819,for hidden ap
1227  //((src->ssid_len == dst->ssid_len) &&
1228  (src->channel == dst->channel) &&
1229  !memcmp(src->bssid, dst->bssid, ETH_ALEN) &&
1230  (!memcmp(src->ssid, dst->ssid, src->ssid_len) || (ieee->iw_mode == IW_MODE_INFRA)) && //YJ,mod,080819,for hidden ap
1232  ((src->capability & WLAN_CAPABILITY_IBSS) ==
1233  (dst->capability & WLAN_CAPABILITY_IBSS)) &&
1234  ((src->capability & WLAN_CAPABILITY_BSS) ==
1235  (dst->capability & WLAN_CAPABILITY_BSS)));
1236 }
1237 
1238 inline void update_network(struct ieee80211_network *dst,
1239  struct ieee80211_network *src)
1240 {
1241  unsigned char quality = src->stats.signalstrength;
1242  unsigned char signal = 0;
1243  unsigned char noise = 0;
1244  if(dst->stats.signalstrength > 0) {
1245  quality = (dst->stats.signalstrength * 5 + src->stats.signalstrength + 5)/6;
1246  }
1247  signal = ieee80211_TranslateToDbm(quality);
1248  //noise = signal - src->stats.noise;
1249  if(dst->stats.noise > 0)
1250  noise = (dst->stats.noise * 5 + src->stats.noise)/6;
1251  //if(strcmp(dst->ssid, "linksys_lzm000") == 0)
1252 // printk("ssid:%s, quality:%d, signal:%d\n", dst->ssid, quality, signal);
1253  memcpy(&dst->stats, &src->stats, sizeof(struct ieee80211_rx_stats));
1254  dst->stats.signalstrength = quality;
1255  dst->stats.signal = signal;
1256 // printk("==================>stats.signal is %d\n",dst->stats.signal);
1257  dst->stats.noise = noise;
1258 
1259 
1260  dst->capability = src->capability;
1261  memcpy(dst->rates, src->rates, src->rates_len);
1262  dst->rates_len = src->rates_len;
1263  memcpy(dst->rates_ex, src->rates_ex, src->rates_ex_len);
1264  dst->rates_ex_len = src->rates_ex_len;
1266  //printk("==========>in %s: src->ssid is %s,chan is %d\n",__func__,src->ssid,src->channel);
1267 
1268  //YJ,add,080819,for hidden ap
1269  if(src->ssid_len > 0)
1270  {
1271  //if(src->ssid_len == 13)
1272  // printk("=====================>>>>>>>> Dst ssid: %s Src ssid: %s\n", dst->ssid, src->ssid);
1273  memset(dst->ssid, 0, dst->ssid_len);
1274  dst->ssid_len = src->ssid_len;
1275  memcpy(dst->ssid, src->ssid, src->ssid_len);
1276  }
1277  //YJ,add,080819,for hidden ap,end
1278 
1279  dst->channel = src->channel;
1280  dst->mode = src->mode;
1281  dst->flags = src->flags;
1282  dst->time_stamp[0] = src->time_stamp[0];
1283  dst->time_stamp[1] = src->time_stamp[1];
1284 
1285  dst->beacon_interval = src->beacon_interval;
1286  dst->listen_interval = src->listen_interval;
1287  dst->atim_window = src->atim_window;
1288  dst->dtim_period = src->dtim_period;
1289  dst->dtim_data = src->dtim_data;
1290  dst->last_dtim_sta_time[0] = src->last_dtim_sta_time[0];
1291  dst->last_dtim_sta_time[1] = src->last_dtim_sta_time[1];
1292 // printk("update:%s, dtim_period:%x, dtim_data:%x\n", src->ssid, src->dtim_period, src->dtim_data);
1293  memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len);
1294  dst->wpa_ie_len = src->wpa_ie_len;
1295  memcpy(dst->rsn_ie, src->rsn_ie, src->rsn_ie_len);
1296  dst->rsn_ie_len = src->rsn_ie_len;
1297 
1298  dst->last_scanned = jiffies;
1299  /* dst->last_associate is not overwritten */
1300 // disable QoS process now, added by David 2006/7/25
1301 #if 1
1302  dst->wmm_info = src->wmm_info; //sure to exist in beacon or probe response frame.
1303 /*
1304  if((dst->wmm_info^src->wmm_info)&0x0f) {//Param Set Count change, update Parameter
1305  memcpy(dst->wmm_param, src->wmm_param, IEEE80211_AC_PRAM_LEN);
1306  }
1307 */
1308  if(src->wmm_param[0].ac_aci_acm_aifsn|| \
1309  src->wmm_param[1].ac_aci_acm_aifsn|| \
1310  src->wmm_param[2].ac_aci_acm_aifsn|| \
1311  src->wmm_param[3].ac_aci_acm_aifsn) {
1313  }
1314  dst->QoS_Enable = src->QoS_Enable;
1315 #else
1316  dst->QoS_Enable = 1;//for Rtl8187 simulation
1317 #endif
1318  dst->SignalStrength = src->SignalStrength;
1319  dst->Turbo_Enable = src->Turbo_Enable;
1320  dst->CountryIeLen = src->CountryIeLen;
1321  memcpy(dst->CountryIeBuf, src->CountryIeBuf, src->CountryIeLen);
1322 }
1323 
1324 
1326  struct ieee80211_device *ieee,
1328  struct ieee80211_rx_stats *stats)
1329 {
1330  struct ieee80211_network network;
1331  struct ieee80211_network *target;
1332  struct ieee80211_network *oldest = NULL;
1333 #ifdef CONFIG_IEEE80211_DEBUG
1334  struct ieee80211_info_element *info_element = &beacon->info_element;
1335 #endif
1336  unsigned long flags;
1337  short renew;
1338  u8 wmm_info;
1339  u8 is_beacon = (WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == IEEE80211_STYPE_BEACON)? 1:0; //YJ,add,080819,for hidden ap
1340 
1341  memset(&network, 0, sizeof(struct ieee80211_network));
1342 
1344  "'%s' (%pM): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
1345  escape_essid(info_element->data, info_element->len),
1346  beacon->header.addr3,
1347  (beacon->capability & (1<<0xf)) ? '1' : '0',
1348  (beacon->capability & (1<<0xe)) ? '1' : '0',
1349  (beacon->capability & (1<<0xd)) ? '1' : '0',
1350  (beacon->capability & (1<<0xc)) ? '1' : '0',
1351  (beacon->capability & (1<<0xb)) ? '1' : '0',
1352  (beacon->capability & (1<<0xa)) ? '1' : '0',
1353  (beacon->capability & (1<<0x9)) ? '1' : '0',
1354  (beacon->capability & (1<<0x8)) ? '1' : '0',
1355  (beacon->capability & (1<<0x7)) ? '1' : '0',
1356  (beacon->capability & (1<<0x6)) ? '1' : '0',
1357  (beacon->capability & (1<<0x5)) ? '1' : '0',
1358  (beacon->capability & (1<<0x4)) ? '1' : '0',
1359  (beacon->capability & (1<<0x3)) ? '1' : '0',
1360  (beacon->capability & (1<<0x2)) ? '1' : '0',
1361  (beacon->capability & (1<<0x1)) ? '1' : '0',
1362  (beacon->capability & (1<<0x0)) ? '1' : '0');
1363 
1364  if (ieee80211_network_init(ieee, beacon, &network, stats)) {
1365  IEEE80211_DEBUG_SCAN("Dropped '%s' (%pM) via %s.\n",
1366  escape_essid(info_element->data,
1367  info_element->len),
1368  beacon->header.addr3,
1369  WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
1371  "PROBE RESPONSE" : "BEACON");
1372  return;
1373  }
1374 
1375  // For Asus EeePc request,
1376  // (1) if wireless adapter receive get any 802.11d country code in AP beacon,
1377  // wireless adapter should follow the country code.
1378  // (2) If there is no any country code in beacon,
1379  // then wireless adapter should do active scan from ch1~11 and
1380  // passive scan from ch12~14
1381  if(ieee->bGlobalDomain)
1382  {
1383  if (WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == IEEE80211_STYPE_PROBE_RESP)
1384  {
1385  // Case 1: Country code
1386  if(IS_COUNTRY_IE_VALID(ieee) )
1387  {
1388  if( !IsLegalChannel(ieee, network.channel) )
1389  {
1390  printk("GetScanInfo(): For Country code, filter probe response at channel(%d).\n", network.channel);
1391  return;
1392  }
1393  }
1394  // Case 2: No any country code.
1395  else
1396  {
1397  // Filter over channel ch12~14
1398  if(network.channel > 11)
1399  {
1400  printk("GetScanInfo(): For Global Domain, filter probe response at channel(%d).\n", network.channel);
1401  return;
1402  }
1403  }
1404  }
1405  else
1406  {
1407  // Case 1: Country code
1408  if(IS_COUNTRY_IE_VALID(ieee) )
1409  {
1410  if( !IsLegalChannel(ieee, network.channel) )
1411  {
1412  printk("GetScanInfo(): For Country code, filter beacon at channel(%d).\n",network.channel);
1413  return;
1414  }
1415  }
1416  // Case 2: No any country code.
1417  else
1418  {
1419  // Filter over channel ch12~14
1420  if(network.channel > 14)
1421  {
1422  printk("GetScanInfo(): For Global Domain, filter beacon at channel(%d).\n",network.channel);
1423  return;
1424  }
1425  }
1426  }
1427  }
1428  /* The network parsed correctly -- so now we scan our known networks
1429  * to see if we can find it in our list.
1430  *
1431  * NOTE: This search is definitely not optimized. Once its doing
1432  * the "right thing" we'll optimize it for efficiency if
1433  * necessary */
1434 
1435  /* Search for this entry in the list and update it if it is
1436  * already there. */
1437 
1438  spin_lock_irqsave(&ieee->lock, flags);
1439 
1440  if(is_same_network(&ieee->current_network, &network, ieee)) {
1441  wmm_info = ieee->current_network.wmm_info;
1442  //YJ,add,080819,for hidden ap
1443  if(is_beacon == 0)
1444  network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & ieee->current_network.flags);
1445  else if(ieee->state == IEEE80211_LINKED)
1446  ieee->NumRxBcnInPeriod++;
1447  //YJ,add,080819,for hidden ap,end
1448  //printk("====>network.ssid=%s cur_ssid=%s\n", network.ssid, ieee->current_network.ssid);
1449  update_network(&ieee->current_network, &network);
1450  }
1451 
1452  list_for_each_entry(target, &ieee->network_list, list) {
1453  if (is_same_network(target, &network, ieee))
1454  break;
1455  if ((oldest == NULL) ||
1456  (target->last_scanned < oldest->last_scanned))
1457  oldest = target;
1458  }
1459 
1460  /* If we didn't find a match, then get a new network slot to initialize
1461  * with this beacon's information */
1462  if (&target->list == &ieee->network_list) {
1463  if (list_empty(&ieee->network_free_list)) {
1464  /* If there are no more slots, expire the oldest */
1465  list_del(&oldest->list);
1466  target = oldest;
1467  IEEE80211_DEBUG_SCAN("Expired '%s' (%pM) from "
1468  "network list.\n",
1469  escape_essid(target->ssid,
1470  target->ssid_len),
1471  target->bssid);
1472  } else {
1473  /* Otherwise just pull from the free list */
1474  target = list_entry(ieee->network_free_list.next,
1475  struct ieee80211_network, list);
1476  list_del(ieee->network_free_list.next);
1477  }
1478 
1479 
1480 #ifdef CONFIG_IEEE80211_DEBUG
1481  IEEE80211_DEBUG_SCAN("Adding '%s' (%pM) via %s.\n",
1482  escape_essid(network.ssid,
1483  network.ssid_len),
1484  network.bssid,
1485  WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
1487  "PROBE RESPONSE" : "BEACON");
1488 #endif
1489 
1490  memcpy(target, &network, sizeof(*target));
1491  list_add_tail(&target->list, &ieee->network_list);
1492  } else {
1493  IEEE80211_DEBUG_SCAN("Updating '%s' (%pM) via %s.\n",
1494  escape_essid(target->ssid,
1495  target->ssid_len),
1496  target->bssid,
1497  WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
1499  "PROBE RESPONSE" : "BEACON");
1500 
1501  /* we have an entry and we are going to update it. But this entry may
1502  * be already expired. In this case we do the same as we found a new
1503  * net and call the new_net handler
1504  */
1505  renew = !time_after(target->last_scanned + ieee->scan_age, jiffies);
1506  //YJ,add,080819,for hidden ap
1507  if(is_beacon == 0)
1508  network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & target->flags);
1509  //if(strncmp(network.ssid, "linksys-c",9) == 0)
1510  // printk("====>2 network.ssid=%s FLAG=%d target.ssid=%s FLAG=%d\n", network.ssid, network.flags, target->ssid, target->flags);
1511  if(((network.flags & NETWORK_EMPTY_ESSID) == NETWORK_EMPTY_ESSID) \
1512  && (((network.ssid_len > 0) && (strncmp(target->ssid, network.ssid, network.ssid_len)))\
1513  ||((ieee->current_network.ssid_len == network.ssid_len)&&(strncmp(ieee->current_network.ssid, network.ssid, network.ssid_len) == 0)&&(ieee->state == IEEE80211_NOLINK))))
1514  renew = 1;
1515  //YJ,add,080819,for hidden ap,end
1516  update_network(target, &network);
1517  }
1518 
1519  spin_unlock_irqrestore(&ieee->lock, flags);
1520 }
1521 
1523  struct ieee80211_hdr_4addr *header,
1524  struct ieee80211_rx_stats *stats)
1525 {
1526  switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
1527 
1529  IEEE80211_DEBUG_MGMT("received BEACON (%d)\n",
1530  WLAN_FC_GET_STYPE(header->frame_ctl));
1531  IEEE80211_DEBUG_SCAN("Beacon\n");
1533  ieee, (struct ieee80211_probe_response *)header, stats);
1534  break;
1535 
1537  IEEE80211_DEBUG_MGMT("received PROBE RESPONSE (%d)\n",
1538  WLAN_FC_GET_STYPE(header->frame_ctl));
1539  IEEE80211_DEBUG_SCAN("Probe response\n");
1541  ieee, (struct ieee80211_probe_response *)header, stats);
1542  break;
1543  }
1544 }