aboutsummaryrefslogtreecommitdiffstats
path: root/net/ieee80211
diff options
context:
space:
mode:
Diffstat (limited to 'net/ieee80211')
-rw-r--r--net/ieee80211/softmac/Kconfig1
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_assoc.c25
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_event.c40
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_io.c18
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_module.c2
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_scan.c2
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_wx.c37
7 files changed, 102 insertions, 23 deletions
diff --git a/net/ieee80211/softmac/Kconfig b/net/ieee80211/softmac/Kconfig
index 6cd9f3427be6..f2a27cc6ecb1 100644
--- a/net/ieee80211/softmac/Kconfig
+++ b/net/ieee80211/softmac/Kconfig
@@ -1,6 +1,7 @@
1config IEEE80211_SOFTMAC 1config IEEE80211_SOFTMAC
2 tristate "Software MAC add-on to the IEEE 802.11 networking stack" 2 tristate "Software MAC add-on to the IEEE 802.11 networking stack"
3 depends on IEEE80211 && EXPERIMENTAL 3 depends on IEEE80211 && EXPERIMENTAL
4 select WIRELESS_EXT
4 ---help--- 5 ---help---
5 This option enables the hardware independent software MAC addon 6 This option enables the hardware independent software MAC addon
6 for the IEEE 802.11 networking stack. 7 for the IEEE 802.11 networking stack.
diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c
index be61de78dfa4..fb79ce7d6439 100644
--- a/net/ieee80211/softmac/ieee80211softmac_assoc.c
+++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c
@@ -101,6 +101,7 @@ ieee80211softmac_disassoc(struct ieee80211softmac_device *mac, u16 reason)
101 /* Do NOT clear bssvalid as that will break ieee80211softmac_assoc_work! */ 101 /* Do NOT clear bssvalid as that will break ieee80211softmac_assoc_work! */
102 mac->associated = 0; 102 mac->associated = 0;
103 mac->associnfo.associating = 0; 103 mac->associnfo.associating = 0;
104 ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
104 spin_unlock_irqrestore(&mac->lock, flags); 105 spin_unlock_irqrestore(&mac->lock, flags);
105} 106}
106 107
@@ -143,6 +144,12 @@ network_matches_request(struct ieee80211softmac_device *mac, struct ieee80211_ne
143 if (!we_support_all_basic_rates(mac, net->rates_ex, net->rates_ex_len)) 144 if (!we_support_all_basic_rates(mac, net->rates_ex, net->rates_ex_len))
144 return 0; 145 return 0;
145 146
147 /* assume that users know what they're doing ...
148 * (note we don't let them select a net we're incompatible with) */
149 if (mac->associnfo.bssfixed) {
150 return !memcmp(mac->associnfo.bssid, net->bssid, ETH_ALEN);
151 }
152
146 /* if 'ANY' network requested, take any that doesn't have privacy enabled */ 153 /* if 'ANY' network requested, take any that doesn't have privacy enabled */
147 if (mac->associnfo.req_essid.len == 0 154 if (mac->associnfo.req_essid.len == 0
148 && !(net->capability & WLAN_CAPABILITY_PRIVACY)) 155 && !(net->capability & WLAN_CAPABILITY_PRIVACY))
@@ -175,7 +182,7 @@ ieee80211softmac_assoc_work(void *d)
175 ieee80211softmac_disassoc(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT); 182 ieee80211softmac_disassoc(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT);
176 183
177 /* try to find the requested network in our list, if we found one already */ 184 /* try to find the requested network in our list, if we found one already */
178 if (mac->associnfo.bssvalid) 185 if (mac->associnfo.bssvalid || mac->associnfo.bssfixed)
179 found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid); 186 found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);
180 187
181 /* Search the ieee80211 networks for this network if we didn't find it by bssid, 188 /* Search the ieee80211 networks for this network if we didn't find it by bssid,
@@ -240,19 +247,25 @@ ieee80211softmac_assoc_work(void *d)
240 if (ieee80211softmac_start_scan(mac)) 247 if (ieee80211softmac_start_scan(mac))
241 dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n"); 248 dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n");
242 return; 249 return;
243 } 250 } else {
244 else {
245 spin_lock_irqsave(&mac->lock, flags); 251 spin_lock_irqsave(&mac->lock, flags);
246 mac->associnfo.associating = 0; 252 mac->associnfo.associating = 0;
247 mac->associated = 0; 253 mac->associated = 0;
248 spin_unlock_irqrestore(&mac->lock, flags); 254 spin_unlock_irqrestore(&mac->lock, flags);
249 255
250 dprintk(KERN_INFO PFX "Unable to find matching network after scan!\n"); 256 dprintk(KERN_INFO PFX "Unable to find matching network after scan!\n");
257 /* reset the retry counter for the next user request since we
258 * break out and don't reschedule ourselves after this point. */
259 mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
251 ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND, NULL); 260 ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND, NULL);
252 return; 261 return;
253 } 262 }
254 } 263 }
255 264
265 /* reset the retry counter for the next user request since we
266 * now found a net and will try to associate to it, but not
267 * schedule this function again. */
268 mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
256 mac->associnfo.bssvalid = 1; 269 mac->associnfo.bssvalid = 1;
257 memcpy(mac->associnfo.bssid, found->bssid, ETH_ALEN); 270 memcpy(mac->associnfo.bssid, found->bssid, ETH_ALEN);
258 /* copy the ESSID for displaying it */ 271 /* copy the ESSID for displaying it */
@@ -373,6 +386,7 @@ ieee80211softmac_handle_disassoc(struct net_device * dev,
373 spin_lock_irqsave(&mac->lock, flags); 386 spin_lock_irqsave(&mac->lock, flags);
374 mac->associnfo.bssvalid = 0; 387 mac->associnfo.bssvalid = 0;
375 mac->associated = 0; 388 mac->associated = 0;
389 ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
376 schedule_work(&mac->associnfo.work); 390 schedule_work(&mac->associnfo.work);
377 spin_unlock_irqrestore(&mac->lock, flags); 391 spin_unlock_irqrestore(&mac->lock, flags);
378 392
@@ -391,6 +405,7 @@ ieee80211softmac_handle_reassoc_req(struct net_device * dev,
391 dprintkl(KERN_INFO PFX "reassoc request from unknown network\n"); 405 dprintkl(KERN_INFO PFX "reassoc request from unknown network\n");
392 return 0; 406 return 0;
393 } 407 }
394 ieee80211softmac_assoc(mac, network); 408 schedule_work(&mac->associnfo.work);
409
395 return 0; 410 return 0;
396} 411}
diff --git a/net/ieee80211/softmac/ieee80211softmac_event.c b/net/ieee80211/softmac/ieee80211softmac_event.c
index 0a52bbda1e4c..8cc8f3f0f8e7 100644
--- a/net/ieee80211/softmac/ieee80211softmac_event.c
+++ b/net/ieee80211/softmac/ieee80211softmac_event.c
@@ -67,6 +67,7 @@ static char *event_descriptions[IEEE80211SOFTMAC_EVENT_LAST+1] = {
67 "authenticating failed", 67 "authenticating failed",
68 "authenticating timed out", 68 "authenticating timed out",
69 "associating failed because no suitable network was found", 69 "associating failed because no suitable network was found",
70 "disassociated",
70}; 71};
71 72
72 73
@@ -128,13 +129,42 @@ void
128ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int event, void *event_ctx) 129ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int event, void *event_ctx)
129{ 130{
130 struct ieee80211softmac_event *eventptr, *tmp; 131 struct ieee80211softmac_event *eventptr, *tmp;
131 union iwreq_data wrqu; 132 struct ieee80211softmac_network *network;
132 char *msg;
133 133
134 if (event >= 0) { 134 if (event >= 0) {
135 msg = event_descriptions[event]; 135 union iwreq_data wrqu;
136 wrqu.data.length = strlen(msg); 136 int we_event;
137 wireless_send_event(mac->dev, IWEVCUSTOM, &wrqu, msg); 137 char *msg = NULL;
138
139 switch(event) {
140 case IEEE80211SOFTMAC_EVENT_ASSOCIATED:
141 network = (struct ieee80211softmac_network *)event_ctx;
142 wrqu.data.length = 0;
143 wrqu.data.flags = 0;
144 memcpy(wrqu.ap_addr.sa_data, &network->bssid[0], ETH_ALEN);
145 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
146 we_event = SIOCGIWAP;
147 break;
148 case IEEE80211SOFTMAC_EVENT_DISASSOCIATED:
149 wrqu.data.length = 0;
150 wrqu.data.flags = 0;
151 memset(&wrqu, '\0', sizeof (union iwreq_data));
152 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
153 we_event = SIOCGIWAP;
154 break;
155 case IEEE80211SOFTMAC_EVENT_SCAN_FINISHED:
156 wrqu.data.length = 0;
157 wrqu.data.flags = 0;
158 memset(&wrqu, '\0', sizeof (union iwreq_data));
159 we_event = SIOCGIWSCAN;
160 break;
161 default:
162 msg = event_descriptions[event];
163 wrqu.data.length = strlen(msg);
164 we_event = IWEVCUSTOM;
165 break;
166 }
167 wireless_send_event(mac->dev, we_event, &wrqu, msg);
138 } 168 }
139 169
140 if (!list_empty(&mac->events)) 170 if (!list_empty(&mac->events))
diff --git a/net/ieee80211/softmac/ieee80211softmac_io.c b/net/ieee80211/softmac/ieee80211softmac_io.c
index febc51dbb412..cc6cd56c85b1 100644
--- a/net/ieee80211/softmac/ieee80211softmac_io.c
+++ b/net/ieee80211/softmac/ieee80211softmac_io.c
@@ -180,9 +180,21 @@ ieee80211softmac_assoc_req(struct ieee80211_assoc_request **pkt,
180 ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_ASSOC_REQ, net->bssid, net->bssid); 180 ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_ASSOC_REQ, net->bssid, net->bssid);
181 181
182 /* Fill in capability Info */ 182 /* Fill in capability Info */
183 (*pkt)->capability = (mac->ieee->iw_mode == IW_MODE_MASTER) || (mac->ieee->iw_mode == IW_MODE_INFRA) ? 183 switch (mac->ieee->iw_mode) {
184 cpu_to_le16(WLAN_CAPABILITY_ESS) : 184 case IW_MODE_INFRA:
185 cpu_to_le16(WLAN_CAPABILITY_IBSS); 185 (*pkt)->capability = cpu_to_le16(WLAN_CAPABILITY_ESS);
186 break;
187 case IW_MODE_ADHOC:
188 (*pkt)->capability = cpu_to_le16(WLAN_CAPABILITY_IBSS);
189 break;
190 case IW_MODE_AUTO:
191 (*pkt)->capability = net->capabilities & (WLAN_CAPABILITY_ESS|WLAN_CAPABILITY_IBSS);
192 break;
193 default:
194 /* bleh. we don't ever go to these modes */
195 printk(KERN_ERR PFX "invalid iw_mode!\n");
196 break;
197 }
186 /* Need to add this 198 /* Need to add this
187 (*pkt)->capability |= mac->ieee->short_slot ? 199 (*pkt)->capability |= mac->ieee->short_slot ?
188 cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME) : 0; 200 cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME) : 0;
diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c
index 60f06a31f0d1..be83bdc1644a 100644
--- a/net/ieee80211/softmac/ieee80211softmac_module.c
+++ b/net/ieee80211/softmac/ieee80211softmac_module.c
@@ -45,6 +45,8 @@ struct net_device *alloc_ieee80211softmac(int sizeof_priv)
45 softmac->ieee->handle_disassoc = ieee80211softmac_handle_disassoc; 45 softmac->ieee->handle_disassoc = ieee80211softmac_handle_disassoc;
46 softmac->scaninfo = NULL; 46 softmac->scaninfo = NULL;
47 47
48 softmac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
49
48 /* TODO: initialise all the other callbacks in the ieee struct 50 /* TODO: initialise all the other callbacks in the ieee struct
49 * (once they're written) 51 * (once they're written)
50 */ 52 */
diff --git a/net/ieee80211/softmac/ieee80211softmac_scan.c b/net/ieee80211/softmac/ieee80211softmac_scan.c
index bb9ab8b45d09..2b9e7edfa3ce 100644
--- a/net/ieee80211/softmac/ieee80211softmac_scan.c
+++ b/net/ieee80211/softmac/ieee80211softmac_scan.c
@@ -47,6 +47,7 @@ ieee80211softmac_start_scan(struct ieee80211softmac_device *sm)
47 sm->scanning = 1; 47 sm->scanning = 1;
48 spin_unlock_irqrestore(&sm->lock, flags); 48 spin_unlock_irqrestore(&sm->lock, flags);
49 49
50 netif_tx_disable(sm->ieee->dev);
50 ret = sm->start_scan(sm->dev); 51 ret = sm->start_scan(sm->dev);
51 if (ret) { 52 if (ret) {
52 spin_lock_irqsave(&sm->lock, flags); 53 spin_lock_irqsave(&sm->lock, flags);
@@ -239,6 +240,7 @@ void ieee80211softmac_scan_finished(struct ieee80211softmac_device *sm)
239 if (net) 240 if (net)
240 sm->set_channel(sm->dev, net->channel); 241 sm->set_channel(sm->dev, net->channel);
241 } 242 }
243 netif_wake_queue(sm->ieee->dev);
242 ieee80211softmac_call_events(sm, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, NULL); 244 ieee80211softmac_call_events(sm, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, NULL);
243} 245}
244EXPORT_SYMBOL_GPL(ieee80211softmac_scan_finished); 246EXPORT_SYMBOL_GPL(ieee80211softmac_scan_finished);
diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c
index b559aa9b5507..27edb2b5581a 100644
--- a/net/ieee80211/softmac/ieee80211softmac_wx.c
+++ b/net/ieee80211/softmac/ieee80211softmac_wx.c
@@ -27,7 +27,8 @@
27#include "ieee80211softmac_priv.h" 27#include "ieee80211softmac_priv.h"
28 28
29#include <net/iw_handler.h> 29#include <net/iw_handler.h>
30 30/* for is_broadcast_ether_addr and is_zero_ether_addr */
31#include <linux/etherdevice.h>
31 32
32int 33int
33ieee80211softmac_wx_trigger_scan(struct net_device *net_dev, 34ieee80211softmac_wx_trigger_scan(struct net_device *net_dev,
@@ -41,13 +42,23 @@ ieee80211softmac_wx_trigger_scan(struct net_device *net_dev,
41EXPORT_SYMBOL_GPL(ieee80211softmac_wx_trigger_scan); 42EXPORT_SYMBOL_GPL(ieee80211softmac_wx_trigger_scan);
42 43
43 44
45/* if we're still scanning, return -EAGAIN so that userspace tools
46 * can get the complete scan results, otherwise return 0. */
44int 47int
45ieee80211softmac_wx_get_scan_results(struct net_device *net_dev, 48ieee80211softmac_wx_get_scan_results(struct net_device *net_dev,
46 struct iw_request_info *info, 49 struct iw_request_info *info,
47 union iwreq_data *data, 50 union iwreq_data *data,
48 char *extra) 51 char *extra)
49{ 52{
53 unsigned long flags;
50 struct ieee80211softmac_device *sm = ieee80211_priv(net_dev); 54 struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
55
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);
51 return ieee80211_wx_get_scan(sm->ieee, info, data, extra); 62 return ieee80211_wx_get_scan(sm->ieee, info, data, extra);
52} 63}
53EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_scan_results); 64EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_scan_results);
@@ -73,7 +84,6 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev,
73 sm->associnfo.static_essid = 1; 84 sm->associnfo.static_essid = 1;
74 } 85 }
75 } 86 }
76 sm->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
77 87
78 /* set our requested ESSID length. 88 /* set our requested ESSID length.
79 * If applicable, we have already copied the data in */ 89 * If applicable, we have already copied the data in */
@@ -300,8 +310,6 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev,
300 char *extra) 310 char *extra)
301{ 311{
302 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); 312 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
303 static const unsigned char any[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
304 static const unsigned char off[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
305 unsigned long flags; 313 unsigned long flags;
306 314
307 /* sanity check */ 315 /* sanity check */
@@ -310,10 +318,17 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev,
310 } 318 }
311 319
312 spin_lock_irqsave(&mac->lock, flags); 320 spin_lock_irqsave(&mac->lock, flags);
313 if (!memcmp(any, data->ap_addr.sa_data, ETH_ALEN) || 321 if (is_broadcast_ether_addr(data->ap_addr.sa_data)) {
314 !memcmp(off, data->ap_addr.sa_data, ETH_ALEN)) { 322 /* the bssid we have is not to be fixed any longer,
315 schedule_work(&mac->associnfo.work); 323 * and we should reassociate to the best AP. */
316 goto out; 324 mac->associnfo.bssfixed = 0;
325 /* force reassociation */
326 mac->associnfo.bssvalid = 0;
327 if (mac->associated)
328 schedule_work(&mac->associnfo.work);
329 } else if (is_zero_ether_addr(data->ap_addr.sa_data)) {
330 /* the bssid we have is no longer fixed */
331 mac->associnfo.bssfixed = 0;
317 } else { 332 } else {
318 if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) { 333 if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) {
319 if (mac->associnfo.associating || mac->associated) { 334 if (mac->associnfo.associating || mac->associated) {
@@ -323,12 +338,14 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev,
323 } else { 338 } else {
324 /* copy new value in data->ap_addr.sa_data to bssid */ 339 /* copy new value in data->ap_addr.sa_data to bssid */
325 memcpy(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN); 340 memcpy(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN);
326 } 341 }
342 /* tell the other code that this bssid should be used no matter what */
343 mac->associnfo.bssfixed = 1;
327 /* queue associate if new bssid or (old one again and not associated) */ 344 /* queue associate if new bssid or (old one again and not associated) */
328 schedule_work(&mac->associnfo.work); 345 schedule_work(&mac->associnfo.work);
329 } 346 }
330 347
331out: 348 out:
332 spin_unlock_irqrestore(&mac->lock, flags); 349 spin_unlock_irqrestore(&mac->lock, flags);
333 return 0; 350 return 0;
334} 351}