diff --git a/wpa_supplicant/blacklist.c b/wpa_supplicant/blacklist.c index 2e01e7fea..e53dc38b3 100644 --- a/wpa_supplicant/blacklist.c +++ b/wpa_supplicant/blacklist.c @@ -123,14 +123,19 @@ int wpa_blacklist_del(struct wpa_supplicant *wpa_s, const u8 *bssid) void wpa_blacklist_clear(struct wpa_supplicant *wpa_s) { struct wpa_blacklist *e, *prev; + int max_count = 0; e = wpa_s->blacklist; wpa_s->blacklist = NULL; while (e) { + if (e->count > max_count) + max_count = e->count; prev = e; e = e->next; wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR " from " "blacklist (clear)", MAC2STR(prev->bssid)); os_free(prev); } + + wpa_s->extra_blacklist_count += max_count; } diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index f47495d57..328d382fa 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -4786,6 +4786,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) reply_len = -1; else { + wpa_s->extra_blacklist_count = 0; wpa_s->disconnected = 0; wpa_s->reassociate = 1; wpa_supplicant_req_scan(wpa_s, 0, 0); @@ -4796,6 +4797,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) reply_len = -1; else if (wpa_s->disconnected) { + wpa_s->extra_blacklist_count = 0; wpa_s->disconnected = 0; wpa_s->reassociate = 1; wpa_supplicant_req_scan(wpa_s, 0, 0); diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c index a0b7479bf..ce736678b 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/wpa_supplicant/dbus/dbus_new_handlers.c @@ -1455,6 +1455,7 @@ DBusMessage * wpas_dbus_handler_reassociate(DBusMessage *message, struct wpa_supplicant *wpa_s) { if (wpa_s->current_ssid != NULL) { + wpa_s->extra_blacklist_count = 0; wpa_s->normal_scans = 0; wpa_supplicant_reinit_autoscan(wpa_s); wpa_s->disconnected = 0; diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index a5bd58ae5..901057e9f 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -665,6 +665,7 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, ssid && ssid->id_str ? ssid->id_str : ""); #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ wpas_clear_temp_disabled(wpa_s, ssid, 1); + wpa_s->extra_blacklist_count = 0; wpa_s->new_connection = 0; wpa_s->reassociated_connection = 1; wpa_drv_set_operstate(wpa_s, 1); @@ -3446,6 +3447,12 @@ void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid) } } + /* + * Add previous failure count in case the temporary blacklist was + * cleared due to no other BSSes being available. + */ + count += wpa_s->extra_blacklist_count; + switch (count) { case 1: timeout = 100; @@ -3456,10 +3463,17 @@ void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid) case 3: timeout = 1000; break; - default: + case 4: timeout = 5000; + break; + default: + timeout = 10000; + break; } + wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d " + "ms", count, timeout); + /* * TODO: if more than one possible AP is available in scan results, * could try the other ones before requesting a new scan. diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 071944d2b..c10bcbf73 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -397,6 +397,18 @@ struct wpa_supplicant { struct wpa_blacklist *blacklist; + /** + * extra_blacklist_count - Sum of blacklist counts after last connection + * + * This variable is used to maintain a count of temporary blacklisting + * failures (maximum number for any BSS) over blacklist clear + * operations. This is needed for figuring out whether there has been + * failures prior to the last blacklist clear operation which happens + * whenever no other not-blacklisted BSS candidates are available. This + * gets cleared whenever a connection has been established successfully. + */ + int extra_blacklist_count; + /** * scan_req - Type of the scan request */