• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2002-2005, Instant802 Networks, Inc.
3  * Copyright 2005-2006, Devicescape Software, Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  */
9 
10 #include <linux/module.h>
11 #include <linux/init.h>
12 #include <linux/netdevice.h>
13 #include <linux/types.h>
14 #include <linux/slab.h>
15 #include <linux/skbuff.h>
16 #include <linux/etherdevice.h>
17 #include <linux/if_arp.h>
18 #include <linux/wireless.h>
19 #include <net/iw_handler.h>
20 #include <asm/uaccess.h>
21 
22 #include <net/mac80211.h>
23 #include "ieee80211_i.h"
24 #include "led.h"
25 #include "rate.h"
26 #include "wpa.h"
27 #include "aes_ccm.h"
28 
29 
ieee80211_set_encryption(struct ieee80211_sub_if_data * sdata,u8 * sta_addr,int idx,int alg,int remove,int set_tx_key,const u8 * _key,size_t key_len)30 static int ieee80211_set_encryption(struct ieee80211_sub_if_data *sdata, u8 *sta_addr,
31 				    int idx, int alg, int remove,
32 				    int set_tx_key, const u8 *_key,
33 				    size_t key_len)
34 {
35 	struct ieee80211_local *local = sdata->local;
36 	struct sta_info *sta;
37 	struct ieee80211_key *key;
38 	int err;
39 
40 	if (idx < 0 || idx >= NUM_DEFAULT_KEYS) {
41 		printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n",
42 		       sdata->dev->name, idx);
43 		return -EINVAL;
44 	}
45 
46 	if (remove) {
47 		rcu_read_lock();
48 
49 		err = 0;
50 
51 		if (is_broadcast_ether_addr(sta_addr)) {
52 			key = sdata->keys[idx];
53 		} else {
54 			sta = sta_info_get(local, sta_addr);
55 			if (!sta) {
56 				err = -ENOENT;
57 				goto out_unlock;
58 			}
59 			key = sta->key;
60 		}
61 
62 		ieee80211_key_free(key);
63 	} else {
64 		key = ieee80211_key_alloc(alg, idx, key_len, _key);
65 		if (!key)
66 			return -ENOMEM;
67 
68 		sta = NULL;
69 		err = 0;
70 
71 		rcu_read_lock();
72 
73 		if (!is_broadcast_ether_addr(sta_addr)) {
74 			set_tx_key = 0;
75 			/*
76 			 * According to the standard, the key index of a
77 			 * pairwise key must be zero. However, some AP are
78 			 * broken when it comes to WEP key indices, so we
79 			 * work around this.
80 			 */
81 			if (idx != 0 && alg != ALG_WEP) {
82 				ieee80211_key_free(key);
83 				err = -EINVAL;
84 				goto out_unlock;
85 			}
86 
87 			sta = sta_info_get(local, sta_addr);
88 			if (!sta) {
89 				ieee80211_key_free(key);
90 				err = -ENOENT;
91 				goto out_unlock;
92 			}
93 		}
94 
95 		if (alg == ALG_WEP &&
96 			key_len != LEN_WEP40 && key_len != LEN_WEP104) {
97 			ieee80211_key_free(key);
98 			err = -EINVAL;
99 			goto out_unlock;
100 		}
101 
102 		ieee80211_key_link(key, sdata, sta);
103 
104 		if (set_tx_key || (!sta && !sdata->default_key && key))
105 			ieee80211_set_default_key(sdata, idx);
106 	}
107 
108  out_unlock:
109 	rcu_read_unlock();
110 
111 	return err;
112 }
113 
ieee80211_ioctl_siwgenie(struct net_device * dev,struct iw_request_info * info,struct iw_point * data,char * extra)114 static int ieee80211_ioctl_siwgenie(struct net_device *dev,
115 				    struct iw_request_info *info,
116 				    struct iw_point *data, char *extra)
117 {
118 	struct ieee80211_sub_if_data *sdata;
119 
120 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
121 
122 	if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME)
123 		return -EOPNOTSUPP;
124 
125 	if (sdata->vif.type == NL80211_IFTYPE_STATION ||
126 	    sdata->vif.type == NL80211_IFTYPE_ADHOC) {
127 		int ret = ieee80211_sta_set_extra_ie(sdata, extra, data->length);
128 		if (ret)
129 			return ret;
130 		sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
131 		ieee80211_sta_req_auth(sdata, &sdata->u.sta);
132 		return 0;
133 	}
134 
135 	return -EOPNOTSUPP;
136 }
137 
ieee80211_ioctl_giwrange(struct net_device * dev,struct iw_request_info * info,struct iw_point * data,char * extra)138 static int ieee80211_ioctl_giwrange(struct net_device *dev,
139 				 struct iw_request_info *info,
140 				 struct iw_point *data, char *extra)
141 {
142 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
143 	struct iw_range *range = (struct iw_range *) extra;
144 	enum ieee80211_band band;
145 	int c = 0;
146 
147 	data->length = sizeof(struct iw_range);
148 	memset(range, 0, sizeof(struct iw_range));
149 
150 	range->we_version_compiled = WIRELESS_EXT;
151 	range->we_version_source = 21;
152 	range->retry_capa = IW_RETRY_LIMIT;
153 	range->retry_flags = IW_RETRY_LIMIT;
154 	range->min_retry = 0;
155 	range->max_retry = 255;
156 	range->min_rts = 0;
157 	range->max_rts = 2347;
158 	range->min_frag = 256;
159 	range->max_frag = 2346;
160 
161 	range->encoding_size[0] = 5;
162 	range->encoding_size[1] = 13;
163 	range->num_encoding_sizes = 2;
164 	range->max_encoding_tokens = NUM_DEFAULT_KEYS;
165 
166 	if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC ||
167 	    local->hw.flags & IEEE80211_HW_SIGNAL_DB)
168 		range->max_qual.level = local->hw.max_signal;
169 	else if  (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
170 		range->max_qual.level = -110;
171 	else
172 		range->max_qual.level = 0;
173 
174 	if (local->hw.flags & IEEE80211_HW_NOISE_DBM)
175 		range->max_qual.noise = -110;
176 	else
177 		range->max_qual.noise = 0;
178 
179 	range->max_qual.qual = 100;
180 	range->max_qual.updated = local->wstats_flags;
181 
182 	range->avg_qual.qual = 50;
183 	/* not always true but better than nothing */
184 	range->avg_qual.level = range->max_qual.level / 2;
185 	range->avg_qual.noise = range->max_qual.noise / 2;
186 	range->avg_qual.updated = local->wstats_flags;
187 
188 	range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
189 			  IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
190 
191 
192 	for (band = 0; band < IEEE80211_NUM_BANDS; band ++) {
193 		int i;
194 		struct ieee80211_supported_band *sband;
195 
196 		sband = local->hw.wiphy->bands[band];
197 
198 		if (!sband)
199 			continue;
200 
201 		for (i = 0; i < sband->n_channels && c < IW_MAX_FREQUENCIES; i++) {
202 			struct ieee80211_channel *chan = &sband->channels[i];
203 
204 			if (!(chan->flags & IEEE80211_CHAN_DISABLED)) {
205 				range->freq[c].i =
206 					ieee80211_frequency_to_channel(
207 						chan->center_freq);
208 				range->freq[c].m = chan->center_freq;
209 				range->freq[c].e = 6;
210 				c++;
211 			}
212 		}
213 	}
214 	range->num_channels = c;
215 	range->num_frequency = c;
216 
217 	IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
218 	IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
219 	IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
220 
221 	range->scan_capa |= IW_SCAN_CAPA_ESSID;
222 
223 	return 0;
224 }
225 
226 
ieee80211_ioctl_siwfreq(struct net_device * dev,struct iw_request_info * info,struct iw_freq * freq,char * extra)227 static int ieee80211_ioctl_siwfreq(struct net_device *dev,
228 				   struct iw_request_info *info,
229 				   struct iw_freq *freq, char *extra)
230 {
231 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
232 
233 	if (sdata->vif.type == NL80211_IFTYPE_STATION)
234 		sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_CHANNEL_SEL;
235 
236 	/* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */
237 	if (freq->e == 0) {
238 		if (freq->m < 0) {
239 			if (sdata->vif.type == NL80211_IFTYPE_STATION)
240 				sdata->u.sta.flags |=
241 					IEEE80211_STA_AUTO_CHANNEL_SEL;
242 			return 0;
243 		} else
244 			return ieee80211_set_freq(sdata,
245 				ieee80211_channel_to_frequency(freq->m));
246 	} else {
247 		int i, div = 1000000;
248 		for (i = 0; i < freq->e; i++)
249 			div /= 10;
250 		if (div > 0)
251 			return ieee80211_set_freq(sdata, freq->m / div);
252 		else
253 			return -EINVAL;
254 	}
255 }
256 
257 
ieee80211_ioctl_giwfreq(struct net_device * dev,struct iw_request_info * info,struct iw_freq * freq,char * extra)258 static int ieee80211_ioctl_giwfreq(struct net_device *dev,
259 				   struct iw_request_info *info,
260 				   struct iw_freq *freq, char *extra)
261 {
262 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
263 
264 	freq->m = local->hw.conf.channel->center_freq;
265 	freq->e = 6;
266 
267 	return 0;
268 }
269 
270 
ieee80211_ioctl_siwessid(struct net_device * dev,struct iw_request_info * info,struct iw_point * data,char * ssid)271 static int ieee80211_ioctl_siwessid(struct net_device *dev,
272 				    struct iw_request_info *info,
273 				    struct iw_point *data, char *ssid)
274 {
275 	struct ieee80211_sub_if_data *sdata;
276 	size_t len = data->length;
277 
278 	/* iwconfig uses nul termination in SSID.. */
279 	if (len > 0 && ssid[len - 1] == '\0')
280 		len--;
281 
282 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
283 	if (sdata->vif.type == NL80211_IFTYPE_STATION ||
284 	    sdata->vif.type == NL80211_IFTYPE_ADHOC) {
285 		int ret;
286 		if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) {
287 			if (len > IEEE80211_MAX_SSID_LEN)
288 				return -EINVAL;
289 			memcpy(sdata->u.sta.ssid, ssid, len);
290 			sdata->u.sta.ssid_len = len;
291 			return 0;
292 		}
293 		if (data->flags)
294 			sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_SSID_SEL;
295 		else
296 			sdata->u.sta.flags |= IEEE80211_STA_AUTO_SSID_SEL;
297 		ret = ieee80211_sta_set_ssid(sdata, ssid, len);
298 		if (ret)
299 			return ret;
300 		ieee80211_sta_req_auth(sdata, &sdata->u.sta);
301 		return 0;
302 	}
303 
304 	return -EOPNOTSUPP;
305 }
306 
307 
ieee80211_ioctl_giwessid(struct net_device * dev,struct iw_request_info * info,struct iw_point * data,char * ssid)308 static int ieee80211_ioctl_giwessid(struct net_device *dev,
309 				    struct iw_request_info *info,
310 				    struct iw_point *data, char *ssid)
311 {
312 	size_t len;
313 
314 	struct ieee80211_sub_if_data *sdata;
315 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
316 	if (sdata->vif.type == NL80211_IFTYPE_STATION ||
317 	    sdata->vif.type == NL80211_IFTYPE_ADHOC) {
318 		int res = ieee80211_sta_get_ssid(sdata, ssid, &len);
319 		if (res == 0) {
320 			data->length = len;
321 			data->flags = 1;
322 		} else
323 			data->flags = 0;
324 		return res;
325 	}
326 
327 	return -EOPNOTSUPP;
328 }
329 
330 
ieee80211_ioctl_siwap(struct net_device * dev,struct iw_request_info * info,struct sockaddr * ap_addr,char * extra)331 static int ieee80211_ioctl_siwap(struct net_device *dev,
332 				 struct iw_request_info *info,
333 				 struct sockaddr *ap_addr, char *extra)
334 {
335 	struct ieee80211_sub_if_data *sdata;
336 
337 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
338 	if (sdata->vif.type == NL80211_IFTYPE_STATION ||
339 	    sdata->vif.type == NL80211_IFTYPE_ADHOC) {
340 		int ret;
341 		if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) {
342 			memcpy(sdata->u.sta.bssid, (u8 *) &ap_addr->sa_data,
343 			       ETH_ALEN);
344 			return 0;
345 		}
346 		if (is_zero_ether_addr((u8 *) &ap_addr->sa_data))
347 			sdata->u.sta.flags |= IEEE80211_STA_AUTO_BSSID_SEL |
348 				IEEE80211_STA_AUTO_CHANNEL_SEL;
349 		else if (is_broadcast_ether_addr((u8 *) &ap_addr->sa_data))
350 			sdata->u.sta.flags |= IEEE80211_STA_AUTO_BSSID_SEL;
351 		else
352 			sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
353 		ret = ieee80211_sta_set_bssid(sdata, (u8 *) &ap_addr->sa_data);
354 		if (ret)
355 			return ret;
356 		ieee80211_sta_req_auth(sdata, &sdata->u.sta);
357 		return 0;
358 	} else if (sdata->vif.type == NL80211_IFTYPE_WDS) {
359 		/*
360 		 * If it is necessary to update the WDS peer address
361 		 * while the interface is running, then we need to do
362 		 * more work here, namely if it is running we need to
363 		 * add a new and remove the old STA entry, this is
364 		 * normally handled by _open() and _stop().
365 		 */
366 		if (netif_running(dev))
367 			return -EBUSY;
368 
369 		memcpy(&sdata->u.wds.remote_addr, (u8 *) &ap_addr->sa_data,
370 		       ETH_ALEN);
371 
372 		return 0;
373 	}
374 
375 	return -EOPNOTSUPP;
376 }
377 
378 
ieee80211_ioctl_giwap(struct net_device * dev,struct iw_request_info * info,struct sockaddr * ap_addr,char * extra)379 static int ieee80211_ioctl_giwap(struct net_device *dev,
380 				 struct iw_request_info *info,
381 				 struct sockaddr *ap_addr, char *extra)
382 {
383 	struct ieee80211_sub_if_data *sdata;
384 
385 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
386 	if (sdata->vif.type == NL80211_IFTYPE_STATION ||
387 	    sdata->vif.type == NL80211_IFTYPE_ADHOC) {
388 		if (sdata->u.sta.state == IEEE80211_STA_MLME_ASSOCIATED ||
389 		    sdata->u.sta.state == IEEE80211_STA_MLME_IBSS_JOINED) {
390 			ap_addr->sa_family = ARPHRD_ETHER;
391 			memcpy(&ap_addr->sa_data, sdata->u.sta.bssid, ETH_ALEN);
392 			return 0;
393 		} else {
394 			memset(&ap_addr->sa_data, 0, ETH_ALEN);
395 			return 0;
396 		}
397 	} else if (sdata->vif.type == NL80211_IFTYPE_WDS) {
398 		ap_addr->sa_family = ARPHRD_ETHER;
399 		memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN);
400 		return 0;
401 	}
402 
403 	return -EOPNOTSUPP;
404 }
405 
406 
ieee80211_ioctl_siwscan(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)407 static int ieee80211_ioctl_siwscan(struct net_device *dev,
408 				   struct iw_request_info *info,
409 				   union iwreq_data *wrqu, char *extra)
410 {
411 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
412 	struct iw_scan_req *req = NULL;
413 	u8 *ssid = NULL;
414 	size_t ssid_len = 0;
415 
416 	if (!netif_running(dev))
417 		return -ENETDOWN;
418 
419 	if (sdata->vif.type != NL80211_IFTYPE_STATION &&
420 	    sdata->vif.type != NL80211_IFTYPE_ADHOC &&
421 	    sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
422 		return -EOPNOTSUPP;
423 
424 	/* if SSID was specified explicitly then use that */
425 	if (wrqu->data.length == sizeof(struct iw_scan_req) &&
426 	    wrqu->data.flags & IW_SCAN_THIS_ESSID) {
427 		req = (struct iw_scan_req *)extra;
428 		ssid = req->essid;
429 		ssid_len = req->essid_len;
430 	}
431 
432 	return ieee80211_request_scan(sdata, ssid, ssid_len);
433 }
434 
435 
ieee80211_ioctl_giwscan(struct net_device * dev,struct iw_request_info * info,struct iw_point * data,char * extra)436 static int ieee80211_ioctl_giwscan(struct net_device *dev,
437 				   struct iw_request_info *info,
438 				   struct iw_point *data, char *extra)
439 {
440 	int res;
441 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
442 	struct ieee80211_sub_if_data *sdata;
443 
444 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
445 
446 	if (local->sw_scanning || local->hw_scanning)
447 		return -EAGAIN;
448 
449 	res = ieee80211_scan_results(local, info, extra, data->length);
450 	if (res >= 0) {
451 		data->length = res;
452 		return 0;
453 	}
454 	data->length = 0;
455 	return res;
456 }
457 
458 
ieee80211_ioctl_siwrate(struct net_device * dev,struct iw_request_info * info,struct iw_param * rate,char * extra)459 static int ieee80211_ioctl_siwrate(struct net_device *dev,
460 				  struct iw_request_info *info,
461 				  struct iw_param *rate, char *extra)
462 {
463 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
464 	int i, err = -EINVAL;
465 	u32 target_rate = rate->value / 100000;
466 	struct ieee80211_sub_if_data *sdata;
467 	struct ieee80211_supported_band *sband;
468 
469 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
470 
471 	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
472 
473 	/* target_rate = -1, rate->fixed = 0 means auto only, so use all rates
474 	 * target_rate = X, rate->fixed = 1 means only rate X
475 	 * target_rate = X, rate->fixed = 0 means all rates <= X */
476 	sdata->max_ratectrl_rateidx = -1;
477 	sdata->force_unicast_rateidx = -1;
478 	if (rate->value < 0)
479 		return 0;
480 
481 	for (i=0; i< sband->n_bitrates; i++) {
482 		struct ieee80211_rate *brate = &sband->bitrates[i];
483 		int this_rate = brate->bitrate;
484 
485 		if (target_rate == this_rate) {
486 			sdata->max_ratectrl_rateidx = i;
487 			if (rate->fixed)
488 				sdata->force_unicast_rateidx = i;
489 			err = 0;
490 			break;
491 		}
492 	}
493 	return err;
494 }
495 
ieee80211_ioctl_giwrate(struct net_device * dev,struct iw_request_info * info,struct iw_param * rate,char * extra)496 static int ieee80211_ioctl_giwrate(struct net_device *dev,
497 				  struct iw_request_info *info,
498 				  struct iw_param *rate, char *extra)
499 {
500 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
501 	struct sta_info *sta;
502 	struct ieee80211_sub_if_data *sdata;
503 	struct ieee80211_supported_band *sband;
504 
505 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
506 
507 	if (sdata->vif.type != NL80211_IFTYPE_STATION)
508 		return -EOPNOTSUPP;
509 
510 	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
511 
512 	rcu_read_lock();
513 
514 	sta = sta_info_get(local, sdata->u.sta.bssid);
515 
516 	if (sta && !(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS))
517 		rate->value = sband->bitrates[sta->last_tx_rate.idx].bitrate;
518 	else
519 		rate->value = 0;
520 
521 	rcu_read_unlock();
522 
523 	if (!sta)
524 		return -ENODEV;
525 
526 	rate->value *= 100000;
527 
528 	return 0;
529 }
530 
ieee80211_ioctl_siwtxpower(struct net_device * dev,struct iw_request_info * info,union iwreq_data * data,char * extra)531 static int ieee80211_ioctl_siwtxpower(struct net_device *dev,
532 				      struct iw_request_info *info,
533 				      union iwreq_data *data, char *extra)
534 {
535 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
536 	struct ieee80211_channel* chan = local->hw.conf.channel;
537 	u32 reconf_flags = 0;
538 	int new_power_level;
539 
540 	if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
541 		return -EINVAL;
542 	if (data->txpower.flags & IW_TXPOW_RANGE)
543 		return -EINVAL;
544 	if (!chan)
545 		return -EINVAL;
546 
547 	if (data->txpower.fixed)
548 		new_power_level = min(data->txpower.value, chan->max_power);
549 	else /* Automatic power level setting */
550 		new_power_level = chan->max_power;
551 
552 	if (local->hw.conf.power_level != new_power_level) {
553 		local->hw.conf.power_level = new_power_level;
554 		reconf_flags |= IEEE80211_CONF_CHANGE_POWER;
555 	}
556 
557 	if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) {
558 		local->hw.conf.radio_enabled = !(data->txpower.disabled);
559 		reconf_flags |= IEEE80211_CONF_CHANGE_RADIO_ENABLED;
560 		ieee80211_led_radio(local, local->hw.conf.radio_enabled);
561 	}
562 
563 	if (reconf_flags)
564 		ieee80211_hw_config(local, reconf_flags);
565 
566 	return 0;
567 }
568 
ieee80211_ioctl_giwtxpower(struct net_device * dev,struct iw_request_info * info,union iwreq_data * data,char * extra)569 static int ieee80211_ioctl_giwtxpower(struct net_device *dev,
570 				   struct iw_request_info *info,
571 				   union iwreq_data *data, char *extra)
572 {
573 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
574 
575 	data->txpower.fixed = 1;
576 	data->txpower.disabled = !(local->hw.conf.radio_enabled);
577 	data->txpower.value = local->hw.conf.power_level;
578 	data->txpower.flags = IW_TXPOW_DBM;
579 
580 	return 0;
581 }
582 
ieee80211_ioctl_siwrts(struct net_device * dev,struct iw_request_info * info,struct iw_param * rts,char * extra)583 static int ieee80211_ioctl_siwrts(struct net_device *dev,
584 				  struct iw_request_info *info,
585 				  struct iw_param *rts, char *extra)
586 {
587 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
588 
589 	if (rts->disabled)
590 		local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
591 	else if (!rts->fixed)
592 		/* if the rts value is not fixed, then take default */
593 		local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
594 	else if (rts->value < 0 || rts->value > IEEE80211_MAX_RTS_THRESHOLD)
595 		return -EINVAL;
596 	else
597 		local->rts_threshold = rts->value;
598 
599 	/* If the wlan card performs RTS/CTS in hardware/firmware,
600 	 * configure it here */
601 
602 	if (local->ops->set_rts_threshold)
603 		local->ops->set_rts_threshold(local_to_hw(local),
604 					     local->rts_threshold);
605 
606 	return 0;
607 }
608 
ieee80211_ioctl_giwrts(struct net_device * dev,struct iw_request_info * info,struct iw_param * rts,char * extra)609 static int ieee80211_ioctl_giwrts(struct net_device *dev,
610 				  struct iw_request_info *info,
611 				  struct iw_param *rts, char *extra)
612 {
613 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
614 
615 	rts->value = local->rts_threshold;
616 	rts->disabled = (rts->value >= IEEE80211_MAX_RTS_THRESHOLD);
617 	rts->fixed = 1;
618 
619 	return 0;
620 }
621 
622 
ieee80211_ioctl_siwfrag(struct net_device * dev,struct iw_request_info * info,struct iw_param * frag,char * extra)623 static int ieee80211_ioctl_siwfrag(struct net_device *dev,
624 				   struct iw_request_info *info,
625 				   struct iw_param *frag, char *extra)
626 {
627 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
628 
629 	if (frag->disabled)
630 		local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
631 	else if (!frag->fixed)
632 		local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
633 	else if (frag->value < 256 ||
634 		 frag->value > IEEE80211_MAX_FRAG_THRESHOLD)
635 		return -EINVAL;
636 	else {
637 		/* Fragment length must be even, so strip LSB. */
638 		local->fragmentation_threshold = frag->value & ~0x1;
639 	}
640 
641 	return 0;
642 }
643 
ieee80211_ioctl_giwfrag(struct net_device * dev,struct iw_request_info * info,struct iw_param * frag,char * extra)644 static int ieee80211_ioctl_giwfrag(struct net_device *dev,
645 				   struct iw_request_info *info,
646 				   struct iw_param *frag, char *extra)
647 {
648 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
649 
650 	frag->value = local->fragmentation_threshold;
651 	frag->disabled = (frag->value >= IEEE80211_MAX_RTS_THRESHOLD);
652 	frag->fixed = 1;
653 
654 	return 0;
655 }
656 
657 
ieee80211_ioctl_siwretry(struct net_device * dev,struct iw_request_info * info,struct iw_param * retry,char * extra)658 static int ieee80211_ioctl_siwretry(struct net_device *dev,
659 				    struct iw_request_info *info,
660 				    struct iw_param *retry, char *extra)
661 {
662 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
663 
664 	if (retry->disabled ||
665 	    (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
666 		return -EINVAL;
667 
668 	if (retry->flags & IW_RETRY_MAX) {
669 		local->hw.conf.long_frame_max_tx_count = retry->value;
670 	} else if (retry->flags & IW_RETRY_MIN) {
671 		local->hw.conf.short_frame_max_tx_count = retry->value;
672 	} else {
673 		local->hw.conf.long_frame_max_tx_count = retry->value;
674 		local->hw.conf.short_frame_max_tx_count = retry->value;
675 	}
676 
677 	ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_RETRY_LIMITS);
678 
679 	return 0;
680 }
681 
682 
ieee80211_ioctl_giwretry(struct net_device * dev,struct iw_request_info * info,struct iw_param * retry,char * extra)683 static int ieee80211_ioctl_giwretry(struct net_device *dev,
684 				    struct iw_request_info *info,
685 				    struct iw_param *retry, char *extra)
686 {
687 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
688 
689 	retry->disabled = 0;
690 	if (retry->flags == 0 || retry->flags & IW_RETRY_MIN) {
691 		/* first return min value, iwconfig will ask max value
692 		 * later if needed */
693 		retry->flags |= IW_RETRY_LIMIT;
694 		retry->value = local->hw.conf.short_frame_max_tx_count;
695 		if (local->hw.conf.long_frame_max_tx_count !=
696 		    local->hw.conf.short_frame_max_tx_count)
697 			retry->flags |= IW_RETRY_MIN;
698 		return 0;
699 	}
700 	if (retry->flags & IW_RETRY_MAX) {
701 		retry->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
702 		retry->value = local->hw.conf.long_frame_max_tx_count;
703 	}
704 
705 	return 0;
706 }
707 
ieee80211_ioctl_siwmlme(struct net_device * dev,struct iw_request_info * info,struct iw_point * data,char * extra)708 static int ieee80211_ioctl_siwmlme(struct net_device *dev,
709 				   struct iw_request_info *info,
710 				   struct iw_point *data, char *extra)
711 {
712 	struct ieee80211_sub_if_data *sdata;
713 	struct iw_mlme *mlme = (struct iw_mlme *) extra;
714 
715 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
716 	if (sdata->vif.type != NL80211_IFTYPE_STATION &&
717 	    sdata->vif.type != NL80211_IFTYPE_ADHOC)
718 		return -EINVAL;
719 
720 	switch (mlme->cmd) {
721 	case IW_MLME_DEAUTH:
722 		/* TODO: mlme->addr.sa_data */
723 		return ieee80211_sta_deauthenticate(sdata, mlme->reason_code);
724 	case IW_MLME_DISASSOC:
725 		/* TODO: mlme->addr.sa_data */
726 		return ieee80211_sta_disassociate(sdata, mlme->reason_code);
727 	default:
728 		return -EOPNOTSUPP;
729 	}
730 }
731 
732 
ieee80211_ioctl_siwencode(struct net_device * dev,struct iw_request_info * info,struct iw_point * erq,char * keybuf)733 static int ieee80211_ioctl_siwencode(struct net_device *dev,
734 				     struct iw_request_info *info,
735 				     struct iw_point *erq, char *keybuf)
736 {
737 	struct ieee80211_sub_if_data *sdata;
738 	int idx, i, alg = ALG_WEP;
739 	u8 bcaddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
740 	int remove = 0;
741 
742 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
743 
744 	idx = erq->flags & IW_ENCODE_INDEX;
745 	if (idx == 0) {
746 		if (sdata->default_key)
747 			for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
748 				if (sdata->default_key == sdata->keys[i]) {
749 					idx = i;
750 					break;
751 				}
752 			}
753 	} else if (idx < 1 || idx > 4)
754 		return -EINVAL;
755 	else
756 		idx--;
757 
758 	if (erq->flags & IW_ENCODE_DISABLED)
759 		remove = 1;
760 	else if (erq->length == 0) {
761 		/* No key data - just set the default TX key index */
762 		ieee80211_set_default_key(sdata, idx);
763 		return 0;
764 	}
765 
766 	return ieee80211_set_encryption(
767 		sdata, bcaddr,
768 		idx, alg, remove,
769 		!sdata->default_key,
770 		keybuf, erq->length);
771 }
772 
773 
ieee80211_ioctl_giwencode(struct net_device * dev,struct iw_request_info * info,struct iw_point * erq,char * key)774 static int ieee80211_ioctl_giwencode(struct net_device *dev,
775 				     struct iw_request_info *info,
776 				     struct iw_point *erq, char *key)
777 {
778 	struct ieee80211_sub_if_data *sdata;
779 	int idx, i;
780 
781 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
782 
783 	idx = erq->flags & IW_ENCODE_INDEX;
784 	if (idx < 1 || idx > 4) {
785 		idx = -1;
786 		if (!sdata->default_key)
787 			idx = 0;
788 		else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
789 			if (sdata->default_key == sdata->keys[i]) {
790 				idx = i;
791 				break;
792 			}
793 		}
794 		if (idx < 0)
795 			return -EINVAL;
796 	} else
797 		idx--;
798 
799 	erq->flags = idx + 1;
800 
801 	if (!sdata->keys[idx]) {
802 		erq->length = 0;
803 		erq->flags |= IW_ENCODE_DISABLED;
804 		return 0;
805 	}
806 
807 	memcpy(key, sdata->keys[idx]->conf.key,
808 	       min_t(int, erq->length, sdata->keys[idx]->conf.keylen));
809 	erq->length = sdata->keys[idx]->conf.keylen;
810 	erq->flags |= IW_ENCODE_ENABLED;
811 
812 	if (sdata->vif.type == NL80211_IFTYPE_STATION) {
813 		struct ieee80211_if_sta *ifsta = &sdata->u.sta;
814 		switch (ifsta->auth_alg) {
815 		case WLAN_AUTH_OPEN:
816 		case WLAN_AUTH_LEAP:
817 			erq->flags |= IW_ENCODE_OPEN;
818 			break;
819 		case WLAN_AUTH_SHARED_KEY:
820 			erq->flags |= IW_ENCODE_RESTRICTED;
821 			break;
822 		}
823 	}
824 
825 	return 0;
826 }
827 
ieee80211_ioctl_siwpower(struct net_device * dev,struct iw_request_info * info,struct iw_param * wrq,char * extra)828 static int ieee80211_ioctl_siwpower(struct net_device *dev,
829 				    struct iw_request_info *info,
830 				    struct iw_param *wrq,
831 				    char *extra)
832 {
833 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
834 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
835 	struct ieee80211_conf *conf = &local->hw.conf;
836 	int ret = 0, timeout = 0;
837 	bool ps;
838 
839 	if (sdata->vif.type != NL80211_IFTYPE_STATION)
840 		return -EINVAL;
841 
842 	if (wrq->disabled) {
843 		ps = false;
844 		timeout = 0;
845 		goto set;
846 	}
847 
848 	switch (wrq->flags & IW_POWER_MODE) {
849 	case IW_POWER_ON:       /* If not specified */
850 	case IW_POWER_MODE:     /* If set all mask */
851 	case IW_POWER_ALL_R:    /* If explicitely state all */
852 		ps = true;
853 		break;
854 	default:                /* Otherwise we ignore */
855 		break;
856 	}
857 
858 	if (wrq->flags & IW_POWER_TIMEOUT)
859 		timeout = wrq->value / 1000;
860 
861 set:
862 	if (ps == local->powersave && timeout == local->dynamic_ps_timeout)
863 		return ret;
864 
865 	local->powersave = ps;
866 	local->dynamic_ps_timeout = timeout;
867 
868 	if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) {
869 		if (!(local->hw.flags & IEEE80211_HW_NO_STACK_DYNAMIC_PS) &&
870 		    local->dynamic_ps_timeout > 0)
871 			mod_timer(&local->dynamic_ps_timer, jiffies +
872 				  msecs_to_jiffies(local->dynamic_ps_timeout));
873 		else {
874 			if (local->powersave)
875 				conf->flags |= IEEE80211_CONF_PS;
876 			else
877 				conf->flags &= ~IEEE80211_CONF_PS;
878 		}
879 		ret = ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
880 	}
881 
882 	return ret;
883 }
884 
ieee80211_ioctl_giwpower(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)885 static int ieee80211_ioctl_giwpower(struct net_device *dev,
886 				    struct iw_request_info *info,
887 				    union iwreq_data *wrqu,
888 				    char *extra)
889 {
890 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
891 
892 	wrqu->power.disabled = !local->powersave;
893 
894 	return 0;
895 }
896 
ieee80211_ioctl_siwauth(struct net_device * dev,struct iw_request_info * info,struct iw_param * data,char * extra)897 static int ieee80211_ioctl_siwauth(struct net_device *dev,
898 				   struct iw_request_info *info,
899 				   struct iw_param *data, char *extra)
900 {
901 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
902 	int ret = 0;
903 
904 	switch (data->flags & IW_AUTH_INDEX) {
905 	case IW_AUTH_WPA_VERSION:
906 	case IW_AUTH_CIPHER_PAIRWISE:
907 	case IW_AUTH_CIPHER_GROUP:
908 	case IW_AUTH_WPA_ENABLED:
909 	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
910 	case IW_AUTH_KEY_MGMT:
911 		break;
912 	case IW_AUTH_DROP_UNENCRYPTED:
913 		sdata->drop_unencrypted = !!data->value;
914 		break;
915 	case IW_AUTH_PRIVACY_INVOKED:
916 		if (sdata->vif.type != NL80211_IFTYPE_STATION)
917 			ret = -EINVAL;
918 		else {
919 			sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED;
920 			/*
921 			 * Privacy invoked by wpa_supplicant, store the
922 			 * value and allow associating to a protected
923 			 * network without having a key up front.
924 			 */
925 			if (data->value)
926 				sdata->u.sta.flags |=
927 					IEEE80211_STA_PRIVACY_INVOKED;
928 		}
929 		break;
930 	case IW_AUTH_80211_AUTH_ALG:
931 		if (sdata->vif.type == NL80211_IFTYPE_STATION ||
932 		    sdata->vif.type == NL80211_IFTYPE_ADHOC)
933 			sdata->u.sta.auth_algs = data->value;
934 		else
935 			ret = -EOPNOTSUPP;
936 		break;
937 	default:
938 		ret = -EOPNOTSUPP;
939 		break;
940 	}
941 	return ret;
942 }
943 
944 /* Get wireless statistics.  Called by /proc/net/wireless and by SIOCGIWSTATS */
ieee80211_get_wireless_stats(struct net_device * dev)945 static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev)
946 {
947 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
948 	struct iw_statistics *wstats = &local->wstats;
949 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
950 	struct sta_info *sta = NULL;
951 
952 	rcu_read_lock();
953 
954 	if (sdata->vif.type == NL80211_IFTYPE_STATION ||
955 	    sdata->vif.type == NL80211_IFTYPE_ADHOC)
956 		sta = sta_info_get(local, sdata->u.sta.bssid);
957 	if (!sta) {
958 		wstats->discard.fragment = 0;
959 		wstats->discard.misc = 0;
960 		wstats->qual.qual = 0;
961 		wstats->qual.level = 0;
962 		wstats->qual.noise = 0;
963 		wstats->qual.updated = IW_QUAL_ALL_INVALID;
964 	} else {
965 		wstats->qual.level = sta->last_signal;
966 		wstats->qual.qual = sta->last_qual;
967 		wstats->qual.noise = sta->last_noise;
968 		wstats->qual.updated = local->wstats_flags;
969 	}
970 
971 	rcu_read_unlock();
972 
973 	return wstats;
974 }
975 
ieee80211_ioctl_giwauth(struct net_device * dev,struct iw_request_info * info,struct iw_param * data,char * extra)976 static int ieee80211_ioctl_giwauth(struct net_device *dev,
977 				   struct iw_request_info *info,
978 				   struct iw_param *data, char *extra)
979 {
980 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
981 	int ret = 0;
982 
983 	switch (data->flags & IW_AUTH_INDEX) {
984 	case IW_AUTH_80211_AUTH_ALG:
985 		if (sdata->vif.type == NL80211_IFTYPE_STATION ||
986 		    sdata->vif.type == NL80211_IFTYPE_ADHOC)
987 			data->value = sdata->u.sta.auth_algs;
988 		else
989 			ret = -EOPNOTSUPP;
990 		break;
991 	default:
992 		ret = -EOPNOTSUPP;
993 		break;
994 	}
995 	return ret;
996 }
997 
998 
ieee80211_ioctl_siwencodeext(struct net_device * dev,struct iw_request_info * info,struct iw_point * erq,char * extra)999 static int ieee80211_ioctl_siwencodeext(struct net_device *dev,
1000 					struct iw_request_info *info,
1001 					struct iw_point *erq, char *extra)
1002 {
1003 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1004 	struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
1005 	int uninitialized_var(alg), idx, i, remove = 0;
1006 
1007 	switch (ext->alg) {
1008 	case IW_ENCODE_ALG_NONE:
1009 		remove = 1;
1010 		break;
1011 	case IW_ENCODE_ALG_WEP:
1012 		alg = ALG_WEP;
1013 		break;
1014 	case IW_ENCODE_ALG_TKIP:
1015 		alg = ALG_TKIP;
1016 		break;
1017 	case IW_ENCODE_ALG_CCMP:
1018 		alg = ALG_CCMP;
1019 		break;
1020 	default:
1021 		return -EOPNOTSUPP;
1022 	}
1023 
1024 	if (erq->flags & IW_ENCODE_DISABLED)
1025 		remove = 1;
1026 
1027 	idx = erq->flags & IW_ENCODE_INDEX;
1028 	if (idx < 1 || idx > 4) {
1029 		idx = -1;
1030 		if (!sdata->default_key)
1031 			idx = 0;
1032 		else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
1033 			if (sdata->default_key == sdata->keys[i]) {
1034 				idx = i;
1035 				break;
1036 			}
1037 		}
1038 		if (idx < 0)
1039 			return -EINVAL;
1040 	} else
1041 		idx--;
1042 
1043 	return ieee80211_set_encryption(sdata, ext->addr.sa_data, idx, alg,
1044 					remove,
1045 					ext->ext_flags &
1046 					IW_ENCODE_EXT_SET_TX_KEY,
1047 					ext->key, ext->key_len);
1048 }
1049 
1050 
1051 /* Structures to export the Wireless Handlers */
1052 
1053 static const iw_handler ieee80211_handler[] =
1054 {
1055 	(iw_handler) NULL,				/* SIOCSIWCOMMIT */
1056 	(iw_handler) cfg80211_wext_giwname,		/* SIOCGIWNAME */
1057 	(iw_handler) NULL,				/* SIOCSIWNWID */
1058 	(iw_handler) NULL,				/* SIOCGIWNWID */
1059 	(iw_handler) ieee80211_ioctl_siwfreq,		/* SIOCSIWFREQ */
1060 	(iw_handler) ieee80211_ioctl_giwfreq,		/* SIOCGIWFREQ */
1061 	(iw_handler) cfg80211_wext_siwmode,		/* SIOCSIWMODE */
1062 	(iw_handler) cfg80211_wext_giwmode,		/* SIOCGIWMODE */
1063 	(iw_handler) NULL,				/* SIOCSIWSENS */
1064 	(iw_handler) NULL,				/* SIOCGIWSENS */
1065 	(iw_handler) NULL /* not used */,		/* SIOCSIWRANGE */
1066 	(iw_handler) ieee80211_ioctl_giwrange,		/* SIOCGIWRANGE */
1067 	(iw_handler) NULL /* not used */,		/* SIOCSIWPRIV */
1068 	(iw_handler) NULL /* kernel code */,		/* SIOCGIWPRIV */
1069 	(iw_handler) NULL /* not used */,		/* SIOCSIWSTATS */
1070 	(iw_handler) NULL /* kernel code */,		/* SIOCGIWSTATS */
1071 	(iw_handler) NULL,				/* SIOCSIWSPY */
1072 	(iw_handler) NULL,				/* SIOCGIWSPY */
1073 	(iw_handler) NULL,				/* SIOCSIWTHRSPY */
1074 	(iw_handler) NULL,				/* SIOCGIWTHRSPY */
1075 	(iw_handler) ieee80211_ioctl_siwap,		/* SIOCSIWAP */
1076 	(iw_handler) ieee80211_ioctl_giwap,		/* SIOCGIWAP */
1077 	(iw_handler) ieee80211_ioctl_siwmlme,		/* SIOCSIWMLME */
1078 	(iw_handler) NULL,				/* SIOCGIWAPLIST */
1079 	(iw_handler) ieee80211_ioctl_siwscan,		/* SIOCSIWSCAN */
1080 	(iw_handler) ieee80211_ioctl_giwscan,		/* SIOCGIWSCAN */
1081 	(iw_handler) ieee80211_ioctl_siwessid,		/* SIOCSIWESSID */
1082 	(iw_handler) ieee80211_ioctl_giwessid,		/* SIOCGIWESSID */
1083 	(iw_handler) NULL,				/* SIOCSIWNICKN */
1084 	(iw_handler) NULL,				/* SIOCGIWNICKN */
1085 	(iw_handler) NULL,				/* -- hole -- */
1086 	(iw_handler) NULL,				/* -- hole -- */
1087 	(iw_handler) ieee80211_ioctl_siwrate,		/* SIOCSIWRATE */
1088 	(iw_handler) ieee80211_ioctl_giwrate,		/* SIOCGIWRATE */
1089 	(iw_handler) ieee80211_ioctl_siwrts,		/* SIOCSIWRTS */
1090 	(iw_handler) ieee80211_ioctl_giwrts,		/* SIOCGIWRTS */
1091 	(iw_handler) ieee80211_ioctl_siwfrag,		/* SIOCSIWFRAG */
1092 	(iw_handler) ieee80211_ioctl_giwfrag,		/* SIOCGIWFRAG */
1093 	(iw_handler) ieee80211_ioctl_siwtxpower,	/* SIOCSIWTXPOW */
1094 	(iw_handler) ieee80211_ioctl_giwtxpower,	/* SIOCGIWTXPOW */
1095 	(iw_handler) ieee80211_ioctl_siwretry,		/* SIOCSIWRETRY */
1096 	(iw_handler) ieee80211_ioctl_giwretry,		/* SIOCGIWRETRY */
1097 	(iw_handler) ieee80211_ioctl_siwencode,		/* SIOCSIWENCODE */
1098 	(iw_handler) ieee80211_ioctl_giwencode,		/* SIOCGIWENCODE */
1099 	(iw_handler) ieee80211_ioctl_siwpower,		/* SIOCSIWPOWER */
1100 	(iw_handler) ieee80211_ioctl_giwpower,		/* SIOCGIWPOWER */
1101 	(iw_handler) NULL,				/* -- hole -- */
1102 	(iw_handler) NULL,				/* -- hole -- */
1103 	(iw_handler) ieee80211_ioctl_siwgenie,		/* SIOCSIWGENIE */
1104 	(iw_handler) NULL,				/* SIOCGIWGENIE */
1105 	(iw_handler) ieee80211_ioctl_siwauth,		/* SIOCSIWAUTH */
1106 	(iw_handler) ieee80211_ioctl_giwauth,		/* SIOCGIWAUTH */
1107 	(iw_handler) ieee80211_ioctl_siwencodeext,	/* SIOCSIWENCODEEXT */
1108 	(iw_handler) NULL,				/* SIOCGIWENCODEEXT */
1109 	(iw_handler) NULL,				/* SIOCSIWPMKSA */
1110 	(iw_handler) NULL,				/* -- hole -- */
1111 };
1112 
1113 const struct iw_handler_def ieee80211_iw_handler_def =
1114 {
1115 	.num_standard	= ARRAY_SIZE(ieee80211_handler),
1116 	.standard	= (iw_handler *) ieee80211_handler,
1117 	.get_wireless_stats = ieee80211_get_wireless_stats,
1118 };
1119