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