diff -up wpa_supplicant-0.6.8/wpa_supplicant/events.c.disconnect-spam wpa_supplicant-0.6.8/wpa_supplicant/events.c --- wpa_supplicant-0.6.8/wpa_supplicant/events.c.disconnect-spam 2010-05-06 18:10:51.348288705 -0700 +++ wpa_supplicant-0.6.8/wpa_supplicant/events.c 2010-05-06 18:10:51.356288887 -0700 @@ -1302,6 +1302,15 @@ static void wpa_supplicant_event_disasso wpa_s->keys_cleared = 0; wpa_clear_keys(wpa_s, wpa_s->bssid); } + + if (wpa_s->wpa_state == WPA_DISCONNECTED) { + wpa_s->disconnect_count++; + if (!eloop_is_timeout_registered(wpa_disconnect_spam_handle, wpa_s, NULL)) { + eloop_register_timeout(6, 0, wpa_disconnect_spam_handle, wpa_s, NULL); + wpa_printf(MSG_DEBUG, "%s: scheduled DISCONNECT spam handler", __FUNCTION__); + } + } + wpa_supplicant_mark_disassoc(wpa_s); bgscan_deinit(wpa_s); wpa_s->bgscan_ssid = NULL; diff -up wpa_supplicant-0.6.8/wpa_supplicant/wpa_supplicant.c.disconnect-spam wpa_supplicant-0.6.8/wpa_supplicant/wpa_supplicant.c --- wpa_supplicant-0.6.8/wpa_supplicant/wpa_supplicant.c.disconnect-spam 2010-05-06 18:10:51.340288662 -0700 +++ wpa_supplicant-0.6.8/wpa_supplicant/wpa_supplicant.c 2010-05-06 18:12:06.090413976 -0700 @@ -382,6 +382,9 @@ static void wpa_supplicant_cleanup(struc wpa_supplicant_cancel_scan(wpa_s); wpa_supplicant_cancel_auth_timeout(wpa_s); + if (eloop_is_timeout_registered(wpa_disconnect_spam_handle, wpa_s, NULL)) + eloop_cancel_timeout(wpa_disconnect_spam_handle, wpa_s, NULL); + ieee80211_sta_deinit(wpa_s); wpas_wps_deinit(wpa_s); @@ -461,6 +464,23 @@ const char * wpa_supplicant_state_txt(in } +void wpa_disconnect_spam_handle(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_supplicant *wpa_s = eloop_ctx; + const u8 bssid[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + + wpa_printf(MSG_DEBUG, "%s: %d disconnect events in 6 seconds", + __FUNCTION__, wpa_s->disconnect_count); + + if (wpa_s->disconnect_count >= 3) { + wpa_printf(MSG_DEBUG, "%s: forcing SSID/BSSID reset", __FUNCTION__); + wpa_drv_disassociate(wpa_s, bssid, WLAN_REASON_DEAUTH_LEAVING); + wpa_supplicant_req_scan(wpa_s, 1, 0); + } + wpa_s->disconnect_count = 0; +} + + /** * wpa_supplicant_set_state - Set current connection state * @wpa_s: Pointer to wpa_supplicant data @@ -478,6 +498,18 @@ void wpa_supplicant_set_state(struct wpa if (state != WPA_SCANNING) wpa_supplicant_notify_scanning(wpa_s, 0); + if (state != WPA_DISCONNECTED && state != WPA_SCANNING) { + /* If the state isn't disconnected, cancel any registered + * disconnect spam handler, which should only live while + * disconnect events are coming in quickly. + */ + wpa_s->disconnect_count = 0; + if (eloop_is_timeout_registered(wpa_disconnect_spam_handle, wpa_s, NULL)) { + wpa_printf(MSG_DEBUG, "%s: canceling DISCONNECT spam handler", __FUNCTION__); + eloop_cancel_timeout(wpa_disconnect_spam_handle, wpa_s, NULL); + } + } + if (state == WPA_COMPLETED && wpa_s->new_connection) { #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG) struct wpa_ssid *ssid = wpa_s->current_ssid; diff -up wpa_supplicant-0.6.8/wpa_supplicant/wpa_supplicant_i.h.disconnect-spam wpa_supplicant-0.6.8/wpa_supplicant/wpa_supplicant_i.h --- wpa_supplicant-0.6.8/wpa_supplicant/wpa_supplicant_i.h.disconnect-spam 2009-02-15 10:00:00.000000000 -0800 +++ wpa_supplicant-0.6.8/wpa_supplicant/wpa_supplicant_i.h 2010-05-06 18:10:51.358288792 -0700 @@ -397,6 +397,8 @@ struct wpa_supplicant { int wps_success; /* WPS success event received */ struct wps_er *wps_er; int blacklist_cleared; + + int disconnect_count; struct wpabuf *pending_eapol_rx; struct os_time pending_eapol_rx_time; @@ -461,6 +463,7 @@ void wpa_clear_keys(struct wpa_supplican int sec, int usec); void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, enum wpa_states state); +void wpa_disconnect_spam_handle(void *eloop_ctx, void *timeout_ctx); struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s); void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s); void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,