cfg80211: implement wext key handling
[safe/jmp/linux-2.6] / net / mac80211 / wext.c
1 /*
2  * Copyright 2002-2005, Instant802 Networks, Inc.
3  * Copyright 2005-2006, Devicescape Software, Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  */
9
10 #include <linux/module.h>
11 #include <linux/init.h>
12 #include <linux/netdevice.h>
13 #include <linux/types.h>
14 #include <linux/slab.h>
15 #include <linux/skbuff.h>
16 #include <linux/etherdevice.h>
17 #include <linux/if_arp.h>
18 #include <linux/wireless.h>
19 #include <net/iw_handler.h>
20 #include <asm/uaccess.h>
21
22 #include <net/mac80211.h>
23 #include "ieee80211_i.h"
24 #include "led.h"
25 #include "rate.h"
26 #include "wpa.h"
27 #include "aes_ccm.h"
28
29
30 static int ieee80211_ioctl_siwgenie(struct net_device *dev,
31                                     struct iw_request_info *info,
32                                     struct iw_point *data, char *extra)
33 {
34         struct ieee80211_sub_if_data *sdata;
35
36         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
37
38         if (sdata->vif.type == NL80211_IFTYPE_STATION) {
39                 int ret = ieee80211_sta_set_extra_ie(sdata, extra, data->length);
40                 if (ret)
41                         return ret;
42                 sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
43                 sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME;
44                 ieee80211_sta_req_auth(sdata);
45                 return 0;
46         }
47
48         return -EOPNOTSUPP;
49 }
50
51 static int ieee80211_ioctl_siwfreq(struct net_device *dev,
52                                    struct iw_request_info *info,
53                                    struct iw_freq *freq, char *extra)
54 {
55         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
56
57         if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
58                 return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra);
59         else if (sdata->vif.type == NL80211_IFTYPE_STATION)
60                 sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_CHANNEL_SEL;
61
62         /* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */
63         if (freq->e == 0) {
64                 if (freq->m < 0) {
65                         if (sdata->vif.type == NL80211_IFTYPE_STATION)
66                                 sdata->u.mgd.flags |=
67                                         IEEE80211_STA_AUTO_CHANNEL_SEL;
68                         return 0;
69                 } else
70                         return ieee80211_set_freq(sdata,
71                                 ieee80211_channel_to_frequency(freq->m));
72         } else {
73                 int i, div = 1000000;
74                 for (i = 0; i < freq->e; i++)
75                         div /= 10;
76                 if (div > 0)
77                         return ieee80211_set_freq(sdata, freq->m / div);
78                 else
79                         return -EINVAL;
80         }
81 }
82
83
84 static int ieee80211_ioctl_giwfreq(struct net_device *dev,
85                                    struct iw_request_info *info,
86                                    struct iw_freq *freq, char *extra)
87 {
88         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
89         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
90
91         if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
92                 return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra);
93
94         freq->m = local->oper_channel->center_freq;
95         freq->e = 6;
96
97         return 0;
98 }
99
100
101 static int ieee80211_ioctl_siwessid(struct net_device *dev,
102                                     struct iw_request_info *info,
103                                     struct iw_point *data, char *ssid)
104 {
105         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
106         size_t len = data->length;
107         int ret;
108
109         if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
110                 return cfg80211_ibss_wext_siwessid(dev, info, data, ssid);
111
112         /* iwconfig uses nul termination in SSID.. */
113         if (len > 0 && ssid[len - 1] == '\0')
114                 len--;
115
116         if (sdata->vif.type == NL80211_IFTYPE_STATION) {
117                 if (data->flags)
118                         sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_SSID_SEL;
119                 else
120                         sdata->u.mgd.flags |= IEEE80211_STA_AUTO_SSID_SEL;
121
122                 ret = ieee80211_sta_set_ssid(sdata, ssid, len);
123                 if (ret)
124                         return ret;
125
126                 sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME;
127                 ieee80211_sta_req_auth(sdata);
128                 return 0;
129         }
130
131         return -EOPNOTSUPP;
132 }
133
134
135 static int ieee80211_ioctl_giwessid(struct net_device *dev,
136                                     struct iw_request_info *info,
137                                     struct iw_point *data, char *ssid)
138 {
139         size_t len;
140         struct ieee80211_sub_if_data *sdata;
141
142         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
143
144         if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
145                 return cfg80211_ibss_wext_giwessid(dev, info, data, ssid);
146
147         if (sdata->vif.type == NL80211_IFTYPE_STATION) {
148                 int res = ieee80211_sta_get_ssid(sdata, ssid, &len);
149                 if (res == 0) {
150                         data->length = len;
151                         data->flags = 1;
152                 } else
153                         data->flags = 0;
154                 return res;
155         }
156
157         return -EOPNOTSUPP;
158 }
159
160
161 static int ieee80211_ioctl_siwap(struct net_device *dev,
162                                  struct iw_request_info *info,
163                                  struct sockaddr *ap_addr, char *extra)
164 {
165         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
166
167         if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
168                 return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra);
169
170         if (sdata->vif.type == NL80211_IFTYPE_STATION) {
171                 int ret;
172
173                 if (is_zero_ether_addr((u8 *) &ap_addr->sa_data))
174                         sdata->u.mgd.flags |= IEEE80211_STA_AUTO_BSSID_SEL |
175                                 IEEE80211_STA_AUTO_CHANNEL_SEL;
176                 else if (is_broadcast_ether_addr((u8 *) &ap_addr->sa_data))
177                         sdata->u.mgd.flags |= IEEE80211_STA_AUTO_BSSID_SEL;
178                 else
179                         sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
180                 ret = ieee80211_sta_set_bssid(sdata, (u8 *) &ap_addr->sa_data);
181                 if (ret)
182                         return ret;
183                 sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME;
184                 ieee80211_sta_req_auth(sdata);
185                 return 0;
186         } else if (sdata->vif.type == NL80211_IFTYPE_WDS) {
187                 /*
188                  * If it is necessary to update the WDS peer address
189                  * while the interface is running, then we need to do
190                  * more work here, namely if it is running we need to
191                  * add a new and remove the old STA entry, this is
192                  * normally handled by _open() and _stop().
193                  */
194                 if (netif_running(dev))
195                         return -EBUSY;
196
197                 memcpy(&sdata->u.wds.remote_addr, (u8 *) &ap_addr->sa_data,
198                        ETH_ALEN);
199
200                 return 0;
201         }
202
203         return -EOPNOTSUPP;
204 }
205
206
207 static int ieee80211_ioctl_giwap(struct net_device *dev,
208                                  struct iw_request_info *info,
209                                  struct sockaddr *ap_addr, char *extra)
210 {
211         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
212
213         if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
214                 return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra);
215
216         if (sdata->vif.type == NL80211_IFTYPE_STATION) {
217                 if (sdata->u.mgd.state == IEEE80211_STA_MLME_ASSOCIATED) {
218                         ap_addr->sa_family = ARPHRD_ETHER;
219                         memcpy(&ap_addr->sa_data, sdata->u.mgd.bssid, ETH_ALEN);
220                 } else
221                         memset(&ap_addr->sa_data, 0, ETH_ALEN);
222                 return 0;
223         } else if (sdata->vif.type == NL80211_IFTYPE_WDS) {
224                 ap_addr->sa_family = ARPHRD_ETHER;
225                 memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN);
226                 return 0;
227         }
228
229         return -EOPNOTSUPP;
230 }
231
232
233 static int ieee80211_ioctl_siwrate(struct net_device *dev,
234                                   struct iw_request_info *info,
235                                   struct iw_param *rate, char *extra)
236 {
237         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
238         int i, err = -EINVAL;
239         u32 target_rate = rate->value / 100000;
240         struct ieee80211_sub_if_data *sdata;
241         struct ieee80211_supported_band *sband;
242
243         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
244
245         sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
246
247         /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates
248          * target_rate = X, rate->fixed = 1 means only rate X
249          * target_rate = X, rate->fixed = 0 means all rates <= X */
250         sdata->max_ratectrl_rateidx = -1;
251         sdata->force_unicast_rateidx = -1;
252         if (rate->value < 0)
253                 return 0;
254
255         for (i=0; i< sband->n_bitrates; i++) {
256                 struct ieee80211_rate *brate = &sband->bitrates[i];
257                 int this_rate = brate->bitrate;
258
259                 if (target_rate == this_rate) {
260                         sdata->max_ratectrl_rateidx = i;
261                         if (rate->fixed)
262                                 sdata->force_unicast_rateidx = i;
263                         err = 0;
264                         break;
265                 }
266         }
267         return err;
268 }
269
270 static int ieee80211_ioctl_giwrate(struct net_device *dev,
271                                   struct iw_request_info *info,
272                                   struct iw_param *rate, char *extra)
273 {
274         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
275         struct sta_info *sta;
276         struct ieee80211_sub_if_data *sdata;
277         struct ieee80211_supported_band *sband;
278
279         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
280
281         if (sdata->vif.type != NL80211_IFTYPE_STATION)
282                 return -EOPNOTSUPP;
283
284         sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
285
286         rcu_read_lock();
287
288         sta = sta_info_get(local, sdata->u.mgd.bssid);
289
290         if (sta && !(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS))
291                 rate->value = sband->bitrates[sta->last_tx_rate.idx].bitrate;
292         else
293                 rate->value = 0;
294
295         rcu_read_unlock();
296
297         if (!sta)
298                 return -ENODEV;
299
300         rate->value *= 100000;
301
302         return 0;
303 }
304
305 static int ieee80211_ioctl_siwtxpower(struct net_device *dev,
306                                       struct iw_request_info *info,
307                                       union iwreq_data *data, char *extra)
308 {
309         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
310         struct ieee80211_channel* chan = local->hw.conf.channel;
311         bool reconf = false;
312         u32 reconf_flags = 0;
313         int new_power_level;
314
315         if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
316                 return -EINVAL;
317         if (data->txpower.flags & IW_TXPOW_RANGE)
318                 return -EINVAL;
319         if (!chan)
320                 return -EINVAL;
321
322         /* only change when not disabling */
323         if (!data->txpower.disabled) {
324                 if (data->txpower.fixed) {
325                         if (data->txpower.value < 0)
326                                 return -EINVAL;
327                         new_power_level = data->txpower.value;
328                         /*
329                          * Debatable, but we cannot do a fixed power
330                          * level above the regulatory constraint.
331                          * Use "iwconfig wlan0 txpower 15dBm" instead.
332                          */
333                         if (new_power_level > chan->max_power)
334                                 return -EINVAL;
335                 } else {
336                         /*
337                          * Automatic power level setting, max being the value
338                          * passed in from userland.
339                          */
340                         if (data->txpower.value < 0)
341                                 new_power_level = -1;
342                         else
343                                 new_power_level = data->txpower.value;
344                 }
345
346                 reconf = true;
347
348                 /*
349                  * ieee80211_hw_config() will limit to the channel's
350                  * max power and possibly power constraint from AP.
351                  */
352                 local->user_power_level = new_power_level;
353         }
354
355         if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) {
356                 local->hw.conf.radio_enabled = !(data->txpower.disabled);
357                 reconf_flags |= IEEE80211_CONF_CHANGE_RADIO_ENABLED;
358                 ieee80211_led_radio(local, local->hw.conf.radio_enabled);
359         }
360
361         if (reconf || reconf_flags)
362                 ieee80211_hw_config(local, reconf_flags);
363
364         return 0;
365 }
366
367 static int ieee80211_ioctl_giwtxpower(struct net_device *dev,
368                                    struct iw_request_info *info,
369                                    union iwreq_data *data, char *extra)
370 {
371         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
372
373         data->txpower.fixed = 1;
374         data->txpower.disabled = !(local->hw.conf.radio_enabled);
375         data->txpower.value = local->hw.conf.power_level;
376         data->txpower.flags = IW_TXPOW_DBM;
377
378         return 0;
379 }
380
381 static int ieee80211_ioctl_siwpower(struct net_device *dev,
382                                     struct iw_request_info *info,
383                                     struct iw_param *wrq,
384                                     char *extra)
385 {
386         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
387         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
388         struct ieee80211_conf *conf = &local->hw.conf;
389         int timeout = 0;
390         bool ps;
391
392         if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS))
393                 return -EOPNOTSUPP;
394
395         if (sdata->vif.type != NL80211_IFTYPE_STATION)
396                 return -EINVAL;
397
398         if (wrq->disabled) {
399                 ps = false;
400                 timeout = 0;
401                 goto set;
402         }
403
404         switch (wrq->flags & IW_POWER_MODE) {
405         case IW_POWER_ON:       /* If not specified */
406         case IW_POWER_MODE:     /* If set all mask */
407         case IW_POWER_ALL_R:    /* If explicitely state all */
408                 ps = true;
409                 break;
410         default:                /* Otherwise we ignore */
411                 return -EINVAL;
412         }
413
414         if (wrq->flags & ~(IW_POWER_MODE | IW_POWER_TIMEOUT))
415                 return -EINVAL;
416
417         if (wrq->flags & IW_POWER_TIMEOUT)
418                 timeout = wrq->value / 1000;
419
420  set:
421         if (ps == sdata->u.mgd.powersave && timeout == conf->dynamic_ps_timeout)
422                 return 0;
423
424         sdata->u.mgd.powersave = ps;
425         conf->dynamic_ps_timeout = timeout;
426
427         if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)
428                 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
429
430         ieee80211_recalc_ps(local, -1);
431
432         return 0;
433 }
434
435 static int ieee80211_ioctl_giwpower(struct net_device *dev,
436                                     struct iw_request_info *info,
437                                     union iwreq_data *wrqu,
438                                     char *extra)
439 {
440         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
441
442         wrqu->power.disabled = !sdata->u.mgd.powersave;
443
444         return 0;
445 }
446
447 static int ieee80211_ioctl_siwauth(struct net_device *dev,
448                                    struct iw_request_info *info,
449                                    struct iw_param *data, char *extra)
450 {
451         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
452         int ret = 0;
453
454         switch (data->flags & IW_AUTH_INDEX) {
455         case IW_AUTH_WPA_VERSION:
456         case IW_AUTH_CIPHER_GROUP:
457         case IW_AUTH_WPA_ENABLED:
458         case IW_AUTH_RX_UNENCRYPTED_EAPOL:
459         case IW_AUTH_KEY_MGMT:
460         case IW_AUTH_CIPHER_GROUP_MGMT:
461                 break;
462         case IW_AUTH_CIPHER_PAIRWISE:
463                 if (sdata->vif.type == NL80211_IFTYPE_STATION) {
464                         if (data->value & (IW_AUTH_CIPHER_WEP40 |
465                             IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_TKIP))
466                                 sdata->u.mgd.flags |=
467                                         IEEE80211_STA_TKIP_WEP_USED;
468                         else
469                                 sdata->u.mgd.flags &=
470                                         ~IEEE80211_STA_TKIP_WEP_USED;
471                 }
472                 break;
473         case IW_AUTH_DROP_UNENCRYPTED:
474                 sdata->drop_unencrypted = !!data->value;
475                 break;
476         case IW_AUTH_PRIVACY_INVOKED:
477                 if (sdata->vif.type != NL80211_IFTYPE_STATION)
478                         ret = -EINVAL;
479                 else {
480                         sdata->u.mgd.flags &= ~IEEE80211_STA_PRIVACY_INVOKED;
481                         /*
482                          * Privacy invoked by wpa_supplicant, store the
483                          * value and allow associating to a protected
484                          * network without having a key up front.
485                          */
486                         if (data->value)
487                                 sdata->u.mgd.flags |=
488                                         IEEE80211_STA_PRIVACY_INVOKED;
489                 }
490                 break;
491         case IW_AUTH_80211_AUTH_ALG:
492                 if (sdata->vif.type == NL80211_IFTYPE_STATION)
493                         sdata->u.mgd.auth_algs = data->value;
494                 else
495                         ret = -EOPNOTSUPP;
496                 break;
497         case IW_AUTH_MFP:
498                 if (!(sdata->local->hw.flags & IEEE80211_HW_MFP_CAPABLE)) {
499                         ret = -EOPNOTSUPP;
500                         break;
501                 }
502                 if (sdata->vif.type == NL80211_IFTYPE_STATION) {
503                         switch (data->value) {
504                         case IW_AUTH_MFP_DISABLED:
505                                 sdata->u.mgd.mfp = IEEE80211_MFP_DISABLED;
506                                 break;
507                         case IW_AUTH_MFP_OPTIONAL:
508                                 sdata->u.mgd.mfp = IEEE80211_MFP_OPTIONAL;
509                                 break;
510                         case IW_AUTH_MFP_REQUIRED:
511                                 sdata->u.mgd.mfp = IEEE80211_MFP_REQUIRED;
512                                 break;
513                         default:
514                                 ret = -EINVAL;
515                         }
516                 } else
517                         ret = -EOPNOTSUPP;
518                 break;
519         default:
520                 ret = -EOPNOTSUPP;
521                 break;
522         }
523         return ret;
524 }
525
526 /* Get wireless statistics.  Called by /proc/net/wireless and by SIOCGIWSTATS */
527 static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev)
528 {
529         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
530         struct iw_statistics *wstats = &local->wstats;
531         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
532         struct sta_info *sta = NULL;
533
534         rcu_read_lock();
535
536         if (sdata->vif.type == NL80211_IFTYPE_STATION)
537                 sta = sta_info_get(local, sdata->u.mgd.bssid);
538
539         if (!sta) {
540                 wstats->discard.fragment = 0;
541                 wstats->discard.misc = 0;
542                 wstats->qual.qual = 0;
543                 wstats->qual.level = 0;
544                 wstats->qual.noise = 0;
545                 wstats->qual.updated = IW_QUAL_ALL_INVALID;
546         } else {
547                 wstats->qual.updated = 0;
548                 /*
549                  * mirror what cfg80211 does for iwrange/scan results,
550                  * otherwise userspace gets confused.
551                  */
552                 if (local->hw.flags & (IEEE80211_HW_SIGNAL_UNSPEC |
553                                        IEEE80211_HW_SIGNAL_DBM)) {
554                         wstats->qual.updated |= IW_QUAL_LEVEL_UPDATED;
555                         wstats->qual.updated |= IW_QUAL_QUAL_UPDATED;
556                 } else {
557                         wstats->qual.updated |= IW_QUAL_LEVEL_INVALID;
558                         wstats->qual.updated |= IW_QUAL_QUAL_INVALID;
559                 }
560
561                 if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) {
562                         wstats->qual.level = sta->last_signal;
563                         wstats->qual.qual = sta->last_signal;
564                 } else if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
565                         int sig = sta->last_signal;
566
567                         wstats->qual.updated |= IW_QUAL_DBM;
568                         wstats->qual.level = sig;
569                         if (sig < -110)
570                                 sig = -110;
571                         else if (sig > -40)
572                                 sig = -40;
573                         wstats->qual.qual = sig + 110;
574                 }
575
576                 if (local->hw.flags & IEEE80211_HW_NOISE_DBM) {
577                         /*
578                          * This assumes that if driver reports noise, it also
579                          * reports signal in dBm.
580                          */
581                         wstats->qual.noise = sta->last_noise;
582                         wstats->qual.updated |= IW_QUAL_NOISE_UPDATED;
583                 } else {
584                         wstats->qual.updated |= IW_QUAL_NOISE_INVALID;
585                 }
586         }
587
588         rcu_read_unlock();
589
590         return wstats;
591 }
592
593 static int ieee80211_ioctl_giwauth(struct net_device *dev,
594                                    struct iw_request_info *info,
595                                    struct iw_param *data, char *extra)
596 {
597         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
598         int ret = 0;
599
600         switch (data->flags & IW_AUTH_INDEX) {
601         case IW_AUTH_80211_AUTH_ALG:
602                 if (sdata->vif.type == NL80211_IFTYPE_STATION)
603                         data->value = sdata->u.mgd.auth_algs;
604                 else
605                         ret = -EOPNOTSUPP;
606                 break;
607         default:
608                 ret = -EOPNOTSUPP;
609                 break;
610         }
611         return ret;
612 }
613
614
615 /* Structures to export the Wireless Handlers */
616
617 static const iw_handler ieee80211_handler[] =
618 {
619         (iw_handler) NULL,                              /* SIOCSIWCOMMIT */
620         (iw_handler) cfg80211_wext_giwname,             /* SIOCGIWNAME */
621         (iw_handler) NULL,                              /* SIOCSIWNWID */
622         (iw_handler) NULL,                              /* SIOCGIWNWID */
623         (iw_handler) ieee80211_ioctl_siwfreq,           /* SIOCSIWFREQ */
624         (iw_handler) ieee80211_ioctl_giwfreq,           /* SIOCGIWFREQ */
625         (iw_handler) cfg80211_wext_siwmode,             /* SIOCSIWMODE */
626         (iw_handler) cfg80211_wext_giwmode,             /* SIOCGIWMODE */
627         (iw_handler) NULL,                              /* SIOCSIWSENS */
628         (iw_handler) NULL,                              /* SIOCGIWSENS */
629         (iw_handler) NULL /* not used */,               /* SIOCSIWRANGE */
630         (iw_handler) cfg80211_wext_giwrange,            /* SIOCGIWRANGE */
631         (iw_handler) NULL /* not used */,               /* SIOCSIWPRIV */
632         (iw_handler) NULL /* kernel code */,            /* SIOCGIWPRIV */
633         (iw_handler) NULL /* not used */,               /* SIOCSIWSTATS */
634         (iw_handler) NULL /* kernel code */,            /* SIOCGIWSTATS */
635         (iw_handler) NULL,                              /* SIOCSIWSPY */
636         (iw_handler) NULL,                              /* SIOCGIWSPY */
637         (iw_handler) NULL,                              /* SIOCSIWTHRSPY */
638         (iw_handler) NULL,                              /* SIOCGIWTHRSPY */
639         (iw_handler) ieee80211_ioctl_siwap,             /* SIOCSIWAP */
640         (iw_handler) ieee80211_ioctl_giwap,             /* SIOCGIWAP */
641         (iw_handler) cfg80211_wext_siwmlme,             /* SIOCSIWMLME */
642         (iw_handler) NULL,                              /* SIOCGIWAPLIST */
643         (iw_handler) cfg80211_wext_siwscan,             /* SIOCSIWSCAN */
644         (iw_handler) cfg80211_wext_giwscan,             /* SIOCGIWSCAN */
645         (iw_handler) ieee80211_ioctl_siwessid,          /* SIOCSIWESSID */
646         (iw_handler) ieee80211_ioctl_giwessid,          /* SIOCGIWESSID */
647         (iw_handler) NULL,                              /* SIOCSIWNICKN */
648         (iw_handler) NULL,                              /* SIOCGIWNICKN */
649         (iw_handler) NULL,                              /* -- hole -- */
650         (iw_handler) NULL,                              /* -- hole -- */
651         (iw_handler) ieee80211_ioctl_siwrate,           /* SIOCSIWRATE */
652         (iw_handler) ieee80211_ioctl_giwrate,           /* SIOCGIWRATE */
653         (iw_handler) cfg80211_wext_siwrts,              /* SIOCSIWRTS */
654         (iw_handler) cfg80211_wext_giwrts,              /* SIOCGIWRTS */
655         (iw_handler) cfg80211_wext_siwfrag,             /* SIOCSIWFRAG */
656         (iw_handler) cfg80211_wext_giwfrag,             /* SIOCGIWFRAG */
657         (iw_handler) ieee80211_ioctl_siwtxpower,        /* SIOCSIWTXPOW */
658         (iw_handler) ieee80211_ioctl_giwtxpower,        /* SIOCGIWTXPOW */
659         (iw_handler) cfg80211_wext_siwretry,            /* SIOCSIWRETRY */
660         (iw_handler) cfg80211_wext_giwretry,            /* SIOCGIWRETRY */
661         (iw_handler) cfg80211_wext_siwencode,           /* SIOCSIWENCODE */
662         (iw_handler) cfg80211_wext_giwencode,           /* SIOCGIWENCODE */
663         (iw_handler) ieee80211_ioctl_siwpower,          /* SIOCSIWPOWER */
664         (iw_handler) ieee80211_ioctl_giwpower,          /* SIOCGIWPOWER */
665         (iw_handler) NULL,                              /* -- hole -- */
666         (iw_handler) NULL,                              /* -- hole -- */
667         (iw_handler) ieee80211_ioctl_siwgenie,          /* SIOCSIWGENIE */
668         (iw_handler) NULL,                              /* SIOCGIWGENIE */
669         (iw_handler) ieee80211_ioctl_siwauth,           /* SIOCSIWAUTH */
670         (iw_handler) ieee80211_ioctl_giwauth,           /* SIOCGIWAUTH */
671         (iw_handler) cfg80211_wext_siwencodeext,        /* SIOCSIWENCODEEXT */
672         (iw_handler) NULL,                              /* SIOCGIWENCODEEXT */
673         (iw_handler) NULL,                              /* SIOCSIWPMKSA */
674         (iw_handler) NULL,                              /* -- hole -- */
675 };
676
677 const struct iw_handler_def ieee80211_iw_handler_def =
678 {
679         .num_standard   = ARRAY_SIZE(ieee80211_handler),
680         .standard       = (iw_handler *) ieee80211_handler,
681         .get_wireless_stats = ieee80211_get_wireless_stats,
682 };