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

Nils Rottgardt n.rottgardt at gmail.com
Sun Aug 2 13:23:05 PDT 2026


Hi,

a small ping to this patch. If there is something missing let me know. 
It is necessary to allow the controller to handle station responses well.

Regards,

Nils

Am 09.06.2026 um 23:15 schrieb Nils Hendrik Rottgardt:
> 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);



More information about the Hostap mailing list