diff options
Diffstat (limited to 'net/mac80211/wext.c')
-rw-r--r-- | net/mac80211/wext.c | 552 |
1 files changed, 47 insertions, 505 deletions
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 959aa8379ccf..c14394744a9c 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c | |||
@@ -27,100 +27,6 @@ | |||
27 | #include "aes_ccm.h" | 27 | #include "aes_ccm.h" |
28 | 28 | ||
29 | 29 | ||
30 | static int ieee80211_set_encryption(struct ieee80211_sub_if_data *sdata, u8 *sta_addr, | ||
31 | int idx, int alg, int remove, | ||
32 | int set_tx_key, const u8 *_key, | ||
33 | size_t key_len) | ||
34 | { | ||
35 | struct ieee80211_local *local = sdata->local; | ||
36 | struct sta_info *sta; | ||
37 | struct ieee80211_key *key; | ||
38 | int err; | ||
39 | |||
40 | if (alg == ALG_AES_CMAC) { | ||
41 | if (idx < NUM_DEFAULT_KEYS || | ||
42 | idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) { | ||
43 | printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d " | ||
44 | "(BIP)\n", sdata->dev->name, idx); | ||
45 | return -EINVAL; | ||
46 | } | ||
47 | } else if (idx < 0 || idx >= NUM_DEFAULT_KEYS) { | ||
48 | printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n", | ||
49 | sdata->dev->name, idx); | ||
50 | return -EINVAL; | ||
51 | } | ||
52 | |||
53 | if (remove) { | ||
54 | rcu_read_lock(); | ||
55 | |||
56 | err = 0; | ||
57 | |||
58 | if (is_broadcast_ether_addr(sta_addr)) { | ||
59 | key = sdata->keys[idx]; | ||
60 | } else { | ||
61 | sta = sta_info_get(local, sta_addr); | ||
62 | if (!sta) { | ||
63 | err = -ENOENT; | ||
64 | goto out_unlock; | ||
65 | } | ||
66 | key = sta->key; | ||
67 | } | ||
68 | |||
69 | ieee80211_key_free(key); | ||
70 | } else { | ||
71 | key = ieee80211_key_alloc(alg, idx, key_len, _key); | ||
72 | if (!key) | ||
73 | return -ENOMEM; | ||
74 | |||
75 | sta = NULL; | ||
76 | err = 0; | ||
77 | |||
78 | rcu_read_lock(); | ||
79 | |||
80 | if (!is_broadcast_ether_addr(sta_addr)) { | ||
81 | set_tx_key = 0; | ||
82 | /* | ||
83 | * According to the standard, the key index of a | ||
84 | * pairwise key must be zero. However, some AP are | ||
85 | * broken when it comes to WEP key indices, so we | ||
86 | * work around this. | ||
87 | */ | ||
88 | if (idx != 0 && alg != ALG_WEP) { | ||
89 | ieee80211_key_free(key); | ||
90 | err = -EINVAL; | ||
91 | goto out_unlock; | ||
92 | } | ||
93 | |||
94 | sta = sta_info_get(local, sta_addr); | ||
95 | if (!sta) { | ||
96 | ieee80211_key_free(key); | ||
97 | err = -ENOENT; | ||
98 | goto out_unlock; | ||
99 | } | ||
100 | } | ||
101 | |||
102 | if (alg == ALG_WEP && | ||
103 | key_len != LEN_WEP40 && key_len != LEN_WEP104) { | ||
104 | ieee80211_key_free(key); | ||
105 | err = -EINVAL; | ||
106 | goto out_unlock; | ||
107 | } | ||
108 | |||
109 | ieee80211_key_link(key, sdata, sta); | ||
110 | |||
111 | if (set_tx_key || (!sta && !sdata->default_key && key)) | ||
112 | ieee80211_set_default_key(sdata, idx); | ||
113 | if (alg == ALG_AES_CMAC && | ||
114 | (set_tx_key || (!sta && !sdata->default_mgmt_key && key))) | ||
115 | ieee80211_set_default_mgmt_key(sdata, idx); | ||
116 | } | ||
117 | |||
118 | out_unlock: | ||
119 | rcu_read_unlock(); | ||
120 | |||
121 | return err; | ||
122 | } | ||
123 | |||
124 | static int ieee80211_ioctl_siwgenie(struct net_device *dev, | 30 | static int ieee80211_ioctl_siwgenie(struct net_device *dev, |
125 | struct iw_request_info *info, | 31 | struct iw_request_info *info, |
126 | struct iw_point *data, char *extra) | 32 | struct iw_point *data, char *extra) |
@@ -135,6 +41,7 @@ static int ieee80211_ioctl_siwgenie(struct net_device *dev, | |||
135 | return ret; | 41 | return ret; |
136 | sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL; | 42 | sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL; |
137 | sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME; | 43 | sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME; |
44 | sdata->u.mgd.flags &= ~IEEE80211_STA_CONTROL_PORT; | ||
138 | ieee80211_sta_req_auth(sdata); | 45 | ieee80211_sta_req_auth(sdata); |
139 | return 0; | 46 | return 0; |
140 | } | 47 | } |
@@ -149,17 +56,14 @@ static int ieee80211_ioctl_siwfreq(struct net_device *dev, | |||
149 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 56 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
150 | 57 | ||
151 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | 58 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) |
152 | sdata->u.ibss.flags &= ~IEEE80211_IBSS_AUTO_CHANNEL_SEL; | 59 | return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra); |
153 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) | 60 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) |
154 | sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_CHANNEL_SEL; | 61 | sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_CHANNEL_SEL; |
155 | 62 | ||
156 | /* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */ | 63 | /* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */ |
157 | if (freq->e == 0) { | 64 | if (freq->e == 0) { |
158 | if (freq->m < 0) { | 65 | if (freq->m < 0) { |
159 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | 66 | if (sdata->vif.type == NL80211_IFTYPE_STATION) |
160 | sdata->u.ibss.flags |= | ||
161 | IEEE80211_IBSS_AUTO_CHANNEL_SEL; | ||
162 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) | ||
163 | sdata->u.mgd.flags |= | 67 | sdata->u.mgd.flags |= |
164 | IEEE80211_STA_AUTO_CHANNEL_SEL; | 68 | IEEE80211_STA_AUTO_CHANNEL_SEL; |
165 | return 0; | 69 | return 0; |
@@ -183,8 +87,12 @@ static int ieee80211_ioctl_giwfreq(struct net_device *dev, | |||
183 | struct iw_freq *freq, char *extra) | 87 | struct iw_freq *freq, char *extra) |
184 | { | 88 | { |
185 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 89 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
90 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
91 | |||
92 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | ||
93 | return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra); | ||
186 | 94 | ||
187 | freq->m = local->hw.conf.channel->center_freq; | 95 | freq->m = local->oper_channel->center_freq; |
188 | freq->e = 6; | 96 | freq->e = 6; |
189 | 97 | ||
190 | return 0; | 98 | return 0; |
@@ -195,15 +103,17 @@ static int ieee80211_ioctl_siwessid(struct net_device *dev, | |||
195 | struct iw_request_info *info, | 103 | struct iw_request_info *info, |
196 | struct iw_point *data, char *ssid) | 104 | struct iw_point *data, char *ssid) |
197 | { | 105 | { |
198 | struct ieee80211_sub_if_data *sdata; | 106 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
199 | size_t len = data->length; | 107 | size_t len = data->length; |
200 | int ret; | 108 | int ret; |
201 | 109 | ||
110 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | ||
111 | return cfg80211_ibss_wext_siwessid(dev, info, data, ssid); | ||
112 | |||
202 | /* iwconfig uses nul termination in SSID.. */ | 113 | /* iwconfig uses nul termination in SSID.. */ |
203 | if (len > 0 && ssid[len - 1] == '\0') | 114 | if (len > 0 && ssid[len - 1] == '\0') |
204 | len--; | 115 | len--; |
205 | 116 | ||
206 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
207 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 117 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
208 | if (data->flags) | 118 | if (data->flags) |
209 | sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_SSID_SEL; | 119 | sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_SSID_SEL; |
@@ -215,10 +125,10 @@ static int ieee80211_ioctl_siwessid(struct net_device *dev, | |||
215 | return ret; | 125 | return ret; |
216 | 126 | ||
217 | sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME; | 127 | sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME; |
128 | sdata->u.mgd.flags &= ~IEEE80211_STA_CONTROL_PORT; | ||
218 | ieee80211_sta_req_auth(sdata); | 129 | ieee80211_sta_req_auth(sdata); |
219 | return 0; | 130 | return 0; |
220 | } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | 131 | } |
221 | return ieee80211_ibss_set_ssid(sdata, ssid, len); | ||
222 | 132 | ||
223 | return -EOPNOTSUPP; | 133 | return -EOPNOTSUPP; |
224 | } | 134 | } |
@@ -229,9 +139,13 @@ static int ieee80211_ioctl_giwessid(struct net_device *dev, | |||
229 | struct iw_point *data, char *ssid) | 139 | struct iw_point *data, char *ssid) |
230 | { | 140 | { |
231 | size_t len; | 141 | size_t len; |
232 | |||
233 | struct ieee80211_sub_if_data *sdata; | 142 | struct ieee80211_sub_if_data *sdata; |
143 | |||
234 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 144 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
145 | |||
146 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | ||
147 | return cfg80211_ibss_wext_giwessid(dev, info, data, ssid); | ||
148 | |||
235 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 149 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
236 | int res = ieee80211_sta_get_ssid(sdata, ssid, &len); | 150 | int res = ieee80211_sta_get_ssid(sdata, ssid, &len); |
237 | if (res == 0) { | 151 | if (res == 0) { |
@@ -240,14 +154,6 @@ static int ieee80211_ioctl_giwessid(struct net_device *dev, | |||
240 | } else | 154 | } else |
241 | data->flags = 0; | 155 | data->flags = 0; |
242 | return res; | 156 | return res; |
243 | } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { | ||
244 | int res = ieee80211_ibss_get_ssid(sdata, ssid, &len); | ||
245 | if (res == 0) { | ||
246 | data->length = len; | ||
247 | data->flags = 1; | ||
248 | } else | ||
249 | data->flags = 0; | ||
250 | return res; | ||
251 | } | 157 | } |
252 | 158 | ||
253 | return -EOPNOTSUPP; | 159 | return -EOPNOTSUPP; |
@@ -258,9 +164,11 @@ static int ieee80211_ioctl_siwap(struct net_device *dev, | |||
258 | struct iw_request_info *info, | 164 | struct iw_request_info *info, |
259 | struct sockaddr *ap_addr, char *extra) | 165 | struct sockaddr *ap_addr, char *extra) |
260 | { | 166 | { |
261 | struct ieee80211_sub_if_data *sdata; | 167 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
168 | |||
169 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | ||
170 | return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra); | ||
262 | 171 | ||
263 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
264 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 172 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
265 | int ret; | 173 | int ret; |
266 | 174 | ||
@@ -275,18 +183,9 @@ static int ieee80211_ioctl_siwap(struct net_device *dev, | |||
275 | if (ret) | 183 | if (ret) |
276 | return ret; | 184 | return ret; |
277 | sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME; | 185 | sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME; |
186 | sdata->u.mgd.flags &= ~IEEE80211_STA_CONTROL_PORT; | ||
278 | ieee80211_sta_req_auth(sdata); | 187 | ieee80211_sta_req_auth(sdata); |
279 | return 0; | 188 | return 0; |
280 | } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { | ||
281 | if (is_zero_ether_addr((u8 *) &ap_addr->sa_data)) | ||
282 | sdata->u.ibss.flags |= IEEE80211_IBSS_AUTO_BSSID_SEL | | ||
283 | IEEE80211_IBSS_AUTO_CHANNEL_SEL; | ||
284 | else if (is_broadcast_ether_addr((u8 *) &ap_addr->sa_data)) | ||
285 | sdata->u.ibss.flags |= IEEE80211_IBSS_AUTO_BSSID_SEL; | ||
286 | else | ||
287 | sdata->u.ibss.flags &= ~IEEE80211_IBSS_AUTO_BSSID_SEL; | ||
288 | |||
289 | return ieee80211_ibss_set_bssid(sdata, (u8 *) &ap_addr->sa_data); | ||
290 | } else if (sdata->vif.type == NL80211_IFTYPE_WDS) { | 189 | } else if (sdata->vif.type == NL80211_IFTYPE_WDS) { |
291 | /* | 190 | /* |
292 | * If it is necessary to update the WDS peer address | 191 | * If it is necessary to update the WDS peer address |
@@ -312,9 +211,11 @@ static int ieee80211_ioctl_giwap(struct net_device *dev, | |||
312 | struct iw_request_info *info, | 211 | struct iw_request_info *info, |
313 | struct sockaddr *ap_addr, char *extra) | 212 | struct sockaddr *ap_addr, char *extra) |
314 | { | 213 | { |
315 | struct ieee80211_sub_if_data *sdata; | 214 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
215 | |||
216 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | ||
217 | return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra); | ||
316 | 218 | ||
317 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
318 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 219 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
319 | if (sdata->u.mgd.state == IEEE80211_STA_MLME_ASSOCIATED) { | 220 | if (sdata->u.mgd.state == IEEE80211_STA_MLME_ASSOCIATED) { |
320 | ap_addr->sa_family = ARPHRD_ETHER; | 221 | ap_addr->sa_family = ARPHRD_ETHER; |
@@ -322,13 +223,6 @@ static int ieee80211_ioctl_giwap(struct net_device *dev, | |||
322 | } else | 223 | } else |
323 | memset(&ap_addr->sa_data, 0, ETH_ALEN); | 224 | memset(&ap_addr->sa_data, 0, ETH_ALEN); |
324 | return 0; | 225 | return 0; |
325 | } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { | ||
326 | if (sdata->u.ibss.state == IEEE80211_IBSS_MLME_JOINED) { | ||
327 | ap_addr->sa_family = ARPHRD_ETHER; | ||
328 | memcpy(&ap_addr->sa_data, sdata->u.ibss.bssid, ETH_ALEN); | ||
329 | } else | ||
330 | memset(&ap_addr->sa_data, 0, ETH_ALEN); | ||
331 | return 0; | ||
332 | } else if (sdata->vif.type == NL80211_IFTYPE_WDS) { | 226 | } else if (sdata->vif.type == NL80211_IFTYPE_WDS) { |
333 | ap_addr->sa_family = ARPHRD_ETHER; | 227 | ap_addr->sa_family = ARPHRD_ETHER; |
334 | memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN); | 228 | memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN); |
@@ -487,258 +381,6 @@ static int ieee80211_ioctl_giwtxpower(struct net_device *dev, | |||
487 | return 0; | 381 | return 0; |
488 | } | 382 | } |
489 | 383 | ||
490 | static int ieee80211_ioctl_siwrts(struct net_device *dev, | ||
491 | struct iw_request_info *info, | ||
492 | struct iw_param *rts, char *extra) | ||
493 | { | ||
494 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
495 | |||
496 | if (rts->disabled) | ||
497 | local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; | ||
498 | else if (!rts->fixed) | ||
499 | /* if the rts value is not fixed, then take default */ | ||
500 | local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; | ||
501 | else if (rts->value < 0 || rts->value > IEEE80211_MAX_RTS_THRESHOLD) | ||
502 | return -EINVAL; | ||
503 | else | ||
504 | local->rts_threshold = rts->value; | ||
505 | |||
506 | /* If the wlan card performs RTS/CTS in hardware/firmware, | ||
507 | * configure it here */ | ||
508 | |||
509 | if (local->ops->set_rts_threshold) | ||
510 | local->ops->set_rts_threshold(local_to_hw(local), | ||
511 | local->rts_threshold); | ||
512 | |||
513 | return 0; | ||
514 | } | ||
515 | |||
516 | static int ieee80211_ioctl_giwrts(struct net_device *dev, | ||
517 | struct iw_request_info *info, | ||
518 | struct iw_param *rts, char *extra) | ||
519 | { | ||
520 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
521 | |||
522 | rts->value = local->rts_threshold; | ||
523 | rts->disabled = (rts->value >= IEEE80211_MAX_RTS_THRESHOLD); | ||
524 | rts->fixed = 1; | ||
525 | |||
526 | return 0; | ||
527 | } | ||
528 | |||
529 | |||
530 | static int ieee80211_ioctl_siwfrag(struct net_device *dev, | ||
531 | struct iw_request_info *info, | ||
532 | struct iw_param *frag, char *extra) | ||
533 | { | ||
534 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
535 | |||
536 | if (frag->disabled) | ||
537 | local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD; | ||
538 | else if (!frag->fixed) | ||
539 | local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD; | ||
540 | else if (frag->value < 256 || | ||
541 | frag->value > IEEE80211_MAX_FRAG_THRESHOLD) | ||
542 | return -EINVAL; | ||
543 | else { | ||
544 | /* Fragment length must be even, so strip LSB. */ | ||
545 | local->fragmentation_threshold = frag->value & ~0x1; | ||
546 | } | ||
547 | |||
548 | return 0; | ||
549 | } | ||
550 | |||
551 | static int ieee80211_ioctl_giwfrag(struct net_device *dev, | ||
552 | struct iw_request_info *info, | ||
553 | struct iw_param *frag, char *extra) | ||
554 | { | ||
555 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
556 | |||
557 | frag->value = local->fragmentation_threshold; | ||
558 | frag->disabled = (frag->value >= IEEE80211_MAX_FRAG_THRESHOLD); | ||
559 | frag->fixed = 1; | ||
560 | |||
561 | return 0; | ||
562 | } | ||
563 | |||
564 | |||
565 | static int ieee80211_ioctl_siwretry(struct net_device *dev, | ||
566 | struct iw_request_info *info, | ||
567 | struct iw_param *retry, char *extra) | ||
568 | { | ||
569 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
570 | |||
571 | if (retry->disabled || | ||
572 | (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT) | ||
573 | return -EINVAL; | ||
574 | |||
575 | if (retry->flags & IW_RETRY_MAX) { | ||
576 | local->hw.conf.long_frame_max_tx_count = retry->value; | ||
577 | } else if (retry->flags & IW_RETRY_MIN) { | ||
578 | local->hw.conf.short_frame_max_tx_count = retry->value; | ||
579 | } else { | ||
580 | local->hw.conf.long_frame_max_tx_count = retry->value; | ||
581 | local->hw.conf.short_frame_max_tx_count = retry->value; | ||
582 | } | ||
583 | |||
584 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_RETRY_LIMITS); | ||
585 | |||
586 | return 0; | ||
587 | } | ||
588 | |||
589 | |||
590 | static int ieee80211_ioctl_giwretry(struct net_device *dev, | ||
591 | struct iw_request_info *info, | ||
592 | struct iw_param *retry, char *extra) | ||
593 | { | ||
594 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
595 | |||
596 | retry->disabled = 0; | ||
597 | if (retry->flags == 0 || retry->flags & IW_RETRY_MIN) { | ||
598 | /* first return min value, iwconfig will ask max value | ||
599 | * later if needed */ | ||
600 | retry->flags |= IW_RETRY_LIMIT; | ||
601 | retry->value = local->hw.conf.short_frame_max_tx_count; | ||
602 | if (local->hw.conf.long_frame_max_tx_count != | ||
603 | local->hw.conf.short_frame_max_tx_count) | ||
604 | retry->flags |= IW_RETRY_MIN; | ||
605 | return 0; | ||
606 | } | ||
607 | if (retry->flags & IW_RETRY_MAX) { | ||
608 | retry->flags = IW_RETRY_LIMIT | IW_RETRY_MAX; | ||
609 | retry->value = local->hw.conf.long_frame_max_tx_count; | ||
610 | } | ||
611 | |||
612 | return 0; | ||
613 | } | ||
614 | |||
615 | static int ieee80211_ioctl_siwmlme(struct net_device *dev, | ||
616 | struct iw_request_info *info, | ||
617 | struct iw_point *data, char *extra) | ||
618 | { | ||
619 | struct ieee80211_sub_if_data *sdata; | ||
620 | struct iw_mlme *mlme = (struct iw_mlme *) extra; | ||
621 | |||
622 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
623 | if (!(sdata->vif.type == NL80211_IFTYPE_STATION)) | ||
624 | return -EINVAL; | ||
625 | |||
626 | switch (mlme->cmd) { | ||
627 | case IW_MLME_DEAUTH: | ||
628 | /* TODO: mlme->addr.sa_data */ | ||
629 | return ieee80211_sta_deauthenticate(sdata, mlme->reason_code); | ||
630 | case IW_MLME_DISASSOC: | ||
631 | /* TODO: mlme->addr.sa_data */ | ||
632 | return ieee80211_sta_disassociate(sdata, mlme->reason_code); | ||
633 | default: | ||
634 | return -EOPNOTSUPP; | ||
635 | } | ||
636 | } | ||
637 | |||
638 | |||
639 | static int ieee80211_ioctl_siwencode(struct net_device *dev, | ||
640 | struct iw_request_info *info, | ||
641 | struct iw_point *erq, char *keybuf) | ||
642 | { | ||
643 | struct ieee80211_sub_if_data *sdata; | ||
644 | int idx, i, alg = ALG_WEP; | ||
645 | u8 bcaddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | ||
646 | int remove = 0, ret; | ||
647 | |||
648 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
649 | |||
650 | idx = erq->flags & IW_ENCODE_INDEX; | ||
651 | if (idx == 0) { | ||
652 | if (sdata->default_key) | ||
653 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) { | ||
654 | if (sdata->default_key == sdata->keys[i]) { | ||
655 | idx = i; | ||
656 | break; | ||
657 | } | ||
658 | } | ||
659 | } else if (idx < 1 || idx > 4) | ||
660 | return -EINVAL; | ||
661 | else | ||
662 | idx--; | ||
663 | |||
664 | if (erq->flags & IW_ENCODE_DISABLED) | ||
665 | remove = 1; | ||
666 | else if (erq->length == 0) { | ||
667 | /* No key data - just set the default TX key index */ | ||
668 | ieee80211_set_default_key(sdata, idx); | ||
669 | return 0; | ||
670 | } | ||
671 | |||
672 | ret = ieee80211_set_encryption( | ||
673 | sdata, bcaddr, | ||
674 | idx, alg, remove, | ||
675 | !sdata->default_key, | ||
676 | keybuf, erq->length); | ||
677 | |||
678 | if (!ret) { | ||
679 | if (remove) | ||
680 | sdata->u.mgd.flags &= ~IEEE80211_STA_TKIP_WEP_USED; | ||
681 | else | ||
682 | sdata->u.mgd.flags |= IEEE80211_STA_TKIP_WEP_USED; | ||
683 | } | ||
684 | |||
685 | return ret; | ||
686 | } | ||
687 | |||
688 | |||
689 | static int ieee80211_ioctl_giwencode(struct net_device *dev, | ||
690 | struct iw_request_info *info, | ||
691 | struct iw_point *erq, char *key) | ||
692 | { | ||
693 | struct ieee80211_sub_if_data *sdata; | ||
694 | int idx, i; | ||
695 | |||
696 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
697 | |||
698 | idx = erq->flags & IW_ENCODE_INDEX; | ||
699 | if (idx < 1 || idx > 4) { | ||
700 | idx = -1; | ||
701 | if (!sdata->default_key) | ||
702 | idx = 0; | ||
703 | else for (i = 0; i < NUM_DEFAULT_KEYS; i++) { | ||
704 | if (sdata->default_key == sdata->keys[i]) { | ||
705 | idx = i; | ||
706 | break; | ||
707 | } | ||
708 | } | ||
709 | if (idx < 0) | ||
710 | return -EINVAL; | ||
711 | } else | ||
712 | idx--; | ||
713 | |||
714 | erq->flags = idx + 1; | ||
715 | |||
716 | if (!sdata->keys[idx]) { | ||
717 | erq->length = 0; | ||
718 | erq->flags |= IW_ENCODE_DISABLED; | ||
719 | return 0; | ||
720 | } | ||
721 | |||
722 | memcpy(key, sdata->keys[idx]->conf.key, | ||
723 | min_t(int, erq->length, sdata->keys[idx]->conf.keylen)); | ||
724 | erq->length = sdata->keys[idx]->conf.keylen; | ||
725 | erq->flags |= IW_ENCODE_ENABLED; | ||
726 | |||
727 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
728 | switch (sdata->u.mgd.auth_alg) { | ||
729 | case WLAN_AUTH_OPEN: | ||
730 | case WLAN_AUTH_LEAP: | ||
731 | erq->flags |= IW_ENCODE_OPEN; | ||
732 | break; | ||
733 | case WLAN_AUTH_SHARED_KEY: | ||
734 | erq->flags |= IW_ENCODE_RESTRICTED; | ||
735 | break; | ||
736 | } | ||
737 | } | ||
738 | |||
739 | return 0; | ||
740 | } | ||
741 | |||
742 | static int ieee80211_ioctl_siwpower(struct net_device *dev, | 384 | static int ieee80211_ioctl_siwpower(struct net_device *dev, |
743 | struct iw_request_info *info, | 385 | struct iw_request_info *info, |
744 | struct iw_param *wrq, | 386 | struct iw_param *wrq, |
@@ -747,7 +389,7 @@ static int ieee80211_ioctl_siwpower(struct net_device *dev, | |||
747 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 389 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
748 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 390 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
749 | struct ieee80211_conf *conf = &local->hw.conf; | 391 | struct ieee80211_conf *conf = &local->hw.conf; |
750 | int ret = 0, timeout = 0; | 392 | int timeout = 0; |
751 | bool ps; | 393 | bool ps; |
752 | 394 | ||
753 | if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) | 395 | if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) |
@@ -779,42 +421,18 @@ static int ieee80211_ioctl_siwpower(struct net_device *dev, | |||
779 | timeout = wrq->value / 1000; | 421 | timeout = wrq->value / 1000; |
780 | 422 | ||
781 | set: | 423 | set: |
782 | if (ps == local->powersave && timeout == conf->dynamic_ps_timeout) | 424 | if (ps == sdata->u.mgd.powersave && timeout == conf->dynamic_ps_timeout) |
783 | return ret; | 425 | return 0; |
784 | 426 | ||
785 | local->powersave = ps; | 427 | sdata->u.mgd.powersave = ps; |
786 | conf->dynamic_ps_timeout = timeout; | 428 | conf->dynamic_ps_timeout = timeout; |
787 | 429 | ||
788 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) | 430 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) |
789 | ret = ieee80211_hw_config(local, | 431 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); |
790 | IEEE80211_CONF_CHANGE_DYNPS_TIMEOUT); | ||
791 | 432 | ||
792 | if (!(sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED)) | 433 | ieee80211_recalc_ps(local, -1); |
793 | return ret; | ||
794 | |||
795 | if (conf->dynamic_ps_timeout > 0 && | ||
796 | !(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)) { | ||
797 | mod_timer(&local->dynamic_ps_timer, jiffies + | ||
798 | msecs_to_jiffies(conf->dynamic_ps_timeout)); | ||
799 | } else { | ||
800 | if (local->powersave) { | ||
801 | if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) | ||
802 | ieee80211_send_nullfunc(local, sdata, 1); | ||
803 | conf->flags |= IEEE80211_CONF_PS; | ||
804 | ret = ieee80211_hw_config(local, | ||
805 | IEEE80211_CONF_CHANGE_PS); | ||
806 | } else { | ||
807 | conf->flags &= ~IEEE80211_CONF_PS; | ||
808 | ret = ieee80211_hw_config(local, | ||
809 | IEEE80211_CONF_CHANGE_PS); | ||
810 | if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) | ||
811 | ieee80211_send_nullfunc(local, sdata, 0); | ||
812 | del_timer_sync(&local->dynamic_ps_timer); | ||
813 | cancel_work_sync(&local->dynamic_ps_enable_work); | ||
814 | } | ||
815 | } | ||
816 | 434 | ||
817 | return ret; | 435 | return 0; |
818 | } | 436 | } |
819 | 437 | ||
820 | static int ieee80211_ioctl_giwpower(struct net_device *dev, | 438 | static int ieee80211_ioctl_giwpower(struct net_device *dev, |
@@ -822,9 +440,9 @@ static int ieee80211_ioctl_giwpower(struct net_device *dev, | |||
822 | union iwreq_data *wrqu, | 440 | union iwreq_data *wrqu, |
823 | char *extra) | 441 | char *extra) |
824 | { | 442 | { |
825 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 443 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
826 | 444 | ||
827 | wrqu->power.disabled = !local->powersave; | 445 | wrqu->power.disabled = !sdata->u.mgd.powersave; |
828 | 446 | ||
829 | return 0; | 447 | return 0; |
830 | } | 448 | } |
@@ -997,82 +615,6 @@ static int ieee80211_ioctl_giwauth(struct net_device *dev, | |||
997 | } | 615 | } |
998 | 616 | ||
999 | 617 | ||
1000 | static int ieee80211_ioctl_siwencodeext(struct net_device *dev, | ||
1001 | struct iw_request_info *info, | ||
1002 | struct iw_point *erq, char *extra) | ||
1003 | { | ||
1004 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1005 | struct iw_encode_ext *ext = (struct iw_encode_ext *) extra; | ||
1006 | int uninitialized_var(alg), idx, i, remove = 0; | ||
1007 | |||
1008 | switch (ext->alg) { | ||
1009 | case IW_ENCODE_ALG_NONE: | ||
1010 | remove = 1; | ||
1011 | break; | ||
1012 | case IW_ENCODE_ALG_WEP: | ||
1013 | alg = ALG_WEP; | ||
1014 | break; | ||
1015 | case IW_ENCODE_ALG_TKIP: | ||
1016 | alg = ALG_TKIP; | ||
1017 | break; | ||
1018 | case IW_ENCODE_ALG_CCMP: | ||
1019 | alg = ALG_CCMP; | ||
1020 | break; | ||
1021 | case IW_ENCODE_ALG_AES_CMAC: | ||
1022 | alg = ALG_AES_CMAC; | ||
1023 | break; | ||
1024 | default: | ||
1025 | return -EOPNOTSUPP; | ||
1026 | } | ||
1027 | |||
1028 | if (erq->flags & IW_ENCODE_DISABLED) | ||
1029 | remove = 1; | ||
1030 | |||
1031 | idx = erq->flags & IW_ENCODE_INDEX; | ||
1032 | if (alg == ALG_AES_CMAC) { | ||
1033 | if (idx < NUM_DEFAULT_KEYS + 1 || | ||
1034 | idx > NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) { | ||
1035 | idx = -1; | ||
1036 | if (!sdata->default_mgmt_key) | ||
1037 | idx = 0; | ||
1038 | else for (i = NUM_DEFAULT_KEYS; | ||
1039 | i < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS; | ||
1040 | i++) { | ||
1041 | if (sdata->default_mgmt_key == sdata->keys[i]) | ||
1042 | { | ||
1043 | idx = i; | ||
1044 | break; | ||
1045 | } | ||
1046 | } | ||
1047 | if (idx < 0) | ||
1048 | return -EINVAL; | ||
1049 | } else | ||
1050 | idx--; | ||
1051 | } else { | ||
1052 | if (idx < 1 || idx > 4) { | ||
1053 | idx = -1; | ||
1054 | if (!sdata->default_key) | ||
1055 | idx = 0; | ||
1056 | else for (i = 0; i < NUM_DEFAULT_KEYS; i++) { | ||
1057 | if (sdata->default_key == sdata->keys[i]) { | ||
1058 | idx = i; | ||
1059 | break; | ||
1060 | } | ||
1061 | } | ||
1062 | if (idx < 0) | ||
1063 | return -EINVAL; | ||
1064 | } else | ||
1065 | idx--; | ||
1066 | } | ||
1067 | |||
1068 | return ieee80211_set_encryption(sdata, ext->addr.sa_data, idx, alg, | ||
1069 | remove, | ||
1070 | ext->ext_flags & | ||
1071 | IW_ENCODE_EXT_SET_TX_KEY, | ||
1072 | ext->key, ext->key_len); | ||
1073 | } | ||
1074 | |||
1075 | |||
1076 | /* Structures to export the Wireless Handlers */ | 618 | /* Structures to export the Wireless Handlers */ |
1077 | 619 | ||
1078 | static const iw_handler ieee80211_handler[] = | 620 | static const iw_handler ieee80211_handler[] = |
@@ -1099,7 +641,7 @@ static const iw_handler ieee80211_handler[] = | |||
1099 | (iw_handler) NULL, /* SIOCGIWTHRSPY */ | 641 | (iw_handler) NULL, /* SIOCGIWTHRSPY */ |
1100 | (iw_handler) ieee80211_ioctl_siwap, /* SIOCSIWAP */ | 642 | (iw_handler) ieee80211_ioctl_siwap, /* SIOCSIWAP */ |
1101 | (iw_handler) ieee80211_ioctl_giwap, /* SIOCGIWAP */ | 643 | (iw_handler) ieee80211_ioctl_giwap, /* SIOCGIWAP */ |
1102 | (iw_handler) ieee80211_ioctl_siwmlme, /* SIOCSIWMLME */ | 644 | (iw_handler) cfg80211_wext_siwmlme, /* SIOCSIWMLME */ |
1103 | (iw_handler) NULL, /* SIOCGIWAPLIST */ | 645 | (iw_handler) NULL, /* SIOCGIWAPLIST */ |
1104 | (iw_handler) cfg80211_wext_siwscan, /* SIOCSIWSCAN */ | 646 | (iw_handler) cfg80211_wext_siwscan, /* SIOCSIWSCAN */ |
1105 | (iw_handler) cfg80211_wext_giwscan, /* SIOCGIWSCAN */ | 647 | (iw_handler) cfg80211_wext_giwscan, /* SIOCGIWSCAN */ |
@@ -1111,16 +653,16 @@ static const iw_handler ieee80211_handler[] = | |||
1111 | (iw_handler) NULL, /* -- hole -- */ | 653 | (iw_handler) NULL, /* -- hole -- */ |
1112 | (iw_handler) ieee80211_ioctl_siwrate, /* SIOCSIWRATE */ | 654 | (iw_handler) ieee80211_ioctl_siwrate, /* SIOCSIWRATE */ |
1113 | (iw_handler) ieee80211_ioctl_giwrate, /* SIOCGIWRATE */ | 655 | (iw_handler) ieee80211_ioctl_giwrate, /* SIOCGIWRATE */ |
1114 | (iw_handler) ieee80211_ioctl_siwrts, /* SIOCSIWRTS */ | 656 | (iw_handler) cfg80211_wext_siwrts, /* SIOCSIWRTS */ |
1115 | (iw_handler) ieee80211_ioctl_giwrts, /* SIOCGIWRTS */ | 657 | (iw_handler) cfg80211_wext_giwrts, /* SIOCGIWRTS */ |
1116 | (iw_handler) ieee80211_ioctl_siwfrag, /* SIOCSIWFRAG */ | 658 | (iw_handler) cfg80211_wext_siwfrag, /* SIOCSIWFRAG */ |
1117 | (iw_handler) ieee80211_ioctl_giwfrag, /* SIOCGIWFRAG */ | 659 | (iw_handler) cfg80211_wext_giwfrag, /* SIOCGIWFRAG */ |
1118 | (iw_handler) ieee80211_ioctl_siwtxpower, /* SIOCSIWTXPOW */ | 660 | (iw_handler) ieee80211_ioctl_siwtxpower, /* SIOCSIWTXPOW */ |
1119 | (iw_handler) ieee80211_ioctl_giwtxpower, /* SIOCGIWTXPOW */ | 661 | (iw_handler) ieee80211_ioctl_giwtxpower, /* SIOCGIWTXPOW */ |
1120 | (iw_handler) ieee80211_ioctl_siwretry, /* SIOCSIWRETRY */ | 662 | (iw_handler) cfg80211_wext_siwretry, /* SIOCSIWRETRY */ |
1121 | (iw_handler) ieee80211_ioctl_giwretry, /* SIOCGIWRETRY */ | 663 | (iw_handler) cfg80211_wext_giwretry, /* SIOCGIWRETRY */ |
1122 | (iw_handler) ieee80211_ioctl_siwencode, /* SIOCSIWENCODE */ | 664 | (iw_handler) cfg80211_wext_siwencode, /* SIOCSIWENCODE */ |
1123 | (iw_handler) ieee80211_ioctl_giwencode, /* SIOCGIWENCODE */ | 665 | (iw_handler) cfg80211_wext_giwencode, /* SIOCGIWENCODE */ |
1124 | (iw_handler) ieee80211_ioctl_siwpower, /* SIOCSIWPOWER */ | 666 | (iw_handler) ieee80211_ioctl_siwpower, /* SIOCSIWPOWER */ |
1125 | (iw_handler) ieee80211_ioctl_giwpower, /* SIOCGIWPOWER */ | 667 | (iw_handler) ieee80211_ioctl_giwpower, /* SIOCGIWPOWER */ |
1126 | (iw_handler) NULL, /* -- hole -- */ | 668 | (iw_handler) NULL, /* -- hole -- */ |
@@ -1129,7 +671,7 @@ static const iw_handler ieee80211_handler[] = | |||
1129 | (iw_handler) NULL, /* SIOCGIWGENIE */ | 671 | (iw_handler) NULL, /* SIOCGIWGENIE */ |
1130 | (iw_handler) ieee80211_ioctl_siwauth, /* SIOCSIWAUTH */ | 672 | (iw_handler) ieee80211_ioctl_siwauth, /* SIOCSIWAUTH */ |
1131 | (iw_handler) ieee80211_ioctl_giwauth, /* SIOCGIWAUTH */ | 673 | (iw_handler) ieee80211_ioctl_giwauth, /* SIOCGIWAUTH */ |
1132 | (iw_handler) ieee80211_ioctl_siwencodeext, /* SIOCSIWENCODEEXT */ | 674 | (iw_handler) cfg80211_wext_siwencodeext, /* SIOCSIWENCODEEXT */ |
1133 | (iw_handler) NULL, /* SIOCGIWENCODEEXT */ | 675 | (iw_handler) NULL, /* SIOCGIWENCODEEXT */ |
1134 | (iw_handler) NULL, /* SIOCSIWPMKSA */ | 676 | (iw_handler) NULL, /* SIOCSIWPMKSA */ |
1135 | (iw_handler) NULL, /* -- hole -- */ | 677 | (iw_handler) NULL, /* -- hole -- */ |