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