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_network *n;
74 struct ieee80211softmac_auth_queue_item *authptr;
77 mutex_lock(&sm->associnfo.mutex);
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!
83 if((sm->associnfo.associating || sm->associnfo.associated) &&
84 (data->essid.flags && data->essid.length)) {
85 /* Get the associating network */
86 n = ieee80211softmac_get_network_by_bssid(sm, sm->associnfo.bssid);
87 if(n && n->essid.len == data->essid.length &&
88 !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));
93 dprintk(KERN_INFO PFX "Canceling existing associate request!\n");
94 /* 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;
101 flush_scheduled_work();
102 sm->associnfo.associating = 0;
103 sm->associnfo.associated = 0;
108 sm->associnfo.static_essid = 0;
109 sm->associnfo.assoc_wait = 0;
111 if (data->essid.flags && data->essid.length) {
112 length = min((int)data->essid.length, IW_ESSID_MAX_SIZE);
114 memcpy(sm->associnfo.req_essid.data, extra, length);
115 sm->associnfo.static_essid = 1;
119 /* set our requested ESSID length.
120 * If applicable, we have already copied the data in */
121 sm->associnfo.req_essid.len = length;
123 sm->associnfo.associating = 1;
124 /* queue lower level code to do work (if necessary) */
125 schedule_delayed_work(&sm->associnfo.work, 0);
127 mutex_unlock(&sm->associnfo.mutex);
131 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_essid);
134 ieee80211softmac_wx_get_essid(struct net_device *net_dev,
135 struct iw_request_info *info,
136 union iwreq_data *data,
139 struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
141 mutex_lock(&sm->associnfo.mutex);
142 /* If all fails, return ANY (empty) */
143 data->essid.length = 0;
144 data->essid.flags = 0; /* active */
146 /* 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);
153 /* If we're associating/associated, return that */
154 if (sm->associnfo.associated || sm->associnfo.associating) {
155 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);
159 mutex_unlock(&sm->associnfo.mutex);
163 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_essid);
166 ieee80211softmac_wx_set_rate(struct net_device *net_dev,
167 struct iw_request_info *info,
168 union iwreq_data *data,
171 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
172 struct ieee80211_device *ieee = mac->ieee;
174 s32 in_rate = data->bitrate.value;
180 /* 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
184 ieee80211softmac_wx_set_rate() */
185 if (ieee->modulation & IEEE80211_CCK_MODULATION)
193 rate = IEEE80211_CCK_RATE_1MB;
196 rate = IEEE80211_CCK_RATE_2MB;
199 rate = IEEE80211_CCK_RATE_5MB;
202 rate = IEEE80211_CCK_RATE_11MB;
205 rate = IEEE80211_OFDM_RATE_6MB;
209 rate = IEEE80211_OFDM_RATE_9MB;
213 rate = IEEE80211_OFDM_RATE_12MB;
217 rate = IEEE80211_OFDM_RATE_18MB;
221 rate = IEEE80211_OFDM_RATE_24MB;
225 rate = IEEE80211_OFDM_RATE_36MB;
229 rate = IEEE80211_OFDM_RATE_48MB;
233 rate = IEEE80211_OFDM_RATE_54MB;
240 spin_lock_irqsave(&mac->lock, flags);
242 /* Check if correct modulation for this PHY. */
243 if (is_ofdm && !(ieee->modulation & IEEE80211_OFDM_MODULATION))
246 mac->txrates.user_rate = rate;
247 ieee80211softmac_recalc_txrates(mac);
251 spin_unlock_irqrestore(&mac->lock, flags);
255 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_rate);
258 ieee80211softmac_wx_get_rate(struct net_device *net_dev,
259 struct iw_request_info *info,
260 union iwreq_data *data,
263 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
267 spin_lock_irqsave(&mac->lock, flags);
268 switch (mac->txrates.default_rate) {
269 case IEEE80211_CCK_RATE_1MB:
270 data->bitrate.value = 1000000;
272 case IEEE80211_CCK_RATE_2MB:
273 data->bitrate.value = 2000000;
275 case IEEE80211_CCK_RATE_5MB:
276 data->bitrate.value = 5500000;
278 case IEEE80211_CCK_RATE_11MB:
279 data->bitrate.value = 11000000;
281 case IEEE80211_OFDM_RATE_6MB:
282 data->bitrate.value = 6000000;
284 case IEEE80211_OFDM_RATE_9MB:
285 data->bitrate.value = 9000000;
287 case IEEE80211_OFDM_RATE_12MB:
288 data->bitrate.value = 12000000;
290 case IEEE80211_OFDM_RATE_18MB:
291 data->bitrate.value = 18000000;
293 case IEEE80211_OFDM_RATE_24MB:
294 data->bitrate.value = 24000000;
296 case IEEE80211_OFDM_RATE_36MB:
297 data->bitrate.value = 36000000;
299 case IEEE80211_OFDM_RATE_48MB:
300 data->bitrate.value = 48000000;
302 case IEEE80211_OFDM_RATE_54MB:
303 data->bitrate.value = 54000000;
311 spin_unlock_irqrestore(&mac->lock, flags);
315 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_rate);
318 ieee80211softmac_wx_get_wap(struct net_device *net_dev,
319 struct iw_request_info *info,
320 union iwreq_data *data,
323 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
326 mutex_lock(&mac->associnfo.mutex);
327 if (mac->associnfo.bssvalid)
328 memcpy(data->ap_addr.sa_data, mac->associnfo.bssid, ETH_ALEN);
330 memset(data->ap_addr.sa_data, 0xff, ETH_ALEN);
331 data->ap_addr.sa_family = ARPHRD_ETHER;
332 mutex_unlock(&mac->associnfo.mutex);
336 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_wap);
339 ieee80211softmac_wx_set_wap(struct net_device *net_dev,
340 struct iw_request_info *info,
341 union iwreq_data *data,
344 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
347 if (data->ap_addr.sa_family != ARPHRD_ETHER) {
351 mutex_lock(&mac->associnfo.mutex);
352 if (is_broadcast_ether_addr(data->ap_addr.sa_data)) {
353 /* the bssid we have is not to be fixed any longer,
354 * and we should reassociate to the best AP. */
355 mac->associnfo.bssfixed = 0;
356 /* force reassociation */
357 mac->associnfo.bssvalid = 0;
358 if (mac->associnfo.associated)
359 schedule_delayed_work(&mac->associnfo.work, 0);
360 } else if (is_zero_ether_addr(data->ap_addr.sa_data)) {
361 /* the bssid we have is no longer fixed */
362 mac->associnfo.bssfixed = 0;
364 if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) {
365 if (mac->associnfo.associating || mac->associnfo.associated) {
366 /* bssid unchanged and associated or associating - just return */
370 /* copy new value in data->ap_addr.sa_data to bssid */
371 memcpy(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN);
373 /* tell the other code that this bssid should be used no matter what */
374 mac->associnfo.bssfixed = 1;
375 /* queue associate if new bssid or (old one again and not associated) */
376 schedule_delayed_work(&mac->associnfo.work, 0);
380 mutex_unlock(&mac->associnfo.mutex);
384 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_wap);
387 ieee80211softmac_wx_set_genie(struct net_device *dev,
388 struct iw_request_info *info,
389 union iwreq_data *wrqu,
392 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
398 mutex_lock(&mac->associnfo.mutex);
399 spin_lock_irqsave(&mac->lock, flags);
400 /* bleh. shouldn't be locked for that kmalloc... */
402 if (wrqu->data.length) {
403 if ((wrqu->data.length < 2) || (extra[1]+2 != wrqu->data.length)) {
404 /* this is an IE, so the length must be
405 * correct. Is it possible though that
406 * more than one IE is passed in?
411 if (mac->wpa.IEbuflen <= wrqu->data.length) {
412 buf = kmalloc(wrqu->data.length, GFP_ATOMIC);
419 mac->wpa.IEbuflen = wrqu->data.length;
421 memcpy(mac->wpa.IE, extra, wrqu->data.length);
422 dprintk(KERN_INFO PFX "generic IE set to ");
423 for (i=0;i<wrqu->data.length;i++)
424 dprintk("%.2x", (u8)mac->wpa.IE[i]);
426 mac->wpa.IElen = wrqu->data.length;
431 mac->wpa.IEbuflen = 0;
435 spin_unlock_irqrestore(&mac->lock, flags);
436 mutex_unlock(&mac->associnfo.mutex);
440 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_genie);
443 ieee80211softmac_wx_get_genie(struct net_device *dev,
444 struct iw_request_info *info,
445 union iwreq_data *wrqu,
448 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
451 int space = wrqu->data.length;
453 mutex_lock(&mac->associnfo.mutex);
454 spin_lock_irqsave(&mac->lock, flags);
456 wrqu->data.length = 0;
458 if (mac->wpa.IE && mac->wpa.IElen) {
459 wrqu->data.length = mac->wpa.IElen;
460 if (mac->wpa.IElen <= space)
461 memcpy(extra, mac->wpa.IE, mac->wpa.IElen);
465 spin_unlock_irqrestore(&mac->lock, flags);
466 mutex_unlock(&mac->associnfo.mutex);
470 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_genie);
473 ieee80211softmac_wx_set_mlme(struct net_device *dev,
474 struct iw_request_info *info,
475 union iwreq_data *wrqu,
478 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
479 struct iw_mlme *mlme = (struct iw_mlme *)extra;
480 u16 reason = cpu_to_le16(mlme->reason_code);
481 struct ieee80211softmac_network *net;
484 mutex_lock(&mac->associnfo.mutex);
486 if (memcmp(mac->associnfo.bssid, mlme->addr.sa_data, ETH_ALEN)) {
487 printk(KERN_DEBUG PFX "wx_set_mlme: requested operation on net we don't use\n");
493 net = ieee80211softmac_get_network_by_bssid_locked(mac, mlme->addr.sa_data);
495 printk(KERN_DEBUG PFX "wx_set_mlme: we should know the net here...\n");
498 err = ieee80211softmac_deauth_req(mac, net, reason);
500 case IW_MLME_DISASSOC:
501 ieee80211softmac_send_disassoc_req(mac, reason);
502 mac->associnfo.associated = 0;
503 mac->associnfo.associating = 0;
511 mutex_unlock(&mac->associnfo.mutex);
515 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_mlme);