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