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 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 #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 
ieee80211_wx_get_scan(struct ieee80211_device * ieee,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)262 int 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 
ieee80211_wx_set_encode(struct ieee80211_device * ieee,struct iw_request_info * info,union iwreq_data * wrqu,char * keybuf)309 int 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 
ieee80211_wx_get_encode(struct ieee80211_device * ieee,struct iw_request_info * info,union iwreq_data * wrqu,char * keybuf)483 int 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)
ieee80211_wx_set_encode_ext(struct ieee80211_device * ieee,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)525 int 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 	}
686 done:
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 
ieee80211_wx_get_encode_ext(struct ieee80211_device * ieee,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)699 int 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 
ieee80211_wx_set_mlme(struct ieee80211_device * ieee,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)754 int 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 
ieee80211_wx_set_auth(struct ieee80211_device * ieee,struct iw_request_info * info,struct iw_param * data,char * extra)770 int 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
ieee80211_wx_set_gen_ie(struct ieee80211_device * ieee,u8 * ie,size_t len)832 int 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 		kfree(ieee->wpa_ie);
859 		ieee->wpa_ie = NULL;
860 		ieee->wpa_ie_len = 0;
861 	}
862 	return 0;
863 
864 }
865 
866 EXPORT_SYMBOL(ieee80211_wx_set_gen_ie);
867 #if (WIRELESS_EXT >= 18)
868 EXPORT_SYMBOL(ieee80211_wx_set_mlme);
869 EXPORT_SYMBOL(ieee80211_wx_set_auth);
870 EXPORT_SYMBOL(ieee80211_wx_set_encode_ext);
871 EXPORT_SYMBOL(ieee80211_wx_get_encode_ext);
872 #endif
873 EXPORT_SYMBOL(ieee80211_wx_get_scan);
874 EXPORT_SYMBOL(ieee80211_wx_set_encode);
875 EXPORT_SYMBOL(ieee80211_wx_get_encode);
876