~ubuntu-branches/ubuntu/hardy/linux-backports-modules-2.6.24/hardy-security

« back to all changes in this revision

Viewing changes to updates/wireless/iwlwifi/mac80211/compatible/net/mac80211/ieee80211_ioctl.c

  • Committer: Bazaar Package Importer
  • Author(s): , Ben Collins
  • Date: 2008-04-02 06:59:04 UTC
  • Revision ID: james.westby@ubuntu.com-20080402065904-e5knh2gn2hms3xbb
Tags: 2.6.24-14.11
[Ben Collins]

* iwlwifi: Update to iwlwifi-1.2.25 and mac80211-10.0.4
  - LP: #200950
* ubuntu: Slight cleanups to module hiearchy and Makefiles
* mac80211: Enable LED triggers
* iwlwifi: Add LED trigger support (rx and tx only)
  - LP: #176090

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 "hostapd_ioctl.h"
 
25
#include "ieee80211_rate.h"
 
26
#include "wpa.h"
 
27
#include "aes_ccm.h"
 
28
#include "debugfs_key.h"
 
29
 
 
30
static void ieee80211_set_hw_encryption(struct net_device *dev,
 
31
                                        struct sta_info *sta, u8 addr[ETH_ALEN],
 
32
                                        struct ieee80211_key *key)
 
33
{
 
34
        struct ieee80211_key_conf *keyconf = NULL;
 
35
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
36
 
 
37
        /* default to sw encryption; this will be cleared by low-level
 
38
         * driver if the hw supports requested encryption */
 
39
        if (key)
 
40
                key->force_sw_encrypt = 1;
 
41
 
 
42
        if (key && local->ops->set_key &&
 
43
            (keyconf = ieee80211_key_data2conf(local, key))) {
 
44
                if (local->ops->set_key(local_to_hw(local), SET_KEY, addr,
 
45
                                       keyconf, sta ? sta->aid : 0)) {
 
46
                        key->force_sw_encrypt = 1;
 
47
                        key->hw_key_idx = HW_KEY_IDX_INVALID;
 
48
                } else {
 
49
                        key->force_sw_encrypt =
 
50
                                !!(keyconf->flags & IEEE80211_KEY_FORCE_SW_ENCRYPT);
 
51
                        key->hw_key_idx =
 
52
                                keyconf->hw_key_idx;
 
53
 
 
54
                }
 
55
        }
 
56
        kfree(keyconf);
 
57
}
 
58
 
 
59
 
 
60
static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr,
 
61
                                    int idx, int alg, int set_tx_key,
 
62
                                    const u8 *_key, size_t key_len)
 
63
{
 
64
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
65
        int ret = 0;
 
66
        struct sta_info *sta;
 
67
        struct ieee80211_key *key, *old_key;
 
68
        int try_hwaccel = 1;
 
69
        struct ieee80211_key_conf *keyconf;
 
70
        struct ieee80211_sub_if_data *sdata;
 
71
 
 
72
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
73
 
 
74
        if (is_broadcast_ether_addr(sta_addr)) {
 
75
                sta = NULL;
 
76
                if (idx >= NUM_DEFAULT_KEYS) {
 
77
                        printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n",
 
78
                               dev->name, idx);
 
79
                        return -EINVAL;
 
80
                }
 
81
                key = sdata->keys[idx];
 
82
 
 
83
                /* TODO: consider adding hwaccel support for these; at least
 
84
                 * Atheros key cache should be able to handle this since AP is
 
85
                 * only transmitting frames with default keys. */
 
86
                /* FIX: hw key cache can be used when only one virtual
 
87
                 * STA is associated with each AP. If more than one STA
 
88
                 * is associated to the same AP, software encryption
 
89
                 * must be used. This should be done automatically
 
90
                 * based on configured station devices. For the time
 
91
                 * being, this can be only set at compile time. */
 
92
        } else {
 
93
                set_tx_key = 0;
 
94
                if (idx != 0) {
 
95
                        printk(KERN_DEBUG "%s: set_encrypt - non-zero idx for "
 
96
                               "individual key\n", dev->name);
 
97
                        return -EINVAL;
 
98
                }
 
99
 
 
100
                if (is_zero_ether_addr(sta_addr))
 
101
                        sta = iwlwifi_sta_info_get(local, sdata->u.sta.bssid);
 
102
                else
 
103
                        sta = iwlwifi_sta_info_get(local, sta_addr);
 
104
                if (!sta) {
 
105
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
 
106
                        printk(KERN_DEBUG "%s: set_encrypt - unknown addr "
 
107
                               MAC_FMT "\n",
 
108
                               dev->name, MAC_ARG(sta_addr));
 
109
#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
 
110
 
 
111
                        return -ENOENT;
 
112
                }
 
113
 
 
114
                key = sta->key;
 
115
        }
 
116
 
 
117
        /* FIX:
 
118
         * Cannot configure default hwaccel keys with WEP algorithm, if
 
119
         * any of the virtual interfaces is using static WEP
 
120
         * configuration because hwaccel would otherwise try to decrypt
 
121
         * these frames.
 
122
         *
 
123
         * For now, just disable WEP hwaccel for broadcast when there is
 
124
         * possibility of conflict with default keys. This can maybe later be
 
125
         * optimized by using non-default keys (at least with Atheros ar521x).
 
126
         */
 
127
        if (!sta && alg == ALG_WEP && !local->default_wep_only &&
 
128
            sdata->type != IEEE80211_IF_TYPE_IBSS &&
 
129
            sdata->type != IEEE80211_IF_TYPE_AP) {
 
130
                try_hwaccel = 0;
 
131
        }
 
132
 
 
133
        if (local->hw.flags & IEEE80211_HW_DEVICE_HIDES_WEP) {
 
134
                /* Software encryption cannot be used with devices that hide
 
135
                 * encryption from the host system, so always try to use
 
136
                 * hardware acceleration with such devices. */
 
137
                try_hwaccel = 1;
 
138
        }
 
139
 
 
140
        if ((local->hw.flags & IEEE80211_HW_NO_TKIP_WMM_HWACCEL) &&
 
141
            alg == ALG_TKIP) {
 
142
                if (sta && (sta->flags & WLAN_STA_WME)) {
 
143
                /* Hardware does not support hwaccel with TKIP when using WMM.
 
144
                 */
 
145
                        try_hwaccel = 0;
 
146
                }
 
147
                else if (sdata->type == IEEE80211_IF_TYPE_STA) {
 
148
                        sta = iwlwifi_sta_info_get(local, sdata->u.sta.bssid);
 
149
                        if (sta) {
 
150
                                if (sta->flags & WLAN_STA_WME) {
 
151
                                        try_hwaccel = 0;
 
152
                                }
 
153
                                iwlwifi_sta_info_put(sta);
 
154
                                sta = NULL;
 
155
                        }
 
156
                }
 
157
        }
 
158
 
 
159
        if (alg == ALG_NONE) {
 
160
                keyconf = NULL;
 
161
                if (try_hwaccel && key &&
 
162
                    key->hw_key_idx != HW_KEY_IDX_INVALID &&
 
163
                    local->ops->set_key &&
 
164
                    (keyconf = ieee80211_key_data2conf(local, key)) != NULL &&
 
165
                    local->ops->set_key(local_to_hw(local), DISABLE_KEY,
 
166
                                       sta_addr, keyconf, sta ? sta->aid : 0)) {
 
167
                        printk(KERN_DEBUG "%s: set_encrypt - low-level disable"
 
168
                               " failed\n", dev->name);
 
169
                        ret = -EINVAL;
 
170
                }
 
171
                kfree(keyconf);
 
172
 
 
173
                if (set_tx_key || sdata->default_key == key) {
 
174
                        ieee80211_debugfs_key_remove_default(sdata);
 
175
                        sdata->default_key = NULL;
 
176
                }
 
177
                ieee80211_debugfs_key_remove(key);
 
178
                if (sta)
 
179
                        sta->key = NULL;
 
180
                else
 
181
                        sdata->keys[idx] = NULL;
 
182
                ieee80211_key_free(key);
 
183
                key = NULL;
 
184
        } else {
 
185
                old_key = key;
 
186
                key = ieee80211_key_alloc(sta ? NULL : sdata, idx, key_len,
 
187
                                          GFP_KERNEL);
 
188
                if (!key) {
 
189
                        ret = -ENOMEM;
 
190
                        goto err_out;
 
191
                }
 
192
 
 
193
                /* default to sw encryption; low-level driver sets these if the
 
194
                 * requested encryption is supported */
 
195
                key->hw_key_idx = HW_KEY_IDX_INVALID;
 
196
                key->force_sw_encrypt = 1;
 
197
 
 
198
                key->alg = alg;
 
199
                key->keyidx = idx;
 
200
                key->keylen = key_len;
 
201
                memcpy(key->key, _key, key_len);
 
202
                if (set_tx_key)
 
203
                        key->default_tx_key = 1;
 
204
 
 
205
                if (alg == ALG_CCMP) {
 
206
                        /* Initialize AES key state here as an optimization
 
207
                         * so that it does not need to be initialized for every
 
208
                         * packet. */
 
209
                        key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(
 
210
                                key->key);
 
211
                        if (!key->u.ccmp.tfm) {
 
212
                                ret = -ENOMEM;
 
213
                                goto err_free;
 
214
                        }
 
215
                }
 
216
 
 
217
                if (set_tx_key || sdata->default_key == old_key) {
 
218
                        ieee80211_debugfs_key_remove_default(sdata);
 
219
                        sdata->default_key = NULL;
 
220
                }
 
221
                ieee80211_debugfs_key_remove(old_key);
 
222
                if (sta)
 
223
                        sta->key = key;
 
224
                else
 
225
                        sdata->keys[idx] = key;
 
226
                ieee80211_key_free(old_key);
 
227
                ieee80211_debugfs_key_add(local, key);
 
228
                if (sta)
 
229
                        ieee80211_debugfs_key_sta_link(key, sta);
 
230
 
 
231
                if (try_hwaccel &&
 
232
                    (alg == ALG_WEP || alg == ALG_TKIP || alg == ALG_CCMP))
 
233
                        ieee80211_set_hw_encryption(dev, sta, sta_addr, key);
 
234
        }
 
