• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/drivers/staging/rtl8187se/ieee80211/
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"
38static const char *ieee80211_modes[] = {
39	"?", "a", "b", "ab", "g", "ag", "bg", "abg"
40};
41
42#define MAX_CUSTOM_LEN 64
43static 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
204int 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
254int 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
423int 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
474int 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 //skip_host_crypt:
596	//printk("skip_host_crypt:ext_flags:%x\n", ext->ext_flags);
597        if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
598                ieee->tx_keyidx = idx;
599                sec.active_key = idx;
600                sec.flags |= SEC_ACTIVE_KEY;
601        }
602
603        if (ext->alg != IW_ENCODE_ALG_NONE) {
604                memcpy(sec.keys[idx], ext->key, ext->key_len);
605                sec.key_sizes[idx] = ext->key_len;
606                sec.flags |= (1 << idx);
607                if (ext->alg == IW_ENCODE_ALG_WEP) {
608                      //  sec.encode_alg[idx] = SEC_ALG_WEP;
609                        sec.flags |= SEC_LEVEL;
610                        sec.level = SEC_LEVEL_1;
611                } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
612                      //  sec.encode_alg[idx] = SEC_ALG_TKIP;
613                        sec.flags |= SEC_LEVEL;
614                        sec.level = SEC_LEVEL_2;
615                } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
616                       // sec.encode_alg[idx] = SEC_ALG_CCMP;
617                        sec.flags |= SEC_LEVEL;
618                        sec.level = SEC_LEVEL_3;
619                }
620                /* Don't set sec level for group keys. */
621                if (group_key)
622                        sec.flags &= ~SEC_LEVEL;
623        }
624done:
625        if (ieee->set_security)
626                ieee->set_security(ieee->dev, &sec);
627
628	 if (ieee->reset_on_keychange &&
629            ieee->iw_mode != IW_MODE_INFRA &&
630            ieee->reset_port && ieee->reset_port(dev)) {
631                IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
632                return -EINVAL;
633        }
634
635        return ret;
636}
637int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
638                               struct iw_request_info *info,
639                               union iwreq_data *wrqu, char *extra)
640{
641	struct iw_mlme *mlme = (struct iw_mlme *) extra;
642//	printk("\ndkgadfslkdjgalskdf===============>%s(), cmd:%x\n", __func__, mlme->cmd);
643	switch (mlme->cmd) {
644        case IW_MLME_DEAUTH:
645	case IW_MLME_DISASSOC:
646	//	printk("disassoc now\n");
647		ieee80211_disassociate(ieee);
648		break;
649	 default:
650                return -EOPNOTSUPP;
651        }
652	return 0;
653}
654
655int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
656                               struct iw_request_info *info,
657                               struct iw_param *data, char *extra)
658{
659/*
660	 struct ieee80211_security sec = {
661                .flags = SEC_AUTH_MODE,
662	}
663*/
664	//printk("set auth:flag:%x, data value:%x\n", data->flags, data->value);
665	switch (data->flags & IW_AUTH_INDEX) {
666        case IW_AUTH_WPA_VERSION:
667	     /*need to support wpa2 here*/
668		//printk("wpa version:%x\n", data->value);
669		break;
670        case IW_AUTH_CIPHER_PAIRWISE:
671        case IW_AUTH_CIPHER_GROUP:
672        case IW_AUTH_KEY_MGMT:
673                /*
674 *                  * Host AP driver does not use these parameters and allows
675 *                                   * wpa_supplicant to control them internally.
676 *                                                    */
677                break;
678        case IW_AUTH_TKIP_COUNTERMEASURES:
679                ieee->tkip_countermeasures = data->value;
680                break;
681        case IW_AUTH_DROP_UNENCRYPTED:
682                ieee->drop_unencrypted = data->value;
683		break;
684
685	case IW_AUTH_80211_AUTH_ALG:
686		ieee->open_wep = (data->value&IW_AUTH_ALG_OPEN_SYSTEM)?1:0;
687		//printk("open_wep:%d\n", ieee->open_wep);
688		break;
689
690	case IW_AUTH_WPA_ENABLED:
691		ieee->wpa_enabled = (data->value)?1:0;
692		//printk("enable wpa:%d\n", ieee->wpa_enabled);
693		break;
694	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
695                ieee->ieee802_1x = data->value;
696		break;
697	case IW_AUTH_PRIVACY_INVOKED:
698		ieee->privacy_invoked = data->value;
699		break;
700	default:
701                return -EOPNOTSUPP;
702	}
703	return 0;
704}
705
706int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
707{
708	u8 *buf = NULL;
709
710	if (len>MAX_WPA_IE_LEN || (len && ie == NULL))
711	{
712		printk("return error out, len:%zu\n", len);
713	return -EINVAL;
714	}
715
716	if (len)
717	{
718		if (len != ie[1]+2){
719			printk("len:%zu, ie:%d\n", len, ie[1]);
720			return -EINVAL;
721		}
722		buf = kmemdup(ie, len, GFP_KERNEL);
723		if (buf == NULL)
724			return -ENOMEM;
725		kfree(ieee->wpa_ie);
726		ieee->wpa_ie = buf;
727		ieee->wpa_ie_len = len;
728	}
729	else{
730		if (ieee->wpa_ie)
731		kfree(ieee->wpa_ie);
732		ieee->wpa_ie = NULL;
733		ieee->wpa_ie_len = 0;
734	}
735//	printk("<=====out %s()\n", __func__);
736
737	return 0;
738
739}
740