]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - net/mac80211/ieee80211_ioctl.c
[MAC80211]: fix race conditions with keys
[linux-2.6-omap-h63xx.git] / net / mac80211 / ieee80211_ioctl.c
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 "hostapd_ioctl.h"
25 #include "ieee80211_rate.h"
26 #include "wpa.h"
27 #include "aes_ccm.h"
28
29 static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr,
30                                     int idx, int alg, int set_tx_key,
31                                     const u8 *_key, size_t key_len)
32 {
33         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
34         int ret = 0;
35         struct sta_info *sta;
36         struct ieee80211_key *key;
37         struct ieee80211_sub_if_data *sdata;
38
39         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
40
41         if (is_broadcast_ether_addr(sta_addr)) {
42                 sta = NULL;
43                 if (idx >= NUM_DEFAULT_KEYS) {
44                         printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n",
45                                dev->name, idx);
46                         return -EINVAL;
47                 }
48                 key = sdata->keys[idx];
49         } else {
50                 set_tx_key = 0;
51                 if (idx != 0) {
52                         printk(KERN_DEBUG "%s: set_encrypt - non-zero idx for "
53                                "individual key\n", dev->name);
54                         return -EINVAL;
55                 }
56
57                 sta = sta_info_get(local, sta_addr);
58                 if (!sta) {
59 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
60                         printk(KERN_DEBUG "%s: set_encrypt - unknown addr "
61                                MAC_FMT "\n",
62                                dev->name, MAC_ARG(sta_addr));
63 #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
64
65                         return -ENOENT;
66                 }
67
68                 key = sta->key;
69         }
70
71         if (alg == ALG_NONE) {
72                 ieee80211_key_free(key);
73                 key = NULL;
74         } else {
75                 /*
76                  * Automatically frees any old key if present.
77                  */
78                 key = ieee80211_key_alloc(sdata, sta, alg, idx, key_len, _key);
79                 if (!key) {
80                         ret = -ENOMEM;
81                         goto err_out;
82                 }
83         }
84
85         if (set_tx_key || (!sta && !sdata->default_key && key))
86                 ieee80211_set_default_key(sdata, idx);
87
88         ret = 0;
89  err_out:
90         if (sta)
91                 sta_info_put(sta);
92         return ret;
93 }
94
95 static int ieee80211_ioctl_siwgenie(struct net_device *dev,
96                                     struct iw_request_info *info,
97                                     struct iw_point *data, char *extra)
98 {
99         struct ieee80211_sub_if_data *sdata;
100         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
101
102         if (local->user_space_mlme)
103                 return -EOPNOTSUPP;
104
105         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
106         if (sdata->type == IEEE80211_IF_TYPE_STA ||
107             sdata->type == IEEE80211_IF_TYPE_IBSS) {
108                 int ret = ieee80211_sta_set_extra_ie(dev, extra, data->length);
109                 if (ret)
110                         return ret;
111                 sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
112                 ieee80211_sta_req_auth(dev, &sdata->u.sta);
113                 return 0;
114         }
115
116         if (sdata->type == IEEE80211_IF_TYPE_AP) {
117                 kfree(sdata->u.ap.generic_elem);
118                 sdata->u.ap.generic_elem = kmalloc(data->length, GFP_KERNEL);
119                 if (!sdata->u.ap.generic_elem)
120                         return -ENOMEM;
121                 memcpy(sdata->u.ap.generic_elem, extra, data->length);
122                 sdata->u.ap.generic_elem_len = data->length;
123                 return ieee80211_if_config(dev);
124         }
125         return -EOPNOTSUPP;
126 }
127
128 static int ieee80211_ioctl_giwname(struct net_device *dev,
129                                    struct iw_request_info *info,
130                                    char *name, char *extra)
131 {
132         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
133
134         switch (local->hw.conf.phymode) {
135         case MODE_IEEE80211A:
136                 strcpy(name, "IEEE 802.11a");
137                 break;
138         case MODE_IEEE80211B:
139                 strcpy(name, "IEEE 802.11b");
140                 break;
141         case MODE_IEEE80211G:
142                 strcpy(name, "IEEE 802.11g");
143                 break;
144         case MODE_ATHEROS_TURBO:
145                 strcpy(name, "5GHz Turbo");
146                 break;
147         default:
148                 strcpy(name, "IEEE 802.11");
149                 break;
150         }
151
152         return 0;
153 }
154
155
156 static int ieee80211_ioctl_giwrange(struct net_device *dev,
157                                  struct iw_request_info *info,
158                                  struct iw_point *data, char *extra)
159 {
160         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
161         struct iw_range *range = (struct iw_range *) extra;
162         struct ieee80211_hw_mode *mode = NULL;
163         int c = 0;
164
165         data->length = sizeof(struct iw_range);
166         memset(range, 0, sizeof(struct iw_range));
167
168         range->we_version_compiled = WIRELESS_EXT;
169         range->we_version_source = 21;
170         range->retry_capa = IW_RETRY_LIMIT;
171         range->retry_flags = IW_RETRY_LIMIT;
172         range->min_retry = 0;
173         range->max_retry = 255;
174         range->min_rts = 0;
175         range->max_rts = 2347;
176         range->min_frag = 256;
177         range->max_frag = 2346;
178
179         range->encoding_size[0] = 5;
180         range->encoding_size[1] = 13;
181         range->num_encoding_sizes = 2;
182         range->max_encoding_tokens = NUM_DEFAULT_KEYS;
183
184         range->max_qual.qual = local->hw.max_signal;
185         range->max_qual.level = local->hw.max_rssi;
186         range->max_qual.noise = local->hw.max_noise;
187         range->max_qual.updated = local->wstats_flags;
188
189         range->avg_qual.qual = local->hw.max_signal/2;
190         range->avg_qual.level = 0;
191         range->avg_qual.noise = 0;
192         range->avg_qual.updated = local->wstats_flags;
193
194         range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
195                           IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
196
197         list_for_each_entry(mode, &local->modes_list, list) {
198                 int i = 0;
199
200                 if (!(local->enabled_modes & (1 << mode->mode)) ||
201                     (local->hw_modes & local->enabled_modes &
202                      (1 << MODE_IEEE80211G) && mode->mode == MODE_IEEE80211B))
203                         continue;
204
205                 while (i < mode->num_channels && c < IW_MAX_FREQUENCIES) {
206                         struct ieee80211_channel *chan = &mode->channels[i];
207
208                         if (chan->flag & IEEE80211_CHAN_W_SCAN) {
209                                 range->freq[c].i = chan->chan;
210                                 range->freq[c].m = chan->freq * 100000;
211                                 range->freq[c].e = 1;
212                                 c++;
213                         }
214                         i++;
215                 }
216         }
217         range->num_channels = c;
218         range->num_frequency = c;
219
220         IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
221         IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY);
222         IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
223         IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
224
225         return 0;
226 }
227
228
229 static int ieee80211_ioctl_siwmode(struct net_device *dev,
230                                    struct iw_request_info *info,
231                                    __u32 *mode, char *extra)
232 {
233         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
234         int type;
235
236         if (sdata->type == IEEE80211_IF_TYPE_VLAN)
237                 return -EOPNOTSUPP;
238
239         switch (*mode) {
240         case IW_MODE_INFRA:
241                 type = IEEE80211_IF_TYPE_STA;
242                 break;
243         case IW_MODE_ADHOC:
244                 type = IEEE80211_IF_TYPE_IBSS;
245                 break;
246         case IW_MODE_MONITOR:
247                 type = IEEE80211_IF_TYPE_MNTR;
248                 break;
249         default:
250                 return -EINVAL;
251         }
252
253         if (type == sdata->type)
254                 return 0;
255         if (netif_running(dev))
256                 return -EBUSY;
257
258         ieee80211_if_reinit(dev);
259         ieee80211_if_set_type(dev, type);
260
261         return 0;
262 }
263
264
265 static int ieee80211_ioctl_giwmode(struct net_device *dev,
266                                    struct iw_request_info *info,
267                                    __u32 *mode, char *extra)
268 {
269         struct ieee80211_sub_if_data *sdata;
270
271         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
272         switch (sdata->type) {
273         case IEEE80211_IF_TYPE_AP:
274                 *mode = IW_MODE_MASTER;
275                 break;
276         case IEEE80211_IF_TYPE_STA:
277                 *mode = IW_MODE_INFRA;
278                 break;
279         case IEEE80211_IF_TYPE_IBSS:
280                 *mode = IW_MODE_ADHOC;
281                 break;
282         case IEEE80211_IF_TYPE_MNTR:
283                 *mode = IW_MODE_MONITOR;
284                 break;
285         case IEEE80211_IF_TYPE_WDS:
286                 *mode = IW_MODE_REPEAT;
287                 break;
288         case IEEE80211_IF_TYPE_VLAN:
289                 *mode = IW_MODE_SECOND;         /* FIXME */
290                 break;
291         default:
292                 *mode = IW_MODE_AUTO;
293                 break;
294         }
295         return 0;
296 }
297
298 int ieee80211_set_channel(struct ieee80211_local *local, int channel, int freq)
299 {
300         struct ieee80211_hw_mode *mode;
301         int c, set = 0;
302         int ret = -EINVAL;
303
304         list_for_each_entry(mode, &local->modes_list, list) {
305                 if (!(local->enabled_modes & (1 << mode->mode)))
306                         continue;
307                 for (c = 0; c < mode->num_channels; c++) {
308                         struct ieee80211_channel *chan = &mode->channels[c];
309                         if (chan->flag & IEEE80211_CHAN_W_SCAN &&
310                             ((chan->chan == channel) || (chan->freq == freq))) {
311                                 /* Use next_mode as the mode preference to
312                                  * resolve non-unique channel numbers. */
313                                 if (set && mode->mode != local->next_mode)
314                                         continue;
315
316                                 local->oper_channel = chan;
317                                 local->oper_hw_mode = mode;
318                                 set++;
319                         }
320                 }
321         }
322
323         if (set) {
324                 if (local->sta_scanning)
325                         ret = 0;
326                 else
327                         ret = ieee80211_hw_config(local);
328
329                 rate_control_clear(local);
330         }
331
332         return ret;
333 }
334
335 static int ieee80211_ioctl_siwfreq(struct net_device *dev,
336                                    struct iw_request_info *info,
337                                    struct iw_freq *freq, char *extra)
338 {
339         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
340         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
341
342         if (sdata->type == IEEE80211_IF_TYPE_STA)
343                 sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_CHANNEL_SEL;
344
345         /* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */
346         if (freq->e == 0) {
347                 if (freq->m < 0) {
348                         if (sdata->type == IEEE80211_IF_TYPE_STA)
349                                 sdata->u.sta.flags |=
350                                         IEEE80211_STA_AUTO_CHANNEL_SEL;
351                         return 0;
352                 } else
353                         return ieee80211_set_channel(local, freq->m, -1);
354         } else {
355                 int i, div = 1000000;
356                 for (i = 0; i < freq->e; i++)
357                         div /= 10;
358                 if (div > 0)
359                         return ieee80211_set_channel(local, -1, freq->m / div);
360                 else
361                         return -EINVAL;
362         }
363 }
364
365
366 static int ieee80211_ioctl_giwfreq(struct net_device *dev,
367                                    struct iw_request_info *info,
368                                    struct iw_freq *freq, char *extra)
369 {
370         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
371
372         /* TODO: in station mode (Managed/Ad-hoc) might need to poll low-level
373          * driver for the current channel with firmware-based management */
374
375         freq->m = local->hw.conf.freq;
376         freq->e = 6;
377
378         return 0;
379 }
380
381
382 static int ieee80211_ioctl_siwessid(struct net_device *dev,
383                                     struct iw_request_info *info,
384                                     struct iw_point *data, char *ssid)
385 {
386         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
387         struct ieee80211_sub_if_data *sdata;
388         size_t len = data->length;
389
390         /* iwconfig uses nul termination in SSID.. */
391         if (len > 0 && ssid[len - 1] == '\0')
392                 len--;
393
394         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
395         if (sdata->type == IEEE80211_IF_TYPE_STA ||
396             sdata->type == IEEE80211_IF_TYPE_IBSS) {
397                 int ret;
398                 if (local->user_space_mlme) {
399                         if (len > IEEE80211_MAX_SSID_LEN)
400                                 return -EINVAL;
401                         memcpy(sdata->u.sta.ssid, ssid, len);
402                         sdata->u.sta.ssid_len = len;
403                         return 0;
404                 }
405                 if (data->flags)
406                         sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_SSID_SEL;
407                 else
408                         sdata->u.sta.flags |= IEEE80211_STA_AUTO_SSID_SEL;
409                 ret = ieee80211_sta_set_ssid(dev, ssid, len);
410                 if (ret)
411                         return ret;
412                 ieee80211_sta_req_auth(dev, &sdata->u.sta);
413                 return 0;
414         }
415
416         if (sdata->type == IEEE80211_IF_TYPE_AP) {
417                 memcpy(sdata->u.ap.ssid, ssid, len);
418                 memset(sdata->u.ap.ssid + len, 0,
419                        IEEE80211_MAX_SSID_LEN - len);
420                 sdata->u.ap.ssid_len = len;
421                 return ieee80211_if_config(dev);
422         }
423         return -EOPNOTSUPP;
424 }
425
426
427 static int ieee80211_ioctl_giwessid(struct net_device *dev,
428                                     struct iw_request_info *info,
429                                     struct iw_point *data, char *ssid)
430 {
431         size_t len;
432
433         struct ieee80211_sub_if_data *sdata;
434         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
435         if (sdata->type == IEEE80211_IF_TYPE_STA ||
436             sdata->type == IEEE80211_IF_TYPE_IBSS) {
437                 int res = ieee80211_sta_get_ssid(dev, ssid, &len);
438                 if (res == 0) {
439                         data->length = len;
440                         data->flags = 1;
441                 } else
442                         data->flags = 0;
443                 return res;
444         }
445
446         if (sdata->type == IEEE80211_IF_TYPE_AP) {
447                 len = sdata->u.ap.ssid_len;
448                 if (len > IW_ESSID_MAX_SIZE)
449                         len = IW_ESSID_MAX_SIZE;
450                 memcpy(ssid, sdata->u.ap.ssid, len);
451                 data->length = len;
452                 data->flags = 1;
453                 return 0;
454         }
455         return -EOPNOTSUPP;
456 }
457
458
459 static int ieee80211_ioctl_siwap(struct net_device *dev,
460                                  struct iw_request_info *info,
461                                  struct sockaddr *ap_addr, char *extra)
462 {
463         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
464         struct ieee80211_sub_if_data *sdata;
465
466         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
467         if (sdata->type == IEEE80211_IF_TYPE_STA ||
468             sdata->type == IEEE80211_IF_TYPE_IBSS) {
469                 int ret;
470                 if (local->user_space_mlme) {
471                         memcpy(sdata->u.sta.bssid, (u8 *) &ap_addr->sa_data,
472                                ETH_ALEN);
473                         return 0;
474                 }
475                 if (is_zero_ether_addr((u8 *) &ap_addr->sa_data))
476                         sdata->u.sta.flags |= IEEE80211_STA_AUTO_BSSID_SEL |
477                                 IEEE80211_STA_AUTO_CHANNEL_SEL;
478                 else if (is_broadcast_ether_addr((u8 *) &ap_addr->sa_data))
479                         sdata->u.sta.flags |= IEEE80211_STA_AUTO_BSSID_SEL;
480                 else
481                         sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
482                 ret = ieee80211_sta_set_bssid(dev, (u8 *) &ap_addr->sa_data);
483                 if (ret)
484                         return ret;
485                 ieee80211_sta_req_auth(dev, &sdata->u.sta);
486                 return 0;
487         } else if (sdata->type == IEEE80211_IF_TYPE_WDS) {
488                 if (memcmp(sdata->u.wds.remote_addr, (u8 *) &ap_addr->sa_data,
489                            ETH_ALEN) == 0)
490                         return 0;
491                 return ieee80211_if_update_wds(dev, (u8 *) &ap_addr->sa_data);
492         }
493
494         return -EOPNOTSUPP;
495 }
496
497
498 static int ieee80211_ioctl_giwap(struct net_device *dev,
499                                  struct iw_request_info *info,
500                                  struct sockaddr *ap_addr, char *extra)
501 {
502         struct ieee80211_sub_if_data *sdata;
503
504         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
505         if (sdata->type == IEEE80211_IF_TYPE_STA ||
506             sdata->type == IEEE80211_IF_TYPE_IBSS) {
507                 ap_addr->sa_family = ARPHRD_ETHER;
508                 memcpy(&ap_addr->sa_data, sdata->u.sta.bssid, ETH_ALEN);
509                 return 0;
510         } else if (sdata->type == IEEE80211_IF_TYPE_WDS) {
511                 ap_addr->sa_family = ARPHRD_ETHER;
512                 memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN);
513                 return 0;
514         }
515
516         return -EOPNOTSUPP;
517 }
518
519
520 static int ieee80211_ioctl_siwscan(struct net_device *dev,
521                                    struct iw_request_info *info,
522                                    struct iw_point *data, char *extra)
523 {
524         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
525         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
526         u8 *ssid = NULL;
527         size_t ssid_len = 0;
528
529         if (!netif_running(dev))
530                 return -ENETDOWN;
531
532         switch (sdata->type) {
533         case IEEE80211_IF_TYPE_STA:
534         case IEEE80211_IF_TYPE_IBSS:
535                 if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID) {
536                         ssid = sdata->u.sta.ssid;
537                         ssid_len = sdata->u.sta.ssid_len;
538                 }
539                 break;
540         case IEEE80211_IF_TYPE_AP:
541                 if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID) {
542                         ssid = sdata->u.ap.ssid;
543                         ssid_len = sdata->u.ap.ssid_len;
544                 }
545                 break;
546         default:
547                 return -EOPNOTSUPP;
548         }
549
550         return ieee80211_sta_req_scan(dev, ssid, ssid_len);
551 }
552
553
554 static int ieee80211_ioctl_giwscan(struct net_device *dev,
555                                    struct iw_request_info *info,
556                                    struct iw_point *data, char *extra)
557 {
558         int res;
559         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
560         if (local->sta_scanning)
561                 return -EAGAIN;
562         res = ieee80211_sta_scan_results(dev, extra, data->length);
563         if (res >= 0) {
564                 data->length = res;
565                 return 0;
566         }
567         data->length = 0;
568         return res;
569 }
570
571
572 static int ieee80211_ioctl_siwrate(struct net_device *dev,
573                                   struct iw_request_info *info,
574                                   struct iw_param *rate, char *extra)
575 {
576         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
577         struct ieee80211_hw_mode *mode;
578         int i;
579         u32 target_rate = rate->value / 100000;
580         struct ieee80211_sub_if_data *sdata;
581
582         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
583         if (!sdata->bss)
584                 return -ENODEV;
585         mode = local->oper_hw_mode;
586         /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates
587          * target_rate = X, rate->fixed = 1 means only rate X
588          * target_rate = X, rate->fixed = 0 means all rates <= X */
589         sdata->bss->max_ratectrl_rateidx = -1;
590         sdata->bss->force_unicast_rateidx = -1;
591         if (rate->value < 0)
592                 return 0;
593         for (i=0; i< mode->num_rates; i++) {
594                 struct ieee80211_rate *rates = &mode->rates[i];
595                 int this_rate = rates->rate;
596
597                 if (mode->mode == MODE_ATHEROS_TURBO ||
598                     mode->mode == MODE_ATHEROS_TURBOG)
599                         this_rate *= 2;
600                 if (target_rate == this_rate) {
601                         sdata->bss->max_ratectrl_rateidx = i;
602                         if (rate->fixed)
603                                 sdata->bss->force_unicast_rateidx = i;
604                         break;
605                 }
606         }
607         return 0;
608 }
609
610 static int ieee80211_ioctl_giwrate(struct net_device *dev,
611                                   struct iw_request_info *info,
612                                   struct iw_param *rate, char *extra)
613 {
614         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
615         struct sta_info *sta;
616         struct ieee80211_sub_if_data *sdata;
617
618         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
619         if (sdata->type == IEEE80211_IF_TYPE_STA)
620                 sta = sta_info_get(local, sdata->u.sta.bssid);
621         else
622                 return -EOPNOTSUPP;
623         if (!sta)
624                 return -ENODEV;
625         if (sta->txrate < local->oper_hw_mode->num_rates)
626                 rate->value = local->oper_hw_mode->rates[sta->txrate].rate * 100000;
627         else
628                 rate->value = 0;
629         sta_info_put(sta);
630         return 0;
631 }
632
633 static int ieee80211_ioctl_giwtxpower(struct net_device *dev,
634                                    struct iw_request_info *info,
635                                    union iwreq_data *data, char *extra)
636 {
637         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
638
639         data->txpower.fixed = 1;
640         data->txpower.disabled = !(local->hw.conf.radio_enabled);
641         data->txpower.value = local->hw.conf.power_level;
642         data->txpower.flags = IW_TXPOW_DBM;
643
644         return 0;
645 }
646
647 static int ieee80211_ioctl_siwrts(struct net_device *dev,
648                                   struct iw_request_info *info,
649                                   struct iw_param *rts, char *extra)
650 {
651         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
652
653         if (rts->disabled)
654                 local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
655         else if (rts->value < 0 || rts->value > IEEE80211_MAX_RTS_THRESHOLD)
656                 return -EINVAL;
657         else
658                 local->rts_threshold = rts->value;
659
660         /* If the wlan card performs RTS/CTS in hardware/firmware,
661          * configure it here */
662
663         if (local->ops->set_rts_threshold)
664                 local->ops->set_rts_threshold(local_to_hw(local),
665                                              local->rts_threshold);
666
667         return 0;
668 }
669
670 static int ieee80211_ioctl_giwrts(struct net_device *dev,
671                                   struct iw_request_info *info,
672                                   struct iw_param *rts, char *extra)
673 {
674         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
675
676         rts->value = local->rts_threshold;
677         rts->disabled = (rts->value >= IEEE80211_MAX_RTS_THRESHOLD);
678         rts->fixed = 1;
679
680         return 0;
681 }
682
683
684 static int ieee80211_ioctl_siwfrag(struct net_device *dev,
685                                    struct iw_request_info *info,
686                                    struct iw_param *frag, char *extra)
687 {
688         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
689
690         if (frag->disabled)
691                 local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
692         else if (frag->value < 256 ||
693                  frag->value > IEEE80211_MAX_FRAG_THRESHOLD)
694                 return -EINVAL;
695         else {
696                 /* Fragment length must be even, so strip LSB. */
697                 local->fragmentation_threshold = frag->value & ~0x1;
698         }
699
700         /* If the wlan card performs fragmentation in hardware/firmware,
701          * configure it here */
702
703         if (local->ops->set_frag_threshold)
704                 local->ops->set_frag_threshold(
705                         local_to_hw(local),
706                         local->fragmentation_threshold);
707
708         return 0;
709 }
710
711 static int ieee80211_ioctl_giwfrag(struct net_device *dev,
712                                    struct iw_request_info *info,
713                                    struct iw_param *frag, char *extra)
714 {
715         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
716
717         frag->value = local->fragmentation_threshold;
718         frag->disabled = (frag->value >= IEEE80211_MAX_RTS_THRESHOLD);
719         frag->fixed = 1;
720
721         return 0;
722 }
723
724
725 static int ieee80211_ioctl_siwretry(struct net_device *dev,
726                                     struct iw_request_info *info,
727                                     struct iw_param *retry, char *extra)
728 {
729         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
730
731         if (retry->disabled ||
732             (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
733                 return -EINVAL;
734
735         if (retry->flags & IW_RETRY_MAX)
736                 local->long_retry_limit = retry->value;
737         else if (retry->flags & IW_RETRY_MIN)
738                 local->short_retry_limit = retry->value;
739         else {
740                 local->long_retry_limit = retry->value;
741                 local->short_retry_limit = retry->value;
742         }
743
744         if (local->ops->set_retry_limit) {
745                 return local->ops->set_retry_limit(
746                         local_to_hw(local),
747                         local->short_retry_limit,
748                         local->long_retry_limit);
749         }
750
751         return 0;
752 }
753
754
755 static int ieee80211_ioctl_giwretry(struct net_device *dev,
756                                     struct iw_request_info *info,
757                                     struct iw_param *retry, char *extra)
758 {
759         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
760
761         retry->disabled = 0;
762         if (retry->flags == 0 || retry->flags & IW_RETRY_MIN) {
763                 /* first return min value, iwconfig will ask max value
764                  * later if needed */
765                 retry->flags |= IW_RETRY_LIMIT;
766                 retry->value = local->short_retry_limit;
767                 if (local->long_retry_limit != local->short_retry_limit)
768                         retry->flags |= IW_RETRY_MIN;
769                 return 0;
770         }
771         if (retry->flags & IW_RETRY_MAX) {
772                 retry->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
773                 retry->value = local->long_retry_limit;
774         }
775
776         return 0;
777 }
778
779 static int ieee80211_ioctl_prism2_param(struct net_device *dev,
780                                         struct iw_request_info *info,
781                                         void *wrqu, char *extra)
782 {
783         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
784         struct ieee80211_sub_if_data *sdata;
785         int *i = (int *) extra;
786         int param = *i;
787         int value = *(i + 1);
788         int ret = 0;
789
790         if (!capable(CAP_NET_ADMIN))
791                 return -EPERM;
792
793         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
794
795         switch (param) {
796         case PRISM2_PARAM_IEEE_802_1X:
797                 if (local->ops->set_ieee8021x)
798                         ret = local->ops->set_ieee8021x(local_to_hw(local),
799                                                         value);
800                 if (ret)
801                         printk(KERN_DEBUG "%s: failed to set IEEE 802.1X (%d) "
802                                "for low-level driver\n", dev->name, value);
803                 else
804                         sdata->ieee802_1x = value;
805                 break;
806
807         case PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES:
808                 if (sdata->type == IEEE80211_IF_TYPE_AP) {
809                         if (value)
810                                 sdata->flags |= IEEE80211_SDATA_USE_PROTECTION;
811                         else
812                                 sdata->flags &= ~IEEE80211_SDATA_USE_PROTECTION;
813                         ieee80211_erp_info_change_notify(dev,
814                                         IEEE80211_ERP_CHANGE_PROTECTION);
815                 } else {
816                         ret = -ENOENT;
817                 }
818                 break;
819
820         case PRISM2_PARAM_PREAMBLE:
821                 if (sdata->type == IEEE80211_IF_TYPE_AP) {
822                         if (value)
823                                 sdata->flags |= IEEE80211_SDATA_SHORT_PREAMBLE;
824                         else
825                                 sdata->flags &= ~IEEE80211_SDATA_SHORT_PREAMBLE;
826                         ieee80211_erp_info_change_notify(dev,
827                                         IEEE80211_ERP_CHANGE_PREAMBLE);
828                 } else {
829                         ret = -ENOENT;
830                 }
831                 break;
832
833         case PRISM2_PARAM_SHORT_SLOT_TIME:
834                 if (value)
835                         local->hw.conf.flags |= IEEE80211_CONF_SHORT_SLOT_TIME;
836                 else
837                         local->hw.conf.flags &= ~IEEE80211_CONF_SHORT_SLOT_TIME;
838                 if (ieee80211_hw_config(local))
839                         ret = -EINVAL;
840                 break;
841
842         case PRISM2_PARAM_NEXT_MODE:
843                 local->next_mode = value;
844                 break;
845
846         case PRISM2_PARAM_KEY_TX_RX_THRESHOLD:
847                 local->key_tx_rx_threshold = value;
848                 break;
849
850         case PRISM2_PARAM_WIFI_WME_NOACK_TEST:
851                 local->wifi_wme_noack_test = value;
852                 break;
853
854         case PRISM2_PARAM_SCAN_FLAGS:
855                 local->scan_flags = value;
856                 break;
857
858         case PRISM2_PARAM_MIXED_CELL:
859                 if (sdata->type != IEEE80211_IF_TYPE_STA &&
860                     sdata->type != IEEE80211_IF_TYPE_IBSS)
861                         ret = -EINVAL;
862                 else {
863                         if (value)
864                                 sdata->u.sta.flags |= IEEE80211_STA_MIXED_CELL;
865                         else
866                                 sdata->u.sta.flags &= ~IEEE80211_STA_MIXED_CELL;
867                 }
868                 break;
869
870         case PRISM2_PARAM_HW_MODES:
871                 local->enabled_modes = value;
872                 break;
873
874         case PRISM2_PARAM_CREATE_IBSS:
875                 if (sdata->type != IEEE80211_IF_TYPE_IBSS)
876                         ret = -EINVAL;
877                 else {
878                         if (value)
879                                 sdata->u.sta.flags |= IEEE80211_STA_CREATE_IBSS;
880                         else
881                                 sdata->u.sta.flags &= ~IEEE80211_STA_CREATE_IBSS;
882                 }
883                 break;
884         case PRISM2_PARAM_WMM_ENABLED:
885                 if (sdata->type != IEEE80211_IF_TYPE_STA &&
886                     sdata->type != IEEE80211_IF_TYPE_IBSS)
887                         ret = -EINVAL;
888                 else {
889                         if (value)
890                                 sdata->u.sta.flags |= IEEE80211_STA_WMM_ENABLED;
891                         else
892                                 sdata->u.sta.flags &= ~IEEE80211_STA_WMM_ENABLED;
893                 }
894                 break;
895         default:
896                 ret = -EOPNOTSUPP;
897                 break;
898         }
899
900         return ret;
901 }
902
903
904 static int ieee80211_ioctl_get_prism2_param(struct net_device *dev,
905                                             struct iw_request_info *info,
906                                             void *wrqu, char *extra)
907 {
908         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
909         struct ieee80211_sub_if_data *sdata;
910         int *param = (int *) extra;
911         int ret = 0;
912
913         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
914
915         switch (*param) {
916         case PRISM2_PARAM_IEEE_802_1X:
917                 *param = sdata->ieee802_1x;
918                 break;
919
920         case PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES:
921                 *param = !!(sdata->flags & IEEE80211_SDATA_USE_PROTECTION);
922                 break;
923
924         case PRISM2_PARAM_PREAMBLE:
925                 *param = !!(sdata->flags & IEEE80211_SDATA_SHORT_PREAMBLE);
926                 break;
927
928         case PRISM2_PARAM_SHORT_SLOT_TIME:
929                 *param = !!(local->hw.conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME);
930                 break;
931
932         case PRISM2_PARAM_NEXT_MODE:
933                 *param = local->next_mode;
934                 break;
935
936         case PRISM2_PARAM_KEY_TX_RX_THRESHOLD:
937                 *param = local->key_tx_rx_threshold;
938                 break;
939
940         case PRISM2_PARAM_WIFI_WME_NOACK_TEST:
941                 *param = local->wifi_wme_noack_test;
942                 break;
943
944         case PRISM2_PARAM_SCAN_FLAGS:
945                 *param = local->scan_flags;
946                 break;
947
948         case PRISM2_PARAM_HW_MODES:
949                 *param = local->enabled_modes;
950                 break;
951
952         case PRISM2_PARAM_CREATE_IBSS:
953                 if (sdata->type != IEEE80211_IF_TYPE_IBSS)
954                         ret = -EINVAL;
955                 else
956                         *param = !!(sdata->u.sta.flags &
957                                         IEEE80211_STA_CREATE_IBSS);
958                 break;
959
960         case PRISM2_PARAM_MIXED_CELL:
961                 if (sdata->type != IEEE80211_IF_TYPE_STA &&
962                     sdata->type != IEEE80211_IF_TYPE_IBSS)
963                         ret = -EINVAL;
964                 else
965                         *param = !!(sdata->u.sta.flags &
966                                         IEEE80211_STA_MIXED_CELL);
967                 break;
968
969         case PRISM2_PARAM_WMM_ENABLED:
970                 if (sdata->type != IEEE80211_IF_TYPE_STA &&
971                     sdata->type != IEEE80211_IF_TYPE_IBSS)
972                         ret = -EINVAL;
973                 else
974                         *param = !!(sdata->u.sta.flags &
975                                         IEEE80211_STA_WMM_ENABLED);
976                 break;
977         default:
978                 ret = -EOPNOTSUPP;
979                 break;
980         }
981
982         return ret;
983 }
984
985 static int ieee80211_ioctl_siwmlme(struct net_device *dev,
986                                    struct iw_request_info *info,
987                                    struct iw_point *data, char *extra)
988 {
989         struct ieee80211_sub_if_data *sdata;
990         struct iw_mlme *mlme = (struct iw_mlme *) extra;
991
992         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
993         if (sdata->type != IEEE80211_IF_TYPE_STA &&
994             sdata->type != IEEE80211_IF_TYPE_IBSS)
995                 return -EINVAL;
996
997         switch (mlme->cmd) {
998         case IW_MLME_DEAUTH:
999                 /* TODO: mlme->addr.sa_data */
1000                 return ieee80211_sta_deauthenticate(dev, mlme->reason_code);
1001         case IW_MLME_DISASSOC:
1002                 /* TODO: mlme->addr.sa_data */
1003                 return ieee80211_sta_disassociate(dev, mlme->reason_code);
1004         default:
1005                 return -EOPNOTSUPP;
1006         }
1007 }
1008
1009
1010 static int ieee80211_ioctl_siwencode(struct net_device *dev,
1011                                      struct iw_request_info *info,
1012                                      struct iw_point *erq, char *keybuf)
1013 {
1014         struct ieee80211_sub_if_data *sdata;
1015         int idx, i, alg = ALG_WEP;
1016         u8 bcaddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1017
1018         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1019
1020         idx = erq->flags & IW_ENCODE_INDEX;
1021         if (idx == 0) {
1022                 if (sdata->default_key)
1023                         for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
1024                                 if (sdata->default_key == sdata->keys[i]) {
1025                                         idx = i;
1026                                         break;
1027                                 }
1028                         }
1029         } else if (idx < 1 || idx > 4)
1030                 return -EINVAL;
1031         else
1032                 idx--;
1033
1034         if (erq->flags & IW_ENCODE_DISABLED)
1035                 alg = ALG_NONE;
1036         else if (erq->length == 0) {
1037                 /* No key data - just set the default TX key index */
1038                 ieee80211_set_default_key(sdata, idx);
1039                 return 0;
1040         }
1041
1042         return ieee80211_set_encryption(
1043                 dev, bcaddr,
1044                 idx, alg,
1045                 !sdata->default_key,
1046                 keybuf, erq->length);
1047 }
1048
1049
1050 static int ieee80211_ioctl_giwencode(struct net_device *dev,
1051                                      struct iw_request_info *info,
1052                                      struct iw_point *erq, char *key)
1053 {
1054         struct ieee80211_sub_if_data *sdata;
1055         int idx, i;
1056
1057         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1058
1059         idx = erq->flags & IW_ENCODE_INDEX;
1060         if (idx < 1 || idx > 4) {
1061                 idx = -1;
1062                 if (!sdata->default_key)
1063                         idx = 0;
1064                 else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
1065                         if (sdata->default_key == sdata->keys[i]) {
1066                                 idx = i;
1067                                 break;
1068                         }
1069                 }
1070                 if (idx < 0)
1071                         return -EINVAL;
1072         } else
1073                 idx--;
1074
1075         erq->flags = idx + 1;
1076
1077         if (!sdata->keys[idx]) {
1078                 erq->length = 0;
1079                 erq->flags |= IW_ENCODE_DISABLED;
1080                 return 0;
1081         }
1082
1083         memcpy(key, sdata->keys[idx]->conf.key,
1084                min_t(int, erq->length, sdata->keys[idx]->conf.keylen));
1085         erq->length = sdata->keys[idx]->conf.keylen;
1086         erq->flags |= IW_ENCODE_ENABLED;
1087
1088         return 0;
1089 }
1090
1091 static int ieee80211_ioctl_siwauth(struct net_device *dev,
1092                                    struct iw_request_info *info,
1093                                    struct iw_param *data, char *extra)
1094 {
1095         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
1096         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1097         int ret = 0;
1098
1099         switch (data->flags & IW_AUTH_INDEX) {
1100         case IW_AUTH_WPA_VERSION:
1101         case IW_AUTH_CIPHER_PAIRWISE:
1102         case IW_AUTH_CIPHER_GROUP:
1103         case IW_AUTH_WPA_ENABLED:
1104         case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1105                 break;
1106         case IW_AUTH_KEY_MGMT:
1107                 if (sdata->type != IEEE80211_IF_TYPE_STA)
1108                         ret = -EINVAL;
1109                 else {
1110                         /*
1111                          * Key management was set by wpa_supplicant,
1112                          * we only need this to associate to a network
1113                          * that has privacy enabled regardless of not
1114                          * having a key.
1115                          */
1116                         sdata->u.sta.key_management_enabled = !!data->value;
1117                 }
1118                 break;
1119         case IW_AUTH_80211_AUTH_ALG:
1120                 if (sdata->type == IEEE80211_IF_TYPE_STA ||
1121                     sdata->type == IEEE80211_IF_TYPE_IBSS)
1122                         sdata->u.sta.auth_algs = data->value;
1123                 else
1124                         ret = -EOPNOTSUPP;
1125                 break;
1126         case IW_AUTH_PRIVACY_INVOKED:
1127                 if (local->ops->set_privacy_invoked)
1128                         ret = local->ops->set_privacy_invoked(
1129                                         local_to_hw(local), data->value);
1130                 break;
1131         default:
1132                 ret = -EOPNOTSUPP;
1133                 break;
1134         }
1135         return ret;
1136 }
1137
1138 /* Get wireless statistics.  Called by /proc/net/wireless and by SIOCGIWSTATS */
1139 static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev)
1140 {
1141         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
1142         struct iw_statistics *wstats = &local->wstats;
1143         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1144         struct sta_info *sta = NULL;
1145
1146         if (sdata->type == IEEE80211_IF_TYPE_STA ||
1147             sdata->type == IEEE80211_IF_TYPE_IBSS)
1148                 sta = sta_info_get(local, sdata->u.sta.bssid);
1149         if (!sta) {
1150                 wstats->discard.fragment = 0;
1151                 wstats->discard.misc = 0;
1152                 wstats->qual.qual = 0;
1153                 wstats->qual.level = 0;
1154                 wstats->qual.noise = 0;
1155                 wstats->qual.updated = IW_QUAL_ALL_INVALID;
1156         } else {
1157                 wstats->qual.level = sta->last_rssi;
1158                 wstats->qual.qual = sta->last_signal;
1159                 wstats->qual.noise = sta->last_noise;
1160                 wstats->qual.updated = local->wstats_flags;
1161                 sta_info_put(sta);
1162         }
1163         return wstats;
1164 }
1165
1166 static int ieee80211_ioctl_giwauth(struct net_device *dev,
1167                                    struct iw_request_info *info,
1168                                    struct iw_param *data, char *extra)
1169 {
1170         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1171         int ret = 0;
1172
1173         switch (data->flags & IW_AUTH_INDEX) {
1174         case IW_AUTH_80211_AUTH_ALG:
1175                 if (sdata->type == IEEE80211_IF_TYPE_STA ||
1176                     sdata->type == IEEE80211_IF_TYPE_IBSS)
1177                         data->value = sdata->u.sta.auth_algs;
1178                 else
1179                         ret = -EOPNOTSUPP;
1180                 break;
1181         default:
1182                 ret = -EOPNOTSUPP;
1183                 break;
1184         }
1185         return ret;
1186 }
1187
1188
1189 static int ieee80211_ioctl_siwencodeext(struct net_device *dev,
1190                                         struct iw_request_info *info,
1191                                         struct iw_point *erq, char *extra)
1192 {
1193         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1194         struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
1195         int alg, idx, i;
1196
1197         switch (ext->alg) {
1198         case IW_ENCODE_ALG_NONE:
1199                 alg = ALG_NONE;
1200                 break;
1201         case IW_ENCODE_ALG_WEP:
1202                 alg = ALG_WEP;
1203                 break;
1204         case IW_ENCODE_ALG_TKIP:
1205                 alg = ALG_TKIP;
1206                 break;
1207         case IW_ENCODE_ALG_CCMP:
1208                 alg = ALG_CCMP;
1209                 break;
1210         default:
1211                 return -EOPNOTSUPP;
1212         }
1213
1214         if (erq->flags & IW_ENCODE_DISABLED)
1215                 alg = ALG_NONE;
1216
1217         idx = erq->flags & IW_ENCODE_INDEX;
1218         if (idx < 1 || idx > 4) {
1219                 idx = -1;
1220                 if (!sdata->default_key)
1221                         idx = 0;
1222                 else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
1223                         if (sdata->default_key == sdata->keys[i]) {
1224                                 idx = i;
1225                                 break;
1226                         }
1227                 }
1228                 if (idx < 0)
1229                         return -EINVAL;
1230         } else
1231                 idx--;
1232
1233         return ieee80211_set_encryption(dev, ext->addr.sa_data, idx, alg,
1234                                         ext->ext_flags &
1235                                         IW_ENCODE_EXT_SET_TX_KEY,
1236                                         ext->key, ext->key_len);
1237 }
1238
1239
1240 static const struct iw_priv_args ieee80211_ioctl_priv[] = {
1241         { PRISM2_IOCTL_PRISM2_PARAM,
1242           IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "param" },
1243         { PRISM2_IOCTL_GET_PRISM2_PARAM,
1244           IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1245           IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_param" },
1246 };
1247
1248 /* Structures to export the Wireless Handlers */
1249
1250 static const iw_handler ieee80211_handler[] =
1251 {
1252         (iw_handler) NULL,                              /* SIOCSIWCOMMIT */
1253         (iw_handler) ieee80211_ioctl_giwname,           /* SIOCGIWNAME */
1254         (iw_handler) NULL,                              /* SIOCSIWNWID */
1255         (iw_handler) NULL,                              /* SIOCGIWNWID */
1256         (iw_handler) ieee80211_ioctl_siwfreq,           /* SIOCSIWFREQ */
1257         (iw_handler) ieee80211_ioctl_giwfreq,           /* SIOCGIWFREQ */
1258         (iw_handler) ieee80211_ioctl_siwmode,           /* SIOCSIWMODE */
1259         (iw_handler) ieee80211_ioctl_giwmode,           /* SIOCGIWMODE */
1260         (iw_handler) NULL,                              /* SIOCSIWSENS */
1261         (iw_handler) NULL,                              /* SIOCGIWSENS */
1262         (iw_handler) NULL /* not used */,               /* SIOCSIWRANGE */
1263         (iw_handler) ieee80211_ioctl_giwrange,          /* SIOCGIWRANGE */
1264         (iw_handler) NULL /* not used */,               /* SIOCSIWPRIV */
1265         (iw_handler) NULL /* kernel code */,            /* SIOCGIWPRIV */
1266         (iw_handler) NULL /* not used */,               /* SIOCSIWSTATS */
1267         (iw_handler) NULL /* kernel code */,            /* SIOCGIWSTATS */
1268         (iw_handler) NULL,                              /* SIOCSIWSPY */
1269         (iw_handler) NULL,                              /* SIOCGIWSPY */
1270         (iw_handler) NULL,                              /* SIOCSIWTHRSPY */
1271         (iw_handler) NULL,                              /* SIOCGIWTHRSPY */
1272         (iw_handler) ieee80211_ioctl_siwap,             /* SIOCSIWAP */
1273         (iw_handler) ieee80211_ioctl_giwap,             /* SIOCGIWAP */
1274         (iw_handler) ieee80211_ioctl_siwmlme,           /* SIOCSIWMLME */
1275         (iw_handler) NULL,                              /* SIOCGIWAPLIST */
1276         (iw_handler) ieee80211_ioctl_siwscan,           /* SIOCSIWSCAN */
1277         (iw_handler) ieee80211_ioctl_giwscan,           /* SIOCGIWSCAN */
1278         (iw_handler) ieee80211_ioctl_siwessid,          /* SIOCSIWESSID */
1279         (iw_handler) ieee80211_ioctl_giwessid,          /* SIOCGIWESSID */
1280         (iw_handler) NULL,                              /* SIOCSIWNICKN */
1281         (iw_handler) NULL,                              /* SIOCGIWNICKN */
1282         (iw_handler) NULL,                              /* -- hole -- */
1283         (iw_handler) NULL,                              /* -- hole -- */
1284         (iw_handler) ieee80211_ioctl_siwrate,           /* SIOCSIWRATE */
1285         (iw_handler) ieee80211_ioctl_giwrate,           /* SIOCGIWRATE */
1286         (iw_handler) ieee80211_ioctl_siwrts,            /* SIOCSIWRTS */
1287         (iw_handler) ieee80211_ioctl_giwrts,            /* SIOCGIWRTS */
1288         (iw_handler) ieee80211_ioctl_siwfrag,           /* SIOCSIWFRAG */
1289         (iw_handler) ieee80211_ioctl_giwfrag,           /* SIOCGIWFRAG */
1290         (iw_handler) NULL,                              /* SIOCSIWTXPOW */
1291         (iw_handler) ieee80211_ioctl_giwtxpower,        /* SIOCGIWTXPOW */
1292         (iw_handler) ieee80211_ioctl_siwretry,          /* SIOCSIWRETRY */
1293         (iw_handler) ieee80211_ioctl_giwretry,          /* SIOCGIWRETRY */
1294         (iw_handler) ieee80211_ioctl_siwencode,         /* SIOCSIWENCODE */
1295         (iw_handler) ieee80211_ioctl_giwencode,         /* SIOCGIWENCODE */
1296         (iw_handler) NULL,                              /* SIOCSIWPOWER */
1297         (iw_handler) NULL,                              /* SIOCGIWPOWER */
1298         (iw_handler) NULL,                              /* -- hole -- */
1299         (iw_handler) NULL,                              /* -- hole -- */
1300         (iw_handler) ieee80211_ioctl_siwgenie,          /* SIOCSIWGENIE */
1301         (iw_handler) NULL,                              /* SIOCGIWGENIE */
1302         (iw_handler) ieee80211_ioctl_siwauth,           /* SIOCSIWAUTH */
1303         (iw_handler) ieee80211_ioctl_giwauth,           /* SIOCGIWAUTH */
1304         (iw_handler) ieee80211_ioctl_siwencodeext,      /* SIOCSIWENCODEEXT */
1305         (iw_handler) NULL,                              /* SIOCGIWENCODEEXT */
1306         (iw_handler) NULL,                              /* SIOCSIWPMKSA */
1307         (iw_handler) NULL,                              /* -- hole -- */
1308 };
1309
1310 static const iw_handler ieee80211_private_handler[] =
1311 {                                                       /* SIOCIWFIRSTPRIV + */
1312         (iw_handler) ieee80211_ioctl_prism2_param,      /* 0 */
1313         (iw_handler) ieee80211_ioctl_get_prism2_param,  /* 1 */
1314 };
1315
1316 const struct iw_handler_def ieee80211_iw_handler_def =
1317 {
1318         .num_standard   = ARRAY_SIZE(ieee80211_handler),
1319         .num_private    = ARRAY_SIZE(ieee80211_private_handler),
1320         .num_private_args = ARRAY_SIZE(ieee80211_ioctl_priv),
1321         .standard       = (iw_handler *) ieee80211_handler,
1322         .private        = (iw_handler *) ieee80211_private_handler,
1323         .private_args   = (struct iw_priv_args *) ieee80211_ioctl_priv,
1324         .get_wireless_stats = ieee80211_get_wireless_stats,
1325 };