diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 21c9ab288..b88071a58 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -2884,6 +2884,15 @@ static int hostapd_config_fill(struct hostapd_config *conf,
 		bss->wpa_gmk_rekey = atoi(pos);
 	} else if (os_strcmp(buf, "wpa_ptk_rekey") == 0) {
 		bss->wpa_ptk_rekey = atoi(pos);
+	} else if (os_strcmp(buf, "wpa_deny_ptk0_rekey") == 0) {
+		bss->wpa_deny_ptk0_rekey = atoi(pos);
+		if (bss->wpa_deny_ptk0_rekey < 0 ||
+		    bss->wpa_deny_ptk0_rekey > 2) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: Invalid wpa_deny_ptk0_rekey=%d; allowed range 0..2",
+				   line, bss->wpa_deny_ptk0_rekey);
+			return 1;
+		}
 	} else if (os_strcmp(buf, "wpa_group_update_count") == 0) {
 		char *endp;
 		unsigned long val = strtoul(pos, &endp, 0);
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index 263a04e8f..b61176717 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -903,6 +903,8 @@ eapol_key_index_workaround=0
 
 # EAP reauthentication period in seconds (default: 3600 seconds; 0 = disable
 # reauthentication).
+# Reauthentications may enforce a disconnect, check the related setting
+# "wpa_deny_ptk0_rekey" for details.
 #eap_reauth_period=3600
 
 # Use PAE group address (01:80:c2:00:00:03) instead of individual target
@@ -1607,8 +1609,38 @@ own_ip_addr=127.0.0.1
 
 # Maximum lifetime for PTK in seconds. This can be used to enforce rekeying of
 # PTK to mitigate some attacks against TKIP deficiencies.
+# Warning: PTK rekeying is buggy with many drivers/devices and the only secure
+# method to rekey the PTK without Extended Key ID support requires a disconnect.
+# Check the related setting "wpa_deny_ptk0_rekey" for details.
 #wpa_ptk_rekey=600
 
+# Workaround for PTK rekey issues
+#
+# Rekeying the PTK without using "Extended Key ID for Individually Addressed
+# Frames" can - depending on the cards/drivers - reduce both the security and
+# the stability of connections. Both ends can freeze the connection or even leak
+# the PTK by repeating MPDU's without encryption. To avoid the issues hostapd is
+# now by default replacing all PTK rekeys using only keyid 0 (PTK0 rekeys) with
+# disconnects.
+# This is a regression for setups able to rekey the PTK and actually do so.
+#
+# Eap reauthentication depends on replacing the PTK and is therefore just
+# another way to rekey the PTK and affected by the setting, too.
+#
+# Unfortunately there is no way to detect if a remote stations can safely rekey
+# the PTK and the default is therefore to replace all those rekeys with a
+# disconnect when not two keyids (Extended Key ID for Individually Addressed
+# Frames) are available for it.
+#
+# If you are sure your cards/drivers don't need the workaround the old behavior
+# can be restored by setting wpa_deny_ptk0_rekey = 0.
+#
+# Available options:
+# 0 = always rekey when configured/instructed (old behavior)
+# 1 = only rekey when the local driver is able to do it bug free
+# 2 = never allow PTK0 rekeys (default)
+# wpa_deny_ptk0_rekey = 2
+
 # The number of times EAPOL-Key Message 1/4 and Message 3/4 in the RSN 4-Way
 # Handshake are retried per 4-Way Handshake attempt.
 # (dot11RSNAConfigPairwiseUpdateCount)
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 68af3c1d1..98a7f6e26 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -64,6 +64,7 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
 
 	bss->wpa_group_rekey = 600;
 	bss->wpa_gmk_rekey = 86400;
+	bss->wpa_deny_ptk0_rekey = PTK0_REKEY_ALLOW_NEVER;
 	bss->wpa_group_update_count = 4;
 	bss->wpa_pairwise_update_count = 4;
 	bss->wpa_disable_eapol_key_retries =
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 7e4b9262c..0b4483ea1 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -368,6 +368,7 @@ struct hostapd_bss_config {
 	int wpa_strict_rekey;
 	int wpa_gmk_rekey;
 	int wpa_ptk_rekey;
+	int wpa_deny_ptk0_rekey;
 	u32 wpa_group_update_count;
 	u32 wpa_pairwise_update_count;
 	int wpa_disable_eapol_key_retries;
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index 6611b0e53..5c52f0f76 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -755,8 +755,17 @@ static void wpa_request_new_ptk(struct wpa_state_machine *sm)
 	if (sm == NULL)
 		return;
 
-	sm->PTKRequest = TRUE;
-	sm->PTK_valid = 0;
+	if (sm->wpa_auth->conf.wpa_deny_ptk0_rekey) {
+		wpa_printf(MSG_WARNING,
+			   "WPA: PTK0 rekey not allowed, disconnect " MACSTR,
+			   MAC2STR(sm->addr));
+		sm->Disconnect = TRUE;
+		/* Try to encourage the STA reconnect */
+		sm->disconnect_reason = WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA;
+	} else {
+		sm->PTKRequest = TRUE;
+		sm->PTK_valid = 0;
+	}
 }
 
 
@@ -1775,6 +1784,16 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event)
 			sm->Init = FALSE;
 			sm->AuthenticationRequest = TRUE;
 			break;
+		} else {
+			if (sm->wpa_auth->conf.wpa_deny_ptk0_rekey) {
+				wpa_printf(MSG_WARNING,
+					   "WPA: PTK0 rekey not allowed, disconnect "
+					   MACSTR, MAC2STR(sm->addr));
+				sm->Disconnect = TRUE;
+				/* Try to encourage the STA reconnect */
+				sm->disconnect_reason = WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA;
+				break;
+			}
 		}
 		if (sm->GUpdateStationKeys) {
 			/*
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index 933a4b8ed..0e44cbe0b 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -176,6 +176,7 @@ struct wpa_auth_config {
 	int wpa_strict_rekey;
 	int wpa_gmk_rekey;
 	int wpa_ptk_rekey;
+	int wpa_deny_ptk0_rekey;
 	u32 wpa_group_update_count;
 	u32 wpa_pairwise_update_count;
 	int wpa_disable_eapol_key_retries;
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index b655ae57b..951c7364b 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -1348,6 +1348,18 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
 		_conf.tx_status = 1;
 	if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_MLME)
 		_conf.ap_mlme = 1;
+
+	if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_WIRED) &&
+	    (hapd->conf->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER ||
+	     (hapd->conf->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK &&
+	      !(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) {
+		wpa_msg(hapd->msg_ctx, MSG_INFO, "Disable PTK0 rekey support");
+		_conf.wpa_deny_ptk0_rekey = 1;
+	} else {
+		wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "Support PTK0 rekey");
+		_conf.wpa_deny_ptk0_rekey = 0;
+	}
+
 	hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb, hapd);
 	if (hapd->wpa_auth == NULL) {
 		wpa_printf(MSG_ERROR, "WPA initialization failed.");
diff --git a/src/common/defs.h b/src/common/defs.h
index e2fa4b291..1cf027340 100644
--- a/src/common/defs.h
+++ b/src/common/defs.h
@@ -423,4 +423,10 @@ enum chan_width {
 	CHAN_WIDTH_UNKNOWN
 };
 
+enum ptk0_rekey_handling {
+	PTK0_REKEY_ALLOW_ALWAYS,
+	PTK0_REKEY_ALLOW_LOCAL_OK,
+	PTK0_REKEY_ALLOW_NEVER
+};
+
 #endif /* DEFS_H */
