mirror of https://gitee.com/openkylin/linux.git
[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: Daniel Drake <dsd@gentoo.org> Acked-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
76ea4c7f4c
commit
6ae15df16e
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
* 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)
|
||||||
* 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)
|
||||||
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
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue