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 struct modes_unit {
39 	char *mode_string;
40 	int mode_size;
41 };
42 static struct 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
54 static 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 
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 
228 
229 	/* Add EXTRA: Age to display seconds since last beacon/probe response
230 	 * for given network. */
231 	iwe.cmd = IWEVCUSTOM;
232 	p = custom;
233 	p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
234 		      " Last beacon: %lums ago", (jiffies - network->last_scanned) / (HZ / 100));
235 	iwe.u.data.length = p - custom;
236 	if (iwe.u.data.length)
237 	    start = iwe_stream_add_point(info, start, stop, &iwe, custom);
238 
239 	return start;
240 }
241 
242 int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
243 			  struct iw_request_info *info,
244 			  union iwreq_data *wrqu, char *extra)
245 {
246 	struct ieee80211_network *network;
247 	unsigned long flags;
248 
249 	char *ev = extra;
250 //	char *stop = ev + IW_SCAN_MAX_DATA;
251 	char *stop = ev + wrqu->data.length;//IW_SCAN_MAX_DATA;
252 	//char *stop = ev + IW_SCAN_MAX_DATA;
253 	int i = 0;
254 	int err = 0;
255 	IEEE80211_DEBUG_WX("Getting scan\n");
256 	mutex_lock(&ieee->wx_mutex);
257 	spin_lock_irqsave(&ieee->lock, flags);
258 
259 	list_for_each_entry(network, &ieee->network_list, list) {
260 		i++;
261 		if((stop-ev)<200)
262 		{
263 			err = -E2BIG;
264 			break;
265 		}
266 		if (ieee->scan_age == 0 ||
267 		    time_after(network->last_scanned + ieee->scan_age, jiffies))
268 			ev = rtl819x_translate_scan(ieee, ev, stop, network, info);
269 		else
270 			IEEE80211_DEBUG_SCAN(
271 				"Not showing network '%s ("
272 				"%pM)' due to age (%lums).\n",
273 				escape_essid(network->ssid,
274 					     network->ssid_len),
275 				network->bssid,
276 				(jiffies - network->last_scanned) / (HZ / 100));
277 	}
278 
279 	spin_unlock_irqrestore(&ieee->lock, flags);
280 	mutex_unlock(&ieee->wx_mutex);
281 	wrqu->data.length = ev -  extra;
282 	wrqu->data.flags = 0;
283 
284 	IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
285 
286 	return err;
287 }
288 EXPORT_SYMBOL(ieee80211_wx_get_scan);
289 
290 int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
291 			    struct iw_request_info *info,
292 			    union iwreq_data *wrqu, char *keybuf)
293 {
294 	struct iw_point *erq = &(wrqu->encoding);
295 	struct net_device *dev = ieee->dev;
296 	struct ieee80211_security sec = {
297 		.flags = 0
298 	};
299 	int i, key, key_provided, len;
300 	struct ieee80211_crypt_data **crypt;
301 
302 	IEEE80211_DEBUG_WX("SET_ENCODE\n");
303 
304 	key = erq->flags & IW_ENCODE_INDEX;
305 	if (key) {
306 		if (key > WEP_KEYS)
307 			return -EINVAL;
308 		key--;
309 		key_provided = 1;
310 	} else {
311 		key_provided = 0;
312 		key = ieee->tx_keyidx;
313 	}
314 
315 	IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
316 			   "provided" : "default");
317 	crypt = &ieee->crypt[key];
318 
319 	if (erq->flags & IW_ENCODE_DISABLED) {
320 		if (key_provided && *crypt) {
321 			IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
322 					   key);
323 			ieee80211_crypt_delayed_deinit(ieee, crypt);
324 		} else
325 			IEEE80211_DEBUG_WX("Disabling encryption.\n");
326 
327 		/* Check all the keys to see if any are still configured,
328 		 * and if no key index was provided, de-init them all */
329 		for (i = 0; i < WEP_KEYS; i++) {
330 			if (ieee->crypt[i] != NULL) {
331 				if (key_provided)
332 					break;
333 				ieee80211_crypt_delayed_deinit(
334 					ieee, &ieee->crypt[i]);
335 			}
336 		}
337 
338 		if (i == WEP_KEYS) {
339 			sec.enabled = 0;
340 			sec.level = SEC_LEVEL_0;
341 			sec.flags |= SEC_ENABLED | SEC_LEVEL;
342 		}
343 
344 		goto done;
345 	}
346 
347 
348 
349 	sec.enabled = 1;
350 	sec.flags |= SEC_ENABLED;
351 
352 	if (*crypt != NULL && (*crypt)->ops != NULL &&
353 	    strcmp((*crypt)->ops->name, "WEP") != 0) {
354 		/* changing to use WEP; deinit previously used algorithm
355 		 * on this key */
356 		ieee80211_crypt_delayed_deinit(ieee, crypt);
357 	}
358 
359 	if (*crypt == NULL) {
360 		struct ieee80211_crypt_data *new_crypt;
361 
362 		/* take WEP into use */
363 		new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data),
364 				    GFP_KERNEL);
365 		if (!new_crypt)
366 			return -ENOMEM;
367 		new_crypt->ops = try_then_request_module(ieee80211_get_crypto_ops("WEP"),
368 							 "ieee80211_crypt_wep");
369 		if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
370 			new_crypt->priv = new_crypt->ops->init(key);
371 
372 		if (!new_crypt->ops || !new_crypt->priv) {
373 			kfree(new_crypt);
374 			new_crypt = NULL;
375 
376 			printk(KERN_WARNING "%s: could not initialize WEP: "
377 			       "load module ieee80211_crypt_wep\n",
378 			       dev->name);
379 			return -EOPNOTSUPP;
380 		}
381 		*crypt = new_crypt;
382 	}
383 
384 	/* If a new key was provided, set it up */
385 	if (erq->length > 0) {
386 		len = erq->length <= 5 ? 5 : 13;
387 		memcpy(sec.keys[key], keybuf, erq->length);
388 		if (len > erq->length)
389 			memset(sec.keys[key] + erq->length, 0,
390 			       len - erq->length);
391 		IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
392 				   key, escape_essid(sec.keys[key], len),
393 				   erq->length, len);
394 		sec.key_sizes[key] = len;
395 		(*crypt)->ops->set_key(sec.keys[key], len, NULL,
396 				       (*crypt)->priv);
397 		sec.flags |= (1 << key);
398 		/* This ensures a key will be activated if no key is
399 		 * explicitely set */
400 		if (key == sec.active_key)
401 			sec.flags |= SEC_ACTIVE_KEY;
402 		ieee->tx_keyidx = key;
403 
404 	} else {
405 		len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
406 					     NULL, (*crypt)->priv);
407 		if (len == 0) {
408 			/* Set a default key of all 0 */
409 			printk("Setting key %d to all zero.\n",
410 					   key);
411 
412 			IEEE80211_DEBUG_WX("Setting key %d to all zero.\n",
413 					   key);
414 			memset(sec.keys[key], 0, 13);
415 			(*crypt)->ops->set_key(sec.keys[key], 13, NULL,
416 					       (*crypt)->priv);
417 			sec.key_sizes[key] = 13;
418 			sec.flags |= (1 << key);
419 		}
420 
421 		/* No key data - just set the default TX key index */
422 		if (key_provided) {
423 			IEEE80211_DEBUG_WX(
424 				"Setting key %d to default Tx key.\n", key);
425 			ieee->tx_keyidx = key;
426 			sec.active_key = key;
427 			sec.flags |= SEC_ACTIVE_KEY;
428 		}
429 	}
430 
431  done:
432 	ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
433 	ieee->auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
434 	sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
435 	sec.flags |= SEC_AUTH_MODE;
436 	IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
437 			   "OPEN" : "SHARED KEY");
438 
439 	/* For now we just support WEP, so only set that security level...
440 	 * TODO: When WPA is added this is one place that needs to change */
441 	sec.flags |= SEC_LEVEL;
442 	sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
443 
444 	if (ieee->set_security)
445 		ieee->set_security(dev, &sec);
446 
447 	/* Do not reset port if card is in Managed mode since resetting will
448 	 * generate new IEEE 802.11 authentication which may end up in looping
449 	 * with IEEE 802.1X.  If your hardware requires a reset after WEP
450 	 * configuration (for example... Prism2), implement the reset_port in
451 	 * the callbacks structures used to initialize the 802.11 stack. */
452 	if (ieee->reset_on_keychange &&
453 	    ieee->iw_mode != IW_MODE_INFRA &&
454 	    ieee->reset_port && ieee->reset_port(dev)) {
455 		printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
456 		return -EINVAL;
457 	}
458 	return 0;
459 }
460 EXPORT_SYMBOL(ieee80211_wx_set_encode);
461 
462 int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
463 			    struct iw_request_info *info,
464 			    union iwreq_data *wrqu, char *keybuf)
465 {
466 	struct iw_point *erq = &(wrqu->encoding);
467 	int len, key;
468 	struct ieee80211_crypt_data *crypt;
469 
470 	IEEE80211_DEBUG_WX("GET_ENCODE\n");
471 
472 	if(ieee->iw_mode == IW_MODE_MONITOR)
473 		return -1;
474 
475 	key = erq->flags & IW_ENCODE_INDEX;
476 	if (key) {
477 		if (key > WEP_KEYS)
478 			return -EINVAL;
479 		key--;
480 	} else
481 		key = ieee->tx_keyidx;
482 
483 	crypt = ieee->crypt[key];
484 	erq->flags = key + 1;
485 
486 	if (crypt == NULL || crypt->ops == NULL) {
487 		erq->length = 0;
488 		erq->flags |= IW_ENCODE_DISABLED;
489 		return 0;
490 	}
491 	len = crypt->ops->get_key(keybuf, SCM_KEY_LEN, NULL, crypt->priv);
492 	erq->length = (len >= 0 ? len : 0);
493 
494 	erq->flags |= IW_ENCODE_ENABLED;
495 
496 	if (ieee->open_wep)
497 		erq->flags |= IW_ENCODE_OPEN;
498 	else
499 		erq->flags |= IW_ENCODE_RESTRICTED;
500 
501 	return 0;
502 }
503 EXPORT_SYMBOL(ieee80211_wx_get_encode);
504 
505 int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
506 			       struct iw_request_info *info,
507 			       union iwreq_data *wrqu, char *extra)
508 {
509 	int ret = 0;
510 	struct net_device *dev = ieee->dev;
511 	struct iw_point *encoding = &wrqu->encoding;
512 	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
513 	int i, idx;
514 	int group_key = 0;
515 	const char *alg, *module;
516 	struct ieee80211_crypto_ops *ops;
517 	struct ieee80211_crypt_data **crypt;
518 
519 	struct ieee80211_security sec = {
520 		.flags = 0,
521 	};
522 	idx = encoding->flags & IW_ENCODE_INDEX;
523 	if (idx) {
524 		if (idx < 1 || idx > WEP_KEYS)
525 			return -EINVAL;
526 		idx--;
527 	} else
528 		idx = ieee->tx_keyidx;
529 
530 	if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
531 
532 		crypt = &ieee->crypt[idx];
533 
534 		group_key = 1;
535 	} else {
536 		/* some Cisco APs use idx>0 for unicast in dynamic WEP */
537 		if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
538 			return -EINVAL;
539 		if (ieee->iw_mode == IW_MODE_INFRA)
540 
541 			crypt = &ieee->crypt[idx];
542 
543 		else
544 			return -EINVAL;
545 	}
546 
547 	sec.flags |= SEC_ENABLED;// | SEC_ENCRYPT;
548 	if ((encoding->flags & IW_ENCODE_DISABLED) ||
549 	    ext->alg == IW_ENCODE_ALG_NONE) {
550 		if (*crypt)
551 			ieee80211_crypt_delayed_deinit(ieee, crypt);
552 
553 		for (i = 0; i < WEP_KEYS; i++)
554 
555 			if (ieee->crypt[i] != NULL)
556 
557 				break;
558 
559 		if (i == WEP_KEYS) {
560 			sec.enabled = 0;
561 		      //  sec.encrypt = 0;
562 			sec.level = SEC_LEVEL_0;
563 			sec.flags |= SEC_LEVEL;
564 		}
565 		goto done;
566 	}
567 
568 	sec.enabled = 1;
569     //    sec.encrypt = 1;
570 	switch (ext->alg) {
571 	case IW_ENCODE_ALG_WEP:
572 		alg = "WEP";
573 		module = "ieee80211_crypt_wep";
574 		break;
575 	case IW_ENCODE_ALG_TKIP:
576 		alg = "TKIP";
577 		module = "ieee80211_crypt_tkip";
578 		break;
579 	case IW_ENCODE_ALG_CCMP:
580 		alg = "CCMP";
581 		module = "ieee80211_crypt_ccmp";
582 		break;
583 	default:
584 		IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
585 				   dev->name, ext->alg);
586 		ret = -EINVAL;
587 		goto done;
588 	}
589 	printk("alg name:%s\n",alg);
590 
591 	ops = try_then_request_module(ieee80211_get_crypto_ops(alg), module);
592 	if (!ops) {
593 		IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
594 				   dev->name, ext->alg);
595 		printk("========>unknown crypto alg %d\n", ext->alg);
596 		ret = -EINVAL;
597 		goto done;
598 	}
599 
600 	if (*crypt == NULL || (*crypt)->ops != ops) {
601 		struct ieee80211_crypt_data *new_crypt;
602 
603 		ieee80211_crypt_delayed_deinit(ieee, crypt);
604 
605 		new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
606 		if (!new_crypt) {
607 			ret = -ENOMEM;
608 			goto done;
609 		}
610 		new_crypt->ops = ops;
611 		if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
612 			new_crypt->priv = new_crypt->ops->init(idx);
613 		if (new_crypt->priv == NULL) {
614 			kfree(new_crypt);
615 			ret = -EINVAL;
616 			goto done;
617 		}
618 		*crypt = new_crypt;
619 	}
620 
621 	if (ext->key_len > 0 && (*crypt)->ops->set_key &&
622 	    (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
623 				   (*crypt)->priv) < 0) {
624 		IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
625 		printk("key setting failed\n");
626 		ret = -EINVAL;
627 		goto done;
628 	}
629  //skip_host_crypt:
630 	if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
631 		ieee->tx_keyidx = idx;
632 		sec.active_key = idx;
633 		sec.flags |= SEC_ACTIVE_KEY;
634 	}
635 
636 	if (ext->alg != IW_ENCODE_ALG_NONE) {
637 		//memcpy(sec.keys[idx], ext->key, ext->key_len);
638 		sec.key_sizes[idx] = ext->key_len;
639 		sec.flags |= (1 << idx);
640 		if (ext->alg == IW_ENCODE_ALG_WEP) {
641 		      //  sec.encode_alg[idx] = SEC_ALG_WEP;
642 			sec.flags |= SEC_LEVEL;
643 			sec.level = SEC_LEVEL_1;
644 		} else if (ext->alg == IW_ENCODE_ALG_TKIP) {
645 		      //  sec.encode_alg[idx] = SEC_ALG_TKIP;
646 			sec.flags |= SEC_LEVEL;
647 			sec.level = SEC_LEVEL_2;
648 		} else if (ext->alg == IW_ENCODE_ALG_CCMP) {
649 		       // sec.encode_alg[idx] = SEC_ALG_CCMP;
650 			sec.flags |= SEC_LEVEL;
651 			sec.level = SEC_LEVEL_3;
652 		}
653 		/* Don't set sec level for group keys. */
654 		if (group_key)
655 			sec.flags &= ~SEC_LEVEL;
656 	}
657 done:
658 	if (ieee->set_security)
659 		ieee->set_security(ieee->dev, &sec);
660 
661 	if (ieee->reset_on_keychange &&
662 	    ieee->iw_mode != IW_MODE_INFRA &&
663 	    ieee->reset_port && ieee->reset_port(dev)) {
664 		IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
665 		return -EINVAL;
666 	}
667 	return ret;
668 }
669 EXPORT_SYMBOL(ieee80211_wx_set_encode_ext);
670 
671 int ieee80211_wx_get_encode_ext(struct ieee80211_device *ieee,
672 			       struct iw_request_info *info,
673 			       union iwreq_data *wrqu, char *extra)
674 {
675 	struct iw_point *encoding = &wrqu->encoding;
676 	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
677 	struct ieee80211_crypt_data *crypt;
678 	int idx, max_key_len;
679 
680 	max_key_len = encoding->length - sizeof(*ext);
681 	if (max_key_len < 0)
682 		return -EINVAL;
683 
684 	idx = encoding->flags & IW_ENCODE_INDEX;
685 	if (idx) {
686 		if (idx < 1 || idx > WEP_KEYS)
687 			return -EINVAL;
688 		idx--;
689 	} else
690 		idx = ieee->tx_keyidx;
691 
692 	if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
693 	    ext->alg != IW_ENCODE_ALG_WEP)
694 		if (idx != 0 || ieee->iw_mode != IW_MODE_INFRA)
695 			return -EINVAL;
696 
697 	crypt = ieee->crypt[idx];
698 	encoding->flags = idx + 1;
699 	memset(ext, 0, sizeof(*ext));
700 
701 	if (crypt == NULL || crypt->ops == NULL ) {
702 		ext->alg = IW_ENCODE_ALG_NONE;
703 		ext->key_len = 0;
704 		encoding->flags |= IW_ENCODE_DISABLED;
705 	} else {
706 		if (strcmp(crypt->ops->name, "WEP") == 0 )
707 			ext->alg = IW_ENCODE_ALG_WEP;
708 		else if (strcmp(crypt->ops->name, "TKIP"))
709 			ext->alg = IW_ENCODE_ALG_TKIP;
710 		else if (strcmp(crypt->ops->name, "CCMP"))
711 			ext->alg = IW_ENCODE_ALG_CCMP;
712 		else
713 			return -EINVAL;
714 		ext->key_len = crypt->ops->get_key(ext->key, SCM_KEY_LEN, NULL, crypt->priv);
715 		encoding->flags |= IW_ENCODE_ENABLED;
716 		if (ext->key_len &&
717 		    (ext->alg == IW_ENCODE_ALG_TKIP ||
718 		     ext->alg == IW_ENCODE_ALG_CCMP))
719 			ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
720 	}
721 
722 	return 0;
723 }
724 EXPORT_SYMBOL(ieee80211_wx_get_encode_ext);
725 
726 int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
727 			       struct iw_request_info *info,
728 			       union iwreq_data *wrqu, char *extra)
729 {
730 	struct iw_mlme *mlme = (struct iw_mlme *) extra;
731 	switch (mlme->cmd) {
732 	case IW_MLME_DEAUTH:
733 	case IW_MLME_DISASSOC:
734 		ieee80211_disassociate(ieee);
735 		break;
736 	default:
737 		return -EOPNOTSUPP;
738 	}
739 	return 0;
740 }
741 EXPORT_SYMBOL(ieee80211_wx_set_mlme);
742 
743 int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
744 			       struct iw_request_info *info,
745 			       struct iw_param *data, char *extra)
746 {
747 	switch (data->flags & IW_AUTH_INDEX) {
748 	case IW_AUTH_WPA_VERSION:
749 	     /*need to support wpa2 here*/
750 		break;
751 	case IW_AUTH_CIPHER_PAIRWISE:
752 	case IW_AUTH_CIPHER_GROUP:
753 	case IW_AUTH_KEY_MGMT:
754 		/*
755  *                  * Host AP driver does not use these parameters and allows
756  *                                   * wpa_supplicant to control them internally.
757  *                                                    */
758 		break;
759 	case IW_AUTH_TKIP_COUNTERMEASURES:
760 		ieee->tkip_countermeasures = data->value;
761 		break;
762 	case IW_AUTH_DROP_UNENCRYPTED:
763 		ieee->drop_unencrypted = data->value;
764 		break;
765 
766 	case IW_AUTH_80211_AUTH_ALG:
767 		//printk("======>%s():data->value is %d\n",__func__,data->value);
768 	//	ieee->open_wep = (data->value&IW_AUTH_ALG_OPEN_SYSTEM)?1:0;
769 		if(data->value & IW_AUTH_ALG_SHARED_KEY){
770 			ieee->open_wep = 0;
771 			ieee->auth_mode = 1;
772 		}
773 		else if(data->value & IW_AUTH_ALG_OPEN_SYSTEM){
774 			ieee->open_wep = 1;
775 			ieee->auth_mode = 0;
776 		}
777 		else if(data->value & IW_AUTH_ALG_LEAP){
778 			ieee->open_wep = 1;
779 			ieee->auth_mode = 2;
780 		}
781 		else
782 			return -EINVAL;
783 		break;
784 
785 	case IW_AUTH_WPA_ENABLED:
786 		ieee->wpa_enabled = (data->value)?1:0;
787 		break;
788 
789 	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
790 		ieee->ieee802_1x = data->value;
791 		break;
792 	case IW_AUTH_PRIVACY_INVOKED:
793 		ieee->privacy_invoked = data->value;
794 		break;
795 	default:
796 		return -EOPNOTSUPP;
797 	}
798 	return 0;
799 }
800 EXPORT_SYMBOL(ieee80211_wx_set_auth);
801 
802 int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
803 {
804 	u8 *buf;
805 
806 	if (len>MAX_WPA_IE_LEN || (len && ie == NULL))
807 	{
808 	//	printk("return error out, len:%d\n", len);
809 	return -EINVAL;
810 	}
811 
812 
813 	if (len)
814 	{
815 		if (len != ie[1]+2)
816 		{
817 			printk("len:%zu, ie:%d\n", len, ie[1]);
818 			return -EINVAL;
819 		}
820 		buf = kmemdup(ie, len, GFP_KERNEL);
821 		if (buf == NULL)
822 			return -ENOMEM;
823 		kfree(ieee->wpa_ie);
824 		ieee->wpa_ie = buf;
825 		ieee->wpa_ie_len = len;
826 	}
827 	else{
828 		kfree(ieee->wpa_ie);
829 		ieee->wpa_ie = NULL;
830 		ieee->wpa_ie_len = 0;
831 	}
832 	return 0;
833 }
834 EXPORT_SYMBOL(ieee80211_wx_set_gen_ie);
835