blob: bb789cc9208d5d9c785e4f13dd2737c4dc264a08 [file] [log] [blame]
Larry Finger94a79942011-08-23 19:00:42 -05001/*
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
Andrea Merello559a4c32013-08-26 13:53:30 +020017 Andrea Merello <andrea.merello@gmail.com>
Larry Finger94a79942011-08-23 19:00:42 -050018
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>
Larry Finger94a79942011-08-23 19:00:42 -050039#include <linux/wireless.h>
40#include <linux/etherdevice.h>
Larry Fingerdb8971b2011-08-25 11:48:25 -050041#include <linux/uaccess.h>
Larry Finger94a79942011-08-23 19:00:42 -050042#include <linux/ctype.h>
43
44#include "rtllib.h"
Larry Finger94a79942011-08-23 19:00:42 -050045#include "dot11d.h"
Larry Finger94a79942011-08-23 19:00:42 -050046
Larry Finger94a79942011-08-23 19:00:42 -050047static inline void rtllib_monitor_rx(struct rtllib_device *ieee,
Larry Fingerdb8971b2011-08-25 11:48:25 -050048 struct sk_buff *skb, struct rtllib_rx_stats *rx_status,
Larry Finger94a79942011-08-23 19:00:42 -050049 size_t hdr_length)
50{
Larry Finger94a79942011-08-23 19:00:42 -050051 skb->dev = ieee->dev;
Larry Fingerdb8971b2011-08-25 11:48:25 -050052 skb_reset_mac_header(skb);
Larry Finger94a79942011-08-23 19:00:42 -050053 skb_pull(skb, hdr_length);
54 skb->pkt_type = PACKET_OTHERHOST;
Mahati Chamarthy3f76a4e2014-09-18 19:27:09 +053055 skb->protocol = htons(ETH_P_80211_RAW);
Larry Finger94a79942011-08-23 19:00:42 -050056 memset(skb->cb, 0, sizeof(skb->cb));
57 netif_rx(skb);
Larry Finger94a79942011-08-23 19:00:42 -050058}
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,
Larry Fingerdb8971b2011-08-25 11:48:25 -050063 unsigned int frag, u8 tid, u8 *src, u8 *dst)
Larry Finger94a79942011-08-23 19:00:42 -050064{
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(
Jonathan Jin6d6163c2014-12-15 21:28:23 -060073 "expiring fragment cache entry seq=%u last_frag=%u\n",
Larry Finger94a79942011-08-23 19:00:42 -050074 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
Larry Fingerdb8971b2011-08-25 11:48:25 -0500104 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++;
Larry Finger94a79942011-08-23 19:00:42 -0500109 } else if (RTLLIB_QOS_HAS_SEQ(fc)) {
Larry Fingerdb8971b2011-08-25 11:48:25 -0500110 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++;
Larry Finger94a79942011-08-23 19:00:42 -0500114 } else {
Larry Fingerdb8971b2011-08-25 11:48:25 -0500115 tid = 0;
Larry Finger94a79942011-08-23 19:00:42 -0500116 }
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 */ +
Larry Fingerdb8971b2011-08-25 11:48:25 -0500126 (RTLLIB_QOS_HAS_SEQ(fc) ? 2 : 0) /* QOS Control */);
Larry Finger94a79942011-08-23 19:00:42 -0500127 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
Mateusz Kulikowski14b40d92015-04-01 00:24:37 +0200146 * should have already been received
147 */
Larry Fingerdb8971b2011-08-25 11:48:25 -0500148 entry = rtllib_frag_cache_find(ieee, seq, frag, tid, hdr->addr2,
Larry Finger94a79942011-08-23 19:00:42 -0500149 hdr->addr1);
150 if (entry != NULL) {
151 entry->last_frag = frag;
152 skb = entry->skb;
153 }
154 }
155
156 return skb;
157}
158
159
160/* Called only as a tasklet (software IRQ) */
161static int rtllib_frag_cache_invalidate(struct rtllib_device *ieee,
162 struct rtllib_hdr_4addr *hdr)
163{
164 u16 fc = le16_to_cpu(hdr->frame_ctl);
165 u16 sc = le16_to_cpu(hdr->seq_ctl);
166 unsigned int seq = WLAN_GET_SEQ_SEQ(sc);
167 struct rtllib_frag_entry *entry;
168 struct rtllib_hdr_3addrqos *hdr_3addrqos;
169 struct rtllib_hdr_4addrqos *hdr_4addrqos;
170 u8 tid;
171
Larry Fingerdb8971b2011-08-25 11:48:25 -0500172 if (((fc & RTLLIB_FCTL_DSTODS) == RTLLIB_FCTL_DSTODS) && RTLLIB_QOS_HAS_SEQ(fc)) {
173 hdr_4addrqos = (struct rtllib_hdr_4addrqos *)hdr;
174 tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & RTLLIB_QCTL_TID;
175 tid = UP2AC(tid);
176 tid++;
Larry Finger94a79942011-08-23 19:00:42 -0500177 } else if (RTLLIB_QOS_HAS_SEQ(fc)) {
Larry Fingerdb8971b2011-08-25 11:48:25 -0500178 hdr_3addrqos = (struct rtllib_hdr_3addrqos *)hdr;
179 tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & RTLLIB_QCTL_TID;
180 tid = UP2AC(tid);
181 tid++;
Larry Finger94a79942011-08-23 19:00:42 -0500182 } else {
Larry Fingerdb8971b2011-08-25 11:48:25 -0500183 tid = 0;
Larry Finger94a79942011-08-23 19:00:42 -0500184 }
185
Larry Fingerdb8971b2011-08-25 11:48:25 -0500186 entry = rtllib_frag_cache_find(ieee, seq, -1, tid, hdr->addr2,
Larry Finger94a79942011-08-23 19:00:42 -0500187 hdr->addr1);
188
189 if (entry == NULL) {
190 RTLLIB_DEBUG_FRAG(
Jonathan Jin6d6163c2014-12-15 21:28:23 -0600191 "could not invalidate fragment cache entry (seq=%u)\n", seq);
Larry Finger94a79942011-08-23 19:00:42 -0500192 return -1;
193 }
194
195 entry->skb = NULL;
196 return 0;
197}
198
Larry Finger94a79942011-08-23 19:00:42 -0500199/* rtllib_rx_frame_mgtmt
200 *
201 * Responsible for handling management control frames
202 *
Mateusz Kulikowski14b40d92015-04-01 00:24:37 +0200203 * Called by rtllib_rx
204 */
Larry Finger94a79942011-08-23 19:00:42 -0500205static inline int
206rtllib_rx_frame_mgmt(struct rtllib_device *ieee, struct sk_buff *skb,
207 struct rtllib_rx_stats *rx_stats, u16 type,
208 u16 stype)
209{
210 /* On the struct stats definition there is written that
211 * this is not mandatory.... but seems that the probe
212 * response parser uses it
213 */
Matthias Schoepea0711c42013-12-26 20:23:32 +0100214 struct rtllib_hdr_3addr *hdr = (struct rtllib_hdr_3addr *)skb->data;
Larry Finger94a79942011-08-23 19:00:42 -0500215
216 rx_stats->len = skb->len;
Larry Fingerdb8971b2011-08-25 11:48:25 -0500217 rtllib_rx_mgt(ieee, skb, rx_stats);
Larry Finger94a79942011-08-23 19:00:42 -0500218 if ((memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN))) {
219 dev_kfree_skb_any(skb);
220 return 0;
221 }
222 rtllib_rx_frame_softmac(ieee, skb, rx_stats, type, stype);
223
224 dev_kfree_skb_any(skb);
225
226 return 0;
Larry Finger94a79942011-08-23 19:00:42 -0500227}
228
Mateusz Kulikowski14b40d92015-04-01 00:24:37 +0200229/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation
230 * Ethernet-II snap header (RFC1042 for most EtherTypes)
231 */
Larry Fingerdb8971b2011-08-25 11:48:25 -0500232static unsigned char rfc1042_header[] = {
233 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00
234};
Larry Finger94a79942011-08-23 19:00:42 -0500235/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
Larry Fingerdb8971b2011-08-25 11:48:25 -0500236static unsigned char bridge_tunnel_header[] = {
237 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8
238};
Larry Finger94a79942011-08-23 19:00:42 -0500239/* No encapsulation header if EtherType < 0x600 (=length) */
Larry Finger94a79942011-08-23 19:00:42 -0500240
241/* Called by rtllib_rx_frame_decrypt */
242static int rtllib_is_eapol_frame(struct rtllib_device *ieee,
243 struct sk_buff *skb, size_t hdrlen)
244{
245 struct net_device *dev = ieee->dev;
246 u16 fc, ethertype;
247 struct rtllib_hdr_4addr *hdr;
248 u8 *pos;
249
250 if (skb->len < 24)
251 return 0;
252
253 hdr = (struct rtllib_hdr_4addr *) skb->data;
254 fc = le16_to_cpu(hdr->frame_ctl);
255
256 /* check that the frame is unicast frame to us */
257 if ((fc & (RTLLIB_FCTL_TODS | RTLLIB_FCTL_FROMDS)) ==
258 RTLLIB_FCTL_TODS &&
259 memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0 &&
260 memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0) {
261 /* ToDS frame with own addr BSSID and DA */
262 } else if ((fc & (RTLLIB_FCTL_TODS | RTLLIB_FCTL_FROMDS)) ==
263 RTLLIB_FCTL_FROMDS &&
264 memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) {
265 /* FromDS frame with own addr as DA */
266 } else
267 return 0;
268
269 if (skb->len < 24 + 8)
270 return 0;
271
272 /* check for port access entity Ethernet type */
273 pos = skb->data + hdrlen;
274 ethertype = (pos[6] << 8) | pos[7];
275 if (ethertype == ETH_P_PAE)
276 return 1;
277
278 return 0;
279}
280
281/* Called only as a tasklet (software IRQ), by rtllib_rx */
282static inline int
Larry Fingerdb8971b2011-08-25 11:48:25 -0500283rtllib_rx_frame_decrypt(struct rtllib_device *ieee, struct sk_buff *skb,
Sean MacLennan32c44cb2011-12-19 23:20:41 -0500284 struct lib80211_crypt_data *crypt)
Larry Finger94a79942011-08-23 19:00:42 -0500285{
286 struct rtllib_hdr_4addr *hdr;
287 int res, hdrlen;
288
289 if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL)
290 return 0;
Mike McCormack4f6807e2011-07-11 08:56:20 +0900291
Larry Fingerdb8971b2011-08-25 11:48:25 -0500292 if (ieee->hwsec_active) {
293 struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
Matthew Casey3a6b70c2014-08-22 06:27:52 -0400294
Larry Finger94a79942011-08-23 19:00:42 -0500295 tcb_desc->bHwSec = 1;
296
297 if (ieee->need_sw_enc)
298 tcb_desc->bHwSec = 0;
299 }
Mike McCormack4f6807e2011-07-11 08:56:20 +0900300
Larry Finger94a79942011-08-23 19:00:42 -0500301 hdr = (struct rtllib_hdr_4addr *) skb->data;
302 hdrlen = rtllib_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
303
Larry Finger94a79942011-08-23 19:00:42 -0500304 atomic_inc(&crypt->refcnt);
305 res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
306 atomic_dec(&crypt->refcnt);
307 if (res < 0) {
308 RTLLIB_DEBUG_DROP(
Jonathan Jin6d6163c2014-12-15 21:28:23 -0600309 "decryption failed (SA= %pM) res=%d\n", hdr->addr2, res);
Larry Finger94a79942011-08-23 19:00:42 -0500310 if (res == -2)
Jonathan Jin6d6163c2014-12-15 21:28:23 -0600311 RTLLIB_DEBUG_DROP("Decryption failed ICV mismatch (key %d)\n",
Larry Finger94a79942011-08-23 19:00:42 -0500312 skb->data[hdrlen + 3] >> 6);
313 ieee->ieee_stats.rx_discards_undecryptable++;
314 return -1;
315 }
316
317 return res;
318}
319
320
321/* Called only as a tasklet (software IRQ), by rtllib_rx */
322static inline int
Larry Fingerdb8971b2011-08-25 11:48:25 -0500323rtllib_rx_frame_decrypt_msdu(struct rtllib_device *ieee, struct sk_buff *skb,
Sean MacLennan32c44cb2011-12-19 23:20:41 -0500324 int keyidx, struct lib80211_crypt_data *crypt)
Larry Finger94a79942011-08-23 19:00:42 -0500325{
326 struct rtllib_hdr_4addr *hdr;
327 int res, hdrlen;
328
329 if (crypt == NULL || crypt->ops->decrypt_msdu == NULL)
330 return 0;
Larry Fingerdb8971b2011-08-25 11:48:25 -0500331 if (ieee->hwsec_active) {
332 struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
Matthew Casey3a6b70c2014-08-22 06:27:52 -0400333
Larry Finger94a79942011-08-23 19:00:42 -0500334 tcb_desc->bHwSec = 1;
335
336 if (ieee->need_sw_enc)
337 tcb_desc->bHwSec = 0;
338 }
339
340 hdr = (struct rtllib_hdr_4addr *) skb->data;
341 hdrlen = rtllib_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
342
343 atomic_inc(&crypt->refcnt);
Sean MacLennan32c44cb2011-12-19 23:20:41 -0500344 res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv);
Larry Finger94a79942011-08-23 19:00:42 -0500345 atomic_dec(&crypt->refcnt);
346 if (res < 0) {
Jonathan Jin6d6163c2014-12-15 21:28:23 -0600347 printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed (SA= %pM keyidx=%d)\n",
Larry Fingerac50dda2011-08-25 14:07:03 -0500348 ieee->dev->name, hdr->addr2, keyidx);
Larry Finger94a79942011-08-23 19:00:42 -0500349 return -1;
350 }
351
352 return 0;
353}
354
355
356/* this function is stolen from ipw2200 driver*/
357#define IEEE_PACKET_RETRY_TIME (5*HZ)
358static int is_duplicate_packet(struct rtllib_device *ieee,
359 struct rtllib_hdr_4addr *header)
360{
361 u16 fc = le16_to_cpu(header->frame_ctl);
362 u16 sc = le16_to_cpu(header->seq_ctl);
363 u16 seq = WLAN_GET_SEQ_SEQ(sc);
364 u16 frag = WLAN_GET_SEQ_FRAG(sc);
365 u16 *last_seq, *last_frag;
366 unsigned long *last_time;
367 struct rtllib_hdr_3addrqos *hdr_3addrqos;
368 struct rtllib_hdr_4addrqos *hdr_4addrqos;
369 u8 tid;
370
Larry Fingerdb8971b2011-08-25 11:48:25 -0500371 if (((fc & RTLLIB_FCTL_DSTODS) == RTLLIB_FCTL_DSTODS) && RTLLIB_QOS_HAS_SEQ(fc)) {
372 hdr_4addrqos = (struct rtllib_hdr_4addrqos *)header;
373 tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & RTLLIB_QCTL_TID;
374 tid = UP2AC(tid);
375 tid++;
Larry Finger94a79942011-08-23 19:00:42 -0500376 } else if (RTLLIB_QOS_HAS_SEQ(fc)) {
Larry Fingerdb8971b2011-08-25 11:48:25 -0500377 hdr_3addrqos = (struct rtllib_hdr_3addrqos *)header;
378 tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & RTLLIB_QCTL_TID;
379 tid = UP2AC(tid);
380 tid++;
Larry Finger94a79942011-08-23 19:00:42 -0500381 } else {
Larry Fingerdb8971b2011-08-25 11:48:25 -0500382 tid = 0;
Larry Finger94a79942011-08-23 19:00:42 -0500383 }
384
385 switch (ieee->iw_mode) {
386 case IW_MODE_ADHOC:
387 {
388 struct list_head *p;
389 struct ieee_ibss_seq *entry = NULL;
390 u8 *mac = header->addr2;
391 int index = mac[5] % IEEE_IBSS_MAC_HASH_SIZE;
Matthew Casey3a6b70c2014-08-22 06:27:52 -0400392
Larry Finger94a79942011-08-23 19:00:42 -0500393 list_for_each(p, &ieee->ibss_mac_hash[index]) {
394 entry = list_entry(p, struct ieee_ibss_seq, list);
395 if (!memcmp(entry->mac, mac, ETH_ALEN))
396 break;
397 }
398 if (p == &ieee->ibss_mac_hash[index]) {
399 entry = kmalloc(sizeof(struct ieee_ibss_seq), GFP_ATOMIC);
Quentin Lambertb6b00122015-03-05 14:12:15 +0100400 if (!entry)
Larry Finger94a79942011-08-23 19:00:42 -0500401 return 0;
Quentin Lambertb6b00122015-03-05 14:12:15 +0100402
Larry Finger94a79942011-08-23 19:00:42 -0500403 memcpy(entry->mac, mac, ETH_ALEN);
404 entry->seq_num[tid] = seq;
405 entry->frag_num[tid] = frag;
406 entry->packet_time[tid] = jiffies;
407 list_add(&entry->list, &ieee->ibss_mac_hash[index]);
408 return 0;
409 }
410 last_seq = &entry->seq_num[tid];
411 last_frag = &entry->frag_num[tid];
412 last_time = &entry->packet_time[tid];
413 break;
414 }
415
416 case IW_MODE_INFRA:
417 last_seq = &ieee->last_rxseq_num[tid];
418 last_frag = &ieee->last_rxfrag_num[tid];
419 last_time = &ieee->last_packet_time[tid];
420 break;
421 default:
422 return 0;
423 }
424
425 if ((*last_seq == seq) &&
426 time_after(*last_time + IEEE_PACKET_RETRY_TIME, jiffies)) {
Larry Fingerdb8971b2011-08-25 11:48:25 -0500427 if (*last_frag == frag)
Larry Finger94a79942011-08-23 19:00:42 -0500428 goto drop;
Larry Finger94a79942011-08-23 19:00:42 -0500429 if (*last_frag + 1 != frag)
430 /* out-of-order fragment */
431 goto drop;
432 } else
433 *last_seq = seq;
434
435 *last_frag = frag;
436 *last_time = jiffies;
437 return 0;
438
439drop:
440
441 return 1;
442}
Larry Fingerdb8971b2011-08-25 11:48:25 -0500443
Larry Finger49aab5f2011-08-25 14:07:05 -0500444static bool AddReorderEntry(struct rx_ts_record *pTS,
445 struct rx_reorder_entry *pReorderEntry)
Larry Finger94a79942011-08-23 19:00:42 -0500446{
447 struct list_head *pList = &pTS->RxPendingPktList;
448
Larry Fingerdb8971b2011-08-25 11:48:25 -0500449 while (pList->next != &pTS->RxPendingPktList) {
Larry Finger49aab5f2011-08-25 14:07:05 -0500450 if (SN_LESS(pReorderEntry->SeqNum, ((struct rx_reorder_entry *)
451 list_entry(pList->next, struct rx_reorder_entry,
452 List))->SeqNum))
Larry Finger94a79942011-08-23 19:00:42 -0500453 pList = pList->next;
Larry Finger49aab5f2011-08-25 14:07:05 -0500454 else if (SN_EQUAL(pReorderEntry->SeqNum,
455 ((struct rx_reorder_entry *)list_entry(pList->next,
456 struct rx_reorder_entry, List))->SeqNum))
457 return false;
Larry Finger94a79942011-08-23 19:00:42 -0500458 else
Larry Finger94a79942011-08-23 19:00:42 -0500459 break;
Larry Finger94a79942011-08-23 19:00:42 -0500460 }
461 pReorderEntry->List.next = pList->next;
462 pReorderEntry->List.next->prev = &pReorderEntry->List;
463 pReorderEntry->List.prev = pList;
464 pList->next = &pReorderEntry->List;
465
466 return true;
467}
468
Larry Fingerdb8971b2011-08-25 11:48:25 -0500469void rtllib_indicate_packets(struct rtllib_device *ieee, struct rtllib_rxb **prxbIndicateArray, u8 index)
Larry Finger94a79942011-08-23 19:00:42 -0500470{
471 struct net_device_stats *stats = &ieee->stats;
Mateusz Kulikowskif6692282015-04-13 23:47:27 +0200472 u8 i = 0, j = 0;
Larry Finger94a79942011-08-23 19:00:42 -0500473 u16 ethertype;
Matthew Casey3a6b70c2014-08-22 06:27:52 -0400474
Larry Finger94a79942011-08-23 19:00:42 -0500475 for (j = 0; j < index; j++) {
Larry Fingerdb8971b2011-08-25 11:48:25 -0500476 struct rtllib_rxb *prxb = prxbIndicateArray[j];
Matthew Casey3a6b70c2014-08-22 06:27:52 -0400477
Larry Fingerdb8971b2011-08-25 11:48:25 -0500478 for (i = 0; i < prxb->nr_subframes; i++) {
Larry Finger94a79942011-08-23 19:00:42 -0500479 struct sk_buff *sub_skb = prxb->subframes[i];
480
481 /* convert hdr + possible LLC headers into Ethernet header */
482 ethertype = (sub_skb->data[6] << 8) | sub_skb->data[7];
483 if (sub_skb->len >= 8 &&
Larry Fingerdb8971b2011-08-25 11:48:25 -0500484 ((memcmp(sub_skb->data, rfc1042_header, SNAP_SIZE) == 0 &&
485 ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
486 memcmp(sub_skb->data, bridge_tunnel_header, SNAP_SIZE) == 0)) {
487 /* remove RFC1042 or Bridge-Tunnel encapsulation
Mateusz Kulikowski14b40d92015-04-01 00:24:37 +0200488 * and replace EtherType
489 */
Larry Finger94a79942011-08-23 19:00:42 -0500490 skb_pull(sub_skb, SNAP_SIZE);
491 memcpy(skb_push(sub_skb, ETH_ALEN), prxb->src, ETH_ALEN);
492 memcpy(skb_push(sub_skb, ETH_ALEN), prxb->dst, ETH_ALEN);
493 } else {
494 u16 len;
495 /* Leave Ethernet header part of hdr and full payload */
Rashika Kheria1f5a0d02013-11-02 23:34:44 +0530496 len = sub_skb->len;
Larry Finger94a79942011-08-23 19:00:42 -0500497 memcpy(skb_push(sub_skb, 2), &len, 2);
498 memcpy(skb_push(sub_skb, ETH_ALEN), prxb->src, ETH_ALEN);
499 memcpy(skb_push(sub_skb, ETH_ALEN), prxb->dst, ETH_ALEN);
500 }
501
Justin P. Mattockcd017122012-04-23 07:36:52 -0700502 /* Indicate the packets to upper layer */
Larry Finger94a79942011-08-23 19:00:42 -0500503 if (sub_skb) {
504 stats->rx_packets++;
505 stats->rx_bytes += sub_skb->len;
506
507 memset(sub_skb->cb, 0, sizeof(sub_skb->cb));
508 sub_skb->protocol = eth_type_trans(sub_skb, ieee->dev);
509 sub_skb->dev = ieee->dev;
510 sub_skb->dev->stats.rx_packets++;
511 sub_skb->dev->stats.rx_bytes += sub_skb->len;
Larry Finger94a79942011-08-23 19:00:42 -0500512 sub_skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */
Larry Finger94a79942011-08-23 19:00:42 -0500513 ieee->last_rx_ps_time = jiffies;
514 netif_rx(sub_skb);
515 }
516 }
517 kfree(prxb);
518 prxb = NULL;
519 }
520}
521
Larry Fingerdb8971b2011-08-25 11:48:25 -0500522void rtllib_FlushRxTsPendingPkts(struct rtllib_device *ieee, struct rx_ts_record *pTS)
Larry Finger94a79942011-08-23 19:00:42 -0500523{
Larry Finger8cba1432011-07-18 22:16:48 -0500524 struct rx_reorder_entry *pRxReorderEntry;
Larry Fingerdb8971b2011-08-25 11:48:25 -0500525 u8 RfdCnt = 0;
Larry Finger94a79942011-08-23 19:00:42 -0500526
527 del_timer_sync(&pTS->RxPktPendingTimer);
Larry Fingerdb8971b2011-08-25 11:48:25 -0500528 while (!list_empty(&pTS->RxPendingPktList)) {
529 if (RfdCnt >= REORDER_WIN_SIZE) {
Mateusz Kulikowskid69d2052015-03-17 00:00:52 +0100530 netdev_info(ieee->dev,
531 "-------------->%s() error! RfdCnt >= REORDER_WIN_SIZE\n",
532 __func__);
Larry Finger94a79942011-08-23 19:00:42 -0500533 break;
534 }
535
Larry Fingerdb8971b2011-08-25 11:48:25 -0500536 pRxReorderEntry = (struct rx_reorder_entry *)list_entry(pTS->RxPendingPktList.prev, struct rx_reorder_entry, List);
537 RTLLIB_DEBUG(RTLLIB_DL_REORDER, "%s(): Indicate SeqNum %d!\n", __func__, pRxReorderEntry->SeqNum);
Larry Finger94a79942011-08-23 19:00:42 -0500538 list_del_init(&pRxReorderEntry->List);
539
Larry Finger2eed3de2011-09-01 12:23:20 -0500540 ieee->RfdArray[RfdCnt] = pRxReorderEntry->prxb;
Larry Finger94a79942011-08-23 19:00:42 -0500541
542 RfdCnt = RfdCnt + 1;
543 list_add_tail(&pRxReorderEntry->List, &ieee->RxReorder_Unused_List);
544 }
Larry Finger2eed3de2011-09-01 12:23:20 -0500545 rtllib_indicate_packets(ieee, ieee->RfdArray, RfdCnt);
Larry Finger94a79942011-08-23 19:00:42 -0500546
547 pTS->RxIndicateSeq = 0xffff;
Larry Finger94a79942011-08-23 19:00:42 -0500548}
549
Larry Finger49aab5f2011-08-25 14:07:05 -0500550static void RxReorderIndicatePacket(struct rtllib_device *ieee,
551 struct rtllib_rxb *prxb,
552 struct rx_ts_record *pTS, u16 SeqNum)
Larry Finger94a79942011-08-23 19:00:42 -0500553{
Larry Finger7796d932011-07-18 20:22:19 -0500554 struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
Larry Finger8cba1432011-07-18 22:16:48 -0500555 struct rx_reorder_entry *pReorderEntry = NULL;
Larry Fingerdb8971b2011-08-25 11:48:25 -0500556 u8 WinSize = pHTInfo->RxReorderWinSize;
557 u16 WinEnd = 0;
558 u8 index = 0;
559 bool bMatchWinStart = false, bPktInBuf = false;
Larry Finger94a79942011-08-23 19:00:42 -0500560 unsigned long flags;
561
Jonathan Jin6d6163c2014-12-15 21:28:23 -0600562 RTLLIB_DEBUG(RTLLIB_DL_REORDER, "%s(): Seq is %d, pTS->RxIndicateSeq is %d, WinSize is %d\n", __func__, SeqNum,
Larry Fingerdb8971b2011-08-25 11:48:25 -0500563 pTS->RxIndicateSeq, WinSize);
Larry Finger94a79942011-08-23 19:00:42 -0500564
565 spin_lock_irqsave(&(ieee->reorder_spinlock), flags);
566
Larry Fingerdb8971b2011-08-25 11:48:25 -0500567 WinEnd = (pTS->RxIndicateSeq + WinSize - 1) % 4096;
Larry Finger94a79942011-08-23 19:00:42 -0500568 /* Rx Reorder initialize condition.*/
Larry Fingerdb8971b2011-08-25 11:48:25 -0500569 if (pTS->RxIndicateSeq == 0xffff)
Larry Finger94a79942011-08-23 19:00:42 -0500570 pTS->RxIndicateSeq = SeqNum;
Larry Finger94a79942011-08-23 19:00:42 -0500571
572 /* Drop out the packet which SeqNum is smaller than WinStart */
573 if (SN_LESS(SeqNum, pTS->RxIndicateSeq)) {
Larry Fingerdb8971b2011-08-25 11:48:25 -0500574 RTLLIB_DEBUG(RTLLIB_DL_REORDER, "Packet Drop! IndicateSeq: %d, NewSeq: %d\n",
Larry Finger94a79942011-08-23 19:00:42 -0500575 pTS->RxIndicateSeq, SeqNum);
576 pHTInfo->RxReorderDropCounter++;
577 {
578 int i;
Matthew Casey3a6b70c2014-08-22 06:27:52 -0400579
Larry Fingerdb8971b2011-08-25 11:48:25 -0500580 for (i = 0; i < prxb->nr_subframes; i++)
Larry Finger94a79942011-08-23 19:00:42 -0500581 dev_kfree_skb(prxb->subframes[i]);
Larry Finger94a79942011-08-23 19:00:42 -0500582 kfree(prxb);
583 prxb = NULL;
584 }
585 spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
586 return;
587 }
588
Mateusz Kulikowski14b40d92015-04-01 00:24:37 +0200589 /* Sliding window manipulation. Conditions includes:
Larry Finger94a79942011-08-23 19:00:42 -0500590 * 1. Incoming SeqNum is equal to WinStart =>Window shift 1
591 * 2. Incoming SeqNum is larger than the WinEnd => Window shift N
592 */
593 if (SN_EQUAL(SeqNum, pTS->RxIndicateSeq)) {
594 pTS->RxIndicateSeq = (pTS->RxIndicateSeq + 1) % 4096;
595 bMatchWinStart = true;
596 } else if (SN_LESS(WinEnd, SeqNum)) {
Larry Fingerdb8971b2011-08-25 11:48:25 -0500597 if (SeqNum >= (WinSize - 1))
598 pTS->RxIndicateSeq = SeqNum + 1 - WinSize;
599 else
600 pTS->RxIndicateSeq = 4095 - (WinSize - (SeqNum + 1)) + 1;
Jonathan Jin6d6163c2014-12-15 21:28:23 -0600601 RTLLIB_DEBUG(RTLLIB_DL_REORDER, "Window Shift! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, SeqNum);
Larry Finger94a79942011-08-23 19:00:42 -0500602 }
603
Mateusz Kulikowski14b40d92015-04-01 00:24:37 +0200604 /* Indication process.
Larry Fingerdb8971b2011-08-25 11:48:25 -0500605 * After Packet dropping and Sliding Window shifting as above, we can
606 * now just indicate the packets with the SeqNum smaller than latest
607 * WinStart and struct buffer other packets.
Mateusz Kulikowski14b40d92015-04-01 00:24:37 +0200608 *
609 * For Rx Reorder condition:
Larry Finger94a79942011-08-23 19:00:42 -0500610 * 1. All packets with SeqNum smaller than WinStart => Indicate
Larry Fingerdb8971b2011-08-25 11:48:25 -0500611 * 2. All packets with SeqNum larger than or equal to
612 * WinStart => Buffer it.
Larry Finger94a79942011-08-23 19:00:42 -0500613 */
614 if (bMatchWinStart) {
615 /* Current packet is going to be indicated.*/
Jonathan Jin6d6163c2014-12-15 21:28:23 -0600616 RTLLIB_DEBUG(RTLLIB_DL_REORDER, "Packets indication!! IndicateSeq: %d, NewSeq: %d\n",
Larry Finger94a79942011-08-23 19:00:42 -0500617 pTS->RxIndicateSeq, SeqNum);
Larry Finger2eed3de2011-09-01 12:23:20 -0500618 ieee->prxbIndicateArray[0] = prxb;
Larry Finger94a79942011-08-23 19:00:42 -0500619 index = 1;
620 } else {
621 /* Current packet is going to be inserted into pending list.*/
622 if (!list_empty(&ieee->RxReorder_Unused_List)) {
Larry Fingerdb8971b2011-08-25 11:48:25 -0500623 pReorderEntry = (struct rx_reorder_entry *)
624 list_entry(ieee->RxReorder_Unused_List.next,
625 struct rx_reorder_entry, List);
Larry Finger94a79942011-08-23 19:00:42 -0500626 list_del_init(&pReorderEntry->List);
627
628 /* Make a reorder entry and insert into a the packet list.*/
629 pReorderEntry->SeqNum = SeqNum;
630 pReorderEntry->prxb = prxb;
631
Larry Finger94a79942011-08-23 19:00:42 -0500632 if (!AddReorderEntry(pTS, pReorderEntry)) {
Larry Fingerdb8971b2011-08-25 11:48:25 -0500633 RTLLIB_DEBUG(RTLLIB_DL_REORDER,
Jonathan Jin6d6163c2014-12-15 21:28:23 -0600634 "%s(): Duplicate packet is dropped!! IndicateSeq: %d, NewSeq: %d\n",
Larry Fingerdb8971b2011-08-25 11:48:25 -0500635 __func__, pTS->RxIndicateSeq,
636 SeqNum);
637 list_add_tail(&pReorderEntry->List,
638 &ieee->RxReorder_Unused_List); {
Larry Finger94a79942011-08-23 19:00:42 -0500639 int i;
Matthew Casey3a6b70c2014-08-22 06:27:52 -0400640
Larry Fingerdb8971b2011-08-25 11:48:25 -0500641 for (i = 0; i < prxb->nr_subframes; i++)
Larry Finger94a79942011-08-23 19:00:42 -0500642 dev_kfree_skb(prxb->subframes[i]);
Larry Finger94a79942011-08-23 19:00:42 -0500643 kfree(prxb);
644 prxb = NULL;
645 }
646 } else {
647 RTLLIB_DEBUG(RTLLIB_DL_REORDER,
Jonathan Jin6d6163c2014-12-15 21:28:23 -0600648 "Pkt insert into struct buffer!! IndicateSeq: %d, NewSeq: %d\n",
Larry Fingerdb8971b2011-08-25 11:48:25 -0500649 pTS->RxIndicateSeq, SeqNum);
Larry Finger94a79942011-08-23 19:00:42 -0500650 }
Larry Fingerdb8971b2011-08-25 11:48:25 -0500651 } else {
Mateusz Kulikowski14b40d92015-04-01 00:24:37 +0200652 /* Packets are dropped if there are not enough reorder
Larry Fingerdb8971b2011-08-25 11:48:25 -0500653 * entries. This part should be modified!! We can just
654 * indicate all the packets in struct buffer and get
655 * reorder entries.
Larry Finger94a79942011-08-23 19:00:42 -0500656 */
Jonathan Jin6d6163c2014-12-15 21:28:23 -0600657 RTLLIB_DEBUG(RTLLIB_DL_ERR, "RxReorderIndicatePacket(): There is no reorder entry!! Packet is dropped!!\n");
Larry Finger94a79942011-08-23 19:00:42 -0500658 {
659 int i;
Matthew Casey3a6b70c2014-08-22 06:27:52 -0400660
Larry Fingerdb8971b2011-08-25 11:48:25 -0500661 for (i = 0; i < prxb->nr_subframes; i++)
Larry Finger94a79942011-08-23 19:00:42 -0500662 dev_kfree_skb(prxb->subframes[i]);
Larry Finger94a79942011-08-23 19:00:42 -0500663 kfree(prxb);
664 prxb = NULL;
665 }
666 }
667 }
668
669 /* Check if there is any packet need indicate.*/
Larry Fingerdb8971b2011-08-25 11:48:25 -0500670 while (!list_empty(&pTS->RxPendingPktList)) {
671 RTLLIB_DEBUG(RTLLIB_DL_REORDER, "%s(): start RREORDER indicate\n", __func__);
Mike McCormack4f6807e2011-07-11 08:56:20 +0900672
Larry Fingerdb8971b2011-08-25 11:48:25 -0500673 pReorderEntry = (struct rx_reorder_entry *)list_entry(pTS->RxPendingPktList.prev,
674 struct rx_reorder_entry, List);
675 if (SN_LESS(pReorderEntry->SeqNum, pTS->RxIndicateSeq) ||
676 SN_EQUAL(pReorderEntry->SeqNum, pTS->RxIndicateSeq)) {
Larry Fingerfc22c052011-07-19 00:32:34 -0500677 /* This protect struct buffer from overflow. */
Larry Finger94a79942011-08-23 19:00:42 -0500678 if (index >= REORDER_WIN_SIZE) {
Jonathan Jin6d6163c2014-12-15 21:28:23 -0600679 RTLLIB_DEBUG(RTLLIB_DL_ERR, "RxReorderIndicatePacket(): Buffer overflow!!\n");
Larry Finger94a79942011-08-23 19:00:42 -0500680 bPktInBuf = true;
681 break;
682 }
683
684 list_del_init(&pReorderEntry->List);
685
686 if (SN_EQUAL(pReorderEntry->SeqNum, pTS->RxIndicateSeq))
687 pTS->RxIndicateSeq = (pTS->RxIndicateSeq + 1) % 4096;
688
Larry Finger2eed3de2011-09-01 12:23:20 -0500689 ieee->prxbIndicateArray[index] = pReorderEntry->prxb;
Jonathan Jin6d6163c2014-12-15 21:28:23 -0600690 RTLLIB_DEBUG(RTLLIB_DL_REORDER, "%s(): Indicate SeqNum %d!\n", __func__, pReorderEntry->SeqNum);
Larry Finger94a79942011-08-23 19:00:42 -0500691 index++;
692
Larry Fingerdb8971b2011-08-25 11:48:25 -0500693 list_add_tail(&pReorderEntry->List,
694 &ieee->RxReorder_Unused_List);
Larry Finger94a79942011-08-23 19:00:42 -0500695 } else {
696 bPktInBuf = true;
697 break;
698 }
Larry Finger94a79942011-08-23 19:00:42 -0500699 }
700
Larry Fingerdb8971b2011-08-25 11:48:25 -0500701 /* Handling pending timer. Set this timer to prevent from long time
Mateusz Kulikowski14b40d92015-04-01 00:24:37 +0200702 * Rx buffering.
703 */
Larry Fingerdb8971b2011-08-25 11:48:25 -0500704 if (index > 0) {
705 if (timer_pending(&pTS->RxPktPendingTimer))
Larry Finger94a79942011-08-23 19:00:42 -0500706 del_timer_sync(&pTS->RxPktPendingTimer);
Larry Finger94a79942011-08-23 19:00:42 -0500707 pTS->RxTimeoutIndicateSeq = 0xffff;
708
Larry Fingerdb8971b2011-08-25 11:48:25 -0500709 if (index > REORDER_WIN_SIZE) {
Jonathan Jin6d6163c2014-12-15 21:28:23 -0600710 RTLLIB_DEBUG(RTLLIB_DL_ERR, "RxReorderIndicatePacket(): Rx Reorder struct buffer full!!\n");
Larry Fingerdb8971b2011-08-25 11:48:25 -0500711 spin_unlock_irqrestore(&(ieee->reorder_spinlock),
712 flags);
Larry Finger94a79942011-08-23 19:00:42 -0500713 return;
714 }
Larry Finger2eed3de2011-09-01 12:23:20 -0500715 rtllib_indicate_packets(ieee, ieee->prxbIndicateArray, index);
Larry Finger94a79942011-08-23 19:00:42 -0500716 bPktInBuf = false;
717 }
718
Larry Fingerdb8971b2011-08-25 11:48:25 -0500719 if (bPktInBuf && pTS->RxTimeoutIndicateSeq == 0xffff) {
720 RTLLIB_DEBUG(RTLLIB_DL_REORDER, "%s(): SET rx timeout timer\n",
721 __func__);
Larry Finger94a79942011-08-23 19:00:42 -0500722 pTS->RxTimeoutIndicateSeq = pTS->RxIndicateSeq;
Larry Fingerdb8971b2011-08-25 11:48:25 -0500723 mod_timer(&pTS->RxPktPendingTimer, jiffies +
Vaishali Thakkar8b9733c2015-03-11 13:51:36 +0530724 msecs_to_jiffies(pHTInfo->RxReorderPendingTime));
Larry Finger94a79942011-08-23 19:00:42 -0500725 }
726 spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
727}
728
Larry Finger49aab5f2011-08-25 14:07:05 -0500729static u8 parse_subframe(struct rtllib_device *ieee, struct sk_buff *skb,
730 struct rtllib_rx_stats *rx_stats,
731 struct rtllib_rxb *rxb, u8 *src, u8 *dst)
Larry Finger94a79942011-08-23 19:00:42 -0500732{
Larry Fingerdb8971b2011-08-25 11:48:25 -0500733 struct rtllib_hdr_3addr *hdr = (struct rtllib_hdr_3addr *)skb->data;
Larry Finger94a79942011-08-23 19:00:42 -0500734 u16 fc = le16_to_cpu(hdr->frame_ctl);
735
Larry Fingerdb8971b2011-08-25 11:48:25 -0500736 u16 LLCOffset = sizeof(struct rtllib_hdr_3addr);
Larry Finger94a79942011-08-23 19:00:42 -0500737 u16 ChkLength;
738 bool bIsAggregateFrame = false;
739 u16 nSubframe_Length;
740 u8 nPadding_Length = 0;
Larry Fingerdb8971b2011-08-25 11:48:25 -0500741 u16 SeqNum = 0;
Larry Finger94a79942011-08-23 19:00:42 -0500742 struct sk_buff *sub_skb;
Larry Fingerdb8971b2011-08-25 11:48:25 -0500743 u8 *data_ptr;
Larry Finger94a79942011-08-23 19:00:42 -0500744 /* just for debug purpose */
745 SeqNum = WLAN_GET_SEQ_SEQ(le16_to_cpu(hdr->seq_ctl));
Larry Fingerdb8971b2011-08-25 11:48:25 -0500746 if ((RTLLIB_QOS_HAS_SEQ(fc)) &&
747 (((union frameqos *)(skb->data + RTLLIB_3ADDR_LEN))->field.reserved))
Larry Finger94a79942011-08-23 19:00:42 -0500748 bIsAggregateFrame = true;
Larry Finger94a79942011-08-23 19:00:42 -0500749
Larry Fingerdb8971b2011-08-25 11:48:25 -0500750 if (RTLLIB_QOS_HAS_SEQ(fc))
Larry Finger94a79942011-08-23 19:00:42 -0500751 LLCOffset += 2;
Larry Fingerdb8971b2011-08-25 11:48:25 -0500752 if (rx_stats->bContainHTC)
Larry Finger94a79942011-08-23 19:00:42 -0500753 LLCOffset += sHTCLng;
Larry Finger94a79942011-08-23 19:00:42 -0500754
Larry Fingerdb8971b2011-08-25 11:48:25 -0500755 ChkLength = LLCOffset;
Larry Finger94a79942011-08-23 19:00:42 -0500756
Larry Fingerdb8971b2011-08-25 11:48:25 -0500757 if (skb->len <= ChkLength)
Larry Finger94a79942011-08-23 19:00:42 -0500758 return 0;
Larry Finger94a79942011-08-23 19:00:42 -0500759
760 skb_pull(skb, LLCOffset);
761 ieee->bIsAggregateFrame = bIsAggregateFrame;
762 if (!bIsAggregateFrame) {
763 rxb->nr_subframes = 1;
764
765 /* altered by clark 3/30/2010
Larry Fingerfc22c052011-07-19 00:32:34 -0500766 * The struct buffer size of the skb indicated to upper layer
Larry Finger94a79942011-08-23 19:00:42 -0500767 * must be less than 5000, or the defraged IP datagram
768 * in the IP layer will exceed "ipfrag_high_tresh" and be
769 * discarded. so there must not use the function
770 * "skb_copy" and "skb_clone" for "skb".
771 */
772
773 /* Allocate new skb for releasing to upper layer */
774 sub_skb = dev_alloc_skb(RTLLIB_SKBBUFFER_SIZE);
Iker Pedrosa59aabd62013-08-08 12:56:44 +0200775 if (!sub_skb)
776 return 0;
Larry Finger94a79942011-08-23 19:00:42 -0500777 skb_reserve(sub_skb, 12);
778 data_ptr = (u8 *)skb_put(sub_skb, skb->len);
779 memcpy(data_ptr, skb->data, skb->len);
780 sub_skb->dev = ieee->dev;
781
782 rxb->subframes[0] = sub_skb;
783
Larry Fingerdb8971b2011-08-25 11:48:25 -0500784 memcpy(rxb->src, src, ETH_ALEN);
785 memcpy(rxb->dst, dst, ETH_ALEN);
Larry Finger94a79942011-08-23 19:00:42 -0500786 rxb->subframes[0]->dev = ieee->dev;
787 return 1;
Mateusz Kulikowski285b7c02015-04-01 00:24:26 +0200788 }
Larry Finger94a79942011-08-23 19:00:42 -0500789
Mateusz Kulikowski285b7c02015-04-01 00:24:26 +0200790 rxb->nr_subframes = 0;
791 memcpy(rxb->src, src, ETH_ALEN);
792 memcpy(rxb->dst, dst, ETH_ALEN);
793 while (skb->len > ETHERNET_HEADER_SIZE) {
794 /* Offset 12 denote 2 mac address */
795 nSubframe_Length = *((u16 *)(skb->data + 12));
796 nSubframe_Length = (nSubframe_Length >> 8) +
797 (nSubframe_Length << 8);
Larry Finger94a79942011-08-23 19:00:42 -0500798
Mateusz Kulikowski285b7c02015-04-01 00:24:26 +0200799 if (skb->len < (ETHERNET_HEADER_SIZE + nSubframe_Length)) {
800 netdev_info(ieee->dev,
801 "%s: A-MSDU parse error!! pRfd->nTotalSubframe : %d\n",
802 __func__, rxb->nr_subframes);
803 netdev_info(ieee->dev,
804 "%s: A-MSDU parse error!! Subframe Length: %d\n",
805 __func__, nSubframe_Length);
806 netdev_info(ieee->dev,
807 "nRemain_Length is %d and nSubframe_Length is : %d\n",
808 skb->len, nSubframe_Length);
809 netdev_info(ieee->dev,
810 "The Packet SeqNum is %d\n",
811 SeqNum);
812 return 0;
Larry Finger94a79942011-08-23 19:00:42 -0500813 }
814
Mateusz Kulikowski285b7c02015-04-01 00:24:26 +0200815 /* move the data point to data content */
816 skb_pull(skb, ETHERNET_HEADER_SIZE);
817
818 /* altered by clark 3/30/2010
819 * The struct buffer size of the skb indicated to upper layer
820 * must be less than 5000, or the defraged IP datagram
821 * in the IP layer will exceed "ipfrag_high_tresh" and be
822 * discarded. so there must not use the function
823 * "skb_copy" and "skb_clone" for "skb".
824 */
825
826 /* Allocate new skb for releasing to upper layer */
827 sub_skb = dev_alloc_skb(nSubframe_Length + 12);
828 if (!sub_skb)
829 return 0;
830 skb_reserve(sub_skb, 12);
831 data_ptr = (u8 *)skb_put(sub_skb, nSubframe_Length);
832 memcpy(data_ptr, skb->data, nSubframe_Length);
833
834 sub_skb->dev = ieee->dev;
835 rxb->subframes[rxb->nr_subframes++] = sub_skb;
836 if (rxb->nr_subframes >= MAX_SUBFRAME_COUNT) {
837 RTLLIB_DEBUG_RX("ParseSubframe(): Too many Subframes! Packets dropped!\n");
838 break;
839 }
840 skb_pull(skb, nSubframe_Length);
841
842 if (skb->len != 0) {
843 nPadding_Length = 4 - ((nSubframe_Length +
844 ETHERNET_HEADER_SIZE) % 4);
845 if (nPadding_Length == 4)
846 nPadding_Length = 0;
847
848 if (skb->len < nPadding_Length)
849 return 0;
850
851 skb_pull(skb, nPadding_Length);
852 }
Larry Finger94a79942011-08-23 19:00:42 -0500853 }
Mateusz Kulikowski285b7c02015-04-01 00:24:26 +0200854
855 return rxb->nr_subframes;
Larry Finger94a79942011-08-23 19:00:42 -0500856}
857
858
Larry Finger49aab5f2011-08-25 14:07:05 -0500859static size_t rtllib_rx_get_hdrlen(struct rtllib_device *ieee,
860 struct sk_buff *skb,
861 struct rtllib_rx_stats *rx_stats)
Larry Finger94a79942011-08-23 19:00:42 -0500862{
863 struct rtllib_hdr_4addr *hdr = (struct rtllib_hdr_4addr *)skb->data;
864 u16 fc = le16_to_cpu(hdr->frame_ctl);
865 size_t hdrlen = 0;
866
867 hdrlen = rtllib_get_hdrlen(fc);
868 if (HTCCheck(ieee, skb->data)) {
869 if (net_ratelimit())
Mateusz Kulikowskid69d2052015-03-17 00:00:52 +0100870 netdev_info(ieee->dev, "%s: find HTCControl!\n",
871 __func__);
Larry Finger94a79942011-08-23 19:00:42 -0500872 hdrlen += 4;
Valentina Manea014e4c22013-10-29 20:58:48 +0200873 rx_stats->bContainHTC = true;
Larry Finger94a79942011-08-23 19:00:42 -0500874 }
875
876 if (RTLLIB_QOS_HAS_SEQ(fc))
Valentina Manea014e4c22013-10-29 20:58:48 +0200877 rx_stats->bIsQosData = true;
Larry Finger94a79942011-08-23 19:00:42 -0500878
879 return hdrlen;
880}
881
Larry Finger49aab5f2011-08-25 14:07:05 -0500882static int rtllib_rx_check_duplicate(struct rtllib_device *ieee,
883 struct sk_buff *skb, u8 multicast)
Larry Finger94a79942011-08-23 19:00:42 -0500884{
885 struct rtllib_hdr_4addr *hdr = (struct rtllib_hdr_4addr *)skb->data;
886 u16 fc, sc;
887 u8 frag, type, stype;
888
889 fc = le16_to_cpu(hdr->frame_ctl);
890 type = WLAN_FC_GET_TYPE(fc);
891 stype = WLAN_FC_GET_STYPE(fc);
892 sc = le16_to_cpu(hdr->seq_ctl);
893 frag = WLAN_GET_SEQ_FRAG(sc);
894
Larry Fingerdb8971b2011-08-25 11:48:25 -0500895 if ((ieee->pHTInfo->bCurRxReorderEnable == false) ||
Larry Finger94a79942011-08-23 19:00:42 -0500896 !ieee->current_network.qos_data.active ||
897 !IsDataFrame(skb->data) ||
898 IsLegacyDataFrame(skb->data)) {
Larry Fingerdb8971b2011-08-25 11:48:25 -0500899 if (!((type == RTLLIB_FTYPE_MGMT) && (stype == RTLLIB_STYPE_BEACON))) {
900 if (is_duplicate_packet(ieee, hdr))
Larry Finger94a79942011-08-23 19:00:42 -0500901 return -1;
Larry Finger94a79942011-08-23 19:00:42 -0500902 }
903 } else {
Larry Finger2c47ae22011-07-18 20:11:56 -0500904 struct rx_ts_record *pRxTS = NULL;
Matthew Casey3a6b70c2014-08-22 06:27:52 -0400905
Larry Finger74724de2011-07-18 20:19:19 -0500906 if (GetTs(ieee, (struct ts_common_info **) &pRxTS, hdr->addr2,
Larry Fingerdb8971b2011-08-25 11:48:25 -0500907 (u8)Frame_QoSTID((u8 *)(skb->data)), RX_DIR, true)) {
Larry Finger94a79942011-08-23 19:00:42 -0500908 if ((fc & (1<<11)) && (frag == pRxTS->RxLastFragNum) &&
Mahati Chamarthy59422a72014-09-19 23:12:53 +0530909 (WLAN_GET_SEQ_SEQ(sc) == pRxTS->RxLastSeqNum))
Larry Finger94a79942011-08-23 19:00:42 -0500910 return -1;
Mahati Chamarthy59422a72014-09-19 23:12:53 +0530911 pRxTS->RxLastFragNum = frag;
912 pRxTS->RxLastSeqNum = WLAN_GET_SEQ_SEQ(sc);
Larry Finger94a79942011-08-23 19:00:42 -0500913 } else {
Jonathan Jin6d6163c2014-12-15 21:28:23 -0600914 RTLLIB_DEBUG(RTLLIB_DL_ERR, "ERR!!%s(): No TS!! Skip the check!!\n", __func__);
Larry Finger94a79942011-08-23 19:00:42 -0500915 return -1;
916 }
917 }
918
919 return 0;
920}
Larry Fingerdb8971b2011-08-25 11:48:25 -0500921
Larry Finger49aab5f2011-08-25 14:07:05 -0500922static void rtllib_rx_extract_addr(struct rtllib_device *ieee,
923 struct rtllib_hdr_4addr *hdr, u8 *dst,
924 u8 *src, u8 *bssid)
Larry Finger94a79942011-08-23 19:00:42 -0500925{
926 u16 fc = le16_to_cpu(hdr->frame_ctl);
927
928 switch (fc & (RTLLIB_FCTL_FROMDS | RTLLIB_FCTL_TODS)) {
Larry Fingerdb8971b2011-08-25 11:48:25 -0500929 case RTLLIB_FCTL_FROMDS:
930 memcpy(dst, hdr->addr1, ETH_ALEN);
931 memcpy(src, hdr->addr3, ETH_ALEN);
932 memcpy(bssid, hdr->addr2, ETH_ALEN);
933 break;
934 case RTLLIB_FCTL_TODS:
935 memcpy(dst, hdr->addr3, ETH_ALEN);
936 memcpy(src, hdr->addr2, ETH_ALEN);
937 memcpy(bssid, hdr->addr1, ETH_ALEN);
938 break;
939 case RTLLIB_FCTL_FROMDS | RTLLIB_FCTL_TODS:
940 memcpy(dst, hdr->addr3, ETH_ALEN);
941 memcpy(src, hdr->addr4, ETH_ALEN);
942 memcpy(bssid, ieee->current_network.bssid, ETH_ALEN);
943 break;
944 case 0:
945 memcpy(dst, hdr->addr1, ETH_ALEN);
946 memcpy(src, hdr->addr2, ETH_ALEN);
947 memcpy(bssid, hdr->addr3, ETH_ALEN);
948 break;
Larry Finger94a79942011-08-23 19:00:42 -0500949 }
950}
Larry Fingerdb8971b2011-08-25 11:48:25 -0500951
Larry Finger49aab5f2011-08-25 14:07:05 -0500952static int rtllib_rx_data_filter(struct rtllib_device *ieee, u16 fc,
953 u8 *dst, u8 *src, u8 *bssid, u8 *addr2)
Larry Finger94a79942011-08-23 19:00:42 -0500954{
Larry Finger94a79942011-08-23 19:00:42 -0500955 u8 type, stype;
956
957 type = WLAN_FC_GET_TYPE(fc);
958 stype = WLAN_FC_GET_STYPE(fc);
959
960 /* Filter frames from different BSS */
Joe Perches83294192013-09-01 12:15:47 -0700961 if (((fc & RTLLIB_FCTL_DSTODS) != RTLLIB_FCTL_DSTODS) &&
962 !ether_addr_equal(ieee->current_network.bssid, bssid) &&
963 !is_zero_ether_addr(ieee->current_network.bssid)) {
Larry Finger94a79942011-08-23 19:00:42 -0500964 return -1;
965 }
966
967 /* Filter packets sent by an STA that will be forwarded by AP */
Larry Fingerdb8971b2011-08-25 11:48:25 -0500968 if (ieee->IntelPromiscuousModeInfo.bPromiscuousOn &&
969 ieee->IntelPromiscuousModeInfo.bFilterSourceStationFrame) {
Larry Finger94a79942011-08-23 19:00:42 -0500970 if ((fc & RTLLIB_FCTL_TODS) && !(fc & RTLLIB_FCTL_FROMDS) &&
Joe Perches83294192013-09-01 12:15:47 -0700971 !ether_addr_equal(dst, ieee->current_network.bssid) &&
972 ether_addr_equal(bssid, ieee->current_network.bssid)) {
Larry Finger94a79942011-08-23 19:00:42 -0500973 return -1;
974 }
975 }
976
977 /* Nullfunc frames may have PS-bit set, so they must be passed to
Mateusz Kulikowski14b40d92015-04-01 00:24:37 +0200978 * hostap_handle_sta_rx() before being dropped here.
979 */
Larry Fingerdb8971b2011-08-25 11:48:25 -0500980 if (!ieee->IntelPromiscuousModeInfo.bPromiscuousOn) {
Larry Finger94a79942011-08-23 19:00:42 -0500981 if (stype != RTLLIB_STYPE_DATA &&
982 stype != RTLLIB_STYPE_DATA_CFACK &&
983 stype != RTLLIB_STYPE_DATA_CFPOLL &&
Larry Fingerdb8971b2011-08-25 11:48:25 -0500984 stype != RTLLIB_STYPE_DATA_CFACKPOLL &&
985 stype != RTLLIB_STYPE_QOS_DATA) {
Larry Finger94a79942011-08-23 19:00:42 -0500986 if (stype != RTLLIB_STYPE_NULLFUNC)
987 RTLLIB_DEBUG_DROP(
Jonathan Jin6d6163c2014-12-15 21:28:23 -0600988 "RX: dropped data frame with no data (type=0x%02x, subtype=0x%02x)\n",
Larry Finger94a79942011-08-23 19:00:42 -0500989 type, stype);
990 return -1;
991 }
992 }
993
994 if (ieee->iw_mode != IW_MODE_MESH) {
995 /* packets from our adapter are dropped (echo) */
996 if (!memcmp(src, ieee->dev->dev_addr, ETH_ALEN))
997 return -1;
998
999 /* {broad,multi}cast packets to our BSS go through */
Joe Perches14fc4232012-05-08 10:11:56 -07001000 if (is_multicast_ether_addr(dst)) {
Larry Fingerdb8971b2011-08-25 11:48:25 -05001001 if (memcmp(bssid, ieee->current_network.bssid, ETH_ALEN))
Larry Finger94a79942011-08-23 19:00:42 -05001002 return -1;
Larry Finger94a79942011-08-23 19:00:42 -05001003 }
1004 }
1005 return 0;
1006}
Larry Fingerdb8971b2011-08-25 11:48:25 -05001007
Larry Finger49aab5f2011-08-25 14:07:05 -05001008static int rtllib_rx_get_crypt(struct rtllib_device *ieee, struct sk_buff *skb,
Sean MacLennan32c44cb2011-12-19 23:20:41 -05001009 struct lib80211_crypt_data **crypt, size_t hdrlen)
Larry Finger94a79942011-08-23 19:00:42 -05001010{
1011 struct rtllib_hdr_4addr *hdr = (struct rtllib_hdr_4addr *)skb->data;
1012 u16 fc = le16_to_cpu(hdr->frame_ctl);
1013 int idx = 0;
1014
1015 if (ieee->host_decrypt) {
1016 if (skb->len >= hdrlen + 3)
1017 idx = skb->data[hdrlen + 3] >> 6;
1018
Sean MacLennan0ddcf5f2011-12-19 23:21:41 -05001019 *crypt = ieee->crypt_info.crypt[idx];
Larry Finger94a79942011-08-23 19:00:42 -05001020 /* allow NULL decrypt to indicate an station specific override
Mateusz Kulikowski14b40d92015-04-01 00:24:37 +02001021 * for default encryption
1022 */
Larry Finger94a79942011-08-23 19:00:42 -05001023 if (*crypt && ((*crypt)->ops == NULL ||
1024 (*crypt)->ops->decrypt_mpdu == NULL))
1025 *crypt = NULL;
1026
1027 if (!*crypt && (fc & RTLLIB_FCTL_WEP)) {
1028 /* This seems to be triggered by some (multicast?)
1029 * frames from other than current BSS, so just drop the
1030 * frames silently instead of filling system log with
Mateusz Kulikowski14b40d92015-04-01 00:24:37 +02001031 * these reports.
1032 */
Jonathan Jin6d6163c2014-12-15 21:28:23 -06001033 RTLLIB_DEBUG_DROP("Decryption failed (not set) (SA= %pM)\n",
Larry Fingerac50dda2011-08-25 14:07:03 -05001034 hdr->addr2);
Larry Finger94a79942011-08-23 19:00:42 -05001035 ieee->ieee_stats.rx_discards_undecryptable++;
1036 return -1;
1037 }
1038 }
1039
1040 return 0;
1041}
Larry Fingerdb8971b2011-08-25 11:48:25 -05001042
Larry Finger49aab5f2011-08-25 14:07:05 -05001043static int rtllib_rx_decrypt(struct rtllib_device *ieee, struct sk_buff *skb,
Larry Fingerdb8971b2011-08-25 11:48:25 -05001044 struct rtllib_rx_stats *rx_stats,
Sean MacLennan32c44cb2011-12-19 23:20:41 -05001045 struct lib80211_crypt_data *crypt, size_t hdrlen)
Larry Finger94a79942011-08-23 19:00:42 -05001046{
1047 struct rtllib_hdr_4addr *hdr;
1048 int keyidx = 0;
1049 u16 fc, sc;
1050 u8 frag;
1051
1052 hdr = (struct rtllib_hdr_4addr *)skb->data;
1053 fc = le16_to_cpu(hdr->frame_ctl);
1054 sc = le16_to_cpu(hdr->seq_ctl);
1055 frag = WLAN_GET_SEQ_FRAG(sc);
1056
Larry Fingerdb8971b2011-08-25 11:48:25 -05001057 if ((!rx_stats->Decrypted))
Larry Finger94a79942011-08-23 19:00:42 -05001058 ieee->need_sw_enc = 1;
Larry Fingerdb8971b2011-08-25 11:48:25 -05001059 else
Larry Finger94a79942011-08-23 19:00:42 -05001060 ieee->need_sw_enc = 0;
Larry Finger94a79942011-08-23 19:00:42 -05001061
Larry Fingerdb8971b2011-08-25 11:48:25 -05001062 keyidx = rtllib_rx_frame_decrypt(ieee, skb, crypt);
1063 if (ieee->host_decrypt && (fc & RTLLIB_FCTL_WEP) && (keyidx < 0)) {
Mateusz Kulikowskid69d2052015-03-17 00:00:52 +01001064 netdev_info(ieee->dev, "%s: decrypt frame error\n", __func__);
Larry Finger94a79942011-08-23 19:00:42 -05001065 return -1;
1066 }
1067
1068 hdr = (struct rtllib_hdr_4addr *) skb->data;
1069 if ((frag != 0 || (fc & RTLLIB_FCTL_MOREFRAGS))) {
1070 int flen;
1071 struct sk_buff *frag_skb = rtllib_frag_cache_get(ieee, hdr);
Matthew Casey3a6b70c2014-08-22 06:27:52 -04001072
Larry Finger94a79942011-08-23 19:00:42 -05001073 RTLLIB_DEBUG_FRAG("Rx Fragment received (%u)\n", frag);
1074
1075 if (!frag_skb) {
1076 RTLLIB_DEBUG(RTLLIB_DL_RX | RTLLIB_DL_FRAG,
Jonathan Jin6d6163c2014-12-15 21:28:23 -06001077 "Rx cannot get skb from fragment cache (morefrag=%d seq=%u frag=%u)\n",
Larry Finger94a79942011-08-23 19:00:42 -05001078 (fc & RTLLIB_FCTL_MOREFRAGS) != 0,
1079 WLAN_GET_SEQ_SEQ(sc), frag);
1080 return -1;
1081 }
1082 flen = skb->len;
1083 if (frag != 0)
1084 flen -= hdrlen;
1085
1086 if (frag_skb->tail + flen > frag_skb->end) {
Mateusz Kulikowskid69d2052015-03-17 00:00:52 +01001087 netdev_warn(ieee->dev,
1088 "%s: host decrypted and reassembled frame did not fit skb\n",
1089 __func__);
Larry Finger94a79942011-08-23 19:00:42 -05001090 rtllib_frag_cache_invalidate(ieee, hdr);
1091 return -1;
1092 }
1093
1094 if (frag == 0) {
1095 /* copy first fragment (including full headers) into
Mateusz Kulikowski14b40d92015-04-01 00:24:37 +02001096 * beginning of the fragment cache skb
1097 */
Larry Finger94a79942011-08-23 19:00:42 -05001098 memcpy(skb_put(frag_skb, flen), skb->data, flen);
1099 } else {
1100 /* append frame payload to the end of the fragment
Mateusz Kulikowski14b40d92015-04-01 00:24:37 +02001101 * cache skb
1102 */
Larry Finger94a79942011-08-23 19:00:42 -05001103 memcpy(skb_put(frag_skb, flen), skb->data + hdrlen,
1104 flen);
1105 }
1106 dev_kfree_skb_any(skb);
1107 skb = NULL;
1108
1109 if (fc & RTLLIB_FCTL_MOREFRAGS) {
1110 /* more fragments expected - leave the skb in fragment
1111 * cache for now; it will be delivered to upper layers
Mateusz Kulikowski14b40d92015-04-01 00:24:37 +02001112 * after all fragments have been received
1113 */
Larry Finger94a79942011-08-23 19:00:42 -05001114 return -2;
1115 }
1116
1117 /* this was the last fragment and the frame will be
Mateusz Kulikowski14b40d92015-04-01 00:24:37 +02001118 * delivered, so remove skb from fragment cache
1119 */
Larry Finger94a79942011-08-23 19:00:42 -05001120 skb = frag_skb;
1121 hdr = (struct rtllib_hdr_4addr *) skb->data;
1122 rtllib_frag_cache_invalidate(ieee, hdr);
1123 }
1124
1125 /* skb: hdr + (possible reassembled) full MSDU payload; possibly still
Mateusz Kulikowski14b40d92015-04-01 00:24:37 +02001126 * encrypted/authenticated
1127 */
Larry Finger94a79942011-08-23 19:00:42 -05001128 if (ieee->host_decrypt && (fc & RTLLIB_FCTL_WEP) &&
Larry Fingerdb8971b2011-08-25 11:48:25 -05001129 rtllib_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt)) {
Mateusz Kulikowskid69d2052015-03-17 00:00:52 +01001130 netdev_info(ieee->dev, "%s: ==>decrypt msdu error\n", __func__);
Larry Finger94a79942011-08-23 19:00:42 -05001131 return -1;
1132 }
1133
1134 hdr = (struct rtllib_hdr_4addr *) skb->data;
1135 if (crypt && !(fc & RTLLIB_FCTL_WEP) && !ieee->open_wep) {
1136 if (/*ieee->ieee802_1x &&*/
1137 rtllib_is_eapol_frame(ieee, skb, hdrlen)) {
1138
Larry Finger94a79942011-08-23 19:00:42 -05001139 /* pass unencrypted EAPOL frames even if encryption is
Mateusz Kulikowski14b40d92015-04-01 00:24:37 +02001140 * configured
1141 */
Larry Finger94a79942011-08-23 19:00:42 -05001142 struct eapol *eap = (struct eapol *)(skb->data +
1143 24);
1144 RTLLIB_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n",
1145 eap_get_type(eap->type));
Larry Finger94a79942011-08-23 19:00:42 -05001146 } else {
1147 RTLLIB_DEBUG_DROP(
Jonathan Jin6d6163c2014-12-15 21:28:23 -06001148 "encryption configured, but RX frame not encrypted (SA= %pM)\n",
Larry Fingerac50dda2011-08-25 14:07:03 -05001149 hdr->addr2);
Larry Finger94a79942011-08-23 19:00:42 -05001150 return -1;
1151 }
1152 }
1153
Larry Finger94a79942011-08-23 19:00:42 -05001154 if (crypt && !(fc & RTLLIB_FCTL_WEP) &&
1155 rtllib_is_eapol_frame(ieee, skb, hdrlen)) {
1156 struct eapol *eap = (struct eapol *)(skb->data +
1157 24);
1158 RTLLIB_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n",
1159 eap_get_type(eap->type));
1160 }
Larry Finger94a79942011-08-23 19:00:42 -05001161
1162 if (crypt && !(fc & RTLLIB_FCTL_WEP) && !ieee->open_wep &&
1163 !rtllib_is_eapol_frame(ieee, skb, hdrlen)) {
1164 RTLLIB_DEBUG_DROP(
Jonathan Jin6d6163c2014-12-15 21:28:23 -06001165 "dropped unencrypted RX data frame from %pM (drop_unencrypted=1)\n",
Larry Fingerac50dda2011-08-25 14:07:03 -05001166 hdr->addr2);
Larry Finger94a79942011-08-23 19:00:42 -05001167 return -1;
1168 }
1169
Larry Fingerdb8971b2011-08-25 11:48:25 -05001170 if (rtllib_is_eapol_frame(ieee, skb, hdrlen))
Mateusz Kulikowskid69d2052015-03-17 00:00:52 +01001171 netdev_warn(ieee->dev, "RX: IEEE802.1X EAPOL frame!\n");
Larry Finger94a79942011-08-23 19:00:42 -05001172
1173 return 0;
1174}
Larry Fingerdb8971b2011-08-25 11:48:25 -05001175
Larry Finger49aab5f2011-08-25 14:07:05 -05001176static void rtllib_rx_check_leave_lps(struct rtllib_device *ieee, u8 unicast, u8 nr_subframes)
Larry Finger94a79942011-08-23 19:00:42 -05001177{
Larry Fingerdb8971b2011-08-25 11:48:25 -05001178 if (unicast) {
Larry Finger94a79942011-08-23 19:00:42 -05001179
Mateusz Kulikowski025b8bb2015-04-01 00:24:29 +02001180 if (ieee->state == RTLLIB_LINKED) {
Larry Fingerdb8971b2011-08-25 11:48:25 -05001181 if (((ieee->LinkDetectInfo.NumRxUnicastOkInPeriod +
1182 ieee->LinkDetectInfo.NumTxOkInPeriod) > 8) ||
1183 (ieee->LinkDetectInfo.NumRxUnicastOkInPeriod > 2)) {
Larry Finger94a79942011-08-23 19:00:42 -05001184 if (ieee->LeisurePSLeave)
1185 ieee->LeisurePSLeave(ieee->dev);
1186 }
1187 }
1188 }
Larry Finger94a79942011-08-23 19:00:42 -05001189 ieee->last_rx_ps_time = jiffies;
1190}
Larry Fingerdb8971b2011-08-25 11:48:25 -05001191
Larry Finger49aab5f2011-08-25 14:07:05 -05001192static void rtllib_rx_indicate_pkt_legacy(struct rtllib_device *ieee,
Larry Finger94a79942011-08-23 19:00:42 -05001193 struct rtllib_rx_stats *rx_stats,
Larry Fingerdb8971b2011-08-25 11:48:25 -05001194 struct rtllib_rxb *rxb,
Larry Finger94a79942011-08-23 19:00:42 -05001195 u8 *dst,
1196 u8 *src)
1197{
1198 struct net_device *dev = ieee->dev;
1199 u16 ethertype;
1200 int i = 0;
1201
Larry Fingerdb8971b2011-08-25 11:48:25 -05001202 if (rxb == NULL) {
Mateusz Kulikowskid69d2052015-03-17 00:00:52 +01001203 netdev_info(dev, "%s: rxb is NULL!!\n", __func__);
Mateusz Kulikowskidc986e32015-03-17 00:00:49 +01001204 return;
Larry Finger94a79942011-08-23 19:00:42 -05001205 }
1206
Larry Fingerdb8971b2011-08-25 11:48:25 -05001207 for (i = 0; i < rxb->nr_subframes; i++) {
Larry Finger94a79942011-08-23 19:00:42 -05001208 struct sk_buff *sub_skb = rxb->subframes[i];
1209
1210 if (sub_skb) {
1211 /* convert hdr + possible LLC headers into Ethernet header */
1212 ethertype = (sub_skb->data[6] << 8) | sub_skb->data[7];
1213 if (sub_skb->len >= 8 &&
Larry Fingerdb8971b2011-08-25 11:48:25 -05001214 ((memcmp(sub_skb->data, rfc1042_header, SNAP_SIZE) == 0 &&
1215 ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
1216 memcmp(sub_skb->data, bridge_tunnel_header, SNAP_SIZE) == 0)) {
Larry Finger94a79942011-08-23 19:00:42 -05001217 /* remove RFC1042 or Bridge-Tunnel encapsulation and
Mateusz Kulikowski14b40d92015-04-01 00:24:37 +02001218 * replace EtherType
1219 */
Larry Finger94a79942011-08-23 19:00:42 -05001220 skb_pull(sub_skb, SNAP_SIZE);
1221 memcpy(skb_push(sub_skb, ETH_ALEN), src, ETH_ALEN);
1222 memcpy(skb_push(sub_skb, ETH_ALEN), dst, ETH_ALEN);
1223 } else {
1224 u16 len;
1225 /* Leave Ethernet header part of hdr and full payload */
Rashika Kheria1f5a0d02013-11-02 23:34:44 +05301226 len = sub_skb->len;
Larry Finger94a79942011-08-23 19:00:42 -05001227 memcpy(skb_push(sub_skb, 2), &len, 2);
1228 memcpy(skb_push(sub_skb, ETH_ALEN), src, ETH_ALEN);
1229 memcpy(skb_push(sub_skb, ETH_ALEN), dst, ETH_ALEN);
1230 }
1231
1232 ieee->stats.rx_packets++;
1233 ieee->stats.rx_bytes += sub_skb->len;
1234
Larry Fingerdb8971b2011-08-25 11:48:25 -05001235 if (is_multicast_ether_addr(dst))
Larry Finger94a79942011-08-23 19:00:42 -05001236 ieee->stats.multicast++;
Larry Finger94a79942011-08-23 19:00:42 -05001237
Justin P. Mattockcd017122012-04-23 07:36:52 -07001238 /* Indicate the packets to upper layer */
Larry Finger94a79942011-08-23 19:00:42 -05001239 memset(sub_skb->cb, 0, sizeof(sub_skb->cb));
1240 sub_skb->protocol = eth_type_trans(sub_skb, dev);
1241 sub_skb->dev = dev;
1242 sub_skb->dev->stats.rx_packets++;
1243 sub_skb->dev->stats.rx_bytes += sub_skb->len;
Larry Finger94a79942011-08-23 19:00:42 -05001244 sub_skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */
Larry Finger94a79942011-08-23 19:00:42 -05001245 netif_rx(sub_skb);
1246 }
1247 }
1248 kfree(rxb);
Larry Finger94a79942011-08-23 19:00:42 -05001249}
Larry Fingerdb8971b2011-08-25 11:48:25 -05001250
Larry Finger49aab5f2011-08-25 14:07:05 -05001251static int rtllib_rx_InfraAdhoc(struct rtllib_device *ieee, struct sk_buff *skb,
Larry Finger94a79942011-08-23 19:00:42 -05001252 struct rtllib_rx_stats *rx_stats)
1253{
1254 struct net_device *dev = ieee->dev;
1255 struct rtllib_hdr_4addr *hdr = (struct rtllib_hdr_4addr *)skb->data;
Sean MacLennan32c44cb2011-12-19 23:20:41 -05001256 struct lib80211_crypt_data *crypt = NULL;
Larry Fingerdb8971b2011-08-25 11:48:25 -05001257 struct rtllib_rxb *rxb = NULL;
Larry Finger2c47ae22011-07-18 20:11:56 -05001258 struct rx_ts_record *pTS = NULL;
Larry Finger94a79942011-08-23 19:00:42 -05001259 u16 fc, sc, SeqNum = 0;
1260 u8 type, stype, multicast = 0, unicast = 0, nr_subframes = 0, TID = 0;
1261 u8 dst[ETH_ALEN], src[ETH_ALEN], bssid[ETH_ALEN] = {0}, *payload;
1262 size_t hdrlen = 0;
1263 bool bToOtherSTA = false;
1264 int ret = 0, i = 0;
1265
1266 hdr = (struct rtllib_hdr_4addr *)skb->data;
1267 fc = le16_to_cpu(hdr->frame_ctl);
1268 type = WLAN_FC_GET_TYPE(fc);
1269 stype = WLAN_FC_GET_STYPE(fc);
1270 sc = le16_to_cpu(hdr->seq_ctl);
1271
1272 /*Filter pkt not to me*/
Joe Perches14fc4232012-05-08 10:11:56 -07001273 multicast = is_multicast_ether_addr(hdr->addr1);
Larry Finger94a79942011-08-23 19:00:42 -05001274 unicast = !multicast;
Joe Perches83294192013-09-01 12:15:47 -07001275 if (unicast && !ether_addr_equal(dev->dev_addr, hdr->addr1)) {
Larry Finger94a79942011-08-23 19:00:42 -05001276 if (ieee->bNetPromiscuousMode)
1277 bToOtherSTA = true;
1278 else
1279 goto rx_dropped;
1280 }
1281
1282 /*Filter pkt has too small length */
1283 hdrlen = rtllib_rx_get_hdrlen(ieee, skb, rx_stats);
Larry Fingerdb8971b2011-08-25 11:48:25 -05001284 if (skb->len < hdrlen) {
Mateusz Kulikowskid69d2052015-03-17 00:00:52 +01001285 netdev_info(dev, "%s():ERR!!! skb->len is smaller than hdrlen\n",
1286 __func__);
Larry Finger94a79942011-08-23 19:00:42 -05001287 goto rx_dropped;
1288 }
1289
1290 /* Filter Duplicate pkt */
1291 ret = rtllib_rx_check_duplicate(ieee, skb, multicast);
1292 if (ret < 0)
1293 goto rx_dropped;
1294
1295 /* Filter CTRL Frame */
Larry Fingerdb8971b2011-08-25 11:48:25 -05001296 if (type == RTLLIB_FTYPE_CTL)
Larry Finger94a79942011-08-23 19:00:42 -05001297 goto rx_dropped;
Larry Finger94a79942011-08-23 19:00:42 -05001298
1299 /* Filter MGNT Frame */
1300 if (type == RTLLIB_FTYPE_MGMT) {
1301 if (bToOtherSTA)
1302 goto rx_dropped;
1303 if (rtllib_rx_frame_mgmt(ieee, skb, rx_stats, type, stype))
1304 goto rx_dropped;
1305 else
1306 goto rx_exit;
1307 }
1308
1309 /* Filter WAPI DATA Frame */
1310
1311 /* Update statstics for AP roaming */
Larry Fingerdb8971b2011-08-25 11:48:25 -05001312 if (!bToOtherSTA) {
Larry Finger94a79942011-08-23 19:00:42 -05001313 ieee->LinkDetectInfo.NumRecvDataInPeriod++;
1314 ieee->LinkDetectInfo.NumRxOkInPeriod++;
1315 }
1316 dev->last_rx = jiffies;
1317
1318 /* Data frame - extract src/dst addresses */
1319 rtllib_rx_extract_addr(ieee, hdr, dst, src, bssid);
1320
1321 /* Filter Data frames */
1322 ret = rtllib_rx_data_filter(ieee, fc, dst, src, bssid, hdr->addr2);
1323 if (ret < 0)
1324 goto rx_dropped;
1325
Larry Fingerdb8971b2011-08-25 11:48:25 -05001326 if (skb->len == hdrlen)
Larry Finger94a79942011-08-23 19:00:42 -05001327 goto rx_dropped;
Larry Finger94a79942011-08-23 19:00:42 -05001328
1329 /* Send pspoll based on moredata */
1330 if ((ieee->iw_mode == IW_MODE_INFRA) && (ieee->sta_sleep == LPS_IS_SLEEP)
1331 && (ieee->polling) && (!bToOtherSTA)) {
1332 if (WLAN_FC_MORE_DATA(fc)) {
1333 /* more data bit is set, let's request a new frame from the AP */
1334 rtllib_sta_ps_send_pspoll_frame(ieee);
1335 } else {
1336 ieee->polling = false;
1337 }
1338 }
1339
Larry Finger94a79942011-08-23 19:00:42 -05001340 /* Get crypt if encrypted */
1341 ret = rtllib_rx_get_crypt(ieee, skb, &crypt, hdrlen);
1342 if (ret == -1)
1343 goto rx_dropped;
1344
1345 /* Decrypt data frame (including reassemble) */
1346 ret = rtllib_rx_decrypt(ieee, skb, rx_stats, crypt, hdrlen);
1347 if (ret == -1)
1348 goto rx_dropped;
1349 else if (ret == -2)
1350 goto rx_exit;
1351
1352 /* Get TS for Rx Reorder */
1353 hdr = (struct rtllib_hdr_4addr *) skb->data;
1354 if (ieee->current_network.qos_data.active && IsQoSDataFrame(skb->data)
Joe Perches14fc4232012-05-08 10:11:56 -07001355 && !is_multicast_ether_addr(hdr->addr1)
Larry Fingerdb8971b2011-08-25 11:48:25 -05001356 && (!bToOtherSTA)) {
Larry Finger94a79942011-08-23 19:00:42 -05001357 TID = Frame_QoSTID(skb->data);
1358 SeqNum = WLAN_GET_SEQ_SEQ(sc);
Larry Fingerdb8971b2011-08-25 11:48:25 -05001359 GetTs(ieee, (struct ts_common_info **) &pTS, hdr->addr2, TID, RX_DIR, true);
1360 if (TID != 0 && TID != 3)
Larry Finger94a79942011-08-23 19:00:42 -05001361 ieee->bis_any_nonbepkts = true;
Larry Finger94a79942011-08-23 19:00:42 -05001362 }
1363
1364 /* Parse rx data frame (For AMSDU) */
1365 /* skb: hdr + (possible reassembled) full plaintext payload */
1366 payload = skb->data + hdrlen;
Larry Fingerdb8971b2011-08-25 11:48:25 -05001367 rxb = kmalloc(sizeof(struct rtllib_rxb), GFP_ATOMIC);
Quentin Lambertb6b00122015-03-05 14:12:15 +01001368 if (rxb == NULL)
Larry Finger94a79942011-08-23 19:00:42 -05001369 goto rx_dropped;
Quentin Lambertb6b00122015-03-05 14:12:15 +01001370
Larry Finger94a79942011-08-23 19:00:42 -05001371 /* to parse amsdu packets */
1372 /* qos data packets & reserved bit is 1 */
Larry Fingerdb8971b2011-08-25 11:48:25 -05001373 if (parse_subframe(ieee, skb, rx_stats, rxb, src, dst) == 0) {
Larry Finger94a79942011-08-23 19:00:42 -05001374 /* only to free rxb, and not submit the packets to upper layer */
Larry Fingerdb8971b2011-08-25 11:48:25 -05001375 for (i = 0; i < rxb->nr_subframes; i++)
Larry Finger94a79942011-08-23 19:00:42 -05001376 dev_kfree_skb(rxb->subframes[i]);
Larry Finger94a79942011-08-23 19:00:42 -05001377 kfree(rxb);
1378 rxb = NULL;
1379 goto rx_dropped;
1380 }
1381
1382 /* Update WAPI PN */
1383
1384 /* Check if leave LPS */
Larry Fingerdb8971b2011-08-25 11:48:25 -05001385 if (!bToOtherSTA) {
Larry Finger94a79942011-08-23 19:00:42 -05001386 if (ieee->bIsAggregateFrame)
1387 nr_subframes = rxb->nr_subframes;
1388 else
1389 nr_subframes = 1;
1390 if (unicast)
1391 ieee->LinkDetectInfo.NumRxUnicastOkInPeriod += nr_subframes;
1392 rtllib_rx_check_leave_lps(ieee, unicast, nr_subframes);
1393 }
1394
1395 /* Indicate packets to upper layer or Rx Reorder */
Larry Fingerdb8971b2011-08-25 11:48:25 -05001396 if (ieee->pHTInfo->bCurRxReorderEnable == false || pTS == NULL || bToOtherSTA)
Larry Finger94a79942011-08-23 19:00:42 -05001397 rtllib_rx_indicate_pkt_legacy(ieee, rx_stats, rxb, dst, src);
Larry Fingerdb8971b2011-08-25 11:48:25 -05001398 else
Larry Finger94a79942011-08-23 19:00:42 -05001399 RxReorderIndicatePacket(ieee, rxb, pTS, SeqNum);
Larry Finger94a79942011-08-23 19:00:42 -05001400
1401 dev_kfree_skb(skb);
1402
1403 rx_exit:
1404 return 1;
1405
1406 rx_dropped:
Larry Finger94a79942011-08-23 19:00:42 -05001407 ieee->stats.rx_dropped++;
1408
1409 /* Returning 0 indicates to caller that we have not handled the SKB--
1410 * so it is still allocated and can be used again by underlying
Mateusz Kulikowski14b40d92015-04-01 00:24:37 +02001411 * hardware as a DMA target
1412 */
Larry Finger94a79942011-08-23 19:00:42 -05001413 return 0;
1414}
1415
Larry Finger49aab5f2011-08-25 14:07:05 -05001416static int rtllib_rx_Master(struct rtllib_device *ieee, struct sk_buff *skb,
Larry Finger94a79942011-08-23 19:00:42 -05001417 struct rtllib_rx_stats *rx_stats)
1418{
1419 return 0;
1420}
Larry Fingerdb8971b2011-08-25 11:48:25 -05001421
Larry Finger49aab5f2011-08-25 14:07:05 -05001422static int rtllib_rx_Monitor(struct rtllib_device *ieee, struct sk_buff *skb,
Larry Finger94a79942011-08-23 19:00:42 -05001423 struct rtllib_rx_stats *rx_stats)
1424{
1425 struct rtllib_hdr_4addr *hdr = (struct rtllib_hdr_4addr *)skb->data;
1426 u16 fc = le16_to_cpu(hdr->frame_ctl);
1427 size_t hdrlen = rtllib_get_hdrlen(fc);
1428
Larry Fingerdb8971b2011-08-25 11:48:25 -05001429 if (skb->len < hdrlen) {
Mateusz Kulikowskid69d2052015-03-17 00:00:52 +01001430 netdev_info(ieee->dev,
1431 "%s():ERR!!! skb->len is smaller than hdrlen\n",
1432 __func__);
Larry Finger94a79942011-08-23 19:00:42 -05001433 return 0;
1434 }
1435
1436 if (HTCCheck(ieee, skb->data)) {
1437 if (net_ratelimit())
Mateusz Kulikowskid69d2052015-03-17 00:00:52 +01001438 netdev_info(ieee->dev, "%s: Find HTCControl!\n",
1439 __func__);
Larry Finger94a79942011-08-23 19:00:42 -05001440 hdrlen += 4;
1441 }
1442
Larry Finger94a79942011-08-23 19:00:42 -05001443 rtllib_monitor_rx(ieee, skb, rx_stats, hdrlen);
1444 ieee->stats.rx_packets++;
1445 ieee->stats.rx_bytes += skb->len;
Mike McCormack35917332011-07-11 08:56:03 +09001446
Larry Finger94a79942011-08-23 19:00:42 -05001447 return 1;
1448}
1449
Larry Finger49aab5f2011-08-25 14:07:05 -05001450static int rtllib_rx_Mesh(struct rtllib_device *ieee, struct sk_buff *skb,
Larry Finger94a79942011-08-23 19:00:42 -05001451 struct rtllib_rx_stats *rx_stats)
1452{
1453 return 0;
1454}
1455
Larry Finger94a79942011-08-23 19:00:42 -05001456/* All received frames are sent to this function. @skb contains the frame in
1457 * IEEE 802.11 format, i.e., in the format it was sent over air.
Mateusz Kulikowski14b40d92015-04-01 00:24:37 +02001458 * This function is called only as a tasklet (software IRQ).
1459 */
Larry Finger94a79942011-08-23 19:00:42 -05001460int rtllib_rx(struct rtllib_device *ieee, struct sk_buff *skb,
1461 struct rtllib_rx_stats *rx_stats)
1462{
1463 int ret = 0;
1464
Larry Fingerdb8971b2011-08-25 11:48:25 -05001465 if ((NULL == ieee) || (NULL == skb) || (NULL == rx_stats)) {
Mateusz Kulikowskid69d2052015-03-17 00:00:52 +01001466 pr_info("%s: Input parameters NULL!\n", __func__);
Larry Finger94a79942011-08-23 19:00:42 -05001467 goto rx_dropped;
1468 }
1469 if (skb->len < 10) {
Mateusz Kulikowskid69d2052015-03-17 00:00:52 +01001470 netdev_info(ieee->dev, "%s: SKB length < 10\n", __func__);
Larry Finger94a79942011-08-23 19:00:42 -05001471 goto rx_dropped;
1472 }
1473
1474 switch (ieee->iw_mode) {
1475 case IW_MODE_ADHOC:
1476 case IW_MODE_INFRA:
1477 ret = rtllib_rx_InfraAdhoc(ieee, skb, rx_stats);
1478 break;
1479 case IW_MODE_MASTER:
1480 case IW_MODE_REPEAT:
1481 ret = rtllib_rx_Master(ieee, skb, rx_stats);
1482 break;
1483 case IW_MODE_MONITOR:
1484 ret = rtllib_rx_Monitor(ieee, skb, rx_stats);
1485 break;
1486 case IW_MODE_MESH:
1487 ret = rtllib_rx_Mesh(ieee, skb, rx_stats);
1488 break;
1489 default:
Mateusz Kulikowskid69d2052015-03-17 00:00:52 +01001490 netdev_info(ieee->dev, "%s: ERR iw mode!!!\n", __func__);
Larry Finger94a79942011-08-23 19:00:42 -05001491 break;
1492 }
1493
1494 return ret;
1495
1496 rx_dropped:
Emil Goode4fa42602014-07-02 11:25:51 +02001497 if (ieee)
1498 ieee->stats.rx_dropped++;
Larry Finger94a79942011-08-23 19:00:42 -05001499 return 0;
1500}
Sean MacLennan3b284992011-11-28 20:20:26 -05001501EXPORT_SYMBOL(rtllib_rx);
Larry Finger94a79942011-08-23 19:00:42 -05001502
1503static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 };
1504
Mateusz Kulikowski14b40d92015-04-01 00:24:37 +02001505/* Make ther structure we read from the beacon packet has the right values */
Larry Finger94a79942011-08-23 19:00:42 -05001506static int rtllib_verify_qos_info(struct rtllib_qos_information_element
Larry Fingerdb8971b2011-08-25 11:48:25 -05001507 *info_element, int sub_type)
Larry Finger94a79942011-08-23 19:00:42 -05001508{
1509
Larry Fingerdb8971b2011-08-25 11:48:25 -05001510 if (info_element->qui_subtype != sub_type)
1511 return -1;
1512 if (memcmp(info_element->qui, qos_oui, QOS_OUI_LEN))
1513 return -1;
1514 if (info_element->qui_type != QOS_OUI_TYPE)
1515 return -1;
1516 if (info_element->version != QOS_VERSION_1)
1517 return -1;
Larry Finger94a79942011-08-23 19:00:42 -05001518
Larry Fingerdb8971b2011-08-25 11:48:25 -05001519 return 0;
Larry Finger94a79942011-08-23 19:00:42 -05001520}
1521
1522
Mateusz Kulikowski14b40d92015-04-01 00:24:37 +02001523/* Parse a QoS parameter element */
Larry Finger94a79942011-08-23 19:00:42 -05001524static int rtllib_read_qos_param_element(struct rtllib_qos_parameter_info
Larry Fingerdb8971b2011-08-25 11:48:25 -05001525 *element_param, struct rtllib_info_element
1526 *info_element)
Larry Finger94a79942011-08-23 19:00:42 -05001527{
Larry Fingerdb8971b2011-08-25 11:48:25 -05001528 int ret = 0;
1529 u16 size = sizeof(struct rtllib_qos_parameter_info) - 2;
Larry Finger94a79942011-08-23 19:00:42 -05001530
Larry Fingerdb8971b2011-08-25 11:48:25 -05001531 if ((info_element == NULL) || (element_param == NULL))
1532 return -1;
Larry Finger94a79942011-08-23 19:00:42 -05001533
Larry Fingerdb8971b2011-08-25 11:48:25 -05001534 if (info_element->id == QOS_ELEMENT_ID && info_element->len == size) {
1535 memcpy(element_param->info_element.qui, info_element->data,
1536 info_element->len);
1537 element_param->info_element.elementID = info_element->id;
1538 element_param->info_element.length = info_element->len;
1539 } else
1540 ret = -1;
1541 if (ret == 0)
1542 ret = rtllib_verify_qos_info(&element_param->info_element,
1543 QOS_OUI_PARAM_SUB_TYPE);
1544 return ret;
Larry Finger94a79942011-08-23 19:00:42 -05001545}
1546
Mateusz Kulikowski14b40d92015-04-01 00:24:37 +02001547/* Parse a QoS information element */
Larry Finger94a79942011-08-23 19:00:42 -05001548static int rtllib_read_qos_info_element(struct
Larry Fingerdb8971b2011-08-25 11:48:25 -05001549 rtllib_qos_information_element
1550 *element_info, struct rtllib_info_element
1551 *info_element)
Larry Finger94a79942011-08-23 19:00:42 -05001552{
Larry Fingerdb8971b2011-08-25 11:48:25 -05001553 int ret = 0;
1554 u16 size = sizeof(struct rtllib_qos_information_element) - 2;
Larry Finger94a79942011-08-23 19:00:42 -05001555
Larry Fingerdb8971b2011-08-25 11:48:25 -05001556 if (element_info == NULL)
1557 return -1;
1558 if (info_element == NULL)
1559 return -1;
Larry Finger94a79942011-08-23 19:00:42 -05001560
Larry Fingerdb8971b2011-08-25 11:48:25 -05001561 if ((info_element->id == QOS_ELEMENT_ID) && (info_element->len == size)) {
1562 memcpy(element_info->qui, info_element->data,
1563 info_element->len);
1564 element_info->elementID = info_element->id;
1565 element_info->length = info_element->len;
1566 } else
1567 ret = -1;
Larry Finger94a79942011-08-23 19:00:42 -05001568
Larry Fingerdb8971b2011-08-25 11:48:25 -05001569 if (ret == 0)
1570 ret = rtllib_verify_qos_info(element_info,
1571 QOS_OUI_INFO_SUB_TYPE);
1572 return ret;
Larry Finger94a79942011-08-23 19:00:42 -05001573}
1574
1575
Mateusz Kulikowski14b40d92015-04-01 00:24:37 +02001576/* Write QoS parameters from the ac parameters. */
Larry Finger94a79942011-08-23 19:00:42 -05001577static int rtllib_qos_convert_ac_to_parameters(struct rtllib_qos_parameter_info *param_elm,
1578 struct rtllib_qos_data *qos_data)
1579{
Larry Fingerdb8971b2011-08-25 11:48:25 -05001580 struct rtllib_qos_ac_parameter *ac_params;
Larry Finger94a79942011-08-23 19:00:42 -05001581 struct rtllib_qos_parameters *qos_param = &(qos_data->parameters);
Larry Fingerdb8971b2011-08-25 11:48:25 -05001582 int i;
Larry Finger94a79942011-08-23 19:00:42 -05001583 u8 aci;
1584 u8 acm;
1585
1586 qos_data->wmm_acm = 0;
Larry Fingerdb8971b2011-08-25 11:48:25 -05001587 for (i = 0; i < QOS_QUEUE_NUM; i++) {
1588 ac_params = &(param_elm->ac_params_record[i]);
Larry Finger94a79942011-08-23 19:00:42 -05001589
1590 aci = (ac_params->aci_aifsn & 0x60) >> 5;
1591 acm = (ac_params->aci_aifsn & 0x10) >> 4;
1592
1593 if (aci >= QOS_QUEUE_NUM)
1594 continue;
1595 switch (aci) {
Larry Fingerdb8971b2011-08-25 11:48:25 -05001596 case 1:
1597 /* BIT(0) | BIT(3) */
1598 if (acm)
1599 qos_data->wmm_acm |= (0x01<<0)|(0x01<<3);
1600 break;
1601 case 2:
1602 /* BIT(4) | BIT(5) */
1603 if (acm)
1604 qos_data->wmm_acm |= (0x01<<4)|(0x01<<5);
1605 break;
1606 case 3:
1607 /* BIT(6) | BIT(7) */
1608 if (acm)
1609 qos_data->wmm_acm |= (0x01<<6)|(0x01<<7);
1610 break;
1611 case 0:
1612 default:
1613 /* BIT(1) | BIT(2) */
1614 if (acm)
1615 qos_data->wmm_acm |= (0x01<<1)|(0x01<<2);
1616 break;
Larry Finger94a79942011-08-23 19:00:42 -05001617 }
1618
Larry Fingerdb8971b2011-08-25 11:48:25 -05001619 qos_param->aifs[aci] = (ac_params->aci_aifsn) & 0x0f;
Larry Finger94a79942011-08-23 19:00:42 -05001620
1621 /* WMM spec P.11: The minimum value for AIFSN shall be 2 */
Larry Fingerdb8971b2011-08-25 11:48:25 -05001622 qos_param->aifs[aci] = (qos_param->aifs[aci] < 2) ? 2 : qos_param->aifs[aci];
Larry Finger94a79942011-08-23 19:00:42 -05001623
Rashika Kheria1f5a0d02013-11-02 23:34:44 +05301624 qos_param->cw_min[aci] = cpu_to_le16(ac_params->ecw_min_max & 0x0F);
Larry Finger94a79942011-08-23 19:00:42 -05001625
Rashika Kheria1f5a0d02013-11-02 23:34:44 +05301626 qos_param->cw_max[aci] = cpu_to_le16((ac_params->ecw_min_max & 0xF0) >> 4);
Larry Finger94a79942011-08-23 19:00:42 -05001627
Larry Fingerdb8971b2011-08-25 11:48:25 -05001628 qos_param->flag[aci] =
1629 (ac_params->aci_aifsn & 0x10) ? 0x01 : 0x00;
Rashika Kheria1f5a0d02013-11-02 23:34:44 +05301630 qos_param->tx_op_limit[aci] = ac_params->tx_op_limit;
Larry Fingerdb8971b2011-08-25 11:48:25 -05001631 }
Peter Senna Tschudin4764ca92014-05-26 16:08:50 +02001632 return 0;
Larry Finger94a79942011-08-23 19:00:42 -05001633}
1634
Mateusz Kulikowski14b40d92015-04-01 00:24:37 +02001635/* we have a generic data element which it may contain QoS information or
Larry Finger94a79942011-08-23 19:00:42 -05001636 * parameters element. check the information element length to decide
1637 * which type to read
1638 */
1639static int rtllib_parse_qos_info_param_IE(struct rtllib_info_element
Larry Fingerdb8971b2011-08-25 11:48:25 -05001640 *info_element,
1641 struct rtllib_network *network)
Larry Finger94a79942011-08-23 19:00:42 -05001642{
Larry Fingerdb8971b2011-08-25 11:48:25 -05001643 int rc = 0;
1644 struct rtllib_qos_information_element qos_info_element;
Larry Finger94a79942011-08-23 19:00:42 -05001645
Larry Fingerdb8971b2011-08-25 11:48:25 -05001646 rc = rtllib_read_qos_info_element(&qos_info_element, info_element);
Larry Finger94a79942011-08-23 19:00:42 -05001647
Larry Fingerdb8971b2011-08-25 11:48:25 -05001648 if (rc == 0) {
1649 network->qos_data.param_count = qos_info_element.ac_info & 0x0F;
1650 network->flags |= NETWORK_HAS_QOS_INFORMATION;
1651 } else {
1652 struct rtllib_qos_parameter_info param_element;
Larry Finger94a79942011-08-23 19:00:42 -05001653
Larry Fingerdb8971b2011-08-25 11:48:25 -05001654 rc = rtllib_read_qos_param_element(&param_element,
1655 info_element);
1656 if (rc == 0) {
1657 rtllib_qos_convert_ac_to_parameters(&param_element,
1658 &(network->qos_data));
1659 network->flags |= NETWORK_HAS_QOS_PARAMETERS;
1660 network->qos_data.param_count =
1661 param_element.info_element.ac_info & 0x0F;
1662 }
1663 }
Larry Finger94a79942011-08-23 19:00:42 -05001664
Larry Fingerdb8971b2011-08-25 11:48:25 -05001665 if (rc == 0) {
1666 RTLLIB_DEBUG_QOS("QoS is supported\n");
1667 network->qos_data.supported = 1;
1668 }
1669 return rc;
Larry Finger94a79942011-08-23 19:00:42 -05001670}
1671
Larry Finger94a79942011-08-23 19:00:42 -05001672#define MFIE_STRING(x) case MFIE_TYPE_ ##x: return #x
1673
1674static const char *get_info_element_string(u16 id)
1675{
Larry Fingerdb8971b2011-08-25 11:48:25 -05001676 switch (id) {
1677 MFIE_STRING(SSID);
1678 MFIE_STRING(RATES);
1679 MFIE_STRING(FH_SET);
1680 MFIE_STRING(DS_SET);
1681 MFIE_STRING(CF_SET);
1682 MFIE_STRING(TIM);
1683 MFIE_STRING(IBSS_SET);
1684 MFIE_STRING(COUNTRY);
1685 MFIE_STRING(HOP_PARAMS);
1686 MFIE_STRING(HOP_TABLE);
1687 MFIE_STRING(REQUEST);
1688 MFIE_STRING(CHALLENGE);
1689 MFIE_STRING(POWER_CONSTRAINT);
1690 MFIE_STRING(POWER_CAPABILITY);
1691 MFIE_STRING(TPC_REQUEST);
1692 MFIE_STRING(TPC_REPORT);
1693 MFIE_STRING(SUPP_CHANNELS);
1694 MFIE_STRING(CSA);
1695 MFIE_STRING(MEASURE_REQUEST);
1696 MFIE_STRING(MEASURE_REPORT);
1697 MFIE_STRING(QUIET);
1698 MFIE_STRING(IBSS_DFS);
1699 MFIE_STRING(RSN);
1700 MFIE_STRING(RATES_EX);
1701 MFIE_STRING(GENERIC);
1702 MFIE_STRING(QOS_PARAMETER);
1703 default:
1704 return "UNKNOWN";
1705 }
Larry Finger94a79942011-08-23 19:00:42 -05001706}
Larry Finger94a79942011-08-23 19:00:42 -05001707
Larry Finger94a79942011-08-23 19:00:42 -05001708static inline void rtllib_extract_country_ie(
1709 struct rtllib_device *ieee,
1710 struct rtllib_info_element *info_element,
1711 struct rtllib_network *network,
Larry Fingerdb8971b2011-08-25 11:48:25 -05001712 u8 *addr2)
Larry Finger94a79942011-08-23 19:00:42 -05001713{
1714 if (IS_DOT11D_ENABLE(ieee)) {
Larry Fingerdb8971b2011-08-25 11:48:25 -05001715 if (info_element->len != 0) {
Larry Finger94a79942011-08-23 19:00:42 -05001716 memcpy(network->CountryIeBuf, info_element->data, info_element->len);
1717 network->CountryIeLen = info_element->len;
1718
Larry Fingerdb8971b2011-08-25 11:48:25 -05001719 if (!IS_COUNTRY_IE_VALID(ieee)) {
Valentina Manea4bb01422013-10-25 11:28:10 +03001720 if (rtllib_act_scanning(ieee, false) && ieee->FirstIe_InScan)
Mateusz Kulikowskid69d2052015-03-17 00:00:52 +01001721 netdev_info(ieee->dev,
1722 "Received beacon ContryIE, SSID: <%s>\n",
1723 network->ssid);
Larry Finger94a79942011-08-23 19:00:42 -05001724 Dot11d_UpdateCountryIe(ieee, addr2, info_element->len, info_element->data);
1725 }
1726 }
1727
Larry Fingerdb8971b2011-08-25 11:48:25 -05001728 if (IS_EQUAL_CIE_SRC(ieee, addr2))
Larry Finger94a79942011-08-23 19:00:42 -05001729 UPDATE_CIE_WATCHDOG(ieee);
Larry Finger94a79942011-08-23 19:00:42 -05001730 }
1731
1732}
Larry Finger94a79942011-08-23 19:00:42 -05001733
1734int rtllib_parse_info_param(struct rtllib_device *ieee,
1735 struct rtllib_info_element *info_element,
1736 u16 length,
1737 struct rtllib_network *network,
1738 struct rtllib_rx_stats *stats)
1739{
1740 u8 i;
1741 short offset;
Larry Fingerdb8971b2011-08-25 11:48:25 -05001742 u16 tmp_htcap_len = 0;
1743 u16 tmp_htinfo_len = 0;
1744 u16 ht_realtek_agg_len = 0;
Larry Finger94a79942011-08-23 19:00:42 -05001745 u8 ht_realtek_agg_buf[MAX_IE_LEN];
Larry Finger94a79942011-08-23 19:00:42 -05001746 char rates_str[64];
1747 char *p;
Larry Finger8cc638e2011-07-14 18:48:38 -05001748
Larry Finger94a79942011-08-23 19:00:42 -05001749 while (length >= sizeof(*info_element)) {
1750 if (sizeof(*info_element) + info_element->len > length) {
Jonathan Jin6d6163c2014-12-15 21:28:23 -06001751 RTLLIB_DEBUG_MGMT("Info elem: parse failed: info_element->len + 2 > left : info_element->len+2=%zd left=%d, id=%d.\n",
Larry Finger94a79942011-08-23 19:00:42 -05001752 info_element->len +
1753 sizeof(*info_element),
1754 length, info_element->id);
1755 /* We stop processing but don't return an error here
1756 * because some misbehaviour APs break this rule. ie.
Mateusz Kulikowski14b40d92015-04-01 00:24:37 +02001757 * Orinoco AP1000.
1758 */
Larry Finger94a79942011-08-23 19:00:42 -05001759 break;
1760 }
1761
1762 switch (info_element->id) {
1763 case MFIE_TYPE_SSID:
1764 if (rtllib_is_empty_essid(info_element->data,
1765 info_element->len)) {
1766 network->flags |= NETWORK_EMPTY_ESSID;
1767 break;
1768 }
1769
1770 network->ssid_len = min(info_element->len,
1771 (u8) IW_ESSID_MAX_SIZE);
1772 memcpy(network->ssid, info_element->data, network->ssid_len);
1773 if (network->ssid_len < IW_ESSID_MAX_SIZE)
1774 memset(network->ssid + network->ssid_len, 0,
1775 IW_ESSID_MAX_SIZE - network->ssid_len);
1776
1777 RTLLIB_DEBUG_MGMT("MFIE_TYPE_SSID: '%s' len=%d.\n",
1778 network->ssid, network->ssid_len);
1779 break;
1780
1781 case MFIE_TYPE_RATES:
Larry Finger94a79942011-08-23 19:00:42 -05001782 p = rates_str;
Larry Finger94a79942011-08-23 19:00:42 -05001783 network->rates_len = min(info_element->len,
1784 MAX_RATES_LENGTH);
1785 for (i = 0; i < network->rates_len; i++) {
1786 network->rates[i] = info_element->data[i];
Larry Finger94a79942011-08-23 19:00:42 -05001787 p += snprintf(p, sizeof(rates_str) -
1788 (p - rates_str), "%02X ",
1789 network->rates[i]);
Larry Finger94a79942011-08-23 19:00:42 -05001790 if (rtllib_is_ofdm_rate
1791 (info_element->data[i])) {
1792 network->flags |= NETWORK_HAS_OFDM;
1793 if (info_element->data[i] &
1794 RTLLIB_BASIC_RATE_MASK)
1795 network->flags &=
1796 ~NETWORK_HAS_CCK;
1797 }
1798
1799 if (rtllib_is_cck_rate
1800 (info_element->data[i])) {
1801 network->flags |= NETWORK_HAS_CCK;
1802 }
1803 }
1804
1805 RTLLIB_DEBUG_MGMT("MFIE_TYPE_RATES: '%s' (%d)\n",
1806 rates_str, network->rates_len);
1807 break;
1808
1809 case MFIE_TYPE_RATES_EX:
Larry Finger94a79942011-08-23 19:00:42 -05001810 p = rates_str;
Larry Finger94a79942011-08-23 19:00:42 -05001811 network->rates_ex_len = min(info_element->len,
1812 MAX_RATES_EX_LENGTH);
1813 for (i = 0; i < network->rates_ex_len; i++) {
1814 network->rates_ex[i] = info_element->data[i];
Larry Finger94a79942011-08-23 19:00:42 -05001815 p += snprintf(p, sizeof(rates_str) -
1816 (p - rates_str), "%02X ",
Dan Carpenter03e71d62013-05-29 09:57:36 +03001817 network->rates_ex[i]);
Larry Finger94a79942011-08-23 19:00:42 -05001818 if (rtllib_is_ofdm_rate
1819 (info_element->data[i])) {
1820 network->flags |= NETWORK_HAS_OFDM;
1821 if (info_element->data[i] &
1822 RTLLIB_BASIC_RATE_MASK)
1823 network->flags &=
1824 ~NETWORK_HAS_CCK;
1825 }
1826 }
1827
1828 RTLLIB_DEBUG_MGMT("MFIE_TYPE_RATES_EX: '%s' (%d)\n",
1829 rates_str, network->rates_ex_len);
1830 break;
1831
1832 case MFIE_TYPE_DS_SET:
1833 RTLLIB_DEBUG_MGMT("MFIE_TYPE_DS_SET: %d\n",
1834 info_element->data[0]);
1835 network->channel = info_element->data[0];
1836 break;
1837
1838 case MFIE_TYPE_FH_SET:
1839 RTLLIB_DEBUG_MGMT("MFIE_TYPE_FH_SET: ignored\n");
1840 break;
1841
1842 case MFIE_TYPE_CF_SET:
1843 RTLLIB_DEBUG_MGMT("MFIE_TYPE_CF_SET: ignored\n");
1844 break;
1845
1846 case MFIE_TYPE_TIM:
1847 if (info_element->len < 4)
1848 break;
1849
1850 network->tim.tim_count = info_element->data[0];
1851 network->tim.tim_period = info_element->data[1];
1852
Larry Fingerdb8971b2011-08-25 11:48:25 -05001853 network->dtim_period = info_element->data[1];
1854 if (ieee->state != RTLLIB_LINKED)
1855 break;
Larry Finger0dd56502011-08-25 11:48:12 -05001856 network->last_dtim_sta_time = jiffies;
Larry Finger94a79942011-08-23 19:00:42 -05001857
Larry Fingerdb8971b2011-08-25 11:48:25 -05001858 network->dtim_data = RTLLIB_DTIM_VALID;
Larry Finger94a79942011-08-23 19:00:42 -05001859
1860
Larry Fingerdb8971b2011-08-25 11:48:25 -05001861 if (info_element->data[2] & 1)
1862 network->dtim_data |= RTLLIB_DTIM_MBCAST;
Larry Finger94a79942011-08-23 19:00:42 -05001863
Larry Fingerdb8971b2011-08-25 11:48:25 -05001864 offset = (info_element->data[2] >> 1)*2;
Larry Finger94a79942011-08-23 19:00:42 -05001865
1866
Larry Fingerdb8971b2011-08-25 11:48:25 -05001867 if (ieee->assoc_id < 8*offset ||
1868 ieee->assoc_id > 8*(offset + info_element->len - 3))
1869 break;
Larry Finger94a79942011-08-23 19:00:42 -05001870
Larry Fingerdb8971b2011-08-25 11:48:25 -05001871 offset = (ieee->assoc_id / 8) - offset;
1872 if (info_element->data[3 + offset] &
1873 (1 << (ieee->assoc_id % 8)))
1874 network->dtim_data |= RTLLIB_DTIM_UCAST;
Larry Finger94a79942011-08-23 19:00:42 -05001875
1876 network->listen_interval = network->dtim_period;
1877 break;
1878
1879 case MFIE_TYPE_ERP:
1880 network->erp_value = info_element->data[0];
1881 network->flags |= NETWORK_HAS_ERP_VALUE;
1882 RTLLIB_DEBUG_MGMT("MFIE_TYPE_ERP_SET: %d\n",
1883 network->erp_value);
1884 break;
1885 case MFIE_TYPE_IBSS_SET:
1886 network->atim_window = info_element->data[0];
1887 RTLLIB_DEBUG_MGMT("MFIE_TYPE_IBSS_SET: %d\n",
1888 network->atim_window);
1889 break;
1890
1891 case MFIE_TYPE_CHALLENGE:
1892 RTLLIB_DEBUG_MGMT("MFIE_TYPE_CHALLENGE: ignored\n");
1893 break;
1894
1895 case MFIE_TYPE_GENERIC:
1896 RTLLIB_DEBUG_MGMT("MFIE_TYPE_GENERIC: %d bytes\n",
1897 info_element->len);
1898 if (!rtllib_parse_qos_info_param_IE(info_element,
1899 network))
1900 break;
1901 if (info_element->len >= 4 &&
1902 info_element->data[0] == 0x00 &&
1903 info_element->data[1] == 0x50 &&
1904 info_element->data[2] == 0xf2 &&
1905 info_element->data[3] == 0x01) {
1906 network->wpa_ie_len = min(info_element->len + 2,
1907 MAX_WPA_IE_LEN);
1908 memcpy(network->wpa_ie, info_element,
1909 network->wpa_ie_len);
1910 break;
1911 }
Larry Fingerdb8971b2011-08-25 11:48:25 -05001912 if (info_element->len == 7 &&
1913 info_element->data[0] == 0x00 &&
1914 info_element->data[1] == 0xe0 &&
1915 info_element->data[2] == 0x4c &&
1916 info_element->data[3] == 0x01 &&
1917 info_element->data[4] == 0x02)
1918 network->Turbo_Enable = 1;
Larry Finger94a79942011-08-23 19:00:42 -05001919
1920 if (tmp_htcap_len == 0) {
1921 if (info_element->len >= 4 &&
1922 info_element->data[0] == 0x00 &&
1923 info_element->data[1] == 0x90 &&
1924 info_element->data[2] == 0x4c &&
1925 info_element->data[3] == 0x033) {
1926
Mateusz Kulikowskifbb052f2015-04-13 23:47:30 +02001927 tmp_htcap_len = min_t(u8, info_element->len, MAX_IE_LEN);
1928 if (tmp_htcap_len != 0) {
1929 network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC;
1930 network->bssht.bdHTCapLen = min_t(u16, tmp_htcap_len, sizeof(network->bssht.bdHTCapBuf));
1931 memcpy(network->bssht.bdHTCapBuf, info_element->data, network->bssht.bdHTCapLen);
1932 }
Larry Finger94a79942011-08-23 19:00:42 -05001933 }
Larry Fingerdb8971b2011-08-25 11:48:25 -05001934 if (tmp_htcap_len != 0) {
Larry Finger94a79942011-08-23 19:00:42 -05001935 network->bssht.bdSupportHT = true;
Larry Fingere92b71d2011-07-18 20:34:19 -05001936 network->bssht.bdHT1R = ((((struct ht_capab_ele *)(network->bssht.bdHTCapBuf))->MCS[1]) == 0);
Larry Fingerdb8971b2011-08-25 11:48:25 -05001937 } else {
Larry Finger94a79942011-08-23 19:00:42 -05001938 network->bssht.bdSupportHT = false;
1939 network->bssht.bdHT1R = false;
1940 }
1941 }
1942
1943
Larry Fingerdb8971b2011-08-25 11:48:25 -05001944 if (tmp_htinfo_len == 0) {
Larry Finger94a79942011-08-23 19:00:42 -05001945 if (info_element->len >= 4 &&
Larry Fingerdb8971b2011-08-25 11:48:25 -05001946 info_element->data[0] == 0x00 &&
1947 info_element->data[1] == 0x90 &&
1948 info_element->data[2] == 0x4c &&
1949 info_element->data[3] == 0x034) {
Darshana Padmadasd009f0d2015-03-08 23:33:40 +05301950 tmp_htinfo_len = min_t(u8, info_element->len, MAX_IE_LEN);
Larry Fingerdb8971b2011-08-25 11:48:25 -05001951 if (tmp_htinfo_len != 0) {
1952 network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC;
Mateusz Kulikowskifbb052f2015-04-13 23:47:30 +02001953 network->bssht.bdHTInfoLen = min_t(u16, tmp_htinfo_len, sizeof(network->bssht.bdHTInfoBuf));
1954 memcpy(network->bssht.bdHTInfoBuf, info_element->data, network->bssht.bdHTInfoLen);
Larry Fingerdb8971b2011-08-25 11:48:25 -05001955 }
1956
Larry Finger94a79942011-08-23 19:00:42 -05001957 }
1958 }
1959
Larry Fingerdb8971b2011-08-25 11:48:25 -05001960 if (ieee->aggregation) {
1961 if (network->bssht.bdSupportHT) {
Larry Finger94a79942011-08-23 19:00:42 -05001962 if (info_element->len >= 4 &&
Larry Fingerdb8971b2011-08-25 11:48:25 -05001963 info_element->data[0] == 0x00 &&
1964 info_element->data[1] == 0xe0 &&
1965 info_element->data[2] == 0x4c &&
1966 info_element->data[3] == 0x02) {
Darshana Padmadasd009f0d2015-03-08 23:33:40 +05301967 ht_realtek_agg_len = min_t(u8, info_element->len, MAX_IE_LEN);
Larry Fingerdb8971b2011-08-25 11:48:25 -05001968 memcpy(ht_realtek_agg_buf, info_element->data, info_element->len);
Larry Finger94a79942011-08-23 19:00:42 -05001969 }
Larry Fingerdb8971b2011-08-25 11:48:25 -05001970 if (ht_realtek_agg_len >= 5) {
Larry Finger94a79942011-08-23 19:00:42 -05001971 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))
Larry Fingerdb8971b2011-08-25 11:48:25 -05001975 network->bssht.bdRT2RTLongSlotTime = true;
Larry Finger94a79942011-08-23 19:00:42 -05001976
Larry Fingerdb8971b2011-08-25 11:48:25 -05001977 if ((ht_realtek_agg_buf[4] == 1) && (ht_realtek_agg_buf[5] & RT_HT_CAP_USE_92SE))
Larry Finger94a79942011-08-23 19:00:42 -05001978 network->bssht.RT2RT_HT_Mode |= RT_HT_CAP_USE_92SE;
Larry Finger94a79942011-08-23 19:00:42 -05001979 }
1980 }
Larry Fingerdb8971b2011-08-25 11:48:25 -05001981 if (ht_realtek_agg_len >= 5) {
Larry Finger94a79942011-08-23 19:00:42 -05001982 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
Larry Fingerdb8971b2011-08-25 11:48:25 -05001987 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;
Larry Finger94a79942011-08-23 19:00:42 -05002000 }
2001 if (info_element->len >= 3 &&
Larry Fingerdb8971b2011-08-25 11:48:25 -05002002 info_element->data[0] == 0x00 &&
2003 info_element->data[1] == 0x0c &&
2004 info_element->data[2] == 0x43)
Larry Finger94a79942011-08-23 19:00:42 -05002005 network->ralink_cap_exist = true;
Larry Finger94a79942011-08-23 19:00:42 -05002006 if ((info_element->len >= 3 &&
Larry Fingerdb8971b2011-08-25 11:48:25 -05002007 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))
Larry Finger94a79942011-08-23 19:00:42 -05002014 network->atheros_cap_exist = true;
Larry Finger94a79942011-08-23 19:00:42 -05002015
2016 if ((info_element->len >= 3 &&
Larry Fingerdb8971b2011-08-25 11:48:25 -05002017 info_element->data[0] == 0x00 &&
2018 info_element->data[1] == 0x50 &&
2019 info_element->data[2] == 0x43))
2020 network->marvell_cap_exist = true;
Larry Finger94a79942011-08-23 19:00:42 -05002021 if (info_element->len >= 3 &&
Larry Fingerdb8971b2011-08-25 11:48:25 -05002022 info_element->data[0] == 0x00 &&
2023 info_element->data[1] == 0x40 &&
2024 info_element->data[2] == 0x96)
Larry Finger94a79942011-08-23 19:00:42 -05002025 network->cisco_cap_exist = true;
Larry Finger94a79942011-08-23 19:00:42 -05002026
2027
2028 if (info_element->len >= 3 &&
Larry Fingerdb8971b2011-08-25 11:48:25 -05002029 info_element->data[0] == 0x00 &&
2030 info_element->data[1] == 0x0a &&
2031 info_element->data[2] == 0xf5)
Larry Finger94a79942011-08-23 19:00:42 -05002032 network->airgo_cap_exist = true;
Larry Finger94a79942011-08-23 19:00:42 -05002033
2034 if (info_element->len > 4 &&
Larry Fingerdb8971b2011-08-25 11:48:25 -05002035 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) {
Larry Finger94a79942011-08-23 19:00:42 -05002040 memcpy(network->CcxRmState, &info_element[4], 2);
2041 if (network->CcxRmState[0] != 0)
Larry Finger94a79942011-08-23 19:00:42 -05002042 network->bCcxRmEnable = true;
Larry Finger94a79942011-08-23 19:00:42 -05002043 else
2044 network->bCcxRmEnable = false;
2045 network->MBssidMask = network->CcxRmState[1] & 0x07;
Larry Fingerdb8971b2011-08-25 11:48:25 -05002046 if (network->MBssidMask != 0) {
Larry Finger94a79942011-08-23 19:00:42 -05002047 network->bMBssidValid = true;
2048 network->MBssidMask = 0xff << (network->MBssidMask);
2049 memcpy(network->MBssid, network->bssid, ETH_ALEN);
2050 network->MBssid[5] &= network->MBssidMask;
Larry Fingerdb8971b2011-08-25 11:48:25 -05002051 } else {
Larry Finger94a79942011-08-23 19:00:42 -05002052 network->bMBssidValid = false;
2053 }
Larry Fingerdb8971b2011-08-25 11:48:25 -05002054 } else {
Larry Finger94a79942011-08-23 19:00:42 -05002055 network->bCcxRmEnable = false;
2056 }
2057 }
2058 if (info_element->len > 4 &&
Larry Fingerdb8971b2011-08-25 11:48:25 -05002059 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) {
Larry Finger94a79942011-08-23 19:00:42 -05002064 network->bWithCcxVerNum = true;
2065 network->BssCcxVerNumber = info_element->data[4];
Larry Fingerdb8971b2011-08-25 11:48:25 -05002066 } else {
Larry Finger94a79942011-08-23 19:00:42 -05002067 network->bWithCcxVerNum = false;
2068 network->BssCcxVerNumber = 0;
2069 }
2070 }
2071 if (info_element->len > 4 &&
Larry Fingerdb8971b2011-08-25 11:48:25 -05002072 info_element->data[0] == 0x00 &&
2073 info_element->data[1] == 0x50 &&
2074 info_element->data[2] == 0xf2 &&
2075 info_element->data[3] == 0x04) {
Larry Finger94a79942011-08-23 19:00:42 -05002076 RTLLIB_DEBUG_MGMT("MFIE_TYPE_WZC: %d bytes\n",
2077 info_element->len);
Larry Finger94a79942011-08-23 19:00:42 -05002078 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);
Larry Finger94a79942011-08-23 19:00:42 -05002082 }
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);
Darshana Padmadasd009f0d2015-03-08 23:33:40 +05302097 tmp_htcap_len = min_t(u8, info_element->len, MAX_IE_LEN);
Larry Fingerdb8971b2011-08-25 11:48:25 -05002098 if (tmp_htcap_len != 0) {
Larry Finger94a79942011-08-23 19:00:42 -05002099 network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC;
Larry Fingerdb8971b2011-08-25 11:48:25 -05002100 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);
Larry Finger94a79942011-08-23 19:00:42 -05002105
2106 network->bssht.bdSupportHT = true;
Larry Fingerdb8971b2011-08-25 11:48:25 -05002107 network->bssht.bdHT1R = ((((struct ht_capab_ele *)
2108 network->bssht.bdHTCapBuf))->MCS[1]) == 0;
Larry Finger94a79942011-08-23 19:00:42 -05002109
Larry Fingerdb8971b2011-08-25 11:48:25 -05002110 network->bssht.bdBandWidth = (enum ht_channel_width)
2111 (((struct ht_capab_ele *)
2112 (network->bssht.bdHTCapBuf))->ChlWidth);
2113 } else {
Larry Finger94a79942011-08-23 19:00:42 -05002114 network->bssht.bdSupportHT = false;
2115 network->bssht.bdHT1R = false;
Larry Fingerdb8971b2011-08-25 11:48:25 -05002116 network->bssht.bdBandWidth = HT_CHANNEL_WIDTH_20;
Larry Finger94a79942011-08-23 19:00:42 -05002117 }
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);
Darshana Padmadasd009f0d2015-03-08 23:33:40 +05302124 tmp_htinfo_len = min_t(u8, info_element->len, MAX_IE_LEN);
Larry Fingerdb8971b2011-08-25 11:48:25 -05002125 if (tmp_htinfo_len) {
Larry Finger94a79942011-08-23 19:00:42 -05002126 network->bssht.bdHTSpecVer = HT_SPEC_VER_IEEE;
Larry Fingerdb8971b2011-08-25 11:48:25 -05002127 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);
Larry Finger94a79942011-08-23 19:00:42 -05002134 }
2135 break;
2136
2137 case MFIE_TYPE_AIRONET:
2138 RTLLIB_DEBUG_SCAN("MFIE_TYPE_AIRONET: %d bytes\n",
2139 info_element->len);
Larry Fingerdb8971b2011-08-25 11:48:25 -05002140 if (info_element->len > IE_CISCO_FLAG_POSITION) {
Larry Finger94a79942011-08-23 19:00:42 -05002141 network->bWithAironetIE = true;
2142
Larry Fingerdb8971b2011-08-25 11:48:25 -05002143 if ((info_element->data[IE_CISCO_FLAG_POSITION]
2144 & SUPPORT_CKIP_MIC) ||
2145 (info_element->data[IE_CISCO_FLAG_POSITION]
2146 & SUPPORT_CKIP_PK))
Larry Finger94a79942011-08-23 19:00:42 -05002147 network->bCkipSupported = true;
Larry Finger94a79942011-08-23 19:00:42 -05002148 else
Larry Finger94a79942011-08-23 19:00:42 -05002149 network->bCkipSupported = false;
Larry Fingerdb8971b2011-08-25 11:48:25 -05002150 } else {
Larry Finger94a79942011-08-23 19:00:42 -05002151 network->bWithAironetIE = false;
2152 network->bCkipSupported = false;
2153 }
2154 break;
2155 case MFIE_TYPE_QOS_PARAMETER:
Mateusz Kulikowskid69d2052015-03-17 00:00:52 +01002156 netdev_err(ieee->dev,
2157 "QoS Error need to parse QOS_PARAMETER IE\n");
Larry Finger94a79942011-08-23 19:00:42 -05002158 break;
2159
Larry Finger94a79942011-08-23 19:00:42 -05002160 case MFIE_TYPE_COUNTRY:
2161 RTLLIB_DEBUG_SCAN("MFIE_TYPE_COUNTRY: %d bytes\n",
2162 info_element->len);
Larry Fingerdb8971b2011-08-25 11:48:25 -05002163 rtllib_extract_country_ie(ieee, info_element, network,
2164 network->bssid);
Larry Finger94a79942011-08-23 19:00:42 -05002165 break;
Larry Finger94a79942011-08-23 19:00:42 -05002166/* 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 &&
Larry Fingerdb8971b2011-08-25 11:48:25 -05002182 !network->cisco_cap_exist && !network->ralink_cap_exist &&
2183 !network->bssht.bdRT2RTAggregation)
Larry Finger94a79942011-08-23 19:00:42 -05002184 network->unknown_cap_exist = true;
Larry Finger94a79942011-08-23 19:00:42 -05002185 else
Larry Finger94a79942011-08-23 19:00:42 -05002186 network->unknown_cap_exist = false;
Larry Finger94a79942011-08-23 19:00:42 -05002187 return 0;
2188}
2189
Larry Finger49aab5f2011-08-25 14:07:05 -05002190static long rtllib_translate_todbm(u8 signal_strength_index)
Larry Finger94a79942011-08-23 19:00:42 -05002191{
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{
Larry Finger94a79942011-08-23 19:00:42 -05002206 memset(&network->qos_data, 0, sizeof(struct rtllib_qos_data));
2207
2208 /* Pull out fixed field data */
2209 memcpy(network->bssid, beacon->header.addr3, ETH_ALEN);
2210 network->capability = le16_to_cpu(beacon->capability);
2211 network->last_scanned = jiffies;
Rashika Kheriae0b1ca62013-11-02 23:37:04 +05302212 network->time_stamp[0] = beacon->time_stamp[0];
2213 network->time_stamp[1] = beacon->time_stamp[1];
2214 network->beacon_interval = le16_to_cpu(beacon->beacon_interval);
Larry Finger94a79942011-08-23 19:00:42 -05002215 /* Where to pull this? beacon->listen_interval;*/
2216 network->listen_interval = 0x0A;
2217 network->rates_len = network->rates_ex_len = 0;
2218 network->last_associate = 0;
2219 network->ssid_len = 0;
2220 network->hidden_ssid_len = 0;
2221 memset(network->hidden_ssid, 0, sizeof(network->hidden_ssid));
2222 network->flags = 0;
2223 network->atim_window = 0;
2224 network->erp_value = (network->capability & WLAN_CAPABILITY_IBSS) ?
Larry Fingerdb8971b2011-08-25 11:48:25 -05002225 0x3 : 0x0;
Larry Finger94a79942011-08-23 19:00:42 -05002226 network->berp_info_valid = false;
Larry Fingerdb8971b2011-08-25 11:48:25 -05002227 network->broadcom_cap_exist = false;
Larry Finger94a79942011-08-23 19:00:42 -05002228 network->ralink_cap_exist = false;
2229 network->atheros_cap_exist = false;
2230 network->cisco_cap_exist = false;
2231 network->unknown_cap_exist = false;
2232 network->realtek_cap_exit = false;
2233 network->marvell_cap_exist = false;
2234 network->airgo_cap_exist = false;
2235 network->Turbo_Enable = 0;
2236 network->SignalStrength = stats->SignalStrength;
2237 network->RSSI = stats->SignalStrength;
Larry Finger94a79942011-08-23 19:00:42 -05002238 network->CountryIeLen = 0;
2239 memset(network->CountryIeBuf, 0, MAX_IE_LEN);
Larry Finger94a79942011-08-23 19:00:42 -05002240 HTInitializeBssDesc(&network->bssht);
2241 if (stats->freq == RTLLIB_52GHZ_BAND) {
2242 /* for A band (No DS info) */
2243 network->channel = stats->received_channel;
2244 } else
2245 network->flags |= NETWORK_HAS_CCK;
2246
2247 network->wpa_ie_len = 0;
2248 network->rsn_ie_len = 0;
Larry Finger94a79942011-08-23 19:00:42 -05002249 network->wzc_ie_len = 0;
Larry Finger94a79942011-08-23 19:00:42 -05002250
Larry Fingerdb8971b2011-08-25 11:48:25 -05002251 if (rtllib_parse_info_param(ieee,
Larry Finger94a79942011-08-23 19:00:42 -05002252 beacon->info_element,
2253 (stats->len - sizeof(*beacon)),
2254 network,
2255 stats))
Larry Fingerdb8971b2011-08-25 11:48:25 -05002256 return 1;
Larry Finger94a79942011-08-23 19:00:42 -05002257
2258 network->mode = 0;
2259 if (stats->freq == RTLLIB_52GHZ_BAND)
2260 network->mode = IEEE_A;
2261 else {
2262 if (network->flags & NETWORK_HAS_OFDM)
2263 network->mode |= IEEE_G;
2264 if (network->flags & NETWORK_HAS_CCK)
2265 network->mode |= IEEE_B;
2266 }
2267
2268 if (network->mode == 0) {
Jonathan Jin6d6163c2014-12-15 21:28:23 -06002269 RTLLIB_DEBUG_SCAN("Filtered out '%s (%pM)' network.\n",
Larry Finger94a79942011-08-23 19:00:42 -05002270 escape_essid(network->ssid,
2271 network->ssid_len),
Larry Fingerac50dda2011-08-25 14:07:03 -05002272 network->bssid);
Larry Finger94a79942011-08-23 19:00:42 -05002273 return 1;
2274 }
2275
Larry Fingerdb8971b2011-08-25 11:48:25 -05002276 if (network->bssht.bdSupportHT) {
Larry Finger94a79942011-08-23 19:00:42 -05002277 if (network->mode == IEEE_A)
2278 network->mode = IEEE_N_5G;
2279 else if (network->mode & (IEEE_G | IEEE_B))
2280 network->mode = IEEE_N_24G;
2281 }
2282 if (rtllib_is_empty_essid(network->ssid, network->ssid_len))
2283 network->flags |= NETWORK_EMPTY_ESSID;
2284 stats->signal = 30 + (stats->SignalStrength * 70) / 100;
Larry Fingerdb8971b2011-08-25 11:48:25 -05002285 stats->noise = rtllib_translate_todbm((u8)(100-stats->signal)) - 25;
Larry Finger94a79942011-08-23 19:00:42 -05002286
2287 memcpy(&network->stats, stats, sizeof(network->stats));
2288
2289 return 0;
2290}
2291
2292static inline int is_same_network(struct rtllib_network *src,
2293 struct rtllib_network *dst, u8 ssidbroad)
2294{
2295 /* A network is only a duplicate if the channel, BSSID, ESSID
2296 * and the capability field (in particular IBSS and BSS) all match.
2297 * We treat all <hidden> with the same BSSID and channel
Mateusz Kulikowski14b40d92015-04-01 00:24:37 +02002298 * as one network
2299 */
Larry Fingerdb8971b2011-08-25 11:48:25 -05002300 return (((src->ssid_len == dst->ssid_len) || (!ssidbroad)) &&
Larry Finger94a79942011-08-23 19:00:42 -05002301 (src->channel == dst->channel) &&
2302 !memcmp(src->bssid, dst->bssid, ETH_ALEN) &&
Larry Fingerdb8971b2011-08-25 11:48:25 -05002303 (!memcmp(src->ssid, dst->ssid, src->ssid_len) ||
2304 (!ssidbroad)) &&
Larry Finger94a79942011-08-23 19:00:42 -05002305 ((src->capability & WLAN_CAPABILITY_IBSS) ==
2306 (dst->capability & WLAN_CAPABILITY_IBSS)) &&
2307 ((src->capability & WLAN_CAPABILITY_ESS) ==
2308 (dst->capability & WLAN_CAPABILITY_ESS)));
2309}
2310
Larry Finger94a79942011-08-23 19:00:42 -05002311
2312static inline void update_network(struct rtllib_network *dst,
2313 struct rtllib_network *src)
2314{
2315 int qos_active;
2316 u8 old_param;
2317
2318 memcpy(&dst->stats, &src->stats, sizeof(struct rtllib_rx_stats));
2319 dst->capability = src->capability;
2320 memcpy(dst->rates, src->rates, src->rates_len);
2321 dst->rates_len = src->rates_len;
2322 memcpy(dst->rates_ex, src->rates_ex, src->rates_ex_len);
2323 dst->rates_ex_len = src->rates_ex_len;
Larry Fingerdb8971b2011-08-25 11:48:25 -05002324 if (src->ssid_len > 0) {
2325 if (dst->ssid_len == 0) {
Larry Finger94a79942011-08-23 19:00:42 -05002326 memset(dst->hidden_ssid, 0, sizeof(dst->hidden_ssid));
2327 dst->hidden_ssid_len = src->ssid_len;
2328 memcpy(dst->hidden_ssid, src->ssid, src->ssid_len);
Larry Fingerdb8971b2011-08-25 11:48:25 -05002329 } else {
Larry Finger94a79942011-08-23 19:00:42 -05002330 memset(dst->ssid, 0, dst->ssid_len);
2331 dst->ssid_len = src->ssid_len;
2332 memcpy(dst->ssid, src->ssid, src->ssid_len);
2333 }
2334 }
2335 dst->mode = src->mode;
2336 dst->flags = src->flags;
2337 dst->time_stamp[0] = src->time_stamp[0];
2338 dst->time_stamp[1] = src->time_stamp[1];
Larry Fingerdb8971b2011-08-25 11:48:25 -05002339 if (src->flags & NETWORK_HAS_ERP_VALUE) {
Larry Finger94a79942011-08-23 19:00:42 -05002340 dst->erp_value = src->erp_value;
2341 dst->berp_info_valid = src->berp_info_valid = true;
2342 }
2343 dst->beacon_interval = src->beacon_interval;
2344 dst->listen_interval = src->listen_interval;
2345 dst->atim_window = src->atim_window;
2346 dst->dtim_period = src->dtim_period;
2347 dst->dtim_data = src->dtim_data;
Larry Finger0dd56502011-08-25 11:48:12 -05002348 dst->last_dtim_sta_time = src->last_dtim_sta_time;
Larry Finger94a79942011-08-23 19:00:42 -05002349 memcpy(&dst->tim, &src->tim, sizeof(struct rtllib_tim_parameters));
2350
Larry Fingerdb8971b2011-08-25 11:48:25 -05002351 dst->bssht.bdSupportHT = src->bssht.bdSupportHT;
Larry Finger94a79942011-08-23 19:00:42 -05002352 dst->bssht.bdRT2RTAggregation = src->bssht.bdRT2RTAggregation;
Larry Fingerdb8971b2011-08-25 11:48:25 -05002353 dst->bssht.bdHTCapLen = src->bssht.bdHTCapLen;
2354 memcpy(dst->bssht.bdHTCapBuf, src->bssht.bdHTCapBuf,
2355 src->bssht.bdHTCapLen);
2356 dst->bssht.bdHTInfoLen = src->bssht.bdHTInfoLen;
2357 memcpy(dst->bssht.bdHTInfoBuf, src->bssht.bdHTInfoBuf,
2358 src->bssht.bdHTInfoLen);
Larry Finger94a79942011-08-23 19:00:42 -05002359 dst->bssht.bdHTSpecVer = src->bssht.bdHTSpecVer;
2360 dst->bssht.bdRT2RTLongSlotTime = src->bssht.bdRT2RTLongSlotTime;
2361 dst->broadcom_cap_exist = src->broadcom_cap_exist;
2362 dst->ralink_cap_exist = src->ralink_cap_exist;
2363 dst->atheros_cap_exist = src->atheros_cap_exist;
2364 dst->realtek_cap_exit = src->realtek_cap_exit;
2365 dst->marvell_cap_exist = src->marvell_cap_exist;
2366 dst->cisco_cap_exist = src->cisco_cap_exist;
2367 dst->airgo_cap_exist = src->airgo_cap_exist;
2368 dst->unknown_cap_exist = src->unknown_cap_exist;
2369 memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len);
2370 dst->wpa_ie_len = src->wpa_ie_len;
2371 memcpy(dst->rsn_ie, src->rsn_ie, src->rsn_ie_len);
2372 dst->rsn_ie_len = src->rsn_ie_len;
Larry Finger94a79942011-08-23 19:00:42 -05002373 memcpy(dst->wzc_ie, src->wzc_ie, src->wzc_ie_len);
2374 dst->wzc_ie_len = src->wzc_ie_len;
Larry Finger94a79942011-08-23 19:00:42 -05002375
2376 dst->last_scanned = jiffies;
2377 /* qos related parameters */
2378 qos_active = dst->qos_data.active;
2379 old_param = dst->qos_data.param_count;
2380 dst->qos_data.supported = src->qos_data.supported;
2381 if (dst->flags & NETWORK_HAS_QOS_PARAMETERS)
Larry Fingerdb8971b2011-08-25 11:48:25 -05002382 memcpy(&dst->qos_data, &src->qos_data,
2383 sizeof(struct rtllib_qos_data));
Larry Finger94a79942011-08-23 19:00:42 -05002384 if (dst->qos_data.supported == 1) {
2385 if (dst->ssid_len)
2386 RTLLIB_DEBUG_QOS
2387 ("QoS the network %s is QoS supported\n",
2388 dst->ssid);
2389 else
2390 RTLLIB_DEBUG_QOS
2391 ("QoS the network is QoS supported\n");
2392 }
2393 dst->qos_data.active = qos_active;
2394 dst->qos_data.old_param_count = old_param;
2395
2396 /* dst->last_associate is not overwritten */
2397 dst->wmm_info = src->wmm_info;
Larry Fingerdb8971b2011-08-25 11:48:25 -05002398 if (src->wmm_param[0].ac_aci_acm_aifsn ||
2399 src->wmm_param[1].ac_aci_acm_aifsn ||
2400 src->wmm_param[2].ac_aci_acm_aifsn ||
Julia Lawalla2f9dc52012-01-12 22:49:27 +01002401 src->wmm_param[3].ac_aci_acm_aifsn)
Larry Fingerdb8971b2011-08-25 11:48:25 -05002402 memcpy(dst->wmm_param, src->wmm_param, WME_AC_PRAM_LEN);
Larry Finger94a79942011-08-23 19:00:42 -05002403
2404 dst->SignalStrength = src->SignalStrength;
2405 dst->RSSI = src->RSSI;
2406 dst->Turbo_Enable = src->Turbo_Enable;
2407
Larry Finger94a79942011-08-23 19:00:42 -05002408 dst->CountryIeLen = src->CountryIeLen;
2409 memcpy(dst->CountryIeBuf, src->CountryIeBuf, src->CountryIeLen);
Larry Finger94a79942011-08-23 19:00:42 -05002410
2411 dst->bWithAironetIE = src->bWithAironetIE;
2412 dst->bCkipSupported = src->bCkipSupported;
Larry Fingerdb8971b2011-08-25 11:48:25 -05002413 memcpy(dst->CcxRmState, src->CcxRmState, 2);
Larry Finger94a79942011-08-23 19:00:42 -05002414 dst->bCcxRmEnable = src->bCcxRmEnable;
2415 dst->MBssidMask = src->MBssidMask;
2416 dst->bMBssidValid = src->bMBssidValid;
Larry Fingerdb8971b2011-08-25 11:48:25 -05002417 memcpy(dst->MBssid, src->MBssid, 6);
Larry Finger94a79942011-08-23 19:00:42 -05002418 dst->bWithCcxVerNum = src->bWithCcxVerNum;
2419 dst->BssCcxVerNumber = src->BssCcxVerNumber;
Larry Finger94a79942011-08-23 19:00:42 -05002420}
Larry Fingerdb8971b2011-08-25 11:48:25 -05002421
Larry Finger94a79942011-08-23 19:00:42 -05002422static inline int is_beacon(__le16 fc)
2423{
2424 return (WLAN_FC_GET_STYPE(le16_to_cpu(fc)) == RTLLIB_STYPE_BEACON);
2425}
2426
Larry Fingerdb8971b2011-08-25 11:48:25 -05002427static int IsPassiveChannel(struct rtllib_device *rtllib, u8 channel)
Larry Finger94a79942011-08-23 19:00:42 -05002428{
2429 if (MAX_CHANNEL_NUMBER < channel) {
Mateusz Kulikowskid69d2052015-03-17 00:00:52 +01002430 netdev_info(rtllib->dev, "%s(): Invalid Channel\n", __func__);
Larry Finger94a79942011-08-23 19:00:42 -05002431 return 0;
2432 }
2433
2434 if (rtllib->active_channel_map[channel] == 2)
2435 return 1;
2436
2437 return 0;
2438}
2439
Sean MacLennan976d5342011-11-30 15:18:52 -05002440int rtllib_legal_channel(struct rtllib_device *rtllib, u8 channel)
Larry Finger94a79942011-08-23 19:00:42 -05002441{
2442 if (MAX_CHANNEL_NUMBER < channel) {
Mateusz Kulikowskid69d2052015-03-17 00:00:52 +01002443 netdev_info(rtllib->dev, "%s(): Invalid Channel\n", __func__);
Larry Finger94a79942011-08-23 19:00:42 -05002444 return 0;
2445 }
2446 if (rtllib->active_channel_map[channel] > 0)
2447 return 1;
2448
2449 return 0;
2450}
Sean MacLennan976d5342011-11-30 15:18:52 -05002451EXPORT_SYMBOL(rtllib_legal_channel);
Larry Finger94a79942011-08-23 19:00:42 -05002452
Larry Finger94a79942011-08-23 19:00:42 -05002453static inline void rtllib_process_probe_response(
2454 struct rtllib_device *ieee,
2455 struct rtllib_probe_response *beacon,
2456 struct rtllib_rx_stats *stats)
2457{
2458 struct rtllib_network *target;
2459 struct rtllib_network *oldest = NULL;
Larry Finger94a79942011-08-23 19:00:42 -05002460 struct rtllib_info_element *info_element = &beacon->info_element[0];
Larry Finger94a79942011-08-23 19:00:42 -05002461 unsigned long flags;
2462 short renew;
Larry Fingerdb8971b2011-08-25 11:48:25 -05002463 struct rtllib_network *network = kzalloc(sizeof(struct rtllib_network),
2464 GFP_ATOMIC);
Larry Finger94a79942011-08-23 19:00:42 -05002465
Mike McCormackcb762152011-07-11 08:56:20 +09002466 if (!network)
Larry Finger94a79942011-08-23 19:00:42 -05002467 return;
Larry Finger94a79942011-08-23 19:00:42 -05002468
2469 RTLLIB_DEBUG_SCAN(
Larry Fingerac50dda2011-08-25 14:07:03 -05002470 "'%s' ( %pM ): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
Larry Finger94a79942011-08-23 19:00:42 -05002471 escape_essid(info_element->data, info_element->len),
Larry Fingerac50dda2011-08-25 14:07:03 -05002472 beacon->header.addr3,
Rashika Kheria26a6b072013-11-02 23:36:12 +05302473 (le16_to_cpu(beacon->capability) & (1<<0xf)) ? '1' : '0',
2474 (le16_to_cpu(beacon->capability) & (1<<0xe)) ? '1' : '0',
2475 (le16_to_cpu(beacon->capability) & (1<<0xd)) ? '1' : '0',
2476 (le16_to_cpu(beacon->capability) & (1<<0xc)) ? '1' : '0',
2477 (le16_to_cpu(beacon->capability) & (1<<0xb)) ? '1' : '0',
2478 (le16_to_cpu(beacon->capability) & (1<<0xa)) ? '1' : '0',
2479 (le16_to_cpu(beacon->capability) & (1<<0x9)) ? '1' : '0',
2480 (le16_to_cpu(beacon->capability) & (1<<0x8)) ? '1' : '0',
2481 (le16_to_cpu(beacon->capability) & (1<<0x7)) ? '1' : '0',
2482 (le16_to_cpu(beacon->capability) & (1<<0x6)) ? '1' : '0',
2483 (le16_to_cpu(beacon->capability) & (1<<0x5)) ? '1' : '0',
2484 (le16_to_cpu(beacon->capability) & (1<<0x4)) ? '1' : '0',
2485 (le16_to_cpu(beacon->capability) & (1<<0x3)) ? '1' : '0',
2486 (le16_to_cpu(beacon->capability) & (1<<0x2)) ? '1' : '0',
2487 (le16_to_cpu(beacon->capability) & (1<<0x1)) ? '1' : '0',
2488 (le16_to_cpu(beacon->capability) & (1<<0x0)) ? '1' : '0');
Larry Finger94a79942011-08-23 19:00:42 -05002489
2490 if (rtllib_network_init(ieee, beacon, network, stats)) {
Larry Fingerac50dda2011-08-25 14:07:03 -05002491 RTLLIB_DEBUG_SCAN("Dropped '%s' ( %pM) via %s.\n",
Larry Fingerdb8971b2011-08-25 11:48:25 -05002492 escape_essid(info_element->data,
2493 info_element->len),
Larry Fingerac50dda2011-08-25 14:07:03 -05002494 beacon->header.addr3,
Rashika Kheria26a6b072013-11-02 23:36:12 +05302495 WLAN_FC_GET_STYPE(
2496 le16_to_cpu(beacon->header.frame_ctl)) ==
Larry Fingerdb8971b2011-08-25 11:48:25 -05002497 RTLLIB_STYPE_PROBE_RESP ?
2498 "PROBE RESPONSE" : "BEACON");
Larry Finger94a79942011-08-23 19:00:42 -05002499 goto free_network;
2500 }
2501
2502
Sean MacLennan976d5342011-11-30 15:18:52 -05002503 if (!rtllib_legal_channel(ieee, network->channel))
Larry Finger94a79942011-08-23 19:00:42 -05002504 goto free_network;
2505
Rashika Kheria26a6b072013-11-02 23:36:12 +05302506 if (WLAN_FC_GET_STYPE(le16_to_cpu(beacon->header.frame_ctl)) ==
Larry Fingerdb8971b2011-08-25 11:48:25 -05002507 RTLLIB_STYPE_PROBE_RESP) {
Larry Finger94a79942011-08-23 19:00:42 -05002508 if (IsPassiveChannel(ieee, network->channel)) {
Mateusz Kulikowskid69d2052015-03-17 00:00:52 +01002509 netdev_info(ieee->dev,
2510 "GetScanInfo(): For Global Domain, filter probe response at channel(%d).\n",
2511 network->channel);
Larry Finger94a79942011-08-23 19:00:42 -05002512 goto free_network;
2513 }
2514 }
2515
2516 /* The network parsed correctly -- so now we scan our known networks
2517 * to see if we can find it in our list.
2518 *
2519 * NOTE: This search is definitely not optimized. Once its doing
Larry Fingerdb8971b2011-08-25 11:48:25 -05002520 * the "right thing" we'll optimize it for efficiency if
Mateusz Kulikowski14b40d92015-04-01 00:24:37 +02002521 * necessary
2522 */
Larry Finger94a79942011-08-23 19:00:42 -05002523
2524 /* Search for this entry in the list and update it if it is
Mateusz Kulikowski14b40d92015-04-01 00:24:37 +02002525 * already there.
2526 */
Larry Finger94a79942011-08-23 19:00:42 -05002527
2528 spin_lock_irqsave(&ieee->lock, flags);
Larry Fingerdb8971b2011-08-25 11:48:25 -05002529 if (is_same_network(&ieee->current_network, network,
2530 (network->ssid_len ? 1 : 0))) {
2531 update_network(&ieee->current_network, network);
2532 if ((ieee->current_network.mode == IEEE_N_24G ||
2533 ieee->current_network.mode == IEEE_G)
2534 && ieee->current_network.berp_info_valid) {
2535 if (ieee->current_network.erp_value & ERP_UseProtection)
Larry Finger94a79942011-08-23 19:00:42 -05002536 ieee->current_network.buseprotection = true;
Larry Fingerdb8971b2011-08-25 11:48:25 -05002537 else
2538 ieee->current_network.buseprotection = false;
Larry Finger94a79942011-08-23 19:00:42 -05002539 }
Larry Fingerdb8971b2011-08-25 11:48:25 -05002540 if (is_beacon(beacon->header.frame_ctl)) {
2541 if (ieee->state >= RTLLIB_LINKED)
2542 ieee->LinkDetectInfo.NumRecvBcnInPeriod++;
Larry Finger94a79942011-08-23 19:00:42 -05002543 }
2544 }
Larry Finger94a79942011-08-23 19:00:42 -05002545 list_for_each_entry(target, &ieee->network_list, list) {
Larry Fingerdb8971b2011-08-25 11:48:25 -05002546 if (is_same_network(target, network,
2547 (target->ssid_len ? 1 : 0)))
Larry Finger94a79942011-08-23 19:00:42 -05002548 break;
2549 if ((oldest == NULL) ||
2550 (target->last_scanned < oldest->last_scanned))
2551 oldest = target;
2552 }
2553
2554 /* If we didn't find a match, then get a new network slot to initialize
Mateusz Kulikowski14b40d92015-04-01 00:24:37 +02002555 * with this beacon's information
2556 */
Larry Finger94a79942011-08-23 19:00:42 -05002557 if (&target->list == &ieee->network_list) {
2558 if (list_empty(&ieee->network_free_list)) {
2559 /* If there are no more slots, expire the oldest */
2560 list_del(&oldest->list);
2561 target = oldest;
Jonathan Jin6d6163c2014-12-15 21:28:23 -06002562 RTLLIB_DEBUG_SCAN("Expired '%s' ( %pM) from network list.\n",
Larry Finger94a79942011-08-23 19:00:42 -05002563 escape_essid(target->ssid,
2564 target->ssid_len),
Larry Fingerac50dda2011-08-25 14:07:03 -05002565 target->bssid);
Larry Finger94a79942011-08-23 19:00:42 -05002566 } else {
2567 /* Otherwise just pull from the free list */
2568 target = list_entry(ieee->network_free_list.next,
2569 struct rtllib_network, list);
2570 list_del(ieee->network_free_list.next);
2571 }
2572
2573
Larry Fingerac50dda2011-08-25 14:07:03 -05002574 RTLLIB_DEBUG_SCAN("Adding '%s' ( %pM) via %s.\n",
Larry Fingerdb8971b2011-08-25 11:48:25 -05002575 escape_essid(network->ssid,
Larry Fingerac50dda2011-08-25 14:07:03 -05002576 network->ssid_len), network->bssid,
Rashika Kheria26a6b072013-11-02 23:36:12 +05302577 WLAN_FC_GET_STYPE(
2578 le16_to_cpu(beacon->header.frame_ctl)) ==
Larry Fingerdb8971b2011-08-25 11:48:25 -05002579 RTLLIB_STYPE_PROBE_RESP ?
2580 "PROBE RESPONSE" : "BEACON");
Larry Finger94a79942011-08-23 19:00:42 -05002581 memcpy(target, network, sizeof(*target));
2582 list_add_tail(&target->list, &ieee->network_list);
2583 if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE)
2584 rtllib_softmac_new_net(ieee, network);
2585 } else {
Larry Fingerac50dda2011-08-25 14:07:03 -05002586 RTLLIB_DEBUG_SCAN("Updating '%s' ( %pM) via %s.\n",
Larry Fingerdb8971b2011-08-25 11:48:25 -05002587 escape_essid(target->ssid,
Larry Fingerac50dda2011-08-25 14:07:03 -05002588 target->ssid_len), target->bssid,
Rashika Kheria26a6b072013-11-02 23:36:12 +05302589 WLAN_FC_GET_STYPE(
2590 le16_to_cpu(beacon->header.frame_ctl)) ==
Larry Fingerdb8971b2011-08-25 11:48:25 -05002591 RTLLIB_STYPE_PROBE_RESP ?
2592 "PROBE RESPONSE" : "BEACON");
Larry Finger94a79942011-08-23 19:00:42 -05002593
Larry Fingerdb8971b2011-08-25 11:48:25 -05002594 /* we have an entry and we are going to update it. But this
2595 * entry may be already expired. In this case we do the same
2596 * as we found a new net and call the new_net handler
Larry Finger94a79942011-08-23 19:00:42 -05002597 */
Larry Fingerdb8971b2011-08-25 11:48:25 -05002598 renew = !time_after(target->last_scanned + ieee->scan_age,
2599 jiffies);
Larry Finger94a79942011-08-23 19:00:42 -05002600 if ((!target->ssid_len) &&
Larry Fingerdb8971b2011-08-25 11:48:25 -05002601 (((network->ssid_len > 0) && (target->hidden_ssid_len == 0))
2602 || ((ieee->current_network.ssid_len == network->ssid_len) &&
2603 (strncmp(ieee->current_network.ssid, network->ssid,
2604 network->ssid_len) == 0) &&
2605 (ieee->state == RTLLIB_NOLINK))))
Larry Finger94a79942011-08-23 19:00:42 -05002606 renew = 1;
Larry Finger94a79942011-08-23 19:00:42 -05002607 update_network(target, network);
2608 if (renew && (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE))
2609 rtllib_softmac_new_net(ieee, network);
2610 }
2611
2612 spin_unlock_irqrestore(&ieee->lock, flags);
Larry Fingerdb8971b2011-08-25 11:48:25 -05002613 if (is_beacon(beacon->header.frame_ctl) &&
2614 is_same_network(&ieee->current_network, network,
2615 (network->ssid_len ? 1 : 0)) &&
2616 (ieee->state == RTLLIB_LINKED)) {
2617 if (ieee->handle_beacon != NULL)
2618 ieee->handle_beacon(ieee->dev, beacon,
2619 &ieee->current_network);
Larry Finger94a79942011-08-23 19:00:42 -05002620 }
2621free_network:
2622 kfree(network);
Larry Finger94a79942011-08-23 19:00:42 -05002623}
2624
2625void rtllib_rx_mgt(struct rtllib_device *ieee,
Larry Fingerdb8971b2011-08-25 11:48:25 -05002626 struct sk_buff *skb,
Larry Finger94a79942011-08-23 19:00:42 -05002627 struct rtllib_rx_stats *stats)
2628{
Athira Lekshmi73df9982014-11-28 18:26:13 +05302629 struct rtllib_hdr_4addr *header = (struct rtllib_hdr_4addr *)skb->data;
Larry Finger94a79942011-08-23 19:00:42 -05002630
Rashika Kheria26a6b072013-11-02 23:36:12 +05302631 if ((WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl)) !=
2632 RTLLIB_STYPE_PROBE_RESP) &&
2633 (WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl)) !=
2634 RTLLIB_STYPE_BEACON))
Larry Fingerdb8971b2011-08-25 11:48:25 -05002635 ieee->last_rx_ps_time = jiffies;
Larry Finger94a79942011-08-23 19:00:42 -05002636
Rashika Kheria26a6b072013-11-02 23:36:12 +05302637 switch (WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl))) {
Larry Finger94a79942011-08-23 19:00:42 -05002638
Larry Fingerdb8971b2011-08-25 11:48:25 -05002639 case RTLLIB_STYPE_BEACON:
2640 RTLLIB_DEBUG_MGMT("received BEACON (%d)\n",
Rashika Kheria26a6b072013-11-02 23:36:12 +05302641 WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl)));
Larry Fingerdb8971b2011-08-25 11:48:25 -05002642 RTLLIB_DEBUG_SCAN("Beacon\n");
2643 rtllib_process_probe_response(
2644 ieee, (struct rtllib_probe_response *)header,
2645 stats);
Larry Finger94a79942011-08-23 19:00:42 -05002646
Larry Fingerdb8971b2011-08-25 11:48:25 -05002647 if (ieee->sta_sleep || (ieee->ps != RTLLIB_PS_DISABLED &&
2648 ieee->iw_mode == IW_MODE_INFRA &&
2649 ieee->state == RTLLIB_LINKED))
2650 tasklet_schedule(&ieee->ps_task);
Larry Finger94a79942011-08-23 19:00:42 -05002651
Larry Fingerdb8971b2011-08-25 11:48:25 -05002652 break;
Larry Finger94a79942011-08-23 19:00:42 -05002653
Larry Fingerdb8971b2011-08-25 11:48:25 -05002654 case RTLLIB_STYPE_PROBE_RESP:
2655 RTLLIB_DEBUG_MGMT("received PROBE RESPONSE (%d)\n",
Rashika Kheria26a6b072013-11-02 23:36:12 +05302656 WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl)));
Larry Fingerdb8971b2011-08-25 11:48:25 -05002657 RTLLIB_DEBUG_SCAN("Probe response\n");
2658 rtllib_process_probe_response(ieee,
2659 (struct rtllib_probe_response *)header, stats);
2660 break;
2661 case RTLLIB_STYPE_PROBE_REQ:
2662 RTLLIB_DEBUG_MGMT("received PROBE RESQUEST (%d)\n",
Rashika Kheria26a6b072013-11-02 23:36:12 +05302663 WLAN_FC_GET_STYPE(
2664 le16_to_cpu(header->frame_ctl)));
Larry Fingerdb8971b2011-08-25 11:48:25 -05002665 RTLLIB_DEBUG_SCAN("Probe request\n");
2666 if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) &&
2667 ((ieee->iw_mode == IW_MODE_ADHOC ||
2668 ieee->iw_mode == IW_MODE_MASTER) &&
2669 ieee->state == RTLLIB_LINKED))
2670 rtllib_rx_probe_rq(ieee, skb);
2671 break;
2672 }
Larry Finger94a79942011-08-23 19:00:42 -05002673}