[MAC80211]: Remove bitfields from struct ieee80211_txrx_data
[linux-2.6-block.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;
273 sdata->u.sta.auto_bssid_sel = 0;
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)
505 sdata->u.sta.auto_channel_sel = 0;
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)
511 sdata->u.sta.auto_channel_sel = 1;
512 return 0;
513 } else
514 return ieee80211_set_channel(local, freq->m, -1);
515 } else {
516 int i, div = 1000000;
517 for (i = 0; i < freq->e; i++)
518 div /= 10;
519 if (div > 0)
520 return ieee80211_set_channel(local, -1, freq->m / div);
521 else
522 return -EINVAL;
523 }
524}
525
526
527static int ieee80211_ioctl_giwfreq(struct net_device *dev,
528 struct iw_request_info *info,
529 struct iw_freq *freq, char *extra)
530{
531 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
532
533 /* TODO: in station mode (Managed/Ad-hoc) might need to poll low-level
534 * driver for the current channel with firmware-based management */
535
536 freq->m = local->hw.conf.freq;
537 freq->e = 6;
538
539 return 0;
540}
541
542
543static int ieee80211_ioctl_siwessid(struct net_device *dev,
544 struct iw_request_info *info,
545 struct iw_point *data, char *ssid)
546{
547 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
548 struct ieee80211_sub_if_data *sdata;
549 size_t len = data->length;
550
551 /* iwconfig uses nul termination in SSID.. */
552 if (len > 0 && ssid[len - 1] == '\0')
553 len--;
554
555 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
556 if (sdata->type == IEEE80211_IF_TYPE_STA ||
557 sdata->type == IEEE80211_IF_TYPE_IBSS) {
558 int ret;
559 if (local->user_space_mlme) {
560 if (len > IEEE80211_MAX_SSID_LEN)
561 return -EINVAL;
562 memcpy(sdata->u.sta.ssid, ssid, len);
563 sdata->u.sta.ssid_len = len;
564 return 0;
565 }
566 sdata->u.sta.auto_ssid_sel = !data->flags;
567 ret = ieee80211_sta_set_ssid(dev, ssid, len);
568 if (ret)
569 return ret;
570 ieee80211_sta_req_auth(dev, &sdata->u.sta);
571 return 0;
572 }
573
574 if (sdata->type == IEEE80211_IF_TYPE_AP) {
575 memcpy(sdata->u.ap.ssid, ssid, len);
576 memset(sdata->u.ap.ssid + len, 0,
577 IEEE80211_MAX_SSID_LEN - len);
578 sdata->u.ap.ssid_len = len;
579 return ieee80211_if_config(dev);
580 }
581 return -EOPNOTSUPP;
582}
583
584
585static int ieee80211_ioctl_giwessid(struct net_device *dev,
586 struct iw_request_info *info,
587 struct iw_point *data, char *ssid)
588{
589 size_t len;
590
591 struct ieee80211_sub_if_data *sdata;
592 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
593 if (sdata->type == IEEE80211_IF_TYPE_STA ||
594 sdata->type == IEEE80211_IF_TYPE_IBSS) {
595 int res = ieee80211_sta_get_ssid(dev, ssid, &len);
596 if (res == 0) {
597 data->length = len;
598 data->flags = 1;
599 } else
600 data->flags = 0;
601 return res;
602 }
603
604 if (sdata->type == IEEE80211_IF_TYPE_AP) {
605 len = sdata->u.ap.ssid_len;
606 if (len > IW_ESSID_MAX_SIZE)
607 len = IW_ESSID_MAX_SIZE;
608 memcpy(ssid, sdata->u.ap.ssid, len);
609 data->length = len;
610 data->flags = 1;
611 return 0;
612 }
613 return -EOPNOTSUPP;
614}
615
616
617static int ieee80211_ioctl_siwap(struct net_device *dev,
618 struct iw_request_info *info,
619 struct sockaddr *ap_addr, char *extra)
620{
621 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
622 struct ieee80211_sub_if_data *sdata;
623
624 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
625 if (sdata->type == IEEE80211_IF_TYPE_STA ||
626 sdata->type == IEEE80211_IF_TYPE_IBSS) {
627 int ret;
628 if (local->user_space_mlme) {
629 memcpy(sdata->u.sta.bssid, (u8 *) &ap_addr->sa_data,
630 ETH_ALEN);
631 return 0;
632 }
633 if (is_zero_ether_addr((u8 *) &ap_addr->sa_data)) {
634 sdata->u.sta.auto_bssid_sel = 1;
635 sdata->u.sta.auto_channel_sel = 1;
636 } else if (is_broadcast_ether_addr((u8 *) &ap_addr->sa_data))
637 sdata->u.sta.auto_bssid_sel = 1;
638 else
639 sdata->u.sta.auto_bssid_sel = 0;
640 ret = ieee80211_sta_set_bssid(dev, (u8 *) &ap_addr->sa_data);
641 if (ret)
642 return ret;
643 ieee80211_sta_req_auth(dev, &sdata->u.sta);
644 return 0;
645 } else if (sdata->type == IEEE80211_IF_TYPE_WDS) {
646 if (memcmp(sdata->u.wds.remote_addr, (u8 *) &ap_addr->sa_data,
647 ETH_ALEN) == 0)
648 return 0;
649 return ieee80211_if_update_wds(dev, (u8 *) &ap_addr->sa_data);
650 }
651
652 return -EOPNOTSUPP;
653}
654
655
656static int ieee80211_ioctl_giwap(struct net_device *dev,
657 struct iw_request_info *info,
658 struct sockaddr *ap_addr, char *extra)
659{
660 struct ieee80211_sub_if_data *sdata;
661
662 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
663 if (sdata->type == IEEE80211_IF_TYPE_STA ||
664 sdata->type == IEEE80211_IF_TYPE_IBSS) {
665 ap_addr->sa_family = ARPHRD_ETHER;
666 memcpy(&ap_addr->sa_data, sdata->u.sta.bssid, ETH_ALEN);
667 return 0;
668 } else if (sdata->type == IEEE80211_IF_TYPE_WDS) {
669 ap_addr->sa_family = ARPHRD_ETHER;
670 memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN);
671 return 0;
672 }
673
674 return -EOPNOTSUPP;
675}
676
677
678static int ieee80211_ioctl_siwscan(struct net_device *dev,
679 struct iw_request_info *info,
680 struct iw_point *data, char *extra)
681{
682 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
683 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
684 u8 *ssid = NULL;
685 size_t ssid_len = 0;
686
687 if (!netif_running(dev))
688 return -ENETDOWN;
689
f27b62d3
DD
690 switch (sdata->type) {
691 case IEEE80211_IF_TYPE_STA:
692 case IEEE80211_IF_TYPE_IBSS:
693 if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID) {
f0706e82
JB
694 ssid = sdata->u.sta.ssid;
695 ssid_len = sdata->u.sta.ssid_len;
f27b62d3
DD
696 }
697 break;
698 case IEEE80211_IF_TYPE_AP:
699 if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID) {
f0706e82
JB
700 ssid = sdata->u.ap.ssid;
701 ssid_len = sdata->u.ap.ssid_len;
f27b62d3
DD
702 }
703 break;
704 default:
705 return -EOPNOTSUPP;
f0706e82 706 }
f27b62d3 707
f0706e82
JB
708 return ieee80211_sta_req_scan(dev, ssid, ssid_len);
709}
710
711
712static int ieee80211_ioctl_giwscan(struct net_device *dev,
713 struct iw_request_info *info,
714 struct iw_point *data, char *extra)
715{
716 int res;
717 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
718 if (local->sta_scanning)
719 return -EAGAIN;
720 res = ieee80211_sta_scan_results(dev, extra, data->length);
721 if (res >= 0) {
722 data->length = res;
723 return 0;
724 }
725 data->length = 0;
726 return res;
727}
728
729
1fd5e589
LF
730static int ieee80211_ioctl_siwrate(struct net_device *dev,
731 struct iw_request_info *info,
732 struct iw_param *rate, char *extra)
733{
734 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
735 struct ieee80211_hw_mode *mode;
736 int i;
737 u32 target_rate = rate->value / 100000;
738 struct ieee80211_sub_if_data *sdata;
739
740 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
741 if (!sdata->bss)
742 return -ENODEV;
743 mode = local->oper_hw_mode;
744 /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates
745 * target_rate = X, rate->fixed = 1 means only rate X
746 * target_rate = X, rate->fixed = 0 means all rates <= X */
747 sdata->bss->max_ratectrl_rateidx = -1;
748 sdata->bss->force_unicast_rateidx = -1;
749 if (rate->value < 0)
750 return 0;
751 for (i=0; i< mode->num_rates; i++) {
752 struct ieee80211_rate *rates = &mode->rates[i];
753 int this_rate = rates->rate;
754
755 if (mode->mode == MODE_ATHEROS_TURBO ||
756 mode->mode == MODE_ATHEROS_TURBOG)
757 this_rate *= 2;
758 if (target_rate == this_rate) {
759 sdata->bss->max_ratectrl_rateidx = i;
760 if (rate->fixed)
761 sdata->bss->force_unicast_rateidx = i;
762 break;
763 }
764 }
765 return 0;
766}
767
b3d88ad4
LF
768static int ieee80211_ioctl_giwrate(struct net_device *dev,
769 struct iw_request_info *info,
770 struct iw_param *rate, char *extra)
771{
772 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
773 struct sta_info *sta;
774 struct ieee80211_sub_if_data *sdata;
775
776 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
777 if (sdata->type == IEEE80211_IF_TYPE_STA)
778 sta = sta_info_get(local, sdata->u.sta.bssid);
779 else
780 return -EOPNOTSUPP;
781 if (!sta)
782 return -ENODEV;
783 if (sta->txrate < local->oper_hw_mode->num_rates)
784 rate->value = local->oper_hw_mode->rates[sta->txrate].rate * 100000;
785 else
786 rate->value = 0;
787 sta_info_put(sta);
788 return 0;
789}
790
fe6aa301
LF
791static int ieee80211_ioctl_giwtxpower(struct net_device *dev,
792 struct iw_request_info *info,
793 union iwreq_data *data, char *extra)
794{
795 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
796
797 data->txpower.fixed = 1;
798 data->txpower.disabled = !(local->hw.conf.radio_enabled);
799 data->txpower.value = local->hw.conf.power_level;
800 data->txpower.flags = IW_TXPOW_DBM;
801
802 return 0;
803}
804
f0706e82
JB
805static int ieee80211_ioctl_siwrts(struct net_device *dev,
806 struct iw_request_info *info,
807 struct iw_param *rts, char *extra)
808{
809 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
810
811 if (rts->disabled)
812 local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
813 else if (rts->value < 0 || rts->value > IEEE80211_MAX_RTS_THRESHOLD)
814 return -EINVAL;
815 else
816 local->rts_threshold = rts->value;
817
818 /* If the wlan card performs RTS/CTS in hardware/firmware,
819 * configure it here */
820
821 if (local->ops->set_rts_threshold)
822 local->ops->set_rts_threshold(local_to_hw(local),
823 local->rts_threshold);
824
825 return 0;
826}
827
828static int ieee80211_ioctl_giwrts(struct net_device *dev,
829 struct iw_request_info *info,
830 struct iw_param *rts, char *extra)
831{
832 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
833
834 rts->value = local->rts_threshold;
835 rts->disabled = (rts->value >= IEEE80211_MAX_RTS_THRESHOLD);
836 rts->fixed = 1;
837
838 return 0;
839}
840
841
842static int ieee80211_ioctl_siwfrag(struct net_device *dev,
843 struct iw_request_info *info,
844 struct iw_param *frag, char *extra)
845{
846 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
847
848 if (frag->disabled)
849 local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
850 else if (frag->value < 256 ||
851 frag->value > IEEE80211_MAX_FRAG_THRESHOLD)
852 return -EINVAL;
853 else {
854 /* Fragment length must be even, so strip LSB. */
855 local->fragmentation_threshold = frag->value & ~0x1;
856 }
857
858 /* If the wlan card performs fragmentation in hardware/firmware,
859 * configure it here */
860
861 if (local->ops->set_frag_threshold)
862 local->ops->set_frag_threshold(
863 local_to_hw(local),
864 local->fragmentation_threshold);
865
866 return 0;
867}
868
869static int ieee80211_ioctl_giwfrag(struct net_device *dev,
870 struct iw_request_info *info,
871 struct iw_param *frag, char *extra)
872{
873 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
874
875 frag->value = local->fragmentation_threshold;
876 frag->disabled = (frag->value >= IEEE80211_MAX_RTS_THRESHOLD);
877 frag->fixed = 1;
878
879 return 0;
880}
881
882
883static int ieee80211_ioctl_siwretry(struct net_device *dev,
884 struct iw_request_info *info,
885 struct iw_param *retry, char *extra)
886{
887 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
888
889 if (retry->disabled ||
890 (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
891 return -EINVAL;
892
893 if (retry->flags & IW_RETRY_MAX)
894 local->long_retry_limit = retry->value;
895 else if (retry->flags & IW_RETRY_MIN)
896 local->short_retry_limit = retry->value;
897 else {
898 local->long_retry_limit = retry->value;
899 local->short_retry_limit = retry->value;
900 }
901
902 if (local->ops->set_retry_limit) {
903 return local->ops->set_retry_limit(
904 local_to_hw(local),
905 local->short_retry_limit,
906 local->long_retry_limit);
907 }
908
909 return 0;
910}
911
912
913static int ieee80211_ioctl_giwretry(struct net_device *dev,
914 struct iw_request_info *info,
915 struct iw_param *retry, char *extra)
916{
917 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
918
919 retry->disabled = 0;
920 if (retry->flags == 0 || retry->flags & IW_RETRY_MIN) {
921 /* first return min value, iwconfig will ask max value
922 * later if needed */
923 retry->flags |= IW_RETRY_LIMIT;
924 retry->value = local->short_retry_limit;
925 if (local->long_retry_limit != local->short_retry_limit)
926 retry->flags |= IW_RETRY_MIN;
927 return 0;
928 }
929 if (retry->flags & IW_RETRY_MAX) {
930 retry->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
931 retry->value = local->long_retry_limit;
932 }
933
934 return 0;
935}
936
f0706e82
JB
937static void ieee80211_key_enable_hwaccel(struct ieee80211_local *local,
938 struct ieee80211_key *key)
939{
940 struct ieee80211_key_conf *keyconf;
941 u8 addr[ETH_ALEN];
942
943 if (!key || key->alg != ALG_WEP || !key->force_sw_encrypt ||
944 (local->hw.flags & IEEE80211_HW_DEVICE_HIDES_WEP))
945 return;
946
947 memset(addr, 0xff, ETH_ALEN);
948 keyconf = ieee80211_key_data2conf(local, key);
949 if (keyconf && local->ops->set_key &&
950 local->ops->set_key(local_to_hw(local),
951 SET_KEY, addr, keyconf, 0) == 0) {
952 key->force_sw_encrypt =
953 !!(keyconf->flags & IEEE80211_KEY_FORCE_SW_ENCRYPT);
954 key->hw_key_idx = keyconf->hw_key_idx;
955 }
956 kfree(keyconf);
957}
958
959
960static void ieee80211_key_disable_hwaccel(struct ieee80211_local *local,
961 struct ieee80211_key *key)
962{
963 struct ieee80211_key_conf *keyconf;
964 u8 addr[ETH_ALEN];
965
966 if (!key || key->alg != ALG_WEP || key->force_sw_encrypt ||
967 (local->hw.flags & IEEE80211_HW_DEVICE_HIDES_WEP))
968 return;
969
970 memset(addr, 0xff, ETH_ALEN);
971 keyconf = ieee80211_key_data2conf(local, key);
972 if (keyconf && local->ops->set_key)
973 local->ops->set_key(local_to_hw(local), DISABLE_KEY,
974 addr, keyconf, 0);
975 kfree(keyconf);
976 key->force_sw_encrypt = 1;
977}
978
979
980static int ieee80211_ioctl_default_wep_only(struct ieee80211_local *local,
981 int value)
982{
983 int i;
984 struct ieee80211_sub_if_data *sdata;
985
986 local->default_wep_only = value;
987 read_lock(&local->sub_if_lock);
988 list_for_each_entry(sdata, &local->sub_if_list, list)
989 for (i = 0; i < NUM_DEFAULT_KEYS; i++)
990 if (value)
991 ieee80211_key_enable_hwaccel(local,
992 sdata->keys[i]);
993 else
994 ieee80211_key_disable_hwaccel(local,
995 sdata->keys[i]);
996 read_unlock(&local->sub_if_lock);
997
998 return 0;
999}
1000
1001
1002void ieee80211_update_default_wep_only(struct ieee80211_local *local)
1003{
1004 int i = 0;
1005 struct ieee80211_sub_if_data *sdata;
1006
1007 read_lock(&local->sub_if_lock);
1008 list_for_each_entry(sdata, &local->sub_if_list, list) {
1009
1010 if (sdata->dev == local->mdev)
1011 continue;
1012
1013 /* If there is an AP interface then depend on userspace to
1014 set default_wep_only correctly. */
1015 if (sdata->type == IEEE80211_IF_TYPE_AP) {
1016 read_unlock(&local->sub_if_lock);
1017 return;
1018 }
1019
1020 i++;
1021 }
1022
1023 read_unlock(&local->sub_if_lock);
1024
1025 if (i <= 1)
1026 ieee80211_ioctl_default_wep_only(local, 1);
1027 else
1028 ieee80211_ioctl_default_wep_only(local, 0);
1029}
1030
1031
1032static int ieee80211_ioctl_prism2_param(struct net_device *dev,
1033 struct iw_request_info *info,
1034 void *wrqu, char *extra)
1035{
1036 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
1037 struct ieee80211_sub_if_data *sdata;
1038 int *i = (int *) extra;
1039 int param = *i;
1040 int value = *(i + 1);
1041 int ret = 0;
1042
1043 if (!capable(CAP_NET_ADMIN))
1044 return -EPERM;
1045
1046 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1047
1048 switch (param) {
1049 case PRISM2_PARAM_IEEE_802_1X:
1050 if (local->ops->set_ieee8021x)
1051 ret = local->ops->set_ieee8021x(local_to_hw(local),
1052 value);
1053 if (ret)
1054 printk(KERN_DEBUG "%s: failed to set IEEE 802.1X (%d) "
1055 "for low-level driver\n", dev->name, value);
1056 else
1057 sdata->ieee802_1x = value;
1058 break;
1059
f0706e82 1060 case PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES:
d9430a32
DD
1061 if (sdata->type == IEEE80211_IF_TYPE_AP) {
1062 sdata->use_protection = !!value;
1063 ieee80211_erp_info_change_notify(dev, IEEE80211_ERP_CHANGE_PROTECTION);
1064 } else {
63fc33ce 1065 ret = -ENOENT;
d9430a32 1066 }
f0706e82
JB
1067 break;
1068
f0706e82 1069 case PRISM2_PARAM_PREAMBLE:
d9430a32
DD
1070 if (sdata->type != IEEE80211_IF_TYPE_AP) {
1071 sdata->short_preamble = !!value;
1072 ieee80211_erp_info_change_notify(dev, IEEE80211_ERP_CHANGE_PREAMBLE);
1073 } else {
7e9ed188 1074 ret = -ENOENT;
d9430a32 1075 }
f0706e82
JB
1076 break;
1077
f0706e82
JB
1078 case PRISM2_PARAM_SHORT_SLOT_TIME:
1079 if (value)
1080 local->hw.conf.flags |= IEEE80211_CONF_SHORT_SLOT_TIME;
1081 else
1082 local->hw.conf.flags &= ~IEEE80211_CONF_SHORT_SLOT_TIME;
1083 if (ieee80211_hw_config(local))
1084 ret = -EINVAL;
1085 break;
1086
1087 case PRISM2_PARAM_NEXT_MODE:
1088 local->next_mode = value;
1089 break;
1090
f0706e82
JB
1091 case PRISM2_PARAM_KEY_TX_RX_THRESHOLD:
1092 local->key_tx_rx_threshold = value;
1093 break;
1094
f0706e82
JB
1095 case PRISM2_PARAM_WIFI_WME_NOACK_TEST:
1096 local->wifi_wme_noack_test = value;
1097 break;
1098
1099 case PRISM2_PARAM_SCAN_FLAGS:
1100 local->scan_flags = value;
1101 break;
1102
1103 case PRISM2_PARAM_MIXED_CELL:
1104 if (sdata->type != IEEE80211_IF_TYPE_STA &&
1105 sdata->type != IEEE80211_IF_TYPE_IBSS)
1106 ret = -EINVAL;
1107 else
1108 sdata->u.sta.mixed_cell = !!value;
1109 break;
1110
1111 case PRISM2_PARAM_HW_MODES:
1112 local->enabled_modes = value;
1113 break;
1114
1115 case PRISM2_PARAM_CREATE_IBSS:
1116 if (sdata->type != IEEE80211_IF_TYPE_IBSS)
1117 ret = -EINVAL;
1118 else
1119 sdata->u.sta.create_ibss = !!value;
1120 break;
1121 case PRISM2_PARAM_WMM_ENABLED:
1122 if (sdata->type != IEEE80211_IF_TYPE_STA &&
1123 sdata->type != IEEE80211_IF_TYPE_IBSS)
1124 ret = -EINVAL;
1125 else
1126 sdata->u.sta.wmm_enabled = !!value;
1127 break;
f0706e82
JB
1128 default:
1129 ret = -EOPNOTSUPP;
1130 break;
1131 }
1132
1133 return ret;
1134}
1135
1136
1137static int ieee80211_ioctl_get_prism2_param(struct net_device *dev,
1138 struct iw_request_info *info,
1139 void *wrqu, char *extra)
1140{
1141 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
1142 struct ieee80211_sub_if_data *sdata;
1143 int *param = (int *) extra;
1144 int ret = 0;
1145
1146 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1147
1148 switch (*param) {
1149 case PRISM2_PARAM_IEEE_802_1X:
1150 *param = sdata->ieee802_1x;
1151 break;
1152
f0706e82 1153 case PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES:
63fc33ce 1154 *param = sdata->use_protection;
f0706e82
JB
1155 break;
1156
f0706e82 1157 case PRISM2_PARAM_PREAMBLE:
7e9ed188 1158 *param = sdata->short_preamble;
f0706e82
JB
1159 break;
1160
f0706e82
JB
1161 case PRISM2_PARAM_SHORT_SLOT_TIME:
1162 *param = !!(local->hw.conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME);
1163 break;
1164
1165 case PRISM2_PARAM_NEXT_MODE:
1166 *param = local->next_mode;
1167 break;
1168
f0706e82
JB
1169 case PRISM2_PARAM_KEY_TX_RX_THRESHOLD:
1170 *param = local->key_tx_rx_threshold;
1171 break;
1172
f0706e82
JB
1173 case PRISM2_PARAM_WIFI_WME_NOACK_TEST:
1174 *param = local->wifi_wme_noack_test;
1175 break;
1176
1177 case PRISM2_PARAM_SCAN_FLAGS:
1178 *param = local->scan_flags;
1179 break;
1180
1181 case PRISM2_PARAM_HW_MODES:
1182 *param = local->enabled_modes;
1183 break;
1184
1185 case PRISM2_PARAM_CREATE_IBSS:
1186 if (sdata->type != IEEE80211_IF_TYPE_IBSS)
1187 ret = -EINVAL;
1188 else
1189 *param = !!sdata->u.sta.create_ibss;
1190 break;
1191
1192 case PRISM2_PARAM_MIXED_CELL:
1193 if (sdata->type != IEEE80211_IF_TYPE_STA &&
1194 sdata->type != IEEE80211_IF_TYPE_IBSS)
1195 ret = -EINVAL;
1196 else
1197 *param = !!sdata->u.sta.mixed_cell;
1198 break;
1199 case PRISM2_PARAM_WMM_ENABLED:
1200 if (sdata->type != IEEE80211_IF_TYPE_STA &&
1201 sdata->type != IEEE80211_IF_TYPE_IBSS)
1202 ret = -EINVAL;
1203 else
1204 *param = !!sdata->u.sta.wmm_enabled;
1205 break;
1206 default:
1207 ret = -EOPNOTSUPP;
1208 break;
1209 }
1210
1211 return ret;
1212}
1213
1214static int ieee80211_ioctl_siwmlme(struct net_device *dev,
1215 struct iw_request_info *info,
1216 struct iw_point *data, char *extra)
1217{
1218 struct ieee80211_sub_if_data *sdata;
1219 struct iw_mlme *mlme = (struct iw_mlme *) extra;
1220
1221 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1222 if (sdata->type != IEEE80211_IF_TYPE_STA &&
1223 sdata->type != IEEE80211_IF_TYPE_IBSS)
1224 return -EINVAL;
1225
1226 switch (mlme->cmd) {
1227 case IW_MLME_DEAUTH:
1228 /* TODO: mlme->addr.sa_data */
1229 return ieee80211_sta_deauthenticate(dev, mlme->reason_code);
1230 case IW_MLME_DISASSOC:
1231 /* TODO: mlme->addr.sa_data */
1232 return ieee80211_sta_disassociate(dev, mlme->reason_code);
1233 default:
1234 return -EOPNOTSUPP;
1235 }
1236}
1237
1238
1239static int ieee80211_ioctl_siwencode(struct net_device *dev,
1240 struct iw_request_info *info,
1241 struct iw_point *erq, char *keybuf)
1242{
1243 struct ieee80211_sub_if_data *sdata;
1244 int idx, i, alg = ALG_WEP;
1245 u8 bcaddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1246
1247 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1248
1249 idx = erq->flags & IW_ENCODE_INDEX;
1250 if (idx == 0) {
1251 if (sdata->default_key)
1252 for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
1253 if (sdata->default_key == sdata->keys[i]) {
1254 idx = i;
1255 break;
1256 }
1257 }
1258 } else if (idx < 1 || idx > 4)
1259 return -EINVAL;
1260 else
1261 idx--;
1262
1263 if (erq->flags & IW_ENCODE_DISABLED)
1264 alg = ALG_NONE;
1265 else if (erq->length == 0) {
1266 /* No key data - just set the default TX key index */
e9f207f0
JB
1267 if (sdata->default_key != sdata->keys[idx]) {
1268 ieee80211_debugfs_key_remove_default(sdata);
f0706e82 1269 sdata->default_key = sdata->keys[idx];
e9f207f0
JB
1270 if (sdata->default_key)
1271 ieee80211_debugfs_key_add_default(sdata);
1272 }
f0706e82
JB
1273 return 0;
1274 }
1275
1276 return ieee80211_set_encryption(
1277 dev, bcaddr,
1278 idx, alg,
1279 !sdata->default_key,
1280 keybuf, erq->length);
1281}
1282
1283
1284static int ieee80211_ioctl_giwencode(struct net_device *dev,
1285 struct iw_request_info *info,
1286 struct iw_point *erq, char *key)
1287{
1288 struct ieee80211_sub_if_data *sdata;
1289 int idx, i;
1290
1291 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1292
1293 idx = erq->flags & IW_ENCODE_INDEX;
1294 if (idx < 1 || idx > 4) {
1295 idx = -1;
1296 if (!sdata->default_key)
1297 idx = 0;
1298 else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
1299 if (sdata->default_key == sdata->keys[i]) {
1300 idx = i;
1301 break;
1302 }
1303 }
1304 if (idx < 0)
1305 return -EINVAL;
1306 } else
1307 idx--;
1308
1309 erq->flags = idx + 1;
1310
1311 if (!sdata->keys[idx]) {
1312 erq->length = 0;
1313 erq->flags |= IW_ENCODE_DISABLED;
1314 return 0;
1315 }
1316
1317 memcpy(key, sdata->keys[idx]->key,
1318 min((int)erq->length, sdata->keys[idx]->keylen));
1319 erq->length = sdata->keys[idx]->keylen;
1320 erq->flags |= IW_ENCODE_ENABLED;
1321
1322 return 0;
1323}
1324
1325static int ieee80211_ioctl_siwauth(struct net_device *dev,
1326 struct iw_request_info *info,
1327 struct iw_param *data, char *extra)
1328{
1329 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
1330 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1331 int ret = 0;
1332
1333 switch (data->flags & IW_AUTH_INDEX) {
1334 case IW_AUTH_WPA_VERSION:
1335 case IW_AUTH_CIPHER_PAIRWISE:
1336 case IW_AUTH_CIPHER_GROUP:
1337 case IW_AUTH_WPA_ENABLED:
1338 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1339 break;
1340 case IW_AUTH_KEY_MGMT:
1341 if (sdata->type != IEEE80211_IF_TYPE_STA)
1342 ret = -EINVAL;
1343 else {
1344 /*
808718c1
JB
1345 * Key management was set by wpa_supplicant,
1346 * we only need this to associate to a network
1347 * that has privacy enabled regardless of not
1348 * having a key.
f0706e82 1349 */
808718c1 1350 sdata->u.sta.key_management_enabled = !!data->value;
f0706e82
JB
1351 }
1352 break;
1353 case IW_AUTH_80211_AUTH_ALG:
1354 if (sdata->type == IEEE80211_IF_TYPE_STA ||
1355 sdata->type == IEEE80211_IF_TYPE_IBSS)
1356 sdata->u.sta.auth_algs = data->value;
1357 else
1358 ret = -EOPNOTSUPP;
1359 break;
1360 case IW_AUTH_PRIVACY_INVOKED:
1361 if (local->ops->set_privacy_invoked)
1362 ret = local->ops->set_privacy_invoked(
1363 local_to_hw(local), data->value);
1364 break;
1365 default:
1366 ret = -EOPNOTSUPP;
1367 break;
1368 }
1369 return ret;
1370}
1371
1372/* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */
1373static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev)
1374{
1375 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
1376 struct iw_statistics *wstats = &local->wstats;
1377 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1378 struct sta_info *sta = NULL;
1379
1380 if (sdata->type == IEEE80211_IF_TYPE_STA ||
1381 sdata->type == IEEE80211_IF_TYPE_IBSS)
1382 sta = sta_info_get(local, sdata->u.sta.bssid);
1383 if (!sta) {
1384 wstats->discard.fragment = 0;
1385 wstats->discard.misc = 0;
1386 wstats->qual.qual = 0;
1387 wstats->qual.level = 0;
1388 wstats->qual.noise = 0;
1389 wstats->qual.updated = IW_QUAL_ALL_INVALID;
1390 } else {
1391 wstats->qual.level = sta->last_rssi;
1392 wstats->qual.qual = sta->last_signal;
1393 wstats->qual.noise = sta->last_noise;
1394 wstats->qual.updated = local->wstats_flags;
1395 sta_info_put(sta);
1396 }
1397 return wstats;
1398}
1399
1400static int ieee80211_ioctl_giwauth(struct net_device *dev,
1401 struct iw_request_info *info,
1402 struct iw_param *data, char *extra)
1403{
1404 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1405 int ret = 0;
1406
1407 switch (data->flags & IW_AUTH_INDEX) {
1408 case IW_AUTH_80211_AUTH_ALG:
1409 if (sdata->type == IEEE80211_IF_TYPE_STA ||
1410 sdata->type == IEEE80211_IF_TYPE_IBSS)
1411 data->value = sdata->u.sta.auth_algs;
1412 else
1413 ret = -EOPNOTSUPP;
1414 break;
1415 default:
1416 ret = -EOPNOTSUPP;
1417 break;
1418 }
1419 return ret;
1420}
1421
1422
1423static int ieee80211_ioctl_siwencodeext(struct net_device *dev,
1424 struct iw_request_info *info,
1425 struct iw_point *erq, char *extra)
1426{
1427 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1428 struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
1429 int alg, idx, i;
1430
1431 switch (ext->alg) {
1432 case IW_ENCODE_ALG_NONE:
1433 alg = ALG_NONE;
1434 break;
1435 case IW_ENCODE_ALG_WEP:
1436 alg = ALG_WEP;
1437 break;
1438 case IW_ENCODE_ALG_TKIP:
1439 alg = ALG_TKIP;
1440 break;
1441 case IW_ENCODE_ALG_CCMP:
1442 alg = ALG_CCMP;
1443 break;
1444 default:
1445 return -EOPNOTSUPP;
1446 }
1447
1448 if (erq->flags & IW_ENCODE_DISABLED)
1449 alg = ALG_NONE;
1450
1451 idx = erq->flags & IW_ENCODE_INDEX;
1452 if (idx < 1 || idx > 4) {
1453 idx = -1;
1454 if (!sdata->default_key)
1455 idx = 0;
1456 else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
1457 if (sdata->default_key == sdata->keys[i]) {
1458 idx = i;
1459 break;
1460 }
1461 }
1462 if (idx < 0)
1463 return -EINVAL;
1464 } else
1465 idx--;
1466
1467 return ieee80211_set_encryption(dev, ext->addr.sa_data, idx, alg,
1468 ext->ext_flags &
1469 IW_ENCODE_EXT_SET_TX_KEY,
1470 ext->key, ext->key_len);
1471}
1472
1473
1474static const struct iw_priv_args ieee80211_ioctl_priv[] = {
1475 { PRISM2_IOCTL_PRISM2_PARAM,
1476 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "param" },
1477 { PRISM2_IOCTL_GET_PRISM2_PARAM,
1478 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1479 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_param" },
1480};
1481
1482/* Structures to export the Wireless Handlers */
1483
1484static const iw_handler ieee80211_handler[] =
1485{
1486 (iw_handler) NULL, /* SIOCSIWCOMMIT */
1487 (iw_handler) ieee80211_ioctl_giwname, /* SIOCGIWNAME */
1488 (iw_handler) NULL, /* SIOCSIWNWID */
1489 (iw_handler) NULL, /* SIOCGIWNWID */
1490 (iw_handler) ieee80211_ioctl_siwfreq, /* SIOCSIWFREQ */
1491 (iw_handler) ieee80211_ioctl_giwfreq, /* SIOCGIWFREQ */
1492 (iw_handler) ieee80211_ioctl_siwmode, /* SIOCSIWMODE */
1493 (iw_handler) ieee80211_ioctl_giwmode, /* SIOCGIWMODE */
1494 (iw_handler) NULL, /* SIOCSIWSENS */
1495 (iw_handler) NULL, /* SIOCGIWSENS */
1496 (iw_handler) NULL /* not used */, /* SIOCSIWRANGE */
1497 (iw_handler) ieee80211_ioctl_giwrange, /* SIOCGIWRANGE */
1498 (iw_handler) NULL /* not used */, /* SIOCSIWPRIV */
1499 (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */
1500 (iw_handler) NULL /* not used */, /* SIOCSIWSTATS */
1501 (iw_handler) NULL /* kernel code */, /* SIOCGIWSTATS */
1502 iw_handler_set_spy, /* SIOCSIWSPY */
1503 iw_handler_get_spy, /* SIOCGIWSPY */
1504 iw_handler_set_thrspy, /* SIOCSIWTHRSPY */
1505 iw_handler_get_thrspy, /* SIOCGIWTHRSPY */
1506 (iw_handler) ieee80211_ioctl_siwap, /* SIOCSIWAP */
1507 (iw_handler) ieee80211_ioctl_giwap, /* SIOCGIWAP */
1508 (iw_handler) ieee80211_ioctl_siwmlme, /* SIOCSIWMLME */
1509 (iw_handler) NULL, /* SIOCGIWAPLIST */
1510 (iw_handler) ieee80211_ioctl_siwscan, /* SIOCSIWSCAN */
1511 (iw_handler) ieee80211_ioctl_giwscan, /* SIOCGIWSCAN */
1512 (iw_handler) ieee80211_ioctl_siwessid, /* SIOCSIWESSID */
1513 (iw_handler) ieee80211_ioctl_giwessid, /* SIOCGIWESSID */
1514 (iw_handler) NULL, /* SIOCSIWNICKN */
1515 (iw_handler) NULL, /* SIOCGIWNICKN */
1516 (iw_handler) NULL, /* -- hole -- */
1517 (iw_handler) NULL, /* -- hole -- */
1fd5e589 1518 (iw_handler) ieee80211_ioctl_siwrate, /* SIOCSIWRATE */
b3d88ad4 1519 (iw_handler) ieee80211_ioctl_giwrate, /* SIOCGIWRATE */
f0706e82
JB
1520 (iw_handler) ieee80211_ioctl_siwrts, /* SIOCSIWRTS */
1521 (iw_handler) ieee80211_ioctl_giwrts, /* SIOCGIWRTS */
1522 (iw_handler) ieee80211_ioctl_siwfrag, /* SIOCSIWFRAG */
1523 (iw_handler) ieee80211_ioctl_giwfrag, /* SIOCGIWFRAG */
1524 (iw_handler) NULL, /* SIOCSIWTXPOW */
fe6aa301 1525 (iw_handler) ieee80211_ioctl_giwtxpower, /* SIOCGIWTXPOW */
f0706e82
JB
1526 (iw_handler) ieee80211_ioctl_siwretry, /* SIOCSIWRETRY */
1527 (iw_handler) ieee80211_ioctl_giwretry, /* SIOCGIWRETRY */
1528 (iw_handler) ieee80211_ioctl_siwencode, /* SIOCSIWENCODE */
1529 (iw_handler) ieee80211_ioctl_giwencode, /* SIOCGIWENCODE */
1530 (iw_handler) NULL, /* SIOCSIWPOWER */
1531 (iw_handler) NULL, /* SIOCGIWPOWER */
1532 (iw_handler) NULL, /* -- hole -- */
1533 (iw_handler) NULL, /* -- hole -- */
1534 (iw_handler) ieee80211_ioctl_siwgenie, /* SIOCSIWGENIE */
1535 (iw_handler) NULL, /* SIOCGIWGENIE */
1536 (iw_handler) ieee80211_ioctl_siwauth, /* SIOCSIWAUTH */
1537 (iw_handler) ieee80211_ioctl_giwauth, /* SIOCGIWAUTH */
1538 (iw_handler) ieee80211_ioctl_siwencodeext, /* SIOCSIWENCODEEXT */
1539 (iw_handler) NULL, /* SIOCGIWENCODEEXT */
1540 (iw_handler) NULL, /* SIOCSIWPMKSA */
1541 (iw_handler) NULL, /* -- hole -- */
1542};
1543
1544static const iw_handler ieee80211_private_handler[] =
1545{ /* SIOCIWFIRSTPRIV + */
1546 (iw_handler) ieee80211_ioctl_prism2_param, /* 0 */
1547 (iw_handler) ieee80211_ioctl_get_prism2_param, /* 1 */
1548};
1549
1550const struct iw_handler_def ieee80211_iw_handler_def =
1551{
1552 .num_standard = ARRAY_SIZE(ieee80211_handler),
1553 .num_private = ARRAY_SIZE(ieee80211_private_handler),
1554 .num_private_args = ARRAY_SIZE(ieee80211_ioctl_priv),
1555 .standard = (iw_handler *) ieee80211_handler,
1556 .private = (iw_handler *) ieee80211_private_handler,
1557 .private_args = (struct iw_priv_args *) ieee80211_ioctl_priv,
1558 .get_wireless_stats = ieee80211_get_wireless_stats,
1559};