235
 
 
236
        if (set_tx_key || (!sta && !sdata->default_key && key)) {
 
237
                sdata->default_key = key;
 
238
                if (key)
 
239
                        ieee80211_debugfs_key_add_default(sdata);
 
240
 
 
241
                if (local->ops->set_key_idx &&
 
242
                    local->ops->set_key_idx(local_to_hw(local), idx))
 
243
                        printk(KERN_DEBUG "%s: failed to set TX key idx for "
 
244
                               "low-level driver\n", dev->name);
 
245
        }
 
246
 
 
247
        if (sta)
 
248
                iwlwifi_sta_info_put(sta);
 
249
 
 
250
        return 0;
 
251
 
 
252
err_free:
 
253
        ieee80211_key_free(key);
 
254
err_out:
 
255
        if (sta)
 
256
                iwlwifi_sta_info_put(sta);
 
257
        return ret;
 
258
}
 
259
 
 
260
static int ieee80211_ioctl_siwgenie(struct net_device *dev,
 
261
                                    struct iw_request_info *info,
 
262
                                    struct iw_point *data, char *extra)
 
263
{
 
264
        struct ieee80211_sub_if_data *sdata;
 
265
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
266
 
 
267
        if (local->user_space_mlme)
 
268
                return -EOPNOTSUPP;
 
269
 
 
270
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
271
        if (sdata->type == IEEE80211_IF_TYPE_STA ||
 
272
            sdata->type == IEEE80211_IF_TYPE_IBSS) {
 
273
                int ret = ieee80211_sta_set_extra_ie(dev, extra, data->length);
 
274
                if (ret)
 
275
                        return ret;
 
276
                sdata->u.sta.auto_bssid_sel = 0;
 
277
                ieee80211_sta_req_auth(dev, &sdata->u.sta);
 
278
                return 0;
 
279
        }
 
280
 
 
281
        if (sdata->type == IEEE80211_IF_TYPE_AP) {
 
282
                kfree(sdata->u.ap.generic_elem);
 
283
                sdata->u.ap.generic_elem = kmalloc(data->length, GFP_KERNEL);
 
284
                if (!sdata->u.ap.generic_elem)
 
285
                        return -ENOMEM;
 
286
                memcpy(sdata->u.ap.generic_elem, extra, data->length);
 
287
                sdata->u.ap.generic_elem_len = data->length;
 
288
                return ieee80211_if_config(dev);
 
289
        }
 
290
        return -EOPNOTSUPP;
 
291
}
 
292
 
 
293
static int ieee80211_ioctl_set_radio_enabled(struct net_device *dev,
 
294
                                             int val)
 
295
{
 
296
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
297
        struct ieee80211_conf *conf = &local->hw.conf;
 
298
 
 
299
        conf->radio_enabled = val;
 
300
        return ieee80211_hw_config(wdev_priv(dev->ieee80211_ptr));
 
301
}
 
302
 
 
303
static int ieee80211_ioctl_giwname(struct net_device *dev,
 
304
                                   struct iw_request_info *info,
 
305
                                   char *name, char *extra)
 
306
{
 
307
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
308
 
 
309
        switch (local->hw.conf.phymode) {
 
310
        case MODE_IEEE80211A:
 
311
                strcpy(name, "IEEE 802.11a");
 
312
                break;
 
313
        case MODE_IEEE80211B:
 
314
                strcpy(name, "IEEE 802.11b");
 
315
                break;
 
316
        case MODE_IEEE80211G:
 
317
                strcpy(name, "IEEE 802.11g");
 
318
                break;
 
319
        case MODE_ATHEROS_TURBO:
 
320
                strcpy(name, "5GHz Turbo");
 
321
                break;
 
322
        default:
 
323
                strcpy(name, "IEEE 802.11");
 
324
                break;
 
325
        }
 
326
 
 
327
        return 0;
 
328
}
 
329
 
 
330
 
 
331
static int ieee80211_ioctl_giwrange(struct net_device *dev,
 
332
                                 struct iw_request_info *info,
 
333
                                 struct iw_point *data, char *extra)
 
334
{
 
335
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
336
        struct iw_range *range = (struct iw_range *) extra;
 
337
        struct ieee80211_hw_mode *mode = NULL;
 
338
        int c = 0;
 
339
 
 
340
        data->length = sizeof(struct iw_range);
 
341
        memset(range, 0, sizeof(struct iw_range));
 
342
 
 
343
        range->we_version_compiled = WIRELESS_EXT;
 
344
        range->we_version_source = 21;
 
345
        range->retry_capa = IW_RETRY_LIMIT;
 
346
        range->retry_flags = IW_RETRY_LIMIT;
 
347
        range->min_retry = 0;
 
348
        range->max_retry = 255;
 
349
        range->min_rts = 0;
 
350
        range->max_rts = 2347;
 
351
        range->min_frag = 256;
 
352
        range->max_frag = 2346;
 
353
 
 
354
        range->encoding_size[0] = 5;
 
355
        range->encoding_size[1] = 13;
 
356
        range->num_encoding_sizes = 2;
 
357
        range->max_encoding_tokens = NUM_DEFAULT_KEYS;
 
358
 
 
359
        range->max_qual.qual = local->hw.max_signal;
 
360
        range->max_qual.level = local->hw.max_rssi;
 
361
        range->max_qual.noise = local->hw.max_noise;
 
362
        range->max_qual.updated = local->wstats_flags;
 
363
 
 
364
        range->avg_qual.qual = local->hw.max_signal/2;
 
365
        range->avg_qual.level = 0;
 
366
        range->avg_qual.noise = 0;
 
367
        range->avg_qual.updated = local->wstats_flags;
 
368
 
 
369
        range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
 
370
                          IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
 
371
 
 
372
        list_for_each_entry(mode, &local->modes_list, list) {
 
373
                int i = 0;
 
374
 
 
375
                if (!(local->enabled_modes & (1 << mode->mode)) ||
 
376
                    (local->hw_modes & local->enabled_modes &
 
377
                     (1 << MODE_IEEE80211G) && mode->mode == MODE_IEEE80211B))
 
378
                        continue;
 
379
 
 
380
                while (i < mode->num_channels && c < IW_MAX_FREQUENCIES) {
 
381
                        struct ieee80211_channel *chan = &mode->channels[i];
 
382
 
 
383
                        if (chan->flag & IEEE80211_CHAN_W_SCAN) {
 
384
                                range->freq[c].i = chan->chan;
 
385
                                range->freq[c].m = chan->freq * 100000;
 
386
                                range->freq[c].e = 1;
 
387
                                c++;
 
388
                        }
 
389
                        i++;
 
390
                }
 
391
        }
 
392
        range->num_channels = c;
 
393
        range->num_frequency = c;
 
394
 
 
395
        IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
 
396
        IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY);
 
397
        IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
 
398
        IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
 
399
 
 
400
        return 0;
 
401
}
 
402
 
 
403
 
 
404
static int ieee80211_ioctl_siwmode(struct net_device *dev,
 
405
                                   struct iw_request_info *info,
 
406
                                   __u32 *mode, char *extra)
 
407
{
 
408
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
409
        int type;
 
410
 
 
411
        if (sdata->type == IEEE80211_IF_TYPE_VLAN)
 
412
                return -EOPNOTSUPP;
 
413
 
 
414
        switch (*mode) {
 
415
        case IW_MODE_INFRA:
 
416
                type = IEEE80211_IF_TYPE_STA;
 
417
                break;
 
418
        case IW_MODE_ADHOC:
 
419
                type = IEEE80211_IF_TYPE_IBSS;
 
420
                break;
 
421
        case IW_MODE_MONITOR:
 
422
                type = IEEE80211_IF_TYPE_MNTR;
 
423
                break;
 
424
        default:
 
425
                return -EINVAL;
 
426
        }
 
427
 
 
428
        if (type == sdata->type)
 
429
                return 0;
 
430
        if (netif_running(dev))
 
431
                return -EBUSY;
 
432
 
 
433
        ieee80211_if_reinit(dev);
 
434
        ieee80211_if_set_type(dev, type);
 
435
 
 
436
        return 0;
 
437
}
 
438
 
 
439
 
 
440
static int ieee80211_ioctl_giwmode(struct net_device *dev,
 
441
                                   struct iw_request_info *info,
 
442
                                   __u32 *mode, char *extra)
 
443
{
 
444
        struct ieee80211_sub_if_data *sdata;
 
445
 
 
446
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
447
        switch (sdata->type) {
 
448
        case IEEE80211_IF_TYPE_AP:
 
449
                *mode = IW_MODE_MASTER;
 
450
                break;
 
451
        case IEEE80211_IF_TYPE_STA:
 
452
                *mode = IW_MODE_INFRA;
 
453
                break;
 
454
        case IEEE80211_IF_TYPE_IBSS:
 
455
                *mode = IW_MODE_ADHOC;
 
456
                break;
 
457
        case IEEE80211_IF_TYPE_MNTR:
 
458
                *mode = IW_MODE_MONITOR;
 
459
                break;
 
460
        case IEEE80211_IF_TYPE_WDS:
 
461
                *mode = IW_MODE_REPEAT;
 
462
                break;
 
463
        case IEEE80211_IF_TYPE_VLAN:
 
464
                *mode = IW_MODE_SECOND;         /* FIXME */
 
465
                break;
 
466
        default:
 
467
                *mode = IW_MODE_AUTO;
 
468
                break;
 
469
        }
 
470
        return 0;
 
471
}
 
472
 
 
473
int ieee80211_set_channel(struct ieee80211_local *local, int channel, int freq)
 
474
{
 
475
        struct ieee80211_hw_mode *mode;
 
476
        int c, set = 0;
 
477
        int ret = -EINVAL;
 
478
 
 
479
        list_for_each_entry(mode, &local->modes_list, list) {
 
480
                if (!(local->enabled_modes & (1 << mode->mode)))
 
481
                        continue;
 
482
                for (c = 0; c < mode->num_channels; c++) {
 
483
                        struct ieee80211_channel *chan = &mode->channels[c];
 
484
                        if (chan->flag & IEEE80211_CHAN_W_SCAN &&
 
485
                            ((chan->chan == channel) || (chan->freq == freq))) {
 
486
                                /* Use next_mode as the mode preference to
 
487
                                 * resolve non-unique channel numbers. */
 
488
                                if (set && mode->mode != local->next_mode)
 
489
                                        continue;
 
490
 
 
491
                                local->oper_channel = chan;
 
492
                                local->oper_hw_mode = mode;
 
493
                                set++;
 
494
                        }
 
495
                }
 
496
        }
 
497
 
 
498
        if (set) {
 
499
                if (local->sta_sw_scanning)
 
500
                        ret = 0;
 
501
                else
 
502
                        ret = ieee80211_hw_config(local);
 
503
 
 
504
                rate_control_clear(local);
 
505
        }
 
506
 
 
507
        return ret;
 
508
}
 
509
 
 
510
static int ieee80211_ioctl_siwfreq(struct net_device *dev,
 
511
                                   struct iw_request_info *info,
 
512
                                   struct iw_freq *freq, char *extra)
 
513
{
 
514
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
515
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
516
 
 
517
        if (sdata->type == IEEE80211_IF_TYPE_STA)
 
518
                sdata->u.sta.auto_channel_sel = 0;
 
519
 
 
520
        /* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */
 
521
        if (freq->e == 0) {
 
522
                if (freq->m < 0) {
 
523
                        if (sdata->type == IEEE80211_IF_TYPE_STA)
 
524
                                sdata->u.sta.auto_channel_sel = 1;
 
525
                        return 0;
 
526
                } else
 
527
                        return ieee80211_set_channel(local, freq->m, -1);
 
528
        } else {
 
529
                int i, div = 1000000;
 
530
                for (i = 0; i < freq->e; i++)
 
531
                        div /= 10;
 
532
                if (div > 0)
 
533
                        return ieee80211_set_channel(local, -1, freq->m / div);
 
534
                else
 
535
                        return -EINVAL;
 
536
        }
 
537
}
 
538
 
 
539
 
 
540
static int ieee80211_ioctl_giwfreq(struct net_device *dev,
 
541
                                   struct iw_request_info *info,
 
542
                                   struct iw_freq *freq, char *extra)
 
543
{
 
544
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
545
 
 
546
        /* TODO: in station mode (Managed/Ad-hoc) might need to poll low-level
 
547
         * driver for the current channel with firmware-based management */
 
548
 
 
549
        freq->m = local->hw.conf.freq;
 
550
        freq->e = 6;
 
551
 
 
552
        return 0;
 
553
}
 
554
 
 
555
 
 
556
static int ieee80211_ioctl_siwessid(struct net_device *dev,
 
557
                                    struct iw_request_info *info,
 
558
                                    struct iw_point *data, char *ssid)
 
559
{
 
560
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
561
        struct ieee80211_sub_if_data *sdata;
 
562
        size_t len = data->length;
 
563
 
 
564
        /* iwconfig uses nul termination in SSID.. */
 
565
        if (len > 0 && ssid[len - 1] == '\0')
 
566
                len--;
 
567
 
 
568
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
569
        if (sdata->type == IEEE80211_IF_TYPE_STA ||
 
570
            sdata->type == IEEE80211_IF_TYPE_IBSS) {
 
571
                int ret;
 
572
                if (local->user_space_mlme) {
 
573
                        if (len > IEEE80211_MAX_SSID_LEN)
 
574
                                return -EINVAL;
 
575
                        memcpy(sdata->u.sta.ssid, ssid, len);
 
576
                        sdata->u.sta.ssid_len = len;
 
577
                        return 0;
 
578
                }
 
579
                sdata->u.sta.auto_ssid_sel = !data->flags;
 
580
                ret = ieee80211_sta_set_ssid(dev, ssid, len);
 
581
                if (ret)
 
582
                        return ret;
 
583
                ieee80211_sta_req_auth(dev, &sdata->u.sta);
 
584
                return 0;
 
585
        }
 
586
 
 
587
        if (sdata->type == IEEE80211_IF_TYPE_AP) {
 
588
                memcpy(sdata->u.ap.ssid, ssid, len);
 
589
                memset(sdata->u.ap.ssid + len, 0,
 
590
                       IEEE80211_MAX_SSID_LEN - len);
 
591
                sdata->u.ap.ssid_len = len;
 
592
                return ieee80211_if_config(dev);
 
593
        }
 
594
        return -EOPNOTSUPP;
 
595
}
 
596
 
 
597
 
 
598
static int ieee80211_ioctl_giwessid(struct net_device *dev,
 
599
                                    struct iw_request_info *info,
 
600
                                    struct iw_point *data, char *ssid)
 
601
{
 
602
        size_t len;
 
603
 
 
604
        struct ieee80211_sub_if_data *sdata;
 
605
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
606
        if (sdata->type == IEEE80211_IF_TYPE_STA ||
 
607
            sdata->type == IEEE80211_IF_TYPE_IBSS) {
 
608
                int res = ieee80211_sta_get_ssid(dev, ssid, &len);
 
609
                if (res == 0) {
 
610
                        data->length = len;
 
611
                        data->flags = 1;
 
612
                } else
 
613
                        data->flags = 0;
 
614
                return res;
 
615
        }
 
616
 
 
617
        if (sdata->type == IEEE80211_IF_TYPE_AP) {
 
618
                len = sdata->u.ap.ssid_len;
 
619
                if (len > IW_ESSID_MAX_SIZE)
 
620
                        len = IW_ESSID_MAX_SIZE;
 
621
                memcpy(ssid, sdata->u.ap.ssid, len);
 
622
                data->length = len;
 
623
                data->flags = 1;
 
624
                return 0;
 
625
        }
 
626
        return -EOPNOTSUPP;
 
627
}
 
628
 
 
629
 
 
630
static int ieee80211_ioctl_siwap(struct net_device *dev,
 
631
                                 struct iw_request_info *info,
 
632
                                 struct sockaddr *ap_addr, char *extra)
 
633
{
 
634
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
635
        struct ieee80211_sub_if_data *sdata;
 
636
 
 
637
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
638
        if (sdata->type == IEEE80211_IF_TYPE_STA ||
 
639
            sdata->type == IEEE80211_IF_TYPE_IBSS) {
 
640
                int ret;
 
641
                if (local->user_space_mlme) {
 
642
                        memcpy(sdata->u.sta.bssid, (u8 *) &ap_addr->sa_data,
 
643
                               ETH_ALEN);
 
644
                        return 0;
 
645
                }
 
646
                if (is_zero_ether_addr((u8 *) &ap_addr->sa_data)) {
 
647
                        sdata->u.sta.auto_bssid_sel = 1;
 
648
                        sdata->u.sta.auto_channel_sel = 1;
 
649
                } else if (is_broadcast_ether_addr((u8 *) &ap_addr->sa_data))
 
650
                        sdata->u.sta.auto_bssid_sel = 1;
 
651
                else
 
652
                        sdata->u.sta.auto_bssid_sel = 0;
 
653
                ret = ieee80211_sta_set_bssid(dev, (u8 *) &ap_addr->sa_data);
 
654
                if (ret)
 
655
                        return ret;
 
656
                ieee80211_sta_req_auth(dev, &sdata->u.sta);
 
657
                return 0;
 
658
        } else if (sdata->type == IEEE80211_IF_TYPE_WDS) {
 
659
                if (memcmp(sdata->u.wds.remote_addr, (u8 *) &ap_addr->sa_data,
 
660
                           ETH_ALEN) == 0)
 
661
                        return 0;
 
662
                return ieee80211_if_update_wds(dev, (u8 *) &ap_addr->sa_data);
 
663
        }
 
664
 
 
665
        return -EOPNOTSUPP;
 
666
}
 
667
 
 
668
 
 
669
static int ieee80211_ioctl_giwap(struct net_device *dev,
 
670
                                 struct iw_request_info *info,
 
671
                                 struct sockaddr *ap_addr, char *extra)
 
672
{
 
673
        struct ieee80211_sub_if_data *sdata;
 
674
 
 
675
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
676
        if (sdata->type == IEEE80211_IF_TYPE_STA ||
 
677
            sdata->type == IEEE80211_IF_TYPE_IBSS) {
 
678
                ap_addr->sa_family = ARPHRD_ETHER;
 
679
                memcpy(&ap_addr->sa_data, sdata->u.sta.bssid, ETH_ALEN);
 
680
                return 0;
 
681
        } else if (sdata->type == IEEE80211_IF_TYPE_WDS) {
 
682
                ap_addr->sa_family = ARPHRD_ETHER;
 
683
                memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN);
 
684
                return 0;
 
685
        }
 
686
 
 
687
        return -EOPNOTSUPP;
 
688
}
 
