[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