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