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