• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/net/wireless/
1/*
2 * cfg80211 - wext compat code
3 *
4 * This is temporary code until all wireless functionality is migrated
5 * into cfg80211, when that happens all the exports here go away and
6 * we directly assign the wireless handlers of wireless interfaces.
7 *
8 * Copyright 2008-2009	Johannes Berg <johannes@sipsolutions.net>
9 */
10
11#include <linux/wireless.h>
12#include <linux/nl80211.h>
13#include <linux/if_arp.h>
14#include <linux/etherdevice.h>
15#include <linux/slab.h>
16#include <net/iw_handler.h>
17#include <net/cfg80211.h>
18#include "wext-compat.h"
19#include "core.h"
20
21int cfg80211_wext_giwname(struct net_device *dev,
22			  struct iw_request_info *info,
23			  char *name, char *extra)
24{
25	struct wireless_dev *wdev = dev->ieee80211_ptr;
26	struct ieee80211_supported_band *sband;
27	bool is_ht = false, is_a = false, is_b = false, is_g = false;
28
29	if (!wdev)
30		return -EOPNOTSUPP;
31
32	sband = wdev->wiphy->bands[IEEE80211_BAND_5GHZ];
33	if (sband) {
34		is_a = true;
35		is_ht |= sband->ht_cap.ht_supported;
36	}
37
38	sband = wdev->wiphy->bands[IEEE80211_BAND_2GHZ];
39	if (sband) {
40		int i;
41		/* Check for mandatory rates */
42		for (i = 0; i < sband->n_bitrates; i++) {
43			if (sband->bitrates[i].bitrate == 10)
44				is_b = true;
45			if (sband->bitrates[i].bitrate == 60)
46				is_g = true;
47		}
48		is_ht |= sband->ht_cap.ht_supported;
49	}
50
51	strcpy(name, "IEEE 802.11");
52	if (is_a)
53		strcat(name, "a");
54	if (is_b)
55		strcat(name, "b");
56	if (is_g)
57		strcat(name, "g");
58	if (is_ht)
59		strcat(name, "n");
60
61	return 0;
62}
63EXPORT_SYMBOL_GPL(cfg80211_wext_giwname);
64
65int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
66			  u32 *mode, char *extra)
67{
68	struct wireless_dev *wdev = dev->ieee80211_ptr;
69	struct cfg80211_registered_device *rdev;
70	struct vif_params vifparams;
71	enum nl80211_iftype type;
72	int ret;
73
74	rdev = wiphy_to_dev(wdev->wiphy);
75
76	switch (*mode) {
77	case IW_MODE_INFRA:
78		type = NL80211_IFTYPE_STATION;
79		break;
80	case IW_MODE_ADHOC:
81		type = NL80211_IFTYPE_ADHOC;
82		break;
83	case IW_MODE_REPEAT:
84		type = NL80211_IFTYPE_WDS;
85		break;
86	case IW_MODE_MONITOR:
87		type = NL80211_IFTYPE_MONITOR;
88		break;
89	default:
90		return -EINVAL;
91	}
92
93	if (type == wdev->iftype)
94		return 0;
95
96	memset(&vifparams, 0, sizeof(vifparams));
97
98	cfg80211_lock_rdev(rdev);
99	ret = cfg80211_change_iface(rdev, dev, type, NULL, &vifparams);
100	cfg80211_unlock_rdev(rdev);
101
102	return ret;
103}
104EXPORT_SYMBOL_GPL(cfg80211_wext_siwmode);
105
106int cfg80211_wext_giwmode(struct net_device *dev, struct iw_request_info *info,
107			  u32 *mode, char *extra)
108{
109	struct wireless_dev *wdev = dev->ieee80211_ptr;
110
111	if (!wdev)
112		return -EOPNOTSUPP;
113
114	switch (wdev->iftype) {
115	case NL80211_IFTYPE_AP:
116		*mode = IW_MODE_MASTER;
117		break;
118	case NL80211_IFTYPE_STATION:
119		*mode = IW_MODE_INFRA;
120		break;
121	case NL80211_IFTYPE_ADHOC:
122		*mode = IW_MODE_ADHOC;
123		break;
124	case NL80211_IFTYPE_MONITOR:
125		*mode = IW_MODE_MONITOR;
126		break;
127	case NL80211_IFTYPE_WDS:
128		*mode = IW_MODE_REPEAT;
129		break;
130	case NL80211_IFTYPE_AP_VLAN:
131		*mode = IW_MODE_SECOND;
132		break;
133	default:
134		*mode = IW_MODE_AUTO;
135		break;
136	}
137	return 0;
138}
139EXPORT_SYMBOL_GPL(cfg80211_wext_giwmode);
140
141
142int cfg80211_wext_giwrange(struct net_device *dev,
143			   struct iw_request_info *info,
144			   struct iw_point *data, char *extra)
145{
146	struct wireless_dev *wdev = dev->ieee80211_ptr;
147	struct iw_range *range = (struct iw_range *) extra;
148	enum ieee80211_band band;
149	int i, c = 0;
150
151	if (!wdev)
152		return -EOPNOTSUPP;
153
154	data->length = sizeof(struct iw_range);
155	memset(range, 0, sizeof(struct iw_range));
156
157	range->we_version_compiled = WIRELESS_EXT;
158	range->we_version_source = 21;
159	range->retry_capa = IW_RETRY_LIMIT;
160	range->retry_flags = IW_RETRY_LIMIT;
161	range->min_retry = 0;
162	range->max_retry = 255;
163	range->min_rts = 0;
164	range->max_rts = 2347;
165	range->min_frag = 256;
166	range->max_frag = 2346;
167
168	range->max_encoding_tokens = 4;
169
170	range->max_qual.updated = IW_QUAL_NOISE_INVALID;
171
172	switch (wdev->wiphy->signal_type) {
173	case CFG80211_SIGNAL_TYPE_NONE:
174		break;
175	case CFG80211_SIGNAL_TYPE_MBM:
176		range->max_qual.level = -110;
177		range->max_qual.qual = 70;
178		range->avg_qual.qual = 35;
179		range->max_qual.updated |= IW_QUAL_DBM;
180		range->max_qual.updated |= IW_QUAL_QUAL_UPDATED;
181		range->max_qual.updated |= IW_QUAL_LEVEL_UPDATED;
182		break;
183	case CFG80211_SIGNAL_TYPE_UNSPEC:
184		range->max_qual.level = 100;
185		range->max_qual.qual = 100;
186		range->avg_qual.qual = 50;
187		range->max_qual.updated |= IW_QUAL_QUAL_UPDATED;
188		range->max_qual.updated |= IW_QUAL_LEVEL_UPDATED;
189		break;
190	}
191
192	range->avg_qual.level = range->max_qual.level / 2;
193	range->avg_qual.noise = range->max_qual.noise / 2;
194	range->avg_qual.updated = range->max_qual.updated;
195
196	for (i = 0; i < wdev->wiphy->n_cipher_suites; i++) {
197		switch (wdev->wiphy->cipher_suites[i]) {
198		case WLAN_CIPHER_SUITE_TKIP:
199			range->enc_capa |= (IW_ENC_CAPA_CIPHER_TKIP |
200					    IW_ENC_CAPA_WPA);
201			break;
202
203		case WLAN_CIPHER_SUITE_CCMP:
204			range->enc_capa |= (IW_ENC_CAPA_CIPHER_CCMP |
205					    IW_ENC_CAPA_WPA2);
206			break;
207
208		case WLAN_CIPHER_SUITE_WEP40:
209			range->encoding_size[range->num_encoding_sizes++] =
210				WLAN_KEY_LEN_WEP40;
211			break;
212
213		case WLAN_CIPHER_SUITE_WEP104:
214			range->encoding_size[range->num_encoding_sizes++] =
215				WLAN_KEY_LEN_WEP104;
216			break;
217		}
218	}
219
220	for (band = 0; band < IEEE80211_NUM_BANDS; band ++) {
221		struct ieee80211_supported_band *sband;
222
223		sband = wdev->wiphy->bands[band];
224
225		if (!sband)
226			continue;
227
228		for (i = 0; i < sband->n_channels && c < IW_MAX_FREQUENCIES; i++) {
229			struct ieee80211_channel *chan = &sband->channels[i];
230
231			if (!(chan->flags & IEEE80211_CHAN_DISABLED)) {
232				range->freq[c].i =
233					ieee80211_frequency_to_channel(
234						chan->center_freq);
235				range->freq[c].m = chan->center_freq;
236				range->freq[c].e = 6;
237				c++;
238			}
239		}
240	}
241	range->num_channels = c;
242	range->num_frequency = c;
243
244	IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
245	IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
246	IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
247
248	if (wdev->wiphy->max_scan_ssids > 0)
249		range->scan_capa |= IW_SCAN_CAPA_ESSID;
250
251	return 0;
252}
253EXPORT_SYMBOL_GPL(cfg80211_wext_giwrange);
254
255
256/**
257 * cfg80211_wext_freq - get wext frequency for non-"auto"
258 * @wiphy: the wiphy
259 * @freq: the wext freq encoding
260 *
261 * Returns a frequency, or a negative error code, or 0 for auto.
262 */
263int cfg80211_wext_freq(struct wiphy *wiphy, struct iw_freq *freq)
264{
265	/*
266	 * Parse frequency - return 0 for auto and
267	 * -EINVAL for impossible things.
268	 */
269	if (freq->e == 0) {
270		if (freq->m < 0)
271			return 0;
272		return ieee80211_channel_to_frequency(freq->m);
273	} else {
274		int i, div = 1000000;
275		for (i = 0; i < freq->e; i++)
276			div /= 10;
277		if (div <= 0)
278			return -EINVAL;
279		return freq->m / div;
280	}
281}
282
283int cfg80211_wext_siwrts(struct net_device *dev,
284			 struct iw_request_info *info,
285			 struct iw_param *rts, char *extra)
286{
287	struct wireless_dev *wdev = dev->ieee80211_ptr;
288	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
289	u32 orts = wdev->wiphy->rts_threshold;
290	int err;
291
292	if (rts->disabled || !rts->fixed)
293		wdev->wiphy->rts_threshold = (u32) -1;
294	else if (rts->value < 0)
295		return -EINVAL;
296	else
297		wdev->wiphy->rts_threshold = rts->value;
298
299	err = rdev->ops->set_wiphy_params(wdev->wiphy,
300					  WIPHY_PARAM_RTS_THRESHOLD);
301	if (err)
302		wdev->wiphy->rts_threshold = orts;
303
304	return err;
305}
306EXPORT_SYMBOL_GPL(cfg80211_wext_siwrts);
307
308int cfg80211_wext_giwrts(struct net_device *dev,
309			 struct iw_request_info *info,
310			 struct iw_param *rts, char *extra)
311{
312	struct wireless_dev *wdev = dev->ieee80211_ptr;
313
314	rts->value = wdev->wiphy->rts_threshold;
315	rts->disabled = rts->value == (u32) -1;
316	rts->fixed = 1;
317
318	return 0;
319}
320EXPORT_SYMBOL_GPL(cfg80211_wext_giwrts);
321
322int cfg80211_wext_siwfrag(struct net_device *dev,
323			  struct iw_request_info *info,
324			  struct iw_param *frag, char *extra)
325{
326	struct wireless_dev *wdev = dev->ieee80211_ptr;
327	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
328	u32 ofrag = wdev->wiphy->frag_threshold;
329	int err;
330
331	if (frag->disabled || !frag->fixed)
332		wdev->wiphy->frag_threshold = (u32) -1;
333	else if (frag->value < 256)
334		return -EINVAL;
335	else {
336		/* Fragment length must be even, so strip LSB. */
337		wdev->wiphy->frag_threshold = frag->value & ~0x1;
338	}
339
340	err = rdev->ops->set_wiphy_params(wdev->wiphy,
341					  WIPHY_PARAM_FRAG_THRESHOLD);
342	if (err)
343		wdev->wiphy->frag_threshold = ofrag;
344
345	return err;
346}
347EXPORT_SYMBOL_GPL(cfg80211_wext_siwfrag);
348
349int cfg80211_wext_giwfrag(struct net_device *dev,
350			  struct iw_request_info *info,
351			  struct iw_param *frag, char *extra)
352{
353	struct wireless_dev *wdev = dev->ieee80211_ptr;
354
355	frag->value = wdev->wiphy->frag_threshold;
356	frag->disabled = frag->value == (u32) -1;
357	frag->fixed = 1;
358
359	return 0;
360}
361EXPORT_SYMBOL_GPL(cfg80211_wext_giwfrag);
362
363int cfg80211_wext_siwretry(struct net_device *dev,
364			   struct iw_request_info *info,
365			   struct iw_param *retry, char *extra)
366{
367	struct wireless_dev *wdev = dev->ieee80211_ptr;
368	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
369	u32 changed = 0;
370	u8 olong = wdev->wiphy->retry_long;
371	u8 oshort = wdev->wiphy->retry_short;
372	int err;
373
374	if (retry->disabled ||
375	    (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
376		return -EINVAL;
377
378	if (retry->flags & IW_RETRY_LONG) {
379		wdev->wiphy->retry_long = retry->value;
380		changed |= WIPHY_PARAM_RETRY_LONG;
381	} else if (retry->flags & IW_RETRY_SHORT) {
382		wdev->wiphy->retry_short = retry->value;
383		changed |= WIPHY_PARAM_RETRY_SHORT;
384	} else {
385		wdev->wiphy->retry_short = retry->value;
386		wdev->wiphy->retry_long = retry->value;
387		changed |= WIPHY_PARAM_RETRY_LONG;
388		changed |= WIPHY_PARAM_RETRY_SHORT;
389	}
390
391	if (!changed)
392		return 0;
393
394	err = rdev->ops->set_wiphy_params(wdev->wiphy, changed);
395	if (err) {
396		wdev->wiphy->retry_short = oshort;
397		wdev->wiphy->retry_long = olong;
398	}
399
400	return err;
401}
402EXPORT_SYMBOL_GPL(cfg80211_wext_siwretry);
403
404int cfg80211_wext_giwretry(struct net_device *dev,
405			   struct iw_request_info *info,
406			   struct iw_param *retry, char *extra)
407{
408	struct wireless_dev *wdev = dev->ieee80211_ptr;
409
410	retry->disabled = 0;
411
412	if (retry->flags == 0 || (retry->flags & IW_RETRY_SHORT)) {
413		/*
414		 * First return short value, iwconfig will ask long value
415		 * later if needed
416		 */
417		retry->flags |= IW_RETRY_LIMIT;
418		retry->value = wdev->wiphy->retry_short;
419		if (wdev->wiphy->retry_long != wdev->wiphy->retry_short)
420			retry->flags |= IW_RETRY_LONG;
421
422		return 0;
423	}
424
425	if (retry->flags & IW_RETRY_LONG) {
426		retry->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
427		retry->value = wdev->wiphy->retry_long;
428	}
429
430	return 0;
431}
432EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry);
433
434static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
435				     struct net_device *dev, const u8 *addr,
436				     bool remove, bool tx_key, int idx,
437				     struct key_params *params)
438{
439	struct wireless_dev *wdev = dev->ieee80211_ptr;
440	int err, i;
441	bool rejoin = false;
442
443	if (!wdev->wext.keys) {
444		wdev->wext.keys = kzalloc(sizeof(*wdev->wext.keys),
445					      GFP_KERNEL);
446		if (!wdev->wext.keys)
447			return -ENOMEM;
448		for (i = 0; i < 6; i++)
449			wdev->wext.keys->params[i].key =
450				wdev->wext.keys->data[i];
451	}
452
453	if (wdev->iftype != NL80211_IFTYPE_ADHOC &&
454	    wdev->iftype != NL80211_IFTYPE_STATION)
455		return -EOPNOTSUPP;
456
457	if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
458		if (!wdev->current_bss)
459			return -ENOLINK;
460
461		if (!rdev->ops->set_default_mgmt_key)
462			return -EOPNOTSUPP;
463
464		if (idx < 4 || idx > 5)
465			return -EINVAL;
466	} else if (idx < 0 || idx > 3)
467		return -EINVAL;
468
469	if (remove) {
470		err = 0;
471		if (wdev->current_bss) {
472			/*
473			 * If removing the current TX key, we will need to
474			 * join a new IBSS without the privacy bit clear.
475			 */
476			if (idx == wdev->wext.default_key &&
477			    wdev->iftype == NL80211_IFTYPE_ADHOC) {
478				__cfg80211_leave_ibss(rdev, wdev->netdev, true);
479				rejoin = true;
480			}
481			err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr);
482		}
483		wdev->wext.connect.privacy = false;
484		/*
485		 * Applications using wireless extensions expect to be
486		 * able to delete keys that don't exist, so allow that.
487		 */
488		if (err == -ENOENT)
489			err = 0;
490		if (!err) {
491			if (!addr) {
492				wdev->wext.keys->params[idx].key_len = 0;
493				wdev->wext.keys->params[idx].cipher = 0;
494			}
495			if (idx == wdev->wext.default_key)
496				wdev->wext.default_key = -1;
497			else if (idx == wdev->wext.default_mgmt_key)
498				wdev->wext.default_mgmt_key = -1;
499		}
500
501		if (!err && rejoin)
502			err = cfg80211_ibss_wext_join(rdev, wdev);
503
504		return err;
505	}
506
507	if (addr)
508		tx_key = false;
509
510	if (cfg80211_validate_key_settings(rdev, params, idx, addr))
511		return -EINVAL;
512
513	err = 0;
514	if (wdev->current_bss)
515		err = rdev->ops->add_key(&rdev->wiphy, dev, idx, addr, params);
516	if (err)
517		return err;
518
519	if (!addr) {
520		wdev->wext.keys->params[idx] = *params;
521		memcpy(wdev->wext.keys->data[idx],
522			params->key, params->key_len);
523		wdev->wext.keys->params[idx].key =
524			wdev->wext.keys->data[idx];
525	}
526
527	if ((params->cipher == WLAN_CIPHER_SUITE_WEP40 ||
528	     params->cipher == WLAN_CIPHER_SUITE_WEP104) &&
529	    (tx_key || (!addr && wdev->wext.default_key == -1))) {
530		if (wdev->current_bss) {
531			/*
532			 * If we are getting a new TX key from not having
533			 * had one before we need to join a new IBSS with
534			 * the privacy bit set.
535			 */
536			if (wdev->iftype == NL80211_IFTYPE_ADHOC &&
537			    wdev->wext.default_key == -1) {
538				__cfg80211_leave_ibss(rdev, wdev->netdev, true);
539				rejoin = true;
540			}
541			err = rdev->ops->set_default_key(&rdev->wiphy,
542							 dev, idx);
543		}
544		if (!err) {
545			wdev->wext.default_key = idx;
546			if (rejoin)
547				err = cfg80211_ibss_wext_join(rdev, wdev);
548		}
549		return err;
550	}
551
552	if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC &&
553	    (tx_key || (!addr && wdev->wext.default_mgmt_key == -1))) {
554		if (wdev->current_bss)
555			err = rdev->ops->set_default_mgmt_key(&rdev->wiphy,
556							      dev, idx);
557		if (!err)
558			wdev->wext.default_mgmt_key = idx;
559		return err;
560	}
561
562	return 0;
563}
564
565static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
566				   struct net_device *dev, const u8 *addr,
567				   bool remove, bool tx_key, int idx,
568				   struct key_params *params)
569{
570	int err;
571
572	/* devlist mutex needed for possible IBSS re-join */
573	mutex_lock(&rdev->devlist_mtx);
574	wdev_lock(dev->ieee80211_ptr);
575	err = __cfg80211_set_encryption(rdev, dev, addr, remove,
576					tx_key, idx, params);
577	wdev_unlock(dev->ieee80211_ptr);
578	mutex_unlock(&rdev->devlist_mtx);
579
580	return err;
581}
582
583int cfg80211_wext_siwencode(struct net_device *dev,
584			    struct iw_request_info *info,
585			    struct iw_point *erq, char *keybuf)
586{
587	struct wireless_dev *wdev = dev->ieee80211_ptr;
588	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
589	int idx, err;
590	bool remove = false;
591	struct key_params params;
592
593	if (wdev->iftype != NL80211_IFTYPE_STATION &&
594	    wdev->iftype != NL80211_IFTYPE_ADHOC)
595		return -EOPNOTSUPP;
596
597	/* no use -- only MFP (set_default_mgmt_key) is optional */
598	if (!rdev->ops->del_key ||
599	    !rdev->ops->add_key ||
600	    !rdev->ops->set_default_key)
601		return -EOPNOTSUPP;
602
603	idx = erq->flags & IW_ENCODE_INDEX;
604	if (idx == 0) {
605		idx = wdev->wext.default_key;
606		if (idx < 0)
607			idx = 0;
608	} else if (idx < 1 || idx > 4)
609		return -EINVAL;
610	else
611		idx--;
612
613	if (erq->flags & IW_ENCODE_DISABLED)
614		remove = true;
615	else if (erq->length == 0) {
616		/* No key data - just set the default TX key index */
617		err = 0;
618		wdev_lock(wdev);
619		if (wdev->current_bss)
620			err = rdev->ops->set_default_key(&rdev->wiphy,
621							 dev, idx);
622		if (!err)
623			wdev->wext.default_key = idx;
624		wdev_unlock(wdev);
625		return err;
626	}
627
628	memset(&params, 0, sizeof(params));
629	params.key = keybuf;
630	params.key_len = erq->length;
631	if (erq->length == 5)
632		params.cipher = WLAN_CIPHER_SUITE_WEP40;
633	else if (erq->length == 13)
634		params.cipher = WLAN_CIPHER_SUITE_WEP104;
635	else if (!remove)
636		return -EINVAL;
637
638	return cfg80211_set_encryption(rdev, dev, NULL, remove,
639				       wdev->wext.default_key == -1,
640				       idx, &params);
641}
642EXPORT_SYMBOL_GPL(cfg80211_wext_siwencode);
643
644int cfg80211_wext_siwencodeext(struct net_device *dev,
645			       struct iw_request_info *info,
646			       struct iw_point *erq, char *extra)
647{
648	struct wireless_dev *wdev = dev->ieee80211_ptr;
649	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
650	struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
651	const u8 *addr;
652	int idx;
653	bool remove = false;
654	struct key_params params;
655	u32 cipher;
656
657	if (wdev->iftype != NL80211_IFTYPE_STATION &&
658	    wdev->iftype != NL80211_IFTYPE_ADHOC)
659		return -EOPNOTSUPP;
660
661	/* no use -- only MFP (set_default_mgmt_key) is optional */
662	if (!rdev->ops->del_key ||
663	    !rdev->ops->add_key ||
664	    !rdev->ops->set_default_key)
665		return -EOPNOTSUPP;
666
667	switch (ext->alg) {
668	case IW_ENCODE_ALG_NONE:
669		remove = true;
670		cipher = 0;
671		break;
672	case IW_ENCODE_ALG_WEP:
673		if (ext->key_len == 5)
674			cipher = WLAN_CIPHER_SUITE_WEP40;
675		else if (ext->key_len == 13)
676			cipher = WLAN_CIPHER_SUITE_WEP104;
677		else
678			return -EINVAL;
679		break;
680	case IW_ENCODE_ALG_TKIP:
681		cipher = WLAN_CIPHER_SUITE_TKIP;
682		break;
683	case IW_ENCODE_ALG_CCMP:
684		cipher = WLAN_CIPHER_SUITE_CCMP;
685		break;
686	case IW_ENCODE_ALG_AES_CMAC:
687		cipher = WLAN_CIPHER_SUITE_AES_CMAC;
688		break;
689	default:
690		return -EOPNOTSUPP;
691	}
692
693	if (erq->flags & IW_ENCODE_DISABLED)
694		remove = true;
695
696	idx = erq->flags & IW_ENCODE_INDEX;
697	if (cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
698		if (idx < 4 || idx > 5) {
699			idx = wdev->wext.default_mgmt_key;
700			if (idx < 0)
701				return -EINVAL;
702		} else
703			idx--;
704	} else {
705		if (idx < 1 || idx > 4) {
706			idx = wdev->wext.default_key;
707			if (idx < 0)
708				return -EINVAL;
709		} else
710			idx--;
711	}
712
713	addr = ext->addr.sa_data;
714	if (is_broadcast_ether_addr(addr))
715		addr = NULL;
716
717	memset(&params, 0, sizeof(params));
718	params.key = ext->key;
719	params.key_len = ext->key_len;
720	params.cipher = cipher;
721
722	if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
723		params.seq = ext->rx_seq;
724		params.seq_len = 6;
725	}
726
727	return cfg80211_set_encryption(
728			rdev, dev, addr, remove,
729			ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
730			idx, &params);
731}
732EXPORT_SYMBOL_GPL(cfg80211_wext_siwencodeext);
733
734int cfg80211_wext_giwencode(struct net_device *dev,
735			    struct iw_request_info *info,
736			    struct iw_point *erq, char *keybuf)
737{
738	struct wireless_dev *wdev = dev->ieee80211_ptr;
739	int idx;
740
741	if (wdev->iftype != NL80211_IFTYPE_STATION &&
742	    wdev->iftype != NL80211_IFTYPE_ADHOC)
743		return -EOPNOTSUPP;
744
745	idx = erq->flags & IW_ENCODE_INDEX;
746	if (idx == 0) {
747		idx = wdev->wext.default_key;
748		if (idx < 0)
749			idx = 0;
750	} else if (idx < 1 || idx > 4)
751		return -EINVAL;
752	else
753		idx--;
754
755	erq->flags = idx + 1;
756
757	if (!wdev->wext.keys || !wdev->wext.keys->params[idx].cipher) {
758		erq->flags |= IW_ENCODE_DISABLED;
759		erq->length = 0;
760		return 0;
761	}
762
763	erq->length = min_t(size_t, erq->length,
764			    wdev->wext.keys->params[idx].key_len);
765	memcpy(keybuf, wdev->wext.keys->params[idx].key, erq->length);
766	erq->flags |= IW_ENCODE_ENABLED;
767
768	return 0;
769}
770EXPORT_SYMBOL_GPL(cfg80211_wext_giwencode);
771
772int cfg80211_wext_siwfreq(struct net_device *dev,
773			  struct iw_request_info *info,
774			  struct iw_freq *wextfreq, char *extra)
775{
776	struct wireless_dev *wdev = dev->ieee80211_ptr;
777	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
778	int freq, err;
779
780	switch (wdev->iftype) {
781	case NL80211_IFTYPE_STATION:
782		return cfg80211_mgd_wext_siwfreq(dev, info, wextfreq, extra);
783	case NL80211_IFTYPE_ADHOC:
784		return cfg80211_ibss_wext_siwfreq(dev, info, wextfreq, extra);
785	case NL80211_IFTYPE_MONITOR:
786	case NL80211_IFTYPE_WDS:
787	case NL80211_IFTYPE_MESH_POINT:
788		freq = cfg80211_wext_freq(wdev->wiphy, wextfreq);
789		if (freq < 0)
790			return freq;
791		if (freq == 0)
792			return -EINVAL;
793		wdev_lock(wdev);
794		mutex_lock(&rdev->devlist_mtx);
795		err = cfg80211_set_freq(rdev, wdev, freq, NL80211_CHAN_NO_HT);
796		mutex_unlock(&rdev->devlist_mtx);
797		wdev_unlock(wdev);
798		return err;
799	default:
800		return -EOPNOTSUPP;
801	}
802}
803EXPORT_SYMBOL_GPL(cfg80211_wext_siwfreq);
804
805int cfg80211_wext_giwfreq(struct net_device *dev,
806			  struct iw_request_info *info,
807			  struct iw_freq *freq, char *extra)
808{
809	struct wireless_dev *wdev = dev->ieee80211_ptr;
810
811	switch (wdev->iftype) {
812	case NL80211_IFTYPE_STATION:
813		return cfg80211_mgd_wext_giwfreq(dev, info, freq, extra);
814	case NL80211_IFTYPE_ADHOC:
815		return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra);
816	default:
817		if (!wdev->channel)
818			return -EINVAL;
819		freq->m = wdev->channel->center_freq;
820		freq->e = 6;
821		return 0;
822	}
823}
824EXPORT_SYMBOL_GPL(cfg80211_wext_giwfreq);
825
826int cfg80211_wext_siwtxpower(struct net_device *dev,
827			     struct iw_request_info *info,
828			     union iwreq_data *data, char *extra)
829{
830	struct wireless_dev *wdev = dev->ieee80211_ptr;
831	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
832	enum nl80211_tx_power_setting type;
833	int dbm = 0;
834
835	if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
836		return -EINVAL;
837	if (data->txpower.flags & IW_TXPOW_RANGE)
838		return -EINVAL;
839
840	if (!rdev->ops->set_tx_power)
841		return -EOPNOTSUPP;
842
843	/* only change when not disabling */
844	if (!data->txpower.disabled) {
845		rfkill_set_sw_state(rdev->rfkill, false);
846
847		if (data->txpower.fixed) {
848			/*
849			 * wext doesn't support negative values, see
850			 * below where it's for automatic
851			 */
852			if (data->txpower.value < 0)
853				return -EINVAL;
854			dbm = data->txpower.value;
855			type = NL80211_TX_POWER_FIXED;
856			/* TODO: do regulatory check! */
857		} else {
858			/*
859			 * Automatic power level setting, max being the value
860			 * passed in from userland.
861			 */
862			if (data->txpower.value < 0) {
863				type = NL80211_TX_POWER_AUTOMATIC;
864			} else {
865				dbm = data->txpower.value;
866				type = NL80211_TX_POWER_LIMITED;
867			}
868		}
869	} else {
870		rfkill_set_sw_state(rdev->rfkill, true);
871		schedule_work(&rdev->rfkill_sync);
872		return 0;
873	}
874
875	return rdev->ops->set_tx_power(wdev->wiphy, type, DBM_TO_MBM(dbm));
876}
877EXPORT_SYMBOL_GPL(cfg80211_wext_siwtxpower);
878
879int cfg80211_wext_giwtxpower(struct net_device *dev,
880			     struct iw_request_info *info,
881			     union iwreq_data *data, char *extra)
882{
883	struct wireless_dev *wdev = dev->ieee80211_ptr;
884	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
885	int err, val;
886
887	if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
888		return -EINVAL;
889	if (data->txpower.flags & IW_TXPOW_RANGE)
890		return -EINVAL;
891
892	if (!rdev->ops->get_tx_power)
893		return -EOPNOTSUPP;
894
895	err = rdev->ops->get_tx_power(wdev->wiphy, &val);
896	if (err)
897		return err;
898
899	/* well... oh well */
900	data->txpower.fixed = 1;
901	data->txpower.disabled = rfkill_blocked(rdev->rfkill);
902	data->txpower.value = val;
903	data->txpower.flags = IW_TXPOW_DBM;
904
905	return 0;
906}
907EXPORT_SYMBOL_GPL(cfg80211_wext_giwtxpower);
908
909static int cfg80211_set_auth_alg(struct wireless_dev *wdev,
910				 s32 auth_alg)
911{
912	int nr_alg = 0;
913
914	if (!auth_alg)
915		return -EINVAL;
916
917	if (auth_alg & ~(IW_AUTH_ALG_OPEN_SYSTEM |
918			 IW_AUTH_ALG_SHARED_KEY |
919			 IW_AUTH_ALG_LEAP))
920		return -EINVAL;
921
922	if (auth_alg & IW_AUTH_ALG_OPEN_SYSTEM) {
923		nr_alg++;
924		wdev->wext.connect.auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM;
925	}
926
927	if (auth_alg & IW_AUTH_ALG_SHARED_KEY) {
928		nr_alg++;
929		wdev->wext.connect.auth_type = NL80211_AUTHTYPE_SHARED_KEY;
930	}
931
932	if (auth_alg & IW_AUTH_ALG_LEAP) {
933		nr_alg++;
934		wdev->wext.connect.auth_type = NL80211_AUTHTYPE_NETWORK_EAP;
935	}
936
937	if (nr_alg > 1)
938		wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
939
940	return 0;
941}
942
943static int cfg80211_set_wpa_version(struct wireless_dev *wdev, u32 wpa_versions)
944{
945	if (wpa_versions & ~(IW_AUTH_WPA_VERSION_WPA |
946			     IW_AUTH_WPA_VERSION_WPA2|
947		             IW_AUTH_WPA_VERSION_DISABLED))
948		return -EINVAL;
949
950	if ((wpa_versions & IW_AUTH_WPA_VERSION_DISABLED) &&
951	    (wpa_versions & (IW_AUTH_WPA_VERSION_WPA|
952			     IW_AUTH_WPA_VERSION_WPA2)))
953		return -EINVAL;
954
955	if (wpa_versions & IW_AUTH_WPA_VERSION_DISABLED)
956		wdev->wext.connect.crypto.wpa_versions &=
957			~(NL80211_WPA_VERSION_1|NL80211_WPA_VERSION_2);
958
959	if (wpa_versions & IW_AUTH_WPA_VERSION_WPA)
960		wdev->wext.connect.crypto.wpa_versions |=
961			NL80211_WPA_VERSION_1;
962
963	if (wpa_versions & IW_AUTH_WPA_VERSION_WPA2)
964		wdev->wext.connect.crypto.wpa_versions |=
965			NL80211_WPA_VERSION_2;
966
967	return 0;
968}
969
970static int cfg80211_set_cipher_group(struct wireless_dev *wdev, u32 cipher)
971{
972	if (cipher & IW_AUTH_CIPHER_WEP40)
973		wdev->wext.connect.crypto.cipher_group =
974			WLAN_CIPHER_SUITE_WEP40;
975	else if (cipher & IW_AUTH_CIPHER_WEP104)
976		wdev->wext.connect.crypto.cipher_group =
977			WLAN_CIPHER_SUITE_WEP104;
978	else if (cipher & IW_AUTH_CIPHER_TKIP)
979		wdev->wext.connect.crypto.cipher_group =
980			WLAN_CIPHER_SUITE_TKIP;
981	else if (cipher & IW_AUTH_CIPHER_CCMP)
982		wdev->wext.connect.crypto.cipher_group =
983			WLAN_CIPHER_SUITE_CCMP;
984	else if (cipher & IW_AUTH_CIPHER_AES_CMAC)
985		wdev->wext.connect.crypto.cipher_group =
986			WLAN_CIPHER_SUITE_AES_CMAC;
987	else if (cipher & IW_AUTH_CIPHER_NONE)
988		wdev->wext.connect.crypto.cipher_group = 0;
989	else
990		return -EINVAL;
991
992	return 0;
993}
994
995static int cfg80211_set_cipher_pairwise(struct wireless_dev *wdev, u32 cipher)
996{
997	int nr_ciphers = 0;
998	u32 *ciphers_pairwise = wdev->wext.connect.crypto.ciphers_pairwise;
999
1000	if (cipher & IW_AUTH_CIPHER_WEP40) {
1001		ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_WEP40;
1002		nr_ciphers++;
1003	}
1004
1005	if (cipher & IW_AUTH_CIPHER_WEP104) {
1006		ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_WEP104;
1007		nr_ciphers++;
1008	}
1009
1010	if (cipher & IW_AUTH_CIPHER_TKIP) {
1011		ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_TKIP;
1012		nr_ciphers++;
1013	}
1014
1015	if (cipher & IW_AUTH_CIPHER_CCMP) {
1016		ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_CCMP;
1017		nr_ciphers++;
1018	}
1019
1020	if (cipher & IW_AUTH_CIPHER_AES_CMAC) {
1021		ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_AES_CMAC;
1022		nr_ciphers++;
1023	}
1024
1025	BUILD_BUG_ON(NL80211_MAX_NR_CIPHER_SUITES < 5);
1026
1027	wdev->wext.connect.crypto.n_ciphers_pairwise = nr_ciphers;
1028
1029	return 0;
1030}
1031
1032
1033static int cfg80211_set_key_mgt(struct wireless_dev *wdev, u32 key_mgt)
1034{
1035	int nr_akm_suites = 0;
1036
1037	if (key_mgt & ~(IW_AUTH_KEY_MGMT_802_1X |
1038			IW_AUTH_KEY_MGMT_PSK))
1039		return -EINVAL;
1040
1041	if (key_mgt & IW_AUTH_KEY_MGMT_802_1X) {
1042		wdev->wext.connect.crypto.akm_suites[nr_akm_suites] =
1043			WLAN_AKM_SUITE_8021X;
1044		nr_akm_suites++;
1045	}
1046
1047	if (key_mgt & IW_AUTH_KEY_MGMT_PSK) {
1048		wdev->wext.connect.crypto.akm_suites[nr_akm_suites] =
1049			WLAN_AKM_SUITE_PSK;
1050		nr_akm_suites++;
1051	}
1052
1053	wdev->wext.connect.crypto.n_akm_suites = nr_akm_suites;
1054
1055	return 0;
1056}
1057
1058int cfg80211_wext_siwauth(struct net_device *dev,
1059			  struct iw_request_info *info,
1060			  struct iw_param *data, char *extra)
1061{
1062	struct wireless_dev *wdev = dev->ieee80211_ptr;
1063
1064	if (wdev->iftype != NL80211_IFTYPE_STATION)
1065		return -EOPNOTSUPP;
1066
1067	switch (data->flags & IW_AUTH_INDEX) {
1068	case IW_AUTH_PRIVACY_INVOKED:
1069		wdev->wext.connect.privacy = data->value;
1070		return 0;
1071	case IW_AUTH_WPA_VERSION:
1072		return cfg80211_set_wpa_version(wdev, data->value);
1073	case IW_AUTH_CIPHER_GROUP:
1074		return cfg80211_set_cipher_group(wdev, data->value);
1075	case IW_AUTH_KEY_MGMT:
1076		return cfg80211_set_key_mgt(wdev, data->value);
1077	case IW_AUTH_CIPHER_PAIRWISE:
1078		return cfg80211_set_cipher_pairwise(wdev, data->value);
1079	case IW_AUTH_80211_AUTH_ALG:
1080		return cfg80211_set_auth_alg(wdev, data->value);
1081	case IW_AUTH_WPA_ENABLED:
1082	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1083	case IW_AUTH_DROP_UNENCRYPTED:
1084	case IW_AUTH_MFP:
1085		return 0;
1086	default:
1087		return -EOPNOTSUPP;
1088	}
1089}
1090EXPORT_SYMBOL_GPL(cfg80211_wext_siwauth);
1091
1092int cfg80211_wext_giwauth(struct net_device *dev,
1093			  struct iw_request_info *info,
1094			  struct iw_param *data, char *extra)
1095{
1096
1097	return -EOPNOTSUPP;
1098}
1099EXPORT_SYMBOL_GPL(cfg80211_wext_giwauth);
1100
1101int cfg80211_wext_siwpower(struct net_device *dev,
1102			   struct iw_request_info *info,
1103			   struct iw_param *wrq, char *extra)
1104{
1105	struct wireless_dev *wdev = dev->ieee80211_ptr;
1106	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
1107	bool ps = wdev->ps;
1108	int timeout = wdev->ps_timeout;
1109	int err;
1110
1111	if (wdev->iftype != NL80211_IFTYPE_STATION)
1112		return -EINVAL;
1113
1114	if (!rdev->ops->set_power_mgmt)
1115		return -EOPNOTSUPP;
1116
1117	if (wrq->disabled) {
1118		ps = false;
1119	} else {
1120		switch (wrq->flags & IW_POWER_MODE) {
1121		case IW_POWER_ON:       /* If not specified */
1122		case IW_POWER_MODE:     /* If set all mask */
1123		case IW_POWER_ALL_R:    /* If explicitely state all */
1124			ps = true;
1125			break;
1126		default:                /* Otherwise we ignore */
1127			return -EINVAL;
1128		}
1129
1130		if (wrq->flags & ~(IW_POWER_MODE | IW_POWER_TIMEOUT))
1131			return -EINVAL;
1132
1133		if (wrq->flags & IW_POWER_TIMEOUT)
1134			timeout = wrq->value / 1000;
1135	}
1136
1137	err = rdev->ops->set_power_mgmt(wdev->wiphy, dev, ps, timeout);
1138	if (err)
1139		return err;
1140
1141	wdev->ps = ps;
1142	wdev->ps_timeout = timeout;
1143
1144	return 0;
1145
1146}
1147EXPORT_SYMBOL_GPL(cfg80211_wext_siwpower);
1148
1149int cfg80211_wext_giwpower(struct net_device *dev,
1150			   struct iw_request_info *info,
1151			   struct iw_param *wrq, char *extra)
1152{
1153	struct wireless_dev *wdev = dev->ieee80211_ptr;
1154
1155	wrq->disabled = !wdev->ps;
1156
1157	return 0;
1158}
1159EXPORT_SYMBOL_GPL(cfg80211_wext_giwpower);
1160
1161static int cfg80211_wds_wext_siwap(struct net_device *dev,
1162				   struct iw_request_info *info,
1163				   struct sockaddr *addr, char *extra)
1164{
1165	struct wireless_dev *wdev = dev->ieee80211_ptr;
1166	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
1167	int err;
1168
1169	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_WDS))
1170		return -EINVAL;
1171
1172	if (addr->sa_family != ARPHRD_ETHER)
1173		return -EINVAL;
1174
1175	if (netif_running(dev))
1176		return -EBUSY;
1177
1178	if (!rdev->ops->set_wds_peer)
1179		return -EOPNOTSUPP;
1180
1181	err = rdev->ops->set_wds_peer(wdev->wiphy, dev, (u8 *) &addr->sa_data);
1182	if (err)
1183		return err;
1184
1185	memcpy(&wdev->wext.bssid, (u8 *) &addr->sa_data, ETH_ALEN);
1186
1187	return 0;
1188}
1189
1190static int cfg80211_wds_wext_giwap(struct net_device *dev,
1191				   struct iw_request_info *info,
1192				   struct sockaddr *addr, char *extra)
1193{
1194	struct wireless_dev *wdev = dev->ieee80211_ptr;
1195
1196	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_WDS))
1197		return -EINVAL;
1198
1199	addr->sa_family = ARPHRD_ETHER;
1200	memcpy(&addr->sa_data, wdev->wext.bssid, ETH_ALEN);
1201
1202	return 0;
1203}
1204
1205int cfg80211_wext_siwrate(struct net_device *dev,
1206			  struct iw_request_info *info,
1207			  struct iw_param *rate, char *extra)
1208{
1209	struct wireless_dev *wdev = dev->ieee80211_ptr;
1210	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
1211	struct cfg80211_bitrate_mask mask;
1212	u32 fixed, maxrate;
1213	struct ieee80211_supported_band *sband;
1214	int band, ridx;
1215	bool match = false;
1216
1217	if (!rdev->ops->set_bitrate_mask)
1218		return -EOPNOTSUPP;
1219
1220	memset(&mask, 0, sizeof(mask));
1221	fixed = 0;
1222	maxrate = (u32)-1;
1223
1224	if (rate->value < 0) {
1225		/* nothing */
1226	} else if (rate->fixed) {
1227		fixed = rate->value / 100000;
1228	} else {
1229		maxrate = rate->value / 100000;
1230	}
1231
1232	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
1233		sband = wdev->wiphy->bands[band];
1234		if (sband == NULL)
1235			continue;
1236		for (ridx = 0; ridx < sband->n_bitrates; ridx++) {
1237			struct ieee80211_rate *srate = &sband->bitrates[ridx];
1238			if (fixed == srate->bitrate) {
1239				mask.control[band].legacy = 1 << ridx;
1240				match = true;
1241				break;
1242			}
1243			if (srate->bitrate <= maxrate) {
1244				mask.control[band].legacy |= 1 << ridx;
1245				match = true;
1246			}
1247		}
1248	}
1249
1250	if (!match)
1251		return -EINVAL;
1252
1253	return rdev->ops->set_bitrate_mask(wdev->wiphy, dev, NULL, &mask);
1254}
1255EXPORT_SYMBOL_GPL(cfg80211_wext_siwrate);
1256
1257int cfg80211_wext_giwrate(struct net_device *dev,
1258			  struct iw_request_info *info,
1259			  struct iw_param *rate, char *extra)
1260{
1261	struct wireless_dev *wdev = dev->ieee80211_ptr;
1262	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
1263	/* we are under RTNL - globally locked - so can use a static struct */
1264	static struct station_info sinfo;
1265	u8 addr[ETH_ALEN];
1266	int err;
1267
1268	if (wdev->iftype != NL80211_IFTYPE_STATION)
1269		return -EOPNOTSUPP;
1270
1271	if (!rdev->ops->get_station)
1272		return -EOPNOTSUPP;
1273
1274	err = 0;
1275	wdev_lock(wdev);
1276	if (wdev->current_bss)
1277		memcpy(addr, wdev->current_bss->pub.bssid, ETH_ALEN);
1278	else
1279		err = -EOPNOTSUPP;
1280	wdev_unlock(wdev);
1281	if (err)
1282		return err;
1283
1284	err = rdev->ops->get_station(&rdev->wiphy, dev, addr, &sinfo);
1285	if (err)
1286		return err;
1287
1288	if (!(sinfo.filled & STATION_INFO_TX_BITRATE))
1289		return -EOPNOTSUPP;
1290
1291	rate->value = 100000 * cfg80211_calculate_bitrate(&sinfo.txrate);
1292
1293	return 0;
1294}
1295EXPORT_SYMBOL_GPL(cfg80211_wext_giwrate);
1296
1297/* Get wireless statistics.  Called by /proc/net/wireless and by SIOCGIWSTATS */
1298struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev)
1299{
1300	struct wireless_dev *wdev = dev->ieee80211_ptr;
1301	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
1302	/* we are under RTNL - globally locked - so can use static structs */
1303	static struct iw_statistics wstats;
1304	static struct station_info sinfo;
1305	u8 bssid[ETH_ALEN];
1306
1307	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION)
1308		return NULL;
1309
1310	if (!rdev->ops->get_station)
1311		return NULL;
1312
1313	/* Grab BSSID of current BSS, if any */
1314	wdev_lock(wdev);
1315	if (!wdev->current_bss) {
1316		wdev_unlock(wdev);
1317		return NULL;
1318	}
1319	memcpy(bssid, wdev->current_bss->pub.bssid, ETH_ALEN);
1320	wdev_unlock(wdev);
1321
1322	if (rdev->ops->get_station(&rdev->wiphy, dev, bssid, &sinfo))
1323		return NULL;
1324
1325	memset(&wstats, 0, sizeof(wstats));
1326
1327	switch (rdev->wiphy.signal_type) {
1328	case CFG80211_SIGNAL_TYPE_MBM:
1329		if (sinfo.filled & STATION_INFO_SIGNAL) {
1330			int sig = sinfo.signal;
1331			wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED;
1332			wstats.qual.updated |= IW_QUAL_QUAL_UPDATED;
1333			wstats.qual.updated |= IW_QUAL_DBM;
1334			wstats.qual.level = sig;
1335			if (sig < -110)
1336				sig = -110;
1337			else if (sig > -40)
1338				sig = -40;
1339			wstats.qual.qual = sig + 110;
1340			break;
1341		}
1342	case CFG80211_SIGNAL_TYPE_UNSPEC:
1343		if (sinfo.filled & STATION_INFO_SIGNAL) {
1344			wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED;
1345			wstats.qual.updated |= IW_QUAL_QUAL_UPDATED;
1346			wstats.qual.level = sinfo.signal;
1347			wstats.qual.qual = sinfo.signal;
1348			break;
1349		}
1350	default:
1351		wstats.qual.updated |= IW_QUAL_LEVEL_INVALID;
1352		wstats.qual.updated |= IW_QUAL_QUAL_INVALID;
1353	}
1354
1355	wstats.qual.updated |= IW_QUAL_NOISE_INVALID;
1356
1357	return &wstats;
1358}
1359EXPORT_SYMBOL_GPL(cfg80211_wireless_stats);
1360
1361int cfg80211_wext_siwap(struct net_device *dev,
1362			struct iw_request_info *info,
1363			struct sockaddr *ap_addr, char *extra)
1364{
1365	struct wireless_dev *wdev = dev->ieee80211_ptr;
1366
1367	switch (wdev->iftype) {
1368	case NL80211_IFTYPE_ADHOC:
1369		return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra);
1370	case NL80211_IFTYPE_STATION:
1371		return cfg80211_mgd_wext_siwap(dev, info, ap_addr, extra);
1372	case NL80211_IFTYPE_WDS:
1373		return cfg80211_wds_wext_siwap(dev, info, ap_addr, extra);
1374	default:
1375		return -EOPNOTSUPP;
1376	}
1377}
1378EXPORT_SYMBOL_GPL(cfg80211_wext_siwap);
1379
1380int cfg80211_wext_giwap(struct net_device *dev,
1381			struct iw_request_info *info,
1382			struct sockaddr *ap_addr, char *extra)
1383{
1384	struct wireless_dev *wdev = dev->ieee80211_ptr;
1385
1386	switch (wdev->iftype) {
1387	case NL80211_IFTYPE_ADHOC:
1388		return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra);
1389	case NL80211_IFTYPE_STATION:
1390		return cfg80211_mgd_wext_giwap(dev, info, ap_addr, extra);
1391	case NL80211_IFTYPE_WDS:
1392		return cfg80211_wds_wext_giwap(dev, info, ap_addr, extra);
1393	default:
1394		return -EOPNOTSUPP;
1395	}
1396}
1397EXPORT_SYMBOL_GPL(cfg80211_wext_giwap);
1398
1399int cfg80211_wext_siwessid(struct net_device *dev,
1400			   struct iw_request_info *info,
1401			   struct iw_point *data, char *ssid)
1402{
1403	struct wireless_dev *wdev = dev->ieee80211_ptr;
1404
1405	switch (wdev->iftype) {
1406	case NL80211_IFTYPE_ADHOC:
1407		return cfg80211_ibss_wext_siwessid(dev, info, data, ssid);
1408	case NL80211_IFTYPE_STATION:
1409		return cfg80211_mgd_wext_siwessid(dev, info, data, ssid);
1410	default:
1411		return -EOPNOTSUPP;
1412	}
1413}
1414EXPORT_SYMBOL_GPL(cfg80211_wext_siwessid);
1415
1416int cfg80211_wext_giwessid(struct net_device *dev,
1417			   struct iw_request_info *info,
1418			   struct iw_point *data, char *ssid)
1419{
1420	struct wireless_dev *wdev = dev->ieee80211_ptr;
1421
1422	data->flags = 0;
1423	data->length = 0;
1424
1425	switch (wdev->iftype) {
1426	case NL80211_IFTYPE_ADHOC:
1427		return cfg80211_ibss_wext_giwessid(dev, info, data, ssid);
1428	case NL80211_IFTYPE_STATION:
1429		return cfg80211_mgd_wext_giwessid(dev, info, data, ssid);
1430	default:
1431		return -EOPNOTSUPP;
1432	}
1433}
1434EXPORT_SYMBOL_GPL(cfg80211_wext_giwessid);
1435
1436int cfg80211_wext_siwpmksa(struct net_device *dev,
1437			   struct iw_request_info *info,
1438			   struct iw_point *data, char *extra)
1439{
1440	struct wireless_dev *wdev = dev->ieee80211_ptr;
1441	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
1442	struct cfg80211_pmksa cfg_pmksa;
1443	struct iw_pmksa *pmksa = (struct iw_pmksa *)extra;
1444
1445	memset(&cfg_pmksa, 0, sizeof(struct cfg80211_pmksa));
1446
1447	if (wdev->iftype != NL80211_IFTYPE_STATION)
1448		return -EINVAL;
1449
1450	cfg_pmksa.bssid = pmksa->bssid.sa_data;
1451	cfg_pmksa.pmkid = pmksa->pmkid;
1452
1453	switch (pmksa->cmd) {
1454	case IW_PMKSA_ADD:
1455		if (!rdev->ops->set_pmksa)
1456			return -EOPNOTSUPP;
1457
1458		return rdev->ops->set_pmksa(&rdev->wiphy, dev, &cfg_pmksa);
1459
1460	case IW_PMKSA_REMOVE:
1461		if (!rdev->ops->del_pmksa)
1462			return -EOPNOTSUPP;
1463
1464		return rdev->ops->del_pmksa(&rdev->wiphy, dev, &cfg_pmksa);
1465
1466	case IW_PMKSA_FLUSH:
1467		if (!rdev->ops->flush_pmksa)
1468			return -EOPNOTSUPP;
1469
1470		return rdev->ops->flush_pmksa(&rdev->wiphy, dev);
1471
1472	default:
1473		return -EOPNOTSUPP;
1474	}
1475}
1476EXPORT_SYMBOL_GPL(cfg80211_wext_siwpmksa);
1477
1478static const iw_handler cfg80211_handlers[] = {
1479	[IW_IOCTL_IDX(SIOCGIWNAME)]	= (iw_handler) cfg80211_wext_giwname,
1480	[IW_IOCTL_IDX(SIOCSIWFREQ)]	= (iw_handler) cfg80211_wext_siwfreq,
1481	[IW_IOCTL_IDX(SIOCGIWFREQ)]	= (iw_handler) cfg80211_wext_giwfreq,
1482	[IW_IOCTL_IDX(SIOCSIWMODE)]	= (iw_handler) cfg80211_wext_siwmode,
1483	[IW_IOCTL_IDX(SIOCGIWMODE)]	= (iw_handler) cfg80211_wext_giwmode,
1484	[IW_IOCTL_IDX(SIOCGIWRANGE)]	= (iw_handler) cfg80211_wext_giwrange,
1485	[IW_IOCTL_IDX(SIOCSIWAP)]	= (iw_handler) cfg80211_wext_siwap,
1486	[IW_IOCTL_IDX(SIOCGIWAP)]	= (iw_handler) cfg80211_wext_giwap,
1487	[IW_IOCTL_IDX(SIOCSIWMLME)]	= (iw_handler) cfg80211_wext_siwmlme,
1488	[IW_IOCTL_IDX(SIOCSIWSCAN)]	= (iw_handler) cfg80211_wext_siwscan,
1489	[IW_IOCTL_IDX(SIOCGIWSCAN)]	= (iw_handler) cfg80211_wext_giwscan,
1490	[IW_IOCTL_IDX(SIOCSIWESSID)]	= (iw_handler) cfg80211_wext_siwessid,
1491	[IW_IOCTL_IDX(SIOCGIWESSID)]	= (iw_handler) cfg80211_wext_giwessid,
1492	[IW_IOCTL_IDX(SIOCSIWRATE)]	= (iw_handler) cfg80211_wext_siwrate,
1493	[IW_IOCTL_IDX(SIOCGIWRATE)]	= (iw_handler) cfg80211_wext_giwrate,
1494	[IW_IOCTL_IDX(SIOCSIWRTS)]	= (iw_handler) cfg80211_wext_siwrts,
1495	[IW_IOCTL_IDX(SIOCGIWRTS)]	= (iw_handler) cfg80211_wext_giwrts,
1496	[IW_IOCTL_IDX(SIOCSIWFRAG)]	= (iw_handler) cfg80211_wext_siwfrag,
1497	[IW_IOCTL_IDX(SIOCGIWFRAG)]	= (iw_handler) cfg80211_wext_giwfrag,
1498	[IW_IOCTL_IDX(SIOCSIWTXPOW)]	= (iw_handler) cfg80211_wext_siwtxpower,
1499	[IW_IOCTL_IDX(SIOCGIWTXPOW)]	= (iw_handler) cfg80211_wext_giwtxpower,
1500	[IW_IOCTL_IDX(SIOCSIWRETRY)]	= (iw_handler) cfg80211_wext_siwretry,
1501	[IW_IOCTL_IDX(SIOCGIWRETRY)]	= (iw_handler) cfg80211_wext_giwretry,
1502	[IW_IOCTL_IDX(SIOCSIWENCODE)]	= (iw_handler) cfg80211_wext_siwencode,
1503	[IW_IOCTL_IDX(SIOCGIWENCODE)]	= (iw_handler) cfg80211_wext_giwencode,
1504	[IW_IOCTL_IDX(SIOCSIWPOWER)]	= (iw_handler) cfg80211_wext_siwpower,
1505	[IW_IOCTL_IDX(SIOCGIWPOWER)]	= (iw_handler) cfg80211_wext_giwpower,
1506	[IW_IOCTL_IDX(SIOCSIWGENIE)]	= (iw_handler) cfg80211_wext_siwgenie,
1507	[IW_IOCTL_IDX(SIOCSIWAUTH)]	= (iw_handler) cfg80211_wext_siwauth,
1508	[IW_IOCTL_IDX(SIOCGIWAUTH)]	= (iw_handler) cfg80211_wext_giwauth,
1509	[IW_IOCTL_IDX(SIOCSIWENCODEEXT)]= (iw_handler) cfg80211_wext_siwencodeext,
1510	[IW_IOCTL_IDX(SIOCSIWPMKSA)]	= (iw_handler) cfg80211_wext_siwpmksa,
1511};
1512
1513const struct iw_handler_def cfg80211_wext_handler = {
1514	.num_standard		= ARRAY_SIZE(cfg80211_handlers),
1515	.standard		= cfg80211_handlers,
1516	.get_wireless_stats = cfg80211_wireless_stats,
1517};
1518