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