diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index baa418b88..798e69476 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -4841,12 +4841,14 @@ static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv, return -1; } + drv->connect_reassoc = 0; if (params->prev_bssid) { wpa_printf(MSG_DEBUG, " * prev_bssid=" MACSTR, MAC2STR(params->prev_bssid)); if (nla_put(msg, NL80211_ATTR_PREV_BSSID, ETH_ALEN, params->prev_bssid)) return -1; + drv->connect_reassoc = 1; } return 0; diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h index 3f655698f..b0d2b6d74 100644 --- a/src/drivers/driver_nl80211.h +++ b/src/drivers/driver_nl80211.h @@ -151,6 +151,7 @@ struct wpa_driver_nl80211_data { unsigned int get_pref_freq_list:1; unsigned int set_prob_oper_freq:1; unsigned int scan_vendor_cmd_avail:1; + unsigned int connect_reassoc:1; u64 vendor_scan_cookie; u64 remain_on_chan_cookie; diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c index dae203a18..bd16edbdc 100644 --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -285,6 +285,8 @@ static void mlme_event_connect(struct wpa_driver_nl80211_data *drv, return; } + drv->connect_reassoc = 0; + status_code = status ? nla_get_u16(status) : WLAN_STATUS_SUCCESS; if (cmd == NL80211_CMD_CONNECT) { @@ -670,6 +672,24 @@ static void mlme_event_deauth_disassoc(struct wpa_driver_nl80211_data *drv, return; } + if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME) && + drv->connect_reassoc && drv->associated && + os_memcmp(bssid, drv->prev_bssid, ETH_ALEN) == 0 && + os_memcmp(bssid, drv->auth_attempt_bssid, ETH_ALEN) != 0) { + /* + * Avoid issues with some roaming cases where + * disconnection event for the old AP may show up after + * we have started connection with the new AP. + */ + wpa_printf(MSG_DEBUG, + "nl80211: Ignore deauth/disassoc event from old AP " + MACSTR + " when already connecting with " MACSTR, + MAC2STR(bssid), + MAC2STR(drv->auth_attempt_bssid)); + return; + } + if (drv->associated != 0 && os_memcmp(bssid, drv->bssid, ETH_ALEN) != 0 && os_memcmp(bssid, drv->auth_bssid, ETH_ALEN) != 0) {