Commit 6ae15df1 authored by Daniel Drake's avatar Daniel Drake Committed by John W. Linville

[PATCH] softmac: Fix handling of authentication failure

My router blew up earlier, but exhibited some interesting behaviour during
its dying moments. It was broadcasting beacons but wouldn't respond to
any authentication requests.

I noticed that softmac wasn't playing nice with this, as I couldn't make it try
to connect to other networks after it had timed out authenticating to my ill
router.

To resolve this, I modified the softmac event/notify API to pass the event
code to the callback, so that callbacks being notified from
IEEE80211SOFTMAC_EVENT_ANY masks can make some judgement. In this case, the
ieee80211softmac_assoc callback needs to make a decision based upon whether
the association passed or failed.
Signed-off-by: default avatarDaniel Drake <dsd@gentoo.org>
Acked-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 76ea4c7f
...@@ -310,7 +310,7 @@ extern void ieee80211softmac_stop(struct net_device *dev); ...@@ -310,7 +310,7 @@ extern void ieee80211softmac_stop(struct net_device *dev);
* - context set to the context data you want passed * - context set to the context data you want passed
* The return value is 0, or an error. * The return value is 0, or an error.
*/ */
typedef void (*notify_function_ptr)(struct net_device *dev, void *context); typedef void (*notify_function_ptr)(struct net_device *dev, int event_type, void *context);
#define ieee80211softmac_notify(dev, event, fun, context) ieee80211softmac_notify_gfp(dev, event, fun, context, GFP_KERNEL); #define ieee80211softmac_notify(dev, event, fun, context) ieee80211softmac_notify_gfp(dev, event, fun, context, GFP_KERNEL);
#define ieee80211softmac_notify_atomic(dev, event, fun, context) ieee80211softmac_notify_gfp(dev, event, fun, context, GFP_ATOMIC); #define ieee80211softmac_notify_atomic(dev, event, fun, context) ieee80211softmac_notify_gfp(dev, event, fun, context, GFP_ATOMIC);
......
...@@ -164,12 +164,28 @@ network_matches_request(struct ieee80211softmac_device *mac, struct ieee80211_ne ...@@ -164,12 +164,28 @@ network_matches_request(struct ieee80211softmac_device *mac, struct ieee80211_ne
} }
static void static void
ieee80211softmac_assoc_notify(struct net_device *dev, void *context) ieee80211softmac_assoc_notify_scan(struct net_device *dev, int event_type, void *context)
{ {
struct ieee80211softmac_device *mac = ieee80211_priv(dev); struct ieee80211softmac_device *mac = ieee80211_priv(dev);
ieee80211softmac_assoc_work((void*)mac); ieee80211softmac_assoc_work((void*)mac);
} }
static void
ieee80211softmac_assoc_notify_auth(struct net_device *dev, int event_type, void *context)
{
struct ieee80211softmac_device *mac = ieee80211_priv(dev);
switch (event_type) {
case IEEE80211SOFTMAC_EVENT_AUTHENTICATED:
ieee80211softmac_assoc_work((void*)mac);
break;
case IEEE80211SOFTMAC_EVENT_AUTH_FAILED:
case IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT:
ieee80211softmac_disassoc(mac);
break;
}
}
/* This function is called to handle userspace requests (asynchronously) */ /* This function is called to handle userspace requests (asynchronously) */
void void
ieee80211softmac_assoc_work(void *d) ieee80211softmac_assoc_work(void *d)
...@@ -249,7 +265,7 @@ ieee80211softmac_assoc_work(void *d) ...@@ -249,7 +265,7 @@ ieee80211softmac_assoc_work(void *d)
* Maybe we can hope to have more memory after scanning finishes ;) * Maybe we can hope to have more memory after scanning finishes ;)
*/ */
dprintk(KERN_INFO PFX "Associate: Scanning for networks first.\n"); dprintk(KERN_INFO PFX "Associate: Scanning for networks first.\n");
ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify, NULL); ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify_scan, NULL);
if (ieee80211softmac_start_scan(mac)) if (ieee80211softmac_start_scan(mac))
dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n"); dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n");
return; return;
...@@ -284,7 +300,7 @@ ieee80211softmac_assoc_work(void *d) ...@@ -284,7 +300,7 @@ ieee80211softmac_assoc_work(void *d)
* otherwise adding the notification would be racy. */ * otherwise adding the notification would be racy. */
if (!ieee80211softmac_auth_req(mac, found)) { if (!ieee80211softmac_auth_req(mac, found)) {
dprintk(KERN_INFO PFX "cannot associate without being authenticated, requested authentication\n"); dprintk(KERN_INFO PFX "cannot associate without being authenticated, requested authentication\n");
ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify, NULL, GFP_KERNEL); ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify_auth, NULL, GFP_KERNEL);
} else { } else {
printkl(KERN_WARNING PFX "Not authenticated, but requesting authentication failed. Giving up to associate\n"); printkl(KERN_WARNING PFX "Not authenticated, but requesting authentication failed. Giving up to associate\n");
ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, found); ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, found);
......
...@@ -78,7 +78,7 @@ ieee80211softmac_notify_callback(void *d) ...@@ -78,7 +78,7 @@ ieee80211softmac_notify_callback(void *d)
struct ieee80211softmac_event event = *(struct ieee80211softmac_event*) d; struct ieee80211softmac_event event = *(struct ieee80211softmac_event*) d;
kfree(d); kfree(d);
event.fun(event.mac->dev, event.context); event.fun(event.mac->dev, event.event_type, event.context);
} }
int int
...@@ -167,6 +167,9 @@ ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int eve ...@@ -167,6 +167,9 @@ ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int eve
if ((eventptr->event_type == event || eventptr->event_type == -1) if ((eventptr->event_type == event || eventptr->event_type == -1)
&& (eventptr->event_context == NULL || eventptr->event_context == event_ctx)) { && (eventptr->event_context == NULL || eventptr->event_context == event_ctx)) {
list_del(&eventptr->list); list_del(&eventptr->list);
/* User may have subscribed to ANY event, so
* we tell them which event triggered it. */
eventptr->event_type = event;
schedule_work(&eventptr->work); schedule_work(&eventptr->work);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment