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