blob: d054e9224b3e270110790f08f540df208cbc0556 [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
Michael Bueschfdc8f432007-07-31 20:41:04 +020077check_assoc_again:
Michael Buesch7c28ad22006-09-27 15:26:33 +030078 mutex_lock(&sm->associnfo.mutex);
Joseph Jezakcb74c432006-06-11 12:00:37 -040079 /* 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;
Michael Buesch7c28ad22006-09-27 15:26:33 +0300101 sm->associnfo.associating = 0;
102 sm->associnfo.associated = 0;
Michael Bueschfdc8f432007-07-31 20:41:04 +0200103 /* We must unlock to avoid deadlocks with the assoc workqueue
104 * on the associnfo.mutex */
105 mutex_unlock(&sm->associnfo.mutex);
106 flush_scheduled_work();
107 /* Avoid race! Check assoc status again. Maybe someone started an
108 * association while we flushed. */
109 goto check_assoc_again;
Joseph Jezakcb74c432006-06-11 12:00:37 -0400110 }
111 }
112
Johannes Berg370121e2006-01-04 16:32:16 +0100113 sm->associnfo.static_essid = 0;
Joseph Jezakcb74c432006-06-11 12:00:37 -0400114 sm->associnfo.assoc_wait = 0;
Johannes Berg370121e2006-01-04 16:32:16 +0100115
Larry Fingerb978d022006-08-31 10:01:39 -0500116 if (data->essid.flags && data->essid.length) {
117 length = min((int)data->essid.length, IW_ESSID_MAX_SIZE);
Johannes Berg370121e2006-01-04 16:32:16 +0100118 if (length) {
119 memcpy(sm->associnfo.req_essid.data, extra, length);
120 sm->associnfo.static_essid = 1;
121 }
122 }
Johannes Berg370121e2006-01-04 16:32:16 +0100123
124 /* set our requested ESSID length.
125 * If applicable, we have already copied the data in */
126 sm->associnfo.req_essid.len = length;
127
Michael Buesch7c28ad22006-09-27 15:26:33 +0300128 sm->associnfo.associating = 1;
Johannes Berg370121e2006-01-04 16:32:16 +0100129 /* queue lower level code to do work (if necessary) */
David Howellsc4028952006-11-22 14:57:56 +0000130 schedule_delayed_work(&sm->associnfo.work, 0);
Michael Buesch7c28ad22006-09-27 15:26:33 +0300131out:
132 mutex_unlock(&sm->associnfo.mutex);
Johannes Berg370121e2006-01-04 16:32:16 +0100133
Johannes Berg370121e2006-01-04 16:32:16 +0100134 return 0;
135}
136EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_essid);
137
138int
139ieee80211softmac_wx_get_essid(struct net_device *net_dev,
140 struct iw_request_info *info,
141 union iwreq_data *data,
142 char *extra)
143{
144 struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
Johannes Berg370121e2006-01-04 16:32:16 +0100145
Michael Buesch7c28ad22006-09-27 15:26:33 +0300146 mutex_lock(&sm->associnfo.mutex);
Johannes Berg370121e2006-01-04 16:32:16 +0100147 /* If all fails, return ANY (empty) */
148 data->essid.length = 0;
149 data->essid.flags = 0; /* active */
YOSHIFUJI Hideaki64265652007-02-09 23:24:46 +0900150
Johannes Berg370121e2006-01-04 16:32:16 +0100151 /* If we have a statically configured ESSID then return it */
152 if (sm->associnfo.static_essid) {
153 data->essid.length = sm->associnfo.req_essid.len;
154 data->essid.flags = 1; /* active */
155 memcpy(extra, sm->associnfo.req_essid.data, sm->associnfo.req_essid.len);
156 }
YOSHIFUJI Hideaki64265652007-02-09 23:24:46 +0900157
Johannes Berg370121e2006-01-04 16:32:16 +0100158 /* If we're associating/associated, return that */
Michael Buesch7c28ad22006-09-27 15:26:33 +0300159 if (sm->associnfo.associated || sm->associnfo.associating) {
Johannes Berg370121e2006-01-04 16:32:16 +0100160 data->essid.length = sm->associnfo.associate_essid.len;
161 data->essid.flags = 1; /* active */
162 memcpy(extra, sm->associnfo.associate_essid.data, sm->associnfo.associate_essid.len);
163 }
Michael Buesch7c28ad22006-09-27 15:26:33 +0300164 mutex_unlock(&sm->associnfo.mutex);
165
Johannes Berg370121e2006-01-04 16:32:16 +0100166 return 0;
167}
168EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_essid);
169
170int
171ieee80211softmac_wx_set_rate(struct net_device *net_dev,
172 struct iw_request_info *info,
173 union iwreq_data *data,
174 char *extra)
175{
176 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
177 struct ieee80211_device *ieee = mac->ieee;
178 unsigned long flags;
179 s32 in_rate = data->bitrate.value;
180 u8 rate;
181 int is_ofdm = 0;
182 int err = -EINVAL;
183
184 if (in_rate == -1) {
Larry Fingerbb52a652007-02-13 18:58:03 -0600185 if (ieee->modulation & IEEE80211_OFDM_MODULATION)
186 in_rate = 24000000;
David Woodhouse2638fed2006-03-23 22:43:38 +0000187 else
Larry Fingerbb52a652007-02-13 18:58:03 -0600188 in_rate = 11000000;
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 Berg9a1771e82006-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 Berg9a1771e82006-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 Berg9a1771e82006-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 Berg9a1771e82006-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 Berg9a1771e82006-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 Berg9a1771e82006-04-20 20:02:02 +0200512 default:
Michael Buesch7c28ad22006-09-27 15:26:33 +0300513 err = -EOPNOTSUPP;
Johannes Berg9a1771e82006-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 Berg9a1771e82006-04-20 20:02:02 +0200520}
521EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_mlme);