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