689
 
 
690
 
 
691
static int ieee80211_ioctl_siwscan(struct net_device *dev,
 
692
                                   struct iw_request_info *info,
 
693
                                   struct iw_point *data, char *extra)
 
694
{
 
695
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
696
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
697
        u8 *ssid = NULL;
 
698
        size_t ssid_len = 0;
 
699
        struct iw_scan_req* scan = (struct iw_scan_req*) extra;
 
700
 
 
701
        if (!netif_running(dev))
 
702
                return -ENETDOWN;
 
703
 
 
704
        switch (sdata->type) {
 
705
        case IEEE80211_IF_TYPE_STA:
 
706
        case IEEE80211_IF_TYPE_IBSS:
 
707
                if (data->flags & IW_SCAN_THIS_ESSID) {
 
708
                        ssid = scan->essid;
 
709
                        ssid_len = scan->essid_len;
 
710
                        local->scan_ssid_len = ssid_len;
 
711
                        memcpy(local->scan_ssid, ssid, ssid_len);
 
712
                } else if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID) {
 
713
                        ssid = sdata->u.sta.ssid;
 
714
                        ssid_len = sdata->u.sta.ssid_len;
 
715
                        local->scan_ssid_len = ssid_len;
 
716
                        memcpy(local->scan_ssid, ssid, ssid_len);
 
717
                }
 
718
                break;
 
719
        case IEEE80211_IF_TYPE_AP:
 
720
                if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID) {
 
721
                        ssid = sdata->u.ap.ssid;
 
722
                        ssid_len = sdata->u.ap.ssid_len;
 
723
                }
 
724
                break;
 
725
        default:
 
726
                return -EOPNOTSUPP;
 
727
        }
 
728
 
 
729
        return ieee80211_sta_req_scan(dev, ssid, ssid_len);
 
730
}
 
731
 
 
732
 
 
733
static int ieee80211_ioctl_giwscan(struct net_device *dev,
 
734
                                   struct iw_request_info *info,
 
735
                                   struct iw_point *data, char *extra)
 
736
{
 
737
        int res;
 
738
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
739
        if (local->sta_sw_scanning || local->sta_hw_scanning)
 
740
                return -EAGAIN;
 
741
        res = ieee80211_sta_scan_results(dev, extra, data->length);
 
742
        if (res >= 0) {
 
743
                data->length = res;
 
744
                return 0;
 
745
        }
 
746
        data->length = 0;
 
747
        return res;
 
748
}
 
749
 
 
750
 
 
751
static int ieee80211_ioctl_siwrate(struct net_device *dev,
 
752
                                  struct iw_request_info *info,
 
753
                                  struct iw_param *rate, char *extra)
 
754
{
 
755
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
756
        struct ieee80211_hw_mode *mode;
 
757
        int i;
 
758
        u32 target_rate = rate->value / 100000;
 
759
        struct ieee80211_sub_if_data *sdata;
 
760
 
 
761
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
762
        if (!sdata->bss)
 
763
                return -ENODEV;
 
764
        mode = local->oper_hw_mode;
 
765
        /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates
 
766
         * target_rate = X, rate->fixed = 1 means only rate X
 
767
         * target_rate = X, rate->fixed = 0 means all rates <= X */
 
768
        sdata->bss->max_ratectrl_rateidx = -1;
 
769
        sdata->bss->force_unicast_rateidx = -1;
 
770
        if (rate->value < 0)
 
771
                return 0;
 
772
        for (i=0; i< mode->num_rates; i++) {
 
773
                struct ieee80211_rate *rates = &mode->rates[i];
 
774
                int this_rate = rates->rate;
 
775
 
 
776
                if (mode->mode == MODE_ATHEROS_TURBO ||
 
777
                    mode->mode == MODE_ATHEROS_TURBOG)
 
778
                        this_rate *= 2;
 
779
                if (target_rate == this_rate) {
 
780
                        sdata->bss->max_ratectrl_rateidx = i;
 
781
                        if (rate->fixed)
 
782
                                sdata->bss->force_unicast_rateidx = i;
 
783
                        break;
 
784
                }
 
785
        }
 
786
        return 0;
 
787
}
 
788
 
 
789
static int ieee80211_ioctl_giwrate(struct net_device *dev,
 
790
                                  struct iw_request_info *info,
 
791
                                  struct iw_param *rate, char *extra)
 
792
{
 
793
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
794
        struct sta_info *sta;
 
795
        struct ieee80211_sub_if_data *sdata;
 
796
 
 
797
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
798
        if (sdata->type == IEEE80211_IF_TYPE_STA)
 
799
                sta = iwlwifi_sta_info_get(local, sdata->u.sta.bssid);
 
800
        else
 
801
                return -EOPNOTSUPP;
 
802
        if (!sta)
 
803
                return -ENODEV;
 
804
        if (sta->txrate < local->oper_hw_mode->num_rates)
 
805
                rate->value = local->oper_hw_mode->rates[sta->txrate].rate * 100000;
 
806
        else
 
807
                rate->value = 0;
 
808
        iwlwifi_sta_info_put(sta);
 
809
        return 0;
 
810
}
 
811
 
 
812
static int ieee80211_ioctl_siwrts(struct net_device *dev,
 
813
                                  struct iw_request_info *info,
 
814
                                  struct iw_param *rts, char *extra)
 
815
{
 
816
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
817
 
 
818
        if (rts->disabled)
 
819
                local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
 
820
        else if (rts->value < 0 || rts->value > IEEE80211_MAX_RTS_THRESHOLD)
 
821
                return -EINVAL;
 
822
        else
 
823
                local->rts_threshold = rts->value;
 
824
 
 
825
        /* If the wlan card performs RTS/CTS in hardware/firmware,
 
826
         * configure it here */
 
827
 
 
828
        if (local->ops->set_rts_threshold)
 
829
                local->ops->set_rts_threshold(local_to_hw(local),
 
830
                                             local->rts_threshold);
 
831
 
 
832
        return 0;
 
833
}
 
834
 
 
835
static int ieee80211_ioctl_giwrts(struct net_device *dev,
 
836
                                  struct iw_request_info *info,
 
837
                                  struct iw_param *rts, char *extra)
 
838
{
 
839
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
840
 
 
841
        rts->value = local->rts_threshold;
 
842
        rts->disabled = (rts->value >= IEEE80211_MAX_RTS_THRESHOLD);
 
843
        rts->fixed = 1;
 
844
 
 
845
        return 0;
 
846
}
 
847
 
 
848
 
 
849
static int ieee80211_ioctl_siwfrag(struct net_device *dev,
 
850
                                   struct iw_request_info *info,
 
851
                                   struct iw_param *frag, char *extra)
 
852
{
 
853
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
854
 
 
855
        if (frag->disabled)
 
856
                local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
 
857
        else if (frag->value < 256 ||
 
858
                 frag->value > IEEE80211_MAX_FRAG_THRESHOLD)
 
859
                return -EINVAL;
 
860
        else {
 
861
                /* Fragment length must be even, so strip LSB. */
 
862
                local->fragmentation_threshold = frag->value & ~0x1;
 
863
        }
 
864
 
 
865
        /* If the wlan card performs fragmentation in hardware/firmware,
 
866
         * configure it here */
 
867
 
 
868
        if (local->ops->set_frag_threshold)
 
869
                local->ops->set_frag_threshold(
 
870
                        local_to_hw(local),
 
871
                        local->fragmentation_threshold);
 
872
 
 
873
        return 0;
 
874
}
 
875
 
 
876
static int ieee80211_ioctl_giwfrag(struct net_device *dev,
 
877
                                   struct iw_request_info *info,
 
878
                                   struct iw_param *frag, char *extra)
 
879
{
 
880
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
881
 
 
882
        frag->value = local->fragmentation_threshold;
 
883
        frag->disabled = (frag->value >= IEEE80211_MAX_RTS_THRESHOLD);
 
884
        frag->fixed = 1;
 
885
 
 
886
        return 0;
 
887
}
 
888
 
 
889
static int ieee80211_ioctl_giwtxpow(struct net_device *dev,
 
890
                                    struct iw_request_info *info,
 
891
                                    union iwreq_data *wrqu,
 
892
                                    char *extra)
 
893
{
 
894
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
895
        struct ieee80211_conf *conf = &local->hw.conf;
 
896
 
 
897
        wrqu->txpower.flags = IW_TXPOW_DBM;
 
898
        wrqu->txpower.fixed = 1;
 
899
        wrqu->txpower.disabled = (conf->radio_enabled) ? 0 : 1;
 
900
        wrqu->txpower.value = conf->power_level;
 
901
        return 0;
 
902
}
 
903
 
 
904
static int ieee80211_ioctl_siwtxpow(struct net_device *dev,
 
905
                                    struct iw_request_info *info,
 
906
                                    union iwreq_data *wrqu,
 
907
                                    char *extra)
 
908
{
 
909
        int rc = 0;
 
910
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
911
 
 
912
 
 
913
        if (wrqu->txpower.flags != IW_TXPOW_DBM)
 
914
                rc = -EINVAL;
 
915
        else if (!wrqu->txpower.disabled) {
 
916
                if (wrqu->txpower.value < 0)
 
917
                        return -EINVAL;
 
918
                local->user_txpow = wrqu->txpower.value;
 
919
        }
 
920
 
 
921
 
 
922
        ieee80211_ioctl_set_radio_enabled(dev, !wrqu->txpower.disabled);
 
923
        return rc;
 
924
}
 
925
 
 
926
static int ieee80211_ioctl_siwpower(struct net_device *dev,
 
927
                                    struct iw_request_info *info,
 
928
                                    union iwreq_data *wrqu,
 
929
                                    char *extra)
 
