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
;
77 mutex_lock(&sm
->associnfo
.mutex
);
78 if((sm
->associnfo
.associating
|| sm
->associnfo
.associated
) &&
79 (data
->essid
.flags
&& data
->essid
.length
)) {
80 dprintk(KERN_INFO PFX
"Canceling existing associate request!\n");
81 /* Cancel assoc work */
82 cancel_delayed_work(&sm
->associnfo
.work
);
83 /* We don't have to do this, but it's a little cleaner */
84 list_for_each_entry(authptr
, &sm
->auth_queue
, list
)
85 cancel_delayed_work(&authptr
->work
);
86 sm
->associnfo
.bssvalid
= 0;
87 sm
->associnfo
.bssfixed
= 0;
88 sm
->associnfo
.associating
= 0;
89 sm
->associnfo
.associated
= 0;
90 /* We must unlock to avoid deadlocks with the assoc workqueue
91 * on the associnfo.mutex */
92 mutex_unlock(&sm
->associnfo
.mutex
);
93 flush_scheduled_work();
94 /* Avoid race! Check assoc status again. Maybe someone started an
95 * association while we flushed. */
96 goto check_assoc_again
;
99 sm
->associnfo
.static_essid
= 0;
100 sm
->associnfo
.assoc_wait
= 0;
102 if (data
->essid
.flags
&& data
->essid
.length
) {
103 length
= min((int)data
->essid
.length
, IW_ESSID_MAX_SIZE
);
105 memcpy(sm
->associnfo
.req_essid
.data
, extra
, length
);
106 sm
->associnfo
.static_essid
= 1;
110 /* set our requested ESSID length.
111 * If applicable, we have already copied the data in */
112 sm
->associnfo
.req_essid
.len
= length
;
114 sm
->associnfo
.associating
= 1;
115 /* queue lower level code to do work (if necessary) */
116 schedule_delayed_work(&sm
->associnfo
.work
, 0);
118 mutex_unlock(&sm
->associnfo
.mutex
);
122 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_essid
);
125 ieee80211softmac_wx_get_essid(struct net_device
*net_dev
,
126 struct iw_request_info
*info
,
127 union iwreq_data
*data
,
130 struct ieee80211softmac_device
*sm
= ieee80211_priv(net_dev
);
132 mutex_lock(&sm
->associnfo
.mutex
);
133 /* If all fails, return ANY (empty) */
134 data
->essid
.length
= 0;
135 data
->essid
.flags
= 0; /* active */
137 /* If we have a statically configured ESSID then return it */
138 if (sm
->associnfo
.static_essid
) {
139 data
->essid
.length
= sm
->associnfo
.req_essid
.len
;
140 data
->essid
.flags
= 1; /* active */
141 memcpy(extra
, sm
->associnfo
.req_essid
.data
, sm
->associnfo
.req_essid
.len
);
142 dprintk(KERN_INFO PFX
"Getting essid from req_essid\n");
143 } else if (sm
->associnfo
.associated
|| sm
->associnfo
.associating
) {
144 /* If we're associating/associated, return that */
145 data
->essid
.length
= sm
->associnfo
.associate_essid
.len
;
146 data
->essid
.flags
= 1; /* active */
147 memcpy(extra
, sm
->associnfo
.associate_essid
.data
, sm
->associnfo
.associate_essid
.len
);
148 dprintk(KERN_INFO PFX
"Getting essid from associate_essid\n");
150 mutex_unlock(&sm
->associnfo
.mutex
);
154 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_essid
);
157 ieee80211softmac_wx_set_rate(struct net_device
*net_dev
,
158 struct iw_request_info
*info
,
159 union iwreq_data
*data
,
162 struct ieee80211softmac_device
*mac
= ieee80211_priv(net_dev
);
163 struct ieee80211_device
*ieee
= mac
->ieee
;
165 s32 in_rate
= data
->bitrate
.value
;
171 if (ieee
->modulation
& IEEE80211_OFDM_MODULATION
)
179 rate
= IEEE80211_CCK_RATE_1MB
;
182 rate
= IEEE80211_CCK_RATE_2MB
;
185 rate
= IEEE80211_CCK_RATE_5MB
;
188 rate
= IEEE80211_CCK_RATE_11MB
;
191 rate
= IEEE80211_OFDM_RATE_6MB
;
195 rate
= IEEE80211_OFDM_RATE_9MB
;
199 rate
= IEEE80211_OFDM_RATE_12MB
;
203 rate
= IEEE80211_OFDM_RATE_18MB
;
207 rate
= IEEE80211_OFDM_RATE_24MB
;
211 rate
= IEEE80211_OFDM_RATE_36MB
;
215 rate
= IEEE80211_OFDM_RATE_48MB
;
219 rate
= IEEE80211_OFDM_RATE_54MB
;
226 spin_lock_irqsave(&mac
->lock
, flags
);
228 /* Check if correct modulation for this PHY. */
229 if (is_ofdm
&& !(ieee
->modulation
& IEEE80211_OFDM_MODULATION
))
232 mac
->txrates
.user_rate
= rate
;
233 ieee80211softmac_recalc_txrates(mac
);
237 spin_unlock_irqrestore(&mac
->lock
, flags
);
241 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_rate
);
244 ieee80211softmac_wx_get_rate(struct net_device
*net_dev
,
245 struct iw_request_info
*info
,
246 union iwreq_data
*data
,
249 struct ieee80211softmac_device
*mac
= ieee80211_priv(net_dev
);
253 spin_lock_irqsave(&mac
->lock
, flags
);
255 if (unlikely(!mac
->running
)) {
260 switch (mac
->txrates
.default_rate
) {
261 case IEEE80211_CCK_RATE_1MB
:
262 data
->bitrate
.value
= 1000000;
264 case IEEE80211_CCK_RATE_2MB
:
265 data
->bitrate
.value
= 2000000;
267 case IEEE80211_CCK_RATE_5MB
:
268 data
->bitrate
.value
= 5500000;
270 case IEEE80211_CCK_RATE_11MB
:
271 data
->bitrate
.value
= 11000000;
273 case IEEE80211_OFDM_RATE_6MB
:
274 data
->bitrate
.value
= 6000000;
276 case IEEE80211_OFDM_RATE_9MB
:
277 data
->bitrate
.value
= 9000000;
279 case IEEE80211_OFDM_RATE_12MB
:
280 data
->bitrate
.value
= 12000000;
282 case IEEE80211_OFDM_RATE_18MB
:
283 data
->bitrate
.value
= 18000000;
285 case IEEE80211_OFDM_RATE_24MB
:
286 data
->bitrate
.value
= 24000000;
288 case IEEE80211_OFDM_RATE_36MB
:
289 data
->bitrate
.value
= 36000000;
291 case IEEE80211_OFDM_RATE_48MB
:
292 data
->bitrate
.value
= 48000000;
294 case IEEE80211_OFDM_RATE_54MB
:
295 data
->bitrate
.value
= 54000000;
303 spin_unlock_irqrestore(&mac
->lock
, flags
);
307 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_rate
);
310 ieee80211softmac_wx_get_wap(struct net_device
*net_dev
,
311 struct iw_request_info
*info
,
312 union iwreq_data
*data
,
315 struct ieee80211softmac_device
*mac
= ieee80211_priv(net_dev
);
318 mutex_lock(&mac
->associnfo
.mutex
);
319 if (mac
->associnfo
.bssvalid
)
320 memcpy(data
->ap_addr
.sa_data
, mac
->associnfo
.bssid
, ETH_ALEN
);
322 memset(data
->ap_addr
.sa_data
, 0xff, ETH_ALEN
);
323 data
->ap_addr
.sa_family
= ARPHRD_ETHER
;
324 mutex_unlock(&mac
->associnfo
.mutex
);
328 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_wap
);
331 ieee80211softmac_wx_set_wap(struct net_device
*net_dev
,
332 struct iw_request_info
*info
,
333 union iwreq_data
*data
,
336 struct ieee80211softmac_device
*mac
= ieee80211_priv(net_dev
);
339 if (data
->ap_addr
.sa_family
!= ARPHRD_ETHER
) {
343 mutex_lock(&mac
->associnfo
.mutex
);
344 if (is_broadcast_ether_addr(data
->ap_addr
.sa_data
)) {
345 /* the bssid we have is not to be fixed any longer,
346 * and we should reassociate to the best AP. */
347 mac
->associnfo
.bssfixed
= 0;
348 /* force reassociation */
349 mac
->associnfo
.bssvalid
= 0;
350 if (mac
->associnfo
.associated
)
351 schedule_delayed_work(&mac
->associnfo
.work
, 0);
352 } else if (is_zero_ether_addr(data
->ap_addr
.sa_data
)) {
353 /* the bssid we have is no longer fixed */
354 mac
->associnfo
.bssfixed
= 0;
356 if (!memcmp(mac
->associnfo
.bssid
, data
->ap_addr
.sa_data
, ETH_ALEN
)) {
357 if (mac
->associnfo
.associating
|| mac
->associnfo
.associated
) {
358 /* bssid unchanged and associated or associating - just return */
362 /* copy new value in data->ap_addr.sa_data to bssid */
363 memcpy(mac
->associnfo
.bssid
, data
->ap_addr
.sa_data
, ETH_ALEN
);
365 /* tell the other code that this bssid should be used no matter what */
366 mac
->associnfo
.bssfixed
= 1;
367 /* queue associate if new bssid or (old one again and not associated) */
368 schedule_delayed_work(&mac
->associnfo
.work
, 0);
372 mutex_unlock(&mac
->associnfo
.mutex
);
376 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_wap
);
379 ieee80211softmac_wx_set_genie(struct net_device
*dev
,
380 struct iw_request_info
*info
,
381 union iwreq_data
*wrqu
,
384 struct ieee80211softmac_device
*mac
= ieee80211_priv(dev
);
390 mutex_lock(&mac
->associnfo
.mutex
);
391 spin_lock_irqsave(&mac
->lock
, flags
);
392 /* bleh. shouldn't be locked for that kmalloc... */
394 if (wrqu
->data
.length
) {
395 if ((wrqu
->data
.length
< 2) || (extra
[1]+2 != wrqu
->data
.length
)) {
396 /* this is an IE, so the length must be
397 * correct. Is it possible though that
398 * more than one IE is passed in?
403 if (mac
->wpa
.IEbuflen
<= wrqu
->data
.length
) {
404 buf
= kmalloc(wrqu
->data
.length
, GFP_ATOMIC
);
411 mac
->wpa
.IEbuflen
= wrqu
->data
.length
;
413 memcpy(mac
->wpa
.IE
, extra
, wrqu
->data
.length
);
414 dprintk(KERN_INFO PFX
"generic IE set to ");
415 for (i
=0;i
<wrqu
->data
.length
;i
++)
416 dprintk("%.2x", (u8
)mac
->wpa
.IE
[i
]);
418 mac
->wpa
.IElen
= wrqu
->data
.length
;
423 mac
->wpa
.IEbuflen
= 0;
427 spin_unlock_irqrestore(&mac
->lock
, flags
);
428 mutex_unlock(&mac
->associnfo
.mutex
);
432 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_genie
);
435 ieee80211softmac_wx_get_genie(struct net_device
*dev
,
436 struct iw_request_info
*info
,
437 union iwreq_data
*wrqu
,
440 struct ieee80211softmac_device
*mac
= ieee80211_priv(dev
);
443 int space
= wrqu
->data
.length
;
445 mutex_lock(&mac
->associnfo
.mutex
);
446 spin_lock_irqsave(&mac
->lock
, flags
);
448 wrqu
->data
.length
= 0;
450 if (mac
->wpa
.IE
&& mac
->wpa
.IElen
) {
451 wrqu
->data
.length
= mac
->wpa
.IElen
;
452 if (mac
->wpa
.IElen
<= space
)
453 memcpy(extra
, mac
->wpa
.IE
, mac
->wpa
.IElen
);
457 spin_unlock_irqrestore(&mac
->lock
, flags
);
458 mutex_unlock(&mac
->associnfo
.mutex
);
462 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_genie
);
465 ieee80211softmac_wx_set_mlme(struct net_device
*dev
,
466 struct iw_request_info
*info
,
467 union iwreq_data
*wrqu
,
470 struct ieee80211softmac_device
*mac
= ieee80211_priv(dev
);
471 struct iw_mlme
*mlme
= (struct iw_mlme
*)extra
;
472 u16 reason
= cpu_to_le16(mlme
->reason_code
);
473 struct ieee80211softmac_network
*net
;
476 mutex_lock(&mac
->associnfo
.mutex
);
478 if (memcmp(mac
->associnfo
.bssid
, mlme
->addr
.sa_data
, ETH_ALEN
)) {
479 printk(KERN_DEBUG PFX
"wx_set_mlme: requested operation on net we don't use\n");
485 net
= ieee80211softmac_get_network_by_bssid_locked(mac
, mlme
->addr
.sa_data
);
487 printk(KERN_DEBUG PFX
"wx_set_mlme: we should know the net here...\n");
490 err
= ieee80211softmac_deauth_req(mac
, net
, reason
);
492 case IW_MLME_DISASSOC
:
493 ieee80211softmac_send_disassoc_req(mac
, reason
);
494 mac
->associnfo
.associated
= 0;
495 mac
->associnfo
.associating
= 0;
503 mutex_unlock(&mac
->associnfo
.mutex
);
507 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_mlme
);