1 // SPDX-License-Identifier: GPL-2.0
3 * Original code based Host AP (software wireless LAN access point) driver
4 * for Intersil Prism2/2.5/3 - hostap.o module, common routines
6 * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
8 * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
9 * Copyright (c) 2004, Intel Corporation
10 ******************************************************************************
12 Few modifications for Realtek's Wi-Fi drivers by
13 Andrea Merello <andrea.merello@gmail.com>
15 A special thanks goes to Realtek for their support !
17 ******************************************************************************/
20 #include <linux/compiler.h>
21 #include <linux/errno.h>
22 #include <linux/if_arp.h>
23 #include <linux/in6.h>
26 #include <linux/kernel.h>
27 #include <linux/module.h>
28 #include <linux/netdevice.h>
29 #include <linux/pci.h>
30 #include <linux/proc_fs.h>
31 #include <linux/skbuff.h>
32 #include <linux/slab.h>
33 #include <linux/tcp.h>
34 #include <linux/types.h>
35 #include <linux/wireless.h>
36 #include <linux/etherdevice.h>
37 #include <linux/uaccess.h>
38 #include <linux/ctype.h>
40 #include "ieee80211.h"
42 static inline void ieee80211_monitor_rx(struct ieee80211_device
*ieee
,
44 struct ieee80211_rx_stats
*rx_stats
)
46 struct rtl_80211_hdr_4addr
*hdr
= (struct rtl_80211_hdr_4addr
*)skb
->data
;
47 u16 fc
= le16_to_cpu(hdr
->frame_ctl
);
50 skb_reset_mac_header(skb
);
52 skb_pull(skb
, ieee80211_get_hdrlen(fc
));
53 skb
->pkt_type
= PACKET_OTHERHOST
;
54 skb
->protocol
= htons(ETH_P_80211_RAW
);
55 memset(skb
->cb
, 0, sizeof(skb
->cb
));
60 /* Called only as a tasklet (software IRQ) */
61 static struct ieee80211_frag_entry
*
62 ieee80211_frag_cache_find(struct ieee80211_device
*ieee
, unsigned int seq
,
63 unsigned int frag
, u8 tid
, u8
*src
, u8
*dst
)
65 struct ieee80211_frag_entry
*entry
;
68 for (i
= 0; i
< IEEE80211_FRAG_CACHE_LEN
; i
++) {
69 entry
= &ieee
->frag_cache
[tid
][i
];
71 time_after(jiffies
, entry
->first_frag_time
+ 2 * HZ
)) {
73 "expiring fragment cache entry "
74 "seq=%u last_frag=%u\n",
75 entry
->seq
, entry
->last_frag
);
76 dev_kfree_skb_any(entry
->skb
);
80 if (entry
->skb
&& entry
->seq
== seq
&&
81 (entry
->last_frag
+ 1 == frag
|| frag
== -1) &&
82 memcmp(entry
->src_addr
, src
, ETH_ALEN
) == 0 &&
83 memcmp(entry
->dst_addr
, dst
, ETH_ALEN
) == 0)
90 /* Called only as a tasklet (software IRQ) */
91 static struct sk_buff
*
92 ieee80211_frag_cache_get(struct ieee80211_device
*ieee
,
93 struct rtl_80211_hdr_4addr
*hdr
)
95 struct sk_buff
*skb
= NULL
;
96 u16 fc
= le16_to_cpu(hdr
->frame_ctl
);
97 u16 sc
= le16_to_cpu(hdr
->seq_ctl
);
98 unsigned int frag
= WLAN_GET_SEQ_FRAG(sc
);
99 unsigned int seq
= WLAN_GET_SEQ_SEQ(sc
);
100 struct ieee80211_frag_entry
*entry
;
101 struct rtl_80211_hdr_3addrqos
*hdr_3addrqos
;
102 struct rtl_80211_hdr_4addrqos
*hdr_4addrqos
;
105 if (((fc
& IEEE80211_FCTL_DSTODS
) == IEEE80211_FCTL_DSTODS
) && IEEE80211_QOS_HAS_SEQ(fc
)) {
106 hdr_4addrqos
= (struct rtl_80211_hdr_4addrqos
*)hdr
;
107 tid
= le16_to_cpu(hdr_4addrqos
->qos_ctl
) & IEEE80211_QCTL_TID
;
110 } else if (IEEE80211_QOS_HAS_SEQ(fc
)) {
111 hdr_3addrqos
= (struct rtl_80211_hdr_3addrqos
*)hdr
;
112 tid
= le16_to_cpu(hdr_3addrqos
->qos_ctl
) & IEEE80211_QCTL_TID
;
120 /* Reserve enough space to fit maximum frame length */
121 skb
= dev_alloc_skb(ieee
->dev
->mtu
+
122 sizeof(struct rtl_80211_hdr_4addr
) +
127 (IEEE80211_QOS_HAS_SEQ(fc
) ? 2 : 0) /* QOS Control */);
131 entry
= &ieee
->frag_cache
[tid
][ieee
->frag_next_idx
[tid
]];
132 ieee
->frag_next_idx
[tid
]++;
133 if (ieee
->frag_next_idx
[tid
] >= IEEE80211_FRAG_CACHE_LEN
)
134 ieee
->frag_next_idx
[tid
] = 0;
137 dev_kfree_skb_any(entry
->skb
);
139 entry
->first_frag_time
= jiffies
;
141 entry
->last_frag
= frag
;
143 memcpy(entry
->src_addr
, hdr
->addr2
, ETH_ALEN
);
144 memcpy(entry
->dst_addr
, hdr
->addr1
, ETH_ALEN
);
146 /* received a fragment of a frame for which the head fragment
147 * should have already been received */
148 entry
= ieee80211_frag_cache_find(ieee
, seq
, frag
, tid
, hdr
->addr2
,
151 entry
->last_frag
= frag
;
160 /* Called only as a tasklet (software IRQ) */
161 static int ieee80211_frag_cache_invalidate(struct ieee80211_device
*ieee
,
162 struct rtl_80211_hdr_4addr
*hdr
)
164 u16 fc
= le16_to_cpu(hdr
->frame_ctl
);
165 u16 sc
= le16_to_cpu(hdr
->seq_ctl
);
166 unsigned int seq
= WLAN_GET_SEQ_SEQ(sc
);
167 struct ieee80211_frag_entry
*entry
;
168 struct rtl_80211_hdr_3addrqos
*hdr_3addrqos
;
169 struct rtl_80211_hdr_4addrqos
*hdr_4addrqos
;
172 if (((fc
& IEEE80211_FCTL_DSTODS
) == IEEE80211_FCTL_DSTODS
) && IEEE80211_QOS_HAS_SEQ(fc
)) {
173 hdr_4addrqos
= (struct rtl_80211_hdr_4addrqos
*)hdr
;
174 tid
= le16_to_cpu(hdr_4addrqos
->qos_ctl
) & IEEE80211_QCTL_TID
;
177 } else if (IEEE80211_QOS_HAS_SEQ(fc
)) {
178 hdr_3addrqos
= (struct rtl_80211_hdr_3addrqos
*)hdr
;
179 tid
= le16_to_cpu(hdr_3addrqos
->qos_ctl
) & IEEE80211_QCTL_TID
;
186 entry
= ieee80211_frag_cache_find(ieee
, seq
, -1, tid
, hdr
->addr2
,
190 IEEE80211_DEBUG_FRAG(
191 "could not invalidate fragment cache "
192 "entry (seq=%u)\n", seq
);
202 /* ieee80211_rx_frame_mgtmt
204 * Responsible for handling management control frames
206 * Called by ieee80211_rx */
208 ieee80211_rx_frame_mgmt(struct ieee80211_device
*ieee
, struct sk_buff
*skb
,
209 struct ieee80211_rx_stats
*rx_stats
, u16 type
,
212 /* On the struct stats definition there is written that
213 * this is not mandatory.... but seems that the probe
214 * response parser uses it
216 struct rtl_80211_hdr_3addr
*hdr
= (struct rtl_80211_hdr_3addr
*)skb
->data
;
218 rx_stats
->len
= skb
->len
;
219 ieee80211_rx_mgt(ieee
, (struct rtl_80211_hdr_4addr
*)skb
->data
, rx_stats
);
220 /* if ((ieee->state == IEEE80211_LINKED) && (memcmp(hdr->addr3, ieee->current_network.bssid, ETH_ALEN))) */
221 if ((memcmp(hdr
->addr1
, ieee
->dev
->dev_addr
, ETH_ALEN
))) {
222 /* use ADDR1 to perform address matching for Management frames */
223 dev_kfree_skb_any(skb
);
227 ieee80211_rx_frame_softmac(ieee
, skb
, rx_stats
, type
, stype
);
229 dev_kfree_skb_any(skb
);
234 if (ieee
->iw_mode
== IW_MODE_MASTER
) {
235 netdev_dbg(ieee
->dev
, "Master mode not yet supported.\n");
238 hostap_update_sta_ps(ieee, (struct hostap_ieee80211_hdr_4addr *)
242 if (ieee
->hostapd
&& type
== IEEE80211_TYPE_MGMT
) {
243 if (stype
== WLAN_FC_STYPE_BEACON
&&
244 ieee
->iw_mode
== IW_MODE_MASTER
) {
245 struct sk_buff
*skb2
;
246 /* Process beacon frames also in kernel driver to
247 * update STA(AP) table statistics */
248 skb2
= skb_clone(skb
, GFP_ATOMIC
);
250 hostap_rx(skb2
->dev
, skb2
, rx_stats
);
253 /* send management frames to the user space daemon for
255 ieee
->apdevstats
.rx_packets
++;
256 ieee
->apdevstats
.rx_bytes
+= skb
->len
;
257 prism2_rx_80211(ieee
->apdev
, skb
, rx_stats
, PRISM2_RX_MGMT
);
261 if (ieee
->iw_mode
== IW_MODE_MASTER
) {
262 if (type
!= WLAN_FC_TYPE_MGMT
&& type
!= WLAN_FC_TYPE_CTRL
) {
263 netdev_dbg(skb
->dev
, "unknown management frame "
264 "(type=0x%02x, stype=0x%02x) dropped\n",
269 hostap_rx(skb
->dev
, skb
, rx_stats
);
273 netdev_dbg(skb
->dev
, "hostap_rx_frame_mgmt: management frame "
274 "received in non-Host AP mode\n");
281 /* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
282 /* Ethernet-II snap header (RFC1042 for most EtherTypes) */
283 static unsigned char rfc1042_header
[] = {
284 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
285 /* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
286 static unsigned char bridge_tunnel_header
[] = {
287 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
288 /* No encapsulation header if EtherType < 0x600 (=length) */
290 /* Called by ieee80211_rx_frame_decrypt */
291 static int ieee80211_is_eapol_frame(struct ieee80211_device
*ieee
,
292 struct sk_buff
*skb
, size_t hdrlen
)
294 struct net_device
*dev
= ieee
->dev
;
296 struct rtl_80211_hdr_4addr
*hdr
;
302 hdr
= (struct rtl_80211_hdr_4addr
*)skb
->data
;
303 fc
= le16_to_cpu(hdr
->frame_ctl
);
305 /* check that the frame is unicast frame to us */
306 if ((fc
& (IEEE80211_FCTL_TODS
| IEEE80211_FCTL_FROMDS
)) ==
307 IEEE80211_FCTL_TODS
&&
308 memcmp(hdr
->addr1
, dev
->dev_addr
, ETH_ALEN
) == 0 &&
309 memcmp(hdr
->addr3
, dev
->dev_addr
, ETH_ALEN
) == 0) {
310 /* ToDS frame with own addr BSSID and DA */
311 } else if ((fc
& (IEEE80211_FCTL_TODS
| IEEE80211_FCTL_FROMDS
)) ==
312 IEEE80211_FCTL_FROMDS
&&
313 memcmp(hdr
->addr1
, dev
->dev_addr
, ETH_ALEN
) == 0) {
314 /* FromDS frame with own addr as DA */
318 if (skb
->len
< 24 + 8)
321 /* check for port access entity Ethernet type */
322 // pos = skb->data + 24;
323 pos
= skb
->data
+ hdrlen
;
324 ethertype
= (pos
[6] << 8) | pos
[7];
325 if (ethertype
== ETH_P_PAE
)
331 /* Called only as a tasklet (software IRQ), by ieee80211_rx */
333 ieee80211_rx_frame_decrypt(struct ieee80211_device
*ieee
, struct sk_buff
*skb
,
334 struct ieee80211_crypt_data
*crypt
)
336 struct rtl_80211_hdr_4addr
*hdr
;
339 if (!crypt
|| !crypt
->ops
->decrypt_mpdu
)
341 if (ieee
->hwsec_active
) {
342 struct cb_desc
*tcb_desc
= (struct cb_desc
*)(skb
->cb
+ MAX_DEV_ADDR_SIZE
);
343 tcb_desc
->bHwSec
= 1;
345 hdr
= (struct rtl_80211_hdr_4addr
*)skb
->data
;
346 hdrlen
= ieee80211_get_hdrlen(le16_to_cpu(hdr
->frame_ctl
));
348 if (ieee
->tkip_countermeasures
&&
349 strcmp(crypt
->ops
->name
, "TKIP") == 0) {
350 if (net_ratelimit()) {
351 netdev_dbg(ieee
->dev
, "TKIP countermeasures: dropped "
352 "received packet from %pM\n",
358 atomic_inc(&crypt
->refcnt
);
359 res
= crypt
->ops
->decrypt_mpdu(skb
, hdrlen
, crypt
->priv
);
360 atomic_dec(&crypt
->refcnt
);
362 IEEE80211_DEBUG_DROP(
363 "decryption failed (SA=%pM"
364 ") res=%d\n", hdr
->addr2
, res
);
366 IEEE80211_DEBUG_DROP("Decryption failed ICV "
367 "mismatch (key %d)\n",
368 skb
->data
[hdrlen
+ 3] >> 6);
369 ieee
->ieee_stats
.rx_discards_undecryptable
++;
377 /* Called only as a tasklet (software IRQ), by ieee80211_rx */
379 ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device
*ieee
, struct sk_buff
*skb
,
380 int keyidx
, struct ieee80211_crypt_data
*crypt
)
382 struct rtl_80211_hdr_4addr
*hdr
;
385 if (!crypt
|| !crypt
->ops
->decrypt_msdu
)
387 if (ieee
->hwsec_active
) {
388 struct cb_desc
*tcb_desc
= (struct cb_desc
*)(skb
->cb
+ MAX_DEV_ADDR_SIZE
);
389 tcb_desc
->bHwSec
= 1;
392 hdr
= (struct rtl_80211_hdr_4addr
*)skb
->data
;
393 hdrlen
= ieee80211_get_hdrlen(le16_to_cpu(hdr
->frame_ctl
));
395 atomic_inc(&crypt
->refcnt
);
396 res
= crypt
->ops
->decrypt_msdu(skb
, keyidx
, hdrlen
, crypt
->priv
);
397 atomic_dec(&crypt
->refcnt
);
399 netdev_dbg(ieee
->dev
, "MSDU decryption/MIC verification failed"
400 " (SA=%pM keyidx=%d)\n",
409 /* this function is stolen from ipw2200 driver*/
410 #define IEEE_PACKET_RETRY_TIME (5 * HZ)
411 static int is_duplicate_packet(struct ieee80211_device
*ieee
,
412 struct rtl_80211_hdr_4addr
*header
)
414 u16 fc
= le16_to_cpu(header
->frame_ctl
);
415 u16 sc
= le16_to_cpu(header
->seq_ctl
);
416 u16 seq
= WLAN_GET_SEQ_SEQ(sc
);
417 u16 frag
= WLAN_GET_SEQ_FRAG(sc
);
418 u16
*last_seq
, *last_frag
;
419 unsigned long *last_time
;
420 struct rtl_80211_hdr_3addrqos
*hdr_3addrqos
;
421 struct rtl_80211_hdr_4addrqos
*hdr_4addrqos
;
426 if (((fc
& IEEE80211_FCTL_DSTODS
) == IEEE80211_FCTL_DSTODS
) && IEEE80211_QOS_HAS_SEQ(fc
)) {
427 hdr_4addrqos
= (struct rtl_80211_hdr_4addrqos
*)header
;
428 tid
= le16_to_cpu(hdr_4addrqos
->qos_ctl
) & IEEE80211_QCTL_TID
;
431 } else if (IEEE80211_QOS_HAS_SEQ(fc
)) { //QoS
432 hdr_3addrqos
= (struct rtl_80211_hdr_3addrqos
*)header
;
433 tid
= le16_to_cpu(hdr_3addrqos
->qos_ctl
) & IEEE80211_QCTL_TID
;
440 switch (ieee
->iw_mode
) {
444 struct ieee_ibss_seq
*entry
= NULL
;
445 u8
*mac
= header
->addr2
;
446 int index
= mac
[5] % IEEE_IBSS_MAC_HASH_SIZE
;
448 list_for_each(p
, &ieee
->ibss_mac_hash
[index
]) {
449 entry
= list_entry(p
, struct ieee_ibss_seq
, list
);
450 if (!memcmp(entry
->mac
, mac
, ETH_ALEN
))
453 // if (memcmp(entry->mac, mac, ETH_ALEN)){
454 if (p
== &ieee
->ibss_mac_hash
[index
]) {
455 entry
= kmalloc(sizeof(struct ieee_ibss_seq
), GFP_ATOMIC
);
458 memcpy(entry
->mac
, mac
, ETH_ALEN
);
459 entry
->seq_num
[tid
] = seq
;
460 entry
->frag_num
[tid
] = frag
;
461 entry
->packet_time
[tid
] = jiffies
;
462 list_add(&entry
->list
, &ieee
->ibss_mac_hash
[index
]);
465 last_seq
= &entry
->seq_num
[tid
];
466 last_frag
= &entry
->frag_num
[tid
];
467 last_time
= &entry
->packet_time
[tid
];
472 last_seq
= &ieee
->last_rxseq_num
[tid
];
473 last_frag
= &ieee
->last_rxfrag_num
[tid
];
474 last_time
= &ieee
->last_packet_time
[tid
];
482 // printk(KERN_WARNING ":)))))))))))%x %x %x, fc(%x)\n", tid, *last_seq, seq, header->frame_ctl);
484 if ((*last_seq
== seq
) &&
485 time_after(*last_time
+ IEEE_PACKET_RETRY_TIME
, jiffies
)) {
486 if (*last_frag
== frag
)
488 if (*last_frag
+ 1 != frag
)
489 /* out-of-order fragment */
495 *last_time
= jiffies
;
499 // BUG_ON(!(fc & IEEE80211_FCTL_RETRY));
504 static bool AddReorderEntry(struct rx_ts_record
*pTS
, struct rx_reorder_entry
*pReorderEntry
)
506 struct list_head
*pList
= &pTS
->rx_pending_pkt_list
;
507 while (pList
->next
!= &pTS
->rx_pending_pkt_list
) {
508 if (SN_LESS(pReorderEntry
->SeqNum
, list_entry(pList
->next
, struct rx_reorder_entry
, List
)->SeqNum
))
510 else if (SN_EQUAL(pReorderEntry
->SeqNum
, list_entry(pList
->next
, struct rx_reorder_entry
, List
)->SeqNum
))
515 pReorderEntry
->List
.next
= pList
->next
;
516 pReorderEntry
->List
.next
->prev
= &pReorderEntry
->List
;
517 pReorderEntry
->List
.prev
= pList
;
518 pList
->next
= &pReorderEntry
->List
;
523 static void indicate_packets(struct ieee80211_device
*ieee
,
524 struct ieee80211_rxb
*rxb
)
526 struct net_device_stats
*stats
= &ieee
->stats
;
527 struct net_device
*dev
= ieee
->dev
;
531 for (i
= 0; i
< rxb
->nr_subframes
; i
++) {
532 struct sk_buff
*sub_skb
= rxb
->subframes
[i
];
537 /* convert hdr + possible LLC headers into Ethernet header */
538 ethertype
= (sub_skb
->data
[6] << 8) | sub_skb
->data
[7];
539 if (sub_skb
->len
>= 8 &&
540 ((!memcmp(sub_skb
->data
, rfc1042_header
, SNAP_SIZE
) &&
541 ethertype
!= ETH_P_AARP
&&
542 ethertype
!= ETH_P_IPX
) ||
543 !memcmp(sub_skb
->data
, bridge_tunnel_header
, SNAP_SIZE
))) {
544 /* remove RFC1042 or Bridge-Tunnel encapsulation and
545 * replace EtherType */
546 skb_pull(sub_skb
, SNAP_SIZE
);
548 /* Leave Ethernet header part of hdr and full payload */
549 put_unaligned_be16(sub_skb
->len
, skb_push(sub_skb
, 2));
551 memcpy(skb_push(sub_skb
, ETH_ALEN
), rxb
->src
, ETH_ALEN
);
552 memcpy(skb_push(sub_skb
, ETH_ALEN
), rxb
->dst
, ETH_ALEN
);
555 stats
->rx_bytes
+= sub_skb
->len
;
556 if (is_multicast_ether_addr(rxb
->dst
))
559 /* Indicate the packets to upper layer */
560 sub_skb
->protocol
= eth_type_trans(sub_skb
, dev
);
561 memset(sub_skb
->cb
, 0, sizeof(sub_skb
->cb
));
563 /* 802.11 crc not sufficient */
564 sub_skb
->ip_summed
= CHECKSUM_NONE
;
565 ieee
->last_rx_ps_time
= jiffies
;
570 void ieee80211_indicate_packets(struct ieee80211_device
*ieee
,
571 struct ieee80211_rxb
**prxbIndicateArray
,
576 for (i
= 0; i
< index
; i
++) {
577 struct ieee80211_rxb
*prxb
= prxbIndicateArray
[i
];
579 indicate_packets(ieee
, prxb
);
585 static void RxReorderIndicatePacket(struct ieee80211_device
*ieee
,
586 struct ieee80211_rxb
*prxb
,
587 struct rx_ts_record
*pTS
, u16 SeqNum
)
589 PRT_HIGH_THROUGHPUT pHTInfo
= ieee
->pHTInfo
;
590 struct rx_reorder_entry
*pReorderEntry
= NULL
;
591 struct ieee80211_rxb
**prxbIndicateArray
;
592 u8 WinSize
= pHTInfo
->RxReorderWinSize
;
593 u16 WinEnd
= (pTS
->rx_indicate_seq
+ WinSize
- 1) % 4096;
595 bool bMatchWinStart
= false, bPktInBuf
= false;
596 IEEE80211_DEBUG(IEEE80211_DL_REORDER
, "%s(): Seq is %d,pTS->rx_indicate_seq is %d, WinSize is %d\n", __func__
, SeqNum
, pTS
->rx_indicate_seq
, WinSize
);
598 prxbIndicateArray
= kmalloc_array(REORDER_WIN_SIZE
,
599 sizeof(struct ieee80211_rxb
*),
601 if (!prxbIndicateArray
)
604 /* Rx Reorder initialize condition.*/
605 if (pTS
->rx_indicate_seq
== 0xffff)
606 pTS
->rx_indicate_seq
= SeqNum
;
608 /* Drop out the packet which SeqNum is smaller than WinStart */
609 if (SN_LESS(SeqNum
, pTS
->rx_indicate_seq
)) {
610 IEEE80211_DEBUG(IEEE80211_DL_REORDER
, "Packet Drop! IndicateSeq: %d, NewSeq: %d\n",
611 pTS
->rx_indicate_seq
, SeqNum
);
612 pHTInfo
->RxReorderDropCounter
++;
615 for (i
= 0; i
< prxb
->nr_subframes
; i
++) {
616 dev_kfree_skb(prxb
->subframes
[i
]);
622 kfree(prxbIndicateArray
);
627 * Sliding window manipulation. Conditions includes:
628 * 1. Incoming SeqNum is equal to WinStart =>Window shift 1
629 * 2. Incoming SeqNum is larger than the WinEnd => Window shift N
631 if (SN_EQUAL(SeqNum
, pTS
->rx_indicate_seq
)) {
632 pTS
->rx_indicate_seq
= (pTS
->rx_indicate_seq
+ 1) % 4096;
633 bMatchWinStart
= true;
634 } else if (SN_LESS(WinEnd
, SeqNum
)) {
635 if (SeqNum
>= (WinSize
- 1)) {
636 pTS
->rx_indicate_seq
= SeqNum
+ 1 - WinSize
;
638 pTS
->rx_indicate_seq
= 4095 - (WinSize
- (SeqNum
+ 1)) + 1;
640 IEEE80211_DEBUG(IEEE80211_DL_REORDER
, "Window Shift! IndicateSeq: %d, NewSeq: %d\n", pTS
->rx_indicate_seq
, SeqNum
);
644 * Indication process.
645 * After Packet dropping and Sliding Window shifting as above, we can now just indicate the packets
646 * with the SeqNum smaller than latest WinStart and buffer other packets.
648 /* For Rx Reorder condition:
649 * 1. All packets with SeqNum smaller than WinStart => Indicate
650 * 2. All packets with SeqNum larger than or equal to WinStart => Buffer it.
652 if (bMatchWinStart
) {
653 /* Current packet is going to be indicated.*/
654 IEEE80211_DEBUG(IEEE80211_DL_REORDER
, "Packets indication!! IndicateSeq: %d, NewSeq: %d\n",\
655 pTS
->rx_indicate_seq
, SeqNum
);
656 prxbIndicateArray
[0] = prxb
;
657 // printk("========================>%s(): SeqNum is %d\n",__func__,SeqNum);
660 /* Current packet is going to be inserted into pending list.*/
661 //IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): We RX no ordered packed, insert to ordered list\n",__func__);
662 if (!list_empty(&ieee
->RxReorder_Unused_List
)) {
663 pReorderEntry
= list_entry(ieee
->RxReorder_Unused_List
.next
, struct rx_reorder_entry
, List
);
664 list_del_init(&pReorderEntry
->List
);
666 /* Make a reorder entry and insert into a the packet list.*/
667 pReorderEntry
->SeqNum
= SeqNum
;
668 pReorderEntry
->prxb
= prxb
;
669 // IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): pREorderEntry->SeqNum is %d\n",__func__,pReorderEntry->SeqNum);
671 if (!AddReorderEntry(pTS
, pReorderEntry
)) {
672 IEEE80211_DEBUG(IEEE80211_DL_REORDER
, "%s(): Duplicate packet is dropped!! IndicateSeq: %d, NewSeq: %d\n",
673 __func__
, pTS
->rx_indicate_seq
, SeqNum
);
674 list_add_tail(&pReorderEntry
->List
, &ieee
->RxReorder_Unused_List
);
677 for (i
= 0; i
< prxb
->nr_subframes
; i
++) {
678 dev_kfree_skb(prxb
->subframes
[i
]);
684 IEEE80211_DEBUG(IEEE80211_DL_REORDER
,
685 "Pkt insert into buffer!! IndicateSeq: %d, NewSeq: %d\n", pTS
->rx_indicate_seq
, SeqNum
);
689 * Packets are dropped if there is not enough reorder entries.
690 * This part shall be modified!! We can just indicate all the
691 * packets in buffer and get reorder entries.
693 IEEE80211_DEBUG(IEEE80211_DL_ERR
, "RxReorderIndicatePacket(): There is no reorder entry!! Packet is dropped!!\n");
696 for (i
= 0; i
< prxb
->nr_subframes
; i
++) {
697 dev_kfree_skb(prxb
->subframes
[i
]);
705 /* Check if there is any packet need indicate.*/
706 while (!list_empty(&pTS
->rx_pending_pkt_list
)) {
707 IEEE80211_DEBUG(IEEE80211_DL_REORDER
, "%s(): start RREORDER indicate\n", __func__
);
708 pReorderEntry
= list_entry(pTS
->rx_pending_pkt_list
.prev
, struct rx_reorder_entry
, List
);
709 if (SN_LESS(pReorderEntry
->SeqNum
, pTS
->rx_indicate_seq
) ||
710 SN_EQUAL(pReorderEntry
->SeqNum
, pTS
->rx_indicate_seq
)) {
711 /* This protect buffer from overflow. */
712 if (index
>= REORDER_WIN_SIZE
) {
713 IEEE80211_DEBUG(IEEE80211_DL_ERR
, "RxReorderIndicatePacket(): Buffer overflow!! \n");
718 list_del_init(&pReorderEntry
->List
);
720 if (SN_EQUAL(pReorderEntry
->SeqNum
, pTS
->rx_indicate_seq
))
721 pTS
->rx_indicate_seq
= (pTS
->rx_indicate_seq
+ 1) % 4096;
723 IEEE80211_DEBUG(IEEE80211_DL_REORDER
, "Packets indication!! IndicateSeq: %d, NewSeq: %d\n", pTS
->rx_indicate_seq
, SeqNum
);
724 prxbIndicateArray
[index
] = pReorderEntry
->prxb
;
725 // printk("========================>%s(): pReorderEntry->SeqNum is %d\n",__func__,pReorderEntry->SeqNum);
728 list_add_tail(&pReorderEntry
->List
, &ieee
->RxReorder_Unused_List
);
735 /* Handling pending timer. Set this timer to prevent from long time Rx buffering.*/
737 // Cancel previous pending timer.
738 // del_timer_sync(&pTS->rx_pkt_pending_timer);
739 pTS
->rx_timeout_indicate_seq
= 0xffff;
742 if (index
> REORDER_WIN_SIZE
) {
743 IEEE80211_DEBUG(IEEE80211_DL_ERR
, "RxReorderIndicatePacket(): Rx Reorder buffer full!! \n");
744 kfree(prxbIndicateArray
);
747 ieee80211_indicate_packets(ieee
, prxbIndicateArray
, index
);
750 if (bPktInBuf
&& pTS
->rx_timeout_indicate_seq
== 0xffff) {
751 // Set new pending timer.
752 IEEE80211_DEBUG(IEEE80211_DL_REORDER
, "%s(): SET rx timeout timer\n", __func__
);
753 pTS
->rx_timeout_indicate_seq
= pTS
->rx_indicate_seq
;
754 if (timer_pending(&pTS
->rx_pkt_pending_timer
))
755 del_timer_sync(&pTS
->rx_pkt_pending_timer
);
756 pTS
->rx_pkt_pending_timer
.expires
= jiffies
+
757 msecs_to_jiffies(pHTInfo
->RxReorderPendingTime
);
758 add_timer(&pTS
->rx_pkt_pending_timer
);
761 kfree(prxbIndicateArray
);
764 static u8
parse_subframe(struct ieee80211_device
*ieee
,
766 struct ieee80211_rx_stats
*rx_stats
,
767 struct ieee80211_rxb
*rxb
, u8
*src
, u8
*dst
)
769 struct rtl_80211_hdr_3addr
*hdr
= (struct rtl_80211_hdr_3addr
*)skb
->data
;
770 u16 fc
= le16_to_cpu(hdr
->frame_ctl
);
772 u16 LLCOffset
= sizeof(struct rtl_80211_hdr_3addr
);
774 bool bIsAggregateFrame
= false;
775 u16 nSubframe_Length
;
776 u8 nPadding_Length
= 0;
779 struct sk_buff
*sub_skb
;
780 /* just for debug purpose */
781 SeqNum
= WLAN_GET_SEQ_SEQ(le16_to_cpu(hdr
->seq_ctl
));
783 if ((IEEE80211_QOS_HAS_SEQ(fc
)) && \
784 (((frameqos
*)(skb
->data
+ IEEE80211_3ADDR_LEN
))->field
.reserved
)) {
785 bIsAggregateFrame
= true;
788 if (IEEE80211_QOS_HAS_SEQ(fc
)) {
792 if (rx_stats
->bContainHTC
) {
795 // Null packet, don't indicate it to upper layer
796 ChkLength
= LLCOffset
;/* + (Frame_WEP(frame)!=0 ?Adapter->MgntInfo.SecurityInfo.EncryptionHeadOverhead:0);*/
798 if (skb
->len
<= ChkLength
)
801 skb_pull(skb
, LLCOffset
);
803 if (!bIsAggregateFrame
) {
804 rxb
->nr_subframes
= 1;
806 rxb
->subframes
[0] = skb
;
808 rxb
->subframes
[0] = skb_copy(skb
, GFP_ATOMIC
);
811 memcpy(rxb
->src
, src
, ETH_ALEN
);
812 memcpy(rxb
->dst
, dst
, ETH_ALEN
);
813 //IEEE80211_DEBUG_DATA(IEEE80211_DL_RX,skb->data,skb->len);
816 rxb
->nr_subframes
= 0;
817 memcpy(rxb
->src
, src
, ETH_ALEN
);
818 memcpy(rxb
->dst
, dst
, ETH_ALEN
);
819 while (skb
->len
> ETHERNET_HEADER_SIZE
) {
820 /* Offset 12 denote 2 mac address */
821 nSubframe_Length
= *((u16
*)(skb
->data
+ 12));
822 //==m==>change the length order
823 nSubframe_Length
= (nSubframe_Length
>> 8) + (nSubframe_Length
<< 8);
825 if (skb
->len
< (ETHERNET_HEADER_SIZE
+ nSubframe_Length
)) {
826 netdev_dbg(ieee
->dev
, "A-MSDU parse error!! pRfd->nTotalSubframe : %d\n",
828 netdev_dbg(ieee
->dev
, "A-MSDU parse error!! Subframe Length: %d\n", nSubframe_Length
);
829 netdev_dbg(ieee
->dev
, "nRemain_Length is %d and nSubframe_Length is : %d\n", skb
->len
, nSubframe_Length
);
830 netdev_dbg(ieee
->dev
, "The Packet SeqNum is %d\n", SeqNum
);
834 /* move the data point to data content */
835 skb_pull(skb
, ETHERNET_HEADER_SIZE
);
838 sub_skb
= skb_clone(skb
, GFP_ATOMIC
);
839 sub_skb
->len
= nSubframe_Length
;
840 sub_skb
->tail
= sub_skb
->data
+ nSubframe_Length
;
842 /* Allocate new skb for releasing to upper layer */
843 sub_skb
= dev_alloc_skb(nSubframe_Length
+ 12);
846 skb_reserve(sub_skb
, 12);
847 skb_put_data(sub_skb
, skb
->data
, nSubframe_Length
);
849 rxb
->subframes
[rxb
->nr_subframes
++] = sub_skb
;
850 if (rxb
->nr_subframes
>= MAX_SUBFRAME_COUNT
) {
851 IEEE80211_DEBUG_RX("ParseSubframe(): Too many Subframes! Packets dropped!\n");
854 skb_pull(skb
, nSubframe_Length
);
857 nPadding_Length
= 4 - ((nSubframe_Length
+ ETHERNET_HEADER_SIZE
) % 4);
858 if (nPadding_Length
== 4) {
862 if (skb
->len
< nPadding_Length
) {
866 skb_pull(skb
, nPadding_Length
);
872 //{just for debug added by david
873 //printk("AMSDU::rxb->nr_subframes = %d\n",rxb->nr_subframes);
875 return rxb
->nr_subframes
;
879 /* All received frames are sent to this function. @skb contains the frame in
880 * IEEE 802.11 format, i.e., in the format it was sent over air.
881 * This function is called only as a tasklet (software IRQ). */
882 int ieee80211_rx(struct ieee80211_device
*ieee
, struct sk_buff
*skb
,
883 struct ieee80211_rx_stats
*rx_stats
)
885 struct net_device
*dev
= ieee
->dev
;
886 struct rtl_80211_hdr_4addr
*hdr
;
887 //struct rtl_80211_hdr_3addrqos *hdr;
890 u16 fc
, type
, stype
, sc
;
891 struct net_device_stats
*stats
;
893 //added by amy for reorder
896 struct rx_ts_record
*pTS
= NULL
;
897 //bool bIsAggregateFrame = false;
898 //added by amy for reorder
900 struct net_device
*wds
= NULL
;
901 struct net_device
*wds
= NULL
;
902 int from_assoc_ap
= 0;
909 struct ieee80211_crypt_data
*crypt
= NULL
;
913 struct ieee80211_rxb
*rxb
= NULL
;
914 // cheat the hdr type
915 hdr
= (struct rtl_80211_hdr_4addr
*)skb
->data
;
916 stats
= &ieee
->stats
;
919 netdev_info(dev
, "SKB length < 10\n");
923 fc
= le16_to_cpu(hdr
->frame_ctl
);
924 type
= WLAN_FC_GET_TYPE(fc
);
925 stype
= WLAN_FC_GET_STYPE(fc
);
926 sc
= le16_to_cpu(hdr
->seq_ctl
);
928 frag
= WLAN_GET_SEQ_FRAG(sc
);
929 hdrlen
= ieee80211_get_hdrlen(fc
);
931 if (HTCCheck(ieee
, skb
->data
)) {
933 netdev_warn(dev
, "find HTCControl\n");
935 rx_stats
->bContainHTC
= true;
938 //IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, skb->data, skb->len);
940 /* Put this code here so that we avoid duplicating it in all
941 * Rx paths. - Jean II */
942 #ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */
943 /* If spy monitoring on */
944 if (iface
->spy_data
.spy_number
> 0) {
945 struct iw_quality wstats
;
946 wstats
.level
= rx_stats
->rssi
;
947 wstats
.noise
= rx_stats
->noise
;
948 wstats
.updated
= 6; /* No qual value */
949 /* Update spy records */
950 wireless_spy_update(dev
, hdr
->addr2
, &wstats
);
952 #endif /* IW_WIRELESS_SPY */
953 hostap_update_rx_stats(local
->ap
, hdr
, rx_stats
);
956 if (ieee
->iw_mode
== IW_MODE_MONITOR
) {
957 ieee80211_monitor_rx(ieee
, skb
, rx_stats
);
959 stats
->rx_bytes
+= skb
->len
;
963 if (ieee
->host_decrypt
) {
965 if (skb
->len
>= hdrlen
+ 3)
966 idx
= skb
->data
[hdrlen
+ 3] >> 6;
967 crypt
= ieee
->crypt
[idx
];
971 /* Use station specific key to override default keys if the
972 * receiver address is a unicast address ("individual RA"). If
973 * bcrx_sta_key parameter is set, station specific key is used
974 * even with broad/multicast targets (this is against IEEE
975 * 802.11, but makes it easier to use different keys with
976 * stations that do not support WEP key mapping). */
978 if (!(hdr
->addr1
[0] & 0x01) || local
->bcrx_sta_key
)
979 (void)hostap_handle_sta_crypto(local
, hdr
, &crypt
,
983 /* allow NULL decrypt to indicate an station specific override
984 * for default encryption */
985 if (crypt
&& (!crypt
->ops
|| !crypt
->ops
->decrypt_mpdu
))
988 if (!crypt
&& (fc
& IEEE80211_FCTL_WEP
)) {
989 /* This seems to be triggered by some (multicast?)
990 * frames from other than current BSS, so just drop the
991 * frames silently instead of filling system log with
993 IEEE80211_DEBUG_DROP("Decryption failed (not set)"
996 ieee
->ieee_stats
.rx_discards_undecryptable
++;
1001 if (skb
->len
< IEEE80211_DATA_HDR3_LEN
)
1004 // if QoS enabled, should check the sequence for each of the AC
1005 if ((!ieee
->pHTInfo
->bCurRxReorderEnable
) || !ieee
->current_network
.qos_data
.active
|| !IsDataFrame(skb
->data
) || IsLegacyDataFrame(skb
->data
)) {
1006 if (is_duplicate_packet(ieee
, hdr
))
1010 struct rx_ts_record
*pRxTS
= NULL
;
1011 //IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): QOS ENABLE AND RECEIVE QOS DATA , we will get Ts, tid:%d\n",__func__, tid);
1014 (struct ts_common_info
**)&pRxTS
,
1016 Frame_QoSTID((u8
*)(skb
->data
)),
1020 // IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): pRxTS->rx_last_frag_num is %d,frag is %d,pRxTS->rx_last_seq_num is %d,seq is %d\n",__func__,pRxTS->rx_last_frag_num,frag,pRxTS->rx_last_seq_num,WLAN_GET_SEQ_SEQ(sc));
1021 if ((fc
& (1 << 11)) &&
1022 (frag
== pRxTS
->rx_last_frag_num
) &&
1023 (WLAN_GET_SEQ_SEQ(sc
) == pRxTS
->rx_last_seq_num
)) {
1026 pRxTS
->rx_last_frag_num
= frag
;
1027 pRxTS
->rx_last_seq_num
= WLAN_GET_SEQ_SEQ(sc
);
1030 IEEE80211_DEBUG(IEEE80211_DL_ERR
, "%s(): No TS!! Skip the check!!\n", __func__
);
1034 if (type
== IEEE80211_FTYPE_MGMT
) {
1037 //IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, skb->data, skb->len);
1038 if (ieee80211_rx_frame_mgmt(ieee
, skb
, rx_stats
, type
, stype
))
1044 /* Data frame - extract src/dst addresses */
1045 switch (fc
& (IEEE80211_FCTL_FROMDS
| IEEE80211_FCTL_TODS
)) {
1046 case IEEE80211_FCTL_FROMDS
:
1047 memcpy(dst
, hdr
->addr1
, ETH_ALEN
);
1048 memcpy(src
, hdr
->addr3
, ETH_ALEN
);
1049 memcpy(bssid
, hdr
->addr2
, ETH_ALEN
);
1051 case IEEE80211_FCTL_TODS
:
1052 memcpy(dst
, hdr
->addr3
, ETH_ALEN
);
1053 memcpy(src
, hdr
->addr2
, ETH_ALEN
);
1054 memcpy(bssid
, hdr
->addr1
, ETH_ALEN
);
1056 case IEEE80211_FCTL_FROMDS
| IEEE80211_FCTL_TODS
:
1057 if (skb
->len
< IEEE80211_DATA_HDR4_LEN
)
1059 memcpy(dst
, hdr
->addr3
, ETH_ALEN
);
1060 memcpy(src
, hdr
->addr4
, ETH_ALEN
);
1061 memcpy(bssid
, ieee
->current_network
.bssid
, ETH_ALEN
);
1064 memcpy(dst
, hdr
->addr1
, ETH_ALEN
);
1065 memcpy(src
, hdr
->addr2
, ETH_ALEN
);
1066 memcpy(bssid
, hdr
->addr3
, ETH_ALEN
);
1071 if (hostap_rx_frame_wds(ieee
, hdr
, fc
, &wds
))
1074 skb
->dev
= dev
= wds
;
1075 stats
= hostap_get_stats(dev
);
1078 if (ieee
->iw_mode
== IW_MODE_MASTER
&& !wds
&&
1079 (fc
& (IEEE80211_FCTL_TODS
| IEEE80211_FCTL_FROMDS
)) == IEEE80211_FCTL_FROMDS
&&
1081 memcmp(hdr
->addr2
, ieee
->assoc_ap_addr
, ETH_ALEN
) == 0) {
1082 /* Frame from BSSID of the AP for which we are a client */
1083 skb
->dev
= dev
= ieee
->stadev
;
1084 stats
= hostap_get_stats(dev
);
1088 if ((ieee
->iw_mode
== IW_MODE_MASTER
||
1089 ieee
->iw_mode
== IW_MODE_REPEAT
) &&
1091 switch (hostap_handle_sta_rx(ieee
, dev
, skb
, rx_stats
,
1093 case AP_RX_CONTINUE_NOT_AUTHORIZED
:
1094 case AP_RX_CONTINUE
:
1103 //IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, skb->data, skb->len);
1104 /* Nullfunc frames may have PS-bit set, so they must be passed to
1105 * hostap_handle_sta_rx() before being dropped here. */
1106 if (stype
!= IEEE80211_STYPE_DATA
&&
1107 stype
!= IEEE80211_STYPE_DATA_CFACK
&&
1108 stype
!= IEEE80211_STYPE_DATA_CFPOLL
&&
1109 stype
!= IEEE80211_STYPE_DATA_CFACKPOLL
&&
1110 stype
!= IEEE80211_STYPE_QOS_DATA
//add by David,2006.8.4
1112 if (stype
!= IEEE80211_STYPE_NULLFUNC
)
1113 IEEE80211_DEBUG_DROP(
1114 "RX: dropped data frame "
1115 "with no data (type=0x%02x, "
1116 "subtype=0x%02x, len=%d)\n",
1117 type
, stype
, skb
->len
);
1120 if (memcmp(bssid
, ieee
->current_network
.bssid
, ETH_ALEN
))
1123 /* skb: hdr + (possibly fragmented, possibly encrypted) payload */
1125 if (ieee
->host_decrypt
&& (fc
& IEEE80211_FCTL_WEP
) &&
1126 (keyidx
= ieee80211_rx_frame_decrypt(ieee
, skb
, crypt
)) < 0) {
1127 netdev_dbg(ieee
->dev
, "decrypt frame error\n");
1132 hdr
= (struct rtl_80211_hdr_4addr
*)skb
->data
;
1134 /* skb: hdr + (possibly fragmented) plaintext payload */
1135 // PR: FIXME: hostap has additional conditions in the "if" below:
1136 // ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) &&
1137 if ((frag
!= 0 || (fc
& IEEE80211_FCTL_MOREFRAGS
))) {
1139 struct sk_buff
*frag_skb
= ieee80211_frag_cache_get(ieee
, hdr
);
1140 IEEE80211_DEBUG_FRAG("Rx Fragment received (%u)\n", frag
);
1143 IEEE80211_DEBUG(IEEE80211_DL_RX
| IEEE80211_DL_FRAG
,
1144 "Rx cannot get skb from fragment "
1145 "cache (morefrag=%d seq=%u frag=%u)\n",
1146 (fc
& IEEE80211_FCTL_MOREFRAGS
) != 0,
1147 WLAN_GET_SEQ_SEQ(sc
), frag
);
1154 if (frag_skb
->tail
+ flen
> frag_skb
->end
) {
1155 netdev_warn(dev
, "host decrypted and "
1156 "reassembled frame did not fit skb\n");
1157 ieee80211_frag_cache_invalidate(ieee
, hdr
);
1162 /* copy first fragment (including full headers) into
1163 * beginning of the fragment cache skb */
1164 skb_put_data(frag_skb
, skb
->data
, flen
);
1166 /* append frame payload to the end of the fragment
1168 skb_put_data(frag_skb
, skb
->data
+ hdrlen
, flen
);
1170 dev_kfree_skb_any(skb
);
1173 if (fc
& IEEE80211_FCTL_MOREFRAGS
) {
1174 /* more fragments expected - leave the skb in fragment
1175 * cache for now; it will be delivered to upper layers
1176 * after all fragments have been received */
1180 /* this was the last fragment and the frame will be
1181 * delivered, so remove skb from fragment cache */
1183 hdr
= (struct rtl_80211_hdr_4addr
*)skb
->data
;
1184 ieee80211_frag_cache_invalidate(ieee
, hdr
);
1187 /* skb: hdr + (possible reassembled) full MSDU payload; possibly still
1188 * encrypted/authenticated */
1189 if (ieee
->host_decrypt
&& (fc
& IEEE80211_FCTL_WEP
) &&
1190 ieee80211_rx_frame_decrypt_msdu(ieee
, skb
, keyidx
, crypt
)) {
1191 netdev_dbg(ieee
->dev
, "==>decrypt msdu error\n");
1195 //added by amy for AP roaming
1196 ieee
->LinkDetectInfo
.NumRecvDataInPeriod
++;
1197 ieee
->LinkDetectInfo
.NumRxOkInPeriod
++;
1199 hdr
= (struct rtl_80211_hdr_4addr
*)skb
->data
;
1200 if (crypt
&& !(fc
& IEEE80211_FCTL_WEP
) && !ieee
->open_wep
) {
1201 if (/*ieee->ieee802_1x &&*/
1202 ieee80211_is_eapol_frame(ieee
, skb
, hdrlen
)) {
1204 #ifdef CONFIG_IEEE80211_DEBUG
1205 /* pass unencrypted EAPOL frames even if encryption is
1207 struct eapol
*eap
= (struct eapol
*)(skb
->data
+
1209 IEEE80211_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n",
1210 eap_get_type(eap
->type
));
1213 IEEE80211_DEBUG_DROP(
1214 "encryption configured, but RX "
1215 "frame not encrypted (SA=%pM)\n",
1221 #ifdef CONFIG_IEEE80211_DEBUG
1222 if (crypt
&& !(fc
& IEEE80211_FCTL_WEP
) &&
1223 ieee80211_is_eapol_frame(ieee
, skb
, hdrlen
)) {
1224 struct eapol
*eap
= (struct eapol
*)(skb
->data
+
1226 IEEE80211_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n",
1227 eap_get_type(eap
->type
));
1231 if (crypt
&& !(fc
& IEEE80211_FCTL_WEP
) && !ieee
->open_wep
&&
1232 !ieee80211_is_eapol_frame(ieee
, skb
, hdrlen
)) {
1233 IEEE80211_DEBUG_DROP(
1234 "dropped unencrypted RX data "
1236 " (drop_unencrypted=1)\n",
1241 if(ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
1242 printk(KERN_WARNING "RX: IEEE802.1X EPAOL frame!\n");
1245 //added by amy for reorder
1246 if (ieee
->current_network
.qos_data
.active
&& IsQoSDataFrame(skb
->data
)
1247 && !is_multicast_ether_addr(hdr
->addr1
)) {
1248 TID
= Frame_QoSTID(skb
->data
);
1249 SeqNum
= WLAN_GET_SEQ_SEQ(sc
);
1250 GetTs(ieee
, (struct ts_common_info
**)&pTS
, hdr
->addr2
, TID
, RX_DIR
, true);
1251 if (TID
!= 0 && TID
!= 3) {
1252 ieee
->bis_any_nonbepkts
= true;
1255 //added by amy for reorder
1256 /* skb: hdr + (possible reassembled) full plaintext payload */
1257 //ethertype = (payload[6] << 8) | payload[7];
1258 rxb
= kmalloc(sizeof(struct ieee80211_rxb
), GFP_ATOMIC
);
1261 /* to parse amsdu packets */
1262 /* qos data packets & reserved bit is 1 */
1263 if (parse_subframe(ieee
, skb
, rx_stats
, rxb
, src
, dst
) == 0) {
1264 /* only to free rxb, and not submit the packets to upper layer */
1265 for (i
= 0; i
< rxb
->nr_subframes
; i
++) {
1266 dev_kfree_skb(rxb
->subframes
[i
]);
1273 //added by amy for reorder
1274 if (!ieee
->pHTInfo
->bCurRxReorderEnable
|| !pTS
) {
1275 indicate_packets(ieee
, rxb
);
1280 IEEE80211_DEBUG(IEEE80211_DL_REORDER
, "%s(): REORDER ENABLE AND PTS not NULL, and we will enter RxReorderIndicatePacket()\n", __func__
);
1281 RxReorderIndicatePacket(ieee
, rxb
, pTS
, SeqNum
);
1290 hostap_handle_sta_release(sta
);
1297 stats
->rx_dropped
++;
1299 /* Returning 0 indicates to caller that we have not handled the SKB--
1300 * so it is still allocated and can be used again by underlying
1301 * hardware as a DMA target */
1304 EXPORT_SYMBOL(ieee80211_rx
);
1306 #define MGMT_FRAME_FIXED_PART_LENGTH 0x24
1308 static u8 qos_oui
[QOS_OUI_LEN
] = { 0x00, 0x50, 0xF2 };
1311 * Make the structure we read from the beacon packet to have
1314 static int ieee80211_verify_qos_info(struct ieee80211_qos_information_element
1315 *info_element
, int sub_type
)
1318 if (info_element
->qui_subtype
!= sub_type
)
1320 if (memcmp(info_element
->qui
, qos_oui
, QOS_OUI_LEN
))
1322 if (info_element
->qui_type
!= QOS_OUI_TYPE
)
1324 if (info_element
->version
!= QOS_VERSION_1
)
1332 * Parse a QoS parameter element
1334 static int ieee80211_read_qos_param_element(struct ieee80211_qos_parameter_info
1335 *element_param
, struct ieee80211_info_element
1339 u16 size
= sizeof(struct ieee80211_qos_parameter_info
) - 2;
1341 if (!info_element
|| !element_param
)
1344 if (info_element
->id
== QOS_ELEMENT_ID
&& info_element
->len
== size
) {
1345 memcpy(element_param
->info_element
.qui
, info_element
->data
,
1347 element_param
->info_element
.elementID
= info_element
->id
;
1348 element_param
->info_element
.length
= info_element
->len
;
1352 ret
= ieee80211_verify_qos_info(&element_param
->info_element
,
1353 QOS_OUI_PARAM_SUB_TYPE
);
1358 * Parse a QoS information element
1360 static int ieee80211_read_qos_info_element(
1361 struct ieee80211_qos_information_element
*element_info
,
1362 struct ieee80211_info_element
*info_element
)
1365 u16 size
= sizeof(struct ieee80211_qos_information_element
) - 2;
1372 if ((info_element
->id
== QOS_ELEMENT_ID
) && (info_element
->len
== size
)) {
1373 memcpy(element_info
->qui
, info_element
->data
,
1375 element_info
->elementID
= info_element
->id
;
1376 element_info
->length
= info_element
->len
;
1381 ret
= ieee80211_verify_qos_info(element_info
,
1382 QOS_OUI_INFO_SUB_TYPE
);
1388 * Write QoS parameters from the ac parameters.
1390 static int ieee80211_qos_convert_ac_to_parameters(
1391 struct ieee80211_qos_parameter_info
*param_elm
,
1392 struct ieee80211_qos_parameters
*qos_param
)
1395 struct ieee80211_qos_ac_parameter
*ac_params
;
1400 for (i
= 0; i
< QOS_QUEUE_NUM
; i
++) {
1401 ac_params
= &(param_elm
->ac_params_record
[i
]);
1403 aci
= (ac_params
->aci_aifsn
& 0x60) >> 5;
1405 if (aci
>= QOS_QUEUE_NUM
)
1407 qos_param
->aifs
[aci
] = (ac_params
->aci_aifsn
) & 0x0f;
1409 /* WMM spec P.11: The minimum value for AIFSN shall be 2 */
1410 qos_param
->aifs
[aci
] = (qos_param
->aifs
[aci
] < 2) ? 2 : qos_param
->aifs
[aci
];
1412 qos_param
->cw_min
[aci
] =
1413 cpu_to_le16(ac_params
->ecw_min_max
& 0x0F);
1415 qos_param
->cw_max
[aci
] =
1416 cpu_to_le16((ac_params
->ecw_min_max
& 0xF0) >> 4);
1418 qos_param
->flag
[aci
] =
1419 (ac_params
->aci_aifsn
& 0x10) ? 0x01 : 0x00;
1420 qos_param
->tx_op_limit
[aci
] = ac_params
->tx_op_limit
;
1426 * we have a generic data element which it may contain QoS information or
1427 * parameters element. check the information element length to decide
1428 * which type to read
1430 static int ieee80211_parse_qos_info_param_IE(struct ieee80211_info_element
1432 struct ieee80211_network
*network
)
1435 struct ieee80211_qos_parameters
*qos_param
= NULL
;
1436 struct ieee80211_qos_information_element qos_info_element
;
1438 rc
= ieee80211_read_qos_info_element(&qos_info_element
, info_element
);
1441 network
->qos_data
.param_count
= qos_info_element
.ac_info
& 0x0F;
1442 network
->flags
|= NETWORK_HAS_QOS_INFORMATION
;
1444 struct ieee80211_qos_parameter_info param_element
;
1446 rc
= ieee80211_read_qos_param_element(¶m_element
,
1449 qos_param
= &(network
->qos_data
.parameters
);
1450 ieee80211_qos_convert_ac_to_parameters(¶m_element
,
1452 network
->flags
|= NETWORK_HAS_QOS_PARAMETERS
;
1453 network
->qos_data
.param_count
=
1454 param_element
.info_element
.ac_info
& 0x0F;
1459 IEEE80211_DEBUG_QOS("QoS is supported\n");
1460 network
->qos_data
.supported
= 1;
1465 #ifdef CONFIG_IEEE80211_DEBUG
1466 #define MFIE_STRING(x) case MFIE_TYPE_ ##x: return #x
1468 static const char *get_info_element_string(u16 id
)
1473 MFIE_STRING(FH_SET
);
1474 MFIE_STRING(DS_SET
);
1475 MFIE_STRING(CF_SET
);
1477 MFIE_STRING(IBSS_SET
);
1478 MFIE_STRING(COUNTRY
);
1479 MFIE_STRING(HOP_PARAMS
);
1480 MFIE_STRING(HOP_TABLE
);
1481 MFIE_STRING(REQUEST
);
1482 MFIE_STRING(CHALLENGE
);
1483 MFIE_STRING(POWER_CONSTRAINT
);
1484 MFIE_STRING(POWER_CAPABILITY
);
1485 MFIE_STRING(TPC_REQUEST
);
1486 MFIE_STRING(TPC_REPORT
);
1487 MFIE_STRING(SUPP_CHANNELS
);
1489 MFIE_STRING(MEASURE_REQUEST
);
1490 MFIE_STRING(MEASURE_REPORT
);
1492 MFIE_STRING(IBSS_DFS
);
1493 // MFIE_STRING(ERP_INFO);
1495 MFIE_STRING(RATES_EX
);
1496 MFIE_STRING(GENERIC
);
1497 MFIE_STRING(QOS_PARAMETER
);
1504 static inline void ieee80211_extract_country_ie(
1505 struct ieee80211_device
*ieee
,
1506 struct ieee80211_info_element
*info_element
,
1507 struct ieee80211_network
*network
,
1511 if (IS_DOT11D_ENABLE(ieee
)) {
1512 if (info_element
->len
!= 0) {
1513 memcpy(network
->CountryIeBuf
, info_element
->data
, info_element
->len
);
1514 network
->CountryIeLen
= info_element
->len
;
1516 if (!IS_COUNTRY_IE_VALID(ieee
)) {
1517 dot11d_update_country_ie(ieee
, addr2
, info_element
->len
, info_element
->data
);
1522 // 070305, rcnjko: I update country IE watch dog here because
1523 // some AP (e.g. Cisco 1242) don't include country IE in their
1524 // probe response frame.
1526 if (IS_EQUAL_CIE_SRC(ieee
, addr2
)) {
1527 UPDATE_CIE_WATCHDOG(ieee
);
1533 int ieee80211_parse_info_param(struct ieee80211_device
*ieee
,
1534 struct ieee80211_info_element
*info_element
,
1536 struct ieee80211_network
*network
,
1537 struct ieee80211_rx_stats
*stats
)
1541 u16 tmp_htcap_len
= 0;
1542 u16 tmp_htinfo_len
= 0;
1543 u16 ht_realtek_agg_len
= 0;
1544 u8 ht_realtek_agg_buf
[MAX_IE_LEN
];
1545 // u16 broadcom_len = 0;
1546 #ifdef CONFIG_IEEE80211_DEBUG
1551 while (length
>= sizeof(*info_element
)) {
1552 if (sizeof(*info_element
) + info_element
->len
> length
) {
1553 IEEE80211_DEBUG_MGMT("Info elem: parse failed: "
1554 "info_element->len + 2 > left : "
1555 "info_element->len+2=%zd left=%d, id=%d.\n",
1557 sizeof(*info_element
),
1558 length
, info_element
->id
);
1559 /* We stop processing but don't return an error here
1560 * because some misbehaviour APs break this rule. ie.
1561 * Orinoco AP1000. */
1565 switch (info_element
->id
) {
1566 case MFIE_TYPE_SSID
:
1567 if (ieee80211_is_empty_essid(info_element
->data
,
1568 info_element
->len
)) {
1569 network
->flags
|= NETWORK_EMPTY_ESSID
;
1573 network
->ssid_len
= min(info_element
->len
,
1574 (u8
)IW_ESSID_MAX_SIZE
);
1575 memcpy(network
->ssid
, info_element
->data
, network
->ssid_len
);
1576 if (network
->ssid_len
< IW_ESSID_MAX_SIZE
)
1577 memset(network
->ssid
+ network
->ssid_len
, 0,
1578 IW_ESSID_MAX_SIZE
- network
->ssid_len
);
1580 IEEE80211_DEBUG_MGMT("MFIE_TYPE_SSID: '%s' len=%d.\n",
1581 network
->ssid
, network
->ssid_len
);
1584 case MFIE_TYPE_RATES
:
1585 #ifdef CONFIG_IEEE80211_DEBUG
1588 network
->rates_len
= min(info_element
->len
,
1590 for (i
= 0; i
< network
->rates_len
; i
++) {
1591 network
->rates
[i
] = info_element
->data
[i
];
1592 #ifdef CONFIG_IEEE80211_DEBUG
1593 p
+= scnprintf(p
, sizeof(rates_str
) -
1594 (p
- rates_str
), "%02X ",
1597 if (ieee80211_is_ofdm_rate
1598 (info_element
->data
[i
])) {
1599 network
->flags
|= NETWORK_HAS_OFDM
;
1600 if (info_element
->data
[i
] &
1601 IEEE80211_BASIC_RATE_MASK
)
1607 IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES: '%s' (%d)\n",
1608 rates_str
, network
->rates_len
);
1611 case MFIE_TYPE_RATES_EX
:
1612 #ifdef CONFIG_IEEE80211_DEBUG
1615 network
->rates_ex_len
= min(info_element
->len
,
1616 MAX_RATES_EX_LENGTH
);
1617 for (i
= 0; i
< network
->rates_ex_len
; i
++) {
1618 network
->rates_ex
[i
] = info_element
->data
[i
];
1619 #ifdef CONFIG_IEEE80211_DEBUG
1620 p
+= scnprintf(p
, sizeof(rates_str
) -
1621 (p
- rates_str
), "%02X ",
1622 network
->rates_ex
[i
]);
1624 if (ieee80211_is_ofdm_rate
1625 (info_element
->data
[i
])) {
1626 network
->flags
|= NETWORK_HAS_OFDM
;
1627 if (info_element
->data
[i
] &
1628 IEEE80211_BASIC_RATE_MASK
)
1634 IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES_EX: '%s' (%d)\n",
1635 rates_str
, network
->rates_ex_len
);
1638 case MFIE_TYPE_DS_SET
:
1639 IEEE80211_DEBUG_MGMT("MFIE_TYPE_DS_SET: %d\n",
1640 info_element
->data
[0]);
1641 network
->channel
= info_element
->data
[0];
1644 case MFIE_TYPE_FH_SET
:
1645 IEEE80211_DEBUG_MGMT("MFIE_TYPE_FH_SET: ignored\n");
1648 case MFIE_TYPE_CF_SET
:
1649 IEEE80211_DEBUG_MGMT("MFIE_TYPE_CF_SET: ignored\n");
1653 if (info_element
->len
< 4)
1656 network
->tim
.tim_count
= info_element
->data
[0];
1657 network
->tim
.tim_period
= info_element
->data
[1];
1659 network
->dtim_period
= info_element
->data
[1];
1660 if (ieee
->state
!= IEEE80211_LINKED
)
1663 network
->last_dtim_sta_time
[0] = stats
->mac_time
[0];
1664 network
->last_dtim_sta_time
[1] = stats
->mac_time
[1];
1666 network
->dtim_data
= IEEE80211_DTIM_VALID
;
1668 if (info_element
->data
[0] != 0)
1671 if (info_element
->data
[2] & 1)
1672 network
->dtim_data
|= IEEE80211_DTIM_MBCAST
;
1674 offset
= (info_element
->data
[2] >> 1) * 2;
1676 if (ieee
->assoc_id
< 8 * offset
||
1677 ieee
->assoc_id
> 8 * (offset
+ info_element
->len
- 3))
1681 offset
= (ieee
->assoc_id
/ 8) - offset
;// + ((aid % 8)? 0 : 1) ;
1683 if (info_element
->data
[3 + offset
] & (1 << (ieee
->assoc_id
% 8)))
1684 network
->dtim_data
|= IEEE80211_DTIM_UCAST
;
1686 //IEEE80211_DEBUG_MGMT("MFIE_TYPE_TIM: partially ignored\n");
1690 network
->erp_value
= info_element
->data
[0];
1691 network
->flags
|= NETWORK_HAS_ERP_VALUE
;
1692 IEEE80211_DEBUG_MGMT("MFIE_TYPE_ERP_SET: %d\n",
1693 network
->erp_value
);
1695 case MFIE_TYPE_IBSS_SET
:
1696 network
->atim_window
= info_element
->data
[0];
1697 IEEE80211_DEBUG_MGMT("MFIE_TYPE_IBSS_SET: %d\n",
1698 network
->atim_window
);
1701 case MFIE_TYPE_CHALLENGE
:
1702 IEEE80211_DEBUG_MGMT("MFIE_TYPE_CHALLENGE: ignored\n");
1705 case MFIE_TYPE_GENERIC
:
1706 IEEE80211_DEBUG_MGMT("MFIE_TYPE_GENERIC: %d bytes\n",
1708 if (!ieee80211_parse_qos_info_param_IE(info_element
,
1712 if (info_element
->len
>= 4 &&
1713 info_element
->data
[0] == 0x00 &&
1714 info_element
->data
[1] == 0x50 &&
1715 info_element
->data
[2] == 0xf2 &&
1716 info_element
->data
[3] == 0x01) {
1717 network
->wpa_ie_len
= min(info_element
->len
+ 2,
1719 memcpy(network
->wpa_ie
, info_element
,
1720 network
->wpa_ie_len
);
1725 if (info_element
->len
== 7 &&
1726 info_element
->data
[0] == 0x00 &&
1727 info_element
->data
[1] == 0xe0 &&
1728 info_element
->data
[2] == 0x4c &&
1729 info_element
->data
[3] == 0x01 &&
1730 info_element
->data
[4] == 0x02) {
1731 network
->Turbo_Enable
= 1;
1735 //for HTcap and HTinfo parameters
1736 if (tmp_htcap_len
== 0) {
1737 if (info_element
->len
>= 4 &&
1738 info_element
->data
[0] == 0x00 &&
1739 info_element
->data
[1] == 0x90 &&
1740 info_element
->data
[2] == 0x4c &&
1741 info_element
->data
[3] == 0x033){
1743 tmp_htcap_len
= min(info_element
->len
, (u8
)MAX_IE_LEN
);
1744 if (tmp_htcap_len
!= 0) {
1745 network
->bssht
.bdHTSpecVer
= HT_SPEC_VER_EWC
;
1746 network
->bssht
.bdHTCapLen
= tmp_htcap_len
> sizeof(network
->bssht
.bdHTCapBuf
) ? \
1747 sizeof(network
->bssht
.bdHTCapBuf
) : tmp_htcap_len
;
1748 memcpy(network
->bssht
.bdHTCapBuf
, info_element
->data
, network
->bssht
.bdHTCapLen
);
1751 if (tmp_htcap_len
!= 0)
1752 network
->bssht
.bdSupportHT
= true;
1754 network
->bssht
.bdSupportHT
= false;
1758 if (tmp_htinfo_len
== 0) {
1759 if (info_element
->len
>= 4 &&
1760 info_element
->data
[0] == 0x00 &&
1761 info_element
->data
[1] == 0x90 &&
1762 info_element
->data
[2] == 0x4c &&
1763 info_element
->data
[3] == 0x034){
1765 tmp_htinfo_len
= min(info_element
->len
, (u8
)MAX_IE_LEN
);
1766 if (tmp_htinfo_len
!= 0) {
1767 network
->bssht
.bdHTSpecVer
= HT_SPEC_VER_EWC
;
1768 if (tmp_htinfo_len
) {
1769 network
->bssht
.bdHTInfoLen
= tmp_htinfo_len
> sizeof(network
->bssht
.bdHTInfoBuf
) ? \
1770 sizeof(network
->bssht
.bdHTInfoBuf
) : tmp_htinfo_len
;
1771 memcpy(network
->bssht
.bdHTInfoBuf
, info_element
->data
, network
->bssht
.bdHTInfoLen
);
1779 if (ieee
->aggregation
) {
1780 if (network
->bssht
.bdSupportHT
) {
1781 if (info_element
->len
>= 4 &&
1782 info_element
->data
[0] == 0x00 &&
1783 info_element
->data
[1] == 0xe0 &&
1784 info_element
->data
[2] == 0x4c &&
1785 info_element
->data
[3] == 0x02){
1787 ht_realtek_agg_len
= min(info_element
->len
, (u8
)MAX_IE_LEN
);
1788 memcpy(ht_realtek_agg_buf
, info_element
->data
, info_element
->len
);
1791 if (ht_realtek_agg_len
>= 5) {
1792 network
->bssht
.bdRT2RTAggregation
= true;
1794 if ((ht_realtek_agg_buf
[4] == 1) && (ht_realtek_agg_buf
[5] & 0x02))
1795 network
->bssht
.bdRT2RTLongSlotTime
= true;
1801 //if(tmp_htcap_len !=0 || tmp_htinfo_len != 0)
1803 if ((info_element
->len
>= 3 &&
1804 info_element
->data
[0] == 0x00 &&
1805 info_element
->data
[1] == 0x05 &&
1806 info_element
->data
[2] == 0xb5) ||
1807 (info_element
->len
>= 3 &&
1808 info_element
->data
[0] == 0x00 &&
1809 info_element
->data
[1] == 0x0a &&
1810 info_element
->data
[2] == 0xf7) ||
1811 (info_element
->len
>= 3 &&
1812 info_element
->data
[0] == 0x00 &&
1813 info_element
->data
[1] == 0x10 &&
1814 info_element
->data
[2] == 0x18)){
1816 network
->broadcom_cap_exist
= true;
1820 if (info_element
->len
>= 3 &&
1821 info_element
->data
[0] == 0x00 &&
1822 info_element
->data
[1] == 0x0c &&
1823 info_element
->data
[2] == 0x43) {
1824 network
->ralink_cap_exist
= true;
1826 network
->ralink_cap_exist
= false;
1827 //added by amy for atheros AP
1828 if ((info_element
->len
>= 3 &&
1829 info_element
->data
[0] == 0x00 &&
1830 info_element
->data
[1] == 0x03 &&
1831 info_element
->data
[2] == 0x7f) ||
1832 (info_element
->len
>= 3 &&
1833 info_element
->data
[0] == 0x00 &&
1834 info_element
->data
[1] == 0x13 &&
1835 info_element
->data
[2] == 0x74)) {
1836 netdev_dbg(ieee
->dev
, "========> athros AP is exist\n");
1837 network
->atheros_cap_exist
= true;
1839 network
->atheros_cap_exist
= false;
1841 if (info_element
->len
>= 3 &&
1842 info_element
->data
[0] == 0x00 &&
1843 info_element
->data
[1] == 0x40 &&
1844 info_element
->data
[2] == 0x96) {
1845 network
->cisco_cap_exist
= true;
1847 network
->cisco_cap_exist
= false;
1848 //added by amy for LEAP of cisco
1849 if (info_element
->len
> 4 &&
1850 info_element
->data
[0] == 0x00 &&
1851 info_element
->data
[1] == 0x40 &&
1852 info_element
->data
[2] == 0x96 &&
1853 info_element
->data
[3] == 0x01) {
1854 if (info_element
->len
== 6) {
1855 memcpy(network
->CcxRmState
, &info_element
[4], 2);
1856 if (network
->CcxRmState
[0] != 0)
1857 network
->bCcxRmEnable
= true;
1859 network
->bCcxRmEnable
= false;
1861 // CCXv4 Table 59-1 MBSSID Masks.
1863 network
->MBssidMask
= network
->CcxRmState
[1] & 0x07;
1864 if (network
->MBssidMask
!= 0) {
1865 network
->bMBssidValid
= true;
1866 network
->MBssidMask
= 0xff << (network
->MBssidMask
);
1867 ether_addr_copy(network
->MBssid
, network
->bssid
);
1868 network
->MBssid
[5] &= network
->MBssidMask
;
1870 network
->bMBssidValid
= false;
1873 network
->bCcxRmEnable
= false;
1876 if (info_element
->len
> 4 &&
1877 info_element
->data
[0] == 0x00 &&
1878 info_element
->data
[1] == 0x40 &&
1879 info_element
->data
[2] == 0x96 &&
1880 info_element
->data
[3] == 0x03) {
1881 if (info_element
->len
== 5) {
1882 network
->bWithCcxVerNum
= true;
1883 network
->BssCcxVerNumber
= info_element
->data
[4];
1885 network
->bWithCcxVerNum
= false;
1886 network
->BssCcxVerNumber
= 0;
1892 IEEE80211_DEBUG_MGMT("MFIE_TYPE_RSN: %d bytes\n",
1894 network
->rsn_ie_len
= min(info_element
->len
+ 2,
1896 memcpy(network
->rsn_ie
, info_element
,
1897 network
->rsn_ie_len
);
1900 //HT related element.
1901 case MFIE_TYPE_HT_CAP
:
1902 IEEE80211_DEBUG_SCAN("MFIE_TYPE_HT_CAP: %d bytes\n",
1904 tmp_htcap_len
= min(info_element
->len
, (u8
)MAX_IE_LEN
);
1905 if (tmp_htcap_len
!= 0) {
1906 network
->bssht
.bdHTSpecVer
= HT_SPEC_VER_EWC
;
1907 network
->bssht
.bdHTCapLen
= tmp_htcap_len
> sizeof(network
->bssht
.bdHTCapBuf
) ? \
1908 sizeof(network
->bssht
.bdHTCapBuf
) : tmp_htcap_len
;
1909 memcpy(network
->bssht
.bdHTCapBuf
, info_element
->data
, network
->bssht
.bdHTCapLen
);
1911 //If peer is HT, but not WMM, call QosSetLegacyWMMParamWithHT()
1912 // windows driver will update WMM parameters each beacon received once connected
1913 // Linux driver is a bit different.
1914 network
->bssht
.bdSupportHT
= true;
1916 network
->bssht
.bdSupportHT
= false;
1920 case MFIE_TYPE_HT_INFO
:
1921 IEEE80211_DEBUG_SCAN("MFIE_TYPE_HT_INFO: %d bytes\n",
1923 tmp_htinfo_len
= min(info_element
->len
, (u8
)MAX_IE_LEN
);
1924 if (tmp_htinfo_len
) {
1925 network
->bssht
.bdHTSpecVer
= HT_SPEC_VER_IEEE
;
1926 network
->bssht
.bdHTInfoLen
= tmp_htinfo_len
> sizeof(network
->bssht
.bdHTInfoBuf
) ? \
1927 sizeof(network
->bssht
.bdHTInfoBuf
) : tmp_htinfo_len
;
1928 memcpy(network
->bssht
.bdHTInfoBuf
, info_element
->data
, network
->bssht
.bdHTInfoLen
);
1932 case MFIE_TYPE_AIRONET
:
1933 IEEE80211_DEBUG_SCAN("MFIE_TYPE_AIRONET: %d bytes\n",
1935 if (info_element
->len
> IE_CISCO_FLAG_POSITION
) {
1936 network
->bWithAironetIE
= true;
1938 // CCX 1 spec v1.13, A01.1 CKIP Negotiation (page23):
1939 // "A Cisco access point advertises support for CKIP in beacon and probe response packets,
1940 // by adding an Aironet element and setting one or both of the CKIP negotiation bits."
1941 if ((info_element
->data
[IE_CISCO_FLAG_POSITION
] & SUPPORT_CKIP_MIC
) ||
1942 (info_element
->data
[IE_CISCO_FLAG_POSITION
] & SUPPORT_CKIP_PK
)) {
1943 network
->bCkipSupported
= true;
1945 network
->bCkipSupported
= false;
1948 network
->bWithAironetIE
= false;
1949 network
->bCkipSupported
= false;
1952 case MFIE_TYPE_QOS_PARAMETER
:
1953 netdev_err(ieee
->dev
,
1954 "QoS Error need to parse QOS_PARAMETER IE\n");
1957 case MFIE_TYPE_COUNTRY
:
1958 IEEE80211_DEBUG_SCAN("MFIE_TYPE_COUNTRY: %d bytes\n",
1960 ieee80211_extract_country_ie(ieee
, info_element
, network
, network
->bssid
);//addr2 is same as addr3 when from an AP
1964 IEEE80211_DEBUG_MGMT
1965 ("Unsupported info element: %s (%d)\n",
1966 get_info_element_string(info_element
->id
),
1971 length
-= sizeof(*info_element
) + info_element
->len
;
1973 (struct ieee80211_info_element
*)&info_element
->
1974 data
[info_element
->len
];
1977 if (!network
->atheros_cap_exist
&& !network
->broadcom_cap_exist
&&
1978 !network
->cisco_cap_exist
&& !network
->ralink_cap_exist
&& !network
->bssht
.bdRT2RTAggregation
) {
1979 network
->unknown_cap_exist
= true;
1981 network
->unknown_cap_exist
= false;
1986 static inline u8
ieee80211_SignalStrengthTranslate(
1992 // Step 1. Scale mapping.
1993 if (CurrSS
>= 71 && CurrSS
<= 100) {
1994 RetSS
= 90 + ((CurrSS
- 70) / 3);
1995 } else if (CurrSS
>= 41 && CurrSS
<= 70) {
1996 RetSS
= 78 + ((CurrSS
- 40) / 3);
1997 } else if (CurrSS
>= 31 && CurrSS
<= 40) {
1998 RetSS
= 66 + (CurrSS
- 30);
1999 } else if (CurrSS
>= 21 && CurrSS
<= 30) {
2000 RetSS
= 54 + (CurrSS
- 20);
2001 } else if (CurrSS
>= 5 && CurrSS
<= 20) {
2002 RetSS
= 42 + (((CurrSS
- 5) * 2) / 3);
2003 } else if (CurrSS
== 4) {
2005 } else if (CurrSS
== 3) {
2007 } else if (CurrSS
== 2) {
2009 } else if (CurrSS
== 1) {
2014 //RT_TRACE(COMP_DBG, DBG_LOUD, ("##### After Mapping: LastSS: %d, CurrSS: %d, RetSS: %d\n", LastSS, CurrSS, RetSS));
2016 // Step 2. Smoothing.
2018 //RT_TRACE(COMP_DBG, DBG_LOUD, ("$$$$$ After Smoothing: LastSS: %d, CurrSS: %d, RetSS: %d\n", LastSS, CurrSS, RetSS));
2024 static long ieee80211_translate_todbm(u8 signal_strength_index
)
2026 long signal_power
; // in dBm.
2028 // Translate to dBm (x=0.5y-95).
2029 signal_power
= (long)((signal_strength_index
+ 1) >> 1);
2032 return signal_power
;
2035 static inline int ieee80211_network_init(
2036 struct ieee80211_device
*ieee
,
2037 struct ieee80211_probe_response
*beacon
,
2038 struct ieee80211_network
*network
,
2039 struct ieee80211_rx_stats
*stats
)
2041 #ifdef CONFIG_IEEE80211_DEBUG
2042 //char rates_str[64];
2046 network
->qos_data
.active
= 0;
2047 network
->qos_data
.supported
= 0;
2048 network
->qos_data
.param_count
= 0;
2049 network
->qos_data
.old_param_count
= 0;
2051 /* Pull out fixed field data */
2052 memcpy(network
->bssid
, beacon
->header
.addr3
, ETH_ALEN
);
2053 network
->capability
= le16_to_cpu(beacon
->capability
);
2054 network
->last_scanned
= jiffies
;
2055 network
->time_stamp
[0] = le32_to_cpu(beacon
->time_stamp
[0]);
2056 network
->time_stamp
[1] = le32_to_cpu(beacon
->time_stamp
[1]);
2057 network
->beacon_interval
= le16_to_cpu(beacon
->beacon_interval
);
2058 /* Where to pull this? beacon->listen_interval;*/
2059 network
->listen_interval
= 0x0A;
2060 network
->rates_len
= network
->rates_ex_len
= 0;
2061 network
->last_associate
= 0;
2062 network
->ssid_len
= 0;
2064 network
->atim_window
= 0;
2065 network
->erp_value
= (network
->capability
& WLAN_CAPABILITY_IBSS
) ?
2067 network
->berp_info_valid
= false;
2068 network
->broadcom_cap_exist
= false;
2069 network
->ralink_cap_exist
= false;
2070 network
->atheros_cap_exist
= false;
2071 network
->cisco_cap_exist
= false;
2072 network
->unknown_cap_exist
= false;
2074 network
->Turbo_Enable
= 0;
2076 network
->CountryIeLen
= 0;
2077 memset(network
->CountryIeBuf
, 0, MAX_IE_LEN
);
2078 //Initialize HT parameters
2079 //ieee80211_ht_initialize(&network->bssht);
2080 HTInitializeBssDesc(&network
->bssht
);
2081 if (stats
->freq
== IEEE80211_52GHZ_BAND
) {
2082 /* for A band (No DS info) */
2083 network
->channel
= stats
->received_channel
;
2085 network
->flags
|= NETWORK_HAS_CCK
;
2087 network
->wpa_ie_len
= 0;
2088 network
->rsn_ie_len
= 0;
2090 if (ieee80211_parse_info_param
2091 (ieee
, beacon
->info_element
, stats
->len
- sizeof(*beacon
), network
, stats
))
2095 if (stats
->freq
== IEEE80211_52GHZ_BAND
)
2096 network
->mode
= IEEE_A
;
2098 if (network
->flags
& NETWORK_HAS_OFDM
)
2099 network
->mode
|= IEEE_G
;
2100 if (network
->flags
& NETWORK_HAS_CCK
)
2101 network
->mode
|= IEEE_B
;
2104 if (network
->mode
== 0) {
2105 IEEE80211_DEBUG_SCAN("Filtered out '%s (%pM)' "
2107 escape_essid(network
->ssid
,
2113 if (network
->bssht
.bdSupportHT
) {
2114 if (network
->mode
== IEEE_A
)
2115 network
->mode
= IEEE_N_5G
;
2116 else if (network
->mode
& (IEEE_G
| IEEE_B
))
2117 network
->mode
= IEEE_N_24G
;
2119 if (ieee80211_is_empty_essid(network
->ssid
, network
->ssid_len
))
2120 network
->flags
|= NETWORK_EMPTY_ESSID
;
2122 stats
->signal
= 30 + (stats
->SignalStrength
* 70) / 100;
2123 //stats->signal = ieee80211_SignalStrengthTranslate(stats->signal);
2124 stats
->noise
= ieee80211_translate_todbm((u8
)(100 - stats
->signal
)) - 25;
2126 memcpy(&network
->stats
, stats
, sizeof(network
->stats
));
2131 static inline int is_same_network(struct ieee80211_network
*src
,
2132 struct ieee80211_network
*dst
, struct ieee80211_device
*ieee
)
2134 /* A network is only a duplicate if the channel, BSSID, ESSID
2135 * and the capability field (in particular IBSS and BSS) all match.
2136 * We treat all <hidden> with the same BSSID and channel
2138 return //((src->ssid_len == dst->ssid_len) &&
2139 (((src
->ssid_len
== dst
->ssid_len
) || (ieee
->iw_mode
== IW_MODE_INFRA
)) &&
2140 (src
->channel
== dst
->channel
) &&
2141 !memcmp(src
->bssid
, dst
->bssid
, ETH_ALEN
) &&
2142 //!memcmp(src->ssid, dst->ssid, src->ssid_len) &&
2143 (!memcmp(src
->ssid
, dst
->ssid
, src
->ssid_len
) || (ieee
->iw_mode
== IW_MODE_INFRA
)) &&
2144 ((src
->capability
& WLAN_CAPABILITY_IBSS
) ==
2145 (dst
->capability
& WLAN_CAPABILITY_IBSS
)) &&
2146 ((src
->capability
& WLAN_CAPABILITY_BSS
) ==
2147 (dst
->capability
& WLAN_CAPABILITY_BSS
)));
2150 static inline void update_network(struct ieee80211_network
*dst
,
2151 struct ieee80211_network
*src
)
2156 memcpy(&dst
->stats
, &src
->stats
, sizeof(struct ieee80211_rx_stats
));
2157 dst
->capability
= src
->capability
;
2158 memcpy(dst
->rates
, src
->rates
, src
->rates_len
);
2159 dst
->rates_len
= src
->rates_len
;
2160 memcpy(dst
->rates_ex
, src
->rates_ex
, src
->rates_ex_len
);
2161 dst
->rates_ex_len
= src
->rates_ex_len
;
2162 if (src
->ssid_len
> 0) {
2163 memset(dst
->ssid
, 0, dst
->ssid_len
);
2164 dst
->ssid_len
= src
->ssid_len
;
2165 memcpy(dst
->ssid
, src
->ssid
, src
->ssid_len
);
2167 dst
->mode
= src
->mode
;
2168 dst
->flags
= src
->flags
;
2169 dst
->time_stamp
[0] = src
->time_stamp
[0];
2170 dst
->time_stamp
[1] = src
->time_stamp
[1];
2171 if (src
->flags
& NETWORK_HAS_ERP_VALUE
) {
2172 dst
->erp_value
= src
->erp_value
;
2173 dst
->berp_info_valid
= src
->berp_info_valid
= true;
2175 dst
->beacon_interval
= src
->beacon_interval
;
2176 dst
->listen_interval
= src
->listen_interval
;
2177 dst
->atim_window
= src
->atim_window
;
2178 dst
->dtim_period
= src
->dtim_period
;
2179 dst
->dtim_data
= src
->dtim_data
;
2180 dst
->last_dtim_sta_time
[0] = src
->last_dtim_sta_time
[0];
2181 dst
->last_dtim_sta_time
[1] = src
->last_dtim_sta_time
[1];
2182 memcpy(&dst
->tim
, &src
->tim
, sizeof(struct ieee80211_tim_parameters
));
2184 dst
->bssht
.bdSupportHT
= src
->bssht
.bdSupportHT
;
2185 dst
->bssht
.bdRT2RTAggregation
= src
->bssht
.bdRT2RTAggregation
;
2186 dst
->bssht
.bdHTCapLen
= src
->bssht
.bdHTCapLen
;
2187 memcpy(dst
->bssht
.bdHTCapBuf
, src
->bssht
.bdHTCapBuf
, src
->bssht
.bdHTCapLen
);
2188 dst
->bssht
.bdHTInfoLen
= src
->bssht
.bdHTInfoLen
;
2189 memcpy(dst
->bssht
.bdHTInfoBuf
, src
->bssht
.bdHTInfoBuf
, src
->bssht
.bdHTInfoLen
);
2190 dst
->bssht
.bdHTSpecVer
= src
->bssht
.bdHTSpecVer
;
2191 dst
->bssht
.bdRT2RTLongSlotTime
= src
->bssht
.bdRT2RTLongSlotTime
;
2192 dst
->broadcom_cap_exist
= src
->broadcom_cap_exist
;
2193 dst
->ralink_cap_exist
= src
->ralink_cap_exist
;
2194 dst
->atheros_cap_exist
= src
->atheros_cap_exist
;
2195 dst
->cisco_cap_exist
= src
->cisco_cap_exist
;
2196 dst
->unknown_cap_exist
= src
->unknown_cap_exist
;
2197 memcpy(dst
->wpa_ie
, src
->wpa_ie
, src
->wpa_ie_len
);
2198 dst
->wpa_ie_len
= src
->wpa_ie_len
;
2199 memcpy(dst
->rsn_ie
, src
->rsn_ie
, src
->rsn_ie_len
);
2200 dst
->rsn_ie_len
= src
->rsn_ie_len
;
2202 dst
->last_scanned
= jiffies
;
2203 /* qos related parameters */
2204 //qos_active = src->qos_data.active;
2205 qos_active
= dst
->qos_data
.active
;
2206 //old_param = dst->qos_data.old_param_count;
2207 old_param
= dst
->qos_data
.param_count
;
2208 if (dst
->flags
& NETWORK_HAS_QOS_MASK
)
2209 memcpy(&dst
->qos_data
, &src
->qos_data
,
2210 sizeof(struct ieee80211_qos_data
));
2212 dst
->qos_data
.supported
= src
->qos_data
.supported
;
2213 dst
->qos_data
.param_count
= src
->qos_data
.param_count
;
2216 if (dst
->qos_data
.supported
== 1) {
2217 dst
->QoS_Enable
= 1;
2220 ("QoS the network %s is QoS supported\n",
2224 ("QoS the network is QoS supported\n");
2226 dst
->qos_data
.active
= qos_active
;
2227 dst
->qos_data
.old_param_count
= old_param
;
2229 /* dst->last_associate is not overwritten */
2230 dst
->wmm_info
= src
->wmm_info
; //sure to exist in beacon or probe response frame.
2231 if (src
->wmm_param
[0].aci_aifsn
|| \
2232 src
->wmm_param
[1].aci_aifsn
|| \
2233 src
->wmm_param
[2].aci_aifsn
|| \
2234 src
->wmm_param
[3].aci_aifsn
) {
2235 memcpy(dst
->wmm_param
, src
->wmm_param
, WME_AC_PRAM_LEN
);
2237 //dst->QoS_Enable = src->QoS_Enable;
2239 dst
->Turbo_Enable
= src
->Turbo_Enable
;
2242 dst
->CountryIeLen
= src
->CountryIeLen
;
2243 memcpy(dst
->CountryIeBuf
, src
->CountryIeBuf
, src
->CountryIeLen
);
2245 //added by amy for LEAP
2246 dst
->bWithAironetIE
= src
->bWithAironetIE
;
2247 dst
->bCkipSupported
= src
->bCkipSupported
;
2248 memcpy(dst
->CcxRmState
, src
->CcxRmState
, 2);
2249 dst
->bCcxRmEnable
= src
->bCcxRmEnable
;
2250 dst
->MBssidMask
= src
->MBssidMask
;
2251 dst
->bMBssidValid
= src
->bMBssidValid
;
2252 memcpy(dst
->MBssid
, src
->MBssid
, 6);
2253 dst
->bWithCcxVerNum
= src
->bWithCcxVerNum
;
2254 dst
->BssCcxVerNumber
= src
->BssCcxVerNumber
;
2258 static inline int is_beacon(__le16 fc
)
2260 return (WLAN_FC_GET_STYPE(le16_to_cpu(fc
)) == IEEE80211_STYPE_BEACON
);
2263 static inline void ieee80211_process_probe_response(
2264 struct ieee80211_device
*ieee
,
2265 struct ieee80211_probe_response
*beacon
,
2266 struct ieee80211_rx_stats
*stats
)
2268 struct ieee80211_network
*network
;
2269 struct ieee80211_network
*target
;
2270 struct ieee80211_network
*oldest
= NULL
;
2271 #ifdef CONFIG_IEEE80211_DEBUG
2272 struct ieee80211_info_element
*info_element
= &beacon
->info_element
[0];
2274 int fc
= WLAN_FC_GET_STYPE(le16_to_cpu(beacon
->header
.frame_ctl
));
2275 unsigned long flags
;
2280 network
= kzalloc(sizeof(*network
), GFP_ATOMIC
);
2284 capability
= le16_to_cpu(beacon
->capability
);
2285 IEEE80211_DEBUG_SCAN(
2286 "'%s' (%pM): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
2287 escape_essid(info_element
->data
, info_element
->len
),
2288 beacon
->header
.addr3
,
2289 (capability
& BIT(0xf)) ? '1' : '0',
2290 (capability
& BIT(0xe)) ? '1' : '0',
2291 (capability
& BIT(0xd)) ? '1' : '0',
2292 (capability
& BIT(0xc)) ? '1' : '0',
2293 (capability
& BIT(0xb)) ? '1' : '0',
2294 (capability
& BIT(0xa)) ? '1' : '0',
2295 (capability
& BIT(0x9)) ? '1' : '0',
2296 (capability
& BIT(0x8)) ? '1' : '0',
2297 (capability
& BIT(0x7)) ? '1' : '0',
2298 (capability
& BIT(0x6)) ? '1' : '0',
2299 (capability
& BIT(0x5)) ? '1' : '0',
2300 (capability
& BIT(0x4)) ? '1' : '0',
2301 (capability
& BIT(0x3)) ? '1' : '0',
2302 (capability
& BIT(0x2)) ? '1' : '0',
2303 (capability
& BIT(0x1)) ? '1' : '0',
2304 (capability
& BIT(0x0)) ? '1' : '0');
2306 if (ieee80211_network_init(ieee
, beacon
, network
, stats
)) {
2307 IEEE80211_DEBUG_SCAN("Dropped '%s' (%pM) via %s.\n",
2308 escape_essid(info_element
->data
,
2310 beacon
->header
.addr3
,
2311 fc
== IEEE80211_STYPE_PROBE_RESP
?
2312 "PROBE RESPONSE" : "BEACON");
2316 // For Asus EeePc request,
2317 // (1) if wireless adapter receive get any 802.11d country code in AP beacon,
2318 // wireless adapter should follow the country code.
2319 // (2) If there is no any country code in beacon,
2320 // then wireless adapter should do active scan from ch1~11 and
2321 // passive scan from ch12~14
2323 if (!is_legal_channel(ieee
, network
->channel
))
2325 if (ieee
->bGlobalDomain
) {
2326 if (fc
== IEEE80211_STYPE_PROBE_RESP
) {
2327 if (IS_COUNTRY_IE_VALID(ieee
)) {
2328 // Case 1: Country code
2329 if (!is_legal_channel(ieee
, network
->channel
)) {
2330 netdev_warn(ieee
->dev
, "GetScanInfo(): For Country code, filter probe response at channel(%d).\n", network
->channel
);
2334 // Case 2: No any country code.
2335 // Filter over channel ch12~14
2336 if (network
->channel
> 11) {
2337 netdev_warn(ieee
->dev
, "GetScanInfo(): For Global Domain, filter probe response at channel(%d).\n", network
->channel
);
2342 if (IS_COUNTRY_IE_VALID(ieee
)) {
2343 // Case 1: Country code
2344 if (!is_legal_channel(ieee
, network
->channel
)) {
2345 netdev_warn(ieee
->dev
, "GetScanInfo(): For Country code, filter beacon at channel(%d).\n", network
->channel
);
2349 // Case 2: No any country code.
2350 // Filter over channel ch12~14
2351 if (network
->channel
> 14) {
2352 netdev_warn(ieee
->dev
, "GetScanInfo(): For Global Domain, filter beacon at channel(%d).\n", network
->channel
);
2359 /* The network parsed correctly -- so now we scan our known networks
2360 * to see if we can find it in our list.
2362 * NOTE: This search is definitely not optimized. Once its doing
2363 * the "right thing" we'll optimize it for efficiency if
2366 /* Search for this entry in the list and update it if it is
2369 spin_lock_irqsave(&ieee
->lock
, flags
);
2371 if (is_same_network(&ieee
->current_network
, network
, ieee
)) {
2372 update_network(&ieee
->current_network
, network
);
2373 if ((ieee
->current_network
.mode
== IEEE_N_24G
|| ieee
->current_network
.mode
== IEEE_G
)
2374 && ieee
->current_network
.berp_info_valid
){
2375 if (ieee
->current_network
.erp_value
& ERP_UseProtection
)
2376 ieee
->current_network
.buseprotection
= true;
2378 ieee
->current_network
.buseprotection
= false;
2380 if (is_beacon(beacon
->header
.frame_ctl
)) {
2381 if (ieee
->state
== IEEE80211_LINKED
)
2382 ieee
->LinkDetectInfo
.NumRecvBcnInPeriod
++;
2384 network
->flags
= (~NETWORK_EMPTY_ESSID
& network
->flags
) | (NETWORK_EMPTY_ESSID
& ieee
->current_network
.flags
);
2387 list_for_each_entry(target
, &ieee
->network_list
, list
) {
2388 if (is_same_network(target
, network
, ieee
))
2391 (target
->last_scanned
< oldest
->last_scanned
))
2395 /* If we didn't find a match, then get a new network slot to initialize
2396 * with this beacon's information */
2397 if (&target
->list
== &ieee
->network_list
) {
2398 if (list_empty(&ieee
->network_free_list
)) {
2399 /* If there are no more slots, expire the oldest */
2400 list_del(&oldest
->list
);
2402 IEEE80211_DEBUG_SCAN("Expired '%s' (%pM) from "
2404 escape_essid(target
->ssid
,
2408 /* Otherwise just pull from the free list */
2409 target
= list_entry(ieee
->network_free_list
.next
,
2410 struct ieee80211_network
, list
);
2411 list_del(ieee
->network_free_list
.next
);
2415 #ifdef CONFIG_IEEE80211_DEBUG
2416 IEEE80211_DEBUG_SCAN("Adding '%s' (%pM) via %s.\n",
2417 escape_essid(network
->ssid
,
2420 fc
== IEEE80211_STYPE_PROBE_RESP
?
2421 "PROBE RESPONSE" : "BEACON");
2423 memcpy(target
, network
, sizeof(*target
));
2424 list_add_tail(&target
->list
, &ieee
->network_list
);
2425 if (ieee
->softmac_features
& IEEE_SOFTMAC_ASSOCIATE
)
2426 ieee80211_softmac_new_net(ieee
, network
);
2428 IEEE80211_DEBUG_SCAN("Updating '%s' (%pM) via %s.\n",
2429 escape_essid(target
->ssid
,
2432 fc
== IEEE80211_STYPE_PROBE_RESP
?
2433 "PROBE RESPONSE" : "BEACON");
2435 /* we have an entry and we are going to update it. But this entry may
2436 * be already expired. In this case we do the same as we found a new
2437 * net and call the new_net handler
2439 renew
= !time_after(target
->last_scanned
+ ieee
->scan_age
, jiffies
);
2440 //YJ,add,080819,for hidden ap
2441 if (is_beacon(beacon
->header
.frame_ctl
) == 0)
2442 network
->flags
= (~NETWORK_EMPTY_ESSID
& network
->flags
) | (NETWORK_EMPTY_ESSID
& target
->flags
);
2443 //if(strncmp(network->ssid, "linksys-c",9) == 0)
2444 // printk("====>2 network->ssid=%s FLAG=%d target.ssid=%s FLAG=%d\n", network->ssid, network->flags, target->ssid, target->flags);
2445 if (((network
->flags
& NETWORK_EMPTY_ESSID
) == NETWORK_EMPTY_ESSID
) \
2446 && (((network
->ssid_len
> 0) && (strncmp(target
->ssid
, network
->ssid
, network
->ssid_len
)))\
2447 || ((ieee
->current_network
.ssid_len
== network
->ssid_len
) && (strncmp(ieee
->current_network
.ssid
, network
->ssid
, network
->ssid_len
) == 0) && (ieee
->state
== IEEE80211_NOLINK
))))
2449 //YJ,add,080819,for hidden ap,end
2451 update_network(target
, network
);
2452 if (renew
&& (ieee
->softmac_features
& IEEE_SOFTMAC_ASSOCIATE
))
2453 ieee80211_softmac_new_net(ieee
, network
);
2456 spin_unlock_irqrestore(&ieee
->lock
, flags
);
2457 if (is_beacon(beacon
->header
.frame_ctl
) && is_same_network(&ieee
->current_network
, network
, ieee
) && \
2458 (ieee
->state
== IEEE80211_LINKED
)) {
2459 if (ieee
->handle_beacon
)
2460 ieee
->handle_beacon(ieee
->dev
, beacon
, &ieee
->current_network
);
2467 void ieee80211_rx_mgt(struct ieee80211_device
*ieee
,
2468 struct rtl_80211_hdr_4addr
*header
,
2469 struct ieee80211_rx_stats
*stats
)
2471 switch (WLAN_FC_GET_STYPE(le16_to_cpu(header
->frame_ctl
))) {
2473 case IEEE80211_STYPE_BEACON
:
2474 IEEE80211_DEBUG_MGMT("received BEACON (%d)\n",
2475 WLAN_FC_GET_STYPE(le16_to_cpu(header
->frame_ctl
)));
2476 IEEE80211_DEBUG_SCAN("Beacon\n");
2477 ieee80211_process_probe_response(
2478 ieee
, (struct ieee80211_probe_response
*)header
, stats
);
2481 case IEEE80211_STYPE_PROBE_RESP
:
2482 IEEE80211_DEBUG_MGMT("received PROBE RESPONSE (%d)\n",
2483 WLAN_FC_GET_STYPE(le16_to_cpu(header
->frame_ctl
)));
2484 IEEE80211_DEBUG_SCAN("Probe response\n");
2485 ieee80211_process_probe_response(
2486 ieee
, (struct ieee80211_probe_response
*)header
, stats
);
2491 EXPORT_SYMBOL(ieee80211_rx_mgt
);