• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/drivers/staging/rtl8187se/ieee80211/
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
6 * <jkmaline@cc.hut.fi>
7 * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
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 <andreamrl@tiscali.it>
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"
47static inline void ieee80211_monitor_rx(struct ieee80211_device *ieee,
48					struct sk_buff *skb,
49					struct ieee80211_rx_stats *rx_stats)
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);
57	skb_pull(skb, ieee80211_get_hdrlen(fc));
58	skb->pkt_type = PACKET_OTHERHOST;
59	skb->protocol = __constant_htons(ETH_P_80211_RAW);
60	memset(skb->cb, 0, sizeof(skb->cb));
61	netif_rx(skb);
62}
63
64
65/* Called only as a tasklet (software IRQ) */
66static struct ieee80211_frag_entry *
67ieee80211_frag_cache_find(struct ieee80211_device *ieee, unsigned int seq,
68			  unsigned int frag, u8 tid,u8 *src, u8 *dst)
69{
70	struct ieee80211_frag_entry *entry;
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)) {
77			IEEE80211_DEBUG_FRAG(
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) */
96static struct sk_buff *
97ieee80211_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) */
166static 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) {
195		IEEE80211_DEBUG_FRAG(
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 */
212static inline int
213ieee80211_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) */
247static unsigned char rfc1042_header[] =
248{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
249/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
250static 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 */
255static 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 */
270	if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
271	    IEEE80211_FCTL_TODS &&
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)) ==
276		   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 */
296static inline int
297ieee80211_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;
307	hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
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) {
325		IEEE80211_DEBUG_DROP(
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 */
341static inline int
342ieee80211_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;
352	hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
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)
370static 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
461drop:
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). */
472int 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)) {
577	case IEEE80211_FCTL_FROMDS:
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 &&
610	    stype != IEEE80211_STYPE_DATA_CFACKPOLL&&
611	    stype != IEEE80211_STYPE_QOS_DATA//add by David,2006.8.4
612	    ) {
613		if (stype != IEEE80211_STYPE_NULLFUNC)
614			IEEE80211_DEBUG_DROP(
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	// ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) &&
637	if ((frag != 0 || (fc & IEEE80211_FCTL_MOREFRAGS))) {
638		int flen;
639		struct sk_buff *frag_skb = ieee80211_frag_cache_get(ieee, hdr);
640		IEEE80211_DEBUG_FRAG("Rx Fragment received (%u)\n", frag);
641
642		if (!frag_skb) {
643			IEEE80211_DEBUG(IEEE80211_DL_RX | IEEE80211_DL_FRAG,
644					"Rx cannot get skb from fragment "
645					"cache (morefrag=%d seq=%u frag=%u)\n",
646					(fc & IEEE80211_FCTL_MOREFRAGS) != 0,
647					WLAN_GET_SEQ_SEQ(sc), frag);
648			goto rx_dropped;
649		}
650		flen = skb->len;
651		if (frag != 0)
652			flen -= hdrlen;
653
654		if (frag_skb->tail + flen > frag_skb->end) {
655			printk(KERN_WARNING "%s: host decrypted and "
656			       "reassembled frame did not fit skb\n",
657			       dev->name);
658			ieee80211_frag_cache_invalidate(ieee, hdr);
659			goto rx_dropped;
660		}
661
662		if (frag == 0) {
663			/* copy first fragment (including full headers) into
664			 * beginning of the fragment cache skb */
665			memcpy(skb_put(frag_skb, flen), skb->data, flen);
666		} else {
667			/* append frame payload to the end of the fragment
668			 * cache skb */
669			memcpy(skb_put(frag_skb, flen), skb->data + hdrlen,
670			       flen);
671		}
672		dev_kfree_skb_any(skb);
673		skb = NULL;
674
675		if (fc & IEEE80211_FCTL_MOREFRAGS) {
676			/* more fragments expected - leave the skb in fragment
677			 * cache for now; it will be delivered to upper layers
678			 * after all fragments have been received */
679			goto rx_exit;
680		}
681
682		/* this was the last fragment and the frame will be
683		 * delivered, so remove skb from fragment cache */
684		skb = frag_skb;
685		hdr = (struct ieee80211_hdr_4addr *)skb->data;
686		ieee80211_frag_cache_invalidate(ieee, hdr);
687	}
688
689	/* skb: hdr + (possible reassembled) full MSDU payload; possibly still
690	 * encrypted/authenticated */
691	if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) &&
692	    ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt))
693		goto rx_dropped;
694
695	hdr = (struct ieee80211_hdr_4addr *)skb->data;
696	if (crypt && !(fc & IEEE80211_FCTL_WEP) && !ieee->open_wep) {
697		if (/*ieee->ieee802_1x &&*/
698		    ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
699
700#ifdef CONFIG_IEEE80211_DEBUG
701			/* pass unencrypted EAPOL frames even if encryption is
702			 * configured */
703			struct eapol *eap = (struct eapol *)(skb->data +
704				24);
705			IEEE80211_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n",
706						eap_get_type(eap->type));
707#endif
708		} else {
709			IEEE80211_DEBUG_DROP(
710				"encryption configured, but RX "
711				"frame not encrypted (SA=%pM)\n",
712				hdr->addr2);
713			goto rx_dropped;
714		}
715	}
716
717#ifdef CONFIG_IEEE80211_DEBUG
718	if (crypt && !(fc & IEEE80211_FCTL_WEP) &&
719	    ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
720			struct eapol *eap = (struct eapol *)(skb->data +
721				24);
722			IEEE80211_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n",
723						eap_get_type(eap->type));
724	}
725#endif
726
727	if (crypt && !(fc & IEEE80211_FCTL_WEP) && !ieee->open_wep &&
728	    !ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
729		IEEE80211_DEBUG_DROP(
730			"dropped unencrypted RX data "
731			"frame from %pM"
732			" (drop_unencrypted=1)\n",
733			hdr->addr2);
734		goto rx_dropped;
735	}
736/*
737	if(ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
738		printk(KERN_WARNING "RX: IEEE802.1X EPAOL frame!\n");
739	}
740*/
741	/* skb: hdr + (possible reassembled) full plaintext payload */
742	payload = skb->data + hdrlen;
743	ethertype = (payload[6] << 8) | payload[7];
744
745
746	/* convert hdr + possible LLC headers into Ethernet header */
747	if (skb->len - hdrlen >= 8 &&
748	    ((memcmp(payload, rfc1042_header, SNAP_SIZE) == 0 &&
749	      ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
750	     memcmp(payload, bridge_tunnel_header, SNAP_SIZE) == 0)) {
751		/* remove RFC1042 or Bridge-Tunnel encapsulation and
752		 * replace EtherType */
753		skb_pull(skb, hdrlen + SNAP_SIZE);
754		memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
755		memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
756	} else {
757		u16 len;
758		/* Leave Ethernet header part of hdr and full payload */
759		skb_pull(skb, hdrlen);
760		len = htons(skb->len);
761		memcpy(skb_push(skb, 2), &len, 2);
762		memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
763		memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
764	}
765
766
767	stats->rx_packets++;
768	stats->rx_bytes += skb->len;
769
770	if (skb) {
771		skb->protocol = eth_type_trans(skb, dev);
772		memset(skb->cb, 0, sizeof(skb->cb));
773		skb->dev = dev;
774		skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */
775		ieee->last_rx_ps_time = jiffies;
776		netif_rx(skb);
777	}
778
779 rx_exit:
780	return 1;
781
782 rx_dropped:
783	stats->rx_dropped++;
784
785	/* Returning 0 indicates to caller that we have not handled the SKB--
786	 * so it is still allocated and can be used again by underlying
787	 * hardware as a DMA target */
788	return 0;
789}
790
791#define MGMT_FRAME_FIXED_PART_LENGTH		0x24
792
793static inline int ieee80211_is_ofdm_rate(u8 rate)
794{
795	switch (rate & ~IEEE80211_BASIC_RATE_MASK) {
796	case IEEE80211_OFDM_RATE_6MB:
797	case IEEE80211_OFDM_RATE_9MB:
798	case IEEE80211_OFDM_RATE_12MB:
799	case IEEE80211_OFDM_RATE_18MB:
800	case IEEE80211_OFDM_RATE_24MB:
801	case IEEE80211_OFDM_RATE_36MB:
802	case IEEE80211_OFDM_RATE_48MB:
803	case IEEE80211_OFDM_RATE_54MB:
804		return 1;
805	}
806        return 0;
807}
808
809static inline int ieee80211_SignalStrengthTranslate(
810	int  CurrSS
811	)
812{
813	int RetSS;
814
815	// Step 1. Scale mapping.
816	if(CurrSS >= 71 && CurrSS <= 100)
817	{
818		RetSS = 90 + ((CurrSS - 70) / 3);
819	}
820	else if(CurrSS >= 41 && CurrSS <= 70)
821	{
822		RetSS = 78 + ((CurrSS - 40) / 3);
823	}
824	else if(CurrSS >= 31 && CurrSS <= 40)
825	{
826		RetSS = 66 + (CurrSS - 30);
827	}
828	else if(CurrSS >= 21 && CurrSS <= 30)
829	{
830		RetSS = 54 + (CurrSS - 20);
831	}
832	else if(CurrSS >= 5 && CurrSS <= 20)
833	{
834		RetSS = 42 + (((CurrSS - 5) * 2) / 3);
835	}
836	else if(CurrSS == 4)
837	{
838		RetSS = 36;
839	}
840	else if(CurrSS == 3)
841	{
842		RetSS = 27;
843	}
844	else if(CurrSS == 2)
845	{
846		RetSS = 18;
847	}
848	else if(CurrSS == 1)
849	{
850		RetSS = 9;
851	}
852	else
853	{
854		RetSS = CurrSS;
855	}
856	//RT_TRACE(COMP_DBG, DBG_LOUD, ("##### After Mapping:  LastSS: %d, CurrSS: %d, RetSS: %d\n", LastSS, CurrSS, RetSS));
857
858	// Step 2. Smoothing.
859
860	//RT_TRACE(COMP_DBG, DBG_LOUD, ("$$$$$ After Smoothing:  LastSS: %d, CurrSS: %d, RetSS: %d\n", LastSS, CurrSS, RetSS));
861
862	return RetSS;
863}
864
865static inline void ieee80211_extract_country_ie(
866	struct ieee80211_device *ieee,
867	struct ieee80211_info_element *info_element,
868	struct ieee80211_network *network,
869	u8 * addr2
870)
871{
872	if(IS_DOT11D_ENABLE(ieee))
873	{
874		if(info_element->len!= 0)
875		{
876			memcpy(network->CountryIeBuf, info_element->data, info_element->len);
877			network->CountryIeLen = info_element->len;
878
879			if(!IS_COUNTRY_IE_VALID(ieee))
880			{
881				Dot11d_UpdateCountryIe(ieee, addr2, info_element->len, info_element->data);
882			}
883		}
884
885		//
886		// 070305, rcnjko: I update country IE watch dog here because
887		// some AP (e.g. Cisco 1242) don't include country IE in their
888		// probe response frame.
889		//
890		if(IS_EQUAL_CIE_SRC(ieee, addr2) )
891		{
892			UPDATE_CIE_WATCHDOG(ieee);
893		}
894	}
895
896}
897
898int
899ieee80211_TranslateToDbm(
900	unsigned char SignalStrengthIndex	// 0-100 index.
901	)
902{
903	unsigned char SignalPower; // in dBm.
904
905	// Translate to dBm (x=0.5y-95).
906	SignalPower = (int)SignalStrengthIndex * 7 / 10;
907	SignalPower -= 95;
908
909	return SignalPower;
910}
911inline int ieee80211_network_init(
912	struct ieee80211_device *ieee,
913	struct ieee80211_probe_response *beacon,
914	struct ieee80211_network *network,
915	struct ieee80211_rx_stats *stats)
916{
917#ifdef CONFIG_IEEE80211_DEBUG
918	char rates_str[64];
919	char *p;
920#endif
921	struct ieee80211_info_element *info_element;
922 	u16 left;
923	u8 i;
924	short offset;
925	u8 curRate = 0,hOpRate = 0,curRate_ex = 0;
926
927	/* Pull out fixed field data */
928	memcpy(network->bssid, beacon->header.addr3, ETH_ALEN);
929	network->capability = beacon->capability;
930	network->last_scanned = jiffies;
931	network->time_stamp[0] = beacon->time_stamp[0];
932	network->time_stamp[1] = beacon->time_stamp[1];
933	network->beacon_interval = beacon->beacon_interval;
934	/* Where to pull this? beacon->listen_interval;*/
935	network->listen_interval = 0x0A;
936	network->rates_len = network->rates_ex_len = 0;
937	network->last_associate = 0;
938	network->ssid_len = 0;
939	network->flags = 0;
940	network->atim_window = 0;
941	network->QoS_Enable = 0;
942//by amy 080312
943	network->HighestOperaRate = 0;
944//by amy 080312
945	network->Turbo_Enable = 0;
946	network->CountryIeLen = 0;
947	memset(network->CountryIeBuf, 0, MAX_IE_LEN);
948
949	if (stats->freq == IEEE80211_52GHZ_BAND) {
950		/* for A band (No DS info) */
951		network->channel = stats->received_channel;
952	} else
953		network->flags |= NETWORK_HAS_CCK;
954
955 	network->wpa_ie_len = 0;
956 	network->rsn_ie_len = 0;
957
958 	info_element = &beacon->info_element;
959	left = stats->len - ((void *)info_element - (void *)beacon);
960	while (left >= sizeof(struct ieee80211_info_element_hdr)) {
961		if (sizeof(struct ieee80211_info_element_hdr) + info_element->len > left) {
962			IEEE80211_DEBUG_SCAN("SCAN: parse failed: info_element->len + 2 > left : info_element->len+2=%d left=%d.\n",
963					     info_element->len + sizeof(struct ieee80211_info_element),
964					     left);
965			return 1;
966               	}
967
968		switch (info_element->id) {
969		case MFIE_TYPE_SSID:
970			if (ieee80211_is_empty_essid(info_element->data,
971						     info_element->len)) {
972				network->flags |= NETWORK_EMPTY_ESSID;
973				break;
974			}
975
976			network->ssid_len = min(info_element->len,
977						(u8)IW_ESSID_MAX_SIZE);
978			memcpy(network->ssid, info_element->data, network->ssid_len);
979        		if (network->ssid_len < IW_ESSID_MAX_SIZE)
980                		memset(network->ssid + network->ssid_len, 0,
981				       IW_ESSID_MAX_SIZE - network->ssid_len);
982
983			IEEE80211_DEBUG_SCAN("MFIE_TYPE_SSID: '%s' len=%d.\n",
984					     network->ssid, network->ssid_len);
985			break;
986
987		case MFIE_TYPE_RATES:
988#ifdef CONFIG_IEEE80211_DEBUG
989			p = rates_str;
990#endif
991			network->rates_len = min(info_element->len, MAX_RATES_LENGTH);
992			for (i = 0; i < network->rates_len; i++) {
993				network->rates[i] = info_element->data[i];
994				curRate = network->rates[i] & 0x7f;
995				if( hOpRate < curRate )
996					hOpRate = curRate;
997#ifdef CONFIG_IEEE80211_DEBUG
998				p += snprintf(p, sizeof(rates_str) - (p - rates_str), "%02X ", network->rates[i]);
999#endif
1000				if (ieee80211_is_ofdm_rate(info_element->data[i])) {
1001					network->flags |= NETWORK_HAS_OFDM;
1002					if (info_element->data[i] &
1003					    IEEE80211_BASIC_RATE_MASK)
1004						network->flags &=
1005							~NETWORK_HAS_CCK;
1006				}
1007			}
1008
1009			IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES: '%s' (%d)\n",
1010					     rates_str, network->rates_len);
1011			break;
1012
1013		case MFIE_TYPE_RATES_EX:
1014#ifdef CONFIG_IEEE80211_DEBUG
1015			p = rates_str;
1016#endif
1017			network->rates_ex_len = min(info_element->len, MAX_RATES_EX_LENGTH);
1018			for (i = 0; i < network->rates_ex_len; i++) {
1019				network->rates_ex[i] = info_element->data[i];
1020				curRate_ex = network->rates_ex[i] & 0x7f;
1021				if( hOpRate < curRate_ex )
1022					hOpRate = curRate_ex;
1023#ifdef CONFIG_IEEE80211_DEBUG
1024				p += snprintf(p, sizeof(rates_str) - (p - rates_str), "%02X ", network->rates[i]);
1025#endif
1026				if (ieee80211_is_ofdm_rate(info_element->data[i])) {
1027					network->flags |= NETWORK_HAS_OFDM;
1028					if (info_element->data[i] &
1029					    IEEE80211_BASIC_RATE_MASK)
1030						network->flags &=
1031							~NETWORK_HAS_CCK;
1032				}
1033			}
1034
1035			IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES_EX: '%s' (%d)\n",
1036					     rates_str, network->rates_ex_len);
1037			break;
1038
1039		case MFIE_TYPE_DS_SET:
1040  			IEEE80211_DEBUG_SCAN("MFIE_TYPE_DS_SET: %d\n",
1041					     info_element->data[0]);
1042			if (stats->freq == IEEE80211_24GHZ_BAND)
1043				network->channel = info_element->data[0];
1044			break;
1045
1046	 	case MFIE_TYPE_FH_SET:
1047  			IEEE80211_DEBUG_SCAN("MFIE_TYPE_FH_SET: ignored\n");
1048			break;
1049
1050		case MFIE_TYPE_CF_SET:
1051			IEEE80211_DEBUG_SCAN("MFIE_TYPE_CF_SET: ignored\n");
1052			break;
1053
1054		case MFIE_TYPE_TIM:
1055
1056			if(info_element->len < 4)
1057				break;
1058
1059			network->dtim_period = info_element->data[1];
1060
1061			if(ieee->state != IEEE80211_LINKED)
1062				break;
1063
1064			network->last_dtim_sta_time[0] = jiffies;
1065			network->last_dtim_sta_time[1] = stats->mac_time[1];
1066
1067			network->dtim_data = IEEE80211_DTIM_VALID;
1068
1069			if(info_element->data[0] != 0)
1070				break;
1071
1072			if(info_element->data[2] & 1)
1073				network->dtim_data |= IEEE80211_DTIM_MBCAST;
1074
1075			offset = (info_element->data[2] >> 1)*2;
1076
1077			//printk("offset1:%x aid:%x\n",offset, ieee->assoc_id);
1078
1079			/* add and modified for ps 2008.1.22 */
1080			if(ieee->assoc_id < 8*offset ||
1081				ieee->assoc_id > 8*(offset + info_element->len -3)) {
1082				break;
1083			}
1084
1085			offset = (ieee->assoc_id/8) - offset;// + ((aid % 8)? 0 : 1) ;
1086
1087		//	printk("offset:%x data:%x, ucast:%d\n", offset,
1088			//	info_element->data[3+offset] ,
1089			//	info_element->data[3+offset] & (1<<(ieee->assoc_id%8)));
1090
1091			if(info_element->data[3+offset] & (1<<(ieee->assoc_id%8))) {
1092				network->dtim_data |= IEEE80211_DTIM_UCAST;
1093			}
1094			break;
1095
1096		case MFIE_TYPE_IBSS_SET:
1097			IEEE80211_DEBUG_SCAN("MFIE_TYPE_IBSS_SET: ignored\n");
1098			break;
1099
1100		case MFIE_TYPE_CHALLENGE:
1101			IEEE80211_DEBUG_SCAN("MFIE_TYPE_CHALLENGE: ignored\n");
1102			break;
1103
1104		case MFIE_TYPE_GENERIC:
1105			//nic is 87B
1106			IEEE80211_DEBUG_SCAN("MFIE_TYPE_GENERIC: %d bytes\n",
1107					     info_element->len);
1108			if (info_element->len >= 4  &&
1109			    info_element->data[0] == 0x00 &&
1110			    info_element->data[1] == 0x50 &&
1111			    info_element->data[2] == 0xf2 &&
1112			    info_element->data[3] == 0x01) {
1113				network->wpa_ie_len = min(info_element->len + 2,
1114							 MAX_WPA_IE_LEN);
1115				memcpy(network->wpa_ie, info_element,
1116				       network->wpa_ie_len);
1117			}
1118
1119			if (info_element->len == 7 &&
1120			    info_element->data[0] == 0x00 &&
1121			    info_element->data[1] == 0xe0 &&
1122			    info_element->data[2] == 0x4c &&
1123			    info_element->data[3] == 0x01 &&
1124			    info_element->data[4] == 0x02) {
1125				network->Turbo_Enable = 1;
1126			}
1127			if (1 == stats->nic_type) {//nic 87
1128				break;
1129			}
1130
1131			if (info_element->len >= 5  &&
1132			    info_element->data[0] == 0x00 &&
1133			    info_element->data[1] == 0x50 &&
1134			    info_element->data[2] == 0xf2 &&
1135			    info_element->data[3] == 0x02 &&
1136			    info_element->data[4] == 0x00) {
1137				//printk(KERN_WARNING "wmm info updated: %x\n", info_element->data[6]);
1138				//WMM Information Element
1139				network->wmm_info = info_element->data[6];
1140				network->QoS_Enable = 1;
1141			}
1142
1143			if (info_element->len >= 8  &&
1144			    info_element->data[0] == 0x00 &&
1145			    info_element->data[1] == 0x50 &&
1146			    info_element->data[2] == 0xf2 &&
1147			    info_element->data[3] == 0x02 &&
1148			    info_element->data[4] == 0x01) {
1149				// Not care about version at present.
1150				//WMM Information Element
1151				//printk(KERN_WARNING "wmm info&param updated: %x\n", info_element->data[6]);
1152				network->wmm_info = info_element->data[6];
1153				//WMM Parameter Element
1154				memcpy(network->wmm_param, (u8 *)(info_element->data + 8),(info_element->len - 8));
1155				network->QoS_Enable = 1;
1156			}
1157			break;
1158
1159		case MFIE_TYPE_RSN:
1160			IEEE80211_DEBUG_SCAN("MFIE_TYPE_RSN: %d bytes\n",
1161					     info_element->len);
1162			network->rsn_ie_len = min(info_element->len + 2,
1163						 MAX_WPA_IE_LEN);
1164			memcpy(network->rsn_ie, info_element,
1165			       network->rsn_ie_len);
1166			break;
1167		case MFIE_TYPE_COUNTRY:
1168			IEEE80211_DEBUG_SCAN("MFIE_TYPE_COUNTRY: %d bytes\n",
1169					     info_element->len);
1170//			printk("=====>Receive <%s> Country IE\n",network->ssid);
1171			ieee80211_extract_country_ie(ieee, info_element, network, beacon->header.addr2);
1172			break;
1173		default:
1174			IEEE80211_DEBUG_SCAN("unsupported IE %d\n",
1175					     info_element->id);
1176                        break;
1177  		}
1178
1179		left -= sizeof(struct ieee80211_info_element_hdr) +
1180			info_element->len;
1181		info_element = (struct ieee80211_info_element *)
1182                	&info_element->data[info_element->len];
1183  	}
1184//by amy 080312
1185	network->HighestOperaRate = hOpRate;
1186//by amy 080312
1187	network->mode = 0;
1188	if (stats->freq == IEEE80211_52GHZ_BAND)
1189		network->mode = IEEE_A;
1190	else {
1191		if (network->flags & NETWORK_HAS_OFDM)
1192			network->mode |= IEEE_G;
1193		if (network->flags & NETWORK_HAS_CCK)
1194			network->mode |= IEEE_B;
1195	}
1196
1197	if (network->mode == 0) {
1198		IEEE80211_DEBUG_SCAN("Filtered out '%s (%pM)' "
1199				     "network.\n",
1200				     escape_essid(network->ssid,
1201						  network->ssid_len),
1202				     network->bssid);
1203		return 1;
1204	}
1205
1206	if (ieee80211_is_empty_essid(network->ssid, network->ssid_len))
1207		network->flags |= NETWORK_EMPTY_ESSID;
1208
1209	stats->signal = ieee80211_TranslateToDbm(stats->signalstrength);
1210	//stats->noise = stats->signal - stats->noise;
1211	stats->noise = ieee80211_TranslateToDbm(100 - stats->signalstrength) - 25;
1212	memcpy(&network->stats, stats, sizeof(network->stats));
1213
1214	return 0;
1215}
1216
1217static inline int is_same_network(struct ieee80211_network *src,
1218				  struct ieee80211_network *dst,
1219				  struct ieee80211_device * ieee)
1220{
1221	/* A network is only a duplicate if the channel, BSSID, ESSID
1222	 * and the capability field (in particular IBSS and BSS) all match.
1223	 * We treat all <hidden> with the same BSSID and channel
1224	 * as one network */
1225	return (((src->ssid_len == dst->ssid_len) || (ieee->iw_mode == IW_MODE_INFRA)) &&  //YJ,mod,080819,for hidden ap
1226		//((src->ssid_len == dst->ssid_len) &&
1227		(src->channel == dst->channel) &&
1228		!memcmp(src->bssid, dst->bssid, ETH_ALEN) &&
1229		(!memcmp(src->ssid, dst->ssid, src->ssid_len) || (ieee->iw_mode == IW_MODE_INFRA)) && //YJ,mod,080819,for hidden ap
1230		//!memcmp(src->ssid, dst->ssid, src->ssid_len) &&
1231		((src->capability & WLAN_CAPABILITY_IBSS) ==
1232		(dst->capability & WLAN_CAPABILITY_IBSS)) &&
1233		((src->capability & WLAN_CAPABILITY_BSS) ==
1234		(dst->capability & WLAN_CAPABILITY_BSS)));
1235}
1236
1237inline void update_network(struct ieee80211_network *dst,
1238				  struct ieee80211_network *src)
1239{
1240	unsigned char quality = src->stats.signalstrength;
1241	unsigned char signal = 0;
1242	unsigned char noise = 0;
1243        if(dst->stats.signalstrength > 0) {
1244                quality = (dst->stats.signalstrength * 5 + src->stats.signalstrength + 5)/6;
1245        }
1246	signal = ieee80211_TranslateToDbm(quality);
1247	//noise = signal - src->stats.noise;
1248	if(dst->stats.noise > 0)
1249		noise = (dst->stats.noise * 5 + src->stats.noise)/6;
1250        //if(strcmp(dst->ssid, "linksys_lzm000") == 0)
1251//	printk("ssid:%s, quality:%d, signal:%d\n", dst->ssid, quality, signal);
1252	memcpy(&dst->stats, &src->stats, sizeof(struct ieee80211_rx_stats));
1253	dst->stats.signalstrength = quality;
1254	dst->stats.signal = signal;
1255//	printk("==================>stats.signal is %d\n",dst->stats.signal);
1256	dst->stats.noise = noise;
1257
1258
1259	dst->capability = src->capability;
1260	memcpy(dst->rates, src->rates, src->rates_len);
1261	dst->rates_len = src->rates_len;
1262	memcpy(dst->rates_ex, src->rates_ex, src->rates_ex_len);
1263	dst->rates_ex_len = src->rates_ex_len;
1264	dst->HighestOperaRate= src->HighestOperaRate;
1265	//printk("==========>in %s: src->ssid is %s,chan is %d\n",__func__,src->ssid,src->channel);
1266
1267	//YJ,add,080819,for hidden ap
1268	if(src->ssid_len > 0)
1269	{
1270		//if(src->ssid_len == 13)
1271		//	printk("=====================>>>>>>>> Dst ssid: %s Src ssid: %s\n", dst->ssid, src->ssid);
1272		memset(dst->ssid, 0, dst->ssid_len);
1273		dst->ssid_len = src->ssid_len;
1274		memcpy(dst->ssid, src->ssid, src->ssid_len);
1275	}
1276	//YJ,add,080819,for hidden ap,end
1277
1278	dst->channel = src->channel;
1279	dst->mode = src->mode;
1280	dst->flags = src->flags;
1281	dst->time_stamp[0] = src->time_stamp[0];
1282	dst->time_stamp[1] = src->time_stamp[1];
1283
1284	dst->beacon_interval = src->beacon_interval;
1285	dst->listen_interval = src->listen_interval;
1286	dst->atim_window = src->atim_window;
1287	dst->dtim_period = src->dtim_period;
1288	dst->dtim_data = src->dtim_data;
1289	dst->last_dtim_sta_time[0] = src->last_dtim_sta_time[0];
1290	dst->last_dtim_sta_time[1] = src->last_dtim_sta_time[1];
1291//	printk("update:%s, dtim_period:%x, dtim_data:%x\n", src->ssid, src->dtim_period, src->dtim_data);
1292	memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len);
1293	dst->wpa_ie_len = src->wpa_ie_len;
1294	memcpy(dst->rsn_ie, src->rsn_ie, src->rsn_ie_len);
1295	dst->rsn_ie_len = src->rsn_ie_len;
1296
1297	dst->last_scanned = jiffies;
1298	/* dst->last_associate is not overwritten */
1299// disable QoS process now, added by David 2006/7/25
1300	dst->wmm_info = src->wmm_info; //sure to exist in beacon or probe response frame.
1301/*
1302	if((dst->wmm_info^src->wmm_info)&0x0f) {//Param Set Count change, update Parameter
1303	  memcpy(dst->wmm_param, src->wmm_param, IEEE80211_AC_PRAM_LEN);
1304	}
1305*/
1306	if(src->wmm_param[0].ac_aci_acm_aifsn|| \
1307	   src->wmm_param[1].ac_aci_acm_aifsn|| \
1308	   src->wmm_param[2].ac_aci_acm_aifsn|| \
1309	   src->wmm_param[3].ac_aci_acm_aifsn) {
1310	  memcpy(dst->wmm_param, src->wmm_param, WME_AC_PRAM_LEN);
1311	}
1312	dst->QoS_Enable = src->QoS_Enable;
1313	dst->SignalStrength = src->SignalStrength;
1314	dst->Turbo_Enable = src->Turbo_Enable;
1315	dst->CountryIeLen = src->CountryIeLen;
1316	memcpy(dst->CountryIeBuf, src->CountryIeBuf, src->CountryIeLen);
1317}
1318
1319
1320inline void ieee80211_process_probe_response(
1321	struct ieee80211_device *ieee,
1322	struct ieee80211_probe_response *beacon,
1323	struct ieee80211_rx_stats *stats)
1324{
1325	struct ieee80211_network network;
1326	struct ieee80211_network *target;
1327	struct ieee80211_network *oldest = NULL;
1328#ifdef CONFIG_IEEE80211_DEBUG
1329	struct ieee80211_info_element *info_element = &beacon->info_element;
1330#endif
1331	unsigned long flags;
1332	short renew;
1333	u8 wmm_info;
1334	u8 is_beacon = (WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == IEEE80211_STYPE_BEACON)? 1:0;  //YJ,add,080819,for hidden ap
1335
1336	memset(&network, 0, sizeof(struct ieee80211_network));
1337
1338	IEEE80211_DEBUG_SCAN(
1339		"'%s' (%pM): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
1340		escape_essid(info_element->data, info_element->len),
1341		beacon->header.addr3,
1342		(beacon->capability & (1<<0xf)) ? '1' : '0',
1343		(beacon->capability & (1<<0xe)) ? '1' : '0',
1344		(beacon->capability & (1<<0xd)) ? '1' : '0',
1345		(beacon->capability & (1<<0xc)) ? '1' : '0',
1346		(beacon->capability & (1<<0xb)) ? '1' : '0',
1347		(beacon->capability & (1<<0xa)) ? '1' : '0',
1348		(beacon->capability & (1<<0x9)) ? '1' : '0',
1349		(beacon->capability & (1<<0x8)) ? '1' : '0',
1350		(beacon->capability & (1<<0x7)) ? '1' : '0',
1351		(beacon->capability & (1<<0x6)) ? '1' : '0',
1352		(beacon->capability & (1<<0x5)) ? '1' : '0',
1353		(beacon->capability & (1<<0x4)) ? '1' : '0',
1354		(beacon->capability & (1<<0x3)) ? '1' : '0',
1355		(beacon->capability & (1<<0x2)) ? '1' : '0',
1356		(beacon->capability & (1<<0x1)) ? '1' : '0',
1357		(beacon->capability & (1<<0x0)) ? '1' : '0');
1358
1359	if (ieee80211_network_init(ieee, beacon, &network, stats)) {
1360		IEEE80211_DEBUG_SCAN("Dropped '%s' (%pM) via %s.\n",
1361				     escape_essid(info_element->data,
1362						  info_element->len),
1363				     beacon->header.addr3,
1364				     WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
1365				     IEEE80211_STYPE_PROBE_RESP ?
1366				     "PROBE RESPONSE" : "BEACON");
1367		return;
1368	}
1369
1370	// For Asus EeePc request,
1371	// (1) if wireless adapter receive get any 802.11d country code in AP beacon,
1372	//	   wireless adapter should follow the country code.
1373	// (2)  If there is no any country code in beacon,
1374	//       then wireless adapter should do active scan from ch1~11 and
1375	//       passive scan from ch12~14
1376	if(ieee->bGlobalDomain)
1377	{
1378		if (WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == IEEE80211_STYPE_PROBE_RESP)
1379		{
1380			// Case 1: Country code
1381			if(IS_COUNTRY_IE_VALID(ieee) )
1382			{
1383				if( !IsLegalChannel(ieee, network.channel) )
1384				{
1385					printk("GetScanInfo(): For Country code, filter probe response at channel(%d).\n", network.channel);
1386					return;
1387				}
1388			}
1389			// Case 2: No any country code.
1390			else
1391			{
1392				// Filter over channel ch12~14
1393				if(network.channel > 11)
1394				{
1395					printk("GetScanInfo(): For Global Domain, filter probe response at channel(%d).\n", network.channel);
1396					return;
1397				}
1398			}
1399		}
1400		else
1401		{
1402			// Case 1: Country code
1403			if(IS_COUNTRY_IE_VALID(ieee) )
1404			{
1405				if( !IsLegalChannel(ieee, network.channel) )
1406				{
1407					printk("GetScanInfo(): For Country code, filter beacon at channel(%d).\n",network.channel);
1408					return;
1409				}
1410			}
1411			// Case 2: No any country code.
1412			else
1413			{
1414				// Filter over channel ch12~14
1415				if(network.channel > 14)
1416				{
1417					printk("GetScanInfo(): For Global Domain, filter beacon at channel(%d).\n",network.channel);
1418					return;
1419				}
1420			}
1421		}
1422	}
1423	/* The network parsed correctly -- so now we scan our known networks
1424	 * to see if we can find it in our list.
1425	 *
1426	 * NOTE:  This search is definitely not optimized.  Once its doing
1427	 *        the "right thing" we'll optimize it for efficiency if
1428	 *        necessary */
1429
1430	/* Search for this entry in the list and update it if it is
1431	 * already there. */
1432
1433	spin_lock_irqsave(&ieee->lock, flags);
1434
1435	if(is_same_network(&ieee->current_network, &network, ieee)) {
1436		wmm_info = ieee->current_network.wmm_info;
1437		//YJ,add,080819,for hidden ap
1438		if(is_beacon == 0)
1439			network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & ieee->current_network.flags);
1440		else if(ieee->state == IEEE80211_LINKED)
1441			ieee->NumRxBcnInPeriod++;
1442		//YJ,add,080819,for hidden ap,end
1443		//printk("====>network.ssid=%s cur_ssid=%s\n", network.ssid, ieee->current_network.ssid);
1444		update_network(&ieee->current_network, &network);
1445	}
1446
1447	list_for_each_entry(target, &ieee->network_list, list) {
1448		if (is_same_network(target, &network, ieee))
1449			break;
1450		if ((oldest == NULL) ||
1451		    (target->last_scanned < oldest->last_scanned))
1452			oldest = target;
1453	}
1454
1455	/* If we didn't find a match, then get a new network slot to initialize
1456	 * with this beacon's information */
1457	if (&target->list == &ieee->network_list) {
1458		if (list_empty(&ieee->network_free_list)) {
1459			/* If there are no more slots, expire the oldest */
1460			list_del(&oldest->list);
1461			target = oldest;
1462			IEEE80211_DEBUG_SCAN("Expired '%s' (%pM) from "
1463					     "network list.\n",
1464					     escape_essid(target->ssid,
1465							  target->ssid_len),
1466					     target->bssid);
1467		} else {
1468			/* Otherwise just pull from the free list */
1469			target = list_entry(ieee->network_free_list.next,
1470					    struct ieee80211_network, list);
1471			list_del(ieee->network_free_list.next);
1472		}
1473
1474
1475#ifdef CONFIG_IEEE80211_DEBUG
1476		IEEE80211_DEBUG_SCAN("Adding '%s' (%pM) via %s.\n",
1477				     escape_essid(network.ssid,
1478						  network.ssid_len),
1479				     network.bssid,
1480				     WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
1481				     IEEE80211_STYPE_PROBE_RESP ?
1482				     "PROBE RESPONSE" : "BEACON");
1483#endif
1484
1485		memcpy(target, &network, sizeof(*target));
1486		list_add_tail(&target->list, &ieee->network_list);
1487	} else {
1488		IEEE80211_DEBUG_SCAN("Updating '%s' (%pM) via %s.\n",
1489				     escape_essid(target->ssid,
1490						  target->ssid_len),
1491				     target->bssid,
1492				     WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
1493				     IEEE80211_STYPE_PROBE_RESP ?
1494				     "PROBE RESPONSE" : "BEACON");
1495
1496		/* we have an entry and we are going to update it. But this entry may
1497		 * be already expired. In this case we do the same as we found a new
1498		 * net and call the new_net handler
1499		 */
1500		renew = !time_after(target->last_scanned + ieee->scan_age, jiffies);
1501		//YJ,add,080819,for hidden ap
1502		if(is_beacon == 0)
1503			network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & target->flags);
1504		//if(strncmp(network.ssid, "linksys-c",9) == 0)
1505		//	printk("====>2 network.ssid=%s FLAG=%d target.ssid=%s FLAG=%d\n", network.ssid, network.flags, target->ssid, target->flags);
1506		if(((network.flags & NETWORK_EMPTY_ESSID) == NETWORK_EMPTY_ESSID) \
1507		    && (((network.ssid_len > 0) && (strncmp(target->ssid, network.ssid, network.ssid_len)))\
1508		    ||((ieee->current_network.ssid_len == network.ssid_len)&&(strncmp(ieee->current_network.ssid, network.ssid, network.ssid_len) == 0)&&(ieee->state == IEEE80211_NOLINK))))
1509			renew = 1;
1510		//YJ,add,080819,for hidden ap,end
1511		update_network(target, &network);
1512	}
1513
1514	spin_unlock_irqrestore(&ieee->lock, flags);
1515}
1516
1517void ieee80211_rx_mgt(struct ieee80211_device *ieee,
1518		      struct ieee80211_hdr_4addr *header,
1519		      struct ieee80211_rx_stats *stats)
1520{
1521	switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
1522
1523	case IEEE80211_STYPE_BEACON:
1524		IEEE80211_DEBUG_MGMT("received BEACON (%d)\n",
1525				     WLAN_FC_GET_STYPE(header->frame_ctl));
1526		IEEE80211_DEBUG_SCAN("Beacon\n");
1527		ieee80211_process_probe_response(
1528			ieee, (struct ieee80211_probe_response *)header, stats);
1529		break;
1530
1531	case IEEE80211_STYPE_PROBE_RESP:
1532		IEEE80211_DEBUG_MGMT("received PROBE RESPONSE (%d)\n",
1533				     WLAN_FC_GET_STYPE(header->frame_ctl));
1534		IEEE80211_DEBUG_SCAN("Probe response\n");
1535		ieee80211_process_probe_response(
1536			ieee, (struct ieee80211_probe_response *)header, stats);
1537		break;
1538	}
1539}
1540