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