[PATCH] wpa_supplicant: add option to suppress deauth on PMKSA expiry

Jason Huang Jason.Huang2 at infineon.com
Thu May 14 19:49:56 PDT 2026


From: Darren Li <Darren.Li at infineon.com>

Some certification-oriented test setups use very short PMKSA lifetime
(for example, dot11RSNAConfigPMKLifetime=1) to effectively disable PMKSA
caching behavior.

In this mode, PMKSA entry removal can trigger local deauthentication in
the supplicant PMKSA free path, which may cause repeated disconnect/reconnect
cycles and interfere with the intended test behavior.

Add a per-network configuration parameter, suppress_deauth_no_pmksa, to
allow suppressing deauthentication when PMKSA entries are removed.

Behavior by configuration:
- suppress_deauth_no_pmksa=0 (default): keep existing behavior
- suppress_deauth_no_pmksa=1: suppress deauthentication on PMKSA removal

This keeps default behavior unchanged while providing explicit control for
test scenarios that require short PMKSA lifetime operation.

Signed-off-by: Darren Li <Darren.Li at infineon.com>
Signed-off-by: Jason Huang <jason.huang2 at infineon.com>
---
 src/rsn_supp/wpa.c           | 5 ++++-
 src/rsn_supp/wpa.h           | 1 +
 src/rsn_supp/wpa_i.h         | 1 +
 wpa_supplicant/config.c      | 1 +
 wpa_supplicant/config_file.c | 1 +
 wpa_supplicant/config_ssid.h | 6 ++++++
 wpa_supplicant/wpas_glue.c   | 2 ++
 7 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index 2c5ed11c8..b42514db2 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -4393,7 +4393,9 @@ static void wpa_sm_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry,
 	if (deauth) {
 		sm->pmk_len = 0;
 		os_memset(sm->pmk, 0, sizeof(sm->pmk));
-		wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
+		if (!sm->suppress_deauth_no_pmksa) {
+			wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
+		}
 	}
 }
 
@@ -4808,6 +4810,7 @@ void wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config)
 		}
 #endif /* CONFIG_FILS */
 		sm->beacon_prot = config->beacon_prot;
+		sm->suppress_deauth_no_pmksa = config->suppress_deauth_no_pmksa;
 	} else {
 		sm->network_ctx = NULL;
 		sm->allowed_pairwise_cipher = 0;
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index d42a7c102..e61197051 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -172,6 +172,7 @@ struct rsn_supp_config {
 	const u8 *fils_cache_id;
 	int beacon_prot;
 	bool force_kdk_derivation;
+	int suppress_deauth_no_pmksa;
 };
 
 struct wpa_sm_link {
diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h
index fc99d2041..68e546350 100644
--- a/src/rsn_supp/wpa_i.h
+++ b/src/rsn_supp/wpa_i.h
@@ -257,6 +257,7 @@ struct wpa_sm {
 	int last_kck_eapol_key_ver;
 	u8 last_kck_aa[ETH_ALEN];
 	int last_eapol_key_ver;
+	int suppress_deauth_no_pmksa;
 };
 
 
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index e99036366..54e1df6f7 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -2959,6 +2959,7 @@ static const struct parse_data ssid_fields[] = {
 #ifdef CONFIG_PASN
 	{ FUNC(pasn_groups) },
 #endif /* CONFIG_PASN */
+	{ INT_RANGE(suppress_deauth_no_pmksa, 0, 1) },
 };
 
 #undef OFFSET
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 81d92b7dd..c7a7e8cdf 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -981,6 +981,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid,
 	INT(beacon_prot);
 	INT(transition_disable);
 	INT(sae_pk);
+	INT(suppress_deauth_no_pmksa);
 #ifdef CONFIG_HT_OVERRIDES
 	INT_DEF(disable_ht, DEFAULT_DISABLE_HT);
 	INT_DEF(disable_ht40, DEFAULT_DISABLE_HT40);
diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h
index 7c60d4e38..b796b2a49 100644
--- a/wpa_supplicant/config_ssid.h
+++ b/wpa_supplicant/config_ssid.h
@@ -1398,6 +1398,12 @@ struct wpa_ssid {
 	 */
 	int *pasn_groups;
 #endif /* CONFIG_PASN */
+	/**
+	 * suppress_deauth_no_pmksa - Whether deauth when PMKSA is empty
+	 * 0 = To deauthenticate if there is no PMKSA entry (default)
+	 * 1 = To suppress deauthenticate if there is no PMKSA entry
+	 */
+	int suppress_deauth_no_pmksa;
 };
 
 #endif /* CONFIG_SSID_H */
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index e57114503..d986b9423 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -1611,6 +1611,8 @@ void wpa_supplicant_rsn_supp_set_config(struct wpa_supplicant *wpa_s,
 		conf.force_kdk_derivation = wpa_s->conf->force_kdk_derivation;
 #endif /* CONFIG_TESTING_OPTIONS */
 #endif /* CONFIG_PASN */
+		conf.beacon_prot = ssid->beacon_prot;
+		conf.suppress_deauth_no_pmksa = ssid->suppress_deauth_no_pmksa;
 	}
 	wpa_sm_set_config(wpa_s->wpa, ssid ? &conf : NULL);
 }
-- 
2.25.1




More information about the Hostap mailing list