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