From 42d235477f2345003b76e4de1f397e21c2fa5b76 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 5 Nov 2012 16:42:28 +0200 Subject: [PATCH] Use wpa_drv_{disassociate,deauthenticate} while waiting for connection wpa_supplicant_{disassociate,deauthenticate}() need to inform the driver about decision to disconnect even if this happens during the time when the driver is still trying to complete association. During that time, wpa_s->bssid is not set, so the code in these functions needs to figure out the correct BSSID based on that field or wpa_s->pending_bssid. In addition, it is possible that the BSSID is not even known at wpa_supplicant at this point in time when using drivers that perform BSS selection internally. In those cases, the disconnect command needs to be sent to the driver without the BSSID. This fixes issues where the driver (or cfg80211 in particular) may be left in mismatching state with wpa_supplicant when disconnection (e.g., due to a ctrl_iface command) happens between connection request and association event. Signed-hostap: Jouni Malinen --- wpa_supplicant/wpa_supplicant.c | 56 ++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index f1efe6ba8..076d31301 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1694,14 +1694,38 @@ void wpa_supplicant_disassociate(struct wpa_supplicant *wpa_s, { u8 *addr = NULL; union wpa_event_data event; + int zero_addr = 0; - if (!is_zero_ether_addr(wpa_s->bssid)) { - wpa_drv_disassociate(wpa_s, wpa_s->bssid, reason_code); + wpa_dbg(wpa_s, MSG_DEBUG, "Request to disassociate - bssid=" MACSTR + " pending_bssid=" MACSTR " reason=%d state=%s", + MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid), + reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state)); + + if (!is_zero_ether_addr(wpa_s->bssid)) addr = wpa_s->bssid; + else if (!is_zero_ether_addr(wpa_s->pending_bssid) && + (wpa_s->wpa_state == WPA_AUTHENTICATING || + wpa_s->wpa_state == WPA_ASSOCIATING)) + addr = wpa_s->pending_bssid; + else if (wpa_s->wpa_state == WPA_ASSOCIATING) { + /* + * When using driver-based BSS selection, we may not know the + * BSSID with which we are currently trying to associate. We + * need to notify the driver of this disconnection even in such + * a case, so use the all zeros address here. + */ + addr = wpa_s->bssid; + zero_addr = 1; + } + + if (addr) { + wpa_drv_disassociate(wpa_s, addr, reason_code); os_memset(&event, 0, sizeof(event)); event.disassoc_info.reason_code = (u16) reason_code; event.disassoc_info.locally_generated = 1; wpa_supplicant_event(wpa_s, EVENT_DISASSOC, &event); + if (zero_addr) + addr = NULL; } wpa_supplicant_clear_connection(wpa_s, addr); @@ -1721,14 +1745,38 @@ void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s, { u8 *addr = NULL; union wpa_event_data event; + int zero_addr = 0; - if (!is_zero_ether_addr(wpa_s->bssid)) { - wpa_drv_deauthenticate(wpa_s, wpa_s->bssid, reason_code); + wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR + " pending_bssid=" MACSTR " reason=%d state=%s", + MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid), + reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state)); + + if (!is_zero_ether_addr(wpa_s->bssid)) addr = wpa_s->bssid; + else if (!is_zero_ether_addr(wpa_s->pending_bssid) && + (wpa_s->wpa_state == WPA_AUTHENTICATING || + wpa_s->wpa_state == WPA_ASSOCIATING)) + addr = wpa_s->pending_bssid; + else if (wpa_s->wpa_state == WPA_ASSOCIATING) { + /* + * When using driver-based BSS selection, we may not know the + * BSSID with which we are currently trying to associate. We + * need to notify the driver of this disconnection even in such + * a case, so use the all zeros address here. + */ + addr = wpa_s->bssid; + zero_addr = 1; + } + + if (addr) { + wpa_drv_deauthenticate(wpa_s, addr, reason_code); os_memset(&event, 0, sizeof(event)); event.deauth_info.reason_code = (u16) reason_code; event.deauth_info.locally_generated = 1; wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event); + if (zero_addr) + addr = NULL; } wpa_supplicant_clear_connection(wpa_s, addr);