930
{
 
931
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
932
        struct ieee80211_conf *conf = &local->hw.conf;
 
933
 
 
934
        if (wrqu->power.disabled) {
 
935
                conf->power_management_enable = 0;
 
936
                if (ieee80211_hw_config(local))
 
937
                        return -EINVAL;
 
938
                return 0;
 
939
        }
 
940
 
 
941
        if (wrqu->power.flags & IW_POWER_TYPE)
 
942
                return -EINVAL;
 
943
 
 
944
        switch (wrqu->power.flags & IW_POWER_MODE) {
 
945
        case IW_POWER_ON:       /* If not specified */
 
946
        case IW_POWER_MODE:     /* If set all mask */
 
947
        case IW_POWER_ALL_R:    /* If explicitely state all */
 
948
                break;
 
949
        default:                /* Otherwise we don't support it */
 
950
                return -EINVAL;
 
951
        }
 
952
 
 
953
        conf->power_management_enable = 1;
 
954
 
 
955
        if (ieee80211_hw_config(local))
 
956
                return -EINVAL;
 
957
 
 
958
        return 0;
 
959
}
 
960
 
 
961
static int ieee80211_ioctl_giwpower(struct net_device *dev,
 
962
                                    struct iw_request_info *info,
 
963
                                    union iwreq_data *wrqu,
 
964
                                    char *extra)
 
965
{
 
966
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
967
        struct ieee80211_conf *conf = &local->hw.conf;
 
968
 
 
969
        if (!conf->power_management_enable)
 
970
                wrqu->power.disabled = 1;
 
971
        else
 
972
                wrqu->power.disabled = 0;
 
973
        return 0;
 
974
}
 
975
 
 
976
static int ieee80211_ioctl_siwnick(struct net_device *dev,
 
977
                                   struct iw_request_info *info,
 
978
                                   union iwreq_data *wrqu, char *extra)
 
979
{
 
980
        struct ieee80211_sub_if_data *sdata;
 
981
        struct ieee80211_if_sta *ifsta;
 
982
 
 
983
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
984
        ifsta = &sdata->u.sta;
 
985
        if (wrqu->data.length >= IW_ESSID_MAX_SIZE)
 
986
                return -E2BIG;
 
987
 
 
988
        memset(ifsta->nick, 0, sizeof(ifsta->nick));
 
989
        memcpy(ifsta->nick, extra, wrqu->data.length);
 
990
        return 0;
 
991
}
 
992
 
 
993
static int ieee80211_ioctl_giwnick(struct net_device *dev,
 
994
                                   struct iw_request_info *info,
 
995
                                   union iwreq_data *wrqu, char *extra)
 
996
{
 
997
        struct ieee80211_sub_if_data *sdata;
 
998
        struct ieee80211_if_sta *ifsta;
 
999
 
 
1000
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
1001
        ifsta = &sdata->u.sta;
 
1002
 
 
1003
        wrqu->data.length = strlen(ifsta->nick) + 1;
 
1004
        memcpy(extra, ifsta->nick, wrqu->data.length);
 
1005
        wrqu->data.flags = 1;   /* active */
 
1006
        return 0;
 
1007
}
 
1008
 
 
1009
static int ieee80211_ioctl_siwretry(struct net_device *dev,
 
1010
                                    struct iw_request_info *info,
 
1011
                                    struct iw_param *retry, char *extra)
 
