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