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