2 * This file contains our _wx handlers. Make sure you EXPORT_SYMBOL_GPL them
4 * 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>
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.
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
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
23 * The full GNU General Public License is included in this distribution in the
24 * file called COPYING.
27 #include "ieee80211softmac_priv.h"
29 #include <net/iw_handler.h>
30 /* for is_broadcast_ether_addr and is_zero_ether_addr */
31 #include <linux/etherdevice.h>
34 ieee80211softmac_wx_trigger_scan(struct net_device
*net_dev
,
35 struct iw_request_info
*info
,
36 union iwreq_data
*data
,
39 struct ieee80211softmac_device
*sm
= ieee80211_priv(net_dev
);
40 return ieee80211softmac_start_scan(sm
);
42 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_trigger_scan
);
45 /* if we're still scanning, return -EAGAIN so that userspace tools
46 * can get the complete scan results, otherwise return 0. */
48 ieee80211softmac_wx_get_scan_results(struct net_device
*net_dev
,
49 struct iw_request_info
*info
,
50 union iwreq_data
*data
,
54 struct ieee80211softmac_device
*sm
= ieee80211_priv(net_dev
);
56 spin_lock_irqsave(&sm
->lock
, flags
);
58 spin_unlock_irqrestore(&sm
->lock
, flags
);
61 spin_unlock_irqrestore(&sm
->lock
, flags
);
62 return ieee80211_wx_get_scan(sm
->ieee
, info
, data
, extra
);
64 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_scan_results
);
67 ieee80211softmac_wx_set_essid(struct net_device
*net_dev
,
68 struct iw_request_info
*info
,
69 union iwreq_data
*data
,
72 struct ieee80211softmac_device
*sm
= ieee80211_priv(net_dev
);
73 struct ieee80211softmac_auth_queue_item
*authptr
;
78 mutex_lock(&sm
->associnfo
.mutex
);
79 if((sm
->associnfo
.associating
|| sm
->associnfo
.associated
) &&
80 (data
->essid
.flags
&& data
->essid
.length
)) {
81 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
);
94 flush_workqueue(sm
->wq
);
95 /* Avoid race! Check assoc status again. Maybe someone started an
96 * association while we flushed. */
97 goto check_assoc_again
;
100 sm
->associnfo
.static_essid
= 0;
101 sm
->associnfo
.assoc_wait
= 0;
103 if (data
->essid
.flags
&& data
->essid
.length
) {
104 length
= min((int)data
->essid
.length
, IW_ESSID_MAX_SIZE
);
106 memcpy(sm
->associnfo
.req_essid
.data
, extra
, length
);
107 sm
->associnfo
.static_essid
= 1;
111 /* set our requested ESSID length.
112 * If applicable, we have already copied the data in */
113 sm
->associnfo
.req_essid
.len
= length
;
115 sm
->associnfo
.associating
= 1;
116 /* queue lower level code to do work (if necessary) */
117 queue_delayed_work(sm
->wq
, &sm
->associnfo
.work
, 0);
119 mutex_unlock(&sm
->associnfo
.mutex
);
123 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_essid
);
126 ieee80211softmac_wx_get_essid(struct net_device
*net_dev
,
127 struct iw_request_info
*info
,
128 union iwreq_data
*data
,
131 struct ieee80211softmac_device
*sm
= ieee80211_priv(net_dev
);
133 mutex_lock(&sm
->associnfo
.mutex
);
134 /* If all fails, return ANY (empty) */
135 data
->essid
.length
= 0;
136 data
->essid
.flags
= 0; /* active */
138 /* 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
);
143 dprintk(KERN_INFO PFX
"Getting essid from req_essid\n");
144 } else if (sm
->associnfo
.associated
|| sm
->associnfo
.associating
) {
145 /* If we're associating/associated, return that */
146 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
);
149 dprintk(KERN_INFO PFX
"Getting essid from associate_essid\n");
151 mutex_unlock(&sm
->associnfo
.mutex
);
155 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_essid
);
158 ieee80211softmac_wx_set_rate(struct net_device
*net_dev
,
159 struct iw_request_info
*info
,
160 union iwreq_data
*data
,
163 struct ieee80211softmac_device
*mac
= ieee80211_priv(net_dev
);
164 struct ieee80211_device
*ieee
= mac
->ieee
;
166 s32 in_rate
= data
->bitrate
.value
;
172 if (ieee
->modulation
& IEEE80211_OFDM_MODULATION
)
180 rate
= IEEE80211_CCK_RATE_1MB
;
183 rate
= IEEE80211_CCK_RATE_2MB
;
186 rate
= IEEE80211_CCK_RATE_5MB
;
189 rate
= IEEE80211_CCK_RATE_11MB
;
192 rate
= IEEE80211_OFDM_RATE_6MB
;
196 rate
= IEEE80211_OFDM_RATE_9MB
;
200 rate
= IEEE80211_OFDM_RATE_12MB
;
204 rate
= IEEE80211_OFDM_RATE_18MB
;
208 rate
= IEEE80211_OFDM_RATE_24MB
;
212 rate
= IEEE80211_OFDM_RATE_36MB
;
216 rate
= IEEE80211_OFDM_RATE_48MB
;
220 rate
= IEEE80211_OFDM_RATE_54MB
;
227 spin_lock_irqsave(&mac
->lock
, flags
);
229 /* Check if correct modulation for this PHY. */
230 if (is_ofdm
&& !(ieee
->modulation
& IEEE80211_OFDM_MODULATION
))
233 mac
->txrates
.user_rate
= rate
;
234 ieee80211softmac_recalc_txrates(mac
);
238 spin_unlock_irqrestore(&mac
->lock
, flags
);
242 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_rate
);
245 ieee80211softmac_wx_get_rate(struct net_device
*net_dev
,
246 struct iw_request_info
*info
,
247 union iwreq_data
*data
,
250 struct ieee80211softmac_device
*mac
= ieee80211_priv(net_dev
);
254 spin_lock_irqsave(&mac
->lock
, flags
);
256 if (unlikely(!mac
->running
)) {
261 switch (mac
->txrates
.default_rate
) {
262 case IEEE80211_CCK_RATE_1MB
:
263 data
->bitrate
.value
= 1000000;
265 case IEEE80211_CCK_RATE_2MB
:
266 data
->bitrate
.value
= 2000000;
268 case IEEE80211_CCK_RATE_5MB
:
269 data
->bitrate
.value
= 5500000;
271 case IEEE80211_CCK_RATE_11MB
:
272 data
->bitrate
.value
= 11000000;
274 case IEEE80211_OFDM_RATE_6MB
:
275 data
->bitrate
.value
= 6000000;
277 case IEEE80211_OFDM_RATE_9MB
:
278 data
->bitrate
.value
= 9000000;
280 case IEEE80211_OFDM_RATE_12MB
:
281 data
->bitrate
.value
= 12000000;
283 case IEEE80211_OFDM_RATE_18MB
:
284 data
->bitrate
.value
= 18000000;
286 case IEEE80211_OFDM_RATE_24MB
:
287 data
->bitrate
.value
= 24000000;
289 case IEEE80211_OFDM_RATE_36MB
:
290 data
->bitrate
.value
= 36000000;
292 case IEEE80211_OFDM_RATE_48MB
:
293 data
->bitrate
.value
= 48000000;
295 case IEEE80211_OFDM_RATE_54MB
:
296 data
->bitrate
.value
= 54000000;
304 spin_unlock_irqrestore(&mac
->lock
, flags
);
308 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_rate
);
311 ieee80211softmac_wx_get_wap(struct net_device
*net_dev
,
312 struct iw_request_info
*info
,
313 union iwreq_data
*data
,
316 struct ieee80211softmac_device
*mac
= ieee80211_priv(net_dev
);
319 mutex_lock(&mac
->associnfo
.mutex
);
320 if (mac
->associnfo
.bssvalid
)
321 memcpy(data
->ap_addr
.sa_data
, mac
->associnfo
.bssid
, ETH_ALEN
);
323 memset(data
->ap_addr
.sa_data
, 0xff, ETH_ALEN
);
324 data
->ap_addr
.sa_family
= ARPHRD_ETHER
;
325 mutex_unlock(&mac
->associnfo
.mutex
);
329 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_wap
);
332 ieee80211softmac_wx_set_wap(struct net_device
*net_dev
,
333 struct iw_request_info
*info
,
334 union iwreq_data
*data
,
337 struct ieee80211softmac_device
*mac
= ieee80211_priv(net_dev
);
340 if (data
->ap_addr
.sa_family
!= ARPHRD_ETHER
) {
344 mutex_lock(&mac
->associnfo
.mutex
);
345 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;
351 if (mac
->associnfo
.associated
)
352 queue_delayed_work(mac
->wq
, &mac
->associnfo
.work
, 0);
353 } 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;
357 if (!memcmp(mac
->associnfo
.bssid
, data
->ap_addr
.sa_data
, ETH_ALEN
)) {
358 if (mac
->associnfo
.associating
|| mac
->associnfo
.associated
) {
359 /* bssid unchanged and associated or associating - just return */
363 /* copy new value in data->ap_addr.sa_data to bssid */
364 memcpy(mac
->associnfo
.bssid
, data
->ap_addr
.sa_data
, ETH_ALEN
);
366 /* tell the other code that this bssid should be used no matter what */
367 mac
->associnfo
.bssfixed
= 1;
368 /* queue associate if new bssid or (old one again and not associated) */
369 queue_delayed_work(mac
->wq
, &mac
->associnfo
.work
, 0);
373 mutex_unlock(&mac
->associnfo
.mutex
);
377 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_wap
);
380 ieee80211softmac_wx_set_genie(struct net_device
*dev
,
381 struct iw_request_info
*info
,
382 union iwreq_data
*wrqu
,
385 struct ieee80211softmac_device
*mac
= ieee80211_priv(dev
);
391 mutex_lock(&mac
->associnfo
.mutex
);
392 spin_lock_irqsave(&mac
->lock
, flags
);
393 /* bleh. shouldn't be locked for that kmalloc... */
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?
404 if (mac
->wpa
.IEbuflen
<= wrqu
->data
.length
) {
405 buf
= kmalloc(wrqu
->data
.length
, GFP_ATOMIC
);
412 mac
->wpa
.IEbuflen
= wrqu
->data
.length
;
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
++)
417 dprintk("%.2x", (u8
)mac
->wpa
.IE
[i
]);
419 mac
->wpa
.IElen
= wrqu
->data
.length
;
424 mac
->wpa
.IEbuflen
= 0;
428 spin_unlock_irqrestore(&mac
->lock
, flags
);
429 mutex_unlock(&mac
->associnfo
.mutex
);
433 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_genie
);
436 ieee80211softmac_wx_get_genie(struct net_device
*dev
,
437 struct iw_request_info
*info
,
438 union iwreq_data
*wrqu
,
441 struct ieee80211softmac_device
*mac
= ieee80211_priv(dev
);
444 int space
= wrqu
->data
.length
;
446 mutex_lock(&mac
->associnfo
.mutex
);
447 spin_lock_irqsave(&mac
->lock
, flags
);
449 wrqu
->data
.length
= 0;
451 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
);
458 spin_unlock_irqrestore(&mac
->lock
, flags
);
459 mutex_unlock(&mac
->associnfo
.mutex
);
463 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_genie
);
466 ieee80211softmac_wx_set_mlme(struct net_device
*dev
,
467 struct iw_request_info
*info
,
468 union iwreq_data
*wrqu
,
471 struct ieee80211softmac_device
*mac
= ieee80211_priv(dev
);
472 struct iw_mlme
*mlme
= (struct iw_mlme
*)extra
;
473 u16 reason
= mlme
->reason_code
;
474 struct ieee80211softmac_network
*net
;
477 mutex_lock(&mac
->associnfo
.mutex
);
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");
486 net
= ieee80211softmac_get_network_by_bssid_locked(mac
, mlme
->addr
.sa_data
);
488 printk(KERN_DEBUG PFX
"wx_set_mlme: we should know the net here...\n");
491 err
= ieee80211softmac_deauth_req(mac
, net
, reason
);
493 case IW_MLME_DISASSOC
:
494 ieee80211softmac_send_disassoc_req(mac
, reason
);
495 mac
->associnfo
.associated
= 0;
496 mac
->associnfo
.associating
= 0;
504 mutex_unlock(&mac
->associnfo
.mutex
);
508 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_mlme
);