1/******************************************************************************
2
3  Copyright(c) 2004-2005 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  <j@w1.fi>
9  Copyright (c) 2002-2003, Jouni Malinen <j@w1.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
33#include <linux/kmod.h>
34#include <linux/module.h>
35#include <linux/jiffies.h>
36
37#include <net/ieee80211.h>
38#include <linux/wireless.h>
39
40static const char *ieee80211_modes[] = {
41	"?", "a", "b", "ab", "g", "ag", "bg", "abg"
42};
43
44#define MAX_CUSTOM_LEN 64
45static char *ieee80211_translate_scan(struct ieee80211_device *ieee,
46					   char *start, char *stop,
47					   struct ieee80211_network *network)
48{
49	char custom[MAX_CUSTOM_LEN];
50	char *p;
51	struct iw_event iwe;
52	int i, j;
53	char *current_val;	/* For rates */
54	u8 rate;
55
56	/* First entry *MUST* be the AP MAC address */
57	iwe.cmd = SIOCGIWAP;
58	iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
59	memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN);
60	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_ADDR_LEN);
61
62	/* Remaining entries will be displayed in the order we provide them */
63
64	/* Add the ESSID */
65	iwe.cmd = SIOCGIWESSID;
66	iwe.u.data.flags = 1;
67	if (network->flags & NETWORK_EMPTY_ESSID) {
68		iwe.u.data.length = sizeof("<hidden>");
69		start = iwe_stream_add_point(start, stop, &iwe, "<hidden>");
70	} else {
71		iwe.u.data.length = min(network->ssid_len, (u8) 32);
72		start = iwe_stream_add_point(start, stop, &iwe, network->ssid);
73	}
74
75	/* Add the protocol name */
76	iwe.cmd = SIOCGIWNAME;
77	snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11%s",
78		 ieee80211_modes[network->mode]);
79	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_CHAR_LEN);
80
81	/* Add mode */
82	iwe.cmd = SIOCGIWMODE;
83	if (network->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {
84		if (network->capability & WLAN_CAPABILITY_ESS)
85			iwe.u.mode = IW_MODE_MASTER;
86		else
87			iwe.u.mode = IW_MODE_ADHOC;
88
89		start = iwe_stream_add_event(start, stop, &iwe, IW_EV_UINT_LEN);
90	}
91
92	/* Add channel and frequency */
93	iwe.cmd = SIOCGIWFREQ;
94	iwe.u.freq.m = network->channel;
95	iwe.u.freq.e = 0;
96	iwe.u.freq.i = 0;
97	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_FREQ_LEN);
98
99	iwe.u.freq.m = ieee80211_channel_to_freq(ieee, network->channel);
100	iwe.u.freq.e = 6;
101	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_FREQ_LEN);
102
103	/* Add encryption capability */
104	iwe.cmd = SIOCGIWENCODE;
105	if (network->capability & WLAN_CAPABILITY_PRIVACY)
106		iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
107	else
108		iwe.u.data.flags = IW_ENCODE_DISABLED;
109	iwe.u.data.length = 0;
110	start = iwe_stream_add_point(start, stop, &iwe, network->ssid);
111
112	/* Add basic and extended rates */
113	/* Rate : stuffing multiple values in a single event require a bit
114	 * more of magic - Jean II */
115	current_val = start + IW_EV_LCP_LEN;
116	iwe.cmd = SIOCGIWRATE;
117	/* Those two flags are ignored... */
118	iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
119
120	for (i = 0, j = 0; i < network->rates_len;) {
121		if (j < network->rates_ex_len &&
122		    ((network->rates_ex[j] & 0x7F) <
123		     (network->rates[i] & 0x7F)))
124			rate = network->rates_ex[j++] & 0x7F;
125		else
126			rate = network->rates[i++] & 0x7F;
127		/* Bit rate given in 500 kb/s units (+ 0x80) */
128		iwe.u.bitrate.value = ((rate & 0x7f) * 500000);
129		/* Add new value to event */
130		current_val = iwe_stream_add_value(start, current_val, stop, &iwe, IW_EV_PARAM_LEN);
131	}
132	for (; j < network->rates_ex_len; j++) {
133		rate = network->rates_ex[j] & 0x7F;
134		/* Bit rate given in 500 kb/s units (+ 0x80) */
135		iwe.u.bitrate.value = ((rate & 0x7f) * 500000);
136		/* Add new value to event */
137		current_val = iwe_stream_add_value(start, current_val, stop, &iwe, IW_EV_PARAM_LEN);
138	}
139	/* Check if we added any rate */
140	if((current_val - start) > IW_EV_LCP_LEN)
141		start = current_val;
142
143	/* Add quality statistics */
144	iwe.cmd = IWEVQUAL;
145	iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED |
146	    IW_QUAL_NOISE_UPDATED;
147
148	if (!(network->stats.mask & IEEE80211_STATMASK_RSSI)) {
149		iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID |
150		    IW_QUAL_LEVEL_INVALID;
151		iwe.u.qual.qual = 0;
152	} else {
153		if (ieee->perfect_rssi == ieee->worst_rssi)
154			iwe.u.qual.qual = 100;
155		else
156			iwe.u.qual.qual =
157			    (100 *
158			     (ieee->perfect_rssi - ieee->worst_rssi) *
159			     (ieee->perfect_rssi - ieee->worst_rssi) -
160			     (ieee->perfect_rssi - network->stats.rssi) *
161			     (15 * (ieee->perfect_rssi - ieee->worst_rssi) +
162			      62 * (ieee->perfect_rssi -
163				    network->stats.rssi))) /
164			    ((ieee->perfect_rssi -
165			      ieee->worst_rssi) * (ieee->perfect_rssi -
166						   ieee->worst_rssi));
167		if (iwe.u.qual.qual > 100)
168			iwe.u.qual.qual = 100;
169		else if (iwe.u.qual.qual < 1)
170			iwe.u.qual.qual = 0;
171	}
172
173	if (!(network->stats.mask & IEEE80211_STATMASK_NOISE)) {
174		iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
175		iwe.u.qual.noise = 0;
176	} else {
177		iwe.u.qual.noise = network->stats.noise;
178	}
179
180	if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL)) {
181		iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
182		iwe.u.qual.level = 0;
183	} else {
184		iwe.u.qual.level = network->stats.signal;
185	}
186
187	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN);
188
189	iwe.cmd = IWEVCUSTOM;
190	p = custom;
191
192	iwe.u.data.length = p - custom;
193	if (iwe.u.data.length)
194		start = iwe_stream_add_point(start, stop, &iwe, custom);
195
196	memset(&iwe, 0, sizeof(iwe));
197	if (network->wpa_ie_len) {
198		char buf[MAX_WPA_IE_LEN];
199		memcpy(buf, network->wpa_ie, network->wpa_ie_len);
200		iwe.cmd = IWEVGENIE;
201		iwe.u.data.length = network->wpa_ie_len;
202		start = iwe_stream_add_point(start, stop, &iwe, buf);
203	}
204
205	memset(&iwe, 0, sizeof(iwe));
206	if (network->rsn_ie_len) {
207		char buf[MAX_WPA_IE_LEN];
208		memcpy(buf, network->rsn_ie, network->rsn_ie_len);
209		iwe.cmd = IWEVGENIE;
210		iwe.u.data.length = network->rsn_ie_len;
211		start = iwe_stream_add_point(start, stop, &iwe, buf);
212	}
213
214	/* Add EXTRA: Age to display seconds since last beacon/probe response
215	 * for given network. */
216	iwe.cmd = IWEVCUSTOM;
217	p = custom;
218	p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
219		      " Last beacon: %dms ago",
220		      jiffies_to_msecs(jiffies - network->last_scanned));
221	iwe.u.data.length = p - custom;
222	if (iwe.u.data.length)
223		start = iwe_stream_add_point(start, stop, &iwe, custom);
224
225	/* Add spectrum management information */
226	iwe.cmd = -1;
227	p = custom;
228	p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Channel flags: ");
229
230	if (ieee80211_get_channel_flags(ieee, network->channel) &
231	    IEEE80211_CH_INVALID) {
232		iwe.cmd = IWEVCUSTOM;
233		p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), "INVALID ");
234	}
235
236	if (ieee80211_get_channel_flags(ieee, network->channel) &
237	    IEEE80211_CH_RADAR_DETECT) {
238		iwe.cmd = IWEVCUSTOM;
239		p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), "DFS ");
240	}
241
242	if (iwe.cmd == IWEVCUSTOM) {
243		iwe.u.data.length = p - custom;
244		start = iwe_stream_add_point(start, stop, &iwe, custom);
245	}
246
247	return start;
248}
249
250#define SCAN_ITEM_SIZE 128
251
252int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
253			  struct iw_request_info *info,
254			  union iwreq_data *wrqu, char *extra)
255{
256	struct ieee80211_network *network;
257	unsigned long flags;
258	int err = 0;
259
260	char *ev = extra;
261	char *stop = ev + wrqu->data.length;
262	int i = 0;
263
264	IEEE80211_DEBUG_WX("Getting scan\n");
265
266	spin_lock_irqsave(&ieee->lock, flags);
267
268	list_for_each_entry(network, &ieee->network_list, list) {
269		i++;
270		if (stop - ev < SCAN_ITEM_SIZE) {
271			err = -E2BIG;
272			break;
273		}
274
275		if (ieee->scan_age == 0 ||
276		    time_after(network->last_scanned + ieee->scan_age, jiffies))
277			ev = ieee80211_translate_scan(ieee, ev, stop, network);
278		else
279			IEEE80211_DEBUG_SCAN("Not showing network '%s ("
280					     MAC_FMT ")' due to age (%dms).\n",
281					     escape_essid(network->ssid,
282							  network->ssid_len),
283					     MAC_ARG(network->bssid),
284					     jiffies_to_msecs(jiffies -
285							      network->
286							      last_scanned));
287	}
288
289	spin_unlock_irqrestore(&ieee->lock, flags);
290
291	wrqu->data.length = ev - extra;
292	wrqu->data.flags = 0;
293
294	IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
295
296	return err;
297}
298
299int ieee80211_wx_set_encode(struct ieee80211_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 ieee80211_security sec = {
306		.flags = 0
307	};
308	int i, key, key_provided, len;
309	struct ieee80211_crypt_data **crypt;
310	int host_crypto = ieee->host_encrypt || ieee->host_decrypt || ieee->host_build_iv;
311
312	IEEE80211_DEBUG_WX("SET_ENCODE\n");
313
314	key = erq->flags & IW_ENCODE_INDEX;
315	if (key) {
316		if (key > WEP_KEYS)
317			return -EINVAL;
318		key--;
319		key_provided = 1;
320	} else {
321		key_provided = 0;
322		key = ieee->tx_keyidx;
323	}
324
325	IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
326			   "provided" : "default");
327
328	crypt = &ieee->crypt[key];
329
330	if (erq->flags & IW_ENCODE_DISABLED) {
331		if (key_provided && *crypt) {
332			IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
333					   key);
334			ieee80211_crypt_delayed_deinit(ieee, crypt);
335		} else
336			IEEE80211_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		for (i = 0; i < WEP_KEYS; i++) {
341			if (ieee->crypt[i] != NULL) {
342				if (key_provided)
343					break;
344				ieee80211_crypt_delayed_deinit(ieee,
345							       &ieee->crypt[i]);
346			}
347		}
348
349		if (i == WEP_KEYS) {
350			sec.enabled = 0;
351			sec.encrypt = 0;
352			sec.level = SEC_LEVEL_0;
353			sec.flags |= SEC_ENABLED | SEC_LEVEL | SEC_ENCRYPT;
354		}
355
356		goto done;
357	}
358
359	sec.enabled = 1;
360	sec.encrypt = 1;
361	sec.flags |= SEC_ENABLED | SEC_ENCRYPT;
362
363	if (*crypt != NULL && (*crypt)->ops != NULL &&
364	    strcmp((*crypt)->ops->name, "WEP") != 0) {
365		/* changing to use WEP; deinit previously used algorithm
366		 * on this key */
367		ieee80211_crypt_delayed_deinit(ieee, crypt);
368	}
369
370	if (*crypt == NULL && host_crypto) {
371		struct ieee80211_crypt_data *new_crypt;
372
373		/* take WEP into use */
374		new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data),
375				    GFP_KERNEL);
376		if (new_crypt == NULL)
377			return -ENOMEM;
378		new_crypt->ops = ieee80211_get_crypto_ops("WEP");
379		if (!new_crypt->ops) {
380			request_module("ieee80211_crypt_wep");
381			new_crypt->ops = ieee80211_get_crypto_ops("WEP");
382		}
383
384		if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
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			printk(KERN_WARNING "%s: could not initialize WEP: "
392			       "load module ieee80211_crypt_wep\n", dev->name);
393			return -EOPNOTSUPP;
394		}
395		*crypt = new_crypt;
396	}
397
398	/* If a new key was provided, set it up */
399	if (erq->length > 0) {
400		len = erq->length <= 5 ? 5 : 13;
401		memcpy(sec.keys[key], keybuf, erq->length);
402		if (len > erq->length)
403			memset(sec.keys[key] + erq->length, 0,
404			       len - erq->length);
405		IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
406				   key, escape_essid(sec.keys[key], len),
407				   erq->length, len);
408		sec.key_sizes[key] = len;
409		if (*crypt)
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		 * explicitely set */
415		if (key == sec.active_key)
416			sec.flags |= SEC_ACTIVE_KEY;
417
418	} else {
419		if (host_crypto) {
420			len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
421						     NULL, (*crypt)->priv);
422			if (len == 0) {
423				/* Set a default key of all 0 */
424				IEEE80211_DEBUG_WX("Setting key %d to all "
425						   "zero.\n", 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			IEEE80211_DEBUG_WX("Setting key %d to default Tx "
436					   "key.\n", key);
437			ieee->tx_keyidx = key;
438			sec.active_key = key;
439			sec.flags |= SEC_ACTIVE_KEY;
440		}
441	}
442	if (erq->flags & (IW_ENCODE_OPEN | IW_ENCODE_RESTRICTED)) {
443		ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
444		sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN :
445		    WLAN_AUTH_SHARED_KEY;
446		sec.flags |= SEC_AUTH_MODE;
447		IEEE80211_DEBUG_WX("Auth: %s\n",
448				   sec.auth_mode == WLAN_AUTH_OPEN ?
449				   "OPEN" : "SHARED KEY");
450	}
451
452	/* For now we just support WEP, so only set that security level...
453	 * TODO: When WPA is added this is one place that needs to change */
454	sec.flags |= SEC_LEVEL;
455	sec.level = SEC_LEVEL_1;	/* 40 and 104 bit WEP */
456	sec.encode_alg[key] = SEC_ALG_WEP;
457
458      done:
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	if (ieee->reset_on_keychange &&
468	    ieee->iw_mode != IW_MODE_INFRA &&
469	    ieee->reset_port && ieee->reset_port(dev)) {
470		printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
471		return -EINVAL;
472	}
473	return 0;
474}
475
476int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
477			    struct iw_request_info *info,
478			    union iwreq_data *wrqu, char *keybuf)
479{
480	struct iw_point *erq = &(wrqu->encoding);
481	int len, key;
482	struct ieee80211_crypt_data *crypt;
483	struct ieee80211_security *sec = &ieee->sec;
484
485	IEEE80211_DEBUG_WX("GET_ENCODE\n");
486
487	key = erq->flags & IW_ENCODE_INDEX;
488	if (key) {
489		if (key > WEP_KEYS)
490			return -EINVAL;
491		key--;
492	} else
493		key = ieee->tx_keyidx;
494
495	crypt = ieee->crypt[key];
496	erq->flags = key + 1;
497
498	if (!sec->enabled) {
499		erq->length = 0;
500		erq->flags |= IW_ENCODE_DISABLED;
501		return 0;
502	}
503
504	len = sec->key_sizes[key];
505	memcpy(keybuf, sec->keys[key], len);
506
507	erq->length = len;
508	erq->flags |= IW_ENCODE_ENABLED;
509
510	if (ieee->open_wep)
511		erq->flags |= IW_ENCODE_OPEN;
512	else
513		erq->flags |= IW_ENCODE_RESTRICTED;
514
515	return 0;
516}
517
518int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee,
519			       struct iw_request_info *info,
520			       union iwreq_data *wrqu, char *extra)
521{
522	struct net_device *dev = ieee->dev;
523	struct iw_point *encoding = &wrqu->encoding;
524	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
525	int i, idx, ret = 0;
526	int group_key = 0;
527	const char *alg, *module;
528	struct ieee80211_crypto_ops *ops;
529	struct ieee80211_crypt_data **crypt;
530
531	struct ieee80211_security sec = {
532		.flags = 0,
533	};
534
535	idx = encoding->flags & IW_ENCODE_INDEX;
536	if (idx) {
537		if (idx < 1 || idx > WEP_KEYS)
538			return -EINVAL;
539		idx--;
540	} else
541		idx = ieee->tx_keyidx;
542
543	if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
544		crypt = &ieee->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[idx];
552		else
553			return -EINVAL;
554	}
555
556	sec.flags |= SEC_ENABLED | SEC_ENCRYPT;
557	if ((encoding->flags & IW_ENCODE_DISABLED) ||
558	    ext->alg == IW_ENCODE_ALG_NONE) {
559		if (*crypt)
560			ieee80211_crypt_delayed_deinit(ieee, crypt);
561
562		for (i = 0; i < WEP_KEYS; i++)
563			if (ieee->crypt[i] != NULL)
564				break;
565
566		if (i == WEP_KEYS) {
567			sec.enabled = 0;
568			sec.encrypt = 0;
569			sec.level = SEC_LEVEL_0;
570			sec.flags |= SEC_LEVEL;
571		}
572		goto done;
573	}
574
575	sec.enabled = 1;
576	sec.encrypt = 1;
577
578	if (group_key ? !ieee->host_mc_decrypt :
579	    !(ieee->host_encrypt || ieee->host_decrypt ||
580	      ieee->host_encrypt_msdu))
581		goto skip_host_crypt;
582
583	switch (ext->alg) {
584	case IW_ENCODE_ALG_WEP:
585		alg = "WEP";
586		module = "ieee80211_crypt_wep";
587		break;
588	case IW_ENCODE_ALG_TKIP:
589		alg = "TKIP";
590		module = "ieee80211_crypt_tkip";
591		break;
592	case IW_ENCODE_ALG_CCMP:
593		alg = "CCMP";
594		module = "ieee80211_crypt_ccmp";
595		break;
596	default:
597		IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
598				   dev->name, ext->alg);
599		ret = -EINVAL;
600		goto done;
601	}
602
603	ops = ieee80211_get_crypto_ops(alg);
604	if (ops == NULL) {
605		request_module(module);
606		ops = ieee80211_get_crypto_ops(alg);
607	}
608	if (ops == NULL) {
609		IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
610				   dev->name, ext->alg);
611		ret = -EINVAL;
612		goto done;
613	}
614
615	if (*crypt == NULL || (*crypt)->ops != ops) {
616		struct ieee80211_crypt_data *new_crypt;
617
618		ieee80211_crypt_delayed_deinit(ieee, 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 && try_module_get(new_crypt->ops->owner))
627			new_crypt->priv = new_crypt->ops->init(idx);
628		if (new_crypt->priv == NULL) {
629			kfree(new_crypt);
630			ret = -EINVAL;
631			goto done;
632		}
633		*crypt = new_crypt;
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		IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
640		ret = -EINVAL;
641		goto done;
642	}
643
644      skip_host_crypt:
645	if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
646		ieee->tx_keyidx = idx;
647		sec.active_key = idx;
648		sec.flags |= SEC_ACTIVE_KEY;
649	}
650
651	if (ext->alg != IW_ENCODE_ALG_NONE) {
652		memcpy(sec.keys[idx], ext->key, ext->key_len);
653		sec.key_sizes[idx] = ext->key_len;
654		sec.flags |= (1 << idx);
655		if (ext->alg == IW_ENCODE_ALG_WEP) {
656			sec.encode_alg[idx] = SEC_ALG_WEP;
657			sec.flags |= SEC_LEVEL;
658			sec.level = SEC_LEVEL_1;
659		} else if (ext->alg == IW_ENCODE_ALG_TKIP) {
660			sec.encode_alg[idx] = SEC_ALG_TKIP;
661			sec.flags |= SEC_LEVEL;
662			sec.level = SEC_LEVEL_2;
663		} else if (ext->alg == IW_ENCODE_ALG_CCMP) {
664			sec.encode_alg[idx] = SEC_ALG_CCMP;
665			sec.flags |= SEC_LEVEL;
666			sec.level = SEC_LEVEL_3;
667		}
668		/* Don't set sec level for group keys. */
669		if (group_key)
670			sec.flags &= ~SEC_LEVEL;
671	}
672      done:
673	if (ieee->set_security)
674		ieee->set_security(ieee->dev, &sec);
675
676	/*
677	 * Do not reset port if card is in Managed mode since resetting will
678	 * generate new IEEE 802.11 authentication which may end up in looping
679	 * with IEEE 802.1X. If your hardware requires a reset after WEP
680	 * configuration (for example... Prism2), implement the reset_port in
681	 * the callbacks structures used to initialize the 802.11 stack.
682	 */
683	if (ieee->reset_on_keychange &&
684	    ieee->iw_mode != IW_MODE_INFRA &&
685	    ieee->reset_port && ieee->reset_port(dev)) {
686		IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
687		return -EINVAL;
688	}
689
690	return ret;
691}
692
693int ieee80211_wx_get_encodeext(struct ieee80211_device *ieee,
694			       struct iw_request_info *info,
695			       union iwreq_data *wrqu, char *extra)
696{
697	struct iw_point *encoding = &wrqu->encoding;
698	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
699	struct ieee80211_security *sec = &ieee->sec;
700	int idx, max_key_len;
701
702	max_key_len = encoding->length - sizeof(*ext);
703	if (max_key_len < 0)
704		return -EINVAL;
705
706	idx = encoding->flags & IW_ENCODE_INDEX;
707	if (idx) {
708		if (idx < 1 || idx > WEP_KEYS)
709			return -EINVAL;
710		idx--;
711	} else
712		idx = ieee->tx_keyidx;
713
714	if (!ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY &&
715	    ext->alg != IW_ENCODE_ALG_WEP)
716		if (idx != 0 || ieee->iw_mode != IW_MODE_INFRA)
717			return -EINVAL;
718
719	encoding->flags = idx + 1;
720	memset(ext, 0, sizeof(*ext));
721
722	if (!sec->enabled) {
723		ext->alg = IW_ENCODE_ALG_NONE;
724		ext->key_len = 0;
725		encoding->flags |= IW_ENCODE_DISABLED;
726	} else {
727		if (sec->encode_alg[idx] == SEC_ALG_WEP)
728			ext->alg = IW_ENCODE_ALG_WEP;
729		else if (sec->encode_alg[idx] == SEC_ALG_TKIP)
730			ext->alg = IW_ENCODE_ALG_TKIP;
731		else if (sec->encode_alg[idx] == SEC_ALG_CCMP)
732			ext->alg = IW_ENCODE_ALG_CCMP;
733		else
734			return -EINVAL;
735
736		ext->key_len = sec->key_sizes[idx];
737		memcpy(ext->key, sec->keys[idx], ext->key_len);
738		encoding->flags |= IW_ENCODE_ENABLED;
739		if (ext->key_len &&
740		    (ext->alg == IW_ENCODE_ALG_TKIP ||
741		     ext->alg == IW_ENCODE_ALG_CCMP))
742			ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
743
744	}
745
746	return 0;
747}
748
749int ieee80211_wx_set_auth(struct net_device *dev,
750			  struct iw_request_info *info,
751			  union iwreq_data *wrqu,
752			  char *extra)
753{
754	struct ieee80211_device *ieee = netdev_priv(dev);
755	unsigned long flags;
756	int err = 0;
757
758	spin_lock_irqsave(&ieee->lock, flags);
759
760	switch (wrqu->param.flags & IW_AUTH_INDEX) {
761	case IW_AUTH_WPA_VERSION:
762	case IW_AUTH_CIPHER_PAIRWISE:
763	case IW_AUTH_CIPHER_GROUP:
764	case IW_AUTH_KEY_MGMT:
765		/*
766		 * Host AP driver does not use these parameters and allows
767		 * wpa_supplicant to control them internally.
768		 */
769		break;
770	case IW_AUTH_TKIP_COUNTERMEASURES:
771		break;
772	case IW_AUTH_DROP_UNENCRYPTED:
773		ieee->drop_unencrypted = !!wrqu->param.value;
774		break;
775	case IW_AUTH_80211_AUTH_ALG:
776		break;
777	case IW_AUTH_WPA_ENABLED:
778		ieee->privacy_invoked = ieee->wpa_enabled = !!wrqu->param.value;
779		break;
780	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
781		ieee->ieee802_1x = !!wrqu->param.value;
782		break;
783	case IW_AUTH_PRIVACY_INVOKED:
784		ieee->privacy_invoked = !!wrqu->param.value;
785		break;
786	default:
787		err = -EOPNOTSUPP;
788		break;
789	}
790	spin_unlock_irqrestore(&ieee->lock, flags);
791	return err;
792}
793
794int ieee80211_wx_get_auth(struct net_device *dev,
795			  struct iw_request_info *info,
796			  union iwreq_data *wrqu,
797			  char *extra)
798{
799	struct ieee80211_device *ieee = netdev_priv(dev);
800	unsigned long flags;
801	int err = 0;
802
803	spin_lock_irqsave(&ieee->lock, flags);
804
805	switch (wrqu->param.flags & IW_AUTH_INDEX) {
806	case IW_AUTH_WPA_VERSION:
807	case IW_AUTH_CIPHER_PAIRWISE:
808	case IW_AUTH_CIPHER_GROUP:
809	case IW_AUTH_KEY_MGMT:
810	case IW_AUTH_TKIP_COUNTERMEASURES:
811	case IW_AUTH_80211_AUTH_ALG:
812		/*
813		 * Host AP driver does not use these parameters and allows
814		 * wpa_supplicant to control them internally.
815		 */
816		err = -EOPNOTSUPP;
817		break;
818	case IW_AUTH_DROP_UNENCRYPTED:
819		wrqu->param.value = ieee->drop_unencrypted;
820		break;
821	case IW_AUTH_WPA_ENABLED:
822		wrqu->param.value = ieee->wpa_enabled;
823		break;
824	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
825		wrqu->param.value = ieee->ieee802_1x;
826		break;
827	default:
828		err = -EOPNOTSUPP;
829		break;
830	}
831	spin_unlock_irqrestore(&ieee->lock, flags);
832	return err;
833}
834
835EXPORT_SYMBOL(ieee80211_wx_set_encodeext);
836EXPORT_SYMBOL(ieee80211_wx_get_encodeext);
837
838EXPORT_SYMBOL(ieee80211_wx_get_scan);
839EXPORT_SYMBOL(ieee80211_wx_set_encode);
840EXPORT_SYMBOL(ieee80211_wx_get_encode);
841
842EXPORT_SYMBOL_GPL(ieee80211_wx_set_auth);
843EXPORT_SYMBOL_GPL(ieee80211_wx_get_auth);
844