1012
{
 
1013
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
1014
 
 
1015
        if (retry->disabled ||
 
1016
            (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
 
1017
                return -EINVAL;
 
1018
 
 
1019
        if (retry->flags & IW_RETRY_MAX)
 
1020
                local->long_retry_limit = retry->value;
 
1021
        else if (retry->flags & IW_RETRY_MIN)
 
1022
                local->short_retry_limit = retry->value;
 
1023
        else {
 
1024
                local->long_retry_limit = retry->value;
 
1025
                local->short_retry_limit = retry->value;
 
1026
        }
 
1027
 
 
1028
        if (local->ops->set_retry_limit) {
 
1029
                return local->ops->set_retry_limit(
 
1030
                        local_to_hw(local),
 
1031
                        local->short_retry_limit,
 
1032
                        local->long_retry_limit);
 
1033
        }
 
1034
 
 
1035
        return 0;
 
1036
}
 
1037
 
 
1038
 
 
1039
static int ieee80211_ioctl_giwretry(struct net_device *dev,
 
1040
                                    struct iw_request_info *info,
 
1041
                                    struct iw_param *retry, char *extra)
 
1042
{
 
1043
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
1044
 
 
1045
        retry->disabled = 0;
 
1046
        if (retry->flags == 0 || retry->flags & IW_RETRY_MIN) {
 
1047
                /* first return min value, iwconfig will ask max value
 
1048
                 * later if needed */
 
1049
                retry->flags |= IW_RETRY_LIMIT;
 
1050
                retry->value = local->short_retry_limit;
 
1051
                if (local->long_retry_limit != local->short_retry_limit)
 
1052
                        retry->flags |= IW_RETRY_MIN;
 
1053
                return 0;
 
1054
        }
 
1055
        if (retry->flags & IW_RETRY_MAX) {
 
1056
                retry->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
 
1057
                retry->value = local->long_retry_limit;
 
1058
        }
 
1059
 
 
1060
        return 0;
 
1061
}
 
1062
 
 
1063
static void ieee80211_key_enable_hwaccel(struct ieee80211_local *local,
 
1064
                                         struct ieee80211_key *key)
 
1065
{
 
1066
        struct ieee80211_key_conf *keyconf;
 
1067
        u8 addr[ETH_ALEN];
 
1068
 
 
1069
        if (!key || key->alg != ALG_WEP || !key->force_sw_encrypt ||
 
1070
            (local->hw.flags & IEEE80211_HW_DEVICE_HIDES_WEP))
 
1071
                return;
 
1072
 
 
1073
        memset(addr, 0xff, ETH_ALEN);
 
1074
        keyconf = ieee80211_key_data2conf(local, key);
 
1075
        if (keyconf && local->ops->set_key &&
 
1076
            local->ops->set_key(local_to_hw(local),
 
1077
                               SET_KEY, addr, keyconf, 0) == 0) {
 
1078
                key->force_sw_encrypt =
 
1079
                        !!(keyconf->flags & IEEE80211_KEY_FORCE_SW_ENCRYPT);
 
1080
                key->hw_key_idx = keyconf->hw_key_idx;
 
1081
        }
 
1082
        kfree(keyconf);
 
1083
}
 
1084
 
 
1085
 
 
1086
static void ieee80211_key_disable_hwaccel(struct ieee80211_local *local,
 
1087
                                          struct ieee80211_key *key)
 
1088
{
 
1089
        struct ieee80211_key_conf *keyconf;
 
1090
        u8 addr[ETH_ALEN];
 
1091
 
 
1092
        if (!key || key->alg != ALG_WEP || key->force_sw_encrypt ||
 
1093
            (local->hw.flags & IEEE80211_HW_DEVICE_HIDES_WEP))
 
1094
                return;
 
1095
 
 
1096
        memset(addr, 0xff, ETH_ALEN);
 
1097
        keyconf = ieee80211_key_data2conf(local, key);
 
1098
        if (keyconf && local->ops->set_key)
 
1099
                local->ops->set_key(local_to_hw(local), DISABLE_KEY,
 
1100
                                   addr, keyconf, 0);
 
1101
        kfree(keyconf);
 
1102
        key->force_sw_encrypt = 1;
 
1103
}
 
1104
 
 
1105
 
 
1106
static int ieee80211_ioctl_default_wep_only(struct ieee80211_local *local,
 
1107
                                            int value)
 
1108
{
 
1109
        int i;
 
1110
        struct ieee80211_sub_if_data *sdata;
 
1111
 
 
1112
        local->default_wep_only = value;
 
1113
        read_lock(&local->sub_if_lock);
 
1114
        list_for_each_entry(sdata, &local->sub_if_list, list)
 
1115
                for (i = 0; i < NUM_DEFAULT_KEYS; i++)
 
1116
                        if (value)
 
1117
                                ieee80211_key_enable_hwaccel(local,
 
1118
                                                             sdata->keys[i]);
 
1119
                        else
 
1120
                                ieee80211_key_disable_hwaccel(local,
 
1121
                                                              sdata->keys[i]);
 
1122
        read_unlock(&local->sub_if_lock);
 
1123
 
 
1124
        return 0;
 
1125
}
 
1126
 
 
1127
 
 
1128
void ieee80211_update_default_wep_only(struct ieee80211_local *local)
 
1129
{
 
1130
        int i = 0;
 
1131
        struct ieee80211_sub_if_data *sdata;
 
1132
 
 
1133
        read_lock(&local->sub_if_lock);
 
1134
        list_for_each_entry(sdata, &local->sub_if_list, list) {
 
1135
 
 
1136
                if (sdata->dev == local->mdev)
 
1137
                        continue;
 
1138
 
 
1139
                /* If there is an AP interface then depend on userspace to
 
1140
                   set default_wep_only correctly. */
 
1141
                if (sdata->type == IEEE80211_IF_TYPE_AP) {
 
1142
                        read_unlock(&local->sub_if_lock);
 
1143
                        return;
 
1144
                }
 
1145
 
 
1146
                i++;
 
1147
        }
 
1148
 
 
1149
        read_unlock(&local->sub_if_lock);
 
1150
 
 
1151
        if (i <= 1)
 
1152
                ieee80211_ioctl_default_wep_only(local, 1);
 
1153
        else
 
1154
                ieee80211_ioctl_default_wep_only(local, 0);
 
1155
}
 
1156
 
 
1157
 
 
1158
static int ieee80211_ioctl_prism2_param(struct net_device *dev,
 
1159
                                        struct iw_request_info *info,
 
1160
                                        void *wrqu, char *extra)
 
1161
{
 
1162
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
1163
        struct ieee80211_sub_if_data *sdata;
 
1164
        int *i = (int *) extra;
 
1165
        int param = *i;
 
1166
        int value = *(i + 1);
 
1167
        int ret = 0;
 
1168
 
 
1169
        if (!capable(CAP_NET_ADMIN))
 
1170
                return -EPERM;
 
1171
 
 
1172
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
1173
 
 
1174
        switch (param) {
 
1175
        case PRISM2_PARAM_IEEE_802_1X:
 
1176
                if (local->ops->set_ieee8021x)
 
1177
                        ret = local->ops->set_ieee8021x(local_to_hw(local),
 
1178
                                                        value);
 
1179
                if (ret)
 
1180
                        printk(KERN_DEBUG "%s: failed to set IEEE 802.1X (%d) "
 
1181
                               "for low-level driver\n", dev->name, value);
 
1182
                else
 
1183
                        sdata->ieee802_1x = value;
 
1184
                break;
 
1185
 
 
1186
        case PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES:
 
1187
                if (sdata->type != IEEE80211_IF_TYPE_AP)
 
1188
                        ret = -ENOENT;
 
1189
                else
 
1190
                        sdata->use_protection = value;
 
1191
                break;
 
1192
 
 
1193
        case PRISM2_PARAM_PREAMBLE:
 
1194
                local->short_preamble = value;
 
1195
                break;
 
1196
 
 
1197
        case PRISM2_PARAM_STAT_TIME:
 
1198
                if (!local->stat_time && value) {
 
1199
                        local->stat_timer.expires = jiffies + HZ * value / 100;
 
1200
                        add_timer(&local->stat_timer);
 
1201
                } else if (local->stat_time && !value) {
 
1202
                        del_timer_sync(&local->stat_timer);
 
1203
                }
 
1204
                local->stat_time = value;
 
1205
                break;
 
1206
        case PRISM2_PARAM_SHORT_SLOT_TIME:
 
1207
                if (value)
 
1208
                        local->hw.conf.flags |= IEEE80211_CONF_SHORT_SLOT_TIME;
 
1209
                else
 
1210
                        local->hw.conf.flags &= ~IEEE80211_CONF_SHORT_SLOT_TIME;
 
1211
                if (ieee80211_hw_config(local))
 
1212
                        ret = -EINVAL;
 
1213
                break;
 
1214
 
 
1215
        case PRISM2_PARAM_NEXT_MODE:
 
1216
                local->next_mode = value;
 
1217
                break;
 
1218
 
 
1219
        case PRISM2_PARAM_RADIO_ENABLED:
 
1220
                ret = ieee80211_ioctl_set_radio_enabled(dev, value);
 
1221
                break;
 
1222
 
 
1223
        case PRISM2_PARAM_ANTENNA_MODE:
 
1224
                local->hw.conf.antenna_mode = value;
 
1225
                if (ieee80211_hw_config(local))
 
1226
                        ret = -EINVAL;
 
1227
                break;
 
1228
 
 
1229
        case PRISM2_PARAM_STA_ANTENNA_SEL:
 
1230
                local->sta_antenna_sel = value;
 
1231
                break;
 
1232
 
 
1233
        case PRISM2_PARAM_TX_POWER_REDUCTION:
 
1234
                if (value < 0)
 
1235
                        ret = -EINVAL;
 
1236
                else
 
1237
                        local->hw.conf.tx_power_reduction = value;
 
1238
                break;
 
1239
 
 
1240
        case PRISM2_PARAM_KEY_TX_RX_THRESHOLD:
 
1241
                local->key_tx_rx_threshold = value;
 
1242
                break;
 
1243
 
 
1244
        case PRISM2_PARAM_DEFAULT_WEP_ONLY:
 
1245
                ret = ieee80211_ioctl_default_wep_only(local, value);
 
1246
                break;
 
1247
 
 
1248
        case PRISM2_PARAM_WIFI_WME_NOACK_TEST:
 
1249
                local->wifi_wme_noack_test = value;
 
1250
                break;
 
1251
 
 
1252
        case PRISM2_PARAM_SCAN_FLAGS:
 
1253
                local->scan_flags = value;
 
1254
                break;
 
1255
 
 
1256
        case PRISM2_PARAM_MIXED_CELL:
 
1257
                if (sdata->type != IEEE80211_IF_TYPE_STA &&
 
1258
                    sdata->type != IEEE80211_IF_TYPE_IBSS)
 
1259
                        ret = -EINVAL;
 
1260
                else
 
1261
                        sdata->u.sta.mixed_cell = !!value;
 
1262
                break;
 
1263
 
 
1264
        case PRISM2_PARAM_HW_MODES:
 
1265
                local->enabled_modes = value;
 
1266
                break;
 
1267
 
 
1268
        case PRISM2_PARAM_CREATE_IBSS:
 
1269
                if (sdata->type != IEEE80211_IF_TYPE_IBSS)
 
1270
                        ret = -EINVAL;
 
1271
                else
 
1272
                        sdata->u.sta.create_ibss = !!value;
 
1273
                break;
 
1274
        case PRISM2_PARAM_WMM_ENABLED:
 
1275
                if (sdata->type != IEEE80211_IF_TYPE_STA &&
 
1276
                    sdata->type != IEEE80211_IF_TYPE_IBSS)
 
1277
                        ret = -EINVAL;
 
1278
                else
 
1279
                        sdata->u.sta.wmm_enabled = !!value;
 
1280
                break;
 
1281
        case PRISM2_PARAM_RADAR_DETECT:
 
1282
                local->hw.conf.radar_detect = value;
 
1283
                break;
 
1284
        case PRISM2_PARAM_SPECTRUM_MGMT:
 
1285
                local->hw.conf.spect_mgmt = value;
 
1286
                break;
 
1287
        default:
 
1288
                ret = -EOPNOTSUPP;
 
1289
                break;
 
1290
        }
 
1291
 
 
1292
        return ret;
 
1293
}
 
1294
 
 
1295
 
 
1296
static int ieee80211_ioctl_get_prism2_param(struct net_device *dev,
 
1297
                                            struct iw_request_info *info,
 
1298
                                            void *wrqu, char *extra)
 
1299
{
 
1300
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
1301
        struct ieee80211_sub_if_data *sdata;
 
1302
        int *param = (int *) extra;
 
1303
        int ret = 0;
 
1304
 
 
1305
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
1306
 
 
1307
        switch (*param) {
 
1308
        case PRISM2_PARAM_IEEE_802_1X:
 
1309
                *param = sdata->ieee802_1x;
 
1310
                break;
 
1311
 
 
1312
        case PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES:
 
1313
                *param = sdata->use_protection;
 
1314
                break;
 
1315
 
 
1316
        case PRISM2_PARAM_PREAMBLE:
 
1317
                *param = local->short_preamble;
 
1318
                break;
 
1319
 
 
1320
        case PRISM2_PARAM_STAT_TIME:
 
1321
                *param = local->stat_time;
 
1322
                break;
 
1323
        case PRISM2_PARAM_SHORT_SLOT_TIME:
 
1324
                *param = !!(local->hw.conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME);
 
1325
                break;
 
1326
 
 
1327
        case PRISM2_PARAM_NEXT_MODE:
 
1328
                *param = local->next_mode;
 
1329
                break;
 
1330
 
 
1331
        case PRISM2_PARAM_ANTENNA_MODE:
 
1332
                *param = local->hw.conf.antenna_mode;
 
1333
                break;
 
1334
 
 
1335
        case PRISM2_PARAM_STA_ANTENNA_SEL:
 
1336
                *param = local->sta_antenna_sel;
 
1337
                break;
 
1338
 
 
1339
        case PRISM2_PARAM_TX_POWER_REDUCTION:
 
1340
                *param = local->hw.conf.tx_power_reduction;
 
1341
                break;
 
1342
 
 
1343
        case PRISM2_PARAM_KEY_TX_RX_THRESHOLD:
 
1344
                *param = local->key_tx_rx_threshold;
 
1345
                break;
 
1346
 
 
1347
        case PRISM2_PARAM_DEFAULT_WEP_ONLY:
 
1348
                *param = local->default_wep_only;
 
1349
                break;
 
1350
 
 
1351
        case PRISM2_PARAM_WIFI_WME_NOACK_TEST:
 
1352
                *param = local->wifi_wme_noack_test;
 
1353
                break;
 
1354
 
 
1355
        case PRISM2_PARAM_SCAN_FLAGS:
 
1356
                *param = local->scan_flags;
 
1357
                break;
 
1358
 
 
1359
        case PRISM2_PARAM_HW_MODES:
 
1360
                *param = local->enabled_modes;
 
1361
                break;
 
1362
 
 
1363
        case PRISM2_PARAM_CREATE_IBSS:
 
1364
                if (sdata->type != IEEE80211_IF_TYPE_IBSS)
 
1365
                        ret = -EINVAL;
 
1366
                else
 
1367
                        *param = !!sdata->u.sta.create_ibss;
 
1368
                break;
 
1369
 
 
1370
        case PRISM2_PARAM_MIXED_CELL:
 
1371
                if (sdata->type != IEEE80211_IF_TYPE_STA &&
 
1372
                    sdata->type != IEEE80211_IF_TYPE_IBSS)
 
1373
                        ret = -EINVAL;
 
1374
                else
 
1375
                        *param = !!sdata->u.sta.mixed_cell;
 
1376
                break;
 
1377
        case PRISM2_PARAM_WMM_ENABLED:
 
1378
                if (sdata->type != IEEE80211_IF_TYPE_STA &&
 
1379
                    sdata->type != IEEE80211_IF_TYPE_IBSS)
 
1380
                        ret = -EINVAL;
 
1381
                else
 
1382
                        *param = !!sdata->u.sta.wmm_enabled;
 
1383
                break;
 
1384
        default:
 
1385
                ret = -EOPNOTSUPP;
 
1386
                break;
 
1387
        }
 
1388
 
 
1389
        return ret;
 
1390
}
 
1391
 
 
1392
static int ieee80211_ioctl_siwmlme(struct net_device *dev,
 
1393
                                   struct iw_request_info *info,
 
1394
                                   struct iw_point *data, char *extra)
 
1395
{
 
1396
        struct ieee80211_sub_if_data *sdata;
 
1397
        struct iw_mlme *mlme = (struct iw_mlme *) extra;
 
1398
 
 
1399
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
1400
        if (sdata->type != IEEE80211_IF_TYPE_STA &&
 
1401
            sdata->type != IEEE80211_IF_TYPE_IBSS)
 
1402
                return -EINVAL;
 
1403
 
 
1404
        switch (mlme->cmd) {
 
1405
        case IW_MLME_DEAUTH:
 
1406
                /* TODO: mlme->addr.sa_data */
 
1407
                return ieee80211_sta_deauthenticate(dev, mlme->reason_code);
 
1408
        case IW_MLME_DISASSOC:
 
1409
                /* TODO: mlme->addr.sa_data */
 
1410
                return ieee80211_sta_disassociate(dev, mlme->reason_code);
 
1411
        default:
 
1412
                return -EOPNOTSUPP;
 
1413
        }
 
1414
}
 
1415
 
 
1416
 
 
1417
static int ieee80211_ioctl_siwencode(struct net_device *dev,
 
1418
                                     struct iw_request_info *info,
 
1419
                                     struct iw_point *erq, char *keybuf)
 
1420
{
 
1421
        struct ieee80211_sub_if_data *sdata;
 
1422
        int idx, i, alg = ALG_WEP;
 
1423
        u8 bcaddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 
1424
 
 
1425
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
1426
 
 
1427
        idx = erq->flags & IW_ENCODE_INDEX;
 
1428
        if (idx == 0) {
 
1429
                if (sdata->default_key)
 
1430
                        for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
 
1431
                                if (sdata->default_key == sdata->keys[i]) {
 
1432
                                        idx = i;
 
1433
                                        break;
 
1434
                                }
 
1435
                        }
 
1436
        } else if (idx < 1 || idx > 4)
 
1437
                return -EINVAL;
 
1438
        else
 
1439
                idx--;
 
1440
 
 
1441
        if (erq->flags & IW_ENCODE_DISABLED)
 
1442
                alg = ALG_NONE;
 
1443
        else if (erq->length == 0) {
 
1444
                /* No key data - just set the default TX key index */
 
1445
                if (sdata->default_key != sdata->keys[idx]) {
 
1446
                        ieee80211_debugfs_key_remove_default(sdata);
 
1447
                        sdata->default_key = sdata->keys[idx];
 
1448
                        if (sdata->default_key)
 
1449
                                ieee80211_debugfs_key_add_default(sdata);
 
1450
                }
 
1451
                return 0;
 
1452
        }
 
1453
 
 
1454
        return ieee80211_set_encryption(
 
1455
                dev, bcaddr,
 
1456
                idx, alg,
 
1457
                !sdata->default_key,
 
1458
                keybuf, erq->length);
 
1459
}
 
1460
 
 
1461
 
 
1462
static int ieee80211_ioctl_giwencode(struct net_device *dev,
 
1463
                                     struct iw_request_info *info,
 
1464
                                     struct iw_point *erq, char *key)
 
1465
{
 
1466
        struct ieee80211_sub_if_data *sdata;
 
1467
        int idx, i;
 
1468
 
 
1469
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
1470
 
 
1471
        idx = erq->flags & IW_ENCODE_INDEX;
 
1472
        if (idx < 1 || idx > 4) {
 
1473
                idx = -1;
 
1474
                if (!sdata->default_key)
 
1475
                        idx = 0;
 
1476
                else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
 
1477
                        if (sdata->default_key == sdata->keys[i]) {
 
1478
                                idx = i;
 
1479
                                break;
 
1480
                        }
 
1481
                }
 
1482
                if (idx < 0)
 
1483
                        return -EINVAL;
 
1484
        } else
 
1485
                idx--;
 
1486
 
 
1487
        erq->flags = idx + 1;
 
1488
 
 
1489
        if (!sdata->keys[idx]) {
 
1490
                erq->length = 0;
 
1491
                erq->flags |= IW_ENCODE_DISABLED;
 
1492
                return 0;
 
1493
        }
 
1494
 
 
1495
        memcpy(key, sdata->keys[idx]->key,
 
1496
               min((int)erq->length, sdata->keys[idx]->keylen));
 
1497
        erq->length = sdata->keys[idx]->keylen;
 
1498
        erq->flags |= IW_ENCODE_ENABLED;
 
1499
 
 
1500
        return 0;
 
1501
}
 
