• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/staging/rtl8192u/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"
38struct modes_unit {
39	char *mode_string;
40	int mode_size;
41};
42struct modes_unit ieee80211_modes[] = {
43	{"a",1},
44	{"b",1},
45	{"g",1},
46	{"?",1},
47	{"N-24G",5},
48	{"N-5G",4},
49};
50
51#define iwe_stream_add_event_rsl iwe_stream_add_event
52
53#define MAX_CUSTOM_LEN 64
54static inline char *rtl819x_translate_scan(struct ieee80211_device *ieee,
55					   char *start, char *stop,
56					   struct ieee80211_network *network,
57					   struct iw_request_info *info)
58{
59	char custom[MAX_CUSTOM_LEN];
60	char proto_name[IFNAMSIZ];
61	char *pname = proto_name;
62	char *p;
63	struct iw_event iwe;
64	int i, j;
65	u16 max_rate, rate;
66	static u8	EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33};
67
68	/* First entry *MUST* be the AP MAC address */
69	iwe.cmd = SIOCGIWAP;
70	iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
71	memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN);
72	start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_ADDR_LEN);
73	/* Remaining entries will be displayed in the order we provide them */
74
75	/* Add the ESSID */
76	iwe.cmd = SIOCGIWESSID;
77	iwe.u.data.flags = 1;
78//	if (network->flags & NETWORK_EMPTY_ESSID) {
79	if (network->ssid_len == 0) {
80		iwe.u.data.length = sizeof("<hidden>");
81		start = iwe_stream_add_point(info, start, stop, &iwe, "<hidden>");
82	} else {
83		iwe.u.data.length = min(network->ssid_len, (u8)32);
84		start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
85	}
86	/* Add the protocol name */
87	iwe.cmd = SIOCGIWNAME;
88	for(i=0; i<ARRAY_SIZE(ieee80211_modes); i++) {
89		if(network->mode&(1<<i)) {
90			sprintf(pname,ieee80211_modes[i].mode_string,ieee80211_modes[i].mode_size);
91			pname +=ieee80211_modes[i].mode_size;
92		}
93	}
94	*pname = '\0';
95	snprintf(iwe.u.name, IFNAMSIZ, "IEEE802.11%s", proto_name);
96	start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_CHAR_LEN);
97	/* Add mode */
98	iwe.cmd = SIOCGIWMODE;
99	if (network->capability &
100	    (WLAN_CAPABILITY_BSS | WLAN_CAPABILITY_IBSS)) {
101		if (network->capability & WLAN_CAPABILITY_BSS)
102			iwe.u.mode = IW_MODE_MASTER;
103		else
104			iwe.u.mode = IW_MODE_ADHOC;
105		start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_UINT_LEN);
106	}
107
108	/* Add frequency/channel */
109	iwe.cmd = SIOCGIWFREQ;
110/*	iwe.u.freq.m = ieee80211_frequency(network->channel, network->mode);
111	iwe.u.freq.e = 3; */
112	iwe.u.freq.m = network->channel;
113	iwe.u.freq.e = 0;
114	iwe.u.freq.i = 0;
115	start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_FREQ_LEN);
116	/* Add encryption capability */
117	iwe.cmd = SIOCGIWENCODE;
118	if (network->capability & WLAN_CAPABILITY_PRIVACY)
119		iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
120	else
121		iwe.u.data.flags = IW_ENCODE_DISABLED;
122	iwe.u.data.length = 0;
123	start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
124	/* Add basic and extended rates */
125	max_rate = 0;
126	p = custom;
127	p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
128	for (i = 0, j = 0; i < network->rates_len; ) {
129		if (j < network->rates_ex_len &&
130		    ((network->rates_ex[j] & 0x7F) <
131		     (network->rates[i] & 0x7F)))
132			rate = network->rates_ex[j++] & 0x7F;
133		else
134			rate = network->rates[i++] & 0x7F;
135		if (rate > max_rate)
136			max_rate = rate;
137		p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
138			      "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
139	}
140	for (; j < network->rates_ex_len; j++) {
141		rate = network->rates_ex[j] & 0x7F;
142		p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
143			      "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
144		if (rate > max_rate)
145			max_rate = rate;
146	}
147
148	if (network->mode >= IEEE_N_24G)//add N rate here;
149	{
150		PHT_CAPABILITY_ELE ht_cap = NULL;
151		bool is40M = false, isShortGI = false;
152		u8 max_mcs = 0;
153		if (!memcmp(network->bssht.bdHTCapBuf, EWC11NHTCap, 4))
154			ht_cap = (PHT_CAPABILITY_ELE)&network->bssht.bdHTCapBuf[4];
155		else
156			ht_cap = (PHT_CAPABILITY_ELE)&network->bssht.bdHTCapBuf[0];
157		is40M = (ht_cap->ChlWidth)?1:0;
158		isShortGI = (ht_cap->ChlWidth)?
159						((ht_cap->ShortGI40Mhz)?1:0):
160						((ht_cap->ShortGI20Mhz)?1:0);
161
162		max_mcs = HTGetHighestMCSRate(ieee, ht_cap->MCS, MCS_FILTER_ALL);
163		rate = MCS_DATA_RATE[is40M][isShortGI][max_mcs&0x7f];
164		if (rate > max_rate)
165			max_rate = rate;
166	}
167	iwe.cmd = SIOCGIWRATE;
168	iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
169	iwe.u.bitrate.value = max_rate * 500000;
170	start = iwe_stream_add_event_rsl(info, start, stop, &iwe,
171				     IW_EV_PARAM_LEN);
172	iwe.cmd = IWEVCUSTOM;
173	iwe.u.data.length = p - custom;
174	if (iwe.u.data.length)
175	start = iwe_stream_add_point(info, start, stop, &iwe, custom);
176	/* Add quality statistics */
177	/* TODO: Fix these values... */
178	iwe.cmd = IWEVQUAL;
179	iwe.u.qual.qual = network->stats.signal;
180	iwe.u.qual.level = network->stats.rssi;
181	iwe.u.qual.noise = network->stats.noise;
182	iwe.u.qual.updated = network->stats.mask & IEEE80211_STATMASK_WEMASK;
183	if (!(network->stats.mask & IEEE80211_STATMASK_RSSI))
184		iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
185	if (!(network->stats.mask & IEEE80211_STATMASK_NOISE))
186		iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
187	if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL))
188		iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID;
189	iwe.u.qual.updated = 7;
190	start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_QUAL_LEN);
191	iwe.cmd = IWEVCUSTOM;
192	p = custom;
193
194	iwe.u.data.length = p - custom;
195	if (iwe.u.data.length)
196	    start = iwe_stream_add_point(info, start, stop, &iwe, custom);
197#if (WIRELESS_EXT < 18)
198	if (ieee->wpa_enabled && network->wpa_ie_len){
199		char buf[MAX_WPA_IE_LEN * 2 + 30];
200	//	printk("WPA IE\n");
201		u8 *p = buf;
202		p += sprintf(p, "wpa_ie=");
203		for (i = 0; i < network->wpa_ie_len; i++) {
204			p += sprintf(p, "%02x", network->wpa_ie[i]);
205		}
206
207		memset(&iwe, 0, sizeof(iwe));
208		iwe.cmd = IWEVCUSTOM;
209		iwe.u.data.length = strlen(buf);
210		start = iwe_stream_add_point(info, start, stop, &iwe, buf);
211	}
212
213	if (ieee->wpa_enabled && network->rsn_ie_len){
214		char buf[MAX_WPA_IE_LEN * 2 + 30];
215
216		u8 *p = buf;
217		p += sprintf(p, "rsn_ie=");
218		for (i = 0; i < network->rsn_ie_len; i++) {
219			p += sprintf(p, "%02x", network->rsn_ie[i]);
220		}
221
222		memset(&iwe, 0, sizeof(iwe));
223		iwe.cmd = IWEVCUSTOM;
224		iwe.u.data.length = strlen(buf);
225		start = iwe_stream_add_point(info, start, stop, &iwe, buf);
226	}
227#else
228	memset(&iwe, 0, sizeof(iwe));
229	if (network->wpa_ie_len)
230	{
231		char buf[MAX_WPA_IE_LEN];
232		memcpy(buf, network->wpa_ie, network->wpa_ie_len);
233		iwe.cmd = IWEVGENIE;
234		iwe.u.data.length = network->wpa_ie_len;
235		start = iwe_stream_add_point(info, start, stop, &iwe, buf);
236	}
237	memset(&iwe, 0, sizeof(iwe));
238	if (network->rsn_ie_len)
239	{
240		char buf[MAX_WPA_IE_LEN];
241		memcpy(buf, network->rsn_ie, network->rsn_ie_len);
242		iwe.cmd = IWEVGENIE;
243		iwe.u.data.length = network->rsn_ie_len;
244		start = iwe_stream_add_point(info, start, stop, &iwe, buf);
245	}
246#endif
247
248
249	/* Add EXTRA: Age to display seconds since last beacon/probe response
250	 * for given network. */
251	iwe.cmd = IWEVCUSTOM;
252	p = custom;
253	p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
254		      " Last beacon: %lums ago", (jiffies - network->last_scanned) / (HZ / 100));
255	iwe.u.data.length = p - custom;
256	if (iwe.u.data.length)
257	    start = iwe_stream_add_point(info, start, stop, &iwe, custom);
258
259	return start;
260}
261
262int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
263			  struct iw_request_info *info,
264			  union iwreq_data *wrqu, char *extra)
265{
266	struct ieee80211_network *network;
267	unsigned long flags;
268
269	char *ev = extra;
270//	char *stop = ev + IW_SCAN_MAX_DATA;
271	char *stop = ev + wrqu->data.length;//IW_SCAN_MAX_DATA;
272	//char *stop = ev + IW_SCAN_MAX_DATA;
273	int i = 0;
274	int err = 0;
275	IEEE80211_DEBUG_WX("Getting scan\n");
276	down(&ieee->wx_sem);
277	spin_lock_irqsave(&ieee->lock, flags);
278
279	list_for_each_entry(network, &ieee->network_list, list) {
280		i++;
281		if((stop-ev)<200)
282		{
283			err = -E2BIG;
284			break;
285												}
286		if (ieee->scan_age == 0 ||
287		    time_after(network->last_scanned + ieee->scan_age, jiffies))
288			ev = rtl819x_translate_scan(ieee, ev, stop, network, info);
289		else
290			IEEE80211_DEBUG_SCAN(
291				"Not showing network '%s ("
292				"%pM)' due to age (%lums).\n",
293				escape_essid(network->ssid,
294					     network->ssid_len),
295				network->bssid,
296				(jiffies - network->last_scanned) / (HZ / 100));
297	}
298
299	spin_unlock_irqrestore(&ieee->lock, flags);
300	up(&ieee->wx_sem);
301	wrqu->data.length = ev -  extra;
302	wrqu->data.flags = 0;
303
304	IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
305
306	return err;
307}
308
309int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
310			    struct iw_request_info *info,
311			    union iwreq_data *wrqu, char *keybuf)
312{
313	struct iw_point *erq = &(wrqu->encoding);
314	struct net_device *dev = ieee->dev;
315	struct ieee80211_security sec = {
316		.flags = 0
317	};
318	int i, key, key_provided, len;
319	struct ieee80211_crypt_data **crypt;
320
321	IEEE80211_DEBUG_WX("SET_ENCODE\n");
322
323	key = erq->flags & IW_ENCODE_INDEX;
324	if (key) {
325		if (key > WEP_KEYS)
326			return -EINVAL;
327		key--;
328		key_provided = 1;
329	} else {
330		key_provided = 0;
331		key = ieee->tx_keyidx;
332	}
333
334	IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
335			   "provided" : "default");
336	crypt = &ieee->crypt[key];
337
338	if (erq->flags & IW_ENCODE_DISABLED) {
339		if (key_provided && *crypt) {
340			IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
341					   key);
342			ieee80211_crypt_delayed_deinit(ieee, crypt);
343		} else
344			IEEE80211_DEBUG_WX("Disabling encryption.\n");
345
346		/* Check all the keys to see if any are still configured,
347		 * and if no key index was provided, de-init them all */
348		for (i = 0; i < WEP_KEYS; i++) {
349			if (ieee->crypt[i] != NULL) {
350				if (key_provided)
351					break;
352				ieee80211_crypt_delayed_deinit(
353					ieee, &ieee->crypt[i]);
354			}
355		}
356
357		if (i == WEP_KEYS) {
358			sec.enabled = 0;
359			sec.level = SEC_LEVEL_0;
360			sec.flags |= SEC_ENABLED | SEC_LEVEL;
361		}
362
363		goto done;
364	}
365
366
367
368	sec.enabled = 1;
369	sec.flags |= SEC_ENABLED;
370
371	if (*crypt != NULL && (*crypt)->ops != NULL &&
372	    strcmp((*crypt)->ops->name, "WEP") != 0) {
373		/* changing to use WEP; deinit previously used algorithm
374		 * on this key */
375		ieee80211_crypt_delayed_deinit(ieee, crypt);
376	}
377
378	if (*crypt == NULL) {
379		struct ieee80211_crypt_data *new_crypt;
380
381		/* take WEP into use */
382		new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data),
383				    GFP_KERNEL);
384		if (new_crypt == NULL)
385			return -ENOMEM;
386		new_crypt->ops = ieee80211_get_crypto_ops("WEP");
387		if (!new_crypt->ops) {
388			request_module("ieee80211_crypt_wep");
389			new_crypt->ops = ieee80211_get_crypto_ops("WEP");
390		}
391		if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
392			new_crypt->priv = new_crypt->ops->init(key);
393
394		if (!new_crypt->ops || !new_crypt->priv) {
395			kfree(new_crypt);
396			new_crypt = NULL;
397
398			printk(KERN_WARNING "%s: could not initialize WEP: "
399			       "load module ieee80211_crypt_wep\n",
400			       dev->name);
401			return -EOPNOTSUPP;
402		}
403		*crypt = new_crypt;
404	}
405
406	/* If a new key was provided, set it up */
407	if (erq->length > 0) {
408		len = erq->length <= 5 ? 5 : 13;
409		memcpy(sec.keys[key], keybuf, erq->length);
410		if (len > erq->length)
411			memset(sec.keys[key] + erq->length, 0,
412			       len - erq->length);
413		IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
414				   key, escape_essid(sec.keys[key], len),
415				   erq->length, len);
416		sec.key_sizes[key] = len;
417		(*crypt)->ops->set_key(sec.keys[key], len, NULL,
418				       (*crypt)->priv);
419		sec.flags |= (1 << key);
420		/* This ensures a key will be activated if no key is
421		 * explicitely set */
422		if (key == sec.active_key)
423			sec.flags |= SEC_ACTIVE_KEY;
424		ieee->tx_keyidx = key;
425
426	} else {
427		len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
428					     NULL, (*crypt)->priv);
429		if (len == 0) {
430			/* Set a default key of all 0 */
431			printk("Setting key %d to all zero.\n",
432					   key);
433
434			IEEE80211_DEBUG_WX("Setting key %d to all zero.\n",
435					   key);
436			memset(sec.keys[key], 0, 13);
437			(*crypt)->ops->set_key(sec.keys[key], 13, NULL,
438					       (*crypt)->priv);
439			sec.key_sizes[key] = 13;
440			sec.flags |= (1 << key);
441		}
442
443		/* No key data - just set the default TX key index */
444		if (key_provided) {
445			IEEE80211_DEBUG_WX(
446				"Setting key %d to default Tx key.\n", key);
447			ieee->tx_keyidx = key;
448			sec.active_key = key;
449			sec.flags |= SEC_ACTIVE_KEY;
450		}
451	}
452
453 done:
454	ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
455	ieee->auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
456	sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
457	sec.flags |= SEC_AUTH_MODE;
458	IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
459			   "OPEN" : "SHARED KEY");
460
461	/* For now we just support WEP, so only set that security level...
462	 * TODO: When WPA is added this is one place that needs to change */
463	sec.flags |= SEC_LEVEL;
464	sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
465
466	if (ieee->set_security)
467		ieee->set_security(dev, &sec);
468
469	/* Do not reset port if card is in Managed mode since resetting will
470	 * generate new IEEE 802.11 authentication which may end up in looping
471	 * with IEEE 802.1X.  If your hardware requires a reset after WEP
472	 * configuration (for example... Prism2), implement the reset_port in
473	 * the callbacks structures used to initialize the 802.11 stack. */
474	if (ieee->reset_on_keychange &&
475	    ieee->iw_mode != IW_MODE_INFRA &&
476	    ieee->reset_port && ieee->reset_port(dev)) {
477		printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
478		return -EINVAL;
479	}
480	return 0;
481}
482
483int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
484			    struct iw_request_info *info,
485			    union iwreq_data *wrqu, char *keybuf)
486{
487	struct iw_point *erq = &(wrqu->encoding);
488	int len, key;
489	struct ieee80211_crypt_data *crypt;
490
491	IEEE80211_DEBUG_WX("GET_ENCODE\n");
492
493	if(ieee->iw_mode == IW_MODE_MONITOR)
494		return -1;
495
496	key = erq->flags & IW_ENCODE_INDEX;
497	if (key) {
498		if (key > WEP_KEYS)
499			return -EINVAL;
500		key--;
501	} else
502		key = ieee->tx_keyidx;
503
504	crypt = ieee->crypt[key];
505	erq->flags = key + 1;
506
507	if (crypt == NULL || crypt->ops == NULL) {
508		erq->length = 0;
509		erq->flags |= IW_ENCODE_DISABLED;
510		return 0;
511	}
512	len = crypt->ops->get_key(keybuf, SCM_KEY_LEN, NULL, crypt->priv);
513	erq->length = (len >= 0 ? len : 0);
514
515	erq->flags |= IW_ENCODE_ENABLED;
516
517	if (ieee->open_wep)
518		erq->flags |= IW_ENCODE_OPEN;
519	else
520		erq->flags |= IW_ENCODE_RESTRICTED;
521
522	return 0;
523}
524#if (WIRELESS_EXT >= 18)
525int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
526			       struct iw_request_info *info,
527			       union iwreq_data *wrqu, char *extra)
528{
529	int ret = 0;
530	struct net_device *dev = ieee->dev;
531	struct iw_point *encoding = &wrqu->encoding;
532	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
533	int i, idx;
534	int group_key = 0;
535	const char *alg, *module;
536	struct ieee80211_crypto_ops *ops;
537	struct ieee80211_crypt_data **crypt;
538
539	struct ieee80211_security sec = {
540		.flags = 0,
541	};
542	//printk("======>encoding flag:%x,ext flag:%x, ext alg:%d\n", encoding->flags,ext->ext_flags, ext->alg);
543	idx = encoding->flags & IW_ENCODE_INDEX;
544	if (idx) {
545		if (idx < 1 || idx > WEP_KEYS)
546			return -EINVAL;
547		idx--;
548	} else
549		idx = ieee->tx_keyidx;
550
551	if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
552
553		crypt = &ieee->crypt[idx];
554
555		group_key = 1;
556	} else {
557		/* some Cisco APs use idx>0 for unicast in dynamic WEP */
558		//printk("not group key, flags:%x, ext->alg:%d\n", ext->ext_flags, ext->alg);
559		if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
560			return -EINVAL;
561		if (ieee->iw_mode == IW_MODE_INFRA)
562
563			crypt = &ieee->crypt[idx];
564
565		else
566			return -EINVAL;
567	}
568
569	sec.flags |= SEC_ENABLED;// | SEC_ENCRYPT;
570	if ((encoding->flags & IW_ENCODE_DISABLED) ||
571	    ext->alg == IW_ENCODE_ALG_NONE) {
572		if (*crypt)
573			ieee80211_crypt_delayed_deinit(ieee, crypt);
574
575		for (i = 0; i < WEP_KEYS; i++)
576
577			if (ieee->crypt[i] != NULL)
578
579				break;
580
581		if (i == WEP_KEYS) {
582			sec.enabled = 0;
583		      //  sec.encrypt = 0;
584			sec.level = SEC_LEVEL_0;
585			sec.flags |= SEC_LEVEL;
586		}
587		//printk("disabled: flag:%x\n", encoding->flags);
588		goto done;
589	}
590
591	sec.enabled = 1;
592    //    sec.encrypt = 1;
593	switch (ext->alg) {
594	case IW_ENCODE_ALG_WEP:
595		alg = "WEP";
596		module = "ieee80211_crypt_wep";
597		break;
598	case IW_ENCODE_ALG_TKIP:
599		alg = "TKIP";
600		module = "ieee80211_crypt_tkip";
601		break;
602	case IW_ENCODE_ALG_CCMP:
603		alg = "CCMP";
604		module = "ieee80211_crypt_ccmp";
605		break;
606	default:
607		IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
608				   dev->name, ext->alg);
609		ret = -EINVAL;
610		goto done;
611	}
612	printk("alg name:%s\n",alg);
613
614	 ops = ieee80211_get_crypto_ops(alg);
615	if (ops == NULL) {
616		request_module(module);
617		ops = ieee80211_get_crypto_ops(alg);
618	}
619	if (ops == NULL) {
620		IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
621				   dev->name, ext->alg);
622		printk("========>unknown crypto alg %d\n", ext->alg);
623		ret = -EINVAL;
624		goto done;
625	}
626
627	if (*crypt == NULL || (*crypt)->ops != ops) {
628		struct ieee80211_crypt_data *new_crypt;
629
630		ieee80211_crypt_delayed_deinit(ieee, crypt);
631
632		new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
633		if (new_crypt == NULL) {
634			ret = -ENOMEM;
635			goto done;
636		}
637		new_crypt->ops = ops;
638		if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
639			new_crypt->priv = new_crypt->ops->init(idx);
640		if (new_crypt->priv == NULL) {
641			kfree(new_crypt);
642			ret = -EINVAL;
643			goto done;
644		}
645		*crypt = new_crypt;
646
647	}
648
649	if (ext->key_len > 0 && (*crypt)->ops->set_key &&
650	    (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
651				   (*crypt)->priv) < 0) {
652		IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
653		printk("key setting failed\n");
654		ret = -EINVAL;
655		goto done;
656	}
657 //skip_host_crypt:
658	//printk("skip_host_crypt:ext_flags:%x\n", ext->ext_flags);
659	if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
660		ieee->tx_keyidx = idx;
661		sec.active_key = idx;
662		sec.flags |= SEC_ACTIVE_KEY;
663	}
664
665	if (ext->alg != IW_ENCODE_ALG_NONE) {
666		//memcpy(sec.keys[idx], ext->key, ext->key_len);
667		sec.key_sizes[idx] = ext->key_len;
668		sec.flags |= (1 << idx);
669		if (ext->alg == IW_ENCODE_ALG_WEP) {
670		      //  sec.encode_alg[idx] = SEC_ALG_WEP;
671			sec.flags |= SEC_LEVEL;
672			sec.level = SEC_LEVEL_1;
673		} else if (ext->alg == IW_ENCODE_ALG_TKIP) {
674		      //  sec.encode_alg[idx] = SEC_ALG_TKIP;
675			sec.flags |= SEC_LEVEL;
676			sec.level = SEC_LEVEL_2;
677		} else if (ext->alg == IW_ENCODE_ALG_CCMP) {
678		       // sec.encode_alg[idx] = SEC_ALG_CCMP;
679			sec.flags |= SEC_LEVEL;
680			sec.level = SEC_LEVEL_3;
681		}
682		/* Don't set sec level for group keys. */
683		if (group_key)
684			sec.flags &= ~SEC_LEVEL;
685	}
686done:
687	if (ieee->set_security)
688		ieee->set_security(ieee->dev, &sec);
689
690	 if (ieee->reset_on_keychange &&
691	    ieee->iw_mode != IW_MODE_INFRA &&
692	    ieee->reset_port && ieee->reset_port(dev)) {
693		IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
694		return -EINVAL;
695	}
696	return ret;
697}
698
699int ieee80211_wx_get_encode_ext(struct ieee80211_device *ieee,
700			       struct iw_request_info *info,
701			       union iwreq_data *wrqu, char *extra)
702{
703	struct iw_point *encoding = &wrqu->encoding;
704	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
705	struct ieee80211_crypt_data *crypt;
706	int idx, max_key_len;
707
708	max_key_len = encoding->length - sizeof(*ext);
709	if (max_key_len < 0)
710		return -EINVAL;
711
712	idx = encoding->flags & IW_ENCODE_INDEX;
713	if (idx) {
714		if (idx < 1 || idx > WEP_KEYS)
715			return -EINVAL;
716		idx--;
717	} else
718		idx = ieee->tx_keyidx;
719
720	if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
721	    ext->alg != IW_ENCODE_ALG_WEP)
722		if (idx != 0 || ieee->iw_mode != IW_MODE_INFRA)
723			return -EINVAL;
724
725	crypt = ieee->crypt[idx];
726	encoding->flags = idx + 1;
727	memset(ext, 0, sizeof(*ext));
728
729	if (crypt == NULL || crypt->ops == NULL ) {
730		ext->alg = IW_ENCODE_ALG_NONE;
731		ext->key_len = 0;
732		encoding->flags |= IW_ENCODE_DISABLED;
733	} else {
734		if (strcmp(crypt->ops->name, "WEP") == 0 )
735			ext->alg = IW_ENCODE_ALG_WEP;
736		else if (strcmp(crypt->ops->name, "TKIP"))
737			ext->alg = IW_ENCODE_ALG_TKIP;
738		else if (strcmp(crypt->ops->name, "CCMP"))
739			ext->alg = IW_ENCODE_ALG_CCMP;
740		else
741			return -EINVAL;
742		ext->key_len = crypt->ops->get_key(ext->key, SCM_KEY_LEN, NULL, crypt->priv);
743		encoding->flags |= IW_ENCODE_ENABLED;
744		if (ext->key_len &&
745		    (ext->alg == IW_ENCODE_ALG_TKIP ||
746		     ext->alg == IW_ENCODE_ALG_CCMP))
747			ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
748
749	}
750
751	return 0;
752}
753
754int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
755			       struct iw_request_info *info,
756			       union iwreq_data *wrqu, char *extra)
757{
758	struct iw_mlme *mlme = (struct iw_mlme *) extra;
759	switch (mlme->cmd) {
760	case IW_MLME_DEAUTH:
761	case IW_MLME_DISASSOC:
762		ieee80211_disassociate(ieee);
763		break;
764	 default:
765		return -EOPNOTSUPP;
766	}
767	return 0;
768}
769
770int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
771			       struct iw_request_info *info,
772			       struct iw_param *data, char *extra)
773{
774	switch (data->flags & IW_AUTH_INDEX) {
775	case IW_AUTH_WPA_VERSION:
776	     /*need to support wpa2 here*/
777		//printk("wpa version:%x\n", data->value);
778		break;
779	case IW_AUTH_CIPHER_PAIRWISE:
780	case IW_AUTH_CIPHER_GROUP:
781	case IW_AUTH_KEY_MGMT:
782		/*
783 *                  * Host AP driver does not use these parameters and allows
784 *                                   * wpa_supplicant to control them internally.
785 *                                                    */
786		break;
787	case IW_AUTH_TKIP_COUNTERMEASURES:
788		ieee->tkip_countermeasures = data->value;
789		break;
790	case IW_AUTH_DROP_UNENCRYPTED:
791		ieee->drop_unencrypted = data->value;
792		break;
793
794	case IW_AUTH_80211_AUTH_ALG:
795		//printk("======>%s():data->value is %d\n",__FUNCTION__,data->value);
796	//	ieee->open_wep = (data->value&IW_AUTH_ALG_OPEN_SYSTEM)?1:0;
797		if(data->value & IW_AUTH_ALG_SHARED_KEY){
798			ieee->open_wep = 0;
799			ieee->auth_mode = 1;
800		}
801		else if(data->value & IW_AUTH_ALG_OPEN_SYSTEM){
802			ieee->open_wep = 1;
803			ieee->auth_mode = 0;
804		}
805		else if(data->value & IW_AUTH_ALG_LEAP){
806			ieee->open_wep = 1;
807			ieee->auth_mode = 2;
808			//printk("hahahaa:LEAP\n");
809		}
810		else
811			return -EINVAL;
812		//printk("open_wep:%d\n", ieee->open_wep);
813		break;
814
815	case IW_AUTH_WPA_ENABLED:
816		ieee->wpa_enabled = (data->value)?1:0;
817		//printk("enalbe wpa:%d\n", ieee->wpa_enabled);
818		break;
819
820	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
821		ieee->ieee802_1x = data->value;
822		break;
823	case IW_AUTH_PRIVACY_INVOKED:
824		ieee->privacy_invoked = data->value;
825		break;
826	default:
827		return -EOPNOTSUPP;
828	}
829	return 0;
830}
831#endif
832int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
833{
834	u8 *buf;
835
836	if (len>MAX_WPA_IE_LEN || (len && ie == NULL))
837	{
838	//	printk("return error out, len:%d\n", len);
839	return -EINVAL;
840	}
841
842
843	if (len)
844	{
845		if (len != ie[1]+2)
846		{
847			printk("len:%zu, ie:%d\n", len, ie[1]);
848			return -EINVAL;
849		}
850		buf = kmemdup(ie, len, GFP_KERNEL);
851		if (buf == NULL)
852			return -ENOMEM;
853		kfree(ieee->wpa_ie);
854		ieee->wpa_ie = buf;
855		ieee->wpa_ie_len = len;
856	}
857	else{
858		if (ieee->wpa_ie)
859		kfree(ieee->wpa_ie);
860		ieee->wpa_ie = NULL;
861		ieee->wpa_ie_len = 0;
862	}
863	return 0;
864
865}
866
867EXPORT_SYMBOL(ieee80211_wx_set_gen_ie);
868#if (WIRELESS_EXT >= 18)
869EXPORT_SYMBOL(ieee80211_wx_set_mlme);
870EXPORT_SYMBOL(ieee80211_wx_set_auth);
871EXPORT_SYMBOL(ieee80211_wx_set_encode_ext);
872EXPORT_SYMBOL(ieee80211_wx_get_encode_ext);
873#endif
874EXPORT_SYMBOL(ieee80211_wx_get_scan);
875EXPORT_SYMBOL(ieee80211_wx_set_encode);
876EXPORT_SYMBOL(ieee80211_wx_get_encode);
877