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