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