1
2
3
4
5
6
7
8
9
10
11
12
13
14#include "ieee80211.h"
15
16#include <linux/random.h>
17#include <linux/delay.h>
18#include <linux/slab.h>
19#include <linux/uaccess.h>
20#include <linux/etherdevice.h>
21
22#include "dot11d.h"
23
24short ieee80211_is_54g(const struct ieee80211_network *net)
25{
26 return (net->rates_ex_len > 0) || (net->rates_len > 4);
27}
28EXPORT_SYMBOL(ieee80211_is_54g);
29
30short ieee80211_is_shortslot(const struct ieee80211_network *net)
31{
32 return net->capability & WLAN_CAPABILITY_SHORT_SLOT;
33}
34EXPORT_SYMBOL(ieee80211_is_shortslot);
35
36
37
38
39
40static unsigned int ieee80211_MFIE_rate_len(struct ieee80211_device *ieee)
41{
42 unsigned int rate_len = 0;
43
44 if (ieee->modulation & IEEE80211_CCK_MODULATION)
45 rate_len = IEEE80211_CCK_RATE_LEN + 2;
46
47 if (ieee->modulation & IEEE80211_OFDM_MODULATION)
48 rate_len += IEEE80211_OFDM_RATE_LEN + 2;
49
50 return rate_len;
51}
52
53
54
55
56
57static void ieee80211_MFIE_Brate(struct ieee80211_device *ieee, u8 **tag_p)
58{
59 u8 *tag = *tag_p;
60
61 if (ieee->modulation & IEEE80211_CCK_MODULATION) {
62 *tag++ = MFIE_TYPE_RATES;
63 *tag++ = 4;
64 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
65 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
66 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
67 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
68 }
69
70
71 *tag_p = tag;
72}
73
74static void ieee80211_MFIE_Grate(struct ieee80211_device *ieee, u8 **tag_p)
75{
76 u8 *tag = *tag_p;
77
78 if (ieee->modulation & IEEE80211_OFDM_MODULATION) {
79 *tag++ = MFIE_TYPE_RATES_EX;
80 *tag++ = 8;
81 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
82 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
83 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
84 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
85 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
86 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
87 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
88 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
89 }
90
91
92 *tag_p = tag;
93}
94
95static void ieee80211_WMM_Info(struct ieee80211_device *ieee, u8 **tag_p)
96{
97 u8 *tag = *tag_p;
98
99 *tag++ = MFIE_TYPE_GENERIC;
100 *tag++ = 7;
101 *tag++ = 0x00;
102 *tag++ = 0x50;
103 *tag++ = 0xf2;
104 *tag++ = 0x02;
105 *tag++ = 0x00;
106 *tag++ = 0x01;
107#ifdef SUPPORT_USPD
108 if (ieee->current_network.wmm_info & 0x80)
109 *tag++ = 0x0f | MAX_SP_Len;
110 else
111 *tag++ = MAX_SP_Len;
112#else
113 *tag++ = MAX_SP_Len;
114#endif
115 *tag_p = tag;
116}
117
118#ifdef THOMAS_TURBO
119static void ieee80211_TURBO_Info(struct ieee80211_device *ieee, u8 **tag_p)
120{
121 u8 *tag = *tag_p;
122
123 *tag++ = MFIE_TYPE_GENERIC;
124 *tag++ = 7;
125 *tag++ = 0x00;
126 *tag++ = 0xe0;
127 *tag++ = 0x4c;
128 *tag++ = 0x01;
129 *tag++ = 0x02;
130 *tag++ = 0x11;
131 *tag++ = 0x00;
132
133 *tag_p = tag;
134 netdev_alert(ieee->dev, "This is enable turbo mode IE process\n");
135}
136#endif
137
138static void enqueue_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb)
139{
140 int nh;
141
142 nh = (ieee->mgmt_queue_head + 1) % MGMT_QUEUE_NUM;
143
144
145
146
147
148
149
150
151 ieee->mgmt_queue_head = nh;
152 ieee->mgmt_queue_ring[nh] = skb;
153
154
155}
156
157static struct sk_buff *dequeue_mgmt(struct ieee80211_device *ieee)
158{
159 struct sk_buff *ret;
160
161 if (ieee->mgmt_queue_tail == ieee->mgmt_queue_head)
162 return NULL;
163
164 ret = ieee->mgmt_queue_ring[ieee->mgmt_queue_tail];
165
166 ieee->mgmt_queue_tail =
167 (ieee->mgmt_queue_tail + 1) % MGMT_QUEUE_NUM;
168
169 return ret;
170}
171
172static void init_mgmt_queue(struct ieee80211_device *ieee)
173{
174 ieee->mgmt_queue_tail = ieee->mgmt_queue_head = 0;
175}
176
177static u8 MgntQuery_MgntFrameTxRate(struct ieee80211_device *ieee)
178{
179 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
180 u8 rate;
181
182
183 if (pHTInfo->IOTAction & HT_IOT_ACT_MGNT_USE_CCK_6M)
184 rate = 0x0c;
185 else
186 rate = ieee->basic_rate & 0x7f;
187
188 if (rate == 0) {
189
190 if (ieee->mode == IEEE_A ||
191 ieee->mode == IEEE_N_5G ||
192 (ieee->mode == IEEE_N_24G && !pHTInfo->bCurSuppCCK))
193 rate = 0x0c;
194 else
195 rate = 0x02;
196 }
197
198
199
200
201
202
203
204
205
206
207 return rate;
208}
209
210void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl);
211
212inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee)
213{
214 unsigned long flags;
215 short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
216 struct rtl_80211_hdr_3addr *header =
217 (struct rtl_80211_hdr_3addr *)skb->data;
218
219 struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
220
221 spin_lock_irqsave(&ieee->lock, flags);
222
223
224 ieee80211_sta_wakeup(ieee, 0);
225
226 tcb_desc->queue_index = MGNT_QUEUE;
227 tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee);
228 tcb_desc->RATRIndex = 7;
229 tcb_desc->bTxDisableRateFallBack = 1;
230 tcb_desc->bTxUseDriverAssingedRate = 1;
231
232 if (single) {
233 if (ieee->queue_stop) {
234 enqueue_mgmt(ieee, skb);
235 } else {
236 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
237
238 if (ieee->seq_ctrl[0] == 0xFFF)
239 ieee->seq_ctrl[0] = 0;
240 else
241 ieee->seq_ctrl[0]++;
242
243
244 netif_trans_update(ieee->dev);
245 ieee->softmac_data_hard_start_xmit(skb, ieee->dev, ieee->basic_rate);
246
247 }
248
249 spin_unlock_irqrestore(&ieee->lock, flags);
250 } else {
251 spin_unlock_irqrestore(&ieee->lock, flags);
252 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags);
253
254 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
255
256 if (ieee->seq_ctrl[0] == 0xFFF)
257 ieee->seq_ctrl[0] = 0;
258 else
259 ieee->seq_ctrl[0]++;
260
261
262 if (!ieee->check_nic_enough_desc(ieee->dev, tcb_desc->queue_index) || \
263 (skb_queue_len(&ieee->skb_waitQ[tcb_desc->queue_index]) != 0) || \
264 (ieee->queue_stop)) {
265
266
267
268
269 printk("%s():insert to waitqueue!\n", __func__);
270 skb_queue_tail(&ieee->skb_waitQ[tcb_desc->queue_index], skb);
271 } else {
272 ieee->softmac_hard_start_xmit(skb, ieee->dev);
273
274 }
275 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags);
276 }
277}
278
279static inline void
280softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee)
281{
282 short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
283 struct rtl_80211_hdr_3addr *header =
284 (struct rtl_80211_hdr_3addr *)skb->data;
285
286 if (single) {
287 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
288
289 if (ieee->seq_ctrl[0] == 0xFFF)
290 ieee->seq_ctrl[0] = 0;
291 else
292 ieee->seq_ctrl[0]++;
293
294
295 netif_trans_update(ieee->dev);
296 ieee->softmac_data_hard_start_xmit(skb, ieee->dev, ieee->basic_rate);
297 } else {
298 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
299
300 if (ieee->seq_ctrl[0] == 0xFFF)
301 ieee->seq_ctrl[0] = 0;
302 else
303 ieee->seq_ctrl[0]++;
304
305 ieee->softmac_hard_start_xmit(skb, ieee->dev);
306 }
307
308}
309
310static inline struct sk_buff *ieee80211_probe_req(struct ieee80211_device *ieee)
311{
312 unsigned int len, rate_len;
313 u8 *tag;
314 struct sk_buff *skb;
315 struct ieee80211_probe_request *req;
316
317 len = ieee->current_network.ssid_len;
318
319 rate_len = ieee80211_MFIE_rate_len(ieee);
320
321 skb = dev_alloc_skb(sizeof(struct ieee80211_probe_request) +
322 2 + len + rate_len + ieee->tx_headroom);
323 if (!skb)
324 return NULL;
325
326 skb_reserve(skb, ieee->tx_headroom);
327
328 req = skb_put(skb, sizeof(struct ieee80211_probe_request));
329 req->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
330 req->header.duration_id = 0;
331
332 eth_broadcast_addr(req->header.addr1);
333 memcpy(req->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
334 eth_broadcast_addr(req->header.addr3);
335
336 tag = skb_put(skb, len + 2 + rate_len);
337
338 *tag++ = MFIE_TYPE_SSID;
339 *tag++ = len;
340 memcpy(tag, ieee->current_network.ssid, len);
341 tag += len;
342
343 ieee80211_MFIE_Brate(ieee, &tag);
344 ieee80211_MFIE_Grate(ieee, &tag);
345 return skb;
346}
347
348struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee);
349
350static void ieee80211_send_beacon(struct ieee80211_device *ieee)
351{
352 struct sk_buff *skb;
353
354 if (!ieee->ieee_up)
355 return;
356
357 skb = ieee80211_get_beacon_(ieee);
358
359 if (skb) {
360 softmac_mgmt_xmit(skb, ieee);
361 ieee->softmac_stats.tx_beacons++;
362
363 }
364
365
366
367
368 if (ieee->beacon_txing && ieee->ieee_up) {
369
370
371 mod_timer(&ieee->beacon_timer,
372 jiffies + msecs_to_jiffies(ieee->current_network.beacon_interval - 5));
373 }
374
375}
376
377static void ieee80211_send_beacon_cb(struct timer_list *t)
378{
379 struct ieee80211_device *ieee =
380 from_timer(ieee, t, beacon_timer);
381 unsigned long flags;
382
383 spin_lock_irqsave(&ieee->beacon_lock, flags);
384 ieee80211_send_beacon(ieee);
385 spin_unlock_irqrestore(&ieee->beacon_lock, flags);
386}
387
388static void ieee80211_send_probe(struct ieee80211_device *ieee)
389{
390 struct sk_buff *skb;
391
392 skb = ieee80211_probe_req(ieee);
393 if (skb) {
394 softmac_mgmt_xmit(skb, ieee);
395 ieee->softmac_stats.tx_probe_rq++;
396
397 }
398}
399
400static void ieee80211_send_probe_requests(struct ieee80211_device *ieee)
401{
402 if (ieee->active_scan && (ieee->softmac_features & IEEE_SOFTMAC_PROBERQ)) {
403 ieee80211_send_probe(ieee);
404 ieee80211_send_probe(ieee);
405 }
406}
407
408
409
410
411void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee)
412{
413 short ch = 0;
414 u8 channel_map[MAX_CHANNEL_NUMBER + 1];
415
416 memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER + 1);
417 mutex_lock(&ieee->scan_mutex);
418
419 while (1) {
420 do {
421 ch++;
422 if (ch > MAX_CHANNEL_NUMBER)
423 goto out;
424 } while (!channel_map[ch]);
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445 if (ieee->state == IEEE80211_LINKED)
446 goto out;
447 ieee->set_chan(ieee->dev, ch);
448 if (channel_map[ch] == 1)
449 ieee80211_send_probe_requests(ieee);
450
451
452
453
454 if (ieee->state >= IEEE80211_LINKED && ieee->sync_scan_hurryup)
455 goto out;
456
457 msleep_interruptible(IEEE80211_SOFTMAC_SCAN_TIME);
458 }
459out:
460 if (ieee->state < IEEE80211_LINKED) {
461 ieee->actscanning = false;
462 mutex_unlock(&ieee->scan_mutex);
463 } else {
464 ieee->sync_scan_hurryup = 0;
465 if (IS_DOT11D_ENABLE(ieee))
466 dot11d_scan_complete(ieee);
467 mutex_unlock(&ieee->scan_mutex);
468 }
469}
470EXPORT_SYMBOL(ieee80211_softmac_scan_syncro);
471
472static void ieee80211_softmac_scan_wq(struct work_struct *work)
473{
474 struct delayed_work *dwork = to_delayed_work(work);
475 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, softmac_scan_wq);
476 static short watchdog;
477 u8 channel_map[MAX_CHANNEL_NUMBER + 1];
478
479 memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER + 1);
480 if (!ieee->ieee_up)
481 return;
482 mutex_lock(&ieee->scan_mutex);
483 do {
484 ieee->current_network.channel =
485 (ieee->current_network.channel + 1) % MAX_CHANNEL_NUMBER;
486 if (watchdog++ > MAX_CHANNEL_NUMBER) {
487
488 if (!channel_map[ieee->current_network.channel]) {
489 ieee->current_network.channel = 6;
490 goto out;
491 }
492 }
493 } while (!channel_map[ieee->current_network.channel]);
494 if (ieee->scanning == 0)
495 goto out;
496 ieee->set_chan(ieee->dev, ieee->current_network.channel);
497 if (channel_map[ieee->current_network.channel] == 1)
498 ieee80211_send_probe_requests(ieee);
499
500 schedule_delayed_work(&ieee->softmac_scan_wq, IEEE80211_SOFTMAC_SCAN_TIME);
501
502 mutex_unlock(&ieee->scan_mutex);
503 return;
504out:
505 if (IS_DOT11D_ENABLE(ieee))
506 dot11d_scan_complete(ieee);
507 ieee->actscanning = false;
508 watchdog = 0;
509 ieee->scanning = 0;
510 mutex_unlock(&ieee->scan_mutex);
511}
512
513static void ieee80211_beacons_start(struct ieee80211_device *ieee)
514{
515 unsigned long flags;
516 spin_lock_irqsave(&ieee->beacon_lock, flags);
517
518 ieee->beacon_txing = 1;
519 ieee80211_send_beacon(ieee);
520
521 spin_unlock_irqrestore(&ieee->beacon_lock, flags);
522}
523
524static void ieee80211_beacons_stop(struct ieee80211_device *ieee)
525{
526 unsigned long flags;
527
528 spin_lock_irqsave(&ieee->beacon_lock, flags);
529
530 ieee->beacon_txing = 0;
531 del_timer_sync(&ieee->beacon_timer);
532
533 spin_unlock_irqrestore(&ieee->beacon_lock, flags);
534}
535
536void ieee80211_stop_send_beacons(struct ieee80211_device *ieee)
537{
538 if (ieee->stop_send_beacons)
539 ieee->stop_send_beacons(ieee->dev);
540 if (ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
541 ieee80211_beacons_stop(ieee);
542}
543EXPORT_SYMBOL(ieee80211_stop_send_beacons);
544
545void ieee80211_start_send_beacons(struct ieee80211_device *ieee)
546{
547 if (ieee->start_send_beacons)
548 ieee->start_send_beacons(ieee->dev, ieee->basic_rate);
549 if (ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
550 ieee80211_beacons_start(ieee);
551}
552EXPORT_SYMBOL(ieee80211_start_send_beacons);
553
554static void ieee80211_softmac_stop_scan(struct ieee80211_device *ieee)
555{
556
557
558
559
560 mutex_lock(&ieee->scan_mutex);
561
562
563 if (ieee->scanning == 1) {
564 ieee->scanning = 0;
565
566 cancel_delayed_work(&ieee->softmac_scan_wq);
567 }
568
569
570 mutex_unlock(&ieee->scan_mutex);
571}
572
573void ieee80211_stop_scan(struct ieee80211_device *ieee)
574{
575 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
576 ieee80211_softmac_stop_scan(ieee);
577 else
578 ieee->stop_scan(ieee->dev);
579}
580EXPORT_SYMBOL(ieee80211_stop_scan);
581
582
583static void ieee80211_start_scan(struct ieee80211_device *ieee)
584{
585 if (IS_DOT11D_ENABLE(ieee)) {
586 if (IS_COUNTRY_IE_VALID(ieee))
587 RESET_CIE_WATCHDOG(ieee);
588 }
589 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN) {
590 if (ieee->scanning == 0) {
591 ieee->scanning = 1;
592 schedule_delayed_work(&ieee->softmac_scan_wq, 0);
593 }
594 } else {
595 ieee->start_scan(ieee->dev);
596 }
597}
598
599
600void ieee80211_start_scan_syncro(struct ieee80211_device *ieee)
601{
602 if (IS_DOT11D_ENABLE(ieee)) {
603 if (IS_COUNTRY_IE_VALID(ieee))
604 RESET_CIE_WATCHDOG(ieee);
605 }
606 ieee->sync_scan_hurryup = 0;
607 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
608 ieee80211_softmac_scan_syncro(ieee);
609 else
610 ieee->scan_syncro(ieee->dev);
611}
612EXPORT_SYMBOL(ieee80211_start_scan_syncro);
613
614static inline struct sk_buff *
615ieee80211_authentication_req(struct ieee80211_network *beacon,
616 struct ieee80211_device *ieee, int challengelen)
617{
618 struct sk_buff *skb;
619 struct ieee80211_authentication *auth;
620 int len = sizeof(struct ieee80211_authentication) + challengelen + ieee->tx_headroom;
621
622 skb = dev_alloc_skb(len);
623 if (!skb)
624 return NULL;
625
626 skb_reserve(skb, ieee->tx_headroom);
627 auth = skb_put(skb, sizeof(struct ieee80211_authentication));
628
629 if (challengelen)
630 auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH
631 | IEEE80211_FCTL_WEP);
632 else
633 auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH);
634
635 auth->header.duration_id = cpu_to_le16(0x013a);
636
637 memcpy(auth->header.addr1, beacon->bssid, ETH_ALEN);
638 memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
639 memcpy(auth->header.addr3, beacon->bssid, ETH_ALEN);
640
641
642 if (ieee->auth_mode == 0)
643 auth->algorithm = WLAN_AUTH_OPEN;
644 else if (ieee->auth_mode == 1)
645 auth->algorithm = cpu_to_le16(WLAN_AUTH_SHARED_KEY);
646 else if (ieee->auth_mode == 2)
647 auth->algorithm = WLAN_AUTH_OPEN;
648 printk("=================>%s():auth->algorithm is %d\n", __func__, auth->algorithm);
649 auth->transaction = cpu_to_le16(ieee->associate_seq);
650 ieee->associate_seq++;
651
652 auth->status = cpu_to_le16(WLAN_STATUS_SUCCESS);
653
654 return skb;
655}
656
657static struct sk_buff *ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *dest)
658{
659 u8 *tag;
660 int beacon_size;
661 struct ieee80211_probe_response *beacon_buf;
662 struct sk_buff *skb = NULL;
663 int encrypt;
664 int atim_len, erp_len;
665 struct ieee80211_crypt_data *crypt;
666
667 char *ssid = ieee->current_network.ssid;
668 int ssid_len = ieee->current_network.ssid_len;
669 int rate_len = ieee->current_network.rates_len + 2;
670 int rate_ex_len = ieee->current_network.rates_ex_len;
671 int wpa_ie_len = ieee->wpa_ie_len;
672 u8 erpinfo_content = 0;
673
674 u8 *tmp_ht_cap_buf;
675 u8 tmp_ht_cap_len = 0;
676 u8 *tmp_ht_info_buf;
677 u8 tmp_ht_info_len = 0;
678 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
679 u8 *tmp_generic_ie_buf = NULL;
680 u8 tmp_generic_ie_len = 0;
681
682 if (rate_ex_len > 0)
683 rate_ex_len += 2;
684
685 if (ieee->current_network.capability & WLAN_CAPABILITY_IBSS)
686 atim_len = 4;
687 else
688 atim_len = 0;
689
690 if (ieee80211_is_54g(&ieee->current_network))
691 erp_len = 3;
692 else
693 erp_len = 0;
694
695 crypt = ieee->crypt[ieee->tx_keyidx];
696
697 encrypt = ieee->host_encrypt && crypt && crypt->ops &&
698 ((0 == strcmp(crypt->ops->name, "WEP") || wpa_ie_len));
699
700 tmp_ht_cap_buf = (u8 *)&ieee->pHTInfo->SelfHTCap;
701 tmp_ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
702 tmp_ht_info_buf = (u8 *)&ieee->pHTInfo->SelfHTInfo;
703 tmp_ht_info_len = sizeof(ieee->pHTInfo->SelfHTInfo);
704 HTConstructCapabilityElement(ieee, tmp_ht_cap_buf, &tmp_ht_cap_len, encrypt);
705 HTConstructInfoElement(ieee, tmp_ht_info_buf, &tmp_ht_info_len, encrypt);
706
707 if (pHTInfo->bRegRT2RTAggregation) {
708 tmp_generic_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
709 tmp_generic_ie_len = sizeof(ieee->pHTInfo->szRT2RTAggBuffer);
710 HTConstructRT2RTAggElement(ieee, tmp_generic_ie_buf, &tmp_generic_ie_len);
711 }
712
713 beacon_size = sizeof(struct ieee80211_probe_response) + 2
714 + ssid_len
715 + 3
716 + rate_len
717 + rate_ex_len
718 + atim_len
719 + erp_len
720 + wpa_ie_len
721
722
723
724
725 + ieee->tx_headroom;
726 skb = dev_alloc_skb(beacon_size);
727 if (!skb)
728 return NULL;
729 skb_reserve(skb, ieee->tx_headroom);
730 beacon_buf = skb_put(skb, (beacon_size - ieee->tx_headroom));
731 memcpy(beacon_buf->header.addr1, dest, ETH_ALEN);
732 memcpy(beacon_buf->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
733 memcpy(beacon_buf->header.addr3, ieee->current_network.bssid, ETH_ALEN);
734
735 beacon_buf->header.duration_id = 0;
736 beacon_buf->beacon_interval =
737 cpu_to_le16(ieee->current_network.beacon_interval);
738 beacon_buf->capability =
739 cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_IBSS);
740 beacon_buf->capability |=
741 cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE);
742
743 if (ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT))
744 beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
745
746 if (encrypt)
747 beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
748
749 beacon_buf->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_RESP);
750 beacon_buf->info_element[0].id = MFIE_TYPE_SSID;
751 beacon_buf->info_element[0].len = ssid_len;
752
753 tag = (u8 *)beacon_buf->info_element[0].data;
754
755 memcpy(tag, ssid, ssid_len);
756
757 tag += ssid_len;
758
759 *(tag++) = MFIE_TYPE_RATES;
760 *(tag++) = rate_len - 2;
761 memcpy(tag, ieee->current_network.rates, rate_len - 2);
762 tag += rate_len - 2;
763
764 *(tag++) = MFIE_TYPE_DS_SET;
765 *(tag++) = 1;
766 *(tag++) = ieee->current_network.channel;
767
768 if (atim_len) {
769 *(tag++) = MFIE_TYPE_IBSS_SET;
770 *(tag++) = 2;
771
772 put_unaligned_le16(ieee->current_network.atim_window,
773 tag);
774 tag += 2;
775 }
776
777 if (erp_len) {
778 *(tag++) = MFIE_TYPE_ERP;
779 *(tag++) = 1;
780 *(tag++) = erpinfo_content;
781 }
782 if (rate_ex_len) {
783 *(tag++) = MFIE_TYPE_RATES_EX;
784 *(tag++) = rate_ex_len - 2;
785 memcpy(tag, ieee->current_network.rates_ex, rate_ex_len - 2);
786 tag += rate_ex_len - 2;
787 }
788
789 if (wpa_ie_len) {
790 if (ieee->iw_mode == IW_MODE_ADHOC) {
791
792 memcpy(&ieee->wpa_ie[14], &ieee->wpa_ie[8], 4);
793 }
794 memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
795 tag += wpa_ie_len;
796 }
797
798
799 return skb;
800}
801
802static struct sk_buff *ieee80211_assoc_resp(struct ieee80211_device *ieee,
803 u8 *dest)
804{
805 struct sk_buff *skb;
806 u8 *tag;
807
808 struct ieee80211_crypt_data *crypt;
809 struct ieee80211_assoc_response_frame *assoc;
810 short encrypt;
811
812 unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
813 int len = sizeof(struct ieee80211_assoc_response_frame) + rate_len + ieee->tx_headroom;
814
815 skb = dev_alloc_skb(len);
816
817 if (!skb)
818 return NULL;
819
820 skb_reserve(skb, ieee->tx_headroom);
821
822 assoc = skb_put(skb, sizeof(struct ieee80211_assoc_response_frame));
823
824 assoc->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP);
825 memcpy(assoc->header.addr1, dest, ETH_ALEN);
826 memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
827 memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
828 assoc->capability = cpu_to_le16(ieee->iw_mode == IW_MODE_MASTER ?
829 WLAN_CAPABILITY_BSS : WLAN_CAPABILITY_IBSS);
830
831 if (ieee->short_slot)
832 assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
833
834 if (ieee->host_encrypt)
835 crypt = ieee->crypt[ieee->tx_keyidx];
836 else
837 crypt = NULL;
838
839 encrypt = crypt && crypt->ops;
840
841 if (encrypt)
842 assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
843
844 assoc->status = 0;
845 assoc->aid = cpu_to_le16(ieee->assoc_id);
846 if (ieee->assoc_id == 0x2007)
847 ieee->assoc_id = 0;
848 else
849 ieee->assoc_id++;
850
851 tag = skb_put(skb, rate_len);
852
853 ieee80211_MFIE_Brate(ieee, &tag);
854 ieee80211_MFIE_Grate(ieee, &tag);
855
856 return skb;
857}
858
859static struct sk_buff *ieee80211_auth_resp(struct ieee80211_device *ieee,
860 int status, u8 *dest)
861{
862 struct sk_buff *skb;
863 struct ieee80211_authentication *auth;
864 int len = ieee->tx_headroom + sizeof(struct ieee80211_authentication) + 1;
865
866 skb = dev_alloc_skb(len);
867
868 if (!skb)
869 return NULL;
870
871 skb->len = sizeof(struct ieee80211_authentication);
872
873 auth = (struct ieee80211_authentication *)skb->data;
874
875 auth->status = cpu_to_le16(status);
876 auth->transaction = cpu_to_le16(2);
877 auth->algorithm = cpu_to_le16(WLAN_AUTH_OPEN);
878
879 memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
880 memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
881 memcpy(auth->header.addr1, dest, ETH_ALEN);
882 auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH);
883 return skb;
884}
885
886static struct sk_buff *ieee80211_null_func(struct ieee80211_device *ieee,
887 short pwr)
888{
889 struct sk_buff *skb;
890 struct rtl_80211_hdr_3addr *hdr;
891
892 skb = dev_alloc_skb(sizeof(struct rtl_80211_hdr_3addr));
893
894 if (!skb)
895 return NULL;
896
897 hdr = skb_put(skb, sizeof(struct rtl_80211_hdr_3addr));
898
899 memcpy(hdr->addr1, ieee->current_network.bssid, ETH_ALEN);
900 memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN);
901 memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN);
902
903 hdr->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA |
904 IEEE80211_STYPE_NULLFUNC | IEEE80211_FCTL_TODS |
905 (pwr ? IEEE80211_FCTL_PM : 0));
906
907 return skb;
908}
909
910static void ieee80211_resp_to_assoc_rq(struct ieee80211_device *ieee, u8 *dest)
911{
912 struct sk_buff *buf = ieee80211_assoc_resp(ieee, dest);
913
914 if (buf)
915 softmac_mgmt_xmit(buf, ieee);
916}
917
918static void ieee80211_resp_to_auth(struct ieee80211_device *ieee, int s,
919 u8 *dest)
920{
921 struct sk_buff *buf = ieee80211_auth_resp(ieee, s, dest);
922
923 if (buf)
924 softmac_mgmt_xmit(buf, ieee);
925}
926
927static void ieee80211_resp_to_probe(struct ieee80211_device *ieee, u8 *dest)
928{
929 struct sk_buff *buf = ieee80211_probe_resp(ieee, dest);
930 if (buf)
931 softmac_mgmt_xmit(buf, ieee);
932}
933
934static inline struct sk_buff *
935ieee80211_association_req(struct ieee80211_network *beacon,
936 struct ieee80211_device *ieee)
937{
938 struct sk_buff *skb;
939
940
941 struct ieee80211_assoc_request_frame *hdr;
942 u8 *tag;
943
944
945
946
947
948
949 u8 *ht_cap_buf = NULL;
950 u8 ht_cap_len = 0;
951 u8 *realtek_ie_buf = NULL;
952 u8 realtek_ie_len = 0;
953 int wpa_ie_len = ieee->wpa_ie_len;
954 unsigned int ckip_ie_len = 0;
955 unsigned int ccxrm_ie_len = 0;
956 unsigned int cxvernum_ie_len = 0;
957 struct ieee80211_crypt_data *crypt;
958 int encrypt;
959
960 unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
961 unsigned int wmm_info_len = beacon->qos_data.supported ? 9 : 0;
962#ifdef THOMAS_TURBO
963 unsigned int turbo_info_len = beacon->Turbo_Enable ? 9 : 0;
964#endif
965
966 int len = 0;
967
968 crypt = ieee->crypt[ieee->tx_keyidx];
969 encrypt = ieee->host_encrypt && crypt && crypt->ops && ((0 == strcmp(crypt->ops->name, "WEP") || wpa_ie_len));
970
971
972 if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT) {
973 ht_cap_buf = (u8 *)&ieee->pHTInfo->SelfHTCap;
974 ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
975 HTConstructCapabilityElement(ieee, ht_cap_buf, &ht_cap_len, encrypt);
976 if (ieee->pHTInfo->bCurrentRT2RTAggregation) {
977 realtek_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
978 realtek_ie_len = sizeof(ieee->pHTInfo->szRT2RTAggBuffer);
979 HTConstructRT2RTAggElement(ieee, realtek_ie_buf, &realtek_ie_len);
980 }
981 }
982 if (ieee->qos_support)
983 wmm_info_len = beacon->qos_data.supported ? 9 : 0;
984
985 if (beacon->bCkipSupported)
986 ckip_ie_len = 30 + 2;
987
988 if (beacon->bCcxRmEnable)
989 ccxrm_ie_len = 6 + 2;
990
991 if (beacon->BssCcxVerNumber >= 2)
992 cxvernum_ie_len = 5 + 2;
993
994#ifdef THOMAS_TURBO
995 len = sizeof(struct ieee80211_assoc_request_frame) + 2
996 + beacon->ssid_len
997 + rate_len
998 + wpa_ie_len
999 + wmm_info_len
1000 + turbo_info_len
1001 + ht_cap_len
1002 + realtek_ie_len
1003 + ckip_ie_len
1004 + ccxrm_ie_len
1005 + cxvernum_ie_len
1006 + ieee->tx_headroom;
1007#else
1008 len = sizeof(struct ieee80211_assoc_request_frame) + 2
1009 + beacon->ssid_len
1010 + rate_len
1011 + wpa_ie_len
1012 + wmm_info_len
1013 + ht_cap_len
1014 + realtek_ie_len
1015 + ckip_ie_len
1016 + ccxrm_ie_len
1017 + cxvernum_ie_len
1018 + ieee->tx_headroom;
1019#endif
1020 skb = dev_alloc_skb(len);
1021
1022 if (!skb)
1023 return NULL;
1024
1025 skb_reserve(skb, ieee->tx_headroom);
1026
1027 hdr = skb_put(skb, sizeof(struct ieee80211_assoc_request_frame) + 2);
1028
1029 hdr->header.frame_ctl = IEEE80211_STYPE_ASSOC_REQ;
1030 hdr->header.duration_id = cpu_to_le16(37);
1031 memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN);
1032 memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
1033 memcpy(hdr->header.addr3, beacon->bssid, ETH_ALEN);
1034
1035 memcpy(ieee->ap_mac_addr, beacon->bssid, ETH_ALEN);
1036
1037 hdr->capability = cpu_to_le16(WLAN_CAPABILITY_BSS);
1038 if (beacon->capability & WLAN_CAPABILITY_PRIVACY)
1039 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
1040
1041 if (beacon->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1042 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE);
1043
1044 if (ieee->short_slot)
1045 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
1046 if (wmm_info_len)
1047 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_QOS);
1048
1049 hdr->listen_interval = cpu_to_le16(0xa);
1050
1051 hdr->info_element[0].id = MFIE_TYPE_SSID;
1052
1053 hdr->info_element[0].len = beacon->ssid_len;
1054 skb_put_data(skb, beacon->ssid, beacon->ssid_len);
1055
1056 tag = skb_put(skb, rate_len);
1057
1058 ieee80211_MFIE_Brate(ieee, &tag);
1059 ieee80211_MFIE_Grate(ieee, &tag);
1060
1061 if (beacon->bCkipSupported) {
1062 static u8 AironetIeOui[] = {0x00, 0x01, 0x66};
1063 u8 CcxAironetBuf[30];
1064 struct octet_string osCcxAironetIE;
1065
1066 memset(CcxAironetBuf, 0, 30);
1067 osCcxAironetIE.octet = CcxAironetBuf;
1068 osCcxAironetIE.length = sizeof(CcxAironetBuf);
1069
1070
1071
1072
1073 memcpy(osCcxAironetIE.octet, AironetIeOui, sizeof(AironetIeOui));
1074
1075
1076
1077
1078 osCcxAironetIE.octet[IE_CISCO_FLAG_POSITION] |= (SUPPORT_CKIP_PK | SUPPORT_CKIP_MIC);
1079 tag = skb_put(skb, ckip_ie_len);
1080 *tag++ = MFIE_TYPE_AIRONET;
1081 *tag++ = osCcxAironetIE.length;
1082 memcpy(tag, osCcxAironetIE.octet, osCcxAironetIE.length);
1083 tag += osCcxAironetIE.length;
1084 }
1085
1086 if (beacon->bCcxRmEnable) {
1087 static u8 CcxRmCapBuf[] = {0x00, 0x40, 0x96, 0x01, 0x01, 0x00};
1088 struct octet_string osCcxRmCap;
1089
1090 osCcxRmCap.octet = CcxRmCapBuf;
1091 osCcxRmCap.length = sizeof(CcxRmCapBuf);
1092 tag = skb_put(skb, ccxrm_ie_len);
1093 *tag++ = MFIE_TYPE_GENERIC;
1094 *tag++ = osCcxRmCap.length;
1095 memcpy(tag, osCcxRmCap.octet, osCcxRmCap.length);
1096 tag += osCcxRmCap.length;
1097 }
1098
1099 if (beacon->BssCcxVerNumber >= 2) {
1100 u8 CcxVerNumBuf[] = {0x00, 0x40, 0x96, 0x03, 0x00};
1101 struct octet_string osCcxVerNum;
1102 CcxVerNumBuf[4] = beacon->BssCcxVerNumber;
1103 osCcxVerNum.octet = CcxVerNumBuf;
1104 osCcxVerNum.length = sizeof(CcxVerNumBuf);
1105 tag = skb_put(skb, cxvernum_ie_len);
1106 *tag++ = MFIE_TYPE_GENERIC;
1107 *tag++ = osCcxVerNum.length;
1108 memcpy(tag, osCcxVerNum.octet, osCcxVerNum.length);
1109 tag += osCcxVerNum.length;
1110 }
1111
1112 if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT) {
1113 if (ieee->pHTInfo->ePeerHTSpecVer != HT_SPEC_VER_EWC) {
1114 tag = skb_put(skb, ht_cap_len);
1115 *tag++ = MFIE_TYPE_HT_CAP;
1116 *tag++ = ht_cap_len - 2;
1117 memcpy(tag, ht_cap_buf, ht_cap_len - 2);
1118 tag += ht_cap_len - 2;
1119 }
1120 }
1121
1122
1123 if (wpa_ie_len)
1124 skb_put_data(skb, ieee->wpa_ie, wpa_ie_len);
1125
1126 if (wmm_info_len) {
1127 tag = skb_put(skb, wmm_info_len);
1128 ieee80211_WMM_Info(ieee, &tag);
1129 }
1130#ifdef THOMAS_TURBO
1131 if (turbo_info_len) {
1132 tag = skb_put(skb, turbo_info_len);
1133 ieee80211_TURBO_Info(ieee, &tag);
1134 }
1135#endif
1136
1137 if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT) {
1138 if (ieee->pHTInfo->ePeerHTSpecVer == HT_SPEC_VER_EWC) {
1139 tag = skb_put(skb, ht_cap_len);
1140 *tag++ = MFIE_TYPE_GENERIC;
1141 *tag++ = ht_cap_len - 2;
1142 memcpy(tag, ht_cap_buf, ht_cap_len - 2);
1143 tag += ht_cap_len - 2;
1144 }
1145
1146 if (ieee->pHTInfo->bCurrentRT2RTAggregation) {
1147 tag = skb_put(skb, realtek_ie_len);
1148 *tag++ = MFIE_TYPE_GENERIC;
1149 *tag++ = realtek_ie_len - 2;
1150 memcpy(tag, realtek_ie_buf, realtek_ie_len - 2);
1151 }
1152 }
1153
1154
1155 return skb;
1156}
1157
1158void ieee80211_associate_abort(struct ieee80211_device *ieee)
1159{
1160 unsigned long flags;
1161 spin_lock_irqsave(&ieee->lock, flags);
1162
1163 ieee->associate_seq++;
1164
1165
1166
1167
1168
1169
1170
1171 if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING) {
1172 IEEE80211_DEBUG_MGMT("Authentication failed\n");
1173 ieee->softmac_stats.no_auth_rs++;
1174 } else {
1175 IEEE80211_DEBUG_MGMT("Association failed\n");
1176 ieee->softmac_stats.no_ass_rs++;
1177 }
1178
1179 ieee->state = IEEE80211_ASSOCIATING_RETRY;
1180
1181 schedule_delayed_work(&ieee->associate_retry_wq, \
1182 IEEE80211_SOFTMAC_ASSOC_RETRY_TIME);
1183
1184 spin_unlock_irqrestore(&ieee->lock, flags);
1185}
1186
1187static void ieee80211_associate_abort_cb(struct timer_list *t)
1188{
1189 struct ieee80211_device *dev = from_timer(dev, t, associate_timer);
1190
1191 ieee80211_associate_abort(dev);
1192}
1193
1194static void ieee80211_associate_step1(struct ieee80211_device *ieee)
1195{
1196 struct ieee80211_network *beacon = &ieee->current_network;
1197 struct sk_buff *skb;
1198
1199 IEEE80211_DEBUG_MGMT("Stopping scan\n");
1200
1201 ieee->softmac_stats.tx_auth_rq++;
1202 skb = ieee80211_authentication_req(beacon, ieee, 0);
1203
1204 if (!skb) {
1205 ieee80211_associate_abort(ieee);
1206 } else {
1207 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATING;
1208 IEEE80211_DEBUG_MGMT("Sending authentication request\n");
1209 softmac_mgmt_xmit(skb, ieee);
1210
1211 if (!timer_pending(&ieee->associate_timer)) {
1212 ieee->associate_timer.expires = jiffies + (HZ / 2);
1213 add_timer(&ieee->associate_timer);
1214 }
1215
1216 }
1217}
1218
1219static void ieee80211_auth_challenge(struct ieee80211_device *ieee,
1220 u8 *challenge,
1221 int chlen)
1222{
1223 u8 *c;
1224 struct sk_buff *skb;
1225 struct ieee80211_network *beacon = &ieee->current_network;
1226
1227
1228 ieee->associate_seq++;
1229 ieee->softmac_stats.tx_auth_rq++;
1230
1231 skb = ieee80211_authentication_req(beacon, ieee, chlen + 2);
1232 if (!skb) {
1233 ieee80211_associate_abort(ieee);
1234 } else {
1235 c = skb_put(skb, chlen + 2);
1236 *(c++) = MFIE_TYPE_CHALLENGE;
1237 *(c++) = chlen;
1238 memcpy(c, challenge, chlen);
1239
1240 IEEE80211_DEBUG_MGMT("Sending authentication challenge response\n");
1241
1242 ieee80211_encrypt_fragment(ieee, skb, sizeof(struct rtl_80211_hdr_3addr));
1243
1244 softmac_mgmt_xmit(skb, ieee);
1245 mod_timer(&ieee->associate_timer, jiffies + (HZ / 2));
1246
1247 }
1248 kfree(challenge);
1249}
1250
1251static void ieee80211_associate_step2(struct ieee80211_device *ieee)
1252{
1253 struct sk_buff *skb;
1254 struct ieee80211_network *beacon = &ieee->current_network;
1255
1256 del_timer_sync(&ieee->associate_timer);
1257
1258 IEEE80211_DEBUG_MGMT("Sending association request\n");
1259
1260 ieee->softmac_stats.tx_ass_rq++;
1261 skb = ieee80211_association_req(beacon, ieee);
1262 if (!skb) {
1263 ieee80211_associate_abort(ieee);
1264 } else {
1265 softmac_mgmt_xmit(skb, ieee);
1266 mod_timer(&ieee->associate_timer, jiffies + (HZ / 2));
1267
1268 }
1269}
1270static void ieee80211_associate_complete_wq(struct work_struct *work)
1271{
1272 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_complete_wq);
1273
1274 netdev_info(ieee->dev, "Associated successfully\n");
1275 if (ieee80211_is_54g(&ieee->current_network) &&
1276 (ieee->modulation & IEEE80211_OFDM_MODULATION)) {
1277 ieee->rate = 108;
1278 netdev_info(ieee->dev, "Using G rates:%d\n", ieee->rate);
1279 } else {
1280 ieee->rate = 22;
1281 netdev_info(ieee->dev, "Using B rates:%d\n", ieee->rate);
1282 }
1283 if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT) {
1284 printk("Successfully associated, ht enabled\n");
1285 HTOnAssocRsp(ieee);
1286 } else {
1287 printk("Successfully associated, ht not enabled(%d, %d)\n", ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bEnableHT);
1288 memset(ieee->dot11HTOperationalRateSet, 0, 16);
1289
1290 }
1291 ieee->LinkDetectInfo.SlotNum = 2 * (1 + ieee->current_network.beacon_interval / 500);
1292
1293 if (ieee->LinkDetectInfo.NumRecvBcnInPeriod == 0 || ieee->LinkDetectInfo.NumRecvDataInPeriod == 0) {
1294 ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1;
1295 ieee->LinkDetectInfo.NumRecvDataInPeriod = 1;
1296 }
1297 ieee->link_change(ieee->dev);
1298 if (!ieee->is_silent_reset) {
1299 printk("============>normal associate\n");
1300 notify_wx_assoc_event(ieee);
1301 } else {
1302 printk("==================>silent reset associate\n");
1303 ieee->is_silent_reset = false;
1304 }
1305
1306 if (ieee->data_hard_resume)
1307 ieee->data_hard_resume(ieee->dev);
1308 netif_carrier_on(ieee->dev);
1309}
1310
1311static void ieee80211_associate_complete(struct ieee80211_device *ieee)
1312{
1313
1314
1315 del_timer_sync(&ieee->associate_timer);
1316
1317 ieee->state = IEEE80211_LINKED;
1318
1319 schedule_work(&ieee->associate_complete_wq);
1320}
1321
1322static void ieee80211_associate_procedure_wq(struct work_struct *work)
1323{
1324 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_procedure_wq);
1325 ieee->sync_scan_hurryup = 1;
1326 mutex_lock(&ieee->wx_mutex);
1327
1328 if (ieee->data_hard_stop)
1329 ieee->data_hard_stop(ieee->dev);
1330
1331 ieee80211_stop_scan(ieee);
1332 printk("===>%s(), chan:%d\n", __func__, ieee->current_network.channel);
1333
1334 HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1335
1336 ieee->associate_seq = 1;
1337 ieee80211_associate_step1(ieee);
1338
1339 mutex_unlock(&ieee->wx_mutex);
1340}
1341
1342inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee80211_network *net)
1343{
1344 u8 tmp_ssid[IW_ESSID_MAX_SIZE + 1];
1345 int tmp_ssid_len = 0;
1346
1347 short apset, ssidset, ssidbroad, apmatch, ssidmatch;
1348
1349
1350
1351
1352 if (ieee->state != IEEE80211_NOLINK)
1353 return;
1354
1355 if ((ieee->iw_mode == IW_MODE_INFRA) && !(net->capability & WLAN_CAPABILITY_BSS))
1356 return;
1357
1358 if ((ieee->iw_mode == IW_MODE_ADHOC) && !(net->capability & WLAN_CAPABILITY_IBSS))
1359 return;
1360
1361 if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC) {
1362
1363
1364
1365
1366 apset = ieee->wap_set;
1367 ssidset = ieee->ssid_set;
1368 ssidbroad = !(net->ssid_len == 0 || net->ssid[0] == '\0');
1369 apmatch = (memcmp(ieee->current_network.bssid, net->bssid, ETH_ALEN) == 0);
1370 ssidmatch = (ieee->current_network.ssid_len == net->ssid_len) &&
1371 (!strncmp(ieee->current_network.ssid, net->ssid, net->ssid_len));
1372
1373
1374
1375
1376
1377
1378 if ((apset && apmatch &&
1379 ((ssidset && ssidbroad && ssidmatch) || (ssidbroad && !ssidset) || (!ssidbroad && ssidset))) ||
1380
1381
1382
1383 (!apset && ssidset && ssidbroad && ssidmatch)) {
1384
1385
1386
1387 if (!ssidbroad) {
1388 strncpy(tmp_ssid, ieee->current_network.ssid, IW_ESSID_MAX_SIZE);
1389 tmp_ssid_len = ieee->current_network.ssid_len;
1390 }
1391 memcpy(&ieee->current_network, net, sizeof(struct ieee80211_network));
1392
1393 strncpy(ieee->current_network.ssid, tmp_ssid, IW_ESSID_MAX_SIZE);
1394 ieee->current_network.ssid_len = tmp_ssid_len;
1395 netdev_info(ieee->dev,
1396 "Linking with %s,channel:%d, qos:%d, myHT:%d, networkHT:%d\n",
1397 ieee->current_network.ssid,
1398 ieee->current_network.channel,
1399 ieee->current_network.qos_data.supported,
1400 ieee->pHTInfo->bEnableHT,
1401 ieee->current_network.bssht.bdSupportHT);
1402
1403
1404 HTResetIOTSetting(ieee->pHTInfo);
1405 if (ieee->iw_mode == IW_MODE_INFRA) {
1406
1407 ieee->AsocRetryCount = 0;
1408
1409 if ((ieee->current_network.qos_data.supported == 1) &&
1410
1411 ieee->current_network.bssht.bdSupportHT) {
1412
1413
1414 HTResetSelfAndSavePeerSetting(ieee, &ieee->current_network);
1415 } else {
1416 ieee->pHTInfo->bCurrentHTSupport = false;
1417 }
1418
1419 ieee->state = IEEE80211_ASSOCIATING;
1420 schedule_work(&ieee->associate_procedure_wq);
1421 } else {
1422 if (ieee80211_is_54g(&ieee->current_network) &&
1423 (ieee->modulation & IEEE80211_OFDM_MODULATION)) {
1424 ieee->rate = 108;
1425 ieee->SetWirelessMode(ieee->dev, IEEE_G);
1426 netdev_info(ieee->dev,
1427 "Using G rates\n");
1428 } else {
1429 ieee->rate = 22;
1430 ieee->SetWirelessMode(ieee->dev, IEEE_B);
1431 netdev_info(ieee->dev,
1432 "Using B rates\n");
1433 }
1434 memset(ieee->dot11HTOperationalRateSet, 0, 16);
1435
1436 ieee->state = IEEE80211_LINKED;
1437 }
1438 }
1439 }
1440}
1441
1442void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee)
1443{
1444 unsigned long flags;
1445 struct ieee80211_network *target;
1446
1447 spin_lock_irqsave(&ieee->lock, flags);
1448
1449 list_for_each_entry(target, &ieee->network_list, list) {
1450
1451
1452
1453
1454 if (ieee->state != IEEE80211_NOLINK)
1455 break;
1456
1457 if (ieee->scan_age == 0 || time_after(target->last_scanned + ieee->scan_age, jiffies))
1458 ieee80211_softmac_new_net(ieee, target);
1459 }
1460
1461 spin_unlock_irqrestore(&ieee->lock, flags);
1462}
1463
1464static inline u16 auth_parse(struct sk_buff *skb, u8 **challenge, int *chlen)
1465{
1466 struct ieee80211_authentication *a;
1467 u8 *t;
1468 if (skb->len < (sizeof(struct ieee80211_authentication) - sizeof(struct ieee80211_info_element))) {
1469 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len);
1470 return 0xcafe;
1471 }
1472 *challenge = NULL;
1473 a = (struct ieee80211_authentication *)skb->data;
1474 if (skb->len > (sizeof(struct ieee80211_authentication) + 3)) {
1475 t = skb->data + sizeof(struct ieee80211_authentication);
1476
1477 if (*(t++) == MFIE_TYPE_CHALLENGE) {
1478 *chlen = *(t++);
1479 *challenge = kmemdup(t, *chlen, GFP_ATOMIC);
1480 if (!*challenge)
1481 return -ENOMEM;
1482 }
1483 }
1484
1485 return le16_to_cpu(a->status);
1486}
1487
1488static int auth_rq_parse(struct sk_buff *skb, u8 *dest)
1489{
1490 struct ieee80211_authentication *a;
1491
1492 if (skb->len < (sizeof(struct ieee80211_authentication) - sizeof(struct ieee80211_info_element))) {
1493 IEEE80211_DEBUG_MGMT("invalid len in auth request: %d\n", skb->len);
1494 return -1;
1495 }
1496 a = (struct ieee80211_authentication *)skb->data;
1497
1498 memcpy(dest, a->header.addr2, ETH_ALEN);
1499
1500 if (le16_to_cpu(a->algorithm) != WLAN_AUTH_OPEN)
1501 return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
1502
1503 return WLAN_STATUS_SUCCESS;
1504}
1505
1506static short probe_rq_parse(struct ieee80211_device *ieee, struct sk_buff *skb, u8 *src)
1507{
1508 u8 *tag;
1509 u8 *skbend;
1510 u8 *ssid = NULL;
1511 u8 ssidlen = 0;
1512
1513 struct rtl_80211_hdr_3addr *header =
1514 (struct rtl_80211_hdr_3addr *)skb->data;
1515
1516 if (skb->len < sizeof(struct rtl_80211_hdr_3addr))
1517 return -1;
1518
1519 memcpy(src, header->addr2, ETH_ALEN);
1520
1521 skbend = (u8 *)skb->data + skb->len;
1522
1523 tag = skb->data + sizeof(struct rtl_80211_hdr_3addr);
1524
1525 while (tag + 1 < skbend) {
1526 if (*tag == 0) {
1527 ssid = tag + 2;
1528 ssidlen = *(tag + 1);
1529 break;
1530 }
1531 tag++;
1532 tag = tag + *(tag);
1533 tag++;
1534 }
1535
1536
1537 if (ssidlen == 0)
1538 return 1;
1539
1540 if (!ssid)
1541 return 1;
1542
1543 return (!strncmp(ssid, ieee->current_network.ssid, ssidlen));
1544}
1545
1546static int assoc_rq_parse(struct sk_buff *skb, u8 *dest)
1547{
1548 struct ieee80211_assoc_request_frame *a;
1549
1550 if (skb->len < (sizeof(struct ieee80211_assoc_request_frame) -
1551 sizeof(struct ieee80211_info_element))) {
1552 IEEE80211_DEBUG_MGMT("invalid len in auth request:%d \n", skb->len);
1553 return -1;
1554 }
1555
1556 a = (struct ieee80211_assoc_request_frame *)skb->data;
1557
1558 memcpy(dest, a->header.addr2, ETH_ALEN);
1559
1560 return 0;
1561}
1562
1563static inline u16 assoc_parse(struct ieee80211_device *ieee, struct sk_buff *skb, int *aid)
1564{
1565 struct ieee80211_assoc_response_frame *response_head;
1566 u16 status_code;
1567
1568 if (skb->len < sizeof(struct ieee80211_assoc_response_frame)) {
1569 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len);
1570 return 0xcafe;
1571 }
1572
1573 response_head = (struct ieee80211_assoc_response_frame *)skb->data;
1574 *aid = le16_to_cpu(response_head->aid) & 0x3fff;
1575
1576 status_code = le16_to_cpu(response_head->status);
1577 if ((status_code == WLAN_STATUS_ASSOC_DENIED_RATES ||
1578 status_code == WLAN_STATUS_CAPS_UNSUPPORTED) &&
1579 ((ieee->mode == IEEE_G) &&
1580 (ieee->current_network.mode == IEEE_N_24G) &&
1581 (ieee->AsocRetryCount++ < (RT_ASOC_RETRY_LIMIT - 1)))) {
1582 ieee->pHTInfo->IOTAction |= HT_IOT_ACT_PURE_N_MODE;
1583 } else {
1584 ieee->AsocRetryCount = 0;
1585 }
1586
1587 return le16_to_cpu(response_head->status);
1588}
1589
1590static inline void
1591ieee80211_rx_probe_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1592{
1593 u8 dest[ETH_ALEN];
1594
1595
1596 ieee->softmac_stats.rx_probe_rq++;
1597
1598 if (probe_rq_parse(ieee, skb, dest)) {
1599
1600 ieee->softmac_stats.tx_probe_rs++;
1601 ieee80211_resp_to_probe(ieee, dest);
1602 }
1603}
1604
1605static inline void
1606ieee80211_rx_auth_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1607{
1608 u8 dest[ETH_ALEN];
1609 int status;
1610
1611 ieee->softmac_stats.rx_auth_rq++;
1612
1613 status = auth_rq_parse(skb, dest);
1614 if (status != -1)
1615 ieee80211_resp_to_auth(ieee, status, dest);
1616
1617}
1618
1619static inline void
1620ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1621{
1622 u8 dest[ETH_ALEN];
1623
1624
1625 ieee->softmac_stats.rx_ass_rq++;
1626 if (assoc_rq_parse(skb, dest) != -1)
1627 ieee80211_resp_to_assoc_rq(ieee, dest);
1628
1629 netdev_info(ieee->dev, "New client associated: %pM\n", dest);
1630
1631}
1632
1633static void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee,
1634 short pwr)
1635{
1636 struct sk_buff *buf = ieee80211_null_func(ieee, pwr);
1637
1638 if (buf)
1639 softmac_ps_mgmt_xmit(buf, ieee);
1640}
1641
1642
1643static short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h,
1644 u32 *time_l)
1645{
1646 int timeout;
1647 u8 dtim;
1648
1649
1650
1651
1652
1653
1654 dtim = ieee->current_network.dtim_data;
1655 if (!(dtim & IEEE80211_DTIM_VALID))
1656 return 0;
1657 timeout = ieee->current_network.beacon_interval;
1658 ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID;
1659
1660 if (dtim & ((IEEE80211_DTIM_UCAST | IEEE80211_DTIM_MBCAST) & ieee->ps))
1661 return 2;
1662
1663 if (!time_after(jiffies,
1664 dev_trans_start(ieee->dev) + msecs_to_jiffies(timeout)))
1665 return 0;
1666
1667 if (!time_after(jiffies,
1668 ieee->last_rx_ps_time + msecs_to_jiffies(timeout)))
1669 return 0;
1670
1671 if ((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE) &&
1672 (ieee->mgmt_queue_tail != ieee->mgmt_queue_head))
1673 return 0;
1674
1675 if (time_l) {
1676 *time_l = ieee->current_network.last_dtim_sta_time[0]
1677 + (ieee->current_network.beacon_interval
1678 * ieee->current_network.dtim_period) * 1000;
1679 }
1680
1681 if (time_h) {
1682 *time_h = ieee->current_network.last_dtim_sta_time[1];
1683 if (time_l && *time_l < ieee->current_network.last_dtim_sta_time[0])
1684 *time_h += 1;
1685 }
1686
1687 return 1;
1688}
1689
1690static inline void ieee80211_sta_ps(struct tasklet_struct *t)
1691{
1692 struct ieee80211_device *ieee = from_tasklet(ieee, t, ps_task);
1693 u32 th, tl;
1694 short sleep;
1695
1696 unsigned long flags, flags2;
1697
1698 spin_lock_irqsave(&ieee->lock, flags);
1699
1700 if ((ieee->ps == IEEE80211_PS_DISABLED ||
1701 ieee->iw_mode != IW_MODE_INFRA ||
1702 ieee->state != IEEE80211_LINKED)) {
1703
1704 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1705
1706 ieee80211_sta_wakeup(ieee, 1);
1707
1708 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1709 }
1710
1711 sleep = ieee80211_sta_ps_sleep(ieee, &th, &tl);
1712
1713 if (sleep == 0)
1714 goto out;
1715
1716 if (sleep == 1) {
1717 if (ieee->sta_sleep == 1) {
1718 ieee->enter_sleep_state(ieee->dev, th, tl);
1719 } else if (ieee->sta_sleep == 0) {
1720
1721 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1722
1723 if (ieee->ps_is_queue_empty(ieee->dev)) {
1724 ieee->sta_sleep = 2;
1725
1726 ieee->ps_request_tx_ack(ieee->dev);
1727
1728 ieee80211_sta_ps_send_null_frame(ieee, 1);
1729
1730 ieee->ps_th = th;
1731 ieee->ps_tl = tl;
1732 }
1733 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1734 }
1735 } else if (sleep == 2) {
1736
1737 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1738
1739 ieee80211_sta_wakeup(ieee, 1);
1740
1741 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1742 }
1743out:
1744 spin_unlock_irqrestore(&ieee->lock, flags);
1745}
1746
1747void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
1748{
1749 if (ieee->sta_sleep == 0) {
1750 if (nl) {
1751 printk("Warning: driver is probably failing to report TX ps error\n");
1752 ieee->ps_request_tx_ack(ieee->dev);
1753 ieee80211_sta_ps_send_null_frame(ieee, 0);
1754 }
1755 return;
1756 }
1757
1758 if (ieee->sta_sleep == 1)
1759 ieee->sta_wake_up(ieee->dev);
1760
1761 ieee->sta_sleep = 0;
1762
1763 if (nl) {
1764 ieee->ps_request_tx_ack(ieee->dev);
1765 ieee80211_sta_ps_send_null_frame(ieee, 0);
1766 }
1767}
1768
1769void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success)
1770{
1771 unsigned long flags, flags2;
1772
1773 spin_lock_irqsave(&ieee->lock, flags);
1774
1775 if (ieee->sta_sleep == 2) {
1776
1777 if (success) {
1778 ieee->sta_sleep = 1;
1779 ieee->enter_sleep_state(ieee->dev, ieee->ps_th, ieee->ps_tl);
1780 }
1781
1782
1783
1784 } else {
1785
1786 if ((ieee->sta_sleep == 0) && !success) {
1787 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1788 ieee80211_sta_ps_send_null_frame(ieee, 0);
1789 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1790 }
1791 }
1792 spin_unlock_irqrestore(&ieee->lock, flags);
1793}
1794EXPORT_SYMBOL(ieee80211_ps_tx_ack);
1795
1796static void ieee80211_process_action(struct ieee80211_device *ieee,
1797 struct sk_buff *skb)
1798{
1799 struct rtl_80211_hdr *header = (struct rtl_80211_hdr *)skb->data;
1800 u8 *act = ieee80211_get_payload(header);
1801 u8 tmp = 0;
1802
1803 if (!act) {
1804 IEEE80211_DEBUG(IEEE80211_DL_ERR, "error to get payload of action frame\n");
1805 return;
1806 }
1807 tmp = *act;
1808 act++;
1809 switch (tmp) {
1810 case ACT_CAT_BA:
1811 if (*act == ACT_ADDBAREQ)
1812 ieee80211_rx_ADDBAReq(ieee, skb);
1813 else if (*act == ACT_ADDBARSP)
1814 ieee80211_rx_ADDBARsp(ieee, skb);
1815 else if (*act == ACT_DELBA)
1816 ieee80211_rx_DELBA(ieee, skb);
1817 break;
1818 default:
1819 break;
1820 }
1821 return;
1822}
1823
1824static void ieee80211_check_auth_response(struct ieee80211_device *ieee,
1825 struct sk_buff *skb)
1826{
1827
1828 bool bSupportNmode = true, bHalfSupportNmode = false;
1829 u16 errcode;
1830 u8 *challenge;
1831 int chlen = 0;
1832 u32 iotAction;
1833
1834 errcode = auth_parse(skb, &challenge, &chlen);
1835 if (!errcode) {
1836 if (ieee->open_wep || !challenge) {
1837 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATED;
1838 ieee->softmac_stats.rx_auth_rs_ok++;
1839 iotAction = ieee->pHTInfo->IOTAction;
1840 if (!(iotAction & HT_IOT_ACT_PURE_N_MODE)) {
1841 if (!ieee->GetNmodeSupportBySecCfg(ieee->dev)) {
1842
1843 if (IsHTHalfNmodeAPs(ieee)) {
1844 bSupportNmode = true;
1845 bHalfSupportNmode = true;
1846 } else {
1847 bSupportNmode = false;
1848 bHalfSupportNmode = false;
1849 }
1850 netdev_dbg(ieee->dev, "SEC(%d, %d)\n",
1851 bSupportNmode,
1852 bHalfSupportNmode);
1853 }
1854 }
1855
1856 if (bSupportNmode) {
1857
1858 ieee->SetWirelessMode(ieee->dev,
1859 ieee->current_network.mode);
1860 } else {
1861
1862 ieee->SetWirelessMode(ieee->dev, IEEE_G);
1863 }
1864
1865 if (ieee->current_network.mode == IEEE_N_24G &&
1866 bHalfSupportNmode) {
1867 netdev_dbg(ieee->dev, "enter half N mode\n");
1868 ieee->bHalfWirelessN24GMode = true;
1869 } else {
1870 ieee->bHalfWirelessN24GMode = false;
1871 }
1872 ieee80211_associate_step2(ieee);
1873 } else {
1874 ieee80211_auth_challenge(ieee, challenge, chlen);
1875 }
1876 } else {
1877 ieee->softmac_stats.rx_auth_rs_err++;
1878 IEEE80211_DEBUG_MGMT("Auth response status code 0x%x", errcode);
1879 ieee80211_associate_abort(ieee);
1880 }
1881}
1882
1883inline int
1884ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
1885 struct ieee80211_rx_stats *rx_stats, u16 type,
1886 u16 stype)
1887{
1888 struct rtl_80211_hdr_3addr *header = (struct rtl_80211_hdr_3addr *)skb->data;
1889 u16 errcode;
1890 int aid;
1891 struct ieee80211_assoc_response_frame *assoc_resp;
1892
1893
1894 if (!ieee->proto_started)
1895 return 0;
1896
1897 if (ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED &&
1898 ieee->iw_mode == IW_MODE_INFRA &&
1899 ieee->state == IEEE80211_LINKED))
1900 tasklet_schedule(&ieee->ps_task);
1901
1902 if (WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_PROBE_RESP &&
1903 WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_BEACON)
1904 ieee->last_rx_ps_time = jiffies;
1905
1906 switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
1907 case IEEE80211_STYPE_ASSOC_RESP:
1908 case IEEE80211_STYPE_REASSOC_RESP:
1909 IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n",
1910 WLAN_FC_GET_STYPE(header->frame_ctl));
1911 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
1912 ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED &&
1913 ieee->iw_mode == IW_MODE_INFRA) {
1914 struct ieee80211_network *network;
1915
1916 network = kzalloc(sizeof(*network), GFP_KERNEL);
1917 if (!network)
1918 return -ENOMEM;
1919
1920 errcode = assoc_parse(ieee, skb, &aid);
1921 if (!errcode) {
1922 ieee->state = IEEE80211_LINKED;
1923 ieee->assoc_id = aid;
1924 ieee->softmac_stats.rx_ass_ok++;
1925
1926
1927 if (ieee->qos_support) {
1928 assoc_resp = (struct ieee80211_assoc_response_frame *)skb->data;
1929 if (ieee80211_parse_info_param(ieee, assoc_resp->info_element,\
1930 rx_stats->len - sizeof(*assoc_resp), \
1931 network, rx_stats)) {
1932 return 1;
1933 } else {
1934
1935 memcpy(ieee->pHTInfo->PeerHTCapBuf, network->bssht.bdHTCapBuf, network->bssht.bdHTCapLen);
1936 memcpy(ieee->pHTInfo->PeerHTInfoBuf, network->bssht.bdHTInfoBuf, network->bssht.bdHTInfoLen);
1937 }
1938 if (ieee->handle_assoc_response)
1939 ieee->handle_assoc_response(ieee->dev, (struct ieee80211_assoc_response_frame *)header, network);
1940 }
1941 ieee80211_associate_complete(ieee);
1942 } else {
1943
1944 ieee->softmac_stats.rx_ass_err++;
1945 printk("Association response status code 0x%x\n",
1946 errcode);
1947 IEEE80211_DEBUG_MGMT("Association response status code 0x%x\n",
1948 errcode);
1949 if (ieee->AsocRetryCount < RT_ASOC_RETRY_LIMIT)
1950 schedule_work(&ieee->associate_procedure_wq);
1951 else
1952 ieee80211_associate_abort(ieee);
1953 }
1954 kfree(network);
1955 }
1956 break;
1957
1958 case IEEE80211_STYPE_ASSOC_REQ:
1959 case IEEE80211_STYPE_REASSOC_REQ:
1960 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
1961 ieee->iw_mode == IW_MODE_MASTER)
1962 ieee80211_rx_assoc_rq(ieee, skb);
1963 break;
1964
1965 case IEEE80211_STYPE_AUTH:
1966 if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) {
1967 if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING
1968 && ieee->iw_mode == IW_MODE_INFRA) {
1969 IEEE80211_DEBUG_MGMT("Received auth response");
1970 ieee80211_check_auth_response(ieee, skb);
1971 } else if (ieee->iw_mode == IW_MODE_MASTER) {
1972 ieee80211_rx_auth_rq(ieee, skb);
1973 }
1974 }
1975 break;
1976
1977 case IEEE80211_STYPE_PROBE_REQ:
1978 if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) &&
1979 ((ieee->iw_mode == IW_MODE_ADHOC ||
1980 ieee->iw_mode == IW_MODE_MASTER) &&
1981 ieee->state == IEEE80211_LINKED)) {
1982 ieee80211_rx_probe_rq(ieee, skb);
1983 }
1984 break;
1985
1986 case IEEE80211_STYPE_DISASSOC:
1987 case IEEE80211_STYPE_DEAUTH:
1988
1989
1990
1991 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
1992 ieee->state == IEEE80211_LINKED &&
1993 ieee->iw_mode == IW_MODE_INFRA) {
1994 ieee->state = IEEE80211_ASSOCIATING;
1995 ieee->softmac_stats.reassoc++;
1996
1997 notify_wx_assoc_event(ieee);
1998
1999 RemovePeerTS(ieee, header->addr2);
2000 schedule_work(&ieee->associate_procedure_wq);
2001 }
2002 break;
2003 case IEEE80211_STYPE_MANAGE_ACT:
2004 ieee80211_process_action(ieee, skb);
2005 break;
2006 default:
2007 return -1;
2008 }
2009
2010
2011 return 0;
2012}
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee)
2033{
2034 unsigned int queue_index = txb->queue_index;
2035 unsigned long flags;
2036 int i;
2037 struct cb_desc *tcb_desc = NULL;
2038
2039 spin_lock_irqsave(&ieee->lock, flags);
2040
2041
2042 ieee80211_sta_wakeup(ieee, 0);
2043
2044
2045 ieee->stats.tx_bytes += le16_to_cpu(txb->payload_size);
2046 ieee->stats.tx_packets++;
2047 tcb_desc = (struct cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
2048 if (tcb_desc->bMulticast)
2049 ieee->stats.multicast++;
2050
2051
2052 for (i = 0; i < txb->nr_frags; i++) {
2053#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2054 if ((skb_queue_len(&ieee->skb_drv_aggQ[queue_index]) != 0) ||
2055#else
2056 if ((skb_queue_len(&ieee->skb_waitQ[queue_index]) != 0) ||
2057#endif
2058 (!ieee->check_nic_enough_desc(ieee->dev, queue_index)) ||
2059 (ieee->queue_stop)) {
2060
2061
2062
2063
2064
2065
2066#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2067 skb_queue_tail(&ieee->skb_drv_aggQ[queue_index], txb->fragments[i]);
2068#else
2069 skb_queue_tail(&ieee->skb_waitQ[queue_index], txb->fragments[i]);
2070#endif
2071 } else {
2072 ieee->softmac_data_hard_start_xmit(txb->fragments[i],
2073 ieee->dev, ieee->rate);
2074
2075
2076
2077 }
2078 }
2079 ieee80211_txb_free(txb);
2080
2081
2082 spin_unlock_irqrestore(&ieee->lock, flags);
2083}
2084EXPORT_SYMBOL(ieee80211_softmac_xmit);
2085
2086
2087static void ieee80211_resume_tx(struct ieee80211_device *ieee)
2088{
2089 int i;
2090 for (i = ieee->tx_pending.frag; i < ieee->tx_pending.txb->nr_frags; i++) {
2091 if (ieee->queue_stop) {
2092 ieee->tx_pending.frag = i;
2093 return;
2094 } else {
2095 ieee->softmac_data_hard_start_xmit(ieee->tx_pending.txb->fragments[i],
2096 ieee->dev, ieee->rate);
2097
2098 ieee->stats.tx_packets++;
2099 netif_trans_update(ieee->dev);
2100 }
2101 }
2102
2103 ieee80211_txb_free(ieee->tx_pending.txb);
2104 ieee->tx_pending.txb = NULL;
2105}
2106
2107void ieee80211_reset_queue(struct ieee80211_device *ieee)
2108{
2109 unsigned long flags;
2110
2111 spin_lock_irqsave(&ieee->lock, flags);
2112 init_mgmt_queue(ieee);
2113 if (ieee->tx_pending.txb) {
2114 ieee80211_txb_free(ieee->tx_pending.txb);
2115 ieee->tx_pending.txb = NULL;
2116 }
2117 ieee->queue_stop = 0;
2118 spin_unlock_irqrestore(&ieee->lock, flags);
2119}
2120EXPORT_SYMBOL(ieee80211_reset_queue);
2121
2122void ieee80211_wake_queue(struct ieee80211_device *ieee)
2123{
2124 unsigned long flags;
2125 struct sk_buff *skb;
2126 struct rtl_80211_hdr_3addr *header;
2127
2128 spin_lock_irqsave(&ieee->lock, flags);
2129 if (!ieee->queue_stop)
2130 goto exit;
2131
2132 ieee->queue_stop = 0;
2133
2134 if (ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE) {
2135 while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))) {
2136 header = (struct rtl_80211_hdr_3addr *)skb->data;
2137
2138 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2139
2140 if (ieee->seq_ctrl[0] == 0xFFF)
2141 ieee->seq_ctrl[0] = 0;
2142 else
2143 ieee->seq_ctrl[0]++;
2144
2145 ieee->softmac_data_hard_start_xmit(skb, ieee->dev, ieee->basic_rate);
2146
2147 }
2148 }
2149 if (!ieee->queue_stop && ieee->tx_pending.txb)
2150 ieee80211_resume_tx(ieee);
2151
2152 if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)) {
2153 ieee->softmac_stats.swtxawake++;
2154 netif_wake_queue(ieee->dev);
2155 }
2156exit:
2157 spin_unlock_irqrestore(&ieee->lock, flags);
2158}
2159EXPORT_SYMBOL(ieee80211_wake_queue);
2160
2161void ieee80211_stop_queue(struct ieee80211_device *ieee)
2162{
2163
2164
2165
2166 if (!netif_queue_stopped(ieee->dev)) {
2167 netif_stop_queue(ieee->dev);
2168 ieee->softmac_stats.swtxstop++;
2169 }
2170 ieee->queue_stop = 1;
2171
2172}
2173EXPORT_SYMBOL(ieee80211_stop_queue);
2174
2175
2176void ieee80211_start_master_bss(struct ieee80211_device *ieee)
2177{
2178 ieee->assoc_id = 1;
2179
2180 if (ieee->current_network.ssid_len == 0) {
2181 strncpy(ieee->current_network.ssid,
2182 IEEE80211_DEFAULT_TX_ESSID,
2183 IW_ESSID_MAX_SIZE);
2184
2185 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2186 ieee->ssid_set = 1;
2187 }
2188
2189 memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN);
2190
2191 ieee->set_chan(ieee->dev, ieee->current_network.channel);
2192 ieee->state = IEEE80211_LINKED;
2193 ieee->link_change(ieee->dev);
2194 notify_wx_assoc_event(ieee);
2195
2196 if (ieee->data_hard_resume)
2197 ieee->data_hard_resume(ieee->dev);
2198
2199 netif_carrier_on(ieee->dev);
2200}
2201
2202static void ieee80211_start_monitor_mode(struct ieee80211_device *ieee)
2203{
2204 if (ieee->raw_tx) {
2205 if (ieee->data_hard_resume)
2206 ieee->data_hard_resume(ieee->dev);
2207
2208 netif_carrier_on(ieee->dev);
2209 }
2210}
2211static void ieee80211_start_ibss_wq(struct work_struct *work)
2212{
2213 struct delayed_work *dwork = to_delayed_work(work);
2214 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, start_ibss_wq);
2215
2216
2217
2218
2219
2220
2221
2222 if (!ieee->proto_started) {
2223 printk("==========oh driver down return\n");
2224 return;
2225 }
2226 mutex_lock(&ieee->wx_mutex);
2227
2228 if (ieee->current_network.ssid_len == 0) {
2229 strcpy(ieee->current_network.ssid, IEEE80211_DEFAULT_TX_ESSID);
2230 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2231 ieee->ssid_set = 1;
2232 }
2233
2234
2235 ieee80211_softmac_check_all_nets(ieee);
2236
2237
2238 if (ieee->state == IEEE80211_NOLINK)
2239 ieee->current_network.channel = 6;
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254 if (ieee->state == IEEE80211_NOLINK)
2255 ieee80211_start_scan_syncro(ieee);
2256
2257
2258 if (ieee->state == IEEE80211_NOLINK) {
2259 printk("creating new IBSS cell\n");
2260 if (!ieee->wap_set)
2261 eth_random_addr(ieee->current_network.bssid);
2262
2263 if (ieee->modulation & IEEE80211_CCK_MODULATION) {
2264 ieee->current_network.rates_len = 4;
2265
2266 ieee->current_network.rates[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
2267 ieee->current_network.rates[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
2268 ieee->current_network.rates[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
2269 ieee->current_network.rates[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
2270 } else {
2271 ieee->current_network.rates_len = 0;
2272 }
2273 if (ieee->modulation & IEEE80211_OFDM_MODULATION) {
2274 ieee->current_network.rates_ex_len = 8;
2275
2276 ieee->current_network.rates_ex[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
2277 ieee->current_network.rates_ex[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
2278 ieee->current_network.rates_ex[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
2279 ieee->current_network.rates_ex[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
2280 ieee->current_network.rates_ex[4] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
2281 ieee->current_network.rates_ex[5] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
2282 ieee->current_network.rates_ex[6] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
2283 ieee->current_network.rates_ex[7] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
2284
2285 ieee->rate = 108;
2286 } else {
2287 ieee->current_network.rates_ex_len = 0;
2288 ieee->rate = 22;
2289 }
2290
2291
2292 ieee->current_network.QoS_Enable = 0;
2293 ieee->SetWirelessMode(ieee->dev, IEEE_G);
2294 ieee->current_network.atim_window = 0;
2295 ieee->current_network.capability = WLAN_CAPABILITY_IBSS;
2296 if (ieee->short_slot)
2297 ieee->current_network.capability |= WLAN_CAPABILITY_SHORT_SLOT;
2298 }
2299
2300 ieee->state = IEEE80211_LINKED;
2301
2302 ieee->set_chan(ieee->dev, ieee->current_network.channel);
2303 ieee->link_change(ieee->dev);
2304
2305 notify_wx_assoc_event(ieee);
2306
2307 ieee80211_start_send_beacons(ieee);
2308
2309 if (ieee->data_hard_resume)
2310 ieee->data_hard_resume(ieee->dev);
2311 netif_carrier_on(ieee->dev);
2312
2313 mutex_unlock(&ieee->wx_mutex);
2314}
2315
2316inline void ieee80211_start_ibss(struct ieee80211_device *ieee)
2317{
2318 schedule_delayed_work(&ieee->start_ibss_wq, 150);
2319}
2320
2321
2322void ieee80211_start_bss(struct ieee80211_device *ieee)
2323{
2324 unsigned long flags;
2325
2326
2327
2328
2329 if (IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee)) {
2330 if (!ieee->bGlobalDomain)
2331 return;
2332 }
2333
2334
2335
2336
2337
2338 ieee80211_softmac_check_all_nets(ieee);
2339
2340
2341
2342
2343
2344
2345
2346
2347 spin_lock_irqsave(&ieee->lock, flags);
2348
2349 if (ieee->state == IEEE80211_NOLINK) {
2350 ieee->actscanning = true;
2351 ieee80211_start_scan(ieee);
2352 }
2353 spin_unlock_irqrestore(&ieee->lock, flags);
2354}
2355
2356
2357void ieee80211_disassociate(struct ieee80211_device *ieee)
2358{
2359 netif_carrier_off(ieee->dev);
2360 if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)
2361 ieee80211_reset_queue(ieee);
2362
2363 if (ieee->data_hard_stop)
2364 ieee->data_hard_stop(ieee->dev);
2365 if (IS_DOT11D_ENABLE(ieee))
2366 dot11d_reset(ieee);
2367 ieee->state = IEEE80211_NOLINK;
2368 ieee->is_set_key = false;
2369 ieee->link_change(ieee->dev);
2370
2371 notify_wx_assoc_event(ieee);
2372}
2373EXPORT_SYMBOL(ieee80211_disassociate);
2374
2375static void ieee80211_associate_retry_wq(struct work_struct *work)
2376{
2377 struct delayed_work *dwork = to_delayed_work(work);
2378 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, associate_retry_wq);
2379 unsigned long flags;
2380
2381 mutex_lock(&ieee->wx_mutex);
2382 if (!ieee->proto_started)
2383 goto exit;
2384
2385 if (ieee->state != IEEE80211_ASSOCIATING_RETRY)
2386 goto exit;
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401 ieee->state = IEEE80211_NOLINK;
2402
2403 ieee80211_softmac_check_all_nets(ieee);
2404
2405 spin_lock_irqsave(&ieee->lock, flags);
2406
2407 if (ieee->state == IEEE80211_NOLINK)
2408 ieee80211_start_scan(ieee);
2409
2410 spin_unlock_irqrestore(&ieee->lock, flags);
2411
2412exit:
2413 mutex_unlock(&ieee->wx_mutex);
2414}
2415
2416struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee)
2417{
2418 u8 broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
2419
2420 struct sk_buff *skb;
2421 struct ieee80211_probe_response *b;
2422
2423 skb = ieee80211_probe_resp(ieee, broadcast_addr);
2424
2425 if (!skb)
2426 return NULL;
2427
2428 b = (struct ieee80211_probe_response *)skb->data;
2429 b->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_BEACON);
2430
2431 return skb;
2432}
2433
2434struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee)
2435{
2436 struct sk_buff *skb;
2437 struct ieee80211_probe_response *b;
2438
2439 skb = ieee80211_get_beacon_(ieee);
2440 if (!skb)
2441 return NULL;
2442
2443 b = (struct ieee80211_probe_response *)skb->data;
2444 b->header.seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2445
2446 if (ieee->seq_ctrl[0] == 0xFFF)
2447 ieee->seq_ctrl[0] = 0;
2448 else
2449 ieee->seq_ctrl[0]++;
2450
2451 return skb;
2452}
2453EXPORT_SYMBOL(ieee80211_get_beacon);
2454
2455void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee)
2456{
2457 ieee->sync_scan_hurryup = 1;
2458 mutex_lock(&ieee->wx_mutex);
2459 ieee80211_stop_protocol(ieee);
2460 mutex_unlock(&ieee->wx_mutex);
2461}
2462EXPORT_SYMBOL(ieee80211_softmac_stop_protocol);
2463
2464void ieee80211_stop_protocol(struct ieee80211_device *ieee)
2465{
2466 if (!ieee->proto_started)
2467 return;
2468
2469 ieee->proto_started = 0;
2470
2471 ieee80211_stop_send_beacons(ieee);
2472 del_timer_sync(&ieee->associate_timer);
2473 cancel_delayed_work(&ieee->associate_retry_wq);
2474 cancel_delayed_work(&ieee->start_ibss_wq);
2475 ieee80211_stop_scan(ieee);
2476
2477 ieee80211_disassociate(ieee);
2478 RemoveAllTS(ieee);
2479}
2480
2481void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee)
2482{
2483 ieee->sync_scan_hurryup = 0;
2484 mutex_lock(&ieee->wx_mutex);
2485 ieee80211_start_protocol(ieee);
2486 mutex_unlock(&ieee->wx_mutex);
2487}
2488EXPORT_SYMBOL(ieee80211_softmac_start_protocol);
2489
2490void ieee80211_start_protocol(struct ieee80211_device *ieee)
2491{
2492 short ch = 0;
2493 int i = 0;
2494
2495 if (ieee->proto_started)
2496 return;
2497
2498 ieee->proto_started = 1;
2499
2500 if (ieee->current_network.channel == 0) {
2501 do {
2502 ch++;
2503 if (ch > MAX_CHANNEL_NUMBER)
2504 return;
2505 } while (!GET_DOT11D_INFO(ieee)->channel_map[ch]);
2506 ieee->current_network.channel = ch;
2507 }
2508
2509 if (ieee->current_network.beacon_interval == 0)
2510 ieee->current_network.beacon_interval = 100;
2511
2512
2513
2514 for (i = 0; i < 17; i++) {
2515 ieee->last_rxseq_num[i] = -1;
2516 ieee->last_rxfrag_num[i] = -1;
2517 ieee->last_packet_time[i] = 0;
2518 }
2519
2520 ieee->init_wmmparam_flag = 0;
2521
2522
2523
2524
2525
2526
2527 if (ieee->iw_mode == IW_MODE_INFRA)
2528 ieee80211_start_bss(ieee);
2529
2530 else if (ieee->iw_mode == IW_MODE_ADHOC)
2531 ieee80211_start_ibss(ieee);
2532
2533 else if (ieee->iw_mode == IW_MODE_MASTER)
2534 ieee80211_start_master_bss(ieee);
2535
2536 else if (ieee->iw_mode == IW_MODE_MONITOR)
2537 ieee80211_start_monitor_mode(ieee);
2538}
2539
2540#define DRV_NAME "Ieee80211"
2541void ieee80211_softmac_init(struct ieee80211_device *ieee)
2542{
2543 int i;
2544 memset(&ieee->current_network, 0, sizeof(struct ieee80211_network));
2545
2546 ieee->state = IEEE80211_NOLINK;
2547 ieee->sync_scan_hurryup = 0;
2548 for (i = 0; i < 5; i++)
2549 ieee->seq_ctrl[i] = 0;
2550
2551 ieee->dot11d_info = kzalloc(sizeof(struct rt_dot11d_info), GFP_KERNEL);
2552 if (!ieee->dot11d_info)
2553 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for DOT11D\n");
2554
2555 ieee->LinkDetectInfo.SlotNum = 2;
2556 ieee->LinkDetectInfo.NumRecvBcnInPeriod = 0;
2557 ieee->LinkDetectInfo.NumRecvDataInPeriod = 0;
2558
2559 ieee->assoc_id = 0;
2560 ieee->queue_stop = 0;
2561 ieee->scanning = 0;
2562 ieee->softmac_features = 0;
2563 ieee->wap_set = 0;
2564 ieee->ssid_set = 0;
2565 ieee->proto_started = 0;
2566 ieee->basic_rate = IEEE80211_DEFAULT_BASIC_RATE;
2567 ieee->rate = 22;
2568 ieee->ps = IEEE80211_PS_DISABLED;
2569 ieee->sta_sleep = 0;
2570 ieee->Regdot11HTOperationalRateSet[0] = 0xff;
2571 ieee->Regdot11HTOperationalRateSet[1] = 0xff;
2572 ieee->Regdot11HTOperationalRateSet[4] = 0x01;
2573
2574 ieee->actscanning = false;
2575 ieee->beinretry = false;
2576 ieee->is_set_key = false;
2577 init_mgmt_queue(ieee);
2578
2579 ieee->sta_edca_param[0] = 0x0000A403;
2580 ieee->sta_edca_param[1] = 0x0000A427;
2581 ieee->sta_edca_param[2] = 0x005E4342;
2582 ieee->sta_edca_param[3] = 0x002F3262;
2583 ieee->aggregation = true;
2584 ieee->enable_rx_imm_BA = true;
2585 ieee->tx_pending.txb = NULL;
2586
2587 timer_setup(&ieee->associate_timer, ieee80211_associate_abort_cb, 0);
2588
2589 timer_setup(&ieee->beacon_timer, ieee80211_send_beacon_cb, 0);
2590
2591 INIT_DELAYED_WORK(&ieee->start_ibss_wq, ieee80211_start_ibss_wq);
2592 INIT_WORK(&ieee->associate_complete_wq, ieee80211_associate_complete_wq);
2593 INIT_WORK(&ieee->associate_procedure_wq, ieee80211_associate_procedure_wq);
2594 INIT_DELAYED_WORK(&ieee->softmac_scan_wq, ieee80211_softmac_scan_wq);
2595 INIT_DELAYED_WORK(&ieee->associate_retry_wq, ieee80211_associate_retry_wq);
2596 INIT_WORK(&ieee->wx_sync_scan_wq, ieee80211_wx_sync_scan_wq);
2597
2598 mutex_init(&ieee->wx_mutex);
2599 mutex_init(&ieee->scan_mutex);
2600
2601 spin_lock_init(&ieee->mgmt_tx_lock);
2602 spin_lock_init(&ieee->beacon_lock);
2603
2604 tasklet_setup(&ieee->ps_task, ieee80211_sta_ps);
2605}
2606
2607void ieee80211_softmac_free(struct ieee80211_device *ieee)
2608{
2609 mutex_lock(&ieee->wx_mutex);
2610 kfree(ieee->dot11d_info);
2611 ieee->dot11d_info = NULL;
2612 del_timer_sync(&ieee->associate_timer);
2613
2614 cancel_delayed_work(&ieee->associate_retry_wq);
2615
2616 mutex_unlock(&ieee->wx_mutex);
2617}
2618
2619
2620
2621
2622
2623static int ieee80211_wpa_enable(struct ieee80211_device *ieee, int value)
2624{
2625
2626
2627 printk("%s WPA\n", value ? "enabling" : "disabling");
2628 ieee->wpa_enabled = value;
2629 return 0;
2630}
2631
2632static void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee,
2633 char *wpa_ie, int wpa_ie_len)
2634{
2635
2636 ieee80211_wpa_enable(ieee, 1);
2637
2638 ieee80211_disassociate(ieee);
2639}
2640
2641static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command, int reason)
2642{
2643 int ret = 0;
2644
2645 switch (command) {
2646 case IEEE_MLME_STA_DEAUTH:
2647
2648 break;
2649
2650 case IEEE_MLME_STA_DISASSOC:
2651 ieee80211_disassociate(ieee);
2652 break;
2653
2654 default:
2655 printk("Unknown MLME request: %d\n", command);
2656 ret = -EOPNOTSUPP;
2657 }
2658
2659 return ret;
2660}
2661
2662static int ieee80211_wpa_set_wpa_ie(struct ieee80211_device *ieee,
2663 struct ieee_param *param, int plen)
2664{
2665 u8 *buf;
2666
2667 if (param->u.wpa_ie.len > MAX_WPA_IE_LEN)
2668 return -EINVAL;
2669
2670 if (param->u.wpa_ie.len) {
2671 buf = kmemdup(param->u.wpa_ie.data, param->u.wpa_ie.len,
2672 GFP_KERNEL);
2673 if (!buf)
2674 return -ENOMEM;
2675
2676 kfree(ieee->wpa_ie);
2677 ieee->wpa_ie = buf;
2678 ieee->wpa_ie_len = param->u.wpa_ie.len;
2679 } else {
2680 kfree(ieee->wpa_ie);
2681 ieee->wpa_ie = NULL;
2682 ieee->wpa_ie_len = 0;
2683 }
2684
2685 ieee80211_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len);
2686 return 0;
2687}
2688
2689#define AUTH_ALG_OPEN_SYSTEM 0x1
2690#define AUTH_ALG_SHARED_KEY 0x2
2691
2692static int ieee80211_wpa_set_auth_algs(struct ieee80211_device *ieee, int value)
2693{
2694 struct ieee80211_security sec = {
2695 .flags = SEC_AUTH_MODE,
2696 };
2697
2698 if (value & AUTH_ALG_SHARED_KEY) {
2699 sec.auth_mode = WLAN_AUTH_SHARED_KEY;
2700 ieee->open_wep = 0;
2701 ieee->auth_mode = 1;
2702 } else if (value & AUTH_ALG_OPEN_SYSTEM) {
2703 sec.auth_mode = WLAN_AUTH_OPEN;
2704 ieee->open_wep = 1;
2705 ieee->auth_mode = 0;
2706 } else if (value & IW_AUTH_ALG_LEAP) {
2707 sec.auth_mode = WLAN_AUTH_LEAP;
2708 ieee->open_wep = 1;
2709 ieee->auth_mode = 2;
2710 }
2711
2712 if (ieee->set_security)
2713 ieee->set_security(ieee->dev, &sec);
2714
2715
2716
2717 return 0;
2718}
2719
2720static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name, u32 value)
2721{
2722 int ret = 0;
2723 unsigned long flags;
2724
2725 switch (name) {
2726 case IEEE_PARAM_WPA_ENABLED:
2727 ret = ieee80211_wpa_enable(ieee, value);
2728 break;
2729
2730 case IEEE_PARAM_TKIP_COUNTERMEASURES:
2731 ieee->tkip_countermeasures = value;
2732 break;
2733
2734 case IEEE_PARAM_DROP_UNENCRYPTED: {
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746 struct ieee80211_security sec = {
2747 .flags = SEC_ENABLED,
2748 .enabled = value,
2749 };
2750 ieee->drop_unencrypted = value;
2751
2752
2753
2754 if (!value) {
2755 sec.flags |= SEC_LEVEL;
2756 sec.level = SEC_LEVEL_0;
2757 } else {
2758 sec.flags |= SEC_LEVEL;
2759 sec.level = SEC_LEVEL_1;
2760 }
2761 if (ieee->set_security)
2762 ieee->set_security(ieee->dev, &sec);
2763 break;
2764 }
2765
2766 case IEEE_PARAM_PRIVACY_INVOKED:
2767 ieee->privacy_invoked = value;
2768 break;
2769
2770 case IEEE_PARAM_AUTH_ALGS:
2771 ret = ieee80211_wpa_set_auth_algs(ieee, value);
2772 break;
2773
2774 case IEEE_PARAM_IEEE_802_1X:
2775 ieee->ieee802_1x = value;
2776 break;
2777 case IEEE_PARAM_WPAX_SELECT:
2778
2779 spin_lock_irqsave(&ieee->wpax_suitlist_lock, flags);
2780 ieee->wpax_type_set = 1;
2781 ieee->wpax_type_notify = value;
2782 spin_unlock_irqrestore(&ieee->wpax_suitlist_lock, flags);
2783 break;
2784
2785 default:
2786 printk("Unknown WPA param: %d\n", name);
2787 ret = -EOPNOTSUPP;
2788 }
2789
2790 return ret;
2791}
2792
2793
2794static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
2795 struct ieee_param *param, int param_len)
2796{
2797 int ret = 0;
2798 const char *module = NULL;
2799
2800 struct ieee80211_crypto_ops *ops = NULL;
2801 struct ieee80211_crypt_data **crypt;
2802
2803 struct ieee80211_security sec = {
2804 .flags = 0,
2805 };
2806
2807 param->u.crypt.err = 0;
2808 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
2809
2810 if (param_len !=
2811 (int)((char *)param->u.crypt.key - (char *)param) +
2812 param->u.crypt.key_len) {
2813 printk("Len mismatch %d, %d\n", param_len,
2814 param->u.crypt.key_len);
2815 return -EINVAL;
2816 }
2817 if (is_broadcast_ether_addr(param->sta_addr)) {
2818 if (param->u.crypt.idx >= WEP_KEYS)
2819 return -EINVAL;
2820 crypt = &ieee->crypt[param->u.crypt.idx];
2821 } else {
2822 return -EINVAL;
2823 }
2824
2825 if (strcmp(param->u.crypt.alg, "none") == 0) {
2826 if (crypt) {
2827 sec.enabled = 0;
2828
2829
2830 sec.level = SEC_LEVEL_0;
2831 sec.flags |= SEC_ENABLED | SEC_LEVEL;
2832 ieee80211_crypt_delayed_deinit(ieee, crypt);
2833 }
2834 goto done;
2835 }
2836 sec.enabled = 1;
2837
2838
2839 sec.flags |= SEC_ENABLED;
2840
2841
2842 if (!(ieee->host_encrypt || ieee->host_decrypt) &&
2843 strcmp(param->u.crypt.alg, "TKIP"))
2844 goto skip_host_crypt;
2845
2846
2847 if (!strcmp(param->u.crypt.alg, "WEP"))
2848 module = "ieee80211_crypt_wep";
2849 else if (!strcmp(param->u.crypt.alg, "TKIP"))
2850 module = "ieee80211_crypt_tkip";
2851 else if (!strcmp(param->u.crypt.alg, "CCMP"))
2852 module = "ieee80211_crypt_ccmp";
2853 if (module)
2854 ops = try_then_request_module(ieee80211_get_crypto_ops(param->u.crypt.alg),
2855 module);
2856 if (!ops) {
2857 printk("unknown crypto alg '%s'\n", param->u.crypt.alg);
2858 param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
2859 ret = -EINVAL;
2860 goto done;
2861 }
2862
2863 if (!*crypt || (*crypt)->ops != ops) {
2864 struct ieee80211_crypt_data *new_crypt;
2865
2866 ieee80211_crypt_delayed_deinit(ieee, crypt);
2867
2868 new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
2869 if (!new_crypt) {
2870 ret = -ENOMEM;
2871 goto done;
2872 }
2873 new_crypt->ops = ops;
2874 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
2875 new_crypt->priv =
2876 new_crypt->ops->init(param->u.crypt.idx);
2877
2878 if (!new_crypt->priv) {
2879 kfree(new_crypt);
2880 param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED;
2881 ret = -EINVAL;
2882 goto done;
2883 }
2884
2885 *crypt = new_crypt;
2886 }
2887
2888 if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key &&
2889 (*crypt)->ops->set_key(param->u.crypt.key,
2890 param->u.crypt.key_len, param->u.crypt.seq,
2891 (*crypt)->priv) < 0) {
2892 printk("key setting failed\n");
2893 param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED;
2894 ret = -EINVAL;
2895 goto done;
2896 }
2897
2898 skip_host_crypt:
2899 if (param->u.crypt.set_tx) {
2900 ieee->tx_keyidx = param->u.crypt.idx;
2901 sec.active_key = param->u.crypt.idx;
2902 sec.flags |= SEC_ACTIVE_KEY;
2903 } else {
2904 sec.flags &= ~SEC_ACTIVE_KEY;
2905 }
2906 memcpy(sec.keys[param->u.crypt.idx],
2907 param->u.crypt.key,
2908 param->u.crypt.key_len);
2909 sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len;
2910 sec.flags |= (1 << param->u.crypt.idx);
2911
2912 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
2913 sec.flags |= SEC_LEVEL;
2914 sec.level = SEC_LEVEL_1;
2915 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
2916 sec.flags |= SEC_LEVEL;
2917 sec.level = SEC_LEVEL_2;
2918 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
2919 sec.flags |= SEC_LEVEL;
2920 sec.level = SEC_LEVEL_3;
2921 }
2922 done:
2923 if (ieee->set_security)
2924 ieee->set_security(ieee->dev, &sec);
2925
2926
2927
2928
2929
2930
2931 if (ieee->reset_on_keychange &&
2932 ieee->iw_mode != IW_MODE_INFRA &&
2933 ieee->reset_port &&
2934 ieee->reset_port(ieee->dev)) {
2935 printk("reset_port failed\n");
2936 param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED;
2937 return -EINVAL;
2938 }
2939
2940 return ret;
2941}
2942
2943static inline struct sk_buff *ieee80211_disassociate_skb(struct ieee80211_network *beacon,
2944 struct ieee80211_device *ieee,
2945 u8 asRsn)
2946{
2947 struct sk_buff *skb;
2948 struct ieee80211_disassoc *disass;
2949
2950 skb = dev_alloc_skb(sizeof(struct ieee80211_disassoc));
2951 if (!skb)
2952 return NULL;
2953
2954 disass = skb_put(skb, sizeof(struct ieee80211_disassoc));
2955 disass->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_DISASSOC);
2956 disass->header.duration_id = 0;
2957
2958 memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN);
2959 memcpy(disass->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
2960 memcpy(disass->header.addr3, beacon->bssid, ETH_ALEN);
2961
2962 disass->reason = cpu_to_le16(asRsn);
2963 return skb;
2964}
2965
2966void
2967SendDisassociation(struct ieee80211_device *ieee,
2968 u8 *asSta,
2969 u8 asRsn
2970)
2971{
2972 struct ieee80211_network *beacon = &ieee->current_network;
2973 struct sk_buff *skb;
2974
2975 skb = ieee80211_disassociate_skb(beacon, ieee, asRsn);
2976 if (skb) {
2977 softmac_mgmt_xmit(skb, ieee);
2978
2979 }
2980}
2981EXPORT_SYMBOL(SendDisassociation);
2982
2983int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p)
2984{
2985 struct ieee_param *param;
2986 int ret = 0;
2987
2988 mutex_lock(&ieee->wx_mutex);
2989
2990
2991 if (p->length < sizeof(struct ieee_param) || !p->pointer) {
2992 ret = -EINVAL;
2993 goto out;
2994 }
2995
2996 param = memdup_user(p->pointer, p->length);
2997 if (IS_ERR(param)) {
2998 ret = PTR_ERR(param);
2999 goto out;
3000 }
3001
3002 switch (param->cmd) {
3003 case IEEE_CMD_SET_WPA_PARAM:
3004 ret = ieee80211_wpa_set_param(ieee, param->u.wpa_param.name,
3005 param->u.wpa_param.value);
3006 break;
3007
3008 case IEEE_CMD_SET_WPA_IE:
3009 ret = ieee80211_wpa_set_wpa_ie(ieee, param, p->length);
3010 break;
3011
3012 case IEEE_CMD_SET_ENCRYPTION:
3013 ret = ieee80211_wpa_set_encryption(ieee, param, p->length);
3014 break;
3015
3016 case IEEE_CMD_MLME:
3017 ret = ieee80211_wpa_mlme(ieee, param->u.mlme.command,
3018 param->u.mlme.reason_code);
3019 break;
3020
3021 default:
3022 printk("Unknown WPA supplicant request: %d\n", param->cmd);
3023 ret = -EOPNOTSUPP;
3024 break;
3025 }
3026
3027 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
3028 ret = -EFAULT;
3029
3030 kfree(param);
3031out:
3032 mutex_unlock(&ieee->wx_mutex);
3033
3034 return ret;
3035}
3036EXPORT_SYMBOL(ieee80211_wpa_supplicant_ioctl);
3037
3038void notify_wx_assoc_event(struct ieee80211_device *ieee)
3039{
3040 union iwreq_data wrqu;
3041
3042 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3043 if (ieee->state == IEEE80211_LINKED)
3044 memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN);
3045 else
3046 eth_zero_addr(wrqu.ap_addr.sa_data);
3047 wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL);
3048}
3049EXPORT_SYMBOL(notify_wx_assoc_event);
3050