]> err.no Git - linux-2.6/blobdiff - net/ieee80211/softmac/ieee80211softmac_auth.c
[PATCH] SoftMAC: Prevent multiple authentication attempts on the same network
[linux-2.6] / net / ieee80211 / softmac / ieee80211softmac_auth.c
index 84ad029031ba10973496a299fa988269a71a2c1a..ebc33ca6e6920d19b870d8b24e0e657356bcc7b3 100644 (file)
@@ -1,11 +1,11 @@
 /*
  * This file contains the softmac's authentication logic.
  *
- * Copyright (c) 2005 Johannes Berg <johannes@sipsolutions.net>
- *                    Joseph Jezak <josejx@gentoo.org>
- *                    Larry Finger <Larry.Finger@lwfinger.net>
- *                    Danny van Dyk <kugelfang@gentoo.org>
- *                    Michael Buesch <mbuesch@freenet.de>
+ * Copyright (c) 2005, 2006 Johannes Berg <johannes@sipsolutions.net>
+ *                          Joseph Jezak <josejx@gentoo.org>
+ *                          Larry Finger <Larry.Finger@lwfinger.net>
+ *                          Danny van Dyk <kugelfang@gentoo.org>
+ *                          Michael Buesch <mbuesch@freenet.de>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -36,10 +36,9 @@ ieee80211softmac_auth_req(struct ieee80211softmac_device *mac,
        struct ieee80211softmac_auth_queue_item *auth;
        unsigned long flags;
        
-       function_enter();
-       
-       if (net->authenticating)
+       if (net->authenticating || net->authenticated)
                return 0;
+       net->authenticating = 1;
 
        /* Add the network if it's not already added */
        ieee80211softmac_add_network(mac, net);
@@ -78,8 +77,6 @@ ieee80211softmac_auth_queue(void *data)
        struct ieee80211softmac_network *net;
        unsigned long flags;
 
-       function_enter();
-       
        auth = (struct ieee80211softmac_auth_queue_item *)data;
        net = auth->net;
        mac = auth->mac;
@@ -90,8 +87,12 @@ ieee80211softmac_auth_queue(void *data)
                
                /* Lock and set flags */
                spin_lock_irqsave(&mac->lock, flags);
+               if (unlikely(!mac->running)) {
+                       /* Prevent reschedule on workqueue flush */
+                       spin_unlock_irqrestore(&mac->lock, flags);
+                       return;
+               }
                net->authenticated = 0;
-               net->authenticating = 1;
                /* add a timeout call so we eventually give up waiting for an auth reply */
                schedule_delayed_work(&auth->work, IEEE80211SOFTMAC_AUTH_TIMEOUT);
                auth->retry--;
@@ -106,6 +107,7 @@ ieee80211softmac_auth_queue(void *data)
        printkl(KERN_WARNING PFX "Authentication timed out with "MAC_FMT"\n", MAC_ARG(net->bssid));
        /* Remove this item from the queue */
        spin_lock_irqsave(&mac->lock, flags);
+       net->authenticating = 0;
        ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT, net);
        cancel_delayed_work(&auth->work); /* just to make sure... */
        list_del(&auth->list);
@@ -128,8 +130,9 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth)
        unsigned long flags;
        u8 * data;
        
-       function_enter();
-       
+       if (unlikely(!mac->running))
+               return -ENODEV;
+
        /* Find correct auth queue item */
        spin_lock_irqsave(&mac->lock, flags);
        list_for_each(list_ptr, &mac->auth_queue) {
@@ -210,13 +213,13 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth)
                        aq->state = IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE; 
                        spin_unlock_irqrestore(&mac->lock, flags);
 
-                       /* Switch to correct channel for this network */
-                       mac->set_channel(mac->dev, net->channel);
-                       
-                       /* Send our response (How to encrypt?) */
+                       /* Send our response */
                        ieee80211softmac_send_mgt_frame(mac, aq->net, IEEE80211_STYPE_AUTH, aq->state);
-                       break;
+                       return 0;
                case IEEE80211SOFTMAC_AUTH_SHARED_PASS:
+                       kfree(net->challenge);
+                       net->challenge = NULL;
+                       net->challenge_len = 0;
                        /* Check the status code of the response */
                        switch(auth->status) {
                        case WLAN_STATUS_SUCCESS:
@@ -227,6 +230,7 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth)
                                spin_unlock_irqrestore(&mac->lock, flags);
                                printkl(KERN_NOTICE PFX "Shared Key Authentication completed with "MAC_FMT"\n", 
                                        MAC_ARG(net->bssid));
+                               ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_AUTHENTICATED, net);
                                break;
                        default:
                                printkl(KERN_NOTICE PFX "Shared Key Authentication with "MAC_FMT" failed, error code: %i\n", 
@@ -277,8 +281,9 @@ ieee80211softmac_deauth_from_net(struct ieee80211softmac_device *mac,
        struct list_head *list_ptr;
        unsigned long flags;
 
-       function_enter();
-       
+       /* deauthentication implies disassociation */
+       ieee80211softmac_disassoc(mac);
+
        /* Lock and reset status flags */
        spin_lock_irqsave(&mac->lock, flags);
        net->authenticating = 0;
@@ -306,8 +311,6 @@ ieee80211softmac_deauth_from_net(struct ieee80211softmac_device *mac,
        
        /* can't transmit data right now... */
        netif_carrier_off(mac->dev);
-       /* let's try to re-associate */
-       schedule_work(&mac->associnfo.work);
        spin_unlock_irqrestore(&mac->lock, flags);
 }
 
@@ -320,8 +323,6 @@ ieee80211softmac_deauth_req(struct ieee80211softmac_device *mac,
 {
        int ret;
        
-       function_enter();
-
        /* Make sure the network is authenticated */
        if (!net->authenticated)
        {
@@ -342,24 +343,25 @@ ieee80211softmac_deauth_req(struct ieee80211softmac_device *mac,
  * This should be registered with ieee80211 as handle_deauth
  */
 int 
-ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_auth *auth)
+ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *deauth)
 {
        
        struct ieee80211softmac_network *net = NULL;
        struct ieee80211softmac_device *mac = ieee80211_priv(dev);
        
-       function_enter();
-       
-       if (!auth) {
+       if (unlikely(!mac->running))
+               return -ENODEV;
+
+       if (!deauth) {
                dprintk("deauth without deauth packet. eek!\n");
                return 0;
        }
 
-       net = ieee80211softmac_get_network_by_bssid(mac, auth->header.addr2);
+       net = ieee80211softmac_get_network_by_bssid(mac, deauth->header.addr2);
        
        if (net == NULL) {
-               printkl(KERN_DEBUG PFX "Recieved deauthentication packet from "MAC_FMT", but that network is unknown.\n",
-                       MAC_ARG(auth->header.addr2));
+               printkl(KERN_DEBUG PFX "Received deauthentication packet from "MAC_FMT", but that network is unknown.\n",
+                       MAC_ARG(deauth->header.addr2));
                return 0;
        }
 
@@ -372,5 +374,8 @@ ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_auth *auth
        }
 
        ieee80211softmac_deauth_from_net(mac, net);
+
+       /* let's try to re-associate */
+       schedule_work(&mac->associnfo.work);
        return 0;
 }