[PATCH] WNM: Add API for Wi‑Fi controller to cancel planned disassociation

Nils Hendrik Rottgardt n.rottgardt at gmail.com
Tue Jun 9 14:15:29 PDT 2026


sta_info: Move PMKSA cache deletion from the preparation step to the disassociation timer.
This allows a planned disassociation to be cleanly cancelled.

wnm_ap: Add an API for Wi‑Fi controllers such as Usteer.
Currently, a STA is disassociated in ieee802_11_rx_bss_trans_mgmt_resp even when it responds with a valid status code.
To support scenarios between roaming without disassociation (soft) and roaming with imminent disassociation (hard), a controller must be able to stop a forced disassociation.
This behaviour is aligned with IEEE specifications. Since the decision logic can be complex and infrastructure‑dependent, it should be handled by the controller.

Signed-off-by: Nils Hendrik Rottgardt <n.rottgardt at gmail.com>
---
 src/ap/sta_info.c |  8 +++++++-
 src/ap/wnm_ap.c   | 28 +++++++++++++++++++++-------
 src/ap/wnm_ap.h   |  2 ++
 3 files changed, 30 insertions(+), 8 deletions(-)

diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index 2bb7e1235..700eae8bb 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -741,8 +741,14 @@ skip_poll:
 		eloop_register_timeout(AP_DISASSOC_DELAY, 0, ap_handle_timer,
 				       hapd, sta);
 		break;
-	case STA_DISASSOC:
 	case STA_DISASSOC_FROM_CLI:
+		/*
+		 * Prevent STA from reconnecting using cached PMKSA to force
+		 * full authentication with the authentication server (which may
+		 * decide to reject the connection),
+		 */
+		wpa_auth_pmksa_remove(hapd->wpa_auth, sta->addr);
+	case STA_DISASSOC:
 		ap_sta_set_authorized(hapd, sta, 0);
 		sta->flags &= ~WLAN_STA_ASSOC;
 		hostapd_set_sta_flags(hapd, sta);
diff --git a/src/ap/wnm_ap.c b/src/ap/wnm_ap.c
index 90922cd85..f3a998236 100644
--- a/src/ap/wnm_ap.c
+++ b/src/ap/wnm_ap.c
@@ -882,13 +882,6 @@ static void set_disassoc_timer(struct hostapd_data *hapd, struct sta_info *sta,
 {
 	int timeout, beacon_int;
 
-	/*
-	 * Prevent STA from reconnecting using cached PMKSA to force
-	 * full authentication with the authentication server (which may
-	 * decide to reject the connection),
-	 */
-	wpa_auth_pmksa_remove(hapd->wpa_auth, sta->addr);
-
 	beacon_int = hapd->iconf->beacon_int;
 	if (beacon_int < 1)
 		beacon_int = 100; /* best guess */
@@ -905,6 +898,27 @@ static void set_disassoc_timer(struct hostapd_data *hapd, struct sta_info *sta,
 }
 
 
+int stop_disassoc_timer(struct hostapd_data *hapd,
+                             struct sta_info *sta)
+{
+	if (!hapd || !sta)
+		return -1;
+
+	if (sta->timeout_next == STA_DISASSOC_FROM_CLI) {
+		sta->timeout_next = STA_NULLFUNC;
+		eloop_cancel_timeout(ap_handle_timer, hapd, sta);
+		eloop_register_timeout(2, 0, ap_handle_timer, hapd, sta);
+		wpa_printf(MSG_DEBUG, "Disassociation timer for " MACSTR
+			   " stopped", MAC2STR(sta->addr));
+		return 0;
+	} else {
+		wpa_printf(MSG_DEBUG, "Disassociation timer for " MACSTR
+			   " is not active - next timeout: %d", MAC2STR(sta->addr), sta->timeout_next);
+		return -1;
+	}
+}
+
+
 int wnm_send_ess_disassoc_imminent(struct hostapd_data *hapd,
 				   struct sta_info *sta, const char *url,
 				   int disassoc_timer)
diff --git a/src/ap/wnm_ap.h b/src/ap/wnm_ap.h
index f86c6b2af..f21812dd2 100644
--- a/src/ap/wnm_ap.h
+++ b/src/ap/wnm_ap.h
@@ -23,6 +23,8 @@ int wnm_send_bss_tm_req(struct hostapd_data *hapd, struct sta_info *sta,
 			const u8 *bss_term_dur, u8 dialog_token,
 			const char *url, const u8 *nei_rep, size_t nei_rep_len,
 			const u8 *mbo_attrs, size_t mbo_len);
+int stop_disassoc_timer(struct hostapd_data *hapd,
+                             struct sta_info *sta);
 void ap_sta_reset_steer_flag_timer(void *eloop_ctx, void *timeout_ctx);
 int wnm_send_coloc_intf_req(struct hostapd_data *hapd, struct sta_info *sta,
 			    unsigned int auto_report, unsigned int timeout);
-- 
2.39.5




More information about the Hostap mailing list