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