aa3ba450eceffc9a0e8ef5d51c9e312106fda967
[safe/jmp/linux-2.6] / drivers / staging / rtl8187se / ieee80211 / ieee80211_wx.c
1 /******************************************************************************
2
3   Copyright(c) 2004 Intel Corporation. All rights reserved.
4
5   Portions of this file are based on the WEP enablement code provided by the
6   Host AP project hostap-drivers v0.1.3
7   Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
8   <jkmaline@cc.hut.fi>
9   Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
10
11   This program is free software; you can redistribute it and/or modify it
12   under the terms of version 2 of the GNU General Public License as
13   published by the Free Software Foundation.
14
15   This program is distributed in the hope that it will be useful, but WITHOUT
16   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
18   more details.
19
20   You should have received a copy of the GNU General Public License along with
21   this program; if not, write to the Free Software Foundation, Inc., 59
22   Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23
24   The full GNU General Public License is included in this distribution in the
25   file called LICENSE.
26
27   Contact Information:
28   James P. Ketrenos <ipw2100-admin@linux.intel.com>
29   Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
30
31 ******************************************************************************/
32 #include <linux/wireless.h>
33 #include <linux/kmod.h>
34 #include <linux/slab.h>
35 #include <linux/module.h>
36
37 #include "ieee80211.h"
38 static const char *ieee80211_modes[] = {
39         "?", "a", "b", "ab", "g", "ag", "bg", "abg"
40 };
41
42 #define MAX_CUSTOM_LEN 64
43 static inline char *rtl818x_translate_scan(struct ieee80211_device *ieee,
44                                            char *start, char *stop,
45                                            struct ieee80211_network *network,
46                                            struct iw_request_info *info)
47 {
48         char custom[MAX_CUSTOM_LEN];
49         char *p;
50         struct iw_event iwe;
51         int i, j;
52         u8 max_rate, rate;
53
54         /* First entry *MUST* be the AP MAC address */
55         iwe.cmd = SIOCGIWAP;
56         iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
57         memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN);
58         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
59
60         /* Remaining entries will be displayed in the order we provide them */
61
62         /* Add the ESSID */
63         iwe.cmd = SIOCGIWESSID;
64         iwe.u.data.flags = 1;
65         //YJ,modified,080903,for hidden ap
66         //if (network->flags & NETWORK_EMPTY_ESSID) {
67         if (network->ssid_len == 0) {
68         //YJ,modified,080903,end
69                 iwe.u.data.length = sizeof("<hidden>");
70                 start = iwe_stream_add_point(info, start, stop, &iwe, "<hidden>");
71         } else {
72                 iwe.u.data.length = min(network->ssid_len, (u8)32);
73                 start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
74         }
75         //printk("ESSID: %s\n",network->ssid);
76         /* Add the protocol name */
77         iwe.cmd = SIOCGIWNAME;
78         snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11%s", ieee80211_modes[network->mode]);
79         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
80
81         /* Add mode */
82         iwe.cmd = SIOCGIWMODE;
83         if (network->capability &
84             (WLAN_CAPABILITY_BSS | WLAN_CAPABILITY_IBSS)) {
85                 if (network->capability & WLAN_CAPABILITY_BSS)
86                         iwe.u.mode = IW_MODE_MASTER;
87                 else
88                         iwe.u.mode = IW_MODE_ADHOC;
89
90                 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
91         }
92
93         /* Add frequency/channel */
94         iwe.cmd = SIOCGIWFREQ;
95 /*      iwe.u.freq.m = ieee80211_frequency(network->channel, network->mode);
96         iwe.u.freq.e = 3; */
97         iwe.u.freq.m = network->channel;
98         iwe.u.freq.e = 0;
99         iwe.u.freq.i = 0;
100         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
101
102         /* Add encryption capability */
103         iwe.cmd = SIOCGIWENCODE;
104         if (network->capability & WLAN_CAPABILITY_PRIVACY)
105                 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
106         else
107                 iwe.u.data.flags = IW_ENCODE_DISABLED;
108         iwe.u.data.length = 0;
109         start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
110
111         /* Add basic and extended rates */
112         max_rate = 0;
113         p = custom;
114         p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
115         for (i = 0, j = 0; i < network->rates_len; ) {
116                 if (j < network->rates_ex_len &&
117                     ((network->rates_ex[j] & 0x7F) <
118                      (network->rates[i] & 0x7F)))
119                         rate = network->rates_ex[j++] & 0x7F;
120                 else
121                         rate = network->rates[i++] & 0x7F;
122                 if (rate > max_rate)
123                         max_rate = rate;
124                 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
125                               "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
126         }
127         for (; j < network->rates_ex_len; j++) {
128                 rate = network->rates_ex[j] & 0x7F;
129                 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
130                               "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
131                 if (rate > max_rate)
132                         max_rate = rate;
133         }
134
135         iwe.cmd = SIOCGIWRATE;
136         iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
137         iwe.u.bitrate.value = max_rate * 500000;
138         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_PARAM_LEN);
139
140         iwe.cmd = IWEVCUSTOM;
141         iwe.u.data.length = p - custom;
142         if (iwe.u.data.length)
143                 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
144
145         /* Add quality statistics */
146         /* TODO: Fix these values... */
147         if (network->stats.signal == 0 || network->stats.rssi == 0)
148         printk("========>signal:%d, rssi:%d\n", network->stats.signal, network->stats.rssi);
149         iwe.cmd = IWEVQUAL;
150 //      printk("SIGNAL: %d,RSSI: %d,NOISE: %d\n",network->stats.signal,network->stats.rssi,network->stats.noise);
151         iwe.u.qual.qual = network->stats.signalstrength;
152         iwe.u.qual.level = network->stats.signal;
153         iwe.u.qual.noise = network->stats.noise;
154         iwe.u.qual.updated = network->stats.mask & IEEE80211_STATMASK_WEMASK;
155         if (!(network->stats.mask & IEEE80211_STATMASK_RSSI))
156                 iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
157         if (!(network->stats.mask & IEEE80211_STATMASK_NOISE))
158                 iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
159         if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL))
160                 iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID;
161         iwe.u.qual.updated = 7;
162         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
163
164         iwe.cmd = IWEVCUSTOM;
165         p = custom;
166
167         iwe.u.data.length = p - custom;
168         if (iwe.u.data.length)
169                 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
170
171                 memset(&iwe, 0, sizeof(iwe));
172         if (network->wpa_ie_len) {
173         //      printk("wpa_ie_len:%d\n", network->wpa_ie_len);
174                 char buf[MAX_WPA_IE_LEN];
175                 memcpy(buf, network->wpa_ie, network->wpa_ie_len);
176                 iwe.cmd = IWEVGENIE;
177                 iwe.u.data.length = network->wpa_ie_len;
178                 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
179         }
180
181         memset(&iwe, 0, sizeof(iwe));
182         if (network->rsn_ie_len) {
183         //      printk("=====>rsn_ie_len:\n", network->rsn_ie_len);
184                 char buf[MAX_WPA_IE_LEN];
185                 memcpy(buf, network->rsn_ie, network->rsn_ie_len);
186                 iwe.cmd = IWEVGENIE;
187                 iwe.u.data.length = network->rsn_ie_len;
188                 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
189         }
190
191         /* Add EXTRA: Age to display seconds since last beacon/probe response
192          * for given network. */
193         iwe.cmd = IWEVCUSTOM;
194         p = custom;
195         p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
196                       " Last beacon: %lums ago", (jiffies - network->last_scanned) / (HZ / 100));
197         iwe.u.data.length = p - custom;
198         if (iwe.u.data.length)
199                 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
200
201         return start;
202 }
203
204 int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
205                           struct iw_request_info *info,
206                           union iwreq_data *wrqu, char *extra)
207 {
208         struct ieee80211_network *network;
209         unsigned long flags;
210         int err = 0;
211         char *ev = extra;
212         char *stop = ev + wrqu->data.length;//IW_SCAN_MAX_DATA;
213         //char *stop = ev + IW_SCAN_MAX_DATA;
214         int i = 0;
215
216         IEEE80211_DEBUG_WX("Getting scan\n");
217         down(&ieee->wx_sem);
218         spin_lock_irqsave(&ieee->lock, flags);
219
220         if(!ieee->bHwRadioOff)
221         {
222                 list_for_each_entry(network, &ieee->network_list, list) {
223                         i++;
224
225                         if((stop-ev)<200)
226                         {
227                                 err = -E2BIG;
228                                 break;
229                         }
230                         if (ieee->scan_age == 0 ||
231                             time_after(network->last_scanned + ieee->scan_age, jiffies))
232                         {
233                                 ev = rtl818x_translate_scan(ieee, ev, stop, network, info);
234                         }
235                         else
236                                 IEEE80211_DEBUG_SCAN(
237                                         "Not showing network '%s ("
238                                         "%pM)' due to age (%lums).\n",
239                                         escape_essid(network->ssid,
240                                                      network->ssid_len),
241                                         network->bssid,
242                                         (jiffies - network->last_scanned) / (HZ / 100));
243                 }
244         }
245         spin_unlock_irqrestore(&ieee->lock, flags);
246         up(&ieee->wx_sem);
247         wrqu->data.length = ev -  extra;
248         wrqu->data.flags = 0;
249         IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
250
251         return err;
252 }
253
254 int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
255                             struct iw_request_info *info,
256                             union iwreq_data *wrqu, char *keybuf)
257 {
258         struct iw_point *erq = &(wrqu->encoding);
259         struct net_device *dev = ieee->dev;
260         struct ieee80211_security sec = {
261                 .flags = 0
262         };
263         int i, key, key_provided, len;
264         struct ieee80211_crypt_data **crypt;
265
266         IEEE80211_DEBUG_WX("SET_ENCODE\n");
267
268         key = erq->flags & IW_ENCODE_INDEX;
269         if (key) {
270                 if (key > WEP_KEYS)
271                         return -EINVAL;
272                 key--;
273                 key_provided = 1;
274         } else {
275                 key_provided = 0;
276                 key = ieee->tx_keyidx;
277         }
278
279         IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
280                            "provided" : "default");
281
282         crypt = &ieee->crypt[key];
283
284         if (erq->flags & IW_ENCODE_DISABLED) {
285                 if (key_provided && *crypt) {
286                         IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
287                                            key);
288                         ieee80211_crypt_delayed_deinit(ieee, crypt);
289                 } else
290                         IEEE80211_DEBUG_WX("Disabling encryption.\n");
291
292                 /* Check all the keys to see if any are still configured,
293                  * and if no key index was provided, de-init them all */
294                 for (i = 0; i < WEP_KEYS; i++) {
295                         if (ieee->crypt[i] != NULL) {
296                                 if (key_provided)
297                                         break;
298                                 ieee80211_crypt_delayed_deinit(
299                                         ieee, &ieee->crypt[i]);
300                         }
301                 }
302
303                 if (i == WEP_KEYS) {
304                         sec.enabled = 0;
305                         sec.level = SEC_LEVEL_0;
306                         sec.flags |= SEC_ENABLED | SEC_LEVEL;
307                 }
308
309                 goto done;
310         }
311
312
313
314         sec.enabled = 1;
315         sec.flags |= SEC_ENABLED;
316
317         if (*crypt != NULL && (*crypt)->ops != NULL &&
318             strcmp((*crypt)->ops->name, "WEP") != 0) {
319                 /* changing to use WEP; deinit previously used algorithm
320                  * on this key */
321                 ieee80211_crypt_delayed_deinit(ieee, crypt);
322         }
323
324         if (*crypt == NULL) {
325                 struct ieee80211_crypt_data *new_crypt;
326
327                 /* take WEP into use */
328                 new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data),
329                                     GFP_KERNEL);
330                 if (new_crypt == NULL)
331                         return -ENOMEM;
332                 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
333                 if (!new_crypt->ops)
334                         new_crypt->ops = ieee80211_get_crypto_ops("WEP");
335
336                 if (new_crypt->ops)
337                         new_crypt->priv = new_crypt->ops->init(key);
338
339                 if (!new_crypt->ops || !new_crypt->priv) {
340                         kfree(new_crypt);
341                         new_crypt = NULL;
342
343                         printk(KERN_WARNING "%s: could not initialize WEP: "
344                                "load module ieee80211_crypt_wep\n",
345                                dev->name);
346                         return -EOPNOTSUPP;
347                 }
348                 *crypt = new_crypt;
349         }
350
351         /* If a new key was provided, set it up */
352         if (erq->length > 0) {
353                 len = erq->length <= 5 ? 5 : 13;
354                 memcpy(sec.keys[key], keybuf, erq->length);
355                 if (len > erq->length)
356                         memset(sec.keys[key] + erq->length, 0,
357                                len - erq->length);
358                 IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
359                                    key, escape_essid(sec.keys[key], len),
360                                    erq->length, len);
361                 sec.key_sizes[key] = len;
362                 (*crypt)->ops->set_key(sec.keys[key], len, NULL,
363                                        (*crypt)->priv);
364                 sec.flags |= (1 << key);
365                 /* This ensures a key will be activated if no key is
366                  * explicitely set */
367                 if (key == sec.active_key)
368                         sec.flags |= SEC_ACTIVE_KEY;
369                 ieee->tx_keyidx = key;//by wb 080312
370         } else {
371                 len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
372                                              NULL, (*crypt)->priv);
373                 if (len == 0) {
374                         /* Set a default key of all 0 */
375                         IEEE80211_DEBUG_WX("Setting key %d to all zero.\n",
376                                            key);
377                         memset(sec.keys[key], 0, 13);
378                         (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
379                                                (*crypt)->priv);
380                         sec.key_sizes[key] = 13;
381                         sec.flags |= (1 << key);
382                 }
383
384                 /* No key data - just set the default TX key index */
385                 if (key_provided) {
386                         IEEE80211_DEBUG_WX(
387                                 "Setting key %d to default Tx key.\n", key);
388                         ieee->tx_keyidx = key;
389                         sec.active_key = key;
390                         sec.flags |= SEC_ACTIVE_KEY;
391                 }
392         }
393
394  done:
395         ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
396         sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
397         sec.flags |= SEC_AUTH_MODE;
398         IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
399                            "OPEN" : "SHARED KEY");
400
401         /* For now we just support WEP, so only set that security level...
402          * TODO: When WPA is added this is one place that needs to change */
403         sec.flags |= SEC_LEVEL;
404         sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
405
406         if (ieee->set_security)
407                 ieee->set_security(dev, &sec);
408
409         /* Do not reset port if card is in Managed mode since resetting will
410          * generate new IEEE 802.11 authentication which may end up in looping
411          * with IEEE 802.1X.  If your hardware requires a reset after WEP
412          * configuration (for example... Prism2), implement the reset_port in
413          * the callbacks structures used to initialize the 802.11 stack. */
414         if (ieee->reset_on_keychange &&
415             ieee->iw_mode != IW_MODE_INFRA &&
416             ieee->reset_port && ieee->reset_port(dev)) {
417                 printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
418                 return -EINVAL;
419         }
420         return 0;
421 }
422
423 int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
424                             struct iw_request_info *info,
425                             union iwreq_data *wrqu, char *keybuf)
426 {
427         struct iw_point *erq = &(wrqu->encoding);
428         int len, key;
429         struct ieee80211_crypt_data *crypt;
430
431         IEEE80211_DEBUG_WX("GET_ENCODE\n");
432
433         if(ieee->iw_mode == IW_MODE_MONITOR)
434                 return -1;
435
436         key = erq->flags & IW_ENCODE_INDEX;
437         if (key) {
438                 if (key > WEP_KEYS)
439                         return -EINVAL;
440                 key--;
441         } else
442                 key = ieee->tx_keyidx;
443
444         crypt = ieee->crypt[key];
445         erq->flags = key + 1;
446
447         if (crypt == NULL || crypt->ops == NULL) {
448                 erq->length = 0;
449                 erq->flags |= IW_ENCODE_DISABLED;
450                 return 0;
451         }
452
453         if (strcmp(crypt->ops->name, "WEP") != 0) {
454                 /* only WEP is supported with wireless extensions, so just
455                  * report that encryption is used */
456                 erq->length = 0;
457                 erq->flags |= IW_ENCODE_ENABLED;
458                 return 0;
459         }
460
461         len = crypt->ops->get_key(keybuf, WEP_KEY_LEN, NULL, crypt->priv);
462         erq->length = (len >= 0 ? len : 0);
463
464         erq->flags |= IW_ENCODE_ENABLED;
465
466         if (ieee->open_wep)
467                 erq->flags |= IW_ENCODE_OPEN;
468         else
469                 erq->flags |= IW_ENCODE_RESTRICTED;
470
471         return 0;
472 }
473
474 int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
475                                struct iw_request_info *info,
476                                union iwreq_data *wrqu, char *extra)
477 {
478         struct net_device *dev = ieee->dev;
479         struct iw_point *encoding = &wrqu->encoding;
480         struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
481         int i, idx, ret = 0;
482         int group_key = 0;
483         const char *alg;
484         struct ieee80211_crypto_ops *ops;
485         struct ieee80211_crypt_data **crypt;
486
487         struct ieee80211_security sec = {
488                 .flags = 0,
489         };
490         //printk("======>encoding flag:%x,ext flag:%x, ext alg:%d\n", encoding->flags,ext->ext_flags, ext->alg);
491         idx = encoding->flags & IW_ENCODE_INDEX;
492         if (idx) {
493                 if (idx < 1 || idx > WEP_KEYS)
494                         return -EINVAL;
495                 idx--;
496         } else
497                 idx = ieee->tx_keyidx;
498
499         if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
500                 crypt = &ieee->crypt[idx];
501                 group_key = 1;
502         } else {
503                 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
504                 //printk("not group key, flags:%x, ext->alg:%d\n", ext->ext_flags, ext->alg);
505                 if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
506                         return -EINVAL;
507                 if (ieee->iw_mode == IW_MODE_INFRA)
508                         crypt = &ieee->crypt[idx];
509                 else
510                         return -EINVAL;
511         }
512
513         sec.flags |= SEC_ENABLED;// | SEC_ENCRYPT;
514         if ((encoding->flags & IW_ENCODE_DISABLED) ||
515             ext->alg == IW_ENCODE_ALG_NONE) {
516                 if (*crypt)
517                         ieee80211_crypt_delayed_deinit(ieee, crypt);
518
519                 for (i = 0; i < WEP_KEYS; i++)
520                         if (ieee->crypt[i] != NULL)
521                                 break;
522
523                 if (i == WEP_KEYS) {
524                         sec.enabled = 0;
525                       //  sec.encrypt = 0;
526                         sec.level = SEC_LEVEL_0;
527                         sec.flags |= SEC_LEVEL;
528                 }
529                 //printk("disabled: flag:%x\n", encoding->flags);
530                 goto done;
531         }
532
533         sec.enabled = 1;
534     //    sec.encrypt = 1;
535
536         switch (ext->alg) {
537         case IW_ENCODE_ALG_WEP:
538                 alg = "WEP";
539                 break;
540         case IW_ENCODE_ALG_TKIP:
541                 alg = "TKIP";
542                 break;
543         case IW_ENCODE_ALG_CCMP:
544                 alg = "CCMP";
545                 break;
546         default:
547                 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
548                                    dev->name, ext->alg);
549                 ret = -EINVAL;
550                 goto done;
551         }
552 //      printk("8-09-08-9=====>%s, alg name:%s\n",__func__, alg);
553
554          ops = ieee80211_get_crypto_ops(alg);
555         if (ops == NULL)
556                 ops = ieee80211_get_crypto_ops(alg);
557         if (ops == NULL) {
558                 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
559                                    dev->name, ext->alg);
560                 printk("========>unknown crypto alg %d\n", ext->alg);
561                 ret = -EINVAL;
562                 goto done;
563         }
564
565         if (*crypt == NULL || (*crypt)->ops != ops) {
566                 struct ieee80211_crypt_data *new_crypt;
567
568                 ieee80211_crypt_delayed_deinit(ieee, crypt);
569
570                 new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
571                 if (new_crypt == NULL) {
572                         ret = -ENOMEM;
573                         goto done;
574                 }
575                 new_crypt->ops = ops;
576                 if (new_crypt->ops)
577                         new_crypt->priv = new_crypt->ops->init(idx);
578                 if (new_crypt->priv == NULL) {
579                         kfree(new_crypt);
580                         ret = -EINVAL;
581                         goto done;
582                 }
583                 *crypt = new_crypt;
584
585         }
586
587         if (ext->key_len > 0 && (*crypt)->ops->set_key &&
588             (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
589                                    (*crypt)->priv) < 0) {
590                 IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
591                 printk("key setting failed\n");
592                 ret = -EINVAL;
593                 goto done;
594         }
595 #if 1
596  //skip_host_crypt:
597         //printk("skip_host_crypt:ext_flags:%x\n", ext->ext_flags);
598         if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
599                 ieee->tx_keyidx = idx;
600                 sec.active_key = idx;
601                 sec.flags |= SEC_ACTIVE_KEY;
602         }
603
604         if (ext->alg != IW_ENCODE_ALG_NONE) {
605                 memcpy(sec.keys[idx], ext->key, ext->key_len);
606                 sec.key_sizes[idx] = ext->key_len;
607                 sec.flags |= (1 << idx);
608                 if (ext->alg == IW_ENCODE_ALG_WEP) {
609                       //  sec.encode_alg[idx] = SEC_ALG_WEP;
610                         sec.flags |= SEC_LEVEL;
611                         sec.level = SEC_LEVEL_1;
612                 } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
613                       //  sec.encode_alg[idx] = SEC_ALG_TKIP;
614                         sec.flags |= SEC_LEVEL;
615                         sec.level = SEC_LEVEL_2;
616                 } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
617                        // sec.encode_alg[idx] = SEC_ALG_CCMP;
618                         sec.flags |= SEC_LEVEL;
619                         sec.level = SEC_LEVEL_3;
620                 }
621                 /* Don't set sec level for group keys. */
622                 if (group_key)
623                         sec.flags &= ~SEC_LEVEL;
624         }
625 #endif
626 done:
627         if (ieee->set_security)
628                 ieee->set_security(ieee->dev, &sec);
629
630          if (ieee->reset_on_keychange &&
631             ieee->iw_mode != IW_MODE_INFRA &&
632             ieee->reset_port && ieee->reset_port(dev)) {
633                 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
634                 return -EINVAL;
635         }
636
637         return ret;
638 }
639 int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
640                                struct iw_request_info *info,
641                                union iwreq_data *wrqu, char *extra)
642 {
643         struct iw_mlme *mlme = (struct iw_mlme *) extra;
644 //      printk("\ndkgadfslkdjgalskdf===============>%s(), cmd:%x\n", __func__, mlme->cmd);
645 #if 1
646         switch (mlme->cmd) {
647         case IW_MLME_DEAUTH:
648         case IW_MLME_DISASSOC:
649         //      printk("disassoc now\n");
650                 ieee80211_disassociate(ieee);
651                 break;
652          default:
653                 return -EOPNOTSUPP;
654         }
655 #endif
656         return 0;
657 }
658
659 int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
660                                struct iw_request_info *info,
661                                struct iw_param *data, char *extra)
662 {
663 /*
664          struct ieee80211_security sec = {
665                 .flags = SEC_AUTH_MODE,
666         }
667 */
668         //printk("set auth:flag:%x, data value:%x\n", data->flags, data->value);
669         switch (data->flags & IW_AUTH_INDEX) {
670         case IW_AUTH_WPA_VERSION:
671              /*need to support wpa2 here*/
672                 //printk("wpa version:%x\n", data->value);
673                 break;
674         case IW_AUTH_CIPHER_PAIRWISE:
675         case IW_AUTH_CIPHER_GROUP:
676         case IW_AUTH_KEY_MGMT:
677                 /*
678  *                  * Host AP driver does not use these parameters and allows
679  *                                   * wpa_supplicant to control them internally.
680  *                                                    */
681                 break;
682         case IW_AUTH_TKIP_COUNTERMEASURES:
683                 ieee->tkip_countermeasures = data->value;
684                 break;
685         case IW_AUTH_DROP_UNENCRYPTED:
686                 ieee->drop_unencrypted = data->value;
687                 break;
688
689         case IW_AUTH_80211_AUTH_ALG:
690                 ieee->open_wep = (data->value&IW_AUTH_ALG_OPEN_SYSTEM)?1:0;
691                 //printk("open_wep:%d\n", ieee->open_wep);
692                 break;
693
694 #if 1
695         case IW_AUTH_WPA_ENABLED:
696                 ieee->wpa_enabled = (data->value)?1:0;
697                 //printk("enable wpa:%d\n", ieee->wpa_enabled);
698                 break;
699
700 #endif
701         case IW_AUTH_RX_UNENCRYPTED_EAPOL:
702                 ieee->ieee802_1x = data->value;
703                 break;
704         case IW_AUTH_PRIVACY_INVOKED:
705                 ieee->privacy_invoked = data->value;
706                 break;
707         default:
708                 return -EOPNOTSUPP;
709         }
710         return 0;
711 }
712
713 #if 1
714 int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
715 {
716         u8 *buf = NULL;
717
718         if (len>MAX_WPA_IE_LEN || (len && ie == NULL))
719         {
720                 printk("return error out, len:%zu\n", len);
721         return -EINVAL;
722         }
723
724         if (len)
725         {
726                 if (len != ie[1]+2){
727                         printk("len:%zu, ie:%d\n", len, ie[1]);
728                         return -EINVAL;
729                 }
730                 buf = kmalloc(len, GFP_KERNEL);
731                 if (buf == NULL)
732                         return -ENOMEM;
733                 memcpy(buf, ie, len);
734                 kfree(ieee->wpa_ie);
735                 ieee->wpa_ie = buf;
736                 ieee->wpa_ie_len = len;
737         }
738         else{
739                 if (ieee->wpa_ie)
740                 kfree(ieee->wpa_ie);
741                 ieee->wpa_ie = NULL;
742                 ieee->wpa_ie_len = 0;
743         }
744 //      printk("<=====out %s()\n", __func__);
745
746         return 0;
747
748 }
749 #endif