From 5ac977758d3535e91160ff210f3e8a578031029d Mon Sep 17 00:00:00 2001 From: Matthew Wang Date: Fri, 5 Mar 2021 17:43:44 -0800 Subject: [PATCH] Reject authentication start during explicit roam requests The roam D-Bus and ROAM control itnerface commands flip the reassociate bit before calling wpa_supplicant_connect(). wpa_supplicant connect eventually aborts ongoing scans (if any), which causes scan results to be reported. Since the reassociate bit is set, this will trigger a connection attempt based on the aborted scan's scan results and cancel the initial connetion request. This often causes wpa_supplicant to reassociate to the same AP it is currently associated to instead of the explicitly requested roaming target. Add a roam_in_progress flag to indicate that we're currently attempting to roam via an explicitly request to a specific BSS so that we don't initiate another connection attempt based on the possibly received scan results from a scan that was in progress at the time the roam command was received. Signed-off-by: Matthew Wang --- wpa_supplicant/ctrl_iface.c | 10 ++++++++++ wpa_supplicant/dbus/dbus_new_handlers.c | 10 ++++++++++ wpa_supplicant/sme.c | 7 +++++++ wpa_supplicant/wpa_supplicant_i.h | 1 + 4 files changed, 28 insertions(+) diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 0d4c2bc8f..7fc7e7d69 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -5656,6 +5656,7 @@ static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s, u8 bssid[ETH_ALEN]; struct wpa_bss *bss; struct wpa_ssid *ssid = wpa_s->current_ssid; + struct wpa_radio_work *already_connecting; if (hwaddr_aton(addr, bssid)) { wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid " @@ -5683,9 +5684,18 @@ static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s, * allow roaming to other networks */ + already_connecting = radio_work_pending(wpa_s, "sme-connect"); wpa_s->reassociate = 1; wpa_supplicant_connect(wpa_s, bss, ssid); + /* + * Indicate that an explicitly requested roam is in progress so scan + * results that come in before the 'sme-connect' radio work gets + * executed do not override the original connection attempt. + */ + if (!already_connecting && radio_work_pending(wpa_s, "sme-connect")) + wpa_s->roam_in_progress = true; + return 0; #endif /* CONFIG_NO_SCAN_PROCESSING */ } diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c index 7d20f2123..db9f30c9a 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/wpa_supplicant/dbus/dbus_new_handlers.c @@ -1979,6 +1979,7 @@ DBusMessage * wpas_dbus_handler_roam(DBusMessage *message, struct wpa_bss *bss; struct wpa_ssid *ssid = wpa_s->current_ssid; char *addr; + struct wpa_radio_work *already_connecting; if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &addr, DBUS_TYPE_INVALID)) @@ -2002,9 +2003,18 @@ DBusMessage * wpas_dbus_handler_roam(DBusMessage *message, message, "Target BSS not found"); } + already_connecting = radio_work_pending(wpa_s, "sme-connect"); wpa_s->reassociate = 1; wpa_supplicant_connect(wpa_s, bss, ssid); + /* + * Indicate that an explicitly requested roam is in progress so scan + * results that come in before the 'sme-connect' radio work gets + * executed do not override the original connection attempt. + */ + if (!already_connecting && radio_work_pending(wpa_s, "sme-connect")) + wpa_s->roam_in_progress = true; + return NULL; #endif /* CONFIG_NO_SCAN_PROCESSING */ } diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index 522c8297f..dde80863a 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -941,6 +941,8 @@ static void sme_auth_start_cb(struct wpa_radio_work *work, int deinit) struct wpa_connect_work *cwork = work->ctx; struct wpa_supplicant *wpa_s = work->wpa_s; + wpa_s->roam_in_progress = false; + if (deinit) { if (work->started) wpa_s->connect_work = NULL; @@ -981,6 +983,11 @@ void sme_authenticate(struct wpa_supplicant *wpa_s, return; } + if (wpa_s->roam_in_progress) { + wpa_dbg(wpa_s, MSG_DEBUG, + "SME: Reject sme_authenticate() in favor of explicit roam request"); + return; + } if (radio_work_pending(wpa_s, "sme-connect")) { /* * The previous sme-connect work might no longer be valid due to diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 7d14b627d..b6c339ab7 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -621,6 +621,7 @@ struct wpa_supplicant { u8 pending_bssid[ETH_ALEN]; /* If wpa_state == WPA_ASSOCIATING, this * field contains the target BSSID. */ int reassociate; /* reassociation requested */ + bool roam_in_progress; /* roam in progress */ unsigned int reassoc_same_bss:1; /* reassociating to the same BSS */ unsigned int reassoc_same_ess:1; /* reassociating to the same ESS */ int disconnected; /* all connections disabled; i.e., do no reassociate