1502
 
 
1503
static int ieee80211_ioctl_siwauth(struct net_device *dev,
 
1504
                                   struct iw_request_info *info,
 
1505
                                   struct iw_param *data, char *extra)
 
1506
{
 
1507
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
1508
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
1509
        int ret = 0;
 
1510
 
 
1511
        switch (data->flags & IW_AUTH_INDEX) {
 
1512
        case IW_AUTH_WPA_VERSION:
 
1513
        case IW_AUTH_CIPHER_PAIRWISE:
 
1514
        case IW_AUTH_CIPHER_GROUP:
 
1515
        case IW_AUTH_WPA_ENABLED:
 
1516
        case IW_AUTH_RX_UNENCRYPTED_EAPOL:
 
1517
                break;
 
1518
        case IW_AUTH_KEY_MGMT:
 
1519
                if (sdata->type != IEEE80211_IF_TYPE_STA)
 
1520
                        ret = -EINVAL;
 
1521
                else {
 
1522
                        /*
 
1523
                         * TODO: sdata->u.sta.key_mgmt does not match with WE18
 
1524
                         * value completely; could consider modifying this to
 
1525
                         * be closer to WE18. For now, this value is not really
 
1526
                         * used for anything else than Privacy matching, so the
 
1527
                         * current code here should be more or less OK.
 
1528
                         */
 
1529
                        if (data->value & IW_AUTH_KEY_MGMT_802_1X) {
 
1530
                                sdata->u.sta.key_mgmt =
 
1531
                                        IEEE80211_KEY_MGMT_WPA_EAP;
 
1532
                        } else if (data->value & IW_AUTH_KEY_MGMT_PSK) {
 
1533
                                sdata->u.sta.key_mgmt =
 
1534
                                        IEEE80211_KEY_MGMT_WPA_PSK;
 
1535
                        } else {
 
1536
                                sdata->u.sta.key_mgmt =
 
1537
                                        IEEE80211_KEY_MGMT_NONE;
 
1538
                        }
 
1539
                }
 
1540
                break;
 
1541
        case IW_AUTH_80211_AUTH_ALG:
 
1542
                if (sdata->type == IEEE80211_IF_TYPE_STA ||
 
1543
                    sdata->type == IEEE80211_IF_TYPE_IBSS)
 
1544
                        sdata->u.sta.auth_algs = data->value;
 
1545
                else
 
1546
                        ret = -EOPNOTSUPP;
 
1547
                break;
 
1548
        case IW_AUTH_PRIVACY_INVOKED:
 
1549
                if (local->ops->set_privacy_invoked)
 
1550
                        ret = local->ops->set_privacy_invoked(
 
1551
                                        local_to_hw(local), data->value);
 
1552
                break;
 
1553
        default:
 
1554
                ret = -EOPNOTSUPP;
 
1555
                break;
 
1556
        }
 
1557
        return ret;
 
1558
}
 
1559
 
 
1560
/* Get wireless statistics.  Called by /proc/net/wireless and by SIOCGIWSTATS */
 
1561
static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev)
 
1562
{
 
1563
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
1564
        struct iw_statistics *wstats = &local->wstats;
 
1565
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
1566
        struct sta_info *sta = NULL;
 
1567
 
 
1568
        if (sdata->type == IEEE80211_IF_TYPE_STA ||
 
1569
            sdata->type == IEEE80211_IF_TYPE_IBSS)
 
1570
                sta = iwlwifi_sta_info_get(local, sdata->u.sta.bssid);
 
1571
        if (!sta) {
 
1572
                wstats->discard.fragment = 0;
 
1573
                wstats->discard.misc = 0;
 
1574
                wstats->qual.qual = 0;
 
1575
                wstats->qual.level = 0;
 
1576
                wstats->qual.noise = 0;
 
1577
                wstats->qual.updated = IW_QUAL_ALL_INVALID;
 
1578
        } else {
 
1579
                wstats->qual.level = sta->last_rssi;
 
1580
                wstats->qual.qual = sta->last_signal;
 
1581
                wstats->qual.noise = sta->last_noise;
 
1582
                wstats->qual.updated = local->wstats_flags;
 
1583
                iwlwifi_sta_info_put(sta);
 
1584
        }
 
1585
        return wstats;
 
1586
}
 
1587
 
 
1588
static int ieee80211_ioctl_giwauth(struct net_device *dev,
 
1589
                                   struct iw_request_info *info,
 
1590
                                   struct iw_param *data, char *extra)
 
