blob: ac36767b56e892c63d7eb0c0684b4d1b088f835e [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_auth_queue_item *authptr;
Johannes Berg370121e2006-01-04 16:32:16 +010074 int length = 0;
Joe Perches0795af52007-10-03 17:59:30 -070075 DECLARE_MAC_BUF(mac);
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);
Michael Buesch7c28ad22006-09-27 15:26:33 +030079 if((sm->associnfo.associating || sm->associnfo.associated) &&
Larry Fingerb978d022006-08-31 10:01:39 -050080 (data->essid.flags && data->essid.length)) {
Larry Fingerefe870f2007-09-18 22:00:52 -050081 dprintk(KERN_INFO PFX "Canceling existing associate request!\n");
82 /* Cancel assoc work */
83 cancel_delayed_work(&sm->associnfo.work);
84 /* We don't have to do this, but it's a little cleaner */
85 list_for_each_entry(authptr, &sm->auth_queue, list)
86 cancel_delayed_work(&authptr->work);
87 sm->associnfo.bssvalid = 0;
88 sm->associnfo.bssfixed = 0;
89 sm->associnfo.associating = 0;
90 sm->associnfo.associated = 0;
91 /* We must unlock to avoid deadlocks with the assoc workqueue
92 * on the associnfo.mutex */
93 mutex_unlock(&sm->associnfo.mutex);
Johannes Berg501d8572007-10-03 18:14:23 -070094 flush_workqueue(sm->wq);
Larry Fingerefe870f2007-09-18 22:00:52 -050095 /* Avoid race! Check assoc status again. Maybe someone started an
96 * association while we flushed. */
97 goto check_assoc_again;
Joseph Jezakcb74c432006-06-11 12:00:37 -040098 }
99
Johannes Berg370121e2006-01-04 16:32:16 +0100100 sm->associnfo.static_essid = 0;
Joseph Jezakcb74c432006-06-11 12:00:37 -0400101 sm->associnfo.assoc_wait = 0;
Johannes Berg370121e2006-01-04 16:32:16 +0100102
Larry Fingerb978d022006-08-31 10:01:39 -0500103 if (data->essid.flags && data->essid.length) {
104 length = min((int)data->essid.length, IW_ESSID_MAX_SIZE);
Johannes Berg370121e2006-01-04 16:32:16 +0100105 if (length) {
106 memcpy(sm->associnfo.req_essid.data, extra, length);
107 sm->associnfo.static_essid = 1;
108 }
109 }
Johannes Berg370121e2006-01-04 16:32:16 +0100110
111 /* set our requested ESSID length.
112 * If applicable, we have already copied the data in */
113 sm->associnfo.req_essid.len = length;
114
Michael Buesch7c28ad22006-09-27 15:26:33 +0300115 sm->associnfo.associating = 1;
Johannes Berg370121e2006-01-04 16:32:16 +0100116 /* queue lower level code to do work (if necessary) */
Johannes Berg501d8572007-10-03 18:14:23 -0700117 queue_delayed_work(sm->wq, &sm->associnfo.work, 0);
Richard Knutssonee0a8162007-10-01 02:24:38 +0200118
Michael Buesch7c28ad22006-09-27 15:26:33 +0300119 mutex_unlock(&sm->associnfo.mutex);
Johannes Berg370121e2006-01-04 16:32:16 +0100120
Johannes Berg370121e2006-01-04 16:32:16 +0100121 return 0;
122}
123EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_essid);
124
125int
126ieee80211softmac_wx_get_essid(struct net_device *net_dev,
127 struct iw_request_info *info,
128 union iwreq_data *data,
129 char *extra)
130{
131 struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
Johannes Berg370121e2006-01-04 16:32:16 +0100132
Michael Buesch7c28ad22006-09-27 15:26:33 +0300133 mutex_lock(&sm->associnfo.mutex);
Johannes Berg370121e2006-01-04 16:32:16 +0100134 /* If all fails, return ANY (empty) */
135 data->essid.length = 0;
136 data->essid.flags = 0; /* active */
YOSHIFUJI Hideaki64265652007-02-09 23:24:46 +0900137
Johannes Berg370121e2006-01-04 16:32:16 +0100138 /* If we have a statically configured ESSID then return it */
139 if (sm->associnfo.static_essid) {
140 data->essid.length = sm->associnfo.req_essid.len;
141 data->essid.flags = 1; /* active */
142 memcpy(extra, sm->associnfo.req_essid.data, sm->associnfo.req_essid.len);
Larry Fingerefe870f2007-09-18 22:00:52 -0500143 dprintk(KERN_INFO PFX "Getting essid from req_essid\n");
144 } else if (sm->associnfo.associated || sm->associnfo.associating) {
Johannes Berg370121e2006-01-04 16:32:16 +0100145 /* If we're associating/associated, return that */
Johannes Berg370121e2006-01-04 16:32:16 +0100146 data->essid.length = sm->associnfo.associate_essid.len;
147 data->essid.flags = 1; /* active */
148 memcpy(extra, sm->associnfo.associate_essid.data, sm->associnfo.associate_essid.len);
Larry Fingerefe870f2007-09-18 22:00:52 -0500149 dprintk(KERN_INFO PFX "Getting essid from associate_essid\n");
Johannes Berg370121e2006-01-04 16:32:16 +0100150 }
Michael Buesch7c28ad22006-09-27 15:26:33 +0300151 mutex_unlock(&sm->associnfo.mutex);
152
Johannes Berg370121e2006-01-04 16:32:16 +0100153 return 0;
154}
155EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_essid);
156
157int
158ieee80211softmac_wx_set_rate(struct net_device *net_dev,
159 struct iw_request_info *info,
160 union iwreq_data *data,
161 char *extra)
162{
163 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
164 struct ieee80211_device *ieee = mac->ieee;
165 unsigned long flags;
166 s32 in_rate = data->bitrate.value;
167 u8 rate;
168 int is_ofdm = 0;
169 int err = -EINVAL;
170
171 if (in_rate == -1) {
Larry Fingerbb52a652007-02-13 18:58:03 -0600172 if (ieee->modulation & IEEE80211_OFDM_MODULATION)
173 in_rate = 24000000;
David Woodhouse2638fed2006-03-23 22:43:38 +0000174 else
Larry Fingerbb52a652007-02-13 18:58:03 -0600175 in_rate = 11000000;
Johannes Berg370121e2006-01-04 16:32:16 +0100176 }
177
178 switch (in_rate) {
179 case 1000000:
180 rate = IEEE80211_CCK_RATE_1MB;
181 break;
182 case 2000000:
183 rate = IEEE80211_CCK_RATE_2MB;
184 break;
185 case 5500000:
186 rate = IEEE80211_CCK_RATE_5MB;
187 break;
188 case 11000000:
189 rate = IEEE80211_CCK_RATE_11MB;
190 break;
191 case 6000000:
192 rate = IEEE80211_OFDM_RATE_6MB;
193 is_ofdm = 1;
194 break;
195 case 9000000:
196 rate = IEEE80211_OFDM_RATE_9MB;
197 is_ofdm = 1;
198 break;
199 case 12000000:
200 rate = IEEE80211_OFDM_RATE_12MB;
201 is_ofdm = 1;
202 break;
203 case 18000000:
204 rate = IEEE80211_OFDM_RATE_18MB;
205 is_ofdm = 1;
206 break;
207 case 24000000:
208 rate = IEEE80211_OFDM_RATE_24MB;
209 is_ofdm = 1;
210 break;
211 case 36000000:
212 rate = IEEE80211_OFDM_RATE_36MB;
213 is_ofdm = 1;
214 break;
215 case 48000000:
216 rate = IEEE80211_OFDM_RATE_48MB;
217 is_ofdm = 1;
218 break;
219 case 54000000:
220 rate = IEEE80211_OFDM_RATE_54MB;
221 is_ofdm = 1;
222 break;
223 default:
224 goto out;
225 }
226
227 spin_lock_irqsave(&mac->lock, flags);
228
229 /* Check if correct modulation for this PHY. */
230 if (is_ofdm && !(ieee->modulation & IEEE80211_OFDM_MODULATION))
231 goto out_unlock;
232
Daniel Drake8462fe32006-05-01 22:45:50 +0100233 mac->txrates.user_rate = rate;
234 ieee80211softmac_recalc_txrates(mac);
Johannes Berg370121e2006-01-04 16:32:16 +0100235 err = 0;
236
YOSHIFUJI Hideaki64265652007-02-09 23:24:46 +0900237out_unlock:
Johannes Berg370121e2006-01-04 16:32:16 +0100238 spin_unlock_irqrestore(&mac->lock, flags);
239out:
240 return err;
241}
242EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_rate);
243
244int
245ieee80211softmac_wx_get_rate(struct net_device *net_dev,
246 struct iw_request_info *info,
247 union iwreq_data *data,
248 char *extra)
249{
250 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
251 unsigned long flags;
252 int err = -EINVAL;
253
254 spin_lock_irqsave(&mac->lock, flags);
John W. Linville6bbdce52007-01-02 21:22:05 -0500255
256 if (unlikely(!mac->running)) {
257 err = -ENODEV;
258 goto out_unlock;
259 }
260
Johannes Berg370121e2006-01-04 16:32:16 +0100261 switch (mac->txrates.default_rate) {
262 case IEEE80211_CCK_RATE_1MB:
263 data->bitrate.value = 1000000;
264 break;
265 case IEEE80211_CCK_RATE_2MB:
266 data->bitrate.value = 2000000;
267 break;
268 case IEEE80211_CCK_RATE_5MB:
269 data->bitrate.value = 5500000;
270 break;
271 case IEEE80211_CCK_RATE_11MB:
272 data->bitrate.value = 11000000;
273 break;
274 case IEEE80211_OFDM_RATE_6MB:
275 data->bitrate.value = 6000000;
276 break;
277 case IEEE80211_OFDM_RATE_9MB:
278 data->bitrate.value = 9000000;
279 break;
280 case IEEE80211_OFDM_RATE_12MB:
281 data->bitrate.value = 12000000;
282 break;
283 case IEEE80211_OFDM_RATE_18MB:
284 data->bitrate.value = 18000000;
285 break;
286 case IEEE80211_OFDM_RATE_24MB:
287 data->bitrate.value = 24000000;
288 break;
289 case IEEE80211_OFDM_RATE_36MB:
290 data->bitrate.value = 36000000;
291 break;
292 case IEEE80211_OFDM_RATE_48MB:
293 data->bitrate.value = 48000000;
294 break;
295 case IEEE80211_OFDM_RATE_54MB:
296 data->bitrate.value = 54000000;
297 break;
298 default:
299 assert(0);
300 goto out_unlock;
301 }
302 err = 0;
303out_unlock:
304 spin_unlock_irqrestore(&mac->lock, flags);
305
306 return err;
307}
308EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_rate);
309
310int
311ieee80211softmac_wx_get_wap(struct net_device *net_dev,
312 struct iw_request_info *info,
313 union iwreq_data *data,
314 char *extra)
315{
316 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
317 int err = 0;
Johannes Berg370121e2006-01-04 16:32:16 +0100318
Michael Buesch7c28ad22006-09-27 15:26:33 +0300319 mutex_lock(&mac->associnfo.mutex);
Johannes Berg370121e2006-01-04 16:32:16 +0100320 if (mac->associnfo.bssvalid)
321 memcpy(data->ap_addr.sa_data, mac->associnfo.bssid, ETH_ALEN);
322 else
323 memset(data->ap_addr.sa_data, 0xff, ETH_ALEN);
324 data->ap_addr.sa_family = ARPHRD_ETHER;
Michael Buesch7c28ad22006-09-27 15:26:33 +0300325 mutex_unlock(&mac->associnfo.mutex);
326
Johannes Berg370121e2006-01-04 16:32:16 +0100327 return err;
328}
329EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_wap);
330
331int
332ieee80211softmac_wx_set_wap(struct net_device *net_dev,
333 struct iw_request_info *info,
334 union iwreq_data *data,
335 char *extra)
336{
337 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
Johannes Berg370121e2006-01-04 16:32:16 +0100338
339 /* sanity check */
340 if (data->ap_addr.sa_family != ARPHRD_ETHER) {
341 return -EINVAL;
342 }
343
Michael Buesch7c28ad22006-09-27 15:26:33 +0300344 mutex_lock(&mac->associnfo.mutex);
Johannes Berg818667f2006-04-20 20:02:03 +0200345 if (is_broadcast_ether_addr(data->ap_addr.sa_data)) {
346 /* the bssid we have is not to be fixed any longer,
347 * and we should reassociate to the best AP. */
348 mac->associnfo.bssfixed = 0;
349 /* force reassociation */
350 mac->associnfo.bssvalid = 0;
Michael Buesch7c28ad22006-09-27 15:26:33 +0300351 if (mac->associnfo.associated)
Johannes Berg501d8572007-10-03 18:14:23 -0700352 queue_delayed_work(mac->wq, &mac->associnfo.work, 0);
Johannes Berg818667f2006-04-20 20:02:03 +0200353 } else if (is_zero_ether_addr(data->ap_addr.sa_data)) {
354 /* the bssid we have is no longer fixed */
355 mac->associnfo.bssfixed = 0;
YOSHIFUJI Hideaki64265652007-02-09 23:24:46 +0900356 } else {
Johannes Berg370121e2006-01-04 16:32:16 +0100357 if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) {
Michael Buesch7c28ad22006-09-27 15:26:33 +0300358 if (mac->associnfo.associating || mac->associnfo.associated) {
Johannes Berg370121e2006-01-04 16:32:16 +0100359 /* bssid unchanged and associated or associating - just return */
360 goto out;
361 }
362 } else {
363 /* copy new value in data->ap_addr.sa_data to bssid */
364 memcpy(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN);
Johannes Berg818667f2006-04-20 20:02:03 +0200365 }
366 /* tell the other code that this bssid should be used no matter what */
367 mac->associnfo.bssfixed = 1;
Johannes Berg370121e2006-01-04 16:32:16 +0100368 /* queue associate if new bssid or (old one again and not associated) */
Johannes Berg501d8572007-10-03 18:14:23 -0700369 queue_delayed_work(mac->wq, &mac->associnfo.work, 0);
YOSHIFUJI Hideaki64265652007-02-09 23:24:46 +0900370 }
Johannes Berg370121e2006-01-04 16:32:16 +0100371
Johannes Berg818667f2006-04-20 20:02:03 +0200372 out:
Michael Buesch7c28ad22006-09-27 15:26:33 +0300373 mutex_unlock(&mac->associnfo.mutex);
374
Johannes Berg370121e2006-01-04 16:32:16 +0100375 return 0;
376}
377EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_wap);
378
379int
380ieee80211softmac_wx_set_genie(struct net_device *dev,
381 struct iw_request_info *info,
382 union iwreq_data *wrqu,
383 char *extra)
384{
385 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
386 unsigned long flags;
387 int err = 0;
388 char *buf;
389 int i;
Michael Buesch7c28ad22006-09-27 15:26:33 +0300390
391 mutex_lock(&mac->associnfo.mutex);
Johannes Berg370121e2006-01-04 16:32:16 +0100392 spin_lock_irqsave(&mac->lock, flags);
393 /* bleh. shouldn't be locked for that kmalloc... */
394
395 if (wrqu->data.length) {
396 if ((wrqu->data.length < 2) || (extra[1]+2 != wrqu->data.length)) {
397 /* this is an IE, so the length must be
398 * correct. Is it possible though that
399 * more than one IE is passed in?
400 */
401 err = -EINVAL;
402 goto out;
403 }
404 if (mac->wpa.IEbuflen <= wrqu->data.length) {
405 buf = kmalloc(wrqu->data.length, GFP_ATOMIC);
406 if (!buf) {
407 err = -ENOMEM;
408 goto out;
409 }
410 kfree(mac->wpa.IE);
411 mac->wpa.IE = buf;
412 mac->wpa.IEbuflen = wrqu->data.length;
413 }
414 memcpy(mac->wpa.IE, extra, wrqu->data.length);
415 dprintk(KERN_INFO PFX "generic IE set to ");
416 for (i=0;i<wrqu->data.length;i++)
Larry Finger7bd6b912006-06-08 09:47:42 -0500417 dprintk("%.2x", (u8)mac->wpa.IE[i]);
Johannes Berg370121e2006-01-04 16:32:16 +0100418 dprintk("\n");
419 mac->wpa.IElen = wrqu->data.length;
420 } else {
421 kfree(mac->wpa.IE);
422 mac->wpa.IE = NULL;
423 mac->wpa.IElen = 0;
424 mac->wpa.IEbuflen = 0;
425 }
426
YOSHIFUJI Hideaki64265652007-02-09 23:24:46 +0900427 out:
Johannes Berg370121e2006-01-04 16:32:16 +0100428 spin_unlock_irqrestore(&mac->lock, flags);
Michael Buesch7c28ad22006-09-27 15:26:33 +0300429 mutex_unlock(&mac->associnfo.mutex);
430
Johannes Berg370121e2006-01-04 16:32:16 +0100431 return err;
432}
433EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_genie);
434
435int
436ieee80211softmac_wx_get_genie(struct net_device *dev,
437 struct iw_request_info *info,
438 union iwreq_data *wrqu,
439 char *extra)
440{
441 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
442 unsigned long flags;
443 int err = 0;
444 int space = wrqu->data.length;
Michael Buesch7c28ad22006-09-27 15:26:33 +0300445
446 mutex_lock(&mac->associnfo.mutex);
Johannes Berg370121e2006-01-04 16:32:16 +0100447 spin_lock_irqsave(&mac->lock, flags);
YOSHIFUJI Hideaki64265652007-02-09 23:24:46 +0900448
Johannes Berg370121e2006-01-04 16:32:16 +0100449 wrqu->data.length = 0;
YOSHIFUJI Hideaki64265652007-02-09 23:24:46 +0900450
Johannes Berg370121e2006-01-04 16:32:16 +0100451 if (mac->wpa.IE && mac->wpa.IElen) {
452 wrqu->data.length = mac->wpa.IElen;
453 if (mac->wpa.IElen <= space)
454 memcpy(extra, mac->wpa.IE, mac->wpa.IElen);
455 else
456 err = -E2BIG;
457 }
458 spin_unlock_irqrestore(&mac->lock, flags);
Ulrich Kunitz0c234ae2006-12-10 18:27:01 +0100459 mutex_unlock(&mac->associnfo.mutex);
Michael Buesch7c28ad22006-09-27 15:26:33 +0300460
Johannes Berg370121e2006-01-04 16:32:16 +0100461 return err;
462}
463EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_genie);
464
Johannes Berg9a1771e2006-04-20 20:02:02 +0200465int
466ieee80211softmac_wx_set_mlme(struct net_device *dev,
467 struct iw_request_info *info,
468 union iwreq_data *wrqu,
469 char *extra)
470{
471 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
472 struct iw_mlme *mlme = (struct iw_mlme *)extra;
473 u16 reason = cpu_to_le16(mlme->reason_code);
474 struct ieee80211softmac_network *net;
Michael Buesch7c28ad22006-09-27 15:26:33 +0300475 int err = -EINVAL;
476
477 mutex_lock(&mac->associnfo.mutex);
Johannes Berg9a1771e2006-04-20 20:02:02 +0200478
479 if (memcmp(mac->associnfo.bssid, mlme->addr.sa_data, ETH_ALEN)) {
480 printk(KERN_DEBUG PFX "wx_set_mlme: requested operation on net we don't use\n");
Michael Buesch7c28ad22006-09-27 15:26:33 +0300481 goto out;
Johannes Berg9a1771e2006-04-20 20:02:02 +0200482 }
483
484 switch (mlme->cmd) {
485 case IW_MLME_DEAUTH:
486 net = ieee80211softmac_get_network_by_bssid_locked(mac, mlme->addr.sa_data);
487 if (!net) {
488 printk(KERN_DEBUG PFX "wx_set_mlme: we should know the net here...\n");
Michael Buesch7c28ad22006-09-27 15:26:33 +0300489 goto out;
Johannes Berg9a1771e2006-04-20 20:02:02 +0200490 }
Maxime Austruycc8ce992006-12-03 10:40:01 -0600491 err = ieee80211softmac_deauth_req(mac, net, reason);
492 goto out;
Johannes Berg9a1771e2006-04-20 20:02:02 +0200493 case IW_MLME_DISASSOC:
Daniel Drake6d92f832006-05-01 22:23:27 +0100494 ieee80211softmac_send_disassoc_req(mac, reason);
Michael Buesch7c28ad22006-09-27 15:26:33 +0300495 mac->associnfo.associated = 0;
496 mac->associnfo.associating = 0;
497 err = 0;
498 goto out;
Johannes Berg9a1771e2006-04-20 20:02:02 +0200499 default:
Michael Buesch7c28ad22006-09-27 15:26:33 +0300500 err = -EOPNOTSUPP;
Johannes Berg9a1771e2006-04-20 20:02:02 +0200501 }
Michael Buesch7c28ad22006-09-27 15:26:33 +0300502
503out:
504 mutex_unlock(&mac->associnfo.mutex);
505
506 return err;
Johannes Berg9a1771e2006-04-20 20:02:02 +0200507}
508EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_mlme);