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 < (sizeof(rtllib_modes)/sizeof(rtllib_modes[0])); 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 		if (!memcmp(network->bssht.bdHTCapBuf, EWC11NHTCap, 4))
162 			ht_cap = (struct ht_capab_ele *)
163 				 &network->bssht.bdHTCapBuf[4];
164 		else
165 			ht_cap = (struct ht_capab_ele *)
166 				 &network->bssht.bdHTCapBuf[0];
167 		is40M = (ht_cap->ChlWidth) ? 1 : 0;
168 		isShortGI = (ht_cap->ChlWidth) ?
169 				((ht_cap->ShortGI40Mhz) ? 1 : 0) :
170 				((ht_cap->ShortGI20Mhz) ? 1 : 0);
171 
172 		max_mcs = HTGetHighestMCSRate(ieee, ht_cap->MCS,
173 					      MCS_FILTER_ALL);
174 		rate = MCS_DATA_RATE[is40M][isShortGI][max_mcs & 0x7f];
175 		if (rate > max_rate)
176 			max_rate = rate;
177 	}
178 	iwe.cmd = SIOCGIWRATE;
179 	iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
180 	iwe.u.bitrate.value = max_rate * 500000;
181 	start = iwe_stream_add_event_rsl(info, start, stop, &iwe,
182 				     IW_EV_PARAM_LEN);
183 	iwe.cmd = IWEVCUSTOM;
184 	iwe.u.data.length = p - custom;
185 	if (iwe.u.data.length)
186 		start = iwe_stream_add_point_rsl(info, start, stop,
187 						 &iwe, custom);
188 	/* Add quality statistics */
189 	/* TODO: Fix these values... */
190 	iwe.cmd = IWEVQUAL;
191 	iwe.u.qual.qual = network->stats.signal;
192 	iwe.u.qual.level = network->stats.rssi;
193 	iwe.u.qual.noise = network->stats.noise;
194 	iwe.u.qual.updated = network->stats.mask & RTLLIB_STATMASK_WEMASK;
195 	if (!(network->stats.mask & RTLLIB_STATMASK_RSSI))
196 		iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
197 	if (!(network->stats.mask & RTLLIB_STATMASK_NOISE))
198 		iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
199 	if (!(network->stats.mask & RTLLIB_STATMASK_SIGNAL))
200 		iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID;
201 	iwe.u.qual.updated = 7;
202 	start = iwe_stream_add_event_rsl(info, start, stop, &iwe,
203 					 IW_EV_QUAL_LEN);
204 
205 	iwe.cmd = IWEVCUSTOM;
206 	p = custom;
207 	iwe.u.data.length = p - custom;
208 	if (iwe.u.data.length)
209 		start = iwe_stream_add_point_rsl(info, start, stop,
210 						 &iwe, custom);
211 
212 	memset(&iwe, 0, sizeof(iwe));
213 	if (network->wpa_ie_len) {
214 		char buf[MAX_WPA_IE_LEN];
215 		memcpy(buf, network->wpa_ie, network->wpa_ie_len);
216 		iwe.cmd = IWEVGENIE;
217 		iwe.u.data.length = network->wpa_ie_len;
218 		start = iwe_stream_add_point_rsl(info, start, stop, &iwe, buf);
219 	}
220 	memset(&iwe, 0, sizeof(iwe));
221 	if (network->rsn_ie_len) {
222 		char buf[MAX_WPA_IE_LEN];
223 		memcpy(buf, network->rsn_ie, network->rsn_ie_len);
224 		iwe.cmd = IWEVGENIE;
225 		iwe.u.data.length = network->rsn_ie_len;
226 		start = iwe_stream_add_point_rsl(info, start, stop, &iwe, buf);
227 	}
228 
229 	/* add info for WZC */
230 	memset(&iwe, 0, sizeof(iwe));
231 	if (network->wzc_ie_len) {
232 		char buf[MAX_WZC_IE_LEN];
233 		memcpy(buf, network->wzc_ie, network->wzc_ie_len);
234 		iwe.cmd = IWEVGENIE;
235 		iwe.u.data.length = network->wzc_ie_len;
236 		start = iwe_stream_add_point_rsl(info, start, stop, &iwe, buf);
237 	}
238 
239 	/* Add EXTRA: Age to display seconds since last beacon/probe response
240 	 * for given network. */
241 	iwe.cmd = IWEVCUSTOM;
242 	p = custom;
243 	p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
244 		      " Last beacon: %lums ago",
245 		      (jiffies - network->last_scanned) / (HZ / 100));
246 	iwe.u.data.length = p - custom;
247 	if (iwe.u.data.length)
248 		start = iwe_stream_add_point_rsl(info, start, stop,
249 						 &iwe, custom);
250 
251 	return start;
252 }
253 
rtllib_wx_get_scan(struct rtllib_device * ieee,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)254 int rtllib_wx_get_scan(struct rtllib_device *ieee,
255 			  struct iw_request_info *info,
256 			  union iwreq_data *wrqu, char *extra)
257 {
258 	struct rtllib_network *network;
259 	unsigned long flags;
260 
261 	char *ev = extra;
262 	char *stop = ev + wrqu->data.length;
263 	int i = 0;
264 	int err = 0;
265 	RTLLIB_DEBUG_WX("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 			RTLLIB_DEBUG_SCAN("Not showing network '%s ("
281 				" %pM)' due to age (%lums).\n",
282 				escape_essid(network->ssid,
283 					     network->ssid_len),
284 				network->bssid,
285 				(jiffies - network->last_scanned) / (HZ / 100));
286 	}
287 
288 	spin_unlock_irqrestore(&ieee->lock, flags);
289 	up(&ieee->wx_sem);
290 	wrqu->data.length = ev -  extra;
291 	wrqu->data.flags = 0;
292 
293 	RTLLIB_DEBUG_WX("exit: %d networks returned.\n", i);
294 
295 	return err;
296 }
297 EXPORT_SYMBOL(rtllib_wx_get_scan);
298 
rtllib_wx_set_encode(struct rtllib_device * ieee,struct iw_request_info * info,union iwreq_data * wrqu,char * keybuf)299 int rtllib_wx_set_encode(struct rtllib_device *ieee,
300 			    struct iw_request_info *info,
301 			    union iwreq_data *wrqu, char *keybuf)
302 {
303 	struct iw_point *erq = &(wrqu->encoding);
304 	struct net_device *dev = ieee->dev;
305 	struct rtllib_security sec = {
306 		.flags = 0
307 	};
308 	int i, key, key_provided, len;
309 	struct lib80211_crypt_data **crypt;
310 
311 	RTLLIB_DEBUG_WX("SET_ENCODE\n");
312 
313 	key = erq->flags & IW_ENCODE_INDEX;
314 	if (key) {
315 		if (key > NUM_WEP_KEYS)
316 			return -EINVAL;
317 		key--;
318 		key_provided = 1;
319 	} else {
320 		key_provided = 0;
321 		key = ieee->crypt_info.tx_keyidx;
322 	}
323 
324 	RTLLIB_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
325 			   "provided" : "default");
326 	crypt = &ieee->crypt_info.crypt[key];
327 	if (erq->flags & IW_ENCODE_DISABLED) {
328 		if (key_provided && *crypt) {
329 			RTLLIB_DEBUG_WX("Disabling encryption on key %d.\n",
330 					   key);
331 			lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
332 		} else
333 			RTLLIB_DEBUG_WX("Disabling encryption.\n");
334 
335 		/* Check all the keys to see if any are still configured,
336 		 * and if no key index was provided, de-init them all */
337 		for (i = 0; i < NUM_WEP_KEYS; i++) {
338 			if (ieee->crypt_info.crypt[i] != NULL) {
339 				if (key_provided)
340 					break;
341 				lib80211_crypt_delayed_deinit(&ieee->crypt_info,
342 							    &ieee->crypt_info.crypt[i]);
343 			}
344 		}
345 
346 		if (i == NUM_WEP_KEYS) {
347 			sec.enabled = 0;
348 			sec.level = SEC_LEVEL_0;
349 			sec.flags |= SEC_ENABLED | SEC_LEVEL;
350 		}
351 
352 		goto done;
353 	}
354 
355 
356 
357 	sec.enabled = 1;
358 	sec.flags |= SEC_ENABLED;
359 
360 	if (*crypt != NULL && (*crypt)->ops != NULL &&
361 	    strcmp((*crypt)->ops->name, "R-WEP") != 0) {
362 		/* changing to use WEP; deinit previously used algorithm
363 		 * on this key */
364 		lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
365 	}
366 
367 	if (*crypt == NULL) {
368 		struct lib80211_crypt_data *new_crypt;
369 
370 		/* take WEP into use */
371 		new_crypt = kzalloc(sizeof(struct lib80211_crypt_data),
372 				    GFP_KERNEL);
373 		if (new_crypt == NULL)
374 			return -ENOMEM;
375 		new_crypt->ops = lib80211_get_crypto_ops("R-WEP");
376 		if (!new_crypt->ops) {
377 			request_module("rtllib_crypt_wep");
378 			new_crypt->ops = lib80211_get_crypto_ops("R-WEP");
379 		}
380 
381 		if (new_crypt->ops)
382 			new_crypt->priv = new_crypt->ops->init(key);
383 
384 		if (!new_crypt->ops || !new_crypt->priv) {
385 			kfree(new_crypt);
386 			new_crypt = NULL;
387 
388 			printk(KERN_WARNING "%s: could not initialize WEP: "
389 			       "load module rtllib_crypt_wep\n",
390 			       dev->name);
391 			return -EOPNOTSUPP;
392 		}
393 		*crypt = new_crypt;
394 	}
395 
396 	/* If a new key was provided, set it up */
397 	if (erq->length > 0) {
398 		len = erq->length <= 5 ? 5 : 13;
399 		memcpy(sec.keys[key], keybuf, erq->length);
400 		if (len > erq->length)
401 			memset(sec.keys[key] + erq->length, 0,
402 			       len - erq->length);
403 		RTLLIB_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
404 				   key, escape_essid(sec.keys[key], len),
405 				   erq->length, len);
406 		sec.key_sizes[key] = len;
407 		(*crypt)->ops->set_key(sec.keys[key], len, NULL,
408 				       (*crypt)->priv);
409 		sec.flags |= (1 << key);
410 		/* This ensures a key will be activated if no key is
411 		 * explicitely set */
412 		if (key == sec.active_key)
413 			sec.flags |= SEC_ACTIVE_KEY;
414 		ieee->crypt_info.tx_keyidx = key;
415 
416 	} else {
417 		len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
418 					     NULL, (*crypt)->priv);
419 		if (len == 0) {
420 			/* Set a default key of all 0 */
421 			printk(KERN_INFO "Setting key %d to all zero.\n",
422 					   key);
423 
424 			RTLLIB_DEBUG_WX("Setting key %d to all zero.\n",
425 					   key);
426 			memset(sec.keys[key], 0, 13);
427 			(*crypt)->ops->set_key(sec.keys[key], 13, NULL,
428 					       (*crypt)->priv);
429 			sec.key_sizes[key] = 13;
430 			sec.flags |= (1 << key);
431 		}
432 
433 		/* No key data - just set the default TX key index */
434 		if (key_provided) {
435 			RTLLIB_DEBUG_WX(
436 				"Setting key %d to default Tx key.\n", key);
437 			ieee->crypt_info.tx_keyidx = key;
438 			sec.active_key = key;
439 			sec.flags |= SEC_ACTIVE_KEY;
440 		}
441 	}
442  done:
443 	ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
444 	ieee->auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN :
445 			  WLAN_AUTH_SHARED_KEY;
446 	sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
447 	sec.flags |= SEC_AUTH_MODE;
448 	RTLLIB_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
449 			   "OPEN" : "SHARED KEY");
450 
451 	/* For now we just support WEP, so only set that security level...
452 	 * TODO: When WPA is added this is one place that needs to change */
453 	sec.flags |= SEC_LEVEL;
454 	sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
455 
456 	if (ieee->set_security)
457 		ieee->set_security(dev, &sec);
458 
459 	/* Do not reset port if card is in Managed mode since resetting will
460 	 * generate new IEEE 802.11 authentication which may end up in looping
461 	 * with IEEE 802.1X.  If your hardware requires a reset after WEP
462 	 * configuration (for example... Prism2), implement the reset_port in
463 	 * the callbacks structures used to initialize the 802.11 stack. */
464 	if (ieee->reset_on_keychange &&
465 	    ieee->iw_mode != IW_MODE_INFRA &&
466 	    ieee->reset_port && ieee->reset_port(dev)) {
467 		printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
468 		return -EINVAL;
469 	}
470 	return 0;
471 }
472 EXPORT_SYMBOL(rtllib_wx_set_encode);
473 
rtllib_wx_get_encode(struct rtllib_device * ieee,struct iw_request_info * info,union iwreq_data * wrqu,char * keybuf)474 int rtllib_wx_get_encode(struct rtllib_device *ieee,
475 			    struct iw_request_info *info,
476 			    union iwreq_data *wrqu, char *keybuf)
477 {
478 	struct iw_point *erq = &(wrqu->encoding);
479 	int len, key;
480 	struct lib80211_crypt_data *crypt;
481 
482 	RTLLIB_DEBUG_WX("GET_ENCODE\n");
483 
484 	if (ieee->iw_mode == IW_MODE_MONITOR)
485 		return -1;
486 
487 	key = erq->flags & IW_ENCODE_INDEX;
488 	if (key) {
489 		if (key > NUM_WEP_KEYS)
490 			return -EINVAL;
491 		key--;
492 	} else {
493 		key = ieee->crypt_info.tx_keyidx;
494 	}
495 	crypt = ieee->crypt_info.crypt[key];
496 
497 	erq->flags = key + 1;
498 
499 	if (crypt == NULL || crypt->ops == NULL) {
500 		erq->length = 0;
501 		erq->flags |= IW_ENCODE_DISABLED;
502 		return 0;
503 	}
504 	len = crypt->ops->get_key(keybuf, SCM_KEY_LEN, NULL, crypt->priv);
505 	erq->length = (len >= 0 ? len : 0);
506 
507 	erq->flags |= IW_ENCODE_ENABLED;
508 
509 	if (ieee->open_wep)
510 		erq->flags |= IW_ENCODE_OPEN;
511 	else
512 		erq->flags |= IW_ENCODE_RESTRICTED;
513 
514 	return 0;
515 }
516 EXPORT_SYMBOL(rtllib_wx_get_encode);
517 
rtllib_wx_set_encode_ext(struct rtllib_device * ieee,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)518 int rtllib_wx_set_encode_ext(struct rtllib_device *ieee,
519 			       struct iw_request_info *info,
520 			       union iwreq_data *wrqu, char *extra)
521 {
522 	int ret = 0;
523 	struct net_device *dev = ieee->dev;
524 	struct iw_point *encoding = &wrqu->encoding;
525 	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
526 	int i, idx;
527 	int group_key = 0;
528 	const char *alg, *module;
529 	struct lib80211_crypto_ops *ops;
530 	struct lib80211_crypt_data **crypt;
531 
532 	struct rtllib_security sec = {
533 		.flags = 0,
534 	};
535 	idx = encoding->flags & IW_ENCODE_INDEX;
536 	if (idx) {
537 		if (idx < 1 || idx > NUM_WEP_KEYS)
538 			return -EINVAL;
539 		idx--;
540 	} else{
541 			idx = ieee->crypt_info.tx_keyidx;
542 	}
543 	if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
544 		crypt = &ieee->crypt_info.crypt[idx];
545 		group_key = 1;
546 	} else {
547 		/* some Cisco APs use idx>0 for unicast in dynamic WEP */
548 		if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
549 			return -EINVAL;
550 		if (ieee->iw_mode == IW_MODE_INFRA)
551 			crypt = &ieee->crypt_info.crypt[idx];
552 		else
553 			return -EINVAL;
554 	}
555 
556 	sec.flags |= SEC_ENABLED;
557 	if ((encoding->flags & IW_ENCODE_DISABLED) ||
558 	    ext->alg == IW_ENCODE_ALG_NONE) {
559 		if (*crypt)
560 			lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
561 
562 		for (i = 0; i < NUM_WEP_KEYS; i++) {
563 			if (ieee->crypt_info.crypt[i] != NULL)
564 				break;
565 		}
566 		if (i == NUM_WEP_KEYS) {
567 			sec.enabled = 0;
568 			sec.level = SEC_LEVEL_0;
569 			sec.flags |= SEC_LEVEL;
570 		}
571 		goto done;
572 	}
573 
574 	sec.enabled = 1;
575 	switch (ext->alg) {
576 	case IW_ENCODE_ALG_WEP:
577 		alg = "R-WEP";
578 		module = "rtllib_crypt_wep";
579 		break;
580 	case IW_ENCODE_ALG_TKIP:
581 		alg = "R-TKIP";
582 		module = "rtllib_crypt_tkip";
583 		break;
584 	case IW_ENCODE_ALG_CCMP:
585 		alg = "R-CCMP";
586 		module = "rtllib_crypt_ccmp";
587 		break;
588 	default:
589 		RTLLIB_DEBUG_WX("%s: unknown crypto alg %d\n",
590 				   dev->name, ext->alg);
591 		ret = -EINVAL;
592 		goto done;
593 	}
594 	printk(KERN_INFO "alg name:%s\n", alg);
595 
596 	ops = lib80211_get_crypto_ops(alg);
597 	if (ops == NULL) {
598 		char tempbuf[100];
599 
600 		memset(tempbuf, 0x00, 100);
601 		sprintf(tempbuf, "%s", module);
602 		request_module("%s", tempbuf);
603 		ops = lib80211_get_crypto_ops(alg);
604 	}
605 	if (ops == NULL) {
606 		RTLLIB_DEBUG_WX("%s: unknown crypto alg %d\n",
607 				   dev->name, ext->alg);
608 		printk(KERN_INFO "========>unknown crypto alg %d\n", ext->alg);
609 		ret = -EINVAL;
610 		goto done;
611 	}
612 
613 	if (*crypt == NULL || (*crypt)->ops != ops) {
614 		struct lib80211_crypt_data *new_crypt;
615 
616 		lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
617 
618 		new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
619 		if (new_crypt == NULL) {
620 			ret = -ENOMEM;
621 			goto done;
622 		}
623 		new_crypt->ops = ops;
624 		if (new_crypt->ops)
625 			new_crypt->priv = new_crypt->ops->init(idx);
626 
627 		if (new_crypt->priv == NULL) {
628 			kfree(new_crypt);
629 			ret = -EINVAL;
630 			goto done;
631 		}
632 		*crypt = new_crypt;
633 
634 	}
635 
636 	if (ext->key_len > 0 && (*crypt)->ops->set_key &&
637 	    (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
638 				   (*crypt)->priv) < 0) {
639 		RTLLIB_DEBUG_WX("%s: key setting failed\n", dev->name);
640 		printk(KERN_INFO "key setting failed\n");
641 		ret = -EINVAL;
642 		goto done;
643 	}
644 	if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
645 		ieee->crypt_info.tx_keyidx = idx;
646 		sec.active_key = idx;
647 		sec.flags |= SEC_ACTIVE_KEY;
648 	}
649 	if (ext->alg != IW_ENCODE_ALG_NONE) {
650 		sec.key_sizes[idx] = ext->key_len;
651 		sec.flags |= (1 << idx);
652 		if (ext->alg == IW_ENCODE_ALG_WEP) {
653 			sec.flags |= SEC_LEVEL;
654 			sec.level = SEC_LEVEL_1;
655 		} else if (ext->alg == IW_ENCODE_ALG_TKIP) {
656 			sec.flags |= SEC_LEVEL;
657 			sec.level = SEC_LEVEL_2;
658 		} else if (ext->alg == IW_ENCODE_ALG_CCMP) {
659 			sec.flags |= SEC_LEVEL;
660 			sec.level = SEC_LEVEL_3;
661 		}
662 		/* Don't set sec level for group keys. */
663 		if (group_key)
664 			sec.flags &= ~SEC_LEVEL;
665 	}
666 done:
667 	if (ieee->set_security)
668 		ieee->set_security(ieee->dev, &sec);
669 
670 	 if (ieee->reset_on_keychange &&
671 	    ieee->iw_mode != IW_MODE_INFRA &&
672 	    ieee->reset_port && ieee->reset_port(dev)) {
673 		RTLLIB_DEBUG_WX("%s: reset_port failed\n", dev->name);
674 		return -EINVAL;
675 	}
676 	return ret;
677 }
678 EXPORT_SYMBOL(rtllib_wx_set_encode_ext);
679 
rtllib_wx_get_encode_ext(struct rtllib_device * ieee,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)680 int rtllib_wx_get_encode_ext(struct rtllib_device *ieee,
681 			       struct iw_request_info *info,
682 			       union iwreq_data *wrqu, char *extra)
683 {
684 	struct iw_point *encoding = &wrqu->encoding;
685 	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
686 	struct lib80211_crypt_data *crypt;
687 	int idx, max_key_len;
688 
689 	max_key_len = encoding->length - sizeof(*ext);
690 	if (max_key_len < 0)
691 		return -EINVAL;
692 
693 	idx = encoding->flags & IW_ENCODE_INDEX;
694 	if (idx) {
695 		if (idx < 1 || idx > NUM_WEP_KEYS)
696 			return -EINVAL;
697 		idx--;
698 	} else {
699 		idx = ieee->crypt_info.tx_keyidx;
700 	}
701 	if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
702 	    (ext->alg != IW_ENCODE_ALG_WEP))
703 		if (idx != 0 || (ieee->iw_mode != IW_MODE_INFRA))
704 			return -EINVAL;
705 
706 	crypt = ieee->crypt_info.crypt[idx];
707 
708 	encoding->flags = idx + 1;
709 	memset(ext, 0, sizeof(*ext));
710 
711 	if (crypt == NULL || crypt->ops == NULL) {
712 		ext->alg = IW_ENCODE_ALG_NONE;
713 		ext->key_len = 0;
714 		encoding->flags |= IW_ENCODE_DISABLED;
715 	} else {
716 		if (strcmp(crypt->ops->name, "R-WEP") == 0)
717 			ext->alg = IW_ENCODE_ALG_WEP;
718 		else if (strcmp(crypt->ops->name, "R-TKIP"))
719 			ext->alg = IW_ENCODE_ALG_TKIP;
720 		else if (strcmp(crypt->ops->name, "R-CCMP"))
721 			ext->alg = IW_ENCODE_ALG_CCMP;
722 		else
723 			return -EINVAL;
724 		ext->key_len = crypt->ops->get_key(ext->key, SCM_KEY_LEN,
725 						   NULL, crypt->priv);
726 		encoding->flags |= IW_ENCODE_ENABLED;
727 		if (ext->key_len &&
728 		    (ext->alg == IW_ENCODE_ALG_TKIP ||
729 		     ext->alg == IW_ENCODE_ALG_CCMP))
730 			ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
731 
732 	}
733 
734 	return 0;
735 }
736 
rtllib_wx_set_mlme(struct rtllib_device * ieee,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)737 int rtllib_wx_set_mlme(struct rtllib_device *ieee,
738 			       struct iw_request_info *info,
739 			       union iwreq_data *wrqu, char *extra)
740 {
741 	u8 i = 0;
742 	bool deauth = false;
743 	struct iw_mlme *mlme = (struct iw_mlme *) extra;
744 
745 	if (ieee->state != RTLLIB_LINKED)
746 		return -ENOLINK;
747 
748 	down(&ieee->wx_sem);
749 
750 	switch (mlme->cmd) {
751 	case IW_MLME_DEAUTH:
752 		deauth = true;
753 		/* leave break out intentionly */
754 
755 	case IW_MLME_DISASSOC:
756 		if (deauth == true)
757 			printk(KERN_INFO "disauth packet !\n");
758 		else
759 			printk(KERN_INFO "dis associate packet!\n");
760 
761 		ieee->cannot_notify = true;
762 
763 		SendDisassociation(ieee, deauth, mlme->reason_code);
764 		rtllib_disassociate(ieee);
765 
766 		ieee->wap_set = 0;
767 		for (i = 0; i < 6; i++)
768 			ieee->current_network.bssid[i] = 0x55;
769 
770 		ieee->ssid_set = 0;
771 		ieee->current_network.ssid[0] = '\0';
772 		ieee->current_network.ssid_len = 0;
773 		break;
774 	default:
775 		up(&ieee->wx_sem);
776 		return -EOPNOTSUPP;
777 	}
778 
779 	up(&ieee->wx_sem);
780 
781 	return 0;
782 }
783 EXPORT_SYMBOL(rtllib_wx_set_mlme);
784 
rtllib_wx_set_auth(struct rtllib_device * ieee,struct iw_request_info * info,struct iw_param * data,char * extra)785 int rtllib_wx_set_auth(struct rtllib_device *ieee,
786 			       struct iw_request_info *info,
787 			       struct iw_param *data, char *extra)
788 {
789 	switch (data->flags & IW_AUTH_INDEX) {
790 	case IW_AUTH_WPA_VERSION:
791 		break;
792 	case IW_AUTH_CIPHER_PAIRWISE:
793 	case IW_AUTH_CIPHER_GROUP:
794 	case IW_AUTH_KEY_MGMT:
795 		/*
796 		 * Host AP driver does not use these parameters and allows
797 		 * wpa_supplicant to control them internally.
798 		 */
799 		break;
800 	case IW_AUTH_TKIP_COUNTERMEASURES:
801 		ieee->tkip_countermeasures = data->value;
802 		break;
803 	case IW_AUTH_DROP_UNENCRYPTED:
804 		ieee->drop_unencrypted = data->value;
805 		break;
806 
807 	case IW_AUTH_80211_AUTH_ALG:
808 		if (data->value & IW_AUTH_ALG_SHARED_KEY) {
809 			ieee->open_wep = 0;
810 			ieee->auth_mode = 1;
811 		} else if (data->value & IW_AUTH_ALG_OPEN_SYSTEM) {
812 			ieee->open_wep = 1;
813 			ieee->auth_mode = 0;
814 		} else if (data->value & IW_AUTH_ALG_LEAP) {
815 			ieee->open_wep = 1;
816 			ieee->auth_mode = 2;
817 		} else
818 			return -EINVAL;
819 		break;
820 
821 	case IW_AUTH_WPA_ENABLED:
822 		ieee->wpa_enabled = (data->value) ? 1 : 0;
823 		break;
824 
825 	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
826 		ieee->ieee802_1x = data->value;
827 		break;
828 	case IW_AUTH_PRIVACY_INVOKED:
829 		ieee->privacy_invoked = data->value;
830 		break;
831 	default:
832 		return -EOPNOTSUPP;
833 	}
834 	return 0;
835 }
836 EXPORT_SYMBOL(rtllib_wx_set_auth);
837 
rtllib_wx_set_gen_ie(struct rtllib_device * ieee,u8 * ie,size_t len)838 int rtllib_wx_set_gen_ie(struct rtllib_device *ieee, u8 *ie, size_t len)
839 {
840 	u8 *buf;
841 	u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
842 
843 	if (len > MAX_WPA_IE_LEN || (len && ie == NULL))
844 		return -EINVAL;
845 
846 	if (len) {
847 		eid = ie[0];
848 		if ((eid == MFIE_TYPE_GENERIC) && (!memcmp(&ie[2],
849 		     wps_oui, 4))) {
850 
851 			ieee->wps_ie_len = (len < MAX_WZC_IE_LEN) ? (len) :
852 					   (MAX_WZC_IE_LEN);
853 			buf = kmemdup(ie, ieee->wps_ie_len, GFP_KERNEL);
854 			if (buf == NULL)
855 				return -ENOMEM;
856 			ieee->wps_ie = buf;
857 			return 0;
858 		}
859 	}
860 	ieee->wps_ie_len = 0;
861 	kfree(ieee->wps_ie);
862 	ieee->wps_ie = NULL;
863 	if (len) {
864 		if (len != ie[1]+2)
865 			return -EINVAL;
866 		buf = kmemdup(ie, len, GFP_KERNEL);
867 		if (buf == NULL)
868 			return -ENOMEM;
869 		kfree(ieee->wpa_ie);
870 		ieee->wpa_ie = buf;
871 		ieee->wpa_ie_len = len;
872 	} else {
873 		kfree(ieee->wpa_ie);
874 		ieee->wpa_ie = NULL;
875 		ieee->wpa_ie_len = 0;
876 	}
877 	return 0;
878 }
879 EXPORT_SYMBOL(rtllib_wx_set_gen_ie);
880