blob: c306d52566e0dfda1673b37a089a85dd40ea78a7 [file] [log] [blame]
Johannes Berg370121e2006-01-04 16:32:16 +01001/*
2 * This file contains our _wx handlers. Make sure you EXPORT_SYMBOL_GPL them
Johannes Berg4855d252006-01-12 21:12:59 +01003 *
Johannes Berg79859052006-01-31 19:31:41 +01004 * Copyright (c) 2005, 2006 Johannes Berg <johannes@sipsolutions.net>
5 * Joseph Jezak <josejx@gentoo.org>
6 * Larry Finger <Larry.Finger@lwfinger.net>
7 * Danny van Dyk <kugelfang@gentoo.org>
8 * Michael Buesch <mbuesch@freenet.de>
Johannes Berg4855d252006-01-12 21:12:59 +01009 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of version 2 of the GNU General Public License as
12 * published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 * The full GNU General Public License is included in this distribution in the
24 * file called COPYING.
Johannes Berg370121e2006-01-04 16:32:16 +010025 */
26
27#include "ieee80211softmac_priv.h"
28
29#include <net/iw_handler.h>
Johannes Berg818667f2006-04-20 20:02:03 +020030/* for is_broadcast_ether_addr and is_zero_ether_addr */
31#include <linux/etherdevice.h>
Johannes Berg370121e2006-01-04 16:32:16 +010032
33int
34ieee80211softmac_wx_trigger_scan(struct net_device *net_dev,
35 struct iw_request_info *info,
36 union iwreq_data *data,
37 char *extra)
38{
39 struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
40 return ieee80211softmac_start_scan(sm);
41}
42EXPORT_SYMBOL_GPL(ieee80211softmac_wx_trigger_scan);
43
44
johannes@sipsolutions.netba2f8c12006-04-11 10:58:06 +020045/* if we're still scanning, return -EAGAIN so that userspace tools
46 * can get the complete scan results, otherwise return 0. */
Johannes Berg370121e2006-01-04 16:32:16 +010047int
48ieee80211softmac_wx_get_scan_results(struct net_device *net_dev,
49 struct iw_request_info *info,
50 union iwreq_data *data,
51 char *extra)
52{
johannes@sipsolutions.netba2f8c12006-04-11 10:58:06 +020053 unsigned long flags;
Johannes Berg370121e2006-01-04 16:32:16 +010054 struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
johannes@sipsolutions.netba2f8c12006-04-11 10:58:06 +020055
56 spin_lock_irqsave(&sm->lock, flags);
57 if (sm->scanning) {
58 spin_unlock_irqrestore(&sm->lock, flags);
59 return -EAGAIN;
60 }
61 spin_unlock_irqrestore(&sm->lock, flags);
Johannes Berg370121e2006-01-04 16:32:16 +010062 return ieee80211_wx_get_scan(sm->ieee, info, data, extra);
63}
64EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_scan_results);
65
66int
67ieee80211softmac_wx_set_essid(struct net_device *net_dev,
68 struct iw_request_info *info,
69 union iwreq_data *data,
70 char *extra)
71{
72 struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
Joseph Jezakcb74c432006-06-11 12:00:37 -040073 struct ieee80211softmac_network *n;
74 struct ieee80211softmac_auth_queue_item *authptr;
Johannes Berg370121e2006-01-04 16:32:16 +010075 int length = 0;
Michael Buesch7c28ad22006-09-27 15:26:33 +030076
77 mutex_lock(&sm->associnfo.mutex);
Joseph Jezakcb74c432006-06-11 12:00:37 -040078
79 /* Check if we're already associating to this or another network
80 * If it's another network, cancel and start over with our new network
81 * If it's our network, ignore the change, we're already doing it!
82 */
Michael Buesch7c28ad22006-09-27 15:26:33 +030083 if((sm->associnfo.associating || sm->associnfo.associated) &&
Larry Fingerb978d022006-08-31 10:01:39 -050084 (data->essid.flags && data->essid.length)) {
Joseph Jezakcb74c432006-06-11 12:00:37 -040085 /* Get the associating network */
86 n = ieee80211softmac_get_network_by_bssid(sm, sm->associnfo.bssid);
Larry Fingerb978d022006-08-31 10:01:39 -050087 if(n && n->essid.len == data->essid.length &&
Joseph Jezakcb74c432006-06-11 12:00:37 -040088 !memcmp(n->essid.data, extra, n->essid.len)) {
89 dprintk(KERN_INFO PFX "Already associating or associated to "MAC_FMT"\n",
90 MAC_ARG(sm->associnfo.bssid));
Michael Buesch7c28ad22006-09-27 15:26:33 +030091 goto out;
Joseph Jezakcb74c432006-06-11 12:00:37 -040092 } else {
93 dprintk(KERN_INFO PFX "Canceling existing associate request!\n");
Joseph Jezakcb74c432006-06-11 12:00:37 -040094 /* Cancel assoc work */
95 cancel_delayed_work(&sm->associnfo.work);
96 /* We don't have to do this, but it's a little cleaner */
97 list_for_each_entry(authptr, &sm->auth_queue, list)
98 cancel_delayed_work(&authptr->work);
99 sm->associnfo.bssvalid = 0;
100 sm->associnfo.bssfixed = 0;
Joseph Jezakcb74c432006-06-11 12:00:37 -0400101 flush_scheduled_work();
Michael Buesch7c28ad22006-09-27 15:26:33 +0300102 sm->associnfo.associating = 0;
103 sm->associnfo.associated = 0;
Joseph Jezakcb74c432006-06-11 12:00:37 -0400104 }
105 }
106
107
Johannes Berg370121e2006-01-04 16:32:16 +0100108 sm->associnfo.static_essid = 0;
Joseph Jezakcb74c432006-06-11 12:00:37 -0400109 sm->associnfo.assoc_wait = 0;
Johannes Berg370121e2006-01-04 16:32:16 +0100110
Larry Fingerb978d022006-08-31 10:01:39 -0500111 if (data->essid.flags && data->essid.length) {
112 length = min((int)data->essid.length, IW_ESSID_MAX_SIZE);
Johannes Berg370121e2006-01-04 16:32:16 +0100113 if (length) {
114 memcpy(sm->associnfo.req_essid.data, extra, length);
115 sm->associnfo.static_essid = 1;
116 }
117 }
Johannes Berg370121e2006-01-04 16:32:16 +0100118
119 /* set our requested ESSID length.
120 * If applicable, we have already copied the data in */
121 sm->associnfo.req_essid.len = length;
122
Michael Buesch7c28ad22006-09-27 15:26:33 +0300123 sm->associnfo.associating = 1;
Johannes Berg370121e2006-01-04 16:32:16 +0100124 /* queue lower level code to do work (if necessary) */
David Howellsc4028952006-11-22 14:57:56 +0000125 schedule_delayed_work(&sm->associnfo.work, 0);
Michael Buesch7c28ad22006-09-27 15:26:33 +0300126out:
127 mutex_unlock(&sm->associnfo.mutex);
Johannes Berg370121e2006-01-04 16:32:16 +0100128
Johannes Berg370121e2006-01-04 16:32:16 +0100129 return 0;
130}
131EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_essid);
132
133int
134ieee80211softmac_wx_get_essid(struct net_device *net_dev,
135 struct iw_request_info *info,
136 union iwreq_data *data,
137 char *extra)
138{
139 struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
Johannes Berg370121e2006-01-04 16:32:16 +0100140
Michael Buesch7c28ad22006-09-27 15:26:33 +0300141 mutex_lock(&sm->associnfo.mutex);
Johannes Berg370121e2006-01-04 16:32:16 +0100142 /* If all fails, return ANY (empty) */
143 data->essid.length = 0;
144 data->essid.flags = 0; /* active */
YOSHIFUJI Hideaki64265652007-02-09 23:24:46 +0900145
Johannes Berg370121e2006-01-04 16:32:16 +0100146 /* If we have a statically configured ESSID then return it */
147 if (sm->associnfo.static_essid) {
148 data->essid.length = sm->associnfo.req_essid.len;
149 data->essid.flags = 1; /* active */
150 memcpy(extra, sm->associnfo.req_essid.data, sm->associnfo.req_essid.len);
151 }
YOSHIFUJI Hideaki64265652007-02-09 23:24:46 +0900152
Johannes Berg370121e2006-01-04 16:32:16 +0100153 /* If we're associating/associated, return that */
Michael Buesch7c28ad22006-09-27 15:26:33 +0300154 if (sm->associnfo.associated || sm->associnfo.associating) {
Johannes Berg370121e2006-01-04 16:32:16 +0100155 data->essid.length = sm->associnfo.associate_essid.len;
156 data->essid.flags = 1; /* active */
157 memcpy(extra, sm->associnfo.associate_essid.data, sm->associnfo.associate_essid.len);
158 }
Michael Buesch7c28ad22006-09-27 15:26:33 +0300159 mutex_unlock(&sm->associnfo.mutex);
160
Johannes Berg370121e2006-01-04 16:32:16 +0100161 return 0;
162}
163EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_essid);
164
165int
166ieee80211softmac_wx_set_rate(struct net_device *net_dev,
167 struct iw_request_info *info,
168 union iwreq_data *data,
169 char *extra)
170{
171 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
172 struct ieee80211_device *ieee = mac->ieee;
173 unsigned long flags;
174 s32 in_rate = data->bitrate.value;
175 u8 rate;
176 int is_ofdm = 0;
177 int err = -EINVAL;
178
179 if (in_rate == -1) {
David Woodhouse2638fed2006-03-23 22:43:38 +0000180 /* FIXME: We don't correctly handle backing down to lower
181 rates, so 801.11g devices start off at 11M for now. People
182 can manually change it if they really need to, but 11M is
183 more reliable. Note similar logic in
YOSHIFUJI Hideaki64265652007-02-09 23:24:46 +0900184 ieee80211softmac_wx_set_rate() */
David Woodhouse2638fed2006-03-23 22:43:38 +0000185 if (ieee->modulation & IEEE80211_CCK_MODULATION)
Johannes Berg370121e2006-01-04 16:32:16 +0100186 in_rate = 11000000;
David Woodhouse2638fed2006-03-23 22:43:38 +0000187 else
188 in_rate = 54000000;
Johannes Berg370121e2006-01-04 16:32:16 +0100189 }
190
191 switch (in_rate) {
192 case 1000000:
193 rate = IEEE80211_CCK_RATE_1MB;
194 break;
195 case 2000000:
196 rate = IEEE80211_CCK_RATE_2MB;
197 break;
198 case 5500000:
199 rate = IEEE80211_CCK_RATE_5MB;
200 break;
201 case 11000000:
202 rate = IEEE80211_CCK_RATE_11MB;
203 break;
204 case 6000000:
205 rate = IEEE80211_OFDM_RATE_6MB;
206 is_ofdm = 1;
207 break;
208 case 9000000:
209 rate = IEEE80211_OFDM_RATE_9MB;
210 is_ofdm = 1;
211 break;
212 case 12000000:
213 rate = IEEE80211_OFDM_RATE_12MB;
214 is_ofdm = 1;
215 break;
216 case 18000000:
217 rate = IEEE80211_OFDM_RATE_18MB;
218 is_ofdm = 1;
219 break;
220 case 24000000:
221 rate = IEEE80211_OFDM_RATE_24MB;
222 is_ofdm = 1;
223 break;
224 case 36000000:
225 rate = IEEE80211_OFDM_RATE_36MB;
226 is_ofdm = 1;
227 break;
228 case 48000000:
229 rate = IEEE80211_OFDM_RATE_48MB;
230 is_ofdm = 1;
231 break;
232 case 54000000:
233 rate = IEEE80211_OFDM_RATE_54MB;
234 is_ofdm = 1;
235 break;
236 default:
237 goto out;
238 }
239
240 spin_lock_irqsave(&mac->lock, flags);
241
242 /* Check if correct modulation for this PHY. */
243 if (is_ofdm && !(ieee->modulation & IEEE80211_OFDM_MODULATION))
244 goto out_unlock;
245
Daniel Drake8462fe32006-05-01 22:45:50 +0100246 mac->txrates.user_rate = rate;
247 ieee80211softmac_recalc_txrates(mac);
Johannes Berg370121e2006-01-04 16:32:16 +0100248 err = 0;
249
YOSHIFUJI Hideaki64265652007-02-09 23:24:46 +0900250out_unlock:
Johannes Berg370121e2006-01-04 16:32:16 +0100251 spin_unlock_irqrestore(&mac->lock, flags);
252out:
253 return err;
254}
255EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_rate);
256
257int
258ieee80211softmac_wx_get_rate(struct net_device *net_dev,
259 struct iw_request_info *info,
260 union iwreq_data *data,
261 char *extra)
262{
263 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
264 unsigned long flags;
265 int err = -EINVAL;
266
267 spin_lock_irqsave(&mac->lock, flags);
John W. Linville6bbdce52007-01-02 21:22:05 -0500268
269 if (unlikely(!mac->running)) {
270 err = -ENODEV;
271 goto out_unlock;
272 }
273
Johannes Berg370121e2006-01-04 16:32:16 +0100274 switch (mac->txrates.default_rate) {
275 case IEEE80211_CCK_RATE_1MB:
276 data->bitrate.value = 1000000;
277 break;
278 case IEEE80211_CCK_RATE_2MB:
279 data->bitrate.value = 2000000;
280 break;
281 case IEEE80211_CCK_RATE_5MB:
282 data->bitrate.value = 5500000;
283 break;
284 case IEEE80211_CCK_RATE_11MB:
285 data->bitrate.value = 11000000;
286 break;
287 case IEEE80211_OFDM_RATE_6MB:
288 data->bitrate.value = 6000000;
289 break;
290 case IEEE80211_OFDM_RATE_9MB:
291 data->bitrate.value = 9000000;
292 break;
293 case IEEE80211_OFDM_RATE_12MB:
294 data->bitrate.value = 12000000;
295 break;
296 case IEEE80211_OFDM_RATE_18MB:
297 data->bitrate.value = 18000000;
298 break;
299 case IEEE80211_OFDM_RATE_24MB:
300 data->bitrate.value = 24000000;
301 break;
302 case IEEE80211_OFDM_RATE_36MB:
303 data->bitrate.value = 36000000;
304 break;
305 case IEEE80211_OFDM_RATE_48MB:
306 data->bitrate.value = 48000000;
307 break;
308 case IEEE80211_OFDM_RATE_54MB:
309 data->bitrate.value = 54000000;
310 break;
311 default:
312 assert(0);
313 goto out_unlock;
314 }
315 err = 0;
316out_unlock:
317 spin_unlock_irqrestore(&mac->lock, flags);
318
319 return err;
320}
321EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_rate);
322
323int
324ieee80211softmac_wx_get_wap(struct net_device *net_dev,
325 struct iw_request_info *info,
326 union iwreq_data *data,
327 char *extra)
328{
329 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
330 int err = 0;
Johannes Berg370121e2006-01-04 16:32:16 +0100331
Michael Buesch7c28ad22006-09-27 15:26:33 +0300332 mutex_lock(&mac->associnfo.mutex);
Johannes Berg370121e2006-01-04 16:32:16 +0100333 if (mac->associnfo.bssvalid)
334 memcpy(data->ap_addr.sa_data, mac->associnfo.bssid, ETH_ALEN);
335 else
336 memset(data->ap_addr.sa_data, 0xff, ETH_ALEN);
337 data->ap_addr.sa_family = ARPHRD_ETHER;
Michael Buesch7c28ad22006-09-27 15:26:33 +0300338 mutex_unlock(&mac->associnfo.mutex);
339
Johannes Berg370121e2006-01-04 16:32:16 +0100340 return err;
341}
342EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_wap);
343
344int
345ieee80211softmac_wx_set_wap(struct net_device *net_dev,
346 struct iw_request_info *info,
347 union iwreq_data *data,
348 char *extra)
349{
350 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
Johannes Berg370121e2006-01-04 16:32:16 +0100351
352 /* sanity check */
353 if (data->ap_addr.sa_family != ARPHRD_ETHER) {
354 return -EINVAL;
355 }
356
Michael Buesch7c28ad22006-09-27 15:26:33 +0300357 mutex_lock(&mac->associnfo.mutex);
Johannes Berg818667f2006-04-20 20:02:03 +0200358 if (is_broadcast_ether_addr(data->ap_addr.sa_data)) {
359 /* the bssid we have is not to be fixed any longer,
360 * and we should reassociate to the best AP. */
361 mac->associnfo.bssfixed = 0;
362 /* force reassociation */
363 mac->associnfo.bssvalid = 0;
Michael Buesch7c28ad22006-09-27 15:26:33 +0300364 if (mac->associnfo.associated)
David Howellsc4028952006-11-22 14:57:56 +0000365 schedule_delayed_work(&mac->associnfo.work, 0);
Johannes Berg818667f2006-04-20 20:02:03 +0200366 } else if (is_zero_ether_addr(data->ap_addr.sa_data)) {
367 /* the bssid we have is no longer fixed */
368 mac->associnfo.bssfixed = 0;
YOSHIFUJI Hideaki64265652007-02-09 23:24:46 +0900369 } else {
Johannes Berg370121e2006-01-04 16:32:16 +0100370 if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) {
Michael Buesch7c28ad22006-09-27 15:26:33 +0300371 if (mac->associnfo.associating || mac->associnfo.associated) {
Johannes Berg370121e2006-01-04 16:32:16 +0100372 /* bssid unchanged and associated or associating - just return */
373 goto out;
374 }
375 } else {
376 /* copy new value in data->ap_addr.sa_data to bssid */
377 memcpy(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN);
Johannes Berg818667f2006-04-20 20:02:03 +0200378 }
379 /* tell the other code that this bssid should be used no matter what */
380 mac->associnfo.bssfixed = 1;
Johannes Berg370121e2006-01-04 16:32:16 +0100381 /* queue associate if new bssid or (old one again and not associated) */
David Howellsc4028952006-11-22 14:57:56 +0000382 schedule_delayed_work(&mac->associnfo.work, 0);
YOSHIFUJI Hideaki64265652007-02-09 23:24:46 +0900383 }
Johannes Berg370121e2006-01-04 16:32:16 +0100384
Johannes Berg818667f2006-04-20 20:02:03 +0200385 out:
Michael Buesch7c28ad22006-09-27 15:26:33 +0300386 mutex_unlock(&mac->associnfo.mutex);
387
Johannes Berg370121e2006-01-04 16:32:16 +0100388 return 0;
389}
390EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_wap);
391
392int
393ieee80211softmac_wx_set_genie(struct net_device *dev,
394 struct iw_request_info *info,
395 union iwreq_data *wrqu,
396 char *extra)
397{
398 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
399 unsigned long flags;
400 int err = 0;
401 char *buf;
402 int i;
Michael Buesch7c28ad22006-09-27 15:26:33 +0300403
404 mutex_lock(&mac->associnfo.mutex);
Johannes Berg370121e2006-01-04 16:32:16 +0100405 spin_lock_irqsave(&mac->lock, flags);
406 /* bleh. shouldn't be locked for that kmalloc... */
407
408 if (wrqu->data.length) {
409 if ((wrqu->data.length < 2) || (extra[1]+2 != wrqu->data.length)) {
410 /* this is an IE, so the length must be
411 * correct. Is it possible though that
412 * more than one IE is passed in?
413 */
414 err = -EINVAL;
415 goto out;
416 }
417 if (mac->wpa.IEbuflen <= wrqu->data.length) {
418 buf = kmalloc(wrqu->data.length, GFP_ATOMIC);
419 if (!buf) {
420 err = -ENOMEM;
421 goto out;
422 }
423 kfree(mac->wpa.IE);
424 mac->wpa.IE = buf;
425 mac->wpa.IEbuflen = wrqu->data.length;
426 }
427 memcpy(mac->wpa.IE, extra, wrqu->data.length);
428 dprintk(KERN_INFO PFX "generic IE set to ");
429 for (i=0;i<wrqu->data.length;i++)
Larry Finger7bd6b912006-06-08 09:47:42 -0500430 dprintk("%.2x", (u8)mac->wpa.IE[i]);
Johannes Berg370121e2006-01-04 16:32:16 +0100431 dprintk("\n");
432 mac->wpa.IElen = wrqu->data.length;
433 } else {
434 kfree(mac->wpa.IE);
435 mac->wpa.IE = NULL;
436 mac->wpa.IElen = 0;
437 mac->wpa.IEbuflen = 0;
438 }
439
YOSHIFUJI Hideaki64265652007-02-09 23:24:46 +0900440 out:
Johannes Berg370121e2006-01-04 16:32:16 +0100441 spin_unlock_irqrestore(&mac->lock, flags);
Michael Buesch7c28ad22006-09-27 15:26:33 +0300442 mutex_unlock(&mac->associnfo.mutex);
443
Johannes Berg370121e2006-01-04 16:32:16 +0100444 return err;
445}
446EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_genie);
447
448int
449ieee80211softmac_wx_get_genie(struct net_device *dev,
450 struct iw_request_info *info,
451 union iwreq_data *wrqu,
452 char *extra)
453{
454 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
455 unsigned long flags;
456 int err = 0;
457 int space = wrqu->data.length;
Michael Buesch7c28ad22006-09-27 15:26:33 +0300458
459 mutex_lock(&mac->associnfo.mutex);
Johannes Berg370121e2006-01-04 16:32:16 +0100460 spin_lock_irqsave(&mac->lock, flags);
YOSHIFUJI Hideaki64265652007-02-09 23:24:46 +0900461
Johannes Berg370121e2006-01-04 16:32:16 +0100462 wrqu->data.length = 0;
YOSHIFUJI Hideaki64265652007-02-09 23:24:46 +0900463
Johannes Berg370121e2006-01-04 16:32:16 +0100464 if (mac->wpa.IE && mac->wpa.IElen) {
465 wrqu->data.length = mac->wpa.IElen;
466 if (mac->wpa.IElen <= space)
467 memcpy(extra, mac->wpa.IE, mac->wpa.IElen);
468 else
469 err = -E2BIG;
470 }
471 spin_unlock_irqrestore(&mac->lock, flags);
Ulrich Kunitz0c234ae2006-12-10 18:27:01 +0100472 mutex_unlock(&mac->associnfo.mutex);
Michael Buesch7c28ad22006-09-27 15:26:33 +0300473
Johannes Berg370121e2006-01-04 16:32:16 +0100474 return err;
475}
476EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_genie);
477
Johannes Berg9a1771e2006-04-20 20:02:02 +0200478int
479ieee80211softmac_wx_set_mlme(struct net_device *dev,
480 struct iw_request_info *info,
481 union iwreq_data *wrqu,
482 char *extra)
483{
484 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
485 struct iw_mlme *mlme = (struct iw_mlme *)extra;
486 u16 reason = cpu_to_le16(mlme->reason_code);
487 struct ieee80211softmac_network *net;
Michael Buesch7c28ad22006-09-27 15:26:33 +0300488 int err = -EINVAL;
489
490 mutex_lock(&mac->associnfo.mutex);
Johannes Berg9a1771e2006-04-20 20:02:02 +0200491
492 if (memcmp(mac->associnfo.bssid, mlme->addr.sa_data, ETH_ALEN)) {
493 printk(KERN_DEBUG PFX "wx_set_mlme: requested operation on net we don't use\n");
Michael Buesch7c28ad22006-09-27 15:26:33 +0300494 goto out;
Johannes Berg9a1771e2006-04-20 20:02:02 +0200495 }
496
497 switch (mlme->cmd) {
498 case IW_MLME_DEAUTH:
499 net = ieee80211softmac_get_network_by_bssid_locked(mac, mlme->addr.sa_data);
500 if (!net) {
501 printk(KERN_DEBUG PFX "wx_set_mlme: we should know the net here...\n");
Michael Buesch7c28ad22006-09-27 15:26:33 +0300502 goto out;
Johannes Berg9a1771e2006-04-20 20:02:02 +0200503 }
Maxime Austruycc8ce992006-12-03 10:40:01 -0600504 err = ieee80211softmac_deauth_req(mac, net, reason);
505 goto out;
Johannes Berg9a1771e2006-04-20 20:02:02 +0200506 case IW_MLME_DISASSOC:
Daniel Drake6d92f832006-05-01 22:23:27 +0100507 ieee80211softmac_send_disassoc_req(mac, reason);
Michael Buesch7c28ad22006-09-27 15:26:33 +0300508 mac->associnfo.associated = 0;
509 mac->associnfo.associating = 0;
510 err = 0;
511 goto out;
Johannes Berg9a1771e2006-04-20 20:02:02 +0200512 default:
Michael Buesch7c28ad22006-09-27 15:26:33 +0300513 err = -EOPNOTSUPP;
Johannes Berg9a1771e2006-04-20 20:02:02 +0200514 }
Michael Buesch7c28ad22006-09-27 15:26:33 +0300515
516out:
517 mutex_unlock(&mac->associnfo.mutex);
518
519 return err;
Johannes Berg9a1771e2006-04-20 20:02:02 +0200520}
521EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_mlme);