cfg80211: check for current_bss from giwrate
[safe/jmp/linux-2.6] / net / wireless / wext-compat.c
1 /*
2  * cfg80211 - wext compat code
3  *
4  * This is temporary code until all wireless functionality is migrated
5  * into cfg80211, when that happens all the exports here go away and
6  * we directly assign the wireless handlers of wireless interfaces.
7  *
8  * Copyright 2008-2009  Johannes Berg <johannes@sipsolutions.net>
9  */
10
11 #include <linux/wireless.h>
12 #include <linux/nl80211.h>
13 #include <linux/if_arp.h>
14 #include <linux/etherdevice.h>
15 #include <net/iw_handler.h>
16 #include <net/cfg80211.h>
17 #include "core.h"
18
19 int cfg80211_wext_giwname(struct net_device *dev,
20                           struct iw_request_info *info,
21                           char *name, char *extra)
22 {
23         struct wireless_dev *wdev = dev->ieee80211_ptr;
24         struct ieee80211_supported_band *sband;
25         bool is_ht = false, is_a = false, is_b = false, is_g = false;
26
27         if (!wdev)
28                 return -EOPNOTSUPP;
29
30         sband = wdev->wiphy->bands[IEEE80211_BAND_5GHZ];
31         if (sband) {
32                 is_a = true;
33                 is_ht |= sband->ht_cap.ht_supported;
34         }
35
36         sband = wdev->wiphy->bands[IEEE80211_BAND_2GHZ];
37         if (sband) {
38                 int i;
39                 /* Check for mandatory rates */
40                 for (i = 0; i < sband->n_bitrates; i++) {
41                         if (sband->bitrates[i].bitrate == 10)
42                                 is_b = true;
43                         if (sband->bitrates[i].bitrate == 60)
44                                 is_g = true;
45                 }
46                 is_ht |= sband->ht_cap.ht_supported;
47         }
48
49         strcpy(name, "IEEE 802.11");
50         if (is_a)
51                 strcat(name, "a");
52         if (is_b)
53                 strcat(name, "b");
54         if (is_g)
55                 strcat(name, "g");
56         if (is_ht)
57                 strcat(name, "n");
58
59         return 0;
60 }
61 EXPORT_SYMBOL_GPL(cfg80211_wext_giwname);
62
63 int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
64                           u32 *mode, char *extra)
65 {
66         struct wireless_dev *wdev = dev->ieee80211_ptr;
67         struct cfg80211_registered_device *rdev;
68         struct vif_params vifparams;
69         enum nl80211_iftype type;
70         int ret;
71
72         if (!wdev)
73                 return -EOPNOTSUPP;
74
75         rdev = wiphy_to_dev(wdev->wiphy);
76
77         if (!rdev->ops->change_virtual_intf)
78                 return -EOPNOTSUPP;
79
80         /* don't support changing VLANs, you just re-create them */
81         if (wdev->iftype == NL80211_IFTYPE_AP_VLAN)
82                 return -EOPNOTSUPP;
83
84         switch (*mode) {
85         case IW_MODE_INFRA:
86                 type = NL80211_IFTYPE_STATION;
87                 break;
88         case IW_MODE_ADHOC:
89                 type = NL80211_IFTYPE_ADHOC;
90                 break;
91         case IW_MODE_REPEAT:
92                 type = NL80211_IFTYPE_WDS;
93                 break;
94         case IW_MODE_MONITOR:
95                 type = NL80211_IFTYPE_MONITOR;
96                 break;
97         default:
98                 return -EINVAL;
99         }
100
101         if (type == wdev->iftype)
102                 return 0;
103
104         memset(&vifparams, 0, sizeof(vifparams));
105
106         ret = rdev->ops->change_virtual_intf(wdev->wiphy, dev, type,
107                                              NULL, &vifparams);
108         WARN_ON(!ret && wdev->iftype != type);
109
110         return ret;
111 }
112 EXPORT_SYMBOL_GPL(cfg80211_wext_siwmode);
113
114 int cfg80211_wext_giwmode(struct net_device *dev, struct iw_request_info *info,
115                           u32 *mode, char *extra)
116 {
117         struct wireless_dev *wdev = dev->ieee80211_ptr;
118
119         if (!wdev)
120                 return -EOPNOTSUPP;
121
122         switch (wdev->iftype) {
123         case NL80211_IFTYPE_AP:
124                 *mode = IW_MODE_MASTER;
125                 break;
126         case NL80211_IFTYPE_STATION:
127                 *mode = IW_MODE_INFRA;
128                 break;
129         case NL80211_IFTYPE_ADHOC:
130                 *mode = IW_MODE_ADHOC;
131                 break;
132         case NL80211_IFTYPE_MONITOR:
133                 *mode = IW_MODE_MONITOR;
134                 break;
135         case NL80211_IFTYPE_WDS:
136                 *mode = IW_MODE_REPEAT;
137                 break;
138         case NL80211_IFTYPE_AP_VLAN:
139                 *mode = IW_MODE_SECOND;         /* FIXME */
140                 break;
141         default:
142                 *mode = IW_MODE_AUTO;
143                 break;
144         }
145         return 0;
146 }
147 EXPORT_SYMBOL_GPL(cfg80211_wext_giwmode);
148
149
150 int cfg80211_wext_giwrange(struct net_device *dev,
151                            struct iw_request_info *info,
152                            struct iw_point *data, char *extra)
153 {
154         struct wireless_dev *wdev = dev->ieee80211_ptr;
155         struct iw_range *range = (struct iw_range *) extra;
156         enum ieee80211_band band;
157         int i, c = 0;
158
159         if (!wdev)
160                 return -EOPNOTSUPP;
161
162         data->length = sizeof(struct iw_range);
163         memset(range, 0, sizeof(struct iw_range));
164
165         range->we_version_compiled = WIRELESS_EXT;
166         range->we_version_source = 21;
167         range->retry_capa = IW_RETRY_LIMIT;
168         range->retry_flags = IW_RETRY_LIMIT;
169         range->min_retry = 0;
170         range->max_retry = 255;
171         range->min_rts = 0;
172         range->max_rts = 2347;
173         range->min_frag = 256;
174         range->max_frag = 2346;
175
176         range->max_encoding_tokens = 4;
177
178         range->max_qual.updated = IW_QUAL_NOISE_INVALID;
179
180         switch (wdev->wiphy->signal_type) {
181         case CFG80211_SIGNAL_TYPE_NONE:
182                 break;
183         case CFG80211_SIGNAL_TYPE_MBM:
184                 range->max_qual.level = -110;
185                 range->max_qual.qual = 70;
186                 range->avg_qual.qual = 35;
187                 range->max_qual.updated |= IW_QUAL_DBM;
188                 range->max_qual.updated |= IW_QUAL_QUAL_UPDATED;
189                 range->max_qual.updated |= IW_QUAL_LEVEL_UPDATED;
190                 break;
191         case CFG80211_SIGNAL_TYPE_UNSPEC:
192                 range->max_qual.level = 100;
193                 range->max_qual.qual = 100;
194                 range->avg_qual.qual = 50;
195                 range->max_qual.updated |= IW_QUAL_QUAL_UPDATED;
196                 range->max_qual.updated |= IW_QUAL_LEVEL_UPDATED;
197                 break;
198         }
199
200         range->avg_qual.level = range->max_qual.level / 2;
201         range->avg_qual.noise = range->max_qual.noise / 2;
202         range->avg_qual.updated = range->max_qual.updated;
203
204         for (i = 0; i < wdev->wiphy->n_cipher_suites; i++) {
205                 switch (wdev->wiphy->cipher_suites[i]) {
206                 case WLAN_CIPHER_SUITE_TKIP:
207                         range->enc_capa |= (IW_ENC_CAPA_CIPHER_TKIP |
208                                             IW_ENC_CAPA_WPA);
209                         break;
210
211                 case WLAN_CIPHER_SUITE_CCMP:
212                         range->enc_capa |= (IW_ENC_CAPA_CIPHER_CCMP |
213                                             IW_ENC_CAPA_WPA2);
214                         break;
215
216                 case WLAN_CIPHER_SUITE_WEP40:
217                         range->encoding_size[range->num_encoding_sizes++] =
218                                 WLAN_KEY_LEN_WEP40;
219                         break;
220
221                 case WLAN_CIPHER_SUITE_WEP104:
222                         range->encoding_size[range->num_encoding_sizes++] =
223                                 WLAN_KEY_LEN_WEP104;
224                         break;
225                 }
226         }
227
228         for (band = 0; band < IEEE80211_NUM_BANDS; band ++) {
229                 struct ieee80211_supported_band *sband;
230
231                 sband = wdev->wiphy->bands[band];
232
233                 if (!sband)
234                         continue;
235
236                 for (i = 0; i < sband->n_channels && c < IW_MAX_FREQUENCIES; i++) {
237                         struct ieee80211_channel *chan = &sband->channels[i];
238
239                         if (!(chan->flags & IEEE80211_CHAN_DISABLED)) {
240                                 range->freq[c].i =
241                                         ieee80211_frequency_to_channel(
242                                                 chan->center_freq);
243                                 range->freq[c].m = chan->center_freq;
244                                 range->freq[c].e = 6;
245                                 c++;
246                         }
247                 }
248         }
249         range->num_channels = c;
250         range->num_frequency = c;
251
252         IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
253         IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
254         IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
255
256         if (wdev->wiphy->max_scan_ssids > 0)
257                 range->scan_capa |= IW_SCAN_CAPA_ESSID;
258
259         return 0;
260 }
261 EXPORT_SYMBOL_GPL(cfg80211_wext_giwrange);
262
263
264 /**
265  * cfg80211_wext_freq - get wext frequency for non-"auto"
266  * @wiphy: the wiphy
267  * @freq: the wext freq encoding
268  *
269  * Returns a channel, %NULL for auto, or an ERR_PTR for errors!
270  */
271 struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy,
272                                              struct iw_freq *freq)
273 {
274         struct ieee80211_channel *chan;
275         int f;
276
277         /*
278          * Parse frequency - return NULL for auto and
279          * -EINVAL for impossible things.
280          */
281         if (freq->e == 0) {
282                 if (freq->m < 0)
283                         return NULL;
284                 f = ieee80211_channel_to_frequency(freq->m);
285         } else {
286                 int i, div = 1000000;
287                 for (i = 0; i < freq->e; i++)
288                         div /= 10;
289                 if (div <= 0)
290                         return ERR_PTR(-EINVAL);
291                 f = freq->m / div;
292         }
293
294         /*
295          * Look up channel struct and return -EINVAL when
296          * it cannot be found.
297          */
298         chan = ieee80211_get_channel(wiphy, f);
299         if (!chan)
300                 return ERR_PTR(-EINVAL);
301         return chan;
302 }
303 EXPORT_SYMBOL_GPL(cfg80211_wext_freq);
304
305 int cfg80211_wext_siwrts(struct net_device *dev,
306                          struct iw_request_info *info,
307                          struct iw_param *rts, char *extra)
308 {
309         struct wireless_dev *wdev = dev->ieee80211_ptr;
310         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
311         u32 orts = wdev->wiphy->rts_threshold;
312         int err;
313
314         if (rts->disabled || !rts->fixed)
315                 wdev->wiphy->rts_threshold = (u32) -1;
316         else if (rts->value < 0)
317                 return -EINVAL;
318         else
319                 wdev->wiphy->rts_threshold = rts->value;
320
321         err = rdev->ops->set_wiphy_params(wdev->wiphy,
322                                           WIPHY_PARAM_RTS_THRESHOLD);
323         if (err)
324                 wdev->wiphy->rts_threshold = orts;
325
326         return err;
327 }
328 EXPORT_SYMBOL_GPL(cfg80211_wext_siwrts);
329
330 int cfg80211_wext_giwrts(struct net_device *dev,
331                          struct iw_request_info *info,
332                          struct iw_param *rts, char *extra)
333 {
334         struct wireless_dev *wdev = dev->ieee80211_ptr;
335
336         rts->value = wdev->wiphy->rts_threshold;
337         rts->disabled = rts->value == (u32) -1;
338         rts->fixed = 1;
339
340         return 0;
341 }
342 EXPORT_SYMBOL_GPL(cfg80211_wext_giwrts);
343
344 int cfg80211_wext_siwfrag(struct net_device *dev,
345                           struct iw_request_info *info,
346                           struct iw_param *frag, char *extra)
347 {
348         struct wireless_dev *wdev = dev->ieee80211_ptr;
349         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
350         u32 ofrag = wdev->wiphy->frag_threshold;
351         int err;
352
353         if (frag->disabled || !frag->fixed)
354                 wdev->wiphy->frag_threshold = (u32) -1;
355         else if (frag->value < 256)
356                 return -EINVAL;
357         else {
358                 /* Fragment length must be even, so strip LSB. */
359                 wdev->wiphy->frag_threshold = frag->value & ~0x1;
360         }
361
362         err = rdev->ops->set_wiphy_params(wdev->wiphy,
363                                           WIPHY_PARAM_FRAG_THRESHOLD);
364         if (err)
365                 wdev->wiphy->frag_threshold = ofrag;
366
367         return err;
368 }
369 EXPORT_SYMBOL_GPL(cfg80211_wext_siwfrag);
370
371 int cfg80211_wext_giwfrag(struct net_device *dev,
372                           struct iw_request_info *info,
373                           struct iw_param *frag, char *extra)
374 {
375         struct wireless_dev *wdev = dev->ieee80211_ptr;
376
377         frag->value = wdev->wiphy->frag_threshold;
378         frag->disabled = frag->value == (u32) -1;
379         frag->fixed = 1;
380
381         return 0;
382 }
383 EXPORT_SYMBOL_GPL(cfg80211_wext_giwfrag);
384
385 int cfg80211_wext_siwretry(struct net_device *dev,
386                            struct iw_request_info *info,
387                            struct iw_param *retry, char *extra)
388 {
389         struct wireless_dev *wdev = dev->ieee80211_ptr;
390         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
391         u32 changed = 0;
392         u8 olong = wdev->wiphy->retry_long;
393         u8 oshort = wdev->wiphy->retry_short;
394         int err;
395
396         if (retry->disabled ||
397             (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
398                 return -EINVAL;
399
400         if (retry->flags & IW_RETRY_LONG) {
401                 wdev->wiphy->retry_long = retry->value;
402                 changed |= WIPHY_PARAM_RETRY_LONG;
403         } else if (retry->flags & IW_RETRY_SHORT) {
404                 wdev->wiphy->retry_short = retry->value;
405                 changed |= WIPHY_PARAM_RETRY_SHORT;
406         } else {
407                 wdev->wiphy->retry_short = retry->value;
408                 wdev->wiphy->retry_long = retry->value;
409                 changed |= WIPHY_PARAM_RETRY_LONG;
410                 changed |= WIPHY_PARAM_RETRY_SHORT;
411         }
412
413         if (!changed)
414                 return 0;
415
416         err = rdev->ops->set_wiphy_params(wdev->wiphy, changed);
417         if (err) {
418                 wdev->wiphy->retry_short = oshort;
419                 wdev->wiphy->retry_long = olong;
420         }
421
422         return err;
423 }
424 EXPORT_SYMBOL_GPL(cfg80211_wext_siwretry);
425
426 int cfg80211_wext_giwretry(struct net_device *dev,
427                            struct iw_request_info *info,
428                            struct iw_param *retry, char *extra)
429 {
430         struct wireless_dev *wdev = dev->ieee80211_ptr;
431
432         retry->disabled = 0;
433
434         if (retry->flags == 0 || (retry->flags & IW_RETRY_SHORT)) {
435                 /*
436                  * First return short value, iwconfig will ask long value
437                  * later if needed
438                  */
439                 retry->flags |= IW_RETRY_LIMIT;
440                 retry->value = wdev->wiphy->retry_short;
441                 if (wdev->wiphy->retry_long != wdev->wiphy->retry_short)
442                         retry->flags |= IW_RETRY_LONG;
443
444                 return 0;
445         }
446
447         if (retry->flags & IW_RETRY_LONG) {
448                 retry->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
449                 retry->value = wdev->wiphy->retry_long;
450         }
451
452         return 0;
453 }
454 EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry);
455
456 static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
457                                    struct net_device *dev, const u8 *addr,
458                                    bool remove, bool tx_key, int idx,
459                                    struct key_params *params)
460 {
461         struct wireless_dev *wdev = dev->ieee80211_ptr;
462         int err;
463
464         if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
465                 if (!rdev->ops->set_default_mgmt_key)
466                         return -EOPNOTSUPP;
467
468                 if (idx < 4 || idx > 5)
469                         return -EINVAL;
470         } else if (idx < 0 || idx > 3)
471                 return -EINVAL;
472
473         if (remove) {
474                 err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr);
475                 if (!err) {
476                         if (idx == wdev->wext.default_key)
477                                 wdev->wext.default_key = -1;
478                         else if (idx == wdev->wext.default_mgmt_key)
479                                 wdev->wext.default_mgmt_key = -1;
480                 }
481                 /*
482                  * Applications using wireless extensions expect to be
483                  * able to delete keys that don't exist, so allow that.
484                  */
485                 if (err == -ENOENT)
486                         return 0;
487
488                 return err;
489         } else {
490                 if (addr)
491                         tx_key = false;
492
493                 if (cfg80211_validate_key_settings(params, idx, addr))
494                         return -EINVAL;
495
496                 err = rdev->ops->add_key(&rdev->wiphy, dev, idx, addr, params);
497                 if (err)
498                         return err;
499
500                 if (tx_key || (!addr && wdev->wext.default_key == -1)) {
501                         err = rdev->ops->set_default_key(&rdev->wiphy,
502                                                          dev, idx);
503                         if (!err)
504                                 wdev->wext.default_key = idx;
505                         return err;
506                 }
507
508                 if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC &&
509                     (tx_key || (!addr && wdev->wext.default_mgmt_key == -1))) {
510                         err = rdev->ops->set_default_mgmt_key(&rdev->wiphy,
511                                                               dev, idx);
512                         if (!err)
513                                 wdev->wext.default_mgmt_key = idx;
514                         return err;
515                 }
516
517                 return 0;
518         }
519 }
520
521 int cfg80211_wext_siwencode(struct net_device *dev,
522                             struct iw_request_info *info,
523                             struct iw_point *erq, char *keybuf)
524 {
525         struct wireless_dev *wdev = dev->ieee80211_ptr;
526         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
527         int idx, err;
528         bool remove = false;
529         struct key_params params;
530
531         /* no use -- only MFP (set_default_mgmt_key) is optional */
532         if (!rdev->ops->del_key ||
533             !rdev->ops->add_key ||
534             !rdev->ops->set_default_key)
535                 return -EOPNOTSUPP;
536
537         idx = erq->flags & IW_ENCODE_INDEX;
538         if (idx == 0) {
539                 idx = wdev->wext.default_key;
540                 if (idx < 0)
541                         idx = 0;
542         } else if (idx < 1 || idx > 4)
543                 return -EINVAL;
544         else
545                 idx--;
546
547         if (erq->flags & IW_ENCODE_DISABLED)
548                 remove = true;
549         else if (erq->length == 0) {
550                 /* No key data - just set the default TX key index */
551                 err = rdev->ops->set_default_key(&rdev->wiphy, dev, idx);
552                 if (!err)
553                         wdev->wext.default_key = idx;
554                 return err;
555         }
556
557         memset(&params, 0, sizeof(params));
558         params.key = keybuf;
559         params.key_len = erq->length;
560         if (erq->length == 5)
561                 params.cipher = WLAN_CIPHER_SUITE_WEP40;
562         else if (erq->length == 13)
563                 params.cipher = WLAN_CIPHER_SUITE_WEP104;
564         else if (!remove)
565                 return -EINVAL;
566
567         return cfg80211_set_encryption(rdev, dev, NULL, remove,
568                                        wdev->wext.default_key == -1,
569                                        idx, &params);
570 }
571 EXPORT_SYMBOL_GPL(cfg80211_wext_siwencode);
572
573 int cfg80211_wext_siwencodeext(struct net_device *dev,
574                                struct iw_request_info *info,
575                                struct iw_point *erq, char *extra)
576 {
577         struct wireless_dev *wdev = dev->ieee80211_ptr;
578         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
579         struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
580         const u8 *addr;
581         int idx;
582         bool remove = false;
583         struct key_params params;
584         u32 cipher;
585
586         /* no use -- only MFP (set_default_mgmt_key) is optional */
587         if (!rdev->ops->del_key ||
588             !rdev->ops->add_key ||
589             !rdev->ops->set_default_key)
590                 return -EOPNOTSUPP;
591
592         switch (ext->alg) {
593         case IW_ENCODE_ALG_NONE:
594                 remove = true;
595                 cipher = 0;
596                 break;
597         case IW_ENCODE_ALG_WEP:
598                 if (ext->key_len == 5)
599                         cipher = WLAN_CIPHER_SUITE_WEP40;
600                 else if (ext->key_len == 13)
601                         cipher = WLAN_CIPHER_SUITE_WEP104;
602                 else
603                         return -EINVAL;
604                 break;
605         case IW_ENCODE_ALG_TKIP:
606                 cipher = WLAN_CIPHER_SUITE_TKIP;
607                 break;
608         case IW_ENCODE_ALG_CCMP:
609                 cipher = WLAN_CIPHER_SUITE_CCMP;
610                 break;
611         case IW_ENCODE_ALG_AES_CMAC:
612                 cipher = WLAN_CIPHER_SUITE_AES_CMAC;
613                 break;
614         default:
615                 return -EOPNOTSUPP;
616         }
617
618         if (erq->flags & IW_ENCODE_DISABLED)
619                 remove = true;
620
621         idx = erq->flags & IW_ENCODE_INDEX;
622         if (cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
623                 if (idx < 4 || idx > 5) {
624                         idx = wdev->wext.default_mgmt_key;
625                         if (idx < 0)
626                                 return -EINVAL;
627                 } else
628                         idx--;
629         } else {
630                 if (idx < 1 || idx > 4) {
631                         idx = wdev->wext.default_key;
632                         if (idx < 0)
633                                 return -EINVAL;
634                 } else
635                         idx--;
636         }
637
638         addr = ext->addr.sa_data;
639         if (is_broadcast_ether_addr(addr))
640                 addr = NULL;
641
642         memset(&params, 0, sizeof(params));
643         params.key = ext->key;
644         params.key_len = ext->key_len;
645         params.cipher = cipher;
646
647         if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
648                 params.seq = ext->rx_seq;
649                 params.seq_len = 6;
650         }
651
652         return cfg80211_set_encryption(
653                         rdev, dev, addr, remove,
654                         ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
655                         idx, &params);
656 }
657 EXPORT_SYMBOL_GPL(cfg80211_wext_siwencodeext);
658
659 struct giwencode_cookie {
660         size_t buflen;
661         char *keybuf;
662 };
663
664 static void giwencode_get_key_cb(void *cookie, struct key_params *params)
665 {
666         struct giwencode_cookie *data = cookie;
667
668         if (!params->key) {
669                 data->buflen = 0;
670                 return;
671         }
672
673         data->buflen = min_t(size_t, data->buflen, params->key_len);
674         memcpy(data->keybuf, params->key, data->buflen);
675 }
676
677 int cfg80211_wext_giwencode(struct net_device *dev,
678                             struct iw_request_info *info,
679                             struct iw_point *erq, char *keybuf)
680 {
681         struct wireless_dev *wdev = dev->ieee80211_ptr;
682         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
683         int idx, err;
684         struct giwencode_cookie data = {
685                 .keybuf = keybuf,
686                 .buflen = erq->length,
687         };
688
689         if (!rdev->ops->get_key)
690                 return -EOPNOTSUPP;
691
692         idx = erq->flags & IW_ENCODE_INDEX;
693         if (idx == 0) {
694                 idx = wdev->wext.default_key;
695                 if (idx < 0)
696                         idx = 0;
697         } else if (idx < 1 || idx > 4)
698                 return -EINVAL;
699         else
700                 idx--;
701
702         erq->flags = idx + 1;
703
704         err = rdev->ops->get_key(&rdev->wiphy, dev, idx, NULL, &data,
705                                  giwencode_get_key_cb);
706         if (!err) {
707                 erq->length = data.buflen;
708                 erq->flags |= IW_ENCODE_ENABLED;
709                 return 0;
710         }
711
712         if (err == -ENOENT) {
713                 erq->flags |= IW_ENCODE_DISABLED;
714                 erq->length = 0;
715                 return 0;
716         }
717
718         return err;
719 }
720 EXPORT_SYMBOL_GPL(cfg80211_wext_giwencode);
721
722 int cfg80211_wext_siwtxpower(struct net_device *dev,
723                              struct iw_request_info *info,
724                              union iwreq_data *data, char *extra)
725 {
726         struct wireless_dev *wdev = dev->ieee80211_ptr;
727         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
728         enum tx_power_setting type;
729         int dbm = 0;
730
731         if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
732                 return -EINVAL;
733         if (data->txpower.flags & IW_TXPOW_RANGE)
734                 return -EINVAL;
735
736         if (!rdev->ops->set_tx_power)
737                 return -EOPNOTSUPP;
738
739         /* only change when not disabling */
740         if (!data->txpower.disabled) {
741                 rfkill_set_sw_state(rdev->rfkill, false);
742
743                 if (data->txpower.fixed) {
744                         /*
745                          * wext doesn't support negative values, see
746                          * below where it's for automatic
747                          */
748                         if (data->txpower.value < 0)
749                                 return -EINVAL;
750                         dbm = data->txpower.value;
751                         type = TX_POWER_FIXED;
752                         /* TODO: do regulatory check! */
753                 } else {
754                         /*
755                          * Automatic power level setting, max being the value
756                          * passed in from userland.
757                          */
758                         if (data->txpower.value < 0) {
759                                 type = TX_POWER_AUTOMATIC;
760                         } else {
761                                 dbm = data->txpower.value;
762                                 type = TX_POWER_LIMITED;
763                         }
764                 }
765         } else {
766                 rfkill_set_sw_state(rdev->rfkill, true);
767                 schedule_work(&rdev->rfkill_sync);
768                 return 0;
769         }
770
771         return rdev->ops->set_tx_power(wdev->wiphy, type, dbm);;
772 }
773 EXPORT_SYMBOL_GPL(cfg80211_wext_siwtxpower);
774
775 int cfg80211_wext_giwtxpower(struct net_device *dev,
776                              struct iw_request_info *info,
777                              union iwreq_data *data, char *extra)
778 {
779         struct wireless_dev *wdev = dev->ieee80211_ptr;
780         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
781         int err, val;
782
783         if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
784                 return -EINVAL;
785         if (data->txpower.flags & IW_TXPOW_RANGE)
786                 return -EINVAL;
787
788         if (!rdev->ops->get_tx_power)
789                 return -EOPNOTSUPP;
790
791         err = rdev->ops->get_tx_power(wdev->wiphy, &val);
792         if (err)
793                 return err;
794
795         /* well... oh well */
796         data->txpower.fixed = 1;
797         data->txpower.disabled = rfkill_blocked(rdev->rfkill);
798         data->txpower.value = val;
799         data->txpower.flags = IW_TXPOW_DBM;
800
801         return 0;
802 }
803 EXPORT_SYMBOL_GPL(cfg80211_wext_giwtxpower);
804
805 static int cfg80211_set_auth_alg(struct wireless_dev *wdev,
806                                  s32 auth_alg)
807 {
808         int nr_alg = 0;
809
810         if (!auth_alg)
811                 return -EINVAL;
812
813         if (auth_alg & ~(IW_AUTH_ALG_OPEN_SYSTEM |
814                          IW_AUTH_ALG_SHARED_KEY |
815                          IW_AUTH_ALG_LEAP))
816                 return -EINVAL;
817
818         if (auth_alg & IW_AUTH_ALG_OPEN_SYSTEM) {
819                 nr_alg++;
820                 wdev->wext.connect.auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM;
821         }
822
823         if (auth_alg & IW_AUTH_ALG_SHARED_KEY) {
824                 nr_alg++;
825                 wdev->wext.connect.auth_type = NL80211_AUTHTYPE_SHARED_KEY;
826         }
827
828         if (auth_alg & IW_AUTH_ALG_LEAP) {
829                 nr_alg++;
830                 wdev->wext.connect.auth_type = NL80211_AUTHTYPE_NETWORK_EAP;
831         }
832
833         if (nr_alg > 1)
834                 wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
835
836         return 0;
837 }
838
839 static int cfg80211_set_wpa_version(struct wireless_dev *wdev, u32 wpa_versions)
840 {
841         wdev->wext.connect.crypto.wpa_versions = 0;
842
843         if (wpa_versions & ~(IW_AUTH_WPA_VERSION_WPA |
844                              IW_AUTH_WPA_VERSION_WPA2))
845                 return -EINVAL;
846
847         if (wpa_versions & IW_AUTH_WPA_VERSION_WPA)
848                 wdev->wext.connect.crypto.wpa_versions |=
849                         NL80211_WPA_VERSION_1;
850
851         if (wpa_versions & IW_AUTH_WPA_VERSION_WPA2)
852                 wdev->wext.connect.crypto.wpa_versions |=
853                         NL80211_WPA_VERSION_2;
854
855         return 0;
856 }
857
858 int cfg80211_set_cipher_group(struct wireless_dev *wdev, u32 cipher)
859 {
860         wdev->wext.connect.crypto.cipher_group = 0;
861
862         if (cipher & IW_AUTH_CIPHER_WEP40)
863                 wdev->wext.connect.crypto.cipher_group =
864                         WLAN_CIPHER_SUITE_WEP40;
865         else if (cipher & IW_AUTH_CIPHER_WEP104)
866                 wdev->wext.connect.crypto.cipher_group =
867                         WLAN_CIPHER_SUITE_WEP104;
868         else if (cipher & IW_AUTH_CIPHER_TKIP)
869                 wdev->wext.connect.crypto.cipher_group =
870                         WLAN_CIPHER_SUITE_TKIP;
871         else if (cipher & IW_AUTH_CIPHER_CCMP)
872                 wdev->wext.connect.crypto.cipher_group =
873                         WLAN_CIPHER_SUITE_CCMP;
874         else if (cipher & IW_AUTH_CIPHER_AES_CMAC)
875                 wdev->wext.connect.crypto.cipher_group =
876                         WLAN_CIPHER_SUITE_AES_CMAC;
877         else
878                 return -EINVAL;
879
880         return 0;
881 }
882
883 int cfg80211_set_cipher_pairwise(struct wireless_dev *wdev, u32 cipher)
884 {
885         int nr_ciphers = 0;
886         u32 *ciphers_pairwise = wdev->wext.connect.crypto.ciphers_pairwise;
887
888         if (cipher & IW_AUTH_CIPHER_WEP40) {
889                 ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_WEP40;
890                 nr_ciphers++;
891         }
892
893         if (cipher & IW_AUTH_CIPHER_WEP104) {
894                 ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_WEP104;
895                 nr_ciphers++;
896         }
897
898         if (cipher & IW_AUTH_CIPHER_TKIP) {
899                 ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_TKIP;
900                 nr_ciphers++;
901         }
902
903         if (cipher & IW_AUTH_CIPHER_CCMP) {
904                 ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_CCMP;
905                 nr_ciphers++;
906         }
907
908         if (cipher & IW_AUTH_CIPHER_AES_CMAC) {
909                 ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_AES_CMAC;
910                 nr_ciphers++;
911         }
912
913         BUILD_BUG_ON(NL80211_MAX_NR_CIPHER_SUITES < 5);
914
915         wdev->wext.connect.crypto.n_ciphers_pairwise = nr_ciphers;
916
917         return 0;
918 }
919
920
921 int cfg80211_set_key_mgt(struct wireless_dev *wdev, u32 key_mgt)
922 {
923         int nr_akm_suites = 0;
924
925         if (key_mgt & ~(IW_AUTH_KEY_MGMT_802_1X |
926                         IW_AUTH_KEY_MGMT_PSK))
927                 return -EINVAL;
928
929         if (key_mgt & IW_AUTH_KEY_MGMT_802_1X) {
930                 wdev->wext.connect.crypto.akm_suites[nr_akm_suites] =
931                         WLAN_AKM_SUITE_8021X;
932                 nr_akm_suites++;
933         }
934
935         if (key_mgt & IW_AUTH_KEY_MGMT_PSK) {
936                 wdev->wext.connect.crypto.akm_suites[nr_akm_suites] =
937                         WLAN_AKM_SUITE_PSK;
938                 nr_akm_suites++;
939         }
940
941         wdev->wext.connect.crypto.n_akm_suites = nr_akm_suites;
942
943         return 0;
944 }
945
946 int cfg80211_wext_siwauth(struct net_device *dev,
947                           struct iw_request_info *info,
948                           struct iw_param *data, char *extra)
949 {
950         struct wireless_dev *wdev = dev->ieee80211_ptr;
951
952         if (wdev->iftype != NL80211_IFTYPE_STATION)
953                 return -EOPNOTSUPP;
954
955         switch (data->flags & IW_AUTH_INDEX) {
956         case IW_AUTH_PRIVACY_INVOKED:
957                 wdev->wext.connect.privacy = data->value;
958                 return 0;
959         case IW_AUTH_WPA_VERSION:
960                 return cfg80211_set_wpa_version(wdev, data->value);
961         case IW_AUTH_CIPHER_GROUP:
962                 return cfg80211_set_cipher_group(wdev, data->value);
963         case IW_AUTH_KEY_MGMT:
964                 return cfg80211_set_key_mgt(wdev, data->value);
965         case IW_AUTH_CIPHER_PAIRWISE:
966                 return cfg80211_set_cipher_pairwise(wdev, data->value);
967         case IW_AUTH_80211_AUTH_ALG:
968                 return cfg80211_set_auth_alg(wdev, data->value);
969         case IW_AUTH_WPA_ENABLED:
970         case IW_AUTH_RX_UNENCRYPTED_EAPOL:
971         case IW_AUTH_DROP_UNENCRYPTED:
972         case IW_AUTH_MFP:
973                 return 0;
974         default:
975                 return -EOPNOTSUPP;
976         }
977 }
978 EXPORT_SYMBOL_GPL(cfg80211_wext_siwauth);
979
980 int cfg80211_wext_giwauth(struct net_device *dev,
981                           struct iw_request_info *info,
982                           struct iw_param *data, char *extra)
983 {
984         /* XXX: what do we need? */
985
986         return -EOPNOTSUPP;
987 }
988 EXPORT_SYMBOL_GPL(cfg80211_wext_giwauth);
989
990 int cfg80211_wext_siwpower(struct net_device *dev,
991                            struct iw_request_info *info,
992                            struct iw_param *wrq, char *extra)
993 {
994         struct wireless_dev *wdev = dev->ieee80211_ptr;
995         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
996         bool ps = wdev->wext.ps;
997         int timeout = wdev->wext.ps_timeout;
998         int err;
999
1000         if (wdev->iftype != NL80211_IFTYPE_STATION)
1001                 return -EINVAL;
1002
1003         if (!rdev->ops->set_power_mgmt)
1004                 return -EOPNOTSUPP;
1005
1006         if (wrq->disabled) {
1007                 ps = false;
1008         } else {
1009                 switch (wrq->flags & IW_POWER_MODE) {
1010                 case IW_POWER_ON:       /* If not specified */
1011                 case IW_POWER_MODE:     /* If set all mask */
1012                 case IW_POWER_ALL_R:    /* If explicitely state all */
1013                         ps = true;
1014                         break;
1015                 default:                /* Otherwise we ignore */
1016                         return -EINVAL;
1017                 }
1018
1019                 if (wrq->flags & ~(IW_POWER_MODE | IW_POWER_TIMEOUT))
1020                         return -EINVAL;
1021
1022                 if (wrq->flags & IW_POWER_TIMEOUT)
1023                         timeout = wrq->value / 1000;
1024         }
1025
1026         err = rdev->ops->set_power_mgmt(wdev->wiphy, dev, ps, timeout);
1027         if (err)
1028                 return err;
1029
1030         wdev->wext.ps = ps;
1031         wdev->wext.ps_timeout = timeout;
1032
1033         return 0;
1034
1035 }
1036 EXPORT_SYMBOL_GPL(cfg80211_wext_siwpower);
1037
1038 int cfg80211_wext_giwpower(struct net_device *dev,
1039                            struct iw_request_info *info,
1040                            struct iw_param *wrq, char *extra)
1041 {
1042         struct wireless_dev *wdev = dev->ieee80211_ptr;
1043
1044         wrq->disabled = !wdev->wext.ps;
1045
1046         return 0;
1047 }
1048 EXPORT_SYMBOL_GPL(cfg80211_wext_giwpower);
1049
1050 int cfg80211_wds_wext_siwap(struct net_device *dev,
1051                             struct iw_request_info *info,
1052                             struct sockaddr *addr, char *extra)
1053 {
1054         struct wireless_dev *wdev = dev->ieee80211_ptr;
1055         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
1056         int err;
1057
1058         if (WARN_ON(wdev->iftype != NL80211_IFTYPE_WDS))
1059                 return -EINVAL;
1060
1061         if (addr->sa_family != ARPHRD_ETHER)
1062                 return -EINVAL;
1063
1064         if (netif_running(dev))
1065                 return -EBUSY;
1066
1067         if (!rdev->ops->set_wds_peer)
1068                 return -EOPNOTSUPP;
1069
1070         err = rdev->ops->set_wds_peer(wdev->wiphy, dev, (u8 *) &addr->sa_data);
1071         if (err)
1072                 return err;
1073
1074         memcpy(&wdev->wext.bssid, (u8 *) &addr->sa_data, ETH_ALEN);
1075
1076         return 0;
1077 }
1078 EXPORT_SYMBOL_GPL(cfg80211_wds_wext_siwap);
1079
1080 int cfg80211_wds_wext_giwap(struct net_device *dev,
1081                             struct iw_request_info *info,
1082                             struct sockaddr *addr, char *extra)
1083 {
1084         struct wireless_dev *wdev = dev->ieee80211_ptr;
1085
1086         if (WARN_ON(wdev->iftype != NL80211_IFTYPE_WDS))
1087                 return -EINVAL;
1088
1089         addr->sa_family = ARPHRD_ETHER;
1090         memcpy(&addr->sa_data, wdev->wext.bssid, ETH_ALEN);
1091
1092         return 0;
1093 }
1094 EXPORT_SYMBOL_GPL(cfg80211_wds_wext_giwap);
1095
1096 int cfg80211_wext_siwrate(struct net_device *dev,
1097                           struct iw_request_info *info,
1098                           struct iw_param *rate, char *extra)
1099 {
1100         struct wireless_dev *wdev = dev->ieee80211_ptr;
1101         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
1102         struct cfg80211_bitrate_mask mask;
1103
1104         if (!rdev->ops->set_bitrate_mask)
1105                 return -EOPNOTSUPP;
1106
1107         mask.fixed = 0;
1108         mask.maxrate = 0;
1109
1110         if (rate->value < 0) {
1111                 /* nothing */
1112         } else if (rate->fixed) {
1113                 mask.fixed = rate->value / 1000; /* kbps */
1114         } else {
1115                 mask.maxrate = rate->value / 1000; /* kbps */
1116         }
1117
1118         return rdev->ops->set_bitrate_mask(wdev->wiphy, dev, NULL, &mask);
1119 }
1120 EXPORT_SYMBOL_GPL(cfg80211_wext_siwrate);
1121
1122 int cfg80211_wext_giwrate(struct net_device *dev,
1123                           struct iw_request_info *info,
1124                           struct iw_param *rate, char *extra)
1125 {
1126         struct wireless_dev *wdev = dev->ieee80211_ptr;
1127         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
1128         /* we are under RTNL - globally locked - so can use a static struct */
1129         static struct station_info sinfo;
1130         u8 *addr;
1131         int err;
1132
1133         if (wdev->iftype != NL80211_IFTYPE_STATION)
1134                 return -EOPNOTSUPP;
1135
1136         if (!rdev->ops->get_station)
1137                 return -EOPNOTSUPP;
1138
1139         if (wdev->current_bss)
1140                 addr = wdev->current_bss->pub.bssid;
1141         else if (wdev->wext.connect.bssid)
1142                 addr = wdev->wext.connect.bssid;
1143         else
1144                 return -EOPNOTSUPP;
1145
1146         err = rdev->ops->get_station(&rdev->wiphy, dev, addr, &sinfo);
1147         if (err)
1148                 return err;
1149
1150         if (!(sinfo.filled & STATION_INFO_TX_BITRATE))
1151                 return -EOPNOTSUPP;
1152
1153         rate->value = 0;
1154
1155         if (!(sinfo.txrate.flags & RATE_INFO_FLAGS_MCS))
1156                 rate->value = 100000 * sinfo.txrate.legacy;
1157
1158         return 0;
1159 }
1160 EXPORT_SYMBOL_GPL(cfg80211_wext_giwrate);
1161
1162 /* Get wireless statistics.  Called by /proc/net/wireless and by SIOCGIWSTATS */
1163 struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev)
1164 {
1165         struct wireless_dev *wdev = dev->ieee80211_ptr;
1166         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
1167         /* we are under RTNL - globally locked - so can use static structs */
1168         static struct iw_statistics wstats;
1169         static struct station_info sinfo;
1170         u8 *addr;
1171
1172         if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION)
1173                 return NULL;
1174
1175         if (!rdev->ops->get_station)
1176                 return NULL;
1177
1178         addr = wdev->wext.connect.bssid;
1179         if (!addr)
1180                 return NULL;
1181
1182         if (rdev->ops->get_station(&rdev->wiphy, dev, addr, &sinfo))
1183                 return NULL;
1184
1185         memset(&wstats, 0, sizeof(wstats));
1186
1187         switch (rdev->wiphy.signal_type) {
1188         case CFG80211_SIGNAL_TYPE_MBM:
1189                 if (sinfo.filled & STATION_INFO_SIGNAL) {
1190                         int sig = sinfo.signal;
1191                         wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED;
1192                         wstats.qual.updated |= IW_QUAL_QUAL_UPDATED;
1193                         wstats.qual.updated |= IW_QUAL_DBM;
1194                         wstats.qual.level = sig;
1195                         if (sig < -110)
1196                                 sig = -110;
1197                         else if (sig > -40)
1198                                 sig = -40;
1199                         wstats.qual.qual = sig + 110;
1200                         break;
1201                 }
1202         case CFG80211_SIGNAL_TYPE_UNSPEC:
1203                 if (sinfo.filled & STATION_INFO_SIGNAL) {
1204                         wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED;
1205                         wstats.qual.updated |= IW_QUAL_QUAL_UPDATED;
1206                         wstats.qual.level = sinfo.signal;
1207                         wstats.qual.qual = sinfo.signal;
1208                         break;
1209                 }
1210         default:
1211                 wstats.qual.updated |= IW_QUAL_LEVEL_INVALID;
1212                 wstats.qual.updated |= IW_QUAL_QUAL_INVALID;
1213         }
1214
1215         wstats.qual.updated |= IW_QUAL_NOISE_INVALID;
1216
1217         return &wstats;
1218 }
1219 EXPORT_SYMBOL_GPL(cfg80211_wireless_stats);