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