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