[PATCH] softmac: Fix handling of authentication failure
authorDaniel Drake <dsd@gentoo.org>
Thu, 1 Jun 2006 14:37:22 +0000 (15:37 +0100)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 5 Jun 2006 19:51:30 +0000 (15:51 -0400)
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: Daniel Drake <dsd@gentoo.org>
Acked-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
include/net/ieee80211softmac.h
net/ieee80211/softmac/ieee80211softmac_assoc.c
net/ieee80211/softmac/ieee80211softmac_event.c

index 703463a8828b2f8e5ba3a14f6214f968c4fd3c3e..7a483ab4022f98cd20d4946dc7f61054d08e30f0 100644 (file)
@@ -310,7 +310,7 @@ extern void ieee80211softmac_stop(struct net_device *dev);
  *     - context set to the context data you want passed
  * 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_atomic(dev, event, fun, context) ieee80211softmac_notify_gfp(dev, event, fun, context, GFP_ATOMIC);
index 5d90b9a6ee50f5863027a1e957b1d918bbdfa0b7..5e9a90651d04f5433225357dad60ac5c396218d2 100644 (file)
@@ -164,12 +164,28 @@ network_matches_request(struct ieee80211softmac_device *mac, struct ieee80211_ne
 }
 
 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);
        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) */
 void
 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 ;)
                         */
                        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))
                                dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n");
                        return;
@@ -284,7 +300,7 @@ ieee80211softmac_assoc_work(void *d)
                 * otherwise adding the notification would be racy. */
                if (!ieee80211softmac_auth_req(mac, found)) {
                        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 {
                        printkl(KERN_WARNING PFX "Not authenticated, but requesting authentication failed. Giving up to associate\n");
                        ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, found);
index 4b153f7cc96c7096f41515a15013882734d45197..f34fa2ef666b5fa56247f060bae06a2d94f7f06e 100644 (file)
@@ -78,7 +78,7 @@ ieee80211softmac_notify_callback(void *d)
        struct ieee80211softmac_event event = *(struct ieee80211softmac_event*) d;
        kfree(d);
        
-       event.fun(event.mac->dev, event.context);
+       event.fun(event.mac->dev, event.event_type, event.context);
 }
 
 int
@@ -167,6 +167,9 @@ ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int eve
                        if ((eventptr->event_type == event || eventptr->event_type == -1)
                                && (eventptr->event_context == NULL || eventptr->event_context == event_ctx)) {
                                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);
                        }
                }