]> git.karo-electronics.de Git - karo-tx-linux.git/blob - net/wireless/wext-compat.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
[karo-tx-linux.git] / 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 "wext-compat.h"
18 #include "core.h"
19
20 int cfg80211_wext_giwname(struct net_device *dev,
21                           struct iw_request_info *info,
22                           char *name, char *extra)
23 {
24         struct wireless_dev *wdev = dev->ieee80211_ptr;
25         struct ieee80211_supported_band *sband;
26         bool is_ht = false, is_a = false, is_b = false, is_g = false;
27
28         if (!wdev)
29                 return -EOPNOTSUPP;
30
31         sband = wdev->wiphy->bands[IEEE80211_BAND_5GHZ];
32         if (sband) {
33                 is_a = true;
34                 is_ht |= sband->ht_cap.ht_supported;
35         }
36
37         sband = wdev->wiphy->bands[IEEE80211_BAND_2GHZ];
38         if (sband) {
39                 int i;
40                 /* Check for mandatory rates */
41                 for (i = 0; i < sband->n_bitrates; i++) {
42                         if (sband->bitrates[i].bitrate == 10)
43                                 is_b = true;
44                         if (sband->bitrates[i].bitrate == 60)
45                                 is_g = true;
46                 }
47                 is_ht |= sband->ht_cap.ht_supported;
48         }
49
50         strcpy(name, "IEEE 802.11");
51         if (is_a)
52                 strcat(name, "a");
53         if (is_b)
54                 strcat(name, "b");
55         if (is_g)
56                 strcat(name, "g");
57         if (is_ht)
58                 strcat(name, "n");
59
60         return 0;
61 }
62 EXPORT_SYMBOL_GPL(cfg80211_wext_giwname);
63
64 int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
65                           u32 *mode, char *extra)
66 {
67         struct wireless_dev *wdev = dev->ieee80211_ptr;
68         struct cfg80211_registered_device *rdev;
69         struct vif_params vifparams;
70         enum nl80211_iftype type;
71         int ret;
72
73         rdev = wiphy_to_dev(wdev->wiphy);
74
75         switch (*mode) {
76         case IW_MODE_INFRA:
77                 type = NL80211_IFTYPE_STATION;
78                 break;
79         case IW_MODE_ADHOC:
80                 type = NL80211_IFTYPE_ADHOC;
81                 break;
82         case IW_MODE_REPEAT:
83                 type = NL80211_IFTYPE_WDS;
84                 break;
85         case IW_MODE_MONITOR:
86                 type = NL80211_IFTYPE_MONITOR;
87                 break;
88         default:
89                 return -EINVAL;
90         }
91
92         if (type == wdev->iftype)
93                 return 0;
94
95         memset(&vifparams, 0, sizeof(vifparams));
96
97         cfg80211_lock_rdev(rdev);
98         ret = cfg80211_change_iface(rdev, dev, type, NULL, &vifparams);
99         cfg80211_unlock_rdev(rdev);
100
101         return ret;
102 }
103 EXPORT_SYMBOL_GPL(cfg80211_wext_siwmode);
104
105 int cfg80211_wext_giwmode(struct net_device *dev, struct iw_request_info *info,
106                           u32 *mode, char *extra)
107 {
108         struct wireless_dev *wdev = dev->ieee80211_ptr;
109
110         if (!wdev)
111                 return -EOPNOTSUPP;
112
113         switch (wdev->iftype) {
114         case NL80211_IFTYPE_AP:
115                 *mode = IW_MODE_MASTER;
116                 break;
117         case NL80211_IFTYPE_STATION:
118                 *mode = IW_MODE_INFRA;
119                 break;
120         case NL80211_IFTYPE_ADHOC:
121                 *mode = IW_MODE_ADHOC;
122                 break;
123         case NL80211_IFTYPE_MONITOR:
124                 *mode = IW_MODE_MONITOR;
125                 break;
126         case NL80211_IFTYPE_WDS:
127                 *mode = IW_MODE_REPEAT;
128                 break;
129         case NL80211_IFTYPE_AP_VLAN:
130                 *mode = IW_MODE_SECOND;         /* FIXME */
131                 break;
132         default:
133                 *mode = IW_MODE_AUTO;
134                 break;
135         }
136         return 0;
137 }
138 EXPORT_SYMBOL_GPL(cfg80211_wext_giwmode);
139
140
141 int cfg80211_wext_giwrange(struct net_device *dev,
142                            struct iw_request_info *info,
143                            struct iw_point *data, char *extra)
144 {
145         struct wireless_dev *wdev = dev->ieee80211_ptr;
146         struct iw_range *range = (struct iw_range *) extra;
147         enum ieee80211_band band;
148         int i, c = 0;
149
150         if (!wdev)
151                 return -EOPNOTSUPP;
152
153         data->length = sizeof(struct iw_range);
154         memset(range, 0, sizeof(struct iw_range));
155
156         range->we_version_compiled = WIRELESS_EXT;
157         range->we_version_source = 21;
158         range->retry_capa = IW_RETRY_LIMIT;
159         range->retry_flags = IW_RETRY_LIMIT;
160         range->min_retry = 0;
161         range->max_retry = 255;
162         range->min_rts = 0;
163         range->max_rts = 2347;
164         range->min_frag = 256;
165         range->max_frag = 2346;
166
167         range->max_encoding_tokens = 4;
168
169         range->max_qual.updated = IW_QUAL_NOISE_INVALID;
170
171         switch (wdev->wiphy->signal_type) {
172         case CFG80211_SIGNAL_TYPE_NONE:
173                 break;
174         case CFG80211_SIGNAL_TYPE_MBM:
175                 range->max_qual.level = -110;
176                 range->max_qual.qual = 70;
177                 range->avg_qual.qual = 35;
178                 range->max_qual.updated |= IW_QUAL_DBM;
179                 range->max_qual.updated |= IW_QUAL_QUAL_UPDATED;
180                 range->max_qual.updated |= IW_QUAL_LEVEL_UPDATED;
181                 break;
182         case CFG80211_SIGNAL_TYPE_UNSPEC:
183                 range->max_qual.level = 100;
184                 range->max_qual.qual = 100;
185                 range->avg_qual.qual = 50;
186                 range->max_qual.updated |= IW_QUAL_QUAL_UPDATED;
187                 range->max_qual.updated |= IW_QUAL_LEVEL_UPDATED;
188                 break;
189         }
190
191         range->avg_qual.level = range->max_qual.level / 2;
192         range->avg_qual.noise = range->max_qual.noise / 2;
193         range->avg_qual.updated = range->max_qual.updated;
194
195         for (i = 0; i < wdev->wiphy->n_cipher_suites; i++) {
196                 switch (wdev->wiphy->cipher_suites[i]) {
197                 case WLAN_CIPHER_SUITE_TKIP:
198                         range->enc_capa |= (IW_ENC_CAPA_CIPHER_TKIP |
199                                             IW_ENC_CAPA_WPA);
200                         break;
201
202                 case WLAN_CIPHER_SUITE_CCMP:
203                         range->enc_capa |= (IW_ENC_CAPA_CIPHER_CCMP |
204                                             IW_ENC_CAPA_WPA2);
205                         break;
206
207                 case WLAN_CIPHER_SUITE_WEP40:
208                         range->encoding_size[range->num_encoding_sizes++] =
209                                 WLAN_KEY_LEN_WEP40;
210                         break;
211
212                 case WLAN_CIPHER_SUITE_WEP104:
213                         range->encoding_size[range->num_encoding_sizes++] =
214                                 WLAN_KEY_LEN_WEP104;
215                         break;
216                 }
217         }
218
219         for (band = 0; band < IEEE80211_NUM_BANDS; band ++) {
220                 struct ieee80211_supported_band *sband;
221
222                 sband = wdev->wiphy->bands[band];
223
224                 if (!sband)
225                         continue;
226
227                 for (i = 0; i < sband->n_channels && c < IW_MAX_FREQUENCIES; i++) {
228                         struct ieee80211_channel *chan = &sband->channels[i];
229
230                         if (!(chan->flags & IEEE80211_CHAN_DISABLED)) {
231                                 range->freq[c].i =
232                                         ieee80211_frequency_to_channel(
233                                                 chan->center_freq);
234                                 range->freq[c].m = chan->center_freq;
235                                 range->freq[c].e = 6;
236                                 c++;
237                         }
238                 }
239         }
240         range->num_channels = c;
241         range->num_frequency = c;
242
243         IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
244         IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
245         IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
246
247         if (wdev->wiphy->max_scan_ssids > 0)
248                 range->scan_capa |= IW_SCAN_CAPA_ESSID;
249
250         return 0;
251 }
252 EXPORT_SYMBOL_GPL(cfg80211_wext_giwrange);
253
254
255 /**
256  * cfg80211_wext_freq - get wext frequency for non-"auto"
257  * @wiphy: the wiphy
258  * @freq: the wext freq encoding
259  *
260  * Returns a frequency, or a negative error code, or 0 for auto.
261  */
262 int cfg80211_wext_freq(struct wiphy *wiphy, struct iw_freq *freq)
263 {
264         /*
265          * Parse frequency - return 0 for auto and
266          * -EINVAL for impossible things.
267          */
268         if (freq->e == 0) {
269                 if (freq->m < 0)
270                         return 0;
271                 return ieee80211_channel_to_frequency(freq->m);
272         } else {
273                 int i, div = 1000000;
274                 for (i = 0; i < freq->e; i++)
275                         div /= 10;
276                 if (div <= 0)
277                         return -EINVAL;
278                 return freq->m / div;
279         }
280 }
281
282 int cfg80211_wext_siwrts(struct net_device *dev,
283                          struct iw_request_info *info,
284                          struct iw_param *rts, char *extra)
285 {
286         struct wireless_dev *wdev = dev->ieee80211_ptr;
287         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
288         u32 orts = wdev->wiphy->rts_threshold;
289         int err;
290
291         if (rts->disabled || !rts->fixed)
292                 wdev->wiphy->rts_threshold = (u32) -1;
293         else if (rts->value < 0)
294                 return -EINVAL;
295         else
296                 wdev->wiphy->rts_threshold = rts->value;
297
298         err = rdev->ops->set_wiphy_params(wdev->wiphy,
299                                           WIPHY_PARAM_RTS_THRESHOLD);
300         if (err)
301                 wdev->wiphy->rts_threshold = orts;
302
303         return err;
304 }
305 EXPORT_SYMBOL_GPL(cfg80211_wext_siwrts);
306
307 int cfg80211_wext_giwrts(struct net_device *dev,
308                          struct iw_request_info *info,
309                          struct iw_param *rts, char *extra)
310 {
311         struct wireless_dev *wdev = dev->ieee80211_ptr;
312
313         rts->value = wdev->wiphy->rts_threshold;
314         rts->disabled = rts->value == (u32) -1;
315         rts->fixed = 1;
316
317         return 0;
318 }
319 EXPORT_SYMBOL_GPL(cfg80211_wext_giwrts);
320
321 int cfg80211_wext_siwfrag(struct net_device *dev,
322                           struct iw_request_info *info,
323                           struct iw_param *frag, char *extra)
324 {
325         struct wireless_dev *wdev = dev->ieee80211_ptr;
326         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
327         u32 ofrag = wdev->wiphy->frag_threshold;
328         int err;
329
330         if (frag->disabled || !frag->fixed)
331                 wdev->wiphy->frag_threshold = (u32) -1;
332         else if (frag->value < 256)
333                 return -EINVAL;
334         else {
335                 /* Fragment length must be even, so strip LSB. */
336                 wdev->wiphy->frag_threshold = frag->value & ~0x1;
337         }
338
339         err = rdev->ops->set_wiphy_params(wdev->wiphy,
340                                           WIPHY_PARAM_FRAG_THRESHOLD);
341         if (err)
342                 wdev->wiphy->frag_threshold = ofrag;
343
344         return err;
345 }
346 EXPORT_SYMBOL_GPL(cfg80211_wext_siwfrag);
347
348 int cfg80211_wext_giwfrag(struct net_device *dev,
349                           struct iw_request_info *info,
350                           struct iw_param *frag, char *extra)
351 {
352         struct wireless_dev *wdev = dev->ieee80211_ptr;
353
354         frag->value = wdev->wiphy->frag_threshold;
355         frag->disabled = frag->value == (u32) -1;
356         frag->fixed = 1;
357
358         return 0;
359 }
360 EXPORT_SYMBOL_GPL(cfg80211_wext_giwfrag);
361
362 int cfg80211_wext_siwretry(struct net_device *dev,
363                            struct iw_request_info *info,
364                            struct iw_param *retry, char *extra)
365 {
366         struct wireless_dev *wdev = dev->ieee80211_ptr;
367         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
368         u32 changed = 0;
369         u8 olong = wdev->wiphy->retry_long;
370         u8 oshort = wdev->wiphy->retry_short;
371         int err;
372
373         if (retry->disabled ||
374             (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
375                 return -EINVAL;
376
377         if (retry->flags & IW_RETRY_LONG) {
378                 wdev->wiphy->retry_long = retry->value;
379                 changed |= WIPHY_PARAM_RETRY_LONG;
380         } else if (retry->flags & IW_RETRY_SHORT) {
381                 wdev->wiphy->retry_short = retry->value;
382                 changed |= WIPHY_PARAM_RETRY_SHORT;
383         } else {
384                 wdev->wiphy->retry_short = retry->value;
385                 wdev->wiphy->retry_long = retry->value;
386                 changed |= WIPHY_PARAM_RETRY_LONG;
387                 changed |= WIPHY_PARAM_RETRY_SHORT;
388         }
389
390         if (!changed)
391                 return 0;
392
393         err = rdev->ops->set_wiphy_params(wdev->wiphy, changed);
394         if (err) {
395                 wdev->wiphy->retry_short = oshort;
396                 wdev->wiphy->retry_long = olong;
397         }
398
399         return err;
400 }
401 EXPORT_SYMBOL_GPL(cfg80211_wext_siwretry);
402
403 int cfg80211_wext_giwretry(struct net_device *dev,
404                            struct iw_request_info *info,
405                            struct iw_param *retry, char *extra)
406 {
407         struct wireless_dev *wdev = dev->ieee80211_ptr;
408
409         retry->disabled = 0;
410
411         if (retry->flags == 0 || (retry->flags & IW_RETRY_SHORT)) {
412                 /*
413                  * First return short value, iwconfig will ask long value
414                  * later if needed
415                  */
416                 retry->flags |= IW_RETRY_LIMIT;
417                 retry->value = wdev->wiphy->retry_short;
418                 if (wdev->wiphy->retry_long != wdev->wiphy->retry_short)
419                         retry->flags |= IW_RETRY_LONG;
420
421                 return 0;
422         }
423
424         if (retry->flags & IW_RETRY_LONG) {
425                 retry->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
426                 retry->value = wdev->wiphy->retry_long;
427         }
428
429         return 0;
430 }
431 EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry);
432
433 static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
434                                      struct net_device *dev, const u8 *addr,
435                                      bool remove, bool tx_key, int idx,
436                                      struct key_params *params)
437 {
438         struct wireless_dev *wdev = dev->ieee80211_ptr;
439         int err, i;
440         bool rejoin = false;
441
442         if (!wdev->wext.keys) {
443                 wdev->wext.keys = kzalloc(sizeof(*wdev->wext.keys),
444                                               GFP_KERNEL);
445                 if (!wdev->wext.keys)
446                         return -ENOMEM;
447                 for (i = 0; i < 6; i++)
448                         wdev->wext.keys->params[i].key =
449                                 wdev->wext.keys->data[i];
450         }
451
452         if (wdev->iftype != NL80211_IFTYPE_ADHOC &&
453             wdev->iftype != NL80211_IFTYPE_STATION)
454                 return -EOPNOTSUPP;
455
456         if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
457                 if (!wdev->current_bss)
458                         return -ENOLINK;
459
460                 if (!rdev->ops->set_default_mgmt_key)
461                         return -EOPNOTSUPP;
462
463                 if (idx < 4 || idx > 5)
464                         return -EINVAL;
465         } else if (idx < 0 || idx > 3)
466                 return -EINVAL;
467
468         if (remove) {
469                 err = 0;
470                 if (wdev->current_bss) {
471                         /*
472                          * If removing the current TX key, we will need to
473                          * join a new IBSS without the privacy bit clear.
474                          */
475                         if (idx == wdev->wext.default_key &&
476                             wdev->iftype == NL80211_IFTYPE_ADHOC) {
477                                 __cfg80211_leave_ibss(rdev, wdev->netdev, true);
478                                 rejoin = true;
479                         }
480                         err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr);
481                 }
482                 wdev->wext.connect.privacy = false;
483                 /*
484                  * Applications using wireless extensions expect to be
485                  * able to delete keys that don't exist, so allow that.
486                  */
487                 if (err == -ENOENT)
488                         err = 0;
489                 if (!err) {
490                         if (!addr) {
491                                 wdev->wext.keys->params[idx].key_len = 0;
492                                 wdev->wext.keys->params[idx].cipher = 0;
493                         }
494                         if (idx == wdev->wext.default_key)
495                                 wdev->wext.default_key = -1;
496                         else if (idx == wdev->wext.default_mgmt_key)
497                                 wdev->wext.default_mgmt_key = -1;
498                 }
499
500                 if (!err && rejoin)
501                         err = cfg80211_ibss_wext_join(rdev, wdev);
502
503                 return err;
504         }
505
506         if (addr)
507                 tx_key = false;
508
509         if (cfg80211_validate_key_settings(rdev, params, idx, addr))
510                 return -EINVAL;
511
512         err = 0;
513         if (wdev->current_bss)
514                 err = rdev->ops->add_key(&rdev->wiphy, dev, idx, addr, params);
515         if (err)
516                 return err;
517
518         if (!addr) {
519                 wdev->wext.keys->params[idx] = *params;
520                 memcpy(wdev->wext.keys->data[idx],
521                         params->key, params->key_len);
522                 wdev->wext.keys->params[idx].key =
523                         wdev->wext.keys->data[idx];
524         }
525
526         if ((params->cipher == WLAN_CIPHER_SUITE_WEP40 ||
527              params->cipher == WLAN_CIPHER_SUITE_WEP104) &&
528             (tx_key || (!addr && wdev->wext.default_key == -1))) {
529                 if (wdev->current_bss) {
530                         /*
531                          * If we are getting a new TX key from not having
532                          * had one before we need to join a new IBSS with
533                          * the privacy bit set.
534                          */
535                         if (wdev->iftype == NL80211_IFTYPE_ADHOC &&
536                             wdev->wext.default_key == -1) {
537                                 __cfg80211_leave_ibss(rdev, wdev->netdev, true);
538                                 rejoin = true;
539                         }
540                         err = rdev->ops->set_default_key(&rdev->wiphy,
541                                                          dev, idx);
542                 }
543                 if (!err) {
544                         wdev->wext.default_key = idx;
545                         if (rejoin)
546                                 err = cfg80211_ibss_wext_join(rdev, wdev);
547                 }
548                 return err;
549         }
550
551         if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC &&
552             (tx_key || (!addr && wdev->wext.default_mgmt_key == -1))) {
553                 if (wdev->current_bss)
554                         err = rdev->ops->set_default_mgmt_key(&rdev->wiphy,
555                                                               dev, idx);
556                 if (!err)
557                         wdev->wext.default_mgmt_key = idx;
558                 return err;
559         }
560
561         return 0;
562 }
563
564 static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
565                                    struct net_device *dev, const u8 *addr,
566                                    bool remove, bool tx_key, int idx,
567                                    struct key_params *params)
568 {
569         int err;
570
571         /* devlist mutex needed for possible IBSS re-join */
572         mutex_lock(&rdev->devlist_mtx);
573         wdev_lock(dev->ieee80211_ptr);
574         err = __cfg80211_set_encryption(rdev, dev, addr, remove,
575                                         tx_key, idx, params);
576         wdev_unlock(dev->ieee80211_ptr);
577         mutex_unlock(&rdev->devlist_mtx);
578
579         return err;
580 }
581
582 int cfg80211_wext_siwencode(struct net_device *dev,
583                             struct iw_request_info *info,
584                             struct iw_point *erq, char *keybuf)
585 {
586         struct wireless_dev *wdev = dev->ieee80211_ptr;
587         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
588         int idx, err;
589         bool remove = false;
590         struct key_params params;
591
592         if (wdev->iftype != NL80211_IFTYPE_STATION &&
593             wdev->iftype != NL80211_IFTYPE_ADHOC)
594                 return -EOPNOTSUPP;
595
596         /* no use -- only MFP (set_default_mgmt_key) is optional */
597         if (!rdev->ops->del_key ||
598             !rdev->ops->add_key ||
599             !rdev->ops->set_default_key)
600                 return -EOPNOTSUPP;
601
602         idx = erq->flags & IW_ENCODE_INDEX;
603         if (idx == 0) {
604                 idx = wdev->wext.default_key;
605                 if (idx < 0)
606                         idx = 0;
607         } else if (idx < 1 || idx > 4)
608                 return -EINVAL;
609         else
610                 idx--;
611
612         if (erq->flags & IW_ENCODE_DISABLED)
613                 remove = true;
614         else if (erq->length == 0) {
615                 /* No key data - just set the default TX key index */
616                 err = 0;
617                 wdev_lock(wdev);
618                 if (wdev->current_bss)
619                         err = rdev->ops->set_default_key(&rdev->wiphy,
620                                                          dev, idx);
621                 if (!err)
622                         wdev->wext.default_key = idx;
623                 wdev_unlock(wdev);
624                 return err;
625         }
626
627         memset(&params, 0, sizeof(params));
628         params.key = keybuf;
629         params.key_len = erq->length;
630         if (erq->length == 5)
631                 params.cipher = WLAN_CIPHER_SUITE_WEP40;
632         else if (erq->length == 13)
633                 params.cipher = WLAN_CIPHER_SUITE_WEP104;
634         else if (!remove)
635                 return -EINVAL;
636
637         return cfg80211_set_encryption(rdev, dev, NULL, remove,
638                                        wdev->wext.default_key == -1,
639                                        idx, &params);
640 }
641 EXPORT_SYMBOL_GPL(cfg80211_wext_siwencode);
642
643 int cfg80211_wext_siwencodeext(struct net_device *dev,
644                                struct iw_request_info *info,
645                                struct iw_point *erq, char *extra)
646 {
647         struct wireless_dev *wdev = dev->ieee80211_ptr;
648         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
649         struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
650         const u8 *addr;
651         int idx;
652         bool remove = false;
653         struct key_params params;
654         u32 cipher;
655
656         if (wdev->iftype != NL80211_IFTYPE_STATION &&
657             wdev->iftype != NL80211_IFTYPE_ADHOC)
658                 return -EOPNOTSUPP;
659
660         /* no use -- only MFP (set_default_mgmt_key) is optional */
661         if (!rdev->ops->del_key ||
662             !rdev->ops->add_key ||
663             !rdev->ops->set_default_key)
664                 return -EOPNOTSUPP;
665
666         switch (ext->alg) {
667         case IW_ENCODE_ALG_NONE:
668                 remove = true;
669                 cipher = 0;
670                 break;
671         case IW_ENCODE_ALG_WEP:
672                 if (ext->key_len == 5)
673                         cipher = WLAN_CIPHER_SUITE_WEP40;
674                 else if (ext->key_len == 13)
675                         cipher = WLAN_CIPHER_SUITE_WEP104;
676                 else
677                         return -EINVAL;
678                 break;
679         case IW_ENCODE_ALG_TKIP:
680                 cipher = WLAN_CIPHER_SUITE_TKIP;
681                 break;
682         case IW_ENCODE_ALG_CCMP:
683                 cipher = WLAN_CIPHER_SUITE_CCMP;
684                 break;
685         case IW_ENCODE_ALG_AES_CMAC:
686                 cipher = WLAN_CIPHER_SUITE_AES_CMAC;
687                 break;
688         default:
689                 return -EOPNOTSUPP;
690         }
691
692         if (erq->flags & IW_ENCODE_DISABLED)
693                 remove = true;
694
695         idx = erq->flags & IW_ENCODE_INDEX;
696         if (cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
697                 if (idx < 4 || idx > 5) {
698                         idx = wdev->wext.default_mgmt_key;
699                         if (idx < 0)
700                                 return -EINVAL;
701                 } else
702                         idx--;
703         } else {
704                 if (idx < 1 || idx > 4) {
705                         idx = wdev->wext.default_key;
706                         if (idx < 0)
707                                 return -EINVAL;
708                 } else
709                         idx--;
710         }
711
712         addr = ext->addr.sa_data;
713         if (is_broadcast_ether_addr(addr))
714                 addr = NULL;
715
716         memset(&params, 0, sizeof(params));
717         params.key = ext->key;
718         params.key_len = ext->key_len;
719         params.cipher = cipher;
720
721         if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
722                 params.seq = ext->rx_seq;
723                 params.seq_len = 6;
724         }
725
726         return cfg80211_set_encryption(
727                         rdev, dev, addr, remove,
728                         ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
729                         idx, &params);
730 }
731 EXPORT_SYMBOL_GPL(cfg80211_wext_siwencodeext);
732
733 int cfg80211_wext_giwencode(struct net_device *dev,
734                             struct iw_request_info *info,
735                             struct iw_point *erq, char *keybuf)
736 {
737         struct wireless_dev *wdev = dev->ieee80211_ptr;
738         int idx;
739
740         if (wdev->iftype != NL80211_IFTYPE_STATION &&
741             wdev->iftype != NL80211_IFTYPE_ADHOC)
742                 return -EOPNOTSUPP;
743
744         idx = erq->flags & IW_ENCODE_INDEX;
745         if (idx == 0) {
746                 idx = wdev->wext.default_key;
747                 if (idx < 0)
748                         idx = 0;
749         } else if (idx < 1 || idx > 4)
750                 return -EINVAL;
751         else
752                 idx--;
753
754         erq->flags = idx + 1;
755
756         if (!wdev->wext.keys || !wdev->wext.keys->params[idx].cipher) {
757                 erq->flags |= IW_ENCODE_DISABLED;
758                 erq->length = 0;
759                 return 0;
760         }
761
762         erq->length = min_t(size_t, erq->length,
763                             wdev->wext.keys->params[idx].key_len);
764         memcpy(keybuf, wdev->wext.keys->params[idx].key, erq->length);
765         erq->flags |= IW_ENCODE_ENABLED;
766
767         return 0;
768 }
769 EXPORT_SYMBOL_GPL(cfg80211_wext_giwencode);
770
771 int cfg80211_wext_siwfreq(struct net_device *dev,
772                           struct iw_request_info *info,
773                           struct iw_freq *wextfreq, char *extra)
774 {
775         struct wireless_dev *wdev = dev->ieee80211_ptr;
776         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
777         int freq, err;
778
779         switch (wdev->iftype) {
780         case NL80211_IFTYPE_STATION:
781                 return cfg80211_mgd_wext_siwfreq(dev, info, wextfreq, extra);
782         case NL80211_IFTYPE_ADHOC:
783                 return cfg80211_ibss_wext_siwfreq(dev, info, wextfreq, extra);
784         default:
785                 freq = cfg80211_wext_freq(wdev->wiphy, wextfreq);
786                 if (freq < 0)
787                         return freq;
788                 if (freq == 0)
789                         return -EINVAL;
790                 mutex_lock(&rdev->devlist_mtx);
791                 err = rdev_set_freq(rdev, NULL, freq, NL80211_CHAN_NO_HT);
792                 mutex_unlock(&rdev->devlist_mtx);
793                 return err;
794         }
795 }
796 EXPORT_SYMBOL_GPL(cfg80211_wext_siwfreq);
797
798 int cfg80211_wext_giwfreq(struct net_device *dev,
799                           struct iw_request_info *info,
800                           struct iw_freq *freq, char *extra)
801 {
802         struct wireless_dev *wdev = dev->ieee80211_ptr;
803         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
804
805         switch (wdev->iftype) {
806         case NL80211_IFTYPE_STATION:
807                 return cfg80211_mgd_wext_giwfreq(dev, info, freq, extra);
808         case NL80211_IFTYPE_ADHOC:
809                 return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra);
810         default:
811                 if (!rdev->channel)
812                         return -EINVAL;
813                 freq->m = rdev->channel->center_freq;
814                 freq->e = 6;
815                 return 0;
816         }
817 }
818 EXPORT_SYMBOL_GPL(cfg80211_wext_giwfreq);
819
820 int cfg80211_wext_siwtxpower(struct net_device *dev,
821                              struct iw_request_info *info,
822                              union iwreq_data *data, char *extra)
823 {
824         struct wireless_dev *wdev = dev->ieee80211_ptr;
825         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
826         enum tx_power_setting type;
827         int dbm = 0;
828
829         if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
830                 return -EINVAL;
831         if (data->txpower.flags & IW_TXPOW_RANGE)
832                 return -EINVAL;
833
834         if (!rdev->ops->set_tx_power)
835                 return -EOPNOTSUPP;
836
837         /* only change when not disabling */
838         if (!data->txpower.disabled) {
839                 rfkill_set_sw_state(rdev->rfkill, false);
840
841                 if (data->txpower.fixed) {
842                         /*
843                          * wext doesn't support negative values, see
844                          * below where it's for automatic
845                          */
846                         if (data->txpower.value < 0)
847                                 return -EINVAL;
848                         dbm = data->txpower.value;
849                         type = TX_POWER_FIXED;
850                         /* TODO: do regulatory check! */
851                 } else {
852                         /*
853                          * Automatic power level setting, max being the value
854                          * passed in from userland.
855                          */
856                         if (data->txpower.value < 0) {
857                                 type = TX_POWER_AUTOMATIC;
858                         } else {
859                                 dbm = data->txpower.value;
860                                 type = TX_POWER_LIMITED;
861                         }
862                 }
863         } else {
864                 rfkill_set_sw_state(rdev->rfkill, true);
865                 schedule_work(&rdev->rfkill_sync);
866                 return 0;
867         }
868
869         return rdev->ops->set_tx_power(wdev->wiphy, type, dbm);
870 }
871 EXPORT_SYMBOL_GPL(cfg80211_wext_siwtxpower);
872
873 int cfg80211_wext_giwtxpower(struct net_device *dev,
874                              struct iw_request_info *info,
875                              union iwreq_data *data, char *extra)
876 {
877         struct wireless_dev *wdev = dev->ieee80211_ptr;
878         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
879         int err, val;
880
881         if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
882                 return -EINVAL;
883         if (data->txpower.flags & IW_TXPOW_RANGE)
884                 return -EINVAL;
885
886         if (!rdev->ops->get_tx_power)
887                 return -EOPNOTSUPP;
888
889         err = rdev->ops->get_tx_power(wdev->wiphy, &val);
890         if (err)
891                 return err;
892
893         /* well... oh well */
894         data->txpower.fixed = 1;
895         data->txpower.disabled = rfkill_blocked(rdev->rfkill);
896         data->txpower.value = val;
897         data->txpower.flags = IW_TXPOW_DBM;
898
899         return 0;
900 }
901 EXPORT_SYMBOL_GPL(cfg80211_wext_giwtxpower);
902
903 static int cfg80211_set_auth_alg(struct wireless_dev *wdev,
904                                  s32 auth_alg)
905 {
906         int nr_alg = 0;
907
908         if (!auth_alg)
909                 return -EINVAL;
910
911         if (auth_alg & ~(IW_AUTH_ALG_OPEN_SYSTEM |
912                          IW_AUTH_ALG_SHARED_KEY |
913                          IW_AUTH_ALG_LEAP))
914                 return -EINVAL;
915
916         if (auth_alg & IW_AUTH_ALG_OPEN_SYSTEM) {
917                 nr_alg++;
918                 wdev->wext.connect.auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM;
919         }
920
921         if (auth_alg & IW_AUTH_ALG_SHARED_KEY) {
922                 nr_alg++;
923                 wdev->wext.connect.auth_type = NL80211_AUTHTYPE_SHARED_KEY;
924         }
925
926         if (auth_alg & IW_AUTH_ALG_LEAP) {
927                 nr_alg++;
928                 wdev->wext.connect.auth_type = NL80211_AUTHTYPE_NETWORK_EAP;
929         }
930
931         if (nr_alg > 1)
932                 wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
933
934         return 0;
935 }
936
937 static int cfg80211_set_wpa_version(struct wireless_dev *wdev, u32 wpa_versions)
938 {
939         if (wpa_versions & ~(IW_AUTH_WPA_VERSION_WPA |
940                              IW_AUTH_WPA_VERSION_WPA2|
941                              IW_AUTH_WPA_VERSION_DISABLED))
942                 return -EINVAL;
943
944         if ((wpa_versions & IW_AUTH_WPA_VERSION_DISABLED) &&
945             (wpa_versions & (IW_AUTH_WPA_VERSION_WPA|
946                              IW_AUTH_WPA_VERSION_WPA2)))
947                 return -EINVAL;
948
949         if (wpa_versions & IW_AUTH_WPA_VERSION_DISABLED)
950                 wdev->wext.connect.crypto.wpa_versions &=
951                         ~(NL80211_WPA_VERSION_1|NL80211_WPA_VERSION_2);
952
953         if (wpa_versions & IW_AUTH_WPA_VERSION_WPA)
954                 wdev->wext.connect.crypto.wpa_versions |=
955                         NL80211_WPA_VERSION_1;
956
957         if (wpa_versions & IW_AUTH_WPA_VERSION_WPA2)
958                 wdev->wext.connect.crypto.wpa_versions |=
959                         NL80211_WPA_VERSION_2;
960
961         return 0;
962 }
963
964 static int cfg80211_set_cipher_group(struct wireless_dev *wdev, u32 cipher)
965 {
966         if (cipher & IW_AUTH_CIPHER_WEP40)
967                 wdev->wext.connect.crypto.cipher_group =
968                         WLAN_CIPHER_SUITE_WEP40;
969         else if (cipher & IW_AUTH_CIPHER_WEP104)
970                 wdev->wext.connect.crypto.cipher_group =
971                         WLAN_CIPHER_SUITE_WEP104;
972         else if (cipher & IW_AUTH_CIPHER_TKIP)
973                 wdev->wext.connect.crypto.cipher_group =
974                         WLAN_CIPHER_SUITE_TKIP;
975         else if (cipher & IW_AUTH_CIPHER_CCMP)
976                 wdev->wext.connect.crypto.cipher_group =
977                         WLAN_CIPHER_SUITE_CCMP;
978         else if (cipher & IW_AUTH_CIPHER_AES_CMAC)
979                 wdev->wext.connect.crypto.cipher_group =
980                         WLAN_CIPHER_SUITE_AES_CMAC;
981         else if (cipher & IW_AUTH_CIPHER_NONE)
982                 wdev->wext.connect.crypto.cipher_group = 0;
983         else
984                 return -EINVAL;
985
986         return 0;
987 }
988
989 static int cfg80211_set_cipher_pairwise(struct wireless_dev *wdev, u32 cipher)
990 {
991         int nr_ciphers = 0;
992         u32 *ciphers_pairwise = wdev->wext.connect.crypto.ciphers_pairwise;
993
994         if (cipher & IW_AUTH_CIPHER_WEP40) {
995                 ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_WEP40;
996                 nr_ciphers++;
997         }
998
999         if (cipher & IW_AUTH_CIPHER_WEP104) {
1000                 ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_WEP104;
1001                 nr_ciphers++;
1002         }
1003
1004         if (cipher & IW_AUTH_CIPHER_TKIP) {
1005                 ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_TKIP;
1006                 nr_ciphers++;
1007         }
1008
1009         if (cipher & IW_AUTH_CIPHER_CCMP) {
1010                 ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_CCMP;
1011                 nr_ciphers++;
1012         }
1013
1014         if (cipher & IW_AUTH_CIPHER_AES_CMAC) {
1015                 ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_AES_CMAC;
1016                 nr_ciphers++;
1017         }
1018
1019         BUILD_BUG_ON(NL80211_MAX_NR_CIPHER_SUITES < 5);
1020
1021         wdev->wext.connect.crypto.n_ciphers_pairwise = nr_ciphers;
1022
1023         return 0;
1024 }
1025
1026
1027 static int cfg80211_set_key_mgt(struct wireless_dev *wdev, u32 key_mgt)
1028 {
1029         int nr_akm_suites = 0;
1030
1031         if (key_mgt & ~(IW_AUTH_KEY_MGMT_802_1X |
1032                         IW_AUTH_KEY_MGMT_PSK))
1033                 return -EINVAL;
1034
1035         if (key_mgt & IW_AUTH_KEY_MGMT_802_1X) {
1036                 wdev->wext.connect.crypto.akm_suites[nr_akm_suites] =
1037                         WLAN_AKM_SUITE_8021X;
1038                 nr_akm_suites++;
1039         }
1040
1041         if (key_mgt & IW_AUTH_KEY_MGMT_PSK) {
1042                 wdev->wext.connect.crypto.akm_suites[nr_akm_suites] =
1043                         WLAN_AKM_SUITE_PSK;
1044                 nr_akm_suites++;
1045         }
1046
1047         wdev->wext.connect.crypto.n_akm_suites = nr_akm_suites;
1048
1049         return 0;
1050 }
1051
1052 int cfg80211_wext_siwauth(struct net_device *dev,
1053                           struct iw_request_info *info,
1054                           struct iw_param *data, char *extra)
1055 {
1056         struct wireless_dev *wdev = dev->ieee80211_ptr;
1057
1058         if (wdev->iftype != NL80211_IFTYPE_STATION)
1059                 return -EOPNOTSUPP;
1060
1061         switch (data->flags & IW_AUTH_INDEX) {
1062         case IW_AUTH_PRIVACY_INVOKED:
1063                 wdev->wext.connect.privacy = data->value;
1064                 return 0;
1065         case IW_AUTH_WPA_VERSION:
1066                 return cfg80211_set_wpa_version(wdev, data->value);
1067         case IW_AUTH_CIPHER_GROUP:
1068                 return cfg80211_set_cipher_group(wdev, data->value);
1069         case IW_AUTH_KEY_MGMT:
1070                 return cfg80211_set_key_mgt(wdev, data->value);
1071         case IW_AUTH_CIPHER_PAIRWISE:
1072                 return cfg80211_set_cipher_pairwise(wdev, data->value);
1073         case IW_AUTH_80211_AUTH_ALG:
1074                 return cfg80211_set_auth_alg(wdev, data->value);
1075         case IW_AUTH_WPA_ENABLED:
1076         case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1077         case IW_AUTH_DROP_UNENCRYPTED:
1078         case IW_AUTH_MFP:
1079                 return 0;
1080         default:
1081                 return -EOPNOTSUPP;
1082         }
1083 }
1084 EXPORT_SYMBOL_GPL(cfg80211_wext_siwauth);
1085
1086 int cfg80211_wext_giwauth(struct net_device *dev,
1087                           struct iw_request_info *info,
1088                           struct iw_param *data, char *extra)
1089 {
1090         /* XXX: what do we need? */
1091
1092         return -EOPNOTSUPP;
1093 }
1094 EXPORT_SYMBOL_GPL(cfg80211_wext_giwauth);
1095
1096 int cfg80211_wext_siwpower(struct net_device *dev,
1097                            struct iw_request_info *info,
1098                            struct iw_param *wrq, char *extra)
1099 {
1100         struct wireless_dev *wdev = dev->ieee80211_ptr;
1101         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
1102         bool ps = wdev->wext.ps;
1103         int timeout = wdev->wext.ps_timeout;
1104         int err;
1105
1106         if (wdev->iftype != NL80211_IFTYPE_STATION)
1107                 return -EINVAL;
1108
1109         if (!rdev->ops->set_power_mgmt)
1110                 return -EOPNOTSUPP;
1111
1112         if (wrq->disabled) {
1113                 ps = false;
1114         } else {
1115                 switch (wrq->flags & IW_POWER_MODE) {
1116                 case IW_POWER_ON:       /* If not specified */
1117                 case IW_POWER_MODE:     /* If set all mask */
1118                 case IW_POWER_ALL_R:    /* If explicitely state all */
1119                         ps = true;
1120                         break;
1121                 default:                /* Otherwise we ignore */
1122                         return -EINVAL;
1123                 }
1124
1125                 if (wrq->flags & ~(IW_POWER_MODE | IW_POWER_TIMEOUT))
1126                         return -EINVAL;
1127
1128                 if (wrq->flags & IW_POWER_TIMEOUT)
1129                         timeout = wrq->value / 1000;
1130         }
1131
1132         err = rdev->ops->set_power_mgmt(wdev->wiphy, dev, ps, timeout);
1133         if (err)
1134                 return err;
1135
1136         wdev->wext.ps = ps;
1137         wdev->wext.ps_timeout = timeout;
1138
1139         return 0;
1140
1141 }
1142 EXPORT_SYMBOL_GPL(cfg80211_wext_siwpower);
1143
1144 int cfg80211_wext_giwpower(struct net_device *dev,
1145                            struct iw_request_info *info,
1146                            struct iw_param *wrq, char *extra)
1147 {
1148         struct wireless_dev *wdev = dev->ieee80211_ptr;
1149
1150         wrq->disabled = !wdev->wext.ps;
1151
1152         return 0;
1153 }
1154 EXPORT_SYMBOL_GPL(cfg80211_wext_giwpower);
1155
1156 static int cfg80211_wds_wext_siwap(struct net_device *dev,
1157                                    struct iw_request_info *info,
1158                                    struct sockaddr *addr, char *extra)
1159 {
1160         struct wireless_dev *wdev = dev->ieee80211_ptr;
1161         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
1162         int err;
1163
1164         if (WARN_ON(wdev->iftype != NL80211_IFTYPE_WDS))
1165                 return -EINVAL;
1166
1167         if (addr->sa_family != ARPHRD_ETHER)
1168                 return -EINVAL;
1169
1170         if (netif_running(dev))
1171                 return -EBUSY;
1172
1173         if (!rdev->ops->set_wds_peer)
1174                 return -EOPNOTSUPP;
1175
1176         err = rdev->ops->set_wds_peer(wdev->wiphy, dev, (u8 *) &addr->sa_data);
1177         if (err)
1178                 return err;
1179
1180         memcpy(&wdev->wext.bssid, (u8 *) &addr->sa_data, ETH_ALEN);
1181
1182         return 0;
1183 }
1184
1185 static int cfg80211_wds_wext_giwap(struct net_device *dev,
1186                                    struct iw_request_info *info,
1187                                    struct sockaddr *addr, char *extra)
1188 {
1189         struct wireless_dev *wdev = dev->ieee80211_ptr;
1190
1191         if (WARN_ON(wdev->iftype != NL80211_IFTYPE_WDS))
1192                 return -EINVAL;
1193
1194         addr->sa_family = ARPHRD_ETHER;
1195         memcpy(&addr->sa_data, wdev->wext.bssid, ETH_ALEN);
1196
1197         return 0;
1198 }
1199
1200 int cfg80211_wext_siwrate(struct net_device *dev,
1201                           struct iw_request_info *info,
1202                           struct iw_param *rate, char *extra)
1203 {
1204         struct wireless_dev *wdev = dev->ieee80211_ptr;
1205         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
1206         struct cfg80211_bitrate_mask mask;
1207
1208         if (!rdev->ops->set_bitrate_mask)
1209                 return -EOPNOTSUPP;
1210
1211         mask.fixed = 0;
1212         mask.maxrate = 0;
1213
1214         if (rate->value < 0) {
1215                 /* nothing */
1216         } else if (rate->fixed) {
1217                 mask.fixed = rate->value / 1000; /* kbps */
1218         } else {
1219                 mask.maxrate = rate->value / 1000; /* kbps */
1220         }
1221
1222         return rdev->ops->set_bitrate_mask(wdev->wiphy, dev, NULL, &mask);
1223 }
1224 EXPORT_SYMBOL_GPL(cfg80211_wext_siwrate);
1225
1226 int cfg80211_wext_giwrate(struct net_device *dev,
1227                           struct iw_request_info *info,
1228                           struct iw_param *rate, char *extra)
1229 {
1230         struct wireless_dev *wdev = dev->ieee80211_ptr;
1231         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
1232         /* we are under RTNL - globally locked - so can use a static struct */
1233         static struct station_info sinfo;
1234         u8 addr[ETH_ALEN];
1235         int err;
1236
1237         if (wdev->iftype != NL80211_IFTYPE_STATION)
1238                 return -EOPNOTSUPP;
1239
1240         if (!rdev->ops->get_station)
1241                 return -EOPNOTSUPP;
1242
1243         err = 0;
1244         wdev_lock(wdev);
1245         if (wdev->current_bss)
1246                 memcpy(addr, wdev->current_bss->pub.bssid, ETH_ALEN);
1247         else
1248                 err = -EOPNOTSUPP;
1249         wdev_unlock(wdev);
1250         if (err)
1251                 return err;
1252
1253         err = rdev->ops->get_station(&rdev->wiphy, dev, addr, &sinfo);
1254         if (err)
1255                 return err;
1256
1257         if (!(sinfo.filled & STATION_INFO_TX_BITRATE))
1258                 return -EOPNOTSUPP;
1259
1260         rate->value = 0;
1261
1262         if (!(sinfo.txrate.flags & RATE_INFO_FLAGS_MCS))
1263                 rate->value = 100000 * sinfo.txrate.legacy;
1264
1265         return 0;
1266 }
1267 EXPORT_SYMBOL_GPL(cfg80211_wext_giwrate);
1268
1269 /* Get wireless statistics.  Called by /proc/net/wireless and by SIOCGIWSTATS */
1270 struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev)
1271 {
1272         struct wireless_dev *wdev = dev->ieee80211_ptr;
1273         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
1274         /* we are under RTNL - globally locked - so can use static structs */
1275         static struct iw_statistics wstats;
1276         static struct station_info sinfo;
1277         u8 bssid[ETH_ALEN];
1278
1279         if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION)
1280                 return NULL;
1281
1282         if (!rdev->ops->get_station)
1283                 return NULL;
1284
1285         /* Grab BSSID of current BSS, if any */
1286         wdev_lock(wdev);
1287         if (!wdev->current_bss) {
1288                 wdev_unlock(wdev);
1289                 return NULL;
1290         }
1291         memcpy(bssid, wdev->current_bss->pub.bssid, ETH_ALEN);
1292         wdev_unlock(wdev);
1293
1294         if (rdev->ops->get_station(&rdev->wiphy, dev, bssid, &sinfo))
1295                 return NULL;
1296
1297         memset(&wstats, 0, sizeof(wstats));
1298
1299         switch (rdev->wiphy.signal_type) {
1300         case CFG80211_SIGNAL_TYPE_MBM:
1301                 if (sinfo.filled & STATION_INFO_SIGNAL) {
1302                         int sig = sinfo.signal;
1303                         wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED;
1304                         wstats.qual.updated |= IW_QUAL_QUAL_UPDATED;
1305                         wstats.qual.updated |= IW_QUAL_DBM;
1306                         wstats.qual.level = sig;
1307                         if (sig < -110)
1308                                 sig = -110;
1309                         else if (sig > -40)
1310                                 sig = -40;
1311                         wstats.qual.qual = sig + 110;
1312                         break;
1313                 }
1314         case CFG80211_SIGNAL_TYPE_UNSPEC:
1315                 if (sinfo.filled & STATION_INFO_SIGNAL) {
1316                         wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED;
1317                         wstats.qual.updated |= IW_QUAL_QUAL_UPDATED;
1318                         wstats.qual.level = sinfo.signal;
1319                         wstats.qual.qual = sinfo.signal;
1320                         break;
1321                 }
1322         default:
1323                 wstats.qual.updated |= IW_QUAL_LEVEL_INVALID;
1324                 wstats.qual.updated |= IW_QUAL_QUAL_INVALID;
1325         }
1326
1327         wstats.qual.updated |= IW_QUAL_NOISE_INVALID;
1328
1329         return &wstats;
1330 }
1331 EXPORT_SYMBOL_GPL(cfg80211_wireless_stats);
1332
1333 int cfg80211_wext_siwap(struct net_device *dev,
1334                         struct iw_request_info *info,
1335                         struct sockaddr *ap_addr, char *extra)
1336 {
1337         struct wireless_dev *wdev = dev->ieee80211_ptr;
1338
1339         switch (wdev->iftype) {
1340         case NL80211_IFTYPE_ADHOC:
1341                 return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra);
1342         case NL80211_IFTYPE_STATION:
1343                 return cfg80211_mgd_wext_siwap(dev, info, ap_addr, extra);
1344         case NL80211_IFTYPE_WDS:
1345                 return cfg80211_wds_wext_siwap(dev, info, ap_addr, extra);
1346         default:
1347                 return -EOPNOTSUPP;
1348         }
1349 }
1350 EXPORT_SYMBOL_GPL(cfg80211_wext_siwap);
1351
1352 int cfg80211_wext_giwap(struct net_device *dev,
1353                         struct iw_request_info *info,
1354                         struct sockaddr *ap_addr, char *extra)
1355 {
1356         struct wireless_dev *wdev = dev->ieee80211_ptr;
1357
1358         switch (wdev->iftype) {
1359         case NL80211_IFTYPE_ADHOC:
1360                 return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra);
1361         case NL80211_IFTYPE_STATION:
1362                 return cfg80211_mgd_wext_giwap(dev, info, ap_addr, extra);
1363         case NL80211_IFTYPE_WDS:
1364                 return cfg80211_wds_wext_giwap(dev, info, ap_addr, extra);
1365         default:
1366                 return -EOPNOTSUPP;
1367         }
1368 }
1369 EXPORT_SYMBOL_GPL(cfg80211_wext_giwap);
1370
1371 int cfg80211_wext_siwessid(struct net_device *dev,
1372                            struct iw_request_info *info,
1373                            struct iw_point *data, char *ssid)
1374 {
1375         struct wireless_dev *wdev = dev->ieee80211_ptr;
1376
1377         switch (wdev->iftype) {
1378         case NL80211_IFTYPE_ADHOC:
1379                 return cfg80211_ibss_wext_siwessid(dev, info, data, ssid);
1380         case NL80211_IFTYPE_STATION:
1381                 return cfg80211_mgd_wext_siwessid(dev, info, data, ssid);
1382         default:
1383                 return -EOPNOTSUPP;
1384         }
1385 }
1386 EXPORT_SYMBOL_GPL(cfg80211_wext_siwessid);
1387
1388 int cfg80211_wext_giwessid(struct net_device *dev,
1389                            struct iw_request_info *info,
1390                            struct iw_point *data, char *ssid)
1391 {
1392         struct wireless_dev *wdev = dev->ieee80211_ptr;
1393
1394         switch (wdev->iftype) {
1395         case NL80211_IFTYPE_ADHOC:
1396                 return cfg80211_ibss_wext_giwessid(dev, info, data, ssid);
1397         case NL80211_IFTYPE_STATION:
1398                 return cfg80211_mgd_wext_giwessid(dev, info, data, ssid);
1399         default:
1400                 return -EOPNOTSUPP;
1401         }
1402 }
1403 EXPORT_SYMBOL_GPL(cfg80211_wext_giwessid);
1404
1405 int cfg80211_wext_siwpmksa(struct net_device *dev,
1406                            struct iw_request_info *info,
1407                            struct iw_point *data, char *extra)
1408 {
1409         struct wireless_dev *wdev = dev->ieee80211_ptr;
1410         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
1411         struct cfg80211_pmksa cfg_pmksa;
1412         struct iw_pmksa *pmksa = (struct iw_pmksa *)extra;
1413
1414         memset(&cfg_pmksa, 0, sizeof(struct cfg80211_pmksa));
1415
1416         if (wdev->iftype != NL80211_IFTYPE_STATION)
1417                 return -EINVAL;
1418
1419         cfg_pmksa.bssid = pmksa->bssid.sa_data;
1420         cfg_pmksa.pmkid = pmksa->pmkid;
1421
1422         switch (pmksa->cmd) {
1423         case IW_PMKSA_ADD:
1424                 if (!rdev->ops->set_pmksa)
1425                         return -EOPNOTSUPP;
1426
1427                 return rdev->ops->set_pmksa(&rdev->wiphy, dev, &cfg_pmksa);
1428
1429         case IW_PMKSA_REMOVE:
1430                 if (!rdev->ops->del_pmksa)
1431                         return -EOPNOTSUPP;
1432
1433                 return rdev->ops->del_pmksa(&rdev->wiphy, dev, &cfg_pmksa);
1434
1435         case IW_PMKSA_FLUSH:
1436                 if (!rdev->ops->flush_pmksa)
1437                         return -EOPNOTSUPP;
1438
1439                 return rdev->ops->flush_pmksa(&rdev->wiphy, dev);
1440
1441         default:
1442                 return -EOPNOTSUPP;
1443         }
1444 }
1445
1446 static const iw_handler cfg80211_handlers[] = {
1447         [IW_IOCTL_IDX(SIOCGIWNAME)]     = (iw_handler) cfg80211_wext_giwname,
1448         [IW_IOCTL_IDX(SIOCSIWFREQ)]     = (iw_handler) cfg80211_wext_siwfreq,
1449         [IW_IOCTL_IDX(SIOCGIWFREQ)]     = (iw_handler) cfg80211_wext_giwfreq,
1450         [IW_IOCTL_IDX(SIOCSIWMODE)]     = (iw_handler) cfg80211_wext_siwmode,
1451         [IW_IOCTL_IDX(SIOCGIWMODE)]     = (iw_handler) cfg80211_wext_giwmode,
1452         [IW_IOCTL_IDX(SIOCGIWRANGE)]    = (iw_handler) cfg80211_wext_giwrange,
1453         [IW_IOCTL_IDX(SIOCSIWAP)]       = (iw_handler) cfg80211_wext_siwap,
1454         [IW_IOCTL_IDX(SIOCGIWAP)]       = (iw_handler) cfg80211_wext_giwap,
1455         [IW_IOCTL_IDX(SIOCSIWMLME)]     = (iw_handler) cfg80211_wext_siwmlme,
1456         [IW_IOCTL_IDX(SIOCSIWSCAN)]     = (iw_handler) cfg80211_wext_siwscan,
1457         [IW_IOCTL_IDX(SIOCGIWSCAN)]     = (iw_handler) cfg80211_wext_giwscan,
1458         [IW_IOCTL_IDX(SIOCSIWESSID)]    = (iw_handler) cfg80211_wext_siwessid,
1459         [IW_IOCTL_IDX(SIOCGIWESSID)]    = (iw_handler) cfg80211_wext_giwessid,
1460         [IW_IOCTL_IDX(SIOCSIWRATE)]     = (iw_handler) cfg80211_wext_siwrate,
1461         [IW_IOCTL_IDX(SIOCGIWRATE)]     = (iw_handler) cfg80211_wext_giwrate,
1462         [IW_IOCTL_IDX(SIOCSIWRTS)]      = (iw_handler) cfg80211_wext_siwrts,
1463         [IW_IOCTL_IDX(SIOCGIWRTS)]      = (iw_handler) cfg80211_wext_giwrts,
1464         [IW_IOCTL_IDX(SIOCSIWFRAG)]     = (iw_handler) cfg80211_wext_siwfrag,
1465         [IW_IOCTL_IDX(SIOCGIWFRAG)]     = (iw_handler) cfg80211_wext_giwfrag,
1466         [IW_IOCTL_IDX(SIOCSIWTXPOW)]    = (iw_handler) cfg80211_wext_siwtxpower,
1467         [IW_IOCTL_IDX(SIOCGIWTXPOW)]    = (iw_handler) cfg80211_wext_giwtxpower,
1468         [IW_IOCTL_IDX(SIOCSIWRETRY)]    = (iw_handler) cfg80211_wext_siwretry,
1469         [IW_IOCTL_IDX(SIOCGIWRETRY)]    = (iw_handler) cfg80211_wext_giwretry,
1470         [IW_IOCTL_IDX(SIOCSIWENCODE)]   = (iw_handler) cfg80211_wext_siwencode,
1471         [IW_IOCTL_IDX(SIOCGIWENCODE)]   = (iw_handler) cfg80211_wext_giwencode,
1472         [IW_IOCTL_IDX(SIOCSIWPOWER)]    = (iw_handler) cfg80211_wext_siwpower,
1473         [IW_IOCTL_IDX(SIOCGIWPOWER)]    = (iw_handler) cfg80211_wext_giwpower,
1474         [IW_IOCTL_IDX(SIOCSIWGENIE)]    = (iw_handler) cfg80211_wext_siwgenie,
1475         [IW_IOCTL_IDX(SIOCSIWAUTH)]     = (iw_handler) cfg80211_wext_siwauth,
1476         [IW_IOCTL_IDX(SIOCGIWAUTH)]     = (iw_handler) cfg80211_wext_giwauth,
1477         [IW_IOCTL_IDX(SIOCSIWENCODEEXT)]= (iw_handler) cfg80211_wext_siwencodeext,
1478         [IW_IOCTL_IDX(SIOCSIWPMKSA)]    = (iw_handler) cfg80211_wext_siwpmksa,
1479 };
1480
1481 const struct iw_handler_def cfg80211_wext_handler = {
1482         .num_standard           = ARRAY_SIZE(cfg80211_handlers),
1483         .standard               = cfg80211_handlers,
1484         .get_wireless_stats = cfg80211_wireless_stats,
1485 };