1591
{
 
1592
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
1593
        int ret = 0;
 
1594
 
 
1595
        switch (data->flags & IW_AUTH_INDEX) {
 
1596
        case IW_AUTH_80211_AUTH_ALG:
 
1597
                if (sdata->type == IEEE80211_IF_TYPE_STA ||
 
1598
                    sdata->type == IEEE80211_IF_TYPE_IBSS)
 
1599
                        data->value = sdata->u.sta.auth_algs;
 
1600
                else
 
1601
                        ret = -EOPNOTSUPP;
 
1602
                break;
 
1603
        default:
 
1604
                ret = -EOPNOTSUPP;
 
1605
                break;
 
1606
        }
 
1607
        return ret;
 
1608
}
 
1609
 
 
1610
 
 
1611
static int ieee80211_ioctl_siwencodeext(struct net_device *dev,
 
1612
                                        struct iw_request_info *info,
 
1613
                                        struct iw_point *erq, char *extra)
 
1614
{
 
1615
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
1616
        struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
 
1617
        int alg, idx, i;
 
1618
 
 
1619
        switch (ext->alg) {
 
1620
        case IW_ENCODE_ALG_NONE:
 
1621
                alg = ALG_NONE;
 
1622
                break;
 
1623
        case IW_ENCODE_ALG_WEP:
 
1624
                alg = ALG_WEP;
 
1625
                break;
 
1626
        case IW_ENCODE_ALG_TKIP:
 
1627
                alg = ALG_TKIP;
 
1628
                break;
 
1629
        case IW_ENCODE_ALG_CCMP:
 
1630
                alg = ALG_CCMP;
 
1631
                break;
 
1632
        default:
 
1633
                return -EOPNOTSUPP;
 
1634
        }
 
1635
 
 
1636
        if (erq->flags & IW_ENCODE_DISABLED)
 
1637
                alg = ALG_NONE;
 
1638
 
 
1639
        idx = erq->flags & IW_ENCODE_INDEX;
 
1640
        if (idx < 1 || idx > 4) {
 
1641
                idx = -1;
 
1642
                if (!sdata->default_key)
 
1643
                        idx = 0;
 
1644
                else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
 
1645
                        if (sdata->default_key == sdata->keys[i]) {
 
1646
                                idx = i;
 
1647
                                break;
 
1648
                        }
 
1649
                }
 
1650
                if (idx < 0)
 
1651
                        return -EINVAL;
 
1652
        } else
 
1653
                idx--;
 
1654
 
 
1655
        return ieee80211_set_encryption(dev, ext->addr.sa_data, idx, alg,
 
1656
                                        ext->ext_flags &
 
1657
                                        IW_ENCODE_EXT_SET_TX_KEY,
 
1658
                                        ext->key, ext->key_len);
 
1659
}
 
1660
 
 
1661
 
 
1662
static const struct iw_priv_args ieee80211_ioctl_priv[] = {
 
1663
        { PRISM2_IOCTL_PRISM2_PARAM,
 
1664
          IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "param" },
 
1665
        { PRISM2_IOCTL_GET_PRISM2_PARAM,
 
1666
          IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
 
1667
          IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_param" },
 
1668
};
 
1669
 
 
1670
/* Structures to export the Wireless Handlers */
 
1671
 
 
1672
static const iw_handler ieee80211_handler[] =
 
1673
{
 
1674
        (iw_handler) NULL,                              /* SIOCSIWCOMMIT */
 
1675
        (iw_handler) ieee80211_ioctl_giwname,           /* SIOCGIWNAME */
 
1676
        (iw_handler) NULL,                              /* SIOCSIWNWID */
 
1677
        (iw_handler) NULL,                              /* SIOCGIWNWID */
 
1678
        (iw_handler) ieee80211_ioctl_siwfreq,           /* SIOCSIWFREQ */
 
1679
        (iw_handler) ieee80211_ioctl_giwfreq,           /* SIOCGIWFREQ */
 
1680
        (iw_handler) ieee80211_ioctl_siwmode,           /* SIOCSIWMODE */
 
1681
        (iw_handler) ieee80211_ioctl_giwmode,           /* SIOCGIWMODE */
 
1682
        (iw_handler) NULL,                              /* SIOCSIWSENS */
 
1683
        (iw_handler) NULL,                              /* SIOCGIWSENS */
 
1684
        (iw_handler) NULL /* not used */,               /* SIOCSIWRANGE */
 
1685
        (iw_handler) ieee80211_ioctl_giwrange,          /* SIOCGIWRANGE */
 
1686
        (iw_handler) NULL /* not used */,               /* SIOCSIWPRIV */
 
1687
        (iw_handler) NULL /* kernel code */,            /* SIOCGIWPRIV */
 
1688
        (iw_handler) NULL /* not used */,               /* SIOCSIWSTATS */
 
1689
        (iw_handler) NULL /* kernel code */,            /* SIOCGIWSTATS */
 
1690
        iw_handler_set_spy,                             /* SIOCSIWSPY */
 
1691
        iw_handler_get_spy,                             /* SIOCGIWSPY */
 
1692
        iw_handler_set_thrspy,                          /* SIOCSIWTHRSPY */
 
1693
        iw_handler_get_thrspy,                          /* SIOCGIWTHRSPY */
 
1694
        (iw_handler) ieee80211_ioctl_siwap,             /* SIOCSIWAP */
 
1695
        (iw_handler) ieee80211_ioctl_giwap,             /* SIOCGIWAP */
 
1696
        (iw_handler) ieee80211_ioctl_siwmlme,           /* SIOCSIWMLME */
 
1697
        (iw_handler) NULL,                              /* SIOCGIWAPLIST */
 
1698
        (iw_handler) ieee80211_ioctl_siwscan,           /* SIOCSIWSCAN */
 
1699
        (iw_handler) ieee80211_ioctl_giwscan,           /* SIOCGIWSCAN */
 
1700
        (iw_handler) ieee80211_ioctl_siwessid,          /* SIOCSIWESSID */
 
1701
        (iw_handler) ieee80211_ioctl_giwessid,          /* SIOCGIWESSID */
 
1702
        (iw_handler) ieee80211_ioctl_siwnick,           /* SIOCSIWNICKN */
 
1703
        (iw_handler) ieee80211_ioctl_giwnick,           /* SIOCGIWNICKN */
 
1704
        (iw_handler) NULL,                              /* -- hole -- */
 
1705
        (iw_handler) NULL,                              /* -- hole -- */
 
1706
        (iw_handler) ieee80211_ioctl_siwrate,           /* SIOCSIWRATE */
 
1707
        (iw_handler) ieee80211_ioctl_giwrate,           /* SIOCGIWRATE */
 
1708
        (iw_handler) ieee80211_ioctl_siwrts,            /* SIOCSIWRTS */
 
1709
        (iw_handler) ieee80211_ioctl_giwrts,            /* SIOCGIWRTS */
 
1710
        (iw_handler) ieee80211_ioctl_siwfrag,           /* SIOCSIWFRAG */
 
1711
        (iw_handler) ieee80211_ioctl_giwfrag,           /* SIOCGIWFRAG */
 
1712
        (iw_handler) ieee80211_ioctl_siwtxpow,          /* SIOCSIWTXPOW */
 
1713
        (iw_handler) ieee80211_ioctl_giwtxpow,          /* SIOCGIWTXPOW */
 
1714
        (iw_handler) ieee80211_ioctl_siwretry,          /* SIOCSIWRETRY */
 
1715
        (iw_handler) ieee80211_ioctl_giwretry,          /* SIOCGIWRETRY */
 
1716
        (iw_handler) ieee80211_ioctl_siwencode,         /* SIOCSIWENCODE */
 
1717
        (iw_handler) ieee80211_ioctl_giwencode,         /* SIOCGIWENCODE */
 
1718
        (iw_handler) ieee80211_ioctl_siwpower,          /* SIOCSIWPOWER */
 
1719
        (iw_handler) ieee80211_ioctl_giwpower,          /* SIOCGIWPOWER */
 
1720
        (iw_handler) NULL,                              /* -- hole -- */
 
1721
        (iw_handler) NULL,                              /* -- hole -- */
 
1722
        (iw_handler) ieee80211_ioctl_siwgenie,          /* SIOCSIWGENIE */
 
1723
        (iw_handler) NULL,                              /* SIOCGIWGENIE */
 
1724
        (iw_handler) ieee80211_ioctl_siwauth,           /* SIOCSIWAUTH */
 
1725
        (iw_handler) ieee80211_ioctl_giwauth,           /* SIOCGIWAUTH */
 
1726
        (iw_handler) ieee80211_ioctl_siwencodeext,      /* SIOCSIWENCODEEXT */
 
1727
        (iw_handler) NULL,                              /* SIOCGIWENCODEEXT */
 
1728
        (iw_handler) NULL,                              /* SIOCSIWPMKSA */
 
1729
        (iw_handler) NULL,                              /* -- hole -- */
 
1730
};
 
1731
 
 
1732
static const iw_handler ieee80211_private_handler[] =
 
1733
{                                                       /* SIOCIWFIRSTPRIV + */
 
1734
        (iw_handler) ieee80211_ioctl_prism2_param,      /* 0 */
 
1735
        (iw_handler) ieee80211_ioctl_get_prism2_param,  /* 1 */
 
1736
};
 
1737
 
 
1738
const struct iw_handler_def ieee80211_iw_handler_def =
 
1739
{
 
1740
        .num_standard   = ARRAY_SIZE(ieee80211_handler),
 
1741
        .num_private    = ARRAY_SIZE(ieee80211_private_handler),
 
1742
        .num_private_args = ARRAY_SIZE(ieee80211_ioctl_priv),
 
1743
        .standard       = (iw_handler *) ieee80211_handler,
 
1744
        .private        = (iw_handler *) ieee80211_private_handler,
 
1745
        .private_args   = (struct iw_priv_args *) ieee80211_ioctl_priv,
 
1746
        .get_wireless_stats = ieee80211_get_wireless_stats,
 
1747
};