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