cfg80211: re-join IBSS when privacy changes
[linux-2.6.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                 /*
483                  * Applications using wireless extensions expect to be
484                  * able to delete keys that don't exist, so allow that.
485                  */
486                 if (err == -ENOENT)
487                         err = 0;
488                 if (!err) {
489                         if (!addr) {
490                                 wdev->wext.keys->params[idx].key_len = 0;
491                                 wdev->wext.keys->params[idx].cipher = 0;
492                         }
493                         if (idx == wdev->wext.default_key)
494                                 wdev->wext.default_key = -1;
495                         else if (idx == wdev->wext.default_mgmt_key)
496                                 wdev->wext.default_mgmt_key = -1;
497                 }
498
499                 if (!err && rejoin)
500                         err = cfg80211_ibss_wext_join(rdev, wdev);
501
502                 return err;
503         }
504
505         if (addr)
506                 tx_key = false;
507
508         if (cfg80211_validate_key_settings(rdev, params, idx, addr))
509                 return -EINVAL;
510
511         err = 0;
512         if (wdev->current_bss)
513                 err = rdev->ops->add_key(&rdev->wiphy, dev, idx, addr, params);
514         if (err)
515                 return err;
516
517         if (!addr) {
518                 wdev->wext.keys->params[idx] = *params;
519                 memcpy(wdev->wext.keys->data[idx],
520                         params->key, params->key_len);
521                 wdev->wext.keys->params[idx].key =
522                         wdev->wext.keys->data[idx];
523         }
524
525         if ((params->cipher == WLAN_CIPHER_SUITE_WEP40 ||
526              params->cipher == WLAN_CIPHER_SUITE_WEP104) &&
527             (tx_key || (!addr && wdev->wext.default_key == -1))) {
528                 if (wdev->current_bss) {
529                         /*
530                          * If we are getting a new TX key from not having
531                          * had one before we need to join a new IBSS with
532                          * the privacy bit set.
533                          */
534                         if (wdev->iftype == NL80211_IFTYPE_ADHOC &&
535                             wdev->wext.default_key == -1) {
536                                 __cfg80211_leave_ibss(rdev, wdev->netdev, true);
537                                 rejoin = true;
538                         }
539                         err = rdev->ops->set_default_key(&rdev->wiphy,
540                                                          dev, idx);
541                 }
542                 if (!err) {
543                         wdev->wext.default_key = idx;
544                         if (rejoin)
545                                 err = cfg80211_ibss_wext_join(rdev, wdev);
546                 }
547                 return err;
548         }
549
550         if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC &&
551             (tx_key || (!addr && wdev->wext.default_mgmt_key == -1))) {
552                 if (wdev->current_bss)
553                         err = rdev->ops->set_default_mgmt_key(&rdev->wiphy,
554                                                               dev, idx);
555                 if (!err)
556                         wdev->wext.default_mgmt_key = idx;
557                 return err;
558         }
559
560         return 0;
561 }
562
563 static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
564                                    struct net_device *dev, const u8 *addr,
565                                    bool remove, bool tx_key, int idx,
566                                    struct key_params *params)
567 {
568         int err;
569
570         /* devlist mutex needed for possible IBSS re-join */
571         mutex_lock(&rdev->devlist_mtx);
572         wdev_lock(dev->ieee80211_ptr);
573         err = __cfg80211_set_encryption(rdev, dev, addr, remove,
574                                         tx_key, idx, params);
575         wdev_unlock(dev->ieee80211_ptr);
576         mutex_unlock(&rdev->devlist_mtx);
577
578         return err;
579 }
580
581 int cfg80211_wext_siwencode(struct net_device *dev,
582                             struct iw_request_info *info,
583                             struct iw_point *erq, char *keybuf)
584 {
585         struct wireless_dev *wdev = dev->ieee80211_ptr;
586         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
587         int idx, err;
588         bool remove = false;
589         struct key_params params;
590
591         if (wdev->iftype != NL80211_IFTYPE_STATION &&
592             wdev->iftype != NL80211_IFTYPE_ADHOC)
593                 return -EOPNOTSUPP;
594
595         /* no use -- only MFP (set_default_mgmt_key) is optional */
596         if (!rdev->ops->del_key ||
597             !rdev->ops->add_key ||
598             !rdev->ops->set_default_key)
599                 return -EOPNOTSUPP;
600
601         idx = erq->flags & IW_ENCODE_INDEX;
602         if (idx == 0) {
603                 idx = wdev->wext.default_key;
604                 if (idx < 0)
605                         idx = 0;
606         } else if (idx < 1 || idx > 4)
607                 return -EINVAL;
608         else
609                 idx--;
610
611         if (erq->flags & IW_ENCODE_DISABLED)
612                 remove = true;
613         else if (erq->length == 0) {
614                 /* No key data - just set the default TX key index */
615                 err = 0;
616                 wdev_lock(wdev);
617                 if (wdev->current_bss)
618                         err = rdev->ops->set_default_key(&rdev->wiphy,
619                                                          dev, idx);
620                 if (!err)
621                         wdev->wext.default_key = idx;
622                 wdev_unlock(wdev);
623                 return err;
624         }
625
626         memset(&params, 0, sizeof(params));
627         params.key = keybuf;
628         params.key_len = erq->length;
629         if (erq->length == 5)
630                 params.cipher = WLAN_CIPHER_SUITE_WEP40;
631         else if (erq->length == 13)
632                 params.cipher = WLAN_CIPHER_SUITE_WEP104;
633         else if (!remove)
634                 return -EINVAL;
635
636         return cfg80211_set_encryption(rdev, dev, NULL, remove,
637                                        wdev->wext.default_key == -1,
638                                        idx, &params);
639 }
640 EXPORT_SYMBOL_GPL(cfg80211_wext_siwencode);
641
642 int cfg80211_wext_siwencodeext(struct net_device *dev,
643                                struct iw_request_info *info,
644                                struct iw_point *erq, char *extra)
645 {
646         struct wireless_dev *wdev = dev->ieee80211_ptr;
647         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
648         struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
649         const u8 *addr;
650         int idx;
651         bool remove = false;
652         struct key_params params;
653         u32 cipher;
654
655         if (wdev->iftype != NL80211_IFTYPE_STATION &&
656             wdev->iftype != NL80211_IFTYPE_ADHOC)
657                 return -EOPNOTSUPP;
658
659         /* no use -- only MFP (set_default_mgmt_key) is optional */
660         if (!rdev->ops->del_key ||
661             !rdev->ops->add_key ||
662             !rdev->ops->set_default_key)
663                 return -EOPNOTSUPP;
664
665         switch (ext->alg) {
666         case IW_ENCODE_ALG_NONE:
667                 remove = true;
668                 cipher = 0;
669                 break;
670         case IW_ENCODE_ALG_WEP:
671                 if (ext->key_len == 5)
672                         cipher = WLAN_CIPHER_SUITE_WEP40;
673                 else if (ext->key_len == 13)
674                         cipher = WLAN_CIPHER_SUITE_WEP104;
675                 else
676                         return -EINVAL;
677                 break;
678         case IW_ENCODE_ALG_TKIP:
679                 cipher = WLAN_CIPHER_SUITE_TKIP;
680                 break;
681         case IW_ENCODE_ALG_CCMP:
682                 cipher = WLAN_CIPHER_SUITE_CCMP;
683                 break;
684         case IW_ENCODE_ALG_AES_CMAC:
685                 cipher = WLAN_CIPHER_SUITE_AES_CMAC;
686                 break;
687         default:
688                 return -EOPNOTSUPP;
689         }
690
691         if (erq->flags & IW_ENCODE_DISABLED)
692                 remove = true;
693
694         idx = erq->flags & IW_ENCODE_INDEX;
695         if (cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
696                 if (idx < 4 || idx > 5) {
697                         idx = wdev->wext.default_mgmt_key;
698                         if (idx < 0)
699                                 return -EINVAL;
700                 } else
701                         idx--;
702         } else {
703                 if (idx < 1 || idx > 4) {
704                         idx = wdev->wext.default_key;
705                         if (idx < 0)
706                                 return -EINVAL;
707                 } else
708                         idx--;
709         }
710
711         addr = ext->addr.sa_data;
712         if (is_broadcast_ether_addr(addr))
713                 addr = NULL;
714
715         memset(&params, 0, sizeof(params));
716         params.key = ext->key;
717         params.key_len = ext->key_len;
718         params.cipher = cipher;
719
720         if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
721                 params.seq = ext->rx_seq;
722                 params.seq_len = 6;
723         }
724
725         return cfg80211_set_encryption(
726                         rdev, dev, addr, remove,
727                         ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
728                         idx, &params);
729 }
730 EXPORT_SYMBOL_GPL(cfg80211_wext_siwencodeext);
731
732 int cfg80211_wext_giwencode(struct net_device *dev,
733                             struct iw_request_info *info,
734                             struct iw_point *erq, char *keybuf)
735 {
736         struct wireless_dev *wdev = dev->ieee80211_ptr;
737         int idx;
738
739         if (wdev->iftype != NL80211_IFTYPE_STATION &&
740             wdev->iftype != NL80211_IFTYPE_ADHOC)
741                 return -EOPNOTSUPP;
742
743         idx = erq->flags & IW_ENCODE_INDEX;
744         if (idx == 0) {
745                 idx = wdev->wext.default_key;
746                 if (idx < 0)
747                         idx = 0;
748         } else if (idx < 1 || idx > 4)
749                 return -EINVAL;
750         else
751                 idx--;
752
753         erq->flags = idx + 1;
754
755         if (!wdev->wext.keys || !wdev->wext.keys->params[idx].cipher) {
756                 erq->flags |= IW_ENCODE_DISABLED;
757                 erq->length = 0;
758                 return 0;
759         }
760
761         erq->length = min_t(size_t, erq->length,
762                             wdev->wext.keys->params[idx].key_len);
763         memcpy(keybuf, wdev->wext.keys->params[idx].key, erq->length);
764         erq->flags |= IW_ENCODE_ENABLED;
765
766         return 0;
767 }
768 EXPORT_SYMBOL_GPL(cfg80211_wext_giwencode);
769
770 int cfg80211_wext_siwfreq(struct net_device *dev,
771                           struct iw_request_info *info,
772                           struct iw_freq *wextfreq, char *extra)
773 {
774         struct wireless_dev *wdev = dev->ieee80211_ptr;
775         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
776         int freq, err;
777
778         switch (wdev->iftype) {
779         case NL80211_IFTYPE_STATION:
780                 return cfg80211_mgd_wext_siwfreq(dev, info, wextfreq, extra);
781         case NL80211_IFTYPE_ADHOC:
782                 return cfg80211_ibss_wext_siwfreq(dev, info, wextfreq, extra);
783         default:
784                 freq = cfg80211_wext_freq(wdev->wiphy, wextfreq);
785                 if (freq < 0)
786                         return freq;
787                 if (freq == 0)
788                         return -EINVAL;
789                 mutex_lock(&rdev->devlist_mtx);
790                 err = rdev_set_freq(rdev, NULL, freq, NL80211_CHAN_NO_HT);
791                 mutex_unlock(&rdev->devlist_mtx);
792                 return err;
793         }
794 }
795 EXPORT_SYMBOL_GPL(cfg80211_wext_siwfreq);
796
797 int cfg80211_wext_giwfreq(struct net_device *dev,
798                           struct iw_request_info *info,
799                           struct iw_freq *freq, char *extra)
800 {
801         struct wireless_dev *wdev = dev->ieee80211_ptr;
802         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
803
804         switch (wdev->iftype) {
805         case NL80211_IFTYPE_STATION:
806                 return cfg80211_mgd_wext_giwfreq(dev, info, freq, extra);
807         case NL80211_IFTYPE_ADHOC:
808                 return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra);
809         default:
810                 if (!rdev->channel)
811                         return -EINVAL;
812                 freq->m = rdev->channel->center_freq;
813                 freq->e = 6;
814                 return 0;
815         }
816 }
817 EXPORT_SYMBOL_GPL(cfg80211_wext_giwfreq);
818
819 int cfg80211_wext_siwtxpower(struct net_device *dev,
820                              struct iw_request_info *info,
821                              union iwreq_data *data, char *extra)
822 {
823         struct wireless_dev *wdev = dev->ieee80211_ptr;
824         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
825         enum tx_power_setting type;
826         int dbm = 0;
827
828         if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
829                 return -EINVAL;
830         if (data->txpower.flags & IW_TXPOW_RANGE)
831                 return -EINVAL;
832
833         if (!rdev->ops->set_tx_power)
834                 return -EOPNOTSUPP;
835
836         /* only change when not disabling */
837         if (!data->txpower.disabled) {
838                 rfkill_set_sw_state(rdev->rfkill, false);
839
840                 if (data->txpower.fixed) {
841                         /*
842                          * wext doesn't support negative values, see
843                          * below where it's for automatic
844                          */
845                         if (data->txpower.value < 0)
846                                 return -EINVAL;
847                         dbm = data->txpower.value;
848                         type = TX_POWER_FIXED;
849                         /* TODO: do regulatory check! */
850                 } else {
851                         /*
852                          * Automatic power level setting, max being the value
853                          * passed in from userland.
854                          */
855                         if (data->txpower.value < 0) {
856                                 type = TX_POWER_AUTOMATIC;
857                         } else {
858                                 dbm = data->txpower.value;
859                                 type = TX_POWER_LIMITED;
860                         }
861                 }
862         } else {
863                 rfkill_set_sw_state(rdev->rfkill, true);
864                 schedule_work(&rdev->rfkill_sync);
865                 return 0;
866         }
867
868         return rdev->ops->set_tx_power(wdev->wiphy, type, dbm);
869 }
870 EXPORT_SYMBOL_GPL(cfg80211_wext_siwtxpower);
871
872 int cfg80211_wext_giwtxpower(struct net_device *dev,
873                              struct iw_request_info *info,
874                              union iwreq_data *data, char *extra)
875 {
876         struct wireless_dev *wdev = dev->ieee80211_ptr;
877         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
878         int err, val;
879
880         if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
881                 return -EINVAL;
882         if (data->txpower.flags & IW_TXPOW_RANGE)
883                 return -EINVAL;
884
885         if (!rdev->ops->get_tx_power)
886                 return -EOPNOTSUPP;
887
888         err = rdev->ops->get_tx_power(wdev->wiphy, &val);
889         if (err)
890                 return err;
891
892         /* well... oh well */
893         data->txpower.fixed = 1;
894         data->txpower.disabled = rfkill_blocked(rdev->rfkill);
895         data->txpower.value = val;
896         data->txpower.flags = IW_TXPOW_DBM;
897
898         return 0;
899 }
900 EXPORT_SYMBOL_GPL(cfg80211_wext_giwtxpower);
901
902 static int cfg80211_set_auth_alg(struct wireless_dev *wdev,
903                                  s32 auth_alg)
904 {
905         int nr_alg = 0;
906
907         if (!auth_alg)
908                 return -EINVAL;
909
910         if (auth_alg & ~(IW_AUTH_ALG_OPEN_SYSTEM |
911                          IW_AUTH_ALG_SHARED_KEY |
912                          IW_AUTH_ALG_LEAP))
913                 return -EINVAL;
914
915         if (auth_alg & IW_AUTH_ALG_OPEN_SYSTEM) {
916                 nr_alg++;
917                 wdev->wext.connect.auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM;
918         }
919
920         if (auth_alg & IW_AUTH_ALG_SHARED_KEY) {
921                 nr_alg++;
922                 wdev->wext.connect.auth_type = NL80211_AUTHTYPE_SHARED_KEY;
923         }
924
925         if (auth_alg & IW_AUTH_ALG_LEAP) {
926                 nr_alg++;
927                 wdev->wext.connect.auth_type = NL80211_AUTHTYPE_NETWORK_EAP;
928         }
929
930         if (nr_alg > 1)
931                 wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
932
933         return 0;
934 }
935
936 static int cfg80211_set_wpa_version(struct wireless_dev *wdev, u32 wpa_versions)
937 {
938         if (wpa_versions & ~(IW_AUTH_WPA_VERSION_WPA |
939                              IW_AUTH_WPA_VERSION_WPA2|
940                              IW_AUTH_WPA_VERSION_DISABLED))
941                 return -EINVAL;
942
943         if ((wpa_versions & IW_AUTH_WPA_VERSION_DISABLED) &&
944             (wpa_versions & (IW_AUTH_WPA_VERSION_WPA|
945                              IW_AUTH_WPA_VERSION_WPA2)))
946                 return -EINVAL;
947
948         if (wpa_versions & IW_AUTH_WPA_VERSION_DISABLED)
949                 wdev->wext.connect.crypto.wpa_versions &=
950                         ~(NL80211_WPA_VERSION_1|NL80211_WPA_VERSION_2);
951
952         if (wpa_versions & IW_AUTH_WPA_VERSION_WPA)
953                 wdev->wext.connect.crypto.wpa_versions |=
954                         NL80211_WPA_VERSION_1;
955
956         if (wpa_versions & IW_AUTH_WPA_VERSION_WPA2)
957                 wdev->wext.connect.crypto.wpa_versions |=
958                         NL80211_WPA_VERSION_2;
959
960         return 0;
961 }
962
963 static int cfg80211_set_cipher_group(struct wireless_dev *wdev, u32 cipher)
964 {
965         if (cipher & IW_AUTH_CIPHER_WEP40)
966                 wdev->wext.connect.crypto.cipher_group =
967                         WLAN_CIPHER_SUITE_WEP40;
968         else if (cipher & IW_AUTH_CIPHER_WEP104)
969                 wdev->wext.connect.crypto.cipher_group =
970                         WLAN_CIPHER_SUITE_WEP104;
971         else if (cipher & IW_AUTH_CIPHER_TKIP)
972                 wdev->wext.connect.crypto.cipher_group =
973                         WLAN_CIPHER_SUITE_TKIP;
974         else if (cipher & IW_AUTH_CIPHER_CCMP)
975                 wdev->wext.connect.crypto.cipher_group =
976                         WLAN_CIPHER_SUITE_CCMP;
977         else if (cipher & IW_AUTH_CIPHER_AES_CMAC)
978                 wdev->wext.connect.crypto.cipher_group =
979                         WLAN_CIPHER_SUITE_AES_CMAC;
980         else if (cipher & IW_AUTH_CIPHER_NONE)
981                 wdev->wext.connect.crypto.cipher_group = 0;
982         else
983                 return -EINVAL;
984
985         return 0;
986 }
987
988 static int cfg80211_set_cipher_pairwise(struct wireless_dev *wdev, u32 cipher)
989 {
990         int nr_ciphers = 0;
991         u32 *ciphers_pairwise = wdev->wext.connect.crypto.ciphers_pairwise;
992
993         if (cipher & IW_AUTH_CIPHER_WEP40) {
994                 ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_WEP40;
995                 nr_ciphers++;
996         }
997
998         if (cipher & IW_AUTH_CIPHER_WEP104) {
999                 ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_WEP104;
1000                 nr_ciphers++;
1001         }
1002
1003         if (cipher & IW_AUTH_CIPHER_TKIP) {
1004                 ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_TKIP;
1005                 nr_ciphers++;
1006         }
1007
1008         if (cipher & IW_AUTH_CIPHER_CCMP) {
1009                 ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_CCMP;
1010                 nr_ciphers++;
1011         }
1012
1013         if (cipher & IW_AUTH_CIPHER_AES_CMAC) {
1014                 ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_AES_CMAC;
1015                 nr_ciphers++;
1016         }
1017
1018         BUILD_BUG_ON(NL80211_MAX_NR_CIPHER_SUITES < 5);
1019
1020         wdev->wext.connect.crypto.n_ciphers_pairwise = nr_ciphers;
1021
1022         return 0;
1023 }
1024
1025
1026 static int cfg80211_set_key_mgt(struct wireless_dev *wdev, u32 key_mgt)
1027 {
1028         int nr_akm_suites = 0;
1029
1030         if (key_mgt & ~(IW_AUTH_KEY_MGMT_802_1X |
1031                         IW_AUTH_KEY_MGMT_PSK))
1032                 return -EINVAL;
1033
1034         if (key_mgt & IW_AUTH_KEY_MGMT_802_1X) {
1035                 wdev->wext.connect.crypto.akm_suites[nr_akm_suites] =
1036                         WLAN_AKM_SUITE_8021X;
1037                 nr_akm_suites++;
1038         }
1039
1040         if (key_mgt & IW_AUTH_KEY_MGMT_PSK) {
1041                 wdev->wext.connect.crypto.akm_suites[nr_akm_suites] =
1042                         WLAN_AKM_SUITE_PSK;
1043                 nr_akm_suites++;
1044         }
1045
1046         wdev->wext.connect.crypto.n_akm_suites = nr_akm_suites;
1047
1048         return 0;
1049 }
1050
1051 int cfg80211_wext_siwauth(struct net_device *dev,
1052                           struct iw_request_info *info,
1053                           struct iw_param *data, char *extra)
1054 {
1055         struct wireless_dev *wdev = dev->ieee80211_ptr;
1056
1057         if (wdev->iftype != NL80211_IFTYPE_STATION)
1058                 return -EOPNOTSUPP;
1059
1060         switch (data->flags & IW_AUTH_INDEX) {
1061         case IW_AUTH_PRIVACY_INVOKED:
1062                 wdev->wext.connect.privacy = data->value;
1063                 return 0;
1064         case IW_AUTH_WPA_VERSION:
1065                 return cfg80211_set_wpa_version(wdev, data->value);
1066         case IW_AUTH_CIPHER_GROUP:
1067                 return cfg80211_set_cipher_group(wdev, data->value);
1068         case IW_AUTH_KEY_MGMT:
1069                 return cfg80211_set_key_mgt(wdev, data->value);
1070         case IW_AUTH_CIPHER_PAIRWISE:
1071                 return cfg80211_set_cipher_pairwise(wdev, data->value);
1072         case IW_AUTH_80211_AUTH_ALG:
1073                 return cfg80211_set_auth_alg(wdev, data->value);
1074         case IW_AUTH_WPA_ENABLED:
1075         case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1076         case IW_AUTH_DROP_UNENCRYPTED:
1077         case IW_AUTH_MFP:
1078                 return 0;
1079         default:
1080                 return -EOPNOTSUPP;
1081         }
1082 }
1083 EXPORT_SYMBOL_GPL(cfg80211_wext_siwauth);
1084
1085 int cfg80211_wext_giwauth(struct net_device *dev,
1086                           struct iw_request_info *info,
1087                           struct iw_param *data, char *extra)
1088 {
1089         /* XXX: what do we need? */
1090
1091         return -EOPNOTSUPP;
1092 }
1093 EXPORT_SYMBOL_GPL(cfg80211_wext_giwauth);
1094
1095 int cfg80211_wext_siwpower(struct net_device *dev,
1096                            struct iw_request_info *info,
1097                            struct iw_param *wrq, char *extra)
1098 {
1099         struct wireless_dev *wdev = dev->ieee80211_ptr;
1100         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
1101         bool ps = wdev->wext.ps;
1102         int timeout = wdev->wext.ps_timeout;
1103         int err;
1104
1105         if (wdev->iftype != NL80211_IFTYPE_STATION)
1106                 return -EINVAL;
1107
1108         if (!rdev->ops->set_power_mgmt)
1109                 return -EOPNOTSUPP;
1110
1111         if (wrq->disabled) {
1112                 ps = false;
1113         } else {
1114                 switch (wrq->flags & IW_POWER_MODE) {
1115                 case IW_POWER_ON:       /* If not specified */
1116                 case IW_POWER_MODE:     /* If set all mask */
1117                 case IW_POWER_ALL_R:    /* If explicitely state all */
1118                         ps = true;
1119                         break;
1120                 default:                /* Otherwise we ignore */
1121                         return -EINVAL;
1122                 }
1123
1124                 if (wrq->flags & ~(IW_POWER_MODE | IW_POWER_TIMEOUT))
1125                         return -EINVAL;
1126
1127                 if (wrq->flags & IW_POWER_TIMEOUT)
1128                         timeout = wrq->value / 1000;
1129         }
1130
1131         err = rdev->ops->set_power_mgmt(wdev->wiphy, dev, ps, timeout);
1132         if (err)
1133                 return err;
1134
1135         wdev->wext.ps = ps;
1136         wdev->wext.ps_timeout = timeout;
1137
1138         return 0;
1139
1140 }
1141 EXPORT_SYMBOL_GPL(cfg80211_wext_siwpower);
1142
1143 int cfg80211_wext_giwpower(struct net_device *dev,
1144                            struct iw_request_info *info,
1145                            struct iw_param *wrq, char *extra)
1146 {
1147         struct wireless_dev *wdev = dev->ieee80211_ptr;
1148
1149         wrq->disabled = !wdev->wext.ps;
1150
1151         return 0;
1152 }
1153 EXPORT_SYMBOL_GPL(cfg80211_wext_giwpower);
1154
1155 static int cfg80211_wds_wext_siwap(struct net_device *dev,
1156                                    struct iw_request_info *info,
1157                                    struct sockaddr *addr, char *extra)
1158 {
1159         struct wireless_dev *wdev = dev->ieee80211_ptr;
1160         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
1161         int err;
1162
1163         if (WARN_ON(wdev->iftype != NL80211_IFTYPE_WDS))
1164                 return -EINVAL;
1165
1166         if (addr->sa_family != ARPHRD_ETHER)
1167                 return -EINVAL;
1168
1169         if (netif_running(dev))
1170                 return -EBUSY;
1171
1172         if (!rdev->ops->set_wds_peer)
1173                 return -EOPNOTSUPP;
1174
1175         err = rdev->ops->set_wds_peer(wdev->wiphy, dev, (u8 *) &addr->sa_data);
1176         if (err)
1177                 return err;
1178
1179         memcpy(&wdev->wext.bssid, (u8 *) &addr->sa_data, ETH_ALEN);
1180
1181         return 0;
1182 }
1183
1184 static int cfg80211_wds_wext_giwap(struct net_device *dev,
1185                                    struct iw_request_info *info,
1186                                    struct sockaddr *addr, char *extra)
1187 {
1188         struct wireless_dev *wdev = dev->ieee80211_ptr;
1189
1190         if (WARN_ON(wdev->iftype != NL80211_IFTYPE_WDS))
1191                 return -EINVAL;
1192
1193         addr->sa_family = ARPHRD_ETHER;
1194         memcpy(&addr->sa_data, wdev->wext.bssid, ETH_ALEN);
1195
1196         return 0;
1197 }
1198
1199 int cfg80211_wext_siwrate(struct net_device *dev,
1200                           struct iw_request_info *info,
1201                           struct iw_param *rate, char *extra)
1202 {
1203         struct wireless_dev *wdev = dev->ieee80211_ptr;
1204         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
1205         struct cfg80211_bitrate_mask mask;
1206
1207         if (!rdev->ops->set_bitrate_mask)
1208                 return -EOPNOTSUPP;
1209
1210         mask.fixed = 0;
1211         mask.maxrate = 0;
1212
1213         if (rate->value < 0) {
1214                 /* nothing */
1215         } else if (rate->fixed) {
1216                 mask.fixed = rate->value / 1000; /* kbps */
1217         } else {
1218                 mask.maxrate = rate->value / 1000; /* kbps */
1219         }
1220
1221         return rdev->ops->set_bitrate_mask(wdev->wiphy, dev, NULL, &mask);
1222 }
1223 EXPORT_SYMBOL_GPL(cfg80211_wext_siwrate);
1224
1225 int cfg80211_wext_giwrate(struct net_device *dev,
1226                           struct iw_request_info *info,
1227                           struct iw_param *rate, char *extra)
1228 {
1229         struct wireless_dev *wdev = dev->ieee80211_ptr;
1230         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
1231         /* we are under RTNL - globally locked - so can use a static struct */
1232         static struct station_info sinfo;
1233         u8 addr[ETH_ALEN];
1234         int err;
1235
1236         if (wdev->iftype != NL80211_IFTYPE_STATION)
1237                 return -EOPNOTSUPP;
1238
1239         if (!rdev->ops->get_station)
1240                 return -EOPNOTSUPP;
1241
1242         err = 0;
1243         wdev_lock(wdev);
1244         if (wdev->current_bss)
1245                 memcpy(addr, wdev->current_bss->pub.bssid, ETH_ALEN);
1246         else
1247                 err = -EOPNOTSUPP;
1248         wdev_unlock(wdev);
1249         if (err)
1250                 return err;
1251
1252         err = rdev->ops->get_station(&rdev->wiphy, dev, addr, &sinfo);
1253         if (err)
1254                 return err;
1255
1256         if (!(sinfo.filled & STATION_INFO_TX_BITRATE))
1257                 return -EOPNOTSUPP;
1258
1259         rate->value = 0;
1260
1261         if (!(sinfo.txrate.flags & RATE_INFO_FLAGS_MCS))
1262                 rate->value = 100000 * sinfo.txrate.legacy;
1263
1264         return 0;
1265 }
1266 EXPORT_SYMBOL_GPL(cfg80211_wext_giwrate);
1267
1268 /* Get wireless statistics.  Called by /proc/net/wireless and by SIOCGIWSTATS */
1269 struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev)
1270 {
1271         struct wireless_dev *wdev = dev->ieee80211_ptr;
1272         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
1273         /* we are under RTNL - globally locked - so can use static structs */
1274         static struct iw_statistics wstats;
1275         static struct station_info sinfo;
1276         u8 bssid[ETH_ALEN];
1277
1278         if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION)
1279                 return NULL;
1280
1281         if (!rdev->ops->get_station)
1282                 return NULL;
1283
1284         /* Grab BSSID of current BSS, if any */
1285         wdev_lock(wdev);
1286         if (!wdev->current_bss) {
1287                 wdev_unlock(wdev);
1288                 return NULL;
1289         }
1290         memcpy(bssid, wdev->current_bss->pub.bssid, ETH_ALEN);
1291         wdev_unlock(wdev);
1292
1293         if (rdev->ops->get_station(&rdev->wiphy, dev, bssid, &sinfo))
1294                 return NULL;
1295
1296         memset(&wstats, 0, sizeof(wstats));
1297
1298         switch (rdev->wiphy.signal_type) {
1299         case CFG80211_SIGNAL_TYPE_MBM:
1300                 if (sinfo.filled & STATION_INFO_SIGNAL) {
1301                         int sig = sinfo.signal;
1302                         wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED;
1303                         wstats.qual.updated |= IW_QUAL_QUAL_UPDATED;
1304                         wstats.qual.updated |= IW_QUAL_DBM;
1305                         wstats.qual.level = sig;
1306                         if (sig < -110)
1307                                 sig = -110;
1308                         else if (sig > -40)
1309                                 sig = -40;
1310                         wstats.qual.qual = sig + 110;
1311                         break;
1312                 }
1313         case CFG80211_SIGNAL_TYPE_UNSPEC:
1314                 if (sinfo.filled & STATION_INFO_SIGNAL) {
1315                         wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED;
1316                         wstats.qual.updated |= IW_QUAL_QUAL_UPDATED;
1317                         wstats.qual.level = sinfo.signal;
1318                         wstats.qual.qual = sinfo.signal;
1319                         break;
1320                 }
1321         default:
1322                 wstats.qual.updated |= IW_QUAL_LEVEL_INVALID;
1323                 wstats.qual.updated |= IW_QUAL_QUAL_INVALID;
1324         }
1325
1326         wstats.qual.updated |= IW_QUAL_NOISE_INVALID;
1327
1328         return &wstats;
1329 }
1330 EXPORT_SYMBOL_GPL(cfg80211_wireless_stats);
1331
1332 int cfg80211_wext_siwap(struct net_device *dev,
1333                         struct iw_request_info *info,
1334                         struct sockaddr *ap_addr, char *extra)
1335 {
1336         struct wireless_dev *wdev = dev->ieee80211_ptr;
1337
1338         switch (wdev->iftype) {
1339         case NL80211_IFTYPE_ADHOC:
1340                 return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra);
1341         case NL80211_IFTYPE_STATION:
1342                 return cfg80211_mgd_wext_siwap(dev, info, ap_addr, extra);
1343         case NL80211_IFTYPE_WDS:
1344                 return cfg80211_wds_wext_siwap(dev, info, ap_addr, extra);
1345         default:
1346                 return -EOPNOTSUPP;
1347         }
1348 }
1349 EXPORT_SYMBOL_GPL(cfg80211_wext_siwap);
1350
1351 int cfg80211_wext_giwap(struct net_device *dev,
1352                         struct iw_request_info *info,
1353                         struct sockaddr *ap_addr, char *extra)
1354 {
1355         struct wireless_dev *wdev = dev->ieee80211_ptr;
1356
1357         switch (wdev->iftype) {
1358         case NL80211_IFTYPE_ADHOC:
1359                 return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra);
1360         case NL80211_IFTYPE_STATION:
1361                 return cfg80211_mgd_wext_giwap(dev, info, ap_addr, extra);
1362         case NL80211_IFTYPE_WDS:
1363                 return cfg80211_wds_wext_giwap(dev, info, ap_addr, extra);
1364         default:
1365                 return -EOPNOTSUPP;
1366         }
1367 }
1368 EXPORT_SYMBOL_GPL(cfg80211_wext_giwap);
1369
1370 int cfg80211_wext_siwessid(struct net_device *dev,
1371                            struct iw_request_info *info,
1372                            struct iw_point *data, char *ssid)
1373 {
1374         struct wireless_dev *wdev = dev->ieee80211_ptr;
1375
1376         switch (wdev->iftype) {
1377         case NL80211_IFTYPE_ADHOC:
1378                 return cfg80211_ibss_wext_siwessid(dev, info, data, ssid);
1379         case NL80211_IFTYPE_STATION:
1380                 return cfg80211_mgd_wext_siwessid(dev, info, data, ssid);
1381         default:
1382                 return -EOPNOTSUPP;
1383         }
1384 }
1385 EXPORT_SYMBOL_GPL(cfg80211_wext_siwessid);
1386
1387 int cfg80211_wext_giwessid(struct net_device *dev,
1388                            struct iw_request_info *info,
1389                            struct iw_point *data, char *ssid)
1390 {
1391         struct wireless_dev *wdev = dev->ieee80211_ptr;
1392
1393         switch (wdev->iftype) {
1394         case NL80211_IFTYPE_ADHOC:
1395                 return cfg80211_ibss_wext_giwessid(dev, info, data, ssid);
1396         case NL80211_IFTYPE_STATION:
1397                 return cfg80211_mgd_wext_giwessid(dev, info, data, ssid);
1398         default:
1399                 return -EOPNOTSUPP;
1400         }
1401 }
1402 EXPORT_SYMBOL_GPL(cfg80211_wext_giwessid);
1403
1404 static const iw_handler cfg80211_handlers[] = {
1405         [IW_IOCTL_IDX(SIOCGIWNAME)]     = (iw_handler) cfg80211_wext_giwname,
1406         [IW_IOCTL_IDX(SIOCSIWFREQ)]     = (iw_handler) cfg80211_wext_siwfreq,
1407         [IW_IOCTL_IDX(SIOCGIWFREQ)]     = (iw_handler) cfg80211_wext_giwfreq,
1408         [IW_IOCTL_IDX(SIOCSIWMODE)]     = (iw_handler) cfg80211_wext_siwmode,
1409         [IW_IOCTL_IDX(SIOCGIWMODE)]     = (iw_handler) cfg80211_wext_giwmode,
1410         [IW_IOCTL_IDX(SIOCGIWRANGE)]    = (iw_handler) cfg80211_wext_giwrange,
1411         [IW_IOCTL_IDX(SIOCSIWAP)]       = (iw_handler) cfg80211_wext_siwap,
1412         [IW_IOCTL_IDX(SIOCGIWAP)]       = (iw_handler) cfg80211_wext_giwap,
1413         [IW_IOCTL_IDX(SIOCSIWMLME)]     = (iw_handler) cfg80211_wext_siwmlme,
1414         [IW_IOCTL_IDX(SIOCSIWSCAN)]     = (iw_handler) cfg80211_wext_siwscan,
1415         [IW_IOCTL_IDX(SIOCGIWSCAN)]     = (iw_handler) cfg80211_wext_giwscan,
1416         [IW_IOCTL_IDX(SIOCSIWESSID)]    = (iw_handler) cfg80211_wext_siwessid,
1417         [IW_IOCTL_IDX(SIOCGIWESSID)]    = (iw_handler) cfg80211_wext_giwessid,
1418         [IW_IOCTL_IDX(SIOCSIWRATE)]     = (iw_handler) cfg80211_wext_siwrate,
1419         [IW_IOCTL_IDX(SIOCGIWRATE)]     = (iw_handler) cfg80211_wext_giwrate,
1420         [IW_IOCTL_IDX(SIOCSIWRTS)]      = (iw_handler) cfg80211_wext_siwrts,
1421         [IW_IOCTL_IDX(SIOCGIWRTS)]      = (iw_handler) cfg80211_wext_giwrts,
1422         [IW_IOCTL_IDX(SIOCSIWFRAG)]     = (iw_handler) cfg80211_wext_siwfrag,
1423         [IW_IOCTL_IDX(SIOCGIWFRAG)]     = (iw_handler) cfg80211_wext_giwfrag,
1424         [IW_IOCTL_IDX(SIOCSIWTXPOW)]    = (iw_handler) cfg80211_wext_siwtxpower,
1425         [IW_IOCTL_IDX(SIOCGIWTXPOW)]    = (iw_handler) cfg80211_wext_giwtxpower,
1426         [IW_IOCTL_IDX(SIOCSIWRETRY)]    = (iw_handler) cfg80211_wext_siwretry,
1427         [IW_IOCTL_IDX(SIOCGIWRETRY)]    = (iw_handler) cfg80211_wext_giwretry,
1428         [IW_IOCTL_IDX(SIOCSIWENCODE)]   = (iw_handler) cfg80211_wext_siwencode,
1429         [IW_IOCTL_IDX(SIOCGIWENCODE)]   = (iw_handler) cfg80211_wext_giwencode,
1430         [IW_IOCTL_IDX(SIOCSIWPOWER)]    = (iw_handler) cfg80211_wext_siwpower,
1431         [IW_IOCTL_IDX(SIOCGIWPOWER)]    = (iw_handler) cfg80211_wext_giwpower,
1432         [IW_IOCTL_IDX(SIOCSIWGENIE)]    = (iw_handler) cfg80211_wext_siwgenie,
1433         [IW_IOCTL_IDX(SIOCSIWAUTH)]     = (iw_handler) cfg80211_wext_siwauth,
1434         [IW_IOCTL_IDX(SIOCGIWAUTH)]     = (iw_handler) cfg80211_wext_giwauth,
1435         [IW_IOCTL_IDX(SIOCSIWENCODEEXT)]= (iw_handler) cfg80211_wext_siwencodeext,
1436 };
1437
1438 const struct iw_handler_def cfg80211_wext_handler = {
1439         .num_standard           = ARRAY_SIZE(cfg80211_handlers),
1440         .standard               = cfg80211_handlers,
1441         .get_wireless_stats = cfg80211_wireless_stats,
1442 };