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