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