• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
rtl819x_translate_scan(struct ieee80211_device * ieee,char * start,char * stop,struct ieee80211_network * network,struct iw_request_info * info)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 
ieee80211_wx_get_scan(struct ieee80211_device * ieee,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)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 	down(&ieee->wx_sem);
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 	up(&ieee->wx_sem);
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 
ieee80211_wx_set_encode(struct ieee80211_device * ieee,struct iw_request_info * info,union iwreq_data * wrqu,char * keybuf)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 == NULL)
366 			return -ENOMEM;
367 		new_crypt->ops = ieee80211_get_crypto_ops("WEP");
368 		if (!new_crypt->ops) {
369 			request_module("ieee80211_crypt_wep");
370 			new_crypt->ops = ieee80211_get_crypto_ops("WEP");
371 		}
372 		if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
373 			new_crypt->priv = new_crypt->ops->init(key);
374 
375 		if (!new_crypt->ops || !new_crypt->priv) {
376 			kfree(new_crypt);
377 			new_crypt = NULL;
378 
379 			printk(KERN_WARNING "%s: could not initialize WEP: "
380 			       "load module ieee80211_crypt_wep\n",
381 			       dev->name);
382 			return -EOPNOTSUPP;
383 		}
384 		*crypt = new_crypt;
385 	}
386 
387 	/* If a new key was provided, set it up */
388 	if (erq->length > 0) {
389 		len = erq->length <= 5 ? 5 : 13;
390 		memcpy(sec.keys[key], keybuf, erq->length);
391 		if (len > erq->length)
392 			memset(sec.keys[key] + erq->length, 0,
393 			       len - erq->length);
394 		IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
395 				   key, escape_essid(sec.keys[key], len),
396 				   erq->length, len);
397 		sec.key_sizes[key] = len;
398 		(*crypt)->ops->set_key(sec.keys[key], len, NULL,
399 				       (*crypt)->priv);
400 		sec.flags |= (1 << key);
401 		/* This ensures a key will be activated if no key is
402 		 * explicitely set */
403 		if (key == sec.active_key)
404 			sec.flags |= SEC_ACTIVE_KEY;
405 		ieee->tx_keyidx = key;
406 
407 	} else {
408 		len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
409 					     NULL, (*crypt)->priv);
410 		if (len == 0) {
411 			/* Set a default key of all 0 */
412 			printk("Setting key %d to all zero.\n",
413 					   key);
414 
415 			IEEE80211_DEBUG_WX("Setting key %d to all zero.\n",
416 					   key);
417 			memset(sec.keys[key], 0, 13);
418 			(*crypt)->ops->set_key(sec.keys[key], 13, NULL,
419 					       (*crypt)->priv);
420 			sec.key_sizes[key] = 13;
421 			sec.flags |= (1 << key);
422 		}
423 
424 		/* No key data - just set the default TX key index */
425 		if (key_provided) {
426 			IEEE80211_DEBUG_WX(
427 				"Setting key %d to default Tx key.\n", key);
428 			ieee->tx_keyidx = key;
429 			sec.active_key = key;
430 			sec.flags |= SEC_ACTIVE_KEY;
431 		}
432 	}
433 
434  done:
435 	ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
436 	ieee->auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
437 	sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
438 	sec.flags |= SEC_AUTH_MODE;
439 	IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
440 			   "OPEN" : "SHARED KEY");
441 
442 	/* For now we just support WEP, so only set that security level...
443 	 * TODO: When WPA is added this is one place that needs to change */
444 	sec.flags |= SEC_LEVEL;
445 	sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
446 
447 	if (ieee->set_security)
448 		ieee->set_security(dev, &sec);
449 
450 	/* Do not reset port if card is in Managed mode since resetting will
451 	 * generate new IEEE 802.11 authentication which may end up in looping
452 	 * with IEEE 802.1X.  If your hardware requires a reset after WEP
453 	 * configuration (for example... Prism2), implement the reset_port in
454 	 * the callbacks structures used to initialize the 802.11 stack. */
455 	if (ieee->reset_on_keychange &&
456 	    ieee->iw_mode != IW_MODE_INFRA &&
457 	    ieee->reset_port && ieee->reset_port(dev)) {
458 		printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
459 		return -EINVAL;
460 	}
461 	return 0;
462 }
463 EXPORT_SYMBOL(ieee80211_wx_set_encode);
464 
ieee80211_wx_get_encode(struct ieee80211_device * ieee,struct iw_request_info * info,union iwreq_data * wrqu,char * keybuf)465 int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
466 			    struct iw_request_info *info,
467 			    union iwreq_data *wrqu, char *keybuf)
468 {
469 	struct iw_point *erq = &(wrqu->encoding);
470 	int len, key;
471 	struct ieee80211_crypt_data *crypt;
472 
473 	IEEE80211_DEBUG_WX("GET_ENCODE\n");
474 
475 	if(ieee->iw_mode == IW_MODE_MONITOR)
476 		return -1;
477 
478 	key = erq->flags & IW_ENCODE_INDEX;
479 	if (key) {
480 		if (key > WEP_KEYS)
481 			return -EINVAL;
482 		key--;
483 	} else
484 		key = ieee->tx_keyidx;
485 
486 	crypt = ieee->crypt[key];
487 	erq->flags = key + 1;
488 
489 	if (crypt == NULL || crypt->ops == NULL) {
490 		erq->length = 0;
491 		erq->flags |= IW_ENCODE_DISABLED;
492 		return 0;
493 	}
494 	len = crypt->ops->get_key(keybuf, SCM_KEY_LEN, NULL, crypt->priv);
495 	erq->length = (len >= 0 ? len : 0);
496 
497 	erq->flags |= IW_ENCODE_ENABLED;
498 
499 	if (ieee->open_wep)
500 		erq->flags |= IW_ENCODE_OPEN;
501 	else
502 		erq->flags |= IW_ENCODE_RESTRICTED;
503 
504 	return 0;
505 }
506 EXPORT_SYMBOL(ieee80211_wx_get_encode);
507 
ieee80211_wx_set_encode_ext(struct ieee80211_device * ieee,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)508 int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
509 			       struct iw_request_info *info,
510 			       union iwreq_data *wrqu, char *extra)
511 {
512 	int ret = 0;
513 	struct net_device *dev = ieee->dev;
514 	struct iw_point *encoding = &wrqu->encoding;
515 	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
516 	int i, idx;
517 	int group_key = 0;
518 	const char *alg, *module;
519 	struct ieee80211_crypto_ops *ops;
520 	struct ieee80211_crypt_data **crypt;
521 
522 	struct ieee80211_security sec = {
523 		.flags = 0,
524 	};
525 	//printk("======>encoding flag:%x,ext flag:%x, ext alg:%d\n", encoding->flags,ext->ext_flags, ext->alg);
526 	idx = encoding->flags & IW_ENCODE_INDEX;
527 	if (idx) {
528 		if (idx < 1 || idx > WEP_KEYS)
529 			return -EINVAL;
530 		idx--;
531 	} else
532 		idx = ieee->tx_keyidx;
533 
534 	if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
535 
536 		crypt = &ieee->crypt[idx];
537 
538 		group_key = 1;
539 	} else {
540 		/* some Cisco APs use idx>0 for unicast in dynamic WEP */
541 		//printk("not group key, flags:%x, ext->alg:%d\n", ext->ext_flags, ext->alg);
542 		if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
543 			return -EINVAL;
544 		if (ieee->iw_mode == IW_MODE_INFRA)
545 
546 			crypt = &ieee->crypt[idx];
547 
548 		else
549 			return -EINVAL;
550 	}
551 
552 	sec.flags |= SEC_ENABLED;// | SEC_ENCRYPT;
553 	if ((encoding->flags & IW_ENCODE_DISABLED) ||
554 	    ext->alg == IW_ENCODE_ALG_NONE) {
555 		if (*crypt)
556 			ieee80211_crypt_delayed_deinit(ieee, crypt);
557 
558 		for (i = 0; i < WEP_KEYS; i++)
559 
560 			if (ieee->crypt[i] != NULL)
561 
562 				break;
563 
564 		if (i == WEP_KEYS) {
565 			sec.enabled = 0;
566 		      //  sec.encrypt = 0;
567 			sec.level = SEC_LEVEL_0;
568 			sec.flags |= SEC_LEVEL;
569 		}
570 		//printk("disabled: flag:%x\n", encoding->flags);
571 		goto done;
572 	}
573 
574 	sec.enabled = 1;
575     //    sec.encrypt = 1;
576 	switch (ext->alg) {
577 	case IW_ENCODE_ALG_WEP:
578 		alg = "WEP";
579 		module = "ieee80211_crypt_wep";
580 		break;
581 	case IW_ENCODE_ALG_TKIP:
582 		alg = "TKIP";
583 		module = "ieee80211_crypt_tkip";
584 		break;
585 	case IW_ENCODE_ALG_CCMP:
586 		alg = "CCMP";
587 		module = "ieee80211_crypt_ccmp";
588 		break;
589 	default:
590 		IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
591 				   dev->name, ext->alg);
592 		ret = -EINVAL;
593 		goto done;
594 	}
595 	printk("alg name:%s\n",alg);
596 
597 	 ops = ieee80211_get_crypto_ops(alg);
598 	if (ops == NULL) {
599 		request_module(module);
600 		ops = ieee80211_get_crypto_ops(alg);
601 	}
602 	if (ops == NULL) {
603 		IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
604 				   dev->name, ext->alg);
605 		printk("========>unknown crypto alg %d\n", ext->alg);
606 		ret = -EINVAL;
607 		goto done;
608 	}
609 
610 	if (*crypt == NULL || (*crypt)->ops != ops) {
611 		struct ieee80211_crypt_data *new_crypt;
612 
613 		ieee80211_crypt_delayed_deinit(ieee, crypt);
614 
615 		new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
616 		if (new_crypt == NULL) {
617 			ret = -ENOMEM;
618 			goto done;
619 		}
620 		new_crypt->ops = ops;
621 		if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
622 			new_crypt->priv = new_crypt->ops->init(idx);
623 		if (new_crypt->priv == NULL) {
624 			kfree(new_crypt);
625 			ret = -EINVAL;
626 			goto done;
627 		}
628 		*crypt = new_crypt;
629 
630 	}
631 
632 	if (ext->key_len > 0 && (*crypt)->ops->set_key &&
633 	    (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
634 				   (*crypt)->priv) < 0) {
635 		IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
636 		printk("key setting failed\n");
637 		ret = -EINVAL;
638 		goto done;
639 	}
640  //skip_host_crypt:
641 	//printk("skip_host_crypt:ext_flags:%x\n", ext->ext_flags);
642 	if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
643 		ieee->tx_keyidx = idx;
644 		sec.active_key = idx;
645 		sec.flags |= SEC_ACTIVE_KEY;
646 	}
647 
648 	if (ext->alg != IW_ENCODE_ALG_NONE) {
649 		//memcpy(sec.keys[idx], ext->key, ext->key_len);
650 		sec.key_sizes[idx] = ext->key_len;
651 		sec.flags |= (1 << idx);
652 		if (ext->alg == IW_ENCODE_ALG_WEP) {
653 		      //  sec.encode_alg[idx] = SEC_ALG_WEP;
654 			sec.flags |= SEC_LEVEL;
655 			sec.level = SEC_LEVEL_1;
656 		} else if (ext->alg == IW_ENCODE_ALG_TKIP) {
657 		      //  sec.encode_alg[idx] = SEC_ALG_TKIP;
658 			sec.flags |= SEC_LEVEL;
659 			sec.level = SEC_LEVEL_2;
660 		} else if (ext->alg == IW_ENCODE_ALG_CCMP) {
661 		       // sec.encode_alg[idx] = SEC_ALG_CCMP;
662 			sec.flags |= SEC_LEVEL;
663 			sec.level = SEC_LEVEL_3;
664 		}
665 		/* Don't set sec level for group keys. */
666 		if (group_key)
667 			sec.flags &= ~SEC_LEVEL;
668 	}
669 done:
670 	if (ieee->set_security)
671 		ieee->set_security(ieee->dev, &sec);
672 
673 	 if (ieee->reset_on_keychange &&
674 	    ieee->iw_mode != IW_MODE_INFRA &&
675 	    ieee->reset_port && ieee->reset_port(dev)) {
676 		IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
677 		return -EINVAL;
678 	}
679 	return ret;
680 }
681 EXPORT_SYMBOL(ieee80211_wx_set_encode_ext);
682 
ieee80211_wx_get_encode_ext(struct ieee80211_device * ieee,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)683 int ieee80211_wx_get_encode_ext(struct ieee80211_device *ieee,
684 			       struct iw_request_info *info,
685 			       union iwreq_data *wrqu, char *extra)
686 {
687 	struct iw_point *encoding = &wrqu->encoding;
688 	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
689 	struct ieee80211_crypt_data *crypt;
690 	int idx, max_key_len;
691 
692 	max_key_len = encoding->length - sizeof(*ext);
693 	if (max_key_len < 0)
694 		return -EINVAL;
695 
696 	idx = encoding->flags & IW_ENCODE_INDEX;
697 	if (idx) {
698 		if (idx < 1 || idx > WEP_KEYS)
699 			return -EINVAL;
700 		idx--;
701 	} else
702 		idx = ieee->tx_keyidx;
703 
704 	if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
705 	    ext->alg != IW_ENCODE_ALG_WEP)
706 		if (idx != 0 || ieee->iw_mode != IW_MODE_INFRA)
707 			return -EINVAL;
708 
709 	crypt = ieee->crypt[idx];
710 	encoding->flags = idx + 1;
711 	memset(ext, 0, sizeof(*ext));
712 
713 	if (crypt == NULL || crypt->ops == NULL ) {
714 		ext->alg = IW_ENCODE_ALG_NONE;
715 		ext->key_len = 0;
716 		encoding->flags |= IW_ENCODE_DISABLED;
717 	} else {
718 		if (strcmp(crypt->ops->name, "WEP") == 0 )
719 			ext->alg = IW_ENCODE_ALG_WEP;
720 		else if (strcmp(crypt->ops->name, "TKIP"))
721 			ext->alg = IW_ENCODE_ALG_TKIP;
722 		else if (strcmp(crypt->ops->name, "CCMP"))
723 			ext->alg = IW_ENCODE_ALG_CCMP;
724 		else
725 			return -EINVAL;
726 		ext->key_len = crypt->ops->get_key(ext->key, SCM_KEY_LEN, NULL, crypt->priv);
727 		encoding->flags |= IW_ENCODE_ENABLED;
728 		if (ext->key_len &&
729 		    (ext->alg == IW_ENCODE_ALG_TKIP ||
730 		     ext->alg == IW_ENCODE_ALG_CCMP))
731 			ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
732 
733 	}
734 
735 	return 0;
736 }
737 EXPORT_SYMBOL(ieee80211_wx_get_encode_ext);
738 
ieee80211_wx_set_mlme(struct ieee80211_device * ieee,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)739 int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
740 			       struct iw_request_info *info,
741 			       union iwreq_data *wrqu, char *extra)
742 {
743 	struct iw_mlme *mlme = (struct iw_mlme *) extra;
744 	switch (mlme->cmd) {
745 	case IW_MLME_DEAUTH:
746 	case IW_MLME_DISASSOC:
747 		ieee80211_disassociate(ieee);
748 		break;
749 	default:
750 		return -EOPNOTSUPP;
751 	}
752 	return 0;
753 }
754 EXPORT_SYMBOL(ieee80211_wx_set_mlme);
755 
ieee80211_wx_set_auth(struct ieee80211_device * ieee,struct iw_request_info * info,struct iw_param * data,char * extra)756 int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
757 			       struct iw_request_info *info,
758 			       struct iw_param *data, char *extra)
759 {
760 	switch (data->flags & IW_AUTH_INDEX) {
761 	case IW_AUTH_WPA_VERSION:
762 	     /*need to support wpa2 here*/
763 		//printk("wpa version:%x\n", data->value);
764 		break;
765 	case IW_AUTH_CIPHER_PAIRWISE:
766 	case IW_AUTH_CIPHER_GROUP:
767 	case IW_AUTH_KEY_MGMT:
768 		/*
769  *                  * Host AP driver does not use these parameters and allows
770  *                                   * wpa_supplicant to control them internally.
771  *                                                    */
772 		break;
773 	case IW_AUTH_TKIP_COUNTERMEASURES:
774 		ieee->tkip_countermeasures = data->value;
775 		break;
776 	case IW_AUTH_DROP_UNENCRYPTED:
777 		ieee->drop_unencrypted = data->value;
778 		break;
779 
780 	case IW_AUTH_80211_AUTH_ALG:
781 		//printk("======>%s():data->value is %d\n",__func__,data->value);
782 	//	ieee->open_wep = (data->value&IW_AUTH_ALG_OPEN_SYSTEM)?1:0;
783 		if(data->value & IW_AUTH_ALG_SHARED_KEY){
784 			ieee->open_wep = 0;
785 			ieee->auth_mode = 1;
786 		}
787 		else if(data->value & IW_AUTH_ALG_OPEN_SYSTEM){
788 			ieee->open_wep = 1;
789 			ieee->auth_mode = 0;
790 		}
791 		else if(data->value & IW_AUTH_ALG_LEAP){
792 			ieee->open_wep = 1;
793 			ieee->auth_mode = 2;
794 			//printk("hahahaa:LEAP\n");
795 		}
796 		else
797 			return -EINVAL;
798 		//printk("open_wep:%d\n", ieee->open_wep);
799 		break;
800 
801 	case IW_AUTH_WPA_ENABLED:
802 		ieee->wpa_enabled = (data->value)?1:0;
803 		//printk("enalbe wpa:%d\n", ieee->wpa_enabled);
804 		break;
805 
806 	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
807 		ieee->ieee802_1x = data->value;
808 		break;
809 	case IW_AUTH_PRIVACY_INVOKED:
810 		ieee->privacy_invoked = data->value;
811 		break;
812 	default:
813 		return -EOPNOTSUPP;
814 	}
815 	return 0;
816 }
817 EXPORT_SYMBOL(ieee80211_wx_set_auth);
818 
ieee80211_wx_set_gen_ie(struct ieee80211_device * ieee,u8 * ie,size_t len)819 int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
820 {
821 	u8 *buf;
822 
823 	if (len>MAX_WPA_IE_LEN || (len && ie == NULL))
824 	{
825 	//	printk("return error out, len:%d\n", len);
826 	return -EINVAL;
827 	}
828 
829 
830 	if (len)
831 	{
832 		if (len != ie[1]+2)
833 		{
834 			printk("len:%zu, ie:%d\n", len, ie[1]);
835 			return -EINVAL;
836 		}
837 		buf = kmemdup(ie, len, GFP_KERNEL);
838 		if (buf == NULL)
839 			return -ENOMEM;
840 		kfree(ieee->wpa_ie);
841 		ieee->wpa_ie = buf;
842 		ieee->wpa_ie_len = len;
843 	}
844 	else{
845 		kfree(ieee->wpa_ie);
846 		ieee->wpa_ie = NULL;
847 		ieee->wpa_ie_len = 0;
848 	}
849 	return 0;
850 
851 }
852 EXPORT_SYMBOL(ieee80211_wx_set_gen_ie);
853