]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - drivers/staging/rtl8192e/rtllib_rx.c
staging: rtl8192e: remove unused EXPORT_SYMBOL_RSL macro
[mirror_ubuntu-hirsute-kernel.git] / drivers / staging / rtl8192e / rtllib_rx.c
CommitLineData
94a79942
LF
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
559a4c31 17 Andrea Merello <andrea.merello@gmail.com>
94a79942
LF
18
19 A special thanks goes to Realtek for their support !
20
21******************************************************************************/
22
23
24#include <linux/compiler.h>
25#include <linux/errno.h>
26#include <linux/if_arp.h>
27#include <linux/in6.h>
28#include <linux/in.h>
29#include <linux/ip.h>
30#include <linux/kernel.h>
31#include <linux/module.h>
32#include <linux/netdevice.h>
33#include <linux/pci.h>
34#include <linux/proc_fs.h>
35#include <linux/skbuff.h>
36#include <linux/slab.h>
37#include <linux/tcp.h>
38#include <linux/types.h>
94a79942
LF
39#include <linux/wireless.h>
40#include <linux/etherdevice.h>
db8971b6 41#include <linux/uaccess.h>
94a79942
LF
42#include <linux/ctype.h>
43
44#include "rtllib.h"
94a79942 45#include "dot11d.h"
94a79942 46
94a79942 47static inline void rtllib_monitor_rx(struct rtllib_device *ieee,
db8971b6 48 struct sk_buff *skb, struct rtllib_rx_stats *rx_status,
94a79942
LF
49 size_t hdr_length)
50{
94a79942 51 skb->dev = ieee->dev;
db8971b6 52 skb_reset_mac_header(skb);
94a79942
LF
53 skb_pull(skb, hdr_length);
54 skb->pkt_type = PACKET_OTHERHOST;
3f76a4ea 55 skb->protocol = htons(ETH_P_80211_RAW);
94a79942
LF
56 memset(skb->cb, 0, sizeof(skb->cb));
57 netif_rx(skb);
94a79942
LF
58}
59
60/* Called only as a tasklet (software IRQ) */
61static struct rtllib_frag_entry *
62rtllib_frag_cache_find(struct rtllib_device *ieee, unsigned int seq,
db8971b6 63 unsigned int frag, u8 tid, u8 *src, u8 *dst)
94a79942
LF
64{
65 struct rtllib_frag_entry *entry;
66 int i;
67
68 for (i = 0; i < RTLLIB_FRAG_CACHE_LEN; i++) {
69 entry = &ieee->frag_cache[tid][i];
70 if (entry->skb != NULL &&
71 time_after(jiffies, entry->first_frag_time + 2 * HZ)) {
72 RTLLIB_DEBUG_FRAG(
6d6163c3 73 "expiring fragment cache entry seq=%u last_frag=%u\n",
94a79942
LF
74 entry->seq, entry->last_frag);
75 dev_kfree_skb_any(entry->skb);
76 entry->skb = NULL;
77 }
78
79 if (entry->skb != NULL && entry->seq == seq &&
80 (entry->last_frag + 1 == frag || frag == -1) &&
81 memcmp(entry->src_addr, src, ETH_ALEN) == 0 &&
82 memcmp(entry->dst_addr, dst, ETH_ALEN) == 0)
83 return entry;
84 }
85
86 return NULL;
87}
88
89/* Called only as a tasklet (software IRQ) */
90static struct sk_buff *
91rtllib_frag_cache_get(struct rtllib_device *ieee,
92 struct rtllib_hdr_4addr *hdr)
93{
94 struct sk_buff *skb = NULL;
95 u16 fc = le16_to_cpu(hdr->frame_ctl);
96 u16 sc = le16_to_cpu(hdr->seq_ctl);
97 unsigned int frag = WLAN_GET_SEQ_FRAG(sc);
98 unsigned int seq = WLAN_GET_SEQ_SEQ(sc);
99 struct rtllib_frag_entry *entry;
100 struct rtllib_hdr_3addrqos *hdr_3addrqos;
101 struct rtllib_hdr_4addrqos *hdr_4addrqos;
102 u8 tid;
103
db8971b6
LF
104 if (((fc & RTLLIB_FCTL_DSTODS) == RTLLIB_FCTL_DSTODS) && RTLLIB_QOS_HAS_SEQ(fc)) {
105 hdr_4addrqos = (struct rtllib_hdr_4addrqos *)hdr;
106 tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & RTLLIB_QCTL_TID;
107 tid = UP2AC(tid);
108 tid++;
94a79942 109 } else if (RTLLIB_QOS_HAS_SEQ(fc)) {
db8971b6
LF
110 hdr_3addrqos = (struct rtllib_hdr_3addrqos *)hdr;
111 tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & RTLLIB_QCTL_TID;
112 tid = UP2AC(tid);
113 tid++;
94a79942 114 } else {
db8971b6 115 tid = 0;
94a79942
LF
116 }
117
118 if (frag == 0) {
119 /* Reserve enough space to fit maximum frame length */
120 skb = dev_alloc_skb(ieee->dev->mtu +
121 sizeof(struct rtllib_hdr_4addr) +
122 8 /* LLC */ +
123 2 /* alignment */ +
124 8 /* WEP */ +
125 ETH_ALEN /* WDS */ +
db8971b6 126 (RTLLIB_QOS_HAS_SEQ(fc) ? 2 : 0) /* QOS Control */);
94a79942
LF
127 if (skb == NULL)
128 return NULL;
129
130 entry = &ieee->frag_cache[tid][ieee->frag_next_idx[tid]];
131 ieee->frag_next_idx[tid]++;
132 if (ieee->frag_next_idx[tid] >= RTLLIB_FRAG_CACHE_LEN)
133 ieee->frag_next_idx[tid] = 0;
134
135 if (entry->skb != NULL)
136 dev_kfree_skb_any(entry->skb);
137
138 entry->first_frag_time = jiffies;
139 entry->seq = seq;
140 entry->last_frag = frag;
141 entry->skb = skb;
142 memcpy(entry->src_addr, hdr->addr2, ETH_ALEN);
143 memcpy(entry->dst_addr, hdr->addr1, ETH_ALEN);
144 } else {
145 /* received a fragment of a frame for which the head fragment
146 * should have already been received */
db8971b6 147 entry = rtllib_frag_cache_find(ieee, seq, frag, tid, hdr->addr2,
94a79942
LF
148 hdr->addr1);
149 if (entry != NULL) {
150 entry->last_frag = frag;
151 skb = entry->skb;
152 }
153 }
154
155 return skb;
156}
157
158
159/* Called only as a tasklet (software IRQ) */
160static int rtllib_frag_cache_invalidate(struct rtllib_device *ieee,
161 struct rtllib_hdr_4addr *hdr)
162{
163 u16 fc = le16_to_cpu(hdr->frame_ctl);
164 u16 sc = le16_to_cpu(hdr->seq_ctl);
165 unsigned int seq = WLAN_GET_SEQ_SEQ(sc);
166 struct rtllib_frag_entry *entry;
167 struct rtllib_hdr_3addrqos *hdr_3addrqos;
168 struct rtllib_hdr_4addrqos *hdr_4addrqos;
169 u8 tid;
170
db8971b6
LF
171 if (((fc & RTLLIB_FCTL_DSTODS) == RTLLIB_FCTL_DSTODS) && RTLLIB_QOS_HAS_SEQ(fc)) {
172 hdr_4addrqos = (struct rtllib_hdr_4addrqos *)hdr;
173 tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & RTLLIB_QCTL_TID;
174 tid = UP2AC(tid);
175 tid++;
94a79942 176 } else if (RTLLIB_QOS_HAS_SEQ(fc)) {
db8971b6
LF
177 hdr_3addrqos = (struct rtllib_hdr_3addrqos *)hdr;
178 tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & RTLLIB_QCTL_TID;
179 tid = UP2AC(tid);
180 tid++;
94a79942 181 } else {
db8971b6 182 tid = 0;
94a79942
LF
183 }
184
db8971b6 185 entry = rtllib_frag_cache_find(ieee, seq, -1, tid, hdr->addr2,
94a79942
LF
186 hdr->addr1);
187
188 if (entry == NULL) {
189 RTLLIB_DEBUG_FRAG(
6d6163c3 190 "could not invalidate fragment cache entry (seq=%u)\n", seq);
94a79942
LF
191 return -1;
192 }
193
194 entry->skb = NULL;
195 return 0;
196}
197
94a79942
LF
198/* rtllib_rx_frame_mgtmt
199 *
200 * Responsible for handling management control frames
201 *
202 * Called by rtllib_rx */
203static inline int
204rtllib_rx_frame_mgmt(struct rtllib_device *ieee, struct sk_buff *skb,
205 struct rtllib_rx_stats *rx_stats, u16 type,
206 u16 stype)
207{
208 /* On the struct stats definition there is written that
209 * this is not mandatory.... but seems that the probe
210 * response parser uses it
211 */
a0711c4d 212 struct rtllib_hdr_3addr *hdr = (struct rtllib_hdr_3addr *)skb->data;
94a79942
LF
213
214 rx_stats->len = skb->len;
db8971b6 215 rtllib_rx_mgt(ieee, skb, rx_stats);
94a79942
LF
216 if ((memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN))) {
217 dev_kfree_skb_any(skb);
218 return 0;
219 }
220 rtllib_rx_frame_softmac(ieee, skb, rx_stats, type, stype);
221
222 dev_kfree_skb_any(skb);
223
224 return 0;
94a79942
LF
225}
226
94a79942
LF
227/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
228/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
db8971b6
LF
229static unsigned char rfc1042_header[] = {
230 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00
231};
94a79942 232/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
db8971b6
LF
233static unsigned char bridge_tunnel_header[] = {
234 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8
235};
94a79942 236/* No encapsulation header if EtherType < 0x600 (=length) */
94a79942
LF
237
238/* Called by rtllib_rx_frame_decrypt */
239static int rtllib_is_eapol_frame(struct rtllib_device *ieee,
240 struct sk_buff *skb, size_t hdrlen)
241{
242 struct net_device *dev = ieee->dev;
243 u16 fc, ethertype;
244 struct rtllib_hdr_4addr *hdr;
245 u8 *pos;
246
247 if (skb->len < 24)
248 return 0;
249
250 hdr = (struct rtllib_hdr_4addr *) skb->data;
251 fc = le16_to_cpu(hdr->frame_ctl);
252
253 /* check that the frame is unicast frame to us */
254 if ((fc & (RTLLIB_FCTL_TODS | RTLLIB_FCTL_FROMDS)) ==
255 RTLLIB_FCTL_TODS &&
256 memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0 &&
257 memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0) {
258 /* ToDS frame with own addr BSSID and DA */
259 } else if ((fc & (RTLLIB_FCTL_TODS | RTLLIB_FCTL_FROMDS)) ==
260 RTLLIB_FCTL_FROMDS &&
261 memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) {
262 /* FromDS frame with own addr as DA */
263 } else
264 return 0;
265
266 if (skb->len < 24 + 8)
267 return 0;
268
269 /* check for port access entity Ethernet type */
270 pos = skb->data + hdrlen;
271 ethertype = (pos[6] << 8) | pos[7];
272 if (ethertype == ETH_P_PAE)
273 return 1;
274
275 return 0;
276}
277
278/* Called only as a tasklet (software IRQ), by rtllib_rx */
279static inline int
db8971b6 280rtllib_rx_frame_decrypt(struct rtllib_device *ieee, struct sk_buff *skb,
32c44cb5 281 struct lib80211_crypt_data *crypt)
94a79942
LF
282{
283 struct rtllib_hdr_4addr *hdr;
284 int res, hdrlen;
285
286 if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL)
287 return 0;
4f6807e8 288
db8971b6
LF
289 if (ieee->hwsec_active) {
290 struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
3a6b70c3 291
94a79942
LF
292 tcb_desc->bHwSec = 1;
293
294 if (ieee->need_sw_enc)
295 tcb_desc->bHwSec = 0;
296 }
4f6807e8 297
94a79942
LF
298 hdr = (struct rtllib_hdr_4addr *) skb->data;
299 hdrlen = rtllib_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
300
94a79942
LF
301 atomic_inc(&crypt->refcnt);
302 res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
303 atomic_dec(&crypt->refcnt);
304 if (res < 0) {
305 RTLLIB_DEBUG_DROP(
6d6163c3 306 "decryption failed (SA= %pM) res=%d\n", hdr->addr2, res);
94a79942 307 if (res == -2)
6d6163c3 308 RTLLIB_DEBUG_DROP("Decryption failed ICV mismatch (key %d)\n",
94a79942
LF
309 skb->data[hdrlen + 3] >> 6);
310 ieee->ieee_stats.rx_discards_undecryptable++;
311 return -1;
312 }
313
314 return res;
315}
316
317
318/* Called only as a tasklet (software IRQ), by rtllib_rx */
319static inline int
db8971b6 320rtllib_rx_frame_decrypt_msdu(struct rtllib_device *ieee, struct sk_buff *skb,
32c44cb5 321 int keyidx, struct lib80211_crypt_data *crypt)
94a79942
LF
322{
323 struct rtllib_hdr_4addr *hdr;
324 int res, hdrlen;
325
326 if (crypt == NULL || crypt->ops->decrypt_msdu == NULL)
327 return 0;
db8971b6
LF
328 if (ieee->hwsec_active) {
329 struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
3a6b70c3 330
94a79942
LF
331 tcb_desc->bHwSec = 1;
332
333 if (ieee->need_sw_enc)
334 tcb_desc->bHwSec = 0;
335 }
336
337 hdr = (struct rtllib_hdr_4addr *) skb->data;
338 hdrlen = rtllib_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
339
340 atomic_inc(&crypt->refcnt);
32c44cb5 341 res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv);
94a79942
LF
342 atomic_dec(&crypt->refcnt);
343 if (res < 0) {
6d6163c3 344 printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed (SA= %pM keyidx=%d)\n",
ac50ddaa 345 ieee->dev->name, hdr->addr2, keyidx);
94a79942
LF
346 return -1;
347 }
348
349 return 0;
350}
351
352
353/* this function is stolen from ipw2200 driver*/
354#define IEEE_PACKET_RETRY_TIME (5*HZ)
355static int is_duplicate_packet(struct rtllib_device *ieee,
356 struct rtllib_hdr_4addr *header)
357{
358 u16 fc = le16_to_cpu(header->frame_ctl);
359 u16 sc = le16_to_cpu(header->seq_ctl);
360 u16 seq = WLAN_GET_SEQ_SEQ(sc);
361 u16 frag = WLAN_GET_SEQ_FRAG(sc);
362 u16 *last_seq, *last_frag;
363 unsigned long *last_time;
364 struct rtllib_hdr_3addrqos *hdr_3addrqos;
365 struct rtllib_hdr_4addrqos *hdr_4addrqos;
366 u8 tid;
367
db8971b6
LF
368 if (((fc & RTLLIB_FCTL_DSTODS) == RTLLIB_FCTL_DSTODS) && RTLLIB_QOS_HAS_SEQ(fc)) {
369 hdr_4addrqos = (struct rtllib_hdr_4addrqos *)header;
370 tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & RTLLIB_QCTL_TID;
371 tid = UP2AC(tid);
372 tid++;
94a79942 373 } else if (RTLLIB_QOS_HAS_SEQ(fc)) {
db8971b6
LF
374 hdr_3addrqos = (struct rtllib_hdr_3addrqos *)header;
375 tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & RTLLIB_QCTL_TID;
376 tid = UP2AC(tid);
377 tid++;
94a79942 378 } else {
db8971b6 379 tid = 0;
94a79942
LF
380 }
381
382 switch (ieee->iw_mode) {
383 case IW_MODE_ADHOC:
384 {
385 struct list_head *p;
386 struct ieee_ibss_seq *entry = NULL;
387 u8 *mac = header->addr2;
388 int index = mac[5] % IEEE_IBSS_MAC_HASH_SIZE;
3a6b70c3 389
94a79942
LF
390 list_for_each(p, &ieee->ibss_mac_hash[index]) {
391 entry = list_entry(p, struct ieee_ibss_seq, list);
392 if (!memcmp(entry->mac, mac, ETH_ALEN))
393 break;
394 }
395 if (p == &ieee->ibss_mac_hash[index]) {
396 entry = kmalloc(sizeof(struct ieee_ibss_seq), GFP_ATOMIC);
b6b0012c 397 if (!entry)
94a79942 398 return 0;
b6b0012c 399
94a79942
LF
400 memcpy(entry->mac, mac, ETH_ALEN);
401 entry->seq_num[tid] = seq;
402 entry->frag_num[tid] = frag;
403 entry->packet_time[tid] = jiffies;
404 list_add(&entry->list, &ieee->ibss_mac_hash[index]);
405 return 0;
406 }
407 last_seq = &entry->seq_num[tid];
408 last_frag = &entry->frag_num[tid];
409 last_time = &entry->packet_time[tid];
410 break;
411 }
412
413 case IW_MODE_INFRA:
414 last_seq = &ieee->last_rxseq_num[tid];
415 last_frag = &ieee->last_rxfrag_num[tid];
416 last_time = &ieee->last_packet_time[tid];
417 break;
418 default:
419 return 0;
420 }
421
422 if ((*last_seq == seq) &&
423 time_after(*last_time + IEEE_PACKET_RETRY_TIME, jiffies)) {
db8971b6 424 if (*last_frag == frag)
94a79942 425 goto drop;
94a79942
LF
426 if (*last_frag + 1 != frag)
427 /* out-of-order fragment */
428 goto drop;
429 } else
430 *last_seq = seq;
431
432 *last_frag = frag;
433 *last_time = jiffies;
434 return 0;
435
436drop:
437
438 return 1;
439}
db8971b6 440
49aab5fd
LF
441static bool AddReorderEntry(struct rx_ts_record *pTS,
442 struct rx_reorder_entry *pReorderEntry)
94a79942
LF
443{
444 struct list_head *pList = &pTS->RxPendingPktList;
445
db8971b6 446 while (pList->next != &pTS->RxPendingPktList) {
49aab5fd
LF
447 if (SN_LESS(pReorderEntry->SeqNum, ((struct rx_reorder_entry *)
448 list_entry(pList->next, struct rx_reorder_entry,
449 List))->SeqNum))
94a79942 450 pList = pList->next;
49aab5fd
LF
451 else if (SN_EQUAL(pReorderEntry->SeqNum,
452 ((struct rx_reorder_entry *)list_entry(pList->next,
453 struct rx_reorder_entry, List))->SeqNum))
454 return false;
94a79942 455 else
94a79942 456 break;
94a79942
LF
457 }
458 pReorderEntry->List.next = pList->next;
459 pReorderEntry->List.next->prev = &pReorderEntry->List;
460 pReorderEntry->List.prev = pList;
461 pList->next = &pReorderEntry->List;
462
463 return true;
464}
465
db8971b6 466void rtllib_indicate_packets(struct rtllib_device *ieee, struct rtllib_rxb **prxbIndicateArray, u8 index)
94a79942
LF
467{
468 struct net_device_stats *stats = &ieee->stats;
db8971b6 469 u8 i = 0 , j = 0;
94a79942 470 u16 ethertype;
3a6b70c3 471
94a79942 472 for (j = 0; j < index; j++) {
db8971b6 473 struct rtllib_rxb *prxb = prxbIndicateArray[j];
3a6b70c3 474
db8971b6 475 for (i = 0; i < prxb->nr_subframes; i++) {
94a79942
LF
476 struct sk_buff *sub_skb = prxb->subframes[i];
477
478 /* convert hdr + possible LLC headers into Ethernet header */
479 ethertype = (sub_skb->data[6] << 8) | sub_skb->data[7];
480 if (sub_skb->len >= 8 &&
db8971b6
LF
481 ((memcmp(sub_skb->data, rfc1042_header, SNAP_SIZE) == 0 &&
482 ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
483 memcmp(sub_skb->data, bridge_tunnel_header, SNAP_SIZE) == 0)) {
484 /* remove RFC1042 or Bridge-Tunnel encapsulation
485 * and replace EtherType */
94a79942
LF
486 skb_pull(sub_skb, SNAP_SIZE);
487 memcpy(skb_push(sub_skb, ETH_ALEN), prxb->src, ETH_ALEN);
488 memcpy(skb_push(sub_skb, ETH_ALEN), prxb->dst, ETH_ALEN);
489 } else {
490 u16 len;
491 /* Leave Ethernet header part of hdr and full payload */
1f5a0d0c 492 len = sub_skb->len;
94a79942
LF
493 memcpy(skb_push(sub_skb, 2), &len, 2);
494 memcpy(skb_push(sub_skb, ETH_ALEN), prxb->src, ETH_ALEN);
495 memcpy(skb_push(sub_skb, ETH_ALEN), prxb->dst, ETH_ALEN);
496 }
497
cd017123 498 /* Indicate the packets to upper layer */
94a79942
LF
499 if (sub_skb) {
500 stats->rx_packets++;
501 stats->rx_bytes += sub_skb->len;
502
503 memset(sub_skb->cb, 0, sizeof(sub_skb->cb));
504 sub_skb->protocol = eth_type_trans(sub_skb, ieee->dev);
505 sub_skb->dev = ieee->dev;
506 sub_skb->dev->stats.rx_packets++;
507 sub_skb->dev->stats.rx_bytes += sub_skb->len;
94a79942 508 sub_skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */
94a79942
LF
509 ieee->last_rx_ps_time = jiffies;
510 netif_rx(sub_skb);
511 }
512 }
513 kfree(prxb);
514 prxb = NULL;
515 }
516}
517
db8971b6 518void rtllib_FlushRxTsPendingPkts(struct rtllib_device *ieee, struct rx_ts_record *pTS)
94a79942 519{
8cba1432 520 struct rx_reorder_entry *pRxReorderEntry;
db8971b6 521 u8 RfdCnt = 0;
94a79942
LF
522
523 del_timer_sync(&pTS->RxPktPendingTimer);
db8971b6
LF
524 while (!list_empty(&pTS->RxPendingPktList)) {
525 if (RfdCnt >= REORDER_WIN_SIZE) {
d69d2054
MK
526 netdev_info(ieee->dev,
527 "-------------->%s() error! RfdCnt >= REORDER_WIN_SIZE\n",
528 __func__);
94a79942
LF
529 break;
530 }
531
db8971b6
LF
532 pRxReorderEntry = (struct rx_reorder_entry *)list_entry(pTS->RxPendingPktList.prev, struct rx_reorder_entry, List);
533 RTLLIB_DEBUG(RTLLIB_DL_REORDER, "%s(): Indicate SeqNum %d!\n", __func__, pRxReorderEntry->SeqNum);
94a79942
LF
534 list_del_init(&pRxReorderEntry->List);
535
2eed3dee 536 ieee->RfdArray[RfdCnt] = pRxReorderEntry->prxb;
94a79942
LF
537
538 RfdCnt = RfdCnt + 1;
539 list_add_tail(&pRxReorderEntry->List, &ieee->RxReorder_Unused_List);
540 }
2eed3dee 541 rtllib_indicate_packets(ieee, ieee->RfdArray, RfdCnt);
94a79942
LF
542
543 pTS->RxIndicateSeq = 0xffff;
94a79942
LF
544}
545
49aab5fd
LF
546static void RxReorderIndicatePacket(struct rtllib_device *ieee,
547 struct rtllib_rxb *prxb,
548 struct rx_ts_record *pTS, u16 SeqNum)
94a79942 549{
7796d93e 550 struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
8cba1432 551 struct rx_reorder_entry *pReorderEntry = NULL;
db8971b6
LF
552 u8 WinSize = pHTInfo->RxReorderWinSize;
553 u16 WinEnd = 0;
554 u8 index = 0;
555 bool bMatchWinStart = false, bPktInBuf = false;
94a79942
LF
556 unsigned long flags;
557
6d6163c3 558 RTLLIB_DEBUG(RTLLIB_DL_REORDER, "%s(): Seq is %d, pTS->RxIndicateSeq is %d, WinSize is %d\n", __func__, SeqNum,
db8971b6 559 pTS->RxIndicateSeq, WinSize);
94a79942
LF
560
561 spin_lock_irqsave(&(ieee->reorder_spinlock), flags);
562
db8971b6 563 WinEnd = (pTS->RxIndicateSeq + WinSize - 1) % 4096;
94a79942 564 /* Rx Reorder initialize condition.*/
db8971b6 565 if (pTS->RxIndicateSeq == 0xffff)
94a79942 566 pTS->RxIndicateSeq = SeqNum;
94a79942
LF
567
568 /* Drop out the packet which SeqNum is smaller than WinStart */
569 if (SN_LESS(SeqNum, pTS->RxIndicateSeq)) {
db8971b6 570 RTLLIB_DEBUG(RTLLIB_DL_REORDER, "Packet Drop! IndicateSeq: %d, NewSeq: %d\n",
94a79942
LF
571 pTS->RxIndicateSeq, SeqNum);
572 pHTInfo->RxReorderDropCounter++;
573 {
574 int i;
3a6b70c3 575
db8971b6 576 for (i = 0; i < prxb->nr_subframes; i++)
94a79942 577 dev_kfree_skb(prxb->subframes[i]);
94a79942
LF
578 kfree(prxb);
579 prxb = NULL;
580 }
581 spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
582 return;
583 }
584
585 /*
586 * Sliding window manipulation. Conditions includes:
587 * 1. Incoming SeqNum is equal to WinStart =>Window shift 1
588 * 2. Incoming SeqNum is larger than the WinEnd => Window shift N
589 */
590 if (SN_EQUAL(SeqNum, pTS->RxIndicateSeq)) {
591 pTS->RxIndicateSeq = (pTS->RxIndicateSeq + 1) % 4096;
592 bMatchWinStart = true;
593 } else if (SN_LESS(WinEnd, SeqNum)) {
db8971b6
LF
594 if (SeqNum >= (WinSize - 1))
595 pTS->RxIndicateSeq = SeqNum + 1 - WinSize;
596 else
597 pTS->RxIndicateSeq = 4095 - (WinSize - (SeqNum + 1)) + 1;
6d6163c3 598 RTLLIB_DEBUG(RTLLIB_DL_REORDER, "Window Shift! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, SeqNum);
94a79942
LF
599 }
600
601 /*
602 * Indication process.
db8971b6
LF
603 * After Packet dropping and Sliding Window shifting as above, we can
604 * now just indicate the packets with the SeqNum smaller than latest
605 * WinStart and struct buffer other packets.
94a79942
LF
606 */
607 /* For Rx Reorder condition:
608 * 1. All packets with SeqNum smaller than WinStart => Indicate
db8971b6
LF
609 * 2. All packets with SeqNum larger than or equal to
610 * WinStart => Buffer it.
94a79942
LF
611 */
612 if (bMatchWinStart) {
613 /* Current packet is going to be indicated.*/
6d6163c3 614 RTLLIB_DEBUG(RTLLIB_DL_REORDER, "Packets indication!! IndicateSeq: %d, NewSeq: %d\n",
94a79942 615 pTS->RxIndicateSeq, SeqNum);
2eed3dee 616 ieee->prxbIndicateArray[0] = prxb;
94a79942
LF
617 index = 1;
618 } else {
619 /* Current packet is going to be inserted into pending list.*/
620 if (!list_empty(&ieee->RxReorder_Unused_List)) {
db8971b6
LF
621 pReorderEntry = (struct rx_reorder_entry *)
622 list_entry(ieee->RxReorder_Unused_List.next,
623 struct rx_reorder_entry, List);
94a79942
LF
624 list_del_init(&pReorderEntry->List);
625
626 /* Make a reorder entry and insert into a the packet list.*/
627 pReorderEntry->SeqNum = SeqNum;
628 pReorderEntry->prxb = prxb;
629
94a79942 630 if (!AddReorderEntry(pTS, pReorderEntry)) {
db8971b6 631 RTLLIB_DEBUG(RTLLIB_DL_REORDER,
6d6163c3 632 "%s(): Duplicate packet is dropped!! IndicateSeq: %d, NewSeq: %d\n",
db8971b6
LF
633 __func__, pTS->RxIndicateSeq,
634 SeqNum);
635 list_add_tail(&pReorderEntry->List,
636 &ieee->RxReorder_Unused_List); {
94a79942 637 int i;
3a6b70c3 638
db8971b6 639 for (i = 0; i < prxb->nr_subframes; i++)
94a79942 640 dev_kfree_skb(prxb->subframes[i]);
94a79942
LF
641 kfree(prxb);
642 prxb = NULL;
643 }
644 } else {
645 RTLLIB_DEBUG(RTLLIB_DL_REORDER,
6d6163c3 646 "Pkt insert into struct buffer!! IndicateSeq: %d, NewSeq: %d\n",
db8971b6 647 pTS->RxIndicateSeq, SeqNum);
94a79942 648 }
db8971b6 649 } else {
94a79942 650 /*
db8971b6
LF
651 * Packets are dropped if there are not enough reorder
652 * entries. This part should be modified!! We can just
653 * indicate all the packets in struct buffer and get
654 * reorder entries.
94a79942 655 */
6d6163c3 656 RTLLIB_DEBUG(RTLLIB_DL_ERR, "RxReorderIndicatePacket(): There is no reorder entry!! Packet is dropped!!\n");
94a79942
LF
657 {
658 int i;
3a6b70c3 659
db8971b6 660 for (i = 0; i < prxb->nr_subframes; i++)
94a79942 661 dev_kfree_skb(prxb->subframes[i]);
94a79942
LF
662 kfree(prxb);
663 prxb = NULL;
664 }
665 }
666 }
667
668 /* Check if there is any packet need indicate.*/
db8971b6
LF
669 while (!list_empty(&pTS->RxPendingPktList)) {
670 RTLLIB_DEBUG(RTLLIB_DL_REORDER, "%s(): start RREORDER indicate\n", __func__);
4f6807e8 671
db8971b6
LF
672 pReorderEntry = (struct rx_reorder_entry *)list_entry(pTS->RxPendingPktList.prev,
673 struct rx_reorder_entry, List);
674 if (SN_LESS(pReorderEntry->SeqNum, pTS->RxIndicateSeq) ||
675 SN_EQUAL(pReorderEntry->SeqNum, pTS->RxIndicateSeq)) {
fc22c052 676 /* This protect struct buffer from overflow. */
94a79942 677 if (index >= REORDER_WIN_SIZE) {
6d6163c3 678 RTLLIB_DEBUG(RTLLIB_DL_ERR, "RxReorderIndicatePacket(): Buffer overflow!!\n");
94a79942
LF
679 bPktInBuf = true;
680 break;
681 }
682
683 list_del_init(&pReorderEntry->List);
684
685 if (SN_EQUAL(pReorderEntry->SeqNum, pTS->RxIndicateSeq))
686 pTS->RxIndicateSeq = (pTS->RxIndicateSeq + 1) % 4096;
687
2eed3dee 688 ieee->prxbIndicateArray[index] = pReorderEntry->prxb;
6d6163c3 689 RTLLIB_DEBUG(RTLLIB_DL_REORDER, "%s(): Indicate SeqNum %d!\n", __func__, pReorderEntry->SeqNum);
94a79942
LF
690 index++;
691
db8971b6
LF
692 list_add_tail(&pReorderEntry->List,
693 &ieee->RxReorder_Unused_List);
94a79942
LF
694 } else {
695 bPktInBuf = true;
696 break;
697 }
94a79942
LF
698 }
699
db8971b6
LF
700 /* Handling pending timer. Set this timer to prevent from long time
701 * Rx buffering.*/
702 if (index > 0) {
703 if (timer_pending(&pTS->RxPktPendingTimer))
94a79942 704 del_timer_sync(&pTS->RxPktPendingTimer);
94a79942
LF
705 pTS->RxTimeoutIndicateSeq = 0xffff;
706
db8971b6 707 if (index > REORDER_WIN_SIZE) {
6d6163c3 708 RTLLIB_DEBUG(RTLLIB_DL_ERR, "RxReorderIndicatePacket(): Rx Reorder struct buffer full!!\n");
db8971b6
LF
709 spin_unlock_irqrestore(&(ieee->reorder_spinlock),
710 flags);
94a79942
LF
711 return;
712 }
2eed3dee 713 rtllib_indicate_packets(ieee, ieee->prxbIndicateArray, index);
94a79942
LF
714 bPktInBuf = false;
715 }
716
db8971b6
LF
717 if (bPktInBuf && pTS->RxTimeoutIndicateSeq == 0xffff) {
718 RTLLIB_DEBUG(RTLLIB_DL_REORDER, "%s(): SET rx timeout timer\n",
719 __func__);
94a79942 720 pTS->RxTimeoutIndicateSeq = pTS->RxIndicateSeq;
db8971b6 721 mod_timer(&pTS->RxPktPendingTimer, jiffies +
8b9733c1 722 msecs_to_jiffies(pHTInfo->RxReorderPendingTime));
94a79942
LF
723 }
724 spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
725}
726
49aab5fd
LF
727static u8 parse_subframe(struct rtllib_device *ieee, struct sk_buff *skb,
728 struct rtllib_rx_stats *rx_stats,
729 struct rtllib_rxb *rxb, u8 *src, u8 *dst)
94a79942 730{
db8971b6 731 struct rtllib_hdr_3addr *hdr = (struct rtllib_hdr_3addr *)skb->data;
94a79942
LF
732 u16 fc = le16_to_cpu(hdr->frame_ctl);
733
db8971b6 734 u16 LLCOffset = sizeof(struct rtllib_hdr_3addr);
94a79942
LF
735 u16 ChkLength;
736 bool bIsAggregateFrame = false;
737 u16 nSubframe_Length;
738 u8 nPadding_Length = 0;
db8971b6 739 u16 SeqNum = 0;
94a79942 740 struct sk_buff *sub_skb;
db8971b6 741 u8 *data_ptr;
94a79942
LF
742 /* just for debug purpose */
743 SeqNum = WLAN_GET_SEQ_SEQ(le16_to_cpu(hdr->seq_ctl));
db8971b6
LF
744 if ((RTLLIB_QOS_HAS_SEQ(fc)) &&
745 (((union frameqos *)(skb->data + RTLLIB_3ADDR_LEN))->field.reserved))
94a79942 746 bIsAggregateFrame = true;
94a79942 747
db8971b6 748 if (RTLLIB_QOS_HAS_SEQ(fc))
94a79942 749 LLCOffset += 2;
db8971b6 750 if (rx_stats->bContainHTC)
94a79942 751 LLCOffset += sHTCLng;
94a79942 752
db8971b6 753 ChkLength = LLCOffset;
94a79942 754
db8971b6 755 if (skb->len <= ChkLength)
94a79942 756 return 0;
94a79942
LF
757
758 skb_pull(skb, LLCOffset);
759 ieee->bIsAggregateFrame = bIsAggregateFrame;
760 if (!bIsAggregateFrame) {
761 rxb->nr_subframes = 1;
762
763 /* altered by clark 3/30/2010
fc22c052 764 * The struct buffer size of the skb indicated to upper layer
94a79942
LF
765 * must be less than 5000, or the defraged IP datagram
766 * in the IP layer will exceed "ipfrag_high_tresh" and be
767 * discarded. so there must not use the function
768 * "skb_copy" and "skb_clone" for "skb".
769 */
770
771 /* Allocate new skb for releasing to upper layer */
772 sub_skb = dev_alloc_skb(RTLLIB_SKBBUFFER_SIZE);
59aabd6a
IP
773 if (!sub_skb)
774 return 0;
94a79942
LF
775 skb_reserve(sub_skb, 12);
776 data_ptr = (u8 *)skb_put(sub_skb, skb->len);
777 memcpy(data_ptr, skb->data, skb->len);
778 sub_skb->dev = ieee->dev;
779
780 rxb->subframes[0] = sub_skb;
781
db8971b6
LF
782 memcpy(rxb->src, src, ETH_ALEN);
783 memcpy(rxb->dst, dst, ETH_ALEN);
94a79942
LF
784 rxb->subframes[0]->dev = ieee->dev;
785 return 1;
285b7c00 786 }
94a79942 787
285b7c00
MK
788 rxb->nr_subframes = 0;
789 memcpy(rxb->src, src, ETH_ALEN);
790 memcpy(rxb->dst, dst, ETH_ALEN);
791 while (skb->len > ETHERNET_HEADER_SIZE) {
792 /* Offset 12 denote 2 mac address */
793 nSubframe_Length = *((u16 *)(skb->data + 12));
794 nSubframe_Length = (nSubframe_Length >> 8) +
795 (nSubframe_Length << 8);
94a79942 796
285b7c00
MK
797 if (skb->len < (ETHERNET_HEADER_SIZE + nSubframe_Length)) {
798 netdev_info(ieee->dev,
799 "%s: A-MSDU parse error!! pRfd->nTotalSubframe : %d\n",
800 __func__, rxb->nr_subframes);
801 netdev_info(ieee->dev,
802 "%s: A-MSDU parse error!! Subframe Length: %d\n",
803 __func__, nSubframe_Length);
804 netdev_info(ieee->dev,
805 "nRemain_Length is %d and nSubframe_Length is : %d\n",
806 skb->len, nSubframe_Length);
807 netdev_info(ieee->dev,
808 "The Packet SeqNum is %d\n",
809 SeqNum);
810 return 0;
811 }
94a79942 812
285b7c00
MK
813 /* move the data point to data content */
814 skb_pull(skb, ETHERNET_HEADER_SIZE);
94a79942 815
285b7c00
MK
816 /* altered by clark 3/30/2010
817 * The struct buffer size of the skb indicated to upper layer
818 * must be less than 5000, or the defraged IP datagram
819 * in the IP layer will exceed "ipfrag_high_tresh" and be
820 * discarded. so there must not use the function
821 * "skb_copy" and "skb_clone" for "skb".
822 */
94a79942 823
285b7c00
MK
824 /* Allocate new skb for releasing to upper layer */
825 sub_skb = dev_alloc_skb(nSubframe_Length + 12);
826 if (!sub_skb)
827 return 0;
828 skb_reserve(sub_skb, 12);
829 data_ptr = (u8 *)skb_put(sub_skb, nSubframe_Length);
830 memcpy(data_ptr, skb->data, nSubframe_Length);
94a79942 831
285b7c00
MK
832 sub_skb->dev = ieee->dev;
833 rxb->subframes[rxb->nr_subframes++] = sub_skb;
834 if (rxb->nr_subframes >= MAX_SUBFRAME_COUNT) {
835 RTLLIB_DEBUG_RX("ParseSubframe(): Too many Subframes! Packets dropped!\n");
836 break;
94a79942 837 }
285b7c00
MK
838 skb_pull(skb, nSubframe_Length);
839
840 if (skb->len != 0) {
841 nPadding_Length = 4 - ((nSubframe_Length +
842 ETHERNET_HEADER_SIZE) % 4);
843 if (nPadding_Length == 4)
844 nPadding_Length = 0;
94a79942 845
285b7c00
MK
846 if (skb->len < nPadding_Length)
847 return 0;
848
849 skb_pull(skb, nPadding_Length);
850 }
94a79942 851 }
285b7c00
MK
852
853 return rxb->nr_subframes;
94a79942
LF
854}
855
856
49aab5fd
LF
857static size_t rtllib_rx_get_hdrlen(struct rtllib_device *ieee,
858 struct sk_buff *skb,
859 struct rtllib_rx_stats *rx_stats)
94a79942
LF
860{
861 struct rtllib_hdr_4addr *hdr = (struct rtllib_hdr_4addr *)skb->data;
862 u16 fc = le16_to_cpu(hdr->frame_ctl);
863 size_t hdrlen = 0;
864
865 hdrlen = rtllib_get_hdrlen(fc);
866 if (HTCCheck(ieee, skb->data)) {
867 if (net_ratelimit())
d69d2054
MK
868 netdev_info(ieee->dev, "%s: find HTCControl!\n",
869 __func__);
94a79942 870 hdrlen += 4;
014e4c27 871 rx_stats->bContainHTC = true;
94a79942
LF
872 }
873
874 if (RTLLIB_QOS_HAS_SEQ(fc))
014e4c27 875 rx_stats->bIsQosData = true;
94a79942
LF
876
877 return hdrlen;
878}
879
49aab5fd
LF
880static int rtllib_rx_check_duplicate(struct rtllib_device *ieee,
881 struct sk_buff *skb, u8 multicast)
94a79942
LF
882{
883 struct rtllib_hdr_4addr *hdr = (struct rtllib_hdr_4addr *)skb->data;
884 u16 fc, sc;
885 u8 frag, type, stype;
886
887 fc = le16_to_cpu(hdr->frame_ctl);
888 type = WLAN_FC_GET_TYPE(fc);
889 stype = WLAN_FC_GET_STYPE(fc);
890 sc = le16_to_cpu(hdr->seq_ctl);
891 frag = WLAN_GET_SEQ_FRAG(sc);
892
db8971b6 893 if ((ieee->pHTInfo->bCurRxReorderEnable == false) ||
94a79942
LF
894 !ieee->current_network.qos_data.active ||
895 !IsDataFrame(skb->data) ||
896 IsLegacyDataFrame(skb->data)) {
db8971b6
LF
897 if (!((type == RTLLIB_FTYPE_MGMT) && (stype == RTLLIB_STYPE_BEACON))) {
898 if (is_duplicate_packet(ieee, hdr))
94a79942 899 return -1;
94a79942
LF
900 }
901 } else {
2c47ae28 902 struct rx_ts_record *pRxTS = NULL;
3a6b70c3 903
74724de1 904 if (GetTs(ieee, (struct ts_common_info **) &pRxTS, hdr->addr2,
db8971b6 905 (u8)Frame_QoSTID((u8 *)(skb->data)), RX_DIR, true)) {
94a79942 906 if ((fc & (1<<11)) && (frag == pRxTS->RxLastFragNum) &&
59422a74 907 (WLAN_GET_SEQ_SEQ(sc) == pRxTS->RxLastSeqNum))
94a79942 908 return -1;
59422a74
MC
909 pRxTS->RxLastFragNum = frag;
910 pRxTS->RxLastSeqNum = WLAN_GET_SEQ_SEQ(sc);
94a79942 911 } else {
6d6163c3 912 RTLLIB_DEBUG(RTLLIB_DL_ERR, "ERR!!%s(): No TS!! Skip the check!!\n", __func__);
94a79942
LF
913 return -1;
914 }
915 }
916
917 return 0;
918}
db8971b6 919
49aab5fd
LF
920static void rtllib_rx_extract_addr(struct rtllib_device *ieee,
921 struct rtllib_hdr_4addr *hdr, u8 *dst,
922 u8 *src, u8 *bssid)
94a79942
LF
923{
924 u16 fc = le16_to_cpu(hdr->frame_ctl);
925
926 switch (fc & (RTLLIB_FCTL_FROMDS | RTLLIB_FCTL_TODS)) {
db8971b6
LF
927 case RTLLIB_FCTL_FROMDS:
928 memcpy(dst, hdr->addr1, ETH_ALEN);
929 memcpy(src, hdr->addr3, ETH_ALEN);
930 memcpy(bssid, hdr->addr2, ETH_ALEN);
931 break;
932 case RTLLIB_FCTL_TODS:
933 memcpy(dst, hdr->addr3, ETH_ALEN);
934 memcpy(src, hdr->addr2, ETH_ALEN);
935 memcpy(bssid, hdr->addr1, ETH_ALEN);
936 break;
937 case RTLLIB_FCTL_FROMDS | RTLLIB_FCTL_TODS:
938 memcpy(dst, hdr->addr3, ETH_ALEN);
939 memcpy(src, hdr->addr4, ETH_ALEN);
940 memcpy(bssid, ieee->current_network.bssid, ETH_ALEN);
941 break;
942 case 0:
943 memcpy(dst, hdr->addr1, ETH_ALEN);
944 memcpy(src, hdr->addr2, ETH_ALEN);
945 memcpy(bssid, hdr->addr3, ETH_ALEN);
946 break;
94a79942
LF
947 }
948}
db8971b6 949
49aab5fd
LF
950static int rtllib_rx_data_filter(struct rtllib_device *ieee, u16 fc,
951 u8 *dst, u8 *src, u8 *bssid, u8 *addr2)
94a79942 952{
94a79942
LF
953 u8 type, stype;
954
955 type = WLAN_FC_GET_TYPE(fc);
956 stype = WLAN_FC_GET_STYPE(fc);
957
958 /* Filter frames from different BSS */
8329419a
JP
959 if (((fc & RTLLIB_FCTL_DSTODS) != RTLLIB_FCTL_DSTODS) &&
960 !ether_addr_equal(ieee->current_network.bssid, bssid) &&
961 !is_zero_ether_addr(ieee->current_network.bssid)) {
94a79942
LF
962 return -1;
963 }
964
965 /* Filter packets sent by an STA that will be forwarded by AP */
db8971b6
LF
966 if (ieee->IntelPromiscuousModeInfo.bPromiscuousOn &&
967 ieee->IntelPromiscuousModeInfo.bFilterSourceStationFrame) {
94a79942 968 if ((fc & RTLLIB_FCTL_TODS) && !(fc & RTLLIB_FCTL_FROMDS) &&
8329419a
JP
969 !ether_addr_equal(dst, ieee->current_network.bssid) &&
970 ether_addr_equal(bssid, ieee->current_network.bssid)) {
94a79942
LF
971 return -1;
972 }
973 }
974
975 /* Nullfunc frames may have PS-bit set, so they must be passed to
976 * hostap_handle_sta_rx() before being dropped here. */
db8971b6 977 if (!ieee->IntelPromiscuousModeInfo.bPromiscuousOn) {
94a79942
LF
978 if (stype != RTLLIB_STYPE_DATA &&
979 stype != RTLLIB_STYPE_DATA_CFACK &&
980 stype != RTLLIB_STYPE_DATA_CFPOLL &&
db8971b6
LF
981 stype != RTLLIB_STYPE_DATA_CFACKPOLL &&
982 stype != RTLLIB_STYPE_QOS_DATA) {
94a79942
LF
983 if (stype != RTLLIB_STYPE_NULLFUNC)
984 RTLLIB_DEBUG_DROP(
6d6163c3 985 "RX: dropped data frame with no data (type=0x%02x, subtype=0x%02x)\n",
94a79942
LF
986 type, stype);
987 return -1;
988 }
989 }
990
991 if (ieee->iw_mode != IW_MODE_MESH) {
992 /* packets from our adapter are dropped (echo) */
993 if (!memcmp(src, ieee->dev->dev_addr, ETH_ALEN))
994 return -1;
995
996 /* {broad,multi}cast packets to our BSS go through */
14fc4235 997 if (is_multicast_ether_addr(dst)) {
db8971b6 998 if (memcmp(bssid, ieee->current_network.bssid, ETH_ALEN))
94a79942 999 return -1;
94a79942
LF
1000 }
1001 }
1002 return 0;
1003}
db8971b6 1004
49aab5fd 1005static int rtllib_rx_get_crypt(struct rtllib_device *ieee, struct sk_buff *skb,
32c44cb5 1006 struct lib80211_crypt_data **crypt, size_t hdrlen)
94a79942
LF
1007{
1008 struct rtllib_hdr_4addr *hdr = (struct rtllib_hdr_4addr *)skb->data;
1009 u16 fc = le16_to_cpu(hdr->frame_ctl);
1010 int idx = 0;
1011
1012 if (ieee->host_decrypt) {
1013 if (skb->len >= hdrlen + 3)
1014 idx = skb->data[hdrlen + 3] >> 6;
1015
0ddcf5fd 1016 *crypt = ieee->crypt_info.crypt[idx];
94a79942
LF
1017 /* allow NULL decrypt to indicate an station specific override
1018 * for default encryption */
1019 if (*crypt && ((*crypt)->ops == NULL ||
1020 (*crypt)->ops->decrypt_mpdu == NULL))
1021 *crypt = NULL;
1022
1023 if (!*crypt && (fc & RTLLIB_FCTL_WEP)) {
1024 /* This seems to be triggered by some (multicast?)
1025 * frames from other than current BSS, so just drop the
1026 * frames silently instead of filling system log with
1027 * these reports. */
6d6163c3 1028 RTLLIB_DEBUG_DROP("Decryption failed (not set) (SA= %pM)\n",
ac50ddaa 1029 hdr->addr2);
94a79942
LF
1030 ieee->ieee_stats.rx_discards_undecryptable++;
1031 return -1;
1032 }
1033 }
1034
1035 return 0;
1036}
db8971b6 1037
49aab5fd 1038static int rtllib_rx_decrypt(struct rtllib_device *ieee, struct sk_buff *skb,
db8971b6 1039 struct rtllib_rx_stats *rx_stats,
32c44cb5 1040 struct lib80211_crypt_data *crypt, size_t hdrlen)
94a79942
LF
1041{
1042 struct rtllib_hdr_4addr *hdr;
1043 int keyidx = 0;
1044 u16 fc, sc;
1045 u8 frag;
1046
1047 hdr = (struct rtllib_hdr_4addr *)skb->data;
1048 fc = le16_to_cpu(hdr->frame_ctl);
1049 sc = le16_to_cpu(hdr->seq_ctl);
1050 frag = WLAN_GET_SEQ_FRAG(sc);
1051
db8971b6 1052 if ((!rx_stats->Decrypted))
94a79942 1053 ieee->need_sw_enc = 1;
db8971b6 1054 else
94a79942 1055 ieee->need_sw_enc = 0;
94a79942 1056
db8971b6
LF
1057 keyidx = rtllib_rx_frame_decrypt(ieee, skb, crypt);
1058 if (ieee->host_decrypt && (fc & RTLLIB_FCTL_WEP) && (keyidx < 0)) {
d69d2054 1059 netdev_info(ieee->dev, "%s: decrypt frame error\n", __func__);
94a79942
LF
1060 return -1;
1061 }
1062
1063 hdr = (struct rtllib_hdr_4addr *) skb->data;
1064 if ((frag != 0 || (fc & RTLLIB_FCTL_MOREFRAGS))) {
1065 int flen;
1066 struct sk_buff *frag_skb = rtllib_frag_cache_get(ieee, hdr);
3a6b70c3 1067
94a79942
LF
1068 RTLLIB_DEBUG_FRAG("Rx Fragment received (%u)\n", frag);
1069
1070 if (!frag_skb) {
1071 RTLLIB_DEBUG(RTLLIB_DL_RX | RTLLIB_DL_FRAG,
6d6163c3 1072 "Rx cannot get skb from fragment cache (morefrag=%d seq=%u frag=%u)\n",
94a79942
LF
1073 (fc & RTLLIB_FCTL_MOREFRAGS) != 0,
1074 WLAN_GET_SEQ_SEQ(sc), frag);
1075 return -1;
1076 }
1077 flen = skb->len;
1078 if (frag != 0)
1079 flen -= hdrlen;
1080
1081 if (frag_skb->tail + flen > frag_skb->end) {
d69d2054
MK
1082 netdev_warn(ieee->dev,
1083 "%s: host decrypted and reassembled frame did not fit skb\n",
1084 __func__);
94a79942
LF
1085 rtllib_frag_cache_invalidate(ieee, hdr);
1086 return -1;
1087 }
1088
1089 if (frag == 0) {
1090 /* copy first fragment (including full headers) into
1091 * beginning of the fragment cache skb */
1092 memcpy(skb_put(frag_skb, flen), skb->data, flen);
1093 } else {
1094 /* append frame payload to the end of the fragment
1095 * cache skb */
1096 memcpy(skb_put(frag_skb, flen), skb->data + hdrlen,
1097 flen);
1098 }
1099 dev_kfree_skb_any(skb);
1100 skb = NULL;
1101
1102 if (fc & RTLLIB_FCTL_MOREFRAGS) {
1103 /* more fragments expected - leave the skb in fragment
1104 * cache for now; it will be delivered to upper layers
1105 * after all fragments have been received */
1106 return -2;
1107 }
1108
1109 /* this was the last fragment and the frame will be
1110 * delivered, so remove skb from fragment cache */
1111 skb = frag_skb;
1112 hdr = (struct rtllib_hdr_4addr *) skb->data;
1113 rtllib_frag_cache_invalidate(ieee, hdr);
1114 }
1115
1116 /* skb: hdr + (possible reassembled) full MSDU payload; possibly still
1117 * encrypted/authenticated */
1118 if (ieee->host_decrypt && (fc & RTLLIB_FCTL_WEP) &&
db8971b6 1119 rtllib_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt)) {
d69d2054 1120 netdev_info(ieee->dev, "%s: ==>decrypt msdu error\n", __func__);
94a79942
LF
1121 return -1;
1122 }
1123
1124 hdr = (struct rtllib_hdr_4addr *) skb->data;
1125 if (crypt && !(fc & RTLLIB_FCTL_WEP) && !ieee->open_wep) {
1126 if (/*ieee->ieee802_1x &&*/
1127 rtllib_is_eapol_frame(ieee, skb, hdrlen)) {
1128
94a79942
LF
1129 /* pass unencrypted EAPOL frames even if encryption is
1130 * configured */
1131 struct eapol *eap = (struct eapol *)(skb->data +
1132 24);
1133 RTLLIB_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n",
1134 eap_get_type(eap->type));
94a79942
LF
1135 } else {
1136 RTLLIB_DEBUG_DROP(
6d6163c3 1137 "encryption configured, but RX frame not encrypted (SA= %pM)\n",
ac50ddaa 1138 hdr->addr2);
94a79942
LF
1139 return -1;
1140 }
1141 }
1142
94a79942
LF
1143 if (crypt && !(fc & RTLLIB_FCTL_WEP) &&
1144 rtllib_is_eapol_frame(ieee, skb, hdrlen)) {
1145 struct eapol *eap = (struct eapol *)(skb->data +
1146 24);
1147 RTLLIB_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n",
1148 eap_get_type(eap->type));
1149 }
94a79942
LF
1150
1151 if (crypt && !(fc & RTLLIB_FCTL_WEP) && !ieee->open_wep &&
1152 !rtllib_is_eapol_frame(ieee, skb, hdrlen)) {
1153 RTLLIB_DEBUG_DROP(
6d6163c3 1154 "dropped unencrypted RX data frame from %pM (drop_unencrypted=1)\n",
ac50ddaa 1155 hdr->addr2);
94a79942
LF
1156 return -1;
1157 }
1158
db8971b6 1159 if (rtllib_is_eapol_frame(ieee, skb, hdrlen))
d69d2054 1160 netdev_warn(ieee->dev, "RX: IEEE802.1X EAPOL frame!\n");
94a79942
LF
1161
1162 return 0;
1163}
db8971b6 1164
49aab5fd 1165static void rtllib_rx_check_leave_lps(struct rtllib_device *ieee, u8 unicast, u8 nr_subframes)
94a79942 1166{
db8971b6 1167 if (unicast) {
94a79942 1168
db8971b6
LF
1169 if ((ieee->state == RTLLIB_LINKED)) {
1170 if (((ieee->LinkDetectInfo.NumRxUnicastOkInPeriod +
1171 ieee->LinkDetectInfo.NumTxOkInPeriod) > 8) ||
1172 (ieee->LinkDetectInfo.NumRxUnicastOkInPeriod > 2)) {
94a79942
LF
1173 if (ieee->LeisurePSLeave)
1174 ieee->LeisurePSLeave(ieee->dev);
1175 }
1176 }
1177 }
94a79942
LF
1178 ieee->last_rx_ps_time = jiffies;
1179}
db8971b6 1180
49aab5fd 1181static void rtllib_rx_indicate_pkt_legacy(struct rtllib_device *ieee,
94a79942 1182 struct rtllib_rx_stats *rx_stats,
db8971b6 1183 struct rtllib_rxb *rxb,
94a79942
LF
1184 u8 *dst,
1185 u8 *src)
1186{
1187 struct net_device *dev = ieee->dev;
1188 u16 ethertype;
1189 int i = 0;
1190
db8971b6 1191 if (rxb == NULL) {
d69d2054 1192 netdev_info(dev, "%s: rxb is NULL!!\n", __func__);
dc986e3e 1193 return;
94a79942
LF
1194 }
1195
db8971b6 1196 for (i = 0; i < rxb->nr_subframes; i++) {
94a79942
LF
1197 struct sk_buff *sub_skb = rxb->subframes[i];
1198
1199 if (sub_skb) {
1200 /* convert hdr + possible LLC headers into Ethernet header */
1201 ethertype = (sub_skb->data[6] << 8) | sub_skb->data[7];
1202 if (sub_skb->len >= 8 &&
db8971b6
LF
1203 ((memcmp(sub_skb->data, rfc1042_header, SNAP_SIZE) == 0 &&
1204 ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
1205 memcmp(sub_skb->data, bridge_tunnel_header, SNAP_SIZE) == 0)) {
94a79942
LF
1206 /* remove RFC1042 or Bridge-Tunnel encapsulation and
1207 * replace EtherType */
1208 skb_pull(sub_skb, SNAP_SIZE);
1209 memcpy(skb_push(sub_skb, ETH_ALEN), src, ETH_ALEN);
1210 memcpy(skb_push(sub_skb, ETH_ALEN), dst, ETH_ALEN);
1211 } else {
1212 u16 len;
1213 /* Leave Ethernet header part of hdr and full payload */
1f5a0d0c 1214 len = sub_skb->len;
94a79942
LF
1215 memcpy(skb_push(sub_skb, 2), &len, 2);
1216 memcpy(skb_push(sub_skb, ETH_ALEN), src, ETH_ALEN);
1217 memcpy(skb_push(sub_skb, ETH_ALEN), dst, ETH_ALEN);
1218 }
1219
1220 ieee->stats.rx_packets++;
1221 ieee->stats.rx_bytes += sub_skb->len;
1222
db8971b6 1223 if (is_multicast_ether_addr(dst))
94a79942 1224 ieee->stats.multicast++;
94a79942 1225
cd017123 1226 /* Indicate the packets to upper layer */
94a79942
LF
1227 memset(sub_skb->cb, 0, sizeof(sub_skb->cb));
1228 sub_skb->protocol = eth_type_trans(sub_skb, dev);
1229 sub_skb->dev = dev;
1230 sub_skb->dev->stats.rx_packets++;
1231 sub_skb->dev->stats.rx_bytes += sub_skb->len;
94a79942 1232 sub_skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */
94a79942
LF
1233 netif_rx(sub_skb);
1234 }
1235 }
1236 kfree(rxb);
94a79942 1237}
db8971b6 1238
49aab5fd 1239static int rtllib_rx_InfraAdhoc(struct rtllib_device *ieee, struct sk_buff *skb,
94a79942
LF
1240 struct rtllib_rx_stats *rx_stats)
1241{
1242 struct net_device *dev = ieee->dev;
1243 struct rtllib_hdr_4addr *hdr = (struct rtllib_hdr_4addr *)skb->data;
32c44cb5 1244 struct lib80211_crypt_data *crypt = NULL;
db8971b6 1245 struct rtllib_rxb *rxb = NULL;
2c47ae28 1246 struct rx_ts_record *pTS = NULL;
94a79942
LF
1247 u16 fc, sc, SeqNum = 0;
1248 u8 type, stype, multicast = 0, unicast = 0, nr_subframes = 0, TID = 0;
1249 u8 dst[ETH_ALEN], src[ETH_ALEN], bssid[ETH_ALEN] = {0}, *payload;
1250 size_t hdrlen = 0;
1251 bool bToOtherSTA = false;
1252 int ret = 0, i = 0;
1253
1254 hdr = (struct rtllib_hdr_4addr *)skb->data;
1255 fc = le16_to_cpu(hdr->frame_ctl);
1256 type = WLAN_FC_GET_TYPE(fc);
1257 stype = WLAN_FC_GET_STYPE(fc);
1258 sc = le16_to_cpu(hdr->seq_ctl);
1259
1260 /*Filter pkt not to me*/
14fc4235 1261 multicast = is_multicast_ether_addr(hdr->addr1);
94a79942 1262 unicast = !multicast;
8329419a 1263 if (unicast && !ether_addr_equal(dev->dev_addr, hdr->addr1)) {
94a79942
LF
1264 if (ieee->bNetPromiscuousMode)
1265 bToOtherSTA = true;
1266 else
1267 goto rx_dropped;
1268 }
1269
1270 /*Filter pkt has too small length */
1271 hdrlen = rtllib_rx_get_hdrlen(ieee, skb, rx_stats);
db8971b6 1272 if (skb->len < hdrlen) {
d69d2054
MK
1273 netdev_info(dev, "%s():ERR!!! skb->len is smaller than hdrlen\n",
1274 __func__);
94a79942
LF
1275 goto rx_dropped;
1276 }
1277
1278 /* Filter Duplicate pkt */
1279 ret = rtllib_rx_check_duplicate(ieee, skb, multicast);
1280 if (ret < 0)
1281 goto rx_dropped;
1282
1283 /* Filter CTRL Frame */
db8971b6 1284 if (type == RTLLIB_FTYPE_CTL)
94a79942 1285 goto rx_dropped;
94a79942
LF
1286
1287 /* Filter MGNT Frame */
1288 if (type == RTLLIB_FTYPE_MGMT) {
1289 if (bToOtherSTA)
1290 goto rx_dropped;
1291 if (rtllib_rx_frame_mgmt(ieee, skb, rx_stats, type, stype))
1292 goto rx_dropped;
1293 else
1294 goto rx_exit;
1295 }
1296
1297 /* Filter WAPI DATA Frame */
1298
1299 /* Update statstics for AP roaming */
db8971b6 1300 if (!bToOtherSTA) {
94a79942
LF
1301 ieee->LinkDetectInfo.NumRecvDataInPeriod++;
1302 ieee->LinkDetectInfo.NumRxOkInPeriod++;
1303 }
1304 dev->last_rx = jiffies;
1305
1306 /* Data frame - extract src/dst addresses */
1307 rtllib_rx_extract_addr(ieee, hdr, dst, src, bssid);
1308
1309 /* Filter Data frames */
1310 ret = rtllib_rx_data_filter(ieee, fc, dst, src, bssid, hdr->addr2);
1311 if (ret < 0)
1312 goto rx_dropped;
1313
db8971b6 1314 if (skb->len == hdrlen)
94a79942 1315 goto rx_dropped;
94a79942
LF
1316
1317 /* Send pspoll based on moredata */
1318 if ((ieee->iw_mode == IW_MODE_INFRA) && (ieee->sta_sleep == LPS_IS_SLEEP)
1319 && (ieee->polling) && (!bToOtherSTA)) {
1320 if (WLAN_FC_MORE_DATA(fc)) {
1321 /* more data bit is set, let's request a new frame from the AP */
1322 rtllib_sta_ps_send_pspoll_frame(ieee);
1323 } else {
1324 ieee->polling = false;
1325 }
1326 }
1327
94a79942
LF
1328 /* Get crypt if encrypted */
1329 ret = rtllib_rx_get_crypt(ieee, skb, &crypt, hdrlen);
1330 if (ret == -1)
1331 goto rx_dropped;
1332
1333 /* Decrypt data frame (including reassemble) */
1334 ret = rtllib_rx_decrypt(ieee, skb, rx_stats, crypt, hdrlen);
1335 if (ret == -1)
1336 goto rx_dropped;
1337 else if (ret == -2)
1338 goto rx_exit;
1339
1340 /* Get TS for Rx Reorder */
1341 hdr = (struct rtllib_hdr_4addr *) skb->data;
1342 if (ieee->current_network.qos_data.active && IsQoSDataFrame(skb->data)
14fc4235 1343 && !is_multicast_ether_addr(hdr->addr1)
db8971b6 1344 && (!bToOtherSTA)) {
94a79942
LF
1345 TID = Frame_QoSTID(skb->data);
1346 SeqNum = WLAN_GET_SEQ_SEQ(sc);
db8971b6
LF
1347 GetTs(ieee, (struct ts_common_info **) &pTS, hdr->addr2, TID, RX_DIR, true);
1348 if (TID != 0 && TID != 3)
94a79942 1349 ieee->bis_any_nonbepkts = true;
94a79942
LF
1350 }
1351
1352 /* Parse rx data frame (For AMSDU) */
1353 /* skb: hdr + (possible reassembled) full plaintext payload */
1354 payload = skb->data + hdrlen;
db8971b6 1355 rxb = kmalloc(sizeof(struct rtllib_rxb), GFP_ATOMIC);
b6b0012c 1356 if (rxb == NULL)
94a79942 1357 goto rx_dropped;
b6b0012c 1358
94a79942
LF
1359 /* to parse amsdu packets */
1360 /* qos data packets & reserved bit is 1 */
db8971b6 1361 if (parse_subframe(ieee, skb, rx_stats, rxb, src, dst) == 0) {
94a79942 1362 /* only to free rxb, and not submit the packets to upper layer */
db8971b6 1363 for (i = 0; i < rxb->nr_subframes; i++)
94a79942 1364 dev_kfree_skb(rxb->subframes[i]);
94a79942
LF
1365 kfree(rxb);
1366 rxb = NULL;
1367 goto rx_dropped;
1368 }
1369
1370 /* Update WAPI PN */
1371
1372 /* Check if leave LPS */
db8971b6 1373 if (!bToOtherSTA) {
94a79942
LF
1374 if (ieee->bIsAggregateFrame)
1375 nr_subframes = rxb->nr_subframes;
1376 else
1377 nr_subframes = 1;
1378 if (unicast)
1379 ieee->LinkDetectInfo.NumRxUnicastOkInPeriod += nr_subframes;
1380 rtllib_rx_check_leave_lps(ieee, unicast, nr_subframes);
1381 }
1382
1383 /* Indicate packets to upper layer or Rx Reorder */
db8971b6 1384 if (ieee->pHTInfo->bCurRxReorderEnable == false || pTS == NULL || bToOtherSTA)
94a79942 1385 rtllib_rx_indicate_pkt_legacy(ieee, rx_stats, rxb, dst, src);
db8971b6 1386 else
94a79942 1387 RxReorderIndicatePacket(ieee, rxb, pTS, SeqNum);
94a79942
LF
1388
1389 dev_kfree_skb(skb);
1390
1391 rx_exit:
1392 return 1;
1393
1394 rx_dropped:
94a79942
LF
1395 ieee->stats.rx_dropped++;
1396
1397 /* Returning 0 indicates to caller that we have not handled the SKB--
1398 * so it is still allocated and can be used again by underlying
1399 * hardware as a DMA target */
1400 return 0;
1401}
1402
49aab5fd 1403static int rtllib_rx_Master(struct rtllib_device *ieee, struct sk_buff *skb,
94a79942
LF
1404 struct rtllib_rx_stats *rx_stats)
1405{
1406 return 0;
1407}
db8971b6 1408
49aab5fd 1409static int rtllib_rx_Monitor(struct rtllib_device *ieee, struct sk_buff *skb,
94a79942
LF
1410 struct rtllib_rx_stats *rx_stats)
1411{
1412 struct rtllib_hdr_4addr *hdr = (struct rtllib_hdr_4addr *)skb->data;
1413 u16 fc = le16_to_cpu(hdr->frame_ctl);
1414 size_t hdrlen = rtllib_get_hdrlen(fc);
1415
db8971b6 1416 if (skb->len < hdrlen) {
d69d2054
MK
1417 netdev_info(ieee->dev,
1418 "%s():ERR!!! skb->len is smaller than hdrlen\n",
1419 __func__);
94a79942
LF
1420 return 0;
1421 }
1422
1423 if (HTCCheck(ieee, skb->data)) {
1424 if (net_ratelimit())
d69d2054
MK
1425 netdev_info(ieee->dev, "%s: Find HTCControl!\n",
1426 __func__);
94a79942
LF
1427 hdrlen += 4;
1428 }
1429
94a79942
LF
1430 rtllib_monitor_rx(ieee, skb, rx_stats, hdrlen);
1431 ieee->stats.rx_packets++;
1432 ieee->stats.rx_bytes += skb->len;
3591733d 1433
94a79942
LF
1434 return 1;
1435}
1436
49aab5fd 1437static int rtllib_rx_Mesh(struct rtllib_device *ieee, struct sk_buff *skb,
94a79942
LF
1438 struct rtllib_rx_stats *rx_stats)
1439{
1440 return 0;
1441}
1442
94a79942
LF
1443/* All received frames are sent to this function. @skb contains the frame in
1444 * IEEE 802.11 format, i.e., in the format it was sent over air.
1445 * This function is called only as a tasklet (software IRQ). */
1446int rtllib_rx(struct rtllib_device *ieee, struct sk_buff *skb,
1447 struct rtllib_rx_stats *rx_stats)
1448{
1449 int ret = 0;
1450
db8971b6 1451 if ((NULL == ieee) || (NULL == skb) || (NULL == rx_stats)) {
d69d2054 1452 pr_info("%s: Input parameters NULL!\n", __func__);
94a79942
LF
1453 goto rx_dropped;
1454 }
1455 if (skb->len < 10) {
d69d2054 1456 netdev_info(ieee->dev, "%s: SKB length < 10\n", __func__);
94a79942
LF
1457 goto rx_dropped;
1458 }
1459
1460 switch (ieee->iw_mode) {
1461 case IW_MODE_ADHOC:
1462 case IW_MODE_INFRA:
1463 ret = rtllib_rx_InfraAdhoc(ieee, skb, rx_stats);
1464 break;
1465 case IW_MODE_MASTER:
1466 case IW_MODE_REPEAT:
1467 ret = rtllib_rx_Master(ieee, skb, rx_stats);
1468 break;
1469 case IW_MODE_MONITOR:
1470 ret = rtllib_rx_Monitor(ieee, skb, rx_stats);
1471 break;
1472 case IW_MODE_MESH:
1473 ret = rtllib_rx_Mesh(ieee, skb, rx_stats);
1474 break;
1475 default:
d69d2054 1476 netdev_info(ieee->dev, "%s: ERR iw mode!!!\n", __func__);
94a79942
LF
1477 break;
1478 }
1479
1480 return ret;
1481
1482 rx_dropped:
4fa42602
EG
1483 if (ieee)
1484 ieee->stats.rx_dropped++;
94a79942
LF
1485 return 0;
1486}
3b28499c 1487EXPORT_SYMBOL(rtllib_rx);
94a79942
LF
1488
1489static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 };
1490
1491/*
1492* Make ther structure we read from the beacon packet has
1493* the right values
1494*/
1495static int rtllib_verify_qos_info(struct rtllib_qos_information_element
db8971b6 1496 *info_element, int sub_type)
94a79942
LF
1497{
1498
db8971b6
LF
1499 if (info_element->qui_subtype != sub_type)
1500 return -1;
1501 if (memcmp(info_element->qui, qos_oui, QOS_OUI_LEN))
1502 return -1;
1503 if (info_element->qui_type != QOS_OUI_TYPE)
1504 return -1;
1505 if (info_element->version != QOS_VERSION_1)
1506 return -1;
94a79942 1507
db8971b6 1508 return 0;
94a79942
LF
1509}
1510
1511
1512/*
1513 * Parse a QoS parameter element
1514 */
1515static int rtllib_read_qos_param_element(struct rtllib_qos_parameter_info
db8971b6
LF
1516 *element_param, struct rtllib_info_element
1517 *info_element)
94a79942 1518{
db8971b6
LF
1519 int ret = 0;
1520 u16 size = sizeof(struct rtllib_qos_parameter_info) - 2;
1521
1522 if ((info_element == NULL) || (element_param == NULL))
1523 return -1;
1524
1525 if (info_element->id == QOS_ELEMENT_ID && info_element->len == size) {
1526 memcpy(element_param->info_element.qui, info_element->data,
1527 info_element->len);
1528 element_param->info_element.elementID = info_element->id;
1529 element_param->info_element.length = info_element->len;
1530 } else
1531 ret = -1;
1532 if (ret == 0)
1533 ret = rtllib_verify_qos_info(&element_param->info_element,
1534 QOS_OUI_PARAM_SUB_TYPE);
1535 return ret;
94a79942
LF
1536}
1537
1538/*
1539 * Parse a QoS information element
1540 */
1541static int rtllib_read_qos_info_element(struct
db8971b6
LF
1542 rtllib_qos_information_element
1543 *element_info, struct rtllib_info_element
1544 *info_element)
94a79942 1545{
db8971b6
LF
1546 int ret = 0;
1547 u16 size = sizeof(struct rtllib_qos_information_element) - 2;
1548
1549 if (element_info == NULL)
1550 return -1;
1551 if (info_element == NULL)
1552 return -1;
1553
1554 if ((info_element->id == QOS_ELEMENT_ID) && (info_element->len == size)) {
1555 memcpy(element_info->qui, info_element->data,
1556 info_element->len);
1557 element_info->elementID = info_element->id;
1558 element_info->length = info_element->len;
1559 } else
1560 ret = -1;
1561
1562 if (ret == 0)
1563 ret = rtllib_verify_qos_info(element_info,
1564 QOS_OUI_INFO_SUB_TYPE);
1565 return ret;
94a79942
LF
1566}
1567
1568
1569/*
1570 * Write QoS parameters from the ac parameters.
1571 */
1572static int rtllib_qos_convert_ac_to_parameters(struct rtllib_qos_parameter_info *param_elm,
1573 struct rtllib_qos_data *qos_data)
1574{
db8971b6 1575 struct rtllib_qos_ac_parameter *ac_params;
94a79942 1576 struct rtllib_qos_parameters *qos_param = &(qos_data->parameters);
db8971b6 1577 int i;
94a79942
LF
1578 u8 aci;
1579 u8 acm;
1580
1581 qos_data->wmm_acm = 0;
db8971b6
LF
1582 for (i = 0; i < QOS_QUEUE_NUM; i++) {
1583 ac_params = &(param_elm->ac_params_record[i]);
94a79942
LF
1584
1585 aci = (ac_params->aci_aifsn & 0x60) >> 5;
1586 acm = (ac_params->aci_aifsn & 0x10) >> 4;
1587
1588 if (aci >= QOS_QUEUE_NUM)
1589 continue;
1590 switch (aci) {
db8971b6
LF
1591 case 1:
1592 /* BIT(0) | BIT(3) */
1593 if (acm)
1594 qos_data->wmm_acm |= (0x01<<0)|(0x01<<3);
1595 break;
1596 case 2:
1597 /* BIT(4) | BIT(5) */
1598 if (acm)
1599 qos_data->wmm_acm |= (0x01<<4)|(0x01<<5);
1600 break;
1601 case 3:
1602 /* BIT(6) | BIT(7) */
1603 if (acm)
1604 qos_data->wmm_acm |= (0x01<<6)|(0x01<<7);
1605 break;
1606 case 0:
1607 default:
1608 /* BIT(1) | BIT(2) */
1609 if (acm)
1610 qos_data->wmm_acm |= (0x01<<1)|(0x01<<2);
1611 break;
94a79942
LF
1612 }
1613
db8971b6 1614 qos_param->aifs[aci] = (ac_params->aci_aifsn) & 0x0f;
94a79942
LF
1615
1616 /* WMM spec P.11: The minimum value for AIFSN shall be 2 */
db8971b6 1617 qos_param->aifs[aci] = (qos_param->aifs[aci] < 2) ? 2 : qos_param->aifs[aci];
94a79942 1618
1f5a0d0c 1619 qos_param->cw_min[aci] = cpu_to_le16(ac_params->ecw_min_max & 0x0F);
94a79942 1620
1f5a0d0c 1621 qos_param->cw_max[aci] = cpu_to_le16((ac_params->ecw_min_max & 0xF0) >> 4);
94a79942 1622
db8971b6
LF
1623 qos_param->flag[aci] =
1624 (ac_params->aci_aifsn & 0x10) ? 0x01 : 0x00;
1f5a0d0c 1625 qos_param->tx_op_limit[aci] = ac_params->tx_op_limit;
db8971b6 1626 }
4764ca98 1627 return 0;
94a79942
LF
1628}
1629
1630/*
1631 * we have a generic data element which it may contain QoS information or
1632 * parameters element. check the information element length to decide
1633 * which type to read
1634 */
1635static int rtllib_parse_qos_info_param_IE(struct rtllib_info_element
db8971b6
LF
1636 *info_element,
1637 struct rtllib_network *network)
94a79942 1638{
db8971b6
LF
1639 int rc = 0;
1640 struct rtllib_qos_information_element qos_info_element;
1641
1642 rc = rtllib_read_qos_info_element(&qos_info_element, info_element);
1643
1644 if (rc == 0) {
1645 network->qos_data.param_count = qos_info_element.ac_info & 0x0F;
1646 network->flags |= NETWORK_HAS_QOS_INFORMATION;
1647 } else {
1648 struct rtllib_qos_parameter_info param_element;
1649
1650 rc = rtllib_read_qos_param_element(&param_element,
1651 info_element);
1652 if (rc == 0) {
1653 rtllib_qos_convert_ac_to_parameters(&param_element,
1654 &(network->qos_data));
1655 network->flags |= NETWORK_HAS_QOS_PARAMETERS;
1656 network->qos_data.param_count =
1657 param_element.info_element.ac_info & 0x0F;
1658 }
1659 }
1660
1661 if (rc == 0) {
1662 RTLLIB_DEBUG_QOS("QoS is supported\n");
1663 network->qos_data.supported = 1;
1664 }
1665 return rc;
94a79942
LF
1666}
1667
94a79942
LF
1668#define MFIE_STRING(x) case MFIE_TYPE_ ##x: return #x
1669
1670static const char *get_info_element_string(u16 id)
1671{
db8971b6
LF
1672 switch (id) {
1673 MFIE_STRING(SSID);
1674 MFIE_STRING(RATES);
1675 MFIE_STRING(FH_SET);
1676 MFIE_STRING(DS_SET);
1677 MFIE_STRING(CF_SET);
1678 MFIE_STRING(TIM);
1679 MFIE_STRING(IBSS_SET);
1680 MFIE_STRING(COUNTRY);
1681 MFIE_STRING(HOP_PARAMS);
1682 MFIE_STRING(HOP_TABLE);
1683 MFIE_STRING(REQUEST);
1684 MFIE_STRING(CHALLENGE);
1685 MFIE_STRING(POWER_CONSTRAINT);
1686 MFIE_STRING(POWER_CAPABILITY);
1687 MFIE_STRING(TPC_REQUEST);
1688 MFIE_STRING(TPC_REPORT);
1689 MFIE_STRING(SUPP_CHANNELS);
1690 MFIE_STRING(CSA);
1691 MFIE_STRING(MEASURE_REQUEST);
1692 MFIE_STRING(MEASURE_REPORT);
1693 MFIE_STRING(QUIET);
1694 MFIE_STRING(IBSS_DFS);
1695 MFIE_STRING(RSN);
1696 MFIE_STRING(RATES_EX);
1697 MFIE_STRING(GENERIC);
1698 MFIE_STRING(QOS_PARAMETER);
1699 default:
1700 return "UNKNOWN";
1701 }
94a79942 1702}
94a79942 1703
94a79942
LF
1704static inline void rtllib_extract_country_ie(
1705 struct rtllib_device *ieee,
1706 struct rtllib_info_element *info_element,
1707 struct rtllib_network *network,
db8971b6 1708 u8 *addr2)
94a79942
LF
1709{
1710 if (IS_DOT11D_ENABLE(ieee)) {
db8971b6 1711 if (info_element->len != 0) {
94a79942
LF
1712 memcpy(network->CountryIeBuf, info_element->data, info_element->len);
1713 network->CountryIeLen = info_element->len;
1714
db8971b6 1715 if (!IS_COUNTRY_IE_VALID(ieee)) {
4bb01423 1716 if (rtllib_act_scanning(ieee, false) && ieee->FirstIe_InScan)
d69d2054
MK
1717 netdev_info(ieee->dev,
1718 "Received beacon ContryIE, SSID: <%s>\n",
1719 network->ssid);
94a79942
LF
1720 Dot11d_UpdateCountryIe(ieee, addr2, info_element->len, info_element->data);
1721 }
1722 }
1723
db8971b6 1724 if (IS_EQUAL_CIE_SRC(ieee, addr2))
94a79942 1725 UPDATE_CIE_WATCHDOG(ieee);
94a79942
LF
1726 }
1727
1728}
94a79942
LF
1729
1730int rtllib_parse_info_param(struct rtllib_device *ieee,
1731 struct rtllib_info_element *info_element,
1732 u16 length,
1733 struct rtllib_network *network,
1734 struct rtllib_rx_stats *stats)
1735{
1736 u8 i;
1737 short offset;
db8971b6
LF
1738 u16 tmp_htcap_len = 0;
1739 u16 tmp_htinfo_len = 0;
1740 u16 ht_realtek_agg_len = 0;
94a79942 1741 u8 ht_realtek_agg_buf[MAX_IE_LEN];
94a79942
LF
1742 char rates_str[64];
1743 char *p;
8cc638e9 1744
94a79942
LF
1745 while (length >= sizeof(*info_element)) {
1746 if (sizeof(*info_element) + info_element->len > length) {
6d6163c3 1747 RTLLIB_DEBUG_MGMT("Info elem: parse failed: info_element->len + 2 > left : info_element->len+2=%zd left=%d, id=%d.\n",
94a79942
LF
1748 info_element->len +
1749 sizeof(*info_element),
1750 length, info_element->id);
1751 /* We stop processing but don't return an error here
1752 * because some misbehaviour APs break this rule. ie.
1753 * Orinoco AP1000. */
1754 break;
1755 }
1756
1757 switch (info_element->id) {
1758 case MFIE_TYPE_SSID:
1759 if (rtllib_is_empty_essid(info_element->data,
1760 info_element->len)) {
1761 network->flags |= NETWORK_EMPTY_ESSID;
1762 break;
1763 }
1764
1765 network->ssid_len = min(info_element->len,
1766 (u8) IW_ESSID_MAX_SIZE);
1767 memcpy(network->ssid, info_element->data, network->ssid_len);
1768 if (network->ssid_len < IW_ESSID_MAX_SIZE)
1769 memset(network->ssid + network->ssid_len, 0,
1770 IW_ESSID_MAX_SIZE - network->ssid_len);
1771
1772 RTLLIB_DEBUG_MGMT("MFIE_TYPE_SSID: '%s' len=%d.\n",
1773 network->ssid, network->ssid_len);
1774 break;
1775
1776 case MFIE_TYPE_RATES:
94a79942 1777 p = rates_str;
94a79942
LF
1778 network->rates_len = min(info_element->len,
1779 MAX_RATES_LENGTH);
1780 for (i = 0; i < network->rates_len; i++) {
1781 network->rates[i] = info_element->data[i];
94a79942
LF
1782 p += snprintf(p, sizeof(rates_str) -
1783 (p - rates_str), "%02X ",
1784 network->rates[i]);
94a79942
LF
1785 if (rtllib_is_ofdm_rate
1786 (info_element->data[i])) {
1787 network->flags |= NETWORK_HAS_OFDM;
1788 if (info_element->data[i] &
1789 RTLLIB_BASIC_RATE_MASK)
1790 network->flags &=
1791 ~NETWORK_HAS_CCK;
1792 }
1793
1794 if (rtllib_is_cck_rate
1795 (info_element->data[i])) {
1796 network->flags |= NETWORK_HAS_CCK;
1797 }
1798 }
1799
1800 RTLLIB_DEBUG_MGMT("MFIE_TYPE_RATES: '%s' (%d)\n",
1801 rates_str, network->rates_len);
1802 break;
1803
1804 case MFIE_TYPE_RATES_EX:
94a79942 1805 p = rates_str;
94a79942
LF
1806 network->rates_ex_len = min(info_element->len,
1807 MAX_RATES_EX_LENGTH);
1808 for (i = 0; i < network->rates_ex_len; i++) {
1809 network->rates_ex[i] = info_element->data[i];
94a79942
LF
1810 p += snprintf(p, sizeof(rates_str) -
1811 (p - rates_str), "%02X ",
03e71d6b 1812 network->rates_ex[i]);
94a79942
LF
1813 if (rtllib_is_ofdm_rate
1814 (info_element->data[i])) {
1815 network->flags |= NETWORK_HAS_OFDM;
1816 if (info_element->data[i] &
1817 RTLLIB_BASIC_RATE_MASK)
1818 network->flags &=
1819 ~NETWORK_HAS_CCK;
1820 }
1821 }
1822
1823 RTLLIB_DEBUG_MGMT("MFIE_TYPE_RATES_EX: '%s' (%d)\n",
1824 rates_str, network->rates_ex_len);
1825 break;
1826
1827 case MFIE_TYPE_DS_SET:
1828 RTLLIB_DEBUG_MGMT("MFIE_TYPE_DS_SET: %d\n",
1829 info_element->data[0]);
1830 network->channel = info_element->data[0];
1831 break;
1832
1833 case MFIE_TYPE_FH_SET:
1834 RTLLIB_DEBUG_MGMT("MFIE_TYPE_FH_SET: ignored\n");
1835 break;
1836
1837 case MFIE_TYPE_CF_SET:
1838 RTLLIB_DEBUG_MGMT("MFIE_TYPE_CF_SET: ignored\n");
1839 break;
1840
1841 case MFIE_TYPE_TIM:
1842 if (info_element->len < 4)
1843 break;
1844
1845 network->tim.tim_count = info_element->data[0];
1846 network->tim.tim_period = info_element->data[1];
1847
db8971b6
LF
1848 network->dtim_period = info_element->data[1];
1849 if (ieee->state != RTLLIB_LINKED)
1850 break;
0dd56506 1851 network->last_dtim_sta_time = jiffies;
94a79942 1852
db8971b6 1853 network->dtim_data = RTLLIB_DTIM_VALID;
94a79942 1854
94a79942 1855
db8971b6
LF
1856 if (info_element->data[2] & 1)
1857 network->dtim_data |= RTLLIB_DTIM_MBCAST;
94a79942 1858
db8971b6 1859 offset = (info_element->data[2] >> 1)*2;
94a79942 1860
94a79942 1861
db8971b6
LF
1862 if (ieee->assoc_id < 8*offset ||
1863 ieee->assoc_id > 8*(offset + info_element->len - 3))
1864 break;
94a79942 1865
db8971b6
LF
1866 offset = (ieee->assoc_id / 8) - offset;
1867 if (info_element->data[3 + offset] &
1868 (1 << (ieee->assoc_id % 8)))
1869 network->dtim_data |= RTLLIB_DTIM_UCAST;
94a79942
LF
1870
1871 network->listen_interval = network->dtim_period;
1872 break;
1873
1874 case MFIE_TYPE_ERP:
1875 network->erp_value = info_element->data[0];
1876 network->flags |= NETWORK_HAS_ERP_VALUE;
1877 RTLLIB_DEBUG_MGMT("MFIE_TYPE_ERP_SET: %d\n",
1878 network->erp_value);
1879 break;
1880 case MFIE_TYPE_IBSS_SET:
1881 network->atim_window = info_element->data[0];
1882 RTLLIB_DEBUG_MGMT("MFIE_TYPE_IBSS_SET: %d\n",
1883 network->atim_window);
1884 break;
1885
1886 case MFIE_TYPE_CHALLENGE:
1887 RTLLIB_DEBUG_MGMT("MFIE_TYPE_CHALLENGE: ignored\n");
1888 break;
1889
1890 case MFIE_TYPE_GENERIC:
1891 RTLLIB_DEBUG_MGMT("MFIE_TYPE_GENERIC: %d bytes\n",
1892 info_element->len);
1893 if (!rtllib_parse_qos_info_param_IE(info_element,
1894 network))
1895 break;
1896 if (info_element->len >= 4 &&
1897 info_element->data[0] == 0x00 &&
1898 info_element->data[1] == 0x50 &&
1899 info_element->data[2] == 0xf2 &&
1900 info_element->data[3] == 0x01) {
1901 network->wpa_ie_len = min(info_element->len + 2,
1902 MAX_WPA_IE_LEN);
1903 memcpy(network->wpa_ie, info_element,
1904 network->wpa_ie_len);
1905 break;
1906 }
db8971b6
LF
1907 if (info_element->len == 7 &&
1908 info_element->data[0] == 0x00 &&
1909 info_element->data[1] == 0xe0 &&
1910 info_element->data[2] == 0x4c &&
1911 info_element->data[3] == 0x01 &&
1912 info_element->data[4] == 0x02)
1913 network->Turbo_Enable = 1;
94a79942
LF
1914
1915 if (tmp_htcap_len == 0) {
1916 if (info_element->len >= 4 &&
1917 info_element->data[0] == 0x00 &&
1918 info_element->data[1] == 0x90 &&
1919 info_element->data[2] == 0x4c &&
1920 info_element->data[3] == 0x033) {
1921
d009f0d7 1922 tmp_htcap_len = min_t(u8, info_element->len, MAX_IE_LEN);
db8971b6 1923 if (tmp_htcap_len != 0) {
94a79942 1924 network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC;
db8971b6
LF
1925 network->bssht.bdHTCapLen = tmp_htcap_len > sizeof(network->bssht.bdHTCapBuf) ?
1926 sizeof(network->bssht.bdHTCapBuf) : tmp_htcap_len;
1927 memcpy(network->bssht.bdHTCapBuf, info_element->data, network->bssht.bdHTCapLen);
94a79942
LF
1928 }
1929 }
db8971b6 1930 if (tmp_htcap_len != 0) {
94a79942 1931 network->bssht.bdSupportHT = true;
e92b71d5 1932 network->bssht.bdHT1R = ((((struct ht_capab_ele *)(network->bssht.bdHTCapBuf))->MCS[1]) == 0);
db8971b6 1933 } else {
94a79942
LF
1934 network->bssht.bdSupportHT = false;
1935 network->bssht.bdHT1R = false;
1936 }
1937 }
1938
1939
db8971b6 1940 if (tmp_htinfo_len == 0) {
94a79942 1941 if (info_element->len >= 4 &&
db8971b6
LF
1942 info_element->data[0] == 0x00 &&
1943 info_element->data[1] == 0x90 &&
1944 info_element->data[2] == 0x4c &&
1945 info_element->data[3] == 0x034) {
d009f0d7 1946 tmp_htinfo_len = min_t(u8, info_element->len, MAX_IE_LEN);
db8971b6
LF
1947 if (tmp_htinfo_len != 0) {
1948 network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC;
1949 if (tmp_htinfo_len) {
1950 network->bssht.bdHTInfoLen = tmp_htinfo_len > sizeof(network->bssht.bdHTInfoBuf) ?
1951 sizeof(network->bssht.bdHTInfoBuf) : tmp_htinfo_len;
1952 memcpy(network->bssht.bdHTInfoBuf, info_element->data, network->bssht.bdHTInfoLen);
94a79942
LF
1953 }
1954
db8971b6
LF
1955 }
1956
94a79942
LF
1957 }
1958 }
1959
db8971b6
LF
1960 if (ieee->aggregation) {
1961 if (network->bssht.bdSupportHT) {
94a79942 1962 if (info_element->len >= 4 &&
db8971b6
LF
1963 info_element->data[0] == 0x00 &&
1964 info_element->data[1] == 0xe0 &&
1965 info_element->data[2] == 0x4c &&
1966 info_element->data[3] == 0x02) {
d009f0d7 1967 ht_realtek_agg_len = min_t(u8, info_element->len, MAX_IE_LEN);
db8971b6 1968 memcpy(ht_realtek_agg_buf, info_element->data, info_element->len);
94a79942 1969 }
db8971b6 1970 if (ht_realtek_agg_len >= 5) {
94a79942
LF
1971 network->realtek_cap_exit = true;
1972 network->bssht.bdRT2RTAggregation = true;
1973
1974 if ((ht_realtek_agg_buf[4] == 1) && (ht_realtek_agg_buf[5] & 0x02))
db8971b6 1975 network->bssht.bdRT2RTLongSlotTime = true;
94a79942 1976
db8971b6 1977 if ((ht_realtek_agg_buf[4] == 1) && (ht_realtek_agg_buf[5] & RT_HT_CAP_USE_92SE))
94a79942 1978 network->bssht.RT2RT_HT_Mode |= RT_HT_CAP_USE_92SE;
94a79942
LF
1979 }
1980 }
db8971b6 1981 if (ht_realtek_agg_len >= 5) {
94a79942
LF
1982 if ((ht_realtek_agg_buf[5] & RT_HT_CAP_USE_SOFTAP))
1983 network->bssht.RT2RT_HT_Mode |= RT_HT_CAP_USE_SOFTAP;
1984 }
1985 }
1986
db8971b6
LF
1987 if ((info_element->len >= 3 &&
1988 info_element->data[0] == 0x00 &&
1989 info_element->data[1] == 0x05 &&
1990 info_element->data[2] == 0xb5) ||
1991 (info_element->len >= 3 &&
1992 info_element->data[0] == 0x00 &&
1993 info_element->data[1] == 0x0a &&
1994 info_element->data[2] == 0xf7) ||
1995 (info_element->len >= 3 &&
1996 info_element->data[0] == 0x00 &&
1997 info_element->data[1] == 0x10 &&
1998 info_element->data[2] == 0x18)) {
1999 network->broadcom_cap_exist = true;
94a79942
LF
2000 }
2001 if (info_element->len >= 3 &&
db8971b6
LF
2002 info_element->data[0] == 0x00 &&
2003 info_element->data[1] == 0x0c &&
2004 info_element->data[2] == 0x43)
94a79942 2005 network->ralink_cap_exist = true;
94a79942 2006 if ((info_element->len >= 3 &&
db8971b6
LF
2007 info_element->data[0] == 0x00 &&
2008 info_element->data[1] == 0x03 &&
2009 info_element->data[2] == 0x7f) ||
2010 (info_element->len >= 3 &&
2011 info_element->data[0] == 0x00 &&
2012 info_element->data[1] == 0x13 &&
2013 info_element->data[2] == 0x74))
94a79942 2014 network->atheros_cap_exist = true;
94a79942
LF
2015
2016 if ((info_element->len >= 3 &&
db8971b6
LF
2017 info_element->data[0] == 0x00 &&
2018 info_element->data[1] == 0x50 &&
2019 info_element->data[2] == 0x43))
2020 network->marvell_cap_exist = true;
94a79942 2021 if (info_element->len >= 3 &&
db8971b6
LF
2022 info_element->data[0] == 0x00 &&
2023 info_element->data[1] == 0x40 &&
2024 info_element->data[2] == 0x96)
94a79942 2025 network->cisco_cap_exist = true;
94a79942
LF
2026
2027
2028 if (info_element->len >= 3 &&
db8971b6
LF
2029 info_element->data[0] == 0x00 &&
2030 info_element->data[1] == 0x0a &&
2031 info_element->data[2] == 0xf5)
94a79942 2032 network->airgo_cap_exist = true;
94a79942
LF
2033
2034 if (info_element->len > 4 &&
db8971b6
LF
2035 info_element->data[0] == 0x00 &&
2036 info_element->data[1] == 0x40 &&
2037 info_element->data[2] == 0x96 &&
2038 info_element->data[3] == 0x01) {
2039 if (info_element->len == 6) {
94a79942
LF
2040 memcpy(network->CcxRmState, &info_element[4], 2);
2041 if (network->CcxRmState[0] != 0)
94a79942 2042 network->bCcxRmEnable = true;
94a79942
LF
2043 else
2044 network->bCcxRmEnable = false;
2045 network->MBssidMask = network->CcxRmState[1] & 0x07;
db8971b6 2046 if (network->MBssidMask != 0) {
94a79942
LF
2047 network->bMBssidValid = true;
2048 network->MBssidMask = 0xff << (network->MBssidMask);
2049 memcpy(network->MBssid, network->bssid, ETH_ALEN);
2050 network->MBssid[5] &= network->MBssidMask;
db8971b6 2051 } else {
94a79942
LF
2052 network->bMBssidValid = false;
2053 }
db8971b6 2054 } else {
94a79942
LF
2055 network->bCcxRmEnable = false;
2056 }
2057 }
2058 if (info_element->len > 4 &&
db8971b6
LF
2059 info_element->data[0] == 0x00 &&
2060 info_element->data[1] == 0x40 &&
2061 info_element->data[2] == 0x96 &&
2062 info_element->data[3] == 0x03) {
2063 if (info_element->len == 5) {
94a79942
LF
2064 network->bWithCcxVerNum = true;
2065 network->BssCcxVerNumber = info_element->data[4];
db8971b6 2066 } else {
94a79942
LF
2067 network->bWithCcxVerNum = false;
2068 network->BssCcxVerNumber = 0;
2069 }
2070 }
2071 if (info_element->len > 4 &&
db8971b6
LF
2072 info_element->data[0] == 0x00 &&
2073 info_element->data[1] == 0x50 &&
2074 info_element->data[2] == 0xf2 &&
2075 info_element->data[3] == 0x04) {
94a79942
LF
2076 RTLLIB_DEBUG_MGMT("MFIE_TYPE_WZC: %d bytes\n",
2077 info_element->len);
94a79942
LF
2078 network->wzc_ie_len = min(info_element->len+2,
2079 MAX_WZC_IE_LEN);
2080 memcpy(network->wzc_ie, info_element,
2081 network->wzc_ie_len);
94a79942
LF
2082 }
2083 break;
2084
2085 case MFIE_TYPE_RSN:
2086 RTLLIB_DEBUG_MGMT("MFIE_TYPE_RSN: %d bytes\n",
2087 info_element->len);
2088 network->rsn_ie_len = min(info_element->len + 2,
2089 MAX_WPA_IE_LEN);
2090 memcpy(network->rsn_ie, info_element,
2091 network->rsn_ie_len);
2092 break;
2093
2094 case MFIE_TYPE_HT_CAP:
2095 RTLLIB_DEBUG_SCAN("MFIE_TYPE_HT_CAP: %d bytes\n",
2096 info_element->len);
d009f0d7 2097 tmp_htcap_len = min_t(u8, info_element->len, MAX_IE_LEN);
db8971b6 2098 if (tmp_htcap_len != 0) {
94a79942 2099 network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC;
db8971b6
LF
2100 network->bssht.bdHTCapLen = tmp_htcap_len > sizeof(network->bssht.bdHTCapBuf) ?
2101 sizeof(network->bssht.bdHTCapBuf) : tmp_htcap_len;
2102 memcpy(network->bssht.bdHTCapBuf,
2103 info_element->data,
2104 network->bssht.bdHTCapLen);
94a79942
LF
2105
2106 network->bssht.bdSupportHT = true;
db8971b6
LF
2107 network->bssht.bdHT1R = ((((struct ht_capab_ele *)
2108 network->bssht.bdHTCapBuf))->MCS[1]) == 0;
94a79942 2109
db8971b6
LF
2110 network->bssht.bdBandWidth = (enum ht_channel_width)
2111 (((struct ht_capab_ele *)
2112 (network->bssht.bdHTCapBuf))->ChlWidth);
2113 } else {
94a79942
LF
2114 network->bssht.bdSupportHT = false;
2115 network->bssht.bdHT1R = false;
db8971b6 2116 network->bssht.bdBandWidth = HT_CHANNEL_WIDTH_20;
94a79942
LF
2117 }
2118 break;
2119
2120
2121 case MFIE_TYPE_HT_INFO:
2122 RTLLIB_DEBUG_SCAN("MFIE_TYPE_HT_INFO: %d bytes\n",
2123 info_element->len);
d009f0d7 2124 tmp_htinfo_len = min_t(u8, info_element->len, MAX_IE_LEN);
db8971b6 2125 if (tmp_htinfo_len) {
94a79942 2126 network->bssht.bdHTSpecVer = HT_SPEC_VER_IEEE;
db8971b6
LF
2127 network->bssht.bdHTInfoLen = tmp_htinfo_len >
2128 sizeof(network->bssht.bdHTInfoBuf) ?
2129 sizeof(network->bssht.bdHTInfoBuf) :
2130 tmp_htinfo_len;
2131 memcpy(network->bssht.bdHTInfoBuf,
2132 info_element->data,
2133 network->bssht.bdHTInfoLen);
94a79942
LF
2134 }
2135 break;
2136
2137 case MFIE_TYPE_AIRONET:
2138 RTLLIB_DEBUG_SCAN("MFIE_TYPE_AIRONET: %d bytes\n",
2139 info_element->len);
db8971b6 2140 if (info_element->len > IE_CISCO_FLAG_POSITION) {
94a79942
LF
2141 network->bWithAironetIE = true;
2142
db8971b6
LF
2143 if ((info_element->data[IE_CISCO_FLAG_POSITION]
2144 & SUPPORT_CKIP_MIC) ||
2145 (info_element->data[IE_CISCO_FLAG_POSITION]
2146 & SUPPORT_CKIP_PK))
94a79942 2147 network->bCkipSupported = true;
94a79942 2148 else
94a79942 2149 network->bCkipSupported = false;
db8971b6 2150 } else {
94a79942
LF
2151 network->bWithAironetIE = false;
2152 network->bCkipSupported = false;
2153 }
2154 break;
2155 case MFIE_TYPE_QOS_PARAMETER:
d69d2054
MK
2156 netdev_err(ieee->dev,
2157 "QoS Error need to parse QOS_PARAMETER IE\n");
94a79942
LF
2158 break;
2159
94a79942
LF
2160 case MFIE_TYPE_COUNTRY:
2161 RTLLIB_DEBUG_SCAN("MFIE_TYPE_COUNTRY: %d bytes\n",
2162 info_element->len);
db8971b6
LF
2163 rtllib_extract_country_ie(ieee, info_element, network,
2164 network->bssid);
94a79942 2165 break;
94a79942
LF
2166/* TODO */
2167 default:
2168 RTLLIB_DEBUG_MGMT
2169 ("Unsupported info element: %s (%d)\n",
2170 get_info_element_string(info_element->id),
2171 info_element->id);
2172 break;
2173 }
2174
2175 length -= sizeof(*info_element) + info_element->len;
2176 info_element =
2177 (struct rtllib_info_element *)&info_element->
2178 data[info_element->len];
2179 }
2180
2181 if (!network->atheros_cap_exist && !network->broadcom_cap_exist &&
db8971b6
LF
2182 !network->cisco_cap_exist && !network->ralink_cap_exist &&
2183 !network->bssht.bdRT2RTAggregation)
94a79942 2184 network->unknown_cap_exist = true;
94a79942 2185 else
94a79942 2186 network->unknown_cap_exist = false;
94a79942
LF
2187 return 0;
2188}
2189
49aab5fd 2190static long rtllib_translate_todbm(u8 signal_strength_index)
94a79942
LF
2191{
2192 long signal_power;
2193
2194 signal_power = (long)((signal_strength_index + 1) >> 1);
2195 signal_power -= 95;
2196
2197 return signal_power;
2198}
2199
2200static inline int rtllib_network_init(
2201 struct rtllib_device *ieee,
2202 struct rtllib_probe_response *beacon,
2203 struct rtllib_network *network,
2204 struct rtllib_rx_stats *stats)
2205{
94a79942
LF
2206
2207 /*
db8971b6
LF
2208 network->qos_data.active = 0;
2209 network->qos_data.supported = 0;
2210 network->qos_data.param_count = 0;
2211 network->qos_data.old_param_count = 0;
94a79942
LF
2212 */
2213 memset(&network->qos_data, 0, sizeof(struct rtllib_qos_data));
2214
2215 /* Pull out fixed field data */
2216 memcpy(network->bssid, beacon->header.addr3, ETH_ALEN);
2217 network->capability = le16_to_cpu(beacon->capability);
2218 network->last_scanned = jiffies;
e0b1ca60
RK
2219 network->time_stamp[0] = beacon->time_stamp[0];
2220 network->time_stamp[1] = beacon->time_stamp[1];
2221 network->beacon_interval = le16_to_cpu(beacon->beacon_interval);
94a79942
LF
2222 /* Where to pull this? beacon->listen_interval;*/
2223 network->listen_interval = 0x0A;
2224 network->rates_len = network->rates_ex_len = 0;
2225 network->last_associate = 0;
2226 network->ssid_len = 0;
2227 network->hidden_ssid_len = 0;
2228 memset(network->hidden_ssid, 0, sizeof(network->hidden_ssid));
2229 network->flags = 0;
2230 network->atim_window = 0;
2231 network->erp_value = (network->capability & WLAN_CAPABILITY_IBSS) ?
db8971b6 2232 0x3 : 0x0;
94a79942 2233 network->berp_info_valid = false;
db8971b6 2234 network->broadcom_cap_exist = false;
94a79942
LF
2235 network->ralink_cap_exist = false;
2236 network->atheros_cap_exist = false;
2237 network->cisco_cap_exist = false;
2238 network->unknown_cap_exist = false;
2239 network->realtek_cap_exit = false;
2240 network->marvell_cap_exist = false;
2241 network->airgo_cap_exist = false;
2242 network->Turbo_Enable = 0;
2243 network->SignalStrength = stats->SignalStrength;
2244 network->RSSI = stats->SignalStrength;
94a79942
LF
2245 network->CountryIeLen = 0;
2246 memset(network->CountryIeBuf, 0, MAX_IE_LEN);
94a79942
LF
2247 HTInitializeBssDesc(&network->bssht);
2248 if (stats->freq == RTLLIB_52GHZ_BAND) {
2249 /* for A band (No DS info) */
2250 network->channel = stats->received_channel;
2251 } else
2252 network->flags |= NETWORK_HAS_CCK;
2253
2254 network->wpa_ie_len = 0;
2255 network->rsn_ie_len = 0;
94a79942 2256 network->wzc_ie_len = 0;
94a79942 2257
db8971b6 2258 if (rtllib_parse_info_param(ieee,
94a79942
LF
2259 beacon->info_element,
2260 (stats->len - sizeof(*beacon)),
2261 network,
2262 stats))
db8971b6 2263 return 1;
94a79942
LF
2264
2265 network->mode = 0;
2266 if (stats->freq == RTLLIB_52GHZ_BAND)
2267 network->mode = IEEE_A;
2268 else {
2269 if (network->flags & NETWORK_HAS_OFDM)
2270 network->mode |= IEEE_G;
2271 if (network->flags & NETWORK_HAS_CCK)
2272 network->mode |= IEEE_B;
2273 }
2274
2275 if (network->mode == 0) {
6d6163c3 2276 RTLLIB_DEBUG_SCAN("Filtered out '%s (%pM)' network.\n",
94a79942
LF
2277 escape_essid(network->ssid,
2278 network->ssid_len),
ac50ddaa 2279 network->bssid);
94a79942
LF
2280 return 1;
2281 }
2282
db8971b6 2283 if (network->bssht.bdSupportHT) {
94a79942
LF
2284 if (network->mode == IEEE_A)
2285 network->mode = IEEE_N_5G;
2286 else if (network->mode & (IEEE_G | IEEE_B))
2287 network->mode = IEEE_N_24G;
2288 }
2289 if (rtllib_is_empty_essid(network->ssid, network->ssid_len))
2290 network->flags |= NETWORK_EMPTY_ESSID;
2291 stats->signal = 30 + (stats->SignalStrength * 70) / 100;
db8971b6 2292 stats->noise = rtllib_translate_todbm((u8)(100-stats->signal)) - 25;
94a79942
LF
2293
2294 memcpy(&network->stats, stats, sizeof(network->stats));
2295
2296 return 0;
2297}
2298
2299static inline int is_same_network(struct rtllib_network *src,
2300 struct rtllib_network *dst, u8 ssidbroad)
2301{
2302 /* A network is only a duplicate if the channel, BSSID, ESSID
2303 * and the capability field (in particular IBSS and BSS) all match.
2304 * We treat all <hidden> with the same BSSID and channel
2305 * as one network */
db8971b6 2306 return (((src->ssid_len == dst->ssid_len) || (!ssidbroad)) &&
94a79942
LF
2307 (src->channel == dst->channel) &&
2308 !memcmp(src->bssid, dst->bssid, ETH_ALEN) &&
db8971b6
LF
2309 (!memcmp(src->ssid, dst->ssid, src->ssid_len) ||
2310 (!ssidbroad)) &&
94a79942
LF
2311 ((src->capability & WLAN_CAPABILITY_IBSS) ==
2312 (dst->capability & WLAN_CAPABILITY_IBSS)) &&
2313 ((src->capability & WLAN_CAPABILITY_ESS) ==
2314 (dst->capability & WLAN_CAPABILITY_ESS)));
2315}
2316
94a79942
LF
2317
2318static inline void update_network(struct rtllib_network *dst,
2319 struct rtllib_network *src)
2320{
2321 int qos_active;
2322 u8 old_param;
2323
2324 memcpy(&dst->stats, &src->stats, sizeof(struct rtllib_rx_stats));
2325 dst->capability = src->capability;
2326 memcpy(dst->rates, src->rates, src->rates_len);
2327 dst->rates_len = src->rates_len;
2328 memcpy(dst->rates_ex, src->rates_ex, src->rates_ex_len);
2329 dst->rates_ex_len = src->rates_ex_len;
db8971b6
LF
2330 if (src->ssid_len > 0) {
2331 if (dst->ssid_len == 0) {
94a79942
LF
2332 memset(dst->hidden_ssid, 0, sizeof(dst->hidden_ssid));
2333 dst->hidden_ssid_len = src->ssid_len;
2334 memcpy(dst->hidden_ssid, src->ssid, src->ssid_len);
db8971b6 2335 } else {
94a79942
LF
2336 memset(dst->ssid, 0, dst->ssid_len);
2337 dst->ssid_len = src->ssid_len;
2338 memcpy(dst->ssid, src->ssid, src->ssid_len);
2339 }
2340 }
2341 dst->mode = src->mode;
2342 dst->flags = src->flags;
2343 dst->time_stamp[0] = src->time_stamp[0];
2344 dst->time_stamp[1] = src->time_stamp[1];
db8971b6 2345 if (src->flags & NETWORK_HAS_ERP_VALUE) {
94a79942
LF
2346 dst->erp_value = src->erp_value;
2347 dst->berp_info_valid = src->berp_info_valid = true;
2348 }
2349 dst->beacon_interval = src->beacon_interval;
2350 dst->listen_interval = src->listen_interval;
2351 dst->atim_window = src->atim_window;
2352 dst->dtim_period = src->dtim_period;
2353 dst->dtim_data = src->dtim_data;
0dd56506 2354 dst->last_dtim_sta_time = src->last_dtim_sta_time;
94a79942
LF
2355 memcpy(&dst->tim, &src->tim, sizeof(struct rtllib_tim_parameters));
2356
db8971b6 2357 dst->bssht.bdSupportHT = src->bssht.bdSupportHT;
94a79942 2358 dst->bssht.bdRT2RTAggregation = src->bssht.bdRT2RTAggregation;
db8971b6
LF
2359 dst->bssht.bdHTCapLen = src->bssht.bdHTCapLen;
2360 memcpy(dst->bssht.bdHTCapBuf, src->bssht.bdHTCapBuf,
2361 src->bssht.bdHTCapLen);
2362 dst->bssht.bdHTInfoLen = src->bssht.bdHTInfoLen;
2363 memcpy(dst->bssht.bdHTInfoBuf, src->bssht.bdHTInfoBuf,
2364 src->bssht.bdHTInfoLen);
94a79942
LF
2365 dst->bssht.bdHTSpecVer = src->bssht.bdHTSpecVer;
2366 dst->bssht.bdRT2RTLongSlotTime = src->bssht.bdRT2RTLongSlotTime;
2367 dst->broadcom_cap_exist = src->broadcom_cap_exist;
2368 dst->ralink_cap_exist = src->ralink_cap_exist;
2369 dst->atheros_cap_exist = src->atheros_cap_exist;
2370 dst->realtek_cap_exit = src->realtek_cap_exit;
2371 dst->marvell_cap_exist = src->marvell_cap_exist;
2372 dst->cisco_cap_exist = src->cisco_cap_exist;
2373 dst->airgo_cap_exist = src->airgo_cap_exist;
2374 dst->unknown_cap_exist = src->unknown_cap_exist;
2375 memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len);
2376 dst->wpa_ie_len = src->wpa_ie_len;
2377 memcpy(dst->rsn_ie, src->rsn_ie, src->rsn_ie_len);
2378 dst->rsn_ie_len = src->rsn_ie_len;
94a79942
LF
2379 memcpy(dst->wzc_ie, src->wzc_ie, src->wzc_ie_len);
2380 dst->wzc_ie_len = src->wzc_ie_len;
94a79942
LF
2381
2382 dst->last_scanned = jiffies;
2383 /* qos related parameters */
2384 qos_active = dst->qos_data.active;
2385 old_param = dst->qos_data.param_count;
2386 dst->qos_data.supported = src->qos_data.supported;
2387 if (dst->flags & NETWORK_HAS_QOS_PARAMETERS)
db8971b6
LF
2388 memcpy(&dst->qos_data, &src->qos_data,
2389 sizeof(struct rtllib_qos_data));
94a79942
LF
2390 if (dst->qos_data.supported == 1) {
2391 if (dst->ssid_len)
2392 RTLLIB_DEBUG_QOS
2393 ("QoS the network %s is QoS supported\n",
2394 dst->ssid);
2395 else
2396 RTLLIB_DEBUG_QOS
2397 ("QoS the network is QoS supported\n");
2398 }
2399 dst->qos_data.active = qos_active;
2400 dst->qos_data.old_param_count = old_param;
2401
2402 /* dst->last_associate is not overwritten */
2403 dst->wmm_info = src->wmm_info;
db8971b6
LF
2404 if (src->wmm_param[0].ac_aci_acm_aifsn ||
2405 src->wmm_param[1].ac_aci_acm_aifsn ||
2406 src->wmm_param[2].ac_aci_acm_aifsn ||
a2f9dc55 2407 src->wmm_param[3].ac_aci_acm_aifsn)
db8971b6 2408 memcpy(dst->wmm_param, src->wmm_param, WME_AC_PRAM_LEN);
94a79942
LF
2409
2410 dst->SignalStrength = src->SignalStrength;
2411 dst->RSSI = src->RSSI;
2412 dst->Turbo_Enable = src->Turbo_Enable;
2413
94a79942
LF
2414 dst->CountryIeLen = src->CountryIeLen;
2415 memcpy(dst->CountryIeBuf, src->CountryIeBuf, src->CountryIeLen);
94a79942
LF
2416
2417 dst->bWithAironetIE = src->bWithAironetIE;
2418 dst->bCkipSupported = src->bCkipSupported;
db8971b6 2419 memcpy(dst->CcxRmState, src->CcxRmState, 2);
94a79942
LF
2420 dst->bCcxRmEnable = src->bCcxRmEnable;
2421 dst->MBssidMask = src->MBssidMask;
2422 dst->bMBssidValid = src->bMBssidValid;
db8971b6 2423 memcpy(dst->MBssid, src->MBssid, 6);
94a79942
LF
2424 dst->bWithCcxVerNum = src->bWithCcxVerNum;
2425 dst->BssCcxVerNumber = src->BssCcxVerNumber;
94a79942 2426}
db8971b6 2427
94a79942
LF
2428static inline int is_beacon(__le16 fc)
2429{
2430 return (WLAN_FC_GET_STYPE(le16_to_cpu(fc)) == RTLLIB_STYPE_BEACON);
2431}
2432
db8971b6 2433static int IsPassiveChannel(struct rtllib_device *rtllib, u8 channel)
94a79942
LF
2434{
2435 if (MAX_CHANNEL_NUMBER < channel) {
d69d2054 2436 netdev_info(rtllib->dev, "%s(): Invalid Channel\n", __func__);
94a79942
LF
2437 return 0;
2438 }
2439
2440 if (rtllib->active_channel_map[channel] == 2)
2441 return 1;
2442
2443 return 0;
2444}
2445
976d5341 2446int rtllib_legal_channel(struct rtllib_device *rtllib, u8 channel)
94a79942
LF
2447{
2448 if (MAX_CHANNEL_NUMBER < channel) {
d69d2054 2449 netdev_info(rtllib->dev, "%s(): Invalid Channel\n", __func__);
94a79942
LF
2450 return 0;
2451 }
2452 if (rtllib->active_channel_map[channel] > 0)
2453 return 1;
2454
2455 return 0;
2456}
976d5341 2457EXPORT_SYMBOL(rtllib_legal_channel);
94a79942 2458
94a79942
LF
2459static inline void rtllib_process_probe_response(
2460 struct rtllib_device *ieee,
2461 struct rtllib_probe_response *beacon,
2462 struct rtllib_rx_stats *stats)
2463{
2464 struct rtllib_network *target;
2465 struct rtllib_network *oldest = NULL;
94a79942 2466 struct rtllib_info_element *info_element = &beacon->info_element[0];
94a79942
LF
2467 unsigned long flags;
2468 short renew;
db8971b6
LF
2469 struct rtllib_network *network = kzalloc(sizeof(struct rtllib_network),
2470 GFP_ATOMIC);
94a79942 2471
cb762154 2472 if (!network)
94a79942 2473 return;
94a79942
LF
2474
2475 RTLLIB_DEBUG_SCAN(
ac50ddaa 2476 "'%s' ( %pM ): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
94a79942 2477 escape_essid(info_element->data, info_element->len),
ac50ddaa 2478 beacon->header.addr3,
26a6b074
RK
2479 (le16_to_cpu(beacon->capability) & (1<<0xf)) ? '1' : '0',
2480 (le16_to_cpu(beacon->capability) & (1<<0xe)) ? '1' : '0',
2481 (le16_to_cpu(beacon->capability) & (1<<0xd)) ? '1' : '0',
2482 (le16_to_cpu(beacon->capability) & (1<<0xc)) ? '1' : '0',
2483 (le16_to_cpu(beacon->capability) & (1<<0xb)) ? '1' : '0',
2484 (le16_to_cpu(beacon->capability) & (1<<0xa)) ? '1' : '0',
2485 (le16_to_cpu(beacon->capability) & (1<<0x9)) ? '1' : '0',
2486 (le16_to_cpu(beacon->capability) & (1<<0x8)) ? '1' : '0',
2487 (le16_to_cpu(beacon->capability) & (1<<0x7)) ? '1' : '0',
2488 (le16_to_cpu(beacon->capability) & (1<<0x6)) ? '1' : '0',
2489 (le16_to_cpu(beacon->capability) & (1<<0x5)) ? '1' : '0',
2490 (le16_to_cpu(beacon->capability) & (1<<0x4)) ? '1' : '0',
2491 (le16_to_cpu(beacon->capability) & (1<<0x3)) ? '1' : '0',
2492 (le16_to_cpu(beacon->capability) & (1<<0x2)) ? '1' : '0',
2493 (le16_to_cpu(beacon->capability) & (1<<0x1)) ? '1' : '0',
2494 (le16_to_cpu(beacon->capability) & (1<<0x0)) ? '1' : '0');
94a79942
LF
2495
2496 if (rtllib_network_init(ieee, beacon, network, stats)) {
ac50ddaa 2497 RTLLIB_DEBUG_SCAN("Dropped '%s' ( %pM) via %s.\n",
db8971b6
LF
2498 escape_essid(info_element->data,
2499 info_element->len),
ac50ddaa 2500 beacon->header.addr3,
26a6b074
RK
2501 WLAN_FC_GET_STYPE(
2502 le16_to_cpu(beacon->header.frame_ctl)) ==
db8971b6
LF
2503 RTLLIB_STYPE_PROBE_RESP ?
2504 "PROBE RESPONSE" : "BEACON");
94a79942
LF
2505 goto free_network;
2506 }
2507
2508
976d5341 2509 if (!rtllib_legal_channel(ieee, network->channel))
94a79942
LF
2510 goto free_network;
2511
26a6b074 2512 if (WLAN_FC_GET_STYPE(le16_to_cpu(beacon->header.frame_ctl)) ==
db8971b6 2513 RTLLIB_STYPE_PROBE_RESP) {
94a79942 2514 if (IsPassiveChannel(ieee, network->channel)) {
d69d2054
MK
2515 netdev_info(ieee->dev,
2516 "GetScanInfo(): For Global Domain, filter probe response at channel(%d).\n",
2517 network->channel);
94a79942
LF
2518 goto free_network;
2519 }
2520 }
2521
2522 /* The network parsed correctly -- so now we scan our known networks
2523 * to see if we can find it in our list.
2524 *
2525 * NOTE: This search is definitely not optimized. Once its doing
db8971b6
LF
2526 * the "right thing" we'll optimize it for efficiency if
2527 * necessary */
94a79942
LF
2528
2529 /* Search for this entry in the list and update it if it is
2530 * already there. */
2531
2532 spin_lock_irqsave(&ieee->lock, flags);
db8971b6
LF
2533 if (is_same_network(&ieee->current_network, network,
2534 (network->ssid_len ? 1 : 0))) {
2535 update_network(&ieee->current_network, network);
2536 if ((ieee->current_network.mode == IEEE_N_24G ||
2537 ieee->current_network.mode == IEEE_G)
2538 && ieee->current_network.berp_info_valid) {
2539 if (ieee->current_network.erp_value & ERP_UseProtection)
94a79942 2540 ieee->current_network.buseprotection = true;
db8971b6
LF
2541 else
2542 ieee->current_network.buseprotection = false;
94a79942 2543 }
db8971b6
LF
2544 if (is_beacon(beacon->header.frame_ctl)) {
2545 if (ieee->state >= RTLLIB_LINKED)
2546 ieee->LinkDetectInfo.NumRecvBcnInPeriod++;
94a79942
LF
2547 }
2548 }
94a79942 2549 list_for_each_entry(target, &ieee->network_list, list) {
db8971b6
LF
2550 if (is_same_network(target, network,
2551 (target->ssid_len ? 1 : 0)))
94a79942
LF
2552 break;
2553 if ((oldest == NULL) ||
2554 (target->last_scanned < oldest->last_scanned))
2555 oldest = target;
2556 }
2557
2558 /* If we didn't find a match, then get a new network slot to initialize
2559 * with this beacon's information */
2560 if (&target->list == &ieee->network_list) {
2561 if (list_empty(&ieee->network_free_list)) {
2562 /* If there are no more slots, expire the oldest */
2563 list_del(&oldest->list);
2564 target = oldest;
6d6163c3 2565 RTLLIB_DEBUG_SCAN("Expired '%s' ( %pM) from network list.\n",
94a79942
LF
2566 escape_essid(target->ssid,
2567 target->ssid_len),
ac50ddaa 2568 target->bssid);
94a79942
LF
2569 } else {
2570 /* Otherwise just pull from the free list */
2571 target = list_entry(ieee->network_free_list.next,
2572 struct rtllib_network, list);
2573 list_del(ieee->network_free_list.next);
2574 }
2575
2576
ac50ddaa 2577 RTLLIB_DEBUG_SCAN("Adding '%s' ( %pM) via %s.\n",
db8971b6 2578 escape_essid(network->ssid,
ac50ddaa 2579 network->ssid_len), network->bssid,
26a6b074
RK
2580 WLAN_FC_GET_STYPE(
2581 le16_to_cpu(beacon->header.frame_ctl)) ==
db8971b6
LF
2582 RTLLIB_STYPE_PROBE_RESP ?
2583 "PROBE RESPONSE" : "BEACON");
94a79942
LF
2584 memcpy(target, network, sizeof(*target));
2585 list_add_tail(&target->list, &ieee->network_list);
2586 if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE)
2587 rtllib_softmac_new_net(ieee, network);
2588 } else {
ac50ddaa 2589 RTLLIB_DEBUG_SCAN("Updating '%s' ( %pM) via %s.\n",
db8971b6 2590 escape_essid(target->ssid,
ac50ddaa 2591 target->ssid_len), target->bssid,
26a6b074
RK
2592 WLAN_FC_GET_STYPE(
2593 le16_to_cpu(beacon->header.frame_ctl)) ==
db8971b6
LF
2594 RTLLIB_STYPE_PROBE_RESP ?
2595 "PROBE RESPONSE" : "BEACON");
2596
2597 /* we have an entry and we are going to update it. But this
2598 * entry may be already expired. In this case we do the same
2599 * as we found a new net and call the new_net handler
94a79942 2600 */
db8971b6
LF
2601 renew = !time_after(target->last_scanned + ieee->scan_age,
2602 jiffies);
94a79942 2603 if ((!target->ssid_len) &&
db8971b6
LF
2604 (((network->ssid_len > 0) && (target->hidden_ssid_len == 0))
2605 || ((ieee->current_network.ssid_len == network->ssid_len) &&
2606 (strncmp(ieee->current_network.ssid, network->ssid,
2607 network->ssid_len) == 0) &&
2608 (ieee->state == RTLLIB_NOLINK))))
94a79942 2609 renew = 1;
94a79942
LF
2610 update_network(target, network);
2611 if (renew && (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE))
2612 rtllib_softmac_new_net(ieee, network);
2613 }
2614
2615 spin_unlock_irqrestore(&ieee->lock, flags);
db8971b6
LF
2616 if (is_beacon(beacon->header.frame_ctl) &&
2617 is_same_network(&ieee->current_network, network,
2618 (network->ssid_len ? 1 : 0)) &&
2619 (ieee->state == RTLLIB_LINKED)) {
2620 if (ieee->handle_beacon != NULL)
2621 ieee->handle_beacon(ieee->dev, beacon,
2622 &ieee->current_network);
94a79942
LF
2623 }
2624free_network:
2625 kfree(network);
94a79942
LF
2626}
2627
2628void rtllib_rx_mgt(struct rtllib_device *ieee,
db8971b6 2629 struct sk_buff *skb,
94a79942
LF
2630 struct rtllib_rx_stats *stats)
2631{
73df9986 2632 struct rtllib_hdr_4addr *header = (struct rtllib_hdr_4addr *)skb->data;
db8971b6 2633
26a6b074
RK
2634 if ((WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl)) !=
2635 RTLLIB_STYPE_PROBE_RESP) &&
2636 (WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl)) !=
2637 RTLLIB_STYPE_BEACON))
db8971b6
LF
2638 ieee->last_rx_ps_time = jiffies;
2639
26a6b074 2640 switch (WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl))) {
db8971b6
LF
2641
2642 case RTLLIB_STYPE_BEACON:
2643 RTLLIB_DEBUG_MGMT("received BEACON (%d)\n",
26a6b074 2644 WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl)));
db8971b6
LF
2645 RTLLIB_DEBUG_SCAN("Beacon\n");
2646 rtllib_process_probe_response(
2647 ieee, (struct rtllib_probe_response *)header,
2648 stats);
94a79942 2649
db8971b6
LF
2650 if (ieee->sta_sleep || (ieee->ps != RTLLIB_PS_DISABLED &&
2651 ieee->iw_mode == IW_MODE_INFRA &&
2652 ieee->state == RTLLIB_LINKED))
2653 tasklet_schedule(&ieee->ps_task);
2654
2655 break;
2656
2657 case RTLLIB_STYPE_PROBE_RESP:
2658 RTLLIB_DEBUG_MGMT("received PROBE RESPONSE (%d)\n",
26a6b074 2659 WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl)));
db8971b6
LF
2660 RTLLIB_DEBUG_SCAN("Probe response\n");
2661 rtllib_process_probe_response(ieee,
2662 (struct rtllib_probe_response *)header, stats);
2663 break;
2664 case RTLLIB_STYPE_PROBE_REQ:
2665 RTLLIB_DEBUG_MGMT("received PROBE RESQUEST (%d)\n",
26a6b074
RK
2666 WLAN_FC_GET_STYPE(
2667 le16_to_cpu(header->frame_ctl)));
db8971b6
LF
2668 RTLLIB_DEBUG_SCAN("Probe request\n");
2669 if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) &&
2670 ((ieee->iw_mode == IW_MODE_ADHOC ||
2671 ieee->iw_mode == IW_MODE_MASTER) &&
2672 ieee->state == RTLLIB_LINKED))
2673 rtllib_rx_probe_rq(ieee, skb);
2674 break;
2675 }
94a79942 2676}