Merge changes from topic "revert-26533062-Supplicant_merge_June24-CUATTSRBBR" into main

* changes:
  Revert "[wpa_supplicant] cumilative patch from commit 3a5d1a7e6"
  Revert "[wpa_supplicant] cumilative patch from commit 4b755c967"
diff --git a/hostapd/Android.bp b/hostapd/Android.bp
index 9bd5d04..8a7dacf 100644
--- a/hostapd/Android.bp
+++ b/hostapd/Android.bp
@@ -239,7 +239,6 @@
         "src/common/ieee802_11_common.c",
         "src/common/wpa_common.c",
         "src/common/hw_features_common.c",
-        "src/common/ptksa_cache.c",
         "src/eapol_auth/eapol_auth_sm.c",
         "src/eapol_auth/eapol_auth_dump.c",
         "src/ap/vlan_init.c",
@@ -331,7 +330,6 @@
         "src/ap/ap_list.c",
         "src/ap/comeback_token.c",
         "src/pasn/pasn_responder.c",
-        "src/pasn/pasn_common.c",
         "src/ap/ieee802_11.c",
         "src/ap/hw_features.c",
         "src/ap/dfs.c",
diff --git a/hostapd/Android.mk b/hostapd/Android.mk
index 227e88c..35ada83 100644
--- a/hostapd/Android.mk
+++ b/hostapd/Android.mk
@@ -170,7 +170,6 @@
 OBJS += src/common/ieee802_11_common.c
 OBJS += src/common/wpa_common.c
 OBJS += src/common/hw_features_common.c
-OBJS += src/common/ptksa_cache.c
 
 OBJS += src/eapol_auth/eapol_auth_sm.c
 
@@ -254,8 +253,6 @@
 OBJS += src/common/ocv.c
 endif
 
-NEED_AES_UNWRAP=y
-
 ifdef CONFIG_IEEE80211R
 L_CFLAGS += -DCONFIG_IEEE80211R -DCONFIG_IEEE80211R_AP
 OBJS += src/ap/wpa_auth_ft.c
@@ -602,12 +599,6 @@
 endif
 endif
 
-ifdef CONFIG_NAN_USD
-OBJS += src/common/nan_de.c
-OBJS += src/ap/nan_usd_ap.c
-L_CFLAGS += -DCONFIG_NAN_USD
-endif
-
 ifdef CONFIG_PASN
 L_CFLAGS += -DCONFIG_PASN
 L_CFLAGS += -DCONFIG_PTKSA_CACHE
@@ -615,6 +606,7 @@
 NEED_HMAC_SHA384_KDF=y
 NEED_SHA256=y
 NEED_SHA384=y
+OBJS += src/common/ptksa_cache.c
 endif
 
 ifdef CONFIG_EAP_IKEV2
@@ -667,11 +659,6 @@
 OBJS += src/eap_common/chap.c
 endif
 
-ifdef CONFIG_RADIUS_TLS
-TLS_FUNCS=y
-L_CFLAGS += -DCONFIG_RADIUS_TLS
-endif
-
 ifdef TLS_FUNCS
 NEED_DES=y
 # Shared TLS functions (needed for EAP_TLS, EAP_PEAP, and EAP_TTLS)
@@ -1071,7 +1058,6 @@
 OBJS += src/ap/ap_list.c
 OBJS += src/ap/comeback_token.c
 OBJS += src/pasn/pasn_responder.c
-OBJS += src/pasn/pasn_common.c
 OBJS += src/ap/ieee802_11.c
 OBJS += src/ap/hw_features.c
 OBJS += src/ap/dfs.c
diff --git a/hostapd/Makefile b/hostapd/Makefile
index 489922c..a2adc85 100644
--- a/hostapd/Makefile
+++ b/hostapd/Makefile
@@ -84,7 +84,6 @@
 OBJS += ../src/ap/bss_load.o
 OBJS += ../src/ap/neighbor_db.o
 OBJS += ../src/ap/rrm.o
-OBJS += ../src/common/ptksa_cache.o
 
 OBJS_c = hostapd_cli.o
 OBJS_c += ../src/common/wpa_ctrl.o
@@ -168,7 +167,7 @@
 
 
 ifdef CONFIG_CODE_COVERAGE
-CFLAGS += -O0 -fprofile-arcs -ftest-coverage -U_FORTIFY_SOURCE
+CFLAGS += -O0 -fprofile-arcs -ftest-coverage
 LIBS += -lgcov
 LIBS_c += -lgcov
 LIBS_h += -lgcov
@@ -277,8 +276,6 @@
 OBJS += ../src/common/ocv.o
 endif
 
-NEED_AES_UNWRAP=y
-
 ifdef CONFIG_IEEE80211R
 CFLAGS += -DCONFIG_IEEE80211R -DCONFIG_IEEE80211R_AP
 OBJS += ../src/ap/wpa_auth_ft.o
@@ -612,12 +609,6 @@
 endif
 endif
 
-ifdef CONFIG_NAN_USD
-OBJS += ../src/common/nan_de.o
-OBJS += ../src/ap/nan_usd_ap.o
-CFLAGS += -DCONFIG_NAN_USD
-endif
-
 ifdef CONFIG_PASN
 CFLAGS += -DCONFIG_PASN
 CFLAGS += -DCONFIG_PTKSA_CACHE
@@ -625,6 +616,7 @@
 NEED_HMAC_SHA384_KDF=y
 NEED_SHA256=y
 NEED_SHA384=y
+OBJS += ../src/common/ptksa_cache.o
 endif
 
 ifdef CONFIG_EAP_IKEV2
@@ -686,11 +678,6 @@
 OBJS += ../src/eap_common/chap.o
 endif
 
-ifdef CONFIG_RADIUS_TLS
-TLS_FUNCS=y
-CFLAGS += -DCONFIG_RADIUS_TLS
-endif
-
 ifdef TLS_FUNCS
 NEED_DES=y
 # Shared TLS functions (needed for EAP_TLS, EAP_PEAP, and EAP_TTLS)
@@ -1201,7 +1188,6 @@
 OBJS += ../src/ap/ap_list.o
 OBJS += ../src/ap/comeback_token.o
 OBJS += ../src/pasn/pasn_responder.o
-OBJS += ../src/pasn/pasn_common.o
 OBJS += ../src/ap/ieee802_11.o
 OBJS += ../src/ap/hw_features.o
 OBJS += ../src/ap/dfs.o
diff --git a/hostapd/android.config b/hostapd/android.config
index 4040d41..1c4dab2 100644
--- a/hostapd/android.config
+++ b/hostapd/android.config
@@ -126,9 +126,6 @@
 # Build IPv6 support for RADIUS operations
 CONFIG_IPV6=y
 
-# Include support fo RADIUS/TLS into the RADIUS client
-#CONFIG_RADIUS_TLS=y
-
 # IEEE Std 802.11r-2008 (Fast BSS Transition)
 #CONFIG_IEEE80211R=y
 
@@ -267,6 +264,3 @@
 # certain percentage of probe requests or auth/(re)assoc frames.
 # Each test case requires a flag set in hostapd.conf or through hostapd_cli
 #CONFIG_TESTING_OPTIONS=y
-
-# Wi-Fi Aware unsynchronized service discovery (NAN USD)
-#CONFIG_NAN_USD=y
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 76e9249..bfb152e 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -1,6 +1,6 @@
 /*
  * hostapd / Configuration file parser
- * Copyright (c) 2003-2024, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2018, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -1020,78 +1020,6 @@
 
 	return 0;
 }
-
-
-int hostapd_config_read_rxkh_file(struct hostapd_bss_config *conf,
-				  const char *fname)
-{
-	FILE *f;
-	char buf[256], *pos;
-	int line = 0, errors = 0;
-
-	if (!fname)
-		return 0;
-
-	f = fopen(fname, "r");
-	if (!f) {
-		wpa_printf(MSG_ERROR, "rxkh file '%s' not found.", fname);
-		return -1;
-	}
-
-	while (fgets(buf, sizeof(buf), f)) {
-		line++;
-
-		if (buf[0] == '#')
-			continue;
-		pos = buf;
-		while (*pos != '\0') {
-			if (*pos == '\n') {
-				*pos = '\0';
-				break;
-			}
-			pos++;
-		}
-		if (buf[0] == '\0')
-			continue;
-
-		pos = os_strchr(buf, '=');
-		if (!pos) {
-			wpa_printf(MSG_ERROR, "Line %d: Invalid line '%s'",
-				   line, buf);
-			errors++;
-			continue;
-		}
-		*pos = '\0';
-		pos++;
-
-		if (os_strcmp(buf, "r0kh") == 0) {
-			if (add_r0kh(conf, pos) < 0) {
-				wpa_printf(MSG_ERROR,
-					   "Line %d: Invalid r0kh '%s'",
-					   line, pos);
-				errors++;
-			}
-		} else if (os_strcmp(buf, "r1kh") == 0) {
-			if (add_r1kh(conf, pos) < 0) {
-				wpa_printf(MSG_ERROR,
-					   "Line %d: Invalid r1kh '%s'",
-					   line, pos);
-				errors++;
-			}
-		}
-	}
-
-	fclose(f);
-
-	if (errors) {
-		wpa_printf(MSG_ERROR,
-			   "%d errors in configuring RxKHs from '%s'",
-			   errors, fname);
-		return -1;
-	}
-	return 0;
-}
-
 #endif /* CONFIG_IEEE80211R_AP */
 
 
@@ -1678,8 +1606,6 @@
 	return 0;
 }
 
-#endif /* CONFIG_INTERWORKING */
-
 
 static int parse_qos_map_set(struct hostapd_bss_config *bss,
 			     char *buf, int line)
@@ -1721,6 +1647,8 @@
 	return 0;
 }
 
+#endif /* CONFIG_INTERWORKING */
+
 
 #ifdef CONFIG_HS20
 static int hs20_parse_conn_capab(struct hostapd_bss_config *bss, char *buf,
@@ -2231,7 +2159,6 @@
 
 
 #ifdef CONFIG_SAE
-
 static int parse_sae_password(struct hostapd_bss_config *bss, const char *val)
 {
 	struct sae_password_entry *pw;
@@ -2335,40 +2262,6 @@
 	os_free(pw);
 	return -1;
 }
-
-
-static int parse_sae_password_file(struct hostapd_bss_config *bss,
-				   const char *fname)
-{
-	FILE *f;
-	char buf[500], *pos;
-	unsigned int line = 0;
-
-	f = fopen(fname, "r");
-	if (!f) {
-		wpa_printf(MSG_ERROR, "sae_password_file '%s' not found.",
-			   fname);
-		return -1;
-	}
-
-	while (fgets(buf, sizeof(buf), f)) {
-		pos = os_strchr(buf, '\n');
-		if (pos)
-			*pos = '\0';
-		line++;
-		if (parse_sae_password(bss, buf)) {
-			wpa_printf(MSG_ERROR,
-				   "Invalid SAE password at line %d in '%s'",
-				   line, fname);
-			fclose(f);
-			return -1;
-		}
-	}
-
-	fclose(f);
-	return 0;
-}
-
 #endif /* CONFIG_SAE */
 
 
@@ -2418,24 +2311,6 @@
 }
 
 
-#ifdef CONFIG_IEEE80211BE
-static int get_u16(const char *pos, int line, u16 *ret_val)
-{
-	char *end;
-	long int val = strtol(pos, &end, 0);
-
-	if (*end || val < 0 || val > 0xffff) {
-		wpa_printf(MSG_ERROR, "Line %d: Invalid value '%s'",
-			   line, pos);
-		return -1;
-	}
-
-	*ret_val = val;
-	return 0;
-}
-#endif /* CONFIG_IEEE80211BE */
-
-
 static int hostapd_config_fill(struct hostapd_config *conf,
 			       struct hostapd_bss_config *bss,
 			       const char *buf, char *pos, int line)
@@ -2869,37 +2744,6 @@
 		os_free(bss->radius->auth_server->shared_secret);
 		bss->radius->auth_server->shared_secret = (u8 *) os_strdup(pos);
 		bss->radius->auth_server->shared_secret_len = len;
-	} else if (bss->radius->auth_server &&
-		   os_strcmp(buf, "auth_server_type") == 0) {
-		if (os_strcmp(pos, "UDP") == 0) {
-			bss->radius->auth_server->tls = false;
-#ifdef CONFIG_RADIUS_TLS
-		} else if (os_strcmp(pos, "TLS") == 0) {
-			bss->radius->auth_server->tls = true;
-#endif /* CONFIG_RADIUS_TLS */
-		} else {
-			wpa_printf(MSG_ERROR, "Line %d: unsupported RADIUS type '%s'",
-				   line, pos);
-			return 1;
-		}
-#ifdef CONFIG_RADIUS_TLS
-	} else if (bss->radius->auth_server &&
-		   os_strcmp(buf, "auth_server_ca_cert") == 0) {
-		os_free(bss->radius->auth_server->ca_cert);
-		bss->radius->auth_server->ca_cert = os_strdup(pos);
-	} else if (bss->radius->auth_server &&
-		   os_strcmp(buf, "auth_server_client_cert") == 0) {
-		os_free(bss->radius->auth_server->client_cert);
-		bss->radius->auth_server->client_cert = os_strdup(pos);
-	} else if (bss->radius->auth_server &&
-		   os_strcmp(buf, "auth_server_private_key") == 0) {
-		os_free(bss->radius->auth_server->private_key);
-		bss->radius->auth_server->private_key = os_strdup(pos);
-	} else if (bss->radius->auth_server &&
-		   os_strcmp(buf, "auth_server_private_key_passwd") == 0) {
-		os_free(bss->radius->auth_server->private_key_passwd);
-		bss->radius->auth_server->private_key_passwd = os_strdup(pos);
-#endif /* CONFIG_RADIUS_TLS */
 	} else if (os_strcmp(buf, "acct_server_addr") == 0) {
 		if (hostapd_config_read_radius_addr(
 			    &bss->radius->acct_servers,
@@ -2934,37 +2778,6 @@
 		os_free(bss->radius->acct_server->shared_secret);
 		bss->radius->acct_server->shared_secret = (u8 *) os_strdup(pos);
 		bss->radius->acct_server->shared_secret_len = len;
-	} else if (bss->radius->acct_server &&
-		   os_strcmp(buf, "acct_server_type") == 0) {
-		if (os_strcmp(pos, "UDP") == 0) {
-			bss->radius->acct_server->tls = false;
-#ifdef CONFIG_RADIUS_TLS
-		} else if (os_strcmp(pos, "TLS") == 0) {
-			bss->radius->acct_server->tls = true;
-#endif /* CONFIG_RADIUS_TLS */
-		} else {
-			wpa_printf(MSG_ERROR, "Line %d: unsupported RADIUS type '%s'",
-				   line, pos);
-			return 1;
-		}
-#ifdef CONFIG_RADIUS_TLS
-	} else if (bss->radius->acct_server &&
-		   os_strcmp(buf, "acct_server_ca_cert") == 0) {
-		os_free(bss->radius->acct_server->ca_cert);
-		bss->radius->acct_server->ca_cert = os_strdup(pos);
-	} else if (bss->radius->acct_server &&
-		   os_strcmp(buf, "acct_server_client_cert") == 0) {
-		os_free(bss->radius->acct_server->client_cert);
-		bss->radius->acct_server->client_cert = os_strdup(pos);
-	} else if (bss->radius->acct_server &&
-		   os_strcmp(buf, "acct_server_private_key") == 0) {
-		os_free(bss->radius->acct_server->private_key);
-		bss->radius->acct_server->private_key = os_strdup(pos);
-	} else if (bss->radius->acct_server &&
-		   os_strcmp(buf, "acct_server_private_key_passwd") == 0) {
-		os_free(bss->radius->acct_server->private_key_passwd);
-		bss->radius->acct_server->private_key_passwd = os_strdup(pos);
-#endif /* CONFIG_RADIUS_TLS */
 	} else if (os_strcmp(buf, "radius_retry_primary_interval") == 0) {
 		bss->radius->retry_primary_interval = atoi(pos);
 	} else if (os_strcmp(buf, "radius_acct_interim_interval") == 0) {
@@ -3234,21 +3047,6 @@
 				   line, pos);
 			return 1;
 		}
-	} else if (os_strcmp(buf, "rxkh_file") == 0) {
-		os_free(bss->rxkh_file);
-		bss->rxkh_file = os_strdup(pos);
-		if (!bss->rxkh_file) {
-			wpa_printf(MSG_ERROR, "Line %d: allocation failed",
-				   line);
-			return 1;
-		}
-		if (hostapd_config_read_rxkh_file(bss, pos)) {
-			wpa_printf(MSG_DEBUG,
-				   "Line %d: failed to read rxkh_file '%s'",
-				   line, pos);
-			/* Allow the file to be created later and read into
-			 * already operating AP context. */
-		}
 	} else if (os_strcmp(buf, "pmk_r1_push") == 0) {
 		bss->pmk_r1_push = atoi(pos);
 	} else if (os_strcmp(buf, "ft_over_ds") == 0) {
@@ -3826,18 +3624,6 @@
 		}
 	} else if (os_strcmp(buf, "he_6ghz_reg_pwr_type") == 0) {
 		conf->he_6ghz_reg_pwr_type = atoi(pos);
-		if (conf->he_6ghz_reg_pwr_type > HE_REG_INFO_6GHZ_AP_TYPE_MAX) {
-			wpa_printf(MSG_ERROR,
-				   "Line %d: invalid he_6ghz_reg_pwr_type value",
-				   line);
-			return 1;
-		}
-	} else if (os_strcmp(buf, "reg_def_cli_eirp_psd") == 0) {
-		conf->reg_def_cli_eirp_psd = atoi(pos);
-	} else if (os_strcmp(buf, "reg_sub_cli_eirp_psd") == 0) {
-		conf->reg_sub_cli_eirp_psd = atoi(pos);
-	} else if (os_strcmp(buf, "reg_def_cli_eirp") == 0) {
-		conf->reg_def_cli_eirp = atoi(pos);
 	} else if (os_strcmp(buf, "he_oper_chwidth") == 0) {
 		conf->he_oper_chwidth = atoi(pos);
 	} else if (os_strcmp(buf, "he_oper_centr_freq_seg0_idx") == 0) {
@@ -4258,10 +4044,10 @@
 		bss->gas_frag_limit = val;
 	} else if (os_strcmp(buf, "gas_comeback_delay") == 0) {
 		bss->gas_comeback_delay = atoi(pos);
-#endif /* CONFIG_INTERWORKING */
 	} else if (os_strcmp(buf, "qos_map_set") == 0) {
 		if (parse_qos_map_set(bss, pos, line) < 0)
 			return 1;
+#endif /* CONFIG_INTERWORKING */
 #ifdef CONFIG_RADIUS_TEST
 	} else if (os_strcmp(buf, "dump_msk_file") == 0) {
 		os_free(bss->dump_msk_file);
@@ -4510,16 +4296,6 @@
 		bss->eap_skip_prot_success = atoi(pos);
 	} else if (os_strcmp(buf, "delay_eapol_tx") == 0) {
 		conf->delay_eapol_tx = atoi(pos);
-	} else if (os_strcmp(buf, "eapol_m1_elements") == 0) {
-		if (parse_wpabuf_hex(line, buf, &bss->eapol_m1_elements, pos))
-			return 1;
-	} else if (os_strcmp(buf, "eapol_m3_elements") == 0) {
-		if (parse_wpabuf_hex(line, buf, &bss->eapol_m3_elements, pos))
-			return 1;
-	} else if (os_strcmp(buf, "eapol_m3_no_encrypt") == 0) {
-		bss->eapol_m3_no_encrypt = atoi(pos);
-	} else if (os_strcmp(buf, "test_assoc_comeback_type") == 0) {
-		bss->test_assoc_comeback_type = atoi(pos);
 #endif /* CONFIG_TESTING_OPTIONS */
 #ifdef CONFIG_SAE
 	} else if (os_strcmp(buf, "sae_password") == 0) {
@@ -4528,13 +4304,6 @@
 				   line);
 			return 1;
 		}
-	} else if (os_strcmp(buf, "sae_password_file") == 0) {
-		if (parse_sae_password_file(bss, pos) < 0) {
-			wpa_printf(MSG_ERROR,
-				   "Line %d: Invalid sae_password in file",
-				   line);
-			return 1;
-		}
 #endif /* CONFIG_SAE */
 	} else if (os_strcmp(buf, "vendor_elements") == 0) {
 		if (parse_wpabuf_hex(line, buf, &bss->vendor_elements, pos))
@@ -4666,10 +4435,6 @@
 				WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE |
 				WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE |
 				WLAN_RRM_CAPS_BEACON_REPORT_TABLE;
-	} else if (os_strcmp(buf, "rrm_link_measurement_report") == 0) {
-		if (atoi(pos))
-			bss->radio_measurements[0] |=
-				WLAN_RRM_CAPS_LINK_MEASUREMENT;
 	} else if (os_strcmp(buf, "gas_address3") == 0) {
 		bss->gas_address3 = atoi(pos);
 	} else if (os_strcmp(buf, "stationary_ap") == 0) {
@@ -4810,36 +4575,6 @@
 		}
 
 		bss->multi_ap = val;
-	} else if (os_strcmp(buf, "multi_ap_profile") == 0) {
-		int val = atoi(pos);
-
-		if (val < MULTI_AP_PROFILE_1 || val > MULTI_AP_PROFILE_MAX) {
-			wpa_printf(MSG_ERROR,
-				   "Line %d: Invalid multi_ap_profile '%s'",
-				   line, buf);
-			return -1;
-		}
-		bss->multi_ap_profile = val;
-	} else if (os_strcmp(buf, "multi_ap_client_disallow") == 0) {
-		int val = atoi(pos);
-
-		if (val < 0 || val > 3) {
-			wpa_printf(MSG_ERROR,
-				   "Line %d: Invalid multi_ap_client_allow '%s'",
-				   line, buf);
-			return -1;
-		}
-		bss->multi_ap_client_disallow = val;
-	} else if (os_strcmp(buf, "multi_ap_vlanid") == 0) {
-		int val = atoi(pos);
-
-		if (val < 0 || val > MAX_VLAN_ID) {
-			wpa_printf(MSG_ERROR,
-				   "Line %d: Invalid multi_ap_vlan_id '%s'",
-				   line, buf);
-			return -1;
-		}
-		bss->multi_ap_vlanid = val;
 	} else if (os_strcmp(buf, "rssi_reject_assoc_rssi") == 0) {
 		conf->rssi_reject_assoc_rssi = atoi(pos);
 	} else if (os_strcmp(buf, "rssi_reject_assoc_timeout") == 0) {
@@ -5035,11 +4770,8 @@
 		conf->eht_phy_capab.su_beamformee = atoi(pos);
 	} else if (os_strcmp(buf, "eht_mu_beamformer") == 0) {
 		conf->eht_phy_capab.mu_beamformer = atoi(pos);
-	} else if (os_strcmp(buf, "eht_default_pe_duration") == 0) {
-		conf->eht_default_pe_duration = atoi(pos);
 	} else if (os_strcmp(buf, "punct_bitmap") == 0) {
-		if (get_u16(pos, line, &conf->punct_bitmap))
-			return 1;
+		conf->punct_bitmap = atoi(pos);
 	} else if (os_strcmp(buf, "punct_acs_threshold") == 0) {
 		int val = atoi(pos);
 
@@ -5052,21 +4784,14 @@
 		conf->punct_acs_threshold = val;
 	} else if (os_strcmp(buf, "mld_ap") == 0) {
 		bss->mld_ap = !!atoi(pos);
+	} else if (os_strcmp(buf, "mld_id") == 0) {
+		bss->mld_id = atoi(pos);
 	} else if (os_strcmp(buf, "mld_addr") == 0) {
 		if (hwaddr_aton(pos, bss->mld_addr)) {
 			wpa_printf(MSG_ERROR, "Line %d: Invalid mld_addr",
 				   line);
 			return 1;
 		}
-	} else if (os_strcmp(buf, "eht_bw320_offset") == 0) {
-		conf->eht_bw320_offset = atoi(pos);
-#ifdef CONFIG_TESTING_OPTIONS
-	} else if (os_strcmp(buf, "eht_oper_puncturing_override") == 0) {
-		if (get_u16(pos, line, &bss->eht_oper_puncturing_override))
-			return 1;
-	} else if (os_strcmp(buf, "mld_indicate_disabled") == 0) {
-		bss->mld_indicate_disabled = atoi(pos);
-#endif /* CONFIG_TESTING_OPTIONS */
 #endif /* CONFIG_IEEE80211BE */
 	} else {
 		wpa_printf(MSG_ERROR,
diff --git a/hostapd/config_file.h b/hostapd/config_file.h
index 9ef6ac8..c98bdb6 100644
--- a/hostapd/config_file.h
+++ b/hostapd/config_file.h
@@ -10,8 +10,6 @@
 #define CONFIG_FILE_H
 
 struct hostapd_config * hostapd_config_read(const char *fname);
-int hostapd_config_read_rxkh_file(struct hostapd_bss_config *conf,
-				  const char *fname);
 int hostapd_set_iface(struct hostapd_config *conf,
 		      struct hostapd_bss_config *bss, const char *field,
 		      char *value);
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index d07567d..57c9997 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -39,7 +39,6 @@
 #include "common/wpa_ctrl.h"
 #include "common/ptksa_cache.h"
 #include "common/hw_features_common.h"
-#include "common/nan_de.h"
 #include "crypto/tls.h"
 #include "drivers/driver.h"
 #include "eapol_auth/eapol_auth_sm.h"
@@ -64,7 +63,6 @@
 #include "ap/rrm.h"
 #include "ap/dpp_hostapd.h"
 #include "ap/dfs.h"
-#include "ap/nan_usd_ap.h"
 #include "wps/wps_defs.h"
 #include "wps/wps.h"
 #include "fst/fst_ctrl_iface.h"
@@ -1309,8 +1307,6 @@
 			hostapd_disassoc_deny_mac(hapd);
 		} else if (os_strcasecmp(cmd, "accept_mac_file") == 0) {
 			hostapd_disassoc_accept_mac(hapd);
-		} else if (os_strcasecmp(cmd, "ssid") == 0) {
-			hostapd_neighbor_sync_own_report(hapd);
 		} else if (os_strncmp(cmd, "wme_ac_", 7) == 0 ||
 			   os_strncmp(cmd, "wmm_ac_", 7) == 0) {
 			hapd->parameter_set_count++;
@@ -1439,7 +1435,7 @@
 		pmk_match = PMK_LEN == pmk_len &&
 			os_memcmp(psk->psk, pmk, pmk_len) == 0;
 		sta_match = psk->group == 0 &&
-			ether_addr_equal(sta->addr, psk->addr);
+			os_memcmp(sta->addr, psk->addr, ETH_ALEN) == 0;
 		bss_match = psk->group == 1;
 
 		if (pmk_match && (sta_match || bss_match))
@@ -1478,79 +1474,6 @@
 }
 
 
-#ifdef CONFIG_IEEE80211R_AP
-
-static int hostapd_ctrl_iface_get_rxkhs(struct hostapd_data *hapd,
-					char *buf, size_t buflen)
-{
-	int ret, start_pos;
-	char *pos, *end;
-	struct ft_remote_r0kh *r0kh;
-	struct ft_remote_r1kh *r1kh;
-	struct hostapd_bss_config *conf = hapd->conf;
-
-	pos = buf;
-	end = buf + buflen;
-
-	for (r0kh = conf->r0kh_list; r0kh; r0kh=r0kh->next) {
-		start_pos = pos - buf;
-		ret = os_snprintf(pos, end - pos, "r0kh=" MACSTR " ",
-				  MAC2STR(r0kh->addr));
-		if (os_snprintf_error(end - pos, ret))
-			return start_pos;
-		pos += ret;
-		if (r0kh->id_len + 1 >= (size_t) (end - pos))
-			return start_pos;
-		os_memcpy(pos, r0kh->id, r0kh->id_len);
-		pos += r0kh->id_len;
-		*pos++ = ' ';
-		pos += wpa_snprintf_hex(pos, end - pos, r0kh->key,
-					sizeof(r0kh->key));
-		ret = os_snprintf(pos, end - pos, "\n");
-		if (os_snprintf_error(end - pos, ret))
-			return start_pos;
-		pos += ret;
-	}
-
-	for (r1kh = conf->r1kh_list; r1kh; r1kh=r1kh->next) {
-		start_pos = pos - buf;
-		ret = os_snprintf(pos, end - pos, "r1kh=" MACSTR " " MACSTR " ",
-			MAC2STR(r1kh->addr), MAC2STR(r1kh->id));
-		if (os_snprintf_error(end - pos, ret))
-			return start_pos;
-		pos += ret;
-		pos += wpa_snprintf_hex(pos, end - pos, r1kh->key,
-					sizeof(r1kh->key));
-		ret = os_snprintf(pos, end - pos, "\n");
-		if (os_snprintf_error(end - pos, ret))
-			return start_pos;
-		pos += ret;
-	}
-
-	return pos - buf;
-}
-
-
-static int hostapd_ctrl_iface_reload_rxkhs(struct hostapd_data *hapd)
-{
-	struct hostapd_bss_config *conf = hapd->conf;
-	int err;
-
-	hostapd_config_clear_rxkhs(conf);
-
-	err = hostapd_config_read_rxkh_file(conf, conf->rxkh_file);
-	if (err < 0) {
-		wpa_printf(MSG_ERROR, "Reloading RxKHs failed: %d",
-			   err);
-		return -1;
-	}
-
-	return 0;
-}
-
-#endif /* CONFIG_IEEE80211R_AP */
-
-
 #ifdef CONFIG_TESTING_OPTIONS
 
 static int hostapd_ctrl_iface_radar(struct hostapd_data *hapd, char *cmd)
@@ -1948,7 +1871,7 @@
 
 #ifdef CONFIG_IEEE80211BE
 	if (hapd->conf->mld_ap)
-		addr = hapd->mld->mld_addr;
+		addr = hapd->mld_addr;
 #endif /* CONFIG_IEEE80211BE */
 	hapd->l2_test = l2_packet_init(ifname, addr,
 					ETHERTYPE_IP, hostapd_data_test_rx,
@@ -2087,6 +2010,74 @@
 }
 
 
+static int hostapd_ctrl_test_alloc_fail(struct hostapd_data *hapd, char *cmd)
+{
+#ifdef WPA_TRACE_BFD
+	char *pos;
+
+	wpa_trace_fail_after = atoi(cmd);
+	pos = os_strchr(cmd, ':');
+	if (pos) {
+		pos++;
+		os_strlcpy(wpa_trace_fail_func, pos,
+			   sizeof(wpa_trace_fail_func));
+	} else {
+		wpa_trace_fail_after = 0;
+	}
+
+	return 0;
+#else /* WPA_TRACE_BFD */
+	return -1;
+#endif /* WPA_TRACE_BFD */
+}
+
+
+static int hostapd_ctrl_get_alloc_fail(struct hostapd_data *hapd,
+				       char *buf, size_t buflen)
+{
+#ifdef WPA_TRACE_BFD
+	return os_snprintf(buf, buflen, "%u:%s", wpa_trace_fail_after,
+			   wpa_trace_fail_func);
+#else /* WPA_TRACE_BFD */
+	return -1;
+#endif /* WPA_TRACE_BFD */
+}
+
+
+static int hostapd_ctrl_test_fail(struct hostapd_data *hapd, char *cmd)
+{
+#ifdef WPA_TRACE_BFD
+	char *pos;
+
+	wpa_trace_test_fail_after = atoi(cmd);
+	pos = os_strchr(cmd, ':');
+	if (pos) {
+		pos++;
+		os_strlcpy(wpa_trace_test_fail_func, pos,
+			   sizeof(wpa_trace_test_fail_func));
+	} else {
+		wpa_trace_test_fail_after = 0;
+	}
+
+	return 0;
+#else /* WPA_TRACE_BFD */
+	return -1;
+#endif /* WPA_TRACE_BFD */
+}
+
+
+static int hostapd_ctrl_get_fail(struct hostapd_data *hapd,
+				 char *buf, size_t buflen)
+{
+#ifdef WPA_TRACE_BFD
+	return os_snprintf(buf, buflen, "%u:%s", wpa_trace_test_fail_after,
+			   wpa_trace_test_fail_func);
+#else /* WPA_TRACE_BFD */
+	return -1;
+#endif /* WPA_TRACE_BFD */
+}
+
+
 static int hostapd_ctrl_reset_pn(struct hostapd_data *hapd, const char *cmd)
 {
 	struct sta_info *sta;
@@ -2644,19 +2635,11 @@
 	unsigned int i;
 	int bandwidth;
 	u8 chan;
-	unsigned int num_err = 0;
-	int err = 0;
 
 	ret = hostapd_parse_csa_settings(pos, &settings);
 	if (ret)
 		return ret;
 
-	settings.link_id = -1;
-#ifdef CONFIG_IEEE80211BE
-	if (iface->num_bss && iface->bss[0]->conf->mld_ap)
-		settings.link_id = iface->bss[0]->mld_link_id;
-#endif /* CONFIG_IEEE80211BE */
-
 	ret = hostapd_ctrl_check_freq_params(&settings.freq_params,
 					     settings.punct_bitmap);
 	if (ret) {
@@ -2719,7 +2702,6 @@
 			   settings.freq_params.center_freq1);
 
 		/* Perform CAC and switch channel */
-		iface->is_ch_switch_dfs = true;
 		hostapd_switch_channel_fallback(iface, &settings.freq_params);
 		return 0;
 	}
@@ -2730,14 +2712,15 @@
 		hostapd_chan_switch_config(iface->bss[i],
 					   &settings.freq_params);
 
-		err = hostapd_switch_channel(iface->bss[i], &settings);
-		if (err) {
-			ret = err;
-			num_err++;
+		ret = hostapd_switch_channel(iface->bss[i], &settings);
+		if (ret) {
+			/* FIX: What do we do if CSA fails in the middle of
+			 * submitting multi-BSS CSA requests? */
+			return ret;
 		}
 	}
 
-	return (iface->num_bss == num_err) ? ret : 0;
+	return 0;
 #else /* NEED_AP_MLME */
 	return -1;
 #endif /* NEED_AP_MLME */
@@ -3211,26 +3194,6 @@
 }
 
 
-static int hostapd_ctrl_iface_req_link_measurement(struct hostapd_data *hapd,
-						   const char *cmd, char *reply,
-						   size_t reply_size)
-{
-	u8 addr[ETH_ALEN];
-	int ret;
-
-	if (hwaddr_aton(cmd, addr)) {
-		wpa_printf(MSG_ERROR,
-			   "CTRL: REQ_LINK_MEASUREMENT: Invalid MAC address");
-		return -1;
-	}
-
-	ret = hostapd_send_link_measurement_req(hapd, addr);
-	if (ret >= 0)
-		ret = os_snprintf(reply, reply_size, "%d", ret);
-	return ret;
-}
-
-
 static int hostapd_ctrl_iface_show_neighbor(struct hostapd_data *hapd,
 					    char *buf, size_t buflen)
 {
@@ -3486,395 +3449,6 @@
 #endif /* ANDROID */
 
 
-#ifdef CONFIG_IEEE80211BE
-
-static int hostapd_ctrl_iface_enable_mld(struct hostapd_iface *iface)
-{
-	unsigned int i;
-
-	if (!iface || !iface->bss[0]->conf->mld_ap) {
-		wpa_printf(MSG_ERROR,
-			   "Trying to enable AP MLD on an interface that is not affiliated with an AP MLD");
-		return -1;
-	}
-
-	for (i = 0; i < iface->interfaces->count; ++i) {
-		struct hostapd_iface *h_iface = iface->interfaces->iface[i];
-		struct hostapd_data *h_hapd = h_iface->bss[0];
-
-		if (!hostapd_is_ml_partner(h_hapd, iface->bss[0]))
-			continue;
-
-		if (hostapd_enable_iface(h_iface)) {
-			wpa_printf(MSG_ERROR, "Enabling of AP MLD failed");
-			return -1;
-		}
-	}
-	return 0;
-}
-
-
-static void hostapd_disable_iface_bss(struct hostapd_iface *iface)
-{
-	unsigned int i;
-
-	for (i = 0; i < iface->num_bss; i++)
-		hostapd_bss_deinit_no_free(iface->bss[i]);
-}
-
-
-static int hostapd_ctrl_iface_disable_mld(struct hostapd_iface *iface)
-{
-	unsigned int i;
-
-	if (!iface || !iface->bss[0]->conf->mld_ap) {
-		wpa_printf(MSG_ERROR,
-			   "Trying to disable AP MLD on an interface that is not affiliated with an AP MLD.");
-		return -1;
-	}
-
-	/* First, disable BSSs before stopping beaconing and doing driver
-	 * deinit so that the broadcast Deauthentication frames go out. */
-
-	for (i = 0; i < iface->interfaces->count; ++i) {
-		struct hostapd_iface *h_iface = iface->interfaces->iface[i];
-		struct hostapd_data *h_hapd = h_iface->bss[0];
-
-		if (!hostapd_is_ml_partner(h_hapd, iface->bss[0]))
-			continue;
-
-		hostapd_disable_iface_bss(iface);
-	}
-
-	/* Then, fully disable interfaces */
-	for (i = 0; i < iface->interfaces->count; ++i) {
-		struct hostapd_iface *h_iface = iface->interfaces->iface[i];
-		struct hostapd_data *h_hapd = h_iface->bss[0];
-
-		if (!hostapd_is_ml_partner(h_hapd, iface->bss[0]))
-			continue;
-
-		if (hostapd_disable_iface(h_iface)) {
-			wpa_printf(MSG_ERROR, "Disabling AP MLD failed");
-			return -1;
-		}
-	}
-
-	return 0;
-}
-
-
-#ifdef CONFIG_TESTING_OPTIONS
-static int hostapd_ctrl_iface_link_remove(struct hostapd_data *hapd, char *cmd,
-					  char *buf, size_t buflen)
-{
-	int ret;
-	u32 count = atoi(cmd);
-
-	if (!count)
-		count = 1;
-
-	ret = hostapd_link_remove(hapd, count);
-	if (ret == 0) {
-		ret = os_snprintf(buf, buflen, "%s\n", "OK");
-		if (os_snprintf_error(buflen, ret))
-			ret = -1;
-		else
-			ret = 0;
-	}
-
-	return ret;
-}
-#endif /* CONFIG_TESTING_OPTIONS */
-#endif /* CONFIG_IEEE80211BE */
-
-
-#ifdef CONFIG_NAN_USD
-
-static int hostapd_ctrl_nan_publish(struct hostapd_data *hapd, char *cmd,
-				    char *buf, size_t buflen)
-{
-	char *token, *context = NULL;
-	int publish_id;
-	struct nan_publish_params params;
-	const char *service_name = NULL;
-	struct wpabuf *ssi = NULL;
-	int ret = -1;
-	enum nan_service_protocol_type srv_proto_type = 0;
-
-	os_memset(&params, 0, sizeof(params));
-	/* USD shall use both solicited and unsolicited transmissions */
-	params.unsolicited = true;
-	params.solicited = true;
-	/* USD shall require FSD without GAS */
-	params.fsd = true;
-
-	while ((token = str_token(cmd, " ", &context))) {
-		if (os_strncmp(token, "service_name=", 13) == 0) {
-			service_name = token + 13;
-			continue;
-		}
-
-		if (os_strncmp(token, "ttl=", 4) == 0) {
-			params.ttl = atoi(token + 4);
-			continue;
-		}
-
-		if (os_strncmp(token, "srv_proto_type=", 15) == 0) {
-			srv_proto_type = atoi(token + 15);
-			continue;
-		}
-
-		if (os_strncmp(token, "ssi=", 4) == 0) {
-			if (ssi)
-				goto fail;
-			ssi = wpabuf_parse_bin(token + 4);
-			if (!ssi)
-				goto fail;
-			continue;
-		}
-
-		if (os_strcmp(token, "solicited=0") == 0) {
-			params.solicited = false;
-			continue;
-		}
-
-		if (os_strcmp(token, "unsolicited=0") == 0) {
-			params.unsolicited = false;
-			continue;
-		}
-
-		if (os_strcmp(token, "fsd=0") == 0) {
-			params.fsd = false;
-			continue;
-		}
-
-		wpa_printf(MSG_INFO, "CTRL: Invalid NAN_PUBLISH parameter: %s",
-			   token);
-		goto fail;
-	}
-
-	publish_id = hostapd_nan_usd_publish(hapd, service_name, srv_proto_type,
-					     ssi, &params);
-	if (publish_id > 0)
-		ret = os_snprintf(buf, buflen, "%d", publish_id);
-fail:
-	wpabuf_free(ssi);
-	return ret;
-}
-
-
-static int hostapd_ctrl_nan_cancel_publish(struct hostapd_data *hapd,
-					   char *cmd)
-{
-	char *token, *context = NULL;
-	int publish_id = 0;
-
-	while ((token = str_token(cmd, " ", &context))) {
-		if (sscanf(token, "publish_id=%i", &publish_id) == 1)
-			continue;
-		wpa_printf(MSG_INFO,
-			   "CTRL: Invalid NAN_CANCEL_PUBLISH parameter: %s",
-			   token);
-		return -1;
-	}
-
-	if (publish_id <= 0) {
-		wpa_printf(MSG_INFO,
-			   "CTRL: Invalid or missing NAN_CANCEL_PUBLISH publish_id");
-		return -1;
-	}
-
-	hostapd_nan_usd_cancel_publish(hapd, publish_id);
-	return 0;
-}
-
-
-static int hostapd_ctrl_nan_update_publish(struct hostapd_data *hapd,
-					   char *cmd)
-{
-	char *token, *context = NULL;
-	int publish_id = 0;
-	struct wpabuf *ssi = NULL;
-	int ret = -1;
-
-	while ((token = str_token(cmd, " ", &context))) {
-		if (sscanf(token, "publish_id=%i", &publish_id) == 1)
-			continue;
-		if (os_strncmp(token, "ssi=", 4) == 0) {
-			if (ssi)
-				goto fail;
-			ssi = wpabuf_parse_bin(token + 4);
-			if (!ssi)
-				goto fail;
-			continue;
-		}
-		wpa_printf(MSG_INFO,
-			   "CTRL: Invalid NAN_UPDATE_PUBLISH parameter: %s",
-			   token);
-		goto fail;
-	}
-
-	if (publish_id <= 0) {
-		wpa_printf(MSG_INFO,
-			   "CTRL: Invalid or missing NAN_UPDATE_PUBLISH publish_id");
-		goto fail;
-	}
-
-	ret = hostapd_nan_usd_update_publish(hapd, publish_id, ssi);
-fail:
-	wpabuf_free(ssi);
-	return ret;
-}
-
-
-static int hostapd_ctrl_nan_subscribe(struct hostapd_data *hapd, char *cmd,
-				      char *buf, size_t buflen)
-{
-	char *token, *context = NULL;
-	int subscribe_id;
-	struct nan_subscribe_params params;
-	const char *service_name = NULL;
-	struct wpabuf *ssi = NULL;
-	int ret = -1;
-	enum nan_service_protocol_type srv_proto_type = 0;
-
-	os_memset(&params, 0, sizeof(params));
-
-	while ((token = str_token(cmd, " ", &context))) {
-		if (os_strncmp(token, "service_name=", 13) == 0) {
-			service_name = token + 13;
-			continue;
-		}
-
-		if (os_strcmp(token, "active=1") == 0) {
-			params.active = true;
-			continue;
-		}
-
-		if (os_strncmp(token, "ttl=", 4) == 0) {
-			params.ttl = atoi(token + 4);
-			continue;
-		}
-
-		if (os_strncmp(token, "srv_proto_type=", 15) == 0) {
-			srv_proto_type = atoi(token + 15);
-			continue;
-		}
-
-		if (os_strncmp(token, "ssi=", 4) == 0) {
-			if (ssi)
-				goto fail;
-			ssi = wpabuf_parse_bin(token + 4);
-			if (!ssi)
-				goto fail;
-			continue;
-		}
-
-		wpa_printf(MSG_INFO,
-			   "CTRL: Invalid NAN_SUBSCRIBE parameter: %s",
-			   token);
-		goto fail;
-	}
-
-	subscribe_id = hostapd_nan_usd_subscribe(hapd, service_name,
-						 srv_proto_type, ssi,
-						 &params);
-	if (subscribe_id > 0)
-		ret = os_snprintf(buf, buflen, "%d", subscribe_id);
-fail:
-	wpabuf_free(ssi);
-	return ret;
-}
-
-
-static int hostapd_ctrl_nan_cancel_subscribe(struct hostapd_data *hapd,
-					     char *cmd)
-{
-	char *token, *context = NULL;
-	int subscribe_id = 0;
-
-	while ((token = str_token(cmd, " ", &context))) {
-		if (sscanf(token, "subscribe_id=%i", &subscribe_id) == 1)
-			continue;
-		wpa_printf(MSG_INFO,
-			   "CTRL: Invalid NAN_CANCEL_SUBSCRIBE parameter: %s",
-			   token);
-		return -1;
-	}
-
-	if (subscribe_id <= 0) {
-		wpa_printf(MSG_INFO,
-			   "CTRL: Invalid or missing NAN_CANCEL_SUBSCRIBE subscribe_id");
-		return -1;
-	}
-
-	hostapd_nan_usd_cancel_subscribe(hapd, subscribe_id);
-	return 0;
-}
-
-
-static int hostapd_ctrl_nan_transmit(struct hostapd_data *hapd, char *cmd)
-{
-	char *token, *context = NULL;
-	int handle = 0;
-	int req_instance_id = 0;
-	struct wpabuf *ssi = NULL;
-	u8 peer_addr[ETH_ALEN];
-	int ret = -1;
-
-	os_memset(peer_addr, 0, ETH_ALEN);
-
-	while ((token = str_token(cmd, " ", &context))) {
-		if (sscanf(token, "handle=%i", &handle) == 1)
-			continue;
-
-		if (sscanf(token, "req_instance_id=%i", &req_instance_id) == 1)
-			continue;
-
-		if (os_strncmp(token, "address=", 8) == 0) {
-			if (hwaddr_aton(token + 8, peer_addr) < 0)
-				return -1;
-			continue;
-		}
-
-		if (os_strncmp(token, "ssi=", 4) == 0) {
-			if (ssi)
-				goto fail;
-			ssi = wpabuf_parse_bin(token + 4);
-			if (!ssi)
-				goto fail;
-			continue;
-		}
-
-		wpa_printf(MSG_INFO,
-			   "CTRL: Invalid NAN_TRANSMIT parameter: %s",
-			   token);
-		goto fail;
-	}
-
-	if (handle <= 0) {
-		wpa_printf(MSG_INFO,
-			   "CTRL: Invalid or missing NAN_TRANSMIT handle");
-		goto fail;
-	}
-
-	if (is_zero_ether_addr(peer_addr)) {
-		wpa_printf(MSG_INFO,
-			   "CTRL: Invalid or missing NAN_TRANSMIT address");
-		goto fail;
-	}
-
-	ret = hostapd_nan_usd_transmit(hapd, handle, ssi, NULL, peer_addr,
-				    req_instance_id);
-fail:
-	wpabuf_free(ssi);
-	return ret;
-}
-
-#endif /* CONFIG_NAN_USD */
-
-
 static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
 					      char *buf, char *reply,
 					      int reply_size,
@@ -4059,30 +3633,19 @@
 	} else if (os_strncmp(buf, "GET ", 4) == 0) {
 		reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply,
 						   reply_size);
-	} else if (os_strcmp(buf, "ENABLE") == 0) {
+	} else if (os_strncmp(buf, "ENABLE", 6) == 0) {
 		if (hostapd_ctrl_iface_enable(hapd->iface))
 			reply_len = -1;
 	} else if (os_strcmp(buf, "RELOAD_WPA_PSK") == 0) {
 		if (hostapd_ctrl_iface_reload_wpa_psk(hapd))
 			reply_len = -1;
-#ifdef CONFIG_IEEE80211R_AP
-	} else if (os_strcmp(buf, "GET_RXKHS") == 0) {
-		reply_len = hostapd_ctrl_iface_get_rxkhs(hapd, reply,
-							 reply_size);
-	} else if (os_strcmp(buf, "RELOAD_RXKHS") == 0) {
-		if (hostapd_ctrl_iface_reload_rxkhs(hapd))
-			reply_len = -1;
-#endif /* CONFIG_IEEE80211R_AP */
 	} else if (os_strcmp(buf, "RELOAD_BSS") == 0) {
 		if (hostapd_ctrl_iface_reload_bss(hapd))
 			reply_len = -1;
-	} else if (os_strcmp(buf, "RELOAD_CONFIG") == 0) {
-		if (hostapd_reload_config(hapd->iface))
-			reply_len = -1;
-	} else if (os_strcmp(buf, "RELOAD") == 0) {
+	} else if (os_strncmp(buf, "RELOAD", 6) == 0) {
 		if (hostapd_ctrl_iface_reload(hapd->iface))
 			reply_len = -1;
-	} else if (os_strcmp(buf, "DISABLE") == 0) {
+	} else if (os_strncmp(buf, "DISABLE", 7) == 0) {
 		if (hostapd_ctrl_iface_disable(hapd->iface))
 			reply_len = -1;
 	} else if (os_strcmp(buf, "UPDATE_BEACON") == 0) {
@@ -4118,15 +3681,16 @@
 		if (hostapd_ctrl_iface_data_test_frame(hapd, buf + 16) < 0)
 			reply_len = -1;
 	} else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) {
-		if (testing_set_fail_pattern(true, buf + 16) < 0)
+		if (hostapd_ctrl_test_alloc_fail(hapd, buf + 16) < 0)
 			reply_len = -1;
 	} else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) {
-		reply_len = testing_get_fail_pattern(true, reply, reply_size);
+		reply_len = hostapd_ctrl_get_alloc_fail(hapd, reply,
+							reply_size);
 	} else if (os_strncmp(buf, "TEST_FAIL ", 10) == 0) {
-		if (testing_set_fail_pattern(false, buf + 10) < 0)
+		if (hostapd_ctrl_test_fail(hapd, buf + 10) < 0)
 			reply_len = -1;
 	} else if (os_strcmp(buf, "GET_FAIL") == 0) {
-		reply_len = testing_get_fail_pattern(false, reply, reply_size);
+		reply_len = hostapd_ctrl_get_fail(hapd, reply, reply_size);
 	} else if (os_strncmp(buf, "RESET_PN ", 9) == 0) {
 		if (hostapd_ctrl_reset_pn(hapd, buf + 9) < 0)
 			reply_len = -1;
@@ -4209,9 +3773,6 @@
 	} else if (os_strncmp(buf, "REQ_BEACON ", 11) == 0) {
 		reply_len = hostapd_ctrl_iface_req_beacon(hapd, buf + 11,
 							  reply, reply_size);
-	} else if (os_strncmp(buf, "REQ_LINK_MEASUREMENT ", 21) == 0) {
-		reply_len = hostapd_ctrl_iface_req_link_measurement(
-			hapd, buf + 21, reply, reply_size);
 	} else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) {
 		reply_len = hostapd_ctrl_driver_flags(hapd->iface, reply,
 						      reply_size);
@@ -4422,26 +3983,6 @@
 			reply_len = -1;
 #endif /* CONFIG_DPP3 */
 #endif /* CONFIG_DPP */
-#ifdef CONFIG_NAN_USD
-	} else if (os_strncmp(buf, "NAN_PUBLISH ", 12) == 0) {
-		reply_len = hostapd_ctrl_nan_publish(hapd, buf + 12, reply,
-						     reply_size);
-	} else if (os_strncmp(buf, "NAN_CANCEL_PUBLISH ", 19) == 0) {
-		if (hostapd_ctrl_nan_cancel_publish(hapd, buf + 19) < 0)
-			reply_len = -1;
-	} else if (os_strncmp(buf, "NAN_UPDATE_PUBLISH ", 19) == 0) {
-		if (hostapd_ctrl_nan_update_publish(hapd, buf + 19) < 0)
-			reply_len = -1;
-	} else if (os_strncmp(buf, "NAN_SUBSCRIBE ", 14) == 0) {
-		reply_len = hostapd_ctrl_nan_subscribe(hapd, buf + 14, reply,
-						       reply_size);
-	} else if (os_strncmp(buf, "NAN_CANCEL_SUBSCRIBE ", 21) == 0) {
-		if (hostapd_ctrl_nan_cancel_subscribe(hapd, buf + 21) < 0)
-			reply_len = -1;
-	} else if (os_strncmp(buf, "NAN_TRANSMIT ", 13) == 0) {
-		if (hostapd_ctrl_nan_transmit(hapd, buf + 13) < 0)
-			reply_len = -1;
-#endif /* CONFIG_NAN_USD */
 #ifdef RADIUS_SERVER
 	} else if (os_strncmp(buf, "DAC_REQUEST ", 12) == 0) {
 		if (radius_server_dac_request(hapd->radius_srv, buf + 12) < 0)
@@ -4459,20 +4000,6 @@
 		reply_len = hostapd_ctrl_iface_driver_cmd(hapd, buf + 7, reply,
 							  reply_size);
 #endif /* ANDROID */
-#ifdef CONFIG_IEEE80211BE
-	} else if (os_strcmp(buf, "ENABLE_MLD") == 0) {
-		if (hostapd_ctrl_iface_enable_mld(hapd->iface))
-			reply_len = -1;
-	} else if (os_strcmp(buf, "DISABLE_MLD") == 0) {
-		if (hostapd_ctrl_iface_disable_mld(hapd->iface))
-			reply_len = -1;
-#ifdef CONFIG_TESTING_OPTIONS
-	} else if (os_strncmp(buf, "LINK_REMOVE ", 12) == 0) {
-		if (hostapd_ctrl_iface_link_remove(hapd, buf + 12,
-						   reply, reply_size))
-			reply_len = -1;
-#endif /* CONFIG_TESTING_OPTIONS */
-#endif /* CONFIG_IEEE80211BE */
 	} else {
 		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
 		reply_len = 16;
@@ -4964,7 +4491,6 @@
 #ifdef CONFIG_DPP
 	dpp_global_clear(interfaces->dpp);
 #ifdef CONFIG_DPP3
-	interfaces->dpp_pb_bi = NULL;
 	{
 		int i;
 
@@ -5368,7 +4894,7 @@
 			reply_len = -1;
 	} else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
 		reply_len = hostapd_global_ctrl_iface_interfaces(
-			interfaces, buf + 10, reply, reply_size);
+			interfaces, buf + 10, reply, sizeof(buffer));
 	} else if (os_strcmp(buf, "TERMINATE") == 0) {
 		eloop_terminate();
 	} else {
diff --git a/hostapd/defconfig b/hostapd/defconfig
index 43cf99f..0a5ceee 100644
--- a/hostapd/defconfig
+++ b/hostapd/defconfig
@@ -141,9 +141,6 @@
 # Build IPv6 support for RADIUS operations
 CONFIG_IPV6=y
 
-# Include support fo RADIUS/TLS into the RADIUS client
-#CONFIG_RADIUS_TLS=y
-
 # IEEE Std 802.11r-2008 (Fast BSS Transition)
 #CONFIG_IEEE80211R=y
 
@@ -427,6 +424,3 @@
 # DPP version 3 support (experimental and still changing; do not enable for
 # production use)
 #CONFIG_DPP3=y
-
-# Wi-Fi Aware unsynchronized service discovery (NAN USD)
-#CONFIG_NAN_USD=y
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index e34d75c..f02cd92 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -980,22 +980,10 @@
 
 # 6 GHz Access Point type
 # This config is to set the 6 GHz Access Point type. Possible options are:
-# 0 = Indoor AP
-# 1 = Standard power AP
-# 2 = Very low power AP (default)
-# 3 = Indoor enabled AP
-# 4 = Indoor standard power AP
+# 0 = Indoor AP (default)
+# 1 = Standard Power AP
 # This has no impact for operation on other bands.
-# See IEEE P802.11-REVme/D4.0, Table E-12 (Regulatory Info subfield encoding)
-# for more details.
 #he_6ghz_reg_pwr_type=0
-#
-# 6 GHz Maximum Tx Power used in Transmit Power Envelope elements, where the
-# "Transmit Power Interpretation" is set to "Regulatory client EIRP PSD".
-# For Maximum Transmit Power Category subfield encoding set to default (0):
-#reg_def_cli_eirp_psd=-1
-# For Maximum Transmit Power Category subfield encoding set to subordinate (1):
-#reg_sub_cli_eirp_psd=-1
 
 # Unsolicited broadcast Probe Response transmission settings
 # This is for the 6 GHz band only. If the interval is set to a non-zero value,
@@ -1039,20 +1027,6 @@
 #eht_oper_chwidth (see vht_oper_chwidth)
 #eht_oper_centr_freq_seg0_idx
 
-#eht_default_pe_duration: The duration of PE field in EHT TB PPDU
-# 0 = PE field duration is the same as he_default_pe_duration (default)
-# 1 = PE field duration is 20 us
-#eht_default_pe_duration=0
-
-#eht_bw320_offset: For automatic channel selection (ACS) to indicate a preferred
-# 320 MHz channelization in EHT mode.
-# If the channel is decided or the bandwidth is not 320 MHz, this option is
-# meaningless.
-# 0 = auto-detect by hostapd
-# 1 = 320 MHz-1 (channel center frequency 31, 95, 159)
-# 2 = 320 MHz-2 (channel center frequency 63, 127, 191)
-#eht_bw320_offset=0
-
 # Disabled subchannel bitmap (16 bits) as per IEEE P802.11be/3.0,
 # Figure 9-1002c (EHT Operation Information field format). Each bit corresponds
 # to a 20 MHz channel, the lowest bit corresponds to the lowest frequency. A
@@ -1071,6 +1045,9 @@
 # 1 = yes (MLO)
 #mld_ap=0
 
+# MLD ID - Affiliated MLD ID
+#mld_id=1
+
 # AP MLD MAC address
 # The configured address will be set as the interface hardware address and used
 # as the AP MLD MAC address. If not set, the current interface hardware address
@@ -1578,16 +1555,6 @@
 #acct_server_port=1813
 #acct_server_shared_secret=secret2
 
-# RADIUS/TLS instead of RADIUS/UDP
-#auth_server_addr=127.0.0.1
-#auth_server_port=2083
-#auth_server_type=TLS
-#auth_server_shared_secret=radsec
-#auth_server_ca_cert=<path to trusted CA certificate(s)>
-#auth_server_client_cert=<path to client certificate>
-#auth_server_private_key=<path to private key>
-#auth_server_private_key_passwd=<password for decrypting private key>
-
 # Retry interval for trying to return to the primary RADIUS server (in
 # seconds). RADIUS client code will automatically try to use the next server
 # when the current server is not replying to requests. If this interval is set,
@@ -1808,10 +1775,6 @@
 #	Tunnel-Password
 # 3 = ask RADIUS server during 4-way handshake if there is no locally
 #	configured PSK/passphrase for the STA
-#
-# The Tunnel-Password attribute in Access-Accept can contain either the
-# 8..63 character ASCII passphrase or a 64 hex character encoding of the PSK.
-#
 #wpa_psk_radius=0
 
 # Set of accepted key management algorithms (WPA-PSK, WPA-EAP, or both). The
@@ -2069,10 +2032,6 @@
 #sae_password=really secret|mac=ff:ff:ff:ff:ff:ff
 #sae_password=example secret|mac=02:03:04:05:06:07|id=pw identifier
 #sae_password=example secret|vlanid=3|id=pw identifier
-#
-# SAE passwords can also be read from a separate file in which each line
-# contains and entry in the same format as sae_password uses.
-#sae_password_file=/tc/hostapd.sae_passwords
 
 # SAE threshold for anti-clogging mechanism (dot11RSNASAEAntiCloggingThreshold)
 # This parameter defines how many open SAE instances can be in progress at the
@@ -2302,12 +2261,6 @@
 # list and thus will receive push notifications.
 #r1kh=00:00:00:00:00:00 00:00:00:00:00:00 00112233445566778899aabbccddeeff
 
-# Optionally, the list of RxKHs can be read from a text file. Format is the same
-# as specified above. File shall contain both r0kh and r1kh. Once this variable
-# is set, RxKHs can be reloaded at runtime without bringing down an interface
-# using the RELOAD_RXKHS command.
-#rxkh_file=<path>
-
 # Timeout (seconds) for newly discovered R0KH/R1KH (see wildcard entries above)
 # Special values: 0 -> do not expire
 # Warning: do not cache implies no sequence number validation with wildcards
@@ -2562,23 +2515,6 @@
 #multi_ap_backhaul_wpa_psk=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
 #multi_ap_backhaul_wpa_passphrase=secret passphrase
 
-# Multi-AP Profile
-# Indicate the supported Multi-AP profile (default: 2)
-# 1 = Supports Multi-AP profile 1 as defined in Wi-Fi EasyMesh specification
-# 2 = Supports Multi-AP profile 2 as defined in Wi-Fi EasyMesh specification
-#multi_ap_profile=2
-
-# Multi-AP client disallow
-# Used to disallow profile specific backhaul STA association
-# Bitmap of the disallowed Profile-X profiles
-# 1 = Profile-1 Backhaul STA association disallowed
-# 2 = Profile-2 Backhaul STA association disallowed
-#multi_ap_client_disallow=0
-
-# Multi-AP VLAN ID
-# A valid non-zero VLAN ID will be used to update Default IEEE 802.1Q Setting
-#multi_ap_vlanid=0
-
 # WPS UPnP interface
 # If set, support for external Registrars is enabled.
 #upnp_iface=br0
@@ -3112,9 +3048,6 @@
 # Enable neighbor report via radio measurements
 #rrm_neighbor_report=1
 
-# Enable link measurement report via radio measurements
-#rrm_link_measurement_report=1
-
 # Enable beacon report via radio measurements
 #rrm_beacon_report=1
 
diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
index e1fe286..45497cd 100644
--- a/hostapd/hostapd_cli.c
+++ b/hostapd/hostapd_cli.c
@@ -1215,14 +1215,14 @@
 
 
 static int hostapd_cli_cmd_enable(struct wpa_ctrl *ctrl, int argc,
-				  char *argv[])
+				      char *argv[])
 {
 	return wpa_ctrl_command(ctrl, "ENABLE");
 }
 
 
 static int hostapd_cli_cmd_reload(struct wpa_ctrl *ctrl, int argc,
-				  char *argv[])
+				      char *argv[])
 {
 	return wpa_ctrl_command(ctrl, "RELOAD");
 }
@@ -1235,48 +1235,20 @@
 }
 
 
-static int hostapd_cli_cmd_reload_config(struct wpa_ctrl *ctrl, int argc,
-					 char *argv[])
-{
-	return wpa_ctrl_command(ctrl, "RELOAD_CONFIG");
-}
-
-
 static int hostapd_cli_cmd_disable(struct wpa_ctrl *ctrl, int argc,
-				   char *argv[])
+				      char *argv[])
 {
 	return wpa_ctrl_command(ctrl, "DISABLE");
 }
 
 
-static int hostapd_cli_cmd_enable_mld(struct wpa_ctrl *ctrl, int argc,
+static int hostapd_cli_cmd_update_beacon(struct wpa_ctrl *ctrl, int argc,
 				      char *argv[])
 {
-	return wpa_ctrl_command(ctrl, "ENABLE_MLD");
-}
-
-
-static int hostapd_cli_cmd_disable_mld(struct wpa_ctrl *ctrl, int argc,
-				       char *argv[])
-{
-	return wpa_ctrl_command(ctrl, "DISABLE_MLD");
-}
-
-
-static int hostapd_cli_cmd_update_beacon(struct wpa_ctrl *ctrl, int argc,
-					 char *argv[])
-{
 	return wpa_ctrl_command(ctrl, "UPDATE_BEACON");
 }
 
 
-static int hostapd_cli_cmd_stop_ap(struct wpa_ctrl *ctrl, int argc,
-				   char *argv[])
-{
-	return wpa_ctrl_command(ctrl, "STOP_AP");
-}
-
-
 static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
 	char cmd[256];
@@ -1605,13 +1577,6 @@
 }
 
 
-static int hostapd_cli_cmd_req_link_measurement(struct wpa_ctrl *ctrl, int argc,
-						char *argv[])
-{
-	return hostapd_cli_cmd(ctrl, "REQ_LINK_MEASUREMENT", 1, argc, argv);
-}
-
-
 static int hostapd_cli_cmd_reload_wpa_psk(struct wpa_ctrl *ctrl, int argc,
 					  char *argv[])
 {
@@ -1619,24 +1584,6 @@
 }
 
 
-#ifdef CONFIG_IEEE80211R_AP
-
-static int hostapd_cli_cmd_get_rxkhs(struct wpa_ctrl *ctrl, int argc,
-				     char *argv[])
-{
-	return wpa_ctrl_command(ctrl, "GET_RXKHS");
-}
-
-
-static int hostapd_cli_cmd_reload_rxkhs(struct wpa_ctrl *ctrl, int argc,
-					char *argv[])
-{
-	return wpa_ctrl_command(ctrl, "RELOAD_RXKHS");
-}
-
-#endif /* CONFIG_IEEE80211R_AP */
-
-
 #ifdef ANDROID
 static int hostapd_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
@@ -1763,18 +1710,10 @@
 	  "= reload configuration for current interface" },
 	{ "reload_bss", hostapd_cli_cmd_reload_bss, NULL,
 	  "= reload configuration for current BSS" },
-	{ "reload_config", hostapd_cli_cmd_reload_config, NULL,
-	  "= reload configuration for current interface" },
 	{ "disable", hostapd_cli_cmd_disable, NULL,
 	  "= disable hostapd on current interface" },
-	{ "enable_mld", hostapd_cli_cmd_enable_mld, NULL,
-	  "= enable AP MLD to which the interface is affiliated" },
-	{ "disable_mld", hostapd_cli_cmd_disable_mld, NULL,
-	  "= disable AP MLD to which the interface is affiliated" },
 	{ "update_beacon", hostapd_cli_cmd_update_beacon, NULL,
 	  "= update Beacon frame contents\n"},
-	{ "stop_ap", hostapd_cli_cmd_stop_ap, NULL,
-	  "= stop AP\n"},
 	{ "erp_flush", hostapd_cli_cmd_erp_flush, NULL,
 	  "= drop all ERP keys"},
 	{ "log_level", hostapd_cli_cmd_log_level, NULL,
@@ -1854,16 +1793,8 @@
 	  "<addr> = poll a STA to check connectivity with a QoS null frame" },
 	{ "req_beacon", hostapd_cli_cmd_req_beacon, NULL,
 	  "<addr> [req_mode=] <measurement request hexdump>  = send a Beacon report request to a station" },
-	{ "req_link_measurement", hostapd_cli_cmd_req_link_measurement, NULL,
-	  "<addr> = send a link measurement report request to a station"},
 	{ "reload_wpa_psk", hostapd_cli_cmd_reload_wpa_psk, NULL,
 	  "= reload wpa_psk_file only" },
-#ifdef CONFIG_IEEE80211R_AP
-	{ "reload_rxkhs", hostapd_cli_cmd_reload_rxkhs, NULL,
-	  "= reload R0KHs and R1KHs" },
-	{ "get_rxkhs", hostapd_cli_cmd_get_rxkhs, NULL,
-	  "= get R0KHs and R1KHs" },
-#endif /* CONFIG_IEEE80211R_AP */
 #ifdef ANDROID
 	{ "driver", hostapd_cli_cmd_driver, NULL,
 	  "<driver sub command> [<hex formatted data>] = send driver command data" },
diff --git a/hostapd/main.c b/hostapd/main.c
index 3a14381..615dc2f 100644
--- a/hostapd/main.c
+++ b/hostapd/main.c
@@ -177,15 +177,9 @@
 			continue;
 		}
 
-		if (!hconf->mld_ap) {
+		if (!hconf->mld_ap || hconf->mld_id != conf->mld_id) {
 			wpa_printf(MSG_DEBUG,
-				   "MLD: Skip non-MLD");
-			continue;
-		}
-
-		if (!hostapd_is_ml_partner(hapd, h_hapd)) {
-			wpa_printf(MSG_DEBUG,
-				   "MLD: Skip non matching MLD vif name");
+				   "MLD: Skip non matching mld_id");
 			continue;
 		}
 
@@ -197,7 +191,6 @@
 		}
 
 		hapd->drv_priv = h_hapd->drv_priv;
-		hapd->interface_added = h_hapd->interface_added;
 
 		/*
 		 * All interfaces participating in the AP MLD would have
@@ -207,15 +200,20 @@
 		 * is not configured, and otherwise it would be the
 		 * configured BSSID.
 		 */
+		os_memcpy(hapd->mld_addr, h_hapd->mld_addr, ETH_ALEN);
 		if (is_zero_ether_addr(b)) {
-			os_memcpy(hapd->own_addr, h_hapd->mld->mld_addr,
-				  ETH_ALEN);
+			os_memcpy(hapd->own_addr, h_hapd->mld_addr, ETH_ALEN);
 			random_mac_addr_keep_oui(hapd->own_addr);
 		} else {
 			os_memcpy(hapd->own_addr, b, ETH_ALEN);
 		}
 
-		hostapd_mld_add_link(hapd);
+		/*
+		 * Mark the interface as a secondary interface, as this
+		 * is needed for the de-initialization flow
+		 */
+		hapd->mld_first_bss = h_hapd;
+		hapd->mld_link_id = hapd->mld_first_bss->mld_next_link_id++;
 
 		goto setup_mld;
 	}
@@ -251,12 +249,8 @@
 	 * Use the configured MLD MAC address as the interface hardware address
 	 * if this AP is a part of an AP MLD.
 	 */
-	if (hapd->conf->mld_ap) {
-		if (!is_zero_ether_addr(hapd->conf->mld_addr))
-			params.bssid = hapd->conf->mld_addr;
-		else
-			params.bssid = NULL;
-	}
+	if (!is_zero_ether_addr(hapd->conf->mld_addr) && hapd->conf->mld_ap)
+		params.bssid = hapd->conf->mld_addr;
 #endif /* CONFIG_IEEE80211BE */
 
 	params.ifname = hapd->conf->iface;
@@ -292,14 +286,13 @@
 	 * configured, and otherwise it would be the configured BSSID.
 	 */
 	if (hapd->conf->mld_ap) {
-		os_memcpy(hapd->mld->mld_addr, hapd->own_addr, ETH_ALEN);
-
+		os_memcpy(hapd->mld_addr, hapd->own_addr, ETH_ALEN);
+		hapd->mld_next_link_id = 0;
+		hapd->mld_link_id = hapd->mld_next_link_id++;
 		if (!b)
 			random_mac_addr_keep_oui(hapd->own_addr);
 		else
 			os_memcpy(hapd->own_addr, b, ETH_ALEN);
-
-		hostapd_mld_add_link(hapd);
 	}
 
 setup_mld:
@@ -311,7 +304,6 @@
 
 		iface->drv_flags = capa.flags;
 		iface->drv_flags2 = capa.flags2;
-		iface->drv_rrm_flags = capa.rrm_flags;
 		iface->probe_resp_offloads = capa.probe_resp_offloads;
 		/*
 		 * Use default extended capa values from per-radio information
@@ -348,13 +340,10 @@
 			return -1;
 		}
 
-		/* Initialize the BSS parameter change to 1 */
-		hapd->eht_mld_bss_param_change = 1;
-
 		wpa_printf(MSG_DEBUG,
 			   "MLD: Set link_id=%u, mld_addr=" MACSTR
 			   ", own_addr=" MACSTR,
-			   hapd->mld_link_id, MAC2STR(hapd->mld->mld_addr),
+			   hapd->mld_link_id, MAC2STR(hapd->mld_addr),
 			   MAC2STR(hapd->own_addr));
 
 		hostapd_drv_link_add(hapd, hapd->mld_link_id,
@@ -762,29 +751,6 @@
 }
 
 
-static void hostapd_global_cleanup_mld(struct hapd_interfaces *interfaces)
-{
-#ifdef CONFIG_IEEE80211BE
-	size_t i;
-
-	if (!interfaces || !interfaces->mld)
-		return;
-
-	for (i = 0; i < interfaces->mld_count; i++) {
-		if (!interfaces->mld[i])
-			continue;
-
-		os_free(interfaces->mld[i]);
-		interfaces->mld[i] = NULL;
-	}
-
-	os_free(interfaces->mld);
-	interfaces->mld = NULL;
-	interfaces->mld_count = 0;
-#endif /* CONFIG_IEEE80211BE */
-}
-
-
 int main(int argc, char *argv[])
 {
 	struct hapd_interfaces interfaces;
@@ -1070,8 +1036,6 @@
 	interfaces.iface = NULL;
 	interfaces.count = 0;
 
-	hostapd_global_cleanup_mld(&interfaces);
-
 #ifdef CONFIG_DPP
 	dpp_global_deinit(interfaces.dpp);
 #endif /* CONFIG_DPP */
diff --git a/src/ap/acs.c b/src/ap/acs.c
index 28b0ba7..e3cfe1d 100644
--- a/src/ap/acs.c
+++ b/src/ap/acs.c
@@ -245,8 +245,6 @@
 	ACS_BW40,
 	ACS_BW80,
 	ACS_BW160,
-	ACS_BW320_1,
-	ACS_BW320_2,
 };
 
 struct bw_item {
@@ -288,20 +286,10 @@
 	{ 6435, 6575, 111 }, { 6595, 6735, 143 },
 	{ 6755, 6895, 175 }, { 6915, 7055, 207 }, { -1, -1, -1 }
 };
-static const struct bw_item bw_320_1[] = {
-	{ 5955, 6255, 31 }, { 6275, 6575, 95 }, { 6595, 6895, 159 },
-	{ -1, -1, -1 }
-};
-static const struct bw_item bw_320_2[] = {
-	{ 6115, 6415, 63 }, { 6435, 6735, 127 }, { 6755, 7055, 191 },
-	{ -1, -1, -1 }
-};
 static const struct bw_item *bw_desc[] = {
 	[ACS_BW40] = bw_40,
 	[ACS_BW80] = bw_80,
 	[ACS_BW160] = bw_160,
-	[ACS_BW320_1] = bw_320_1,
-	[ACS_BW320_2] = bw_320_2,
 };
 
 
@@ -780,42 +768,6 @@
 #endif /* CONFIG_IEEE80211BE */
 
 
-static bool
-acs_usable_bw320_chan(struct hostapd_iface *iface,
-		      struct hostapd_channel_data *chan, int *bw320_offset)
-{
-	const char *bw320_str[] = { "320 MHz", "320 MHz-1", "320 MHz-2" };
-	int conf_bw320_offset = hostapd_get_bw320_offset(iface->conf);
-
-	*bw320_offset = 0;
-	switch (conf_bw320_offset) {
-	case 1:
-		if (acs_usable_bw_chan(chan, ACS_BW320_1))
-			*bw320_offset = 1;
-		break;
-	case 2:
-		if (acs_usable_bw_chan(chan, ACS_BW320_2))
-			*bw320_offset = 2;
-		break;
-	case 0:
-	default:
-		conf_bw320_offset = 0;
-		if (acs_usable_bw_chan(chan, ACS_BW320_1))
-			*bw320_offset = 1;
-		else if (acs_usable_bw_chan(chan, ACS_BW320_2))
-			*bw320_offset = 2;
-		break;
-	}
-
-	if (!*bw320_offset)
-		wpa_printf(MSG_DEBUG,
-			   "ACS: Channel %d: not allowed as primary channel for %s bandwidth",
-			   chan->chan, bw320_str[conf_bw320_offset]);
-
-	return *bw320_offset != 0;
-}
-
-
 static void
 acs_find_ideal_chan_mode(struct hostapd_iface *iface,
 			 struct hostapd_hw_modes *mode,
@@ -827,18 +779,14 @@
 	struct hostapd_channel_data *chan, *adj_chan = NULL, *best;
 	long double factor;
 	int i, j;
-	int bw320_offset = 0, ideal_bw320_offset = 0;
 	unsigned int k;
-	int secondary_channel = 1, freq_offset;
-
-	if (is_24ghz_mode(mode->mode))
-		secondary_channel = iface->conf->secondary_channel;
 
 	for (i = 0; i < mode->num_channels; i++) {
-		double total_weight = 0;
+		double total_weight;
 		struct acs_bias *bias, tmp_bias;
+		bool update_best = true;
 
-		chan = &mode->channels[i];
+		best = chan = &mode->channels[i];
 
 		/* Since in the current ACS implementation the first channel is
 		 * always a primary channel, skip channels not available as
@@ -870,7 +818,7 @@
 		    iface->conf->country[2] == 0x4f)
 			continue;
 
-		if (!chan_bw_allowed(chan, bw, secondary_channel != -1, 1)) {
+		if (!chan_bw_allowed(chan, bw, 1, 1)) {
 			wpa_printf(MSG_DEBUG,
 				   "ACS: Channel %d: BW %u is not supported",
 				   chan->chan, bw);
@@ -891,8 +839,7 @@
 		}
 
 		if (mode->mode == HOSTAPD_MODE_IEEE80211A &&
-		    (iface->conf->ieee80211ac || iface->conf->ieee80211ax ||
-		     iface->conf->ieee80211be)) {
+		    (iface->conf->ieee80211ac || iface->conf->ieee80211ax)) {
 			if (hostapd_get_oper_chwidth(iface->conf) ==
 			    CONF_OPER_CHWIDTH_80MHZ &&
 			    !acs_usable_bw_chan(chan, ACS_BW80)) {
@@ -912,25 +859,13 @@
 			}
 		}
 
-		if (mode->mode == HOSTAPD_MODE_IEEE80211A &&
-		    iface->conf->ieee80211be) {
-			if (hostapd_get_oper_chwidth(iface->conf) ==
-			    CONF_OPER_CHWIDTH_320MHZ &&
-			    !acs_usable_bw320_chan(iface, chan, &bw320_offset))
-				continue;
-		}
-
 		factor = 0;
-		best = NULL;
-		if (acs_usable_chan(chan)) {
+		if (acs_usable_chan(chan))
 			factor = chan->interference_factor;
-			total_weight = 1;
-			best = chan;
-		}
+		total_weight = 1;
 
 		for (j = 1; j < n_chans; j++) {
-			adj_chan = acs_find_chan(iface, chan->freq +
-						 j * secondary_channel * 20);
+			adj_chan = acs_find_chan(iface, chan->freq + (j * 20));
 			if (!adj_chan)
 				break;
 
@@ -941,14 +876,16 @@
 				break;
 			}
 
-			if (!acs_usable_chan(adj_chan))
-				continue;
-
-			factor += adj_chan->interference_factor;
-			total_weight += 1;
+			if (acs_usable_chan(adj_chan)) {
+				factor += adj_chan->interference_factor;
+				total_weight += 1;
+			} else {
+				update_best = false;
+			}
 
 			/* find the best channel in this segment */
-			if (!best || adj_chan->interference_factor <
+			if (update_best &&
+			    adj_chan->interference_factor <
 			    best->interference_factor)
 				best = adj_chan;
 		}
@@ -961,9 +898,8 @@
 
 		/* If the AP is in the 5 GHz or 6 GHz band, lets prefer a less
 		 * crowded primary channel if one was found in the segment */
-		if (iface->current_mode &&
-		    iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
-		    best && chan != best) {
+		if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
+		    chan != best) {
 			wpa_printf(MSG_DEBUG,
 				   "ACS: promoting channel %d over %d (less interference %Lg/%Lg)",
 				   best->chan, chan->chan,
@@ -976,9 +912,8 @@
 		 * channel interference factor. */
 		if (is_24ghz_mode(mode->mode)) {
 			for (j = 0; j < n_chans; j++) {
-				freq_offset = j * 20 * secondary_channel;
 				adj_chan = acs_find_chan(iface, chan->freq +
-							 freq_offset - 5);
+							 (j * 20) - 5);
 				if (adj_chan && acs_usable_chan(adj_chan)) {
 					factor += ACS_ADJ_WEIGHT *
 						adj_chan->interference_factor;
@@ -986,7 +921,7 @@
 				}
 
 				adj_chan = acs_find_chan(iface, chan->freq +
-							 freq_offset - 10);
+							 (j * 20) - 10);
 				if (adj_chan && acs_usable_chan(adj_chan)) {
 					factor += ACS_NEXT_ADJ_WEIGHT *
 						adj_chan->interference_factor;
@@ -994,7 +929,7 @@
 				}
 
 				adj_chan = acs_find_chan(iface, chan->freq +
-							 freq_offset + 5);
+							 (j * 20) + 5);
 				if (adj_chan && acs_usable_chan(adj_chan)) {
 					factor += ACS_ADJ_WEIGHT *
 						adj_chan->interference_factor;
@@ -1002,7 +937,7 @@
 				}
 
 				adj_chan = acs_find_chan(iface, chan->freq +
-							 freq_offset + 10);
+							 (j * 20) + 10);
 				if (adj_chan && acs_usable_chan(adj_chan)) {
 					factor += ACS_NEXT_ADJ_WEIGHT *
 						adj_chan->interference_factor;
@@ -1011,9 +946,6 @@
 			}
 		}
 
-		if (total_weight == 0)
-			continue;
-
 		factor /= total_weight;
 
 		bias = NULL;
@@ -1051,7 +983,6 @@
 
 			*ideal_factor = factor;
 			*ideal_chan = chan;
-			ideal_bw320_offset = bw320_offset;
 
 #ifdef CONFIG_IEEE80211BE
 			if (iface->conf->ieee80211be)
@@ -1062,13 +993,9 @@
 		}
 
 		/* This channel would at least be usable */
-		if (!(*rand_chan)) {
+		if (!(*rand_chan))
 			*rand_chan = chan;
-			ideal_bw320_offset = bw320_offset;
-		}
 	}
-
-	hostapd_set_and_check_bw320_offset(iface->conf, ideal_bw320_offset);
 }
 
 
@@ -1095,12 +1022,19 @@
 		goto bw_selected;
 	}
 
+	/* TODO: HT40- support */
+
+	if (iface->conf->ieee80211n &&
+	    iface->conf->secondary_channel == -1) {
+		wpa_printf(MSG_ERROR, "ACS: HT40- is not supported yet. Please try HT40+");
+		return NULL;
+	}
+
 	if (iface->conf->ieee80211n &&
 	    iface->conf->secondary_channel)
 		n_chans = 2;
 
-	if (iface->conf->ieee80211ac || iface->conf->ieee80211ax ||
-	    iface->conf->ieee80211be) {
+	if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) {
 		switch (hostapd_get_oper_chwidth(iface->conf)) {
 		case CONF_OPER_CHWIDTH_80MHZ:
 			n_chans = 4;
@@ -1108,9 +1042,6 @@
 		case CONF_OPER_CHWIDTH_160MHZ:
 			n_chans = 8;
 			break;
-		case CONF_OPER_CHWIDTH_320MHZ:
-			n_chans = 16;
-			break;
 		default:
 			break;
 		}
@@ -1160,8 +1091,7 @@
 	    acs_find_mode(iface, iface->freq) != HOSTAPD_MODE_IEEE80211A)
 		return;
 
-	wpa_printf(MSG_DEBUG,
-		   "ACS: Adjusting HT/VHT/HE/EHT secondary frequency");
+	wpa_printf(MSG_DEBUG, "ACS: Adjusting HT/VHT/HE secondary frequency");
 
 	for (i = 0; bw_desc[ACS_BW40][i].first != -1; i++) {
 		if (iface->freq == bw_desc[ACS_BW40][i].first)
@@ -1176,7 +1106,7 @@
 {
 	int center;
 
-	wpa_printf(MSG_DEBUG, "ACS: Adjusting center frequency");
+	wpa_printf(MSG_DEBUG, "ACS: Adjusting VHT center frequency");
 
 	switch (hostapd_get_oper_chwidth(iface->conf)) {
 	case CONF_OPER_CHWIDTH_USE_HT:
@@ -1195,28 +1125,11 @@
 	case CONF_OPER_CHWIDTH_160MHZ:
 		center = acs_get_bw_center_chan(iface->freq, ACS_BW160);
 		break;
-	case CONF_OPER_CHWIDTH_320MHZ:
-		switch (hostapd_get_bw320_offset(iface->conf)) {
-		case 1:
-			center = acs_get_bw_center_chan(iface->freq,
-							ACS_BW320_1);
-			break;
-		case 2:
-			center = acs_get_bw_center_chan(iface->freq,
-							ACS_BW320_2);
-			break;
-		default:
-			wpa_printf(MSG_INFO,
-				   "ACS: BW320 offset is not selected");
-			return;
-		}
-
-		break;
 	default:
 		/* TODO: How can this be calculated? Adjust
 		 * acs_find_ideal_chan() */
 		wpa_printf(MSG_INFO,
-			   "ACS: Only VHT20/40/80/160/320 is supported now");
+			   "ACS: Only VHT20/40/80/160 is supported now");
 		return;
 	}
 
@@ -1279,8 +1192,7 @@
 	iface->conf->punct_bitmap = ideal_chan->punct_bitmap;
 #endif /* CONFIG_IEEE80211BE */
 
-	if (iface->conf->ieee80211ac || iface->conf->ieee80211ax ||
-	    iface->conf->ieee80211be) {
+	if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) {
 		acs_adjust_secondary(iface);
 		acs_adjust_center_freq(iface);
 	}
diff --git a/src/ap/airtime_policy.c b/src/ap/airtime_policy.c
index 6844311..abe817c 100644
--- a/src/ap/airtime_policy.c
+++ b/src/ap/airtime_policy.c
@@ -232,7 +232,7 @@
 	struct airtime_sta_weight *wt;
 
 	wt = hapd->conf->airtime_weight_list;
-	while (wt && !ether_addr_equal(wt->addr, sta))
+	while (wt && os_memcmp(wt->addr, sta, ETH_ALEN) != 0)
 		wt = wt->next;
 
 	return wt ? wt->weight : hapd->conf->airtime_weight;
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 9aa61fa..60d3566 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -1,6 +1,6 @@
 /*
  * hostapd / Configuration helper functions
- * Copyright (c) 2003-2024, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2022, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -163,11 +163,8 @@
 	/* Default to strict CRL checking. */
 	bss->check_crl_strict = 1;
 
-	bss->multi_ap_profile = MULTI_AP_PROFILE_2;
-
 #ifdef CONFIG_TESTING_OPTIONS
 	bss->sae_commit_status = -1;
-	bss->test_assoc_comeback_type = -1;
 #endif /* CONFIG_TESTING_OPTIONS */
 
 #ifdef CONFIG_PASN
@@ -286,10 +283,6 @@
 	conf->he_6ghz_max_ampdu_len_exp = 7;
 	conf->he_6ghz_rx_ant_pat = 1;
 	conf->he_6ghz_tx_ant_pat = 1;
-	conf->he_6ghz_reg_pwr_type = HE_REG_INFO_6GHZ_AP_TYPE_VLP;
-	conf->reg_def_cli_eirp_psd = -1;
-	conf->reg_sub_cli_eirp_psd = -1;
-	conf->reg_def_cli_eirp = -1;
 #endif /* CONFIG_IEEE80211AX */
 
 	/* The third octet of the country string uses an ASCII space character
@@ -304,8 +297,6 @@
 	conf->airtime_update_interval = AIRTIME_DEFAULT_UPDATE_INTERVAL;
 #endif /* CONFIG_AIRTIME_POLICY */
 
-	hostapd_set_and_check_bw320_offset(conf, 0);
-
 	return conf;
 }
 
@@ -559,10 +550,6 @@
 
 	for (i = 0; i < num_servers; i++) {
 		os_free(servers[i].shared_secret);
-		os_free(servers[i].ca_cert);
-		os_free(servers[i].client_cert);
-		os_free(servers[i].private_key);
-		os_free(servers[i].private_key_passwd);
 	}
 	os_free(servers);
 }
@@ -708,33 +695,6 @@
 }
 
 
-#ifdef CONFIG_IEEE80211R_AP
-
-void hostapd_config_clear_rxkhs(struct hostapd_bss_config *conf)
-{
-	struct ft_remote_r0kh *r0kh, *r0kh_prev;
-	struct ft_remote_r1kh *r1kh, *r1kh_prev;
-
-	r0kh = conf->r0kh_list;
-	conf->r0kh_list = NULL;
-	while (r0kh) {
-		r0kh_prev = r0kh;
-		r0kh = r0kh->next;
-		os_free(r0kh_prev);
-	}
-
-	r1kh = conf->r1kh_list;
-	conf->r1kh_list = NULL;
-	while (r1kh) {
-		r1kh_prev = r1kh;
-		r1kh = r1kh->next;
-		os_free(r1kh_prev);
-	}
-}
-
-#endif /* CONFIG_IEEE80211R_AP */
-
-
 static void hostapd_config_free_anqp_elem(struct hostapd_bss_config *conf)
 {
 	struct anqp_element *elem;
@@ -867,9 +827,26 @@
 	os_free(conf->time_zone);
 
 #ifdef CONFIG_IEEE80211R_AP
-	hostapd_config_clear_rxkhs(conf);
-	os_free(conf->rxkh_file);
-	conf->rxkh_file = NULL;
+	{
+		struct ft_remote_r0kh *r0kh, *r0kh_prev;
+		struct ft_remote_r1kh *r1kh, *r1kh_prev;
+
+		r0kh = conf->r0kh_list;
+		conf->r0kh_list = NULL;
+		while (r0kh) {
+			r0kh_prev = r0kh;
+			r0kh = r0kh->next;
+			os_free(r0kh_prev);
+		}
+
+		r1kh = conf->r1kh_list;
+		conf->r1kh_list = NULL;
+		while (r1kh) {
+			r1kh_prev = r1kh;
+			r1kh = r1kh->next;
+			os_free(r1kh_prev);
+		}
+	}
 #endif /* CONFIG_IEEE80211R_AP */
 
 #ifdef CONFIG_WPS
@@ -967,8 +944,6 @@
 	wpabuf_free(conf->rsnxe_override_ft);
 	wpabuf_free(conf->gtk_rsc_override);
 	wpabuf_free(conf->igtk_rsc_override);
-	wpabuf_free(conf->eapol_m1_elements);
-	wpabuf_free(conf->eapol_m3_elements);
 #endif /* CONFIG_TESTING_OPTIONS */
 
 	os_free(conf->no_probe_resp_if_seen_on);
@@ -1156,9 +1131,10 @@
 	for (psk = conf->ssid.wpa_psk; psk != NULL; psk = psk->next) {
 		if (next_ok &&
 		    (psk->group ||
-		     (addr && ether_addr_equal(psk->addr, addr)) ||
+		     (addr && os_memcmp(psk->addr, addr, ETH_ALEN) == 0) ||
 		     (!addr && p2p_dev_addr &&
-		      ether_addr_equal(psk->p2p_dev_addr, p2p_dev_addr)))) {
+		      os_memcmp(psk->p2p_dev_addr, p2p_dev_addr, ETH_ALEN) ==
+		      0))) {
 			if (vlan_id)
 				*vlan_id = psk->vlan_id;
 			return psk->psk;
@@ -1582,10 +1558,6 @@
 			   "Cannot set ieee80211be without ieee80211ax");
 		return -1;
 	}
-
-	if (full_config)
-		hostapd_set_and_check_bw320_offset(conf,
-						   conf->eht_bw320_offset);
 #endif /* CONFIG_IEEE80211BE */
 
 	if (full_config && conf->mbssid && !conf->ieee80211ax) {
@@ -1778,7 +1750,7 @@
 	int i = 0;
 
 	while (i < *num) {
-		if (ether_addr_equal((*acl)[i].addr, addr)) {
+		if (os_memcmp((*acl)[i].addr, addr, ETH_ALEN) == 0) {
 			os_remove_in_array(*acl, *num, sizeof(**acl), i);
 			(*num)--;
 		} else {
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 4f2164d..99a6d18 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -1,6 +1,6 @@
 /*
  * hostapd / Configuration definitions and helpers functions
- * Copyright (c) 2003-2024, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2022, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -405,7 +405,6 @@
 	int ft_over_ds;
 	int ft_psk_generate_local;
 	int r1_max_key_lifetime;
-	char *rxkh_file;
 #endif /* CONFIG_IEEE80211R_AP */
 
 	char *ctrl_interface; /* directory for UNIX domain sockets */
@@ -705,14 +704,6 @@
 	unsigned int oci_freq_override_ft_assoc;
 	unsigned int oci_freq_override_fils_assoc;
 	unsigned int oci_freq_override_wnm_sleep;
-	struct wpabuf *eapol_m1_elements;
-	struct wpabuf *eapol_m3_elements;
-	bool eapol_m3_no_encrypt;
-	int test_assoc_comeback_type;
-
-#ifdef CONFIG_IEEE80211BE
-	u16 eht_oper_puncturing_override;
-#endif /* CONFIG_IEEE80211BE */
 #endif /* CONFIG_TESTING_OPTIONS */
 
 #define MESH_ENABLED BIT(0)
@@ -800,14 +791,6 @@
 #define BACKHAUL_BSS 1
 #define FRONTHAUL_BSS 2
 	int multi_ap; /* bitmap of BACKHAUL_BSS, FRONTHAUL_BSS */
-	int multi_ap_profile;
-	/* Multi-AP Profile-1 clients not allowed to connect */
-#define PROFILE1_CLIENT_ASSOC_DISALLOW BIT(0)
-	/* Multi-AP Profile-2 clients not allowed to connect */
-#define PROFILE2_CLIENT_ASSOC_DISALLOW BIT(1)
-	unsigned int multi_ap_client_disallow;
-	/* Primary VLAN ID to use in Multi-AP */
-	int multi_ap_vlanid;
 
 #ifdef CONFIG_AIRTIME_POLICY
 	unsigned int airtime_weight;
@@ -965,14 +948,6 @@
 
 	/* The AP's MLD MAC address within the AP MLD */
 	u8 mld_addr[ETH_ALEN];
-
-#ifdef CONFIG_TESTING_OPTIONS
-	/*
-	 * If set indicate the AP as disabled in the RNR element included in the
-	 * other APs in the AP MLD.
-	 */
-	bool mld_indicate_disabled;
-#endif /* CONFIG_TESTING_OPTIONS */
 #endif /* CONFIG_IEEE80211BE */
 };
 
@@ -1164,19 +1139,6 @@
 	u8 he_6ghz_rx_ant_pat;
 	u8 he_6ghz_tx_ant_pat;
 	u8 he_6ghz_reg_pwr_type;
-
-	int reg_def_cli_eirp_psd;
-	int reg_sub_cli_eirp_psd;
-
-	/*
-	 * This value should be used when regulatory client EIRP PSD values
-	 * advertised by an AP that is an SP AP or an indoor SP AP are
-	 * insufficient to ensure that regulatory client limits on total EIRP
-	 * are always met for all transmission bandwidths within the bandwidth
-	 * of the AP’s BSS.
-	 */
-	int reg_def_cli_eirp;
-
 	bool require_he;
 #endif /* CONFIG_IEEE80211AX */
 
@@ -1213,8 +1175,6 @@
 	struct eht_phy_capabilities_info eht_phy_capab;
 	u16 punct_bitmap; /* a bitmap of disabled 20 MHz channels */
 	u8 punct_acs_threshold;
-	u8 eht_default_pe_duration;
-	u8 eht_bw320_offset;
 #endif /* CONFIG_IEEE80211BE */
 
 	/* EHT enable/disable config from CHAN_SWITCH */
@@ -1282,8 +1242,7 @@
 #ifdef CONFIG_IEEE80211BE
 	if (conf->ieee80211be)
 		conf->eht_oper_centr_freq_seg0_idx = oper_centr_freq_seg0_idx;
-	if (is_6ghz_op_class(conf->op_class) &&
-	    center_idx_to_bw_6ghz(oper_centr_freq_seg0_idx) == 4)
+	if (center_idx_to_bw_6ghz(oper_centr_freq_seg0_idx) == 4)
 		oper_centr_freq_seg0_idx +=
 			conf->channel > oper_centr_freq_seg0_idx ? 16 : -16;
 #endif /* CONFIG_IEEE80211BE */
@@ -1315,43 +1274,6 @@
 	conf->vht_oper_centr_freq_seg1_idx = oper_centr_freq_seg1_idx;
 }
 
-static inline u8
-hostapd_get_bw320_offset(struct hostapd_config *conf)
-{
-#ifdef CONFIG_IEEE80211BE
-	if (conf->ieee80211be && is_6ghz_op_class(conf->op_class) &&
-	    hostapd_get_oper_chwidth(conf) == CONF_OPER_CHWIDTH_320MHZ)
-		return conf->eht_bw320_offset;
-#endif /* CONFIG_IEEE80211BE */
-	return 0;
-}
-
-static inline void
-hostapd_set_and_check_bw320_offset(struct hostapd_config *conf,
-				   u8 bw320_offset)
-{
-#ifdef CONFIG_IEEE80211BE
-	if (conf->ieee80211be && is_6ghz_op_class(conf->op_class) &&
-	    op_class_to_ch_width(conf->op_class) == CONF_OPER_CHWIDTH_320MHZ) {
-		if (conf->channel) {
-			/* If the channel is set, then calculate bw320_offset
-			 * by center frequency segment 0.
-			 */
-			u8 seg0 = hostapd_get_oper_centr_freq_seg0_idx(conf);
-
-			conf->eht_bw320_offset = (seg0 - 31) % 64 ? 2 : 1;
-		} else {
-			/* If the channel is not set, bw320_offset indicates
-			 * preferred offset of 320 MHz.
-			 */
-			conf->eht_bw320_offset = bw320_offset;
-		}
-	} else {
-		conf->eht_bw320_offset = 0;
-	}
-#endif /* CONFIG_IEEE80211BE */
-}
-
 
 int hostapd_mac_comp(const void *a, const void *b);
 struct hostapd_config * hostapd_config_defaults(void);
@@ -1360,7 +1282,6 @@
 void hostapd_config_free_eap_user(struct hostapd_eap_user *user);
 void hostapd_config_free_eap_users(struct hostapd_eap_user *user);
 void hostapd_config_clear_wpa_psk(struct hostapd_wpa_psk **p);
-void hostapd_config_clear_rxkhs(struct hostapd_bss_config *conf);
 void hostapd_config_free_bss(struct hostapd_bss_config *conf);
 void hostapd_config_free(struct hostapd_config *conf);
 int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries,
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index 11fe39c..8f9cc5b 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -265,35 +265,9 @@
 }
 
 
-bool hostapd_sta_is_link_sta(struct hostapd_data *hapd,
-			     struct sta_info *sta)
-{
-#ifdef CONFIG_IEEE80211BE
-	if (ap_sta_is_mld(hapd, sta) &&
-	    sta->mld_assoc_link_id != hapd->mld_link_id)
-		return true;
-#endif /* CONFIG_IEEE80211BE */
-
-	return false;
-}
-
-
 int hostapd_set_authorized(struct hostapd_data *hapd,
 			   struct sta_info *sta, int authorized)
 {
-	/*
-	 * The WPA_STA_AUTHORIZED flag is relevant only for the MLD station and
-	 * not to the link stations (as the authorization is done between the
-	 * MLD peers). Thus, do not propagate the change to the driver for the
-	 * link stations.
-	 */
-	if (hostapd_sta_is_link_sta(hapd, sta)) {
-		wpa_printf(MSG_DEBUG,
-			   "%s: Do not update link station flags (" MACSTR ")",
-			   __func__, MAC2STR(sta->addr));
-		return 0;
-	}
-
 	if (authorized) {
 		return hostapd_sta_set_flags(hapd, sta->addr,
 					     hostapd_sta_flags_to_drv(
@@ -311,24 +285,11 @@
 {
 	int set_flags, total_flags, flags_and, flags_or;
 	total_flags = hostapd_sta_flags_to_drv(sta->flags);
-	set_flags = WPA_STA_SHORT_PREAMBLE | WPA_STA_WMM | WPA_STA_MFP |
-		WPA_STA_AUTHORIZED;
-
-	/*
-	 * All the station flags other than WPA_STA_SHORT_PREAMBLE are relevant
-	 * only for the MLD station and not to the link stations (as these flags
-	 * are related to the MLD state and not the link state). As for the
-	 * WPA_STA_SHORT_PREAMBLE, since the station is an EHT station, it must
-	 * support short preamble. Thus, do not propagate the change to the
-	 * driver for the link stations.
-	 */
-	if (hostapd_sta_is_link_sta(hapd, sta)) {
-		wpa_printf(MSG_DEBUG,
-			   "%s: Do not update link station flags (" MACSTR ")",
-			   __func__, MAC2STR(sta->addr));
-		return 0;
-	}
-
+	set_flags = WPA_STA_SHORT_PREAMBLE | WPA_STA_WMM | WPA_STA_MFP;
+	if (((!hapd->conf->ieee802_1x && !hapd->conf->wpa) ||
+	     sta->auth_alg == WLAN_AUTH_FT) &&
+	    sta->flags & WLAN_STA_AUTHORIZED)
+		set_flags |= WPA_STA_AUTHORIZED;
 	flags_or = total_flags & set_flags;
 	flags_and = total_flags | ~set_flags;
 	return hostapd_sta_set_flags(hapd, sta->addr, total_flags,
@@ -572,33 +533,12 @@
 }
 
 
-#ifdef CONFIG_IEEE80211BE
-int hostapd_if_link_remove(struct hostapd_data *hapd,
-			   enum wpa_driver_if_type type,
-			   const char *ifname, u8 link_id)
-{
-	if (!hapd->driver || !hapd->drv_priv || !hapd->driver->link_remove)
-		return -1;
-
-	return hapd->driver->link_remove(hapd->drv_priv, type, ifname,
-					 hapd->mld_link_id);
-}
-#endif /* CONFIG_IEEE80211BE */
-
-
 int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type,
 		      const char *ifname)
 {
 	if (hapd->driver == NULL || hapd->drv_priv == NULL ||
 	    hapd->driver->if_remove == NULL)
 		return -1;
-
-#ifdef CONFIG_IEEE80211BE
-	if (hapd->conf->mld_ap)
-		return hostapd_if_link_remove(hapd, type, ifname,
-					      hapd->mld_link_id);
-#endif /* CONFIG_IEEE80211BE */
-
 	return hapd->driver->if_remove(hapd->drv_priv, type, ifname);
 }
 
@@ -650,7 +590,7 @@
 				    &cmode->he_capab[IEEE80211_MODE_AP] : NULL,
 				    cmode ?
 				    &cmode->eht_capab[IEEE80211_MODE_AP] :
-				    NULL, hostapd_get_punct_bitmap(hapd)))
+				    NULL))
 		return -1;
 
 	if (hapd->driver == NULL)
@@ -779,8 +719,6 @@
 struct wpa_scan_results * hostapd_driver_get_scan_results(
 	struct hostapd_data *hapd)
 {
-	if (hapd->driver && hapd->driver->get_scan_results)
-		return hapd->driver->get_scan_results(hapd->drv_priv, NULL);
 	if (hapd->driver && hapd->driver->get_scan_results2)
 		return hapd->driver->get_scan_results2(hapd->drv_priv);
 	return NULL;
@@ -855,21 +793,15 @@
 			   const u8 *addr, int reason)
 {
 	int link_id = -1;
-	const u8 *own_addr = hapd->own_addr;
 
 #ifdef CONFIG_IEEE80211BE
-	if (hapd->conf->mld_ap) {
-		struct sta_info *sta = ap_get_sta(hapd, addr);
-
+	if (hapd->conf->mld_ap)
 		link_id = hapd->mld_link_id;
-		if (ap_sta_is_mld(hapd, sta))
-			own_addr = hapd->mld->mld_addr;
-	}
 #endif /* CONFIG_IEEE80211BE */
 
 	if (!hapd->driver || !hapd->driver->sta_deauth || !hapd->drv_priv)
 		return 0;
-	return hapd->driver->sta_deauth(hapd->drv_priv, own_addr, addr,
+	return hapd->driver->sta_deauth(hapd->drv_priv, hapd->own_addr, addr,
 					reason, link_id);
 }
 
@@ -877,20 +809,9 @@
 int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
 			     const u8 *addr, int reason)
 {
-	const u8 *own_addr = hapd->own_addr;
-
-#ifdef CONFIG_IEEE80211BE
-	if (hapd->conf->mld_ap) {
-		struct sta_info *sta = ap_get_sta(hapd, addr);
-
-		if (ap_sta_is_mld(hapd, sta))
-			own_addr = hapd->mld->mld_addr;
-	}
-#endif /* CONFIG_IEEE80211BE */
-
 	if (!hapd->driver || !hapd->driver->sta_disassoc || !hapd->drv_priv)
 		return 0;
-	return hapd->driver->sta_disassoc(hapd->drv_priv, own_addr, addr,
+	return hapd->driver->sta_disassoc(hapd->drv_priv, hapd->own_addr, addr,
 					  reason);
 }
 
@@ -905,22 +826,22 @@
 }
 
 
-static int hapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq,
-				unsigned int wait, const u8 *dst,
-				const u8 *data, size_t len, bool addr3_ap)
+int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq,
+			    unsigned int wait, const u8 *dst, const u8 *data,
+			    size_t len)
 {
-	const u8 *own_addr = hapd->own_addr;
 	const u8 *bssid;
 	const u8 wildcard_bssid[ETH_ALEN] = {
 		0xff, 0xff, 0xff, 0xff, 0xff, 0xff
 	};
-	struct sta_info *sta;
 
 	if (!hapd->driver || !hapd->driver->send_action || !hapd->drv_priv)
 		return 0;
 	bssid = hapd->own_addr;
-	if (!addr3_ap && !is_multicast_ether_addr(dst) &&
+	if (!is_multicast_ether_addr(dst) &&
 	    len > 0 && data[0] == WLAN_ACTION_PUBLIC) {
+		struct sta_info *sta;
+
 		/*
 		 * Public Action frames to a STA that is not a member of the BSS
 		 * shall use wildcard BSSID value.
@@ -928,7 +849,7 @@
 		sta = ap_get_sta(hapd, dst);
 		if (!sta || !(sta->flags & WLAN_STA_ASSOC))
 			bssid = wildcard_bssid;
-	} else if (!addr3_ap && is_broadcast_ether_addr(dst) &&
+	} else if (is_broadcast_ether_addr(dst) &&
 		   len > 0 && data[0] == WLAN_ACTION_PUBLIC) {
 		/*
 		 * The only current use case of Public Action frames with
@@ -937,27 +858,9 @@
 		 * so have to use the wildcard BSSID value.
 		 */
 		bssid = wildcard_bssid;
-#ifdef CONFIG_IEEE80211BE
-	} else if (hapd->conf->mld_ap) {
-		sta = ap_get_sta(hapd, dst);
-
-		if (ap_sta_is_mld(hapd, sta)) {
-			own_addr = hapd->mld->mld_addr;
-			bssid = own_addr;
-		}
-#endif /* CONFIG_IEEE80211BE */
 	}
-
 	return hapd->driver->send_action(hapd->drv_priv, freq, wait, dst,
-					 own_addr, bssid, data, len, 0);
-}
-
-
-int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq,
-			    unsigned int wait, const u8 *dst, const u8 *data,
-			    size_t len)
-{
-	return hapd_drv_send_action(hapd, freq, wait, dst, data, len, false);
+					 hapd->own_addr, bssid, data, len, 0);
 }
 
 
@@ -966,7 +869,11 @@
 				     unsigned int wait, const u8 *dst,
 				     const u8 *data, size_t len)
 {
-	return hapd_drv_send_action(hapd, freq, wait, dst, data, len, true);
+	if (hapd->driver == NULL || hapd->driver->send_action == NULL)
+		return 0;
+	return hapd->driver->send_action(hapd->drv_priv, freq, wait, dst,
+					 hapd->own_addr, hapd->own_addr, data,
+					 len, 0);
 }
 
 
@@ -1000,8 +907,7 @@
 				    center_segment1,
 				    cmode->vht_capab,
 				    &cmode->he_capab[IEEE80211_MODE_AP],
-				    &cmode->eht_capab[IEEE80211_MODE_AP],
-				    hostapd_get_punct_bitmap(hapd))) {
+				    &cmode->eht_capab[IEEE80211_MODE_AP])) {
 		wpa_printf(MSG_ERROR, "Can't set freq params");
 		return -1;
 	}
@@ -1023,8 +929,7 @@
 int hostapd_drv_set_qos_map(struct hostapd_data *hapd,
 			    const u8 *qos_map_set, u8 qos_map_set_len)
 {
-	if (!hapd->driver || !hapd->driver->set_qos_map || !hapd->drv_priv ||
-	    !(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING))
+	if (!hapd->driver || !hapd->driver->set_qos_map || !hapd->drv_priv)
 		return 0;
 	return hapd->driver->set_qos_map(hapd->drv_priv, qos_map_set,
 					 qos_map_set_len);
@@ -1120,12 +1025,6 @@
 
 	os_memset(&params, 0, sizeof(params));
 	params.hw_mode = hapd->iface->conf->hw_mode;
-	params.link_id = -1;
-#ifdef CONFIG_IEEE80211BE
-	if (hapd->conf->mld_ap && hapd->iconf->ieee80211be &&
-	    !hapd->conf->disable_11be)
-		params.link_id = hapd->mld_link_id;
-#endif /* CONFIG_IEEE80211BE */
 
 	/*
 	 * If no chanlist config parameter is provided, include all enabled
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
index d7e79c8..331b0ea 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -26,8 +26,6 @@
 			       struct wpabuf *assocresp);
 int hostapd_reset_ap_wps_ie(struct hostapd_data *hapd);
 int hostapd_set_ap_wps_ie(struct hostapd_data *hapd);
-bool hostapd_sta_is_link_sta(struct hostapd_data *hapd,
-			     struct sta_info *sta);
 int hostapd_set_authorized(struct hostapd_data *hapd,
 			   struct sta_info *sta, int authorized);
 int hostapd_set_sta_flags(struct hostapd_data *hapd, struct sta_info *sta);
@@ -61,9 +59,6 @@
 		   const char *bridge, int use_existing);
 int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type,
 		      const char *ifname);
-int hostapd_if_link_remove(struct hostapd_data *hapd,
-			   enum wpa_driver_if_type type,
-			   const char *ifname, u8 link_id);
 int hostapd_set_ieee8021x(struct hostapd_data *hapd,
 			  struct wpa_bss_params *params);
 int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd,
@@ -393,15 +388,9 @@
 
 static inline int hostapd_drv_stop_ap(struct hostapd_data *hapd)
 {
-	int link_id = -1;
-
 	if (!hapd->driver || !hapd->driver->stop_ap || !hapd->drv_priv)
 		return 0;
-#ifdef CONFIG_IEEE80211BE
-	if (hapd->conf->mld_ap)
-		link_id = hapd->mld_link_id;
-#endif /* CONFIG_IEEE80211BE */
-	return hapd->driver->stop_ap(hapd->drv_priv, link_id);
+	return hapd->driver->stop_ap(hapd->drv_priv);
 }
 
 static inline int hostapd_drv_channel_info(struct hostapd_data *hapd,
@@ -454,28 +443,15 @@
 #endif /* CONFIG_TESTING_OPTIONS */
 
 #ifdef CONFIG_IEEE80211BE
-
 static inline int hostapd_drv_link_add(struct hostapd_data *hapd,
 				       u8 link_id, const u8 *addr)
 {
 	if (!hapd->driver || !hapd->drv_priv || !hapd->driver->link_add)
 		return -1;
 
-	return hapd->driver->link_add(hapd->drv_priv, link_id, addr, hapd);
+	return hapd->driver->link_add(hapd->drv_priv, link_id, addr);
 
 }
-
-static inline int hostapd_drv_link_sta_remove(struct hostapd_data *hapd,
-					      const u8 *addr)
-{
-	if (!hapd->conf->mld_ap || !hapd->driver || !hapd->drv_priv ||
-	    !hapd->driver->link_sta_remove)
-		return -1;
-
-	return hapd->driver->link_sta_remove(hapd->drv_priv, hapd->mld_link_id,
-					     addr);
-}
-
 #endif /* CONFIG_IEEE80211BE */
 
 #endif /* AP_DRV_OPS */
diff --git a/src/ap/ap_list.c b/src/ap/ap_list.c
index 13facab..20be7f8 100644
--- a/src/ap/ap_list.c
+++ b/src/ap/ap_list.c
@@ -55,7 +55,7 @@
 	struct ap_info *s;
 
 	s = iface->ap_hash[STA_HASH(ap)];
-	while (s != NULL && !ether_addr_equal(s->addr, ap))
+	while (s != NULL && os_memcmp(s->addr, ap, ETH_ALEN) != 0)
 		s = s->hnext;
 	return s;
 }
@@ -100,13 +100,13 @@
 
 	s = iface->ap_hash[STA_HASH(ap->addr)];
 	if (s == NULL) return;
-	if (ether_addr_equal(s->addr, ap->addr)) {
+	if (os_memcmp(s->addr, ap->addr, ETH_ALEN) == 0) {
 		iface->ap_hash[STA_HASH(ap->addr)] = s->hnext;
 		return;
 	}
 
 	while (s->hnext != NULL &&
-	       !ether_addr_equal(s->hnext->addr, ap->addr))
+	       os_memcmp(s->hnext->addr, ap->addr, ETH_ALEN) != 0)
 		s = s->hnext;
 	if (s->hnext != NULL)
 		s->hnext = s->hnext->hnext;
diff --git a/src/ap/authsrv.c b/src/ap/authsrv.c
index 6ed4d06..1488dcc 100644
--- a/src/ap/authsrv.c
+++ b/src/ap/authsrv.c
@@ -107,20 +107,13 @@
 	struct radius_server_conf srv;
 	struct hostapd_bss_config *conf = hapd->conf;
 
-#ifdef CONFIG_IEEE80211BE
-	if (!hostapd_mld_is_first_bss(hapd)) {
-		struct hostapd_data *first;
-
+	if (hapd->mld_first_bss) {
 		wpa_printf(MSG_DEBUG,
 			   "MLD: Using RADIUS server of the first BSS");
 
-		first = hostapd_mld_get_first_bss(hapd);
-		if (!first)
-			return -1;
-		hapd->radius_srv = first->radius_srv;
+		hapd->radius_srv = hapd->mld_first_bss->radius_srv;
 		return 0;
 	}
-#endif /* CONFIG_IEEE80211BE */
 
 	os_memset(&srv, 0, sizeof(srv));
 	srv.client_file = conf->radius_server_clients;
@@ -256,25 +249,18 @@
 
 int authsrv_init(struct hostapd_data *hapd)
 {
-#ifdef CONFIG_IEEE80211BE
-	if (!hostapd_mld_is_first_bss(hapd)) {
-		struct hostapd_data *first;
-
+	if (hapd->mld_first_bss) {
 		wpa_printf(MSG_DEBUG, "MLD: Using auth_serv of the first BSS");
 
-		first = hostapd_mld_get_first_bss(hapd);
-		if (!first)
-			return -1;
 #ifdef EAP_TLS_FUNCS
-		hapd->ssl_ctx = first->ssl_ctx;
+		hapd->ssl_ctx = hapd->mld_first_bss->ssl_ctx;
 #endif /* EAP_TLS_FUNCS */
-		hapd->eap_cfg = first->eap_cfg;
+		hapd->eap_cfg = hapd->mld_first_bss->eap_cfg;
 #ifdef EAP_SIM_DB
-		hapd->eap_sim_db_priv = first->eap_sim_db_priv;
+		hapd->eap_sim_db_priv = hapd->mld_first_bss->eap_sim_db_priv;
 #endif /* EAP_SIM_DB */
 		return 0;
 	}
-#endif /* CONFIG_IEEE80211BE */
 
 #ifdef EAP_TLS_FUNCS
 	if (hapd->conf->eap_server &&
@@ -390,8 +376,7 @@
 
 void authsrv_deinit(struct hostapd_data *hapd)
 {
-#ifdef CONFIG_IEEE80211BE
-	if (!hostapd_mld_is_first_bss(hapd)) {
+	if (hapd->mld_first_bss) {
 		wpa_printf(MSG_DEBUG,
 			   "MLD: Deinit auth_serv of a non-first BSS");
 
@@ -405,7 +390,6 @@
 #endif /* EAP_TLS_FUNCS */
 		return;
 	}
-#endif /* CONFIG_IEEE80211BE */
 
 #ifdef RADIUS_SERVER
 	radius_server_deinit(hapd->radius_srv);
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index 32865f6..1b5cea9 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -239,10 +239,12 @@
 			continue; /* can use same entry */
 		}
 
-		if (start && prev)
+		if (start && prev) {
 			pos = hostapd_eid_country_add(hapd, pos, end,
 						      chan_spacing,
 						      start, prev);
+			start = NULL;
+		}
 
 		/* Start new group */
 		start = prev = chan;
@@ -563,78 +565,19 @@
 }
 
 
-static size_t he_elem_len(struct hostapd_data *hapd)
+static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
+				   const struct ieee80211_mgmt *req,
+				   int is_p2p, size_t *resp_len,
+				   const u8 *known_bss, u8 known_bss_len)
 {
-	size_t len = 0;
-
-#ifdef CONFIG_IEEE80211AX
-	if (!hapd->iconf->ieee80211ax || hapd->conf->disable_11ax)
-		return len;
-
-	len += 3 + sizeof(struct ieee80211_he_capabilities) +
-		3 + sizeof(struct ieee80211_he_operation) +
-		3 + sizeof(struct ieee80211_he_mu_edca_parameter_set) +
-		3 + sizeof(struct ieee80211_spatial_reuse);
-	if (is_6ghz_op_class(hapd->iconf->op_class)) {
-		len += sizeof(struct ieee80211_he_6ghz_oper_info) +
-			3 + sizeof(struct ieee80211_he_6ghz_band_cap);
-		/* An additional Transmit Power Envelope element for
-		 * subordinate client */
-		if (he_reg_is_indoor(hapd->iconf->he_6ghz_reg_pwr_type))
-			len += 4;
-
-		/* An additional Transmit Power Envelope element for
-		 * default client with unit interpretation of regulatory
-		 * client EIRP */
-		if (hapd->iconf->reg_def_cli_eirp != -1 &&
-		    he_reg_is_sp(hapd->iconf->he_6ghz_reg_pwr_type))
-			len += 4;
-	}
-#endif /* CONFIG_IEEE80211AX */
-
-	return len;
-}
-
-
-struct probe_resp_params {
-	const struct ieee80211_mgmt *req;
-	bool is_p2p;
-
-	/* Generated IEs will be included inside an ML element */
-	bool is_ml_sta_info;
-	struct hostapd_data *mld_ap;
-	struct mld_info *mld_info;
-
 	struct ieee80211_mgmt *resp;
-	size_t resp_len;
-	u8 *csa_pos;
-	u8 *ecsa_pos;
-	const u8 *known_bss;
-	u8 known_bss_len;
+	u8 *pos, *epos, *csa_pos;
+	size_t buflen;
 
-#ifdef CONFIG_IEEE80211AX
-	u8 *cca_pos;
-#endif /* CONFIG_IEEE80211AX */
-};
+	hapd = hostapd_mbssid_get_tx_bss(hapd);
 
-
-static void hostapd_free_probe_resp_params(struct probe_resp_params *params)
-{
-#ifdef CONFIG_IEEE80211BE
-	if (!params)
-		return;
-	ap_sta_free_sta_profile(params->mld_info);
-	os_free(params->mld_info);
-	params->mld_info = NULL;
-#endif /* CONFIG_IEEE80211BE */
-}
-
-
-static size_t hostapd_probe_resp_elems_len(struct hostapd_data *hapd,
-					   struct probe_resp_params *params)
-{
-	size_t buflen = 0;
-
+#define MAX_PROBERESP_LEN 768
+	buflen = MAX_PROBERESP_LEN;
 #ifdef CONFIG_WPS
 	if (hapd->wps_probe_resp_ie)
 		buflen += wpabuf_len(hapd->wps_probe_resp_ie);
@@ -654,7 +597,23 @@
 			2 + sizeof(struct ieee80211_vht_operation);
 	}
 
-	buflen += he_elem_len(hapd);
+#ifdef CONFIG_IEEE80211AX
+	if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) {
+		buflen += 3 + sizeof(struct ieee80211_he_capabilities) +
+			3 + sizeof(struct ieee80211_he_operation) +
+			3 + sizeof(struct ieee80211_he_mu_edca_parameter_set) +
+			3 + sizeof(struct ieee80211_spatial_reuse);
+		if (is_6ghz_op_class(hapd->iconf->op_class)) {
+			buflen += sizeof(struct ieee80211_he_6ghz_oper_info) +
+				3 + sizeof(struct ieee80211_he_6ghz_band_cap);
+			 /* An additional Transmit Power Envelope element for
+			  * subordinate client */
+			if (hapd->iconf->he_6ghz_reg_pwr_type ==
+			    HE_6GHZ_INDOOR_AP)
+				buflen += 4;
+		}
+	}
+#endif /* CONFIG_IEEE80211AX */
 
 #ifdef CONFIG_IEEE80211BE
 	if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) {
@@ -663,45 +622,58 @@
 		if (hapd->iconf->punct_bitmap)
 			buflen += EHT_OPER_DISABLED_SUBCHAN_BITMAP_SIZE;
 
-		if (!params->is_ml_sta_info && hapd->conf->mld_ap) {
-			struct hostapd_data *ml_elem_ap =
-				params->mld_ap ? params->mld_ap : hapd;
-
-			buflen += hostapd_eid_eht_ml_beacon_len(
-				ml_elem_ap, params->mld_info, !!params->mld_ap);
-		}
+		/*
+		 * TODO: Multi-Link element has variable length and can be
+		 * long based on the common info and number of per
+		 * station profiles. For now use 256.
+		 */
+		if (hapd->conf->mld_ap)
+			buflen += 256;
 	}
 #endif /* CONFIG_IEEE80211BE */
 
 	buflen += hostapd_eid_mbssid_len(hapd, WLAN_FC_STYPE_PROBE_RESP, NULL,
-					 params->known_bss,
-					 params->known_bss_len, NULL);
-	if (!params->is_ml_sta_info)
-		buflen += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_PROBE_RESP);
+					 known_bss, known_bss_len, NULL);
+	buflen += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_PROBE_RESP);
 	buflen += hostapd_mbo_ie_len(hapd);
 	buflen += hostapd_eid_owe_trans_len(hapd);
 	buflen += hostapd_eid_dpp_cc_len(hapd);
 
-	return buflen;
-}
+	resp = os_zalloc(buflen);
+	if (resp == NULL)
+		return NULL;
 
+	epos = ((u8 *) resp) + MAX_PROBERESP_LEN;
 
-static u8 * hostapd_probe_resp_fill_elems(struct hostapd_data *hapd,
-					  struct probe_resp_params *params,
-					  u8 *pos, size_t len)
-{
-	u8 *csa_pos;
-	u8 *epos;
+	resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
+					   WLAN_FC_STYPE_PROBE_RESP);
+	/* Unicast the response to all requests on bands other than 6 GHz. For
+	 * the 6 GHz, unicast is used only if the actual SSID is not included in
+	 * the Beacon frames. Otherwise, broadcast response is used per IEEE
+	 * Std 802.11ax-2021, 26.17.2.3.2. Broadcast address is also used for
+	 * the Probe Response frame template for the unsolicited (i.e., not as
+	 * a response to a specific request) case. */
+	if (req && (!is_6ghz_op_class(hapd->iconf->op_class) ||
+		    hapd->conf->ignore_broadcast_ssid))
+		os_memcpy(resp->da, req->sa, ETH_ALEN);
+	else
+		os_memset(resp->da, 0xff, ETH_ALEN);
 
-	epos = pos + len;
+	os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN);
 
-	if (!params->is_ml_sta_info) {
-		*pos++ = WLAN_EID_SSID;
-		*pos++ = hapd->conf->ssid.ssid_len;
-		os_memcpy(pos, hapd->conf->ssid.ssid,
-			  hapd->conf->ssid.ssid_len);
-		pos += hapd->conf->ssid.ssid_len;
-	}
+	os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
+	resp->u.probe_resp.beacon_int =
+		host_to_le16(hapd->iconf->beacon_int);
+
+	/* hardware or low-level driver will setup seq_ctrl and timestamp */
+	resp->u.probe_resp.capab_info =
+		host_to_le16(hostapd_own_capab_info(hapd));
+
+	pos = resp->u.probe_resp.variable;
+	*pos++ = WLAN_EID_SSID;
+	*pos++ = hapd->conf->ssid.ssid_len;
+	os_memcpy(pos, hapd->conf->ssid.ssid, hapd->conf->ssid.ssid_len);
+	pos += hapd->conf->ssid.ssid_len;
 
 	/* Supported rates */
 	pos = hostapd_eid_supp_rates(hapd, pos);
@@ -714,18 +686,11 @@
 	/* Power Constraint element */
 	pos = hostapd_eid_pwr_constraint(hapd, pos);
 
-	/*
-	 * CSA IE
-	 * TODO: This should be included inside the ML sta profile
-	 */
-	if (!params->is_ml_sta_info) {
-		csa_pos = hostapd_eid_csa(hapd, pos);
-		if (csa_pos != pos)
-			params->csa_pos = csa_pos - 1;
-		else
-			params->csa_pos = NULL;
-		pos = csa_pos;
-	}
+	/* CSA IE */
+	csa_pos = hostapd_eid_csa(hapd, pos);
+	if (csa_pos != pos)
+		hapd->cs_c_off_proberesp = csa_pos - (u8 *) resp - 1;
+	pos = csa_pos;
 
 	/* ERP Information element */
 	pos = hostapd_eid_erp_info(hapd, pos);
@@ -736,23 +701,16 @@
 	pos = hostapd_get_rsne(hapd, pos, epos - pos);
 	pos = hostapd_eid_bss_load(hapd, pos, epos - pos);
 	pos = hostapd_eid_mbssid(hapd, pos, epos, WLAN_FC_STYPE_PROBE_RESP, 0,
-				 NULL, params->known_bss, params->known_bss_len,
-				 NULL, NULL, NULL, 0);
+				 NULL, known_bss, known_bss_len, NULL, NULL,
+				 NULL, 0);
 	pos = hostapd_eid_rm_enabled_capab(hapd, pos, epos - pos);
 	pos = hostapd_get_mde(hapd, pos, epos - pos);
 
-	/*
-	 * eCSA IE
-	 * TODO: This should be included inside the ML sta profile
-	 */
-	if (!params->is_ml_sta_info) {
-		csa_pos = hostapd_eid_ecsa(hapd, pos);
-		if (csa_pos != pos)
-			params->ecsa_pos = csa_pos - 1;
-		else
-			params->ecsa_pos = NULL;
-		pos = csa_pos;
-	}
+	/* eCSA IE */
+	csa_pos = hostapd_eid_ecsa(hapd, pos);
+	if (csa_pos != pos)
+		hapd->cs_c_off_ecsa_proberesp = csa_pos - (u8 *) resp - 1;
+	pos = csa_pos;
 
 	pos = hostapd_eid_supported_op_classes(hapd, pos);
 	pos = hostapd_eid_ht_capabilities(hapd, pos);
@@ -762,7 +720,7 @@
 	 * when a list of known BSSes is included in the Probe Request frame. */
 	pos = hostapd_eid_ext_capab(hapd, pos,
 				    hapd->iconf->mbssid >= MBSSID_ENABLED &&
-				    !params->known_bss_len);
+				    !known_bss_len);
 
 	pos = hostapd_eid_time_adv(hapd, pos);
 	pos = hostapd_eid_time_zone(hapd, pos);
@@ -796,8 +754,7 @@
 
 	pos = hostapd_eid_wb_chsw_wrapper(hapd, pos);
 
-	if (!params->is_ml_sta_info)
-		pos = hostapd_eid_rnr(hapd, pos, WLAN_FC_STYPE_PROBE_RESP);
+	pos = hostapd_eid_rnr(hapd, pos, WLAN_FC_STYPE_PROBE_RESP);
 	pos = hostapd_eid_fils_indic(hapd, pos, 0);
 	pos = hostapd_get_rsnxe(hapd, pos, epos - pos);
 
@@ -811,9 +768,7 @@
 		/* BSS Color Change Announcement element */
 		cca_pos = hostapd_eid_cca(hapd, pos);
 		if (cca_pos != pos)
-			params->cca_pos = cca_pos - 2;
-		else
-			params->cca_pos = NULL;
+			hapd->cca_c_off_proberesp = cca_pos - (u8 *) resp - 2;
 		pos = cca_pos;
 
 		pos = hostapd_eid_spatial_reuse(hapd, pos);
@@ -824,14 +779,8 @@
 
 #ifdef CONFIG_IEEE80211BE
 	if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) {
-		struct hostapd_data *ml_elem_ap =
-			params->mld_ap ? params->mld_ap : hapd;
-
-		if (ml_elem_ap->conf->mld_ap)
-			pos = hostapd_eid_eht_ml_beacon(
-				ml_elem_ap, params->mld_info,
-				pos, !!params->mld_ap);
-
+		if (hapd->conf->mld_ap)
+			pos = hostapd_eid_eht_basic_ml(hapd, pos, NULL, true);
 		pos = hostapd_eid_eht_capab(hapd, pos, IEEE80211_MODE_AP);
 		pos = hostapd_eid_eht_operation(hapd, pos);
 	}
@@ -858,7 +807,7 @@
 #endif /* CONFIG_WPS */
 
 #ifdef CONFIG_P2P
-	if ((hapd->conf->p2p & P2P_ENABLED) && params->is_p2p &&
+	if ((hapd->conf->p2p & P2P_ENABLED) && is_p2p &&
 	    hapd->p2p_probe_resp_ie) {
 		os_memcpy(pos, wpabuf_head(hapd->p2p_probe_resp_ie),
 			  wpabuf_len(hapd->p2p_probe_resp_ie));
@@ -875,9 +824,9 @@
 	pos = hostapd_eid_hs20_indication(hapd, pos);
 #endif /* CONFIG_HS20 */
 
-	pos = hostapd_eid_mbo(hapd, pos, epos - pos);
-	pos = hostapd_eid_owe_trans(hapd, pos, epos - pos);
-	pos = hostapd_eid_dpp_cc(hapd, pos, epos - pos);
+	pos = hostapd_eid_mbo(hapd, pos, (u8 *) resp + buflen - pos);
+	pos = hostapd_eid_owe_trans(hapd, pos, (u8 *) resp + buflen - pos);
+	pos = hostapd_eid_dpp_cc(hapd, pos, (u8 *) resp + buflen - pos);
 
 	if (hapd->conf->vendor_elements) {
 		os_memcpy(pos, wpabuf_head(hapd->conf->vendor_elements),
@@ -885,171 +834,11 @@
 		pos += wpabuf_len(hapd->conf->vendor_elements);
 	}
 
-	return pos;
+	*resp_len = pos - (u8 *) resp;
+	return (u8 *) resp;
 }
 
 
-static void hostapd_gen_probe_resp(struct hostapd_data *hapd,
-				   struct probe_resp_params *params)
-{
-	u8 *pos;
-	size_t buflen;
-
-	hapd = hostapd_mbssid_get_tx_bss(hapd);
-
-#define MAX_PROBERESP_LEN 768
-	buflen = MAX_PROBERESP_LEN;
-	buflen += hostapd_probe_resp_elems_len(hapd, params);
-	params->resp = os_zalloc(buflen);
-	if (!params->resp) {
-		params->resp_len = 0;
-		return;
-	}
-
-	params->resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
-						   WLAN_FC_STYPE_PROBE_RESP);
-	/* Unicast the response to all requests on bands other than 6 GHz. For
-	 * the 6 GHz, unicast is used only if the actual SSID is not included in
-	 * the Beacon frames. Otherwise, broadcast response is used per IEEE
-	 * Std 802.11ax-2021, 26.17.2.3.2. Broadcast address is also used for
-	 * the Probe Response frame template for the unsolicited (i.e., not as
-	 * a response to a specific request) case. */
-	if (params->req && (!is_6ghz_op_class(hapd->iconf->op_class) ||
-		    hapd->conf->ignore_broadcast_ssid))
-		os_memcpy(params->resp->da, params->req->sa, ETH_ALEN);
-	else
-		os_memset(params->resp->da, 0xff, ETH_ALEN);
-	os_memcpy(params->resp->sa, hapd->own_addr, ETH_ALEN);
-
-	os_memcpy(params->resp->bssid, hapd->own_addr, ETH_ALEN);
-	params->resp->u.probe_resp.beacon_int =
-		host_to_le16(hapd->iconf->beacon_int);
-
-	/* hardware or low-level driver will setup seq_ctrl and timestamp */
-	params->resp->u.probe_resp.capab_info =
-		host_to_le16(hostapd_own_capab_info(hapd));
-
-	pos = hostapd_probe_resp_fill_elems(hapd, params,
-					    params->resp->u.probe_resp.variable,
-					    buflen);
-
-	params->resp_len = pos - (u8 *) params->resp;
-}
-
-
-#ifdef CONFIG_IEEE80211BE
-static void hostapd_fill_probe_resp_ml_params(struct hostapd_data *hapd,
-					      struct probe_resp_params *params,
-					      const struct ieee80211_mgmt *mgmt,
-					      int mld_id, u16 links)
-{
-	struct probe_resp_params sta_info_params;
-	struct hostapd_data *link;
-	unsigned int probed_mld_id, i, j;
-
-	params->mld_ap = NULL;
-	params->mld_info = os_zalloc(sizeof(*params->mld_info));
-	if (!params->mld_info)
-		return;
-
-	wpa_printf(MSG_DEBUG,
-		   "MLD: Got ML probe request with AP MLD ID %d for links %04x",
-		   mld_id, links);
-
-	/*
-	 * We want to include the AP MLD ID in the response if it was
-	 * included in the request.
-	 */
-	probed_mld_id = mld_id != -1 ? mld_id : hostapd_get_mld_id(hapd);
-
-	for_each_mld_link(link, i, j, hapd->iface->interfaces,
-			  probed_mld_id) {
-		struct mld_link_info *link_info;
-		size_t buflen;
-		u8 mld_link_id = link->mld_link_id;
-		u8 *epos;
-		u8 buf[EHT_ML_MAX_STA_PROF_LEN];
-
-		/*
-		 * Set mld_ap iff the ML probe request explicitly
-		 * requested a specific MLD ID. In that case, the targeted
-		 * AP may have been a nontransmitted BSSID on the same
-		 * interface.
-		 */
-		if (mld_id != -1 && link->iface == hapd->iface)
-			params->mld_ap = link;
-
-		/* Never duplicate main Probe Response frame body */
-		if (link == hapd)
-			continue;
-
-		/* Only include requested links */
-		if (!(BIT(mld_link_id) & links))
-			continue;
-
-		link_info = &params->mld_info->links[mld_link_id];
-
-		sta_info_params.req = params->req;
-		sta_info_params.is_p2p = false;
-		sta_info_params.is_ml_sta_info = true;
-		sta_info_params.mld_ap = NULL;
-		sta_info_params.mld_info = NULL;
-
-		buflen = MAX_PROBERESP_LEN;
-		buflen += hostapd_probe_resp_elems_len(link, &sta_info_params);
-
-		if (buflen > EHT_ML_MAX_STA_PROF_LEN) {
-			wpa_printf(MSG_DEBUG,
-				   "MLD: Not including link %d in ML probe response (%zu bytes is too long)",
-				   mld_link_id, buflen);
-			goto fail;
-		}
-
-		/*
-		 * NOTE: This does not properly handle inheritance and
-		 * various other things.
-		 */
-		link_info->valid = true;
-		epos = buf;
-
-		/* Capabilities is the only fixed parameter */
-		WPA_PUT_LE16(epos, hostapd_own_capab_info(hapd));
-		epos += 2;
-
-		epos = hostapd_probe_resp_fill_elems(
-			link, &sta_info_params, epos,
-			EHT_ML_MAX_STA_PROF_LEN - 2);
-		link_info->resp_sta_profile_len = epos - buf;
-		os_free(link_info->resp_sta_profile);
-		link_info->resp_sta_profile = os_memdup(
-			buf, link_info->resp_sta_profile_len);
-		if (!link_info->resp_sta_profile)
-			link_info->resp_sta_profile_len = 0;
-		os_memcpy(link_info->local_addr, link->own_addr, ETH_ALEN);
-
-		wpa_printf(MSG_DEBUG,
-			   "MLD: ML probe response includes link sta info for %d: %u bytes (estimate %zu)",
-			   mld_link_id, link_info->resp_sta_profile_len,
-			   buflen);
-	}
-
-	if (mld_id != -1 && !params->mld_ap) {
-		wpa_printf(MSG_DEBUG,
-			   "MLD: No nontransmitted BSSID for MLD ID %d",
-			   mld_id);
-		goto fail;
-	}
-
-	return;
-
-fail:
-	hostapd_free_probe_resp_params(params);
-	params->mld_ap = NULL;
-	params->mld_info = NULL;
-}
-#endif /* CONFIG_IEEE80211BE */
-
-
 enum ssid_match_result {
 	NO_SSID_MATCH,
 	EXACT_SSID_MATCH,
@@ -1164,7 +953,7 @@
 	struct hostapd_sta_info *info;
 
 	dl_list_for_each(info, &iface->sta_seen, struct hostapd_sta_info, list)
-		if (ether_addr_equal(addr, info->addr))
+		if (os_memcmp(addr, info->addr, ETH_ALEN) == 0)
 			return info;
 
 	return NULL;
@@ -1248,109 +1037,21 @@
 #endif /* CONFIG_TAXONOMY */
 
 
-#ifdef CONFIG_IEEE80211BE
-static bool parse_ml_probe_req(const struct ieee80211_eht_ml *ml, size_t ml_len,
-			       int *mld_id, u16 *links)
-{
-	u16 ml_control;
-	const struct element *sub;
-	const u8 *pos;
-	size_t len;
-
-	*mld_id = -1;
-	*links = 0xffff;
-
-	if (ml_len < sizeof(struct ieee80211_eht_ml))
-		return false;
-
-	ml_control = le_to_host16(ml->ml_control);
-	if ((ml_control & MULTI_LINK_CONTROL_TYPE_MASK) !=
-	    MULTI_LINK_CONTROL_TYPE_PROBE_REQ) {
-		wpa_printf(MSG_DEBUG, "MLD: Not an ML probe req");
-		return false;
-	}
-
-	if (sizeof(struct ieee80211_eht_ml) + 1 > ml_len) {
-		wpa_printf(MSG_DEBUG, "MLD: ML probe req too short");
-		return false;
-	}
-
-	pos = ml->variable;
-	len = pos[0];
-	if (len < 1 || sizeof(struct ieee80211_eht_ml) + len > ml_len) {
-		wpa_printf(MSG_DEBUG,
-			   "MLD: ML probe request with invalid length");
-		return false;
-	}
-
-	if (ml_control & EHT_ML_PRES_BM_PROBE_REQ_AP_MLD_ID) {
-		if (len < 2) {
-			wpa_printf(MSG_DEBUG,
-				   "MLD: ML probe req too short for MLD ID");
-			return false;
-		}
-
-		*mld_id = pos[1];
-	}
-	pos += len;
-
-	/* Parse subelements (if there are any) */
-	len = ml_len - len - sizeof(struct ieee80211_eht_ml);
-	for_each_element_id(sub, 0, pos, len) {
-		const struct ieee80211_eht_per_sta_profile *sta;
-		u16 sta_control;
-
-		if (*links == 0xffff)
-			*links = 0;
-
-		if (sub->datalen <
-		    sizeof(struct ieee80211_eht_per_sta_profile)) {
-			wpa_printf(MSG_DEBUG,
-				   "MLD: ML probe req %d too short for sta profile",
-				   sub->datalen);
-			return false;
-		}
-
-		sta = (struct ieee80211_eht_per_sta_profile *) sub->data;
-
-		/*
-		 * Extract the link ID, do not return whether a complete or
-		 * partial profile was requested.
-		 */
-		sta_control = le_to_host16(sta->sta_control);
-		*links |= BIT(sta_control & EHT_PER_STA_CTRL_LINK_ID_MSK);
-	}
-
-	if (!for_each_element_completed(sub, pos, len)) {
-		wpa_printf(MSG_DEBUG,
-			   "MLD: ML probe req sub-elements parsing error");
-		return false;
-	}
-
-	return true;
-}
-#endif /* CONFIG_IEEE80211BE */
-
-
 void handle_probe_req(struct hostapd_data *hapd,
 		      const struct ieee80211_mgmt *mgmt, size_t len,
 		      int ssi_signal)
 {
+	u8 *resp;
 	struct ieee802_11_elems elems;
 	const u8 *ie;
 	size_t ie_len;
-	size_t i;
+	size_t i, resp_len;
 	int noack;
 	enum ssid_match_result res;
 	int ret;
 	u16 csa_offs[2];
 	size_t csa_offs_len;
 	struct radius_sta rad_info;
-	struct probe_resp_params params;
-#ifdef CONFIG_IEEE80211BE
-	int mld_id;
-	u16 links;
-#endif /* CONFIG_IEEE80211BE */
 
 	if (hapd->iconf->rssi_ignore_probe_request && ssi_signal &&
 	    ssi_signal < hapd->iconf->rssi_ignore_probe_request)
@@ -1516,7 +1217,7 @@
 		else
 			hessid = elems.interworking + 1 + 2;
 		if (!is_broadcast_ether_addr(hessid) &&
-		    !ether_addr_equal(hessid, hapd->conf->hessid)) {
+		    os_memcmp(hessid, hapd->conf->hessid, ETH_ALEN) != 0) {
 			wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
 				   " for mismatching HESSID " MACSTR
 				   " ignored",
@@ -1582,28 +1283,10 @@
 	wpa_msg_ctrl(hapd->msg_ctx, MSG_INFO, RX_PROBE_REQUEST "sa=" MACSTR
 		     " signal=%d", MAC2STR(mgmt->sa), ssi_signal);
 
-	os_memset(&params, 0, sizeof(params));
-
-#ifdef CONFIG_IEEE80211BE
-	if (hapd->conf->mld_ap && elems.probe_req_mle &&
-	    parse_ml_probe_req((struct ieee80211_eht_ml *) elems.probe_req_mle,
-			       elems.probe_req_mle_len, &mld_id, &links)) {
-		hostapd_fill_probe_resp_ml_params(hapd, &params, mgmt,
-						  mld_id, links);
-	}
-#endif /* CONFIG_IEEE80211BE */
-
-	params.req = mgmt;
-	params.is_p2p = !!elems.p2p;
-	params.known_bss = elems.mbssid_known_bss;
-	params.known_bss_len = elems.mbssid_known_bss_len;
-	params.is_ml_sta_info = false;
-
-	hostapd_gen_probe_resp(hapd, &params);
-
-	hostapd_free_probe_resp_params(&params);
-
-	if (!params.resp)
+	resp = hostapd_gen_probe_resp(hapd, mgmt, elems.p2p != NULL,
+				      &resp_len, elems.mbssid_known_bss,
+				      elems.mbssid_known_bss_len);
+	if (resp == NULL)
 		return;
 
 	/*
@@ -1615,23 +1298,24 @@
 
 	csa_offs_len = 0;
 	if (hapd->csa_in_progress) {
-		if (params.csa_pos)
+		if (hapd->cs_c_off_proberesp)
 			csa_offs[csa_offs_len++] =
-				params.csa_pos - (u8 *) params.resp;
+				hapd->cs_c_off_proberesp;
 
-		if (params.ecsa_pos)
+		if (hapd->cs_c_off_ecsa_proberesp)
 			csa_offs[csa_offs_len++] =
-				params.ecsa_pos - (u8 *) params.resp;
+				hapd->cs_c_off_ecsa_proberesp;
 	}
 
-	ret = hostapd_drv_send_mlme(hapd, params.resp, params.resp_len, noack,
+	ret = hostapd_drv_send_mlme(hostapd_mbssid_get_tx_bss(hapd), resp,
+				    resp_len, noack,
 				    csa_offs_len ? csa_offs : NULL,
 				    csa_offs_len, 0);
 
 	if (ret < 0)
 		wpa_printf(MSG_INFO, "handle_probe_req: send failed");
 
-	os_free(params.resp);
+	os_free(resp);
 
 	wpa_printf(MSG_EXCESSIVE, "STA " MACSTR " sent probe request for %s "
 		   "SSID", MAC2STR(mgmt->sa),
@@ -1642,8 +1326,6 @@
 static u8 * hostapd_probe_resp_offloads(struct hostapd_data *hapd,
 					size_t *resp_len)
 {
-	struct probe_resp_params params;
-
 	/* check probe response offloading caps and print warnings */
 	if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_PROBE_RESP_OFFLOAD))
 		return NULL;
@@ -1673,32 +1355,7 @@
 			   "this");
 
 	/* Generate a Probe Response template for the non-P2P case */
-	os_memset(&params, 0, sizeof(params));
-	params.req = NULL;
-	params.is_p2p = false;
-	params.known_bss = NULL;
-	params.known_bss_len = 0;
-	params.is_ml_sta_info = false;
-	params.mld_ap = NULL;
-	params.mld_info = NULL;
-
-	hostapd_gen_probe_resp(hapd, &params);
-	*resp_len = params.resp_len;
-	if (!params.resp)
-		return NULL;
-
-	/* TODO: Avoid passing these through struct hostapd_data */
-	if (params.csa_pos)
-		hapd->cs_c_off_proberesp = params.csa_pos - (u8 *) params.resp;
-	if (params.ecsa_pos)
-		hapd->cs_c_off_ecsa_proberesp = params.ecsa_pos -
-			(u8 *) params.resp;
-#ifdef CONFIG_IEEE80211AX
-	if (params.cca_pos)
-		hapd->cca_c_off_proberesp = params.cca_pos - (u8 *) params.resp;
-#endif /* CONFIG_IEEE80211AX */
-
-	return (u8 *) params.resp;
+	return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len, NULL, 0);
 }
 
 #endif /* NEED_AP_MLME */
@@ -1709,26 +1366,15 @@
 static u8 * hostapd_unsol_bcast_probe_resp(struct hostapd_data *hapd,
 					   struct wpa_driver_ap_params *params)
 {
-	struct probe_resp_params probe_params;
-
 	if (!is_6ghz_op_class(hapd->iconf->op_class))
 		return NULL;
 
 	params->unsol_bcast_probe_resp_interval =
 		hapd->conf->unsol_bcast_probe_resp_interval;
 
-	os_memset(&probe_params, 0, sizeof(probe_params));
-	probe_params.req = NULL;
-	probe_params.is_p2p = false;
-	probe_params.known_bss = NULL;
-	probe_params.known_bss_len = 0;
-	probe_params.is_ml_sta_info = false;
-	probe_params.mld_ap = NULL;
-	probe_params.mld_info = NULL;
-
-	hostapd_gen_probe_resp(hapd, &probe_params);
-	params->unsol_bcast_probe_resp_tmpl_len = probe_params.resp_len;
-	return (u8 *) probe_params.resp;
+	return hostapd_gen_probe_resp(hapd, NULL, 0,
+				      &params->unsol_bcast_probe_resp_tmpl_len,
+				      NULL, 0);
 }
 #endif /* CONFIG_IEEE80211AX */
 
@@ -1960,9 +1606,14 @@
 	buf_len = pos - buf;
 	total_len += buf_len;
 
-	/* he_elem_len() may return too large a value for FD frame, but that is
-	 * fine here since this is used as the maximum length of the buffer. */
-	total_len += he_elem_len(hapd);
+#ifdef CONFIG_IEEE80211AX
+	/* Transmit Power Envelope element(s) */
+	if (is_6ghz_op_class(hapd->iconf->op_class)) {
+		total_len += 4;
+		if (hapd->iconf->he_6ghz_reg_pwr_type == HE_6GHZ_INDOOR_AP)
+			total_len += 4;
+	}
+#endif /* CONFIG_IEEE80211AX */
 
 	head = os_zalloc(total_len);
 	if (!head)
@@ -2112,7 +1763,23 @@
 	}
 #endif /* CONFIG_IEEE80211AC */
 
-	tail_len += he_elem_len(hapd);
+#ifdef CONFIG_IEEE80211AX
+	if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) {
+		tail_len += 3 + sizeof(struct ieee80211_he_capabilities) +
+			3 + sizeof(struct ieee80211_he_operation) +
+			3 + sizeof(struct ieee80211_he_mu_edca_parameter_set) +
+			3 + sizeof(struct ieee80211_spatial_reuse);
+		if (is_6ghz_op_class(hapd->iconf->op_class)) {
+			tail_len += sizeof(struct ieee80211_he_6ghz_oper_info) +
+				3 + sizeof(struct ieee80211_he_6ghz_band_cap);
+			 /* An additional Transmit Power Envelope element for
+			  * subordinate client */
+			if (hapd->iconf->he_6ghz_reg_pwr_type ==
+			    HE_6GHZ_INDOOR_AP)
+				tail_len += 4;
+		}
+	}
+#endif /* CONFIG_IEEE80211AX */
 
 #ifdef CONFIG_IEEE80211BE
 	if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) {
@@ -2299,8 +1966,8 @@
 #ifdef CONFIG_IEEE80211BE
 	if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) {
 		if (hapd->conf->mld_ap)
-			tailpos = hostapd_eid_eht_ml_beacon(hapd, NULL,
-							    tailpos, false);
+			tailpos = hostapd_eid_eht_basic_ml(hapd, tailpos, NULL,
+							   true);
 		tailpos = hostapd_eid_eht_capab(hapd, tailpos,
 						IEEE80211_MODE_AP);
 		tailpos = hostapd_eid_eht_operation(hapd, tailpos);
@@ -2616,8 +2283,7 @@
 				    hostapd_get_oper_centr_freq_seg1_idx(iconf),
 				    cmode->vht_capab,
 				    &cmode->he_capab[IEEE80211_MODE_AP],
-				    &cmode->eht_capab[IEEE80211_MODE_AP],
-				    hostapd_get_punct_bitmap(hapd)) == 0)
+				    &cmode->eht_capab[IEEE80211_MODE_AP]) == 0)
 		params.freq = &freq;
 
 	for (i = 0; i < hapd->iface->num_hw_features; i++) {
@@ -2676,7 +2342,8 @@
 			continue;
 
 #ifdef CONFIG_IEEE80211BE
-		if (hostapd_is_ml_partner(hapd, other->bss[0]))
+		if (hapd->conf->mld_ap && other->bss[0]->conf->mld_ap &&
+		    hapd->conf->mld_id == other->bss[0]->conf->mld_id)
 			mld_ap = true;
 #endif /* CONFIG_IEEE80211BE */
 
diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
index eac0606..a6fcb7e 100644
--- a/src/ap/ctrl_iface_ap.c
+++ b/src/ap/ctrl_iface_ap.c
@@ -348,15 +348,11 @@
 
 	if (sta->supp_op_classes &&
 	    buflen - len > (unsigned) (17 + 2 * sta->supp_op_classes[0])) {
-		res = os_snprintf(buf + len, buflen - len, "supp_op_classes=");
-		if (!os_snprintf_error(buflen - len, res))
-			len += res;
+		len += os_snprintf(buf + len, buflen - len, "supp_op_classes=");
 		len += wpa_snprintf_hex(buf + len, buflen - len,
 					sta->supp_op_classes + 1,
 					sta->supp_op_classes[0]);
-		res = os_snprintf(buf + len, buflen - len, "\n");
-		if (!os_snprintf_error(buflen - len, res))
-			len += res;
+		len += os_snprintf(buf + len, buflen - len, "\n");
 	}
 
 	if (sta->power_capab) {
@@ -368,34 +364,6 @@
 			len += ret;
 	}
 
-#ifdef CONFIG_IEEE80211AX
-	if ((sta->flags & WLAN_STA_HE) && sta->he_capab) {
-		res = os_snprintf(buf + len, buflen - len, "he_capab=");
-		if (!os_snprintf_error(buflen - len, res))
-			len += res;
-		len += wpa_snprintf_hex(buf + len, buflen - len,
-					(const u8 *) sta->he_capab,
-					sta->he_capab_len);
-		res = os_snprintf(buf + len, buflen - len, "\n");
-		if (!os_snprintf_error(buflen - len, res))
-			len += res;
-	}
-#endif /* CONFIG_IEEE80211AX */
-
-#ifdef CONFIG_IEEE80211BE
-	if ((sta->flags & WLAN_STA_EHT) && sta->eht_capab) {
-		res = os_snprintf(buf + len, buflen - len, "eht_capab=");
-		if (!os_snprintf_error(buflen - len, res))
-			len += res;
-		len += wpa_snprintf_hex(buf + len, buflen - len,
-					(const u8 *) sta->eht_capab,
-					sta->eht_capab_len);
-		res = os_snprintf(buf + len, buflen - len, "\n");
-		if (!os_snprintf_error(buflen - len, res))
-			len += res;
-	}
-#endif /* CONFIG_IEEE80211BE */
-
 #ifdef CONFIG_IEEE80211AC
 	if ((sta->flags & WLAN_STA_VHT) && sta->vht_capabilities) {
 		res = os_snprintf(buf + len, buflen - len,
@@ -404,16 +372,6 @@
 					       vht_capabilities_info));
 		if (!os_snprintf_error(buflen - len, res))
 			len += res;
-
-		res = os_snprintf(buf + len, buflen - len, "vht_capab=");
-		if (!os_snprintf_error(buflen - len, res))
-			len += res;
-		len += wpa_snprintf_hex(buf + len, buflen - len,
-					(const u8 *) sta->vht_capabilities,
-					sizeof(*sta->vht_capabilities));
-		res = os_snprintf(buf + len, buflen - len, "\n");
-		if (!os_snprintf_error(buflen - len, res))
-			len += res;
 	}
 #endif /* CONFIG_IEEE80211AC */
 
@@ -428,15 +386,11 @@
 
 	if (sta->ext_capability &&
 	    buflen - len > (unsigned) (11 + 2 * sta->ext_capability[0])) {
-		res = os_snprintf(buf + len, buflen - len, "ext_capab=");
-		if (!os_snprintf_error(buflen - len, res))
-			len += res;
+		len += os_snprintf(buf + len, buflen - len, "ext_capab=");
 		len += wpa_snprintf_hex(buf + len, buflen - len,
 					sta->ext_capability + 1,
 					sta->ext_capability[0]);
-		res = os_snprintf(buf + len, buflen - len, "\n");
-		if (!os_snprintf_error(buflen - len, res))
-			len += res;
+		len += os_snprintf(buf + len, buflen - len, "\n");
 	}
 
 	if (sta->flags & WLAN_STA_WDS && sta->ifname_wds) {
@@ -465,21 +419,6 @@
 			len += ret;
 	}
 
-#ifdef CONFIG_IEEE80211BE
-	if (sta->mld_info.mld_sta) {
-		for (i = 0; i < MAX_NUM_MLD_LINKS; ++i) {
-			if (!sta->mld_info.links[i].valid)
-				continue;
-			ret = os_snprintf(
-				buf + len, buflen - len,
-				"peer_addr[%d]=" MACSTR "\n",
-				i, MAC2STR(sta->mld_info.links[i].peer_addr));
-			if (!os_snprintf_error(buflen - len, ret))
-				len += ret;
-		}
-	}
-#endif /* CONFIG_IEEE80211BE */
-
 	return len;
 }
 
@@ -891,17 +830,6 @@
 		if (os_snprintf_error(buflen - len, ret))
 			return len;
 		len += ret;
-
-		if (is_6ghz_op_class(iface->conf->op_class) &&
-		    hostapd_get_oper_chwidth(iface->conf) ==
-		    CONF_OPER_CHWIDTH_320MHZ) {
-			ret = os_snprintf(buf + len, buflen - len,
-					  "eht_bw320_offset=%d\n",
-					  iface->conf->eht_bw320_offset);
-			if (os_snprintf_error(buflen - len, ret))
-				return len;
-			len += ret;
-		}
 	}
 #endif /* CONFIG_IEEE80211BE */
 
@@ -1027,8 +955,8 @@
 					  "mld_addr[%d]=" MACSTR "\n"
 					  "mld_id[%d]=%d\n"
 					  "mld_link_id[%d]=%d\n",
-					  (int) i, MAC2STR(bss->mld->mld_addr),
-					  (int) i, hostapd_get_mld_id(bss),
+					  (int) i, MAC2STR(bss->mld_addr),
+					  (int) i, bss->conf->mld_id,
 					  (int) i, bss->mld_link_id);
 			if (os_snprintf_error(buflen - len, ret))
 				return len;
@@ -1166,7 +1094,7 @@
 		return -1;
 
 	return wpa_auth_pmksa_add2(hapd->wpa_auth, spa, pmk, pmk_len,
-				   pmkid, expiration, akmp, NULL);
+				   pmkid, expiration, akmp);
 }
 
 
@@ -1387,8 +1315,6 @@
 		req_mode |= WNM_BSS_TM_REQ_ABRIDGED;
 	if (os_strstr(cmd, " disassoc_imminent=1"))
 		req_mode |= WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
-	if (os_strstr(cmd, " link_removal_imminent=1"))
-		req_mode |= WNM_BSS_TM_REQ_LINK_REMOVAL_IMMINENT;
 
 #ifdef CONFIG_MBO
 	pos = os_strstr(cmd, "mbo=");
diff --git a/src/ap/dfs.c b/src/ap/dfs.c
index af9dc16..9a5d3c8 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -14,7 +14,6 @@
 #include "common/hw_features_common.h"
 #include "common/wpa_ctrl.h"
 #include "hostapd.h"
-#include "beacon.h"
 #include "ap_drv_ops.h"
 #include "drivers/driver.h"
 #include "dfs.h"
@@ -189,7 +188,7 @@
 	 * If it's not allowed to use the first channel as primary, decline the
 	 * whole channel range. */
 	if (!chan_pri_allowed(first_chan)) {
-		wpa_printf(MSG_DEBUG, "DFS: primary channel not allowed");
+		wpa_printf(MSG_DEBUG, "DFS: primary chanenl not allowed");
 		return 0;
 	}
 
@@ -552,8 +551,6 @@
 	if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0)
 		return NULL;
 	chan_idx = _rand % num_available_chandefs;
-	wpa_printf(MSG_DEBUG, "DFS: Picked random entry from the list: %d/%d",
-		   chan_idx, num_available_chandefs);
 	dfs_find_channel(iface, &chan, chan_idx, type);
 	if (!chan) {
 		wpa_printf(MSG_DEBUG, "DFS: no random channel found");
@@ -973,7 +970,6 @@
 	struct csa_settings csa_settings;
 	u8 new_vht_oper_chwidth;
 	unsigned int i;
-	unsigned int num_err = 0;
 
 	wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d", channel);
 	wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NEW_CHANNEL
@@ -987,11 +983,6 @@
 	os_memset(&csa_settings, 0, sizeof(csa_settings));
 	csa_settings.cs_count = 5;
 	csa_settings.block_tx = 1;
-	csa_settings.link_id = -1;
-#ifdef CONFIG_IEEE80211BE
-	if (iface->bss[0]->conf->mld_ap)
-		csa_settings.link_id = iface->bss[0]->mld_link_id;
-#endif /* CONFIG_IEEE80211BE */
 #ifdef CONFIG_MESH
 	if (iface->mconf)
 		ieee80211_mode = IEEE80211_MODE_MESH;
@@ -1011,8 +1002,7 @@
 				      oper_centr_freq_seg1_idx,
 				      cmode->vht_capab,
 				      &cmode->he_capab[ieee80211_mode],
-				      &cmode->eht_capab[ieee80211_mode],
-				      hostapd_get_punct_bitmap(iface->bss[0]));
+				      &cmode->eht_capab[ieee80211_mode]);
 
 	if (err) {
 		wpa_printf(MSG_ERROR,
@@ -1024,10 +1014,10 @@
 	for (i = 0; i < iface->num_bss; i++) {
 		err = hostapd_switch_channel(iface->bss[i], &csa_settings);
 		if (err)
-			num_err++;
+			break;
 	}
 
-	if (num_err == iface->num_bss) {
+	if (err) {
 		wpa_printf(MSG_WARNING,
 			   "DFS failed to schedule CSA (%d) - trying fallback",
 			   err);
@@ -1054,7 +1044,7 @@
 }
 
 
-static void hostapd_dfs_update_background_chain(struct hostapd_iface *iface)
+static void hostpad_dfs_update_background_chain(struct hostapd_iface *iface)
 {
 	int sec = 0;
 	enum dfs_channel_type channel_type = DFS_NO_CAC_YET;
@@ -1129,7 +1119,7 @@
 	hostapd_set_oper_centr_freq_seg1_idx(
 		iface->conf, iface->radar_background.centr_freq_seg1_idx);
 
-	hostapd_dfs_update_background_chain(iface);
+	hostpad_dfs_update_background_chain(iface);
 
 	return hostapd_dfs_request_channel_switch(
 		iface, iface->conf->channel, iface->freq,
@@ -1144,23 +1134,14 @@
 			     int cf1, int cf2)
 {
 	wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_COMPLETED
-		"success=%d freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d radar_detected=%d",
-		success, freq, ht_enabled, chan_offset, chan_width, cf1, cf2,
-		iface->radar_detected);
+		"success=%d freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d",
+		success, freq, ht_enabled, chan_offset, chan_width, cf1, cf2);
 
 	if (success) {
 		/* Complete iface/ap configuration */
 		if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) {
-			/* Complete AP configuration for the first bring up. If
-			 * a radar was detected in this channel, interface setup
-			 * will be handled in
-			 * 1. hostapd_event_ch_switch() if switching to a
-			 *    non-DFS channel
-			 * 2. on next CAC complete event if switching to another
-			 *    DFS channel.
-			 */
-			if (iface->state != HAPD_IFACE_ENABLED &&
-			    !iface->radar_detected)
+			/* Complete AP configuration for the first bring up. */
+			if (iface->state != HAPD_IFACE_ENABLED)
 				hostapd_setup_interface_complete(iface, 0);
 			else
 				iface->cac_started = 0;
@@ -1202,10 +1183,9 @@
 		}
 	} else if (hostapd_dfs_is_background_event(iface, freq)) {
 		iface->radar_background.cac_started = 0;
-		hostapd_dfs_update_background_chain(iface);
+		hostpad_dfs_update_background_chain(iface);
 	}
 
-	iface->radar_detected = false;
 	return 0;
 }
 
@@ -1337,7 +1317,7 @@
 		 * Just select a new random channel according to the
 		 * regulations for monitoring.
 		 */
-		hostapd_dfs_update_background_chain(iface);
+		hostpad_dfs_update_background_chain(iface);
 		return 0;
 	}
 
@@ -1449,8 +1429,6 @@
 		"freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d",
 		freq, ht_enabled, chan_offset, chan_width, cf1, cf2);
 
-	iface->radar_detected = true;
-
 	/* Proceed only if DFS is not offloaded to the driver */
 	if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)
 		return 0;
@@ -1501,7 +1479,7 @@
 	} else if (dfs_use_radar_background(iface) &&
 		   iface->radar_background.channel == -1) {
 		/* Reset radar background chain if disabled */
-		hostapd_dfs_update_background_chain(iface);
+		hostpad_dfs_update_background_chain(iface);
 	}
 
 	return 0;
@@ -1544,17 +1522,9 @@
 		iface->radar_background.cac_started = 1;
 	} else {
 		/* This is called when the driver indicates that an offloaded
-		 * DFS has started CAC. radar_detected might be set for previous
-		 * DFS channel. Clear it for this new CAC process. */
+		 * DFS has started CAC. */
 		hostapd_set_state(iface, HAPD_IFACE_DFS);
 		iface->cac_started = 1;
-
-		/* Clear radar_detected in case it is for the previous
-		 * frequency. Also remove disabled link's information in RNR
-		 * element from other links. */
-		iface->radar_detected = false;
-		if (iface->interfaces && iface->interfaces->count > 1)
-			ieee802_11_set_beacons(iface);
 	}
 	/* TODO: How to check CAC time for ETSI weather channels? */
 	iface->dfs_cac_ms = 60000;
diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c
index d1bffa8..7a8ea4e 100644
--- a/src/ap/dpp_hostapd.c
+++ b/src/ap/dpp_hostapd.c
@@ -539,15 +539,8 @@
 		return;
 	}
 
-	if (hapd->dpp_auth_ok_on_ack) {
+	if (hapd->dpp_auth_ok_on_ack)
 		hostapd_dpp_auth_success(hapd, 1);
-		if (!hapd->dpp_auth) {
-			/* The authentication session could have been removed in
-			 * some error cases, e.g., when starting GAS client and
-			 * failing to send the initial request. */
-			return;
-		}
-	}
 
 	if (!is_broadcast_ether_addr(dst) && !ok) {
 		wpa_printf(MSG_DEBUG,
@@ -1420,7 +1413,7 @@
 	}
 
 	if (!is_zero_ether_addr(auth->peer_mac_addr) &&
-	    !ether_addr_equal(src, auth->peer_mac_addr)) {
+	    os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
 			   MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
 		return;
@@ -1470,7 +1463,7 @@
 		return;
 	}
 
-	if (!ether_addr_equal(src, auth->peer_mac_addr)) {
+	if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
 			   MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
 		return;
@@ -1579,7 +1572,7 @@
 		return;
 	}
 
-	if (!ether_addr_equal(src, auth->peer_mac_addr)) {
+	if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
 			   MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
 		return;
@@ -1865,7 +1858,7 @@
 		return;
 	}
 
-	if (!ether_addr_equal(src, auth->peer_mac_addr)) {
+	if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
 			   MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
 		return;
@@ -2140,7 +2133,7 @@
 	else
 		expiration = 0;
 
-	if (wpa_auth_pmksa_add2(hapd->wpa_auth, src, intro.pmk, intro.pmk_len,
+	if (wpa_auth_pmksa_add3(hapd->wpa_auth, src, intro.pmk, intro.pmk_len,
 				intro.pmkid, expiration,
 				WPA_KEY_MGMT_DPP, pkhash) < 0) {
 		wpa_printf(MSG_ERROR, "DPP: Failed to add PMKSA cache entry");
@@ -2914,7 +2907,7 @@
 	else
 		expiration = 0;
 
-	if (wpa_auth_pmksa_add2(hapd->wpa_auth, src, intro.pmk, intro.pmk_len,
+	if (wpa_auth_pmksa_add3(hapd->wpa_auth, src, intro.pmk, intro.pmk_len,
 				intro.pmkid, expiration,
 				WPA_KEY_MGMT_DPP, pkhash) < 0) {
 		wpa_printf(MSG_ERROR, "DPP: Failed to add PMKSA cache entry");
@@ -3080,7 +3073,7 @@
 
 	wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR, MAC2STR(sa));
 	if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
-	    !ether_addr_equal(sa, auth->peer_mac_addr)) {
+	    os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
 #ifdef CONFIG_DPP2
 		if (dpp_relay_rx_gas_req(hapd->iface->interfaces->dpp, sa, data,
 				     data_len) == 0) {
@@ -3101,13 +3094,6 @@
 		 * exchange. */
 		dpp_notify_auth_success(hapd->dpp_auth, 1);
 		hapd->dpp_auth_ok_on_ack = 0;
-#ifdef CONFIG_TESTING_OPTIONS
-		if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
-			wpa_printf(MSG_INFO,
-				   "DPP: TESTING - stop at Authentication Confirm");
-			return NULL;
-		}
-#endif /* CONFIG_TESTING_OPTIONS */
 	}
 
 	wpa_hexdump(MSG_DEBUG,
@@ -3941,7 +3927,6 @@
 	eloop_register_timeout(100, 0, hostapd_dpp_push_button_expire,
 			       hapd, NULL);
 
-	wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_PB_STATUS "started");
 	return 0;
 }
 
@@ -3963,25 +3948,11 @@
 	ifaces->dpp_pb_time.usec = 0;
 	dpp_pkex_free(hapd->dpp_pkex);
 	hapd->dpp_pkex = NULL;
-	hapd->dpp_pkex_bi = NULL;
 	os_free(hapd->dpp_pkex_auth_cmd);
 	hapd->dpp_pkex_auth_cmd = NULL;
 
 	if (ifaces->dpp_pb_bi) {
 		char id[20];
-		size_t i;
-
-		for (i = 0; i < ifaces->count; i++) {
-			struct hostapd_iface *iface = ifaces->iface[i];
-			size_t j;
-
-			for (j = 0; iface && j < iface->num_bss; j++) {
-				struct hostapd_data *h = iface->bss[j];
-
-				if (h->dpp_pkex_bi == ifaces->dpp_pb_bi)
-					h->dpp_pkex_bi = NULL;
-			}
-		}
 
 		os_snprintf(id, sizeof(id), "%u", ifaces->dpp_pb_bi->id);
 		dpp_bootstrap_remove(ifaces->dpp, id);
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index b0fcd1c..98794c2 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -42,7 +42,6 @@
 #include "dpp_hostapd.h"
 #include "fils_hlp.h"
 #include "neighbor_db.h"
-#include "nan_usd_ap.h"
 
 
 #ifdef CONFIG_FILS
@@ -53,7 +52,6 @@
 	struct ieee802_11_elems elems;
 	u8 buf[IEEE80211_MAX_MMPDU_SIZE], *p = buf;
 	int new_assoc;
-	bool updated;
 
 	wpa_printf(MSG_DEBUG, "%s FILS: Finish association with " MACSTR,
 		   __func__, MAC2STR(sta->addr));
@@ -78,13 +76,11 @@
 				      sta->fils_pending_assoc_is_reassoc,
 				      WLAN_STATUS_SUCCESS,
 				      buf, p - buf);
-	updated = ap_sta_set_authorized_flag(hapd, sta, 1);
+	ap_sta_set_authorized(hapd, sta, 1);
 	new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
 	sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
 	sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE;
 	hostapd_set_sta_flags(hapd, sta);
-	if (updated)
-		ap_sta_set_authorized_event(hapd, sta, 1);
 	wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FILS);
 	ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
 	hostapd_new_assoc_sta(hapd, sta, !new_assoc);
@@ -162,7 +158,7 @@
 		return -1;
 	}
 
-	mlebuf = ieee802_11_defrag(elems.basic_mle, elems.basic_mle_len, true);
+	mlebuf = ieee802_11_defrag_mle(&elems, MULTI_LINK_CONTROL_TYPE_BASIC);
 	if (!mlebuf) {
 		wpa_printf(MSG_ERROR,
 			   "MLO: Basic Multi-Link element not found in (Re)Association Response frame");
@@ -267,7 +263,6 @@
 #ifdef CONFIG_OWE
 	struct hostapd_iface *iface = hapd->iface;
 #endif /* CONFIG_OWE */
-	bool updated = false;
 
 	if (addr == NULL) {
 		/*
@@ -284,7 +279,7 @@
 
 	if (is_multicast_ether_addr(addr) ||
 	    is_zero_ether_addr(addr) ||
-	    ether_addr_equal(addr, hapd->own_addr)) {
+	    os_memcmp(addr, hapd->own_addr, ETH_ALEN) == 0) {
 		/* Do not process any frames with unexpected/invalid SA so that
 		 * we do not add any state for unexpected STA addresses or end
 		 * up sending out frames to unexpected destination. */
@@ -363,7 +358,7 @@
 		int i, num_valid_links = 0;
 		u8 link_id = hapd->mld_link_id;
 
-		ap_sta_set_mld(sta, true);
+		info->mld_sta = true;
 		sta->mld_assoc_link_id = link_id;
 		os_memcpy(info->common_info.mld_addr, addr, ETH_ALEN);
 		info->links[link_id].valid = true;
@@ -514,10 +509,10 @@
 			return -1;
 		}
 #ifdef CONFIG_IEEE80211BE
-		if (ap_sta_is_mld(hapd, sta)) {
+		if (sta->mld_info.mld_sta) {
 			wpa_printf(MSG_DEBUG,
 				   "MLD: Set ML info in RSN Authenticator");
-			wpa_auth_set_ml_info(sta->wpa_sm, hapd->mld->mld_addr,
+			wpa_auth_set_ml_info(sta->wpa_sm, hapd->mld_addr,
 					     sta->mld_assoc_link_id,
 					     &sta->mld_info);
 		}
@@ -850,30 +845,18 @@
 	    sta->auth_alg == WLAN_AUTH_FILS_SK ||
 	    sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
 	    sta->auth_alg == WLAN_AUTH_FILS_PK)
-		updated = ap_sta_set_authorized_flag(hapd, sta, 1);
+		ap_sta_set_authorized(hapd, sta, 1);
 #else /* CONFIG_IEEE80211R_AP || CONFIG_FILS */
 	/* Keep compiler silent about unused variables */
 	if (status) {
 	}
 #endif /* CONFIG_IEEE80211R_AP || CONFIG_FILS */
 
-#ifdef CONFIG_IEEE80211BE
-	if (hostapd_process_assoc_ml_info(hapd, sta, req_ies, req_ies_len,
-					  !!reassoc, WLAN_STATUS_SUCCESS,
-					  true)) {
-		status = WLAN_STATUS_UNSPECIFIED_FAILURE;
-		reason = WLAN_REASON_UNSPECIFIED;
-		goto fail;
-	}
-#endif /* CONFIG_IEEE80211BE */
-
 	new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
 	sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
 	sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE;
 
 	hostapd_set_sta_flags(hapd, sta);
-	if (updated)
-		ap_sta_set_authorized_event(hapd, sta, 1);
 
 	if (reassoc && (sta->auth_alg == WLAN_AUTH_FT))
 		wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT);
@@ -910,54 +893,6 @@
 }
 
 
-static void hostapd_remove_sta(struct hostapd_data *hapd, struct sta_info *sta)
-{
-	ap_sta_set_authorized(hapd, sta, 0);
-	sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
-	hostapd_set_sta_flags(hapd, sta);
-	wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
-	sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
-	ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
-	ap_free_sta(hapd, sta);
-}
-
-
-#ifdef CONFIG_IEEE80211BE
-static void hostapd_notif_disassoc_mld(struct hostapd_data *assoc_hapd,
-				       struct sta_info *sta,
-				       const u8 *addr)
-{
-	unsigned int link_id, i;
-	struct hostapd_data *tmp_hapd;
-	struct hapd_interfaces *interfaces = assoc_hapd->iface->interfaces;
-
-	/* Remove STA entry in non-assoc links */
-	for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
-		if (!sta->mld_info.links[link_id].valid)
-			continue;
-
-		for (i = 0; i < interfaces->count; i++) {
-			struct sta_info *tmp_sta;
-
-			tmp_hapd = interfaces->iface[i]->bss[0];
-
-			if (!tmp_hapd->conf->mld_ap ||
-			    assoc_hapd == tmp_hapd ||
-			    assoc_hapd->conf->mld_id != tmp_hapd->conf->mld_id)
-				continue;
-
-			tmp_sta = ap_get_sta(tmp_hapd, addr);
-			if (tmp_sta)
-				ap_free_sta(tmp_hapd, tmp_sta);
-		}
-	}
-
-	/* Remove STA in assoc link */
-	hostapd_remove_sta(assoc_hapd, sta);
-}
-#endif /* CONFIG_IEEE80211BE */
-
-
 void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
 {
 	struct sta_info *sta;
@@ -979,50 +914,6 @@
 		       HOSTAPD_LEVEL_INFO, "disassociated");
 
 	sta = ap_get_sta(hapd, addr);
-#ifdef CONFIG_IEEE80211BE
-	if (hostapd_is_mld_ap(hapd)) {
-		struct hostapd_data *assoc_hapd;
-		unsigned int i;
-
-		if (!sta) {
-			/* Find non-MLO cases from any of the affiliated AP
-			 * links. */
-			for (i = 0; i < hapd->iface->interfaces->count; ++i) {
-				struct hostapd_iface *h =
-					hapd->iface->interfaces->iface[i];
-				struct hostapd_data *h_hapd = h->bss[0];
-				struct hostapd_bss_config *hconf = h_hapd->conf;
-
-				if (!hconf->mld_ap ||
-				    hconf->mld_id != hapd->conf->mld_id)
-					continue;
-
-				sta = ap_get_sta(h_hapd, addr);
-				if (sta) {
-					if (!sta->mld_info.mld_sta) {
-						hapd = h_hapd;
-						goto legacy;
-					}
-					break;
-				}
-			}
-		} else if (!sta->mld_info.mld_sta) {
-			goto legacy;
-		}
-		if (!sta) {
-			wpa_printf(MSG_DEBUG,
-			   "Disassociation notification for unknown STA "
-			   MACSTR, MAC2STR(addr));
-			return;
-		}
-		sta = hostapd_ml_get_assoc_sta(hapd, sta, &assoc_hapd);
-		if (sta)
-			hostapd_notif_disassoc_mld(assoc_hapd, sta, addr);
-		return;
-	}
-
-legacy:
-#endif /* CONFIG_IEEE80211BE */
 	if (sta == NULL) {
 		wpa_printf(MSG_DEBUG,
 			   "Disassociation notification for unknown STA "
@@ -1030,7 +921,13 @@
 		return;
 	}
 
-	hostapd_remove_sta(hapd, sta);
+	ap_sta_set_authorized(hapd, sta, 0);
+	sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
+	hostapd_set_sta_flags(hapd, sta);
+	wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
+	sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
+	ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
+	ap_free_sta(hapd, sta);
 }
 
 
@@ -1267,8 +1164,6 @@
 	hostapd_set_oper_chwidth(hapd->iconf, chwidth);
 	hostapd_set_oper_centr_freq_seg0_idx(hapd->iconf, seg0_idx);
 	hostapd_set_oper_centr_freq_seg1_idx(hapd->iconf, seg1_idx);
-	/* Auto-detect new bw320_offset */
-	hostapd_set_and_check_bw320_offset(hapd->iconf, 0);
 #ifdef CONFIG_IEEE80211BE
 	hapd->iconf->punct_bitmap = punct_bitmap;
 #endif /* CONFIG_IEEE80211BE */
@@ -1375,18 +1270,6 @@
 	int err = 0;
 	struct hostapd_channel_data *pri_chan;
 
-#ifdef CONFIG_IEEE80211BE
-	if (acs_res->link_id != -1) {
-		hapd = hostapd_mld_get_link_bss(hapd, acs_res->link_id);
-		if (!hapd) {
-			wpa_printf(MSG_ERROR,
-				   "MLD: Failed to get link BSS for EVENT_ACS_CHANNEL_SELECTED link_id=%d",
-				   acs_res->link_id);
-			return;
-		}
-	}
-#endif /* CONFIG_IEEE80211BE */
-
 	if (hapd->iconf->channel) {
 		wpa_printf(MSG_INFO, "ACS: Channel was already set to %d",
 			   hapd->iconf->channel);
@@ -1693,7 +1576,6 @@
 #endif /* CONFIG_FST */
 #ifdef CONFIG_DPP
 	if (plen >= 2 + 4 &&
-	    mgmt->u.action.category == WLAN_ACTION_PUBLIC &&
 	    mgmt->u.action.u.vs_public_action.action ==
 	    WLAN_PA_VENDOR_SPECIFIC &&
 	    WPA_GET_BE24(mgmt->u.action.u.vs_public_action.oui) ==
@@ -1709,23 +1591,6 @@
 		return;
 	}
 #endif /* CONFIG_DPP */
-#ifdef CONFIG_NAN_USD
-	if (mgmt->u.action.category == WLAN_ACTION_PUBLIC && plen >= 5 &&
-	    mgmt->u.action.u.vs_public_action.action ==
-	    WLAN_PA_VENDOR_SPECIFIC &&
-	    WPA_GET_BE24(mgmt->u.action.u.vs_public_action.oui) ==
-	    OUI_WFA &&
-	    mgmt->u.action.u.vs_public_action.variable[0] == NAN_OUI_TYPE) {
-		const u8 *pos, *end;
-
-		pos = mgmt->u.action.u.vs_public_action.variable;
-		end = drv_mgmt->frame + drv_mgmt->frame_len;
-		pos++;
-		hostapd_nan_usd_rx_sdf(hapd, mgmt->sa, drv_mgmt->freq,
-				       pos, end - pos);
-		return;
-	}
-#endif /* CONFIG_NAN_USD */
 }
 #endif /* NEED_AP_MLME */
 
@@ -1749,34 +1614,6 @@
 }
 
 
-static struct hostapd_data *
-switch_link_scan(struct hostapd_data *hapd, u64 scan_cookie)
-{
-#ifdef CONFIG_IEEE80211BE
-	if (hapd->conf->mld_ap && scan_cookie != 0) {
-		unsigned int i;
-
-		for (i = 0; i < hapd->iface->interfaces->count; i++) {
-			struct hostapd_iface *h;
-			struct hostapd_data *h_hapd;
-
-			h = hapd->iface->interfaces->iface[i];
-			h_hapd = h->bss[0];
-			if (!hostapd_is_ml_partner(hapd, h_hapd))
-				continue;
-
-			if (h_hapd->scan_cookie == scan_cookie) {
-				h_hapd->scan_cookie = 0;
-				return h_hapd;
-			}
-		}
-	}
-#endif /* CONFIG_IEEE80211BE */
-
-	return hapd;
-}
-
-
 #define HAPD_BROADCAST ((struct hostapd_data *) -1)
 
 static struct hostapd_data * get_hapd_bssid(struct hostapd_iface *iface,
@@ -1791,7 +1628,7 @@
 		return HAPD_BROADCAST;
 
 	for (i = 0; i < iface->num_bss; i++) {
-		if (ether_addr_equal(bssid, iface->bss[i]->own_addr))
+		if (os_memcmp(bssid, iface->bss[i]->own_addr, ETH_ALEN) == 0)
 			return iface->bss[i];
 	}
 
@@ -1845,7 +1682,7 @@
 
 #ifdef CONFIG_IEEE80211BE
 	if (hapd->conf->mld_ap &&
-	    ether_addr_equal(hapd->mld->mld_addr, bssid))
+	    os_memcmp(hapd->mld_addr, bssid, ETH_ALEN) == 0)
 		is_mld = true;
 #endif /* CONFIG_IEEE80211BE */
 
@@ -1917,8 +1754,8 @@
 		hapd = tmp_hapd;
 #ifdef CONFIG_IEEE80211BE
 	} else if (hapd->conf->mld_ap &&
-		   ether_addr_equal(hapd->mld->mld_addr,
-				    get_hdr_bssid(hdr, len))) {
+		   os_memcmp(hapd->mld_addr, get_hdr_bssid(hdr, len),
+			     ETH_ALEN) == 0) {
 		/* AP MLD address match - use hapd pointer as-is */
 #endif /* CONFIG_IEEE80211BE */
 	} else {
@@ -1966,15 +1803,14 @@
 
 
 static struct hostapd_data * hostapd_find_by_sta(struct hostapd_iface *iface,
-						 const u8 *src, bool rsn)
+						 const u8 *src)
 {
 	struct sta_info *sta;
 	unsigned int j;
 
 	for (j = 0; j < iface->num_bss; j++) {
 		sta = ap_get_sta(iface->bss[j], src);
-		if (sta && (sta->flags & WLAN_STA_ASSOC) &&
-		    (!rsn || sta->wpa_sm))
+		if (sta && sta->flags & WLAN_STA_ASSOC)
 			return iface->bss[j];
 	}
 
@@ -1982,38 +1818,6 @@
 }
 
 
-#ifdef CONFIG_IEEE80211BE
-static bool search_mld_sta(struct hostapd_data **p_hapd, const u8 *src)
-{
-	struct hostapd_data *hapd = *p_hapd;
-	unsigned int i;
-
-	/* Search for STA on other MLO BSSs */
-	for (i = 0; i < hapd->iface->interfaces->count; i++) {
-		struct hostapd_iface *h =
-			hapd->iface->interfaces->iface[i];
-		struct hostapd_data *h_hapd = h->bss[0];
-
-		if (!hostapd_is_ml_partner(h_hapd, hapd))
-			continue;
-
-		h_hapd = hostapd_find_by_sta(h, src, false);
-		if (h_hapd) {
-			struct sta_info *sta = ap_get_sta(h_hapd, src);
-
-			if (sta && sta->mld_info.mld_sta &&
-			    sta->mld_assoc_link_id != h_hapd->mld_link_id)
-				continue;
-			*p_hapd = h_hapd;
-			return true;
-		}
-	}
-
-	return false;
-}
-#endif /* CONFIG_IEEE80211BE */
-
-
 static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src,
 				   const u8 *data, size_t data_len,
 				   enum frame_encryption encrypted,
@@ -2026,24 +1830,36 @@
 		struct hostapd_data *h_hapd;
 
 		hapd = switch_link_hapd(hapd, link_id);
-		h_hapd = hostapd_find_by_sta(hapd->iface, src, true);
+		h_hapd = hostapd_find_by_sta(hapd->iface, src);
 		if (!h_hapd)
-			h_hapd = hostapd_find_by_sta(orig_hapd->iface, src,
-						     true);
-		if (!h_hapd)
-			h_hapd = hostapd_find_by_sta(hapd->iface, src, false);
-		if (!h_hapd)
-			h_hapd = hostapd_find_by_sta(orig_hapd->iface, src,
-						     false);
+			h_hapd = hostapd_find_by_sta(orig_hapd->iface, src);
 		if (h_hapd)
 			hapd = h_hapd;
 	} else if (hapd->conf->mld_ap) {
-		search_mld_sta(&hapd, src);
+		unsigned int i;
+
+		/* Search for STA on other MLO BSSs */
+		for (i = 0; i < hapd->iface->interfaces->count; i++) {
+			struct hostapd_iface *h =
+				hapd->iface->interfaces->iface[i];
+			struct hostapd_data *h_hapd = h->bss[0];
+			struct hostapd_bss_config *hconf = h_hapd->conf;
+
+			if (!hconf->mld_ap ||
+			    hconf->mld_id != hapd->conf->mld_id)
+				continue;
+
+			h_hapd = hostapd_find_by_sta(h, src);
+			if (h_hapd) {
+				hapd = h_hapd;
+				break;
+			}
+		}
 	} else {
-		hapd = hostapd_find_by_sta(hapd->iface, src, false);
+		hapd = hostapd_find_by_sta(hapd->iface, src);
 	}
 #else /* CONFIG_IEEE80211BE */
-	hapd = hostapd_find_by_sta(hapd->iface, src, false);
+	hapd = hostapd_find_by_sta(hapd->iface, src);
 #endif /* CONFIG_IEEE80211BE */
 
 	if (!hapd) {
@@ -2348,8 +2164,8 @@
 		struct mld_info *info = &sta->mld_info;
 		u8 link_id = hapd->mld_link_id;
 
-		ap_sta_set_mld(sta, true);
-		sta->mld_assoc_link_id = link_id;
+		info->mld_sta = true;
+		sta->mld_assoc_link_id = link_id;;
 		os_memcpy(info->common_info.mld_addr, peer, ETH_ALEN);
 		info->links[link_id].valid = true;
 		os_memcpy(info->links[link_id].local_addr, hapd->own_addr,
@@ -2405,29 +2221,8 @@
 		michael_mic_failure(hapd, data->michael_mic_failure.src, 1);
 		break;
 	case EVENT_SCAN_RESULTS:
-#ifdef NEED_AP_MLME
-		if (data)
-			hapd = switch_link_scan(hapd,
-						data->scan_info.scan_cookie);
-#endif /* NEED_AP_MLME */
 		if (hapd->iface->scan_cb)
 			hapd->iface->scan_cb(hapd->iface);
-#ifdef CONFIG_IEEE80211BE
-		if (!hapd->iface->scan_cb && hapd->conf->mld_ap) {
-			/* Other links may be waiting for HT scan result */
-			unsigned int i;
-
-			for (i = 0; i < hapd->iface->interfaces->count; i++) {
-				struct hostapd_iface *h =
-					hapd->iface->interfaces->iface[i];
-				struct hostapd_data *h_hapd = h->bss[0];
-
-				if (hostapd_is_ml_partner(hapd, h_hapd) &&
-				    h_hapd->iface->scan_cb)
-					h_hapd->iface->scan_cb(h_hapd->iface);
-			}
-		}
-#endif /* CONFIG_IEEE80211BE */
 		break;
 	case EVENT_WPS_BUTTON_PUSHED:
 		hostapd_wps_button_pushed(hapd, NULL);
@@ -2569,18 +2364,6 @@
 	case EVENT_CH_SWITCH:
 		if (!data)
 			break;
-#ifdef CONFIG_IEEE80211BE
-		if (data->ch_switch.link_id != -1) {
-			hapd = hostapd_mld_get_link_bss(
-				hapd, data->ch_switch.link_id);
-			if (!hapd) {
-				wpa_printf(MSG_ERROR,
-					   "MLD: Failed to get link (ID %d) BSS for EVENT_CH_SWITCH/EVENT_CH_SWITCH_STARTED",
-					   data->ch_switch.link_id);
-				break;
-			}
-		}
-#endif /* CONFIG_IEEE80211BE */
 		hostapd_event_ch_switch(hapd, data->ch_switch.freq,
 					data->ch_switch.ht_enabled,
 					data->ch_switch.ch_offset,
@@ -2607,31 +2390,26 @@
 	case EVENT_DFS_RADAR_DETECTED:
 		if (!data)
 			break;
-		hapd = switch_link_hapd(hapd, data->dfs_event.link_id);
 		hostapd_event_dfs_radar_detected(hapd, &data->dfs_event);
 		break;
 	case EVENT_DFS_PRE_CAC_EXPIRED:
 		if (!data)
 			break;
-		hapd = switch_link_hapd(hapd, data->dfs_event.link_id);
 		hostapd_event_dfs_pre_cac_expired(hapd, &data->dfs_event);
 		break;
 	case EVENT_DFS_CAC_FINISHED:
 		if (!data)
 			break;
-		hapd = switch_link_hapd(hapd, data->dfs_event.link_id);
 		hostapd_event_dfs_cac_finished(hapd, &data->dfs_event);
 		break;
 	case EVENT_DFS_CAC_ABORTED:
 		if (!data)
 			break;
-		hapd = switch_link_hapd(hapd, data->dfs_event.link_id);
 		hostapd_event_dfs_cac_aborted(hapd, &data->dfs_event);
 		break;
 	case EVENT_DFS_NOP_FINISHED:
 		if (!data)
 			break;
-		hapd = switch_link_hapd(hapd, data->dfs_event.link_id);
 		hostapd_event_dfs_nop_finished(hapd, &data->dfs_event);
 		break;
 	case EVENT_CHANNEL_LIST_CHANGED:
@@ -2645,7 +2423,6 @@
 	case EVENT_DFS_CAC_STARTED:
 		if (!data)
 			break;
-		hapd = switch_link_hapd(hapd, data->dfs_event.link_id);
 		hostapd_event_dfs_cac_started(hapd, &data->dfs_event);
 		break;
 #endif /* NEED_AP_MLME */
diff --git a/src/ap/fils_hlp.c b/src/ap/fils_hlp.c
index a34b5ba..d64fb8c 100644
--- a/src/ap/fils_hlp.c
+++ b/src/ap/fils_hlp.c
@@ -546,7 +546,7 @@
 		   " src=" MACSTR " len=%u)",
 		   MAC2STR(sta->addr), MAC2STR(pos), MAC2STR(pos + ETH_ALEN),
 		   (unsigned int) len);
-	if (!ether_addr_equal(sta->addr, pos + ETH_ALEN)) {
+	if (os_memcmp(sta->addr, pos + ETH_ALEN, ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG,
 			   "FILS: Ignore HLP request with unexpected source address"
 			   MACSTR, MAC2STR(pos + ETH_ALEN));
diff --git a/src/ap/gas_query_ap.c b/src/ap/gas_query_ap.c
index a471c79..3d94407 100644
--- a/src/ap/gas_query_ap.c
+++ b/src/ap/gas_query_ap.c
@@ -185,7 +185,7 @@
 {
 	struct gas_query_pending *q;
 	dl_list_for_each(q, &gas->pending, struct gas_query_pending, list) {
-		if (ether_addr_equal(q->addr, addr) &&
+		if (os_memcmp(q->addr, addr, ETH_ALEN) == 0 &&
 		    q->dialog_token == dialog_token)
 			return q;
 	}
@@ -223,7 +223,7 @@
 	wpa_printf(MSG_DEBUG, "GAS: TX status: dst=" MACSTR
 		   " ok=%d query=%p dialog_token=%u dur=%d ms",
 		   MAC2STR(dst), ok, query, query->dialog_token, dur);
-	if (!ether_addr_equal(dst, query->addr)) {
+	if (os_memcmp(dst, query->addr, ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG, "GAS: TX status for unexpected destination");
 		return;
 	}
@@ -618,7 +618,7 @@
 {
 	struct gas_query_pending *q;
 	dl_list_for_each(q, &gas->pending, struct gas_query_pending, list) {
-		if (ether_addr_equal(dst, q->addr) &&
+		if (os_memcmp(dst, q->addr, ETH_ALEN) == 0 &&
 		    dialog_token == q->dialog_token)
 			return 0;
 	}
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 56bac45..236381f 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -35,7 +35,6 @@
 #include "wpa_auth.h"
 #include "wps_hostapd.h"
 #include "dpp_hostapd.h"
-#include "nan_usd_ap.h"
 #include "gas_query_ap.h"
 #include "hw_features.h"
 #include "wpa_auth_glue.h"
@@ -184,8 +183,6 @@
 		hostapd_set_generic_elem(hapd, (u8 *) "", 0);
 	}
 
-	hostapd_neighbor_sync_own_report(hapd);
-
 	ieee802_11_set_beacon(hapd);
 	hostapd_update_wps(hapd);
 
@@ -397,62 +394,25 @@
 #endif /* CONFIG_WEP */
 
 
-#ifdef CONFIG_IEEE80211BE
-#ifdef CONFIG_TESTING_OPTIONS
-
-#define TU_TO_USEC(_val) ((_val) * 1024)
-
-static void hostapd_link_remove_timeout_handler(void *eloop_data,
-						void *user_ctx)
+static void hostapd_clear_drv_priv(struct hostapd_data *hapd)
 {
-	struct hostapd_data *hapd = (struct hostapd_data *) eloop_data;
+	unsigned int i;
 
-	if (hapd->eht_mld_link_removal_count == 0)
-		return;
-	hapd->eht_mld_link_removal_count--;
+	for (i = 0; i < hapd->iface->interfaces->count; i++) {
+		struct hostapd_iface *iface = hapd->iface->interfaces->iface[i];
 
-	wpa_printf(MSG_DEBUG, "MLD: Remove link_id=%u in %u beacons",
-		   hapd->mld_link_id,
-		   hapd->eht_mld_link_removal_count);
+		if (hapd->iface == iface || !iface)
+			continue;
 
-	ieee802_11_set_beacon(hapd);
-
-	if (!hapd->eht_mld_link_removal_count) {
-		hostapd_free_link_stas(hapd);
-		hostapd_disable_iface(hapd->iface);
-		return;
+		if (iface->bss && iface->bss[0] &&
+		    iface->bss[0]->mld_first_bss == hapd)
+			iface->bss[0]->drv_priv = NULL;
 	}
 
-	eloop_register_timeout(0, TU_TO_USEC(hapd->iconf->beacon_int),
-			       hostapd_link_remove_timeout_handler,
-			       hapd, NULL);
+	hapd->drv_priv = NULL;
 }
 
 
-int hostapd_link_remove(struct hostapd_data *hapd, u32 count)
-{
-	if (!hapd->conf->mld_ap)
-		return -1;
-
-	wpa_printf(MSG_DEBUG,
-		   "MLD: Remove link_id=%u in %u beacons",
-		   hapd->mld_link_id, count);
-
-	hapd->eht_mld_link_removal_count = count;
-	hapd->eht_mld_bss_param_change++;
-
-	eloop_register_timeout(0, TU_TO_USEC(hapd->iconf->beacon_int),
-			       hostapd_link_remove_timeout_handler,
-			       hapd, NULL);
-
-	ieee802_11_set_beacon(hapd);
-	return 0;
-}
-
-#endif /* CONFIG_TESTING_OPTIONS */
-#endif /* CONFIG_IEEE80211BE */
-
-
 void hostapd_free_hapd_data(struct hostapd_data *hapd)
 {
 	os_free(hapd->probereq_cb);
@@ -480,27 +440,7 @@
 	vlan_deinit(hapd);
 	hostapd_acl_deinit(hapd);
 #ifndef CONFIG_NO_RADIUS
-	if (hostapd_mld_is_first_bss(hapd)) {
-#ifdef CONFIG_IEEE80211BE
-		struct hapd_interfaces *ifaces = hapd->iface->interfaces;
-		size_t i;
-
-		for (i = 0; i < ifaces->count; i++) {
-			struct hostapd_iface *iface = ifaces->iface[i];
-			size_t j;
-
-			for (j = 0; iface && j < iface->num_bss; j++) {
-				struct hostapd_data *h = iface->bss[j];
-
-				if (hapd == h)
-					continue;
-				if (h->radius == hapd->radius)
-					h->radius = NULL;
-				if (h->radius_das == hapd->radius_das)
-					h->radius_das = NULL;
-			}
-		}
-#endif /* CONFIG_IEEE80211BE */
+	if (!hapd->mld_first_bss) {
 		radius_client_deinit(hapd->radius);
 		radius_das_deinit(hapd->radius_das);
 	}
@@ -515,9 +455,6 @@
 	gas_query_ap_deinit(hapd->gas);
 	hapd->gas = NULL;
 #endif /* CONFIG_DPP */
-#ifdef CONFIG_NAN_USD
-	hostapd_nan_usd_deinit(hapd);
-#endif /* CONFIG_NAN_USD */
 
 	authsrv_deinit(hapd);
 
@@ -534,20 +471,10 @@
 			 * driver wrapper may have removed its internal instance
 			 * and hapd->drv_priv is not valid anymore.
 			 */
-			hapd->drv_priv = NULL;
+			hostapd_clear_drv_priv(hapd);
 		}
 	}
 
-#ifdef CONFIG_IEEE80211BE
-	/* If the interface was not added as well as it is not the first BSS,
-	 * at least the link should be removed here since deinit will take care
-	 * of only the first BSS. */
-	if (hapd->conf->mld_ap && !hapd->interface_added &&
-	    hapd->iface->bss[0] != hapd)
-		hostapd_if_link_remove(hapd, WPA_IF_AP_BSS, hapd->conf->iface,
-				       hapd->mld_link_id);
-#endif /* CONFIG_IEEE80211BE */
-
 	wpabuf_free(hapd->time_adv);
 	hapd->time_adv = NULL;
 
@@ -575,9 +502,7 @@
 	hapd->setup_complete_cb = NULL;
 #endif /* CONFIG_MESH */
 
-#ifndef CONFIG_NO_RRM
 	hostapd_clean_rrm(hapd);
-#endif /* CONFIG_NO_RRM */
 	fils_hlp_deinit(hapd);
 
 #ifdef CONFIG_OCV
@@ -600,51 +525,10 @@
 
 #ifdef CONFIG_IEEE80211AX
 	eloop_cancel_timeout(hostapd_switch_color_timeout_handler, hapd, NULL);
-#ifdef CONFIG_TESTING_OPTIONS
-#ifdef CONFIG_IEEE80211BE
-	eloop_cancel_timeout(hostapd_link_remove_timeout_handler, hapd, NULL);
-#endif /* CONFIG_IEEE80211BE */
-#endif /* CONFIG_TESTING_OPTIONS */
-
 #endif /* CONFIG_IEEE80211AX */
 }
 
 
-/* hostapd_bss_link_deinit - Per-BSS ML cleanup (deinitialization)
- * @hapd: Pointer to BSS data
- *
- * This function is used to unlink the BSS from the AP MLD.
- * If the BSS being removed is the first link, the next link becomes the first
- * link.
- */
-static void hostapd_bss_link_deinit(struct hostapd_data *hapd)
-{
-#ifdef CONFIG_IEEE80211BE
-	if (!hapd->conf || !hapd->conf->mld_ap)
-		return;
-
-	if (!hapd->mld->num_links)
-		return;
-
-	/* If not started, not yet linked to the MLD. However, the first
-	 * BSS is always linked since it is linked during driver_init(), and
-	 * hence, need to remove it from the AP MLD.
-	 */
-	if (!hapd->started && hapd->iface->bss[0] != hapd)
-		return;
-
-	/* The first BSS can also be only linked when at least driver_init() is
-	 * executed. But if previous interface fails, it is not, and hence,
-	 * safe to skip.
-	 */
-	if (hapd->iface->bss[0] == hapd && !hapd->drv_priv)
-		return;
-
-	hostapd_mld_remove_link(hapd);
-#endif /* CONFIG_IEEE80211BE */
-}
-
-
 /**
  * hostapd_cleanup - Per-BSS cleanup (deinitialization)
  * @hapd: Pointer to BSS data
@@ -685,7 +569,6 @@
 void hostapd_cleanup_iface_partial(struct hostapd_iface *iface)
 {
 	wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
-	eloop_cancel_timeout(channel_list_update_timeout, iface, NULL);
 #ifdef NEED_AP_MLME
 	hostapd_stop_setup_timers(iface);
 #endif /* NEED_AP_MLME */
@@ -715,6 +598,7 @@
 static void hostapd_cleanup_iface(struct hostapd_iface *iface)
 {
 	wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
+	eloop_cancel_timeout(channel_list_update_timeout, iface, NULL);
 	eloop_cancel_timeout(hostapd_interface_setup_failure_handler, iface,
 			     NULL);
 
@@ -1334,7 +1218,7 @@
 	u8 if_addr[ETH_ALEN];
 	int flush_old_stations = 1;
 
-	if (!hostapd_mld_is_first_bss(hapd))
+	if (hapd->mld_first_bss)
 		wpa_printf(MSG_DEBUG,
 			   "MLD: %s: Setting non-first BSS", __func__);
 
@@ -1496,7 +1380,7 @@
 	}
 #endif /* CONFIG_SQLITE */
 
-	if (hostapd_mld_is_first_bss(hapd)) {
+	if (!hapd->mld_first_bss) {
 		hapd->radius = radius_client_init(hapd, conf->radius);
 		if (!hapd->radius) {
 			wpa_printf(MSG_ERROR,
@@ -1529,17 +1413,10 @@
 			}
 		}
 	} else {
-#ifdef CONFIG_IEEE80211BE
-		struct hostapd_data *f_bss;
-
 		wpa_printf(MSG_DEBUG,
 			   "MLD: Using RADIUS client of the first BSS");
-		f_bss = hostapd_mld_get_first_bss(hapd);
-		if (!f_bss)
-			return -1;
-		hapd->radius = f_bss->radius;
-		hapd->radius_das = f_bss->radius_das;
-#endif /* CONFIG_IEEE80211BE */
+		hapd->radius = hapd->mld_first_bss->radius;
+		hapd->radius_das = hapd->mld_first_bss->radius_das;
 	}
 #endif /* CONFIG_NO_RADIUS */
 
@@ -1558,11 +1435,6 @@
 		return -1;
 #endif /* CONFIG_DPP */
 
-#ifdef CONFIG_NAN_USD
-	if (hostapd_nan_usd_init(hapd) < 0)
-		return -1;
-#endif /* CONFIG_NAN_USD */
-
 	if (authsrv_init(hapd) < 0)
 		return -1;
 
@@ -1584,7 +1456,6 @@
 		wpa_printf(MSG_ERROR, "GAS server initialization failed");
 		return -1;
 	}
-#endif /* CONFIG_INTERWORKING */
 
 	if (conf->qos_map_set_len &&
 	    hostapd_drv_set_qos_map(hapd, conf->qos_map_set,
@@ -1592,6 +1463,7 @@
 		wpa_printf(MSG_ERROR, "Failed to initialize QoS Map");
 		return -1;
 	}
+#endif /* CONFIG_INTERWORKING */
 
 	if (conf->bss_load_update_period && bss_load_update_init(hapd)) {
 		wpa_printf(MSG_ERROR, "BSS Load initialization failed");
@@ -1777,7 +1649,6 @@
 static void hostapd_no_ir_cleanup(struct hostapd_data *bss)
 {
 	hostapd_bss_deinit_no_free(bss);
-	hostapd_bss_link_deinit(bss);
 	hostapd_free_hapd_data(bss);
 	hostapd_cleanup_iface_partial(bss->iface);
 }
@@ -2074,11 +1945,10 @@
 	} else {
 		int ret;
 
-		if (iface->conf->acs && !iface->is_ch_switch_dfs) {
+		if (iface->conf->acs) {
 			iface->freq = 0;
 			iface->conf->channel = 0;
 		}
-		iface->is_ch_switch_dfs = false;
 
 		ret = configured_fixed_chan_to_freq(iface);
 		if (ret < 0)
@@ -2837,8 +2707,6 @@
 		hapd->rad_attr_db = NULL;
 	}
 #endif /* CONFIG_SQLITE */
-
-	hostapd_bss_link_deinit(hapd);
 	hostapd_cleanup(hapd);
 }
 
@@ -2877,40 +2745,6 @@
 }
 
 
-#ifdef CONFIG_IEEE80211BE
-
-static void hostapd_mld_ref_inc(struct hostapd_mld *mld)
-{
-	if (!mld)
-		return;
-
-	if (mld->refcount == HOSTAPD_MLD_MAX_REF_COUNT) {
-		wpa_printf(MSG_ERROR, "AP MLD %s: Ref count overflow",
-			   mld->name);
-		return;
-	}
-
-	mld->refcount++;
-}
-
-
-static void hostapd_mld_ref_dec(struct hostapd_mld *mld)
-{
-	if (!mld)
-		return;
-
-	if (!mld->refcount) {
-		wpa_printf(MSG_ERROR, "AP MLD %s: Ref count underflow",
-			   mld->name);
-		return;
-	}
-
-	mld->refcount--;
-}
-
-#endif /* CONFIG_IEEE80211BE */
-
-
 void hostapd_interface_free(struct hostapd_iface *iface)
 {
 	size_t j;
@@ -2918,10 +2752,6 @@
 	for (j = 0; j < iface->num_bss; j++) {
 		if (!iface->bss)
 			break;
-#ifdef CONFIG_IEEE80211BE
-		if (iface->bss[j])
-			hostapd_mld_ref_dec(iface->bss[j]->mld);
-#endif /* CONFIG_IEEE80211BE */
 		wpa_printf(MSG_DEBUG, "%s: free hapd %p",
 			   __func__, iface->bss[j]);
 		os_free(iface->bss[j]);
@@ -2944,157 +2774,6 @@
 }
 
 
-#ifdef CONFIG_IEEE80211BE
-static void hostapd_bss_alloc_link_id(struct hostapd_data *hapd)
-{
-	hapd->mld_link_id = hapd->mld->next_link_id++;
-	wpa_printf(MSG_DEBUG, "AP MLD: %s: Link ID %d assigned.",
-		   hapd->mld->name, hapd->mld_link_id);
-}
-#endif /* CONFIG_IEEE80211BE */
-
-
-static void hostapd_bss_setup_multi_link(struct hostapd_data *hapd,
-					 struct hapd_interfaces *interfaces)
-{
-#ifdef CONFIG_IEEE80211BE
-	struct hostapd_mld *mld, **all_mld;
-	struct hostapd_bss_config *conf;
-	size_t i;
-
-	conf = hapd->conf;
-
-	if (!hapd->iconf || !hapd->iconf->ieee80211be || !conf->mld_ap ||
-	    conf->disable_11be)
-		return;
-
-	for (i = 0; i < interfaces->mld_count; i++) {
-		mld = interfaces->mld[i];
-
-		if (!mld || os_strcmp(conf->iface, mld->name) != 0)
-			continue;
-
-		hapd->mld = mld;
-		hostapd_mld_ref_inc(mld);
-		hostapd_bss_alloc_link_id(hapd);
-		break;
-	}
-
-	if (hapd->mld)
-		return;
-
-	mld = os_zalloc(sizeof(struct hostapd_mld));
-	if (!mld)
-		goto fail;
-
-	os_strlcpy(mld->name, conf->iface, sizeof(conf->iface));
-	dl_list_init(&mld->links);
-
-	wpa_printf(MSG_DEBUG, "AP MLD %s created", mld->name);
-
-	hapd->mld = mld;
-	hostapd_mld_ref_inc(mld);
-	hostapd_bss_alloc_link_id(hapd);
-
-	all_mld = os_realloc_array(interfaces->mld, interfaces->mld_count + 1,
-				   sizeof(struct hostapd_mld *));
-	if (!all_mld)
-		goto fail;
-
-	interfaces->mld = all_mld;
-	interfaces->mld[interfaces->mld_count] = mld;
-	interfaces->mld_count++;
-
-	return;
-fail:
-	if (!mld)
-		return;
-
-	wpa_printf(MSG_DEBUG, "AP MLD %s: free mld %p", mld->name, mld);
-	os_free(mld);
-	hapd->mld = NULL;
-#endif /* CONFIG_IEEE80211BE */
-}
-
-
-static void hostapd_cleanup_unused_mlds(struct hapd_interfaces *interfaces)
-{
-#ifdef CONFIG_IEEE80211BE
-	struct hostapd_mld *mld, **all_mld;
-	size_t i, j, num_mlds;
-	bool forced_remove, remove;
-
-	if (!interfaces->mld)
-		return;
-
-	num_mlds = interfaces->mld_count;
-
-	for (i = 0; i < interfaces->mld_count; i++) {
-		mld = interfaces->mld[i];
-		if (!mld)
-			continue;
-
-		remove = false;
-		forced_remove = false;
-
-		if (!mld->refcount)
-			remove = true;
-
-		/* If MLD is still being referenced but the number of interfaces
-		 * is zero, it is safe to force its deletion. Normally, this
-		 * should not happen but even if it does, let us free the
-		 * memory.
-		 */
-		if (!remove && !interfaces->count)
-			forced_remove = true;
-
-		if (!remove && !forced_remove)
-			continue;
-
-		wpa_printf(MSG_DEBUG, "AP MLD %s: Freed%s", mld->name,
-			   forced_remove ? " (forced)" : "");
-		os_free(mld);
-		interfaces->mld[i] = NULL;
-		num_mlds--;
-	}
-
-	if (!num_mlds) {
-		interfaces->mld_count = 0;
-		os_free(interfaces->mld);
-		interfaces->mld = NULL;
-		return;
-	}
-
-	all_mld = os_zalloc(num_mlds * sizeof(struct hostapd_mld *));
-	if (!all_mld) {
-		wpa_printf(MSG_ERROR,
-			   "AP MLD: Failed to re-allocate the MLDs. Expect issues");
-		return;
-	}
-
-	for (i = 0, j = 0; i < interfaces->mld_count; i++) {
-		mld = interfaces->mld[i];
-		if (!mld)
-			continue;
-
-		all_mld[j++] = mld;
-	}
-
-	/* This should not happen */
-	if (j != num_mlds) {
-		wpa_printf(MSG_DEBUG,
-			   "AP MLD: Some error occurred while reallocating MLDs. Expect issues.");
-		os_free(all_mld);
-		return;
-	}
-
-	os_free(interfaces->mld);
-	interfaces->mld = all_mld;
-	interfaces->mld_count = num_mlds;
-#endif /* CONFIG_IEEE80211BE */
-}
-
-
 /**
  * hostapd_init - Allocate and initialize per-interface data
  * @config_file: Path to the configuration file
@@ -3138,10 +2817,8 @@
 		if (hapd == NULL)
 			goto fail;
 		hapd->msg_ctx = hapd;
-		hostapd_bss_setup_multi_link(hapd, interfaces);
 	}
 
-	hapd_iface->is_ch_switch_dfs = false;
 	return hapd_iface;
 
 fail:
@@ -3261,8 +2938,6 @@
 		iface->conf->last_bss = bss;
 		iface->bss[iface->num_bss] = hapd;
 		hapd->msg_ctx = hapd;
-		hostapd_bss_setup_multi_link(hapd, interfaces);
-
 
 		bss_idx = iface->num_bss++;
 		conf->num_bss--;
@@ -3296,37 +2971,6 @@
 }
 
 
-static void hostapd_cleanup_driver(const struct wpa_driver_ops *driver,
-				   void *drv_priv, struct hostapd_iface *iface)
-{
-#ifdef CONFIG_IEEE80211BE
-	if (!driver || !driver->hapd_deinit || !drv_priv)
-		return;
-
-	/* In case of non-ML operation, de-init. But if ML operation exist,
-	 * even if that's the last BSS in the interface, the driver (drv) could
-	 * be in use for a different AP MLD. Hence, need to check if drv is
-	 * still being used by some other BSS before de-initiallizing. */
-	if (!iface->bss[0]->conf->mld_ap) {
-		driver->hapd_deinit(drv_priv);
-	} else if (hostapd_mld_is_first_bss(iface->bss[0]) &&
-		   driver->is_drv_shared &&
-		   !driver->is_drv_shared(drv_priv, iface->bss[0])) {
-		driver->hapd_deinit(drv_priv);
-	} else if (hostapd_if_link_remove(iface->bss[0],
-					  WPA_IF_AP_BSS,
-					  iface->bss[0]->conf->iface,
-					  iface->bss[0]->mld_link_id)) {
-		wpa_printf(MSG_WARNING, "Failed to remove BSS interface %s",
-			   iface->bss[0]->conf->iface);
-	}
-#else /* CONFIG_IEEE80211BE */
-	driver->hapd_deinit(drv_priv);
-#endif /* CONFIG_IEEE80211BE */
-	iface->bss[0]->drv_priv = NULL;
-}
-
-
 void hostapd_interface_deinit_free(struct hostapd_iface *iface)
 {
 	const struct wpa_driver_ops *driver;
@@ -3343,7 +2987,11 @@
 	hostapd_interface_deinit(iface);
 	wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit",
 		   __func__, driver, drv_priv);
-	hostapd_cleanup_driver(driver, drv_priv, iface);
+	if (driver && driver->hapd_deinit && drv_priv) {
+		if (!iface->bss[0]->mld_first_bss)
+			driver->hapd_deinit(drv_priv);
+		hostapd_clear_drv_priv(iface->bss[0]);
+	}
 	hostapd_interface_free(iface);
 }
 
@@ -3356,16 +3004,15 @@
 
 	wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit",
 		   __func__, driver, drv_priv);
-
-	hostapd_cleanup_driver(driver, drv_priv, hapd_iface);
-
 	if (driver && driver->hapd_deinit && drv_priv) {
+		if (!hapd_iface->bss[0]->mld_first_bss)
+			driver->hapd_deinit(drv_priv);
 		for (j = 0; j < hapd_iface->num_bss; j++) {
 			wpa_printf(MSG_DEBUG, "%s:bss[%d]->drv_priv=%p",
 				   __func__, (int) j,
 				   hapd_iface->bss[j]->drv_priv);
 			if (hapd_iface->bss[j]->drv_priv == drv_priv) {
-				hapd_iface->bss[j]->drv_priv = NULL;
+				hostapd_clear_drv_priv(hapd_iface->bss[j]);
 				hapd_iface->extended_capa = NULL;
 				hapd_iface->extended_capa_mask = NULL;
 				hapd_iface->extended_capa_len = 0;
@@ -3375,22 +3022,6 @@
 }
 
 
-static void hostapd_refresh_all_iface_beacons(struct hostapd_iface *hapd_iface)
-{
-	size_t j;
-
-	if (!hapd_iface->interfaces || hapd_iface->interfaces->count <= 1)
-		return;
-
-	for (j = 0; j < hapd_iface->interfaces->count; j++) {
-		if (hapd_iface->interfaces->iface[j] == hapd_iface)
-			continue;
-
-		ieee802_11_update_beacons(hapd_iface->interfaces->iface[j]);
-	}
-}
-
-
 int hostapd_enable_iface(struct hostapd_iface *hapd_iface)
 {
 	size_t j;
@@ -3429,8 +3060,6 @@
 		return -1;
 	}
 
-	hostapd_refresh_all_iface_beacons(hapd_iface);
-
 	return 0;
 }
 
@@ -3505,7 +3134,6 @@
 	for (j = 0; j < hapd_iface->num_bss; j++) {
 		struct hostapd_data *hapd = hapd_iface->bss[j];
 		hostapd_bss_deinit_no_free(hapd);
-		hostapd_bss_link_deinit(hapd);
 		hostapd_free_hapd_data(hapd);
 	}
 
@@ -3519,7 +3147,6 @@
 	wpa_printf(MSG_DEBUG, "Interface %s disabled",
 		   hapd_iface->bss[0]->conf->iface);
 	hostapd_set_state(hapd_iface, HAPD_IFACE_DISABLED);
-	hostapd_refresh_all_iface_beacons(hapd_iface);
 	return 0;
 }
 
@@ -3628,7 +3255,6 @@
 			return -1;
 		}
 		hapd->msg_ctx = hapd;
-		hostapd_bss_setup_multi_link(hapd, hapd_iface->interfaces);
 	}
 
 	hapd_iface->conf = conf;
@@ -3702,7 +3328,6 @@
 			if (start_ctrl_iface_bss(hapd) < 0 ||
 			    (hapd_iface->state == HAPD_IFACE_ENABLED &&
 			     hostapd_setup_bss(hapd, -1, true))) {
-				hostapd_bss_link_deinit(hapd);
 				hostapd_cleanup(hapd);
 				hapd_iface->bss[hapd_iface->num_bss - 1] = NULL;
 				hapd_iface->conf->num_bss--;
@@ -3711,9 +3336,6 @@
 					   __func__, hapd, hapd->conf->iface);
 				hostapd_config_free_bss(hapd->conf);
 				hapd->conf = NULL;
-#ifdef CONFIG_IEEE80211BE
-				hostapd_mld_ref_dec(hapd->mld);
-#endif /* CONFIG_IEEE80211BE */
 				os_free(hapd);
 				return -1;
 			}
@@ -3803,11 +3425,7 @@
 				wpa_printf(MSG_DEBUG, "%s: free hapd %p (%s)",
 					   __func__, hapd_iface->bss[i],
 					   hapd->conf->iface);
-				hostapd_bss_link_deinit(hapd);
 				hostapd_cleanup(hapd);
-#ifdef CONFIG_IEEE80211BE
-				hostapd_mld_ref_dec(hapd->mld);
-#endif /* CONFIG_IEEE80211BE */
 				os_free(hapd);
 				hapd_iface->bss[i] = NULL;
 			}
@@ -3817,7 +3435,6 @@
 		if (new_iface) {
 			interfaces->count--;
 			interfaces->iface[interfaces->count] = NULL;
-			hostapd_cleanup_unused_mlds(interfaces);
 		}
 		hostapd_cleanup_iface(hapd_iface);
 	}
@@ -3840,9 +3457,6 @@
 			   __func__, hapd, hapd->conf->iface);
 		hostapd_config_free_bss(hapd->conf);
 		hapd->conf = NULL;
-#ifdef CONFIG_IEEE80211BE
-		hostapd_mld_ref_dec(hapd->mld);
-#endif /* CONFIG_IEEE80211BE */
 		os_free(hapd);
 
 		iface->num_bss--;
@@ -3885,8 +3499,6 @@
 				k++;
 			}
 			interfaces->count--;
-			hostapd_cleanup_unused_mlds(interfaces);
-
 			return 0;
 		}
 
@@ -3924,7 +3536,7 @@
 	}
 
 #ifdef CONFIG_IEEE80211BE
-	if (ap_sta_is_mld(hapd, sta) &&
+	if (hapd->conf->mld_ap && sta->mld_info.mld_sta &&
 	    sta->mld_assoc_link_id != hapd->mld_link_id)
 		return;
 #endif /* CONFIG_IEEE80211BE */
@@ -4156,7 +3768,7 @@
 				      struct hostapd_freq_params *old_params)
 {
 	int channel;
-	u8 seg0 = 0, seg1 = 0;
+	u8 seg0, seg1;
 	struct hostapd_hw_modes *mode;
 
 	if (!params->channel) {
@@ -4186,8 +3798,7 @@
 				    mode ? &mode->he_capab[IEEE80211_MODE_AP] :
 				    NULL,
 				    mode ? &mode->eht_capab[IEEE80211_MODE_AP] :
-				    NULL,
-				    hostapd_get_punct_bitmap(hapd)))
+				    NULL))
 		return -1;
 
 	switch (params->bandwidth) {
@@ -4233,14 +3844,10 @@
 	conf->ieee80211n = params->ht_enabled;
 	conf->ieee80211ac = params->vht_enabled;
 	conf->secondary_channel = params->sec_channel_offset;
-	if (params->center_freq1 &&
-	    ieee80211_freq_to_chan(params->center_freq1, &seg0) ==
-	    NUM_HOSTAPD_MODES)
-		return -1;
-	if (params->center_freq2 &&
-	    ieee80211_freq_to_chan(params->center_freq2,
-				   &seg1) == NUM_HOSTAPD_MODES)
-		return -1;
+	ieee80211_freq_to_chan(params->center_freq1,
+			       &seg0);
+	ieee80211_freq_to_chan(params->center_freq2,
+			       &seg1);
 	hostapd_set_oper_centr_freq_seg0_idx(conf, seg0);
 	hostapd_set_oper_centr_freq_seg1_idx(conf, seg1);
 
@@ -4338,11 +3945,6 @@
 	settings->counter_offset_presp[0] = hapd->cs_c_off_proberesp;
 	settings->counter_offset_beacon[1] = hapd->cs_c_off_ecsa_beacon;
 	settings->counter_offset_presp[1] = hapd->cs_c_off_ecsa_proberesp;
-	settings->link_id = -1;
-#ifdef CONFIG_IEEE80211BE
-	if (hapd->conf->mld_ap)
-		settings->link_id = hapd->mld_link_id;
-#endif /* CONFIG_IEEE80211BE */
 
 	return 0;
 }
@@ -4438,17 +4040,13 @@
 		bw = CONF_OPER_CHWIDTH_USE_HT;
 		break;
 	case 80:
-		if (freq_params->center_freq2) {
+		if (freq_params->center_freq2)
 			bw = CONF_OPER_CHWIDTH_80P80MHZ;
-			iface->conf->vht_capab |=
-				VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
-		} else {
+		else
 			bw = CONF_OPER_CHWIDTH_80MHZ;
-		}
 		break;
 	case 160:
 		bw = CONF_OPER_CHWIDTH_160MHZ;
-		iface->conf->vht_capab |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
 		break;
 	case 320:
 		bw = CONF_OPER_CHWIDTH_320MHZ;
@@ -4677,7 +4275,6 @@
 
 
 #ifdef CONFIG_IEEE80211BE
-
 struct hostapd_data * hostapd_mld_get_link_bss(struct hostapd_data *hapd,
 					       u8 link_id)
 {
@@ -4686,8 +4283,9 @@
 	for (i = 0; i < hapd->iface->interfaces->count; i++) {
 		struct hostapd_iface *h = hapd->iface->interfaces->iface[i];
 		struct hostapd_data *h_hapd = h->bss[0];
+		struct hostapd_bss_config *hconf = h_hapd->conf;
 
-		if (!hostapd_is_ml_partner(hapd, h_hapd))
+		if (!hconf->mld_ap || hconf->mld_id != hapd->conf->mld_id)
 			continue;
 
 		if (h_hapd->mld_link_id == link_id)
@@ -4696,141 +4294,4 @@
 
 	return NULL;
 }
-
-
-bool hostapd_is_ml_partner(struct hostapd_data *hapd1,
-			   struct hostapd_data *hapd2)
-{
-	if (!hapd1->conf->mld_ap || !hapd2->conf->mld_ap)
-		return false;
-
-	return !os_strcmp(hapd1->conf->iface, hapd2->conf->iface);
-}
-
-
-u8 hostapd_get_mld_id(struct hostapd_data *hapd)
-{
-	if (!hapd->conf->mld_ap)
-		return 255;
-
-	/* MLD ID 0 represents self */
-	return 0;
-
-	/* TODO: MLD ID for Multiple BSS cases */
-}
-
-
-int hostapd_mld_add_link(struct hostapd_data *hapd)
-{
-	struct hostapd_mld *mld = hapd->mld;
-
-	if (!hapd->conf->mld_ap)
-		return 0;
-
-	/* Should not happen */
-	if (!mld)
-		return -1;
-
-	dl_list_add_tail(&mld->links, &hapd->link);
-	mld->num_links++;
-
-	wpa_printf(MSG_DEBUG, "AP MLD %s: Link ID %d added. num_links: %d",
-		   mld->name, hapd->mld_link_id, mld->num_links);
-
-	if (mld->fbss)
-		return 0;
-
-	mld->fbss = hapd;
-	wpa_printf(MSG_DEBUG, "AP MLD %s: First link BSS set to %p",
-		   mld->name, mld->fbss);
-	return 0;
-}
-
-
-int hostapd_mld_remove_link(struct hostapd_data *hapd)
-{
-	struct hostapd_mld *mld = hapd->mld;
-	struct hostapd_data *next_fbss;
-
-	if (!hapd->conf->mld_ap)
-		return 0;
-
-	/* Should not happen */
-	if (!mld)
-		return -1;
-
-	dl_list_del(&hapd->link);
-	mld->num_links--;
-
-	wpa_printf(MSG_DEBUG, "AP MLD %s: Link ID %d removed. num_links: %d",
-		   mld->name, hapd->mld_link_id, mld->num_links);
-
-	if (mld->fbss != hapd)
-		return 0;
-
-	/* If the list is empty, all links are removed */
-	if (dl_list_empty(&mld->links)) {
-		mld->fbss = NULL;
-	} else {
-		next_fbss = dl_list_entry(mld->links.next, struct hostapd_data,
-					  link);
-		mld->fbss = next_fbss;
-	}
-
-	wpa_printf(MSG_DEBUG, "AP MLD %s: First link BSS set to %p",
-		   mld->name, mld->fbss);
-	return 0;
-}
-
-
-bool hostapd_mld_is_first_bss(struct hostapd_data *hapd)
-{
-	struct hostapd_mld *mld = hapd->mld;
-
-	if (!hapd->conf->mld_ap)
-		return true;
-
-	/* Should not happen */
-	if (!mld)
-		return false;
-
-	/* If fbss is not set, it is safe to assume the caller is the first BSS.
-	 */
-	if (!mld->fbss)
-		return true;
-
-	return hapd == mld->fbss;
-}
-
-
-struct hostapd_data * hostapd_mld_get_first_bss(struct hostapd_data *hapd)
-{
-	struct hostapd_mld *mld = hapd->mld;
-
-	if (!hapd->conf->mld_ap)
-		return NULL;
-
-	/* Should not happen */
-	if (!mld)
-		return NULL;
-
-	return mld->fbss;
-}
-
 #endif /* CONFIG_IEEE80211BE */
-
-
-u16 hostapd_get_punct_bitmap(struct hostapd_data *hapd)
-{
-	u16 punct_bitmap = 0;
-
-#ifdef CONFIG_IEEE80211BE
-	punct_bitmap = hapd->iconf->punct_bitmap;
-#ifdef CONFIG_TESTING_OPTIONS
-	if (!punct_bitmap)
-		punct_bitmap = hapd->conf->eht_oper_puncturing_override;
-#endif /* CONFIG_TESTING_OPTIONS */
-#endif /* CONFIG_IEEE80211BE */
-
-	return punct_bitmap;
-}
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index ff29726..7f703be 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -44,7 +44,6 @@
 #endif /* CONFIG_CTRL_IFACE_UDP */
 
 struct hostapd_iface;
-struct hostapd_mld;
 
 struct hapd_interfaces {
 	int (*reload_config)(struct hostapd_iface *iface);
@@ -94,10 +93,6 @@
        unsigned char ctrl_iface_cookie[CTRL_IFACE_COOKIE_LEN];
 #endif /* CONFIG_CTRL_IFACE_UDP */
 
-#ifdef CONFIG_IEEE80211BE
-	struct hostapd_mld **mld;
-	size_t mld_count;
-#endif /* CONFIG_IEEE80211BE */
 };
 
 enum hostapd_chan_status {
@@ -180,6 +175,12 @@
 	unsigned int reenable_beacon:1;
 
 	u8 own_addr[ETH_ALEN];
+	u8 mld_addr[ETH_ALEN];
+	u8 mld_link_id;
+	/* Used for mld_link_id assignment - valid on the first MLD BSS only */
+	u8 mld_next_link_id;
+
+	struct hostapd_data *mld_first_bss;
 
 	int num_sta; /* number of entries in sta_list */
 	struct sta_info *sta_list; /* STA info list head */
@@ -405,10 +406,8 @@
 	u8 beacon_req_token;
 	u8 lci_req_token;
 	u8 range_req_token;
-	u8 link_measurement_req_token;
 	unsigned int lci_req_active:1;
 	unsigned int range_req_active:1;
-	unsigned int link_mesr_req_active:1;
 
 	int dhcp_sock; /* UDP socket used with the DHCP server */
 
@@ -470,23 +469,6 @@
 #ifdef CONFIG_CTRL_IFACE_UDP
        unsigned char ctrl_iface_cookie[CTRL_IFACE_COOKIE_LEN];
 #endif /* CONFIG_CTRL_IFACE_UDP */
-
-#ifdef CONFIG_IEEE80211BE
-	u8 eht_mld_bss_param_change;
-	struct hostapd_mld *mld;
-	struct dl_list link;
-	u8 mld_link_id;
-#ifdef CONFIG_TESTING_OPTIONS
-	u8 eht_mld_link_removal_count;
-#endif /* CONFIG_TESTING_OPTIONS */
-#endif /* CONFIG_IEEE80211BE */
-
-#ifdef CONFIG_NAN_USD
-	struct nan_de *nan_de;
-#endif /* CONFIG_NAN_USD */
-
-	u64 scan_cookie; /* Scan instance identifier for the ongoing HT40 scan
-			  */
 };
 
 
@@ -511,29 +493,6 @@
 	HAPD_IFACE_ENABLED
 };
 
-#ifdef CONFIG_IEEE80211BE
-/**
- * struct hostapd_mld - hostapd per-mld data structure
- */
-struct hostapd_mld {
-	char name[IFNAMSIZ + 1];
-	u8 mld_addr[ETH_ALEN];
-	u8 next_link_id;
-	u8 num_links;
-	/* Number of hostapd_data (hapd) referencing this. num_links cannot be
-	 * used since num_links can go to 0 even when a BSS is disabled and
-	 * when it is re-enabled, the MLD should exist and hence it cannot be
-	 * freed when num_links is 0.
-	 */
-	u8 refcount;
-
-	struct hostapd_data *fbss;
-	struct dl_list links; /* List head of all affiliated links */
-};
-
-#define HOSTAPD_MLD_MAX_REF_COUNT      0xFF
-#endif /* CONFIG_IEEE80211BE */
-
 /**
  * struct hostapd_iface - hostapd per-interface data structure
  */
@@ -581,7 +540,6 @@
 
 	u64 drv_flags;
 	u64 drv_flags2;
-	unsigned int drv_rrm_flags;
 
 	/*
 	 * A bitmap of supported protocols for probe response offload. See
@@ -607,8 +565,6 @@
 	int *basic_rates;
 	int freq;
 
-	bool radar_detected;
-
 	/* Background radar configuration */
 	struct {
 		int channel;
@@ -710,8 +666,6 @@
 
 	/* Configured freq of interface is NO_IR */
 	bool is_no_ir;
-
-	bool is_ch_switch_dfs; /* Channel switch from ACS to DFS */
 };
 
 /* hostapd.c */
@@ -817,44 +771,5 @@
 int hostapd_mbssid_get_bss_index(struct hostapd_data *hapd);
 struct hostapd_data * hostapd_mld_get_link_bss(struct hostapd_data *hapd,
 					       u8 link_id);
-int hostapd_link_remove(struct hostapd_data *hapd, u32 count);
-bool hostapd_is_ml_partner(struct hostapd_data *hapd1,
-			   struct hostapd_data *hapd2);
-u8 hostapd_get_mld_id(struct hostapd_data *hapd);
-int hostapd_mld_add_link(struct hostapd_data *hapd);
-int hostapd_mld_remove_link(struct hostapd_data *hapd);
-struct hostapd_data * hostapd_mld_get_first_bss(struct hostapd_data *hapd);
-
-#ifdef CONFIG_IEEE80211BE
-
-bool hostapd_mld_is_first_bss(struct hostapd_data *hapd);
-
-#define for_each_mld_link(_link, _bss_idx, _iface_idx, _ifaces, _mld_id) \
-	for (_iface_idx = 0;						\
-	     _iface_idx < (_ifaces)->count;				\
-	     _iface_idx++)						\
-		for (_bss_idx = 0;					\
-		     _bss_idx <						\
-			(_ifaces)->iface[_iface_idx]->num_bss;		\
-		     _bss_idx++)					\
-			for (_link =					\
-			     (_ifaces)->iface[_iface_idx]->bss[_bss_idx]; \
-			    _link && _link->conf->mld_ap &&		\
-				hostapd_get_mld_id(_link) == _mld_id;	\
-			    _link = NULL)
-
-#else /* CONFIG_IEEE80211BE */
-
-static inline bool hostapd_mld_is_first_bss(struct hostapd_data *hapd)
-{
-	return true;
-}
-
-#define for_each_mld_link(_link, _bss_idx, _iface_idx, _ifaces, _mld_id) \
-	if (false)
-
-#endif /* CONFIG_IEEE80211BE */
-
-u16 hostapd_get_punct_bitmap(struct hostapd_data *hapd);
 
 #endif /* HOSTAPD_H */
diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index c455660..9edbb5a 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -107,7 +107,9 @@
 		 */
 		orig_mode_valid = true;
 		mode = iface->current_mode->mode;
-		is_6ghz = iface->current_mode->is_6ghz;
+		is_6ghz = mode == HOSTAPD_MODE_IEEE80211A &&
+			iface->current_mode->num_channels > 0 &&
+			is_6ghz_freq(iface->current_mode->channels[0].freq);
 		iface->current_mode = NULL;
 	}
 	hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
@@ -506,12 +508,6 @@
 	else
 		ieee80211n_scan_channels_5g(iface, &params);
 
-	params.link_id = -1;
-#ifdef CONFIG_IEEE80211BE
-	if (iface->bss[0]->conf->mld_ap)
-		params.link_id = iface->bss[0]->mld_link_id;
-#endif /* CONFIG_IEEE80211BE */
-
 	ret = hostapd_driver_scan(iface->bss[0], &params);
 	iface->num_ht40_scan_tries++;
 	os_free(params.freqs);
@@ -527,7 +523,6 @@
 
 	if (ret == 0) {
 		iface->scan_cb = ieee80211n_check_scan;
-		iface->bss[0]->scan_cookie = params.scan_cookie;
 		return;
 	}
 
@@ -563,11 +558,6 @@
 	else
 		ieee80211n_scan_channels_5g(iface, &params);
 
-	params.link_id = -1;
-#ifdef CONFIG_IEEE80211BE
-	if (iface->bss[0]->conf->mld_ap)
-		params.link_id = iface->bss[0]->mld_link_id;
-#endif /* CONFIG_IEEE80211BE */
 	ret = hostapd_driver_scan(iface->bss[0], &params);
 	os_free(params.freqs);
 
@@ -589,7 +579,6 @@
 	}
 
 	iface->scan_cb = ieee80211n_check_scan;
-	iface->bss[0]->scan_cookie = params.scan_cookie;
 	return 1;
 }
 
@@ -1012,7 +1001,7 @@
 {
 	int secondary_freq;
 	struct hostapd_channel_data *pri_chan;
-	int err, err2;
+	int err;
 
 	if (!iface->current_mode)
 		return 0;
@@ -1055,15 +1044,15 @@
 
 	/* Both HT40+ and HT40- are set, pick a valid secondary channel */
 	secondary_freq = iface->freq + 20;
-	err2 = hostapd_is_usable_chan(iface, secondary_freq, 0);
-	if (err2 > 0 && (pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P)) {
+	err = hostapd_is_usable_chan(iface, secondary_freq, 0);
+	if (err > 0 && (pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P)) {
 		iface->conf->secondary_channel = 1;
 		return 1;
 	}
 
 	secondary_freq = iface->freq - 20;
-	err2 = hostapd_is_usable_chan(iface, secondary_freq, 0);
-	if (err2 > 0 && (pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40M)) {
+	err = hostapd_is_usable_chan(iface, secondary_freq, 0);
+	if (err > 0 && (pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40M)) {
 		iface->conf->secondary_channel = -1;
 		return 1;
 	}
@@ -1081,7 +1070,9 @@
 		return true;
 
 	if (is_6ghz_op_class(iface->conf->op_class) && iface->freq == 0 &&
-	    !mode->is_6ghz)
+	    (mode->mode != HOSTAPD_MODE_IEEE80211A ||
+	     mode->num_channels == 0 ||
+	     !is_6ghz_freq(mode->channels[0].freq)))
 		return true;
 
 	return false;
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 85a39d5..1f39107 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -56,7 +56,6 @@
 #include "dpp_hostapd.h"
 #include "gas_query_ap.h"
 #include "comeback_token.h"
-#include "nan_usd_ap.h"
 #include "pasn/pasn_common.h"
 
 
@@ -88,31 +87,18 @@
 			      struct sta_info *sta, int reassoc);
 
 
-static u8 * hostapd_eid_multi_ap(struct hostapd_data *hapd, u8 *eid, size_t len)
+u8 * hostapd_eid_multi_ap(struct hostapd_data *hapd, u8 *eid)
 {
-	struct multi_ap_params multi_ap = { 0 };
+	u8 multi_ap_val = 0;
 
 	if (!hapd->conf->multi_ap)
 		return eid;
-
 	if (hapd->conf->multi_ap & BACKHAUL_BSS)
-		multi_ap.capability |= MULTI_AP_BACKHAUL_BSS;
+		multi_ap_val |= MULTI_AP_BACKHAUL_BSS;
 	if (hapd->conf->multi_ap & FRONTHAUL_BSS)
-		multi_ap.capability |= MULTI_AP_FRONTHAUL_BSS;
+		multi_ap_val |= MULTI_AP_FRONTHAUL_BSS;
 
-	if (hapd->conf->multi_ap_client_disallow &
-	    PROFILE1_CLIENT_ASSOC_DISALLOW)
-		multi_ap.capability |=
-			MULTI_AP_PROFILE1_BACKHAUL_STA_DISALLOWED;
-	if (hapd->conf->multi_ap_client_disallow &
-	    PROFILE2_CLIENT_ASSOC_DISALLOW)
-		multi_ap.capability |=
-			MULTI_AP_PROFILE2_BACKHAUL_STA_DISALLOWED;
-
-	multi_ap.profile = hapd->conf->multi_ap_profile;
-	multi_ap.vlanid = hapd->conf->multi_ap_vlanid;
-
-	return eid + add_multi_ap_ie(eid, len, &multi_ap);
+	return eid + add_multi_ap_ie(eid, 9, multi_ap_val);
 }
 
 
@@ -421,8 +407,8 @@
 	 * the MLD MAC address. Thus, use the MLD address instead of translating
 	 * the addresses.
 	 */
-	if (ap_sta_is_mld(hapd, sta)) {
-		sa = hapd->mld->mld_addr;
+	if (hapd->conf->mld_ap && sta && sta->mld_info.mld_sta) {
+		sa = hapd->mld_addr;
 
 		ml_resp = hostapd_ml_auth_resp(hapd);
 		if (!ml_resp)
@@ -570,7 +556,7 @@
 	for (pw = hapd->conf->sae_passwords; pw; pw = pw->next) {
 		if (!is_broadcast_ether_addr(pw->peer_addr) &&
 		    (!sta ||
-		     !ether_addr_equal(pw->peer_addr, sta->addr)))
+		     os_memcmp(pw->peer_addr, sta->addr, ETH_ALEN) != 0))
 			continue;
 		if ((rx_id && !pw->identifier) || (!rx_id && pw->identifier))
 			continue;
@@ -622,8 +608,8 @@
 	const u8 *own_addr = hapd->own_addr;
 
 #ifdef CONFIG_IEEE80211BE
-	if (ap_sta_is_mld(hapd, sta))
-		own_addr = hapd->mld->mld_addr;
+	if (hapd->conf->mld_ap && sta->mld_info.mld_sta)
+		own_addr = hapd->mld_addr;
 #endif /* CONFIG_IEEE80211BE */
 
 	if (sta->sae->tmp) {
@@ -891,7 +877,7 @@
 	params.status = status;
 
 #ifdef CONFIG_IEEE80211BE
-	if (ap_sta_is_mld(hapd, sta))
+	if (sta->mld_info.mld_sta)
 		params.bssid =
 			sta->mld_info.links[sta->mld_assoc_link_id].peer_addr;
 #endif /* CONFIG_IEEE80211BE */
@@ -916,27 +902,23 @@
 			   " to VLAN ID %d",
 			   MAC2STR(sta->addr), sta->sae->tmp->vlan_id);
 
-		if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_VLAN_OFFLOAD)) {
-			os_memset(&vlan_desc, 0, sizeof(vlan_desc));
-			vlan_desc.notempty = 1;
-			vlan_desc.untagged = sta->sae->tmp->vlan_id;
-			if (!hostapd_vlan_valid(hapd->conf->vlan, &vlan_desc)) {
-				wpa_printf(MSG_INFO,
-					   "Invalid VLAN ID %d in sae_password",
-					   sta->sae->tmp->vlan_id);
-				return;
-			}
+		os_memset(&vlan_desc, 0, sizeof(vlan_desc));
+		vlan_desc.notempty = 1;
+		vlan_desc.untagged = sta->sae->tmp->vlan_id;
+		if (!hostapd_vlan_valid(hapd->conf->vlan, &vlan_desc)) {
+			wpa_printf(MSG_INFO,
+				   "Invalid VLAN ID %d in sae_password",
+				   sta->sae->tmp->vlan_id);
+			return;
+		}
 
-			if (ap_sta_set_vlan(hapd, sta, &vlan_desc) < 0 ||
-			    ap_sta_bind_vlan(hapd, sta) < 0) {
-				wpa_printf(MSG_INFO,
-					   "Failed to assign VLAN ID %d from sae_password to "
-					   MACSTR, sta->sae->tmp->vlan_id,
-					   MAC2STR(sta->addr));
-				return;
-			}
-		} else {
-			sta->vlan_id = sta->sae->tmp->vlan_id;
+		if (ap_sta_set_vlan(hapd, sta, &vlan_desc) < 0 ||
+		    ap_sta_bind_vlan(hapd, sta) < 0) {
+			wpa_printf(MSG_INFO,
+				   "Failed to assign VLAN ID %d from sae_password to "
+				   MACSTR, sta->sae->tmp->vlan_id,
+				   MAC2STR(sta->addr));
+			return;
 		}
 	}
 #endif /* CONFIG_NO_VLAN */
@@ -1291,8 +1273,7 @@
 		pos = mgmt->u.auth.variable;
 		end = ((const u8 *) mgmt) + len;
 		resp = status_code;
-		send_auth_reply(hapd, sta, sta->addr, mgmt->bssid,
-				WLAN_AUTH_SAE,
+		send_auth_reply(hapd, sta, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
 				auth_transaction, resp, pos, end - pos,
 				"auth-sae-reflection-attack");
 		goto remove_sta;
@@ -1300,8 +1281,7 @@
 
 	if (hapd->conf->sae_commit_override && auth_transaction == 1) {
 		wpa_printf(MSG_DEBUG, "SAE: TESTING - commit override");
-		send_auth_reply(hapd, sta, sta->addr, mgmt->bssid,
-				WLAN_AUTH_SAE,
+		send_auth_reply(hapd, sta, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
 				auth_transaction, resp,
 				wpabuf_head(hapd->conf->sae_commit_override),
 				wpabuf_len(hapd->conf->sae_commit_override),
@@ -1572,8 +1552,7 @@
 			data = wpabuf_alloc_copy(pos, 2);
 
 		sae_sme_send_external_auth_status(hapd, sta, resp);
-		send_auth_reply(hapd, sta, sta->addr, mgmt->bssid,
-				WLAN_AUTH_SAE,
+		send_auth_reply(hapd, sta, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
 				auth_transaction, resp,
 				data ? wpabuf_head(data) : (u8 *) "",
 				data ? wpabuf_len(data) : 0, "auth-sae");
@@ -1685,7 +1664,7 @@
 	dl_list_for_each(q2, &hapd->sae_commit_queue,
 			 struct hostapd_sae_commit_queue, list) {
 		mgmt2 = (const struct ieee80211_mgmt *) q2->msg;
-		if (ether_addr_equal(mgmt->sa, mgmt2->sa) &&
+		if (os_memcmp(mgmt->sa, mgmt2->sa, ETH_ALEN) == 0 &&
 		    mgmt->u.auth.auth_transaction ==
 		    mgmt2->u.auth.auth_transaction) {
 			wpa_printf(MSG_DEBUG,
@@ -1716,7 +1695,7 @@
 	dl_list_for_each(q, &hapd->sae_commit_queue,
 			 struct hostapd_sae_commit_queue, list) {
 		mgmt = (const struct ieee80211_mgmt *) q->msg;
-		if (ether_addr_equal(addr, mgmt->sa))
+		if (os_memcmp(addr, mgmt->sa, ETH_ALEN) == 0)
 			return 1;
 	}
 
@@ -2042,7 +2021,7 @@
 		}
 
 		os_memcpy(ie_buf, ie, ielen);
-		if (wpa_insert_pmkid(ie_buf, &ielen, pmksa->pmkid, true) < 0) {
+		if (wpa_insert_pmkid(ie_buf, &ielen, pmksa->pmkid) < 0) {
 			*resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
 			goto fail;
 		}
@@ -2170,8 +2149,7 @@
 				    pmk, pmk_len,
 				    sta->fils_erp_pmkid,
 				    session_timeout,
-				    wpa_auth_sta_key_mgmt(sta->wpa_sm),
-				    NULL) < 0) {
+				    wpa_auth_sta_key_mgmt(sta->wpa_sm)) < 0) {
 				wpa_printf(MSG_ERROR,
 					   "FILS: Failed to add PMKSA cache entry based on ERP");
 			}
@@ -2403,7 +2381,7 @@
 	wpa_hexdump(MSG_DEBUG, "RSN: Generated FILS ANonce",
 		    fils->anonce, FILS_NONCE_LEN);
 
-	ret = fils_rmsk_to_pmk(pasn_get_akmp(pasn), msk, msk_len, fils->nonce,
+	ret = fils_rmsk_to_pmk(pasn->akmp, msk, msk_len, fils->nonce,
 			       fils->anonce, NULL, 0, pmk, &pmk_len);
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "FILS: Failed to derive PMK");
@@ -2413,16 +2391,15 @@
 	ret = pasn_pmk_to_ptk(pmk, pmk_len, sta->addr, hapd->own_addr,
 			      wpabuf_head(pasn->secret),
 			      wpabuf_len(pasn->secret),
-			      pasn_get_ptk(sta->pasn), pasn_get_akmp(sta->pasn),
-			      pasn_get_cipher(sta->pasn), sta->pasn->kdk_len);
+			      &sta->pasn->ptk, sta->pasn->akmp,
+			      sta->pasn->cipher, sta->pasn->kdk_len);
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "PASN: FILS: Failed to derive PTK");
 		goto fail;
 	}
 
 	if (pasn->secure_ltf) {
-		ret = wpa_ltf_keyseed(pasn_get_ptk(pasn), pasn_get_akmp(pasn),
-				      pasn_get_cipher(pasn));
+		ret = wpa_ltf_keyseed(&pasn->ptk, pasn->akmp, pasn->cipher);
 		if (ret) {
 			wpa_printf(MSG_DEBUG,
 				   "PASN: FILS: Failed to derive LTF keyseed");
@@ -2543,8 +2520,8 @@
 		    FILS_SESSION_LEN);
 	os_memcpy(fils->session, elems.fils_session, FILS_SESSION_LEN);
 
-	fils_wd = ieee802_11_defrag(elems.wrapped_data, elems.wrapped_data_len,
-				    true);
+	fils_wd = ieee802_11_defrag(&elems, WLAN_EID_EXTENSION,
+				    WLAN_EID_EXT_WRAPPED_DATA);
 
 	if (!fils_wd) {
 		wpa_printf(MSG_DEBUG, "PASN: FILS: Missing wrapped data");
@@ -2568,8 +2545,7 @@
 	 * Calculate pending PMKID here so that we do not need to maintain a
 	 * copy of the EAP-Initiate/Reautt message.
 	 */
-	fils_pmkid_erp(pasn_get_akmp(pasn),
-		       wpabuf_head(fils_wd), wpabuf_len(fils_wd),
+	fils_pmkid_erp(pasn->akmp, wpabuf_head(fils_wd), wpabuf_len(fils_wd),
 		       fils->erp_pmkid);
 
 	wpabuf_free(fils_wd);
@@ -2594,35 +2570,32 @@
 {
 	struct pasn_data *pasn = sta->pasn;
 
-	pasn_register_callbacks(pasn, hapd, hapd_pasn_send_mlme, NULL);
-	pasn_set_bssid(pasn, hapd->own_addr);
-	pasn_set_own_addr(pasn, hapd->own_addr);
-	pasn_set_peer_addr(pasn, sta->addr);
-	pasn_set_wpa_key_mgmt(pasn, hapd->conf->wpa_key_mgmt);
-	pasn_set_rsn_pairwise(pasn, hapd->conf->rsn_pairwise);
+	pasn->cb_ctx = hapd;
+	pasn->send_mgmt = hapd_pasn_send_mlme;
 	pasn->pasn_groups = hapd->conf->pasn_groups;
 	pasn->noauth = hapd->conf->pasn_noauth;
-	if (hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF_AP)
-		pasn_enable_kdk_derivation(pasn);
-
+	pasn->wpa_key_mgmt = hapd->conf->wpa_key_mgmt;
+	pasn->rsn_pairwise = hapd->conf->rsn_pairwise;
+	pasn->derive_kdk = hapd->iface->drv_flags2 &
+		WPA_DRIVER_FLAGS2_SEC_LTF_AP;
 #ifdef CONFIG_TESTING_OPTIONS
 	pasn->corrupt_mic = hapd->conf->pasn_corrupt_mic;
 	if (hapd->conf->force_kdk_derivation)
-		pasn_enable_kdk_derivation(pasn);
+		pasn->derive_kdk = true;
 #endif /* CONFIG_TESTING_OPTIONS */
 	pasn->use_anti_clogging = use_anti_clogging(hapd);
-	pasn_set_password(pasn, sae_get_password(hapd, sta, NULL, NULL,
-						 &pasn->pt, NULL));
+	pasn->password = sae_get_password(hapd, sta, NULL, NULL, &pasn->pt,
+					  NULL);
 	pasn->rsn_ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &pasn->rsn_ie_len);
-	pasn_set_rsnxe_ie(pasn, hostapd_wpa_ie(hapd, WLAN_EID_RSNX));
+	pasn->rsnxe_ie = hostapd_wpa_ie(hapd, WLAN_EID_RSNX);
 	pasn->disable_pmksa_caching = hapd->conf->disable_pmksa_caching;
-	pasn_set_responder_pmksa(pasn,
-				 wpa_auth_get_pmksa_cache(hapd->wpa_auth));
+	pasn->pmksa = wpa_auth_get_pmksa_cache(hapd->wpa_auth);
 
 	pasn->comeback_after = hapd->conf->pasn_comeback_after;
 	pasn->comeback_idx = hapd->comeback_idx;
 	pasn->comeback_key =  hapd->comeback_key;
 	pasn->comeback_pending_idx = hapd->comeback_pending_idx;
+	os_memcpy(pasn->bssid, hapd->own_addr, ETH_ALEN);
 }
 
 
@@ -2639,7 +2612,7 @@
 		return -1;
 	}
 
-	if (!ether_addr_equal(entry->own_addr, own_addr)) {
+	if (os_memcmp(entry->own_addr, own_addr, ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG,
 			   "PASN: own addr " MACSTR " and PTKSA entry own addr "
 			   MACSTR " differ",
@@ -2666,11 +2639,8 @@
 	struct pasn_data *pasn = sta->pasn;
 	struct ieee802_11_elems elems;
 	struct wpa_ie_data rsn_data;
-#ifdef CONFIG_FILS
 	struct wpa_pasn_params_data pasn_params;
 	struct wpabuf *wrapped_data = NULL;
-#endif /* CONFIG_FILS */
-	int akmp;
 
 	if (ieee802_11_parse_elems(mgmt->u.auth.variable,
 				   len - offsetof(struct ieee80211_mgmt,
@@ -2694,12 +2664,10 @@
 		return;
 	}
 
-	pasn_set_akmp(pasn, rsn_data.key_mgmt);
-	pasn_set_cipher(pasn, rsn_data.pairwise_cipher);
+	pasn->akmp = rsn_data.key_mgmt;
+	pasn->cipher = rsn_data.pairwise_cipher;
 
-	akmp = pasn_get_akmp(pasn);
-
-	if (wpa_key_mgmt_ft(akmp) && rsn_data.num_pmkid) {
+	if (wpa_key_mgmt_ft(pasn->akmp) && rsn_data.num_pmkid) {
 #ifdef CONFIG_IEEE80211R_AP
 		pasn->pmk_r1_len = 0;
 		wpa_ft_fetch_pmk_r1(hapd->wpa_auth, sta->addr,
@@ -2710,8 +2678,8 @@
 #endif /* CONFIG_IEEE80211R_AP */
 	}
 #ifdef CONFIG_FILS
-	if (akmp != WPA_KEY_MGMT_FILS_SHA256 &&
-	    akmp != WPA_KEY_MGMT_FILS_SHA384)
+	if (pasn->akmp != WPA_KEY_MGMT_FILS_SHA256 &&
+	    pasn->akmp != WPA_KEY_MGMT_FILS_SHA384)
 		return;
 	if (!elems.pasn_params ||
 	    wpa_pasn_parse_parameter_ie(elems.pasn_params - 3,
@@ -2722,8 +2690,8 @@
 		return;
 	}
 	if (pasn_params.wrapped_data_format != WPA_PASN_WRAPPED_DATA_NO) {
-		wrapped_data = ieee802_11_defrag(elems.wrapped_data,
-						 elems.wrapped_data_len, true);
+		wrapped_data = ieee802_11_defrag(&elems, WLAN_EID_EXTENSION,
+						 WLAN_EID_EXT_WRAPPED_DATA);
 		if (!wrapped_data) {
 			wpa_printf(MSG_DEBUG, "PASN: Missing wrapped data");
 			return;
@@ -2764,7 +2732,7 @@
 			return;
 		}
 
-		sta->pasn = pasn_data_init();
+		sta->pasn = os_zalloc(sizeof(*sta->pasn));
 		if (!sta->pasn) {
 			wpa_printf(MSG_DEBUG,
 				   "PASN: Failed to allocate PASN context");
@@ -2794,14 +2762,13 @@
 		if (handle_auth_pasn_3(sta->pasn, hapd->own_addr,
 				       sta->addr, mgmt, len) == 0) {
 			ptksa_cache_add(hapd->ptksa, hapd->own_addr, sta->addr,
-					pasn_get_cipher(sta->pasn), 43200,
-					pasn_get_ptk(sta->pasn), NULL, NULL,
-					pasn_get_akmp(sta->pasn));
+					sta->pasn->cipher, 43200,
+					&sta->pasn->ptk, NULL, NULL,
+					sta->pasn->akmp);
 
 			pasn_set_keys_from_cache(hapd, hapd->own_addr,
-						 sta->addr,
-						 pasn_get_cipher(sta->pasn),
-						 pasn_get_akmp(sta->pasn));
+						 sta->addr, sta->pasn->cipher,
+						 sta->pasn->akmp);
 		}
 		ap_free_sta(hapd, sta);
 	} else {
@@ -2828,9 +2795,7 @@
 	u16 seq_ctrl;
 	struct radius_sta rad_info;
 	const u8 *dst, *sa, *bssid;
-#ifdef CONFIG_IEEE80211BE
 	bool mld_sta = false;
-#endif /* CONFIG_IEEE80211BE */
 
 	if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
 		wpa_printf(MSG_INFO, "handle_auth - too short payload (len=%lu)",
@@ -2941,24 +2906,22 @@
 		goto fail;
 	}
 
-	if (ether_addr_equal(mgmt->sa, hapd->own_addr)) {
+	if (os_memcmp(mgmt->sa, hapd->own_addr, ETH_ALEN) == 0) {
 		wpa_printf(MSG_INFO, "Station " MACSTR " not allowed to authenticate",
 			   MAC2STR(sa));
 		resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
 		goto fail;
 	}
 
-#ifdef CONFIG_IEEE80211BE
 	if (mld_sta &&
-	    (ether_addr_equal(sa, hapd->own_addr) ||
-	     ether_addr_equal(sa, hapd->mld->mld_addr))) {
+	    (os_memcmp(sa, hapd->own_addr, ETH_ALEN) == 0 ||
+	     os_memcmp(sa, hapd->mld_addr, ETH_ALEN) == 0)) {
 		wpa_printf(MSG_INFO,
 			   "Station " MACSTR " not allowed to authenticate",
 			   MAC2STR(sa));
 		resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
 		goto fail;
 	}
-#endif /* CONFIG_IEEE80211BE */
 
 	if (hapd->conf->no_auth_if_seen_on) {
 		struct hostapd_data *other;
@@ -3058,6 +3021,15 @@
 				       seq_ctrl);
 			return;
 		}
+#ifdef CONFIG_MESH
+		if ((hapd->conf->mesh & MESH_ENABLED) &&
+		    sta->plink_state == PLINK_BLOCKED) {
+			wpa_printf(MSG_DEBUG, "Mesh peer " MACSTR
+				   " is blocked - drop Authentication frame",
+				   MAC2STR(sa));
+			return;
+		}
+#endif /* CONFIG_MESH */
 #ifdef CONFIG_PASN
 		if (auth_alg == WLAN_AUTH_PASN &&
 		    (sta->flags & WLAN_STA_ASSOC)) {
@@ -3095,19 +3067,13 @@
 	}
 
 #ifdef CONFIG_IEEE80211BE
-	/* Set the non-AP MLD information based on the initial Authentication
-	 * frame. Once the STA entry has been added to the driver, the driver
-	 * will translate addresses in the frame and we need to avoid overriding
-	 * peer_addr based on mgmt->sa which would have been translated to the
-	 * MLD MAC address. */
-	if (!sta->added_unassoc && auth_transaction == 1) {
-		ap_sta_free_sta_profile(&sta->mld_info);
+	if (auth_transaction == 1) {
 		os_memset(&sta->mld_info, 0, sizeof(sta->mld_info));
 
 		if (mld_sta) {
 			u8 link_id = hapd->mld_link_id;
 
-			ap_sta_set_mld(sta, true);
+			sta->mld_info.mld_sta = true;
 			sta->mld_assoc_link_id = link_id;
 
 			/*
@@ -3270,9 +3236,9 @@
 	  * the MLD MAC address. It is the responsibility of the driver to
 	  * handle the translations.
 	  */
-	if (ap_sta_is_mld(hapd, sta)) {
+	if (hapd->conf->mld_ap && sta && sta->mld_info.mld_sta) {
 		dst = sta->addr;
-		bssid = hapd->mld->mld_addr;
+		bssid = hapd->mld_addr;
 	}
 #endif /* CONFIG_IEEE80211BE */
 
@@ -3315,7 +3281,7 @@
 
 	/* Do not assign an AID that is in use on any of the affiliated links
 	 * when finding an AID for a non-AP MLD. */
-	if (hapd->conf->mld_ap && sta->mld_info.mld_sta) {
+	if (hapd->conf->mld_ap) {
 		int j;
 
 		for (j = 0; j < MAX_NUM_MLD_LINKS; j++) {
@@ -3432,58 +3398,37 @@
 static u16 check_multi_ap(struct hostapd_data *hapd, struct sta_info *sta,
 			  const u8 *multi_ap_ie, size_t multi_ap_len)
 {
-	struct multi_ap_params multi_ap;
-	u16 status;
+	u8 multi_ap_value = 0;
 
 	sta->flags &= ~WLAN_STA_MULTI_AP;
 
 	if (!hapd->conf->multi_ap)
 		return WLAN_STATUS_SUCCESS;
 
-	if (!multi_ap_ie) {
-		if (!(hapd->conf->multi_ap & FRONTHAUL_BSS)) {
+	if (multi_ap_ie) {
+		const u8 *multi_ap_subelem;
+
+		multi_ap_subelem = get_ie(multi_ap_ie + 4,
+					  multi_ap_len - 4,
+					  MULTI_AP_SUB_ELEM_TYPE);
+		if (multi_ap_subelem && multi_ap_subelem[1] == 1) {
+			multi_ap_value = multi_ap_subelem[2];
+		} else {
 			hostapd_logger(hapd, sta->addr,
 				       HOSTAPD_MODULE_IEEE80211,
 				       HOSTAPD_LEVEL_INFO,
-				       "Non-Multi-AP STA tries to associate with backhaul-only BSS");
-			return WLAN_STATUS_ASSOC_DENIED_UNSPEC;
+				       "Multi-AP IE has missing or invalid Multi-AP subelement");
+			return WLAN_STATUS_INVALID_IE;
 		}
-
-		return WLAN_STATUS_SUCCESS;
 	}
 
-	status = check_multi_ap_ie(multi_ap_ie + 4, multi_ap_len - 4,
-				   &multi_ap);
-	if (status != WLAN_STATUS_SUCCESS)
-		return status;
-
-	if (multi_ap.capability && multi_ap.capability != MULTI_AP_BACKHAUL_STA)
+	if (multi_ap_value && multi_ap_value != MULTI_AP_BACKHAUL_STA)
 		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
 			       HOSTAPD_LEVEL_INFO,
 			       "Multi-AP IE with unexpected value 0x%02x",
-			       multi_ap.capability);
+			       multi_ap_value);
 
-	if (multi_ap.profile == MULTI_AP_PROFILE_1 &&
-	    (hapd->conf->multi_ap_client_disallow &
-	     PROFILE1_CLIENT_ASSOC_DISALLOW)) {
-		hostapd_logger(hapd, sta->addr,
-			       HOSTAPD_MODULE_IEEE80211,
-			       HOSTAPD_LEVEL_INFO,
-			       "Multi-AP Profile-1 clients not allowed");
-		return WLAN_STATUS_ASSOC_DENIED_UNSPEC;
-	}
-
-	if (multi_ap.profile >= MULTI_AP_PROFILE_2 &&
-	    (hapd->conf->multi_ap_client_disallow &
-	     PROFILE2_CLIENT_ASSOC_DISALLOW)) {
-		hostapd_logger(hapd, sta->addr,
-			       HOSTAPD_MODULE_IEEE80211,
-			       HOSTAPD_LEVEL_INFO,
-			       "Multi-AP Profile-2 clients not allowed");
-		return WLAN_STATUS_ASSOC_DENIED_UNSPEC;
-	}
-
-	if (!(multi_ap.capability & MULTI_AP_BACKHAUL_STA)) {
+	if (!(multi_ap_value & MULTI_AP_BACKHAUL_STA)) {
 		if (hapd->conf->multi_ap & FRONTHAUL_BSS)
 			return WLAN_STATUS_SUCCESS;
 
@@ -3710,7 +3655,7 @@
 	wpa_hexdump_key(MSG_DEBUG, "OWE: PMK", sta->owe_pmk, sta->owe_pmk_len);
 	wpa_hexdump(MSG_DEBUG, "OWE: PMKID", pmkid, PMKID_LEN);
 	wpa_auth_pmksa_add2(hapd->wpa_auth, sta->addr, sta->owe_pmk,
-			    sta->owe_pmk_len, pmkid, 0, WPA_KEY_MGMT_OWE, NULL);
+			    sta->owe_pmk_len, pmkid, 0, WPA_KEY_MGMT_OWE);
 
 	return WLAN_STATUS_SUCCESS;
 }
@@ -3782,8 +3727,8 @@
 		goto end;
 	}
 #ifdef CONFIG_IEEE80211BE
-	if (ap_sta_is_mld(hapd, sta))
-		wpa_auth_set_ml_info(sta->wpa_sm, hapd->mld->mld_addr,
+	if (sta->mld_info.mld_sta)
+		wpa_auth_set_ml_info(sta->wpa_sm, hapd->mld_addr,
 				     sta->mld_assoc_link_id, &sta->mld_info);
 #endif /* CONFIG_IEEE80211BE */
 	rsn_ie -= 2;
@@ -4064,11 +4009,11 @@
 			}
 
 #ifdef CONFIG_IEEE80211BE
-			if (ap_sta_is_mld(hapd, sta)) {
+			if (info->mld_sta) {
 				wpa_printf(MSG_DEBUG,
 					   "MLD: Set ML info in RSN Authenticator");
 				wpa_auth_set_ml_info(sta->wpa_sm,
-						     hapd->mld->mld_addr,
+						     hapd->mld_addr,
 						     sta->mld_assoc_link_id,
 						     info);
 			}
@@ -4364,23 +4309,22 @@
 
 #ifdef CONFIG_IEEE80211BE
 
-static void ieee80211_ml_build_assoc_resp(struct hostapd_data *hapd,
-					  struct mld_link_info *link)
+static size_t ieee80211_ml_build_assoc_resp(struct hostapd_data *hapd,
+					    u16 status_code,
+					    u8 *buf, size_t buflen)
 {
-	u8 buf[EHT_ML_MAX_STA_PROF_LEN];
 	u8 *p = buf;
-	size_t buflen = sizeof(buf);
 
 	/* Capability Info */
 	WPA_PUT_LE16(p, hostapd_own_capab_info(hapd));
 	p += 2;
 
 	/* Status Code */
-	WPA_PUT_LE16(p, link->status);
+	WPA_PUT_LE16(p, status_code);
 	p += 2;
 
-	if (link->status != WLAN_STATUS_SUCCESS)
-		goto out;
+	if (status_code != WLAN_STATUS_SUCCESS)
+		return p - buf;
 
 	/* AID is not included */
 	p = hostapd_eid_supp_rates(hapd, p);
@@ -4418,24 +4362,20 @@
 		p += wpabuf_len(hapd->conf->assocresp_elements);
 	}
 
-out:
-	os_free(link->resp_sta_profile);
-	link->resp_sta_profile = os_memdup(buf, p - buf);
-	link->resp_sta_profile_len = link->resp_sta_profile ? p - buf : 0;
+	return p - buf;
 }
 
 
-static int ieee80211_ml_process_link(struct hostapd_data *hapd,
-				     struct sta_info *origin_sta,
-				     struct mld_link_info *link,
-				     const u8 *ies, size_t ies_len,
-				     bool reassoc, bool offload)
+static void ieee80211_ml_process_link(struct hostapd_data *hapd,
+				      struct sta_info *origin_sta,
+				      struct mld_link_info *link,
+				      const u8 *ies, size_t ies_len,
+				      bool reassoc)
 {
 	struct ieee802_11_elems elems;
 	struct wpabuf *mlbuf = NULL;
 	struct sta_info *sta = NULL;
 	u16 status = WLAN_STATUS_SUCCESS;
-	int i;
 
 	wpa_printf(MSG_DEBUG, "MLD: link: link_id=%u, peer=" MACSTR,
 		   hapd->mld_link_id, MAC2STR(link->peer_addr));
@@ -4461,7 +4401,7 @@
 		goto out;
 	}
 
-	mlbuf = ieee802_11_defrag(elems.basic_mle, elems.basic_mle_len, true);
+	mlbuf = ieee802_11_defrag_mle(&elems, MULTI_LINK_CONTROL_TYPE_BASIC);
 	if (!mlbuf)
 		goto out;
 
@@ -4481,33 +4421,25 @@
 		goto out;
 	}
 
-	ap_sta_set_mld(sta, true);
+	sta->mld_info.mld_sta = true;
 	sta->mld_assoc_link_id = origin_sta->mld_assoc_link_id;
 
 	os_memcpy(&sta->mld_info, &origin_sta->mld_info, sizeof(sta->mld_info));
-	for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
-		struct mld_link_info *li = &sta->mld_info.links[i];
 
-		li->resp_sta_profile = NULL;
-		li->resp_sta_profile_len = 0;
+	/*
+	 * Get the AID from the station on which the association was performed,
+	 * and mark it as used.
+	 */
+	sta->aid = origin_sta->aid;
+	if (sta->aid == 0) {
+		wpa_printf(MSG_DEBUG, "MLD: link: No AID assigned");
+		status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+		goto out;
 	}
-
-	if (!offload) {
-		/*
-		 * Get the AID from the station on which the association was
-		 * performed, and mark it as used.
-		 */
-		sta->aid = origin_sta->aid;
-		if (sta->aid == 0) {
-			wpa_printf(MSG_DEBUG, "MLD: link: No AID assigned");
-			status = WLAN_STATUS_UNSPECIFIED_FAILURE;
-			goto out;
-		}
-		hapd->sta_aid[(sta->aid - 1) / 32] |= BIT((sta->aid - 1) % 32);
-		sta->listen_interval = origin_sta->listen_interval;
-		if (update_ht_state(hapd, sta) > 0)
-			ieee802_11_update_beacons(hapd->iface);
-	}
+	hapd->sta_aid[(sta->aid - 1) / 32] |= BIT((sta->aid - 1) % 32);
+	sta->listen_interval = origin_sta->listen_interval;
+	if (update_ht_state(hapd, sta) > 0)
+		ieee802_11_update_beacons(hapd->iface);
 
 	/* RSN Authenticator should always be the one on the original station */
 	wpa_auth_sta_deinit(sta->wpa_sm);
@@ -4533,23 +4465,20 @@
 
 	/* TODO: What other processing is required? */
 
-	if (!offload && add_associated_sta(hapd, sta, reassoc))
+	if (add_associated_sta(hapd, sta, reassoc))
 		status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
 out:
 	wpabuf_free(mlbuf);
 	link->status = status;
 
-	if (!offload)
-		ieee80211_ml_build_assoc_resp(hapd, link);
-
 	wpa_printf(MSG_DEBUG, "MLD: link: status=%u", status);
-	if (status != WLAN_STATUS_SUCCESS) {
-		if (sta)
-			ap_free_sta(hapd, sta);
-		return -1;
-	}
+	if (sta && status != WLAN_STATUS_SUCCESS)
+		ap_free_sta(hapd, sta);
 
-	return 0;
+	link->resp_sta_profile_len =
+		ieee80211_ml_build_assoc_resp(hapd, link->status,
+					      link->resp_sta_profile,
+					      sizeof(link->resp_sta_profile));
 }
 
 
@@ -4568,17 +4497,16 @@
 #endif /* CONFIG_IEEE80211BE */
 
 
-int hostapd_process_assoc_ml_info(struct hostapd_data *hapd,
-				  struct sta_info *sta,
-				  const u8 *ies, size_t ies_len,
-				  bool reassoc, int tx_link_status,
-				  bool offload)
+static void hostapd_process_assoc_ml_info(struct hostapd_data *hapd,
+					  struct sta_info *sta,
+					  const u8 *ies, size_t ies_len,
+					  bool reassoc)
 {
 #ifdef CONFIG_IEEE80211BE
 	unsigned int i, j;
 
 	if (!hostapd_is_mld_ap(hapd))
-		return 0;
+		return;
 
 	/*
 	 * This is not really needed, but make the interaction with the RSN
@@ -4602,34 +4530,28 @@
 			if (hapd->iface == iface)
 				continue;
 
-			if (hostapd_is_ml_partner(hapd, iface->bss[0]) &&
+			if (iface->bss[0]->conf->mld_ap &&
+			    hapd->conf->mld_id == iface->bss[0]->conf->mld_id &&
 			    i == iface->bss[0]->mld_link_id)
 				break;
 		}
 
-		if (!iface || j == hapd->iface->interfaces->count ||
-		    TEST_FAIL()) {
+		if (!iface || j == hapd->iface->interfaces->count) {
 			wpa_printf(MSG_DEBUG,
 				   "MLD: No link match for link_id=%u", i);
 
 			link->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
-			if (!offload)
-				ieee80211_ml_build_assoc_resp(hapd, link);
-		} else if (tx_link_status != WLAN_STATUS_SUCCESS) {
-			/* TX link rejected the connection */
-			link->status = WLAN_STATUS_DENIED_TX_LINK_NOT_ACCEPTED;
-			if (!offload)
-				ieee80211_ml_build_assoc_resp(hapd, link);
+			link->resp_sta_profile_len =
+				ieee80211_ml_build_assoc_resp(
+					hapd, link->status,
+					link->resp_sta_profile,
+					sizeof(link->resp_sta_profile));
 		} else {
-			if (ieee80211_ml_process_link(iface->bss[0], sta, link,
-						      ies, ies_len, reassoc,
-						      offload))
-				return -1;
+			ieee80211_ml_process_link(iface->bss[0], sta, link,
+						  ies, ies_len, reassoc);
 		}
 	}
 #endif /* CONFIG_IEEE80211BE */
-
-	return 0;
 }
 
 
@@ -4667,7 +4589,7 @@
 	bool mld_link_sta = false;
 
 #ifdef CONFIG_IEEE80211BE
-	if (ap_sta_is_mld(hapd, sta)) {
+	if (hapd->conf->mld_ap && sta->mld_info.mld_sta) {
 		u8 mld_link_id = hapd->mld_link_id;
 
 		mld_link_sta = sta->mld_assoc_link_id != mld_link_id;
@@ -4778,7 +4700,7 @@
 static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
 			   const u8 *addr, u16 status_code, int reassoc,
 			   const u8 *ies, size_t ies_len, int rssi,
-			   int omit_rsnxe, bool allow_mld_addr_trans)
+			   int omit_rsnxe)
 {
 	int send_len;
 	u8 *buf;
@@ -4828,8 +4750,8 @@
 	 * Once a non-AP MLD is added to the driver, the addressing should use
 	 * MLD MAC address.
 	 */
-	if (ap_sta_is_mld(hapd, sta) && allow_mld_addr_trans)
-		sa = hapd->mld->mld_addr;
+	if (hapd->conf->mld_ap && sta && sta->mld_info.mld_sta)
+		sa = hapd->mld_addr;
 #endif /* CONFIG_IEEE80211BE */
 
 	os_memcpy(reply->da, addr, ETH_ALEN);
@@ -4971,7 +4893,7 @@
 #ifdef CONFIG_IEEE80211BE
 	if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) {
 		if (hapd->conf->mld_ap)
-			p = hostapd_eid_eht_ml_assoc(hapd, sta, p);
+			p = hostapd_eid_eht_basic_ml(hapd, p, sta, false);
 		p = hostapd_eid_eht_capab(hapd, p, IEEE80211_MODE_AP);
 		p = hostapd_eid_eht_operation(hapd, p);
 	}
@@ -5033,7 +4955,7 @@
 #endif /* CONFIG_WPS */
 
 	if (sta && (sta->flags & WLAN_STA_MULTI_AP))
-		p = hostapd_eid_multi_ap(hapd, p, buf + buflen - p);
+		p = hostapd_eid_multi_ap(hapd, p);
 
 #ifdef CONFIG_P2P
 	if (sta && sta->p2p_ie && hapd->p2p_group) {
@@ -5194,8 +5116,7 @@
 	reply_res = send_assoc_resp(hapd, sta, sta->addr, WLAN_STATUS_SUCCESS,
 				    sta->fils_pending_assoc_is_reassoc,
 				    sta->fils_pending_assoc_req,
-				    sta->fils_pending_assoc_req_len, 0, 0,
-				    true);
+				    sta->fils_pending_assoc_req_len, 0, 0);
 	os_free(sta->fils_pending_assoc_req);
 	sta->fils_pending_assoc_req = NULL;
 	sta->fils_pending_assoc_req_len = 0;
@@ -5230,48 +5151,6 @@
 #endif /* CONFIG_FILS */
 
 
-#ifdef CONFIG_IEEE80211BE
-static struct sta_info * handle_mlo_translate(struct hostapd_data *hapd,
-					      const struct ieee80211_mgmt *mgmt,
-					      size_t len, bool reassoc,
-					      struct hostapd_data **assoc_hapd)
-{
-	struct sta_info *sta;
-	struct ieee802_11_elems elems;
-	u8 mld_addr[ETH_ALEN];
-	const u8 *pos;
-
-	if (!hapd->iconf->ieee80211be || hapd->conf->disable_11be)
-		return NULL;
-
-	if (reassoc) {
-		len -= IEEE80211_HDRLEN + sizeof(mgmt->u.reassoc_req);
-		pos = mgmt->u.reassoc_req.variable;
-	} else {
-		len -= IEEE80211_HDRLEN + sizeof(mgmt->u.assoc_req);
-		pos = mgmt->u.assoc_req.variable;
-	}
-
-	if (ieee802_11_parse_elems(pos, len, &elems, 1) == ParseFailed)
-		return NULL;
-
-	if (hostapd_process_ml_assoc_req_addr(hapd, elems.basic_mle,
-					      elems.basic_mle_len,
-					      mld_addr))
-		return NULL;
-
-	sta = ap_get_sta(hapd, mld_addr);
-	if (!sta)
-		return NULL;
-
-	wpa_printf(MSG_DEBUG, "MLD: assoc: mld=" MACSTR ", link=" MACSTR,
-		   MAC2STR(mld_addr), MAC2STR(mgmt->sa));
-
-	return hostapd_ml_get_assoc_sta(hapd, sta, assoc_hapd);
-}
-#endif /* CONFIG_IEEE80211BE */
-
-
 static void handle_assoc(struct hostapd_data *hapd,
 			 const struct ieee80211_mgmt *mgmt, size_t len,
 			 int reassoc, int rssi)
@@ -5288,7 +5167,6 @@
 #endif /* CONFIG_FILS */
 	int omit_rsnxe = 0;
 	bool set_beacon = false;
-	bool mld_addrs_not_translated = false;
 
 	if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_req) :
 				      sizeof(mgmt->u.assoc_req))) {
@@ -5346,28 +5224,6 @@
 	}
 
 	sta = ap_get_sta(hapd, mgmt->sa);
-
-#ifdef CONFIG_IEEE80211BE
-	/*
-	 * It is possible that the association frame is from an associated
-	 * non-AP MLD station, that tries to re-associate using different link
-	 * addresses. In such a case, try to find the station based on the AP
-	 * MLD MAC address.
-	 */
-	if (!sta) {
-		struct hostapd_data *assoc_hapd;
-
-		sta = handle_mlo_translate(hapd, mgmt, len, reassoc,
-					   &assoc_hapd);
-		if (sta) {
-			wpa_printf(MSG_DEBUG,
-				   "MLD: Switching to assoc hapd/station");
-			hapd = assoc_hapd;
-			mld_addrs_not_translated = true;
-		}
-	}
-#endif /* CONFIG_IEEE80211BE */
-
 #ifdef CONFIG_IEEE80211R_AP
 	if (sta && sta->auth_alg == WLAN_AUTH_FT &&
 	    (sta->flags & WLAN_STA_AUTH) == 0) {
@@ -5644,9 +5500,8 @@
 	 *    issues with processing other non-Data Class 3 frames during this
 	 *    window.
 	 */
-	if (sta)
-		hostapd_process_assoc_ml_info(hapd, sta, pos, left, reassoc,
-					      resp, false);
+	if (resp == WLAN_STATUS_SUCCESS)
+		hostapd_process_assoc_ml_info(hapd, sta, pos, left, reassoc);
 
 	if (resp == WLAN_STATUS_SUCCESS && sta &&
 	    add_associated_sta(hapd, sta, reassoc))
@@ -5690,12 +5545,8 @@
 #endif /* CONFIG_FILS */
 
 	if (resp >= 0)
-		reply_res = send_assoc_resp(hapd,
-					    mld_addrs_not_translated ?
-					    NULL : sta,
-					    mgmt->sa, resp, reassoc,
-					    pos, left, rssi, omit_rsnxe,
-					    !mld_addrs_not_translated);
+		reply_res = send_assoc_resp(hapd, sta, mgmt->sa, resp, reassoc,
+					    pos, left, rssi, omit_rsnxe);
 	os_free(tmp);
 
 	/*
@@ -5786,6 +5637,44 @@
 }
 
 
+#ifdef CONFIG_IEEE80211BE
+static struct sta_info *
+hostapd_ml_get_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
+			 struct hostapd_data **assoc_hapd)
+{
+	struct hostapd_data *other_hapd = NULL;
+	struct sta_info *tmp_sta;
+
+	*assoc_hapd = hapd;
+
+	/* The station is the one on which the association was performed */
+	if (sta->mld_assoc_link_id == hapd->mld_link_id)
+		return sta;
+
+	other_hapd = hostapd_mld_get_link_bss(hapd, sta->mld_assoc_link_id);
+	if (!other_hapd) {
+		wpa_printf(MSG_DEBUG, "MLD: No link match for link_id=%u",
+			   sta->mld_assoc_link_id);
+		return sta;
+	}
+
+	/*
+	 * Iterate over the stations and find the one with the matching link ID
+	 * and association ID.
+	 */
+	for (tmp_sta = other_hapd->sta_list; tmp_sta; tmp_sta = tmp_sta->next) {
+		if (tmp_sta->mld_assoc_link_id == sta->mld_assoc_link_id &&
+		    tmp_sta->aid == sta->aid) {
+			*assoc_hapd = other_hapd;
+			return tmp_sta;
+		}
+	}
+
+	return sta;
+}
+#endif /* CONFIG_IEEE80211BE */
+
+
 static bool hostapd_ml_handle_disconnect(struct hostapd_data *hapd,
 					 struct sta_info *sta,
 					 const struct ieee80211_mgmt *mgmt,
@@ -5804,8 +5693,6 @@
 	 * the information about all the other links.
 	 */
 	assoc_sta = hostapd_ml_get_assoc_sta(hapd, sta, &assoc_hapd);
-	if (!assoc_sta)
-		return false;
 
 	for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
 		for (i = 0; i < assoc_hapd->iface->interfaces->count; i++) {
@@ -5817,7 +5704,8 @@
 			tmp_hapd =
 				assoc_hapd->iface->interfaces->iface[i]->bss[0];
 
-			if (!hostapd_is_ml_partner(assoc_hapd, tmp_hapd))
+			if (!tmp_hapd->conf->mld_ap ||
+			    assoc_hapd->conf->mld_id != tmp_hapd->conf->mld_id)
 				continue;
 
 			for (tmp_sta = tmp_hapd->sta_list; tmp_sta;
@@ -6076,25 +5964,6 @@
 				return 1;
 		}
 #endif /* CONFIG_DPP */
-#ifdef CONFIG_NAN_USD
-		if (mgmt->u.action.category == WLAN_ACTION_PUBLIC &&
-		    len >= IEEE80211_HDRLEN + 5 &&
-		    mgmt->u.action.u.vs_public_action.action ==
-		    WLAN_PA_VENDOR_SPECIFIC &&
-		    WPA_GET_BE24(mgmt->u.action.u.vs_public_action.oui) ==
-		    OUI_WFA &&
-		    mgmt->u.action.u.vs_public_action.variable[0] ==
-		    NAN_OUI_TYPE) {
-			const u8 *pos, *end;
-
-			pos = mgmt->u.action.u.vs_public_action.variable;
-			end = ((const u8 *) mgmt) + len;
-			pos++;
-			hostapd_nan_usd_rx_sdf(hapd, mgmt->sa, freq,
-					       pos, end - pos);
-			return 1;
-		}
-#endif /* CONFIG_NAN_USD */
 		if (hapd->public_action_cb) {
 			hapd->public_action_cb(hapd->public_action_cb_ctx,
 					       (u8 *) mgmt, len, freq);
@@ -6113,11 +5982,9 @@
 				return 1;
 		}
 		break;
-#ifndef CONFIG_NO_RRM
 	case WLAN_ACTION_RADIO_MEASUREMENT:
 		hostapd_handle_radio_measurement(hapd, (const u8 *) mgmt, len);
 		return 1;
-#endif /* CONFIG_NO_RRM */
 	}
 
 	hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
@@ -6202,10 +6069,6 @@
 	int ret = 0;
 	unsigned int freq;
 	int ssi_signal = fi ? fi->ssi_signal : 0;
-#ifdef CONFIG_NAN_USD
-	static const u8 nan_network_id[ETH_ALEN] =
-		{ 0x51, 0x6f, 0x9a, 0x01, 0x00, 0x00 };
-#endif /* CONFIG_NAN_USD */
 
 	if (len < 24)
 		return 0;
@@ -6221,7 +6084,7 @@
 
 	if (is_multicast_ether_addr(mgmt->sa) ||
 	    is_zero_ether_addr(mgmt->sa) ||
-	    ether_addr_equal(mgmt->sa, hapd->own_addr)) {
+	    os_memcmp(mgmt->sa, hapd->own_addr, ETH_ALEN) == 0) {
 		/* Do not process any frames with unexpected/invalid SA so that
 		 * we do not add any state for unexpected STA addresses or end
 		 * up sending out frames to unexpected destination. */
@@ -6247,9 +6110,9 @@
 #endif /* CONFIG_MESH */
 #ifdef CONFIG_IEEE80211BE
 	    !(hapd->conf->mld_ap &&
-	      ether_addr_equal(hapd->mld->mld_addr, mgmt->bssid)) &&
+	      os_memcmp(hapd->mld_addr, mgmt->bssid, ETH_ALEN) == 0) &&
 #endif /* CONFIG_IEEE80211BE */
-	    !ether_addr_equal(mgmt->bssid, hapd->own_addr)) {
+	    os_memcmp(mgmt->bssid, hapd->own_addr, ETH_ALEN) != 0) {
 		wpa_printf(MSG_INFO, "MGMT: BSSID=" MACSTR " not our address",
 			   MAC2STR(mgmt->bssid));
 		return 0;
@@ -6270,12 +6133,9 @@
 	     stype != WLAN_FC_STYPE_ACTION) &&
 #ifdef CONFIG_IEEE80211BE
 	    !(hapd->conf->mld_ap &&
-	      ether_addr_equal(hapd->mld->mld_addr, mgmt->bssid)) &&
+	      os_memcmp(hapd->mld_addr, mgmt->bssid, ETH_ALEN) == 0) &&
 #endif /* CONFIG_IEEE80211BE */
-#ifdef CONFIG_NAN_USD
-	    !ether_addr_equal(mgmt->da, nan_network_id) &&
-#endif /* CONFIG_NAN_USD */
-	    !ether_addr_equal(mgmt->da, hapd->own_addr)) {
+	    os_memcmp(mgmt->da, hapd->own_addr, ETH_ALEN) != 0) {
 		hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
 			       HOSTAPD_LEVEL_DEBUG,
 			       "MGMT: DA=" MACSTR " not our address",
@@ -6425,8 +6285,6 @@
 					   struct mld_link_info *link,
 					   bool ok)
 {
-	bool updated = false;
-
 	if (!ok) {
 		hostapd_logger(hapd, link->peer_addr, HOSTAPD_MODULE_IEEE80211,
 			       HOSTAPD_LEVEL_DEBUG,
@@ -6447,11 +6305,9 @@
 	sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE;
 
 	if (!hapd->conf->ieee802_1x && !hapd->conf->wpa)
-		updated = ap_sta_set_authorized_flag(hapd, sta, 1);
+		ap_sta_set_authorized(hapd, sta, 1);
 
 	hostapd_set_sta_flags(hapd, sta);
-	if (updated)
-		ap_sta_set_authorized_event(hapd, sta, 1);
 
 	/*
 	 * TODOs:
@@ -6484,7 +6340,8 @@
 			struct hostapd_data *tmp_hapd =
 				hapd->iface->interfaces->iface[i]->bss[0];
 
-			if (!hostapd_is_ml_partner(tmp_hapd, hapd))
+			if (tmp_hapd->conf->mld_ap ||
+			    hapd->conf->mld_id != tmp_hapd->conf->mld_id)
 				continue;
 
 			for (tmp_sta = tmp_hapd->sta_list; tmp_sta;
@@ -6522,7 +6379,7 @@
 	}
 
 #ifdef CONFIG_IEEE80211BE
-	if (ap_sta_is_mld(hapd, sta) &&
+	if (hapd->conf->mld_ap && sta->mld_info.mld_sta &&
 	    hapd->mld_link_id != sta->mld_assoc_link_id) {
 		/* See ieee80211_ml_link_sta_assoc_cb() for the MLD case */
 		wpa_printf(MSG_DEBUG,
@@ -6732,9 +6589,7 @@
 			     size_t len, int ok)
 {
 	struct sta_info *sta;
-#ifndef CONFIG_NO_RRM
 	const struct rrm_measurement_report_element *report;
-#endif /* CONFIG_NO_RRM */
 
 #ifdef CONFIG_DPP
 	if (len >= IEEE80211_HDRLEN + 6 &&
@@ -6788,7 +6643,6 @@
 	}
 #endif /* CONFIG_HS20 */
 
-#ifndef CONFIG_NO_RRM
 	if (len < 24 + 5 + sizeof(*report))
 		return;
 	report = (const struct rrm_measurement_report_element *)
@@ -6799,7 +6653,6 @@
 	    report->len >= 3 &&
 	    report->type == MEASURE_TYPE_BEACON)
 		hostapd_rrm_beacon_req_tx_status(hapd, mgmt, len, ok);
-#endif /* CONFIG_NO_RRM */
 }
 
 
@@ -7011,7 +6864,7 @@
 	wpa_printf(MSG_DEBUG, "Data/PS-poll frame from not associated STA "
 		   MACSTR, MAC2STR(src));
 	if (is_multicast_ether_addr(src) || is_zero_ether_addr(src) ||
-	    ether_addr_equal(src, hapd->own_addr)) {
+	    os_memcmp(src, hapd->own_addr, ETH_ALEN) == 0) {
 		/* Broadcast bit set in SA or unexpected SA?! Ignore the frame
 		 * silently. */
 		return;
@@ -7110,35 +6963,21 @@
 		tx_pwr_intrpn = REGULATORY_CLIENT_EIRP_PSD;
 
 		/* Default Transmit Power Envelope for Global Operating Class */
-		if (hapd->iconf->reg_def_cli_eirp_psd != -1)
-			tx_pwr = hapd->iconf->reg_def_cli_eirp_psd;
-		else
-			tx_pwr = REG_PSD_MAX_TXPOWER_FOR_DEFAULT_CLIENT * 2;
-
+		tx_pwr = REG_PSD_MAX_TXPOWER_FOR_DEFAULT_CLIENT * 2;
 		eid = hostapd_add_tpe_info(eid, tx_pwr_count, tx_pwr_intrpn,
 					   REG_DEFAULT_CLIENT, tx_pwr);
 
 		/* Indoor Access Point must include an additional TPE for
 		 * subordinate devices */
-		if (he_reg_is_indoor(iconf->he_6ghz_reg_pwr_type)) {
+		if (iconf->he_6ghz_reg_pwr_type == HE_6GHZ_INDOOR_AP) {
 			/* TODO: Extract PSD limits from channel data */
-			if (hapd->iconf->reg_sub_cli_eirp_psd != -1)
-				tx_pwr = hapd->iconf->reg_sub_cli_eirp_psd;
-			else
-				tx_pwr = REG_PSD_MAX_TXPOWER_FOR_SUBORDINATE_CLIENT * 2;
+			tx_pwr = REG_PSD_MAX_TXPOWER_FOR_SUBORDINATE_CLIENT * 2;
 			eid = hostapd_add_tpe_info(eid, tx_pwr_count,
 						   tx_pwr_intrpn,
 						   REG_SUBORDINATE_CLIENT,
 						   tx_pwr);
 		}
 
-		if (iconf->reg_def_cli_eirp != -1 &&
-		    he_reg_is_sp(iconf->he_6ghz_reg_pwr_type))
-			eid = hostapd_add_tpe_info(
-				eid, tx_pwr_count, REGULATORY_CLIENT_EIRP,
-				REG_DEFAULT_CLIENT,
-				hapd->iconf->reg_def_cli_eirp);
-
 		return eid;
 	}
 #endif /* CONFIG_IEEE80211AX */
@@ -7447,12 +7286,12 @@
 		bool ap_mld = false;
 
 #ifdef CONFIG_IEEE80211BE
-		if (hostapd_is_ml_partner(hapd, iface->bss[0]))
+		if (hapd->conf->mld_ap && iface->bss[0]->conf->mld_ap &&
+		    hapd->conf->mld_id == iface->bss[0]->conf->mld_id)
 			ap_mld = true;
 #endif /* CONFIG_IEEE80211BE */
 
 		if (iface == hapd->iface ||
-		    iface->state != HAPD_IFACE_ENABLED ||
 		    !(is_6ghz_op_class(iface->conf->op_class) || ap_mld))
 			continue;
 
@@ -7553,7 +7392,7 @@
 		/* BSS parameters */
 		*eid++ = nr->bss_parameters;
 		/* 20 MHz PSD */
-		*eid++ = RNR_20_MHZ_PSD_MAX_TXPOWER;
+		*eid++ = RNR_20_MHZ_PSD_MAX_TXPOWER - 1;
 		len += RNR_TBTT_INFO_LEN;
 		*size_offset = (eid - size_offset) - 1;
 	}
@@ -7563,97 +7402,17 @@
 }
 
 
-static bool hostapd_eid_rnr_bss(struct hostapd_data *hapd,
-				struct hostapd_data *reporting_hapd,
-				struct mbssid_ie_profiles *skip_profiles,
-				size_t i, u8 *tbtt_count, size_t *len,
-				u8 **pos)
-{
-	struct hostapd_iface *iface = hapd->iface;
-	struct hostapd_data *bss = iface->bss[i];
-	u8 bss_param = 0;
-	bool ap_mld = false;
-	u8 *eid = *pos;
-
-#ifdef CONFIG_IEEE80211BE
-	ap_mld = !!hapd->conf->mld_ap;
-#endif /* CONFIG_IEEE80211BE */
-
-	if (!bss || !bss->conf || !bss->started ||
-	    bss == reporting_hapd || bss->conf->ignore_broadcast_ssid)
-		return false;
-
-	if (skip_profiles
-	    && i >= skip_profiles->start && i < skip_profiles->end)
-		return false;
-
-	if (*len + RNR_TBTT_INFO_LEN > 255 ||
-	    *tbtt_count >= RNR_TBTT_INFO_COUNT_MAX)
-		return true;
-
-	*eid++ = RNR_NEIGHBOR_AP_OFFSET_UNKNOWN;
-	os_memcpy(eid, bss->own_addr, ETH_ALEN);
-	eid += ETH_ALEN;
-	os_memcpy(eid, &bss->conf->ssid.short_ssid, 4);
-	eid += 4;
-	if (bss->conf->ssid.short_ssid == reporting_hapd->conf->ssid.short_ssid)
-		bss_param |= RNR_BSS_PARAM_SAME_SSID;
-
-	if (iface->conf->mbssid != MBSSID_DISABLED && iface->num_bss > 1) {
-		bss_param |= RNR_BSS_PARAM_MULTIPLE_BSSID;
-		if (bss == hostapd_mbssid_get_tx_bss(hapd))
-			bss_param |= RNR_BSS_PARAM_TRANSMITTED_BSSID;
-	}
-
-	if (is_6ghz_op_class(hapd->iconf->op_class) &&
-	    bss->conf->unsol_bcast_probe_resp_interval)
-		bss_param |= RNR_BSS_PARAM_UNSOLIC_PROBE_RESP_ACTIVE;
-
-	bss_param |= RNR_BSS_PARAM_CO_LOCATED;
-
-	*eid++ = bss_param;
-	*eid++ = RNR_20_MHZ_PSD_MAX_TXPOWER;
-
-	if (!ap_mld) {
-		*len += RNR_TBTT_INFO_LEN;
-	} else {
-#ifdef CONFIG_IEEE80211BE
-		u8 param_ch = hapd->eht_mld_bss_param_change;
-
-		if (hostapd_is_ml_partner(bss, reporting_hapd))
-			*eid++ = 0;
-		else
-			*eid++ = hostapd_get_mld_id(hapd);
-
-		*eid++ = hapd->mld_link_id | ((param_ch & 0xF) << 4);
-		*eid = (param_ch >> 4) & 0xF;
-#ifdef CONFIG_TESTING_OPTIONS
-		if (hapd->conf->mld_indicate_disabled)
-			*eid |= RNR_TBTT_INFO_MLD_PARAM2_LINK_DISABLED;
-#endif /* CONFIG_TESTING_OPTIONS */
-		eid++;
-
-		*len += RNR_TBTT_INFO_MLD_LEN;
-#endif /* CONFIG_IEEE80211BE */
-	}
-
-	(*tbtt_count)++;
-	*pos = eid;
-
-	return false;
-}
-
-
 static u8 * hostapd_eid_rnr_iface(struct hostapd_data *hapd,
 				  struct hostapd_data *reporting_hapd,
 				  u8 *eid, size_t *current_len,
 				  struct mbssid_ie_profiles *skip_profiles)
 {
+	struct hostapd_data *bss;
 	struct hostapd_iface *iface = hapd->iface;
 	size_t i, start = 0;
 	size_t len = *current_len;
 	u8 *tbtt_count_pos, *eid_start = eid, *size_offset = (eid - len) + 1;
-	u8 tbtt_count = 0, op_class, channel;
+	u8 tbtt_count = 0, op_class, channel, bss_param;
 	bool ap_mld = false;
 
 #ifdef CONFIG_IEEE80211BE
@@ -7688,10 +7447,62 @@
 		len += RNR_TBTT_HEADER_LEN;
 
 		for (i = start; i < iface->num_bss; i++) {
-			if (hostapd_eid_rnr_bss(hapd, reporting_hapd,
-						skip_profiles, i,
-						&tbtt_count, &len, &eid))
+			bss_param = 0;
+			bss = iface->bss[i];
+			if (!bss || !bss->conf || !bss->started)
+				continue;
+
+			if (bss == reporting_hapd ||
+			    bss->conf->ignore_broadcast_ssid)
+				continue;
+
+			if (skip_profiles &&
+			    i >= skip_profiles->start && i < skip_profiles->end)
+				continue;
+
+			if (len + RNR_TBTT_INFO_LEN > 255 ||
+			    tbtt_count >= RNR_TBTT_INFO_COUNT_MAX)
 				break;
+
+			*eid++ = RNR_NEIGHBOR_AP_OFFSET_UNKNOWN;
+			os_memcpy(eid, bss->own_addr, ETH_ALEN);
+			eid += ETH_ALEN;
+			os_memcpy(eid, &bss->conf->ssid.short_ssid, 4);
+			eid += 4;
+			if (bss->conf->ssid.short_ssid ==
+			    reporting_hapd->conf->ssid.short_ssid)
+				bss_param |= RNR_BSS_PARAM_SAME_SSID;
+
+			if (iface->conf->mbssid != MBSSID_DISABLED &&
+			    iface->num_bss > 1) {
+				bss_param |= RNR_BSS_PARAM_MULTIPLE_BSSID;
+				if (bss == hostapd_mbssid_get_tx_bss(hapd))
+					bss_param |=
+						RNR_BSS_PARAM_TRANSMITTED_BSSID;
+			}
+
+			if (is_6ghz_op_class(hapd->iconf->op_class) &&
+			    bss->conf->unsol_bcast_probe_resp_interval)
+				bss_param |=
+					RNR_BSS_PARAM_UNSOLIC_PROBE_RESP_ACTIVE;
+
+			bss_param |= RNR_BSS_PARAM_CO_LOCATED;
+
+			*eid++ = bss_param;
+			*eid++ = RNR_20_MHZ_PSD_MAX_TXPOWER - 1;
+
+			if (!ap_mld) {
+				len += RNR_TBTT_INFO_LEN;
+			} else {
+#ifdef CONFIG_IEEE80211BE
+				*eid++ = hapd->conf->mld_id;
+				*eid++ = hapd->mld_link_id | (1 << 4);
+				*eid++ = 0;
+				len += RNR_TBTT_INFO_MLD_LEN;
+#endif /* CONFIG_IEEE80211BE */
+			}
+
+			tbtt_count += 1;
 		}
 
 		start = i;
@@ -7721,12 +7532,12 @@
 		bool ap_mld = false;
 
 #ifdef CONFIG_IEEE80211BE
-		if (hostapd_is_ml_partner(hapd, iface->bss[0]))
+		if (hapd->conf->mld_ap && iface->bss[0]->conf->mld_ap &&
+		    hapd->conf->mld_id == iface->bss[0]->conf->mld_id)
 			ap_mld = true;
 #endif /* CONFIG_IEEE80211BE */
 
 		if (iface == hapd->iface ||
-		    iface->state != HAPD_IFACE_ENABLED ||
 		    !(is_6ghz_op_class(iface->conf->op_class) || ap_mld))
 			continue;
 
@@ -7768,7 +7579,7 @@
 
 	case WLAN_FC_STYPE_ACTION:
 		if (hapd->iface->num_bss > 1 && mode == STANDALONE_6GHZ)
-			eid = hostapd_eid_rnr_iface(hapd, hapd, eid,
+			eid = hostapd_eid_rnr_iface(hapd, hapd,	eid,
 						    &current_len, NULL);
 		break;
 
@@ -7793,46 +7604,13 @@
 }
 
 
-static size_t hostapd_mbssid_ext_capa(struct hostapd_data *bss,
-				      struct hostapd_data *tx_bss, u8 *buf)
-{
-	u8 ext_capa_tx[20], *ext_capa_tx_end, ext_capa[20], *ext_capa_end;
-	size_t ext_capa_len, ext_capa_tx_len;
-
-	ext_capa_tx_end = hostapd_eid_ext_capab(tx_bss, ext_capa_tx,
-						true);
-	ext_capa_tx_len = ext_capa_tx_end - ext_capa_tx;
-	ext_capa_end = hostapd_eid_ext_capab(bss, ext_capa, true);
-	ext_capa_len = ext_capa_end - ext_capa;
-	if (ext_capa_tx_len != ext_capa_len ||
-	    os_memcmp(ext_capa_tx, ext_capa, ext_capa_len) != 0) {
-		os_memcpy(buf, ext_capa, ext_capa_len);
-		return ext_capa_len;
-	}
-
-	return 0;
-}
-
-
 static size_t hostapd_eid_mbssid_elem_len(struct hostapd_data *hapd,
 					  u32 frame_type, size_t *bss_index,
 					  const u8 *known_bss,
 					  size_t known_bss_len)
 {
 	struct hostapd_data *tx_bss = hostapd_mbssid_get_tx_bss(hapd);
-	size_t len, i;
-	u8 ext_capa[20];
-
-	/* Element ID: 1 octet
-	 * Length: 1 octet
-	 * MaxBSSID Indicator: 1 octet
-	 * Optional Subelements: vatiable
-	 *
-	 * Total fixed length: 3 octets
-	 *
-	 * 1 octet in len for the MaxBSSID Indicator field.
-	 */
-	len = 1;
+	size_t len = 3, i;
 
 	for (i = *bss_index; i < hapd->iface->num_bss; i++) {
 		struct hostapd_data *bss = hapd->iface->bss[i];
@@ -7867,10 +7645,6 @@
 			if (rsnx)
 				nontx_profile_len += 2 + rsnx[1];
 		}
-
-		nontx_profile_len += hostapd_mbssid_ext_capa(bss, tx_bss,
-							     ext_capa);
-
 		if (!rsn && hostapd_wpa_ie(tx_bss, WLAN_EID_RSN))
 			ie_count++;
 		if (!rsnx && hostapd_wpa_ie(tx_bss, WLAN_EID_RSNX))
@@ -7889,9 +7663,7 @@
 	}
 
 	*bss_index = i;
-
-	/* Add 2 octets to get the full size of the element */
-	return len + 2;
+	return len;
 }
 
 
@@ -8020,17 +7792,13 @@
 				eid += 2 + rsnx[1];
 			}
 		}
-
-		eid += hostapd_mbssid_ext_capa(bss, tx_bss, eid);
-
-		/* List of Element ID values in increasing order */
 		if (!rsn && hostapd_wpa_ie(tx_bss, WLAN_EID_RSN))
 			non_inherit_ie[ie_count++] = WLAN_EID_RSN;
+		if (!rsnx && hostapd_wpa_ie(tx_bss, WLAN_EID_RSNX))
+			non_inherit_ie[ie_count++] = WLAN_EID_RSNX;
 		if (hapd->conf->xrates_supported &&
 		    !bss->conf->xrates_supported)
 			non_inherit_ie[ie_count++] = WLAN_EID_EXT_SUPP_RATES;
-		if (!rsnx && hostapd_wpa_ie(tx_bss, WLAN_EID_RSNX))
-			non_inherit_ie[ie_count++] = WLAN_EID_RSNX;
 		if (ie_count) {
 			*eid++ = WLAN_EID_EXTENSION;
 			*eid++ = 2 + ie_count + 1;
@@ -8130,4 +7898,73 @@
 	return eid;
 }
 
+
+static void punct_update_legacy_bw_80(u8 bitmap, u8 pri_chan, u8 *seg0)
+{
+	u8 first_chan = *seg0 - 6, sec_chan;
+
+	switch (bitmap) {
+	case 0x6:
+		*seg0 = 0;
+		return;
+	case 0x8:
+	case 0x4:
+	case 0x2:
+	case 0x1:
+	case 0xC:
+	case 0x3:
+		if (pri_chan < *seg0)
+			*seg0 -= 4;
+		else
+			*seg0 += 4;
+		break;
+	}
+
+	if (pri_chan < *seg0)
+		sec_chan = pri_chan + 4;
+	else
+		sec_chan = pri_chan - 4;
+
+	if (bitmap & BIT((sec_chan - first_chan) / 4))
+		*seg0 = 0;
+}
+
+
+static void punct_update_legacy_bw_160(u8 bitmap, u8 pri,
+				       enum oper_chan_width *width, u8 *seg0)
+{
+	if (pri < *seg0) {
+		*seg0 -= 8;
+		if (bitmap & 0x0F) {
+			*width = 0;
+			punct_update_legacy_bw_80(bitmap & 0xF, pri, seg0);
+		}
+	} else {
+		*seg0 += 8;
+		if (bitmap & 0xF0) {
+			*width = 0;
+			punct_update_legacy_bw_80((bitmap & 0xF0) >> 4, pri,
+						  seg0);
+		}
+	}
+}
+
+
+void punct_update_legacy_bw(u16 bitmap, u8 pri, enum oper_chan_width *width,
+			    u8 *seg0, u8 *seg1)
+{
+	if (*width == CONF_OPER_CHWIDTH_80MHZ && (bitmap & 0xF)) {
+		*width = CONF_OPER_CHWIDTH_USE_HT;
+		punct_update_legacy_bw_80(bitmap & 0xF, pri, seg0);
+	}
+
+	if (*width == CONF_OPER_CHWIDTH_160MHZ && (bitmap & 0xFF)) {
+		*width = CONF_OPER_CHWIDTH_80MHZ;
+		*seg1 = 0;
+		punct_update_legacy_bw_160(bitmap & 0xFF, pri, width, seg0);
+	}
+
+	/* TODO: 320 MHz */
+}
+
 #endif /* CONFIG_NATIVE_WINDOWS */
diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
index a35486d..4b58fee 100644
--- a/src/ap/ieee802_11.h
+++ b/src/ap/ieee802_11.h
@@ -23,7 +23,6 @@
 struct sae_pk;
 struct sae_pt;
 struct sae_password_entry;
-struct mld_info;
 
 int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
 		    struct hostapd_frame_info *fi);
@@ -89,14 +88,8 @@
 			   const struct ieee80211_eht_capabilities *src,
 			   struct ieee80211_eht_capabilities *dest,
 			   size_t len);
-u8 * hostapd_eid_eht_ml_beacon(struct hostapd_data *hapd,
-			       struct mld_info *mld_info,
-			       u8 *eid, bool include_mld_id);
-u8 * hostapd_eid_eht_ml_assoc(struct hostapd_data *hapd, struct sta_info *info,
-			      u8 *eid);
-size_t hostapd_eid_eht_ml_beacon_len(struct hostapd_data *hapd,
-				     struct mld_info *info,
-				     bool include_mld_id);
+u8 * hostapd_eid_eht_basic_ml(struct hostapd_data *hapd, u8 *eid,
+			      struct sta_info *info, bool include_mld_id);
 struct wpabuf * hostapd_ml_auth_resp(struct hostapd_data *hapd);
 const u8 * hostapd_process_ml_auth(struct hostapd_data *hapd,
 				   const struct ieee80211_mgmt *mgmt,
@@ -104,9 +97,6 @@
 u16 hostapd_process_ml_assoc_req(struct hostapd_data *hapd,
 				 struct ieee802_11_elems *elems,
 				 struct sta_info *sta);
-int hostapd_process_ml_assoc_req_addr(struct hostapd_data *hapd,
-				      const u8 *basic_mle, size_t basic_mle_len,
-				      u8 *mld_addr);
 int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta);
 u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta,
 		      const u8 *ht_capab);
@@ -248,18 +238,12 @@
 			u8 **elem_offset,
 			const u8 *known_bss, size_t known_bss_len, u8 *rnr_eid,
 			u8 *rnr_count, u8 **rnr_offset, size_t rnr_len);
+void punct_update_legacy_bw(u16 bitmap, u8 pri_chan,
+			    enum oper_chan_width *width, u8 *seg0, u8 *seg1);
 bool hostapd_is_mld_ap(struct hostapd_data *hapd);
 const char * sae_get_password(struct hostapd_data *hapd,
 			      struct sta_info *sta, const char *rx_id,
 			      struct sae_password_entry **pw_entry,
 			      struct sae_pt **s_pt, const struct sae_pk **s_pk);
-struct sta_info * hostapd_ml_get_assoc_sta(struct hostapd_data *hapd,
-					   struct sta_info *sta,
-					   struct hostapd_data **assoc_hapd);
-int hostapd_process_assoc_ml_info(struct hostapd_data *hapd,
-				  struct sta_info *sta,
-				  const u8 *ies, size_t ies_len,
-				  bool reassoc, int tx_link_status,
-				  bool offload);
 
 #endif /* IEEE802_11_H */
diff --git a/src/ap/ieee802_11_auth.c b/src/ap/ieee802_11_auth.c
index e723ae7..4277d82 100644
--- a/src/ap/ieee802_11_auth.c
+++ b/src/ap/ieee802_11_auth.c
@@ -84,7 +84,7 @@
 	os_get_reltime(&now);
 
 	for (entry = hapd->acl_cache; entry; entry = entry->next) {
-		if (!ether_addr_equal(entry->addr, addr))
+		if (os_memcmp(entry->addr, addr, ETH_ALEN) != 0)
 			continue;
 
 		if (os_reltime_expired(&now, &entry->timestamp,
@@ -281,7 +281,7 @@
 
 		query = hapd->acl_queries;
 		while (query) {
-			if (ether_addr_equal(query->addr, addr)) {
+			if (os_memcmp(query->addr, addr, ETH_ALEN) == 0) {
 				/* pending query in RADIUS retransmit queue;
 				 * do not generate a new one */
 				return HOSTAPD_ACL_PENDING;
diff --git a/src/ap/ieee802_11_eht.c b/src/ap/ieee802_11_eht.c
index 638546e..c1ccda4 100644
--- a/src/ap/ieee802_11_eht.c
+++ b/src/ap/ieee802_11_eht.c
@@ -44,13 +44,12 @@
 
 
 static u8 ieee80211_eht_mcs_set_size(enum hostapd_hw_mode mode, u8 opclass,
-				     int he_oper_chwidth, const u8 *he_phy_cap,
+				     u8 he_oper_chwidth, const u8 *he_phy_cap,
 				     const u8 *eht_phy_cap)
 {
 	u8 sz = EHT_PHYCAP_MCS_NSS_LEN_20MHZ_PLUS;
 	bool band24, band5, band6;
 	u8 he_phy_cap_chwidth = ~HE_PHYCAP_CHANNEL_WIDTH_MASK;
-	u8 cap_chwidth;
 
 	switch (he_oper_chwidth) {
 	case CONF_OPER_CHWIDTH_80P80MHZ:
@@ -67,11 +66,7 @@
 		break;
 	}
 
-	cap_chwidth = he_phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX];
-	if (he_oper_chwidth != -1)
-		he_phy_cap_chwidth &= cap_chwidth;
-	else
-		he_phy_cap_chwidth = cap_chwidth;
+	he_phy_cap_chwidth &= he_phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX];
 
 	band24 = mode == HOSTAPD_MODE_IEEE80211B ||
 		mode == HOSTAPD_MODE_IEEE80211G ||
@@ -204,25 +199,12 @@
 	struct ieee80211_eht_operation *oper;
 	u8 *pos = eid, seg0 = 0, seg1 = 0;
 	enum oper_chan_width chwidth;
-	size_t elen = 1 + 4;
-	bool eht_oper_info_present;
-	u16 punct_bitmap = hostapd_get_punct_bitmap(hapd);
+	size_t elen = 1 + 4 + 3;
 
 	if (!hapd->iface->current_mode)
 		return eid;
 
-	if (is_6ghz_op_class(conf->op_class))
-		chwidth = op_class_to_ch_width(conf->op_class);
-	else
-		chwidth = conf->eht_oper_chwidth;
-
-	eht_oper_info_present = chwidth == CONF_OPER_CHWIDTH_320MHZ ||
-		punct_bitmap;
-
-	if (eht_oper_info_present)
-		elen += 3;
-
-	if (punct_bitmap)
+	if (hapd->iconf->punct_bitmap)
 		elen += EHT_OPER_DISABLED_SUBCHAN_BITMAP_SIZE;
 
 	*pos++ = WLAN_EID_EXTENSION;
@@ -230,10 +212,7 @@
 	*pos++ = WLAN_EID_EXT_EHT_OPERATION;
 
 	oper = (struct ieee80211_eht_operation *) pos;
-	oper->oper_params = 0;
-
-	if (hapd->iconf->eht_default_pe_duration)
-		oper->oper_params |= EHT_OPER_DEFAULT_PE_DURATION;
+	oper->oper_params = EHT_OPER_INFO_PRESENT;
 
 	/* TODO: Fill in appropriate EHT-MCS max Nss information */
 	oper->basic_eht_mcs_nss_set[0] = 0x11;
@@ -241,10 +220,11 @@
 	oper->basic_eht_mcs_nss_set[2] = 0x00;
 	oper->basic_eht_mcs_nss_set[3] = 0x00;
 
-	if (!eht_oper_info_present)
-		return pos + elen;
+	if (is_6ghz_op_class(conf->op_class))
+		chwidth = op_class_to_ch_width(conf->op_class);
+	else
+		chwidth = conf->eht_oper_chwidth;
 
-	oper->oper_params |= EHT_OPER_INFO_PRESENT;
 	seg0 = hostapd_get_oper_centr_freq_seg0_idx(conf);
 
 	switch (chwidth) {
@@ -278,10 +258,10 @@
 	oper->oper_info.ccfs0 = seg0 ? seg0 : hapd->iconf->channel;
 	oper->oper_info.ccfs1 = seg1;
 
-	if (punct_bitmap) {
+	if (hapd->iconf->punct_bitmap) {
 		oper->oper_params |= EHT_OPER_DISABLED_SUBCHAN_BITMAP_PRESENT;
 		oper->oper_info.disabled_chan_bitmap =
-			host_to_le16(punct_bitmap);
+			host_to_le16(hapd->iconf->punct_bitmap);
 	}
 
 	return pos + elen;
@@ -358,8 +338,9 @@
 
 
 static bool ieee80211_invalid_eht_cap_size(enum hostapd_hw_mode mode,
-					   u8 opclass, const u8 *he_cap,
-					   const u8 *eht_cap, size_t len)
+					   u8 opclass, u8 he_oper_chwidth,
+					   const u8 *he_cap, const u8 *eht_cap,
+					   size_t len)
 {
 	const struct ieee80211_he_capabilities *he_capab;
 	struct ieee80211_eht_capabilities *cap;
@@ -374,8 +355,8 @@
 	if (len < cap_len)
 		return true;
 
-	cap_len += ieee80211_eht_mcs_set_size(mode, opclass, -1, he_phy_cap,
-					      cap->phy_cap);
+	cap_len += ieee80211_eht_mcs_set_size(mode, opclass, he_oper_chwidth,
+					      he_phy_cap, cap->phy_cap);
 	if (len < cap_len)
 		return true;
 
@@ -399,6 +380,7 @@
 	    !he_capab || he_capab_len < IEEE80211_HE_CAPAB_MIN_LEN ||
 	    !eht_capab ||
 	    ieee80211_invalid_eht_cap_size(mode, hapd->iconf->op_class,
+					   hapd->iconf->he_oper_chwidth,
 					   he_capab, eht_capab,
 					   eht_capab_len) ||
 	    !check_valid_eht_mcs(hapd, eht_capab, opmode)) {
@@ -439,9 +421,8 @@
 }
 
 
-static u8 * hostapd_eid_eht_basic_ml_common(struct hostapd_data *hapd,
-					    u8 *eid, struct mld_info *mld_info,
-					    bool include_mld_id)
+u8 * hostapd_eid_eht_basic_ml(struct hostapd_data *hapd, u8 *eid,
+			      struct sta_info *info, bool include_mld_id)
 {
 	struct wpabuf *buf;
 	u16 control;
@@ -450,8 +431,6 @@
 	size_t len, slice_len;
 	u8 link_id;
 	u8 common_info_len;
-	u16 mld_cap;
-	u8 max_simul_links, active_links;
 
 	/*
 	 * As the Multi-Link element can exceed the size of 255 bytes need to
@@ -475,8 +454,7 @@
 	 * BSS Parameters Change Count (1) + EML Capabilities (2) +
 	 * MLD Capabilities and Operations (2)
 	 */
-#define EHT_ML_COMMON_INFO_LEN 13
-	common_info_len = EHT_ML_COMMON_INFO_LEN;
+	common_info_len = 13;
 
 	if (include_mld_id) {
 		/* AP MLD ID */
@@ -489,7 +467,7 @@
 	wpabuf_put_u8(buf, common_info_len);
 
 	/* Own MLD MAC Address */
-	wpabuf_put_data(buf, hapd->mld->mld_addr, ETH_ALEN);
+	wpabuf_put_data(buf, hapd->mld_addr, ETH_ALEN);
 
 	/* Own Link ID */
 	wpabuf_put_u8(buf, hapd->mld_link_id);
@@ -501,39 +479,22 @@
 		   hapd->iface->mld_eml_capa);
 	wpabuf_put_le16(buf, hapd->iface->mld_eml_capa);
 
-	mld_cap = hapd->iface->mld_mld_capa;
-	max_simul_links = mld_cap & EHT_ML_MLD_CAPA_MAX_NUM_SIM_LINKS_MASK;
-	active_links = hapd->mld->num_links - 1;
-
-	if (active_links > max_simul_links) {
-		wpa_printf(MSG_ERROR,
-			   "MLD: Error in max simultaneous links, advertised: 0x%x current: 0x%x",
-			   max_simul_links, active_links);
-		active_links = max_simul_links;
-	}
-
-	mld_cap &= ~EHT_ML_MLD_CAPA_MAX_NUM_SIM_LINKS_MASK;
-	mld_cap |= active_links & EHT_ML_MLD_CAPA_MAX_NUM_SIM_LINKS_MASK;
-
-	/* TODO: Advertise T2LM based on driver support as well */
-	mld_cap &= ~EHT_ML_MLD_CAPA_TID_TO_LINK_MAP_NEG_SUPP_MSK;
-
 	wpa_printf(MSG_DEBUG, "MLD: MLD Capabilities and Operations=0x%x",
-		   mld_cap);
-	wpabuf_put_le16(buf, mld_cap);
+		   hapd->iface->mld_mld_capa);
+	wpabuf_put_le16(buf, hapd->iface->mld_mld_capa);
 
 	if (include_mld_id) {
 		wpa_printf(MSG_DEBUG, "MLD: AP MLD ID=0x%x",
-			   hostapd_get_mld_id(hapd));
-		wpabuf_put_u8(buf, hostapd_get_mld_id(hapd));
+			   hapd->conf->mld_id);
+		wpabuf_put_u8(buf, hapd->conf->mld_id);
 	}
 
-	if (!mld_info)
+	if (!info)
 		goto out;
 
 	/* Add link info for the other links */
 	for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
-		struct mld_link_info *link = &mld_info->links[link_id];
+		struct mld_link_info *link = &info->mld_info.links[link_id];
 		struct hostapd_data *link_bss;
 
 		/*
@@ -541,9 +502,8 @@
 		 * beacon interval (2) + TSF offset (8) + DTIM info (2) + BSS
 		 * parameters change counter (1) + station profile length.
 		 */
-#define EHT_ML_STA_INFO_LEN 22
-		size_t total_len = EHT_ML_STA_INFO_LEN +
-			link->resp_sta_profile_len;
+		const size_t fixed_len = 22;
+		size_t total_len = fixed_len + link->resp_sta_profile_len;
 
 		/* Skip the local one */
 		if (link_id == hapd->mld_link_id || !link->valid)
@@ -577,7 +537,7 @@
 		/* STA Info */
 
 		/* STA Info Length */
-		wpabuf_put_u8(buf, EHT_ML_STA_INFO_LEN - 2);
+		wpabuf_put_u8(buf, fixed_len - 2);
 		wpabuf_put_data(buf, link->local_addr, ETH_ALEN);
 		wpabuf_put_le16(buf, link_bss->iconf->beacon_int);
 
@@ -589,14 +549,12 @@
 		wpabuf_put_le64(buf, 0);
 
 		/* DTIM Info */
-		wpabuf_put_u8(buf, 0); /* DTIM Count */
-		wpabuf_put_u8(buf, link_bss->conf->dtim_period);
+		wpabuf_put_le16(buf, link_bss->conf->dtim_period);
 
 		/* BSS Parameters Change Count */
-		wpabuf_put_u8(buf, hapd->eht_mld_bss_param_change);
-
-		if (!link->resp_sta_profile)
-			continue;
+		/* TODO: Currently hard code the BSS Parameters Change Count to
+		 * 0x1 */
+		wpabuf_put_u8(buf, 0x1);
 
 		/* Fragment the sub element if needed */
 		if (total_len <= 255) {
@@ -606,7 +564,7 @@
 			ptr = link->resp_sta_profile;
 			len = link->resp_sta_profile_len;
 
-			slice_len = 255 - EHT_ML_STA_INFO_LEN;
+			slice_len = 255 - fixed_len;
 
 			wpabuf_put_data(buf, ptr, slice_len);
 			len -= slice_len;
@@ -667,151 +625,6 @@
 }
 
 
-static u8 * hostapd_eid_eht_reconf_ml(struct hostapd_data *hapd, u8 *eid)
-{
-#ifdef CONFIG_TESTING_OPTIONS
-	struct hostapd_data *other_hapd;
-	u16 control;
-	u8 *pos = eid;
-	unsigned int i;
-
-	wpa_printf(MSG_DEBUG, "MLD: Reconfiguration ML");
-
-	/* First check if the element needs to be added */
-	for (i = 0; i < hapd->iface->interfaces->count; i++) {
-		other_hapd = hapd->iface->interfaces->iface[i]->bss[0];
-
-		wpa_printf(MSG_DEBUG, "MLD: Reconfiguration ML: %u",
-			   other_hapd->eht_mld_link_removal_count);
-
-		if (other_hapd->eht_mld_link_removal_count)
-			break;
-	}
-
-	/* No link is going to be removed */
-	if (i == hapd->iface->interfaces->count)
-		return eid;
-
-	wpa_printf(MSG_DEBUG, "MLD: Reconfiguration ML: Adding element");
-
-	/* The length will be set at the end */
-	*pos++ = WLAN_EID_EXTENSION;
-	*pos++ = 0;
-	*pos++ = WLAN_EID_EXT_MULTI_LINK;
-
-	/* Set the Multi-Link Control field */
-	control = MULTI_LINK_CONTROL_TYPE_RECONF;
-	WPA_PUT_LE16(pos, control);
-	pos += 2;
-
-	/* Common Info doesn't include any information */
-	*pos++ = 1;
-
-	/* Add the per station profiles */
-	for (i = 0; i < hapd->iface->interfaces->count; i++) {
-		other_hapd = hapd->iface->interfaces->iface[i]->bss[0];
-		if (!other_hapd->eht_mld_link_removal_count)
-			continue;
-
-		/* Subelement ID is 0 */
-		*pos++ = 0;
-		*pos++ = 5;
-
-		control = other_hapd->mld_link_id |
-			EHT_PER_STA_RECONF_CTRL_AP_REMOVAL_TIMER;
-
-		WPA_PUT_LE16(pos, control);
-		pos += 2;
-
-		/* STA profile length */
-		*pos++ = 3;
-
-		WPA_PUT_LE16(pos, other_hapd->eht_mld_link_removal_count);
-		pos += 2;
-	}
-
-	eid[1] = pos - eid - 2;
-
-	wpa_hexdump(MSG_DEBUG, "MLD: Reconfiguration ML", eid, eid[1] + 2);
-	return pos;
-#else /* CONFIG_TESTING_OPTIONS */
-	return eid;
-#endif /* CONFIG_TESTING_OPTIONS */
-}
-
-
-static size_t hostapd_eid_eht_ml_len(struct mld_info *info,
-				     bool include_mld_id)
-{
-	size_t len = 0;
-	size_t eht_ml_len = 2 + EHT_ML_COMMON_INFO_LEN;
-	u8 link_id;
-
-	if (include_mld_id)
-		eht_ml_len++;
-
-	for (link_id = 0; info && link_id < ARRAY_SIZE(info->links);
-	     link_id++) {
-		struct mld_link_info *link;
-		size_t sta_len = EHT_ML_STA_INFO_LEN;
-
-		link = &info->links[link_id];
-		if (!link->valid)
-			continue;
-
-		sta_len += link->resp_sta_profile_len;
-
-		/* Element data and (fragmentation) headers */
-		eht_ml_len += sta_len;
-		eht_ml_len += 2 + sta_len / 255 * 2;
-	}
-
-	/* Element data */
-	len += eht_ml_len;
-
-	/* First header (254 bytes of data) */
-	len += 3;
-
-	/* Fragmentation headers; +1 for shorter first chunk */
-	len += (eht_ml_len + 1) / 255 * 2;
-
-	return len;
-}
-#undef EHT_ML_COMMON_INFO_LEN
-#undef EHT_ML_STA_INFO_LEN
-
-
-u8 * hostapd_eid_eht_ml_beacon(struct hostapd_data *hapd,
-			       struct mld_info *info,
-			       u8 *eid, bool include_mld_id)
-{
-	eid = hostapd_eid_eht_basic_ml_common(hapd, eid, info, include_mld_id);
-	return hostapd_eid_eht_reconf_ml(hapd, eid);
-}
-
-
-
-u8 * hostapd_eid_eht_ml_assoc(struct hostapd_data *hapd, struct sta_info *info,
-			      u8 *eid)
-{
-	if (!ap_sta_is_mld(hapd, info))
-		return eid;
-
-	eid = hostapd_eid_eht_basic_ml_common(hapd, eid, &info->mld_info,
-					      false);
-	ap_sta_free_sta_profile(&info->mld_info);
-	return hostapd_eid_eht_reconf_ml(hapd, eid);
-}
-
-
-size_t hostapd_eid_eht_ml_beacon_len(struct hostapd_data *hapd,
-				     struct mld_info *info,
-				     bool include_mld_id)
-{
-	return hostapd_eid_eht_ml_len(info, include_mld_id);
-}
-
-
 struct wpabuf * hostapd_ml_auth_resp(struct hostapd_data *hapd)
 {
 	struct wpabuf *buf = wpabuf_alloc(12);
@@ -824,7 +637,7 @@
 	wpabuf_put_u8(buf, WLAN_EID_EXT_MULTI_LINK);
 	wpabuf_put_le16(buf, MULTI_LINK_CONTROL_TYPE_BASIC);
 	wpabuf_put_u8(buf, ETH_ALEN + 1);
-	wpabuf_put_data(buf, hapd->mld->mld_addr, ETH_ALEN);
+	wpabuf_put_data(buf, hapd->mld_addr, ETH_ALEN);
 
 	return buf;
 }
@@ -1028,12 +841,11 @@
 
 
 static int hostapd_mld_validate_assoc_info(struct hostapd_data *hapd,
-					   struct sta_info *sta)
+					   struct mld_info *info)
 {
 	u8 i, link_id;
-	struct mld_info *info = &sta->mld_info;
 
-	if (!ap_sta_is_mld(hapd, sta)) {
+	if (!info->mld_sta) {
 		wpa_printf(MSG_DEBUG, "MLD: Not a non-AP MLD");
 		return 0;
 	}
@@ -1059,7 +871,8 @@
 			if (hapd == other_hapd)
 				continue;
 
-			if (hostapd_is_ml_partner(hapd, other_hapd) &&
+			if (other_hapd->conf->mld_ap &&
+			    other_hapd->conf->mld_id == hapd->conf->mld_id &&
 			    link_id == other_hapd->mld_link_id)
 				break;
 		}
@@ -1081,85 +894,6 @@
 }
 
 
-int hostapd_process_ml_assoc_req_addr(struct hostapd_data *hapd,
-				      const u8 *basic_mle, size_t basic_mle_len,
-				      u8 *mld_addr)
-{
-	struct wpabuf *mlbuf = ieee802_11_defrag(basic_mle, basic_mle_len,
-						 true);
-	struct ieee80211_eht_ml *ml;
-	struct eht_ml_basic_common_info *common_info;
-	size_t ml_len, common_info_len;
-	int ret = -1;
-	u16 ml_control;
-
-	if (!mlbuf)
-		return WLAN_STATUS_SUCCESS;
-
-	ml = (struct ieee80211_eht_ml *) wpabuf_head(mlbuf);
-	ml_len = wpabuf_len(mlbuf);
-
-	if (ml_len < sizeof(*ml))
-		goto out;
-
-	ml_control = le_to_host16(ml->ml_control);
-	if ((ml_control & MULTI_LINK_CONTROL_TYPE_MASK) !=
-	    MULTI_LINK_CONTROL_TYPE_BASIC) {
-		wpa_printf(MSG_DEBUG, "MLD: Invalid ML type=%u",
-			   ml_control & MULTI_LINK_CONTROL_TYPE_MASK);
-		goto out;
-	}
-
-	/* Common Info Length and MLD MAC Address must always be present */
-	common_info_len = 1 + ETH_ALEN;
-
-	if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_LINK_ID) {
-		wpa_printf(MSG_DEBUG, "MLD: Link ID Info not expected");
-		goto out;
-	}
-
-	if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_BSS_PARAM_CH_COUNT) {
-		wpa_printf(MSG_DEBUG,
-			   "MLD: BSS Parameters Change Count not expected");
-		goto out;
-	}
-
-	if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_MSD_INFO) {
-		wpa_printf(MSG_DEBUG,
-			   "MLD: Medium Synchronization Delay Information not expected");
-		goto out;
-	}
-
-	if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_EML_CAPA)
-		common_info_len += 2;
-
-	if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_MLD_CAPA)
-		common_info_len += 2;
-
-	if (sizeof(*ml) + common_info_len > ml_len) {
-		wpa_printf(MSG_DEBUG, "MLD: Not enough bytes for common info");
-		goto out;
-	}
-
-	common_info = (struct eht_ml_basic_common_info *) ml->variable;
-
-	/* Common information length includes the length octet */
-	if (common_info->len != common_info_len) {
-		wpa_printf(MSG_DEBUG,
-			   "MLD: Invalid common info len=%u", common_info->len);
-		goto out;
-	}
-
-	/* Get the MLD MAC Address */
-	os_memcpy(mld_addr, common_info->mld_addr, ETH_ALEN);
-	ret = 0;
-
-out:
-	wpabuf_free(mlbuf);
-	return ret;
-}
-
-
 u16 hostapd_process_ml_assoc_req(struct hostapd_data *hapd,
 				 struct ieee802_11_elems *elems,
 				 struct sta_info *sta)
@@ -1174,7 +908,7 @@
 	int ret = -1;
 	u16 ml_control;
 
-	mlbuf = ieee802_11_defrag(elems->basic_mle, elems->basic_mle_len, true);
+	mlbuf = ieee802_11_defrag_mle(elems, MULTI_LINK_CONTROL_TYPE_BASIC);
 	if (!mlbuf)
 		return WLAN_STATUS_SUCCESS;
 
@@ -1256,8 +990,8 @@
 		   info->common_info.eml_capa, info->common_info.mld_capa);
 
 	/* Check the MLD MAC Address */
-	if (!ether_addr_equal(info->common_info.mld_addr,
-			      common_info->mld_addr)) {
+	if (os_memcmp(info->common_info.mld_addr, common_info->mld_addr,
+		      ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG,
 			   "MLD: MLD address mismatch between authentication ("
 			   MACSTR ") and association (" MACSTR ")",
@@ -1266,7 +1000,7 @@
 		goto out;
 	}
 
-	info->links[hapd->mld_link_id].valid = 1;
+	info->links[hapd->mld_link_id].valid = true;
 
 	/* Parse the link info field */
 	ml_len -= sizeof(*ml) + common_info_len;
@@ -1297,11 +1031,9 @@
 
 		if (*pos != MULTI_LINK_SUB_ELEM_ID_PER_STA_PROFILE) {
 			wpa_printf(MSG_DEBUG,
-				   "MLD: Skip unknown Multi-Link element subelement ID=%u",
+				   "MLD: Unexpected Multi-Link element subelement ID=%u",
 				   *pos);
-			pos += 2 + sub_elem_len;
-			ml_len -= 2 + sub_elem_len;
-			continue;
+			goto out;
 		}
 
 		/* Skip the subelement ID and the length */
@@ -1406,7 +1138,7 @@
 		goto out;
 	}
 
-	ret = hostapd_mld_validate_assoc_info(hapd, sta);
+	ret = hostapd_mld_validate_assoc_info(hapd, info);
 out:
 	wpabuf_free(mlbuf);
 	if (ret) {
diff --git a/src/ap/ieee802_11_he.c b/src/ap/ieee802_11_he.c
index a2deda6..548a448 100644
--- a/src/ap/ieee802_11_he.c
+++ b/src/ap/ieee802_11_he.c
@@ -12,7 +12,6 @@
 #include "utils/common.h"
 #include "common/ieee802_11_defs.h"
 #include "common/ieee802_11_common.h"
-#include "common/hw_features_common.h"
 #include "hostapd.h"
 #include "ap_config.h"
 #include "beacon.h"
@@ -225,11 +224,10 @@
 		u8 seg0 = hapd->iconf->he_oper_centr_freq_seg0_idx;
 		u8 seg1 = hostapd_get_oper_centr_freq_seg1_idx(hapd->iconf);
 		u8 control;
-#ifdef CONFIG_IEEE80211BE
-		u16 punct_bitmap = hostapd_get_punct_bitmap(hapd);
 
-		if (punct_bitmap) {
-			punct_update_legacy_bw(punct_bitmap,
+#ifdef CONFIG_IEEE80211BE
+		if (hapd->iconf->punct_bitmap) {
+			punct_update_legacy_bw(hapd->iconf->punct_bitmap,
 					       hapd->iconf->channel,
 					       &oper_chwidth, &seg0, &seg1);
 		}
@@ -256,15 +254,16 @@
 			control = 3;
 		else
 			control = center_idx_to_bw_6ghz(seg0);
-
-		control |= hapd->iconf->he_6ghz_reg_pwr_type <<
-			HE_6GHZ_OPER_INFO_CTRL_REG_INFO_SHIFT;
-
+		if (hapd->iconf->he_6ghz_reg_pwr_type == 1)
+			control |= HE_6GHZ_STANDARD_POWER_AP <<
+				HE_6GHZ_OPER_INFO_CTRL_REG_INFO_SHIFT;
+		else
+			control |= HE_6GHZ_INDOOR_AP <<
+				HE_6GHZ_OPER_INFO_CTRL_REG_INFO_SHIFT;
 		*pos++ = control;
 
 		/* Channel Center Freq Seg0/Seg1 */
-		if (oper_chwidth == CONF_OPER_CHWIDTH_160MHZ ||
-		    oper_chwidth == CONF_OPER_CHWIDTH_320MHZ) {
+		if (oper_chwidth == 2) {
 			/*
 			 * Seg 0 indicates the channel center frequency index of
 			 * the 160 MHz channel.
diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c
index 85790c7..31dfb62 100644
--- a/src/ap/ieee802_11_shared.c
+++ b/src/ap/ieee802_11_shared.c
@@ -1,6 +1,6 @@
 /*
  * hostapd / IEEE 802.11 Management
- * Copyright (c) 2002-2024, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -21,25 +21,16 @@
 #include "ieee802_11.h"
 
 
-static u8 * hostapd_eid_timeout_interval(u8 *pos, u8 type, u32 value)
-{
-	*pos++ = WLAN_EID_TIMEOUT_INTERVAL;
-	*pos++ = 5;
-	*pos++ = type;
-	WPA_PUT_LE32(pos, value);
-	pos += 4;
-
-	return pos;
-}
-
-
 u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd,
 				     struct sta_info *sta, u8 *eid)
 {
+	u8 *pos = eid;
 	u32 timeout, tu;
 	struct os_reltime now, passed;
-	u8 type = WLAN_TIMEOUT_ASSOC_COMEBACK;
 
+	*pos++ = WLAN_EID_TIMEOUT_INTERVAL;
+	*pos++ = 5;
+	*pos++ = WLAN_TIMEOUT_ASSOC_COMEBACK;
 	os_get_reltime(&now);
 	os_reltime_sub(&now, &sta->sa_query_start, &passed);
 	tu = (passed.sec * 1000000 + passed.usec) / 1024;
@@ -49,12 +40,10 @@
 		timeout = 0;
 	if (timeout < hapd->conf->assoc_sa_query_max_timeout)
 		timeout++; /* add some extra time for local timers */
+	WPA_PUT_LE32(pos, timeout);
+	pos += 4;
 
-#ifdef CONFIG_TESTING_OPTIONS
-	if (hapd->conf->test_assoc_comeback_type != -1)
-		type = hapd->conf->test_assoc_comeback_type;
-#endif /* CONFIG_TESTING_OPTIONS */
-	return hostapd_eid_timeout_interval(eid, type, timeout);
+	return pos;
 }
 
 
@@ -62,14 +51,13 @@
 void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
 				  const u8 *addr, const u8 *trans_id)
 {
-#if defined(CONFIG_OCV) || defined(CONFIG_IEEE80211BE)
-	struct sta_info *sta = ap_get_sta(hapd, addr);
-#endif /* CONFIG_OCV || CONFIG_IEEE80211BE */
+#ifdef CONFIG_OCV
+	struct sta_info *sta;
+#endif /* CONFIG_OCV */
 	struct ieee80211_mgmt *mgmt;
 	u8 *oci_ie = NULL;
 	u8 oci_ie_len = 0;
 	u8 *end;
-	const u8 *own_addr = hapd->own_addr;
 
 	wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Request to "
 		   MACSTR, MAC2STR(addr));
@@ -77,6 +65,7 @@
 		    trans_id, WLAN_SA_QUERY_TR_ID_LEN);
 
 #ifdef CONFIG_OCV
+	sta = ap_get_sta(hapd, addr);
 	if (sta && wpa_auth_uses_ocv(sta->wpa_sm)) {
 		struct wpa_channel_info ci;
 
@@ -119,16 +108,11 @@
 		return;
 	}
 
-#ifdef CONFIG_IEEE80211BE
-	if (ap_sta_is_mld(hapd, sta))
-		own_addr = hapd->mld->mld_addr;
-#endif /* CONFIG_IEEE80211BE */
-
 	mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
 					   WLAN_FC_STYPE_ACTION);
 	os_memcpy(mgmt->da, addr, ETH_ALEN);
-	os_memcpy(mgmt->sa, own_addr, ETH_ALEN);
-	os_memcpy(mgmt->bssid, own_addr, ETH_ALEN);
+	os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
+	os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
 	mgmt->u.action.category = WLAN_ACTION_SA_QUERY;
 	mgmt->u.action.u.sa_query_req.action = WLAN_SA_QUERY_REQUEST;
 	os_memcpy(mgmt->u.action.u.sa_query_req.trans_id, trans_id,
@@ -157,7 +141,6 @@
 	u8 *oci_ie = NULL;
 	u8 oci_ie_len = 0;
 	u8 *end;
-	const u8 *own_addr = hapd->own_addr;
 
 	wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Request from "
 		   MACSTR, MAC2STR(sa));
@@ -217,16 +200,11 @@
 	wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Response to "
 		   MACSTR, MAC2STR(sa));
 
-#ifdef CONFIG_IEEE80211BE
-	if (ap_sta_is_mld(hapd, sta))
-		own_addr = hapd->mld->mld_addr;
-#endif /* CONFIG_IEEE80211BE */
-
 	resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
 					   WLAN_FC_STYPE_ACTION);
 	os_memcpy(resp->da, sa, ETH_ALEN);
-	os_memcpy(resp->sa, own_addr, ETH_ALEN);
-	os_memcpy(resp->bssid, own_addr, ETH_ALEN);
+	os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN);
+	os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
 	resp->u.action.category = WLAN_ACTION_SA_QUERY;
 	resp->u.action.u.sa_query_req.action = WLAN_SA_QUERY_RESPONSE;
 	os_memcpy(resp->u.action.u.sa_query_req.trans_id, trans_id,
@@ -1138,11 +1116,13 @@
 u16 check_ext_capab(struct hostapd_data *hapd, struct sta_info *sta,
 		    const u8 *ext_capab_ie, size_t ext_capab_ie_len)
 {
+#ifdef CONFIG_INTERWORKING
 	/* check for QoS Map support */
 	if (ext_capab_ie_len >= 5) {
 		if (ext_capab_ie[4] & 0x01)
 			sta->qos_map_enabled = 1;
 	}
+#endif /* CONFIG_INTERWORKING */
 
 	if (ext_capab_ie_len > 0) {
 		sta->ecsa_supported = !!(ext_capab_ie[0] & BIT(2));
@@ -1157,44 +1137,3 @@
 
 	return WLAN_STATUS_SUCCESS;
 }
-
-
-struct sta_info * hostapd_ml_get_assoc_sta(struct hostapd_data *hapd,
-					   struct sta_info *sta,
-					   struct hostapd_data **assoc_hapd)
-{
-#ifdef CONFIG_IEEE80211BE
-	struct hostapd_data *other_hapd = NULL;
-	struct sta_info *tmp_sta;
-
-	if (!ap_sta_is_mld(hapd, sta))
-		return NULL;
-
-	*assoc_hapd = hapd;
-
-	/* The station is the one on which the association was performed */
-	if (sta->mld_assoc_link_id == hapd->mld_link_id)
-		return sta;
-
-	other_hapd = hostapd_mld_get_link_bss(hapd, sta->mld_assoc_link_id);
-	if (!other_hapd) {
-		wpa_printf(MSG_DEBUG, "MLD: No link match for link_id=%u",
-			   sta->mld_assoc_link_id);
-		return sta;
-	}
-
-	/*
-	 * Iterate over the stations and find the one with the matching link ID
-	 * and association ID.
-	 */
-	for (tmp_sta = other_hapd->sta_list; tmp_sta; tmp_sta = tmp_sta->next) {
-		if (tmp_sta->mld_assoc_link_id == sta->mld_assoc_link_id &&
-		    tmp_sta->aid == sta->aid) {
-			*assoc_hapd = other_hapd;
-			return tmp_sta;
-		}
-	}
-#endif /* CONFIG_IEEE80211BE */
-
-	return sta;
-}
diff --git a/src/ap/ieee802_11_vht.c b/src/ap/ieee802_11_vht.c
index 4dc325c..db615a3 100644
--- a/src/ap/ieee802_11_vht.c
+++ b/src/ap/ieee802_11_vht.c
@@ -12,7 +12,6 @@
 
 #include "utils/common.h"
 #include "common/ieee802_11_defs.h"
-#include "common/hw_features_common.h"
 #include "hostapd.h"
 #include "ap_config.h"
 #include "sta_info.h"
@@ -80,9 +79,6 @@
 		hostapd_get_oper_chwidth(hapd->iconf);
 	u8 seg0 = hapd->iconf->vht_oper_centr_freq_seg0_idx;
 	u8 seg1 = hapd->iconf->vht_oper_centr_freq_seg1_idx;
-#ifdef CONFIG_IEEE80211BE
-	u16 punct_bitmap = hostapd_get_punct_bitmap(hapd);
-#endif /* CONFIG_IEEE80211BE */
 
 	if (is_6ghz_op_class(hapd->iconf->op_class))
 		return eid;
@@ -94,8 +90,8 @@
 	os_memset(oper, 0, sizeof(*oper));
 
 #ifdef CONFIG_IEEE80211BE
-	if (punct_bitmap) {
-		punct_update_legacy_bw(punct_bitmap,
+	if (hapd->iconf->punct_bitmap) {
+		punct_update_legacy_bw(hapd->iconf->punct_bitmap,
 				       hapd->iconf->channel,
 				       &oper_chwidth, &seg0, &seg1);
 	}
diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
index 8e98b65..052231e 100644
--- a/src/ap/ieee802_1x.c
+++ b/src/ap/ieee802_1x.c
@@ -114,15 +114,12 @@
 				      bool authorized, bool mld)
 {
 	int res;
-	bool update;
 
 	if (sta->flags & WLAN_STA_PREAUTH)
 		return;
 
-	update = ap_sta_set_authorized_flag(hapd, sta, authorized);
+	ap_sta_set_authorized(hapd, sta, authorized);
 	res = hostapd_set_authorized(hapd, sta, authorized);
-	if (update)
-		ap_sta_set_authorized_event(hapd, sta, authorized);
 	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
 		       HOSTAPD_LEVEL_DEBUG, "%sauthorizing port",
 		       authorized ? "" : "un");
@@ -172,7 +169,8 @@
 			struct hostapd_data *tmp_hapd =
 				hapd->iface->interfaces->iface[i]->bss[0];
 
-			if (!hostapd_is_ml_partner(hapd, tmp_hapd))
+			if (!tmp_hapd->conf->mld_ap ||
+			    hapd->conf->mld_id != tmp_hapd->conf->mld_id)
 				continue;
 
 			for (tmp_sta = tmp_hapd->sta_list; tmp_sta;
@@ -2539,20 +2537,13 @@
 	struct eapol_auth_config conf;
 	struct eapol_auth_cb cb;
 
-#ifdef CONFIG_IEEE80211BE
-	if (!hostapd_mld_is_first_bss(hapd)) {
-		struct hostapd_data *first;
-
+	if (hapd->mld_first_bss) {
 		wpa_printf(MSG_DEBUG,
 			   "MLD: Using IEEE 802.1X state machine of the first BSS");
 
-		first = hostapd_mld_get_first_bss(hapd);
-		if (!first)
-			return -1;
-		hapd->eapol_auth = first->eapol_auth;
+		hapd->eapol_auth = hapd->mld_first_bss->eapol_auth;
 		return 0;
 	}
-#endif /* CONFIG_IEEE80211BE */
 
 	dl_list_init(&hapd->erp_keys);
 
@@ -2638,15 +2629,13 @@
 
 void ieee802_1x_deinit(struct hostapd_data *hapd)
 {
-#ifdef CONFIG_IEEE80211BE
-	if (!hostapd_mld_is_first_bss(hapd)) {
+	if (hapd->mld_first_bss) {
 		wpa_printf(MSG_DEBUG,
 			   "MLD: Deinit IEEE 802.1X state machine of a non-first BSS");
 
 		hapd->eapol_auth = NULL;
 		return;
 	}
-#endif /* CONFIG_IEEE80211BE */
 
 #ifdef CONFIG_WEP
 	eloop_cancel_timeout(ieee802_1x_rekey, hapd, NULL);
diff --git a/src/ap/nan_usd_ap.c b/src/ap/nan_usd_ap.c
deleted file mode 100644
index 52a967a..0000000
--- a/src/ap/nan_usd_ap.c
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * NAN unsynchronized service discovery (USD)
- * Copyright (c) 2024, Qualcomm Innovation Center, Inc.
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#include "utils/includes.h"
-
-#include "utils/common.h"
-#include "common/wpa_ctrl.h"
-#include "common/nan_de.h"
-#include "hostapd.h"
-#include "ap_drv_ops.h"
-#include "nan_usd_ap.h"
-
-
-static int hostapd_nan_de_tx(void *ctx, unsigned int freq,
-			     unsigned int wait_time,
-			     const u8 *dst, const u8 *src, const u8 *bssid,
-			     const struct wpabuf *buf)
-{
-	struct hostapd_data *hapd = ctx;
-
-	wpa_printf(MSG_DEBUG, "NAN: TX NAN SDF A1=" MACSTR " A2=" MACSTR
-		   " A3=" MACSTR " len=%zu",
-		   MAC2STR(dst), MAC2STR(src), MAC2STR(bssid),
-		   wpabuf_len(buf));
-
-	/* TODO: Force use of OFDM */
-	return hostapd_drv_send_action(hapd, hapd->iface->freq, 0, dst,
-				       wpabuf_head(buf), wpabuf_len(buf));
-}
-
-
-static int hostapd_nan_de_listen(void *ctx, unsigned int freq,
-			      unsigned int duration)
-{
-	return 0;
-}
-
-
-static void
-hostapd_nan_de_discovery_result(void *ctx, int subscribe_id,
-				enum nan_service_protocol_type srv_proto_type,
-				const u8 *ssi, size_t ssi_len,
-				int peer_publish_id, const u8 *peer_addr,
-				bool fsd, bool fsd_gas)
-{
-	struct hostapd_data *hapd = ctx;
-	char *ssi_hex;
-
-	ssi_hex = os_zalloc(2 * ssi_len + 1);
-	if (!ssi_hex)
-		return;
-	if (ssi)
-		wpa_snprintf_hex(ssi_hex, 2 * ssi_len + 1, ssi, ssi_len);
-	wpa_msg(hapd->msg_ctx, MSG_INFO, NAN_DISCOVERY_RESULT
-		"subscribe_id=%d publish_id=%d address=" MACSTR
-		" fsd=%d fsd_gas=%d srv_proto_type=%u ssi=%s",
-		subscribe_id, peer_publish_id, MAC2STR(peer_addr),
-		fsd, fsd_gas, srv_proto_type, ssi_hex);
-	os_free(ssi_hex);
-}
-
-
-static void
-hostapd_nan_de_replied(void *ctx, int publish_id, const u8 *peer_addr,
-		       int peer_subscribe_id,
-		       enum nan_service_protocol_type srv_proto_type,
-		       const u8 *ssi, size_t ssi_len)
-{
-	struct hostapd_data *hapd = ctx;
-	char *ssi_hex;
-
-	ssi_hex = os_zalloc(2 * ssi_len + 1);
-	if (!ssi_hex)
-		return;
-	if (ssi)
-		wpa_snprintf_hex(ssi_hex, 2 * ssi_len + 1, ssi, ssi_len);
-	wpa_msg(hapd->msg_ctx, MSG_INFO, NAN_REPLIED
-		"publish_id=%d address=" MACSTR
-		" subscribe_id=%d srv_proto_type=%u ssi=%s",
-		publish_id, MAC2STR(peer_addr), peer_subscribe_id,
-		srv_proto_type, ssi_hex);
-	os_free(ssi_hex);
-}
-
-
-static const char * nan_reason_txt(enum nan_de_reason reason)
-{
-	switch (reason) {
-	case NAN_DE_REASON_TIMEOUT:
-		return "timeout";
-	case NAN_DE_REASON_USER_REQUEST:
-		return "user-request";
-	case NAN_DE_REASON_FAILURE:
-		return "failure";
-	}
-
-	return "unknown";
-}
-
-
-static void hostapd_nan_de_publish_terminated(void *ctx, int publish_id,
-					      enum nan_de_reason reason)
-{
-	struct hostapd_data *hapd = ctx;
-
-	wpa_msg(hapd->msg_ctx, MSG_INFO, NAN_PUBLISH_TERMINATED
-		"publish_id=%d reason=%s",
-		publish_id, nan_reason_txt(reason));
-}
-
-
-static void hostapd_nan_de_subscribe_terminated(void *ctx, int subscribe_id,
-						enum nan_de_reason reason)
-{
-	struct hostapd_data *hapd = ctx;
-
-	wpa_msg(hapd->msg_ctx, MSG_INFO, NAN_SUBSCRIBE_TERMINATED
-		"subscribe_id=%d reason=%s",
-		subscribe_id, nan_reason_txt(reason));
-}
-
-
-static void hostapd_nan_de_receive(void *ctx, int id, int peer_instance_id,
-				   const u8 *ssi, size_t ssi_len,
-				   const u8 *peer_addr)
-{
-	struct hostapd_data *hapd = ctx;
-	char *ssi_hex;
-
-	ssi_hex = os_zalloc(2 * ssi_len + 1);
-	if (!ssi_hex)
-		return;
-	if (ssi)
-		wpa_snprintf_hex(ssi_hex, 2 * ssi_len + 1, ssi, ssi_len);
-	wpa_msg(hapd->msg_ctx, MSG_INFO, NAN_RECEIVE
-		"id=%d peer_instance_id=%d address=" MACSTR " ssi=%s",
-		id, peer_instance_id, MAC2STR(peer_addr), ssi_hex);
-	os_free(ssi_hex);
-}
-
-
-int hostapd_nan_usd_init(struct hostapd_data *hapd)
-{
-	struct nan_callbacks cb;
-
-	os_memset(&cb, 0, sizeof(cb));
-	cb.ctx = hapd;
-	cb.tx = hostapd_nan_de_tx;
-	cb.listen = hostapd_nan_de_listen;
-	cb.discovery_result = hostapd_nan_de_discovery_result;
-	cb.replied = hostapd_nan_de_replied;
-	cb.publish_terminated = hostapd_nan_de_publish_terminated;
-	cb.subscribe_terminated = hostapd_nan_de_subscribe_terminated;
-	cb.receive = hostapd_nan_de_receive;
-
-	hapd->nan_de = nan_de_init(hapd->own_addr, true, &cb);
-	if (!hapd->nan_de)
-		return -1;
-	return 0;
-}
-
-
-void hostapd_nan_usd_deinit(struct hostapd_data *hapd)
-{
-	nan_de_deinit(hapd->nan_de);
-	hapd->nan_de = NULL;
-}
-
-
-void hostapd_nan_usd_rx_sdf(struct hostapd_data *hapd, const u8 *src,
-			    unsigned int freq, const u8 *buf, size_t len)
-{
-	if (!hapd->nan_de)
-		return;
-	nan_de_rx_sdf(hapd->nan_de, src, freq, buf, len);
-}
-
-
-void hostapd_nan_usd_flush(struct hostapd_data *hapd)
-{
-	if (!hapd->nan_de)
-		return;
-	nan_de_flush(hapd->nan_de);
-}
-
-
-int hostapd_nan_usd_publish(struct hostapd_data *hapd, const char *service_name,
-			    enum nan_service_protocol_type srv_proto_type,
-			    const struct wpabuf *ssi,
-			    struct nan_publish_params *params)
-{
-	int publish_id;
-	struct wpabuf *elems = NULL;
-
-	if (!hapd->nan_de)
-		return -1;
-
-	publish_id = nan_de_publish(hapd->nan_de, service_name, srv_proto_type,
-				    ssi, elems, params);
-	wpabuf_free(elems);
-	return publish_id;
-}
-
-
-void hostapd_nan_usd_cancel_publish(struct hostapd_data *hapd, int publish_id)
-{
-	if (!hapd->nan_de)
-		return;
-	nan_de_cancel_publish(hapd->nan_de, publish_id);
-}
-
-
-int hostapd_nan_usd_update_publish(struct hostapd_data *hapd, int publish_id,
-				   const struct wpabuf *ssi)
-{
-	int ret;
-
-	if (!hapd->nan_de)
-		return -1;
-	ret = nan_de_update_publish(hapd->nan_de, publish_id, ssi);
-	return ret;
-}
-
-
-int hostapd_nan_usd_subscribe(struct hostapd_data *hapd,
-			      const char *service_name,
-			      enum nan_service_protocol_type srv_proto_type,
-			      const struct wpabuf *ssi,
-			      struct nan_subscribe_params *params)
-{
-	int subscribe_id;
-	struct wpabuf *elems = NULL;
-
-	if (!hapd->nan_de)
-		return -1;
-
-	subscribe_id = nan_de_subscribe(hapd->nan_de, service_name,
-					srv_proto_type, ssi, elems, params);
-	wpabuf_free(elems);
-	return subscribe_id;
-}
-
-
-void hostapd_nan_usd_cancel_subscribe(struct hostapd_data *hapd,
-				      int subscribe_id)
-{
-	if (!hapd->nan_de)
-		return;
-	nan_de_cancel_subscribe(hapd->nan_de, subscribe_id);
-}
-
-
-int hostapd_nan_usd_transmit(struct hostapd_data *hapd, int handle,
-			     const struct wpabuf *ssi,
-			     const struct wpabuf *elems,
-			     const u8 *peer_addr, u8 req_instance_id)
-{
-	if (!hapd->nan_de)
-		return -1;
-	return nan_de_transmit(hapd->nan_de, handle, ssi, elems, peer_addr,
-			       req_instance_id);
-}
diff --git a/src/ap/nan_usd_ap.h b/src/ap/nan_usd_ap.h
deleted file mode 100644
index 58ff5fc..0000000
--- a/src/ap/nan_usd_ap.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * NAN unsynchronized service discovery (USD)
- * Copyright (c) 2024, Qualcomm Innovation Center, Inc.
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#ifndef NAN_USD_AP_H
-#define NAN_USD_AP_H
-
-struct nan_subscribe_params;
-struct nan_publish_params;
-enum nan_service_protocol_type;
-
-int hostapd_nan_usd_init(struct hostapd_data *hapd);
-void hostapd_nan_usd_deinit(struct hostapd_data *hapd);
-void hostapd_nan_usd_rx_sdf(struct hostapd_data *hapd, const u8 *src,
-			    unsigned int freq, const u8 *buf, size_t len);
-void hostapd_nan_usd_flush(struct hostapd_data *hapd);
-int hostapd_nan_usd_publish(struct hostapd_data *hapd, const char *service_name,
-			    enum nan_service_protocol_type srv_proto_type,
-			    const struct wpabuf *ssi,
-			    struct nan_publish_params *params);
-void hostapd_nan_usd_cancel_publish(struct hostapd_data *hapd, int publish_id);
-int hostapd_nan_usd_update_publish(struct hostapd_data *hapd, int publish_id,
-				   const struct wpabuf *ssi);
-int hostapd_nan_usd_subscribe(struct hostapd_data *hapd,
-			      const char *service_name,
-			      enum nan_service_protocol_type srv_proto_type,
-			      const struct wpabuf *ssi,
-			      struct nan_subscribe_params *params);
-void hostapd_nan_usd_cancel_subscribe(struct hostapd_data *hapd,
-				      int subscribe_id);
-int hostapd_nan_usd_transmit(struct hostapd_data *hapd, int handle,
-			     const struct wpabuf *ssi,
-			     const struct wpabuf *elems,
-			     const u8 *peer_addr, u8 req_instance_id);
-void hostapd_nan_usd_remain_on_channel_cb(struct hostapd_data *hapd,
-					  unsigned int freq,
-					  unsigned int duration);
-void hostapd_nan_usd_cancel_remain_on_channel_cb(struct hostapd_data *hapd,
-						 unsigned int freq);
-void hostapd_nan_usd_tx_wait_expire(struct hostapd_data *hapd);
-
-#endif /* NAN_USD_AP_H */
diff --git a/src/ap/ndisc_snoop.c b/src/ap/ndisc_snoop.c
index bc1eb62..788c12f 100644
--- a/src/ap/ndisc_snoop.c
+++ b/src/ap/ndisc_snoop.c
@@ -61,7 +61,6 @@
 	dl_list_for_each_safe(ip6addr, prev, &sta->ip6addr, struct ip6addr,
 			      list) {
 		hostapd_drv_br_delete_ip_neigh(hapd, 6, (u8 *) &ip6addr->addr);
-		dl_list_del(&ip6addr->list);
 		os_free(ip6addr);
 	}
 }
diff --git a/src/ap/neighbor_db.c b/src/ap/neighbor_db.c
index f7a7d83..5b276e8 100644
--- a/src/ap/neighbor_db.c
+++ b/src/ap/neighbor_db.c
@@ -24,7 +24,7 @@
 
 	dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry,
 			 list) {
-		if (ether_addr_equal(bssid, nr->bssid) &&
+		if (os_memcmp(bssid, nr->bssid, ETH_ALEN) == 0 &&
 		    (!ssid ||
 		     (ssid->ssid_len == nr->ssid.ssid_len &&
 		      os_memcmp(ssid->ssid, nr->ssid.ssid,
@@ -99,10 +99,7 @@
 	nr->civic = NULL;
 	os_memset(nr->bssid, 0, sizeof(nr->bssid));
 	os_memset(&nr->ssid, 0, sizeof(nr->ssid));
-	os_memset(&nr->lci_date, 0, sizeof(nr->lci_date));
 	nr->stationary = 0;
-	nr->short_ssid = 0;
-	nr->bss_parameters = 0;
 }
 
 
@@ -168,14 +165,6 @@
 }
 
 
-static void hostapd_neighbor_free(struct hostapd_neighbor_entry *nr)
-{
-	hostapd_neighbor_clear_entry(nr);
-	dl_list_del(&nr->list);
-	os_free(nr);
-}
-
-
 int hostapd_neighbor_remove(struct hostapd_data *hapd, const u8 *bssid,
 			    const struct wpa_ssid_value *ssid)
 {
@@ -185,7 +174,9 @@
 	if (!nr)
 		return -1;
 
-	hostapd_neighbor_free(nr);
+	hostapd_neighbor_clear_entry(nr);
+	dl_list_del(&nr->list);
+	os_free(nr);
 
 	return 0;
 }
@@ -197,7 +188,9 @@
 
 	dl_list_for_each_safe(nr, prev, &hapd->nr_db,
 			      struct hostapd_neighbor_entry, list) {
-		hostapd_neighbor_free(nr);
+		hostapd_neighbor_clear_entry(nr);
+		dl_list_del(&nr->list);
+		os_free(nr);
 	}
 }
 
@@ -332,35 +325,3 @@
 	wpabuf_free(nr);
 #endif /* NEED_AP_MLME */
 }
-
-
-static struct hostapd_neighbor_entry *
-hostapd_neighbor_get_diff_short_ssid(struct hostapd_data *hapd, const u8 *bssid)
-{
-	struct hostapd_neighbor_entry *nr;
-
-	dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry,
-			 list) {
-		if (ether_addr_equal(bssid, nr->bssid) &&
-		    nr->short_ssid != hapd->conf->ssid.short_ssid)
-			return nr;
-	}
-	return NULL;
-}
-
-
-int hostapd_neighbor_sync_own_report(struct hostapd_data *hapd)
-{
-	struct hostapd_neighbor_entry *nr;
-
-	nr = hostapd_neighbor_get_diff_short_ssid(hapd, hapd->own_addr);
-	if (!nr)
-		return -1;
-
-	/* Clear old entry due to SSID change */
-	hostapd_neighbor_free(nr);
-
-	hostapd_neighbor_set_own_report(hapd);
-
-	return 0;
-}
diff --git a/src/ap/neighbor_db.h b/src/ap/neighbor_db.h
index 53f7142..992671b 100644
--- a/src/ap/neighbor_db.h
+++ b/src/ap/neighbor_db.h
@@ -20,7 +20,6 @@
 			 const struct wpabuf *civic, int stationary,
 			 u8 bss_parameters);
 void hostapd_neighbor_set_own_report(struct hostapd_data *hapd);
-int hostapd_neighbor_sync_own_report(struct hostapd_data *hapd);
 int hostapd_neighbor_remove(struct hostapd_data *hapd, const u8 *bssid,
 			    const struct wpa_ssid_value *ssid);
 void hostapd_free_neighbor_db(struct hostapd_data *hapd);
diff --git a/src/ap/pmksa_cache_auth.c b/src/ap/pmksa_cache_auth.c
index 2fce838..ee4232f 100644
--- a/src/ap/pmksa_cache_auth.c
+++ b/src/ap/pmksa_cache_auth.c
@@ -487,14 +487,14 @@
 		for (entry = pmksa->pmkid[PMKID_HASH(pmkid)]; entry;
 		     entry = entry->hnext) {
 			if ((spa == NULL ||
-			     ether_addr_equal(entry->spa, spa)) &&
+			     os_memcmp(entry->spa, spa, ETH_ALEN) == 0) &&
 			    os_memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0)
 				return entry;
 		}
 	} else {
 		for (entry = pmksa->pmksa; entry; entry = entry->next) {
 			if (spa == NULL ||
-			    ether_addr_equal(entry->spa, spa))
+			    os_memcmp(entry->spa, spa, ETH_ALEN) == 0)
 				return entry;
 		}
 	}
@@ -521,7 +521,7 @@
 	u8 new_pmkid[PMKID_LEN];
 
 	for (entry = pmksa->pmksa; entry; entry = entry->next) {
-		if (!ether_addr_equal(entry->spa, spa))
+		if (os_memcmp(entry->spa, spa, ETH_ALEN) != 0)
 			continue;
 		if (wpa_key_mgmt_sae(entry->akmp) ||
 		    wpa_key_mgmt_fils(entry->akmp)) {
@@ -575,7 +575,7 @@
 	int match = 0;
 
 	if (attr->sta_addr) {
-		if (!ether_addr_equal(attr->sta_addr, entry->spa))
+		if (os_memcmp(attr->sta_addr, entry->spa, ETH_ALEN) != 0)
 			return 0;
 		match++;
 	}
@@ -717,7 +717,7 @@
 	 * <BSSID> <PMKID> <PMK> <expiration in seconds>
 	 */
 	for (entry = pmksa->pmksa; entry; entry = entry->next) {
-		if (addr && !ether_addr_equal(entry->spa, addr))
+		if (addr && os_memcmp(entry->spa, addr, ETH_ALEN) != 0)
 			continue;
 
 		ret = os_snprintf(pos, end - pos, MACSTR " ",
diff --git a/src/ap/preauth_auth.c b/src/ap/preauth_auth.c
index cb225c6..3284a10 100644
--- a/src/ap/preauth_auth.c
+++ b/src/ap/preauth_auth.c
@@ -58,7 +58,7 @@
 	ethhdr = (struct l2_ethhdr *) buf;
 	hdr = (struct ieee802_1x_hdr *) (ethhdr + 1);
 
-	if (!ether_addr_equal(ethhdr->h_dest, hapd->own_addr)) {
+	if (os_memcmp(ethhdr->h_dest, hapd->own_addr, ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG, "RSN: pre-auth for foreign address "
 			   MACSTR, MAC2STR(ethhdr->h_dest));
 		return;
diff --git a/src/ap/rrm.c b/src/ap/rrm.c
index fbcddf3..f2d5cd1 100644
--- a/src/ap/rrm.c
+++ b/src/ap/rrm.c
@@ -334,53 +334,6 @@
 }
 
 
-static void hostapd_link_mesr_rep_timeout_handler(void *eloop_data,
-						  void *user_ctx)
-{
-	struct hostapd_data *hapd = eloop_data;
-
-	wpa_printf(MSG_DEBUG,
-		   "RRM: Link measurement request (token %u) timed out",
-		   hapd->link_measurement_req_token);
-	hapd->link_mesr_req_active = 0;
-}
-
-
-static void hostapd_handle_link_mesr_report(struct hostapd_data *hapd,
-					    const u8 *buf, size_t len)
-{
-	const struct ieee80211_mgmt *mgmt = (const struct ieee80211_mgmt *) buf;
-	const struct rrm_link_measurement_report *report;
-	const u8 *pos, *end;
-	char report_msg[2 * 8 + 1];
-
-	end = buf + len;
-	pos = mgmt->u.action.u.rrm.variable;
-	report = (const struct rrm_link_measurement_report *) (pos - 1);
-	if (end - (const u8 *) report < (int) sizeof(*report))
-		return;
-
-	if (!hapd->link_mesr_req_active ||
-	    (hapd->link_measurement_req_token != report->dialog_token)) {
-		wpa_printf(MSG_INFO,
-			   "Unexpected Link measurement report, token %u",
-			   report->dialog_token);
-		return;
-	}
-
-	hapd->link_mesr_req_active = 0;
-	eloop_cancel_timeout(hostapd_link_mesr_rep_timeout_handler, hapd, NULL);
-
-	report_msg[0] = '\0';
-	if (wpa_snprintf_hex(report_msg, sizeof(report_msg),
-			     pos, end - pos) < 0)
-		return;
-
-	wpa_msg(hapd->msg_ctx, MSG_INFO, LINK_MSR_RESP_RX MACSTR " %u %s",
-		MAC2STR(mgmt->sa), report->dialog_token, report_msg);
-}
-
-
 void hostapd_handle_radio_measurement(struct hostapd_data *hapd,
 				      const u8 *buf, size_t len)
 {
@@ -403,9 +356,6 @@
 	case WLAN_RRM_NEIGHBOR_REPORT_REQUEST:
 		hostapd_handle_nei_report_req(hapd, buf, len);
 		break;
-	case WLAN_RRM_LINK_MEASUREMENT_REPORT:
-		hostapd_handle_link_mesr_report(hapd, buf, len);
-		break;
 	default:
 		wpa_printf(MSG_DEBUG, "RRM action %u is not supported",
 			   mgmt->u.action.u.rrm.action);
@@ -613,7 +563,6 @@
 	hapd->lci_req_active = 0;
 	eloop_cancel_timeout(hostapd_range_rep_timeout_handler, hapd, NULL);
 	hapd->range_req_active = 0;
-	eloop_cancel_timeout(hostapd_link_mesr_rep_timeout_handler, hapd, NULL);
 }
 
 
@@ -723,73 +672,3 @@
 		" %u ack=%d", MAC2STR(mgmt->da),
 		mgmt->u.action.u.rrm.dialog_token, ok);
 }
-
-
-int hostapd_send_link_measurement_req(struct hostapd_data *hapd, const u8 *addr)
-{
-	struct wpabuf *buf;
-	struct sta_info *sta;
-	int ret;
-
-	wpa_printf(MSG_DEBUG, "Request Link Measurement: dest addr " MACSTR,
-		   MAC2STR(addr));
-
-	if (!(hapd->iface->drv_rrm_flags &
-	      WPA_DRIVER_FLAGS_TX_POWER_INSERTION)) {
-		wpa_printf(MSG_INFO,
-			   "Request Link Measurement: the driver does not support TX power insertion");
-		return -1;
-	}
-
-	sta = ap_get_sta(hapd, addr);
-	if (!sta || !(sta->flags & WLAN_STA_AUTHORIZED)) {
-		wpa_printf(MSG_INFO,
-			   "Request Link Measurement: specied STA is not connected");
-		return -1;
-	}
-
-	if (!(sta->rrm_enabled_capa[0] & WLAN_RRM_CAPS_LINK_MEASUREMENT)) {
-		wpa_printf(MSG_INFO,
-			   "Request Link Measurement: destination STA does not support link measurement");
-		return -1;
-	}
-
-	if (hapd->link_mesr_req_active) {
-		wpa_printf(MSG_DEBUG,
-			   "Request Link Measurement: request already in process - overriding");
-		hapd->link_mesr_req_active = 0;
-		eloop_cancel_timeout(hostapd_link_mesr_rep_timeout_handler,
-				     hapd, NULL);
-	}
-
-	/* Action + Action type + token + Tx Power used + Max Tx Power = 5 */
-	buf = wpabuf_alloc(5);
-	if (!buf)
-		return -1;
-
-	hapd->link_measurement_req_token++;
-	if (!hapd->link_measurement_req_token)
-		hapd->link_measurement_req_token++;
-
-	wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
-	wpabuf_put_u8(buf, WLAN_RRM_LINK_MEASUREMENT_REQUEST);
-	wpabuf_put_u8(buf, hapd->link_measurement_req_token);
-	/* NOTE: The driver is expected to fill the Tx Power Used and Max Tx
-	 * Power */
-	wpabuf_put_u8(buf, 0);
-	wpabuf_put_u8(buf, 0);
-
-	ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
-				      wpabuf_head(buf), wpabuf_len(buf));
-	wpabuf_free(buf);
-	if (ret < 0)
-		return ret;
-
-	hapd->link_mesr_req_active = 1;
-
-	eloop_register_timeout(HOSTAPD_RRM_REQUEST_TIMEOUT, 0,
-			       hostapd_link_mesr_rep_timeout_handler, hapd,
-			       NULL);
-
-	return hapd->link_measurement_req_token;
-}
diff --git a/src/ap/rrm.h b/src/ap/rrm.h
index 17751e0..02cd522 100644
--- a/src/ap/rrm.h
+++ b/src/ap/rrm.h
@@ -29,7 +29,5 @@
 void hostapd_rrm_beacon_req_tx_status(struct hostapd_data *hapd,
 				      const struct ieee80211_mgmt *mgmt,
 				      size_t len, int ok);
-int hostapd_send_link_measurement_req(struct hostapd_data *hapd,
-				      const u8 *addr);
 
 #endif /* RRM_H */
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index 32944ed..a00f896 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -92,7 +92,7 @@
 		if (p2p_dev_addr == NULL)
 			continue;
 
-		if (ether_addr_equal(p2p_dev_addr, addr))
+		if (os_memcmp(p2p_dev_addr, addr, ETH_ALEN) == 0)
 			return sta;
 	}
 
@@ -140,7 +140,7 @@
 	}
 
 	while (s->hnext != NULL &&
-	       !ether_addr_equal(s->hnext->addr, sta->addr))
+	       os_memcmp(s->hnext->addr, sta->addr, ETH_ALEN) != 0)
 		s = s->hnext;
 	if (s->hnext != NULL)
 		s->hnext = s->hnext->hnext;
@@ -180,26 +180,13 @@
 		sta->pasn->fils.erp_resp = NULL;
 #endif /* CONFIG_FILS */
 
-		pasn_data_deinit(sta->pasn);
+		bin_clear_free(sta->pasn, sizeof(*sta->pasn));
 		sta->pasn = NULL;
 	}
 }
 
 #endif /* CONFIG_PASN */
 
-
-static void __ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
-{
-#ifdef CONFIG_IEEE80211BE
-	if (hostapd_sta_is_link_sta(hapd, sta) &&
-	    !hostapd_drv_link_sta_remove(hapd, sta->addr))
-		return;
-#endif /* CONFIG_IEEE80211BE */
-
-	hostapd_drv_sta_remove(hapd, sta->addr);
-}
-
-
 void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
 {
 	int set_beacon = 0;
@@ -222,7 +209,7 @@
 
 	if (!hapd->iface->driver_ap_teardown &&
 	    !(sta->flags & WLAN_STA_PREAUTH)) {
-		__ap_free_sta(hapd, sta);
+		hostapd_drv_sta_remove(hapd, sta->addr);
 		sta->added_unassoc = 0;
 	}
 
@@ -316,7 +303,7 @@
 	ieee802_1x_free_station(hapd, sta);
 
 #ifdef CONFIG_IEEE80211BE
-	if (!ap_sta_is_mld(hapd, sta) ||
+	if (!hapd->conf->mld_ap || !sta->mld_info.mld_sta ||
 	    hapd->mld_link_id == sta->mld_assoc_link_id)
 		wpa_auth_sta_deinit(sta->wpa_sm);
 #else
@@ -363,7 +350,6 @@
 #ifdef CONFIG_INTERWORKING
 	if (sta->gas_dialog) {
 		int i;
-
 		for (i = 0; i < GAS_DIALOG_MAX; i++)
 			gas_serv_dialog_clear(&sta->gas_dialog[i]);
 		os_free(sta->gas_dialog);
@@ -434,10 +420,6 @@
 
 	os_free(sta->ifname_wds);
 
-#ifdef CONFIG_IEEE80211BE
-	ap_sta_free_sta_profile(&sta->mld_info);
-#endif /* CONFIG_IEEE80211BE */
-
 #ifdef CONFIG_TESTING_OPTIONS
 	os_free(sta->sae_postponed_commit);
 	forced_memzero(sta->last_tk, WPA_TK_MAX_LEN);
@@ -467,27 +449,6 @@
 }
 
 
-#ifdef CONFIG_IEEE80211BE
-void hostapd_free_link_stas(struct hostapd_data *hapd)
-{
-	struct sta_info *sta, *prev;
-
-	sta = hapd->sta_list;
-	while (sta) {
-		prev = sta;
-		sta = sta->next;
-
-		if (!hostapd_sta_is_link_sta(hapd, prev))
-			continue;
-
-		wpa_printf(MSG_DEBUG, "Removing link station from MLD " MACSTR,
-			   MAC2STR(prev->addr));
-		ap_free_sta(hapd, prev);
-	}
-}
-#endif /* CONFIG_IEEE80211BE */
-
-
 /**
  * ap_handle_timer - Per STA timer handler
  * @eloop_ctx: struct hostapd_data *
@@ -885,20 +846,32 @@
 }
 
 
-static void ap_sta_disconnect_common(struct hostapd_data *hapd,
-				     struct sta_info *sta, unsigned int timeout)
+void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta,
+			 u16 reason)
 {
+	wpa_printf(MSG_DEBUG, "%s: disassociate STA " MACSTR,
+		   hapd->conf->iface, MAC2STR(sta->addr));
 	sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
-
+	if (hapd->iface->current_mode &&
+	    hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211AD) {
+		/* Skip deauthentication in DMG/IEEE 802.11ad */
+		sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC |
+				WLAN_STA_ASSOC_REQ_OK);
+		sta->timeout_next = STA_REMOVE;
+	} else {
+		sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK);
+		sta->timeout_next = STA_DEAUTH;
+	}
 	ap_sta_set_authorized(hapd, sta, 0);
 	hostapd_set_sta_flags(hapd, sta);
-
-	wpa_printf(MSG_DEBUG,
-		   "reschedule ap_handle_timer timeout (%u sec) for " MACSTR,
-		   MAC2STR(sta->addr), timeout);
-
+	wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout "
+		   "for " MACSTR " (%d seconds - "
+		   "AP_MAX_INACTIVITY_AFTER_DISASSOC)",
+		   __func__, MAC2STR(sta->addr),
+		   AP_MAX_INACTIVITY_AFTER_DISASSOC);
 	eloop_cancel_timeout(ap_handle_timer, hapd, sta);
-	eloop_register_timeout(timeout, 0, ap_handle_timer, hapd, sta);
+	eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DISASSOC, 0,
+			       ap_handle_timer, hapd, sta);
 	accounting_sta_stop(hapd, sta);
 	ieee802_1x_free_station(hapd, sta);
 #ifdef CONFIG_IEEE80211BE
@@ -910,27 +883,6 @@
 #endif /* CONFIG_IEEE80211BE */
 
 	sta->wpa_sm = NULL;
-}
-
-
-static void ap_sta_handle_disassociate(struct hostapd_data *hapd,
-				       struct sta_info *sta, u16 reason)
-{
-	wpa_printf(MSG_DEBUG, "%s: disassociate STA " MACSTR,
-		   hapd->conf->iface, MAC2STR(sta->addr));
-
-	if (hapd->iface->current_mode &&
-	    hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211AD) {
-		/* Skip deauthentication in DMG/IEEE 802.11ad */
-		sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC |
-				WLAN_STA_ASSOC_REQ_OK);
-		sta->timeout_next = STA_REMOVE;
-	} else {
-		sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK);
-		sta->timeout_next = STA_DEAUTH;
-	}
-
-	ap_sta_disconnect_common(hapd, sta, AP_MAX_INACTIVITY_AFTER_DISASSOC);
 
 	sta->disassoc_reason = reason;
 	sta->flags |= WLAN_STA_PENDING_DISASSOC_CB;
@@ -953,8 +905,8 @@
 }
 
 
-static void ap_sta_handle_deauthenticate(struct hostapd_data *hapd,
-					 struct sta_info *sta, u16 reason)
+void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta,
+			   u16 reason)
 {
 	if (hapd->iface->current_mode &&
 	    hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211AD) {
@@ -966,11 +918,21 @@
 
 	wpa_printf(MSG_DEBUG, "%s: deauthenticate STA " MACSTR,
 		   hapd->conf->iface, MAC2STR(sta->addr));
-
+	sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
 	sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK);
-
+	ap_sta_set_authorized(hapd, sta, 0);
+	hostapd_set_sta_flags(hapd, sta);
 	sta->timeout_next = STA_REMOVE;
-	ap_sta_disconnect_common(hapd, sta, AP_MAX_INACTIVITY_AFTER_DEAUTH);
+	wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout "
+		   "for " MACSTR " (%d seconds - "
+		   "AP_MAX_INACTIVITY_AFTER_DEAUTH)",
+		   __func__, MAC2STR(sta->addr),
+		   AP_MAX_INACTIVITY_AFTER_DEAUTH);
+	eloop_cancel_timeout(ap_handle_timer, hapd, sta);
+	eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0,
+			       ap_handle_timer, hapd, sta);
+	accounting_sta_stop(hapd, sta);
+	ieee802_1x_free_station(hapd, sta);
 
 	sta->deauth_reason = reason;
 	sta->flags |= WLAN_STA_PENDING_DEAUTH_CB;
@@ -981,104 +943,6 @@
 }
 
 
-static bool ap_sta_ml_disconnect(struct hostapd_data *hapd,
-				 struct sta_info *sta, u16 reason,
-				 bool disassoc)
-{
-#ifdef CONFIG_IEEE80211BE
-	struct hostapd_data *assoc_hapd, *tmp_hapd;
-	struct sta_info *assoc_sta;
-	unsigned int i, link_id;
-	struct hapd_interfaces *interfaces;
-
-	if (!hostapd_is_mld_ap(hapd))
-		return false;
-
-	/*
-	 * Get the station on which the association was performed, as it holds
-	 * the information about all the other links.
-	 */
-	assoc_sta = hostapd_ml_get_assoc_sta(hapd, sta, &assoc_hapd);
-	if (!assoc_sta)
-		return false;
-	interfaces = assoc_hapd->iface->interfaces;
-
-	for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
-		if (!assoc_sta->mld_info.links[link_id].valid)
-			continue;
-
-		for (i = 0; i < interfaces->count; i++) {
-			struct sta_info *tmp_sta;
-
-			tmp_hapd = interfaces->iface[i]->bss[0];
-
-			if (!hostapd_is_ml_partner(tmp_hapd, assoc_hapd))
-				continue;
-
-			for (tmp_sta = tmp_hapd->sta_list; tmp_sta;
-			     tmp_sta = tmp_sta->next) {
-				/*
-				 * Handle the station on which the association
-				 * was done only after all other link station
-				 * are removed. Since there is a only a single
-				 * station per hapd with the same association
-				 * link simply break;
-				 */
-				if (tmp_sta == assoc_sta)
-					break;
-
-				if (tmp_sta->mld_assoc_link_id !=
-				    assoc_sta->mld_assoc_link_id ||
-				    tmp_sta->aid != assoc_sta->aid)
-					continue;
-
-				if (disassoc)
-					ap_sta_handle_disassociate(tmp_hapd,
-								   tmp_sta,
-								   reason);
-				else
-					ap_sta_handle_deauthenticate(tmp_hapd,
-								     tmp_sta,
-								     reason);
-
-				break;
-			}
-		}
-	}
-
-	/* Disconnect the station on which the association was performed. */
-	if (disassoc)
-		ap_sta_handle_disassociate(assoc_hapd, assoc_sta, reason);
-	else
-		ap_sta_handle_deauthenticate(assoc_hapd, assoc_sta, reason);
-
-	return true;
-#else /* CONFIG_IEEE80211BE */
-	return false;
-#endif /* CONFIG_IEEE80211BE */
-}
-
-
-void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta,
-			 u16 reason)
-{
-	if (ap_sta_ml_disconnect(hapd, sta, reason, true))
-		return;
-
-	ap_sta_handle_disassociate(hapd, sta, reason);
-}
-
-
-void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta,
-			   u16 reason)
-{
-	if (ap_sta_ml_disconnect(hapd, sta, reason, false))
-		return;
-
-	ap_sta_handle_deauthenticate(hapd, sta, reason);
-}
-
-
 #ifdef CONFIG_WPS
 int ap_sta_wps_cancel(struct hostapd_data *hapd,
 		      struct sta_info *sta, void *ctx)
@@ -1428,17 +1292,25 @@
 }
 
 
-bool ap_sta_set_authorized_flag(struct hostapd_data *hapd, struct sta_info *sta,
-				int authorized)
+void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta,
+			   int authorized)
 {
+	const u8 *dev_addr = NULL;
+	char buf[100];
+#ifdef CONFIG_P2P
+	u8 addr[ETH_ALEN];
+	u8 ip_addr_buf[4];
+#endif /* CONFIG_P2P */
+	u8 *ip_ptr = NULL;
+
 	if (!!authorized == !!(sta->flags & WLAN_STA_AUTHORIZED))
-		return false;
+		return;
 
 	if (authorized) {
 		int mld_assoc_link_id = -1;
 
 #ifdef CONFIG_IEEE80211BE
-		if (ap_sta_is_mld(hapd, sta)) {
+		if (hapd->conf->mld_ap && sta->mld_info.mld_sta) {
 			if (sta->mld_assoc_link_id == hapd->mld_link_id)
 				mld_assoc_link_id = sta->mld_assoc_link_id;
 			else
@@ -1453,21 +1325,6 @@
 		sta->flags &= ~WLAN_STA_AUTHORIZED;
 	}
 
-	return true;
-}
-
-
-void ap_sta_set_authorized_event(struct hostapd_data *hapd,
-				 struct sta_info *sta, int authorized)
-{
-	const u8 *dev_addr = NULL;
-	char buf[100];
-#ifdef CONFIG_P2P
-	u8 addr[ETH_ALEN];
-	u8 ip_addr_buf[4];
-#endif /* CONFIG_P2P */
-	const u8 *ip_ptr = NULL;
-
 #ifdef CONFIG_P2P
 	if (hapd->p2p_group == NULL) {
 		if (sta->p2p_ie != NULL &&
@@ -1556,15 +1413,6 @@
 }
 
 
-void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta,
-			   int authorized)
-{
-	if (!ap_sta_set_authorized_flag(hapd, sta, authorized))
-		return;
-	ap_sta_set_authorized_event(hapd, sta, authorized);
-}
-
-
 void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
 		       const u8 *addr, u16 reason)
 {
@@ -1756,34 +1604,6 @@
 }
 
 
-#ifdef CONFIG_IEEE80211BE
-static void ap_sta_remove_link_sta(struct hostapd_data *hapd,
-				   struct sta_info *sta)
-{
-	struct hostapd_data *tmp_hapd;
-	unsigned int i, j;
-
-	for_each_mld_link(tmp_hapd, i, j, hapd->iface->interfaces,
-			  hostapd_get_mld_id(hapd)) {
-		struct sta_info *tmp_sta;
-
-		if (hapd == tmp_hapd)
-			continue;
-
-		for (tmp_sta = tmp_hapd->sta_list; tmp_sta;
-		     tmp_sta = tmp_sta->next) {
-			if (tmp_sta == sta ||
-			    !ether_addr_equal(tmp_sta->addr, sta->addr))
-				continue;
-
-			ap_free_sta(tmp_hapd, tmp_sta);
-			break;
-		}
-	}
-}
-#endif /* CONFIG_IEEE80211BE */
-
-
 int ap_sta_re_add(struct hostapd_data *hapd, struct sta_info *sta)
 {
 	const u8 *mld_link_addr = NULL;
@@ -1798,17 +1618,11 @@
 	 */
 
 #ifdef CONFIG_IEEE80211BE
-	if (ap_sta_is_mld(hapd, sta)) {
+	if (hapd->conf->mld_ap && sta->mld_info.mld_sta) {
 		u8 mld_link_id = hapd->mld_link_id;
 
 		mld_link_sta = sta->mld_assoc_link_id != mld_link_id;
 		mld_link_addr = sta->mld_info.links[mld_link_id].peer_addr;
-
-		/*
-		 * In case the AP is affiliated with an AP MLD, we need to
-		 * remove the station from all relevant links/APs.
-		 */
-		ap_sta_remove_link_sta(hapd, sta);
 	}
 #endif /* CONFIG_IEEE80211BE */
 
@@ -1832,19 +1646,3 @@
 	sta->added_unassoc = 1;
 	return 0;
 }
-
-
-#ifdef CONFIG_IEEE80211BE
-void ap_sta_free_sta_profile(struct mld_info *info)
-{
-	int i;
-
-	if (!info)
-		return;
-
-	for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
-		os_free(info->links[i].resp_sta_profile);
-		info->links[i].resp_sta_profile = NULL;
-	}
-}
-#endif /* CONFIG_IEEE80211BE */
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index 153e4a0..e2b9dde 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -17,7 +17,6 @@
 #include "common/sae.h"
 #include "crypto/sha384.h"
 #include "pasn/pasn_common.h"
-#include "hostapd.h"
 
 /* STA flags */
 #define WLAN_STA_AUTH BIT(0)
@@ -82,18 +81,18 @@
 	} common_info;
 
 	struct mld_link_info {
-		u8 valid:1;
-		u8 nstr_bitmap_len:2;
+		u8 valid;
 		u8 local_addr[ETH_ALEN];
 		u8 peer_addr[ETH_ALEN];
 
+		size_t nstr_bitmap_len;
 		u8 nstr_bitmap[2];
 
 		u16 capability;
 
 		u16 status;
-		u16 resp_sta_profile_len;
-		u8 *resp_sta_profile;
+		size_t resp_sta_profile_len;
+		u8 resp_sta_profile[EHT_ML_MAX_STA_PROF_LEN];
 
 		const u8 *rsne, *rsnxe;
 	} links[MAX_NUM_MLD_LINKS];
@@ -394,10 +393,6 @@
 void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
 		       const u8 *addr, u16 reason);
 
-bool ap_sta_set_authorized_flag(struct hostapd_data *hapd, struct sta_info *sta,
-				int authorized);
-void ap_sta_set_authorized_event(struct hostapd_data *hapd,
-				 struct sta_info *sta, int authorized);
 void ap_sta_set_authorized(struct hostapd_data *hapd,
 			   struct sta_info *sta, int authorized);
 static inline int ap_sta_is_authorized(struct sta_info *sta)
@@ -420,26 +415,4 @@
 
 void ap_free_sta_pasn(struct hostapd_data *hapd, struct sta_info *sta);
 
-static inline bool ap_sta_is_mld(struct hostapd_data *hapd,
-				 struct sta_info *sta)
-{
-#ifdef CONFIG_IEEE80211BE
-	return hapd->conf->mld_ap && sta && sta->mld_info.mld_sta;
-#else /* CONFIG_IEEE80211BE */
-	return false;
-#endif /* CONFIG_IEEE80211BE */
-}
-
-static inline void ap_sta_set_mld(struct sta_info *sta, bool mld)
-{
-#ifdef CONFIG_IEEE80211BE
-	if (sta)
-		sta->mld_info.mld_sta = mld;
-#endif /* CONFIG_IEEE80211BE */
-}
-
-void ap_sta_free_sta_profile(struct mld_info *info);
-
-void hostapd_free_link_stas(struct hostapd_data *hapd);
-
 #endif /* STA_INFO_H */
diff --git a/src/ap/wmm.c b/src/ap/wmm.c
index dad768e..9ebb01e 100644
--- a/src/ap/wmm.c
+++ b/src/ap/wmm.c
@@ -20,6 +20,13 @@
 #include "ap_drv_ops.h"
 #include "wmm.h"
 
+#ifndef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+#ifndef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+
 
 static inline u8 wmm_aci_aifsn(int aifsn, int acm, int aci)
 {
diff --git a/src/ap/wnm_ap.c b/src/ap/wnm_ap.c
index af8ccca..153ee40 100644
--- a/src/ap/wnm_ap.c
+++ b/src/ap/wnm_ap.c
@@ -44,20 +44,6 @@
 }
 
 
-static const u8 * wnm_ap_get_own_addr(struct hostapd_data *hapd,
-				      struct sta_info *sta)
-{
-	const u8 *own_addr = hapd->own_addr;
-
-#ifdef CONFIG_IEEE80211BE
-	if (hapd->conf->mld_ap && (!sta || ap_sta_is_mld(hapd, sta)))
-		own_addr = hapd->mld->mld_addr;
-#endif /* CONFIG_IEEE80211BE */
-
-	return own_addr;
-}
-
-
 /* MLME-SLEEPMODE.response */
 static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
 					 const u8 *addr, u8 dialog_token,
@@ -77,7 +63,6 @@
 	struct sta_info *sta;
 	enum wnm_oper tfs_oper = action_type == WNM_SLEEP_MODE_ENTER ?
 		WNM_SLEEP_TFS_RESP_IE_ADD : WNM_SLEEP_TFS_RESP_IE_NONE;
-	const u8 *own_addr;
 
 	sta = ap_get_sta(hapd, addr);
 	if (sta == NULL) {
@@ -158,12 +143,9 @@
 		res = -1;
 		goto fail;
 	}
-
-	own_addr = wnm_ap_get_own_addr(hapd, sta);
-
 	os_memcpy(mgmt->da, addr, ETH_ALEN);
-	os_memcpy(mgmt->sa, own_addr, ETH_ALEN);
-	os_memcpy(mgmt->bssid, own_addr, ETH_ALEN);
+	os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
+	os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
 	mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
 					   WLAN_FC_STYPE_ACTION);
 	mgmt->u.action.category = WLAN_ACTION_WNM;
@@ -384,8 +366,6 @@
 						  u8 dialog_token)
 {
 	struct ieee80211_mgmt *mgmt;
-	const u8 *own_addr;
-	struct sta_info *sta;
 	size_t len;
 	u8 *pos;
 	int res;
@@ -393,13 +373,9 @@
 	mgmt = os_zalloc(sizeof(*mgmt));
 	if (mgmt == NULL)
 		return -1;
-
-	sta = ap_get_sta(hapd, addr);
-	own_addr = wnm_ap_get_own_addr(hapd, sta);
-
 	os_memcpy(mgmt->da, addr, ETH_ALEN);
-	os_memcpy(mgmt->sa, own_addr, ETH_ALEN);
-	os_memcpy(mgmt->bssid, own_addr, ETH_ALEN);
+	os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
+	os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
 	mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
 					   WLAN_FC_STYPE_ACTION);
 	mgmt->u.action.category = WLAN_ACTION_WNM;
@@ -845,15 +821,14 @@
 {
 	u8 buf[1000], *pos;
 	struct ieee80211_mgmt *mgmt;
-	const u8 *own_addr = wnm_ap_get_own_addr(hapd, sta);
 
 	os_memset(buf, 0, sizeof(buf));
 	mgmt = (struct ieee80211_mgmt *) buf;
 	mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
 					   WLAN_FC_STYPE_ACTION);
 	os_memcpy(mgmt->da, sta->addr, ETH_ALEN);
-	os_memcpy(mgmt->sa, own_addr, ETH_ALEN);
-	os_memcpy(mgmt->bssid, own_addr, ETH_ALEN);
+	os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
+	os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
 	mgmt->u.action.category = WLAN_ACTION_WNM;
 	mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ;
 	mgmt->u.action.u.bss_tm_req.dialog_token = 1;
@@ -912,15 +887,14 @@
 	u8 buf[1000], *pos;
 	struct ieee80211_mgmt *mgmt;
 	size_t url_len;
-	const u8 *own_addr = wnm_ap_get_own_addr(hapd, sta);
 
 	os_memset(buf, 0, sizeof(buf));
 	mgmt = (struct ieee80211_mgmt *) buf;
 	mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
 					   WLAN_FC_STYPE_ACTION);
 	os_memcpy(mgmt->da, sta->addr, ETH_ALEN);
-	os_memcpy(mgmt->sa, own_addr, ETH_ALEN);
-	os_memcpy(mgmt->bssid, own_addr, ETH_ALEN);
+	os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
+	os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
 	mgmt->u.action.category = WLAN_ACTION_WNM;
 	mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ;
 	mgmt->u.action.u.bss_tm_req.dialog_token = 1;
@@ -965,7 +939,6 @@
 	u8 *buf, *pos;
 	struct ieee80211_mgmt *mgmt;
 	size_t url_len;
-	const u8 *own_addr = wnm_ap_get_own_addr(hapd, sta);
 
 	wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Request to "
 		   MACSTR
@@ -979,8 +952,8 @@
 	mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
 					   WLAN_FC_STYPE_ACTION);
 	os_memcpy(mgmt->da, sta->addr, ETH_ALEN);
-	os_memcpy(mgmt->sa, own_addr, ETH_ALEN);
-	os_memcpy(mgmt->bssid, own_addr, ETH_ALEN);
+	os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
+	os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
 	mgmt->u.action.category = WLAN_ACTION_WNM;
 	mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ;
 	mgmt->u.action.u.bss_tm_req.dialog_token = dialog_token;
@@ -1029,26 +1002,6 @@
 	os_free(buf);
 
 	if (disassoc_timer) {
-#ifdef CONFIG_IEEE80211BE
-		if (ap_sta_is_mld(hapd, sta)) {
-			int i;
-			unsigned int links = 0;
-
-			for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
-				if (sta->mld_info.links[i].valid)
-					links++;
-			}
-
-			if (links > 1) {
-				wpa_printf(MSG_DEBUG,
-					   "WNM: Only terminating one link - other links remains associated for "
-					   MACSTR,
-					   MAC2STR(sta->mld_info.common_info.mld_addr));
-				return 0;
-			}
-		}
-#endif /* CONFIG_IEEE80211BE */
-
 		/* send disassociation frame after time-out */
 		set_disassoc_timer(hapd, sta, disassoc_timer);
 	}
@@ -1063,7 +1016,6 @@
 	u8 buf[100], *pos;
 	struct ieee80211_mgmt *mgmt;
 	u8 dialog_token = 1;
-	const u8 *own_addr = wnm_ap_get_own_addr(hapd, sta);
 
 	if (auto_report > 3 || timeout > 63)
 		return -1;
@@ -1072,8 +1024,8 @@
 	mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
 					   WLAN_FC_STYPE_ACTION);
 	os_memcpy(mgmt->da, sta->addr, ETH_ALEN);
-	os_memcpy(mgmt->sa, own_addr, ETH_ALEN);
-	os_memcpy(mgmt->bssid, own_addr, ETH_ALEN);
+	os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
+	os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
 	mgmt->u.action.category = WLAN_ACTION_WNM;
 	mgmt->u.action.u.coloc_intf_req.action =
 		WNM_COLLOCATED_INTERFERENCE_REQ;
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index 4bf8d79..a662201 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -194,9 +194,6 @@
 
 	if (!wpa_auth->cb->get_seqnum)
 		return -1;
-#ifdef CONFIG_TESTING_OPTIONS
-	os_memset(seq, 0, WPA_KEY_RSC_LEN);
-#endif /* CONFIG_TESTING_OPTIONS */
 	res = wpa_auth->cb->get_seqnum(wpa_auth->cb_ctx, addr, idx, seq);
 #ifdef CONFIG_TESTING_OPTIONS
 	if (!addr && idx < 4 && wpa_auth->conf.gtk_rsc_override_set) {
@@ -602,15 +599,6 @@
 	}
 #endif /* CONFIG_P2P */
 
-	if (conf->tx_bss_auth && conf->beacon_prot) {
-		conf->tx_bss_auth->non_tx_beacon_prot = true;
-		if (!conf->tx_bss_auth->conf.beacon_prot)
-			conf->tx_bss_auth->conf.beacon_prot = true;
-		if (!conf->tx_bss_auth->conf.group_mgmt_cipher)
-			conf->tx_bss_auth->conf.group_mgmt_cipher =
-				conf->group_mgmt_cipher;
-	}
-
 	return wpa_auth;
 }
 
@@ -630,17 +618,6 @@
 }
 
 
-static void wpa_auth_free_conf(struct wpa_auth_config *conf)
-{
-#ifdef CONFIG_TESTING_OPTIONS
-	wpabuf_free(conf->eapol_m1_elements);
-	conf->eapol_m1_elements = NULL;
-	wpabuf_free(conf->eapol_m3_elements);
-	conf->eapol_m3_elements = NULL;
-#endif /* CONFIG_TESTING_OPTIONS */
-}
-
-
 /**
  * wpa_deinit - Deinitialize WPA authenticator
  * @wpa_auth: Pointer to WPA authenticator data from wpa_init()
@@ -674,7 +651,6 @@
 		bin_clear_free(prev, sizeof(*prev));
 	}
 
-	wpa_auth_free_conf(&wpa_auth->conf);
 	os_free(wpa_auth);
 }
 
@@ -692,7 +668,6 @@
 	if (!wpa_auth)
 		return 0;
 
-	wpa_auth_free_conf(&wpa_auth->conf);
 	os_memcpy(&wpa_auth->conf, conf, sizeof(*conf));
 	if (wpa_auth_gen_wpa_ie(wpa_auth)) {
 		wpa_printf(MSG_ERROR, "Could not generate WPA IE.");
@@ -925,70 +900,19 @@
 			       struct wpa_state_machine *sm,
 			       struct wpa_eapol_ie_parse *kde)
 {
-	struct wpa_ie_data ie, assoc_ie;
+	struct wpa_ie_data ie;
 	struct rsn_mdie *mdie;
-	unsigned int i, j;
-	bool found = false;
-
-	/* Verify that PMKR1Name from EAPOL-Key message 2/4 matches the value
-	 * we derived. */
 
 	if (wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0 ||
-	    ie.num_pmkid < 1 || !ie.pmkid) {
+	    ie.num_pmkid != 1 || !ie.pmkid) {
 		wpa_printf(MSG_DEBUG,
 			   "FT: No PMKR1Name in FT 4-way handshake message 2/4");
 		return -1;
 	}
 
-	if (wpa_parse_wpa_ie_rsn(sm->wpa_ie, sm->wpa_ie_len, &assoc_ie) < 0) {
-		wpa_printf(MSG_DEBUG,
-			   "FT: Could not parse (Re)Association Request frame RSNE");
-		os_memset(&assoc_ie, 0, sizeof(assoc_ie));
-		/* Continue to allow PMKR1Name matching to be done to cover the
-		 * case where it is the only listed PMKID. */
-	}
-
-	for (i = 0; i < ie.num_pmkid; i++) {
-		const u8 *pmkid = ie.pmkid + i * PMKID_LEN;
-
-		if (os_memcmp_const(pmkid, sm->pmk_r1_name,
-				    WPA_PMK_NAME_LEN) == 0) {
-			wpa_printf(MSG_DEBUG,
-				   "FT: RSNE[PMKID[%u]] from supplicant matches PMKR1Name",
-				   i);
-			found = true;
-		} else {
-			for (j = 0; j < assoc_ie.num_pmkid; j++) {
-				if (os_memcmp(pmkid,
-					      assoc_ie.pmkid + j * PMKID_LEN,
-					      PMKID_LEN) == 0)
-					break;
-			}
-
-			if (j == assoc_ie.num_pmkid) {
-				wpa_printf(MSG_DEBUG,
-					   "FT: RSNE[PMKID[%u]] from supplicant is neither PMKR1Name nor included in AssocReq",
-					   i);
-				found = false;
-				break;
-			}
-			wpa_printf(MSG_DEBUG,
-				   "FT: RSNE[PMKID[%u]] from supplicant is not PMKR1Name, but matches a PMKID in AssocReq",
-				   i);
-		}
-	}
-
-	if (!found) {
-		wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm),
-				LOGGER_DEBUG,
-				"PMKR1Name mismatch in FT 4-way handshake");
-		wpa_hexdump(MSG_DEBUG,
-			    "FT: PMKIDs/PMKR1Name from Supplicant",
-			    ie.pmkid, ie.num_pmkid * PMKID_LEN);
-		wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name",
-			    sm->pmk_r1_name, WPA_PMK_NAME_LEN);
-		return -1;
-	}
+	os_memcpy(sm->sup_pmk_r1_name, ie.pmkid, PMKID_LEN);
+	wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from Supplicant",
+		    sm->sup_pmk_r1_name, PMKID_LEN);
 
 	if (!kde->mdie || !kde->ftie) {
 		wpa_printf(MSG_DEBUG,
@@ -1152,166 +1076,28 @@
 }
 
 
-enum eapol_key_msg { PAIRWISE_2, PAIRWISE_4, GROUP_2, REQUEST };
-
-static bool wpa_auth_valid_key_desc_ver(struct wpa_authenticator *wpa_auth,
-					struct wpa_state_machine *sm, u16 ver)
-{
-	if (ver > WPA_KEY_INFO_TYPE_AES_128_CMAC) {
-		wpa_printf(MSG_INFO, "RSN: " MACSTR
-			   " used undefined Key Descriptor Version %d",
-			   MAC2STR(wpa_auth_get_spa(sm)), ver);
-		return false;
-	}
-
-	if (!wpa_use_akm_defined(sm->wpa_key_mgmt) &&
-	    wpa_use_cmac(sm->wpa_key_mgmt) &&
-	    ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
-		wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
-				LOGGER_WARNING,
-				"advertised support for AES-128-CMAC, but did not use it");
-		return false;
-	}
-
-	if (sm->pairwise != WPA_CIPHER_TKIP &&
-	    !wpa_use_akm_defined(sm->wpa_key_mgmt) &&
-	    !wpa_use_cmac(sm->wpa_key_mgmt) &&
-	    ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
-		wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
-				LOGGER_WARNING,
-				"did not use HMAC-SHA1-AES with CCMP/GCMP");
-		return false;
-	}
-
-	if (wpa_use_akm_defined(sm->wpa_key_mgmt) &&
-	    ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) {
-		wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
-				LOGGER_WARNING,
-				"did not use EAPOL-Key descriptor version 0 as required for AKM-defined cases");
-		return false;
-	}
-
-	return true;
-}
-
-
-static bool wpa_auth_valid_request_counter(struct wpa_authenticator *wpa_auth,
-					   struct wpa_state_machine *sm,
-					   const u8 *replay_counter)
-{
-
-	if (sm->req_replay_counter_used &&
-	    os_memcmp(replay_counter, sm->req_replay_counter,
-		      WPA_REPLAY_COUNTER_LEN) <= 0) {
-		wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
-				LOGGER_WARNING,
-				"received EAPOL-Key request with replayed counter");
-		return false;
-	}
-
-	return true;
-}
-
-
-static bool wpa_auth_valid_counter(struct wpa_authenticator *wpa_auth,
-				   struct wpa_state_machine *sm,
-				   const struct wpa_eapol_key *key,
-				   enum eapol_key_msg msg,
-				   const char *msgtxt)
-{
-	int i;
-
-	if (msg == REQUEST)
-		return wpa_auth_valid_request_counter(wpa_auth, sm,
-						      key->replay_counter);
-
-	if (wpa_replay_counter_valid(sm->key_replay, key->replay_counter))
-		return true;
-
-	if (msg == PAIRWISE_2 &&
-	    wpa_replay_counter_valid(sm->prev_key_replay,
-				     key->replay_counter) &&
-	    sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING &&
-	    os_memcmp(sm->SNonce, key->key_nonce, WPA_NONCE_LEN) != 0) {
-		/*
-		 * Some supplicant implementations (e.g., Windows XP
-		 * WZC) update SNonce for each EAPOL-Key 2/4. This
-		 * breaks the workaround on accepting any of the
-		 * pending requests, so allow the SNonce to be updated
-		 * even if we have already sent out EAPOL-Key 3/4.
-		 */
-		wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
-				 LOGGER_DEBUG,
-				 "Process SNonce update from STA based on retransmitted EAPOL-Key 1/4");
-		sm->update_snonce = 1;
-		os_memcpy(sm->alt_SNonce, sm->SNonce, WPA_NONCE_LEN);
-		sm->alt_snonce_valid = true;
-		os_memcpy(sm->alt_replay_counter,
-			  sm->key_replay[0].counter,
-			  WPA_REPLAY_COUNTER_LEN);
-		return true;
-	}
-
-	if (msg == PAIRWISE_4 && sm->alt_snonce_valid &&
-	    sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING &&
-	    os_memcmp(key->replay_counter, sm->alt_replay_counter,
-		      WPA_REPLAY_COUNTER_LEN) == 0) {
-		/*
-		 * Supplicant may still be using the old SNonce since
-		 * there was two EAPOL-Key 2/4 messages and they had
-		 * different SNonce values.
-		 */
-		wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
-				 LOGGER_DEBUG,
-				 "Try to process received EAPOL-Key 4/4 based on old Replay Counter and SNonce from an earlier EAPOL-Key 1/4");
-		return true;
-	}
-
-	if (msg == PAIRWISE_2 &&
-	    wpa_replay_counter_valid(sm->prev_key_replay,
-				     key->replay_counter) &&
-	    sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING) {
-		wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
-				 LOGGER_DEBUG,
-				 "ignore retransmitted EAPOL-Key %s - SNonce did not change",
-				 msgtxt);
-	} else {
-		wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
-				 LOGGER_DEBUG,
-				 "received EAPOL-Key %s with unexpected replay counter",
-				 msgtxt);
-	}
-	for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) {
-		if (!sm->key_replay[i].valid)
-			break;
-		wpa_hexdump(MSG_DEBUG, "pending replay counter",
-			    sm->key_replay[i].counter,
-			    WPA_REPLAY_COUNTER_LEN);
-	}
-	wpa_hexdump(MSG_DEBUG, "received replay counter",
-		    key->replay_counter, WPA_REPLAY_COUNTER_LEN);
-	return false;
-}
-
-
 void wpa_receive(struct wpa_authenticator *wpa_auth,
 		 struct wpa_state_machine *sm,
 		 u8 *data, size_t data_len)
 {
 	struct ieee802_1x_hdr *hdr;
 	struct wpa_eapol_key *key;
-	u16 key_info, ver, key_data_length;
-	enum eapol_key_msg msg;
-	const char *msgtxt;
+	u16 key_info, key_data_length;
+	enum { PAIRWISE_2, PAIRWISE_4, GROUP_2, REQUEST } msg;
+	char *msgtxt;
+	struct wpa_eapol_ie_parse kde;
 	const u8 *key_data;
 	size_t keyhdrlen, mic_len;
 	u8 *mic;
-	u8 *key_data_buf = NULL;
-	size_t key_data_buf_len = 0;
+	bool is_mld = false;
 
 	if (!wpa_auth || !wpa_auth->conf.wpa || !sm)
 		return;
 
+#ifdef CONFIG_IEEE80211BE
+	is_mld = sm->mld_assoc_link_id >= 0;
+#endif /* CONFIG_IEEE80211BE */
+
 	wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL data", data, data_len);
 
 	mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
@@ -1381,31 +1167,11 @@
 		return;
 	}
 
-	ver = key_info & WPA_KEY_INFO_TYPE_MASK;
-	if (!wpa_auth_valid_key_desc_ver(wpa_auth, sm, ver))
-		goto out;
-	if (mic_len > 0 && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA) &&
-	    sm->PTK_valid &&
-	    (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
-	     ver == WPA_KEY_INFO_TYPE_AES_128_CMAC ||
-	     wpa_use_aes_key_wrap(sm->wpa_key_mgmt)) &&
-	    key_data_length >= 8 && key_data_length % 8 == 0) {
-		key_data_length -= 8; /* AES-WRAP adds 8 bytes */
-		key_data_buf = os_malloc(key_data_length);
-		if (!key_data_buf)
-			goto out;
-		key_data_buf_len = key_data_length;
-		if (aes_unwrap(sm->PTK.kek, sm->PTK.kek_len,
-			       key_data_length / 8, key_data, key_data_buf)) {
-			wpa_printf(MSG_INFO,
-				   "RSN: AES unwrap failed - could not decrypt EAPOL-Key key data");
-			goto out;
-		}
-		key_data = key_data_buf;
-		wpa_hexdump_key(MSG_DEBUG, "RSN: Decrypted EAPOL-Key Key Data",
-				key_data, key_data_length);
-	}
-
+	/* TODO: Make this more robust for distinguising EAPOL-Key msg 2/4 from
+	 * 4/4. Secure=1 is used in msg 2/4 when doing PTK rekeying, so the
+	 * MLD mechanism here does not work without the somewhat undesired check
+	 * on wpa_ptk_state.. Would likely need to decrypt Key Data first to be
+	 * able to know which message this is in MLO cases.. */
 	if (key_info & WPA_KEY_INFO_REQUEST) {
 		msg = REQUEST;
 		msgtxt = "Request";
@@ -1413,13 +1179,10 @@
 		msg = GROUP_2;
 		msgtxt = "2/2 Group";
 	} else if (key_data_length == 0 ||
-		   (sm->wpa == WPA_VERSION_WPA2 &&
-		    (!(key_info & WPA_KEY_INFO_ENCR_KEY_DATA) ||
-		     key_data_buf) &&
-		    (key_info & WPA_KEY_INFO_SECURE) &&
-		    !get_ie(key_data, key_data_length, WLAN_EID_RSN)) ||
 		   (mic_len == 0 && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA) &&
-		    key_data_length == AES_BLOCK_SIZE)) {
+		    key_data_length == AES_BLOCK_SIZE) ||
+		   (is_mld && (key_info & WPA_KEY_INFO_SECURE) &&
+		    sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING)) {
 		msg = PAIRWISE_4;
 		msgtxt = "4/4 Pairwise";
 	} else {
@@ -1427,15 +1190,127 @@
 		msgtxt = "2/4 Pairwise";
 	}
 
-	if (!wpa_auth_valid_counter(wpa_auth, sm, key, msg, msgtxt))
-		goto out;
+	if (msg == REQUEST || msg == PAIRWISE_2 || msg == PAIRWISE_4 ||
+	    msg == GROUP_2) {
+		u16 ver = key_info & WPA_KEY_INFO_TYPE_MASK;
+		if (sm->pairwise == WPA_CIPHER_CCMP ||
+		    sm->pairwise == WPA_CIPHER_GCMP) {
+			if (wpa_use_cmac(sm->wpa_key_mgmt) &&
+			    !wpa_use_akm_defined(sm->wpa_key_mgmt) &&
+			    ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
+				wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
+						LOGGER_WARNING,
+						"advertised support for AES-128-CMAC, but did not use it");
+				return;
+			}
 
+			if (!wpa_use_cmac(sm->wpa_key_mgmt) &&
+			    !wpa_use_akm_defined(sm->wpa_key_mgmt) &&
+			    ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
+				wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
+						LOGGER_WARNING,
+						"did not use HMAC-SHA1-AES with CCMP/GCMP");
+				return;
+			}
+		}
+
+		if (wpa_use_akm_defined(sm->wpa_key_mgmt) &&
+		    ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) {
+			wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
+					LOGGER_WARNING,
+					"did not use EAPOL-Key descriptor version 0 as required for AKM-defined cases");
+			return;
+		}
+	}
+
+	if (key_info & WPA_KEY_INFO_REQUEST) {
+		if (sm->req_replay_counter_used &&
+		    os_memcmp(key->replay_counter, sm->req_replay_counter,
+			      WPA_REPLAY_COUNTER_LEN) <= 0) {
+			wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
+					LOGGER_WARNING,
+					"received EAPOL-Key request with replayed counter");
+			return;
+		}
+	}
+
+	if (!(key_info & WPA_KEY_INFO_REQUEST) &&
+	    !wpa_replay_counter_valid(sm->key_replay, key->replay_counter)) {
+		int i;
+
+		if (msg == PAIRWISE_2 &&
+		    wpa_replay_counter_valid(sm->prev_key_replay,
+					     key->replay_counter) &&
+		    sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING &&
+		    os_memcmp(sm->SNonce, key->key_nonce, WPA_NONCE_LEN) != 0)
+		{
+			/*
+			 * Some supplicant implementations (e.g., Windows XP
+			 * WZC) update SNonce for each EAPOL-Key 2/4. This
+			 * breaks the workaround on accepting any of the
+			 * pending requests, so allow the SNonce to be updated
+			 * even if we have already sent out EAPOL-Key 3/4.
+			 */
+			wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
+					 LOGGER_DEBUG,
+					 "Process SNonce update from STA based on retransmitted EAPOL-Key 1/4");
+			sm->update_snonce = 1;
+			os_memcpy(sm->alt_SNonce, sm->SNonce, WPA_NONCE_LEN);
+			sm->alt_snonce_valid = true;
+			os_memcpy(sm->alt_replay_counter,
+				  sm->key_replay[0].counter,
+				  WPA_REPLAY_COUNTER_LEN);
+			goto continue_processing;
+		}
+
+		if (msg == PAIRWISE_4 && sm->alt_snonce_valid &&
+		    sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING &&
+		    os_memcmp(key->replay_counter, sm->alt_replay_counter,
+			      WPA_REPLAY_COUNTER_LEN) == 0) {
+			/*
+			 * Supplicant may still be using the old SNonce since
+			 * there was two EAPOL-Key 2/4 messages and they had
+			 * different SNonce values.
+			 */
+			wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
+					 LOGGER_DEBUG,
+					 "Try to process received EAPOL-Key 4/4 based on old Replay Counter and SNonce from an earlier EAPOL-Key 1/4");
+			goto continue_processing;
+		}
+
+		if (msg == PAIRWISE_2 &&
+		    wpa_replay_counter_valid(sm->prev_key_replay,
+					     key->replay_counter) &&
+		    sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING) {
+			wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
+					 LOGGER_DEBUG,
+					 "ignore retransmitted EAPOL-Key %s - SNonce did not change",
+					 msgtxt);
+		} else {
+			wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
+					 LOGGER_DEBUG,
+					 "received EAPOL-Key %s with unexpected replay counter",
+					 msgtxt);
+		}
+		for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) {
+			if (!sm->key_replay[i].valid)
+				break;
+			wpa_hexdump(MSG_DEBUG, "pending replay counter",
+				    sm->key_replay[i].counter,
+				    WPA_REPLAY_COUNTER_LEN);
+		}
+		wpa_hexdump(MSG_DEBUG, "received replay counter",
+			    key->replay_counter, WPA_REPLAY_COUNTER_LEN);
+		return;
+	}
+
+continue_processing:
 #ifdef CONFIG_FILS
 	if (sm->wpa == WPA_VERSION_WPA2 && mic_len == 0 &&
 	    !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
 		wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
 				 "WPA: Encr Key Data bit not set even though AEAD cipher is supposed to be used - drop frame");
-		goto out;
+		return;
 	}
 #endif /* CONFIG_FILS */
 
@@ -1449,7 +1324,7 @@
 					 LOGGER_INFO,
 					 "received EAPOL-Key msg 2/4 in invalid state (%d) - dropped",
 					 sm->wpa_ptk_state);
-			goto out;
+			return;
 		}
 		random_add_randomness(key->key_nonce, WPA_NONCE_LEN);
 		if (sm->group->reject_4way_hs_for_entropy) {
@@ -1467,7 +1342,7 @@
 			random_mark_pool_ready();
 			wpa_sta_disconnect(wpa_auth, sm->addr,
 					   WLAN_REASON_PREV_AUTH_NOT_VALID);
-			goto out;
+			return;
 		}
 		break;
 	case PAIRWISE_4:
@@ -1477,7 +1352,7 @@
 					 LOGGER_INFO,
 					 "received EAPOL-Key msg 4/4 in invalid state (%d) - dropped",
 					 sm->wpa_ptk_state);
-			goto out;
+			return;
 		}
 		break;
 	case GROUP_2:
@@ -1487,20 +1362,10 @@
 					 LOGGER_INFO,
 					 "received EAPOL-Key msg 2/2 in invalid state (%d) - dropped",
 					 sm->wpa_ptk_group_state);
-			goto out;
+			return;
 		}
 		break;
 	case REQUEST:
-		if (sm->wpa_ptk_state == WPA_PTK_PTKSTART ||
-		    sm->wpa_ptk_state == WPA_PTK_PTKCALCNEGOTIATING ||
-		    sm->wpa_ptk_state == WPA_PTK_PTKCALCNEGOTIATING2 ||
-		    sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING) {
-			wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
-					 LOGGER_INFO,
-					 "received EAPOL-Key Request in invalid state (%d) - dropped",
-					 sm->wpa_ptk_state);
-			goto out;
-		}
 		break;
 	}
 
@@ -1510,14 +1375,14 @@
 	if (key_info & WPA_KEY_INFO_ACK) {
 		wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
 				"received invalid EAPOL-Key: Key Ack set");
-		goto out;
+		return;
 	}
 
 	if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt) &&
 	    !(key_info & WPA_KEY_INFO_MIC)) {
 		wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
 				"received invalid EAPOL-Key: Key MIC not set");
-		goto out;
+		return;
 	}
 
 #ifdef CONFIG_FILS
@@ -1525,7 +1390,7 @@
 	    (key_info & WPA_KEY_INFO_MIC)) {
 		wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
 				"received invalid EAPOL-Key: Key MIC set");
-		goto out;
+		return;
 	}
 #endif /* CONFIG_FILS */
 
@@ -1544,7 +1409,7 @@
 				   "TEST: Ignore Key MIC failure for fuzz testing");
 			goto continue_fuzz;
 #endif /* TEST_FUZZ */
-			goto out;
+			return;
 		}
 #ifdef CONFIG_FILS
 		if (!mic_len &&
@@ -1558,7 +1423,7 @@
 				   "TEST: Ignore Key MIC failure for fuzz testing");
 			goto continue_fuzz;
 #endif /* TEST_FUZZ */
-			goto out;
+			return;
 		}
 #endif /* CONFIG_FILS */
 #ifdef TEST_FUZZ
@@ -1570,12 +1435,6 @@
 	}
 
 	if (key_info & WPA_KEY_INFO_REQUEST) {
-		if (!(key_info & WPA_KEY_INFO_SECURE)) {
-			wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
-					LOGGER_INFO,
-					"received EAPOL-Key request without Secure=1");
-			goto out;
-		}
 		if (sm->MICVerified) {
 			sm->req_replay_counter_used = 1;
 			os_memcpy(sm->req_replay_counter, key->replay_counter,
@@ -1584,19 +1443,28 @@
 			wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
 					LOGGER_INFO,
 					"received EAPOL-Key request with invalid MIC");
-			goto out;
+			return;
 		}
 
+		/*
+		 * TODO: should decrypt key data field if encryption was used;
+		 * even though MAC address KDE is not normally encrypted,
+		 * supplicant is allowed to encrypt it.
+		 */
 		if (key_info & WPA_KEY_INFO_ERROR) {
 			if (wpa_receive_error_report(
 				    wpa_auth, sm,
 				    !(key_info & WPA_KEY_INFO_KEY_TYPE)) > 0)
-				goto out; /* STA entry was removed */
+				return; /* STA entry was removed */
 		} else if (key_info & WPA_KEY_INFO_KEY_TYPE) {
 			wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
 					LOGGER_INFO,
 					"received EAPOL-Key Request for new 4-Way Handshake");
 			wpa_request_new_ptk(sm);
+		} else if (key_data_length > 0 &&
+			   wpa_parse_kde_ies(key_data, key_data_length,
+					     &kde) == 0 &&
+			   kde.mac_addr) {
 		} else {
 			wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
 					LOGGER_INFO,
@@ -1638,7 +1506,7 @@
 	os_free(sm->last_rx_eapol_key);
 	sm->last_rx_eapol_key = os_memdup(data, data_len);
 	if (!sm->last_rx_eapol_key)
-		goto out;
+		return;
 	sm->last_rx_eapol_key_len = data_len;
 
 	sm->rx_eapol_key_secure = !!(key_info & WPA_KEY_INFO_SECURE);
@@ -1647,9 +1515,6 @@
 	sm->EAPOLKeyRequest = !!(key_info & WPA_KEY_INFO_REQUEST);
 	os_memcpy(sm->SNonce, key->key_nonce, WPA_NONCE_LEN);
 	wpa_sm_step(sm);
-
-out:
-	bin_clear_free(key_data_buf, key_data_buf_len);
 }
 
 
@@ -2467,14 +2332,10 @@
 
 SM_STATE(WPA_PTK, PTKSTART)
 {
-	u8 *buf;
-	size_t buf_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN;
+	u8 buf[2 * (2 + RSN_SELECTOR_LEN) + PMKID_LEN + ETH_ALEN];
 	u8 *pmkid = NULL;
 	size_t kde_len = 0;
 	u16 key_info;
-#ifdef CONFIG_TESTING_OPTIONS
-	struct wpa_auth_config *conf = &sm->wpa_auth->conf;
-#endif /* CONFIG_TESTING_OPTIONS */
 
 	SM_ENTRY_MA(WPA_PTK, PTKSTART, wpa_ptk);
 	sm->PTKRequest = false;
@@ -2489,19 +2350,6 @@
 		return;
 	}
 
-#ifdef CONFIG_IEEE80211BE
-	if (sm->mld_assoc_link_id >= 0)
-		buf_len += 2 + RSN_SELECTOR_LEN + ETH_ALEN;
-#endif /* CONFIG_IEEE80211BE */
-#ifdef CONFIG_TESTING_OPTIONS
-	if (conf->eapol_m1_elements)
-		buf_len += wpabuf_len(conf->eapol_m1_elements);
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	buf = os_zalloc(buf_len);
-	if (!buf)
-		return;
-
 	wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
 			"sending 1/4 msg of 4-Way Handshake");
 	/*
@@ -2605,20 +2453,11 @@
 	}
 #endif /* CONFIG_IEEE80211BE */
 
-#ifdef CONFIG_TESTING_OPTIONS
-	if (conf->eapol_m1_elements) {
-		os_memcpy(buf + kde_len, wpabuf_head(conf->eapol_m1_elements),
-			  wpabuf_len(conf->eapol_m1_elements));
-		kde_len += wpabuf_len(conf->eapol_m1_elements);
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
 	key_info = WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE;
 	if (sm->pairwise_set && sm->wpa != WPA_VERSION_WPA)
 		key_info |= WPA_KEY_INFO_SECURE;
 	wpa_send_eapol(sm->wpa_auth, sm, key_info, NULL,
 		       sm->ANonce, kde_len ? buf : NULL, kde_len, 0, 0);
-	os_free(buf);
 }
 
 
@@ -3339,13 +3178,16 @@
 
 	/* MLD MAC address must be the same */
 	if (!kde->mac_addr ||
-	    !ether_addr_equal(kde->mac_addr, sm->peer_mld_addr)) {
+	    os_memcmp(kde->mac_addr, sm->peer_mld_addr, ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG, "RSN: MLD: Invalid MLD address");
 		return -1;
 	}
 
 	/* Find matching link ID and the MAC address for each link */
-	for_each_link(kde->valid_mlo_links, i) {
+	for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+		if (!(kde->valid_mlo_links & BIT(i)))
+			continue;
+
 		/*
 		 * Each entry should contain the link information and the MAC
 		 * address.
@@ -3363,8 +3205,8 @@
 			return -1;
 		}
 
-		if (!ether_addr_equal(sm->mld_links[i].peer_addr,
-				      kde->mlo_link[i] + 1)) {
+		if (os_memcmp(sm->mld_links[i].peer_addr, kde->mlo_link[i] + 1,
+			      ETH_ALEN) != 0) {
 			wpa_printf(MSG_DEBUG,
 				   "RSN: MLD: invalid MAC address=" MACSTR
 				   " expected " MACSTR " (link ID %u)",
@@ -3398,7 +3240,7 @@
 	size_t pmk_len;
 	int ft;
 	const u8 *eapol_key_ie, *key_data, *mic;
-	u16 key_info, ver, key_data_length;
+	u16 key_data_length;
 	size_t mic_len, eapol_key_ie_len;
 	struct ieee802_1x_hdr *hdr;
 	struct wpa_eapol_key *key;
@@ -3408,8 +3250,6 @@
 	u8 pmk_r0[PMK_LEN_MAX], pmk_r0_name[WPA_PMK_NAME_LEN];
 	u8 pmk_r1[PMK_LEN_MAX];
 	size_t key_len;
-	u8 *key_data_buf = NULL;
-	size_t key_data_buf_len = 0;
 
 	SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk);
 	sm->EAPOLKeyReceived = false;
@@ -3517,46 +3357,12 @@
 	hdr = (struct ieee802_1x_hdr *) sm->last_rx_eapol_key;
 	key = (struct wpa_eapol_key *) (hdr + 1);
 	mic = (u8 *) (key + 1);
-	key_info = WPA_GET_BE16(key->key_info);
 	key_data = mic + mic_len + 2;
 	key_data_length = WPA_GET_BE16(mic + mic_len);
 	if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) -
 	    sizeof(*key) - mic_len - 2)
 		goto out;
 
-	ver = key_info & WPA_KEY_INFO_TYPE_MASK;
-	if (mic_len && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
-		if (ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES &&
-		    ver != WPA_KEY_INFO_TYPE_AES_128_CMAC &&
-		    !wpa_use_aes_key_wrap(sm->wpa_key_mgmt)) {
-			wpa_printf(MSG_INFO,
-				   "Unsupported EAPOL-Key Key Data field encryption");
-			goto out;
-		}
-
-		if (key_data_length < 8 || key_data_length % 8) {
-			wpa_printf(MSG_INFO,
-				   "RSN: Unsupported AES-WRAP len %u",
-				   key_data_length);
-			goto out;
-		}
-		key_data_length -= 8; /* AES-WRAP adds 8 bytes */
-		key_data_buf = os_malloc(key_data_length);
-		if (!key_data_buf)
-			goto out;
-		key_data_buf_len = key_data_length;
-		if (aes_unwrap(PTK.kek, PTK.kek_len, key_data_length / 8,
-			       key_data, key_data_buf)) {
-			bin_clear_free(key_data_buf, key_data_buf_len);
-			wpa_printf(MSG_INFO,
-				   "RSN: AES unwrap failed - could not decrypt EAPOL-Key key data");
-			goto out;
-		}
-		key_data = key_data_buf;
-		wpa_hexdump_key(MSG_DEBUG, "RSN: Decrypted EAPOL-Key Key Data",
-				key_data, key_data_length);
-	}
-
 	if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) {
 		wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
 				 "received EAPOL-Key msg 2/4 with invalid Key Data contents");
@@ -3701,6 +3507,27 @@
 		return;
 	}
 
+#ifdef CONFIG_IEEE80211R_AP
+	if (sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
+		/*
+		 * Verify that PMKR1Name from EAPOL-Key message 2/4 matches
+		 * with the value we derived.
+		 */
+		if (os_memcmp_const(sm->sup_pmk_r1_name, sm->pmk_r1_name,
+				    WPA_PMK_NAME_LEN) != 0) {
+			wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm),
+					LOGGER_DEBUG,
+					"PMKR1Name mismatch in FT 4-way handshake");
+			wpa_hexdump(MSG_DEBUG,
+				    "FT: PMKR1Name from Supplicant",
+				    sm->sup_pmk_r1_name, WPA_PMK_NAME_LEN);
+			wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name",
+				    sm->pmk_r1_name, WPA_PMK_NAME_LEN);
+			goto out;
+		}
+	}
+#endif /* CONFIG_IEEE80211R_AP */
+
 	if (vlan_id && wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
 	    wpa_auth_update_vlan(wpa_auth, sm->addr, vlan_id) < 0) {
 		wpa_sta_disconnect(wpa_auth, sm->addr,
@@ -3735,7 +3562,6 @@
 out:
 	forced_memzero(pmk_r0, sizeof(pmk_r0));
 	forced_memzero(pmk_r1, sizeof(pmk_r1));
-	bin_clear_free(key_data_buf, key_data_buf_len);
 }
 
 
@@ -3749,18 +3575,14 @@
 static int ieee80211w_kde_len(struct wpa_state_machine *sm)
 {
 	size_t len = 0;
-	struct wpa_authenticator *wpa_auth = sm->wpa_auth;
 
 	if (sm->mgmt_frame_prot) {
 		len += 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN;
-		len += wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
+		len += wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
 	}
-
-	if (wpa_auth->conf.tx_bss_auth)
-		wpa_auth = wpa_auth->conf.tx_bss_auth;
 	if (sm->mgmt_frame_prot && sm->wpa_auth->conf.beacon_prot) {
 		len += 2 + RSN_SELECTOR_LEN + WPA_BIGTK_KDE_PREFIX_LEN;
-		len += wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
+		len += wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
 	}
 
 	return len;
@@ -3773,8 +3595,7 @@
 	struct wpa_bigtk_kde bigtk;
 	struct wpa_group *gsm = sm->group;
 	u8 rsc[WPA_KEY_RSC_LEN];
-	struct wpa_authenticator *wpa_auth = sm->wpa_auth;
-	struct wpa_auth_config *conf = &wpa_auth->conf;
+	struct wpa_auth_config *conf = &sm->wpa_auth->conf;
 	size_t len = wpa_cipher_key_len(conf->group_mgmt_cipher);
 
 	if (!sm->mgmt_frame_prot)
@@ -3806,14 +3627,7 @@
 			  NULL, 0);
 	forced_memzero(&igtk, sizeof(igtk));
 
-	if (wpa_auth->conf.tx_bss_auth) {
-		wpa_auth = wpa_auth->conf.tx_bss_auth;
-		conf = &wpa_auth->conf;
-		len = wpa_cipher_key_len(conf->group_mgmt_cipher);
-		gsm = wpa_auth->group;
-	}
-
-	if (!sm->wpa_auth->conf.beacon_prot)
+	if (!conf->beacon_prot)
 		return pos;
 
 	bigtk.keyid[0] = gsm->GN_bigtk;
@@ -3971,11 +3785,6 @@
 	if (!beacon_prot)
 		return;
 
-	if (a->conf.tx_bss_auth) {
-		a = a->conf.tx_bss_auth;
-		gsm = a->group;
-	}
-
 	info->bigtkidx = gsm->GN_bigtk;
 	info->bigtk = gsm->BIGTK[gsm->GN_bigtk - 6];
 
@@ -3998,7 +3807,6 @@
 
 static size_t wpa_auth_ml_group_kdes_len(struct wpa_state_machine *sm)
 {
-	struct wpa_authenticator *wpa_auth = sm->wpa_auth;
 	struct wpa_group *gsm = sm->group;
 	size_t gtk_len = gsm->GTK_len;
 	size_t igtk_len;
@@ -4017,15 +3825,10 @@
 		return kde_len;
 
 	/* MLO IGTK KDE for each link */
-	igtk_len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
+	igtk_len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
 	kde_len += n_links * (2 + RSN_SELECTOR_LEN + 2 + 6 + 1 + igtk_len);
 
-	if (wpa_auth->conf.tx_bss_auth) {
-		wpa_auth = wpa_auth->conf.tx_bss_auth;
-		igtk_len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
-	}
-
-	if (!wpa_auth->conf.beacon_prot)
+	if (!sm->wpa_auth->conf.beacon_prot)
 		return kde_len;
 
 	/* MLO BIGTK KDE for each link */
@@ -4062,8 +3865,7 @@
 
 	/* Add MLO GTK KDEs */
 	for (i = 0, link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
-		if (!sm->mld_links[link_id].valid ||
-		    !ml_key_info.links[i].gtk_len)
+		if (!sm->mld_links[link_id].valid)
 			continue;
 
 		wpa_printf(MSG_DEBUG, "RSN: MLO GTK: link=%u", link_id);
@@ -4095,8 +3897,7 @@
 
 	/* Add MLO IGTK KDEs */
 	for (i = 0, link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
-		if (!sm->mld_links[link_id].valid ||
-		    !ml_key_info.links[i].igtk_len)
+		if (!sm->mld_links[link_id].valid)
 			continue;
 
 		wpa_printf(MSG_DEBUG, "RSN: MLO IGTK: link=%u", link_id);
@@ -4135,9 +3936,7 @@
 
 	/* Add MLO BIGTK KDEs */
 	for (i = 0, link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
-		if (!sm->mld_links[link_id].valid ||
-		    !ml_key_info.links[i].bigtk ||
-		    !ml_key_info.links[i].igtk_len)
+		if (!sm->mld_links[link_id].valid)
 			continue;
 
 		wpa_printf(MSG_DEBUG, "RSN: MLO BIGTK: link=%u", link_id);
@@ -4434,11 +4233,6 @@
 
 	kde_len += wpa_auth_ml_kdes_len(sm);
 
-#ifdef CONFIG_TESTING_OPTIONS
-	if (conf->eapol_m3_elements)
-		kde_len += wpabuf_len(conf->eapol_m3_elements);
-#endif /* CONFIG_TESTING_OPTIONS */
-
 	kde = os_malloc(kde_len);
 	if (!kde)
 		goto done;
@@ -4454,7 +4248,7 @@
 		size_t elen;
 
 		elen = pos - kde;
-		res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name, true);
+		res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name);
 		if (res < 0) {
 			wpa_printf(MSG_ERROR,
 				   "FT: Failed to insert PMKR1Name into RSN IE in EAPOL-Key data");
@@ -4553,17 +4347,6 @@
 
 	pos = wpa_auth_ml_kdes(sm, pos);
 
-#ifdef CONFIG_TESTING_OPTIONS
-	if (conf->eapol_m3_elements) {
-		os_memcpy(pos, wpabuf_head(conf->eapol_m3_elements),
-			  wpabuf_len(conf->eapol_m3_elements));
-		pos += wpabuf_len(conf->eapol_m3_elements);
-	}
-
-	if (conf->eapol_m3_no_encrypt)
-		encr = 0;
-#endif /* CONFIG_TESTING_OPTIONS */
-
 	wpa_send_eapol(sm->wpa_auth, sm,
 		       (secure ? WPA_KEY_INFO_SECURE : 0) |
 		       (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
@@ -4615,7 +4398,7 @@
 
 	/* MLD MAC address must be the same */
 	if (!kde.mac_addr ||
-	    !ether_addr_equal(kde.mac_addr, sm->peer_mld_addr)) {
+	    os_memcmp(kde.mac_addr, sm->peer_mld_addr, ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG,
 			   "MLD: Mismatching or missing MLD address in EAPOL-Key msg 4/4");
 		return -1;
@@ -4949,8 +4732,7 @@
 				return;
 
 			kde = pos = kde_buf;
-			pos = wpa_auth_ml_group_kdes(sm, pos);
-			kde_len = pos - kde_buf;
+			wpa_auth_ml_group_kdes(sm, pos);
 		}
 #endif /* CONFIG_IEEE80211BE */
 	} else {
@@ -5130,30 +4912,19 @@
 				group->IGTK[group->GN_igtk - 4], len);
 	}
 
-	if (!wpa_auth->non_tx_beacon_prot &&
-	    conf->ieee80211w == NO_MGMT_FRAME_PROTECTION)
-		return ret;
-	if (!conf->beacon_prot)
-		return ret;
-
-	if (wpa_auth->conf.tx_bss_auth) {
-		group = wpa_auth->conf.tx_bss_auth->group;
-		if (group->bigtk_set)
-			return ret;
-		wpa_printf(MSG_DEBUG, "Set up BIGTK for TX BSS");
+	if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION &&
+	    conf->beacon_prot) {
+		len = wpa_cipher_key_len(conf->group_mgmt_cipher);
+		os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
+		inc_byte_array(group->Counter, WPA_NONCE_LEN);
+		if (wpa_gmk_to_gtk(group->GMK, "BIGTK key expansion",
+				   wpa_auth->addr, group->GNonce,
+				   group->BIGTK[group->GN_bigtk - 6], len) < 0)
+			ret = -1;
+		wpa_hexdump_key(MSG_DEBUG, "BIGTK",
+				group->BIGTK[group->GN_bigtk - 6], len);
 	}
 
-	len = wpa_cipher_key_len(conf->group_mgmt_cipher);
-	os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
-	inc_byte_array(group->Counter, WPA_NONCE_LEN);
-	if (wpa_gmk_to_gtk(group->GMK, "BIGTK key expansion",
-			   wpa_auth->addr, group->GNonce,
-			   group->BIGTK[group->GN_bigtk - 6], len) < 0)
-		return -1;
-	group->bigtk_set = true;
-	wpa_hexdump_key(MSG_DEBUG, "BIGTK",
-			group->BIGTK[group->GN_bigtk - 6], len);
-
 	return ret;
 }
 
@@ -5314,10 +5085,9 @@
 
 int wpa_wnmsleep_bigtk_subelem(struct wpa_state_machine *sm, u8 *pos)
 {
-	struct wpa_authenticator *wpa_auth = sm->wpa_auth;
-	struct wpa_group *gsm = wpa_auth->group;
+	struct wpa_group *gsm = sm->group;
 	u8 *start = pos;
-	size_t len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
+	size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
 
 	/*
 	 * BIGTK subelement:
@@ -5327,7 +5097,7 @@
 	*pos++ = 2 + 6 + len;
 	WPA_PUT_LE16(pos, gsm->GN_bigtk);
 	pos += 2;
-	if (wpa_auth_get_seqnum(wpa_auth, NULL, gsm->GN_bigtk, pos) != 0)
+	if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_bigtk, pos) != 0)
 		return 0;
 	pos += 6;
 
@@ -5417,21 +5187,12 @@
 				     KEY_FLAG_GROUP_TX_DEFAULT) < 0)
 			ret = -1;
 
-		if (ret || !conf->beacon_prot)
-			return ret;
-		if (wpa_auth->conf.tx_bss_auth) {
-			wpa_auth = wpa_auth->conf.tx_bss_auth;
-			group = wpa_auth->group;
-			if (!group->bigtk_set || group->bigtk_configured)
-				return ret;
-		}
-		if (wpa_auth_set_key(wpa_auth, group->vlan_id, alg,
+		if (ret == 0 && conf->beacon_prot &&
+		    wpa_auth_set_key(wpa_auth, group->vlan_id, alg,
 				     broadcast_ether_addr, group->GN_bigtk,
 				     group->BIGTK[group->GN_bigtk - 6], len,
 				     KEY_FLAG_GROUP_TX_DEFAULT) < 0)
 			ret = -1;
-		else
-			group->bigtk_configured = true;
 	}
 
 	return ret;
@@ -5576,11 +5337,9 @@
 		tmp = group->GM_igtk;
 		group->GM_igtk = group->GN_igtk;
 		group->GN_igtk = tmp;
-		if (!wpa_auth->conf.tx_bss_auth) {
-			tmp = group->GM_bigtk;
-			group->GM_bigtk = group->GN_bigtk;
-			group->GN_bigtk = tmp;
-		}
+		tmp = group->GM_bigtk;
+		group->GM_bigtk = group->GN_bigtk;
+		group->GN_bigtk = tmp;
 		wpa_gtk_update(wpa_auth, group);
 		wpa_group_config_group_keys(wpa_auth, group);
 	}
@@ -5930,11 +5689,28 @@
 
 int wpa_auth_pmksa_add2(struct wpa_authenticator *wpa_auth, const u8 *addr,
 			const u8 *pmk, size_t pmk_len, const u8 *pmkid,
+			int session_timeout, int akmp)
+{
+	if (!wpa_auth || wpa_auth->conf.disable_pmksa_caching)
+		return -1;
+
+	wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK (2)", pmk, PMK_LEN);
+	if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, pmk_len, pmkid,
+				 NULL, 0, wpa_auth->addr, addr, session_timeout,
+				 NULL, akmp))
+		return 0;
+
+	return -1;
+}
+
+
+int wpa_auth_pmksa_add3(struct wpa_authenticator *wpa_auth, const u8 *addr,
+			const u8 *pmk, size_t pmk_len, const u8 *pmkid,
 			int session_timeout, int akmp, const u8 *dpp_pkhash)
 {
 	struct rsn_pmksa_cache_entry *entry;
 
-	if (!wpa_auth || wpa_auth->conf.disable_pmksa_caching)
+	if (wpa_auth->conf.disable_pmksa_caching)
 		return -1;
 
 	wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK (3)", pmk, PMK_LEN);
@@ -6058,14 +5834,13 @@
 void wpa_auth_pmksa_set_to_sm(struct rsn_pmksa_cache_entry *pmksa,
 			      struct wpa_state_machine *sm,
 			      struct wpa_authenticator *wpa_auth,
-			      u8 *pmkid, u8 *pmk, size_t *pmk_len)
+			      u8 *pmkid, u8 *pmk)
 {
 	if (!sm)
 		return;
 
 	sm->pmksa = pmksa;
-	os_memcpy(pmk, pmksa->pmk, pmksa->pmk_len);
-	*pmk_len = pmksa->pmk_len;
+	os_memcpy(pmk, pmksa->pmk, PMK_LEN);
 	os_memcpy(pmkid, pmksa->pmkid, PMKID_LEN);
 	os_memcpy(wpa_auth->dot11RSNAPMKIDUsed, pmksa->pmkid, PMKID_LEN);
 }
@@ -6583,7 +6358,7 @@
 		size_t elen;
 
 		elen = pos - kde;
-		res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name, true);
+		res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name);
 		if (res < 0) {
 			wpa_printf(MSG_ERROR,
 				   "FT: Failed to insert PMKR1Name into RSN IE in EAPOL-Key data");
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index 4f6bb76..57fda8a 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -244,9 +244,6 @@
 	unsigned int skip_send_eapol:1;
 	unsigned int enable_eapol_large_timeout:1;
 	bool delay_eapol_tx;
-	struct wpabuf *eapol_m1_elements;
-	struct wpabuf *eapol_m3_elements;
-	bool eapol_m3_no_encrypt;
 #endif /* CONFIG_TESTING_OPTIONS */
 	unsigned int oci_freq_override_eapol_m3;
 	unsigned int oci_freq_override_eapol_g1;
@@ -282,11 +279,6 @@
 	bool force_kdk_derivation;
 
 	bool radius_psk;
-
-	/* Pointer to Multi-BSSID transmitted BSS authenticator instance.
-	 * Set only in nontransmitted BSSs, i.e., is NULL for transmitted BSS
-	 * and in BSSs that are not part of a Multi-BSSID set. */
-	struct wpa_authenticator *tx_bss_auth;
 };
 
 typedef enum {
@@ -487,6 +479,9 @@
 void wpa_auth_add_sae_pmkid(struct wpa_state_machine *sm, const u8 *pmkid);
 int wpa_auth_pmksa_add2(struct wpa_authenticator *wpa_auth, const u8 *addr,
 			const u8 *pmk, size_t pmk_len, const u8 *pmkid,
+			int session_timeout, int akmp);
+int wpa_auth_pmksa_add3(struct wpa_authenticator *wpa_auth, const u8 *addr,
+			const u8 *pmk, size_t pmk_len, const u8 *pmkid,
 			int session_timeout, int akmp, const u8 *dpp_pkhash);
 void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth,
 			   const u8 *sta_addr);
@@ -512,7 +507,7 @@
 void wpa_auth_pmksa_set_to_sm(struct rsn_pmksa_cache_entry *pmksa,
 			      struct wpa_state_machine *sm,
 			      struct wpa_authenticator *wpa_auth,
-			      u8 *pmkid, u8 *pmk, size_t *pmk_len);
+			      u8 *pmkid, u8 *pmk);
 int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id);
 void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth,
 				  struct wpa_state_machine *sm, int ack);
diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c
index 7744ed6..4b16f62 100644
--- a/src/ap/wpa_auth_ft.c
+++ b/src/ap/wpa_auth_ft.c
@@ -1427,7 +1427,7 @@
 
 	os_get_reltime(&now);
 	dl_list_for_each(r0, &cache->pmk_r0, struct wpa_ft_pmk_r0_sa, list) {
-		if (ether_addr_equal(r0->spa, spa) &&
+		if (os_memcmp(r0->spa, spa, ETH_ALEN) == 0 &&
 		    os_memcmp_const(r0->pmk_r0_name, pmk_r0_name,
 				    WPA_PMK_NAME_LEN) == 0) {
 			*r0_out = r0;
@@ -1522,7 +1522,7 @@
 	os_get_reltime(&now);
 
 	dl_list_for_each(r1, &cache->pmk_r1, struct wpa_ft_pmk_r1_sa, list) {
-		if (ether_addr_equal(r1->spa, spa) &&
+		if (os_memcmp(r1->spa, spa, ETH_ALEN) == 0 &&
 		    os_memcmp_const(r1->pmk_r1_name, pmk_r1_name,
 				    WPA_PMK_NAME_LEN) == 0) {
 			os_memcpy(pmk_r1, r1->pmk_r1, r1->pmk_r1_len);
@@ -2024,7 +2024,7 @@
 			    sm->r0kh_id, sm->r0kh_id_len);
 		return -1;
 	}
-	if (ether_addr_equal(r0kh->addr, sm->wpa_auth->addr)) {
+	if (os_memcmp(r0kh->addr, sm->wpa_auth->addr, ETH_ALEN) == 0) {
 		wpa_printf(MSG_DEBUG,
 			   "FT: R0KH-ID points to self - no matching key available");
 		return -1;
@@ -2366,8 +2366,7 @@
 static u8 * wpa_ft_bigtk_subelem(struct wpa_state_machine *sm, size_t *len)
 {
 	u8 *subelem, *pos;
-	struct wpa_authenticator *wpa_auth = sm->wpa_auth;
-	struct wpa_group *gsm = wpa_auth->group;
+	struct wpa_group *gsm = sm->group;
 	size_t subelem_len;
 	const u8 *kek, *bigtk;
 	size_t kek_len;
@@ -2382,7 +2381,7 @@
 		kek_len = sm->PTK.kek_len;
 	}
 
-	bigtk_len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
+	bigtk_len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
 
 	/* Sub-elem ID[1] | Length[1] | KeyID[2] | BIPN[6] | Key Length[1] |
 	 * Key[16+8] */
@@ -2396,7 +2395,7 @@
 	*pos++ = subelem_len - 2;
 	WPA_PUT_LE16(pos, gsm->GN_bigtk);
 	pos += 2;
-	wpa_auth_get_seqnum(wpa_auth, NULL, gsm->GN_bigtk, pos);
+	wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_bigtk, pos);
 	pos += 6;
 	*pos++ = bigtk_len;
 	bigtk = gsm->BIGTK[gsm->GN_bigtk - 6];
@@ -3766,7 +3765,7 @@
 		   " Target AP=" MACSTR " Action=%d)",
 		   MAC2STR(sta_addr), MAC2STR(target_ap), action);
 
-	if (!ether_addr_equal(sta_addr, sm->addr)) {
+	if (os_memcmp(sta_addr, sm->addr, ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG, "FT: Mismatch in FT Action STA address: "
 			   "STA=" MACSTR " STA-Address=" MACSTR,
 			   MAC2STR(sm->addr), MAC2STR(sta_addr));
@@ -3779,7 +3778,7 @@
 	 * APs in the MD (if such a list were configured).
 	 */
 	if ((target_ap[0] & 0x01) ||
-	    ether_addr_equal(target_ap, sm->wpa_auth->addr)) {
+	    os_memcmp(target_ap, sm->wpa_auth->addr, ETH_ALEN) == 0) {
 		wpa_printf(MSG_DEBUG, "FT: Invalid Target AP in FT Action "
 			   "frame");
 		return -1;
@@ -4037,7 +4036,7 @@
 		seq_ret = wpa_ft_rrb_seq_chk(r1kh->seq, src_addr, enc, enc_len,
 					     auth, auth_len, msgtype, no_defer);
 	if (!no_defer && r1kh_wildcard &&
-	    (!r1kh || !ether_addr_equal(r1kh->addr, src_addr))) {
+	    (!r1kh || os_memcmp(r1kh->addr, src_addr, ETH_ALEN) != 0)) {
 		/* wildcard: r1kh-id unknown or changed addr -> do a seq req */
 		seq_ret = FT_RRB_SEQ_DEFER;
 	}
@@ -4204,7 +4203,7 @@
 					     cb ? 0 : 1);
 	}
 	if (cb && r0kh_wildcard &&
-	    (!r0kh || !ether_addr_equal(r0kh->addr, src_addr))) {
+	    (!r0kh || os_memcmp(r0kh->addr, src_addr, ETH_ALEN) != 0)) {
 		/* wildcard: r0kh-id unknown or changed addr -> do a seq req */
 		seq_ret = FT_RRB_SEQ_DEFER;
 	}
@@ -4358,7 +4357,7 @@
 	struct ft_get_sta_ctx *info = ctx;
 
 	if ((info->s1kh_id &&
-	     !ether_addr_equal(info->s1kh_id, sm->addr)) ||
+	     os_memcmp(info->s1kh_id, sm->addr, ETH_ALEN) != 0) ||
 	    os_memcmp(info->nonce, sm->ft_pending_pull_nonce,
 		      FT_RRB_NONCE_LEN) != 0 ||
 	    sm->ft_pending_cb == NULL || sm->ft_pending_req_ies == NULL)
@@ -4483,7 +4482,7 @@
 		wpa_ft_rrb_lookup_r0kh(wpa_auth, f_r0kh_id, f_r0kh_id_len,
 				       &r0kh, &r0kh_wildcard);
 		if (!r0kh_wildcard &&
-		    (!r0kh || !ether_addr_equal(r0kh->addr, src_addr))) {
+		    (!r0kh || os_memcmp(r0kh->addr, src_addr, ETH_ALEN) != 0)) {
 			wpa_hexdump(MSG_DEBUG, "FT: Did not find R0KH-ID",
 				    f_r0kh_id, f_r0kh_id_len);
 			goto out;
@@ -4501,7 +4500,7 @@
 		wpa_ft_rrb_lookup_r1kh(wpa_auth, f_r1kh_id, &r1kh,
 				       &r1kh_wildcard);
 		if (!r1kh_wildcard &&
-		    (!r1kh || !ether_addr_equal(r1kh->addr, src_addr))) {
+		    (!r1kh || os_memcmp(r1kh->addr, src_addr, ETH_ALEN) != 0)) {
 			wpa_hexdump(MSG_DEBUG, "FT: Did not find R1KH-ID",
 				    f_r1kh_id, FT_R1KH_ID_LEN);
 			goto out;
@@ -4807,7 +4806,7 @@
 			return -1;
 		}
 
-		if (!ether_addr_equal(target_ap_addr, wpa_auth->addr)) {
+		if (os_memcmp(target_ap_addr, wpa_auth->addr, ETH_ALEN) != 0) {
 			wpa_printf(MSG_DEBUG, "FT: Target AP address in the "
 				   "RRB Request does not match with own "
 				   "address");
@@ -4970,7 +4969,7 @@
 		return;
 
 	dl_list_for_each(r0, &cache->pmk_r0, struct wpa_ft_pmk_r0_sa, list) {
-		if (ether_addr_equal(r0->spa, addr)) {
+		if (os_memcmp(r0->spa, addr, ETH_ALEN) == 0) {
 			r0found = r0;
 			break;
 		}
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index 34de45c..82d79f2 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -183,15 +183,8 @@
 	wconf->oci_freq_override_ft_assoc = conf->oci_freq_override_ft_assoc;
 	wconf->oci_freq_override_fils_assoc =
 		conf->oci_freq_override_fils_assoc;
-
 	wconf->skip_send_eapol = iconf->skip_send_eapol;
 	wconf->enable_eapol_large_timeout = iconf->enable_eapol_large_timeout;
-
-	if (conf->eapol_m1_elements)
-		wconf->eapol_m1_elements = wpabuf_dup(conf->eapol_m1_elements);
-	if (conf->eapol_m3_elements)
-		wconf->eapol_m3_elements = wpabuf_dup(conf->eapol_m3_elements);
-	wconf->eapol_m3_no_encrypt = conf->eapol_m3_no_encrypt;
 #endif /* CONFIG_TESTING_OPTIONS */
 #ifdef CONFIG_P2P
 	os_memcpy(wconf->ip_addr_go, conf->ip_addr_go, 4);
@@ -563,8 +556,7 @@
 	if (sta) {
 		flags = hostapd_sta_flags_to_drv(sta->flags);
 #ifdef CONFIG_IEEE80211BE
-		if (ap_sta_is_mld(hapd, sta) &&
-		    (sta->flags & WLAN_STA_AUTHORIZED))
+		if (sta->mld_info.mld_sta && (sta->flags & WLAN_STA_AUTHORIZED))
 			link_id = -1;
 #endif /* CONFIG_IEEE80211BE */
 	}
@@ -677,7 +669,7 @@
 		hapd = iface->bss[j];
 		if (hapd == idata->src_hapd ||
 		    !hapd->wpa_auth ||
-		    !ether_addr_equal(hapd->own_addr, idata->dst))
+		    os_memcmp(hapd->own_addr, idata->dst, ETH_ALEN) != 0)
 			continue;
 
 		wpa_printf(MSG_DEBUG,
@@ -867,7 +859,7 @@
 			      MOBILITY_DOMAIN_ID_LEN) != 0)
 			continue; /* no matching FT SSID/mobility domain */
 		if (!is_multicast_ether_addr(idata->dst_addr) &&
-		    !ether_addr_equal(hapd->own_addr, idata->dst_addr))
+		    os_memcmp(hapd->own_addr, idata->dst_addr, ETH_ALEN) != 0)
 			continue; /* destination address does not match */
 
 		/* defer eth_p_oui_deliver until next eloop step as this is
@@ -1165,25 +1157,17 @@
 	if (!sta || !sta->wpa_sm)
 		return -1;
 
-	if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_VLAN_OFFLOAD)) {
-		if (vlan->notempty &&
-		    !hostapd_vlan_valid(hapd->conf->vlan, vlan)) {
-			hostapd_logger(hapd, sta->addr,
-				       HOSTAPD_MODULE_IEEE80211,
-				       HOSTAPD_LEVEL_INFO,
-				       "Invalid VLAN %d%s received from FT",
-				       vlan->untagged, vlan->tagged[0] ?
-				       "+" : "");
-			return -1;
-		}
-
-		if (ap_sta_set_vlan(hapd, sta, vlan) < 0)
-			return -1;
-
-	} else {
-		if (vlan->notempty)
-			sta->vlan_id = vlan->untagged;
+	if (vlan->notempty &&
+	    !hostapd_vlan_valid(hapd->conf->vlan, vlan)) {
+		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
+			       HOSTAPD_LEVEL_INFO,
+			       "Invalid VLAN %d%s received from FT",
+			       vlan->untagged, vlan->tagged[0] ? "+" : "");
+		return -1;
 	}
+
+	if (ap_sta_set_vlan(hapd, sta, vlan) < 0)
+		return -1;
 	/* Configure wpa_group for GTK but ignore error due to driver not
 	 * knowing this STA. */
 	ap_sta_bind_vlan(hapd, sta);
@@ -1206,15 +1190,10 @@
 	if (!sta)
 		return -1;
 
-	if (sta->vlan_desc) {
+	if (sta->vlan_desc)
 		*vlan = *sta->vlan_desc;
-	} else if ((hapd->iface->drv_flags & WPA_DRIVER_FLAGS_VLAN_OFFLOAD) &&
-		   sta->vlan_id) {
-		vlan->notempty = 1;
-		vlan->untagged = sta->vlan_id;
-	} else {
+	else
 		os_memset(vlan, 0, sizeof(*vlan));
-	}
 
 	return 0;
 }
@@ -1417,7 +1396,7 @@
 	wpa_printf(MSG_DEBUG, "FT: RRB received packet " MACSTR " -> "
 		   MACSTR, MAC2STR(ethhdr->h_source), MAC2STR(ethhdr->h_dest));
 	if (!is_multicast_ether_addr(ethhdr->h_dest) &&
-	    !ether_addr_equal(hapd->own_addr, ethhdr->h_dest))
+	    os_memcmp(hapd->own_addr, ethhdr->h_dest, ETH_ALEN) != 0)
 		return;
 	wpa_ft_rrb_rx(hapd->wpa_auth, ethhdr->h_source, buf + sizeof(*ethhdr),
 		      len - sizeof(*ethhdr));
@@ -1433,7 +1412,7 @@
 	wpa_printf(MSG_DEBUG, "FT: RRB received packet " MACSTR " -> "
 		   MACSTR, MAC2STR(src_addr), MAC2STR(dst_addr));
 	if (!is_multicast_ether_addr(dst_addr) &&
-	    !ether_addr_equal(hapd->own_addr, dst_addr))
+	    os_memcmp(hapd->own_addr, dst_addr, ETH_ALEN) != 0)
 		return;
 	wpa_ft_rrb_oui_rx(hapd->wpa_auth, src_addr, dst_addr, oui_suffix, buf,
 			  len);
@@ -1559,9 +1538,9 @@
 			struct hostapd_iface *iface =
 				hapd->iface->interfaces->iface[j];
 
-			if (!hostapd_is_ml_partner(hapd, iface->bss[0]) ||
-			    link_id != iface->bss[0]->mld_link_id ||
-			    !iface->bss[0]->wpa_auth)
+			if (!iface->bss[0]->conf->mld_ap ||
+			    hapd->conf->mld_id != iface->bss[0]->conf->mld_id ||
+			    link_id != iface->bss[0]->mld_link_id)
 				continue;
 
 			wpa_auth_ml_get_rsn_info(iface->bss[0]->wpa_auth,
@@ -1601,9 +1580,9 @@
 			struct hostapd_iface *iface =
 				hapd->iface->interfaces->iface[j];
 
-			if (!hostapd_is_ml_partner(hapd, iface->bss[0]) ||
-			    link_id != iface->bss[0]->mld_link_id ||
-			    !iface->bss[0]->wpa_auth)
+			if (!iface->bss[0]->conf->mld_ap ||
+			    hapd->conf->mld_id != iface->bss[0]->conf->mld_id ||
+			    link_id != iface->bss[0]->mld_link_id)
 				continue;
 
 			wpa_auth_ml_get_key_info(iface->bss[0]->wpa_auth,
@@ -1696,13 +1675,9 @@
 	};
 	const u8 *wpa_ie;
 	size_t wpa_ie_len;
-	struct hostapd_data *tx_bss;
 
 	hostapd_wpa_auth_conf(hapd->conf, hapd->iconf, &_conf);
 	_conf.msg_ctx = hapd->msg_ctx;
-	tx_bss = hostapd_mbssid_get_tx_bss(hapd);
-	if (tx_bss != hapd)
-		_conf.tx_bss_auth = tx_bss->wpa_auth;
 	if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_EAPOL_TX_STATUS)
 		_conf.tx_status = 1;
 	if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_MLME)
diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h
index 9ba8304..74ae5ad 100644
--- a/src/ap/wpa_auth_i.h
+++ b/src/ap/wpa_auth_i.h
@@ -134,6 +134,8 @@
 					   * Request */
 	u8 r0kh_id[FT_R0KH_ID_MAX_LEN]; /* R0KH-ID from FT Auth Request */
 	size_t r0kh_id_len;
+	u8 sup_pmk_r1_name[WPA_PMK_NAME_LEN]; /* PMKR1Name from EAPOL-Key
+					       * message 2/4 */
 	u8 *assoc_resp_ftie;
 
 	void (*ft_pending_cb)(void *ctx, const u8 *dst, const u8 *bssid,
@@ -220,8 +222,6 @@
 	u8 BIGTK[2][WPA_IGTK_MAX_LEN];
 	int GN_igtk, GM_igtk;
 	int GN_bigtk, GM_bigtk;
-	bool bigtk_set;
-	bool bigtk_configured;
 	/* Number of references except those in struct wpa_group->next */
 	unsigned int references;
 	unsigned int num_setup_iface;
@@ -257,8 +257,6 @@
 	struct rsn_pmksa_cache *pmksa;
 	struct wpa_ft_pmk_cache *ft_pmk_cache;
 
-	bool non_tx_beacon_prot;
-
 #ifdef CONFIG_P2P
 	struct bitfield *ip_pool;
 #endif /* CONFIG_P2P */
diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c
index 82d4d5f..aacfa33 100644
--- a/src/ap/wps_hostapd.c
+++ b/src/ap/wps_hostapd.c
@@ -288,7 +288,7 @@
 			any_psk = wpa_psk->psk;
 
 		if (mac_addr && !dev_psk &&
-		    ether_addr_equal(mac_addr, wpa_psk->addr)) {
+		    os_memcmp(mac_addr, wpa_psk->addr, ETH_ALEN) == 0) {
 			dev_psk = wpa_psk->psk;
 			break;
 		}
diff --git a/src/build.rules b/src/build.rules
index c756ccb..acda884 100644
--- a/src/build.rules
+++ b/src/build.rules
@@ -80,7 +80,7 @@
 _DIRS := $(BUILDDIR)/$(PROJ)
 .PHONY: _make_dirs
 _make_dirs:
-	@mkdir -p $(sort $(_DIRS))
+	@mkdir -p $(_DIRS)
 
 $(BUILDDIR)/$(PROJ)/src/%.o: $(ROOTDIR)src/%.c $(CONFIG_FILE) | _make_dirs
 	$(Q)$(CC) -c -o $@ $(CFLAGS) $<
diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c
index 2fad3e1..d226a8a 100644
--- a/src/common/dpp_tcp.c
+++ b/src/common/dpp_tcp.c
@@ -563,7 +563,7 @@
 	struct dpp_connection *conn;
 
 	dl_list_for_each(conn, &ctrl->conn, struct dpp_connection, list) {
-		if (ether_addr_equal(src, conn->mac_addr))
+		if (os_memcmp(src, conn->mac_addr, ETH_ALEN) == 0)
 			return conn;
 		if ((type == DPP_PA_PKEX_EXCHANGE_RESP ||
 		     type == DPP_PA_AUTHENTICATION_RESP) &&
@@ -661,7 +661,7 @@
 	struct dpp_connection *conn;
 
 	dl_list_for_each(conn, &ctrl->conn, struct dpp_connection, list) {
-		if (ether_addr_equal(src, conn->mac_addr))
+		if (os_memcmp(src, conn->mac_addr, ETH_ALEN) == 0)
 			return conn;
 	}
 
@@ -2601,8 +2601,7 @@
 }
 
 
-static void dpp_tcp_send_conn_status_msg(struct dpp_global *dpp,
-					 struct dpp_connection *conn,
+static void dpp_tcp_send_conn_status_msg(struct dpp_connection *conn,
 					 enum dpp_status_error result,
 					 const u8 *ssid, size_t ssid_len,
 					 const char *channel_list)
@@ -2610,7 +2609,6 @@
 	struct dpp_authentication *auth = conn->auth;
 	int res;
 	struct wpabuf *msg;
-	struct dpp_connection *c;
 
 	auth->conn_status_requested = 0;
 
@@ -2629,16 +2627,8 @@
 		return;
 	}
 
-	/* conn might have been removed during the dpp_tcp_send_msg() call, so
-	 * need to check that it is still present before modifying it. */
-	dl_list_for_each(c, &dpp->tcp_init, struct dpp_connection, list) {
-		if (conn == c) {
-			/* This exchange will be terminated in the TX status
-			 * handler */
-			conn->on_tcp_tx_complete_remove = 1;
-			break;
-		}
-	}
+	/* This exchange will be terminated in the TX status handler */
+	conn->on_tcp_tx_complete_remove = 1;
 }
 
 
@@ -2651,7 +2641,7 @@
 
 	dl_list_for_each(conn, &dpp->tcp_init, struct dpp_connection, list) {
 		if (conn->auth && conn->auth->conn_status_requested) {
-			dpp_tcp_send_conn_status_msg(dpp, conn, result, ssid,
+			dpp_tcp_send_conn_status_msg(conn, result, ssid,
 						     ssid_len, channel_list);
 			break;
 		}
diff --git a/src/common/gas_server.c b/src/common/gas_server.c
index 1075500..745a13f 100644
--- a/src/common/gas_server.c
+++ b/src/common/gas_server.c
@@ -352,7 +352,7 @@
 	dl_list_for_each(response, &gas->responses, struct gas_server_response,
 			 list) {
 		if (response->dialog_token != dialog_token ||
-		    !ether_addr_equal(sa, response->dst))
+		    os_memcmp(sa, response->dst, ETH_ALEN) != 0)
 			continue;
 		gas_server_handle_rx_comeback_req(response);
 		return 0;
@@ -470,7 +470,7 @@
 	dl_list_for_each(response, &gas->responses, struct gas_server_response,
 			 list) {
 		if (response->dialog_token != dialog_token ||
-		    !ether_addr_equal(dst, response->dst))
+		    os_memcmp(dst, response->dst, ETH_ALEN) != 0)
 			continue;
 		gas_server_handle_tx_status(response, ack);
 		return;
diff --git a/src/common/hw_features_common.c b/src/common/hw_features_common.c
index 2c47bf8..57b5a8e 100644
--- a/src/common/hw_features_common.c
+++ b/src/common/hw_features_common.c
@@ -381,75 +381,6 @@
 }
 
 
-static void punct_update_legacy_bw_80(u8 bitmap, u8 pri_chan, u8 *seg0)
-{
-	u8 first_chan = *seg0 - 6, sec_chan;
-
-	switch (bitmap) {
-	case 0x6:
-		*seg0 = 0;
-		return;
-	case 0x8:
-	case 0x4:
-	case 0x2:
-	case 0x1:
-	case 0xC:
-	case 0x3:
-		if (pri_chan < *seg0)
-			*seg0 -= 4;
-		else
-			*seg0 += 4;
-		break;
-	}
-
-	if (pri_chan < *seg0)
-		sec_chan = pri_chan + 4;
-	else
-		sec_chan = pri_chan - 4;
-
-	if (bitmap & BIT((sec_chan - first_chan) / 4))
-		*seg0 = 0;
-}
-
-
-static void punct_update_legacy_bw_160(u8 bitmap, u8 pri,
-				       enum oper_chan_width *width, u8 *seg0)
-{
-	if (pri < *seg0) {
-		*seg0 -= 8;
-		if (bitmap & 0x0F) {
-			*width = 0;
-			punct_update_legacy_bw_80(bitmap & 0xF, pri, seg0);
-		}
-	} else {
-		*seg0 += 8;
-		if (bitmap & 0xF0) {
-			*width = 0;
-			punct_update_legacy_bw_80((bitmap & 0xF0) >> 4, pri,
-						  seg0);
-		}
-	}
-}
-
-
-void punct_update_legacy_bw(u16 bitmap, u8 pri, enum oper_chan_width *width,
-			    u8 *seg0, u8 *seg1)
-{
-	if (*width == CONF_OPER_CHWIDTH_80MHZ && (bitmap & 0xF)) {
-		*width = CONF_OPER_CHWIDTH_USE_HT;
-		punct_update_legacy_bw_80(bitmap & 0xF, pri, seg0);
-	}
-
-	if (*width == CONF_OPER_CHWIDTH_160MHZ && (bitmap & 0xFF)) {
-		*width = CONF_OPER_CHWIDTH_80MHZ;
-		*seg1 = 0;
-		punct_update_legacy_bw_160(bitmap & 0xFF, pri, width, seg0);
-	}
-
-	/* TODO: 320 MHz */
-}
-
-
 int hostapd_set_freq_params(struct hostapd_freq_params *data,
 			    enum hostapd_hw_mode mode,
 			    int freq, int channel, int enable_edmg,
@@ -460,12 +391,8 @@
 			    int center_segment0,
 			    int center_segment1, u32 vht_caps,
 			    struct he_capabilities *he_cap,
-			    struct eht_capabilities *eht_cap,
-			    u16 punct_bitmap)
+			    struct eht_capabilities *eht_cap)
 {
-	enum oper_chan_width oper_chwidth_legacy;
-	u8 seg0_legacy, seg1_legacy;
-
 	if (!he_cap || !he_cap->he_supported)
 		he_enabled = 0;
 	if (!eht_cap || !eht_cap->eht_supported)
@@ -521,7 +448,6 @@
 		} else {
 			int freq1, freq2 = 0;
 			int bw = center_idx_to_bw_6ghz(center_segment0);
-			int opclass;
 
 			if (bw < 0) {
 				wpa_printf(MSG_ERROR,
@@ -529,10 +455,7 @@
 				return -1;
 			}
 
-			/* The 6 GHz channel 2 uses a different operating class
-			 */
-			opclass = center_segment0 == 2 ? 136 : 131;
-			freq1 = ieee80211_chan_to_freq(NULL, opclass,
+			freq1 = ieee80211_chan_to_freq(NULL, 131,
 						       center_segment0);
 			if (freq1 < 0) {
 				wpa_printf(MSG_ERROR,
@@ -651,14 +574,6 @@
 		break;
 	}
 
-	oper_chwidth_legacy = oper_chwidth;
-	seg0_legacy = center_segment0;
-	seg1_legacy = center_segment1;
-	if (punct_bitmap)
-		punct_update_legacy_bw(punct_bitmap, channel,
-				       &oper_chwidth_legacy,
-				       &seg0_legacy, &seg1_legacy);
-
 	if (data->eht_enabled || data->he_enabled ||
 	    data->vht_enabled) switch (oper_chwidth) {
 	case CONF_OPER_CHWIDTH_USE_HT:
@@ -683,8 +598,7 @@
 		/* fall through */
 	case CONF_OPER_CHWIDTH_80MHZ:
 		data->bandwidth = 80;
-		if (!sec_channel_offset &&
-		    oper_chwidth_legacy != CONF_OPER_CHWIDTH_USE_HT) {
+		if (!sec_channel_offset) {
 			wpa_printf(MSG_ERROR,
 				   "80/80+80 MHz: no second channel offset");
 			return -1;
@@ -742,8 +656,7 @@
 				   "160 MHz: center segment 1 should not be set");
 			return -1;
 		}
-		if (!sec_channel_offset &&
-		    oper_chwidth_legacy != CONF_OPER_CHWIDTH_USE_HT) {
+		if (!sec_channel_offset) {
 			wpa_printf(MSG_ERROR,
 				   "160 MHz: second channel offset not set");
 			return -1;
diff --git a/src/common/hw_features_common.h b/src/common/hw_features_common.h
index e791c33..82e0282 100644
--- a/src/common/hw_features_common.h
+++ b/src/common/hw_features_common.h
@@ -35,8 +35,6 @@
 int check_40mhz_2g4(struct hostapd_hw_modes *mode,
 		    struct wpa_scan_results *scan_res, int pri_chan,
 		    int sec_chan);
-void punct_update_legacy_bw(u16 bitmap, u8 pri_chan,
-			    enum oper_chan_width *width, u8 *seg0, u8 *seg1);
 int hostapd_set_freq_params(struct hostapd_freq_params *data,
 			    enum hostapd_hw_mode mode,
 			    int freq, int channel, int edmg, u8 edmg_channel,
@@ -47,8 +45,7 @@
 			    int center_segment0,
 			    int center_segment1, u32 vht_caps,
 			    struct he_capabilities *he_caps,
-			    struct eht_capabilities *eht_cap,
-			    u16 punct_bitmap);
+			    struct eht_capabilities *eht_cap);
 void set_disable_ht40(struct ieee80211_ht_capabilities *htcaps,
 		      int disabled);
 int ieee80211ac_cap_check(u32 hw, u32 conf);
diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
index 4de88d1..dbe7b29 100644
--- a/src/common/ieee802_11_common.c
+++ b/src/common/ieee802_11_common.c
@@ -1012,7 +1012,7 @@
 			continue;
 		}
 
-		if (sub_elem_len < 5) {
+		if (sub_elem_len < 3) {
 			if (show_errors)
 				wpa_printf(MSG_DEBUG,
 					   "MLD: error: sub_elem_len=%zu < 5",
@@ -1081,8 +1081,7 @@
 			non_inherit_len -= 1 + non_inherit[0];
 			non_inherit += 1 + non_inherit[0];
 
-			if (non_inherit_len < 1UL ||
-			    non_inherit_len < 1UL + non_inherit[0]) {
+			if (non_inherit_len < 1UL + non_inherit[0]) {
 				if (show_errors)
 					wpa_printf(MSG_DEBUG,
 						   "MLD: Invalid inheritance");
@@ -2050,13 +2049,6 @@
 }
 
 
-bool is_80plus_op_class(u8 op_class)
-{
-	/* Operating classes with "80+" behavior indication in Table E-4 */
-	return op_class == 130 || op_class == 135;
-}
-
-
 static int is_11b(u8 rate)
 {
 	return rate == 0x02 || rate == 0x04 || rate == 0x0b || rate == 0x16
@@ -2424,17 +2416,9 @@
 	 * channel center frequency index value, but it happens to be a 20 MHz
 	 * channel and the channel number in the channel set would match the
 	 * value in for the frequency center.
-	 *
-	 * Operating class value pair 128 and 130 is used to describe a 80+80
-	 * MHz channel on the 5 GHz band. 130 is identified with "80+", so this
-	 * is encoded with two octets 130 and 128. Similarly, operating class
-	 * value pair 133 and 135 is used to describe a 80+80 MHz channel on
-	 * the 6 GHz band (135 being the one with "80+" indication). All other
-	 * operating classes listed here are used as 1-octet values.
 	 */
 	{ HOSTAPD_MODE_IEEE80211A, 128, 36, 177, 4, BW80, P2P_SUPP },
 	{ HOSTAPD_MODE_IEEE80211A, 129, 36, 177, 4, BW160, P2P_SUPP },
-	{ HOSTAPD_MODE_IEEE80211A, 130, 36, 177, 4, BW80P80, P2P_SUPP },
 	{ HOSTAPD_MODE_IEEE80211A, 131, 1, 233, 4, BW20, P2P_SUPP },
 	{ HOSTAPD_MODE_IEEE80211A, 132, 1, 233, 8, BW40, P2P_SUPP },
 	{ HOSTAPD_MODE_IEEE80211A, 133, 1, 233, 16, BW80, P2P_SUPP },
@@ -2442,9 +2426,6 @@
 	{ HOSTAPD_MODE_IEEE80211A, 135, 1, 233, 16, BW80P80, NO_P2P_SUPP },
 	{ HOSTAPD_MODE_IEEE80211A, 136, 2, 2, 4, BW20, NO_P2P_SUPP },
 
-	/* IEEE P802.11be/D5.0, Table E-4 (Global operating classes) */
-	{ HOSTAPD_MODE_IEEE80211A, 137, 31, 191, 32, BW320, NO_P2P_SUPP },
-
 	/*
 	 * IEEE Std 802.11ad-2012 and P802.ay/D5.0 60 GHz operating classes.
 	 * Class 180 has the legacy channels 1-6. Classes 181-183 include
@@ -2455,6 +2436,11 @@
 	{ HOSTAPD_MODE_IEEE80211AD, 182, 17, 20, 1, BW6480, P2P_SUPP },
 	{ HOSTAPD_MODE_IEEE80211AD, 183, 25, 27, 1, BW8640, P2P_SUPP },
 
+	/* Keep the operating class 130 as the last entry as a workaround for
+	 * the OneHundredAndThirty Delimiter value used in the Supported
+	 * Operating Classes element to indicate the end of the Operating
+	 * Classes field. */
+	{ HOSTAPD_MODE_IEEE80211A, 130, 36, 177, 4, BW80P80, P2P_SUPP },
 	{ -1, 0, 0, 0, 0, BW20, NO_P2P_SUPP }
 };
 
@@ -2521,6 +2507,35 @@
 
 
 /**
+ * get_ie_nth - Fetch a specified information element from IEs buffer
+ * @ies: Information elements buffer
+ * @len: Information elements buffer length
+ * @eid: Information element identifier (WLAN_EID_*)
+ * @nth: Return the nth element of the requested type (2 returns the second)
+ * Returns: Pointer to the information element (id field) or %NULL if not found
+ *
+ * This function returns the nth matching information element in the IEs
+ * buffer or %NULL in case the element is not found.
+ */
+const u8 * get_ie_nth(const u8 *ies, size_t len, u8 eid, int nth)
+{
+	const struct element *elem;
+	int sofar = 0;
+
+	if (!ies)
+		return NULL;
+
+	for_each_element_id(elem, eid, ies, len) {
+		sofar++;
+		if (sofar == nth)
+			return &elem->id;
+	}
+
+	return NULL;
+}
+
+
+/**
  * get_ie_ext - Fetch a specified extended information element from IEs buffer
  * @ies: Information elements buffer
  * @len: Information elements buffer length
@@ -2582,141 +2597,21 @@
 }
 
 
-u16 check_multi_ap_ie(const u8 *multi_ap_ie, size_t multi_ap_len,
-		      struct multi_ap_params *multi_ap)
-{
-	const struct element *elem;
-	bool ext_present = false;
-	unsigned int vlan_id;
-
-	os_memset(multi_ap, 0, sizeof(*multi_ap));
-
-	/* Default profile is 1, when Multi-AP profile subelement is not
-	 * present in the element. */
-	multi_ap->profile = 1;
-
-	for_each_element(elem, multi_ap_ie, multi_ap_len) {
-		u8 id = elem->id, elen = elem->datalen;
-		const u8 *pos = elem->data;
-
-		switch (id) {
-		case MULTI_AP_SUB_ELEM_TYPE:
-			if (elen >= 1) {
-				multi_ap->capability = *pos;
-				ext_present = true;
-			} else {
-				wpa_printf(MSG_DEBUG,
-					   "Multi-AP invalid Multi-AP subelement");
-				return WLAN_STATUS_INVALID_IE;
-			}
-			break;
-		case MULTI_AP_PROFILE_SUB_ELEM_TYPE:
-			if (elen < 1) {
-				wpa_printf(MSG_DEBUG,
-					   "Multi-AP IE invalid Multi-AP profile subelement");
-				return WLAN_STATUS_INVALID_IE;
-			}
-
-			multi_ap->profile = *pos;
-			if (multi_ap->profile > MULTI_AP_PROFILE_MAX) {
-				wpa_printf(MSG_DEBUG,
-					   "Multi-AP IE with invalid profile 0x%02x",
-					   multi_ap->profile);
-				return WLAN_STATUS_ASSOC_DENIED_UNSPEC;
-			}
-			break;
-		case MULTI_AP_VLAN_SUB_ELEM_TYPE:
-			if (multi_ap->profile < MULTI_AP_PROFILE_2) {
-				wpa_printf(MSG_DEBUG,
-					   "Multi-AP IE invalid profile to read VLAN IE");
-				return WLAN_STATUS_INVALID_IE;
-			}
-			if (elen < 2) {
-				wpa_printf(MSG_DEBUG,
-					   "Multi-AP IE invalid Multi-AP VLAN subelement");
-				return WLAN_STATUS_INVALID_IE;
-			}
-
-			vlan_id = WPA_GET_LE16(pos);
-			if (vlan_id < 1 || vlan_id > 4094) {
-				wpa_printf(MSG_INFO,
-					   "Multi-AP IE invalid Multi-AP VLAN ID %d",
-					   vlan_id);
-				return WLAN_STATUS_INVALID_IE;
-			}
-			multi_ap->vlanid = vlan_id;
-			break;
-		default:
-			wpa_printf(MSG_DEBUG,
-				   "Ignore unknown subelement %u in Multi-AP IE",
-				   id);
-			break;
-		}
-	}
-
-	if (!for_each_element_completed(elem, multi_ap_ie, multi_ap_len)) {
-		wpa_printf(MSG_DEBUG, "Multi AP IE parse failed @%d",
-			   (int) (multi_ap_ie + multi_ap_len -
-				  (const u8 *) elem));
-		wpa_hexdump(MSG_MSGDUMP, "IEs", multi_ap_ie, multi_ap_len);
-	}
-
-	if (!ext_present) {
-		wpa_printf(MSG_DEBUG,
-			   "Multi-AP element without Multi-AP Extension subelement");
-		return WLAN_STATUS_INVALID_IE;
-	}
-
-	return WLAN_STATUS_SUCCESS;
-}
-
-
-size_t add_multi_ap_ie(u8 *buf, size_t len,
-		       const struct multi_ap_params *multi_ap)
+size_t add_multi_ap_ie(u8 *buf, size_t len, u8 value)
 {
 	u8 *pos = buf;
-	u8 *len_ptr;
 
-	if (len < 6)
+	if (len < 9)
 		return 0;
 
 	*pos++ = WLAN_EID_VENDOR_SPECIFIC;
-	len_ptr = pos; /* Length field to be set at the end */
-	pos++;
+	*pos++ = 7; /* len */
 	WPA_PUT_BE24(pos, OUI_WFA);
 	pos += 3;
 	*pos++ = MULTI_AP_OUI_TYPE;
-
-	/* Multi-AP Extension subelement */
-	if (buf + len - pos < 3)
-		return 0;
 	*pos++ = MULTI_AP_SUB_ELEM_TYPE;
 	*pos++ = 1; /* len */
-	*pos++ = multi_ap->capability;
-
-	/* Add Multi-AP Profile subelement only for R2 or newer configuration */
-	if (multi_ap->profile >= MULTI_AP_PROFILE_2) {
-		if (buf + len - pos < 3)
-			return 0;
-		*pos++ = MULTI_AP_PROFILE_SUB_ELEM_TYPE;
-		*pos++ = 1;
-		*pos++ = multi_ap->profile;
-	}
-
-	/* Add Multi-AP Default 802.1Q Setting subelement only for backhaul BSS
-	 */
-	if (multi_ap->vlanid &&
-	    multi_ap->profile >= MULTI_AP_PROFILE_2 &&
-	    (multi_ap->capability & MULTI_AP_BACKHAUL_BSS)) {
-		if (buf + len - pos < 4)
-			return 0;
-		*pos++ = MULTI_AP_VLAN_SUB_ELEM_TYPE;
-		*pos++ = 2;
-		WPA_PUT_LE16(pos, multi_ap->vlanid);
-		pos += 2;
-	}
-
-	*len_ptr = pos - len_ptr - 1;
+	*pos++ = value;
 
 	return pos - buf;
 }
@@ -2881,8 +2776,6 @@
 	case BW80P80:
 	case BW160:
 		return 160;
-	case BW320:
-		return 320;
 	case BW2160:
 		return 2160;
 	default:
@@ -2981,21 +2874,6 @@
 }
 
 
-bool is_same_band(int freq1, int freq2)
-{
-	if (IS_2P4GHZ(freq1) && IS_2P4GHZ(freq2))
-		return true;
-
-	if (IS_5GHZ(freq1) && IS_5GHZ(freq2))
-		return true;
-
-	if (is_6ghz_freq(freq1) && is_6ghz_freq(freq2))
-		return true;
-
-	return false;
-}
-
-
 int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
 				    size_t nei_rep_len)
 {
@@ -3334,39 +3212,8 @@
 }
 
 
-/**
- * chwidth_freq2_to_ch_width - Determine channel width as enum oper_chan_width
- * @chwidth: Channel width integer
- * @freq2: Value for frequency 2. 0 is not used
- * Returns: enum oper_chan_width, -1 on failure
- */
-int chwidth_freq2_to_ch_width(int chwidth, int freq2)
-{
-	if (freq2 < 0)
-		return -1;
-	if (freq2)
-		return CONF_OPER_CHWIDTH_80P80MHZ;
-
-	switch (chwidth) {
-	case 0:
-	case 20:
-	case 40:
-		return CONF_OPER_CHWIDTH_USE_HT;
-	case 80:
-		return CONF_OPER_CHWIDTH_80MHZ;
-	case 160:
-		return CONF_OPER_CHWIDTH_160MHZ;
-	case 320:
-		return CONF_OPER_CHWIDTH_320MHZ;
-	default:
-		wpa_printf(MSG_DEBUG, "Unknown max oper bandwidth: %d",
-			   chwidth);
-		return -1;
-	}
-}
-
-
-struct wpabuf * ieee802_11_defrag(const u8 *data, size_t len, bool ext_elem)
+struct wpabuf * ieee802_11_defrag_data(const u8 *data, size_t len,
+				       bool ext_elem)
 {
 	struct wpabuf *buf;
 	const u8 *pos, *end = data + len;
@@ -3406,42 +3253,43 @@
 }
 
 
-const u8 * get_ml_ie(const u8 *ies, size_t len, u8 type)
+struct wpabuf * ieee802_11_defrag(struct ieee802_11_elems *elems,
+				  u8 eid, u8 eid_ext)
 {
-	const struct element *elem;
+	const u8 *data;
+	size_t len;
 
-	if (!ies)
+	/*
+	 * TODO: Defragmentation mechanism can be supported for all IEs. For now
+	 * handle only those that are used (or use ieee802_11_defrag_data()).
+	 */
+	switch (eid) {
+	case WLAN_EID_EXTENSION:
+		switch (eid_ext) {
+		case WLAN_EID_EXT_FILS_HLP_CONTAINER:
+			data = elems->fils_hlp;
+			len = elems->fils_hlp_len;
+			break;
+		case WLAN_EID_EXT_WRAPPED_DATA:
+			data = elems->wrapped_data;
+			len = elems->wrapped_data_len;
+			break;
+		default:
+			wpa_printf(MSG_DEBUG,
+				   "Defragmentation not supported. eid_ext=%u",
+				   eid_ext);
+			return NULL;
+		}
+		break;
+	default:
+		wpa_printf(MSG_DEBUG,
+			   "Defragmentation not supported. eid=%u", eid);
 		return NULL;
-
-	for_each_element_extid(elem, WLAN_EID_EXT_MULTI_LINK, ies, len) {
-		if (elem->datalen >= 2 &&
-		    (elem->data[1] & MULTI_LINK_CONTROL_TYPE_MASK) == type)
-			return &elem->id;
 	}
 
-	return NULL;
+	return ieee802_11_defrag_data(data, len, true);
 }
 
-
-const u8 * get_basic_mle_mld_addr(const u8 *buf, size_t len)
-{
-	const size_t mld_addr_pos =
-		2 /* Control field */ +
-		1 /* Common Info Length field */;
-	const size_t fixed_len = mld_addr_pos +
-		ETH_ALEN /* MLD MAC Address field */;
-
-	if (len < fixed_len)
-		return NULL;
-
-	if ((buf[0] & MULTI_LINK_CONTROL_TYPE_MASK) !=
-	    MULTI_LINK_CONTROL_TYPE_BASIC)
-		return NULL;
-
-	return &buf[mld_addr_pos];
-}
-
-
 /* Parse HT capabilities to get maximum number of supported spatial streams */
 static int parse_ht_mcs_set_for_max_nss(
 				struct ieee80211_ht_capabilities *htcaps,
@@ -3571,7 +3419,6 @@
 	return supported_width;
 }
 
-
 /*
  * Parse VHT operation info fields to get operation channel width
  * note that VHT operation info fields could come from VHT operation IE
@@ -3606,7 +3453,6 @@
 	return channel_width;
 }
 
-
 /* Parse 6GHz operation info fields to get operation channel width */
 static enum chan_width get_6ghz_operation_channel_width(
 				struct ieee80211_6ghz_operation_info * six_ghz_oper_info)
@@ -3679,7 +3525,6 @@
 	return channel_width;
 }
 
-
 /* Parse EHT operation IE to get EHT operation channel width */
 static enum chan_width get_eht_operation_channel_width(
 				struct ieee80211_eht_operation *eht_oper,
@@ -3713,7 +3558,6 @@
 	return channel_width;
 }
 
-
 /* Parse HT/VHT/HE operation IEs to get operation channel width */
 enum chan_width get_operation_channel_width(struct ieee802_11_elems *elems)
 {
@@ -3750,8 +3594,6 @@
 	return channel_width;
 }
 
-
-
 /*
  * Get STA operation channel width from AP's operation channel width and
  *  STA's supported channel width
@@ -3773,6 +3615,78 @@
 	return ap_operation_chan_width;
 }
 
+const u8 * get_ml_ie(const u8 *ies, size_t len, u8 type)
+{
+	const struct element *elem;
+
+	if (!ies)
+		return NULL;
+
+	for_each_element_extid(elem, WLAN_EID_EXT_MULTI_LINK, ies, len) {
+		if (elem->datalen >= 2 &&
+		    (elem->data[1] & MULTI_LINK_CONTROL_TYPE_MASK) == type)
+			return &elem->id;
+	}
+
+	return NULL;
+}
+
+
+const u8 * get_basic_mle_mld_addr(const u8 *buf, size_t len)
+{
+	const size_t mld_addr_pos =
+		2 /* Control field */ +
+		1 /* Common Info Length field */;
+	const size_t fixed_len = mld_addr_pos +
+		ETH_ALEN /* MLD MAC Address field */;
+
+	if (len < fixed_len)
+		return NULL;
+
+	if ((buf[0] & MULTI_LINK_CONTROL_TYPE_MASK) !=
+	    MULTI_LINK_CONTROL_TYPE_BASIC)
+		return NULL;
+
+	return &buf[mld_addr_pos];
+}
+
+
+struct wpabuf * ieee802_11_defrag_mle(struct ieee802_11_elems *elems, u8 type)
+{
+	const u8 *data;
+	size_t len;
+
+	switch (type) {
+	case MULTI_LINK_CONTROL_TYPE_BASIC:
+		data = elems->basic_mle;
+		len = elems->basic_mle_len;
+		break;
+	case MULTI_LINK_CONTROL_TYPE_PROBE_REQ:
+		data = elems->probe_req_mle;
+		len = elems->probe_req_mle_len;
+		break;
+	case MULTI_LINK_CONTROL_TYPE_RECONF:
+		data = elems->reconf_mle;
+		len = elems->reconf_mle_len;
+		break;
+	case MULTI_LINK_CONTROL_TYPE_TDLS:
+		data = elems->tdls_mle;
+		len = elems->tdls_mle_len;
+		break;
+	case MULTI_LINK_CONTROL_TYPE_PRIOR_ACCESS:
+		data = elems->prior_access_mle;
+		len = elems->prior_access_mle_len;
+		break;
+	default:
+		wpa_printf(MSG_DEBUG,
+			   "Defragmentation not supported for Multi-Link element type=%u",
+			   type);
+		return NULL;
+	}
+
+	return ieee802_11_defrag_data(data, len, true);
+}
+
 
 unsigned int is_ap_t2lm_negotiation_supported(const u8 *mle, size_t mle_len)
 {
diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
index 56eb0df..6f4fe80 100644
--- a/src/common/ieee802_11_common.h
+++ b/src/common/ieee802_11_common.h
@@ -30,12 +30,6 @@
 	u8 nof_ies;
 };
 
-struct multi_ap_params {
-	u8 capability;
-	u8 profile;
-	u16 vlanid;
-};
-
 /* Parsed Information Elements */
 struct ieee802_11_elems {
 	const u8 *ssid;
@@ -241,7 +235,6 @@
 int ieee80211_is_dfs(int freq, const struct hostapd_hw_modes *modes,
 		     u16 num_modes);
 int is_dfs_global_op_class(u8 op_class);
-bool is_80plus_op_class(u8 op_class);
 enum phy_type ieee80211_get_phy_type(int freq, int ht, int vht);
 
 int supp_rates_11b_only(struct ieee802_11_elems *elems);
@@ -260,7 +253,7 @@
 	u8 max_chan;
 	u8 inc;
 	enum { BW20, BW40PLUS, BW40MINUS, BW40, BW80, BW2160, BW160, BW80P80,
-	       BW320, BW4320, BW6480, BW8640} bw;
+	       BW4320, BW6480, BW8640} bw;
 	enum { P2P_SUPP, NO_P2P_SUPP } p2p;
 };
 
@@ -268,15 +261,13 @@
 extern size_t global_op_class_size;
 
 const u8 * get_ie(const u8 *ies, size_t len, u8 eid);
+const u8 * get_ie_nth(const u8 *ies, size_t len, u8 eid, int nth);
 const u8 * get_ie_ext(const u8 *ies, size_t len, u8 ext);
 const u8 * get_vendor_ie(const u8 *ies, size_t len, u32 vendor_type);
 
 size_t mbo_add_ie(u8 *buf, size_t len, const u8 *attr, size_t attr_len);
 
-u16 check_multi_ap_ie(const u8 *multi_ap_ie, size_t multi_ap_len,
-		      struct multi_ap_params *multi_ap);
-size_t add_multi_ap_ie(u8 *buf, size_t len,
-		       const struct multi_ap_params *multi_ap);
+size_t add_multi_ap_ie(u8 *buf, size_t len, u8 value);
 
 struct country_op_class {
 	u8 country_op_class;
@@ -293,10 +284,6 @@
 bool is_6ghz_psc_frequency(int freq);
 int get_6ghz_sec_channel(int channel);
 
-bool is_same_band(int freq1, int freq2);
-#define IS_2P4GHZ(n) (n >= 2412 && n <= 2484)
-#define IS_5GHZ(n) (n > 4000 && n < 5895)
-
 int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
 				    size_t nei_rep_len);
 
@@ -306,7 +293,6 @@
 bool ieee802_11_rsnx_capab(const u8 *rsnxe, unsigned int capab);
 int op_class_to_bandwidth(u8 op_class);
 enum oper_chan_width op_class_to_ch_width(u8 op_class);
-int chwidth_freq2_to_ch_width(int chwidth, int freq2);
 
 /* element iteration helpers */
 #define for_each_element(_elem, _data, _datalen)			\
@@ -364,7 +350,11 @@
 int ieee802_edmg_is_allowed(struct ieee80211_edmg_config allowed,
 			    struct ieee80211_edmg_config requested);
 
-struct wpabuf * ieee802_11_defrag(const u8 *data, size_t len, bool ext_elem);
+struct wpabuf * ieee802_11_defrag_data(const u8 *data, size_t len,
+				       bool ext_elem);
+struct wpabuf * ieee802_11_defrag(struct ieee802_11_elems *elems,
+				  u8 eid, u8 eid_ext);
+struct wpabuf * ieee802_11_defrag_mle(struct ieee802_11_elems *elems, u8 type);
 const u8 * get_ml_ie(const u8 *ies, size_t len, u8 type);
 const u8 * get_basic_mle_mld_addr(const u8 *buf, size_t len);
 
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index 644bebd..a895f9c 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -24,13 +24,6 @@
 #define WLAN_FC_ISWEP		0x4000
 #define WLAN_FC_HTC		0x8000
 
-#define WLAN_FC_S1G_BEACON_NEXT_TBTT	0x0100
-#define WLAN_FC_S1G_BEACON_COMP_SSID	0x0200
-#define WLAN_FC_S1G_BEACON_ANO		0x0400
-#define WLAN_FC_S1G_BEACON_BSS_BW	0x3800
-#define WLAN_FC_S1G_BEACON_SECURITY	0x4000
-#define WLAN_FC_S1G_BEACON_AP_PM	0x8000
-
 #define WLAN_FC_GET_TYPE(fc)	(((fc) & 0x000c) >> 2)
 #define WLAN_FC_GET_STYPE(fc)	(((fc) & 0x00f0) >> 4)
 
@@ -43,7 +36,6 @@
 #define WLAN_FC_TYPE_MGMT		0
 #define WLAN_FC_TYPE_CTRL		1
 #define WLAN_FC_TYPE_DATA		2
-#define WLAN_FC_TYPE_EXT		3
 
 /* management */
 #define WLAN_FC_STYPE_ASSOC_REQ		0
@@ -85,10 +77,6 @@
 #define WLAN_FC_STYPE_QOS_CFPOLL	14
 #define WLAN_FC_STYPE_QOS_CFACKPOLL	15
 
-/* extension */
-#define WLAN_FC_STYPE_DMG_BEACON	0
-#define WLAN_FC_STYPE_S1G_BEACON	1
-
 /* Authentication algorithms */
 #define WLAN_AUTH_OPEN			0
 #define WLAN_AUTH_SHARED_KEY		1
@@ -119,7 +107,7 @@
 #define WLAN_CAPABILITY_DELAYED_BLOCK_ACK BIT(14)
 #define WLAN_CAPABILITY_IMM_BLOCK_ACK BIT(15)
 
-/* Status codes (IEEE Std 802.11-2020, 9.4.1.9, Table 9-50) */
+/* Status codes (IEEE Std 802.11-2016, 9.4.1.9, Table 9-46) */
 #define WLAN_STATUS_SUCCESS 0
 #define WLAN_STATUS_UNSPECIFIED_FAILURE 1
 #define WLAN_STATUS_TDLS_WAKEUP_ALTERNATE 2
@@ -221,20 +209,11 @@
 #define WLAN_STATUS_DENIED_HE_NOT_SUPPORTED 124
 #define WLAN_STATUS_SAE_HASH_TO_ELEMENT 126
 #define WLAN_STATUS_SAE_PK 127
-#define WLAN_STATUS_DENIED_STA_AFF_WITH_MLD_WITH_EXISTING_ASSOC 130
-#define WLAN_STATUS_EPCS_DENIED_UNAUTHORIZED 131
-#define WLAN_STATUS_EPCS_DENIED 132
-#define WLAN_STATUS_DENIED_TID_TO_LINK_MAPPING 133
-#define WLAN_STATUS_PREFERRED_TID_TO_LINK_MAPPING_SUGGESTED 134
-#define WLAN_STATUS_DENIED_EHT_NOT_SUPPORTED 135
 #define WLAN_STATUS_INVALID_PUBLIC_KEY 136
 #define WLAN_STATUS_PASN_BASE_AKMP_FAILED 137
 #define WLAN_STATUS_OCI_MISMATCH 138
-#define WLAN_STATUS_DENIED_TX_LINK_NOT_ACCEPTED 139
-#define WLAN_STATUS_EPCS_DENIED_VERIFICATION_FAILURE 140
-#define WLAN_STATUS_DENIED_OPERATION_PARAMETER_UPDATE 141
 
-/* Reason codes (IEEE Std 802.11-2020, 9.4.1.7, Table 9-90) */
+/* Reason codes (IEEE Std 802.11-2016, 9.4.1.7, Table 9-45) */
 #define WLAN_REASON_UNSPECIFIED 1
 #define WLAN_REASON_PREV_AUTH_NOT_VALID 2
 #define WLAN_REASON_DEAUTH_LEAVING 3
@@ -298,7 +277,7 @@
 #define WLAN_REASON_MESH_CHANNEL_SWITCH_UNSPECIFIED 66
 
 
-/* Element IDs (IEEE Std 802.11-2020, 9.4.2.1, Table 9-92) */
+/* Information Element IDs (IEEE Std 802.11-2016, 9.4.2.1, Table 9-77) */
 #define WLAN_EID_SSID 0
 #define WLAN_EID_SUPP_RATES 1
 #define WLAN_EID_DS_PARAMS 3
@@ -620,7 +599,7 @@
 /* Multiple BSSID element subelements */
 #define WLAN_MBSSID_SUBELEMENT_NONTRANSMITTED_BSSID_PROFILE 0
 
-/* Action frame categories (IEEE Std 802.11-2020, 9.4.1.11, Table 9-51) */
+/* Action frame categories (IEEE Std 802.11-2016, 9.4.1.11, Table 9-76) */
 #define WLAN_ACTION_SPECTRUM_MGMT 0
 #define WLAN_ACTION_QOS 1
 #define WLAN_ACTION_DLS 2
@@ -661,7 +640,7 @@
 #define WLAN_ACTION_VENDOR_SPECIFIC 127
 /* Note: 128-255 used to report errors by setting category | 0x80 */
 
-/* Public action codes (IEEE Std 802.11-2020, 9.6.7.1, Table 9-364) */
+/* Public action codes (IEEE Std 802.11-2016, 9.6.8.1, Table 9-307) */
 #define WLAN_PA_20_40_BSS_COEX 0
 #define WLAN_PA_DSE_ENABLEMENT 1
 #define WLAN_PA_DSE_DEENABLEMENT 2
@@ -712,8 +691,8 @@
 #define WLAN_VHT_ACTION_GROUP_ID_MGMT 1
 #define WLAN_VHT_ACTION_OPMODE_NOTIF 2
 
-/* Protected Dual of Public Action frames (IEEE Std 802.11-2020, 9.6.10,
- * Table 9-404) */
+/* Protected Dual of Public Action frames (IEEE Std 802.11-2016, 9.6.11,
+ * Table 9-332) */
 #define WLAN_PROT_DSE_ENABLEMENT 1
 #define WLAN_PROT_DSE_DEENABLEMENT 2
 #define WLAN_PROT_EXT_CSA 4
@@ -741,7 +720,7 @@
 #define WLAN_PROT_NETWORK_CHANNEL_CONTROL 30
 #define WLAN_PROT_WHITE_SPACE_MAP_ANNOUNCEMENT 31
 
-/* SA Query Action frame (IEEE Std 802.11-2020, 9.6.9) */
+/* SA Query Action frame (IEEE 802.11w/D8.0, 7.4.9) */
 #define WLAN_SA_QUERY_REQUEST 0
 #define WLAN_SA_QUERY_RESPONSE 1
 
@@ -774,7 +753,7 @@
 #define WLAN_PROT_FTM_REPORT 3
 
 /* Radio Measurement capabilities (from RM Enabled Capabilities element)
- * IEEE Std 802.11-2020, 9.4.2.44, Table 9-179 */
+ * IEEE Std 802.11-2016, 9.4.2.45, Table 9-157 */
 /* byte 1 (out of 5) */
 #define WLAN_RRM_CAPS_LINK_MEASUREMENT BIT(0)
 #define WLAN_RRM_CAPS_NEIGHBOR_REPORT BIT(1)
@@ -787,8 +766,8 @@
 #define WLAN_RRM_CAPS_FTM_RANGE_REPORT BIT(2)
 
 /*
- * IEEE Std 802.11-2020, 9.4.2.20.19 (Fine Timing Measurement Range
- * request) - Minimum AP Count
+ * IEEE P802.11-REVmc/D5.0, 9.4.2.21.19 (Fine Timing Measurement Range
+ * request) - Minimum AP count
  */
 #define WLAN_RRM_RANGE_REQ_MAX_MIN_AP 15
 
@@ -797,8 +776,7 @@
 #define WLAN_TIMEOUT_KEY_LIFETIME 2
 #define WLAN_TIMEOUT_ASSOC_COMEBACK 3
 
-/* Interworking element (IEEE Std 802.11-2020, 9.4.2.91) -
- * Access Network Options */
+/* Interworking element (IEEE 802.11u) - Access Network Options */
 #define INTERWORKING_ANO_ACCESS_NETWORK_MASK 0x0f
 #define INTERWORKING_ANO_INTERNET 0x10
 #define INTERWORKING_ANO_ASRA 0x20
@@ -814,7 +792,7 @@
 #define INTERWORKING_ANT_TEST 6
 #define INTERWORKING_ANT_WILDCARD 15
 
-/* Advertisement Protocol ID definitions (IEEE Std 802.11-2020, Table 9-237) */
+/* Advertisement Protocol ID definitions (IEEE Std 802.11-2016, Table 9-215) */
 enum adv_proto_id {
 	ACCESS_NETWORK_QUERY_PROTOCOL = 0,
 	MIH_INFO_SERVICE = 1,
@@ -824,7 +802,8 @@
 	ADV_PROTO_VENDOR_SPECIFIC = 221
 };
 
-/* ANQP-element definitions (IEEE Std 802.11-2020, Table 9-331) */
+/* Access Network Query Protocol info ID definitions (IEEE Std 802.11-2016,
+ * Table 9-271; P802.11ai) */
 enum anqp_info_id {
 	ANQP_QUERY_LIST = 256,
 	ANQP_CAPABILITY_LIST = 257,
@@ -899,7 +878,7 @@
 #define S1G_ACT_TWT_INFORMATION      11
 
 /*
- * IEEE Std 802.11-2020, Table 9-98 - Measurement type definitions for
+ * IEEE P802.11-REVmc/D5.0 Table 9-81 - Measurement type definitions for
  * measurement requests
  */
 enum measure_type {
@@ -923,7 +902,7 @@
 	MEASURE_TYPE_MEASURE_PAUSE = 255,
 };
 
-/* IEEE Std 802.11-2020, Table 9-110 - Location Subject field definition */
+/* IEEE Std 802.11-2012 Table 8-71 - Location subject definition */
 enum location_subject {
 	LOCATION_SUBJECT_LOCAL = 0,
 	LOCATION_SUBJECT_REMOTE = 1,
@@ -931,7 +910,7 @@
 };
 
 /*
- * IEEE Std 802.11-2020, Table 9-111 - Optional subelement IDs for LCI request
+ * IEEE P802.11-REVmc/D5.0 Table 9-94 - Optional subelement IDs for LCI request
  */
 enum lci_req_subelem {
 	LCI_REQ_SUBELEM_AZIMUTH_REQ = 1,
@@ -966,23 +945,6 @@
 
 #define IEEE80211_HDRLEN (sizeof(struct ieee80211_hdr))
 
-struct ieee80211_hdr_s1g_beacon {
-	le16 frame_control;
-	le16 duration_id;
-	u8 sa[6];
-	u8 timestamp[4];
-	u8 change_seq[1];
-	/* followed by:
-	 *   'u8 next_tbtt[3];' if the Next TBTT Present field in the
-	 *			Frame Control field is 1
-	 *   'u8 compressed_ssid[4];' if the Compressed SSID Present field in
-	 *			the Frame Control is 1
-	 *   'u8 ano[1];' if the ANO field in the Frame Control field is 1
-	 */
-} STRUCT_PACKED;
-
-#define IEEE80211_HDRLEN_S1G_BEACON (sizeof(struct ieee80211_hdr_s1g_beacon))
-
 #define IEEE80211_FC(type, stype) host_to_le16((type << 2) | (stype << 4))
 
 struct ieee80211_mgmt {
@@ -1434,11 +1396,7 @@
 #define WFD_OUI_TYPE 10
 #define HS20_IE_VENDOR_TYPE 0x506f9a10
 #define OSEN_IE_VENDOR_TYPE 0x506f9a12
-#define NAN_IE_VENDOR_TYPE 0x506f9a13
-#define NAN_SDF_VENDOR_TYPE 0x506f9a13
-#define NAN_OUI_TYPE 0x13
 #define MBO_IE_VENDOR_TYPE 0x506f9a16
-#define NAN_NAF_VENDOR_TYPE 0x506f9a18
 #define MBO_OUI_TYPE 22
 #define OWE_IE_VENDOR_TYPE 0x506f9a1c
 #define OWE_OUI_TYPE 28
@@ -1453,20 +1411,11 @@
 #define WFA_CAPA_OUI_TYPE 0x23
 
 #define MULTI_AP_SUB_ELEM_TYPE 0x06
-#define MULTI_AP_PROFILE_SUB_ELEM_TYPE 0x07
-#define MULTI_AP_VLAN_SUB_ELEM_TYPE 0x08
-
-#define MULTI_AP_PROFILE2_BACKHAUL_STA_DISALLOWED BIT(2)
-#define MULTI_AP_PROFILE1_BACKHAUL_STA_DISALLOWED BIT(3)
 #define MULTI_AP_TEAR_DOWN BIT(4)
 #define MULTI_AP_FRONTHAUL_BSS BIT(5)
 #define MULTI_AP_BACKHAUL_BSS BIT(6)
 #define MULTI_AP_BACKHAUL_STA BIT(7)
 
-#define MULTI_AP_PROFILE_1	1
-#define MULTI_AP_PROFILE_2	2
-#define MULTI_AP_PROFILE_MAX	6
-
 #define WMM_OUI_TYPE 2
 #define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0
 #define WMM_OUI_SUBTYPE_PARAMETER_ELEMENT 1
@@ -1933,9 +1882,8 @@
 #define WNM_BSS_TM_REQ_DISASSOC_IMMINENT BIT(2)
 #define WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED BIT(3)
 #define WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT BIT(4)
-#define WNM_BSS_TM_REQ_LINK_REMOVAL_IMMINENT BIT(5)
 
-/* IEEE Std 802.11-2020, Table 9-428 (BTM status code definitions) */
+/* IEEE Std 802.11-2012 - Table 8-253 */
 enum bss_trans_mgmt_status_code {
 	WNM_BSS_TM_ACCEPT = 0,
 	WNM_BSS_TM_REJECT_UNSPECIFIED = 1,
@@ -1948,36 +1896,9 @@
 	WNM_BSS_TM_REJECT_LEAVING_ESS = 8
 };
 
-/* BSS transition management reasons
- * IEEE Std 802.11-2020, Table 9-198 (Transition and Transition Query reasons)
- */
-enum bss_trans_mgmt_reason {
-	WNM_TRANSITION_REASON_UNSPECIFIED = 0,
-	WNM_TRANSITION_REASON_EXCESSIVE_FRAME_LOSS = 1,
-	WNM_TRANSITION_REASON_EXCESSIVE_DELAY = 2,
-	WNM_TRANSITION_REASON_INSUFFICIENT_QOS = 3,
-	WNM_TRANSITION_REASON_FIRST_ESS_ASSOC = 4,
-	WNM_TRANSITION_REASON_LOAD_BALANCING = 5,
-	WNM_TRANSITION_REASON_BETTER_AP_FOUND = 6,
-	WNM_TRANSITION_REASON_DEAUTH_FROM_PREV_AP = 7,
-	WNM_TRANSITION_REASON_AP_FAILED_EAP = 8,
-	WNM_TRANSITION_REASON_AP_FAILED_4WAY_HS = 9,
-	WNM_TRANSITION_REASON_RX_TOO_MANY_REPLAYS = 10,
-	WNM_TRANSITION_REASON_RX_TOO_MANY_MIC_FAILURES = 11,
-	WNM_TRANSITION_REASON_EXCEEDED_MAX_RETRANS = 12,
-	WNM_TRANSITION_REASON_RX_TOO_MANY_BC_DISASSOC = 13,
-	WNM_TRANSITION_REASON_RX_TOO_MANY_BC_DEAUTH = 14,
-	WNM_TRANSITION_REASON_PREV_TRANSITION_FAILED = 15,
-	WNM_TRANSITION_REASON_LOW_RSSI = 16,
-	WNM_TRANSITION_REASON_ROAM_FROM_NON_802_11 = 17,
-	WNM_TRANSITION_REASON_TRANSITION_DUE_TO_BTM_REQ = 18,
-	WNM_TRANSITION_REASON_PREF_TRANSITION_CANDIDATE_LIST = 19,
-	WNM_TRANSITION_REASON_LEAVING_ESS = 20,
-};
-
 /*
- * IEEE Std 802.11-2020, Table 9-173 - Optional subelement IDs for
- * Neighbor Report
+ * IEEE P802.11-REVmc/D5.0 Table 9-150 - Optional subelement IDs for
+ * neighbor report
  */
 #define WNM_NEIGHBOR_TSF                         1
 #define WNM_NEIGHBOR_CONDENSED_COUNTRY_STRING    2
@@ -2004,7 +1925,7 @@
 	QOS_QOS_MAP_CONFIG = 4,
 };
 
-/* IEEE Std 802.11-2020, 9.4.2.59 (20/40 BSS Coexistence element) */
+/* IEEE Std 802.11-2012, 8.4.2.62 20/40 BSS Coexistence element */
 #define WLAN_20_40_BSS_COEX_INFO_REQ            BIT(0)
 #define WLAN_20_40_BSS_COEX_40MHZ_INTOL         BIT(1)
 #define WLAN_20_40_BSS_COEX_20MHZ_WIDTH_REQ     BIT(2)
@@ -2052,7 +1973,7 @@
 	WNM_SLEEP_SUBELEM_BIGTK = 2,
 };
 
-/* WNM notification type (IEEE Std 802.11-2020, Table 9-431) */
+/* WNM notification type (IEEE P802.11-REVmd/D3.0, Table 9-430) */
 enum wnm_notification_Type {
 	WNM_NOTIF_TYPE_FIRMWARE_UPDATE = 0,
 	WNM_NOTIF_TYPE_BEACON_PROTECTION_FAILURE = 2,
@@ -2128,7 +2049,7 @@
 
 #define RRM_CAPABILITIES_IE_LEN 5
 
-/* IEEE Std 802.11-2020, 9.6.6.4 - Link Measurement Request frame format */
+/* IEEE Std 802.11-2012, 8.5.7.4 - Link Measurement Request frame format */
 struct rrm_link_measurement_request {
 	u8 dialog_token;
 	s8 tx_power;
@@ -2136,7 +2057,7 @@
 	u8 variable[0];
 } STRUCT_PACKED;
 
-/* IEEE Std 802.11-2020, 9.6.6.5 - Link Measurement Report frame format */
+/* IEEE Std 802.11-2012, 8.5.7.5 - Link Measurement Report frame format */
 struct rrm_link_measurement_report {
 	u8 dialog_token;
 	struct tpc_report tpc;
@@ -2147,7 +2068,7 @@
 	u8 variable[0];
 } STRUCT_PACKED;
 
-/* IEEE Std 802.11-2020, 9.4.2.20 - Measurement Request element */
+/* IEEE Std 802.11-2016, 9.4.2.21 - Measurement Request element */
 struct rrm_measurement_request_element {
 	u8 eid; /* Element ID */
 	u8 len; /* Length */
@@ -2157,14 +2078,14 @@
 	u8 variable[0]; /* Measurement Request */
 } STRUCT_PACKED;
 
-/* IEEE Std 802.11-2020, Figure 9-180 - Measurement Request Mode field format */
+/* IEEE Std 802.11-2016, Figure 9-148 - Measurement Request Mode field */
 #define MEASUREMENT_REQUEST_MODE_PARALLEL BIT(0)
 #define MEASUREMENT_REQUEST_MODE_ENABLE BIT(1)
 #define MEASUREMENT_REQUEST_MODE_REQUEST BIT(2)
 #define MEASUREMENT_REQUEST_MODE_REPORT BIT(3)
 #define MEASUREMENT_REQUEST_MODE_DURATION_MANDATORY BIT(4)
 
-/* IEEE Std 802.11-2020, 9.4.2.20.7 - Beacon request */
+/* IEEE Std 802.11-2016, 9.4.2.21.7 - Beacon request */
 struct rrm_measurement_beacon_request {
 	u8 oper_class; /* Operating Class */
 	u8 channel; /* Channel Number */
@@ -2176,7 +2097,7 @@
 } STRUCT_PACKED;
 
 /*
- * IEEE Std 802.11-2020, Table 9-103 - Measurement Mode definitions for Beacon
+ * IEEE Std 802.11-2016, Table 9-87 - Measurement Mode definitions for Beacon
  * request
  */
 enum beacon_report_mode {
@@ -2185,19 +2106,20 @@
 	BEACON_REPORT_MODE_TABLE = 2,
 };
 
-/* IEEE Std 802.11-2020, Table 9-104 - Optional subelement IDs for
+/* IEEE Std 802.11-2016, Table 9-88 - Beacon Request subelement IDs */
+/* IEEE P802.11-REVmd/D2.0, Table 9-106 - Optional subelement IDs for
  * Beacon request */
 #define WLAN_BEACON_REQUEST_SUBELEM_SSID	0
 #define WLAN_BEACON_REQUEST_SUBELEM_INFO	1 /* Beacon Reporting */
 #define WLAN_BEACON_REQUEST_SUBELEM_DETAIL	2 /* Reporting Detail */
 #define WLAN_BEACON_REQUEST_SUBELEM_REQUEST	10
-#define WLAN_BEACON_REQUEST_SUBELEM_EXT_REQUEST	11
 #define WLAN_BEACON_REQUEST_SUBELEM_AP_CHANNEL	51 /* AP Channel Report */
-#define WLAN_BEACON_REQUEST_SUBELEM_WIDE_BW_CS	163
 #define WLAN_BEACON_REQUEST_SUBELEM_LAST_INDICATION	164
 #define WLAN_BEACON_REQUEST_SUBELEM_VENDOR	221
 
-/* IEEE Std 802.11-2020, Table 9-106 - Reporting Detail values */
+/*
+ * IEEE Std 802.11-2016, Table 9-90 - Reporting Detail values
+ */
 enum beacon_report_detail {
 	/* No fixed-length fields or elements */
 	BEACON_REPORT_DETAIL_NONE = 0,
@@ -2209,7 +2131,7 @@
 	BEACON_REPORT_DETAIL_ALL_FIELDS_AND_ELEMENTS = 2,
 };
 
-/* IEEE Std 802.11-2020, 9.4.2.21 - Measurement Report element */
+/* IEEE Std 802.11-2016, 9.4.2.22 - Measurement Report element */
 struct rrm_measurement_report_element {
 	u8 eid; /* Element ID */
 	u8 len; /* Length */
@@ -2219,13 +2141,13 @@
 	u8 variable[0]; /* Measurement Report */
 } STRUCT_PACKED;
 
-/* IEEE Std 802.11-2020, Figure 9-223 - Measurement Report Mode field */
+/* IEEE Std 802.11-2016, Figure 9-192 - Measurement Report Mode field */
 #define MEASUREMENT_REPORT_MODE_ACCEPT 0
 #define MEASUREMENT_REPORT_MODE_REJECT_LATE BIT(0)
 #define MEASUREMENT_REPORT_MODE_REJECT_INCAPABLE BIT(1)
 #define MEASUREMENT_REPORT_MODE_REJECT_REFUSED BIT(2)
 
-/* IEEE Std 802.11-2020, 9.4.2.21.7 - Beacon report */
+/* IEEE Std 802.11-2016, 9.4.2.22.7 - Beacon report */
 struct rrm_measurement_beacon_report {
 	u8 op_class; /* Operating Class */
 	u8 channel; /* Channel Number */
@@ -2241,23 +2163,23 @@
 	u8 variable[0]; /* Optional Subelements */
 } STRUCT_PACKED;
 
-/* IEEE Std 802.11-2020, Table 9-130 - Optional subelement IDs for
+/* IEEE Std 802.11-2016, Table 9-112 - Beacon report Subelement IDs */
+/* IEEE P802.11-REVmd/D2.0, Table 9-130 - Optional subelement IDs for
  * Beacon report */
 #define WLAN_BEACON_REPORT_SUBELEM_FRAME_BODY	1
 #define WLAN_BEACON_REPORT_SUBELEM_FRAME_BODY_FRAGMENT_ID	2
-#define WLAN_BEACON_REPORT_SUBELEM_WID_BW_CS	163
 #define WLAN_BEACON_REPORT_SUBELEM_LAST_INDICATION	164
 #define WLAN_BEACON_REPORT_SUBELEM_VENDOR	221
 
-/* IEEE Std 802.11-2020, Table 9-232 - Data field format (of the
- * Reported Frame Body Fragment ID subelement) */
+/* IEEE P802.11-REVmd/D2.0, Table 9-232 - Data field format of the
+ * Reported Frame Body Fragment ID subelement */
 #define REPORTED_FRAME_BODY_SUBELEM_LEN		4
 #define REPORTED_FRAME_BODY_MORE_FRAGMENTS	BIT(7)
 
-/* IEEE Std 802.11-2020, 9.4.2.21.7 - Beacon report  */
+/* IEEE P802.11-REVmd/D2.0, 9.4.2.21.7 - Beacon report  */
 #define BEACON_REPORT_LAST_INDICATION_SUBELEM_LEN	3
 
-/* IEEE Std 802.11-2020, 9.4.2.138 - Multi-band element */
+/* IEEE Std 802.11ad-2012 - Multi-band element */
 struct multi_band_ie {
 	u8 eid; /* WLAN_EID_MULTI_BAND */
 	u8 len;
@@ -2303,7 +2225,7 @@
 #define MB_CONNECTION_CAPABILITY_TDLS ((u8) (BIT(3)))
 #define MB_CONNECTION_CAPABILITY_IBSS ((u8) (BIT(4)))
 
-/* IEEE Std 802.11-2020, Table 9-479 - FST Action field values */
+/* IEEE Std 802.11ad-2014 - FST Action field */
 enum fst_action {
 	FST_ACTION_SETUP_REQUEST = 0,
 	FST_ACTION_SETUP_RESPONSE = 1,
@@ -2313,23 +2235,21 @@
 	FST_ACTION_ON_CHANNEL_TUNNEL = 5,
 };
 
-/* IEEE Std 802.11-2020, Annex C - dot11PHYType */
+/* IEEE Std 802.11ac-2013, Annex C - dot11PHYType */
 enum phy_type {
 	PHY_TYPE_UNSPECIFIED = 0,
+	PHY_TYPE_FHSS = 1,
 	PHY_TYPE_DSSS = 2,
+	PHY_TYPE_IRBASEBAND = 3,
 	PHY_TYPE_OFDM = 4,
 	PHY_TYPE_HRDSSS = 5,
 	PHY_TYPE_ERP = 6,
 	PHY_TYPE_HT = 7,
 	PHY_TYPE_DMG = 8,
 	PHY_TYPE_VHT = 9,
-	PHY_TYPE_TVHT = 10,
-	PHY_TYPE_S1G = 11,
-	PHY_TYPE_CDMG = 12,
-	PHY_TYPE_CMMG = 13,
 };
 
-/* IEEE Std 802.11-2020, 9.4.2.36 - Neighbor Report element */
+/* IEEE P802.11-REVmd/D3.0, 9.4.2.36 - Neighbor Report element */
 /* BSSID Information Field */
 #define NEI_REP_BSSID_INFO_AP_NOT_REACH BIT(0)
 #define NEI_REP_BSSID_INFO_AP_UNKNOWN_REACH BIT(1)
@@ -2350,7 +2270,7 @@
 #define NEI_REP_BSSID_INFO_EHT BIT(21)
 
 /*
- * IEEE Std 802.11-2020, Table 9-175 - HT/VHT Operation Information
+ * IEEE P802.11-REVmc/D5.0 Table 9-152 - HT/VHT Operation Information
  * subfields.
  * Note: These definitions are not the same as other CHANWIDTH_*.
  */
@@ -2514,31 +2434,16 @@
 #define HE_OPERATION_6GHZ_OPER_INFO_LEN 5
 
 /**
- * enum he_reg_info_6ghz_ap_type - Allowed Access Point types for 6 GHz Band
+ * enum he_6ghz_ap_type - Allowed Access Point types for 6 GHz Band
  *
- * IEEE P802.11-REVme/D4.0, Table E-12 (Regulatory Info subfield encoding)
+ * IEEE Std 802.11ax-2021, Table E-12 (Regulatory Info subfield encoding in the
+ * United States)
  */
-enum he_reg_info_6ghz_ap_type {
-	HE_REG_INFO_6GHZ_AP_TYPE_INDOOR         = 0,
-	HE_REG_INFO_6GHZ_AP_TYPE_SP		= 1,
-	HE_REG_INFO_6GHZ_AP_TYPE_VLP		= 2,
-	HE_REG_INFO_6GHZ_AP_TYPE_INDOOR_ENABLED	= 3,
-	HE_REG_INFO_6GHZ_AP_TYPE_INDOOR_SP	= 4,
-	HE_REG_INFO_6GHZ_AP_TYPE_MAX = HE_REG_INFO_6GHZ_AP_TYPE_INDOOR_SP,
+enum he_6ghz_ap_type {
+	HE_6GHZ_INDOOR_AP		= 0,
+	HE_6GHZ_STANDARD_POWER_AP	= 1,
 };
 
-static inline bool he_reg_is_indoor(enum he_reg_info_6ghz_ap_type type)
-{
-	return type == HE_REG_INFO_6GHZ_AP_TYPE_INDOOR ||
-		type == HE_REG_INFO_6GHZ_AP_TYPE_INDOOR_SP;
-}
-
-static inline bool he_reg_is_sp(enum he_reg_info_6ghz_ap_type type)
-{
-	return type == HE_REG_INFO_6GHZ_AP_TYPE_SP ||
-		type == HE_REG_INFO_6GHZ_AP_TYPE_INDOOR_SP;
-}
-
 /* Spatial Reuse defines */
 #define SPATIAL_REUSE_SRP_DISALLOWED		BIT(0)
 #define SPATIAL_REUSE_NON_SRG_OBSS_PD_SR_DISALLOWED	BIT(1)
@@ -2606,18 +2511,7 @@
 #define RNR_BSS_PARAM_MEMBER_CO_LOCATED_ESS         BIT(4)
 #define RNR_BSS_PARAM_UNSOLIC_PROBE_RESP_ACTIVE     BIT(5)
 #define RNR_BSS_PARAM_CO_LOCATED                    BIT(6)
-/* Maximum transmit power in Y/2 dBm (-127..126); 127 indicates no maximum
- * transmit power is specified for the corresponding 20 MHz channel. */
-#define RNR_20_MHZ_PSD_MAX_TXPOWER                  127
-
-/* IEEE P802.11be/D5.0, Figure 9-704c - MLD Parameters subfield format */
-/* B0..B7: AP MLD ID */
-/* B8..B11: Link ID */
-/* B12..B19: BSS Parameters Change Count */
-/* B20: All Updates Included */
-#define RNR_TBTT_INFO_MLD_PARAM2_ALL_UPDATE_INC 0x10
-/* B21: Disabled Link Indication */
-#define RNR_TBTT_INFO_MLD_PARAM2_LINK_DISABLED  0x20
+#define RNR_20_MHZ_PSD_MAX_TXPOWER                  255 /* dBm */
 
 /* IEEE P802.11be/D2.3, 9.4.2.311 - EHT Operation element */
 
@@ -2831,17 +2725,6 @@
 #define EHT_PER_STA_CTRL_NSTR_BM_SIZE_MSK             0x0400
 #define EHT_PER_STA_CTRL_BSS_PARAM_CNT_PRESENT_MSK    0x0800
 
-/* IEEE P802.11be/D4.1, Figure 9-1001x - STA Control field format for the
- * Reconfiguration Multi-Link element */
-#define EHT_PER_STA_RECONF_CTRL_LINK_ID_MSK        0x000f
-#define EHT_PER_STA_RECONF_CTRL_COMPLETE_PROFILE   0x0010
-#define EHT_PER_STA_RECONF_CTRL_MAC_ADDR           0x0020
-#define EHT_PER_STA_RECONF_CTRL_AP_REMOVAL_TIMER   0x0040
-#define EHT_PER_STA_RECONF_CTRL_OP_UPDATE_TYPE_MSK 0x0780
-#define EHT_PER_STA_RECONF_CTRL_OP_PARAMS          0x0800
-#define EHT_PER_STA_RECONF_CTRL_NSTR_BITMAP_SIZE   0x1000
-#define EHT_PER_STA_RECONF_CTRL_NSTR_INDIC_BITMAP  0x2000
-
 /* IEEE P802.11be/D2.0, 9.4.2.312.2.4 - Per-STA Profile subelement format */
 struct ieee80211_eht_per_sta_profile {
 	le16 sta_control;
@@ -2850,11 +2733,9 @@
 	u8 variable[];
 } STRUCT_PACKED;
 
-/* IEEE P802.11be/D4.0, 9.4.2.312.3 - Probe Request Multi-Link element
- * Presence Bitmap field is B4..B15 of the Multi-Link Control field, i.e.,
- * B0 in the presence bitmap is B4 in the control field. */
+/* IEEE P802.11be/D2.0, 9.4.2.312.3 - Probe Request Multi-Link element */
 
-#define EHT_ML_PRES_BM_PROBE_REQ_AP_MLD_ID 0x0010
+#define EHT_ML_PRES_BM_PROBE_REQ_AP_MLD_ID 0x0001
 
 struct eht_ml_probe_req_common_info {
 	u8 len;
@@ -2988,8 +2869,8 @@
 };
 
 /*
- * IEEE Std 802.11-2020, 9.6.7.36 FILS Discovery frame format,
- * Figure 9-900 - FILS Discovery Frame Control subfield format
+ * IEEE Std 802.11ai-2016, 9.6.8.36 FILS Discovery frame format,
+ * Figure 9-687b - FILS Discovery Frame Control subfield format
  */
 #define FD_FRAME_CTL_CAP_PRESENT			((u16) BIT(5))
 #define FD_FRAME_CTL_SHORT_SSID_PRESENT			((u16) BIT(6))
@@ -3002,8 +2883,8 @@
 #define FD_FRAME_CTL_MD_PRESENT				((u16) BIT(13))
 
 /*
- * IEEE Std 802.11-2020, 9.6.7.36 FILS Discovery frame format,
- * Figure 9-901 - FD Capability subfield format
+ * IEEE Std 802.11ai-2016, 9.6.8.36 FILS Discovery frame format,
+ * Figure 9-687c - FD Capability subfield format
  */
 #define FD_CAP_ESS					BIT(0)
 #define FD_CAP_PRIVACY					BIT(1)
@@ -3092,15 +2973,6 @@
 	u8 data[0];
 } STRUCT_PACKED;
 
-/* S1G Beacon Compatibility element */
-struct ieee80211_s1g_beacon_compat {
-	u8 element_id;
-	u8 length;
-	le16 compat_info;
-	le16 beacon_interval;
-	le32 tsf_completion;
-} STRUCT_PACKED;
-
 #ifdef _MSC_VER
 #pragma pack(pop)
 #endif /* _MSC_VER */
diff --git a/src/common/nan.h b/src/common/nan.h
deleted file mode 100644
index 19ab746..0000000
--- a/src/common/nan.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * NAN (Wi-Fi Aware) definitions
- * Copyright (c) 2024, Qualcomm Innovation Center, Inc.
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#ifndef NAN_H
-#define NAN_H
-
-enum nan_attr_id {
-	NAN_ATTR_MASTER_INDICATION = 0x00,
-	NAN_ATTR_CLUSTER = 0x01,
-	NAN_ATTR_NAN_ATTR_SERVICE_ID_LIST = 0x02,
-	NAN_ATTR_SDA = 0x03, /* Service Descriptor attribute */
-	NAN_ATTR_CONN_CAPA = 0x04,
-	NAN_ATTR_WLAN_INFRA = 0x05,
-	NAN_ATTR_P2P_OPER = 0x06,
-	NAN_ATTR_IBSS = 0x07,
-	NAN_ATTR_MESH = 0x08,
-	NAN_ATTR_FURTHER_NAN_SD = 0x09,
-	NAN_ATTR_FURTHER_AVAIL_MAP = 0x0A,
-	NAN_ATTR_COUNTRY_CODE = 0x0B,
-	NAN_ATTR_RANGIN = 0x0C,
-	NAN_ATTR_CLUSTER_DISCOVERY = 0x0D,
-	NAN_ATTR_SDEA = 0x0E, /* Service Descriptor Extension attribute */
-	NAN_ATTR_DEVICE_CAPABILITY = 0x0F,
-	NAN_ATTR_NDP = 0x10,
-	NAN_ATTR_NAN_AVAILABILITY = 0x12,
-	NAN_ATTR_NDC = 0x13,
-	NAN_ATTR_NDL = 0x14,
-	NAN_ATTR_NDL_QOS = 0x15,
-	NAN_ATTR_UNALIGNED_SCHEDULE = 0x17,
-	NAN_ATTR_RANGING_INFO = 0x1A,
-	NAN_ATTR_RANGING_SETUP = 0x1B,
-	NAN_ATTR_FTM_RANGING_REPORT = 0x1C,
-	NAN_ATTR_ELEM_CONTAINER = 0x1D,
-	NAN_ATTR_EXT_WLAN_INFRA = 0x1E,
-	NAN_ATTR_EXT_P2P_OPER = 0x1FE,
-	NAN_ATTR_EXT_IBSS = 0x20,
-	NAN_ATTR_EXT_MESH = 0x21,
-	NAN_ATTR_CSIA = 0x22, /* Cipher Suite Info attribute */
-	NAN_ATTR_SCIA = 0x23, /* Security Context Info attribute */
-	NAN_ATTR_SHARED_KEY_DESCR = 0x24,
-	NAN_ATTR_PUBLIC_AVAILABILITY = 0x27,
-	NAN_ATTR_SUBSC_SERVICE_ID_LIST = 0x28,
-	NAN_ATTR_NDP_EXT = 0x29,
-	NAN_ATTR_DCEA = 0x2A, /* Device Capability Extension attribute */
-	NAN_ATTR_NIRA = 0x2B, /* NAN Identity Resolution attribute */
-	NAN_ATTR_BPBA = 0x2C, /* NAN Pairing Bootstrapping attribute */
-	NAN_ATTR_S3 = 0x2D,
-	NAN_ATTR_TPEA = 0x2E, /* Transmit Power Envelope attribute */
-	NAN_ATTR_VENDOR_SPECIFIC = 0xDD,
-};
-
-/* Service Descriptor attribute (SDA) */
-
-/* Service Control field */
-#define NAN_SRV_CTRL_TYPE_MASK (BIT(0) | BIT(1))
-#define NAN_SRV_CTRL_MATCHING_FILTER BIT(2)
-#define NAN_SRV_CTRL_RESP_FILTER BIT(3)
-#define NAN_SRV_CTRL_SRV_INFO BIT(4)
-#define NAN_SRV_CTRL_DISCOVERY_RANGE_LIMITED BIT(5)
-#define NAN_SRV_CTRL_BINDING_BITMAP BIT(6)
-
-enum nan_service_control_type {
-	NAN_SRV_CTRL_PUBLISH = 0,
-	NAN_SRV_CTRL_SUBSCRIBE = 1,
-	NAN_SRV_CTRL_FOLLOW_UP = 2,
-};
-
-/* Service Descriptor Extension attribute (SDEA) */
-
-/* SDEA Control field */
-#define NAN_SDEA_CTRL_FSD_REQ BIT(0)
-#define NAN_SDEA_CTRL_FSD_GAS BIT(1)
-#define NAN_SDEA_CTRL_DATA_PATH_REQ BIT(2)
-#define NAN_SDEA_CTRL_DATA_PATH_TYPE BIT(3)
-#define NAN_SDEA_CTRL_QOS_REQ BIT(5)
-#define NAN_SDEA_CTRL_SECURITY_REQ BIT(6)
-#define NAN_SDEA_CTRL_RANGING_REQ BIT(7)
-#define NAN_SDEA_CTRL_RANGE_LIMIT BIT(8)
-#define NAN_SDEA_CTRL_SRV_UPD_INDIC BIT(9)
-#define NAN_SDEA_CTRL_GTK_REQ BIT(10)
-
-enum nan_service_protocol_type {
-	NAN_SRV_PROTO_BONJOUR = 1,
-	NAN_SRV_PROTO_GENERIC = 2,
-	NAN_SRV_PROTO_CSA_MATTER = 3,
-};
-
-#define NAN_ATTR_HDR_LEN 3
-#define NAN_SERVICE_ID_LEN 6
-
-#define NAN_USD_DEFAULT_FREQ 2437
-
-#endif /* NAN_H */
diff --git a/src/common/nan_de.c b/src/common/nan_de.c
deleted file mode 100644
index e1999a0..0000000
--- a/src/common/nan_de.c
+++ /dev/null
@@ -1,1389 +0,0 @@
-/*
- * NAN Discovery Engine
- * Copyright (c) 2024, Qualcomm Innovation Center, Inc.
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#include "utils/includes.h"
-
-#include "utils/common.h"
-#include "utils/eloop.h"
-#include "crypto/crypto.h"
-#include "crypto/sha256.h"
-#include "ieee802_11_defs.h"
-#include "nan.h"
-#include "nan_de.h"
-
-static const u8 nan_network_id[ETH_ALEN] =
-{ 0x51, 0x6f, 0x9a, 0x01, 0x00, 0x00 };
-static const u8 wildcard_bssid[ETH_ALEN] =
-{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-
-enum nan_de_service_type {
-	NAN_DE_PUBLISH,
-	NAN_DE_SUBSCRIBE,
-};
-
-struct nan_de_service {
-	int id;
-	enum nan_de_service_type type;
-	char *service_name;
-	u8 service_id[NAN_SERVICE_ID_LEN];
-	struct nan_publish_params publish;
-	struct nan_subscribe_params subscribe;
-	enum nan_service_protocol_type srv_proto_type;
-	struct wpabuf *ssi;
-	struct wpabuf *elems;
-	struct os_reltime time_started;
-	struct os_reltime end_time;
-	struct os_reltime last_multicast;
-	struct os_reltime first_discovered;
-	struct os_reltime last_followup;
-	bool needs_fsd;
-	unsigned int freq;
-	unsigned int default_freq;
-	int *freq_list;
-
-	/* pauseState information for Publish function */
-	struct os_reltime pause_state_end;
-	u8 sel_peer_id;
-	u8 sel_peer_addr[ETH_ALEN];
-
-	/* Publish state - channel iteration */
-	bool in_multi_chan;
-	bool first_multi_chan;
-	int multi_chan_idx; /* index to freq_list[] */
-	struct os_reltime next_publish_state;
-	struct os_reltime next_publish_chan;
-	unsigned int next_publish_duration;
-};
-
-struct nan_de {
-	u8 nmi[ETH_ALEN];
-	bool ap;
-	struct nan_callbacks cb;
-
-	struct nan_de_service *service[NAN_DE_MAX_SERVICE];
-	unsigned int num_service;
-
-	int next_handle;
-
-	unsigned int ext_listen_freq;
-	unsigned int listen_freq;
-	unsigned int tx_wait_status_freq;
-	unsigned int tx_wait_end_freq;
-};
-
-
-struct nan_de * nan_de_init(const u8 *nmi, bool ap,
-			    const struct nan_callbacks *cb)
-{
-	struct nan_de *de;
-
-	de = os_zalloc(sizeof(*de));
-	if (!de)
-		return NULL;
-
-	os_memcpy(de->nmi, nmi, ETH_ALEN);
-	de->ap = ap;
-	os_memcpy(&de->cb, cb, sizeof(*cb));
-
-	return de;
-}
-
-
-static void nan_de_service_free(struct nan_de_service *srv)
-{
-	os_free(srv->service_name);
-	wpabuf_free(srv->ssi);
-	wpabuf_free(srv->elems);
-	os_free(srv->freq_list);
-	os_free(srv);
-}
-
-
-static void nan_de_service_deinit(struct nan_de *de, struct nan_de_service *srv,
-				  enum nan_de_reason reason)
-{
-	if (!srv)
-		return;
-	if (srv->type == NAN_DE_PUBLISH && de->cb.publish_terminated)
-		de->cb.publish_terminated(de->cb.ctx, srv->id, reason);
-	if (srv->type == NAN_DE_SUBSCRIBE && de->cb.subscribe_terminated)
-		de->cb.subscribe_terminated(de->cb.ctx, srv->id, reason);
-	nan_de_service_free(srv);
-}
-
-
-static void nan_de_clear_pending(struct nan_de *de)
-{
-	de->listen_freq = 0;
-	de->tx_wait_status_freq = 0;
-	de->tx_wait_end_freq = 0;
-}
-
-
-void nan_de_flush(struct nan_de *de)
-{
-	unsigned int i;
-
-	if (!de)
-		return;
-
-	for (i = 0; i < NAN_DE_MAX_SERVICE; i++) {
-		nan_de_service_deinit(de, de->service[i],
-				      NAN_DE_REASON_USER_REQUEST);
-		de->service[i] = NULL;
-	}
-
-	de->num_service = 0;
-	nan_de_clear_pending(de);
-}
-
-
-static void nan_de_pause_state(struct nan_de_service *srv, const u8 *peer_addr,
-			       u8 peer_id)
-{
-	wpa_printf(MSG_DEBUG, "NAN: Start pauseState");
-	os_get_reltime(&srv->pause_state_end);
-	srv->pause_state_end.sec += 60;
-	os_memcpy(srv->sel_peer_addr, peer_addr, ETH_ALEN);
-	srv->sel_peer_id = peer_id;
-}
-
-
-static void nan_de_unpause_state(struct nan_de_service *srv)
-{
-	wpa_printf(MSG_DEBUG, "NAN: Stop pauseState");
-	srv->pause_state_end.sec = 0;
-	srv->pause_state_end.usec = 0;
-	os_memset(srv->sel_peer_addr, 0, ETH_ALEN);
-	srv->sel_peer_id = 0;
-}
-
-
-static struct wpabuf * nan_de_alloc_sdf(size_t len)
-{
-	struct wpabuf *buf;
-
-	buf = wpabuf_alloc(2 + 4 + len);
-	if (buf) {
-		wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC);
-		wpabuf_put_u8(buf, WLAN_PA_VENDOR_SPECIFIC);
-		wpabuf_put_be32(buf, NAN_SDF_VENDOR_TYPE);
-	}
-
-	return buf;
-}
-
-
-static int nan_de_tx(struct nan_de *de, unsigned int freq,
-		     unsigned int wait_time,
-		     const u8 *dst, const u8 *src, const u8 *bssid,
-		     const struct wpabuf *buf)
-{
-	int res;
-
-	if (!de->cb.tx)
-		return -1;
-
-	res = de->cb.tx(de->cb.ctx, freq, wait_time, dst, src, bssid, buf);
-	if (res < 0)
-		return res;
-
-	de->tx_wait_status_freq = freq;
-	de->tx_wait_end_freq = wait_time ? freq : 0;
-
-	return res;
-}
-
-
-static void nan_de_tx_sdf(struct nan_de *de, struct nan_de_service *srv,
-			  unsigned int wait_time,
-			  enum nan_service_control_type type,
-			  const u8 *dst, u8 req_instance_id,
-			  const struct wpabuf *ssi)
-{
-	struct wpabuf *buf;
-	size_t len = 0, sda_len, sdea_len;
-	u8 ctrl = type;
-	u16 sdea_ctrl = 0;
-
-	/* Service Descriptor attribute */
-	sda_len = NAN_SERVICE_ID_LEN + 1 + 1 + 1;
-	len += NAN_ATTR_HDR_LEN + sda_len;
-
-	/* Service Descriptor Extension attribute */
-	sdea_len = 1 + 2;
-	if (ssi)
-		sdea_len += 2 + 4 + wpabuf_len(ssi);
-	len += NAN_ATTR_HDR_LEN + sdea_len;
-
-	/* Element Container attribute */
-	if (srv->elems)
-		len += NAN_ATTR_HDR_LEN + 1 + wpabuf_len(srv->elems);
-
-	buf = nan_de_alloc_sdf(len);
-	if (!buf)
-		return;
-
-	/* Service Descriptor attribute */
-	wpabuf_put_u8(buf, NAN_ATTR_SDA);
-	wpabuf_put_le16(buf, sda_len);
-	wpabuf_put_data(buf, srv->service_id, NAN_SERVICE_ID_LEN);
-	wpabuf_put_u8(buf, srv->id); /* Instance ID */
-	wpabuf_put_u8(buf, req_instance_id); /* Requestor Instance ID */
-	wpabuf_put_u8(buf, ctrl);
-
-	/* Service Descriptor Extension attribute */
-	if (srv->type == NAN_DE_PUBLISH || ssi) {
-		wpabuf_put_u8(buf, NAN_ATTR_SDEA);
-		wpabuf_put_le16(buf, sdea_len);
-		wpabuf_put_u8(buf, srv->id); /* Instance ID */
-		if (srv->type == NAN_DE_PUBLISH) {
-			if (srv->publish.fsd)
-				sdea_ctrl |= NAN_SDEA_CTRL_FSD_REQ;
-			if (srv->publish.fsd_gas)
-				sdea_ctrl |= NAN_SDEA_CTRL_FSD_GAS;
-		}
-		wpabuf_put_le16(buf, sdea_ctrl);
-		if (ssi) {
-			wpabuf_put_le16(buf, 4 + wpabuf_len(ssi));
-			wpabuf_put_be24(buf, OUI_WFA);
-			wpabuf_put_u8(buf, srv->srv_proto_type);
-			wpabuf_put_buf(buf, ssi);
-		}
-	}
-
-	/* Element Container attribute */
-	if (srv->elems) {
-		wpabuf_put_u8(buf, NAN_ATTR_ELEM_CONTAINER);
-		wpabuf_put_le16(buf, 1 + wpabuf_len(srv->elems));
-		wpabuf_put_u8(buf, 0); /* Map ID */
-		wpabuf_put_buf(buf, srv->elems);
-	}
-
-	/* Wi-Fi Aware specification v4.0 uses NAN Cluster ID as A3 for USD,
-	 * but there is no synchronization in USD as as such, no NAN Cluster
-	 * either. Use Wildcard BSSID instead. */
-	nan_de_tx(de, srv->freq, wait_time, dst, de->nmi, wildcard_bssid, buf);
-	wpabuf_free(buf);
-}
-
-
-static int nan_de_time_to_next_chan_change(struct nan_de_service *srv)
-{
-	struct os_reltime tmp, diff, now;
-
-	if (os_reltime_before(&srv->next_publish_state,
-			      &srv->next_publish_chan))
-		tmp = srv->next_publish_state;
-	else if (srv->in_multi_chan)
-		tmp = srv->next_publish_chan;
-	else
-		tmp = srv->next_publish_state;
-
-	os_get_reltime(&now);
-	os_reltime_sub(&tmp, &now, &diff);
-	return os_reltime_in_ms(&diff);
-}
-
-
-static void nan_de_set_publish_times(struct nan_de_service *srv)
-{
-	os_get_reltime(&srv->next_publish_state);
-	srv->next_publish_chan = srv->next_publish_state;
-	/* Swap single/multi channel state in N * 100 TU */
-	os_reltime_add_ms(&srv->next_publish_state,
-			  srv->next_publish_duration * 1024 / 1000);
-
-	/* Swap channel in multi channel state after 150 ms */
-	os_reltime_add_ms(&srv->next_publish_chan, 150);
-}
-
-
-static void nan_de_check_chan_change(struct nan_de_service *srv)
-{
-	if (srv->next_publish_duration) {
-		/* Update end times for the first operation of the publish
-		 * iteration */
-		nan_de_set_publish_times(srv);
-		srv->next_publish_duration = 0;
-	} else if (srv->in_multi_chan) {
-		if (!os_reltime_initialized(&srv->pause_state_end)) {
-			srv->multi_chan_idx++;
-			if (srv->freq_list[srv->multi_chan_idx] == 0)
-				srv->multi_chan_idx = 0;
-			srv->freq = srv->freq_list[srv->multi_chan_idx];
-			wpa_printf(MSG_DEBUG,
-				   "NAN: Publish multi-channel change to %u MHz",
-				   srv->freq);
-		}
-		os_get_reltime(&srv->next_publish_chan);
-		os_reltime_add_ms(&srv->next_publish_chan, 150);
-	}
-}
-
-
-static void nan_de_tx_multicast(struct nan_de *de, struct nan_de_service *srv,
-				u8 req_instance_id)
-{
-	enum nan_service_control_type type;
-	unsigned int wait_time = 100;
-
-	if (srv->type == NAN_DE_PUBLISH) {
-		int ms;
-
-		type = NAN_SRV_CTRL_PUBLISH;
-
-		nan_de_check_chan_change(srv);
-		ms = nan_de_time_to_next_chan_change(srv);
-		if (ms < 100)
-			ms = 100;
-		wait_time = ms;
-	} else if (srv->type == NAN_DE_SUBSCRIBE) {
-		type = NAN_SRV_CTRL_SUBSCRIBE;
-	} else {
-		return;
-	}
-
-	nan_de_tx_sdf(de, srv, wait_time, type, nan_network_id,
-		      req_instance_id, srv->ssi);
-	os_get_reltime(&srv->last_multicast);
-}
-
-
-static void nan_de_add_srv(struct nan_de *de, struct nan_de_service *srv)
-{
-	int ttl;
-
-	os_get_reltime(&srv->time_started);
-	ttl = srv->type == NAN_DE_PUBLISH ? srv->publish.ttl :
-		srv->subscribe.ttl;
-	if (ttl) {
-		srv->end_time = srv->time_started;
-		srv->end_time.sec += ttl;
-	}
-
-	de->service[srv->id - 1] = srv;
-	de->num_service++;
-}
-
-
-static void nan_de_del_srv(struct nan_de *de, struct nan_de_service *srv,
-			   enum nan_de_reason reason)
-{
-	de->service[srv->id - 1] = NULL;
-	nan_de_service_deinit(de, srv, reason);
-	de->num_service--;
-	if (de->num_service == 0)
-		nan_de_clear_pending(de);
-}
-
-
-static bool nan_de_srv_expired(struct nan_de_service *srv,
-			       struct os_reltime *now)
-{
-	if (os_reltime_initialized(&srv->end_time))
-		return os_reltime_before(&srv->end_time, now);
-
-	if (srv->type == NAN_DE_PUBLISH) {
-		/* Time out after one transmission (and wait for FSD) */
-		if (!os_reltime_initialized(&srv->last_multicast))
-			return false;
-		if (!srv->publish.fsd)
-			return true;
-		if (os_reltime_initialized(&srv->last_followup) &&
-		    !os_reltime_expired(now, &srv->last_followup, 1))
-			return false;
-		if (os_reltime_expired(now, &srv->last_multicast, 1))
-			return true;
-	}
-
-	if (srv->type == NAN_DE_SUBSCRIBE) {
-		/* Time out after first DiscoveryResult event (and wait for
-		 * FSD) */
-		if (!os_reltime_initialized(&srv->first_discovered))
-			return false;
-		if (!srv->needs_fsd)
-			return true;
-		if (os_reltime_initialized(&srv->last_followup) &&
-		    !os_reltime_expired(now, &srv->last_followup, 1))
-			return false;
-		if (os_reltime_expired(now, &srv->first_discovered, 1))
-			return true;
-	}
-
-	return false;
-}
-
-
-static int nan_de_next_multicast(struct nan_de *de, struct nan_de_service *srv,
-				 struct os_reltime *now)
-{
-	unsigned int period;
-	struct os_reltime next, diff;
-
-	if (srv->type == NAN_DE_PUBLISH && !srv->publish.unsolicited)
-		return -1;
-	if (srv->type == NAN_DE_SUBSCRIBE && !srv->subscribe.active)
-		return -1;
-
-	if (!os_reltime_initialized(&srv->last_multicast))
-		return 0;
-
-	if (srv->type == NAN_DE_PUBLISH && srv->publish.ttl == 0)
-		return -1;
-
-	if (srv->type == NAN_DE_PUBLISH &&
-	    os_reltime_initialized(&srv->pause_state_end))
-		return -1;
-
-	period = srv->type == NAN_DE_PUBLISH ?
-		srv->publish.announcement_period :
-		srv->subscribe.query_period;
-	if (period == 0)
-		period = 100;
-	next = srv->last_multicast;
-	os_reltime_add_ms(&next, period);
-
-	if (srv->type == NAN_DE_PUBLISH) {
-		if (!de->tx_wait_end_freq && srv->publish.unsolicited &&
-		    os_reltime_before(&next, now))
-			return 0;
-		next = srv->next_publish_state;
-	}
-
-	if (os_reltime_before(&next, now))
-		return 0;
-
-	os_reltime_sub(&next, now, &diff);
-	return os_reltime_in_ms(&diff);
-}
-
-
-static int nan_de_srv_time_to_next(struct nan_de *de,
-				   struct nan_de_service *srv,
-				   struct os_reltime *now)
-{
-	struct os_reltime diff;
-	int next = -1, tmp;
-
-	if (os_reltime_initialized(&srv->end_time)) {
-		os_reltime_sub(&srv->end_time, now, &diff);
-		tmp = os_reltime_in_ms(&diff);
-		if (next == -1 || tmp < next)
-			next = tmp;
-	}
-
-	tmp = nan_de_next_multicast(de, srv, now);
-	if (tmp >= 0 && (next == -1 || tmp < next))
-		next = tmp;
-
-	if (srv->type == NAN_DE_PUBLISH &&
-	    os_reltime_initialized(&srv->last_multicast)) {
-		/* Time out after one transmission (and wait for FSD) */
-		tmp = srv->publish.fsd ? 1000 : 100;
-		if (next == -1 || tmp < next)
-			next = tmp;
-	}
-
-	if (srv->type == NAN_DE_SUBSCRIBE &&
-	    os_reltime_initialized(&srv->first_discovered)) {
-		/* Time out after first DiscoveryResult event (and wait for
-		 * FSD) */
-		tmp = srv->needs_fsd ? 1000 : 100;
-		if (next == -1 || tmp < next)
-			next = tmp;
-	}
-
-	if (os_reltime_initialized(&srv->next_publish_state)) {
-		os_reltime_sub(&srv->next_publish_state, now, &diff);
-		if (diff.sec < 0 || (diff.sec == 0 && diff.usec < 0))
-			tmp = 0;
-		else
-			tmp = os_reltime_in_ms(&diff);
-		if (next == -1 || tmp < next)
-			next = tmp;
-	}
-
-	return next;
-}
-
-
-static void nan_de_start_new_publish_state(struct nan_de_service *srv,
-					   bool force_single)
-{
-	unsigned int n;
-
-	if (force_single || !srv->freq_list || srv->freq_list[0] == 0)
-		srv->in_multi_chan = false;
-	else
-		srv->in_multi_chan = !srv->in_multi_chan;
-
-	/* Use hardcoded Nmin=5 and Nmax=10 and pick a random N from that range.
-	 * Use same values for M. */
-	n = 5 + os_random() % 5;
-	srv->next_publish_duration = n * 100;
-
-	nan_de_set_publish_times(srv);
-
-	if (os_reltime_initialized(&srv->pause_state_end))
-		return;
-
-	if (srv->in_multi_chan && srv->freq_list && srv->freq_list[0]) {
-		if (!srv->first_multi_chan)
-			srv->multi_chan_idx++;
-		if (srv->freq_list[srv->multi_chan_idx] == 0)
-			srv->multi_chan_idx = 0;
-		srv->first_multi_chan = false;
-		srv->freq = srv->freq_list[srv->multi_chan_idx];
-	} else {
-		srv->freq = srv->default_freq;
-	}
-
-	wpa_printf(MSG_DEBUG,
-		   "NAN: Publish in %s channel state for %u TU; starting with %u MHz",
-		   srv->in_multi_chan ? "multi" : "single", n * 100, srv->freq);
-}
-
-
-static void nan_de_timer(void *eloop_ctx, void *timeout_ctx)
-{
-	struct nan_de *de = eloop_ctx;
-	unsigned int i;
-	int next = -1;
-	bool started = false;
-	struct os_reltime now;
-
-	os_get_reltime(&now);
-
-	for (i = 0; i < NAN_DE_MAX_SERVICE; i++) {
-		struct nan_de_service *srv = de->service[i];
-		int srv_next;
-
-		if (!srv)
-			continue;
-
-		if (nan_de_srv_expired(srv, &now)) {
-			wpa_printf(MSG_DEBUG, "NAN: Service id %d expired",
-				   srv->id);
-			nan_de_del_srv(de, srv, NAN_DE_REASON_TIMEOUT);
-			continue;
-		}
-
-		if (os_reltime_initialized(&srv->next_publish_state) &&
-		    os_reltime_before(&srv->next_publish_state, &now))
-			nan_de_start_new_publish_state(srv, false);
-
-		if (srv->type == NAN_DE_PUBLISH &&
-		    os_reltime_initialized(&srv->pause_state_end) &&
-		    (os_reltime_before(&srv->pause_state_end, &now) ||
-		     (srv->publish.fsd &&
-		      os_reltime_initialized(&srv->last_followup) &&
-		      os_reltime_expired(&now, &srv->last_followup, 1))))
-			nan_de_unpause_state(srv);
-
-		srv_next = nan_de_srv_time_to_next(de, srv, &now);
-		if (srv_next >= 0 && (next == -1 || srv_next < next))
-			next = srv_next;
-
-		if (srv_next == 0 && !started &&
-		    de->listen_freq == 0 && de->ext_listen_freq == 0 &&
-		    de->tx_wait_end_freq == 0 &&
-		    nan_de_next_multicast(de, srv, &now) == 0) {
-			started = true;
-			nan_de_tx_multicast(de, srv, 0);
-		}
-
-		if (!started && de->cb.listen &&
-		    de->listen_freq == 0 && de->ext_listen_freq == 0 &&
-		    de->tx_wait_end_freq == 0 &&
-		    ((srv->type == NAN_DE_PUBLISH &&
-		      !srv->publish.unsolicited && srv->publish.solicited) ||
-		     (srv->type == NAN_DE_SUBSCRIBE &&
-		      !srv->subscribe.active))) {
-			int duration = 1000;
-
-			if (srv->type == NAN_DE_PUBLISH) {
-				nan_de_check_chan_change(srv);
-				duration = nan_de_time_to_next_chan_change(srv);
-				if (duration < 150)
-					duration = 150;
-			}
-
-			started = true;
-			if (de->cb.listen(de->cb.ctx, srv->freq, duration) == 0)
-				de->listen_freq = srv->freq;
-		}
-
-	}
-
-	if (next < 0)
-		return;
-
-	if (next == 0)
-		next = 1;
-	wpa_printf(MSG_DEBUG, "NAN: Next timer in %u ms", next);
-	eloop_register_timeout(next / 1000, (next % 1000) * 1000, nan_de_timer,
-			       de, NULL);
-}
-
-
-static void nan_de_run_timer(struct nan_de *de)
-{
-	eloop_cancel_timeout(nan_de_timer, de, NULL);
-	eloop_register_timeout(0, 0, nan_de_timer, de, NULL);
-}
-
-
-void nan_de_deinit(struct nan_de *de)
-{
-	eloop_cancel_timeout(nan_de_timer, de, NULL);
-	nan_de_flush(de);
-	os_free(de);
-}
-
-
-void nan_de_listen_started(struct nan_de *de, unsigned int freq,
-			   unsigned int duration)
-{
-	if (freq != de->listen_freq)
-		de->ext_listen_freq = freq;
-}
-
-
-void nan_de_listen_ended(struct nan_de *de, unsigned int freq)
-{
-	if (freq == de->ext_listen_freq)
-		de->ext_listen_freq = 0;
-
-	if (freq == de->listen_freq) {
-		de->listen_freq = 0;
-		nan_de_run_timer(de);
-	}
-}
-
-
-void nan_de_tx_status(struct nan_de *de, unsigned int freq, const u8 *dst)
-{
-	if (freq == de->tx_wait_status_freq)
-		de->tx_wait_status_freq = 0;
-}
-
-
-void nan_de_tx_wait_ended(struct nan_de *de)
-{
-	de->tx_wait_end_freq = 0;
-	nan_de_run_timer(de);
-}
-
-
-static const u8 *
-nan_de_get_attr(const u8 *buf, size_t len, enum nan_attr_id id,
-		unsigned int skip)
-{
-	const u8 *pos = buf, *end = buf + len;
-
-	while (end - pos >= NAN_ATTR_HDR_LEN) {
-		const u8 *attr = pos;
-		u8 attr_id;
-		u16 attr_len;
-
-		attr_id = *pos++;
-		attr_len = WPA_GET_LE16(pos);
-		pos += 2;
-		if (attr_len > end - pos) {
-			wpa_printf(MSG_DEBUG,
-				   "NAN: Truncated attribute %u (len %u; left %zu)",
-				   attr_id, attr_len, end - pos);
-			break;
-		}
-
-		if (attr_id == id) {
-			if (skip == 0)
-				return attr;
-			skip--;
-		}
-
-		pos += attr_len;
-	}
-
-	return NULL;
-}
-
-
-static void nan_de_get_sdea(const u8 *buf, size_t len, u8 instance_id,
-			    u16 *sdea_control,
-			    enum nan_service_protocol_type *srv_proto_type,
-			    const u8 **ssi, size_t *ssi_len)
-{
-	unsigned int skip;
-	const u8 *sdea, *end;
-	u16 sdea_len;
-
-	for (skip = 0; ; skip++) {
-		sdea = nan_de_get_attr(buf, len, NAN_ATTR_SDEA, skip);
-		if (!sdea)
-			break;
-
-		sdea++;
-		sdea_len = WPA_GET_LE16(sdea);
-		sdea += 2;
-		if (sdea_len < 1 + 2)
-			continue;
-		end = sdea + sdea_len;
-
-		if (instance_id != *sdea++)
-			continue; /* Mismatching Instance ID */
-
-		*sdea_control = WPA_GET_LE16(sdea);
-		sdea += 2;
-
-		if (*sdea_control & NAN_SDEA_CTRL_RANGE_LIMIT) {
-			if (end - sdea < 4)
-				continue;
-			sdea += 4;
-		}
-
-		if (*sdea_control & NAN_SDEA_CTRL_SRV_UPD_INDIC) {
-			if (end - sdea < 1)
-				continue;
-			sdea++;
-		}
-
-		if (end - sdea >= 2) {
-			u16 srv_info_len;
-
-			srv_info_len = WPA_GET_LE16(sdea);
-			sdea += 2;
-
-			if (srv_info_len > end - sdea)
-				continue;
-
-			if (srv_info_len >= 4 &&
-			    WPA_GET_BE24(sdea) == OUI_WFA) {
-				*srv_proto_type = sdea[3];
-				*ssi = sdea + 4;
-				*ssi_len = srv_info_len - 4;
-			}
-		}
-	}
-}
-
-
-static void nan_de_rx_publish(struct nan_de *de, struct nan_de_service *srv,
-			      const u8 *peer_addr, u8 instance_id,
-			      u8 req_instance_id, u16 sdea_control,
-			      enum nan_service_protocol_type srv_proto_type,
-			      const u8 *ssi, size_t ssi_len)
-{
-	/* Subscribe function processing of a receive Publish message */
-	if (!os_reltime_initialized(&srv->first_discovered)) {
-		os_get_reltime(&srv->first_discovered);
-		srv->needs_fsd = sdea_control & NAN_SDEA_CTRL_FSD_REQ;
-		nan_de_run_timer(de);
-	}
-
-	if (srv->subscribe.active && req_instance_id == 0) {
-		/* Active subscriber replies with a Subscribe message if it
-		 * received a matching unsolicited Publish message. */
-		nan_de_tx_multicast(de, srv, instance_id);
-	}
-
-	if (!srv->subscribe.active && req_instance_id == 0) {
-		/* Passive subscriber replies with a Follow-up message without
-		 * Service Specific Info field if it received a matching
-		 * unsolicited Publish message. */
-		nan_de_transmit(de, srv->id, NULL, NULL, peer_addr,
-				instance_id);
-	}
-
-	if (de->cb.discovery_result)
-		de->cb.discovery_result(
-			de->cb.ctx, srv->id, srv_proto_type,
-			ssi, ssi_len, instance_id,
-			peer_addr,
-			sdea_control & NAN_SDEA_CTRL_FSD_REQ,
-			sdea_control & NAN_SDEA_CTRL_FSD_GAS);
-}
-
-
-static bool nan_de_filter_match(struct nan_de_service *srv,
-				const u8 *matching_filter,
-				size_t matching_filter_len)
-{
-	const u8 *pos, *end;
-
-	/* Since we do not currently support matching_filter_rx values for the
-	 * local Publish function, any matching filter with at least one
-	 * <length,value> pair with length larger than zero implies a mismatch.
-	 */
-
-	if (!matching_filter)
-		return true;
-
-	pos = matching_filter;
-	end = matching_filter + matching_filter_len;
-
-	while (pos < end) {
-		u8 len;
-
-		len = *pos++;
-		if (len > end - pos)
-			break;
-		if (len) {
-			/* A non-empty Matching Filter entry: no match since
-			 * there is no local matching_filter_rx. */
-			return false;
-		}
-	}
-
-	return true;
-}
-
-
-static void nan_de_rx_subscribe(struct nan_de *de, struct nan_de_service *srv,
-				const u8 *peer_addr, u8 instance_id,
-				const u8 *matching_filter,
-				size_t matching_filter_len,
-				enum nan_service_protocol_type srv_proto_type,
-				const u8 *ssi, size_t ssi_len)
-{
-	struct wpabuf *buf;
-	size_t len = 0, sda_len, sdea_len;
-	u8 ctrl = 0;
-	u16 sdea_ctrl = 0;
-
-	/* Publish function processing of a receive Subscribe message */
-
-	if (!nan_de_filter_match(srv, matching_filter, matching_filter_len))
-		return;
-
-	if (!srv->publish.solicited)
-		return;
-
-	if (os_reltime_initialized(&srv->pause_state_end) &&
-	    (!ether_addr_equal(peer_addr, srv->sel_peer_addr) ||
-	     instance_id != srv->sel_peer_id)) {
-		wpa_printf(MSG_DEBUG,
-			   "NAN: In pauseState - ignore Subscribe message from another subscriber");
-		return;
-	}
-
-	/* Reply with a solicited Publish message */
-	/* Service Descriptor attribute */
-	sda_len = NAN_SERVICE_ID_LEN + 1 + 1 + 1;
-	len += NAN_ATTR_HDR_LEN + sda_len;
-
-	/* Service Descriptor Extension attribute */
-	sdea_len = 1 + 2;
-	if (srv->ssi)
-		sdea_len += 2 + 4 + wpabuf_len(srv->ssi);
-	len += NAN_ATTR_HDR_LEN + sdea_len;
-
-	/* Element Container attribute */
-	if (srv->elems)
-		len += NAN_ATTR_HDR_LEN + 1 + wpabuf_len(srv->elems);
-
-	buf = nan_de_alloc_sdf(len);
-	if (!buf)
-		return;
-
-	/* Service Descriptor attribute */
-	wpabuf_put_u8(buf, NAN_ATTR_SDA);
-	wpabuf_put_le16(buf, sda_len);
-	wpabuf_put_data(buf, srv->service_id, NAN_SERVICE_ID_LEN);
-	wpabuf_put_u8(buf, srv->id); /* Instance ID */
-	wpabuf_put_u8(buf, instance_id); /* Requestor Instance ID */
-	ctrl |= NAN_SRV_CTRL_PUBLISH;
-	wpabuf_put_u8(buf, ctrl);
-
-	/* Service Descriptor Extension attribute */
-	if (srv->type == NAN_DE_PUBLISH || srv->ssi) {
-		wpabuf_put_u8(buf, NAN_ATTR_SDEA);
-		wpabuf_put_le16(buf, sdea_len);
-		wpabuf_put_u8(buf, srv->id); /* Instance ID */
-		if (srv->type == NAN_DE_PUBLISH) {
-			if (srv->publish.fsd)
-				sdea_ctrl |= NAN_SDEA_CTRL_FSD_REQ;
-			if (srv->publish.fsd_gas)
-				sdea_ctrl |= NAN_SDEA_CTRL_FSD_GAS;
-		}
-		wpabuf_put_le16(buf, sdea_ctrl);
-		if (srv->ssi) {
-			wpabuf_put_le16(buf, 4 + wpabuf_len(srv->ssi));
-			wpabuf_put_be24(buf, OUI_WFA);
-			wpabuf_put_u8(buf, srv->srv_proto_type);
-			wpabuf_put_buf(buf, srv->ssi);
-		}
-	}
-
-	/* Element Container attribute */
-	if (srv->elems) {
-		wpabuf_put_u8(buf, NAN_ATTR_ELEM_CONTAINER);
-		wpabuf_put_le16(buf, 1 + wpabuf_len(srv->elems));
-		wpabuf_put_u8(buf, 0); /* Map ID */
-		wpabuf_put_buf(buf, srv->elems);
-	}
-
-	/* Wi-Fi Aware specification v4.0 uses NAN Cluster ID as A3 for USD,
-	 * but there is no synchronization in USD as as such, no NAN Cluster
-	 * either. Use Wildcard BSSID instead. */
-	nan_de_tx(de, srv->freq, 100,
-		  srv->publish.solicited_multicast ? nan_network_id : peer_addr,
-		  de->nmi, wildcard_bssid, buf);
-	wpabuf_free(buf);
-
-	nan_de_pause_state(srv, peer_addr, instance_id);
-
-	if (!srv->publish.disable_events && de->cb.replied)
-		de->cb.replied(de->cb.ctx, srv->id, peer_addr, instance_id,
-			       srv_proto_type, ssi, ssi_len);
-}
-
-
-static void nan_de_rx_follow_up(struct nan_de *de, struct nan_de_service *srv,
-				const u8 *peer_addr, u8 instance_id,
-				const u8 *ssi, size_t ssi_len)
-{
-	/* Follow-up function processing of a receive Follow-up message for a
-	 * Subscribe or Publish instance */
-
-	if (srv->type == NAN_DE_PUBLISH &&
-	    os_reltime_initialized(&srv->pause_state_end) &&
-	    (!ether_addr_equal(peer_addr, srv->sel_peer_addr) ||
-	     instance_id != srv->sel_peer_id ||
-	     !ssi)) {
-		wpa_printf(MSG_DEBUG,
-			   "NAN: In pauseState - ignore Follow-up message from another subscriber or without ssi");
-		return;
-	}
-
-	os_get_reltime(&srv->last_followup);
-
-	if (srv->type == NAN_DE_PUBLISH && !ssi)
-		nan_de_pause_state(srv, peer_addr, instance_id);
-
-	if (de->cb.receive)
-		de->cb.receive(de->cb.ctx, srv->id, instance_id, ssi, ssi_len,
-			       peer_addr);
-}
-
-
-static void nan_de_rx_sda(struct nan_de *de, const u8 *peer_addr,
-			  unsigned int freq, const u8 *buf, size_t len,
-			  const u8 *sda, size_t sda_len)
-{
-	const u8 *service_id;
-	u8 instance_id, req_instance_id, ctrl;
-	u16 sdea_control = 0;
-	unsigned int i;
-	enum nan_service_control_type type = 0;
-	enum nan_service_protocol_type srv_proto_type = 0;
-	const u8 *ssi = NULL;
-	size_t ssi_len = 0;
-	bool first = true;
-	const u8 *end;
-	const u8 *matching_filter = NULL;
-	size_t matching_filter_len = 0;
-
-	if (sda_len < NAN_SERVICE_ID_LEN + 1 + 1 + 1)
-		return;
-	end = sda + sda_len;
-
-	service_id = sda;
-	sda += NAN_SERVICE_ID_LEN;
-	instance_id = *sda++;
-	req_instance_id = *sda++;
-	ctrl = *sda;
-	type = ctrl & NAN_SRV_CTRL_TYPE_MASK;
-	wpa_printf(MSG_DEBUG,
-		   "NAN: SDA - Service ID %02x%02x%02x%02x%02x%02x Instance ID %u Requestor Instance ID %u Service Control 0x%x (Service Control Type %u)",
-		   MAC2STR(service_id), instance_id, req_instance_id,
-		   ctrl, type);
-	if (type != NAN_SRV_CTRL_PUBLISH &&
-	    type != NAN_SRV_CTRL_SUBSCRIBE &&
-	    type != NAN_SRV_CTRL_FOLLOW_UP) {
-		wpa_printf(MSG_DEBUG,
-			   "NAN: Discard SDF with unknown Service Control Type %u",
-			   type);
-		return;
-	}
-
-	if (ctrl & NAN_SRV_CTRL_BINDING_BITMAP) {
-		if (end - sda < 2)
-			return;
-		sda += 2;
-	}
-
-	if (ctrl & NAN_SRV_CTRL_MATCHING_FILTER) {
-		u8 flen;
-
-		if (end - sda < 1)
-			return;
-		flen = *sda++;
-		if (end - sda < flen)
-			return;
-		matching_filter = sda;
-		matching_filter_len = flen;
-		sda += flen;
-	}
-
-	if (ctrl & NAN_SRV_CTRL_RESP_FILTER) {
-		u8 flen;
-
-		if (end - sda < 1)
-			return;
-		flen = *sda++;
-		if (end - sda < flen)
-			return;
-		sda += flen;
-	}
-
-	if (ctrl & NAN_SRV_CTRL_SRV_INFO) {
-		u8 flen;
-
-		if (end - sda < 1)
-			return;
-		flen = *sda++;
-		if (end - sda < flen)
-			return;
-		if (flen >= 4 && WPA_GET_BE24(sda) == OUI_WFA) {
-			srv_proto_type = sda[3];
-			ssi = sda + 4;
-			ssi_len = flen - 4;
-			wpa_printf(MSG_DEBUG, "NAN: Service Protocol Type %d",
-				   srv_proto_type);
-			wpa_hexdump(MSG_MSGDUMP, "NAN: ssi", ssi, ssi_len);
-		}
-		sda += flen;
-	}
-
-	for (i = 0; i < NAN_DE_MAX_SERVICE; i++) {
-		struct nan_de_service *srv = de->service[i];
-
-		if (!srv)
-			continue;
-		if (os_memcmp(srv->service_id, service_id,
-			      NAN_SERVICE_ID_LEN) != 0)
-			continue;
-		if (type == NAN_SRV_CTRL_PUBLISH) {
-			if (srv->type == NAN_DE_PUBLISH)
-				continue;
-			if (req_instance_id && srv->id != req_instance_id)
-				continue;
-		}
-		if (type == NAN_SRV_CTRL_SUBSCRIBE &&
-		    srv->type == NAN_DE_SUBSCRIBE)
-			continue;
-		wpa_printf(MSG_DEBUG, "NAN: Received SDF matches service ID %u",
-			   i + 1);
-
-		if (first) {
-			first = false;
-			nan_de_get_sdea(buf, len, instance_id, &sdea_control,
-					&srv_proto_type, &ssi, &ssi_len);
-
-			if (ssi) {
-				wpa_printf(MSG_DEBUG,
-					   "NAN: Service Protocol Type %d",
-					   srv_proto_type);
-				wpa_hexdump(MSG_MSGDUMP, "NAN: ssi",
-					    ssi, ssi_len);
-			}
-		}
-
-		switch (type) {
-		case NAN_SRV_CTRL_PUBLISH:
-			nan_de_rx_publish(de, srv, peer_addr, instance_id,
-					  req_instance_id,
-					  sdea_control, srv_proto_type,
-					  ssi, ssi_len);
-			break;
-		case NAN_SRV_CTRL_SUBSCRIBE:
-			nan_de_rx_subscribe(de, srv, peer_addr, instance_id,
-					    matching_filter,
-					    matching_filter_len,
-					    srv_proto_type,
-					    ssi, ssi_len);
-			break;
-		case NAN_SRV_CTRL_FOLLOW_UP:
-			nan_de_rx_follow_up(de, srv, peer_addr, instance_id,
-					    ssi, ssi_len);
-			break;
-		}
-	}
-}
-
-
-void nan_de_rx_sdf(struct nan_de *de, const u8 *peer_addr, unsigned int freq,
-		   const u8 *buf, size_t len)
-{
-	const u8 *sda;
-	u16 sda_len;
-	unsigned int skip;
-
-	if (!de->num_service)
-		return;
-
-	wpa_printf(MSG_DEBUG, "NAN: RX SDF from " MACSTR " freq=%u len=%zu",
-		   MAC2STR(peer_addr), freq, len);
-
-	wpa_hexdump(MSG_MSGDUMP, "NAN: SDF payload", buf, len);
-
-	for (skip = 0; ; skip++) {
-		sda = nan_de_get_attr(buf, len, NAN_ATTR_SDA, skip);
-		if (!sda)
-			break;
-
-		sda++;
-		sda_len = WPA_GET_LE16(sda);
-		sda += 2;
-		nan_de_rx_sda(de, peer_addr, freq, buf, len, sda, sda_len);
-	}
-}
-
-
-static int nan_de_get_handle(struct nan_de *de)
-{
-	int i = de->next_handle;
-
-	if (de->num_service >= NAN_DE_MAX_SERVICE)
-		goto fail;
-
-	do {
-		if (!de->service[i]) {
-			de->next_handle = (i + 1) % NAN_DE_MAX_SERVICE;
-			return i + 1;
-		}
-		i = (i + 1) % NAN_DE_MAX_SERVICE;
-	} while (i != de->next_handle);
-
-fail:
-	wpa_printf(MSG_DEBUG, "NAN: No more room for a new service");
-	return -1;
-}
-
-
-static int nan_de_derive_service_id(struct nan_de_service *srv)
-{
-	u8 hash[SHA256_MAC_LEN];
-	char *name, *pos;
-	int ret;
-	const u8 *addr[1];
-	size_t len[1];
-
-	name = os_strdup(srv->service_name);
-	if (!name)
-		return -1;
-	pos = name;
-	while (*pos) {
-		*pos = tolower(*pos);
-		pos++;
-	}
-
-	addr[0] = (u8 *) name;
-	len[0] = os_strlen(name);
-	ret = sha256_vector(1, addr, len, hash);
-	os_free(name);
-	if (ret == 0)
-		os_memcpy(srv->service_id, hash, NAN_SERVICE_ID_LEN);
-
-	return ret;
-}
-
-
-int nan_de_publish(struct nan_de *de, const char *service_name,
-		   enum nan_service_protocol_type srv_proto_type,
-		   const struct wpabuf *ssi, const struct wpabuf *elems,
-		   struct nan_publish_params *params)
-{
-	int publish_id;
-	struct nan_de_service *srv;
-
-	if (!service_name) {
-		wpa_printf(MSG_DEBUG, "NAN: Publish() - no service_name");
-		return -1;
-	}
-
-	publish_id = nan_de_get_handle(de);
-	if (publish_id < 1)
-		return -1;
-
-	srv = os_zalloc(sizeof(*srv));
-	if (!srv)
-		return -1;
-	srv->type = NAN_DE_PUBLISH;
-	srv->freq = srv->default_freq = params->freq;
-	srv->service_name = os_strdup(service_name);
-	if (!srv->service_name)
-		goto fail;
-	if (nan_de_derive_service_id(srv) < 0)
-		goto fail;
-	os_memcpy(&srv->publish, params, sizeof(*params));
-
-	if (params->freq_list) {
-		size_t len;
-
-		len = (int_array_len(params->freq_list) + 1) * sizeof(int);
-		srv->freq_list = os_memdup(params->freq_list, len);
-		if (!srv->freq_list)
-			goto fail;
-	}
-	srv->publish.freq_list = NULL;
-
-	srv->srv_proto_type = srv_proto_type;
-	if (ssi) {
-		srv->ssi = wpabuf_dup(ssi);
-		if (!srv->ssi)
-			goto fail;
-	}
-	if (elems) {
-		srv->elems = wpabuf_dup(elems);
-		if (!srv->elems)
-			goto fail;
-	}
-
-	/* Prepare for single and multi-channel states; starting with
-	 * single channel */
-	srv->first_multi_chan = true;
-	nan_de_start_new_publish_state(srv, true);
-
-	wpa_printf(MSG_DEBUG, "NAN: Assigned new publish handle %d for %s",
-		   publish_id, service_name);
-	srv->id = publish_id;
-	nan_de_add_srv(de, srv);
-	nan_de_run_timer(de);
-	return publish_id;
-fail:
-	nan_de_service_free(srv);
-	return -1;
-}
-
-
-void nan_de_cancel_publish(struct nan_de *de, int publish_id)
-{
-	struct nan_de_service *srv;
-
-	wpa_printf(MSG_DEBUG, "NAN: CancelPublish(publish_id=%d)", publish_id);
-
-	if (publish_id < 1 || publish_id > NAN_DE_MAX_SERVICE)
-		return;
-	srv = de->service[publish_id - 1];
-	if (!srv || srv->type != NAN_DE_PUBLISH)
-		return;
-	nan_de_del_srv(de, srv, NAN_DE_REASON_USER_REQUEST);
-}
-
-
-int nan_de_update_publish(struct nan_de *de, int publish_id,
-			  const struct wpabuf *ssi)
-{
-	struct nan_de_service *srv;
-
-	wpa_printf(MSG_DEBUG, "NAN: UpdatePublish(publish_id=%d)", publish_id);
-
-	if (publish_id < 1 || publish_id > NAN_DE_MAX_SERVICE)
-		return -1;
-	srv = de->service[publish_id - 1];
-	if (!srv || srv->type != NAN_DE_PUBLISH)
-		return -1;
-
-	wpabuf_free(srv->ssi);
-	srv->ssi = NULL;
-	if (!ssi)
-		return 0;
-	srv->ssi = wpabuf_dup(ssi);
-	if (!srv->ssi)
-		return -1;
-	return 0;
-}
-
-
-int nan_de_subscribe(struct nan_de *de, const char *service_name,
-		     enum nan_service_protocol_type srv_proto_type,
-		     const struct wpabuf *ssi, const struct wpabuf *elems,
-		     struct nan_subscribe_params *params)
-{
-	int subscribe_id;
-	struct nan_de_service *srv;
-
-	if (!service_name) {
-		wpa_printf(MSG_DEBUG, "NAN: Subscribe() - no service_name");
-		return -1;
-	}
-
-	subscribe_id = nan_de_get_handle(de);
-	if (subscribe_id < 1)
-		return -1;
-
-	srv = os_zalloc(sizeof(*srv));
-	if (!srv)
-		return -1;
-	srv->type = NAN_DE_SUBSCRIBE;
-	srv->freq = params->freq;
-	srv->service_name = os_strdup(service_name);
-	if (!srv->service_name)
-		goto fail;
-	if (nan_de_derive_service_id(srv) < 0)
-		goto fail;
-	os_memcpy(&srv->subscribe, params, sizeof(*params));
-	srv->srv_proto_type = srv_proto_type;
-	if (ssi) {
-		srv->ssi = wpabuf_dup(ssi);
-		if (!srv->ssi)
-			goto fail;
-	}
-	if (elems) {
-		srv->elems = wpabuf_dup(elems);
-		if (!srv->elems)
-			goto fail;
-	}
-
-	wpa_printf(MSG_DEBUG, "NAN: Assigned new subscribe handle %d for %s",
-		   subscribe_id, service_name);
-	srv->id = subscribe_id;
-	nan_de_add_srv(de, srv);
-	nan_de_run_timer(de);
-	return subscribe_id;
-fail:
-	nan_de_service_free(srv);
-	return -1;
-}
-
-
-void nan_de_cancel_subscribe(struct nan_de *de, int subscribe_id)
-{
-	struct nan_de_service *srv;
-
-	if (subscribe_id < 1 || subscribe_id > NAN_DE_MAX_SERVICE)
-		return;
-	srv = de->service[subscribe_id - 1];
-	if (!srv || srv->type != NAN_DE_SUBSCRIBE)
-		return;
-	nan_de_del_srv(de, srv, NAN_DE_REASON_USER_REQUEST);
-}
-
-
-int nan_de_transmit(struct nan_de *de, int handle,
-		    const struct wpabuf *ssi, const struct wpabuf *elems,
-		    const u8 *peer_addr, u8 req_instance_id)
-{
-	struct nan_de_service *srv;
-
-	if (handle < 1 || handle > NAN_DE_MAX_SERVICE)
-		return -1;
-
-	srv = de->service[handle - 1];
-	if (!srv)
-		return -1;
-
-	nan_de_tx_sdf(de, srv, 100, NAN_SRV_CTRL_FOLLOW_UP,
-		      peer_addr, req_instance_id, ssi);
-
-	os_get_reltime(&srv->last_followup);
-	return 0;
-}
diff --git a/src/common/nan_de.h b/src/common/nan_de.h
deleted file mode 100644
index 6223506..0000000
--- a/src/common/nan_de.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * NAN Discovery Engine
- * Copyright (c) 2024, Qualcomm Innovation Center, Inc.
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#ifndef NAN_DE_H
-#define NAN_DE_H
-
-#include "nan.h"
-
-/* Maximum number of active local publish and subscribe instances */
-#ifndef NAN_DE_MAX_SERVICE
-#define NAN_DE_MAX_SERVICE 20
-#endif /* NAN_DE_MAX_SERVICE */
-
-struct nan_de;
-
-enum nan_de_reason {
-	NAN_DE_REASON_TIMEOUT,
-	NAN_DE_REASON_USER_REQUEST,
-	NAN_DE_REASON_FAILURE,
-};
-
-struct nan_callbacks {
-	void *ctx;
-
-	int (*tx)(void *ctx, unsigned int freq, unsigned int wait_time,
-		  const u8 *dst, const u8 *src, const u8 *bssid,
-		  const struct wpabuf *buf);
-	int (*listen)(void *ctx, unsigned int freq, unsigned int duration);
-
-	/* NAN DE Events */
-	void (*discovery_result)(void *ctx, int subscribe_id,
-				 enum nan_service_protocol_type srv_proto_type,
-				 const u8 *ssi, size_t ssi_len,
-				 int peer_publish_id,
-				 const u8 *peer_addr, bool fsd, bool fsd_gas);
-
-	void (*replied)(void *ctx, int publish_id, const u8 *peer_addr,
-			int peer_subscribe_id,
-			enum nan_service_protocol_type srv_proto_type,
-			const u8 *ssi, size_t ssi_len);
-
-	void (*publish_terminated)(void *ctx, int publish_id,
-				    enum nan_de_reason reason);
-
-	void (*subscribe_terminated)(void *ctx, int subscribe_id,
-				     enum nan_de_reason reason);
-
-	void (*receive)(void *ctx, int id, int peer_instance_id,
-			const u8 *ssi, size_t ssi_len,
-			const u8 *peer_addr);
-};
-
-struct nan_de * nan_de_init(const u8 *nmi, bool ap,
-			    const struct nan_callbacks *cb);
-void nan_de_flush(struct nan_de *de);
-void nan_de_deinit(struct nan_de *de);
-
-void nan_de_listen_started(struct nan_de *de, unsigned int freq,
-			   unsigned int duration);
-void nan_de_listen_ended(struct nan_de *de, unsigned int freq);
-void nan_de_tx_status(struct nan_de *de, unsigned int freq, const u8 *dst);
-void nan_de_tx_wait_ended(struct nan_de *de);
-
-void nan_de_rx_sdf(struct nan_de *de, const u8 *peer_addr, unsigned int freq,
-		   const u8 *buf, size_t len);
-
-struct nan_publish_params {
-	/* configuration_parameters */
-
-	/* Publish type */
-	bool unsolicited;
-	bool solicited;
-
-	/* Solicited transmission type */
-	bool solicited_multicast;
-
-	/* Time to live (in seconds); 0 = one TX only */
-	unsigned int ttl;
-
-	/* Event conditions */
-	bool disable_events;
-
-	/* Further Service Discovery flag */
-	bool fsd;
-
-	/* Further Service Discovery function */
-	bool fsd_gas;
-
-	/* Default frequency (defaultPublishChannel) */
-	unsigned int freq;
-
-	/* Multi-channel frequencies (publishChannelList) */
-	const int *freq_list;
-
-	/* Announcement period in ms; 0 = use default */
-	unsigned int announcement_period;
-};
-
-/* Returns -1 on failure or >0 publish_id */
-int nan_de_publish(struct nan_de *de, const char *service_name,
-		   enum nan_service_protocol_type srv_proto_type,
-		   const struct wpabuf *ssi, const struct wpabuf *elems,
-		   struct nan_publish_params *params);
-
-void nan_de_cancel_publish(struct nan_de *de, int publish_id);
-
-int nan_de_update_publish(struct nan_de *de, int publish_id,
-			  const struct wpabuf *ssi);
-
-struct nan_subscribe_params {
-	/* configuration_parameters */
-
-	/* Subscribe type */
-	bool active;
-
-	/* Time to live (in seconds); 0 = until first result */
-	unsigned int ttl;
-
-	/* Selected frequency */
-	unsigned int freq;
-
-	/* Query period in ms; 0 = use default */
-	unsigned int query_period;
-};
-
-/* Returns -1 on failure or >0 subscribe_id */
-int nan_de_subscribe(struct nan_de *de, const char *service_name,
-		     enum nan_service_protocol_type srv_proto_type,
-		     const struct wpabuf *ssi, const struct wpabuf *elems,
-		     struct nan_subscribe_params *params);
-
-void nan_de_cancel_subscribe(struct nan_de *de, int subscribe_id);
-
-/* handle = publish_id or subscribe_id
- * req_instance_id = peer publish_id or subscribe_id */
-int nan_de_transmit(struct nan_de *de, int handle,
-		    const struct wpabuf *ssi, const struct wpabuf *elems,
-		    const u8 *peer_addr, u8 req_instance_id);
-
-#endif /* NAN_DE_H */
diff --git a/src/common/ptksa_cache.c b/src/common/ptksa_cache.c
index 918a1cc..3b5c0b8 100644
--- a/src/common/ptksa_cache.c
+++ b/src/common/ptksa_cache.c
@@ -19,8 +19,6 @@
 	unsigned int n_ptksa;
 };
 
-#ifdef CONFIG_PTKSA_CACHE
-
 static void ptksa_cache_set_expiration(struct ptksa_cache *ptksa);
 
 
@@ -143,7 +141,7 @@
 		return NULL;
 
 	dl_list_for_each(e, &ptksa->ptksa, struct ptksa_cache_entry, list) {
-		if ((!addr || ether_addr_equal(e->addr, addr)) &&
+		if ((!addr || os_memcmp(e->addr, addr, ETH_ALEN) == 0) &&
 		    (cipher == WPA_CIPHER_NONE || cipher == e->cipher))
 			return e;
 	}
@@ -240,7 +238,7 @@
 
 	dl_list_for_each_safe(e, next, &ptksa->ptksa, struct ptksa_cache_entry,
 			      list) {
-		if ((!addr || ether_addr_equal(e->addr, addr)) &&
+		if ((!addr || os_memcmp(e->addr, addr, ETH_ALEN) == 0) &&
 		    (cipher == WPA_CIPHER_NONE || cipher == e->cipher)) {
 			wpa_printf(MSG_DEBUG,
 				   "Flush PTKSA cache entry for " MACSTR,
@@ -344,44 +342,3 @@
 
 	return entry;
 }
-
-#else /* CONFIG_PTKSA_CACHE */
-
-struct ptksa_cache * ptksa_cache_init(void)
-{
-	return (struct ptksa_cache *) 1;
-}
-
-
-void ptksa_cache_deinit(struct ptksa_cache *ptksa)
-{
-}
-
-
-struct ptksa_cache_entry *
-ptksa_cache_get(struct ptksa_cache *ptksa, const u8 *addr, u32 cipher)
-{
-	return NULL;
-}
-
-
-int ptksa_cache_list(struct ptksa_cache *ptksa, char *buf, size_t len)
-{
-	return -1;
-}
-
-
-struct ptksa_cache_entry *
-ptksa_cache_add(struct ptksa_cache *ptksa, const u8 *own_addr, const u8 *addr,
-		u32 cipher, u32 life_time, const struct wpa_ptk *ptk,
-		void (*cb)(struct ptksa_cache_entry *e), void *ctx, u32 akmp)
-{
-	return NULL;
-}
-
-
-void ptksa_cache_flush(struct ptksa_cache *ptksa, const u8 *addr, u32 cipher)
-{
-}
-
-#endif /* CONFIG_PTKSA_CACHE */
diff --git a/src/common/ptksa_cache.h b/src/common/ptksa_cache.h
index dd5e7db..6182215 100644
--- a/src/common/ptksa_cache.h
+++ b/src/common/ptksa_cache.h
@@ -29,6 +29,7 @@
 	u32 akmp;
 };
 
+#ifdef CONFIG_PTKSA_CACHE
 
 struct ptksa_cache;
 
@@ -47,4 +48,41 @@
 					   void *ctx, u32 akmp);
 void ptksa_cache_flush(struct ptksa_cache *ptksa, const u8 *addr, u32 cipher);
 
+#else /* CONFIG_PTKSA_CACHE */
+
+static inline struct ptksa_cache * ptksa_cache_init(void)
+{
+	return (struct ptksa_cache *) 1;
+}
+
+static inline void ptksa_cache_deinit(struct ptksa_cache *ptksa)
+{
+}
+
+static inline struct ptksa_cache_entry *
+ptksa_cache_get(struct ptksa_cache *ptksa, const u8 *addr, u32 cipher)
+{
+	return NULL;
+}
+
+static inline int ptksa_cache_list(struct ptksa_cache *ptksa,
+				   char *buf, size_t len)
+{
+	return -1;
+}
+
+static inline struct ptksa_cache_entry *
+ptksa_cache_add(struct ptksa_cache *ptksa, const u8 *own_addr, const u8 *addr,
+		u32 cipher, u32 life_time, const struct wpa_ptk *ptk,
+		void (*cb)(struct ptksa_cache_entry *e), void *ctx, u32 akmp)
+{
+	return NULL;
+}
+
+static inline void ptksa_cache_flush(struct ptksa_cache *ptksa,
+				     const u8 *addr, u32 cipher)
+{
+}
+
+#endif /* CONFIG_PTKSA_CACHE */
 #endif /* PTKSA_CACHE_H */
diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h
index 2a4086b..7620f03 100644
--- a/src/common/qca-vendor.h
+++ b/src/common/qca-vendor.h
@@ -1024,39 +1024,6 @@
  *
  *	The attributes used with this subcommand are defined in
  *	enum qca_wlan_vendor_attr_tx_latency.
- *
- * @QCA_NL80211_VENDOR_SUBCMD_REGULATORY_TPC_INFO: Vendor command is used to
- *	query transmit power information on STA interface from the driver for a
- *	connected AP. The attributes included in response are defined in
- *	enum qca_wlan_vendor_attr_tpc_links. In case of MLO STA, multiple links
- *	TPC info may be returned. The information includes regulatory maximum
- *	transmit power limit, AP local power constraint advertised from AP's
- *	Beacon and Probe Response frames. For PSD power mode, the information
- *	includes PSD power levels for each subchannel of operating bandwidth.
- *	The information is driver calculated power limits based on the current
- *	regulatory domain, AP local power constraint, and other IEs. The
- *	information will be set to target. Target will decide the final TX power
- *	based on this and chip specific power conformance test limits (CTL), and
- *	SAR limits.
- *
- * @QCA_NL80211_VENDOR_SUBCMD_FW_PAGE_FAULT_REPORT: Event indication from the
- *	driver to user space which is carrying firmware page fault related
- *	summary report. The attributes for this command are defined in
- *	enum qca_wlan_vendor_attr_fw_page_fault_report.
- *
- * @QCA_NL80211_VENDOR_SUBCMD_DISASSOC_PEER: Event indication from the driver
- *	to user space to disassociate with a peer based on the peer MAC address
- *	provided. Specify the peer MAC address in
- *	QCA_WLAN_VENDOR_ATTR_MAC_ADDR. For MLO, MLD MAC address is provided.
- *
- * @QCA_NL80211_VENDOR_SUBCMD_ADJUST_TX_POWER: This vendor command is used to
- *	adjust transmit power. The attributes used with this subcommand are
- *	defined in enum qca_wlan_vendor_attr_adjust_tx_power.
- *
- * @QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_COMPLETE: Event indication from the
- *	driver to notify user application about the spectral scan completion.
- *	The attributes used with this subcommand are defined in
- *	enum qca_wlan_vendor_attr_spectral_scan_complete.
  */
 enum qca_nl80211_vendor_subcmds {
 	QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0,
@@ -1275,14 +1242,6 @@
 	/* 232 - reserved for QCA */
 	QCA_NL80211_VENDOR_SUBCMD_TX_LATENCY = 233,
 	/* 234 - reserved for QCA */
-	QCA_NL80211_VENDOR_SUBCMD_SDWF_PHY_OPS = 235,
-	QCA_NL80211_VENDOR_SUBCMD_SDWF_DEV_OPS = 236,
-	QCA_NL80211_VENDOR_SUBCMD_REGULATORY_TPC_INFO = 237,
-	QCA_NL80211_VENDOR_SUBCMD_FW_PAGE_FAULT_REPORT = 238,
-	QCA_NL80211_VENDOR_SUBCMD_FLOW_POLICY = 239,
-	QCA_NL80211_VENDOR_SUBCMD_DISASSOC_PEER = 240,
-	QCA_NL80211_VENDOR_SUBCMD_ADJUST_TX_POWER = 241,
-	QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_COMPLETE = 242,
 };
 
 /* Compatibility defines for previously used subcmd names.
@@ -1836,11 +1795,6 @@
  * scoring. In case scan was performed on a partial set of channels configured
  * with this command within last QCA_WLAN_VENDOR_ATTR_ACS_LAST_SCAN_AGEOUT_TIME
  * (in ms), scan only the remaining channels.
- *
- * @QCA_WLAN_VENDOR_ATTR_ACS_LINK_ID: Mandatory on AP MLD (u8).
- * Used with command to configure ACS operation for a specific link affiliated
- * to an AP MLD.
- *
  */
 enum qca_wlan_vendor_attr_acs_offload {
 	QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_INVALID = 0,
@@ -1864,7 +1818,6 @@
 	QCA_WLAN_VENDOR_ATTR_ACS_PUNCTURE_BITMAP = 18,
 	QCA_WLAN_VENDOR_ATTR_ACS_EHT_ENABLED = 19,
 	QCA_WLAN_VENDOR_ATTR_ACS_LAST_SCAN_AGEOUT_TIME = 20,
-	QCA_WLAN_VENDOR_ATTR_ACS_LINK_ID = 21,
 
 	/* keep last */
 	QCA_WLAN_VENDOR_ATTR_ACS_AFTER_LAST,
@@ -2226,8 +2179,7 @@
  * &enum qca_tsf_cmd.
  * @QCA_WLAN_VENDOR_ATTR_TSF_TIMER_VALUE: Optional (u64)
  * This attribute contains TSF timer value. This attribute is only available
- * in %QCA_TSF_GET, %QCA_TSF_SYNC_GET or %QCA_TSF_SYNC_GET_CSA_TIMESTAMP
- * response.
+ * in %QCA_TSF_GET or %QCA_TSF_SYNC_GET response.
  * @QCA_WLAN_VENDOR_ATTR_TSF_SOC_TIMER_VALUE: Optional (u64)
  * This attribute contains SOC timer value at TSF capture. This attribute is
  * only available in %QCA_TSF_GET or %QCA_TSF_SYNC_GET response.
@@ -2271,12 +2223,6 @@
  * userspace can query the TSF and host time mapping via the %QCA_TSF_GET
  * command.
  * @QCA_TSF_SYNC_STOP: Stop periodic TSF sync feature.
- * @QCA_TSF_SYNC_GET_CSA_TIMESTAMP: Get TSF timestamp when AP will move and
- * starts beaconing on a new channel. The driver synchronously responds with the
- * TSF value using attribute %QCA_WLAN_VENDOR_ATTR_TSF_TIMER_VALUE. Userspace
- * gets the valid CSA TSF after receiving %NL80211_CMD_CH_SWITCH_STARTED_NOTIFY
- * on the AP interface. This TSF can be sent via OOB mechanism to connected
- * clients.
  */
 enum qca_tsf_cmd {
 	QCA_TSF_CAPTURE,
@@ -2286,7 +2232,6 @@
 	QCA_TSF_AUTO_REPORT_DISABLE,
 	QCA_TSF_SYNC_START,
 	QCA_TSF_SYNC_STOP,
-	QCA_TSF_SYNC_GET_CSA_TIMESTAMP,
 };
 
 /**
@@ -2428,10 +2373,6 @@
  *	QCA_WLAN_VENDOR_SCAN_PRIORITY_HIGH as the priority of vendor scan.
  * @QCA_WLAN_VENDOR_ATTR_SCAN_PAD: Attribute used for padding for 64-bit
  *	alignment.
- * @QCA_WLAN_VENDOR_ATTR_SCAN_LINK_ID: This u8 attribute is used for OBSS scan
- *	when AP is operating as MLD to specify which link is requesting the
- *	scan or which link the scan result is for. No need of this attribute
- *	in other cases.
  */
 enum qca_wlan_vendor_attr_scan {
 	QCA_WLAN_VENDOR_ATTR_SCAN_INVALID_PARAM = 0,
@@ -2449,7 +2390,6 @@
 	QCA_WLAN_VENDOR_ATTR_SCAN_DWELL_TIME = 12,
 	QCA_WLAN_VENDOR_ATTR_SCAN_PRIORITY = 13,
 	QCA_WLAN_VENDOR_ATTR_SCAN_PAD = 14,
-	QCA_WLAN_VENDOR_ATTR_SCAN_LINK_ID = 15,
 	QCA_WLAN_VENDOR_ATTR_SCAN_AFTER_LAST,
 	QCA_WLAN_VENDOR_ATTR_SCAN_MAX =
 	QCA_WLAN_VENDOR_ATTR_SCAN_AFTER_LAST - 1
@@ -3362,24 +3302,6 @@
 	 */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_COEX_TRAFFIC_SHAPING_MODE = 105,
 
-	/* 8-bit unsigned value.
-	 *
-	 * This attribute is used to specify whether an associated peer is a QCA
-	 * device. The associated peer is specified with
-	 * QCA_WLAN_VENDOR_ATTR_CONFIG_PEER_MAC. For MLO cases, the MLD MAC
-	 * address of the peer is used.
-	 * 1 - QCA device, 0 - non-QCA device.
-	 */
-	QCA_WLAN_VENDOR_ATTR_CONFIG_QCA_PEER = 106,
-
-	/* 8-bit unsigned value to configure BTM support.
-	 *
-	 * The attribute is applicable only for STA interface. Uses enum
-	 * qca_wlan_btm_support values. This configuration is not allowed in
-	 * connected state.
-	 */
-	QCA_WLAN_VENDOR_ATTR_CONFIG_BTM_SUPPORT = 107,
-
 	/* keep last */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST,
 	QCA_WLAN_VENDOR_ATTR_CONFIG_MAX =
@@ -7768,20 +7690,6 @@
 	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_RECAPTURE = 31,
 	/* Attribute used for padding for 64-bit alignment */
 	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PAD = 32,
-	/* Spectral data transport mode. u32 attribute. It uses values
-	 * defined in enum qca_wlan_vendor_spectral_data_transport_mode.
-	 * This is an optional attribute. If this attribute is not populated,
-	 * the driver should configure the default transport mode to netlink.
-	 */
-	QCA_WLAN_VENDOR_ATTR_SPECTRAL_DATA_TRANSPORT_MODE = 33,
-	/* Spectral scan completion timeout. u32 attribute. This
-	 * attribute is used to configure a timeout value (in us). The
-	 * timeout value would be from the beginning of a spectral
-	 * scan. This is an optional attribute. If this attribute is
-	 * not populated, the driver would internally derive the
-	 * timeout value.
-	 */
-	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COMPLETION_TIMEOUT = 34,
 
 	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_AFTER_LAST,
 	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX =
@@ -10081,13 +9989,6 @@
 	 */
 	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MLD_ID_ML_PROBE_REQ = 72,
 
-	/* 8-bit unsigned value to configure the SCS traffic description
-	 * support in the EHT capabilities of an Association Request frame.
-	 * 1-enable, 0-disable
-	 * This attribute is used to configure the testbed device.
-	 */
-	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_SCS_TRAFFIC_SUPPORT = 73,
-
 	/* keep last */
 	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_AFTER_LAST,
 	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX =
@@ -12088,14 +11989,6 @@
  * %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM or based on
  * regulatory/SAE limits if %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM
  * is not provided.
- *
- * @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_IFINDEX: u32 attribute, optional.
- * This specifies the interface index (netdev) for which the corresponding
- * configurations are applied. If the interface index is not specified, the
- * configurations are applied based on
- * %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_IFACES_BITMASK.
- * %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_IFACES_BITMASK along with this
- * attribute shall have the matching nl80211_iftype.
  */
 enum qca_wlan_vendor_attr_avoid_frequency_ext {
 	QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_INVALID = 0,
@@ -12104,7 +11997,6 @@
 	QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END = 3,
 	QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM = 4,
 	QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_IFACES_BITMASK = 5,
-	QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_IFINDEX = 6,
 
 	QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_AFTER_LAST,
 	QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_MAX =
@@ -14277,14 +14169,12 @@
  * @QCA_WLAN_RATEMASK_PARAMS_TYPE_HT: HT rate mask config
  * @QCA_WLAN_RATEMASK_PARAMS_TYPE_VHT: VHT rate mask config
  * @QCA_WLAN_RATEMASK_PARAMS_TYPE_HE: HE rate mask config
- * @QCA_WLAN_RATEMASK_PARAMS_TYPE_EHT: EHT rate mask config
  */
 enum qca_wlan_ratemask_params_type {
 	QCA_WLAN_RATEMASK_PARAMS_TYPE_CCK_OFDM = 0,
 	QCA_WLAN_RATEMASK_PARAMS_TYPE_HT = 1,
 	QCA_WLAN_RATEMASK_PARAMS_TYPE_VHT = 2,
 	QCA_WLAN_RATEMASK_PARAMS_TYPE_HE = 3,
-	QCA_WLAN_RATEMASK_PARAMS_TYPE_EHT = 4,
 };
 
 /**
@@ -14305,11 +14195,7 @@
  * @QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_BITMAP: binary, rate mask bitmap.
  * A bit value of 1 represents rate is enabled and a value of 0
  * represents rate is disabled.
- * For EHT targets,
- * b0-1  => NSS1, MCS 14-15
- * b2-15 => NSS1, MCS 0-13
- * b16-29 => NSS2, MCS 0-13
- * For HE targets, 14 bits correspond to one NSS setting.
+ * For HE targets, 12 bits correspond to one NSS setting.
  * b0-13  => NSS1, MCS 0-13
  * b14-27 => NSS2, MCS 0-13 and so on for other NSS.
  * For VHT targets, 10 bits correspond to one NSS setting.
@@ -14319,18 +14205,12 @@
  * b0-7  => NSS1, MCS 0-7
  * b8-15 => NSS2, MCS 0-7 and so on for other NSS.
  * For OFDM/CCK targets, 8 bits correspond to one NSS setting.
- *
- * @QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_LINK_ID: u8, used to specify the
- * MLO link ID of a link to be configured. Optional attribute.
- * No need of this attribute in non-MLO cases. If the attribute is
- * not provided, ratemask will be applied for setup link.
  */
 enum qca_wlan_vendor_attr_ratemask_params {
 	QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_INVALID = 0,
 	QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_LIST = 1,
 	QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_TYPE = 2,
 	QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_BITMAP = 3,
-	QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_LINK_ID = 4,
 
 	/* keep last */
 	QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_AFTER_LAST,
@@ -15089,25 +14969,12 @@
  * CTL group but user can choose up to 3 SAR set index only, as the top half
  * of the SAR index (0 to 2) is used for non DBS purpose and the bottom half of
  * the SAR index (3 to 5) is used for DBS mode.
- *
- * @QCA_WLAN_VENDOR_SAR_VERSION_4: The firmware supports SAR version 4,
- * known as SAR Smart Transmit (STX) mode. STX is time averaging algorithmic
- * for power limit computation in collaboration with WWAN.
- * In STX mode, firmware has 41 indexes and there is no ctl grouping uses.
- *
- * @QCA_WLAN_VENDOR_SAR_VERSION_5: The firmware supports SAR version 5,
- * known as TAS (Time Averaging SAR) mode. In TAS mode, as name implies
- * instead of fixed static SAR power limit firmware uses time averaging
- * to adjust the SAR limit dynamically. It is wlan soc standalone mechanism.
- * In this mode firmware has up to 43 indexes.
  */
 enum qca_wlan_vendor_sar_version {
 	QCA_WLAN_VENDOR_SAR_VERSION_INVALID = 0,
 	QCA_WLAN_VENDOR_SAR_VERSION_1 = 1,
 	QCA_WLAN_VENDOR_SAR_VERSION_2 = 2,
 	QCA_WLAN_VENDOR_SAR_VERSION_3 = 3,
-	QCA_WLAN_VENDOR_SAR_VERSION_4 = 4,
-	QCA_WLAN_VENDOR_SAR_VERSION_5 = 5,
 };
 
 /**
@@ -16735,311 +16602,4 @@
 	QCA_CHAN_WIDTH_UPDATE_TYPE_TX_RX_EXT = 2,
 };
 
-/**
- * enum qca_wlan_vendor_attr_tpc_pwr_level - Definition of attributes
- * used inside nested attribute %QCA_WLAN_VENDOR_ATTR_TPC_PWR_LEVEL.
- *
- * @QCA_WLAN_VENDOR_ATTR_TPC_PWR_LEVEL_FREQUENCY: u32 channel center
- * frequency (MHz): If PSD power, carries one 20 MHz sub-channel center
- * frequency. If non PSD power, carries either 20 MHz bandwidth's center
- * channel frequency or 40 MHz bandwidth's center channel frequency
- * (or 80/160 MHz bandwidth's center channel frequency).
- *
- * @QCA_WLAN_VENDOR_ATTR_TPC_PWR_LEVEL_TX_POWER: s8 transmit power limit (dBm).
- * If PSD power, carries PSD power value of the
- * QCA_WLAN_VENDOR_ATTR_TPC_PWR_LEVEL_FREQUENCY mentioned sub-channel.
- * If non PSD power, carries EIRP power value of bandwidth mentioned
- * by QCA_WLAN_VENDOR_ATTR_TPC_PWR_LEVEL_FREQUENCY center frequency.
- */
-enum qca_wlan_vendor_attr_tpc_pwr_level {
-	QCA_WLAN_VENDOR_ATTR_TPC_PWR_LEVEL_INVALID = 0,
-	QCA_WLAN_VENDOR_ATTR_TPC_PWR_LEVEL_FREQUENCY = 1,
-	QCA_WLAN_VENDOR_ATTR_TPC_PWR_LEVEL_TX_POWER = 2,
-
-	/* keep last */
-	QCA_WLAN_VENDOR_ATTR_TPC_PWR_LEVEL_AFTER_LAST,
-	QCA_WLAN_VENDOR_ATTR_TPC_PWR_LEVEL_MAX =
-	QCA_WLAN_VENDOR_ATTR_TPC_PWR_LEVEL_AFTER_LAST - 1,
-};
-
-/**
- * enum qca_wlan_vendor_tpc - Definition of link attributes
- * used inside nested attribute %QCA_WLAN_VENDOR_ATTR_TPC_LINKS.
- *
- * @QCA_WLAN_VENDOR_ATTR_TPC_BSSID: 6-bytes AP BSSID.
- * For MLO STA, AP BSSID indicates the AP's link address.
- *
- * @QCA_WLAN_VENDOR_ATTR_TPC_PSD_POWER: PSD power flag
- * Indicates using PSD power mode if this flag is present.
- *
- * @QCA_WLAN_VENDOR_ATTR_TPC_EIRP_POWER: s8 Regulatory EIRP power
- * value in dBm
- *
- * @QCA_WLAN_VENDOR_ATTR_TPC_POWER_TYPE_6GHZ: u8 power type of 6 GHz
- * AP, refer to Table E-12-Regulatory Info subfield encoding in
- * IEEE P802.11-REVme/D4.0. Only present if link is connected to 6 GHz AP.
- *
- * @QCA_WLAN_VENDOR_ATTR_TPC_AP_CONSTRAINT_POWER: u8 Local Power Constraint
- * (dBm) advertised by AP in Power Constraint element, refer to
- * IEEE Std 802.11-2020, 9.4.2.13 Power Constraint element.
- *
- * @QCA_WLAN_VENDOR_ATTR_TPC_PWR_LEVEL: A nested attribute containing
- * attributes defined by enum qca_wlan_vendor_attr_tpc_pwr_level.
- * If PSD power, each power level describes each 20 MHz subchannel PSD
- * power value. If non PSD power, each power level describes each supported
- * bandwidth's EIRP power value (up to Max bandwidth of AP operating on),
- * each level attribute contains corresponding bandwidth's center channel
- * frequency and its EIRP power value.
- */
-enum qca_wlan_vendor_attr_tpc {
-	QCA_WLAN_VENDOR_ATTR_TPC_INVALID = 0,
-	QCA_WLAN_VENDOR_ATTR_TPC_BSSID = 1,
-	QCA_WLAN_VENDOR_ATTR_TPC_PSD_POWER = 2,
-	QCA_WLAN_VENDOR_ATTR_TPC_EIRP_POWER = 3,
-	QCA_WLAN_VENDOR_ATTR_TPC_POWER_TYPE_6GHZ = 4,
-	QCA_WLAN_VENDOR_ATTR_TPC_AP_CONSTRAINT_POWER = 5,
-	QCA_WLAN_VENDOR_ATTR_TPC_PWR_LEVEL = 6,
-
-	/* keep last */
-	QCA_WLAN_VENDOR_ATTR_TPC_AFTER_LAST,
-	QCA_WLAN_VENDOR_ATTR_TPC_MAX =
-	QCA_WLAN_VENDOR_ATTR_TPC_AFTER_LAST - 1,
-};
-
-/**
- * enum qca_wlan_vendor_attr_tpc_links - Definition of attributes
- * for %QCA_NL80211_VENDOR_SUBCMD_REGULATORY_TPC_INFO subcommand
- *
- * @QCA_WLAN_VENDOR_ATTR_TPC_LINKS: A nested attribute containing
- * per-link TPC information of all the active links of MLO STA.
- * For non MLO STA, only one link TPC information will be returned
- * for connected AP in this nested attribute.
- * The attributes used inside this nested attributes are defined
- * in enum qca_wlan_vendor_attr_tpc.
- */
-enum qca_wlan_vendor_attr_tpc_links {
-	QCA_WLAN_VENDOR_ATTR_TPC_LINKS_INVALID = 0,
-	QCA_WLAN_VENDOR_ATTR_TPC_LINKS = 1,
-
-	/* keep last */
-	QCA_WLAN_VENDOR_ATTR_TPC_LINKS_AFTER_LAST,
-	QCA_WLAN_VENDOR_ATTR_TPC_LINKS_MAX =
-	QCA_WLAN_VENDOR_ATTR_TPC_AFTER_LAST - 1,
-};
-
-/**
- * enum qca_wlan_vendor_attr_fw_page_fault_report - Used by the vendor
- * command %QCA_NL80211_VENDOR_SUBCMD_FW_PAGE_FAULT_REPORT.
- *
- * @QCA_WLAN_VENDOR_ATTR_FW_PAGE_FAULT_REPORT_DATA: The binary blob data
- * associated with the firmware page fault that is expected to contain the
- * required dump to analyze frequent page faults.
- * NLA_BINARY attribute, the maximum size is 1024 bytes.
- */
-enum qca_wlan_vendor_attr_fw_page_fault_report {
-	QCA_WLAN_VENDOR_ATTR_FW_PAGE_FAULT_REPORT_INVALID = 0,
-	QCA_WLAN_VENDOR_ATTR_FW_PAGE_FAULT_REPORT_DATA = 1,
-
-	/* keep last */
-	QCA_WLAN_VENDOR_ATTR_FW_PAGE_FAULT_REPORT_LAST,
-	QCA_WLAN_VENDOR_ATTR_FW_PAGE_FAULT_REPORT_MAX =
-	QCA_WLAN_VENDOR_ATTR_FW_PAGE_FAULT_REPORT_LAST - 1,
-};
-
-/**
- * enum qca_wlan_btm_support: BTM support configuration
- *
- * @QCA_WLAN_BTM_SUPPORT_DEFAULT: Restore default BTM support policy. The driver
- * follows the BSS Transition bit in the Extended Capabilities element from the
- * connect request IEs with the default BTM support policy.
- *
- * @QCA_WLAN_BTM_SUPPORT_DISABLE: Disable BTM support for the subsequent
- * (re)association attempts. The driver shall restore the default BTM support
- * policy during the first disconnection after successful association. When this
- * configuration is enabled, the driver shall overwrite the BSS Transition bit
- * as zero in the Extended Capabilities element while sending (Re)Association
- * Request frames. Also, the driver shall drop the BTM frames from userspace and
- * the connected AP when this configuration is enabled.
- */
-enum qca_wlan_btm_support {
-	QCA_WLAN_BTM_SUPPORT_DEFAULT = 0,
-	QCA_WLAN_BTM_SUPPORT_DISABLE = 1,
-};
-
-/**
- * enum qca_wlan_vendor_data_rate_type - Represents the possible values for
- * attribute %QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_RATE_TYPE.
- *
- * @QCA_WLAN_VENDOR_DATA_RATE_TYPE_LEGACY: Data rate type is a legacy rate code
- * used in OFDM/CCK.
- *
- * @QCA_WLAN_VENDOR_DATA_RATE_TYPE_MCS: Data rate type is an MCS index.
- *
- */
-enum qca_wlan_vendor_data_rate_type {
-	QCA_WLAN_VENDOR_DATA_RATE_TYPE_LEGACY = 0,
-	QCA_WLAN_VENDOR_DATA_RATE_TYPE_MCS = 1,
-};
-
-/**
- * enum qca_wlan_vendor_attr_adjust_tx_power_rate - Definition
- * of data rate related attributes which is used inside nested attribute
- * %QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_CHAIN_RATE_CONFIG.
- *
- * @QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_RATE_TYPE: u8 data rate type.
- * For this attribute, valid values are enumerated in enum
- * %qca_wlan_vendor_data_rate_type.
- *
- * @QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_RATE_VALUE: u8 value.
- * This attribute value is interpreted according to the value of attribute
- * %QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_RATE_TYPE. For legacy config
- * type, this attribute value is defined in the units of 0.5 Mbps.
- * For non legacy config type, this attribute carries the MCS index number.
- *
- * @QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_RATE_POWER_VALUE: u8 value in dBm.
- * Usually the target computes a final transmit power that is the maximum
- * power level that doesn't exceed the limits enforced by various sources
- * like chip-specific conformance test limits (CTL), Specific Absorption
- * Rate (SAR), Transmit Power Control (TPC), wiphy-specific limits, STA-specific
- * limits, channel avoidance limits, Automated Frequency Coordination (AFC),
- * and others. In some cases it may be desirable to use a power level that is
- * lower than the maximum power level allowed by all of these limits, so this
- * attribute provides an additional limit that can be used to reduce the
- * transmit power level.
- *
- */
-enum qca_wlan_vendor_attr_adjust_tx_power_rate {
-	QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_RATE_INVALID = 0,
-	QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_RATE_TYPE = 1,
-	QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_RATE_VALUE = 2,
-	QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_RATE_POWER_VALUE = 3,
-
-	/* keep last */
-	QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_CONFIG_AFTER_LAST,
-	QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_CONFIG_MAX =
-	QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_CONFIG_AFTER_LAST - 1,
-};
-
-/**
- * enum qca_wlan_vendor_attr_adjust_tx_power_chain_config - Definition
- * of chain related attributes which is used inside nested attribute
- * %QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_BAND_CHAIN_CONFIG.
- *
- * @QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_CHAIN_INDEX: u8 value.
- * Represents a particular chain for which transmit power adjustment needed.
- *
- * @QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_CHAIN_RATE_CONFIG: A nested
- * attribute containing data rate related information to adjust transmit
- * power. The attributes used inside this nested attributes are defined in
- * enum qca_wlan_vendor_attr_adjust_tx_power_rate.
- */
-enum qca_wlan_vendor_attr_adjust_tx_power_chain_config {
-	QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_CHAIN_INVALID = 0,
-	QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_CHAIN_INDEX = 1,
-	QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_CHAIN_RATE_CONFIG = 2,
-
-	/* keep last */
-	QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_CHAIN_AFTER_LAST,
-	QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_CHAIN_MAX =
-	QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_CHAIN_AFTER_LAST - 1,
-};
-
-/**
- * enum qca_wlan_vendor_attr_adjust_tx_power_band_config - Definition
- * of band related attributes which is used inside nested attribute
- * %QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_BAND_CONFIG.
- *
- * @QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_BAND_INDEX: u8 value to
- * indicate band for which configuration applies. Valid values are enumerated
- * in enum %nl80211_band.
- *
- * @QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_BAND_CHAIN_CONFIG: A nested
- * attribute containing per chain related information to adjust transmit
- * power. The attributes used inside this nested attribute are defined in
- * enum qca_wlan_vendor_attr_adjust_tx_power_chain_config.
- *
- */
-enum qca_wlan_vendor_attr_adjust_tx_power_band_config {
-	QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_BAND_INVALID = 0,
-	QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_BAND_INDEX = 1,
-	QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_BAND_CHAIN_CONFIG = 2,
-
-	/* keep last */
-	QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_BAND_AFTER_LAST,
-	QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_BAND_MAX =
-	QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_BAND_AFTER_LAST - 1,
-};
-
-/**
- * enum qca_wlan_vendor_attr_adjust_tx_power - Definition of attributes
- * for %QCA_NL80211_VENDOR_SUBCMD_ADJUST_TX_POWER subcommand.
- *
- * @QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_BAND_CONFIG: A nested attribute
- * containing per band related information to adjust transmit power.
- * The attributes used inside this nested attributes are defined in
- * enum qca_wlan_vendor_attr_adjust_tx_power_band_config.
- */
-enum qca_wlan_vendor_attr_adjust_tx_power {
-	QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_INVALID = 0,
-	QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_BAND_CONFIG = 1,
-
-	/* keep last */
-	QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_AFTER_LAST,
-	QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_MAX =
-	QCA_WLAN_VENDOR_ATTR_ADJUST_TX_POWER_AFTER_LAST - 1,
-};
-
-/**
- * enum qca_wlan_vendor_spectral_data_transport_mode - Attribute
- * values for QCA_WLAN_VENDOR_ATTR_SPECTRAL_DATA_TRANSPORT_MODE.
- *
- * @QCA_WLAN_VENDOR_SPECTRAL_DATA_TRANSPORT_NETLINK: Use netlink to
- * send spectral data to userspace applications.
- * @QCA_WLAN_VENDOR_SPECTRAL_DATA_TRANSPORT_RELAY: Use relay interface
- * to send spectral data to userspace applications.
- */
-enum qca_wlan_vendor_spectral_data_transport_mode {
-	QCA_WLAN_VENDOR_SPECTRAL_DATA_TRANSPORT_NETLINK = 0,
-	QCA_WLAN_VENDOR_SPECTRAL_DATA_TRANSPORT_RELAY = 1,
-};
-
-/* enum qca_wlan_vendor_spectral_scan_complete_status - Attribute
- * values for QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COMPLETE_STATUS to
- * indicate the completion status for a spectral scan.
- *
- * @QCA_WLAN_VENDOR_SPECTRAL_SCAN_COMPLETE_STATUS_SUCCESSFUL:
- * Indicates a successful completion of the scan.
- *
- * @QCA_WLAN_VENDOR_SPECTRAL_SCAN_COMPLETE_STATUS_TIMEOUT: Indicates
- * a timeout has occured while processing the spectral reports.
- */
-enum qca_wlan_vendor_spectral_scan_complete_status {
-	QCA_WLAN_VENDOR_SPECTRAL_SCAN_COMPLETE_STATUS_SUCCESSFUL = 0,
-	QCA_WLAN_VENDOR_SPECTRAL_SCAN_COMPLETE_STATUS_TIMEOUT = 1,
-};
-
-/* enum qca_wlan_vendor_attr_spectral_scan_complete - Definition of
- * attributes for @QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_COMPLETE
- * to indicate scan status and samples received from hardware.
- *
- * @QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COMPLETE_INVALID: Invalid attribute
- *
- * @QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COMPLETE_STATUS: u32 attribute.
- * Indicates completion status, either the scan is successful or a timeout
- * is issued by the driver.
- * See enum qca_wlan_vendor_spectral_scan_complete_status.
- *
- * @QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COMPLETE_RECEIVED_SAMPLES: u32
- * attribute. Number of spectral samples received after the scan has started.
- */
-enum qca_wlan_vendor_attr_spectral_scan_complete {
-	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COMPLETE_INVALID = 0,
-	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COMPLETE_STATUS = 1,
-	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COMPLETE_RECEIVED_SAMPLES = 2,
-
-	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COMPLETE_AFTER_LAST,
-	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COMPLETE_MAX =
-	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COMPLETE_AFTER_LAST - 1,
-};
-
 #endif /* QCA_VENDOR_H */
diff --git a/src/common/sae.c b/src/common/sae.c
index f1c164e..d4a196f 100644
--- a/src/common/sae.c
+++ b/src/common/sae.c
@@ -458,7 +458,7 @@
 		       * mask */
 	u8 mask;
 	struct crypto_bignum *pwe;
-	size_t prime_len = sae->tmp->prime_len;
+	size_t prime_len = sae->tmp->prime_len * 8;
 	u8 *pwe_buf;
 
 	crypto_bignum_deinit(sae->tmp->pwe_ffc, 1);
diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c
index 6ea3311..d897e0e 100644
--- a/src/common/wpa_common.c
+++ b/src/common/wpa_common.c
@@ -1104,7 +1104,7 @@
 			link_id = pos[2] & 0x0f;
 			wpa_printf(MSG_DEBUG, "FT: MLO GTK (Link ID %u)",
 				   link_id);
-			if (link_id >= MAX_NUM_MLD_LINKS)
+			if (link_id >= MAX_NUM_MLO_LINKS)
 				break;
 			parse->valid_mlo_gtks |= BIT(link_id);
 			parse->mlo_gtk[link_id] = pos;
@@ -1119,7 +1119,7 @@
 			link_id = pos[2 + 6] & 0x0f;
 			wpa_printf(MSG_DEBUG, "FT: MLO IGTK (Link ID %u)",
 				   link_id);
-			if (link_id >= MAX_NUM_MLD_LINKS)
+			if (link_id >= MAX_NUM_MLO_LINKS)
 				break;
 			parse->valid_mlo_igtks |= BIT(link_id);
 			parse->mlo_igtk[link_id] = pos;
@@ -1134,7 +1134,7 @@
 			link_id = pos[2 + 6] & 0x0f;
 			wpa_printf(MSG_DEBUG, "FT: MLO BIGTK (Link ID %u)",
 				   link_id);
-			if (link_id >= MAX_NUM_MLD_LINKS)
+			if (link_id >= MAX_NUM_MLO_LINKS)
 				break;
 			parse->valid_mlo_bigtks |= BIT(link_id);
 			parse->mlo_bigtk[link_id] = pos;
@@ -1329,7 +1329,8 @@
 		if (fte_len < 255) {
 			res = wpa_ft_parse_fte(key_mgmt, fte, fte_len, parse);
 		} else {
-			parse->fte_buf = ieee802_11_defrag(fte, fte_len, false);
+			parse->fte_buf = ieee802_11_defrag_data(fte, fte_len,
+								false);
 			if (!parse->fte_buf)
 				goto fail;
 			res = wpa_ft_parse_fte(key_mgmt,
@@ -1353,7 +1354,7 @@
 
 		/* TODO: This count should be done based on all _requested_,
 		 * not _accepted_ links. */
-		for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
+		for (link_id = 0; link_id < MAX_NUM_MLO_LINKS; link_id++) {
 			if (parse->mlo_gtk[link_id]) {
 				if (parse->rsn)
 					prot_ie_count--;
@@ -2893,7 +2894,7 @@
 }
 
 
-int wpa_insert_pmkid(u8 *ies, size_t *ies_len, const u8 *pmkid, bool replace)
+int wpa_insert_pmkid(u8 *ies, size_t *ies_len, const u8 *pmkid)
 {
 	u8 *start, *end, *rpos, *rend;
 	int added = 0;
@@ -2956,12 +2957,12 @@
 		if (rend - rpos < 2)
 			return -1;
 		num_pmkid = WPA_GET_LE16(rpos);
-		if (num_pmkid * PMKID_LEN > rend - rpos - 2)
-			return -1;
 		/* PMKID-Count was included; use it */
-		if (replace && num_pmkid != 0) {
+		if (num_pmkid != 0) {
 			u8 *after;
 
+			if (num_pmkid * PMKID_LEN > rend - rpos - 2)
+				return -1;
 			/*
 			 * PMKID may have been included in RSN IE in
 			 * (Re)Association Request frame, so remove the old
@@ -2974,9 +2975,8 @@
 			os_memmove(rpos + 2, after, end - after);
 			start[1] -= num_pmkid * PMKID_LEN;
 			added -= num_pmkid * PMKID_LEN;
-			num_pmkid = 0;
 		}
-		WPA_PUT_LE16(rpos, num_pmkid + 1);
+		WPA_PUT_LE16(rpos, 1);
 		rpos += 2;
 		os_memmove(rpos + PMKID_LEN, rpos, end + added - rpos);
 		os_memcpy(rpos, pmkid, PMKID_LEN);
@@ -3551,7 +3551,7 @@
 	    selector == RSN_KEY_DATA_MLO_GTK) {
 		link_id = (p[0] & RSN_MLO_GTK_KDE_PREFIX0_LINK_ID_MASK) >>
 			RSN_MLO_GTK_KDE_PREFIX0_LINK_ID_SHIFT;
-		if (link_id >= MAX_NUM_MLD_LINKS)
+		if (link_id >= MAX_NUM_MLO_LINKS)
 			return 2;
 
 		ie->valid_mlo_gtks |= BIT(link_id);
@@ -3569,7 +3569,7 @@
 	    selector == RSN_KEY_DATA_MLO_IGTK) {
 		link_id = (p[8] & RSN_MLO_IGTK_KDE_PREFIX8_LINK_ID_MASK) >>
 			  RSN_MLO_IGTK_KDE_PREFIX8_LINK_ID_SHIFT;
-		if (link_id >= MAX_NUM_MLD_LINKS)
+		if (link_id >= MAX_NUM_MLO_LINKS)
 			return 2;
 
 		ie->valid_mlo_igtks |= BIT(link_id);
@@ -3587,7 +3587,7 @@
 	    selector == RSN_KEY_DATA_MLO_BIGTK) {
 		link_id = (p[8] & RSN_MLO_BIGTK_KDE_PREFIX8_LINK_ID_MASK) >>
 			  RSN_MLO_BIGTK_KDE_PREFIX8_LINK_ID_SHIFT;
-		if (link_id >= MAX_NUM_MLD_LINKS)
+		if (link_id >= MAX_NUM_MLO_LINKS)
 			return 2;
 
 		ie->valid_mlo_bigtks |= BIT(link_id);
@@ -3605,7 +3605,7 @@
 	    selector == RSN_KEY_DATA_MLO_LINK) {
 		link_id = (p[0] & RSN_MLO_LINK_KDE_LI_LINK_ID_MASK) >>
 			  RSN_MLO_LINK_KDE_LI_LINK_ID_SHIFT;
-		if (link_id >= MAX_NUM_MLD_LINKS)
+		if (link_id >= MAX_NUM_MLO_LINKS)
 			return 2;
 
 		ie->valid_mlo_links |= BIT(link_id);
diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h
index 01efeea..1269bf9 100644
--- a/src/common/wpa_common.h
+++ b/src/common/wpa_common.h
@@ -9,8 +9,6 @@
 #ifndef WPA_COMMON_H
 #define WPA_COMMON_H
 
-#include "common/defs.h"
-
 /* IEEE 802.11i */
 #define PMKID_LEN 16
 #define PMK_LEN 32
@@ -557,7 +555,9 @@
 int wpa_compare_rsn_ie(int ft_initial_assoc,
 		       const u8 *ie1, size_t ie1len,
 		       const u8 *ie2, size_t ie2len);
-int wpa_insert_pmkid(u8 *ies, size_t *ies_len, const u8 *pmkid, bool replace);
+int wpa_insert_pmkid(u8 *ies, size_t *ies_len, const u8 *pmkid);
+
+#define MAX_NUM_MLO_LINKS 15
 
 struct wpa_ft_ies {
 	const u8 *mdie;
@@ -596,14 +596,14 @@
 	const u8 *rsnxe;
 	size_t rsnxe_len;
 	u16 valid_mlo_gtks; /* bitmap of valid link GTK subelements */
-	const u8 *mlo_gtk[MAX_NUM_MLD_LINKS];
-	size_t mlo_gtk_len[MAX_NUM_MLD_LINKS];
+	const u8 *mlo_gtk[MAX_NUM_MLO_LINKS];
+	size_t mlo_gtk_len[MAX_NUM_MLO_LINKS];
 	u16 valid_mlo_igtks; /* bitmap of valid link IGTK subelements */
-	const u8 *mlo_igtk[MAX_NUM_MLD_LINKS];
-	size_t mlo_igtk_len[MAX_NUM_MLD_LINKS];
+	const u8 *mlo_igtk[MAX_NUM_MLO_LINKS];
+	size_t mlo_igtk_len[MAX_NUM_MLO_LINKS];
 	u16 valid_mlo_bigtks; /* bitmap of valid link BIGTK subelements */
-	const u8 *mlo_bigtk[MAX_NUM_MLD_LINKS];
-	size_t mlo_bigtk_len[MAX_NUM_MLD_LINKS];
+	const u8 *mlo_bigtk[MAX_NUM_MLO_LINKS];
+	size_t mlo_bigtk_len[MAX_NUM_MLO_LINKS];
 
 	struct wpabuf *fte_buf;
 };
@@ -700,17 +700,17 @@
 	const u8 *wmm;
 	size_t wmm_len;
 	u16 valid_mlo_gtks; /* bitmap of valid link GTK KDEs */
-	const u8 *mlo_gtk[MAX_NUM_MLD_LINKS];
-	size_t mlo_gtk_len[MAX_NUM_MLD_LINKS];
+	const u8 *mlo_gtk[MAX_NUM_MLO_LINKS];
+	size_t mlo_gtk_len[MAX_NUM_MLO_LINKS];
 	u16 valid_mlo_igtks; /* bitmap of valid link IGTK KDEs */
-	const u8 *mlo_igtk[MAX_NUM_MLD_LINKS];
-	size_t mlo_igtk_len[MAX_NUM_MLD_LINKS];
+	const u8 *mlo_igtk[MAX_NUM_MLO_LINKS];
+	size_t mlo_igtk_len[MAX_NUM_MLO_LINKS];
 	u16 valid_mlo_bigtks; /* bitmap of valid link BIGTK KDEs */
-	const u8 *mlo_bigtk[MAX_NUM_MLD_LINKS];
-	size_t mlo_bigtk_len[MAX_NUM_MLD_LINKS];
+	const u8 *mlo_bigtk[MAX_NUM_MLO_LINKS];
+	size_t mlo_bigtk_len[MAX_NUM_MLO_LINKS];
 	u16 valid_mlo_links; /* bitmap of valid MLO link KDEs */
-	const u8 *mlo_link[MAX_NUM_MLD_LINKS];
-	size_t mlo_link_len[MAX_NUM_MLD_LINKS];
+	const u8 *mlo_link[MAX_NUM_MLO_LINKS];
+	size_t mlo_link_len[MAX_NUM_MLO_LINKS];
 };
 
 int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie);
diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
index f614250..416e0d6 100644
--- a/src/common/wpa_ctrl.h
+++ b/src/common/wpa_ctrl.h
@@ -87,8 +87,6 @@
 #define WPA_EVENT_BEACON_LOSS "CTRL-EVENT-BEACON-LOSS "
 /** Regulatory domain channel */
 #define WPA_EVENT_REGDOM_CHANGE "CTRL-EVENT-REGDOM-CHANGE "
-/** Regulatory beacon hint */
-#define WPA_EVENT_REGDOM_BEACON_HINT "CTRL-EVENT-REGDOM-BEACON-HINT "
 /** Channel switch started (followed by freq=<MHz> and other channel parameters)
  */
 #define WPA_EVENT_CHANNEL_SWITCH_STARTED "CTRL-EVENT-STARTED-CHANNEL-SWITCH "
@@ -232,13 +230,6 @@
 #define DPP_EVENT_PB_RESULT "DPP-PB-RESULT "
 #define DPP_EVENT_RELAY_NEEDS_CONTROLLER "DPP-RELAY-NEEDS-CONTROLLER "
 
-/* Wi-Fi Aware (NAN USD) events */
-#define NAN_DISCOVERY_RESULT "NAN-DISCOVERY-RESULT "
-#define NAN_REPLIED "NAN-REPLIED "
-#define NAN_PUBLISH_TERMINATED "NAN-PUBLISH-TERMINATED "
-#define NAN_SUBSCRIBE_TERMINATED "NAN-SUBSCRIBE-TERMINATED "
-#define NAN_RECEIVE "NAN-RECEIVE "
-
 /* MESH events */
 #define MESH_GROUP_STARTED "MESH-GROUP-STARTED "
 #define MESH_GROUP_REMOVED "MESH-GROUP-REMOVED "
@@ -413,9 +404,6 @@
 /* parameters: <STA address> <dialog token> <report mode> <beacon report> */
 #define BEACON_RESP_RX "BEACON-RESP-RX "
 
-/* parameters: <STA address> <dialog token> <link measurement report> */
-#define LINK_MSR_RESP_RX "LINK-MSR-RESP-RX "
-
 /* PMKSA cache entry added; parameters: <BSSID> <network_id> */
 #define PMKSA_CACHE_ADDED "PMKSA-CACHE-ADDED "
 /* PMKSA cache entry removed; parameters: <BSSID> <network_id> */
diff --git a/src/crypto/crypto_module_tests.c b/src/crypto/crypto_module_tests.c
index ffeddba..4147f41 100644
--- a/src/crypto/crypto_module_tests.c
+++ b/src/crypto/crypto_module_tests.c
@@ -2446,7 +2446,6 @@
 	wpabuf_free(res_pt);
 	wpabuf_free(res_ct);
 	crypto_ec_key_deinit(own_priv);
-	crypto_ec_key_deinit(peer_pub);
 	return res;
 }
 
diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c
index 2d8ff60..22f6ab4 100644
--- a/src/crypto/crypto_openssl.c
+++ b/src/crypto/crypto_openssl.c
@@ -1,6 +1,6 @@
 /*
  * Wrapper functions for OpenSSL libcrypto
- * Copyright (c) 2004-2024, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2022, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -31,11 +31,6 @@
 #else /* OpenSSL version >= 3.0 */
 #include <openssl/cmac.h>
 #endif /* OpenSSL version >= 3.0 */
-#ifdef CONFIG_DPP3
-#if OPENSSL_VERSION_NUMBER >= 0x30200000L
-#include <openssl/hpke.h>
-#endif
-#endif /* CONFIG_DPP3 */
 
 #include "common.h"
 #include "utils/const_time.h"
@@ -476,11 +471,11 @@
 	ctx = EVP_CIPHER_CTX_new();
 	if (ctx == NULL)
 		return NULL;
-	if (EVP_EncryptInit_ex(ctx, type, NULL, key, NULL) != 1 ||
-	    EVP_CIPHER_CTX_set_padding(ctx, 0) != 1) {
+	if (EVP_EncryptInit_ex(ctx, type, NULL, key, NULL) != 1) {
 		EVP_CIPHER_CTX_free(ctx);
 		return NULL;
 	}
+	EVP_CIPHER_CTX_set_padding(ctx, 0);
 	return ctx;
 }
 
@@ -533,11 +528,11 @@
 	ctx = EVP_CIPHER_CTX_new();
 	if (ctx == NULL)
 		return NULL;
-	if (EVP_DecryptInit_ex(ctx, type, NULL, key, NULL) != 1 ||
-	    EVP_CIPHER_CTX_set_padding(ctx, 0) != 1) {
+	if (EVP_DecryptInit_ex(ctx, type, NULL, key, NULL) != 1) {
 		EVP_CIPHER_CTX_free(ctx);
 		return NULL;
 	}
+	EVP_CIPHER_CTX_set_padding(ctx, 0);
 	return ctx;
 }
 
@@ -1318,7 +1313,6 @@
 #else /* OpenSSL version >= 3.0 */
 	HMAC_CTX *ctx;
 #endif /* OpenSSL version >= 3.0 */
-	bool failed;
 };
 
 
@@ -1431,11 +1425,9 @@
 	if (ctx == NULL)
 		return;
 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
-	if (!EVP_MAC_update(ctx->ctx, data, len))
-		ctx->failed = true;
+	EVP_MAC_update(ctx->ctx, data, len);
 #else /* OpenSSL version >= 3.0 */
-	if (!HMAC_Update(ctx->ctx, data, len))
-		ctx->failed = true;
+	HMAC_Update(ctx->ctx, data, len);
 #endif /* OpenSSL version >= 3.0 */
 }
 
@@ -1445,7 +1437,6 @@
 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
 	size_t mdlen;
 	int res;
-	bool failed;
 
 	if (!ctx)
 		return -2;
@@ -1464,15 +1455,11 @@
 	}
 	res = EVP_MAC_final(ctx->ctx, mac, &mdlen, mdlen);
 	EVP_MAC_CTX_free(ctx->ctx);
-	failed = ctx->failed;
 	bin_clear_free(ctx, sizeof(*ctx));
 
 	if (TEST_FAIL())
 		return -1;
 
-	if (failed)
-		return -2;
-
 	if (res == 1) {
 		*len = mdlen;
 		return 0;
@@ -1482,7 +1469,6 @@
 #else /* OpenSSL version >= 3.0 */
 	unsigned int mdlen;
 	int res;
-	bool failed;
 
 	if (ctx == NULL)
 		return -2;
@@ -1496,15 +1482,11 @@
 	mdlen = *len;
 	res = HMAC_Final(ctx->ctx, mac, &mdlen);
 	HMAC_CTX_free(ctx->ctx);
-	failed = ctx->failed;
 	bin_clear_free(ctx, sizeof(*ctx));
 
 	if (TEST_FAIL())
 		return -1;
 
-	if (failed)
-		return -2;
-
 	if (res == 1) {
 		*len = mdlen;
 		return 0;
@@ -1835,7 +1817,6 @@
 	ret = 0;
 fail:
 	EVP_MAC_CTX_free(ctx);
-	EVP_MAC_free(emac);
 	return ret;
 #else /* OpenSSL version >= 3.0 */
 	CMAC_CTX *ctx;
@@ -2860,10 +2841,8 @@
 
 	/* Encode using SECG SEC 1, Sec. 2.3.4 format */
 	peer = os_malloc(1 + len);
-	if (!peer) {
-		EVP_PKEY_free(peerkey);
+	if (!peer)
 		return NULL;
-	}
 	peer[0] = inc_y ? 0x04 : 0x02;
 	os_memcpy(peer + 1, key, len);
 
@@ -3018,15 +2997,11 @@
 		NULL, NULL);
 	if (!ctx ||
 	    OSSL_DECODER_from_data(ctx, &der, &der_len) != 1) {
-		wpa_printf(MSG_INFO,
-			   "OpenSSL: Decoding EC private key (DER) failed: %s",
+		wpa_printf(MSG_INFO, "OpenSSL: Decoding EC private key (DER) failed: %s",
 			   ERR_error_string(ERR_get_error(), NULL));
-		if (ctx)
-			OSSL_DECODER_CTX_free(ctx);
 		goto fail;
 	}
 
-	OSSL_DECODER_CTX_free(ctx);
 	return (struct crypto_ec_key *) pkey;
 fail:
 	crypto_ec_key_deinit((struct crypto_ec_key *) pkey);
@@ -3933,10 +3908,9 @@
 	group = EC_GROUP_new_by_curve_name(nid);
 	prime = BN_new();
 	if (!group || !prime)
-		goto fail;
+		return -1;
 	if (EC_GROUP_get_curve(group, prime, NULL, NULL, NULL) == 1)
 		prime_len = BN_num_bytes(prime);
-fail:
 	EC_GROUP_free(group);
 	BN_free(prime);
 	return prime_len;
@@ -4882,7 +4856,7 @@
 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
 	hmac = EVP_MAC_fetch(NULL, "HMAC", NULL);
 	if (!hmac)
-		goto fail;
+		return -1;
 
 	params[0] = OSSL_PARAM_construct_utf8_string(
 		"digest",
@@ -4891,7 +4865,7 @@
 #else /* OpenSSL version >= 3.0 */
 	hctx = HMAC_CTX_new();
 	if (!hctx)
-		goto fail;
+		return -1;
 #endif /* OpenSSL version >= 3.0 */
 
 	while (left > 0) {
@@ -4900,7 +4874,7 @@
 		EVP_MAC_CTX_free(hctx);
 		hctx = EVP_MAC_CTX_new(hmac);
 		if (!hctx)
-			goto fail;
+			return -1;
 
 		if (EVP_MAC_init(hctx, prk, mdlen, params) != 1)
 			goto fail;
@@ -5151,13 +5125,13 @@
 }
 
 
-static struct wpabuf * hpke_base_seal_int(enum hpke_kem_id kem_id,
-					  enum hpke_kdf_id kdf_id,
-					  enum hpke_aead_id aead_id,
-					  struct crypto_ec_key *peer_pub,
-					  const u8 *info, size_t info_len,
-					  const u8 *aad, size_t aad_len,
-					  const u8 *pt, size_t pt_len)
+struct wpabuf * hpke_base_seal(enum hpke_kem_id kem_id,
+			       enum hpke_kdf_id kdf_id,
+			       enum hpke_aead_id aead_id,
+			       struct crypto_ec_key *peer_pub,
+			       const u8 *info, size_t info_len,
+			       const u8 *aad, size_t aad_len,
+			       const u8 *pt, size_t pt_len)
 {
 	struct hpke_context *ctx;
 	u8 shared_secret[HPKE_MAX_SHARED_SECRET_LEN];
@@ -5315,13 +5289,13 @@
 }
 
 
-static struct wpabuf * hpke_base_open_int(enum hpke_kem_id kem_id,
-					  enum hpke_kdf_id kdf_id,
-					  enum hpke_aead_id aead_id,
-					  struct crypto_ec_key *own_priv,
-					  const u8 *info, size_t info_len,
-					  const u8 *aad, size_t aad_len,
-					  const u8 *enc_ct, size_t enc_ct_len)
+struct wpabuf * hpke_base_open(enum hpke_kem_id kem_id,
+			       enum hpke_kdf_id kdf_id,
+			       enum hpke_aead_id aead_id,
+			       struct crypto_ec_key *own_priv,
+			       const u8 *info, size_t info_len,
+			       const u8 *aad, size_t aad_len,
+			       const u8 *enc_ct, size_t enc_ct_len)
 {
 	struct hpke_context *ctx;
 	u8 shared_secret[HPKE_MAX_SHARED_SECRET_LEN];
@@ -5350,231 +5324,6 @@
 	return pt;
 }
 
-
-#if OPENSSL_VERSION_NUMBER >= 0x30200000L
-
-static bool hpke_set_suite(OSSL_HPKE_SUITE *suite,
-			   enum hpke_kem_id kem_id,
-			   enum hpke_kdf_id kdf_id,
-			   enum hpke_aead_id aead_id)
-{
-	os_memset(suite, 0, sizeof(*suite));
-
-	switch (kem_id) {
-	case HPKE_DHKEM_P256_HKDF_SHA256:
-		suite->kem_id = OSSL_HPKE_KEM_ID_P256;
-		break;
-	case HPKE_DHKEM_P384_HKDF_SHA384:
-		suite->kem_id = OSSL_HPKE_KEM_ID_P384;
-		break;
-	case HPKE_DHKEM_P521_HKDF_SHA512:
-		suite->kem_id = OSSL_HPKE_KEM_ID_P521;
-		break;
-	default:
-		return false;
-	}
-
-	switch (kdf_id) {
-	case HPKE_KDF_HKDF_SHA256:
-		suite->kdf_id = OSSL_HPKE_KDF_ID_HKDF_SHA256;
-		break;
-	case HPKE_KDF_HKDF_SHA384:
-		suite->kdf_id = OSSL_HPKE_KDF_ID_HKDF_SHA384;
-		break;
-	case HPKE_KDF_HKDF_SHA512:
-		suite->kdf_id = OSSL_HPKE_KDF_ID_HKDF_SHA512;
-		break;
-	default:
-		return false;
-	}
-
-	switch (aead_id) {
-	case HPKE_AEAD_AES_128_GCM:
-		suite->aead_id = OSSL_HPKE_AEAD_ID_AES_GCM_128;
-		break;
-	case HPKE_AEAD_AES_256_GCM:
-		suite->aead_id = OSSL_HPKE_AEAD_ID_AES_GCM_256;
-		break;
-	default:
-		return false;
-	}
-
-	if (!OSSL_HPKE_suite_check(*suite)) {
-		wpa_printf(MSG_INFO,
-			   "OpenSSL: HPKE suite kem_id=%d kdf_id=%d aead_id=%d not supported",
-			   kem_id, kdf_id, aead_id);
-		return false;
-	}
-
-	return true;
-}
-
-
-struct wpabuf * hpke_base_seal(enum hpke_kem_id kem_id,
-			       enum hpke_kdf_id kdf_id,
-			       enum hpke_aead_id aead_id,
-			       struct crypto_ec_key *peer_pub,
-			       const u8 *info, size_t info_len,
-			       const u8 *aad, size_t aad_len,
-			       const u8 *pt, size_t pt_len)
-{
-	OSSL_HPKE_SUITE suite;
-	OSSL_HPKE_CTX *ctx = NULL;
-	struct wpabuf *res = NULL, *buf, *pub = NULL;
-	size_t enc_len, ct_len;
-	int group;
-
-	group = crypto_ec_key_group(peer_pub);
-	if (group == 28 || group == 29 || group == 30) {
-		/* Use the internal routines for the special DPP use case with
-		 * brainpool curves, */
-		return hpke_base_seal_int(kem_id, kdf_id, aead_id, peer_pub,
-					  info, info_len, aad, aad_len,
-					  pt, pt_len);
-	}
-
-
-	if (!hpke_set_suite(&suite, kem_id, kdf_id, aead_id))
-		return NULL;
-
-	enc_len = OSSL_HPKE_get_public_encap_size(suite);
-	ct_len = OSSL_HPKE_get_ciphertext_size(suite, pt_len);
-	buf = wpabuf_alloc(enc_len + ct_len);
-	if (!buf)
-		goto out;
-
-	pub = crypto_ec_key_get_pubkey_point(peer_pub, 1);
-	if (!pub)
-		goto out;
-
-	ctx = OSSL_HPKE_CTX_new(OSSL_HPKE_MODE_BASE, suite,
-				OSSL_HPKE_ROLE_SENDER, NULL, NULL);
-	if (!ctx)
-		goto out;
-
-	if (OSSL_HPKE_encap(ctx, wpabuf_put(buf, 0), &enc_len,
-			    wpabuf_head(pub), wpabuf_len(pub),
-			    info, info_len) != 1) {
-		wpa_printf(MSG_DEBUG, "OpenSSL: OSSL_HPKE_encap failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
-		goto out;
-	}
-	wpabuf_put(buf, enc_len);
-
-	if (OSSL_HPKE_seal(ctx, wpabuf_put(buf, 0), &ct_len, aad, aad_len,
-			   pt, pt_len) != 1) {
-		wpa_printf(MSG_DEBUG, "OpenSSL: OSSL_HPKE_seal failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
-		goto out;
-	}
-	wpabuf_put(buf, ct_len);
-	res = buf;
-	buf = NULL;
-
-out:
-	OSSL_HPKE_CTX_free(ctx);
-	wpabuf_free(buf);
-	wpabuf_free(pub);
-	return res;
-}
-
-
-struct wpabuf * hpke_base_open(enum hpke_kem_id kem_id,
-			       enum hpke_kdf_id kdf_id,
-			       enum hpke_aead_id aead_id,
-			       struct crypto_ec_key *own_priv,
-			       const u8 *info, size_t info_len,
-			       const u8 *aad, size_t aad_len,
-			       const u8 *enc_ct, size_t enc_ct_len)
-{
-	OSSL_HPKE_SUITE suite;
-	OSSL_HPKE_CTX *ctx;
-	struct wpabuf *buf = NULL, *res = NULL;
-	size_t len, enc_len;
-	int group;
-
-	group = crypto_ec_key_group(own_priv);
-	if (group == 28 || group == 29 || group == 30) {
-		/* Use the internal routines for the special DPP use case with
-		 * brainpool curves, */
-		return hpke_base_open_int(kem_id, kdf_id, aead_id, own_priv,
-					  info, info_len, aad, aad_len,
-					  enc_ct, enc_ct_len);
-	}
-
-	if (!hpke_set_suite(&suite, kem_id, kdf_id, aead_id))
-		return NULL;
-
-	enc_len = OSSL_HPKE_get_public_encap_size(suite);
-	if (enc_ct_len < enc_len) {
-		wpa_printf(MSG_DEBUG, "OpenSSL: Too short HPKE enc_ct data");
-		return NULL;
-	}
-
-	ctx = OSSL_HPKE_CTX_new(OSSL_HPKE_MODE_BASE, suite,
-				OSSL_HPKE_ROLE_RECEIVER, NULL, NULL);
-	if (!ctx)
-		goto out;
-
-	if (OSSL_HPKE_decap(ctx, enc_ct, enc_len, (EVP_PKEY *) own_priv,
-			    info, info_len) != 1) {
-		wpa_printf(MSG_DEBUG, "OpenSSL: OSSL_HPKE_decap failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
-		goto out;
-	}
-
-	len = enc_ct_len;
-	buf = wpabuf_alloc(len);
-	if (!buf)
-		goto out;
-
-	if (OSSL_HPKE_open(ctx, wpabuf_put(buf, 0), &len, aad, aad_len,
-			   enc_ct + enc_len, enc_ct_len - enc_len) != 1) {
-		wpa_printf(MSG_DEBUG, "OpenSSL: OSSL_HPKE_open failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
-		goto out;
-	}
-
-	wpabuf_put(buf, len);
-	res = buf;
-	buf = NULL;
-
-out:
-	OSSL_HPKE_CTX_free(ctx);
-	wpabuf_free(buf);
-	return res;
-}
-
-#else /* OpenSSL < 3.2 */
-
-struct wpabuf * hpke_base_seal(enum hpke_kem_id kem_id,
-			       enum hpke_kdf_id kdf_id,
-			       enum hpke_aead_id aead_id,
-			       struct crypto_ec_key *peer_pub,
-			       const u8 *info, size_t info_len,
-			       const u8 *aad, size_t aad_len,
-			       const u8 *pt, size_t pt_len)
-{
-	return hpke_base_seal_int(kem_id, kdf_id, aead_id, peer_pub,
-				  info, info_len, aad, aad_len, pt, pt_len);
-}
-
-
-struct wpabuf * hpke_base_open(enum hpke_kem_id kem_id,
-			       enum hpke_kdf_id kdf_id,
-			       enum hpke_aead_id aead_id,
-			       struct crypto_ec_key *own_priv,
-			       const u8 *info, size_t info_len,
-			       const u8 *aad, size_t aad_len,
-			       const u8 *enc_ct, size_t enc_ct_len)
-{
-	return hpke_base_open_int(kem_id, kdf_id, aead_id, own_priv,
-				  info, info_len, aad, aad_len,
-				  enc_ct, enc_ct_len);
-}
-
-#endif /* OpenSSL < 3.2 */
-
 #endif /* CONFIG_DPP3 */
 
 
diff --git a/src/crypto/sha256-internal.c b/src/crypto/sha256-internal.c
index 81e6e5e..ff1e2ba 100644
--- a/src/crypto/sha256-internal.c
+++ b/src/crypto/sha256-internal.c
@@ -76,6 +76,9 @@
 #define Sigma1(x)       (S(x, 6) ^ S(x, 11) ^ S(x, 25))
 #define Gamma0(x)       (S(x, 7) ^ S(x, 18) ^ R(x, 3))
 #define Gamma1(x)       (S(x, 17) ^ S(x, 19) ^ R(x, 10))
+#ifndef MIN
+#define MIN(x, y) (((x) < (y)) ? (x) : (y))
+#endif
 
 /* compress 512-bits */
 static int sha256_compress(struct sha256_state *md, unsigned char *buf)
diff --git a/src/crypto/sha512-internal.c b/src/crypto/sha512-internal.c
index 8e98a9c..c026394 100644
--- a/src/crypto/sha512-internal.c
+++ b/src/crypto/sha512-internal.c
@@ -97,6 +97,9 @@
 #define Sigma1(x)       (S(x, 14) ^ S(x, 18) ^ S(x, 41))
 #define Gamma0(x)       (S(x, 1) ^ S(x, 8) ^ R(x, 7))
 #define Gamma1(x)       (S(x, 19) ^ S(x, 61) ^ R(x, 6))
+#ifndef MIN
+#define MIN(x, y) (((x) < (y)) ? (x) : (y))
+#endif
 
 #define ROR64c(x, y) \
     ( ((((x) & CONST64(0xFFFFFFFFFFFFFFFF)) >> ((u64) (y) & CONST64(63))) | \
diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index f5d734d..103c333 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -19,16 +19,14 @@
 #endif
 #endif
 
-#ifndef OPENSSL_NO_ENGINE
-/* OpenSSL 3.0 has moved away from the engine API */
-#define OPENSSL_SUPPRESS_DEPRECATED
-#include <openssl/engine.h>
-#endif /* OPENSSL_NO_ENGINE */
 #include <openssl/ssl.h>
 #include <openssl/err.h>
 #include <openssl/opensslv.h>
 #include <openssl/pkcs12.h>
 #include <openssl/x509v3.h>
+#ifndef OPENSSL_NO_ENGINE
+#include <openssl/engine.h>
+#endif /* OPENSSL_NO_ENGINE */
 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
 #include <openssl/core_names.h>
 #include <openssl/decoder.h>
@@ -154,7 +152,6 @@
 	unsigned int crl_reload_interval;
 	struct os_reltime crl_last_reload;
 	char *check_cert_subject;
-	char *openssl_ciphers;
 };
 
 struct tls_connection {
@@ -1264,7 +1261,6 @@
 	}
 
 	os_free(data->check_cert_subject);
-	os_free(data->openssl_ciphers);
 	os_free(data);
 }
 
@@ -3253,9 +3249,6 @@
 	}
 #endif
 
-	if (!openssl_ciphers)
-		openssl_ciphers = conn->data->openssl_ciphers;
-
 #ifdef CONFIG_SUITEB
 #ifdef OPENSSL_IS_BORINGSSL
 	/* Start with defaults from BoringSSL */
@@ -5756,14 +5749,6 @@
 		return -1;
 	}
 
-	os_free(data->openssl_ciphers);
-	if (params->openssl_ciphers) {
-		data->openssl_ciphers = os_strdup(params->openssl_ciphers);
-		if (!data->openssl_ciphers)
-			return -1;
-	} else {
-		data->openssl_ciphers = NULL;
-	}
 	if (params->openssl_ciphers &&
 	    SSL_CTX_set_cipher_list(ssl_ctx, params->openssl_ciphers) != 1) {
 		wpa_printf(MSG_INFO,
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 069e741..7ae7d90 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -43,7 +43,6 @@
 
 #define HOSTAPD_CHAN_VHT_80MHZ_SUBCHANNEL 0x00000800
 #define HOSTAPD_CHAN_VHT_160MHZ_SUBCHANNEL 0x00001000
-#define HOSTAPD_CHAN_EHT_320MHZ_SUBCHANNEL 0x00002000
 
 #define HOSTAPD_CHAN_INDOOR_ONLY 0x00010000
 #define HOSTAPD_CHAN_GO_CONCURRENT 0x00020000
@@ -248,11 +247,6 @@
 	enum hostapd_hw_mode mode;
 
 	/**
-	 * is_6ghz - Whether the mode information is for the 6 GHz band
-	 */
-	bool is_6ghz;
-
-	/**
 	 * num_channels - Number of entries in the channels array
 	 */
 	int num_channels;
@@ -701,14 +695,6 @@
 	 */
 	unsigned int min_probe_req_content:1;
 
-	/**
-	 * link_id - Specify the link that is requesting the scan on an MLD
-	 *
-	 * This is set when operating as an AP MLD and doing an OBSS scan.
-	 * -1 indicates that no particular link ID is set.
-	 */
-	s8 link_id;
-
 	/*
 	 * NOTE: Whenever adding new parameters here, please make sure
 	 * wpa_scan_clone_params() and wpa_scan_free_params() get updated with
@@ -963,8 +949,6 @@
 		const u8 *bssid;
 		const u8 *ies;
 		size_t ies_len;
-		int error;
-		bool disabled;
 	} mld_links[MAX_NUM_MLD_LINKS];
 };
 
@@ -2731,7 +2715,6 @@
  * @counter_offset_beacon: Offset to the count field in beacon's tail
  * @counter_offset_presp: Offset to the count field in probe resp.
  * @punct_bitmap - Preamble puncturing bitmap
- * @link_id: Link ID to determine the link for MLD; -1 for non-MLD
  */
 struct csa_settings {
 	u8 cs_count;
@@ -2745,7 +2728,6 @@
 	u16 counter_offset_presp[2];
 
 	u16 punct_bitmap;
-	int link_id;
 };
 
 /**
@@ -2837,9 +2819,6 @@
 
 	/* Indicates whether EHT is enabled */
 	bool eht_enabled;
-
-	/* Indicates the link if MLO case; -1 otherwise */
-	int link_id;
 };
 
 struct wpa_bss_trans_info {
@@ -3385,17 +3364,6 @@
 			     size_t ies_len);
 
 	/**
-	 * get_scan_results - Fetch the latest scan results
-	 * @priv: Private driver interface data
-	 * @bssid: Return results only for the specified BSSID, %NULL for all
-	 *
-	 * Returns: Allocated buffer of scan results (caller is responsible for
-	 * freeing the data structure) on success, NULL on failure
-	 */
-	struct wpa_scan_results * (*get_scan_results)(void *priv,
-						      const u8 *bssid);
-
-	/**
 	 * get_scan_results2 - Fetch the latest scan results
 	 * @priv: private driver interface data
 	 *
@@ -4579,14 +4547,13 @@
 	/**
 	 * stop_ap - Removes beacon from AP
 	 * @priv: Private driver interface data
-	 * @link_id: Link ID of the specified link; -1 for non-MLD
 	 * Returns: 0 on success, -1 on failure (or if not supported)
 	 *
 	 * This optional function can be used to disable AP mode related
 	 * configuration. Unlike deinit_ap, it does not change to station
 	 * mode.
 	 */
-	int (*stop_ap)(void *priv, int link_id);
+	int (*stop_ap)(void *priv);
 
 	/**
 	 * get_survey - Retrieve survey data
@@ -5166,44 +5133,9 @@
 	 * @priv: Private driver interface data
 	 * @link_id: The link ID
 	 * @addr: The MAC address to use for the link
-	 * @bss_ctx: BSS context for %WPA_IF_AP_BSS interfaces
 	 * Returns: 0 on success, negative value on failure
 	 */
-	int (*link_add)(void *priv, u8 link_id, const u8 *addr, void *bss_ctx);
-
-	/**
-	 * link_remove - Remove a link from the AP MLD interface
-	 * @priv: Private driver interface data
-	 * @type: Interface type
-	 * @ifname: Interface name of the virtual interface from where the link
-	 *	is to be removed.
-	 * @link_id: Valid link ID to remove
-	 * Returns: 0 on success, -1 on failure
-	 */
-	int (*link_remove)(void *priv, enum wpa_driver_if_type type,
-			   const char *ifname, u8 link_id);
-
-	/**
-	 * is_drv_shared - Check whether the driver interface is shared
-	 * @priv: Private driver interface data from init()
-	 * @bss_ctx: BSS context for %WPA_IF_AP_BSS interfaces
-	 *
-	 * Checks whether the driver interface is being used by other partner
-	 * BSS(s) or not. This is used to decide whether the driver interface
-	 * needs to be deinitilized when one interface is getting deinitialized.
-	 *
-	 * Returns: true if it is being used or else false.
-	 */
-	bool (*is_drv_shared)(void *priv, void *bss_ctx);
-
-	/**
-	 * link_sta_remove - Remove a link STA from an MLD STA
-	 * @priv: Private driver interface data
-	 * @link_id: The link ID which the link STA is using
-	 * @addr: The MLD MAC address of the MLD STA
-	 * Returns: 0 on success, negative value on failure
-	 */
-	int (*link_sta_remove)(void *priv, u8 link_id, const u8 *addr);
+	int (*link_add)(void *priv, u8 link_id, const u8 *addr);
 
 #ifdef CONFIG_TESTING_OPTIONS
 	int (*register_frame)(void *priv, u16 type,
@@ -6413,8 +6345,6 @@
 	 *	(if available).
 	 * @scan_start_tsf_bssid: The BSSID according to which %scan_start_tsf
 	 *	is set.
-	 * @scan_cookie: Unique identification representing the corresponding
-	 *      scan request. 0 if no unique identification is available.
 	 */
 	struct scan_info {
 		int aborted;
@@ -6426,7 +6356,6 @@
 		int nl_scan_event;
 		u64 scan_start_tsf;
 		u8 scan_start_tsf_bssid[ETH_ALEN];
-		u64 scan_cookie;
 	} scan_info;
 
 	/**
@@ -6606,7 +6535,6 @@
 	/**
 	 * struct dfs_event - Data for radar detected events
 	 * @freq: Frequency of the channel in MHz
-	 * @link_id: If >= 0, Link ID of the MLO link
 	 */
 	struct dfs_event {
 		int freq;
@@ -6615,7 +6543,6 @@
 		enum chan_width chan_width;
 		int cf1;
 		int cf2;
-		int link_id;
 	} dfs_event;
 
 	/**
@@ -6634,22 +6561,11 @@
 	 * @initiator: Initiator of the regulatory change
 	 * @type: Regulatory change type
 	 * @alpha2: Country code (or "" if not available)
-	 * @beacon_hint_before: Data for frequency attributes before beacon hint
-	 *	event if initiator == REGDOM_BEACON_HINT
-	 * @beacon_hint_after: Data for frequency attributes after beacon hint
-	 *	event if initiator == REGDOM_BEACON_HINT
 	 */
 	struct channel_list_changed {
 		enum reg_change_initiator initiator;
 		enum reg_type type;
 		char alpha2[3];
-		struct frequency_attrs {
-			unsigned int freq;
-			unsigned int max_tx_power;
-			bool disabled;
-			bool no_ir;
-			bool radar;
-		} beacon_hint_before, beacon_hint_after;
 	} channel_list_changed;
 
 	/**
@@ -6692,9 +6608,7 @@
 	 * @ch_width: Selected Channel width by driver. Driver may choose to
 	 *	change hostapd configured ACS channel width due driver internal
 	 *	channel restrictions.
-	 * @hw_mode: Selected band (used with hw_mode=any)
-	 * @puncture_bitmap: Indicate the puncturing channels
-	 * @link_id: Indicate the link id if operating as AP MLD; -1 otherwise
+	 * hw_mode: Selected band (used with hw_mode=any)
 	 */
 	struct acs_selected_channels {
 		unsigned int pri_freq;
@@ -6705,7 +6619,6 @@
 		u16 ch_width;
 		enum hostapd_hw_mode hw_mode;
 		u16 puncture_bitmap;
-		int link_id;
 	} acs_selected_channels;
 
 	/**
diff --git a/src/drivers/driver_atheros.c b/src/drivers/driver_atheros.c
index ae7f0e5..59f65b8 100644
--- a/src/drivers/driver_atheros.c
+++ b/src/drivers/driver_atheros.c
@@ -659,7 +659,7 @@
 			 &stats, sizeof(stats))) {
 		wpa_printf(MSG_DEBUG, "%s: Failed to fetch STA stats (addr "
 			   MACSTR ")", __func__, MAC2STR(addr));
-		if (ether_addr_equal(addr, drv->acct_mac)) {
+		if (os_memcmp(addr, drv->acct_mac, ETH_ALEN) == 0) {
 			os_memcpy(data, &drv->acct_data, sizeof(*data));
 			return 0;
 		}
@@ -892,7 +892,7 @@
 	}
 
 	if (stype == WLAN_FC_STYPE_ACTION &&
-	    (ether_addr_equal(drv->own_addr, mgmt->bssid) ||
+	    (os_memcmp(drv->own_addr, mgmt->bssid, ETH_ALEN) == 0 ||
 	     is_broadcast_ether_addr(mgmt->bssid))) {
 		os_memset(&event, 0, sizeof(event));
 		event.rx_mgmt.frame = buf;
@@ -901,7 +901,7 @@
 		return;
 	}
 
-	if (!ether_addr_equal(drv->own_addr, mgmt->bssid)) {
+	if (os_memcmp(drv->own_addr, mgmt->bssid, ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG, "%s: BSSID does not match - ignore",
 			   __func__);
 		return;
@@ -1226,7 +1226,7 @@
 no_ie:
 	drv_event_assoc(hapd, addr, iebuf, ielen, NULL, 0, NULL, -1, 0);
 
-	if (ether_addr_equal(addr, drv->acct_mac)) {
+	if (os_memcmp(addr, drv->acct_mac, ETH_ALEN) == 0) {
 		/* Cached accounting data is not valid anymore. */
 		os_memset(drv->acct_mac, 0, ETH_ALEN);
 		os_memset(&drv->acct_data, 0, sizeof(drv->acct_data));
diff --git a/src/drivers/driver_ndis.c b/src/drivers/driver_ndis.c
index 0351705..b32e009 100644
--- a/src/drivers/driver_ndis.c
+++ b/src/drivers/driver_ndis.c
@@ -1248,7 +1248,7 @@
 	prev = NULL;
 	entry = drv->pmkid;
 	while (entry) {
-		if (ether_addr_equal(entry->bssid, bssid))
+		if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0)
 			break;
 		prev = entry;
 		entry = entry->next;
@@ -1293,7 +1293,7 @@
 	entry = drv->pmkid;
 	prev = NULL;
 	while (entry) {
-		if (ether_addr_equal(entry->bssid, bssid) &&
+		if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0 &&
 		    os_memcmp(entry->pmkid, pmkid, 16) == 0) {
 			if (prev)
 				prev->next = entry->next;
@@ -1434,7 +1434,7 @@
 	pos = (char *) &b->Bssid[0];
 	for (i = 0; i < b->NumberOfItems; i++) {
 		NDIS_WLAN_BSSID_EX *bss = (NDIS_WLAN_BSSID_EX *) pos;
-		if (ether_addr_equal(drv->bssid, bss->MacAddress) &&
+		if (os_memcmp(drv->bssid, bss->MacAddress, ETH_ALEN) == 0 &&
 		    bss->IELength > sizeof(NDIS_802_11_FIXED_IEs)) {
 			data.assoc_info.beacon_ies =
 				((u8 *) bss->IEs) +
@@ -1477,7 +1477,7 @@
 		}
 	} else {
 		/* Connected */
-		if (!ether_addr_equal(drv->bssid, bssid)) {
+		if (os_memcmp(drv->bssid, bssid, ETH_ALEN) != 0) {
 			os_memcpy(drv->bssid, bssid, ETH_ALEN);
 			wpa_driver_ndis_get_associnfo(drv);
 			wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 194a5cd..ac2f457 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -12,12 +12,13 @@
 
 #include "includes.h"
 #include <sys/types.h>
-#include <sys/utsname.h>
 #include <fcntl.h>
 #include <net/if.h>
 #include <netlink/genl/genl.h>
 #include <netlink/genl/ctrl.h>
-#include <netlink/genl/family.h>
+#ifdef CONFIG_LIBNL3_ROUTE
+#include <netlink/route/neighbour.h>
+#endif /* CONFIG_LIBNL3_ROUTE */
 #include <linux/rtnetlink.h>
 #include <netpacket/packet.h>
 #include <linux/errqueue.h>
@@ -169,9 +170,9 @@
 static int nl80211_send_frame_cmd(struct i802_bss *bss,
 				  unsigned int freq, unsigned int wait,
 				  const u8 *buf, size_t buf_len,
-				  int save_cookie, int no_cck, int no_ack,
-				  int offchanok, const u16 *csa_offs,
-				  size_t csa_offs_len, int link_id);
+				  int save_cookie,
+				  int no_cck, int no_ack, int offchanok,
+				  const u16 *csa_offs, size_t csa_offs_len);
 static int wpa_driver_nl80211_probe_req_report(struct i802_bss *bss,
 					       int report);
 
@@ -194,7 +195,6 @@
 
 static int i802_set_iface_flags(struct i802_bss *bss, int up);
 static int nl80211_set_param(void *priv, const char *param);
-static void nl80211_remove_links(struct i802_bss *bss);
 #ifdef CONFIG_MESH
 static int nl80211_put_mesh_config(struct nl_msg *msg,
 				   struct wpa_driver_mesh_bss_params *params);
@@ -345,29 +345,17 @@
 	return NL_SKIP;
 }
 
-struct nl80211_ack_err_args {
-	int err;
-	struct nl_msg *orig_msg;
-	struct nl80211_err_info *err_info;
-};
-
 static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
 			 void *arg)
 {
-	struct nl80211_ack_err_args *err_args = arg;
 	struct nlmsghdr *nlh = (struct nlmsghdr *) err - 1;
-	struct nlmsghdr *orig_nlh = nlmsg_hdr(err_args->orig_msg);
 	int len = nlh->nlmsg_len;
 	struct nlattr *attrs;
 	struct nlattr *tb[NLMSGERR_ATTR_MAX + 1];
+	int *ret = arg;
 	int ack_len = sizeof(*nlh) + sizeof(int) + sizeof(*nlh);
-	struct nlattr *mlo_links, *link_attr;
-	u32 offset;
-	int rem;
 
-	err_args->err = err->error;
-	if (err_args->err_info)
-		err_args->err_info->link_id = -1;
+	*ret = err->error;
 
 	if (!(nlh->nlmsg_flags & NLM_F_ACK_TLVS))
 		return NL_SKIP;
@@ -389,41 +377,6 @@
 			   len, (char *) nla_data(tb[NLMSGERR_ATTR_MSG]));
 	}
 
-	if (!err_args->err_info)
-		return NL_SKIP;
-
-	/* Check if it was a per-link error report */
-
-	if (!tb[NLMSGERR_ATTR_OFFS] ||
-	    os_memcmp(orig_nlh, &err->msg, sizeof(err->msg)) != 0)
-		return NL_SKIP;
-
-	offset = nla_get_u32(tb[NLMSGERR_ATTR_OFFS]);
-
-	mlo_links = nlmsg_find_attr(orig_nlh, GENL_HDRLEN,
-				    NL80211_ATTR_MLO_LINKS);
-	if (!mlo_links)
-		return NL_SKIP;
-
-	nla_for_each_nested(link_attr, mlo_links, rem) {
-		struct nlattr *link_id;
-		size_t link_offset = (u8 *) link_attr - (u8 *) orig_nlh;
-
-		if (offset < link_offset ||
-		    offset >= link_offset + link_attr->nla_len)
-			continue;
-
-		link_id = nla_find(nla_data(link_attr), nla_len(link_attr),
-				   NL80211_ATTR_MLO_LINK_ID);
-		if (link_id) {
-			err_args->err_info->link_id = nla_get_u8(link_id);
-			wpa_printf(MSG_DEBUG,
-				   "nl80211: kernel reports error for link: %d",
-				   err_args->err_info->link_id);
-			break;
-		}
-	}
-
 	return NL_SKIP;
 }
 
@@ -456,61 +409,20 @@
 }
 
 
-static int send_event_marker(struct wpa_driver_nl80211_data *drv)
+static int send_and_recv(struct nl80211_global *global,
+			 struct nl_sock *nl_handle, struct nl_msg *msg,
+			 int (*valid_handler)(struct nl_msg *, void *),
+			 void *valid_data,
+			 int (*ack_handler_custom)(struct nl_msg *, void *),
+			 void *ack_data)
 {
-	struct nl_sock *handle;
-	struct nl_msg *msg;
-	struct nlmsghdr *hdr;
-	int res = 0;
-	int err = -NLE_NOMEM;
-
-	msg = nlmsg_alloc();
-	if (!msg)
-		goto out;
-
-	/* We only care about the returned sequence number for matching. */
-	if (!nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_PROTOCOL_FEATURES))
-		goto out;
-
-	handle = (void *) (((intptr_t) drv->global->nl_event) ^
-			   ELOOP_SOCKET_INVALID);
-
-	err = nl_send_auto_complete(handle, msg);
-	if (err < 0)
-		goto out;
-
-	hdr = nlmsg_hdr(msg);
-	res = hdr->nlmsg_seq;
-
-out:
-	nlmsg_free(msg);
-	if (err)
-		wpa_printf(MSG_INFO, "nl80211: %s failed: %s",
-			   __func__, nl_geterror(err));
-	return res;
-}
-
-
-int send_and_recv(struct nl80211_global *global,
-		  struct nl_sock *nl_handle, struct nl_msg *msg,
-		  int (*valid_handler)(struct nl_msg *, void *),
-		  void *valid_data,
-		  int (*ack_handler_custom)(struct nl_msg *, void *),
-		  void *ack_data,
-		  struct nl80211_err_info *err_info)
-{
-	struct nl_cb *cb, *s_nl_cb;
-	struct nl80211_ack_err_args err;
-	int opt;
+	struct nl_cb *cb;
+	int err = -ENOMEM, opt;
 
 	if (!msg)
 		return -ENOMEM;
 
-	err.err = -ENOMEM;
-
-	s_nl_cb = nl_socket_get_cb(nl_handle);
-	cb = nl_cb_clone(s_nl_cb);
-	nl_cb_put(s_nl_cb);
+	cb = nl_cb_clone(global->nl_cb);
 	if (!cb)
 		goto out;
 
@@ -524,28 +436,26 @@
 	setsockopt(nl_socket_get_fd(nl_handle), SOL_NETLINK,
 		   NETLINK_CAP_ACK, &opt, sizeof(opt));
 
-	err.err = nl_send_auto_complete(nl_handle, msg);
-	if (err.err < 0) {
+	err = nl_send_auto_complete(nl_handle, msg);
+	if (err < 0) {
 		wpa_printf(MSG_INFO,
 			   "nl80211: nl_send_auto_complete() failed: %s",
-			   nl_geterror(err.err));
+			   nl_geterror(err));
 		/* Need to convert libnl error code to an errno value. For now,
 		 * just hardcode this to EBADF; the real error reason is shown
 		 * in that error print above. */
-		err.err = -EBADF;
+		err = -EBADF;
 		goto out;
 	}
 
-	err.err = 1;
-	err.orig_msg = msg;
-	err.err_info = err_info;
+	err = 1;
 
 	nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
-	nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err.err);
+	nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
 	if (ack_handler_custom) {
 		struct nl80211_ack_ext_arg *ext_arg = ack_data;
 
-		ext_arg->err = &err.err;
+		ext_arg->err = &err;
 		nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM,
 			  ack_handler_custom, ack_data);
 	} else {
@@ -556,7 +466,7 @@
 		nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,
 			  valid_handler, valid_data);
 
-	while (err.err > 0) {
+	while (err > 0) {
 		int res = nl_recvmsgs(nl_handle, cb);
 
 		if (res == -NLE_DUMP_INTR) {
@@ -571,7 +481,7 @@
 			 * will stop and return an error. */
 			wpa_printf(MSG_DEBUG, "nl80211: %s; convert to -EAGAIN",
 				   nl_geterror(res));
-			err.err = -EAGAIN;
+			err = -EAGAIN;
 		} else if (res < 0) {
 			wpa_printf(MSG_INFO,
 				   "nl80211: %s->nl_recvmsgs failed: %d (%s)",
@@ -583,20 +493,89 @@
 	/* Always clear the message as it can potentially contain keys */
 	nl80211_nlmsg_clear(msg);
 	nlmsg_free(msg);
-	return err.err;
+	return err;
 }
 
 
-static int nl80211_put_control_port(struct wpa_driver_nl80211_data *drv,
-				    struct nl_msg *msg)
+int send_and_recv_msgs(struct wpa_driver_nl80211_data *drv,
+		       struct nl_msg *msg,
+		       int (*valid_handler)(struct nl_msg *, void *),
+		       void *valid_data,
+		       int (*ack_handler_custom)(struct nl_msg *, void *),
+		       void *ack_data)
 {
-	if (nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT) ||
-	    nla_put_u16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, ETH_P_PAE) ||
-	    ((drv->capa.flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX) &&
-	     (nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_OVER_NL80211) ||
-	      nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_NO_PREAUTH))))
+	return send_and_recv(drv->global, drv->global->nl, msg,
+			     valid_handler, valid_data,
+			     ack_handler_custom, ack_data);
+}
+
+
+/* Use this method to mark that it is necessary to own the connection/interface
+ * for this operation.
+ * handle may be set to NULL, to get the same behavior as send_and_recv_msgs().
+ * set_owner can be used to mark this socket for receiving control port frames.
+ */
+static int send_and_recv_msgs_owner(struct wpa_driver_nl80211_data *drv,
+				    struct nl_msg *msg,
+				    struct nl_sock *handle, int set_owner,
+				    int (*valid_handler)(struct nl_msg *,
+							 void *),
+				    void *valid_data,
+				    int (*ack_handler_custom)(struct nl_msg *,
+							      void *),
+				    void *ack_data)
+{
+	if (!msg)
+		return -ENOMEM;
+
+	/* Control port over nl80211 needs the flags and attributes below.
+	 *
+	 * The Linux kernel has initial checks for them (in nl80211.c) like:
+	 *     validate_pae_over_nl80211(...)
+	 * or final checks like:
+	 *     dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid
+	 *
+	 * Final operations (e.g., disassociate) don't need to set these
+	 * attributes, but they have to be performed on the socket, which has
+	 * the connection owner property set in the kernel.
+	 */
+	if ((drv->capa.flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX) &&
+	    handle && set_owner &&
+	    (nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_OVER_NL80211) ||
+	     nla_put_flag(msg, NL80211_ATTR_SOCKET_OWNER) ||
+	     nla_put_u16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, ETH_P_PAE) ||
+	     nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_NO_PREAUTH)))
 		return -1;
-	return 0;
+
+	return send_and_recv(drv->global, handle ? handle : drv->global->nl,
+			     msg, valid_handler, valid_data,
+			     ack_handler_custom, ack_data);
+}
+
+
+static int
+send_and_recv_msgs_connect_handle(struct wpa_driver_nl80211_data *drv,
+				  struct nl_msg *msg, struct i802_bss *bss,
+				  int set_owner)
+{
+	struct nl_sock *nl_connect = get_connect_handle(bss);
+
+	if (nl_connect)
+		return send_and_recv_msgs_owner(drv, msg, nl_connect, set_owner,
+						process_bss_event, bss, NULL,
+						NULL);
+	else
+		return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+}
+
+
+struct nl_sock * get_connect_handle(struct i802_bss *bss)
+{
+	if ((bss->drv->capa.flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX) ||
+	    bss->use_nl_connect)
+		return bss->nl_connect;
+
+	return NULL;
 }
 
 
@@ -655,7 +634,7 @@
 	}
 
 	ret = send_and_recv(global, global->nl, msg, family_handler, &res,
-			    NULL, NULL, NULL);
+			    NULL, NULL);
 	if (ret == 0)
 		ret = res.id;
 	return ret;
@@ -783,7 +762,8 @@
 	if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_GET_INTERFACE)))
 		return -1;
 
-	if (send_and_recv_resp(bss->drv, msg, netdev_info_handler, &data) == 0)
+	if (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data,
+			       NULL, NULL) == 0)
 		return data.wiphy_idx;
 	return -1;
 }
@@ -800,7 +780,8 @@
 	if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_GET_INTERFACE)))
 		return NL80211_IFTYPE_UNSPECIFIED;
 
-	if (send_and_recv_resp(bss->drv, msg, netdev_info_handler, &data) == 0)
+	if (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data,
+			       NULL, NULL) == 0)
 		return data.nlmode;
 	return NL80211_IFTYPE_UNSPECIFIED;
 }
@@ -816,7 +797,8 @@
 	if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_GET_INTERFACE)))
 		return -1;
 
-	return send_and_recv_resp(bss->drv, msg, netdev_info_handler, &data);
+	return send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data,
+				  NULL, NULL);
 }
 
 
@@ -828,7 +810,8 @@
 	};
 
 	if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_GET_INTERFACE)) ||
-	    send_and_recv_resp(bss->drv, msg, netdev_info_handler, &data))
+	    send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data,
+			       NULL, NULL))
 		return -1;
 	return data.use_4addr;
 }
@@ -851,7 +834,7 @@
 	}
 
 	ret = send_and_recv(drv->global, w->nl_beacons, msg, NULL, NULL,
-			    NULL, NULL, NULL);
+			    NULL, NULL);
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "nl80211: Register beacons command "
 			   "failed: ret=%d (%s)",
@@ -1108,8 +1091,8 @@
 		struct nl_msg *msg;
 
 		msg = nl80211_drv_msg(drv, 0, NL80211_CMD_GET_INTERFACE);
-		if (send_and_recv_resp(drv, msg, get_mlo_info,
-				       &drv->sta_mlo_info))
+		if (send_and_recv_msgs(drv, msg, get_mlo_info,
+				       &drv->sta_mlo_info, NULL, NULL))
 			return -1;
 	}
 
@@ -1266,7 +1249,7 @@
 		wpa_printf(MSG_DEBUG,
 			   "nl80211: %s: failed to re-read MAC address",
 			   bss->ifname);
-	} else if (bss && !ether_addr_equal(addr, bss->addr)) {
+	} else if (bss && os_memcmp(addr, bss->addr, ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG,
 			   "nl80211: Own MAC address on ifindex %d (%s) changed from "
 			   MACSTR " to " MACSTR,
@@ -1654,8 +1637,8 @@
 	msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_GET_SCAN);
 	os_memset(&arg, 0, sizeof(arg));
 	arg.drv = drv;
-	ret = send_and_recv_resp(drv, msg, nl80211_get_assoc_freq_handler,
-				 &arg);
+	ret = send_and_recv_msgs(drv, msg, nl80211_get_assoc_freq_handler,
+				 &arg, NULL, NULL);
 	if (ret == -EAGAIN) {
 		count++;
 		if (count >= 10) {
@@ -1688,8 +1671,8 @@
 	msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_GET_SCAN);
 	os_memset(&arg, 0, sizeof(arg));
 	arg.drv = drv;
-	ret = send_and_recv_resp(drv, msg, nl80211_get_assoc_freq_handler,
-				 &arg);
+	ret = send_and_recv_msgs(drv, msg, nl80211_get_assoc_freq_handler,
+				 &arg, NULL, NULL);
 	if (ret == -EAGAIN) {
 		count++;
 		if (count >= 10) {
@@ -1776,7 +1759,8 @@
 	sig_change->frequency = drv->assoc_freq;
 
 	msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_GET_SURVEY);
-	return send_and_recv_resp(drv, msg, get_link_noise, sig_change);
+	return send_and_recv_msgs(drv, msg, get_link_noise, sig_change,
+				  NULL, NULL);
 }
 
 
@@ -1840,7 +1824,7 @@
 	struct nl_msg *msg;
 
 	msg = nl80211_drv_msg(drv, 0, NL80211_CMD_GET_INTERFACE);
-	return send_and_recv_resp(drv, msg, get_channel_info, ci);
+	return send_and_recv_msgs(drv, msg, get_channel_info, ci, NULL, NULL);
 }
 
 
@@ -1889,7 +1873,7 @@
 		nlmsg_free(msg);
 		return -EINVAL;
 	}
-	if (send_and_recv_cmd(drv, msg))
+	if (send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL))
 		return -EINVAL;
 	return 0;
 }
@@ -1935,7 +1919,8 @@
 	}
 
 	alpha2[0] = '\0';
-	ret = send_and_recv_resp(drv, msg, nl80211_get_country, alpha2);
+	ret = send_and_recv_msgs(drv, msg, nl80211_get_country, alpha2,
+				 NULL, NULL);
 	if (!alpha2[0])
 		ret = -1;
 
@@ -1945,8 +1930,6 @@
 
 static int wpa_driver_nl80211_init_nl_global(struct nl80211_global *global)
 {
-	struct nl_cache *cache = NULL;
-	struct genl_family *family = NULL;
 	int ret;
 
 	global->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
@@ -2018,29 +2001,6 @@
 		/* Continue without vendor events */
 	}
 
-	/* Resolve maxattr for kernel support checks */
-	ret = genl_ctrl_alloc_cache(global->nl, &cache);
-	if (ret < 0) {
-		wpa_printf(MSG_DEBUG,
-			   "nl80211: Could not allocate genl cache: %d (%s)",
-			   ret, nl_geterror(ret));
-		goto err;
-	}
-
-	family = genl_ctrl_search(cache, global->nl80211_id);
-	if (!family) {
-		wpa_printf(MSG_DEBUG,
-			   "nl80211: Could not get nl80211 family from cache: %d (%s)",
-			   ret, nl_geterror(ret));
-		goto err;
-	}
-
-	global->nl80211_maxattr = genl_family_get_maxattr(family);
-	wpa_printf(MSG_DEBUG, "nl80211: Maximum supported attribute ID: %u",
-		   global->nl80211_maxattr);
-	genl_family_put(family);
-	nl_cache_free(cache);
-
 	nl_cb_set(global->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
 		  no_seq_check, NULL);
 	nl_cb_set(global->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
@@ -2053,8 +2013,6 @@
 	return 0;
 
 err:
-	genl_family_put(family);
-	nl_cache_free(cache);
 	nl_destroy_handles(&global->nl_event);
 	nl_destroy_handles(&global->nl);
 	nl_cb_put(global->nl_cb);
@@ -2292,26 +2250,7 @@
 {
 	struct wpa_driver_nl80211_data *drv;
 	struct i802_bss *bss;
-	char path[128], buf[200], *pos;
-	ssize_t len;
-	int ret;
-
-	ret = os_snprintf(path, sizeof(path), "/sys/class/net/%s/device/driver",
-			  ifname);
-	if (!os_snprintf_error(sizeof(path), ret)) {
-		len = readlink(path, buf, sizeof(buf));
-		if (len > 0 && (size_t) len < sizeof(buf)) {
-			buf[len] = '\0';
-			pos = strrchr(buf, '/');
-			if (pos)
-				pos++;
-			else
-				pos = buf;
-			wpa_printf(MSG_DEBUG,
-				   "nl80211: Initialize interface %s (driver: %s)",
-				   ifname, pos);
-		}
-	}
+	unsigned int i;
 
 	if (global_priv == NULL)
 		return NULL;
@@ -2391,12 +2330,16 @@
 	}
 
 	/*
-	 * Use link ID 0 for the single "link" of a non-MLD.
+	 * Set the default link to be the first one, and set its address to that
+	 * of the interface.
 	 */
-	bss->valid_links = 0;
 	bss->flink = &bss->links[0];
+	bss->n_links = 1;
 	os_memcpy(bss->flink->addr, bss->addr, ETH_ALEN);
 
+	for (i = 0; i < MAX_NUM_MLD_LINKS; i++)
+		bss->links[i].link_id = NL80211_DRV_LINK_ID_NA;
+
 	return bss;
 
 failed:
@@ -2446,7 +2389,7 @@
 	}
 
 	ret = send_and_recv(drv->global, nl_handle, msg, NULL, NULL,
-			    NULL, NULL, NULL);
+			    NULL, NULL);
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "nl80211: Register frame command "
 			   "failed (type=%u): ret=%d (%s)",
@@ -2562,13 +2505,6 @@
 					  5) < 0)
 		ret = -1;
 #endif /* CONFIG_P2P */
-#ifdef CONFIG_NAN_USD
-	/* NAN SDF Public Action */
-	if (nl80211_register_action_frame(bss,
-					  (u8 *) "\x04\x09\x50\x6f\x9a\x13",
-					  6) < 0)
-		ret = -1;
-#endif /* CONFIG_NAN_USD */
 #ifdef CONFIG_DPP
 	/* DPP Public Action */
 	if (nl80211_register_action_frame(bss,
@@ -2714,7 +2650,7 @@
 
 	msg = nl80211_bss_msg(bss, 0, NL80211_CMD_UNEXPECTED_FRAME);
 	ret = send_and_recv(bss->drv->global, bss->nl_mgmt, msg, NULL, NULL,
-			    NULL, NULL, NULL);
+			    NULL, NULL);
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "nl80211: Register spurious class3 "
 			   "failed: ret=%d (%s)",
@@ -2868,7 +2804,7 @@
 	int ret;
 
 	msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_DEL_INTERFACE);
-	ret = send_and_recv_cmd(bss->drv, msg);
+	ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL);
 
 	wpa_printf(MSG_DEBUG, "nl80211: Delete P2P Device %s (0x%llx): %s",
 		   bss->ifname, (long long unsigned int) bss->wdev_id,
@@ -2883,7 +2819,7 @@
 
 	msg = nl80211_cmd_msg(bss, 0, start ? NL80211_CMD_START_P2P_DEVICE :
 			      NL80211_CMD_STOP_P2P_DEVICE);
-	ret = send_and_recv_cmd(bss->drv, msg);
+	ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL);
 
 	wpa_printf(MSG_DEBUG, "nl80211: %s P2P Device %s (0x%llx): %s",
 		   start ? "Start" : "Stop",
@@ -2954,7 +2890,8 @@
 	}
 	nla_nest_end(msg, params);
 
-	ret = send_and_recv_resp(drv, msg, qca_vendor_test_cmd_handler, drv);
+	ret = send_and_recv_msgs(drv, msg, qca_vendor_test_cmd_handler, drv,
+				 NULL, NULL);
 	wpa_printf(MSG_DEBUG,
 		   "nl80211: QCA vendor test command returned %d (%s)",
 		   ret, strerror(-ret));
@@ -3071,46 +3008,46 @@
 
 
 static int wpa_driver_nl80211_del_beacon(struct i802_bss *bss,
-					 int link_id)
+					 struct i802_link *link)
 {
 	struct nl_msg *msg;
 	struct wpa_driver_nl80211_data *drv = bss->drv;
-	struct i802_link *link = nl80211_get_link(bss, link_id);
 
 	if (!link->beacon_set)
 		return 0;
 
 	wpa_printf(MSG_DEBUG, "nl80211: Remove beacon (ifindex=%d)",
-		   bss->ifindex);
+		   drv->ifindex);
 	link->beacon_set = 0;
 	link->freq = 0;
 
 	nl80211_put_wiphy_data_ap(bss);
-	msg = nl80211_bss_msg(bss, 0, NL80211_CMD_DEL_BEACON);
+	msg = nl80211_drv_msg(drv, 0, NL80211_CMD_DEL_BEACON);
 	if (!msg)
 		return -ENOBUFS;
 
-	if (link_id != NL80211_DRV_LINK_ID_NA) {
+	if (link->link_id != NL80211_DRV_LINK_ID_NA) {
 		wpa_printf(MSG_DEBUG,
 			   "nl80211: MLD: stop beaconing on link=%u",
-			   link_id);
+			   link->link_id);
 
-		if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id)) {
+		if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID,
+			       link->link_id)) {
 			nlmsg_free(msg);
 			return -ENOBUFS;
 		}
 	}
 
-	return send_and_recv_cmd(drv, msg);
+	return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 }
 
 
 static void wpa_driver_nl80211_del_beacon_all(struct i802_bss *bss)
 {
-	int link_id;
+	unsigned int i;
 
-	for_each_link_default(bss->valid_links, link_id, NL80211_DRV_LINK_ID_NA)
-		wpa_driver_nl80211_del_beacon(bss, link_id);
+	for (i = 0; i < bss->n_links; i++)
+		wpa_driver_nl80211_del_beacon(bss, &bss->links[i]);
 }
 
 
@@ -3162,10 +3099,8 @@
 
 	nl80211_remove_monitor_interface(drv);
 
-	if (is_ap_interface(drv->nlmode)) {
+	if (is_ap_interface(drv->nlmode))
 		wpa_driver_nl80211_del_beacon_all(bss);
-		nl80211_remove_links(bss);
-	}
 
 	if (drv->eapol_sock >= 0) {
 		eloop_unregister_read_sock(drv->eapol_sock);
@@ -3361,6 +3296,57 @@
 	return num_suites;
 }
 
+#if defined(CONFIG_DRIVER_NL80211_BRCM) || defined(CONFIG_DRIVER_NL80211_SYNA)
+static int wpa_driver_do_broadcom_acs(struct wpa_driver_nl80211_data *drv,
+				      struct drv_acs_params *params)
+{
+	struct nl_msg *msg;
+	struct nlattr *data;
+	int freq_list_len;
+	int ret = -1;
+
+	freq_list_len = int_array_len(params->freq_list);
+	wpa_printf(MSG_DEBUG, "%s: freq_list_len=%d",
+		    __func__, freq_list_len);
+
+	msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR);
+	if (!msg ||
+	    nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_BRCM) ||
+	    nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
+			BRCM_VENDOR_SCMD_ACS) ||
+	    !(data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
+	    nla_put_u8(msg, BRCM_VENDOR_ATTR_ACS_HW_MODE, params->hw_mode) ||
+	    nla_put_u8(msg, BRCM_VENDOR_ATTR_ACS_HT_ENABLED,
+		       params->ht_enabled) ||
+	    nla_put_u8(msg, BRCM_VENDOR_ATTR_ACS_HT40_ENABLED,
+		       params->ht40_enabled) ||
+		nla_put_u8(msg, BRCM_VENDOR_ATTR_ACS_VHT_ENABLED,
+		       params->vht_enabled) ||
+	    nla_put_u16(msg, BRCM_VENDOR_ATTR_ACS_CHWIDTH, params->ch_width) ||
+	    (freq_list_len > 0 &&
+	     nla_put(msg, BRCM_VENDOR_ATTR_ACS_FREQ_LIST,
+		     sizeof(int) * freq_list_len, params->freq_list)))
+		goto fail;
+	nla_nest_end(msg, data);
+
+	wpa_printf(MSG_DEBUG,
+		   "nl80211: ACS Params: HW_MODE: %d HT: %d HT40: %d VHT: %d BW: %d",
+		   params->hw_mode, params->ht_enabled, params->ht40_enabled,
+		   params->vht_enabled, params->ch_width);
+
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+	if (ret) {
+		wpa_printf(MSG_ERROR,
+			   "nl80211: BRCM Failed to invoke driver ACS function: %s",
+			   strerror(errno));
+	}
+
+	msg = NULL;
+fail:
+	nlmsg_free(msg);
+	return ret;
+}
+#endif /* CONFIG_DRIVER_NL80211_BRCM || CONFIG_DRIVER_NL80211_SYNA */
 
 #if (defined(CONFIG_DRIVER_NL80211_BRCM) && !defined(WIFI_BRCM_OPEN_SOURCE_MULTI_AKM)) ||   \
 	defined(CONFIG_DRIVER_NL80211_SYNA)
@@ -3382,7 +3368,6 @@
 #endif /* (CONFIG_DRIVER_NL80211_BRCM && !WIFI_BRCM_OPEN_SOURCE_MULTI_AKM) ||
 	* CONFIG_DRIVER_NL80211_SYNA */
 
-
 #ifdef CONFIG_DRIVER_NL80211_QCA
 static int issue_key_mgmt_set_key(struct wpa_driver_nl80211_data *drv,
 				  const u8 *key, size_t key_len)
@@ -3402,7 +3387,7 @@
 		nlmsg_free(msg);
 		return -1;
 	}
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	if (ret) {
 		wpa_printf(MSG_DEBUG,
 			   "nl80211: Key management set key failed: ret=%d (%s)",
@@ -3434,7 +3419,7 @@
 	}
 	nla_nest_end(msg, params);
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, (void *) -1, NULL, NULL);
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "nl80211: Key mgmt set key failed: ret=%d (%s)",
 			ret, strerror(-ret));
@@ -3473,7 +3458,7 @@
 		return -ENOBUFS;
 	}
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "nl80211: Set PMK failed: ret=%d (%s)",
 			   ret, strerror(-ret));
@@ -3654,7 +3639,7 @@
 			goto fail;
 	}
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	if ((ret == -ENOENT || ret == -ENOLINK) && alg == WPA_ALG_NONE)
 		ret = 0;
 	if (ret)
@@ -3723,7 +3708,7 @@
 			goto fail;
 	}
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	if (ret)
 		wpa_printf(MSG_DEBUG,
 			   "nl80211: set_key default failed; err=%d %s",
@@ -3836,6 +3821,7 @@
 {
 	int ret;
 	struct nl_msg *msg;
+	struct nl_sock *nl_connect = get_connect_handle(bss);
 
 	if (!(msg = nl80211_drv_msg(drv, 0, cmd)) ||
 	    nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason_code) ||
@@ -3846,8 +3832,11 @@
 		return -1;
 	}
 
-	ret = send_and_recv(drv->global, bss->nl_connect, msg,
-			    NULL, NULL, NULL, NULL, NULL);
+	if (nl_connect)
+		ret = send_and_recv(drv->global, nl_connect, msg,
+				    process_bss_event, bss, NULL, NULL);
+	else
+		ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	if (ret) {
 		wpa_dbg(drv->ctx, MSG_DEBUG,
 			"nl80211: MLME command failed: reason=%u ret=%d (%s)",
@@ -3862,6 +3851,7 @@
 					 struct i802_bss *bss)
 {
 	int ret;
+	int drv_associated = drv->associated;
 
 	wpa_printf(MSG_DEBUG, "%s(reason_code=%d)", __func__, reason_code);
 	nl80211_mark_disconnected(drv);
@@ -3872,8 +3862,7 @@
 	 * For locally generated disconnect, supplicant already generates a
 	 * DEAUTH event, so ignore the event from NL80211.
 	 */
-	if (ret == 0)
-		drv->ignore_next_local_disconnect = send_event_marker(drv);
+	drv->ignore_next_local_disconnect = drv_associated && (ret == 0);
 
 	return ret;
 }
@@ -3884,6 +3873,7 @@
 {
 	struct wpa_driver_nl80211_data *drv = bss->drv;
 	int ret;
+	int drv_associated = drv->associated;
 
 	if (drv->nlmode == NL80211_IFTYPE_ADHOC) {
 		nl80211_mark_disconnected(drv);
@@ -3901,8 +3891,7 @@
 	 * For locally generated deauthenticate, supplicant already generates a
 	 * DEAUTH event, so ignore the event from NL80211.
 	 */
-	if (ret == 0)
-		drv->ignore_next_local_deauth = send_event_marker(drv);
+	drv->ignore_next_local_deauth = drv_associated && (ret == 0);
 
 	return ret;
 }
@@ -4125,7 +4114,7 @@
 			goto fail;
 	}
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	msg = NULL;
 	if (ret) {
 		wpa_dbg(drv->ctx, MSG_DEBUG,
@@ -4205,7 +4194,6 @@
 {
 	struct wpa_driver_auth_params params;
 	struct i802_bss *bss = drv->first_bss;
-	u8 ap_mld_addr[ETH_ALEN];
 	int i;
 
 	wpa_printf(MSG_DEBUG, "nl80211: Try to authenticate again");
@@ -4231,10 +4219,8 @@
 	params.auth_data_len = drv->auth_data_len;
 	params.mld = drv->auth_mld;
 	params.mld_link_id = drv->auth_mld_link_id;
-	if (drv->auth_mld) {
-		os_memcpy(ap_mld_addr, drv->auth_ap_mld_addr, ETH_ALEN);
-		params.ap_mld_addr = ap_mld_addr;
-	}
+	if (drv->auth_mld)
+		params.ap_mld_addr = drv->auth_ap_mld_addr;
 
 	for (i = 0; i < 4; i++) {
 		if (drv->auth_wep_key_len[i]) {
@@ -4250,11 +4236,14 @@
 
 struct i802_link * nl80211_get_link(struct i802_bss *bss, s8 link_id)
 {
-	if (link_id < 0 || link_id >= MAX_NUM_MLD_LINKS)
-		return bss->flink;
+	unsigned int i;
 
-	if (BIT(link_id) & bss->valid_links)
-		return &bss->links[link_id];
+	for (i = 0; i < bss->n_links; i++) {
+		if (bss->links[i].link_id != link_id)
+			continue;
+
+		return &bss->links[i];
+	}
 
 	return bss->flink;
 }
@@ -4271,10 +4260,10 @@
 static int nl80211_get_link_freq(struct i802_bss *bss, const u8 *addr,
 				 bool bss_freq_debug)
 {
-	u8 i;
+	size_t i;
 
-	for_each_link(bss->valid_links, i) {
-		if (ether_addr_equal(bss->links[i].addr, addr)) {
+	for (i = 0; i < bss->n_links; i++) {
+		if (os_memcmp(bss->links[i].addr, addr, ETH_ALEN) == 0) {
 			wpa_printf(MSG_DEBUG,
 				   "nl80211: Use link freq=%d for address "
 				   MACSTR,
@@ -4310,11 +4299,9 @@
 
 	mgmt = (struct ieee80211_mgmt *) data;
 	fc = le_to_host16(mgmt->frame_control);
-	wpa_printf(MSG_DEBUG, "nl80211: send_mlme - da=" MACSTR " sa=" MACSTR
-		   " bssid=" MACSTR
+	wpa_printf(MSG_DEBUG, "nl80211: send_mlme - da=" MACSTR
 		   " noack=%d freq=%u no_cck=%d offchanok=%d wait_time=%u no_encrypt=%d fc=0x%x (%s) nlmode=%d",
-		   MAC2STR(mgmt->da), MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid),
-		   noack, freq, no_cck, offchanok, wait_time,
+		   MAC2STR(mgmt->da), noack, freq, no_cck, offchanok, wait_time,
 		   no_encrypt, fc, fc2str(fc), drv->nlmode);
 
 	if ((is_sta_interface(drv->nlmode) ||
@@ -4441,7 +4428,7 @@
 	wpa_printf(MSG_DEBUG, "nl80211: send_mlme -> send_frame_cmd");
 	res = nl80211_send_frame_cmd(bss, freq, wait_time, data, data_len,
 				     use_cookie, no_cck, noack, offchanok,
-				     csa_offs, csa_offs_len, link_id);
+				     csa_offs, csa_offs_len);
 	if (!res)
 		drv->send_frame_link_id = link_id;
 
@@ -4467,7 +4454,7 @@
 
 static int nl80211_set_bss(struct i802_bss *bss, int cts, int preamble,
 			   int slot, int ht_opmode, int ap_isolate,
-			   const int *basic_rates, int link_id)
+			   const int *basic_rates)
 {
 	struct wpa_driver_nl80211_data *drv = bss->drv;
 	struct nl_msg *msg;
@@ -4483,14 +4470,12 @@
 	     nla_put_u16(msg, NL80211_ATTR_BSS_HT_OPMODE, ht_opmode)) ||
 	    (ap_isolate >= 0 &&
 	     nla_put_u8(msg, NL80211_ATTR_AP_ISOLATE, ap_isolate)) ||
-	    nl80211_put_basic_rates(msg, basic_rates) ||
-	    (link_id != NL80211_DRV_LINK_ID_NA &&
-	     nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id))) {
+	    nl80211_put_basic_rates(msg, basic_rates)) {
 		nlmsg_free(msg);
 		return -ENOBUFS;
 	}
 
-	return send_and_recv_cmd(drv, msg);
+	return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 }
 
 
@@ -4549,7 +4534,7 @@
 	}
 	nlmsg_free(acl);
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "nl80211: Failed to set MAC ACL: %d (%s)",
 			   ret, strerror(-ret));
@@ -4601,7 +4586,7 @@
 		return ret;
 	}
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	if (ret) {
 		wpa_printf(MSG_ERROR,
 			   "nl80211: Mesh config set failed: %d (%s)",
@@ -4747,7 +4732,7 @@
 		return -ENOBUFS;
 	}
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 
 	switch (ret) {
 	case 0:
@@ -4941,8 +4926,7 @@
 
 #ifdef CONFIG_DRIVER_NL80211_QCA
 static void qca_set_allowed_ap_freqs(struct wpa_driver_nl80211_data *drv,
-				     const int *freqs, int num_freqs,
-				     int link_id)
+				    const int *freqs, int num_freqs)
 {
 	struct nl_msg *msg;
 	struct nlattr *params, *freqs_list;
@@ -4960,10 +4944,6 @@
 	    !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)))
 		goto err;
 
-	if (link_id != NL80211_DRV_LINK_ID_NA &&
-	    nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_CONFIG_MLO_LINK_ID, link_id))
-		goto err;
-
 	freqs_list = nla_nest_start(
 		msg, QCA_WLAN_VENDOR_ATTR_CONFIG_AP_ALLOWED_FREQ_LIST);
 	if (!freqs_list)
@@ -4977,7 +4957,7 @@
 	nla_nest_end(msg, freqs_list);
 	nla_nest_end(msg, params);
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	if (ret)
 		wpa_printf(MSG_ERROR,
 			   "nl80211: Failed set AP alllowed frequency list: %d (%s)",
@@ -5114,18 +5094,20 @@
 #endif /* CONFIG_MESH */
 
 	if (params->mld_ap) {
-		if (!nl80211_link_valid(bss->valid_links,
-					params->mld_link_id)) {
-			wpa_printf(MSG_DEBUG,
-				   "nl80211: Link ID=%u invalid (valid: 0x%04x)",
-				   params->mld_link_id, bss->valid_links);
-			return -EINVAL;
+		size_t i;
+
+		for (i = 0; i < bss->n_links; i++) {
+			if (bss->links[i].link_id == params->mld_link_id) {
+				link = &bss->links[i];
+				break;
+			}
 		}
 
-		link = nl80211_get_link(bss, params->mld_link_id);
-	} else if (bss->valid_links) {
-		wpa_printf(MSG_DEBUG, "nl80211: MLD configuration expected");
-		return -EINVAL;
+		if (i == bss->n_links) {
+			wpa_printf(MSG_DEBUG, "nl80211: Link ID=%u not found",
+				   params->mld_link_id);
+			return -EINVAL;
+		}
 	}
 
 	beacon_set = params->reenable ? 0 : link->beacon_set;
@@ -5166,12 +5148,13 @@
 			   params->mld_link_id);
 
 		if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID,
-			       params->mld_link_id))
+			       params->mld_link_id) ||
+		    (params->freq &&
+		     nl80211_put_freq_params(msg, params->freq) < 0))
 			goto fail;
 
-		if (params->freq)
-			nl80211_link_set_freq(bss, params->mld_link_id,
-					      params->freq->freq);
+		nl80211_link_set_freq(bss, params->mld_link_id,
+				      params->freq->freq);
 	}
 
 	if (params->proberesp && params->proberesp_len) {
@@ -5242,26 +5225,32 @@
 			 suites))
 		goto fail;
 
-	if (wpa_key_mgmt_wpa_psk_no_sae(params->key_mgmt_suites) &&
+	if ((params->key_mgmt_suites & WPA_KEY_MGMT_PSK) &&
 	    (drv->capa.flags2 & WPA_DRIVER_FLAGS2_4WAY_HANDSHAKE_AP_PSK) &&
-	    params->psk_len &&
-	    nla_put(msg, NL80211_ATTR_PMK, params->psk_len, params->psk))
-		goto fail;
+	    params->psk_len) {
+		if (nla_put(msg, NL80211_ATTR_PMK, params->psk_len, params->psk)) {
+			wpa_printf(MSG_ERROR, "nl80211: Setting PSK failed");
+			goto fail;
+		} else
+			wpa_printf(MSG_DEBUG, "nl80211: Setting PSK for offload");
+	}
 
 	if (wpa_key_mgmt_sae(params->key_mgmt_suites) &&
 	    (drv->capa.flags2 & WPA_DRIVER_FLAGS2_SAE_OFFLOAD_AP) &&
-	    params->sae_password &&
-	    nla_put(msg, NL80211_ATTR_SAE_PASSWORD,
-		    os_strlen(params->sae_password), params->sae_password))
-		goto fail;
-
-	if (nl80211_put_control_port(drv, msg) < 0)
-		goto fail;
+	    params->sae_password) {
+		if (nla_put(msg, NL80211_ATTR_SAE_PASSWORD,
+		    os_strlen(params->sae_password), params->sae_password)) {
+			wpa_printf(MSG_ERROR, "nl80211: Setting SAE password failed");
+			goto fail;
+		} else
+			wpa_printf(MSG_DEBUG, "nl80211: SAE password for offload");
+	}
 
 	if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
 	    (!params->pairwise_ciphers ||
 	     params->pairwise_ciphers & (WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40)) &&
-	    nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT))
+	    (nla_put_u16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, ETH_P_PAE) ||
+	     nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT)))
 		goto fail;
 
 	if (drv->device_ap_sme) {
@@ -5280,9 +5269,7 @@
 
 		flags |= NL80211_AP_SETTINGS_SA_QUERY_OFFLOAD_SUPPORT;
 
-		if (nl80211_attr_supported(drv,
-					   NL80211_ATTR_AP_SETTINGS_FLAGS) &&
-		    nla_put_u32(msg, NL80211_ATTR_AP_SETTINGS_FLAGS, flags))
+		if (nla_put_u32(msg, NL80211_ATTR_AP_SETTINGS_FLAGS, flags))
 			goto fail;
 	}
 
@@ -5379,9 +5366,6 @@
 		nla_nest_end(msg, ftm);
 	}
 
-	if (params->freq && nl80211_put_freq_params(msg, params->freq) < 0)
-		goto fail;
-
 #ifdef CONFIG_IEEE80211AX
 	if (params->he_spr_ctrl) {
 		struct nlattr *spr;
@@ -5416,8 +5400,10 @@
 		nla_nest_end(msg, spr);
 	}
 
-	if (params->freq && params->freq->he_enabled &&
-	    nl80211_attr_supported(drv, NL80211_ATTR_HE_BSS_COLOR)) {
+	if (params->freq && nl80211_put_freq_params(msg, params->freq) < 0)
+		goto fail;
+
+	if (params->freq && params->freq->he_enabled) {
 		struct nlattr *bss_color;
 
 		bss_color = nla_nest_start(msg, NL80211_ATTR_HE_BSS_COLOR);
@@ -5469,15 +5455,10 @@
 #ifdef CONFIG_DRIVER_NL80211_QCA
 	if (cmd == NL80211_CMD_NEW_BEACON && params->allowed_freqs)
 		qca_set_allowed_ap_freqs(drv, params->allowed_freqs,
-					 int_array_len(params->allowed_freqs),
-					 params->mld_ap ? params->mld_link_id :
-					 NL80211_DRV_LINK_ID_NA);
+					 int_array_len(params->allowed_freqs));
 #endif /* CONFIG_DRIVER_NL80211_QCA */
 
-	if (nla_put_flag(msg, NL80211_ATTR_SOCKET_OWNER))
-		goto fail;
-	ret = send_and_recv(drv->global, bss->nl_connect, msg, NULL, NULL, NULL,
-			    NULL, NULL);
+	ret = send_and_recv_msgs_connect_handle(drv, msg, bss, 1);
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)",
 			   ret, strerror(-ret));
@@ -5485,9 +5466,7 @@
 		link->beacon_set = 1;
 		nl80211_set_bss(bss, params->cts_protect, params->preamble,
 				params->short_slot_time, params->ht_opmode,
-				params->isolate, params->basic_rates,
-				params->mld_ap ? params->mld_link_id :
-				NL80211_DRV_LINK_ID_NA);
+				params->isolate, params->basic_rates);
 		nl80211_set_multicast_to_unicast(bss,
 						 params->multicast_to_unicast);
 		if (beacon_set && params->freq &&
@@ -5534,6 +5513,27 @@
 }
 
 
+static bool nl80211_link_valid(struct i802_bss *bss, s8 link_id)
+{
+	unsigned int i;
+
+	if (link_id < 0)
+		return false;
+
+	for (i = 0; i < bss->n_links; i++) {
+		wpa_printf(MSG_DEBUG, "nl80211: %s - i=%u, link_id=%u",
+			   __func__, i, bss->links[i].link_id);
+		if (bss->links[i].link_id == NL80211_DRV_LINK_ID_NA)
+			continue;
+
+		if (bss->links[i].link_id == link_id)
+			return true;
+	}
+
+	return false;
+}
+
+
 static int nl80211_set_channel(struct i802_bss *bss,
 			       struct hostapd_freq_params *freq, int set_chan)
 {
@@ -5554,7 +5554,7 @@
 		return -1;
 	}
 
-	if (nl80211_link_valid(bss->valid_links, freq->link_id)) {
+	if (nl80211_link_valid(bss, freq->link_id)) {
 		wpa_printf(MSG_DEBUG, "nl80211: Set link_id=%u for freq",
 			   freq->link_id);
 
@@ -5564,7 +5564,7 @@
 		}
 	}
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	if (ret == 0) {
 		nl80211_link_set_freq(bss, freq->link_id, freq->freq);
 		return 0;
@@ -5905,7 +5905,7 @@
 			goto fail;
 	}
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	msg = NULL;
 	if (ret)
 		wpa_printf(MSG_DEBUG, "nl80211: %s result: %d (%s)",
@@ -5920,25 +5920,26 @@
 
 static void rtnl_neigh_delete_fdb_entry(struct i802_bss *bss, const u8 *addr)
 {
+#ifdef CONFIG_LIBNL3_ROUTE
 	struct wpa_driver_nl80211_data *drv = bss->drv;
-	struct ndmsg nhdr = {
-		.ndm_state = NUD_PERMANENT,
-		.ndm_ifindex = bss->ifindex,
-		.ndm_family = AF_BRIDGE,
-	};
-	struct nl_msg *msg;
+	struct rtnl_neigh *rn;
+	struct nl_addr *nl_addr;
 	int err;
 
-	msg = nlmsg_alloc_simple(RTM_DELNEIGH, NLM_F_CREATE);
-	if (!msg)
+	rn = rtnl_neigh_alloc();
+	if (!rn)
 		return;
 
-	if (nlmsg_append(msg, &nhdr, sizeof(nhdr), NLMSG_ALIGNTO) < 0 ||
-	    nla_put(msg, NDA_LLADDR, ETH_ALEN, (void *) addr) ||
-	    nl_send_auto_complete(drv->rtnl_sk, msg) < 0)
-		goto errout;
+	rtnl_neigh_set_family(rn, AF_BRIDGE);
+	rtnl_neigh_set_ifindex(rn, bss->ifindex);
+	nl_addr = nl_addr_build(AF_BRIDGE, (void *) addr, ETH_ALEN);
+	if (!nl_addr) {
+		rtnl_neigh_put(rn);
+		return;
+	}
+	rtnl_neigh_set_lladdr(rn, nl_addr);
 
-	err = nl_wait_for_ack(drv->rtnl_sk);
+	err = rtnl_neigh_delete(drv->rtnl_sk, rn, 0);
 	if (err < 0) {
 		wpa_printf(MSG_DEBUG, "nl80211: bridge FDB entry delete for "
 			   MACSTR " ifindex=%d failed: %s", MAC2STR(addr),
@@ -5948,8 +5949,9 @@
 			   MACSTR, MAC2STR(addr));
 	}
 
-errout:
-	nlmsg_free(msg);
+	nl_addr_put(nl_addr);
+	rtnl_neigh_put(rn);
+#endif /* CONFIG_LIBNL3_ROUTE */
 }
 
 
@@ -5974,7 +5976,7 @@
 		return -ENOBUFS;
 	}
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	wpa_printf(MSG_DEBUG, "nl80211: sta_remove -> DEL_STATION %s " MACSTR
 		   " --> %d (%s)",
 		   bss->ifname, MAC2STR(addr), ret, strerror(-ret));
@@ -6005,7 +6007,7 @@
 	}
 
 	msg = nl80211_ifindex_msg(drv, ifidx, 0, NL80211_CMD_DEL_INTERFACE);
-	if (send_and_recv_cmd(drv, msg) == 0)
+	if (send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL) == 0)
 		return;
 	wpa_printf(MSG_ERROR, "Failed to remove interface (ifidx=%d)", ifidx);
 }
@@ -6089,7 +6091,7 @@
 	    nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr))
 		goto fail;
 
-	ret = send_and_recv_resp(drv, msg, handler, arg);
+	ret = send_and_recv_msgs(drv, msg, handler, arg, NULL, NULL);
 	msg = NULL;
 	if (ret) {
 	fail:
@@ -6236,8 +6238,7 @@
 		nl80211_mgmt_unsubscribe(bss, "AP teardown");
 
 	nl80211_put_wiphy_data_ap(bss);
-	if (bss->flink)
-		bss->flink->beacon_set = 0;
+	bss->flink->beacon_set = 0;
 }
 
 
@@ -6271,8 +6272,8 @@
 
 	os_memset(&ext_arg, 0, sizeof(struct nl80211_ack_ext_arg));
 	ext_arg.ext_data = &cookie;
-	ret = send_and_recv(bss->drv->global, bss->drv->global->nl, msg,
-			    NULL, NULL, ack_handler_cookie, &ext_arg, NULL);
+	ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL,
+				 ack_handler_cookie, &ext_arg);
 	if (ret) {
 		wpa_printf(MSG_DEBUG,
 			   "nl80211: tx_control_port failed: ret=%d (%s)",
@@ -6439,7 +6440,7 @@
 	if (nla_put(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd))
 		goto fail;
 
-	return send_and_recv_cmd(bss->drv, msg);
+	return send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL);
 fail:
 	nlmsg_free(msg);
 	return -ENOBUFS;
@@ -6462,7 +6463,7 @@
 	    nla_put_u16(msg, NL80211_ATTR_AIRTIME_WEIGHT, weight))
 		goto fail;
 
-	ret = send_and_recv_cmd(bss->drv, msg);
+	ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL);
 	if (ret) {
 		wpa_printf(MSG_DEBUG,
 			   "nl80211: SET_STATION[AIRTIME_WEIGHT] failed: ret=%d (%s)",
@@ -6512,8 +6513,7 @@
 	int ret;
 
 	msg = nl80211_drv_msg(drv, 0, NL80211_CMD_LEAVE_IBSS);
-	ret = send_and_recv(drv->global, drv->first_bss->nl_connect, msg, NULL,
-			    NULL, NULL, NULL, NULL);
+	ret = send_and_recv_msgs_connect_handle(drv, msg, drv->first_bss, 1);
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "nl80211: Leave IBSS failed: ret=%d "
 			   "(%s)", ret, strerror(-ret));
@@ -6643,7 +6643,7 @@
 	    params->key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
 	    params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA384) {
 		wpa_printf(MSG_DEBUG, "  * control port");
-		if (nl80211_put_control_port(drv, msg))
+		if (nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT))
 			goto fail;
 	}
 
@@ -6660,10 +6660,7 @@
 	if (ret < 0)
 		goto fail;
 
-	if (nla_put_flag(msg, NL80211_ATTR_SOCKET_OWNER))
-		goto fail;
-	ret = send_and_recv(drv->global, drv->first_bss->nl_connect, msg, NULL,
-			    NULL, NULL, NULL, NULL);
+	ret = send_and_recv_msgs_connect_handle(drv, msg, drv->first_bss, 1);
 	msg = NULL;
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "nl80211: Join IBSS failed: ret=%d (%s)",
@@ -6746,6 +6743,7 @@
 	if (params->mld_params.mld_addr && params->mld_params.valid_links > 0) {
 		struct wpa_driver_mld_params *mld_params = &params->mld_params;
 		struct nlattr *links, *attr;
+		int i;
 		u8 link_id;
 
 		wpa_printf(MSG_DEBUG, "  * MLD: MLD addr=" MACSTR,
@@ -6761,8 +6759,31 @@
 		if (!links)
 			return -1;
 
-		for_each_link(mld_params->valid_links, link_id) {
-			attr = nla_nest_start(msg, 0);
+		attr = nla_nest_start(msg, 0);
+		if (!attr)
+			return -1;
+
+		/* First add the association link ID */
+		link_id = mld_params->assoc_link_id;
+		if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id) ||
+		    nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
+			    mld_params->mld_links[link_id].bssid) ||
+		    nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
+				mld_params->mld_links[link_id].freq))
+			return -1;
+
+		os_memcpy(drv->sta_mlo_info.links[link_id].bssid,
+			  mld_params->mld_links[link_id].bssid, ETH_ALEN);
+
+		nla_nest_end(msg, attr);
+
+		for (i = 1, link_id = 0; link_id < MAX_NUM_MLD_LINKS;
+		     link_id++) {
+			if (!(mld_params->valid_links & BIT(link_id)) ||
+			    link_id == mld_params->assoc_link_id)
+				continue;
+
+			attr = nla_nest_start(msg, i);
 			if (!attr)
 				return -1;
 
@@ -6772,11 +6793,8 @@
 				    mld_params->mld_links[link_id].bssid) ||
 			    nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
 					mld_params->mld_links[link_id].freq) ||
-			    (mld_params->mld_links[link_id].disabled &&
-			     nla_put_flag(msg,
-					  NL80211_ATTR_MLO_LINK_DISABLED)) ||
 			    (mld_params->mld_links[link_id].ies &&
-			     mld_params->mld_links[link_id].ies_len &&
+			     mld_params->mld_links[i].ies_len &&
 			     nla_put(msg, NL80211_ATTR_IE,
 				     mld_params->mld_links[link_id].ies_len,
 				     mld_params->mld_links[link_id].ies)))
@@ -6786,6 +6804,7 @@
 				  mld_params->mld_links[link_id].bssid,
 				  ETH_ALEN);
 			nla_nest_end(msg, attr);
+			i++;
 		}
 
 		nla_nest_end(msg, links);
@@ -6872,20 +6891,8 @@
 
 		if (params->wpa_proto & WPA_PROTO_WPA)
 			ver |= NL80211_WPA_VERSION_1;
-		if (params->wpa_proto & WPA_PROTO_RSN) {
-#if !defined(CONFIG_DRIVER_NL80211_BRCM) && !defined(CONFIG_DRIVER_NL80211_SYNA)
-			/*
-			 * NL80211_ATTR_SAE_PASSWORD is related and was added
-			 * at the same time as NL80211_WPA_VERSION_3.
-			 */
-			if (nl80211_attr_supported(drv,
-						   NL80211_ATTR_SAE_PASSWORD) &&
-			    wpa_key_mgmt_sae(params->key_mgmt_suite))
-				ver |= NL80211_WPA_VERSION_3;
-			else
-#endif
-				ver |= NL80211_WPA_VERSION_2;
-		}
+		if (params->wpa_proto & WPA_PROTO_RSN)
+			ver |= NL80211_WPA_VERSION_2;
 
 		wpa_printf(MSG_DEBUG, "  * WPA Versions 0x%x", ver);
 		if (nla_put_u32(msg, NL80211_ATTR_WPA_VERSIONS, ver))
@@ -7079,14 +7086,15 @@
 			return -1;
 	}
 
-	if (nl80211_put_control_port(drv, msg))
+	if (nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT))
 		return -1;
 
 	if (params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
 	    (params->pairwise_suite == WPA_CIPHER_NONE ||
 	     params->pairwise_suite == WPA_CIPHER_WEP104 ||
 	     params->pairwise_suite == WPA_CIPHER_WEP40) &&
-	    nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT))
+	    (nla_put_u16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, ETH_P_PAE) ||
+	     nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT)))
 		return -1;
 
 	if (params->rrm_used) {
@@ -7236,10 +7244,7 @@
 	if (ret)
 		goto fail;
 
-	if (nla_put_flag(msg, NL80211_ATTR_SOCKET_OWNER))
-		goto fail;
-	ret = send_and_recv(drv->global, bss->nl_connect, msg, NULL, NULL, NULL,
-			    NULL, NULL);
+	ret = send_and_recv_msgs_connect_handle(drv, msg, bss, 1);
 	msg = NULL;
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "nl80211: MLME connect failed: ret=%d "
@@ -7297,7 +7302,6 @@
 {
 	struct i802_bss *bss = priv;
 	struct wpa_driver_nl80211_data *drv = bss->drv;
-	struct nl80211_err_info err_info;
 	int ret = -1;
 	struct nl_msg *msg;
 
@@ -7315,6 +7319,11 @@
 
 		if (wpa_driver_nl80211_set_mode(priv, nlmode) < 0)
 			return -1;
+		if (wpa_key_mgmt_sae(params->key_mgmt_suite) ||
+		    wpa_key_mgmt_sae(params->allowed_key_mgmts))
+			bss->use_nl_connect = 1;
+		else
+			bss->use_nl_connect = 0;
 
 		return wpa_driver_nl80211_connect(drv, params, bss);
 	}
@@ -7351,42 +7360,13 @@
 			goto fail;
 	}
 
-	if (!TEST_FAIL_TAG("assoc")) {
-		if (nla_put_flag(msg, NL80211_ATTR_SOCKET_OWNER))
-			goto fail;
-		ret = send_and_recv(drv->global, drv->first_bss->nl_connect,
-				    msg, NULL, NULL, NULL, NULL, &err_info);
-		msg = NULL;
-	} else {
-		int i;
-
-		/* Error and force TEST_FAIL checking for each link */
-		ret = -EINVAL;
-		for_each_link(params->mld_params.valid_links, i) {
-			if (TEST_FAIL_TAG("link"))
-				err_info.link_id = i;
-		}
-	}
-
+	ret = send_and_recv_msgs_connect_handle(drv, msg, drv->first_bss, 1);
+	msg = NULL;
 	if (ret) {
 		wpa_dbg(drv->ctx, MSG_DEBUG,
 			"nl80211: MLME command failed (assoc): ret=%d (%s)",
 			ret, strerror(-ret));
 		nl80211_dump_scan(drv);
-
-		/* Mark failed link within params */
-		if (err_info.link_id >= 0) {
-			if (err_info.link_id >= MAX_NUM_MLD_LINKS ||
-			    !(params->mld_params.valid_links &
-			      BIT(err_info.link_id))) {
-				wpa_printf(MSG_DEBUG,
-					   "nl80211: Invalid errorred link_id %d",
-					   err_info.link_id);
-				goto fail;
-			}
-			params->mld_params.mld_links[err_info.link_id].error =
-				ret;
-		}
 	} else {
 		wpa_printf(MSG_DEBUG,
 			   "nl80211: Association request send successfully");
@@ -7411,7 +7391,7 @@
 	if (!msg || nla_put_u32(msg, NL80211_ATTR_IFTYPE, mode))
 		goto fail;
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	msg = NULL;
 	if (!ret)
 		return 0;
@@ -7678,7 +7658,7 @@
 		return -ENOBUFS;
 	}
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	if (!ret)
 		return 0;
 	wpa_printf(MSG_DEBUG, "nl80211: Failed to set STA flag: %d (%s)",
@@ -7745,7 +7725,7 @@
 	}
 
 	os_memset(seq, 0, 6);
-	res = send_and_recv_resp(drv, msg, get_key_handler, seq);
+	res = send_and_recv_msgs(drv, msg, get_key_handler, seq, NULL, NULL);
 	if (res) {
 		wpa_printf(MSG_DEBUG,
 			   "nl80211: Failed to get current TX sequence for a key (link_id=%d idx=%d): %d (%s)",
@@ -7775,7 +7755,7 @@
 		return -ENOBUFS;
 	}
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	if (!ret)
 		return 0;
 	wpa_printf(MSG_DEBUG, "nl80211: Failed to set RTS threshold %d: "
@@ -7803,7 +7783,7 @@
 		return -ENOBUFS;
 	}
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	if (!ret)
 		return 0;
 	wpa_printf(MSG_DEBUG, "nl80211: Failed to set fragmentation threshold "
@@ -7825,7 +7805,7 @@
 	 * XXX: FIX! this needs to flush all VLANs too
 	 */
 	msg = nl80211_bss_msg(bss, 0, NL80211_CMD_DEL_STATION);
-	res = send_and_recv_cmd(bss->drv, msg);
+	res = send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL);
 	if (res) {
 		wpa_printf(MSG_DEBUG, "nl80211: Station flush failed: ret=%d "
 			   "(%s)", res, strerror(-res));
@@ -8156,7 +8136,7 @@
 		return -ENOBUFS;
 	}
 
-	return send_and_recv_resp(drv, msg, get_sta_handler, data);
+	return send_and_recv_msgs(drv, msg, get_sta_handler, data, NULL, NULL);
 }
 
 
@@ -8172,7 +8152,8 @@
 		return -ENOBUFS;
 	}
 
-	return send_and_recv_resp(bss->drv, msg, get_sta_handler, data);
+	return send_and_recv_msgs(bss->drv, msg, get_sta_handler, data,
+				  NULL, NULL);
 }
 
 
@@ -8234,10 +8215,10 @@
 	    nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id))
 		goto fail;
 
-	res = send_and_recv_cmd(drv, msg);
+	res = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	wpa_printf(MSG_DEBUG,
-		   "nl80211: link=%d: TX queue param set: queue=%d aifs=%d cw_min=%d cw_max=%d burst_time=%d --> res=%d",
-		   link_id, queue, aifs, cw_min, cw_max, burst_time, res);
+		   "nl80211: TX queue param set: queue=%d aifs=%d cw_min=%d cw_max=%d burst_time=%d --> res=%d",
+		   queue, aifs, cw_min, cw_max, burst_time, res);
 	if (res == 0)
 		return 0;
 	msg = NULL;
@@ -8269,7 +8250,7 @@
 		return -ENOBUFS;
 	}
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	if (ret < 0) {
 		wpa_printf(MSG_ERROR, "nl80211: NL80211_ATTR_STA_VLAN (addr="
 			   MACSTR " ifname=%s vlan_id=%d) failed: %d (%s)",
@@ -8697,6 +8678,7 @@
 	    (params->num_bridge == 0 || !params->bridge[0]))
 		add_ifidx(drv, br_ifindex, drv->ifindex);
 
+#ifdef CONFIG_LIBNL3_ROUTE
 	if (bss->added_if_into_bridge || bss->already_in_bridge) {
 		int err;
 
@@ -8713,6 +8695,7 @@
 			goto failed;
 		}
 	}
+#endif /* CONFIG_LIBNL3_ROUTE */
 
 	if (drv->capa.flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX) {
 		wpa_printf(MSG_DEBUG,
@@ -8786,7 +8769,7 @@
 	struct wpa_driver_nl80211_data *drv;
 	dl_list_for_each(drv, &global->interfaces,
 			 struct wpa_driver_nl80211_data, list) {
-		if (ether_addr_equal(addr, drv->first_bss->addr))
+		if (os_memcmp(addr, drv->first_bss->addr, ETH_ALEN) == 0)
 			return 1;
 	}
 	return 0;
@@ -8937,6 +8920,7 @@
 
 	if (type == WPA_IF_AP_BSS && setup_ap) {
 		struct i802_bss *new_bss = os_zalloc(sizeof(*new_bss));
+		unsigned int i;
 
 		if (new_bss == NULL) {
 			if (added)
@@ -8944,6 +8928,10 @@
 			return -1;
 		}
 
+		/* Initialize here before any failure path */
+		for (i = 0; i < MAX_NUM_MLD_LINKS; i++)
+			new_bss->links[i].link_id = NL80211_DRV_LINK_ID_NA;
+
 		if (bridge &&
 		    i802_check_bridge(drv, new_bss, bridge, ifname) < 0) {
 			wpa_printf(MSG_ERROR, "nl80211: Failed to add the new "
@@ -8968,7 +8956,7 @@
 		new_bss->drv = drv;
 		new_bss->next = drv->first_bss->next;
 		new_bss->flink = &new_bss->links[0];
-		new_bss->valid_links = 0;
+		new_bss->n_links = 1;
 		os_memcpy(new_bss->flink->addr, new_bss->addr, ETH_ALEN);
 
 		new_bss->flink->freq = drv->first_bss->flink->freq;
@@ -9048,7 +9036,6 @@
 				tbss->next = bss->next;
 				/* Unsubscribe management frames */
 				nl80211_teardown_ap(bss);
-				nl80211_remove_links(bss);
 				nl80211_destroy_bss(bss);
 				if (!bss->added_if)
 					i802_set_iface_flags(bss, 0);
@@ -9063,7 +9050,6 @@
 	} else {
 		wpa_printf(MSG_DEBUG, "nl80211: First BSS - reassign context");
 		nl80211_teardown_ap(bss);
-		nl80211_remove_links(bss);
 		if (!bss->added_if && !drv->first_bss->next)
 			wpa_driver_nl80211_del_beacon_all(bss);
 		nl80211_destroy_bss(bss);
@@ -9072,7 +9058,6 @@
 		if (drv->first_bss->next) {
 			drv->first_bss = drv->first_bss->next;
 			drv->ctx = drv->first_bss->ctx;
-			drv->ifindex = drv->first_bss->ifindex;
 			os_free(bss);
 		} else {
 			wpa_printf(MSG_DEBUG, "nl80211: No second BSS to reassign context to");
@@ -9101,7 +9086,7 @@
 				  const u8 *buf, size_t buf_len,
 				  int save_cookie, int no_cck, int no_ack,
 				  int offchanok, const u16 *csa_offs,
-				  size_t csa_offs_len, int link_id)
+				  size_t csa_offs_len)
 {
 	struct wpa_driver_nl80211_data *drv = bss->drv;
 	struct nl_msg *msg;
@@ -9114,8 +9099,6 @@
 	wpa_hexdump(MSG_MSGDUMP, "CMD_FRAME", buf, buf_len);
 
 	if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_FRAME)) ||
-	    ((link_id != NL80211_DRV_LINK_ID_NA) &&
-	     nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id)) ||
 	    (freq && nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq)) ||
 	    (wait && nla_put_u32(msg, NL80211_ATTR_DURATION, wait)) ||
 	    (offchanok && ((drv->capa.flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX) ||
@@ -9129,7 +9112,7 @@
 		goto fail;
 
 	cookie = 0;
-	ret = send_and_recv_resp(drv, msg, cookie_handler, &cookie);
+	ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie, NULL, NULL);
 	msg = NULL;
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "nl80211: Frame command failed: ret=%d "
@@ -9187,14 +9170,9 @@
 	    bss->flink->beacon_set)
 		offchanok = 0;
 
-	if (!freq && is_sta_interface(drv->nlmode))
-		offchanok = 0;
-
-	wpa_printf(MSG_DEBUG,
-		   "nl80211: Send Action frame (ifindex=%d, freq=%u MHz wait=%d ms no_cck=%d offchanok=%d dst="
-		   MACSTR " src=" MACSTR " bssid=" MACSTR ")",
-		   drv->ifindex, freq, wait_time, no_cck, offchanok,
-		   MAC2STR(dst), MAC2STR(src), MAC2STR(bssid));
+	wpa_printf(MSG_DEBUG, "nl80211: Send Action frame (ifindex=%d, "
+		   "freq=%u MHz wait=%d ms no_cck=%d offchanok=%d)",
+		   drv->ifindex, freq, wait_time, no_cck, offchanok);
 
 	buf = os_zalloc(24 + data_len);
 	if (buf == NULL)
@@ -9207,7 +9185,7 @@
 	os_memcpy(hdr->addr2, src, ETH_ALEN);
 	os_memcpy(hdr->addr3, bssid, ETH_ALEN);
 
-	if (!ether_addr_equal(bss->addr, src)) {
+	if (os_memcmp(bss->addr, src, ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG, "nl80211: Use random TA " MACSTR,
 			   MAC2STR(src));
 		os_memcpy(bss->rand_addr, src, ETH_ALEN);
@@ -9246,9 +9224,8 @@
 						   wait_time, NULL, 0, 0, -1);
 	else
 		ret = nl80211_send_frame_cmd(bss, freq, wait_time, buf,
-					     24 + data_len, 1, no_cck, 0,
-					     offchanok, NULL, 0,
-					     NL80211_DRV_LINK_ID_NA);
+					     24 + data_len,
+					     1, no_cck, 0, offchanok, NULL, 0);
 
 	os_free(buf);
 	return ret;
@@ -9269,7 +9246,7 @@
 		return;
 	}
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	if (ret)
 		wpa_printf(MSG_DEBUG, "nl80211: wait cancel failed: ret=%d "
 			   "(%s)", ret, strerror(-ret));
@@ -9301,43 +9278,6 @@
 }
 
 
-static int nl80211_put_any_link_id(struct nl_msg *msg,
-			       struct driver_sta_mlo_info *mlo,
-			       int freq)
-{
-	int i;
-	int link_id = -1;
-	int any_valid_link_id = -1;
-
-	if (!mlo->valid_links)
-		return 0;
-
-	/* First try to pick a link that uses the same band */
-	for_each_link(mlo->valid_links, i) {
-		if (any_valid_link_id == -1)
-			any_valid_link_id = i;
-
-		if (is_same_band(freq, mlo->links[i].freq)) {
-			link_id = i;
-			break;
-		}
-	}
-
-	/* Use any valid link ID if no band match was found */
-	if (link_id == -1)
-		link_id = any_valid_link_id;
-
-	if (link_id == -1) {
-		wpa_printf(MSG_INFO,
-			   "nl80211: No valid Link ID found for freq %u", freq);
-		return 0;
-	}
-
-	wpa_printf(MSG_DEBUG, "nl80211: Add Link ID %d", link_id);
-	return nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id);
-}
-
-
 static int wpa_driver_nl80211_remain_on_channel(void *priv, unsigned int freq,
 						unsigned int duration)
 {
@@ -9349,14 +9289,13 @@
 
 	if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_REMAIN_ON_CHANNEL)) ||
 	    nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq) ||
-	    nla_put_u32(msg, NL80211_ATTR_DURATION, duration) ||
-	    nl80211_put_any_link_id(msg, &drv->sta_mlo_info, freq)) {
+	    nla_put_u32(msg, NL80211_ATTR_DURATION, duration)) {
 		nlmsg_free(msg);
 		return -1;
 	}
 
 	cookie = 0;
-	ret = send_and_recv_resp(drv, msg, cookie_handler, &cookie);
+	ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie, NULL, NULL);
 	if (ret == 0) {
 		wpa_printf(MSG_DEBUG, "nl80211: Remain-on-channel cookie "
 			   "0x%llx for freq=%u MHz duration=%u",
@@ -9396,7 +9335,7 @@
 		return -1;
 	}
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	if (ret == 0)
 		return 0;
 	wpa_printf(MSG_DEBUG, "nl80211: Failed to cancel remain-on-channel: "
@@ -9493,7 +9432,7 @@
 
 	nla_nest_end(msg, bands);
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "nl80211: Set TX rates failed: ret=%d "
 			   "(%s)", ret, strerror(-ret));
@@ -9508,81 +9447,56 @@
 }
 
 
-static int nl80211_remove_link(struct i802_bss *bss, int link_id)
-{
-	struct wpa_driver_nl80211_data *drv = bss->drv;
-	struct i802_link *link;
-	struct nl_msg *msg;
-	size_t i;
-	int ret;
-
-	wpa_printf(MSG_DEBUG, "nl80211: Remove link (ifindex=%d link_id=%u)",
-		   bss->ifindex, link_id);
-
-	if (!(bss->valid_links & BIT(link_id))) {
-		wpa_printf(MSG_DEBUG,
-			   "nl80211: MLD: remove link: Link not found");
-		return -1;
-	}
-
-	link = &bss->links[link_id];
-
-	wpa_driver_nl80211_del_beacon(bss, link_id);
-
-	/* First remove the link locally */
-	bss->valid_links &= ~BIT(link_id);
-	os_memset(link->addr, 0, ETH_ALEN);
-
-	/* Choose new deflink if we are removing that link */
-	if (bss->flink == link) {
-		for_each_link_default(bss->valid_links, i, 0) {
-			bss->flink = &bss->links[i];
-			break;
-		}
-	}
-
-	/* If this was the last link, reset default link */
-	if (!bss->valid_links) {
-		/* TODO: Does keeping freq/bandwidth make sense? */
-		if (bss->flink != link)
-			os_memcpy(bss->flink, link, sizeof(*link));
-
-		os_memcpy(bss->flink->addr, bss->addr, ETH_ALEN);
-	}
-
-	/* Remove the link from the kernel */
-	msg = nl80211_bss_msg(bss, 0, NL80211_CMD_REMOVE_LINK);
-	if (!msg ||
-	    nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id)) {
-		nlmsg_free(msg);
-		wpa_printf(MSG_ERROR,
-			   "nl80211: remove link (%d) failed", link_id);
-		return -1;
-	}
-
-	ret = send_and_recv_cmd(drv, msg);
-	if (ret)
-		wpa_printf(MSG_ERROR,
-			   "nl80211: remove link (%d) failed. ret=%d (%s)",
-			   link_id, ret, strerror(-ret));
-
-	return ret;
-}
-
-
 static void nl80211_remove_links(struct i802_bss *bss)
 {
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+	struct nl_msg *msg;
 	int ret;
 	u8 link_id;
 
-	for_each_link(bss->valid_links, link_id) {
-		ret = nl80211_remove_link(bss, link_id);
-		if (ret)
-			break;
-	}
+	while (bss->links[0].link_id != NL80211_DRV_LINK_ID_NA) {
+		struct i802_link *link = &bss->links[0];
 
-	if (bss->flink)
-		os_memcpy(bss->flink->addr, bss->addr, ETH_ALEN);
+		wpa_printf(MSG_DEBUG, "nl80211: MLD: remove link_id=%u",
+			   link->link_id);
+
+		wpa_driver_nl80211_del_beacon(bss, link);
+
+		link_id = link->link_id;
+
+		/* First remove the link locally */
+		if (bss->n_links == 1) {
+			bss->flink->link_id = NL80211_DRV_LINK_ID_NA;
+			os_memcpy(bss->flink->addr, bss->addr, ETH_ALEN);
+		} else {
+			struct i802_link *other = &bss->links[bss->n_links - 1];
+
+			os_memcpy(link, other, sizeof(*link));
+			other->link_id = NL80211_DRV_LINK_ID_NA;
+			os_memset(other->addr, 0, ETH_ALEN);
+
+			bss->n_links--;
+		}
+
+		/* Remove the link from the kernel */
+		msg = nl80211_drv_msg(drv, 0, NL80211_CMD_REMOVE_LINK);
+		if (!msg ||
+		    nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id)) {
+			nlmsg_free(msg);
+			wpa_printf(MSG_ERROR,
+				   "nl80211: remove link (%d) failed",
+				   link_id);
+			return;
+		}
+
+		ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+		if (ret) {
+			wpa_printf(MSG_ERROR,
+				   "nl80211: remove link (%d) failed. ret=%d (%s)",
+				   link_id, ret, strerror(-ret));
+			return;
+		}
+	}
 }
 
 
@@ -9595,7 +9509,7 @@
 		return -1;
 
 	/* Stop beaconing */
-	wpa_driver_nl80211_del_beacon(bss, NL80211_DRV_LINK_ID_NA);
+	wpa_driver_nl80211_del_beacon(bss, bss->flink);
 
 	nl80211_remove_links(bss);
 
@@ -9610,7 +9524,7 @@
 }
 
 
-static int wpa_driver_nl80211_stop_ap(void *priv, int link_id)
+static int wpa_driver_nl80211_stop_ap(void *priv)
 {
 	struct i802_bss *bss = priv;
 	struct wpa_driver_nl80211_data *drv = bss->drv;
@@ -9618,17 +9532,9 @@
 	if (!is_ap_interface(drv->nlmode))
 		return -1;
 
-	if (link_id == -1) {
-		wpa_driver_nl80211_del_beacon_all(bss);
-		return 0;
-	}
+	wpa_driver_nl80211_del_beacon_all(bss);
 
-	if (nl80211_link_valid(bss->valid_links, link_id)) {
-		wpa_driver_nl80211_del_beacon(bss, link_id);
-		return 0;
-	}
-
-	return -1;
+	return 0;
 }
 
 
@@ -9682,7 +9588,7 @@
 	}
 	nla_nest_end(msg, cqm);
 
-	return send_and_recv_cmd(drv, msg);
+	return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 }
 
 
@@ -9720,7 +9626,7 @@
 	struct nl_msg *msg;
 
 	msg = nl80211_drv_msg(drv, 0, NL80211_CMD_GET_INTERFACE);
-	return send_and_recv_resp(drv, msg, get_channel_width, sig);
+	return send_and_recv_msgs(drv, msg, get_channel_width, sig, NULL, NULL);
 }
 
 
@@ -9781,7 +9687,10 @@
 	if (!sinfo[NL80211_SURVEY_INFO_NOISE])
 		return NL_SKIP;
 
-	for_each_link(mlo_sig->valid_links, i) {
+	for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+		if (!(mlo_sig->valid_links & BIT(i)))
+			continue;
+
 		if (nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]) !=
 		    mlo_sig->links[i].frequency)
 			continue;
@@ -9801,7 +9710,8 @@
 	struct nl_msg *msg;
 
 	msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_GET_SURVEY);
-	return send_and_recv_resp(drv, msg, get_links_noise, mlo_sig);
+	return send_and_recv_msgs(drv, msg, get_links_noise, mlo_sig,
+				  NULL, NULL);
 }
 
 
@@ -9855,7 +9765,8 @@
 	struct nl_msg *msg;
 
 	msg = nl80211_drv_msg(drv, 0, NL80211_CMD_GET_INTERFACE);
-	return send_and_recv_resp(drv, msg, get_links_channel_width, mlo_sig);
+	return send_and_recv_msgs(drv, msg, get_links_channel_width, mlo_sig,
+				  NULL, NULL);
 }
 
 
@@ -9874,7 +9785,10 @@
 	os_memset(mlo_si, 0, sizeof(*mlo_si));
 	mlo_si->valid_links = drv->sta_mlo_info.valid_links;
 
-	for_each_link(mlo_si->valid_links, i) {
+	for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+		if (!(mlo_si->valid_links & BIT(i)))
+			continue;
+
 		res = nl80211_get_link_signal(drv,
 					      drv->sta_mlo_info.links[i].bssid,
 					      &mlo_si->links[i].data);
@@ -9973,13 +9887,6 @@
 {
 	struct nl80211_global *global;
 	struct netlink_config *cfg;
-	struct utsname name;
-
-	if (uname(&name) == 0) {
-		wpa_printf(MSG_DEBUG, "nl80211: Kernel version: %s %s (%s; %s)",
-			   name.sysname, name.release,
-			   name.version, name.machine);
-	}
 
 	global = os_zalloc(sizeof(*global));
 	if (global == NULL)
@@ -10090,7 +9997,7 @@
 		return -ENOBUFS;
 	}
 
-	return send_and_recv_cmd(bss->drv, msg);
+	return send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL);
 }
 
 
@@ -10166,7 +10073,7 @@
 	msg = nl80211_bss_msg(bss, 0, NL80211_CMD_FLUSH_PMKSA);
 	if (!msg)
 		return -ENOBUFS;
-	return send_and_recv_cmd(bss->drv, msg);
+	return send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL);
 }
 
 
@@ -10330,8 +10237,8 @@
 
 	do {
 		wpa_printf(MSG_DEBUG, "nl80211: Fetch survey data");
-		err = send_and_recv_resp(drv, msg, survey_handler,
-					 survey_results);
+		err = send_and_recv_msgs(drv, msg, survey_handler,
+					 survey_results, NULL, NULL);
 	} while (err > 0);
 
 	if (err)
@@ -10371,7 +10278,7 @@
 
 	nla_nest_end(msg, replay_nested);
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	if (ret == -EOPNOTSUPP) {
 		wpa_printf(MSG_DEBUG,
 			   "nl80211: Driver does not support rekey offload");
@@ -10438,7 +10345,7 @@
 		return;
 	}
 
-	ret = send_and_recv_resp(drv, msg, cookie_handler, &cookie);
+	ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie, NULL, NULL);
 	if (ret < 0) {
 		wpa_printf(MSG_DEBUG, "nl80211: Client probe request for "
 			   MACSTR " failed: ret=%d (%s)",
@@ -10464,7 +10371,7 @@
 		return -ENOBUFS;
 	}
 
-	ret = send_and_recv_cmd(bss->drv, msg);
+	ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL);
 	if (ret < 0) {
 		wpa_printf(MSG_DEBUG,
 			   "nl80211: Setting PS state %s failed: %d (%s)",
@@ -10524,7 +10431,7 @@
 		return -1;
 	}
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	if (ret == 0)
 		return 0;
 	wpa_printf(MSG_DEBUG, "nl80211: Failed to start radar detection: "
@@ -10583,7 +10490,7 @@
 	}
 	nla_nest_end(msg, params);
 
-	return send_and_recv_cmd(drv, msg);
+	return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 #else /* CONFIG_DRIVER_NL80211_QCA */
 	wpa_printf(MSG_ERROR,
 		   "nl80211: Setting TX link for TDLS Discovery Response not supported");
@@ -10621,7 +10528,7 @@
 	    nla_put(msg, NL80211_ATTR_IE, len, buf))
 		goto fail;
 
-	return send_and_recv_cmd(drv, msg);
+	return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 
 fail:
 	nlmsg_free(msg);
@@ -10671,7 +10578,7 @@
 		return -ENOBUFS;
 	}
 
-	res = send_and_recv_cmd(drv, msg);
+	res = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	wpa_printf(MSG_DEBUG, "nl80211: TDLS_OPER: oper=%d mac=" MACSTR
 		   " --> res=%d (%s)", nl80211_oper, MAC2STR(peer), res,
 		   strerror(-res));
@@ -10705,7 +10612,7 @@
 		return ret;
 	}
 
-	return send_and_recv_cmd(drv, msg);
+	return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 }
 
 
@@ -10731,7 +10638,7 @@
 		return -ENOBUFS;
 	}
 
-	return send_and_recv_cmd(drv, msg);
+	return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 }
 
 #endif /* CONFIG TDLS */
@@ -10798,73 +10705,6 @@
 }
 
 
-#ifdef CONFIG_IEEE80211BE
-
-static int driver_nl80211_link_remove(void *priv, enum wpa_driver_if_type type,
-				      const char *ifname, u8 link_id)
-{
-	struct i802_bss *bss = priv;
-	struct wpa_driver_nl80211_data *drv = bss->drv;
-
-	if (type != WPA_IF_AP_BSS ||
-	    !nl80211_link_valid(bss->valid_links, link_id))
-		return -1;
-
-	wpa_printf(MSG_DEBUG,
-		   "nl80211: Teardown AP(%s) link %d (type=%d ifname=%s links=0x%x)",
-		   bss->ifname, link_id, type, ifname, bss->valid_links);
-
-	nl80211_remove_link(bss, link_id);
-
-	bss->ctx = bss->flink->ctx;
-
-	if (drv->first_bss == bss && !bss->valid_links)
-		drv->ctx = bss->ctx;
-
-	if (!bss->valid_links) {
-		wpa_printf(MSG_DEBUG,
-			   "nl80211: No more links remaining, so remove interface");
-		return wpa_driver_nl80211_if_remove(bss, type, ifname);
-	}
-
-	return 0;
-}
-
-
-static bool nl80211_is_drv_shared(void *priv, void *bss_ctx)
-{
-	struct i802_bss *bss = priv;
-	struct wpa_driver_nl80211_data *drv = bss->drv;
-	unsigned int num_bss = 0;
-
-	/* If any other BSS exist, someone else is using this since at this
-	 * time, we would have removed all BSSs created by this driver and only
-	 * this BSS should be remaining if the driver is not shared by anyone.
-	 */
-	for (bss = drv->first_bss; bss; bss = bss->next) {
-		num_bss++;
-		if (num_bss > 1)
-			return true;
-	}
-
-	/* This is the only BSS present */
-	bss = priv;
-
-	/* If only one/no link is there no one is sharing */
-	if (bss->valid_links <= 1)
-		return false;
-
-	/* More than one link means someone is still using. To check if
-	 * only 1 bit is set, power of 2 condition can be checked. */
-	if (!(bss->valid_links & (bss->valid_links - 1)))
-		return false;
-
-	return true;
-}
-
-#endif /* CONFIG_IEEE80211BE */
-
-
 static int driver_nl80211_send_mlme(void *priv, const u8 *data,
 				    size_t data_len, int noack,
 				    unsigned int freq,
@@ -10943,7 +10783,7 @@
 		return -ENOBUFS;
 	}
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "nl80211: update_ft_ies failed "
 			   "err=%d (%s)", ret, strerror(-ret));
@@ -10971,7 +10811,7 @@
 		return -ENOBUFS;
 	}
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	if (ret) {
 		wpa_printf(MSG_DEBUG,
 			   "nl80211: update_dh_ie failed err=%d (%s)",
@@ -11113,9 +10953,9 @@
 			  drv->retry_auth ? "retry_auth=1\n" : "",
 			  drv->use_monitor ? "use_monitor=1\n" : "",
 			  drv->ignore_next_local_disconnect ?
-			  "ignore_next_local_disconnect\n" : "",
+			  "ignore_next_local_disconnect=1\n" : "",
 			  drv->ignore_next_local_deauth ?
-			  "ignore_next_local_deauth\n" : "");
+			  "ignore_next_local_deauth=1\n" : "");
 	if (os_snprintf_error(end - pos, res))
 		return pos - buf;
 	pos += res;
@@ -11133,7 +10973,10 @@
 			return pos - buf;
 		pos += res;
 
-		for_each_link(mlo->valid_links, i) {
+		for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+			if (!(mlo->valid_links & BIT(i)))
+				continue;
+
 			res = os_snprintf(pos, end - pos,
 					  "link_addr[%u]=" MACSTR "\n"
 					  "link_bssid[%u]=" MACSTR "\n"
@@ -11220,8 +11063,8 @@
 	if (msg &&
 	    nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_REG) &&
 	    nla_put_u32(msg, NL80211_ATTR_WIPHY, drv->wiphy_idx) == 0) {
-		if (send_and_recv_resp(drv, msg, nl80211_get_country,
-				       alpha2) == 0 &&
+		if (send_and_recv_msgs(drv, msg, nl80211_get_country,
+				       alpha2, NULL, NULL) == 0 &&
 		    alpha2[0]) {
 			res = os_snprintf(pos, end - pos, "country=%s\n",
 					  alpha2);
@@ -11274,7 +11117,7 @@
 	int i;
 
 	wpa_printf(MSG_DEBUG,
-		   "nl80211: Channel switch request (cs_count=%u block_tx=%u freq=%d channel=%d sec_channel_offset=%d width=%d cf1=%d cf2=%d puncturing_bitmap=0x%04x link_id=%d%s%s%s)",
+		   "nl80211: Channel switch request (cs_count=%u block_tx=%u freq=%d channel=%d sec_channel_offset=%d width=%d cf1=%d cf2=%d puncturing_bitmap=0x%04x%s%s%s)",
 		   settings->cs_count, settings->block_tx,
 		   settings->freq_params.freq,
 		   settings->freq_params.channel,
@@ -11283,7 +11126,6 @@
 		   settings->freq_params.center_freq1,
 		   settings->freq_params.center_freq2,
 		   settings->punct_bitmap,
-		   settings->link_id,
 		   settings->freq_params.ht_enabled ? " ht" : "",
 		   settings->freq_params.vht_enabled ? " vht" : "",
 		   settings->freq_params.he_enabled ? " he" : "");
@@ -11357,9 +11199,7 @@
 	     nla_put_flag(msg, NL80211_ATTR_CH_SWITCH_BLOCK_TX)) ||
 	    (settings->punct_bitmap &&
 	     nla_put_u32(msg, NL80211_ATTR_PUNCT_BITMAP,
-			 settings->punct_bitmap)) ||
-	    (settings->link_id != NL80211_DRV_LINK_ID_NA &&
-	     nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, settings->link_id)))
+			 settings->punct_bitmap)))
 		goto error;
 
 	/* beacon_after params */
@@ -11386,7 +11226,7 @@
 		goto fail;
 
 	nla_nest_end(msg, beacon_csa);
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "nl80211: switch_channel failed err=%d (%s)",
 			   ret, strerror(-ret));
@@ -11467,7 +11307,7 @@
 	}
 
 	nla_nest_end(msg, beacon_cca);
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	if (ret) {
 		wpa_printf(MSG_DEBUG,
 			   "nl80211: switch_color failed err=%d (%s)",
@@ -11508,7 +11348,7 @@
 		return -ENOBUFS;
 	}
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	if (ret)
 		wpa_printf(MSG_DEBUG, "nl80211: add_ts failed err=%d (%s)",
 			   ret, strerror(-ret));
@@ -11535,7 +11375,7 @@
 		return -ENOBUFS;
 	}
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	if (ret)
 		wpa_printf(MSG_DEBUG, "nl80211: del_ts failed err=%d (%s)",
 			   ret, strerror(-ret));
@@ -11637,10 +11477,12 @@
 		    0)
 			goto fail;
 		/* This test vendor_cmd can be used with nl80211 commands that
-		 * need the connect nl_sock, so use the variant that takes in
-		 * bss->nl_connect as the handle. */
-		ret = send_and_recv(drv->global, bss->nl_connect, msg,
-				    cmd_reply_handler, buf, NULL, NULL, NULL);
+		 * need the connect nl_sock, so use the owner-setting variant
+		 * of send_and_recv_msgs(). */
+		ret = send_and_recv_msgs_owner(drv, msg,
+					       get_connect_handle(bss), 0,
+					       cmd_reply_handler, buf,
+					       NULL, NULL);
 		if (ret)
 			wpa_printf(MSG_DEBUG, "nl80211: command failed err=%d",
 				   ret);
@@ -11664,7 +11506,8 @@
 		     data_len, data)))
 		goto fail;
 
-	ret = send_and_recv_resp(drv, msg, vendor_reply_handler, buf);
+	ret = send_and_recv_msgs(drv, msg, vendor_reply_handler, buf,
+				 NULL, NULL);
 	if (ret)
 		wpa_printf(MSG_DEBUG, "nl80211: vendor command failed err=%d",
 			   ret);
@@ -11693,7 +11536,7 @@
 		return -ENOBUFS;
 	}
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	if (ret)
 		wpa_printf(MSG_DEBUG, "nl80211: Setting QoS Map failed");
 
@@ -11728,7 +11571,8 @@
 
 	msg = nl80211_drv_msg(drv, 0, NL80211_CMD_GET_WOWLAN);
 
-	ret = send_and_recv_resp(drv, msg, get_wowlan_handler, &wowlan_enabled);
+	ret = send_and_recv_msgs(drv, msg, get_wowlan_handler, &wowlan_enabled,
+				 NULL, NULL);
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "nl80211: Getting wowlan status failed");
 		return 0;
@@ -11775,7 +11619,7 @@
 
 	nla_nest_end(msg, wowlan_triggers);
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	if (ret)
 		wpa_printf(MSG_DEBUG, "nl80211: Setting wowlan failed");
 
@@ -11814,7 +11658,7 @@
 	}
 	nla_nest_end(msg, params);
 
-	return send_and_recv_cmd(drv, msg);
+	return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 }
 
 
@@ -11842,7 +11686,7 @@
 	}
 	nla_nest_end(msg, params);
 
-	return send_and_recv_cmd(drv, msg);
+	return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 }
 
 
@@ -11899,7 +11743,7 @@
 	nla_nest_end(msg, nlbssids);
 	nla_nest_end(msg, params);
 
-	return send_and_recv_cmd(drv, msg);
+	return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 
 fail:
 	nlmsg_free(msg);
@@ -11937,7 +11781,7 @@
 	}
 	nla_nest_end(msg, params);
 
-	return send_and_recv_cmd(drv, msg);
+	return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 }
 
 #endif /* CONFIG_DRIVER_NL80211_QCA */
@@ -11976,7 +11820,7 @@
 		}
 		nla_nest_end(msg, params);
 
-		ret = send_and_recv_cmd(drv, msg);
+		ret = send_and_recv_msgs(drv, msg, NULL, (void *) -1, NULL, NULL);
 		if (ret) {
 			wpa_printf(MSG_ERROR, "nl80211: p2p set macaddr failed: ret=%d (%s)",
 				ret, strerror(-ret));
@@ -12147,10 +11991,7 @@
 	if (nl80211_put_mesh_config(msg, &params->conf) < 0)
 		goto fail;
 
-	if (nla_put_flag(msg, NL80211_ATTR_SOCKET_OWNER))
-		return -1;
-	ret = send_and_recv(drv->global, bss->nl_connect, msg, NULL, NULL, NULL,
-			    NULL, NULL);
+	ret = send_and_recv_msgs_connect_handle(drv, msg, bss, 1);
 	msg = NULL;
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "nl80211: mesh join failed: ret=%d (%s)",
@@ -12207,8 +12048,7 @@
 
 	wpa_printf(MSG_DEBUG, "nl80211: mesh leave (ifindex=%d)", drv->ifindex);
 	msg = nl80211_drv_msg(drv, 0, NL80211_CMD_LEAVE_MESH);
-	ret = send_and_recv(drv->global, bss->nl_connect, msg, NULL, NULL, NULL,
-			    NULL, NULL);
+	ret = send_and_recv_msgs_connect_handle(drv, msg, bss, 0);
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "nl80211: mesh leave failed: ret=%d (%s)",
 			   ret, strerror(-ret));
@@ -12244,7 +12084,7 @@
 		return -ENOBUFS;
 	}
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "nl80211: mesh link probe to " MACSTR
 			   " failed: ret=%d (%s)",
@@ -12264,14 +12104,13 @@
 				      const u8 *ipaddr, int prefixlen,
 				      const u8 *addr)
 {
+#ifdef CONFIG_LIBNL3_ROUTE
 	struct i802_bss *bss = priv;
 	struct wpa_driver_nl80211_data *drv = bss->drv;
-	struct ndmsg nhdr = {
-		.ndm_state = NUD_PERMANENT,
-		.ndm_ifindex = bss->br_ifindex,
-	};
-	struct nl_msg *msg;
-	int addrsize;
+	struct rtnl_neigh *rn;
+	struct nl_addr *nl_ipaddr = NULL;
+	struct nl_addr *nl_lladdr = NULL;
+	int family, addrsize;
 	int res;
 
 	if (!ipaddr || prefixlen == 0 || !addr)
@@ -12290,62 +12129,85 @@
 	}
 
 	if (version == 4) {
-		nhdr.ndm_family = AF_INET;
+		family = AF_INET;
 		addrsize = 4;
 	} else if (version == 6) {
-		nhdr.ndm_family = AF_INET6;
+		family = AF_INET6;
 		addrsize = 16;
 	} else {
 		return -EINVAL;
 	}
 
-	msg = nlmsg_alloc_simple(RTM_NEWNEIGH, NLM_F_CREATE);
-	if (!msg)
+	rn = rtnl_neigh_alloc();
+	if (rn == NULL)
 		return -ENOMEM;
 
-	res = -ENOMEM;
-	if (nlmsg_append(msg, &nhdr, sizeof(nhdr), NLMSG_ALIGNTO) < 0 ||
-	    nla_put(msg, NDA_DST, addrsize, (void *) ipaddr) ||
-	    nla_put(msg, NDA_LLADDR, ETH_ALEN, (void *) addr))
+	/* set the destination ip address for neigh */
+	nl_ipaddr = nl_addr_build(family, (void *) ipaddr, addrsize);
+	if (nl_ipaddr == NULL) {
+		wpa_printf(MSG_DEBUG, "nl80211: nl_ipaddr build failed");
+		res = -ENOMEM;
 		goto errout;
-
-	res = nl_send_auto_complete(drv->rtnl_sk, msg);
-	if (res < 0)
+	}
+	nl_addr_set_prefixlen(nl_ipaddr, prefixlen);
+	res = rtnl_neigh_set_dst(rn, nl_ipaddr);
+	if (res) {
+		wpa_printf(MSG_DEBUG,
+			   "nl80211: neigh set destination addr failed");
 		goto errout;
+	}
 
-	res = nl_wait_for_ack(drv->rtnl_sk);
+	/* set the corresponding lladdr for neigh */
+	nl_lladdr = nl_addr_build(AF_BRIDGE, (u8 *) addr, ETH_ALEN);
+	if (nl_lladdr == NULL) {
+		wpa_printf(MSG_DEBUG, "nl80211: neigh set lladdr failed");
+		res = -ENOMEM;
+		goto errout;
+	}
+	rtnl_neigh_set_lladdr(rn, nl_lladdr);
+
+	rtnl_neigh_set_ifindex(rn, bss->br_ifindex);
+	rtnl_neigh_set_state(rn, NUD_PERMANENT);
+
+	res = rtnl_neigh_add(drv->rtnl_sk, rn, NLM_F_CREATE);
 	if (res) {
 		wpa_printf(MSG_DEBUG,
 			   "nl80211: Adding bridge ip neigh failed: %s",
 			   nl_geterror(res));
 	}
 errout:
-	nlmsg_free(msg);
+	if (nl_lladdr)
+		nl_addr_put(nl_lladdr);
+	if (nl_ipaddr)
+		nl_addr_put(nl_ipaddr);
+	if (rn)
+		rtnl_neigh_put(rn);
 	return res;
+#else /* CONFIG_LIBNL3_ROUTE */
+	return -1;
+#endif /* CONFIG_LIBNL3_ROUTE */
 }
 
 
 static int wpa_driver_br_delete_ip_neigh(void *priv, u8 version,
 					 const u8 *ipaddr)
 {
+#ifdef CONFIG_LIBNL3_ROUTE
 	struct i802_bss *bss = priv;
 	struct wpa_driver_nl80211_data *drv = bss->drv;
-	struct ndmsg nhdr = {
-		.ndm_state = NUD_PERMANENT,
-		.ndm_ifindex = bss->br_ifindex,
-	};
-	struct nl_msg *msg;
-	int addrsize;
+	struct rtnl_neigh *rn;
+	struct nl_addr *nl_ipaddr;
+	int family, addrsize;
 	int res;
 
 	if (!ipaddr)
 		return -EINVAL;
 
 	if (version == 4) {
-		nhdr.ndm_family = AF_INET;
+		family = AF_INET;
 		addrsize = 4;
 	} else if (version == 6) {
-		nhdr.ndm_family = AF_INET6;
+		family = AF_INET6;
 		addrsize = 16;
 	} else {
 		return -EINVAL;
@@ -12363,28 +12225,41 @@
 		return -1;
 	}
 
-	msg = nlmsg_alloc_simple(RTM_DELNEIGH, NLM_F_CREATE);
-	if (!msg)
+	rn = rtnl_neigh_alloc();
+	if (rn == NULL)
 		return -ENOMEM;
 
-	res = -ENOMEM;
-	if (nlmsg_append(msg, &nhdr, sizeof(nhdr), NLMSG_ALIGNTO) < 0 ||
-	    nla_put(msg, NDA_DST, addrsize, (void *) ipaddr))
+	/* set the destination ip address for neigh */
+	nl_ipaddr = nl_addr_build(family, (void *) ipaddr, addrsize);
+	if (nl_ipaddr == NULL) {
+		wpa_printf(MSG_DEBUG, "nl80211: nl_ipaddr build failed");
+		res = -ENOMEM;
 		goto errout;
-
-	res = nl_send_auto_complete(drv->rtnl_sk, msg);
-	if (res < 0)
+	}
+	res = rtnl_neigh_set_dst(rn, nl_ipaddr);
+	if (res) {
+		wpa_printf(MSG_DEBUG,
+			   "nl80211: neigh set destination addr failed");
 		goto errout;
+	}
 
-	res = nl_wait_for_ack(drv->rtnl_sk);
+	rtnl_neigh_set_ifindex(rn, bss->br_ifindex);
+
+	res = rtnl_neigh_delete(drv->rtnl_sk, rn, 0);
 	if (res) {
 		wpa_printf(MSG_DEBUG,
 			   "nl80211: Deleting bridge ip neigh failed: %s",
 			   nl_geterror(res));
 	}
 errout:
-	nlmsg_free(msg);
+	if (nl_ipaddr)
+		nl_addr_put(nl_ipaddr);
+	if (rn)
+		rtnl_neigh_put(rn);
 	return res;
+#else /* CONFIG_LIBNL3_ROUTE */
+	return -1;
+#endif /* CONFIG_LIBNL3_ROUTE */
 }
 
 
@@ -12614,22 +12489,19 @@
 	    add_acs_ch_list(msg, params->freq_list) ||
 	    add_acs_freq_list(msg, params->freq_list) ||
 	    (params->edmg_enabled &&
-	     nla_put_flag(msg, QCA_WLAN_VENDOR_ATTR_ACS_EDMG_ENABLED)) ||
-	    (params->link_id != NL80211_DRV_LINK_ID_NA &&
-	     nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_ACS_LINK_ID,
-			params->link_id))) {
+	     nla_put_flag(msg, QCA_WLAN_VENDOR_ATTR_ACS_EDMG_ENABLED))) {
 		nlmsg_free(msg);
 		return -ENOBUFS;
 	}
 	nla_nest_end(msg, data);
 
 	wpa_printf(MSG_DEBUG,
-		   "nl80211: ACS Params: HW_MODE: %d HT: %d HT40: %d VHT: %d EHT: %d BW: %d EDMG: %d, link_id: %d",
+		   "nl80211: ACS Params: HW_MODE: %d HT: %d HT40: %d VHT: %d EHT: %d BW: %d EDMG: %d",
 		   params->hw_mode, params->ht_enabled, params->ht40_enabled,
 		   params->vht_enabled, params->eht_enabled, params->ch_width,
-		   params->edmg_enabled, params->link_id);
+		   params->edmg_enabled);
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	if (ret) {
 		wpa_printf(MSG_DEBUG,
 			   "nl80211: Failed to invoke driver ACS function: %s",
@@ -12687,7 +12559,7 @@
 	}
 	nla_nest_end(msg, data);
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	if (ret) {
 		wpa_printf(MSG_DEBUG,
 			   "nl80211: Driver setband function failed: %s",
@@ -12889,10 +12761,11 @@
 
 	if (freq_list)
 		os_memset(freq_list, 0, *num * sizeof(struct weighted_pcl));
-	ret = send_and_recv_resp(drv, msg, preferred_freq_info_handler, &param);
+	ret = send_and_recv_msgs(drv, msg, preferred_freq_info_handler, &param,
+				 NULL, NULL);
 	if (ret) {
 		wpa_printf(MSG_ERROR,
-			   "%s: err in send_and_recv_resp", __func__);
+			   "%s: err in send_and_recv_msgs", __func__);
 		return ret;
 	}
 
@@ -12943,10 +12816,10 @@
 	}
 	nla_nest_end(msg, params);
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	msg = NULL;
 	if (ret) {
-		wpa_printf(MSG_ERROR, "%s: err in send_and_recv_cmd",
+		wpa_printf(MSG_ERROR, "%s: err in send_and_recv_msgs",
 			   __func__);
 		return ret;
 	}
@@ -12999,7 +12872,7 @@
 		goto fail;
 
 	nla_nest_end(msg, container);
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	msg = NULL;
 	if (ret) {
 		wpa_printf(MSG_DEBUG,
@@ -13034,7 +12907,7 @@
 		return -1;
 	}
 
-	return send_and_recv_cmd(drv, msg);
+	return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 }
 
 
@@ -13073,7 +12946,7 @@
 
 	nla_nest_end(msg, params);
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	msg = NULL;
 	if (ret) {
 		wpa_printf(MSG_ERROR,
@@ -13264,9 +13137,9 @@
 	nla_nest_end(msg, attr1);
 	nla_nest_end(msg, attr);
 
-	ret = send_and_recv_resp(drv, msg,
+	ret = send_and_recv_msgs(drv, msg,
 				 nl80211_get_bss_transition_status_handler,
-				 info);
+				 info, NULL, NULL);
 	msg = NULL;
 	if (ret) {
 		wpa_printf(MSG_ERROR,
@@ -13319,7 +13192,7 @@
 
 	nla_nest_end(msg, attr);
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	msg = NULL;
 	if (ret) {
 		wpa_printf(MSG_ERROR,
@@ -13390,7 +13263,7 @@
 	nla_nest_end(msg, nlpeers);
 	nla_nest_end(msg, attr);
 
-	return send_and_recv_cmd(drv, msg);
+	return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 
 fail:
 	nlmsg_free(msg);
@@ -13486,7 +13359,7 @@
 	}
 	nla_nest_end(msg, attr);
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	if (ret)
 		wpa_printf(MSG_DEBUG,
 			   "nl80211: Set secure ranging context failed: ret=%d (%s)",
@@ -13501,60 +13374,6 @@
 
 #endif /* CONFIG_DRIVER_NL80211_QCA */
 
-
-#if defined(CONFIG_DRIVER_NL80211_BRCM) || defined(CONFIG_DRIVER_NL80211_SYNA)
-static int wpa_driver_do_broadcom_acs(struct wpa_driver_nl80211_data *drv,
-				      struct drv_acs_params *params)
-{
-	struct nl_msg *msg;
-	struct nlattr *data;
-	int freq_list_len;
-	int ret = -1;
-
-	freq_list_len = int_array_len(params->freq_list);
-	wpa_printf(MSG_DEBUG, "%s: freq_list_len=%d",
-		   __func__, freq_list_len);
-
-	msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR);
-	if (!msg ||
-	    nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_BRCM) ||
-	    nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
-			BRCM_VENDOR_SCMD_ACS) ||
-	    !(data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
-	    nla_put_u8(msg, BRCM_VENDOR_ATTR_ACS_HW_MODE, params->hw_mode) ||
-	    nla_put_u8(msg, BRCM_VENDOR_ATTR_ACS_HT_ENABLED,
-		       params->ht_enabled) ||
-	    nla_put_u8(msg, BRCM_VENDOR_ATTR_ACS_HT40_ENABLED,
-		       params->ht40_enabled) ||
-	    nla_put_u8(msg, BRCM_VENDOR_ATTR_ACS_VHT_ENABLED,
-		       params->vht_enabled) ||
-	    nla_put_u16(msg, BRCM_VENDOR_ATTR_ACS_CHWIDTH, params->ch_width) ||
-	    (freq_list_len > 0 &&
-	     nla_put(msg, BRCM_VENDOR_ATTR_ACS_FREQ_LIST,
-		     sizeof(int) * freq_list_len, params->freq_list)))
-		goto fail;
-	nla_nest_end(msg, data);
-
-	wpa_printf(MSG_DEBUG,
-		   "nl80211: ACS Params: HW_MODE: %d HT: %d HT40: %d VHT: %d BW: %d",
-		   params->hw_mode, params->ht_enabled, params->ht40_enabled,
-		   params->vht_enabled, params->ch_width);
-
-	ret = send_and_recv_cmd(drv, msg);
-	if (ret) {
-		wpa_printf(MSG_ERROR,
-			   "nl80211: BRCM Failed to invoke driver ACS function: %s",
-			   strerror(errno));
-	}
-
-	msg = NULL;
-fail:
-	nlmsg_free(msg);
-	return ret;
-}
-#endif /* CONFIG_DRIVER_NL80211_BRCM || CONFIG_DRIVER_NL80211_SYNA */
-
-
 static int nl80211_do_acs(void *priv, struct drv_acs_params *params)
 {
 #if defined(CONFIG_DRIVER_NL80211_QCA) || defined(CONFIG_DRIVER_NL80211_BRCM) \
@@ -13810,7 +13629,7 @@
 	    nl80211_put_fils_connect_params(drv, params, msg))
 		goto fail;
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	msg = NULL;
 	if (ret)
 		wpa_dbg(drv->ctx, MSG_DEBUG,
@@ -13853,7 +13672,7 @@
 	    (params->bssid &&
 	     nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, params->bssid)))
 		goto fail;
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	msg = NULL;
 	if (ret) {
 		wpa_printf(MSG_DEBUG,
@@ -13893,7 +13712,7 @@
 		bss->added_if_into_bridge = 0;
 	}
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	msg = NULL;
 	if (ret && val && nl80211_get_4addr(bss) == 1) {
 		wpa_printf(MSG_DEBUG,
@@ -13957,7 +13776,7 @@
 	nla_nest_end(msg, params);
 	wpa_printf(MSG_DEBUG, "nl80211: Transition Disable Policy %d\n", td_policy);
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, (void *) -1, NULL, NULL);
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "nl80211: Transition Disable setting failed: ret=%d (%s)",
 		ret, strerror(-ret));
@@ -13967,12 +13786,12 @@
 }
 #endif /* CONFIG_DRIVER_NL80211_BRCM || CONFIG_DRIVER_NL80211_SYNA */
 
-static int nl80211_link_add(void *priv, u8 link_id, const u8 *addr,
-			    void *bss_ctx)
+static int nl80211_link_add(void *priv, u8 link_id, const u8 *addr)
 {
 	struct i802_bss *bss = priv;
 	struct wpa_driver_nl80211_data *drv = bss->drv;
 	struct nl_msg *msg;
+	unsigned int idx, i;
 	int ret;
 
 	wpa_printf(MSG_DEBUG, "nl80211: MLD: add link_id=%u, addr=" MACSTR,
@@ -13985,24 +13804,32 @@
 		return -EINVAL;
 	}
 
-	if (link_id >= MAX_NUM_MLD_LINKS) {
-		wpa_printf(MSG_DEBUG,
-			   "nl80211: invalid link_id=%u", link_id);
+	if (bss->n_links >= MAX_NUM_MLD_LINKS) {
+		wpa_printf(MSG_DEBUG, "nl80211: MLD: already have n_links=%zu",
+			   bss->n_links);
 		return -EINVAL;
 	}
 
-	if (bss->valid_links & BIT(link_id)) {
-		wpa_printf(MSG_DEBUG,
-			   "nl80211: MLD: Link %u already set", link_id);
-		return -EINVAL;
+	for (i = 0; i < bss->n_links; i++) {
+		if (bss->links[i].link_id == link_id &&
+		    bss->links[i].beacon_set) {
+			wpa_printf(MSG_DEBUG,
+				   "nl80211: MLD: link already set");
+			return -EINVAL;
+		}
 	}
 
-	if (!bss->valid_links) {
-		/* Becoming MLD, verify we were not beaconing */
+	/* try using the first link entry, assuming it is not beaconing yet */
+	if (bss->n_links == 1 &&
+	    bss->flink->link_id == NL80211_DRV_LINK_ID_NA) {
 		if (bss->flink->beacon_set) {
 			wpa_printf(MSG_DEBUG, "nl80211: BSS already beaconing");
 			return -EINVAL;
 		}
+
+		idx = 0;
+	} else {
+		idx = bss->n_links;
 	}
 
 	msg = nl80211_drv_msg(drv, 0, NL80211_CMD_ADD_LINK);
@@ -14013,58 +13840,23 @@
 		return -ENOBUFS;
 	}
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "nl80211: add link failed. ret=%d (%s)",
 			   ret, strerror(-ret));
 		return ret;
 	}
 
-	os_memcpy(bss->links[link_id].addr, addr, ETH_ALEN);
+	bss->links[idx].link_id = link_id;
+	os_memcpy(bss->links[idx].addr, addr, ETH_ALEN);
 
-	/* The new link is the first one, make it the default */
-	if (!bss->valid_links)
-		bss->flink = &bss->links[link_id];
+	bss->n_links = idx + 1;
 
-	bss->valid_links |= BIT(link_id);
-	bss->links[link_id].ctx = bss_ctx;
-
-	wpa_printf(MSG_DEBUG, "nl80211: MLD: valid_links=0x%04x",
-		   bss->valid_links);
+	wpa_printf(MSG_DEBUG, "nl80211: MLD: n_links=%zu", bss->n_links);
 	return 0;
 }
 
 
-#ifdef CONFIG_IEEE80211BE
-static int wpa_driver_nl80211_link_sta_remove(void *priv, u8 link_id,
-					      const u8 *addr)
-{
-	struct i802_bss *bss = priv;
-	struct wpa_driver_nl80211_data *drv = bss->drv;
-	struct nl_msg *msg;
-	int ret;
-
-	if (!(bss->valid_links & BIT(link_id)))
-		return -ENOLINK;
-
-	if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_REMOVE_LINK_STA)) ||
-	    nla_put(msg, NL80211_ATTR_MLD_ADDR, ETH_ALEN, addr) ||
-	    nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id)) {
-		nlmsg_free(msg);
-		return -ENOBUFS;
-	}
-
-	ret = send_and_recv_cmd(drv, msg);
-	wpa_printf(MSG_DEBUG,
-		   "nl80211: link_sta_remove -> REMOVE_LINK_STA on link_id %u from MLD STA "
-		   MACSTR ", from %s --> %d (%s)",
-		   link_id, MAC2STR(addr), bss->ifname, ret, strerror(-ret));
-
-	return ret;
-}
-#endif /* CONFIG_IEEE80211BE */
-
-
 #ifdef CONFIG_TESTING_OPTIONS
 
 static int testing_nl80211_register_frame(void *priv, u16 type,
@@ -14119,7 +13911,7 @@
 	.scan2 = driver_nl80211_scan2,
 	.sched_scan = wpa_driver_nl80211_sched_scan,
 	.stop_sched_scan = wpa_driver_nl80211_stop_sched_scan,
-	.get_scan_results = wpa_driver_nl80211_get_scan_results,
+	.get_scan_results2 = wpa_driver_nl80211_get_scan_results,
 	.abort_scan = wpa_driver_nl80211_abort_scan,
 	.deauthenticate = driver_nl80211_deauthenticate,
 	.authenticate = driver_nl80211_authenticate,
@@ -14259,11 +14051,6 @@
 #endif /* CONFIG_DPP */
 	.get_sta_mlo_info = nl80211_get_sta_mlo_info,
 	.link_add = nl80211_link_add,
-#ifdef CONFIG_IEEE80211BE
-	.link_remove = driver_nl80211_link_remove,
-	.is_drv_shared = nl80211_is_drv_shared,
-	.link_sta_remove = wpa_driver_nl80211_link_sta_remove,
-#endif /* CONFIG_IEEE80211BE */
 #ifdef CONFIG_TESTING_OPTIONS
 	.register_frame = testing_nl80211_register_frame,
 	.radio_disable = testing_nl80211_radio_disable,
diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
index d2c1ffa..d922912 100644
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -32,7 +32,6 @@
 	struct nl_cb *nl_cb;
 	struct nl_sock *nl;
 	int nl80211_id;
-	unsigned int nl80211_maxattr;
 	int nlctrl_id;
 	int ioctl_sock; /* socket for ioctl() use */
 	struct nl_sock *nl_event;
@@ -55,6 +54,7 @@
 struct i802_link {
 	unsigned int beacon_set:1;
 
+	s8 link_id;
 	int freq;
 	int bandwidth;
 	u8 addr[ETH_ALEN];
@@ -65,7 +65,7 @@
 	struct wpa_driver_nl80211_data *drv;
 	struct i802_bss *next;
 
-	u16 valid_links;
+	size_t n_links;
 	struct i802_link links[MAX_NUM_MLD_LINKS];
 	struct i802_link *flink;
 
@@ -81,6 +81,7 @@
 	unsigned int wdev_id_set:1;
 	unsigned int added_if:1;
 	unsigned int static_ap:1;
+	unsigned int use_nl_connect:1;
 
 	u8 addr[ETH_ALEN];
 	u8 prev_addr[ETH_ALEN];
@@ -164,6 +165,8 @@
 	unsigned int scan_for_auth:1;
 	unsigned int retry_auth:1;
 	unsigned int use_monitor:1;
+	unsigned int ignore_next_local_disconnect:1;
+	unsigned int ignore_next_local_deauth:1;
 	unsigned int hostapd:1;
 	unsigned int start_mode_sta:1;
 	unsigned int start_iface_up:1;
@@ -196,14 +199,10 @@
 	unsigned int qca_do_acs:1;
 	unsigned int brcm_do_acs:1;
 	unsigned int uses_6ghz:1;
-	unsigned int uses_s1g:1;
 	unsigned int secure_ranging_ctx_vendor_cmd_avail:1;
 	unsigned int puncturing:1;
 	unsigned int qca_ap_allowed_freqs:1;
 
-	u32 ignore_next_local_disconnect;
-	u32 ignore_next_local_deauth;
-
 	u64 vendor_scan_cookie;
 	u64 remain_on_chan_cookie;
 	u64 send_frame_cookie;
@@ -272,58 +271,18 @@
 
 struct nl_msg;
 
-struct nl80211_err_info {
-	int link_id;
-};
-
 void * nl80211_cmd(struct wpa_driver_nl80211_data *drv,
 		   struct nl_msg *msg, int flags, uint8_t cmd);
 struct nl_msg * nl80211_cmd_msg(struct i802_bss *bss, int flags, uint8_t cmd);
 struct nl_msg * nl80211_drv_msg(struct wpa_driver_nl80211_data *drv, int flags,
 				uint8_t cmd);
 struct nl_msg * nl80211_bss_msg(struct i802_bss *bss, int flags, uint8_t cmd);
-
-int send_and_recv(struct nl80211_global *global,
-		  struct nl_sock *nl_handle, struct nl_msg *msg,
-		  int (*valid_handler)(struct nl_msg *, void *),
-		  void *valid_data,
-		  int (*ack_handler_custom)(struct nl_msg *, void *),
-		  void *ack_data,
-		  struct nl80211_err_info *err_info);
-
-// This function is not used in supplicant anymore. But keeping this wrapper
-// functions for libraries outside wpa_supplicant to build (For eg: lib_driver_cmd_XX)
-static inline int
-send_and_recv_msgs(struct wpa_driver_nl80211_data *drv,
-		   struct nl_msg *msg,
-		   int (*valid_handler)(struct nl_msg *, void *),
-		   void *valid_data,
-		   int (*ack_handler_custom)(struct nl_msg *, void *),
-		   void *ack_data)
-{
-	return send_and_recv(drv->global, drv->global->nl, msg,
-			     valid_handler, valid_data,
-			     ack_handler_custom, ack_data, NULL);
-}
-
-static inline int
-send_and_recv_cmd(struct wpa_driver_nl80211_data *drv,
-		  struct nl_msg *msg)
-{
-	return send_and_recv(drv->global, drv->global->nl, msg,
-			     NULL, NULL, NULL, NULL, NULL);
-}
-
-static inline int
-send_and_recv_resp(struct wpa_driver_nl80211_data *drv,
-		   struct nl_msg *msg,
-		   int (*valid_handler)(struct nl_msg *, void *),
-		   void *valid_data)
-{
-	return send_and_recv(drv->global, drv->global->nl, msg,
-			     valid_handler, valid_data, NULL, NULL, NULL);
-}
-
+int send_and_recv_msgs(struct wpa_driver_nl80211_data *drv, struct nl_msg *msg,
+		       int (*valid_handler)(struct nl_msg *, void *),
+		       void *valid_data,
+		       int (*ack_handler_custom)(struct nl_msg *, void *),
+		       void *ack_data);
+struct nl_sock * get_connect_handle(struct i802_bss *bss);
 int nl80211_create_iface(struct wpa_driver_nl80211_data *drv,
 			 const char *ifname, enum nl80211_iftype iftype,
 			 const u8 *addr, int wds,
@@ -371,24 +330,6 @@
 void nl80211_restore_ap_mode(struct i802_bss *bss);
 struct i802_link * nl80211_get_link(struct i802_bss *bss, s8 link_id);
 
-static inline bool nl80211_link_valid(u16 links, s8 link_id)
-{
-	if (link_id < 0 || link_id >= MAX_NUM_MLD_LINKS)
-		return false;
-
-	if (links & BIT(link_id))
-		return true;
-
-	return false;
-}
-
-
-static inline bool
-nl80211_attr_supported(struct wpa_driver_nl80211_data *drv, unsigned int attr)
-{
-	return attr <= drv->global->nl80211_maxattr;
-}
-
 #ifdef ANDROID
 int android_nl_socket_set_nonblocking(struct nl_sock *handle);
 int android_pno_start(struct i802_bss *bss,
@@ -420,8 +361,7 @@
 int wpa_driver_nl80211_sched_scan(void *priv,
 				  struct wpa_driver_scan_params *params);
 int wpa_driver_nl80211_stop_sched_scan(void *priv);
-struct wpa_scan_results * wpa_driver_nl80211_get_scan_results(void *priv,
-							      const u8 *bssid);
+struct wpa_scan_results * wpa_driver_nl80211_get_scan_results(void *priv);
 void nl80211_dump_scan(struct wpa_driver_nl80211_data *drv);
 int wpa_driver_nl80211_abort_scan(void *priv, u64 scan_cookie);
 int wpa_driver_nl80211_vendor_scan(struct i802_bss *bss,
diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
index d8375cc..11a32af 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -49,7 +49,8 @@
 		return 0;
 	}
 
-	if (send_and_recv_resp(drv, msg, protocol_feature_handler, &feat) == 0)
+	if (send_and_recv_msgs(drv, msg, protocol_feature_handler, &feat,
+			       NULL, NULL) == 0)
 		return feat;
 
 	return 0;
@@ -888,10 +889,6 @@
 				nla_get_u16(tb1[NL80211_ATTR_MLD_CAPA_AND_OPS]);
 		}
 
-		wpa_printf(MSG_DEBUG,
-			   "nl80211: EML Capability: 0x%x MLD Capability: 0x%x",
-			   capa->eml_capa, capa->mld_capa_and_ops);
-
 		drv->num_iface_capa++;
 		if (drv->num_iface_capa == NL80211_IFTYPE_MAX)
 			break;
@@ -1210,7 +1207,7 @@
 		return -1;
 	}
 
-	if (send_and_recv_resp(drv, msg, wiphy_info_handler, info))
+	if (send_and_recv_msgs(drv, msg, wiphy_info_handler, info, NULL, NULL))
 		return -1;
 
 	if (info->auth_supported)
@@ -1323,7 +1320,8 @@
 		return;
 	}
 
-	ret = send_and_recv_resp(drv, msg, dfs_info_handler, &dfs_capability);
+	ret = send_and_recv_msgs(drv, msg, dfs_info_handler, &dfs_capability,
+				 NULL, NULL);
 	if (!ret && dfs_capability)
 		drv->capa.flags |= WPA_DRIVER_FLAGS_DFS_OFFLOAD;
 }
@@ -1410,7 +1408,8 @@
 
 	os_memset(&info, 0, sizeof(info));
 	info.capa = &drv->capa;
-	ret = send_and_recv_resp(drv, msg, features_info_handler, &info);
+	ret = send_and_recv_msgs(drv, msg, features_info_handler, &info,
+				 NULL, NULL);
 	if (ret || !info.flags)
 		return;
 
@@ -2169,9 +2168,6 @@
 	for (m = 0; m < *num_modes; m++) {
 		if (!modes[m].num_channels)
 			continue;
-
-		modes[m].is_6ghz = false;
-
 		if (modes[m].channels[0].freq < 2000) {
 			modes[m].num_channels = 0;
 			continue;
@@ -2183,14 +2179,10 @@
 					break;
 				}
 			}
-		} else if (modes[m].channels[0].freq > 50000) {
+		} else if (modes[m].channels[0].freq > 50000)
 			modes[m].mode = HOSTAPD_MODE_IEEE80211AD;
-		} else if (is_6ghz_freq(modes[m].channels[0].freq)) {
+		else
 			modes[m].mode = HOSTAPD_MODE_IEEE80211A;
-			modes[m].is_6ghz = true;
-		} else {
-			modes[m].mode = HOSTAPD_MODE_IEEE80211A;
-		}
 	}
 
 	/* Remove unsupported bands */
@@ -2418,57 +2410,6 @@
 }
 
 
-static void nl80211_set_6ghz_mode(struct hostapd_hw_modes *mode, int start,
-				  int end, int max_bw)
-{
-	int c;
-
-	for (c = 0; c < mode->num_channels; c++) {
-		struct hostapd_channel_data *chan = &mode->channels[c];
-
-		if (chan->freq - 10 < start || chan->freq + 10 > end)
-			continue;
-
-		if (max_bw >= 80)
-			chan->flag |= HOSTAPD_CHAN_VHT_80MHZ_SUBCHANNEL;
-
-		if (max_bw >= 160)
-			chan->flag |= HOSTAPD_CHAN_VHT_160MHZ_SUBCHANNEL;
-
-		if (max_bw >= 320)
-			chan->flag |= HOSTAPD_CHAN_EHT_320MHZ_SUBCHANNEL;
-	}
-}
-
-
-static void nl80211_reg_rule_6ghz(struct nlattr *tb[],
-				 struct phy_info_arg *results)
-{
-	u32 start, end, max_bw;
-	u16 m;
-
-	if (!tb[NL80211_ATTR_FREQ_RANGE_START] ||
-	    !tb[NL80211_ATTR_FREQ_RANGE_END] ||
-	    !tb[NL80211_ATTR_FREQ_RANGE_MAX_BW])
-		return;
-
-	start = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]) / 1000;
-	end = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]) / 1000;
-	max_bw = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000;
-
-	if (max_bw < 80)
-		return;
-
-	for (m = 0; m < *results->num_modes; m++) {
-		if (results->modes[m].num_channels == 0 ||
-		    !is_6ghz_freq(results->modes[m].channels[0].freq))
-			continue;
-
-		nl80211_set_6ghz_mode(&results->modes[m], start, end, max_bw);
-	}
-}
-
-
 static void nl80211_set_dfs_domain(enum nl80211_dfs_regions region,
 				   u8 *dfs_domain)
 {
@@ -2587,13 +2528,6 @@
 		nl80211_reg_rule_vht(tb_rule, results);
 	}
 
-	nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule)
-	{
-		nla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX,
-			  nla_data(nl_rule), nla_len(nl_rule), reg_policy);
-		nl80211_reg_rule_6ghz(tb_rule, results);
-	}
-
 	return NL_SKIP;
 }
 
@@ -2615,7 +2549,8 @@
 		}
 	}
 
-	return send_and_recv_resp(drv, msg, nl80211_get_reg, results);
+	return send_and_recv_msgs(drv, msg, nl80211_get_reg, results,
+				  NULL, NULL);
 }
 
 
@@ -2657,8 +2592,6 @@
 
 			if (is_6ghz_freq(chan->freq))
 				drv->uses_6ghz = true;
-			if (chan->freq >= 900 && chan->freq < 1000)
-				drv->uses_s1g = true;
 			res = os_snprintf(pos, end - pos, " %d%s%s%s",
 					  chan->freq,
 					  (chan->flag & HOSTAPD_CHAN_DISABLED) ?
@@ -2709,7 +2642,8 @@
 		return NULL;
 	}
 
-	if (send_and_recv_resp(drv, msg, phy_info_handler, &result) == 0) {
+	if (send_and_recv_msgs(drv, msg, phy_info_handler, &result,
+			       NULL, NULL) == 0) {
 		struct hostapd_hw_modes *modes;
 
 		nl80211_set_regulatory_flags(drv, &result);
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
index 9ce73c6..fdaf07b 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -385,9 +385,9 @@
 		return 0;
 	}
 
-	ret = send_and_recv_resp(drv, msg,
+	ret = send_and_recv_msgs(drv, msg,
 				 qca_drv_connect_fail_reason_code_handler,
-				 &reason_code);
+				 &reason_code, NULL, NULL);
 	if (ret)
 		wpa_printf(MSG_DEBUG,
 			   "nl80211: Get connect fail reason_code failed: ret=%d (%s)",
@@ -442,7 +442,7 @@
 	wpa_printf(MSG_DEBUG, "nl80211: AP MLD address " MACSTR
 		   " received in link reconfig event", MAC2STR(ap_mld));
 	if (!drv->sta_mlo_info.valid_links ||
-	    !ether_addr_equal(drv->sta_mlo_info.ap_mld_addr, ap_mld)) {
+	    os_memcmp(drv->sta_mlo_info.ap_mld_addr, ap_mld, ETH_ALEN) != 0) {
 		if (drv->pending_link_reconfig_data == data) {
 			wpa_printf(MSG_DEBUG,
 				   "nl80211: Drop pending link reconfig event since AP MLD not matched even after new connect/roam event");
@@ -476,7 +476,10 @@
 	 * links when the link used for (re)association is removed.
 	 */
 	if (removed_links & BIT(drv->sta_mlo_info.assoc_link_id)) {
-		for_each_link(drv->sta_mlo_info.valid_links, i) {
+		for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+			if (!(drv->sta_mlo_info.valid_links & BIT(i)))
+				continue;
+
 			os_memcpy(drv->bssid, drv->sta_mlo_info.links[i].bssid,
 				  ETH_ALEN);
 			drv->sta_mlo_info.assoc_link_id = i;
@@ -656,8 +659,7 @@
 		return -1;
 	}
 
-	mle = ieee802_11_defrag(req_elems.basic_mle, req_elems.basic_mle_len,
-				true);
+	mle = ieee802_11_defrag_mle(&req_elems, MULTI_LINK_CONTROL_TYPE_BASIC);
 	if (!mle) {
 		wpa_printf(MSG_INFO,
 			   "nl80211: MLO: Basic Multi-Link element not found in Association Request");
@@ -668,8 +670,7 @@
 					 &req_info);
 	wpabuf_free(mle);
 
-	mle = ieee802_11_defrag(resp_elems.basic_mle, resp_elems.basic_mle_len,
-				true);
+	mle = ieee802_11_defrag_mle(&resp_elems, MULTI_LINK_CONTROL_TYPE_BASIC);
 	if (!mle) {
 		wpa_printf(MSG_ERROR,
 			   "nl80211: MLO: Basic Multi-Link element not found in Association Response");
@@ -698,7 +699,10 @@
 	}
 
 	/* Get MLO links info for rejected links */
-	for_each_link((mlo->req_links & ~mlo->valid_links), i) {
+	for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+		if (!((mlo->req_links & ~mlo->valid_links) & BIT(i)))
+			continue;
+
 		os_memcpy(mlo->links[i].bssid, resp_info.addr[i], ETH_ALEN);
 		os_memcpy(mlo->links[i].addr, req_info.addr[i], ETH_ALEN);
 	}
@@ -805,7 +809,7 @@
 	wpa_printf(MSG_DEBUG, "nl80211: AP MLD address " MACSTR
 		   " received in TID to link mapping event", MAC2STR(ap_mld));
 	if (!drv->sta_mlo_info.valid_links ||
-	    !ether_addr_equal(drv->sta_mlo_info.ap_mld_addr, ap_mld)) {
+	    os_memcmp(drv->sta_mlo_info.ap_mld_addr, ap_mld, ETH_ALEN) != 0) {
 		if (drv->pending_t2lm_data == data) {
 			wpa_printf(MSG_DEBUG,
 				   "nl80211: Drop pending TID-to-link mapping event since AP MLD not matched even after new connect/roam event");
@@ -868,7 +872,9 @@
 		wpa_printf(MSG_DEBUG,
 			   "nl80211: TID-to-link: Received uplink %x downlink %x",
 			   uplink, downlink);
-		for_each_link(drv->sta_mlo_info.valid_links, i) {
+		for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+			if (!(drv->sta_mlo_info.valid_links & BIT(i)))
+				continue;
 			if (uplink & BIT(i))
 				event.t2l_map_info.t2lmap[i].uplink |=
 					BIT(tidnum);
@@ -951,8 +957,9 @@
 		if (drv->ignore_next_local_disconnect) {
 			drv->ignore_next_local_disconnect = 0;
 			if (!event.assoc_reject.bssid ||
-			    !ether_addr_equal(event.assoc_reject.bssid,
-					      drv->auth_attempt_bssid)) {
+			    (os_memcmp(event.assoc_reject.bssid,
+				       drv->auth_attempt_bssid,
+				       ETH_ALEN) != 0)) {
 				/*
 				 * Ignore the event that came without a BSSID or
 				 * for the old connection since this is likely
@@ -1260,28 +1267,15 @@
 	if (cf2)
 		data.ch_switch.cf2 = nla_get_u32(cf2);
 
-	if (link)
-		data.ch_switch.link_id = nla_get_u8(link);
-	else
-		data.ch_switch.link_id = NL80211_DRV_LINK_ID_NA;
-
-	if (finished) {
-		if (data.ch_switch.link_id != NL80211_DRV_LINK_ID_NA) {
-			struct i802_link *mld_link;
-
-			mld_link = nl80211_get_link(bss,
-						    data.ch_switch.link_id);
-			mld_link->freq = data.ch_switch.freq;
-		} else {
-			bss->flink->freq = data.ch_switch.freq;
-		}
-	}
+	if (finished)
+		bss->flink->freq = data.ch_switch.freq;
 
 	if (link && is_sta_interface(drv->nlmode)) {
-		u8 link_id = data.ch_switch.link_id;
+		u8 link_id = nla_get_u8(link);
 
 		if (link_id < MAX_NUM_MLD_LINKS &&
 		    drv->sta_mlo_info.valid_links & BIT(link_id)) {
+			data.ch_switch.link_id = link_id;
 			drv->sta_mlo_info.links[link_id].freq =
 				data.ch_switch.freq;
 			wpa_supplicant_event(
@@ -1457,9 +1451,9 @@
 
 		if ((drv->capa.flags & WPA_DRIVER_FLAGS_SME) &&
 		    !drv->associated &&
-		    !ether_addr_equal(bssid, drv->auth_bssid) &&
-		    !ether_addr_equal(bssid, drv->auth_attempt_bssid) &&
-		    ether_addr_equal(bssid, drv->prev_bssid)) {
+		    os_memcmp(bssid, drv->auth_bssid, ETH_ALEN) != 0 &&
+		    os_memcmp(bssid, drv->auth_attempt_bssid, ETH_ALEN) != 0 &&
+		    os_memcmp(bssid, drv->prev_bssid, ETH_ALEN) == 0) {
 			/*
 			 * Avoid issues with some roaming cases where
 			 * disconnection event for the old AP may show up after
@@ -1468,10 +1462,11 @@
 			 * ignore_next_local_deauth as well, to avoid next local
 			 * deauth event be wrongly ignored.
 			 */
-			if (ether_addr_equal(mgmt->sa, drv->first_bss->addr) ||
+			if (os_memcmp(mgmt->sa, drv->first_bss->addr,
+				      ETH_ALEN) == 0 ||
 			    (!is_zero_ether_addr(drv->first_bss->prev_addr) &&
-			     ether_addr_equal(mgmt->sa,
-					      drv->first_bss->prev_addr))) {
+			     os_memcmp(mgmt->sa, drv->first_bss->prev_addr,
+				       ETH_ALEN) == 0)) {
 				wpa_printf(MSG_DEBUG,
 					   "nl80211: Received a locally generated deauth event. Clear ignore_next_local_deauth flag");
 				drv->ignore_next_local_deauth = 0;
@@ -1486,8 +1481,8 @@
 
 		if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME) &&
 		    drv->connect_reassoc && drv->associated &&
-		    ether_addr_equal(bssid, drv->prev_bssid) &&
-		    !ether_addr_equal(bssid, drv->auth_attempt_bssid)) {
+		    os_memcmp(bssid, drv->prev_bssid, ETH_ALEN) == 0 &&
+		    os_memcmp(bssid, drv->auth_attempt_bssid, ETH_ALEN) != 0) {
 			/*
 			 * Avoid issues with some roaming cases where
 			 * disconnection event for the old AP may show up after
@@ -1503,8 +1498,8 @@
 		}
 
 		if (drv->associated != 0 &&
-		    !ether_addr_equal(bssid, drv->bssid) &&
-		    !ether_addr_equal(bssid, drv->auth_bssid)) {
+		    os_memcmp(bssid, drv->bssid, ETH_ALEN) != 0 &&
+		    os_memcmp(bssid, drv->auth_bssid, ETH_ALEN) != 0) {
 			/*
 			 * We have presumably received this deauth as a
 			 * response to a clear_state_mismatch() outgoing
@@ -1526,7 +1521,7 @@
 
 	if (type == EVENT_DISASSOC) {
 		event.disassoc_info.locally_generated =
-			ether_addr_equal(mgmt->sa, drv->first_bss->addr);
+			!os_memcmp(mgmt->sa, drv->first_bss->addr, ETH_ALEN);
 		event.disassoc_info.addr = bssid;
 		event.disassoc_info.reason_code = reason_code;
 		if (frame + len > mgmt->u.disassoc.variable) {
@@ -1536,7 +1531,7 @@
 		}
 	} else {
 		event.deauth_info.locally_generated =
-			ether_addr_equal(mgmt->sa, drv->first_bss->addr);
+			!os_memcmp(mgmt->sa, drv->first_bss->addr, ETH_ALEN);
 		if (drv->ignore_deauth_event) {
 			wpa_printf(MSG_DEBUG, "nl80211: Ignore deauth event due to previous forced deauth-during-auth");
 			drv->ignore_deauth_event = 0;
@@ -1619,17 +1614,18 @@
 }
 
 
-static s8
-nl80211_get_link_id_by_freq(struct i802_bss *bss, unsigned int freq)
+static struct i802_link *
+nl80211_get_mld_link_by_freq(struct i802_bss *bss, unsigned int freq)
 {
 	unsigned int i;
 
-	for_each_link(bss->valid_links, i) {
-		if ((unsigned int) bss->links[i].freq == freq)
-			return i;
+	for (i = 0; i < bss->n_links; i++) {
+		if ((unsigned int) bss->links[i].freq == freq &&
+		    bss->links[i].link_id != -1)
+			return &bss->links[i];
 	}
 
-	return NL80211_DRV_LINK_ID_NA;
+	return NULL;
 }
 
 
@@ -1663,12 +1659,12 @@
 	/* Determine the MLD link either by an explicitly provided link id or
 	 * finding a match based on the frequency. */
 	if (link)
-		link_id = nla_get_u8(link);
+		mld_link = nl80211_get_link(bss, nla_get_u8(link));
 	else if (freq)
-		link_id = nl80211_get_link_id_by_freq(bss, nla_get_u32(freq));
+		mld_link = nl80211_get_mld_link_by_freq(bss, nla_get_u32(freq));
 
-	if (nl80211_link_valid(bss->valid_links, link_id))
-		mld_link = nl80211_get_link(bss, link_id);
+	if (mld_link)
+		link_id = mld_link->link_id;
 
 	data = nla_data(frame);
 	len = nla_len(frame);
@@ -1705,14 +1701,15 @@
 			   bss->ifname);
 	} else if (cmd != NL80211_CMD_FRAME_TX_STATUS  &&
 		   !(data[4] & 0x01) &&
-		   !ether_addr_equal(bss->addr, data + 4) &&
+		   os_memcmp(bss->addr, data + 4, ETH_ALEN) != 0 &&
 		   (is_zero_ether_addr(bss->rand_addr) ||
-		    !ether_addr_equal(bss->rand_addr, data + 4)) &&
-		   !ether_addr_equal(bss->addr, data + 4 + ETH_ALEN) &&
+		    os_memcmp(bss->rand_addr, data + 4, ETH_ALEN) != 0) &&
+		   os_memcmp(bss->addr, data + 4 + ETH_ALEN, ETH_ALEN) != 0 &&
 		   (is_zero_ether_addr(drv->first_bss->prev_addr) ||
-		    !ether_addr_equal(bss->prev_addr, data + 4 + ETH_ALEN)) &&
+		    os_memcmp(bss->prev_addr, data + 4 + ETH_ALEN,
+			      ETH_ALEN) != 0) &&
 		   (!mld_link ||
-		    !ether_addr_equal(mld_link->addr, data + 4))) {
+		    os_memcmp(mld_link->addr, data + 4, ETH_ALEN) != 0)) {
 		wpa_printf(MSG_MSGDUMP, "nl80211: %s: Ignore MLME frame event "
 			   "for foreign address", bss->ifname);
 		return;
@@ -1920,7 +1917,7 @@
 	os_memset(&data, 0, sizeof(data));
 	addr = nla_data(tb[NL80211_ATTR_MAC]);
 
-	if (!bss->valid_links &&
+	if (bss->links[0].link_id == NL80211_DRV_LINK_ID_NA &&
 	    (tb[NL80211_ATTR_MLO_LINK_ID] ||
 	     tb[NL80211_ATTR_MLD_ADDR])) {
 		wpa_printf(MSG_ERROR,
@@ -2184,7 +2181,7 @@
 		u8 *req_ies = NULL, *resp_ies = NULL;
 		size_t req_ies_len = 0, resp_ies_len = 0;
 
-		if (!bss->valid_links &&
+		if (bss->links[0].link_id == NL80211_DRV_LINK_ID_NA &&
 		    (tb[NL80211_ATTR_MLO_LINK_ID] ||
 		     tb[NL80211_ATTR_MLD_ADDR])) {
 			wpa_printf(MSG_ERROR,
@@ -2457,19 +2454,9 @@
 		return;
 
 	os_memset(&data, 0, sizeof(data));
-	data.dfs_event.link_id = NL80211_DRV_LINK_ID_NA;
 	data.dfs_event.freq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]);
 	event_type = nla_get_u32(tb[NL80211_ATTR_RADAR_EVENT]);
 
-	if (tb[NL80211_ATTR_MLO_LINK_ID]) {
-		data.dfs_event.link_id =
-			nla_get_u8(tb[NL80211_ATTR_MLO_LINK_ID]);
-	} else if (data.dfs_event.freq) {
-		data.dfs_event.link_id =
-			nl80211_get_link_id_by_freq(drv->first_bss,
-						    data.dfs_event.freq);
-	}
-
 	/* Check HT params */
 	if (tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
 		data.dfs_event.ht_enabled = 1;
@@ -2500,12 +2487,10 @@
 	if (tb[NL80211_ATTR_CENTER_FREQ2])
 		data.dfs_event.cf2 = nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ2]);
 
-	wpa_printf(MSG_DEBUG,
-		   "nl80211: DFS event on freq %d MHz, ht: %d, offset: %d, width: %d, cf1: %dMHz, cf2: %dMHz, link_id=%d",
+	wpa_printf(MSG_DEBUG, "nl80211: DFS event on freq %d MHz, ht: %d, offset: %d, width: %d, cf1: %dMHz, cf2: %dMHz",
 		   data.dfs_event.freq, data.dfs_event.ht_enabled,
 		   data.dfs_event.chan_offset, data.dfs_event.chan_width,
-		   data.dfs_event.cf1, data.dfs_event.cf2,
-		   data.dfs_event.link_id);
+		   data.dfs_event.cf1, data.dfs_event.cf2);
 
 	switch (event_type) {
 	case NL80211_RADAR_DETECTED:
@@ -2737,14 +2722,8 @@
 	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_PUNCTURE_BITMAP])
 		event.acs_selected_channels.puncture_bitmap =
 			nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_PUNCTURE_BITMAP]);
-	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_LINK_ID])
-		event.acs_selected_channels.link_id =
-			nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_LINK_ID]);
-	else
-		event.acs_selected_channels.link_id = -1;
-
 	wpa_printf(MSG_INFO,
-		   "nl80211: ACS Results: PFreq: %d SFreq: %d BW: %d VHT0: %d VHT1: %d HW_MODE: %d EDMGCH: %d PUNCBITMAP: 0x%x, LinkId: %d",
+		   "nl80211: ACS Results: PFreq: %d SFreq: %d BW: %d VHT0: %d VHT1: %d HW_MODE: %d EDMGCH: %d PUNCBITMAP: 0x%x",
 		   event.acs_selected_channels.pri_freq,
 		   event.acs_selected_channels.sec_freq,
 		   event.acs_selected_channels.ch_width,
@@ -2752,8 +2731,7 @@
 		   event.acs_selected_channels.vht_seg1_center_ch,
 		   event.acs_selected_channels.hw_mode,
 		   event.acs_selected_channels.edmg_channel,
-		   event.acs_selected_channels.puncture_bitmap,
-		   event.acs_selected_channels.link_id);
+		   event.acs_selected_channels.puncture_bitmap);
 
 	/* Ignore ACS channel list check for backwards compatibility */
 
@@ -2848,19 +2826,9 @@
 
 	os_memset(&data, 0, sizeof(data));
 	data.dfs_event.freq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]);
-	data.dfs_event.link_id = NL80211_DRV_LINK_ID_NA;
 
-	if (tb[NL80211_ATTR_MLO_LINK_ID]) {
-		data.dfs_event.link_id =
-			nla_get_u8(tb[NL80211_ATTR_MLO_LINK_ID]);
-	} else if (data.dfs_event.freq) {
-		data.dfs_event.link_id =
-			nl80211_get_link_id_by_freq(drv->first_bss,
-						    data.dfs_event.freq);
-	}
-
-	wpa_printf(MSG_DEBUG, "nl80211: DFS event on freq %d MHz, link=%d",
-		   data.dfs_event.freq, data.dfs_event.link_id);
+	wpa_printf(MSG_DEBUG, "nl80211: DFS event on freq %d MHz",
+		   data.dfs_event.freq);
 
 	/* Check HT params */
 	if (tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
@@ -2968,7 +2936,6 @@
 	info = &event.scan_info;
 	info->aborted = aborted;
 	info->external_scan = external_scan;
-	info->scan_cookie = nla_get_u64(tb[QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE]);
 
 	if (tb[QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS]) {
 		nla_for_each_nested(nl,
@@ -3419,8 +3386,7 @@
 }
 
 
-static void nl80211_parse_freq_attrs(const char *title, struct nlattr *nl_freq,
-				     struct frequency_attrs *attrs)
+static void nl80211_dump_freq(const char *title, struct nlattr *nl_freq)
 {
 	static struct nla_policy freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {
 		[NL80211_FREQUENCY_ATTR_FREQ] = { .type = NLA_U32 },
@@ -3447,15 +3413,6 @@
 		   tb[NL80211_FREQUENCY_ATTR_DISABLED] ? " disabled" : "",
 		   tb[NL80211_FREQUENCY_ATTR_NO_IR] ? " no-IR" : "",
 		   tb[NL80211_FREQUENCY_ATTR_RADAR] ? " radar" : "");
-
-	attrs->freq = freq;
-	attrs->max_tx_power = max_tx_power;
-	if (tb[NL80211_FREQUENCY_ATTR_DISABLED])
-		attrs->disabled = true;
-	if (tb[NL80211_FREQUENCY_ATTR_NO_IR])
-		attrs->no_ir = true;
-	if (tb[NL80211_FREQUENCY_ATTR_RADAR])
-		attrs->radar = true;
 }
 
 
@@ -3469,13 +3426,9 @@
 	data.channel_list_changed.initiator = REGDOM_BEACON_HINT;
 
 	if (tb[NL80211_ATTR_FREQ_BEFORE])
-		nl80211_parse_freq_attrs(
-			"before", tb[NL80211_ATTR_FREQ_BEFORE],
-			&data.channel_list_changed.beacon_hint_before);
+		nl80211_dump_freq("before", tb[NL80211_ATTR_FREQ_BEFORE]);
 	if (tb[NL80211_ATTR_FREQ_AFTER])
-		nl80211_parse_freq_attrs(
-			"after", tb[NL80211_ATTR_FREQ_AFTER],
-			&data.channel_list_changed.beacon_hint_after);
+		nl80211_dump_freq("after", tb[NL80211_ATTR_FREQ_AFTER]);
 
 	wpa_supplicant_event(drv->ctx, EVENT_CHANNEL_LIST_CHANGED, &data);
 }
@@ -3541,6 +3494,8 @@
 {
 	const u8 *addr;
 	union wpa_event_data event;
+	const u8 *connected_addr = drv->sta_mlo_info.valid_links ?
+				drv->sta_mlo_info.ap_mld_addr : drv->bssid;
 
 	os_memset(&event, 0, sizeof(event));
 
@@ -3557,19 +3512,13 @@
 		wpa_printf(MSG_DEBUG,
 			   "nl80211: Port authorized for STA addr "  MACSTR,
 			MAC2STR(addr));
-	} else if (is_sta_interface(drv->nlmode)) {
-		const u8 *connected_addr;
-
-		connected_addr = drv->sta_mlo_info.valid_links ?
-			drv->sta_mlo_info.ap_mld_addr : drv->bssid;
-		if (!ether_addr_equal(addr, connected_addr)) {
-			wpa_printf(MSG_DEBUG,
-				   "nl80211: Ignore port authorized event for "
-				   MACSTR " (not the currently connected BSSID "
-				   MACSTR ")",
-				   MAC2STR(addr), MAC2STR(connected_addr));
-			return;
-		}
+	} else if (is_sta_interface(drv->nlmode) &&
+		   os_memcmp(addr, connected_addr, ETH_ALEN) != 0) {
+		wpa_printf(MSG_DEBUG,
+			   "nl80211: Ignore port authorized event for " MACSTR
+			   " (not the currently connected BSSID " MACSTR ")",
+			   MAC2STR(addr), MAC2STR(connected_addr));
+		return;
 	}
 
 	if (tb[NL80211_ATTR_TD_BITMAP]) {
@@ -3751,11 +3700,8 @@
 		   (long long unsigned int) cookie,
 		   match ? " (match)" : "",
 		   drv->send_frame_cookie == cookie ? " (match-saved)" : "");
-	if (drv->send_frame_cookie == cookie) {
+	if (drv->send_frame_cookie == cookie)
 		drv->send_frame_cookie = (u64) -1;
-		if (!match)
-			goto send_event;
-	}
 	if (!match)
 		return;
 
@@ -3765,7 +3711,6 @@
 			   (drv->num_send_frame_cookies - i - 1) * sizeof(u64));
 	drv->num_send_frame_cookies--;
 
-send_event:
 	wpa_supplicant_event(drv->ctx, EVENT_TX_WAIT_EXPIRE, NULL);
 }
 
@@ -3936,7 +3881,6 @@
 	case NL80211_CMD_ASSOCIATE:
 	case NL80211_CMD_DEAUTHENTICATE:
 	case NL80211_CMD_DISASSOCIATE:
-	case NL80211_CMD_FRAME:
 	case NL80211_CMD_FRAME_TX_STATUS:
 	case NL80211_CMD_UNPROT_DEAUTHENTICATE:
 	case NL80211_CMD_UNPROT_DISASSOCIATE:
@@ -4097,9 +4041,6 @@
 		nl80211_color_change_announcement_completed(bss);
 		break;
 #endif /* CONFIG_IEEE80211AX */
-	case NL80211_CMD_LINKS_REMOVED:
-		wpa_supplicant_event(drv->ctx, EVENT_LINK_RECONFIG, NULL);
-		break;
 	default:
 		wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event "
 			"(cmd=%d)", cmd);
@@ -4108,21 +4049,6 @@
 }
 
 
-static bool nl80211_drv_in_list(struct nl80211_global *global,
-				struct wpa_driver_nl80211_data *drv)
-{
-	struct wpa_driver_nl80211_data *tmp;
-
-	dl_list_for_each(tmp, &global->interfaces,
-			 struct wpa_driver_nl80211_data, list) {
-		if (drv == tmp)
-			return true;
-	}
-
-	return false;
-}
-
-
 int process_global_event(struct nl_msg *msg, void *arg)
 {
 	struct nl80211_global *global = arg;
@@ -4134,31 +4060,6 @@
 	u64 wdev_id = 0;
 	int wdev_id_set = 0;
 	int wiphy_idx_set = 0;
-	bool processed = false;
-
-	/* Event marker, all prior events have been processed */
-	if (gnlh->cmd == NL80211_CMD_GET_PROTOCOL_FEATURES) {
-		u32 seq = nlmsg_hdr(msg)->nlmsg_seq;
-
-		dl_list_for_each_safe(drv, tmp, &global->interfaces,
-				      struct wpa_driver_nl80211_data, list) {
-			if (drv->ignore_next_local_deauth > 0 &&
-			    drv->ignore_next_local_deauth <= seq) {
-				wpa_printf(MSG_DEBUG,
-					   "nl80211: No DEAUTHENTICATE event was ignored");
-				drv->ignore_next_local_deauth = 0;
-			}
-
-			if (drv->ignore_next_local_disconnect > 0 &&
-			    drv->ignore_next_local_disconnect <= seq) {
-				wpa_printf(MSG_DEBUG,
-					   "nl80211: No DISCONNECT event was ignored");
-				drv->ignore_next_local_disconnect = 0;
-			}
-		}
-
-		return NL_SKIP;
-	}
 
 	nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
 		  genlmsg_attrlen(gnlh, 0), NULL);
@@ -4183,28 +4084,16 @@
 			    (wiphy_idx_set && wiphy_idx == wiphy_idx_rx) ||
 			    (wdev_id_set && bss->wdev_id_set &&
 			     wdev_id == bss->wdev_id)) {
-				processed = true;
 				do_process_drv_event(bss, gnlh->cmd, tb);
-				if (!wiphy_idx_set)
-					return NL_SKIP;
-				/* The driver instance could have been removed,
-				 * e.g., due to NL80211_CMD_RADAR_DETECT event,
-				 * so need to stop the loop if that has
-				 * happened. */
-				if (!nl80211_drv_in_list(global, drv))
-					break;
+				return NL_SKIP;
 			}
 		}
+		wpa_printf(MSG_DEBUG,
+			   "nl80211: Ignored event %d (%s) for foreign interface (ifindex %d wdev 0x%llx)",
+			   gnlh->cmd, nl80211_command_to_string(gnlh->cmd),
+			   ifidx, (long long unsigned int) wdev_id);
 	}
 
-	if (processed)
-		return NL_SKIP;
-
-	wpa_printf(MSG_DEBUG,
-		   "nl80211: Ignored event %d (%s) for foreign interface (ifindex %d wdev 0x%llx wiphy %d)",
-		   gnlh->cmd, nl80211_command_to_string(gnlh->cmd),
-		   ifidx, (long long unsigned int) wdev_id, wiphy_idx_rx);
-
 	return NL_SKIP;
 }
 
diff --git a/src/drivers/driver_nl80211_scan.c b/src/drivers/driver_nl80211_scan.c
index 1eb4374..4907e3c 100644
--- a/src/drivers/driver_nl80211_scan.c
+++ b/src/drivers/driver_nl80211_scan.c
@@ -82,7 +82,8 @@
 
 	os_memset(info, 0, sizeof(*info));
 	msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_GET_SURVEY);
-	return send_and_recv_resp(drv, msg, get_noise_for_scan_results, info);
+	return send_and_recv_msgs(drv, msg, get_noise_for_scan_results, info,
+				  NULL, NULL);
 }
 
 
@@ -94,7 +95,7 @@
 
 	wpa_printf(MSG_DEBUG, "nl80211: Abort scan");
 	msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_ABORT_SCAN);
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "nl80211: Abort scan failed: ret=%d (%s)",
 			   ret, strerror(-ret));
@@ -125,7 +126,7 @@
 
 	nla_nest_end(msg, params);
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	msg = NULL;
 	if (ret) {
 		wpa_printf(MSG_INFO,
@@ -396,7 +397,7 @@
 			goto fail;
 	}
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	msg = NULL;
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "nl80211: Scan trigger failed: ret=%d "
@@ -427,9 +428,7 @@
 	drv->scan_state = SCAN_REQUESTED;
 	/* Not all drivers generate "scan completed" wireless event, so try to
 	 * read results after a timeout. */
-	timeout = drv->uses_6ghz ? 20 : 10;
-	if (drv->uses_s1g)
-		timeout += 5;
+	timeout = drv->uses_6ghz ? 15 : 10;
 	if (drv->scan_complete_events) {
 		/*
 		 * The driver seems to deliver events to notify when scan is
@@ -651,7 +650,7 @@
 			params->sched_scan_start_delay))
 		goto fail;
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 
 	/* TODO: if we get an error here, we should fall back to normal scan */
 
@@ -688,7 +687,7 @@
 #endif /* ANDROID */
 
 	msg = nl80211_drv_msg(drv, 0, NL80211_CMD_STOP_SCHED_SCAN);
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	if (ret) {
 		wpa_printf(MSG_DEBUG,
 			   "nl80211: Sched scan stop failed: ret=%d (%s)",
@@ -728,7 +727,7 @@
 
 static struct wpa_scan_res *
 nl80211_parse_bss_info(struct wpa_driver_nl80211_data *drv,
-		       struct nl_msg *msg, const u8 *bssid)
+		       struct nl_msg *msg)
 {
 	struct nlattr *tb[NL80211_ATTR_MAX + 1];
 	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
@@ -762,9 +761,6 @@
 	if (nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS],
 			     bss_policy))
 		return NULL;
-	if (bssid && bss[NL80211_BSS_BSSID] &&
-	    !ether_addr_equal(bssid, nla_data(bss[NL80211_BSS_BSSID])))
-		return NULL;
 	if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) {
 		ie = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
 		ie_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
@@ -869,7 +865,6 @@
 struct nl80211_bss_info_arg {
 	struct wpa_driver_nl80211_data *drv;
 	struct wpa_scan_results *res;
-	const u8 *bssid;
 };
 
 static int bss_info_handler(struct nl_msg *msg, void *arg)
@@ -879,7 +874,7 @@
 	struct wpa_scan_res **tmp;
 	struct wpa_scan_res *r;
 
-	r = nl80211_parse_bss_info(_arg->drv, msg, _arg->bssid);
+	r = nl80211_parse_bss_info(_arg->drv, msg);
 	if (!r)
 		return NL_SKIP;
 
@@ -927,14 +922,14 @@
 			   "nl80211: Local state (not associated) does not match with BSS state");
 		clear_state_mismatch(drv, r->bssid);
 	} else if (is_sta_interface(drv->nlmode) &&
-		   !ether_addr_equal(drv->bssid, r->bssid)) {
+		   os_memcmp(drv->bssid, r->bssid, ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG,
 			   "nl80211: Local state (associated with " MACSTR
 			   ") does not match with BSS state",
 			   MAC2STR(drv->bssid));
 
-		if (!ether_addr_equal(drv->sta_mlo_info.ap_mld_addr,
-				      drv->bssid)) {
+		if (os_memcmp(drv->sta_mlo_info.ap_mld_addr, drv->bssid,
+			      ETH_ALEN) != 0) {
 			clear_state_mismatch(drv, r->bssid);
 
 			if (!is_zero_ether_addr(drv->sta_mlo_info.ap_mld_addr))
@@ -977,7 +972,7 @@
 
 
 static struct wpa_scan_results *
-nl80211_get_scan_results(struct wpa_driver_nl80211_data *drv, const u8 *bssid)
+nl80211_get_scan_results(struct wpa_driver_nl80211_data *drv)
 {
 	struct nl_msg *msg;
 	struct wpa_scan_results *res;
@@ -997,8 +992,7 @@
 
 	arg.drv = drv;
 	arg.res = res;
-	arg.bssid = bssid;
-	ret = send_and_recv_resp(drv, msg, bss_info_handler, &arg);
+	ret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg, NULL, NULL);
 	if (ret == -EAGAIN) {
 		count++;
 		if (count >= 10) {
@@ -1034,18 +1028,16 @@
 
 /**
  * wpa_driver_nl80211_get_scan_results - Fetch the latest scan results
- * @priv: Pointer to private nl80211 data from wpa_driver_nl80211_init()
- * @bssid: Return results only for the specified BSSID, %NULL for all
+ * @priv: Pointer to private wext data from wpa_driver_nl80211_init()
  * Returns: Scan results on success, -1 on failure
  */
-struct wpa_scan_results * wpa_driver_nl80211_get_scan_results(void *priv,
-							      const u8 *bssid)
+struct wpa_scan_results * wpa_driver_nl80211_get_scan_results(void *priv)
 {
 	struct i802_bss *bss = priv;
 	struct wpa_driver_nl80211_data *drv = bss->drv;
 	struct wpa_scan_results *res;
 
-	res = nl80211_get_scan_results(drv, bssid);
+	res = nl80211_get_scan_results(drv);
 	if (res)
 		wpa_driver_nl80211_check_bss_status(drv, res);
 	return res;
@@ -1062,7 +1054,7 @@
 	struct nl80211_dump_scan_ctx *ctx = arg;
 	struct wpa_scan_res *r;
 
-	r = nl80211_parse_bss_info(ctx->drv, msg, NULL);
+	r = nl80211_parse_bss_info(ctx->drv, msg);
 	if (!r)
 		return NL_SKIP;
 	wpa_printf(MSG_DEBUG, "nl80211: %d " MACSTR " %d%s",
@@ -1084,7 +1076,8 @@
 	ctx.idx = 0;
 	msg = nl80211_cmd_msg(drv->first_bss, NLM_F_DUMP, NL80211_CMD_GET_SCAN);
 	if (msg)
-		send_and_recv_resp(drv, msg, nl80211_dump_scan_handler, &ctx);
+		send_and_recv_msgs(drv, msg, nl80211_dump_scan_handler, &ctx,
+				   NULL, NULL);
 }
 
 
@@ -1275,14 +1268,10 @@
 			goto fail;
 	}
 
-	if (is_ap_interface(drv->nlmode) &&
-	    params->link_id != NL80211_DRV_LINK_ID_NA &&
-	    nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_SCAN_LINK_ID, params->link_id))
-		goto fail;
-
 	nla_nest_end(msg, attr);
 
-	ret = send_and_recv_resp(drv, msg, scan_cookie_handler, &cookie);
+	ret = send_and_recv_msgs(drv, msg, scan_cookie_handler, &cookie,
+				 NULL, NULL);
 	msg = NULL;
 	if (ret) {
 		wpa_printf(MSG_DEBUG,
@@ -1345,7 +1334,7 @@
 
 	nla_nest_end(msg, attr);
 
-	ret = send_and_recv_cmd(drv, msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	msg = NULL;
 	if (ret) {
 		wpa_printf(MSG_ERROR,
diff --git a/src/drivers/driver_roboswitch.c b/src/drivers/driver_roboswitch.c
index 23c7086..9beb6c4 100644
--- a/src/drivers/driver_roboswitch.c
+++ b/src/drivers/driver_roboswitch.c
@@ -175,7 +175,7 @@
 	struct wpa_driver_roboswitch_data *drv = priv;
 
 	if (len > 14 && WPA_GET_BE16(buf + 12) == ETH_P_EAPOL &&
-	    ether_addr_equal(buf, drv->own_addr))
+	    os_memcmp(buf, drv->own_addr, ETH_ALEN) == 0)
 		drv_event_eapol_rx(drv->ctx, src_addr, buf + 14, len - 14);
 }
 
diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c
index 2c656fb..cf201fe 100644
--- a/src/drivers/driver_wext.c
+++ b/src/drivers/driver_wext.c
@@ -452,10 +452,9 @@
 				   MAC2STR((u8 *) iwe->u.ap_addr.sa_data));
 			if (is_zero_ether_addr(
 				    (const u8 *) iwe->u.ap_addr.sa_data) ||
-			    ether_addr_equal((const u8 *)
-					     iwe->u.ap_addr.sa_data,
-					     (const u8 *)
-					     "\x44\x44\x44\x44\x44\x44")) {
+			    os_memcmp(iwe->u.ap_addr.sa_data,
+				      "\x44\x44\x44\x44\x44\x44", ETH_ALEN) ==
+			    0) {
 				os_free(drv->assoc_req_ies);
 				drv->assoc_req_ies = NULL;
 				os_free(drv->assoc_resp_ies);
diff --git a/src/drivers/drivers.mak b/src/drivers/drivers.mak
index 3b3098d..0186099 100644
--- a/src/drivers/drivers.mak
+++ b/src/drivers/drivers.mak
@@ -160,6 +160,7 @@
 NEED_LINUX_IOCTL=y
 ifdef CONFIG_VLAN_NETLINK
 NEED_LIBNL=y
+CONFIG_LIBNL3_ROUTE=y
 endif
 endif
 
diff --git a/src/drivers/drivers.mk b/src/drivers/drivers.mk
index 1cbe652..8c58456 100644
--- a/src/drivers/drivers.mk
+++ b/src/drivers/drivers.mk
@@ -154,6 +154,7 @@
 NEED_LINUX_IOCTL=y
 ifdef CONFIG_VLAN_NETLINK
 NEED_LIBNL=y
+CONFIG_LIBNL3_ROUTE=y
 endif
 endif
 
diff --git a/src/drivers/linux_ioctl.c b/src/drivers/linux_ioctl.c
index 29abc0c..7edb9df 100644
--- a/src/drivers/linux_ioctl.c
+++ b/src/drivers/linux_ioctl.c
@@ -161,20 +161,11 @@
 	ifr.ifr_ifindex = ifindex;
 	if (ioctl(sock, SIOCBRADDIF, &ifr) < 0) {
 		int saved_errno = errno;
-		char in_br[IFNAMSIZ];
 
 		wpa_printf(MSG_DEBUG, "Could not add interface %s into bridge "
 			   "%s: %s", ifname, brname, strerror(errno));
 		errno = saved_errno;
-
-		/* If ioctl() returns EBUSY when adding an interface into the
-		 * bridge, the interface might have already been added by an
-		 * external operation, so check whether the interface is
-		 * currently on the right bridge and ignore the error if it is.
-		 */
-		if (errno != EBUSY || linux_br_get(in_br, ifname) != 0 ||
-		    os_strcmp(in_br, brname) != 0)
-			return -1;
+		return -1;
 	}
 
 	return 0;
diff --git a/src/eap_peer/eap.c b/src/eap_peer/eap.c
index 1d8ad62..4a09908 100644
--- a/src/eap_peer/eap.c
+++ b/src/eap_peer/eap.c
@@ -1771,13 +1771,12 @@
 		return NULL;
 
 	wpabuf_put_data(resp, identity, identity_len);
+	wpabuf_free(privacy_identity);
 
 	os_free(sm->identity);
 	sm->identity = os_memdup(identity, identity_len);
 	sm->identity_len = identity_len;
 
-	wpabuf_free(privacy_identity);
-
 	return resp;
 }
 
diff --git a/src/eap_peer/eap_wsc.c b/src/eap_peer/eap_wsc.c
index fe61c83..a1e7bff 100644
--- a/src/eap_peer/eap_wsc.c
+++ b/src/eap_peer/eap_wsc.c
@@ -255,18 +255,8 @@
 		cfg.new_ap_settings = &new_ap_settings;
 	}
 
-	pos = os_strstr(phase1, "multi_ap=");
-	if (pos) {
-		u16 id = atoi(pos + 9);
-
-		if (id != 0) {
-			cfg.multi_ap_backhaul_sta = 1;
-			cfg.multi_ap_profile = id;
-		} else {
-			wpa_printf(MSG_DEBUG,
-				   "EAP-WSC: Invalid multi_ap setting");
-		}
-	}
+	if (os_strstr(phase1, "multi_ap=1"))
+		cfg.multi_ap_backhaul_sta = 1;
 
 	data->wps = wps_init(&cfg);
 	if (data->wps == NULL) {
diff --git a/src/fst/fst_group.c b/src/fst/fst_group.c
index 61c7299..255d0fd 100644
--- a/src/fst/fst_group.c
+++ b/src/fst/fst_group.c
@@ -364,7 +364,8 @@
 				cur_mbie, this_band_id);
 			if (!this_peer_addr)
 				continue;
-			if (ether_addr_equal(this_peer_addr, peer_addr)) {
+			if (os_memcmp(this_peer_addr, peer_addr, ETH_ALEN) ==
+			    0) {
 				os_memcpy(other_peer_addr, cur_peer_addr,
 					  ETH_ALEN);
 				return other_iface;
diff --git a/src/fst/fst_iface.c b/src/fst/fst_iface.c
index 96b2847..90c5fc0 100644
--- a/src/fst/fst_iface.c
+++ b/src/fst/fst_iface.c
@@ -56,7 +56,7 @@
 	const u8 *a = fst_iface_get_peer_first(iface, &ctx, mb_only);
 
 	for (; a != NULL; a = fst_iface_get_peer_next(iface, &ctx, mb_only))
-		if (ether_addr_equal(addr, a))
+		if (os_memcmp(addr, a, ETH_ALEN) == 0)
 			return true;
 
 	return false;
diff --git a/src/fst/fst_session.c b/src/fst/fst_session.c
index 49886ff..e42a85c 100644
--- a/src/fst/fst_session.c
+++ b/src/fst/fst_session.c
@@ -238,8 +238,10 @@
 
 	foreach_fst_session(s) {
 		if (s->group == g &&
-		    (ether_addr_equal(s->data.old_peer_addr, peer_addr) ||
-		     ether_addr_equal(s->data.new_peer_addr, peer_addr)) &&
+		    (os_memcmp(s->data.old_peer_addr, peer_addr,
+			       ETH_ALEN) == 0 ||
+		     os_memcmp(s->data.new_peer_addr, peer_addr,
+			       ETH_ALEN) == 0) &&
 		    fst_session_is_in_progress(s))
 			return s;
 	}
diff --git a/src/l2_packet/l2_packet_freebsd.c b/src/l2_packet/l2_packet_freebsd.c
index 481c8ca..3f0b299 100644
--- a/src/l2_packet/l2_packet_freebsd.c
+++ b/src/l2_packet/l2_packet_freebsd.c
@@ -30,9 +30,6 @@
 #include "eloop.h"
 #include "l2_packet.h"
 
-#ifndef ETHER_VLAN_ENCAP_LEN
-#define ETHER_VLAN_ENCAP_LEN 4
-#endif
 
 static const u8 pae_group_addr[ETH_ALEN] =
 { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 };
diff --git a/src/l2_packet/l2_packet_linux.c b/src/l2_packet/l2_packet_linux.c
index 5da0505..7897bc0 100644
--- a/src/l2_packet/l2_packet_linux.c
+++ b/src/l2_packet/l2_packet_linux.c
@@ -179,7 +179,7 @@
 		 * authorization has been completed (in dormant state).
 		 */
 		if (l2->num_rx_br <= 1 &&
-		    (ether_addr_equal(eth->h_dest, l2->own_addr) ||
+		    (os_memcmp(eth->h_dest, l2->own_addr, ETH_ALEN) == 0 ||
 		     is_multicast_ether_addr(eth->h_dest))) {
 			wpa_printf(MSG_DEBUG,
 				   "l2_packet_receive: Main packet socket for %s seems to have working RX - close workaround bridge socket",
@@ -241,7 +241,7 @@
 	wpa_printf(MSG_DEBUG, "%s: src=" MACSTR " len=%d",
 		   __func__, MAC2STR(ll.sll_addr), (int) res);
 
-	if (ether_addr_equal(ll.sll_addr, l2->own_addr)) {
+	if (os_memcmp(ll.sll_addr, l2->own_addr, ETH_ALEN) == 0) {
 		wpa_printf(MSG_DEBUG, "%s: Drop RX of own frame", __func__);
 		return;
 	}
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index 0f9c924..267399d 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -301,8 +301,6 @@
 		    ies) < 0) {
 		p2p_dbg(p2p, "Failed to start listen mode");
 		p2p->pending_listen_freq = 0;
-	} else {
-		p2p->pending_listen_wait_drv = true;
 	}
 	wpabuf_free(ies);
 }
@@ -352,7 +350,6 @@
 		wpabuf_free(ies);
 		return -1;
 	}
-	p2p->pending_listen_wait_drv = true;
 	wpabuf_free(ies);
 
 	p2p_set_state(p2p, P2P_LISTEN_ONLY);
@@ -381,7 +378,7 @@
 {
 	struct p2p_device *dev;
 	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
-		if (ether_addr_equal(dev->info.p2p_device_addr, addr))
+		if (os_memcmp(dev->info.p2p_device_addr, addr, ETH_ALEN) == 0)
 			return dev;
 	}
 	return NULL;
@@ -399,7 +396,7 @@
 {
 	struct p2p_device *dev;
 	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
-		if (ether_addr_equal(dev->interface_addr, addr))
+		if (os_memcmp(dev->interface_addr, addr, ETH_ALEN) == 0)
 			return dev;
 	}
 	return NULL;
@@ -489,8 +486,8 @@
 	 * group, the information will be restored in the loop following this.
 	 */
 	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
-		if (ether_addr_equal(dev->member_in_go_iface,
-				     go_interface_addr)) {
+		if (os_memcmp(dev->member_in_go_iface, go_interface_addr,
+			      ETH_ALEN) == 0) {
 			os_memset(dev->member_in_go_iface, 0, ETH_ALEN);
 			os_memset(dev->member_in_go_dev, 0, ETH_ALEN);
 		}
@@ -498,7 +495,8 @@
 
 	for (c = 0; c < info.num_clients; c++) {
 		struct p2p_client_info *cli = &info.client[c];
-		if (ether_addr_equal(cli->p2p_device_addr, p2p->cfg->dev_addr))
+		if (os_memcmp(cli->p2p_device_addr, p2p->cfg->dev_addr,
+			      ETH_ALEN) == 0)
 			continue; /* ignore our own entry */
 		dev = p2p_get_device(p2p, cli->p2p_device_addr);
 		if (dev) {
@@ -756,7 +754,7 @@
 	}
 
 	if (!is_zero_ether_addr(p2p->peer_filter) &&
-	    !ether_addr_equal(p2p_dev_addr, p2p->peer_filter)) {
+	    os_memcmp(p2p_dev_addr, p2p->peer_filter, ETH_ALEN) != 0) {
 		p2p_dbg(p2p, "Do not add peer filter for " MACSTR
 			" due to peer filter", MAC2STR(p2p_dev_addr));
 		p2p_parse_free(&msg);
@@ -801,7 +799,7 @@
 	dev->flags &= ~(P2P_DEV_PROBE_REQ_ONLY | P2P_DEV_GROUP_CLIENT_ONLY |
 			P2P_DEV_LAST_SEEN_AS_GROUP_CLIENT);
 
-	if (!ether_addr_equal(addr, p2p_dev_addr))
+	if (os_memcmp(addr, p2p_dev_addr, ETH_ALEN) != 0)
 		os_memcpy(dev->interface_addr, addr, ETH_ALEN);
 	if (msg.ssid &&
 	    msg.ssid[1] <= sizeof(dev->oper_ssid) &&
@@ -1032,7 +1030,6 @@
 		return;
 	}
 	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
-	p2p->pending_listen_wait_drv = false;
 
 	if (p2p->find_pending_full &&
 	    (p2p->find_type == P2P_FIND_PROGRESSIVE ||
@@ -1250,7 +1247,6 @@
 		p2p->pending_listen_freq = 0;
 	}
 	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
-	p2p->pending_listen_wait_drv = false;
 	p2p->find_pending_full = 0;
 	p2p->find_type = type;
 	if (freq != 2412 && freq != 2437 && freq != 2462 && freq != 60480)
@@ -1345,10 +1341,6 @@
 
 void p2p_stop_listen_for_freq(struct p2p_data *p2p, int freq)
 {
-	p2p_dbg(p2p,
-		"%s(freq=%d) pending_listen_freq=%d in_listen=%d drv_in_listen=%d",
-		__func__, freq, p2p->pending_listen_freq, p2p->in_listen,
-		p2p->drv_in_listen);
 	if (freq > 0 &&
 	    ((p2p->drv_in_listen == freq && p2p->in_listen) ||
 	     p2p->pending_listen_freq == (unsigned int) freq)) {
@@ -1368,15 +1360,7 @@
 		p2p_dbg(p2p, "Clear drv_in_listen (%d)", p2p->drv_in_listen);
 		p2p->drv_in_listen = 0;
 	}
-	if (p2p->pending_listen_freq &&
-	    p2p->pending_listen_freq != (unsigned int) freq &&
-	    !p2p->drv_in_listen && p2p->pending_listen_wait_drv) {
-		p2p_dbg(p2p,
-			"Clear pending_listen_freq since the started listen did not complete before being stopped");
-		p2p->pending_listen_freq = 0;
-	}
 	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
-	p2p->pending_listen_wait_drv = false;
 }
 
 
@@ -2045,7 +2029,6 @@
 		p2p->pending_listen_freq = 0;
 	}
 	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
-	p2p->pending_listen_wait_drv = false;
 	p2p->go_neg_peer->status = P2P_SC_SUCCESS;
 	/*
 	 * Set new timeout to make sure a previously set one does not expire
@@ -2066,7 +2049,6 @@
 		p2p->pending_listen_freq = 0;
 	}
 	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
-	p2p->pending_listen_wait_drv = false;
 	p2p_invite_send(p2p, p2p->invite_peer, p2p->invite_go_dev_addr,
 			p2p->invite_dev_pw_id);
 }
@@ -2401,7 +2383,7 @@
 	}
 
 	if (dst && !is_broadcast_ether_addr(dst) &&
-	    !ether_addr_equal(dst, p2p->cfg->dev_addr)) {
+	    os_memcmp(dst, p2p->cfg->dev_addr, ETH_ALEN) != 0) {
 		/* Not sent to the broadcast address or our P2P Device Address
 		 */
 		p2p_dbg(p2p, "Probe Req DA " MACSTR " not ours - ignore it",
@@ -2485,7 +2467,7 @@
 	}
 
 	if (msg.device_id &&
-	    !ether_addr_equal(msg.device_id, p2p->cfg->dev_addr)) {
+	    os_memcmp(msg.device_id, p2p->cfg->dev_addr, ETH_ALEN) != 0) {
 		/* Device ID did not match */
 		p2p_dbg(p2p, "Probe Req requested Device ID " MACSTR " did not match - ignore it",
 			MAC2STR(msg.device_id));
@@ -2574,7 +2556,8 @@
 	 */
 	if ((p2p->state == P2P_CONNECT || p2p->state == P2P_CONNECT_LISTEN) &&
 	    p2p->go_neg_peer &&
-	    ether_addr_equal(addr, p2p->go_neg_peer->info.p2p_device_addr) &&
+	    os_memcmp(addr, p2p->go_neg_peer->info.p2p_device_addr, ETH_ALEN)
+	    == 0 &&
 	    !(p2p->go_neg_peer->flags & P2P_DEV_WAIT_GO_NEG_CONFIRM)) {
 		/* Received a Probe Request from GO Negotiation peer */
 		p2p_dbg(p2p, "Found GO Negotiation peer - try to start GO negotiation from timeout");
@@ -2586,7 +2569,8 @@
 	if ((p2p->state == P2P_INVITE || p2p->state == P2P_INVITE_LISTEN) &&
 	    p2p->invite_peer &&
 	    (p2p->invite_peer->flags & P2P_DEV_WAIT_INV_REQ_ACK) &&
-	    ether_addr_equal(addr, p2p->invite_peer->info.p2p_device_addr)) {
+	    os_memcmp(addr, p2p->invite_peer->info.p2p_device_addr, ETH_ALEN)
+	    == 0) {
 		/* Received a Probe Request from Invite peer */
 		p2p_dbg(p2p, "Found Invite peer - try to start Invite from timeout");
 		eloop_cancel_timeout(p2p_invite_start, p2p, NULL);
@@ -2939,7 +2923,8 @@
 		return; /* No pending Group Formation */
 	}
 
-	if (!ether_addr_equal(mac_addr, p2p->go_neg_peer->intended_addr)) {
+	if (os_memcmp(mac_addr, p2p->go_neg_peer->intended_addr, ETH_ALEN) !=
+	    0) {
 		p2p_dbg(p2p, "Ignore WPS registration success notification for "
 			MACSTR " (GO Negotiation peer " MACSTR ")",
 			MAC2STR(mac_addr),
@@ -3412,8 +3397,8 @@
 	 */
 
 	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
-		if (!ether_addr_equal(p2p->pending_pd_devaddr,
-				      dev->info.p2p_device_addr))
+		if (os_memcmp(p2p->pending_pd_devaddr,
+			      dev->info.p2p_device_addr, ETH_ALEN) != 0)
 			continue;
 		if (!dev->req_config_methods)
 			continue;
@@ -3896,7 +3881,6 @@
 	p2p_dbg(p2p, "Starting Listen timeout(%u,%u) on freq=%u based on callback",
 		p2p->pending_listen_sec, p2p->pending_listen_usec,
 		p2p->pending_listen_freq);
-	p2p->pending_listen_wait_drv = false;
 	p2p->in_listen = 1;
 	p2p->drv_in_listen = freq;
 	if (p2p->pending_listen_sec || p2p->pending_listen_usec) {
@@ -4052,7 +4036,6 @@
 
 	p2p_dbg(p2p, "Go to Listen state while waiting for the peer to become ready for GO Negotiation");
 	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
-	p2p->pending_listen_wait_drv = false;
 	if (p2p->pending_listen_freq) {
 		p2p_dbg(p2p, "Clear pending_listen_freq for %s", __func__);
 		p2p->pending_listen_freq = 0;
@@ -4106,8 +4089,8 @@
 		int for_join = 0;
 
 		dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
-			if (!ether_addr_equal(p2p->pending_pd_devaddr,
-					      dev->info.p2p_device_addr))
+			if (os_memcmp(p2p->pending_pd_devaddr,
+				      dev->info.p2p_device_addr, ETH_ALEN) != 0)
 				continue;
 			if (dev->req_config_methods &&
 			    (dev->flags & P2P_DEV_PD_FOR_JOIN))
@@ -4180,7 +4163,6 @@
 	if (p2p->drv_in_listen) {
 		p2p_dbg(p2p, "Driver is still in listen state - stop it");
 		p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
-		p2p->pending_listen_wait_drv = false;
 	}
 
 	switch (p2p->state) {
@@ -4575,8 +4557,8 @@
 	p2p_dbg(p2p, "Received P2P Action - P2P Presence Request");
 
 	for (g = 0; g < p2p->num_groups; g++) {
-		if (ether_addr_equal(
-			    da, p2p_group_get_interface_addr(p2p->groups[g]))) {
+		if (os_memcmp(da, p2p_group_get_interface_addr(p2p->groups[g]),
+			      ETH_ALEN) == 0) {
 			group = p2p->groups[g];
 			break;
 		}
@@ -4674,6 +4656,15 @@
 				       p2p_ext_listen_timeout, p2p, NULL);
 	}
 
+	if ((p2p->cfg->is_p2p_in_progress &&
+	     p2p->cfg->is_p2p_in_progress(p2p->cfg->cb_ctx)) ||
+	    (p2p->pending_action_state == P2P_PENDING_PD &&
+	     p2p->pd_retries > 0)) {
+		p2p_dbg(p2p, "Operation in progress - skip Extended Listen timeout (%s)",
+			p2p_state_txt(p2p->state));
+		return;
+	}
+
 	if (p2p->state == P2P_LISTEN_ONLY && p2p->ext_listen_only) {
 		/*
 		 * This should not really happen, but it looks like the Listen
@@ -4686,15 +4677,6 @@
 		p2p_set_state(p2p, P2P_IDLE);
 	}
 
-	if ((p2p->cfg->is_p2p_in_progress &&
-	     p2p->cfg->is_p2p_in_progress(p2p->cfg->cb_ctx)) ||
-	    (p2p->pending_action_state == P2P_PENDING_PD &&
-	     p2p->pd_retries > 0)) {
-		p2p_dbg(p2p, "Operation in progress - skip Extended Listen timeout (%s)",
-			p2p_state_txt(p2p->state));
-		return;
-	}
-
 	if (p2p->state != P2P_IDLE) {
 		p2p_dbg(p2p, "Skip Extended Listen timeout in active state (%s)", p2p_state_txt(p2p->state));
 		return;
diff --git a/src/p2p/p2p_dev_disc.c b/src/p2p/p2p_dev_disc.c
index ff2bdfc..98805fe 100644
--- a/src/p2p/p2p_dev_disc.c
+++ b/src/p2p/p2p_dev_disc.c
@@ -223,7 +223,7 @@
 
 	go = p2p->pending_client_disc_go;
 	if (go == NULL ||
-	    !ether_addr_equal(sa, go->info.p2p_device_addr)) {
+	    os_memcmp(sa, go->info.p2p_device_addr, ETH_ALEN) != 0) {
 		p2p_dbg(p2p, "Ignore unexpected Device Discoverability Response");
 		return;
 	}
@@ -249,10 +249,10 @@
 	p2p_dbg(p2p, "Device Discoverability Response status %u", status);
 
 	if (p2p->go_neg_peer == NULL ||
-	    !ether_addr_equal(p2p->pending_client_disc_addr,
-			      p2p->go_neg_peer->info.p2p_device_addr) ||
-	    !ether_addr_equal(p2p->go_neg_peer->member_in_go_dev,
-			      go->info.p2p_device_addr)) {
+	    os_memcmp(p2p->pending_client_disc_addr,
+		      p2p->go_neg_peer->info.p2p_device_addr, ETH_ALEN) != 0 ||
+	    os_memcmp(p2p->go_neg_peer->member_in_go_dev,
+		      go->info.p2p_device_addr, ETH_ALEN) != 0) {
 		p2p_dbg(p2p, "No pending operation with the client discoverability peer anymore");
 		return;
 	}
diff --git a/src/p2p/p2p_go_neg.c b/src/p2p/p2p_go_neg.c
index 30901b3..55db8a5 100644
--- a/src/p2p/p2p_go_neg.c
+++ b/src/p2p/p2p_go_neg.c
@@ -859,7 +859,7 @@
 		goto fail;
 	}
 
-	if (!ether_addr_equal(msg.p2p_device_addr, sa)) {
+	if (os_memcmp(msg.p2p_device_addr, sa, ETH_ALEN) != 0) {
 		p2p_dbg(p2p, "Unexpected GO Negotiation Request SA=" MACSTR
 			" != dev_addr=" MACSTR,
 			MAC2STR(sa), MAC2STR(msg.p2p_device_addr));
diff --git a/src/p2p/p2p_group.c b/src/p2p/p2p_group.c
index c036f92..aa18af6 100644
--- a/src/p2p/p2p_group.c
+++ b/src/p2p/p2p_group.c
@@ -579,7 +579,7 @@
 	m = group->members;
 	prev = NULL;
 	while (m) {
-		if (ether_addr_equal(m->addr, addr))
+		if (os_memcmp(m->addr, addr, ETH_ALEN) == 0)
 			break;
 		prev = m;
 		m = m->next;
@@ -785,11 +785,11 @@
 	if (!msg.device_id)
 		return 1; /* No filter on Device ID */
 
-	if (ether_addr_equal(msg.device_id, group->p2p->cfg->dev_addr))
+	if (os_memcmp(msg.device_id, group->p2p->cfg->dev_addr, ETH_ALEN) == 0)
 		return 1; /* Match with our P2P Device Address */
 
 	for (m = group->members; m; m = m->next) {
-		if (ether_addr_equal(msg.device_id, m->dev_addr))
+		if (os_memcmp(msg.device_id, m->dev_addr, ETH_ALEN) == 0)
 			return 1; /* Match with group client P2P Device Address */
 	}
 
@@ -844,7 +844,7 @@
 	struct p2p_group_member *m;
 
 	for (m = group->members; m; m = m->next) {
-		if (ether_addr_equal(dev_id, m->dev_addr))
+		if (os_memcmp(dev_id, m->dev_addr, ETH_ALEN) == 0)
 			return m;
 	}
 
@@ -872,7 +872,7 @@
 	struct p2p_group_member *m;
 
 	for (m = group->members; m; m = m->next) {
-		if (ether_addr_equal(interface_addr, m->addr))
+		if (os_memcmp(interface_addr, m->addr, ETH_ALEN) == 0)
 			return m;
 	}
 
@@ -1038,7 +1038,7 @@
 	struct p2p_group_member *m;
 
 	for (m = group->members; m; m = m->next) {
-		if (ether_addr_equal(m->dev_addr, dev_addr))
+		if (os_memcmp(m->dev_addr, dev_addr, ETH_ALEN) == 0)
 			return 1;
 	}
 
@@ -1051,7 +1051,7 @@
 {
 	if (group_id_len != ETH_ALEN + group->cfg->ssid_len)
 		return 0;
-	if (!ether_addr_equal(group_id, group->p2p->cfg->dev_addr))
+	if (os_memcmp(group_id, group->p2p->cfg->dev_addr, ETH_ALEN) != 0)
 		return 0;
 	return os_memcmp(group_id + ETH_ALEN, group->cfg->ssid,
 			 group->cfg->ssid_len) == 0;
diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h
index f24544c..235467e 100644
--- a/src/p2p/p2p_i.h
+++ b/src/p2p/p2p_i.h
@@ -400,7 +400,6 @@
 	unsigned int pending_listen_freq;
 	unsigned int pending_listen_sec;
 	unsigned int pending_listen_usec;
-	bool pending_listen_wait_drv;
 
 	u8 dev_capab;
 
diff --git a/src/p2p/p2p_invitation.c b/src/p2p/p2p_invitation.c
index 70a7f6f..941ec00 100644
--- a/src/p2p/p2p_invitation.c
+++ b/src/p2p/p2p_invitation.c
@@ -33,8 +33,8 @@
 		for (i = 0; i < p2p->num_groups; i++) {
 			struct p2p_group *g = p2p->groups[i];
 			struct wpabuf *ie;
-			if (!ether_addr_equal(p2p_group_get_interface_addr(g),
-					      p2p->inv_bssid))
+			if (os_memcmp(p2p_group_get_interface_addr(g),
+				      p2p->inv_bssid, ETH_ALEN) != 0)
 				continue;
 			ie = p2p_group_get_wfd_ie(g);
 			if (ie) {
@@ -127,8 +127,8 @@
 		for (i = 0; i < p2p->num_groups; i++) {
 			struct p2p_group *g = p2p->groups[i];
 			struct wpabuf *ie;
-			if (!ether_addr_equal(p2p_group_get_interface_addr(g),
-					      group_bssid))
+			if (os_memcmp(p2p_group_get_interface_addr(g),
+				      group_bssid, ETH_ALEN) != 0)
 				continue;
 			ie = p2p_group_get_wfd_ie(g);
 			if (ie) {
diff --git a/src/p2p/p2p_pd.c b/src/p2p/p2p_pd.c
index 542521e..f75cee8 100644
--- a/src/p2p/p2p_pd.c
+++ b/src/p2p/p2p_pd.c
@@ -544,7 +544,7 @@
 	if (msg->persistent_dev) {
 		channel_list = 1;
 		config_timeout = 1;
-		if (ether_addr_equal(msg->persistent_dev, addr)) {
+		if (os_memcmp(msg->persistent_dev, addr, ETH_ALEN) == 0) {
 			intended_addr = 1;
 			operating_channel = 1;
 		}
@@ -730,7 +730,7 @@
 	if (!msg.status) {
 		unsigned int forced_freq, pref_freq;
 
-		if (!ether_addr_equal(p2p->cfg->dev_addr, msg.adv_mac)) {
+		if (os_memcmp(p2p->cfg->dev_addr, msg.adv_mac, ETH_ALEN)) {
 			p2p_dbg(p2p,
 				"P2PS PD adv mac does not match the local one");
 			reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
@@ -892,14 +892,14 @@
 		goto out;
 
 	if (p2p->p2ps_prov->adv_id != adv_id ||
-	    !ether_addr_equal(p2p->p2ps_prov->adv_mac, msg.adv_mac)) {
+	    os_memcmp(p2p->p2ps_prov->adv_mac, msg.adv_mac, ETH_ALEN)) {
 		p2p_dbg(p2p,
 			"P2PS Follow-on PD with mismatch Advertisement ID/MAC");
 		goto out;
 	}
 
 	if (p2p->p2ps_prov->session_id != session_id ||
-	    !ether_addr_equal(p2p->p2ps_prov->session_mac, msg.session_mac)) {
+	    os_memcmp(p2p->p2ps_prov->session_mac, msg.session_mac, ETH_ALEN)) {
 		p2p_dbg(p2p, "P2PS Follow-on PD with mismatch Session ID/MAC");
 		goto out;
 	}
@@ -1239,7 +1239,8 @@
 		return -1;
 	}
 
-	if (!ether_addr_equal(p2p->p2ps_prov->session_mac, msg->session_mac)) {
+	if (os_memcmp(p2p->p2ps_prov->session_mac, msg->session_mac,
+		      ETH_ALEN)) {
 		p2p_dbg(p2p,
 			"Ignore PD Response with unexpected Session MAC");
 		return -1;
@@ -1251,7 +1252,7 @@
 		return -1;
 	}
 
-	if (!ether_addr_equal(p2p->p2ps_prov->adv_mac, msg->adv_mac)) {
+	if (os_memcmp(p2p->p2ps_prov->adv_mac, msg->adv_mac, ETH_ALEN) != 0) {
 		p2p_dbg(p2p,
 			"Ignore PD Response with unexpected Advertisement MAC");
 		return -1;
@@ -1395,7 +1396,7 @@
 	 * was sent earlier, we reset that state info here.
 	 */
 	if (p2p->user_initiated_pd &&
-	    ether_addr_equal(p2p->pending_pd_devaddr, sa))
+	    os_memcmp(p2p->pending_pd_devaddr, sa, ETH_ALEN) == 0)
 		p2p_reset_pending_pd(p2p);
 
 	if (msg.wps_config_methods != req_config_methods) {
@@ -1757,8 +1758,8 @@
 	struct p2p_device *dev;
 
 	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
-		if (!ether_addr_equal(p2p->pending_pd_devaddr,
-				      dev->info.p2p_device_addr))
+		if (os_memcmp(p2p->pending_pd_devaddr,
+			      dev->info.p2p_device_addr, ETH_ALEN))
 			continue;
 		if (!dev->req_config_methods)
 			continue;
diff --git a/src/p2p/p2p_sd.c b/src/p2p/p2p_sd.c
index d6882e4..b9e753f 100644
--- a/src/p2p/p2p_sd.c
+++ b/src/p2p/p2p_sd.c
@@ -79,7 +79,8 @@
 			count++;
 		}
 		if (!q->for_all_peers &&
-		    ether_addr_equal(q->peer, dev->info.p2p_device_addr))
+		    os_memcmp(q->peer, dev->info.p2p_device_addr, ETH_ALEN) ==
+		    0)
 			goto found;
 	}
 
@@ -288,7 +289,8 @@
 	if (query == NULL)
 		return -1;
 	if (p2p->state == P2P_SEARCH &&
-	    ether_addr_equal(p2p->sd_query_no_ack, dev->info.p2p_device_addr)) {
+	    os_memcmp(p2p->sd_query_no_ack, dev->info.p2p_device_addr,
+		      ETH_ALEN) == 0) {
 		p2p_dbg(p2p, "Do not start Service Discovery with " MACSTR
 			" due to it being the first no-ACK peer in this search iteration",
 			MAC2STR(dev->info.p2p_device_addr));
@@ -489,21 +491,12 @@
 	u16 slen;
 	u16 update_indic;
 
-	if ((p2p->state != P2P_SD_DURING_FIND && p2p->state != P2P_SEARCH) ||
-	    !p2p->sd_peer ||
-	    !ether_addr_equal(sa, p2p->sd_peer->info.p2p_device_addr)) {
+	if (p2p->state != P2P_SD_DURING_FIND || p2p->sd_peer == NULL ||
+	    os_memcmp(sa, p2p->sd_peer->info.p2p_device_addr, ETH_ALEN) != 0) {
 		p2p_dbg(p2p, "Ignore unexpected GAS Initial Response from "
 			MACSTR, MAC2STR(sa));
 		return;
 	}
-	if (p2p->state == P2P_SEARCH) {
-		/* It is possible for the TX status and RX response events to be
-		 * reordered, so assume the request was ACKed if a response is
-		 * received. */
-		p2p_dbg(p2p,
-			"GAS Initial Request had not yet received TX status - process the response anyway");
-		p2p_set_state(p2p, P2P_SD_DURING_FIND);
-	}
 	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
 	p2p_clear_timeout(p2p);
 
@@ -649,7 +642,7 @@
 		p2p_dbg(p2p, "No pending SD response fragment available");
 		return;
 	}
-	if (!ether_addr_equal(sa, p2p->sd_resp_addr)) {
+	if (os_memcmp(sa, p2p->sd_resp_addr, ETH_ALEN) != 0) {
 		p2p_dbg(p2p, "No pending SD response fragment for " MACSTR,
 			MAC2STR(sa));
 		return;
@@ -714,7 +707,7 @@
 	wpa_hexdump(MSG_DEBUG, "P2P: RX GAS Comeback Response", data, len);
 
 	if (p2p->state != P2P_SD_DURING_FIND || p2p->sd_peer == NULL ||
-	    !ether_addr_equal(sa, p2p->sd_peer->info.p2p_device_addr)) {
+	    os_memcmp(sa, p2p->sd_peer->info.p2p_device_addr, ETH_ALEN) != 0) {
 		p2p_dbg(p2p, "Ignore unexpected GAS Comeback Response from "
 			MACSTR, MAC2STR(sa));
 		return;
diff --git a/src/pae/ieee802_1x_kay.c b/src/pae/ieee802_1x_kay.c
index bc33a25..f75fd8f 100644
--- a/src/pae/ieee802_1x_kay.c
+++ b/src/pae/ieee802_1x_kay.c
@@ -1215,7 +1215,7 @@
 			/* My message id is used by other participant */
 			if (peer_mn > participant->mn &&
 			    !reset_participant_mi(participant))
-				wpa_printf(MSG_DEBUG, "KaY: Could not update MI");
+				wpa_printf(MSG_DEBUG, "KaY: Could not update mi");
 			continue;
 		}
 	}
@@ -2560,7 +2560,7 @@
 	}
 
 	if (ieee802_1x_kay_encode_mkpdu(participant, buf)) {
-		wpa_printf(MSG_ERROR, "KaY: encode MKPDU fail");
+		wpa_printf(MSG_ERROR, "KaY: encode mkpdu fail");
 		return -1;
 	}
 
@@ -2628,7 +2628,9 @@
 			      struct ieee802_1x_kay_peer, list) {
 		if (now.sec > peer->expire) {
 			wpa_printf(MSG_DEBUG, "KaY: Live peer removed");
-			ieee802_1x_kay_dump_peer(peer);
+			wpa_hexdump(MSG_DEBUG, "\tMI: ", peer->mi,
+				    sizeof(peer->mi));
+			wpa_printf(MSG_DEBUG, "\tMN: %d", peer->mn);
 			dl_list_for_each_safe(rxsc, pre_rxsc,
 					      &participant->rxsc_list,
 					      struct receive_sc, list) {
@@ -2657,10 +2659,10 @@
 	if (key_server_removed) {
 		if (!reset_participant_mi(participant))
 			wpa_printf(MSG_WARNING,
-				   "KaY: Could not update MI on key server removal");
+				   "KaY: Could not update mi on key server removal");
 		else
 			wpa_printf(MSG_DEBUG,
-				   "KaY: Update MI on key server removal");
+				   "KaY: Update mi on key server removal");
 	}
 
 	if (lp_changed) {
@@ -2704,7 +2706,9 @@
 			      struct ieee802_1x_kay_peer, list) {
 		if (now.sec > peer->expire) {
 			wpa_printf(MSG_DEBUG, "KaY: Potential peer removed");
-			ieee802_1x_kay_dump_peer(peer);
+			wpa_hexdump(MSG_DEBUG, "\tMI: ", peer->mi,
+				    sizeof(peer->mi));
+			wpa_printf(MSG_DEBUG, "\tMN: %d", peer->mn);
 			dl_list_del(&peer->list);
 			os_free(peer);
 		}
@@ -3161,7 +3165,7 @@
 		   be_to_host16(eth_hdr->ethertype));
 
 	/* the destination address shall not be an individual address */
-	if (!ether_addr_equal(eth_hdr->dest, pae_group_addr)) {
+	if (os_memcmp(eth_hdr->dest, pae_group_addr, ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG,
 			   "KaY: ethernet destination address is not PAE group address");
 		return -1;
@@ -3409,7 +3413,7 @@
 			   "KaY: Discarding Rx MKPDU: decode of parameter set type (%d) failed",
 			   MKA_SAK_USE);
 		if (!reset_participant_mi(participant))
-			wpa_printf(MSG_DEBUG, "KaY: Could not update MI");
+			wpa_printf(MSG_DEBUG, "KaY: Could not update mi");
 		else
 			wpa_printf(MSG_DEBUG,
 				   "KaY: Selected a new random MI: %s",
@@ -3626,7 +3630,7 @@
 		goto error;
 	}
 
-	wpa_printf(MSG_DEBUG, "KaY: SecY init MACsec done");
+	wpa_printf(MSG_DEBUG, "KaY: secy init macsec done");
 
 	/* init CP */
 	kay->cp = ieee802_1x_cp_sm_init(kay);
@@ -3717,7 +3721,7 @@
 		   kay->if_name, mode_txt(mode), yes_no(is_authenticator));
 
 	if (!kay || !ckn || !cak) {
-		wpa_printf(MSG_ERROR, "KaY: CKN or CAK is null");
+		wpa_printf(MSG_ERROR, "KaY: ckn or cak is null");
 		return NULL;
 	}
 
diff --git a/src/pasn/pasn_common.c b/src/pasn/pasn_common.c
deleted file mode 100644
index e2c6681..0000000
--- a/src/pasn/pasn_common.c
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * PASN common processing
- *
- * Copyright (C) 2024, Qualcomm Innovation Center, Inc.
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#include "utils/includes.h"
-
-#include "utils/common.h"
-#include "common/wpa_common.h"
-#include "common/sae.h"
-#include "crypto/sha384.h"
-#include "crypto/crypto.h"
-#include "common/ieee802_11_defs.h"
-#include "pasn_common.h"
-
-
-struct pasn_data * pasn_data_init(void)
-{
-	struct pasn_data *pasn = os_zalloc(sizeof(struct pasn_data));
-
-	return pasn;
-}
-
-
-void pasn_data_deinit(struct pasn_data *pasn)
-{
-	bin_clear_free(pasn, sizeof(struct pasn_data));
-}
-
-
-void pasn_register_callbacks(struct pasn_data *pasn, void *cb_ctx,
-			     int (*send_mgmt)(void *ctx, const u8 *data,
-					      size_t data_len, int noack,
-					      unsigned int freq,
-					      unsigned int wait),
-			     int (*validate_custom_pmkid)(void *ctx,
-							  const u8 *addr,
-							  const u8 *pmkid))
-{
-	if (!pasn)
-		return;
-
-	pasn->cb_ctx = cb_ctx;
-	pasn->send_mgmt = send_mgmt;
-	pasn->validate_custom_pmkid = validate_custom_pmkid;
-}
-
-
-void pasn_enable_kdk_derivation(struct pasn_data *pasn)
-{
-	if (!pasn)
-		return;
-	pasn->derive_kdk = true;
-	pasn->kdk_len = WPA_KDK_MAX_LEN;
-}
-
-
-void pasn_disable_kdk_derivation(struct pasn_data *pasn)
-{
-	if (!pasn)
-		return;
-	pasn->derive_kdk = false;
-	pasn->kdk_len = 0;
-}
-
-
-void pasn_set_akmp(struct pasn_data *pasn, int akmp)
-{
-	if (!pasn)
-		return;
-	pasn->akmp = akmp;
-}
-
-
-void pasn_set_cipher(struct pasn_data *pasn, int cipher)
-{
-	if (!pasn)
-		return;
-	pasn->cipher = cipher;
-}
-
-
-void pasn_set_own_addr(struct pasn_data *pasn, const u8 *addr)
-{
-	if (!pasn || !addr)
-		return;
-	os_memcpy(pasn->own_addr, addr, ETH_ALEN);
-}
-
-
-void pasn_set_peer_addr(struct pasn_data *pasn, const u8 *addr)
-{
-	if (!pasn || !addr)
-		return;
-	os_memcpy(pasn->peer_addr, addr, ETH_ALEN);
-}
-
-
-void pasn_set_bssid(struct pasn_data *pasn, const u8 *addr)
-{
-	if (!pasn || !addr)
-		return;
-	os_memcpy(pasn->bssid, addr, ETH_ALEN);
-}
-
-
-int pasn_set_pt(struct pasn_data *pasn, struct sae_pt *pt)
-{
-	if (!pasn)
-		return -1;
-#ifdef CONFIG_SAE
-	pasn->pt = pt;
-	return 0;
-#else /* CONFIG_SAE */
-	return -1;
-#endif /* CONFIG_SAE */
-}
-
-
-void pasn_set_password(struct pasn_data *pasn, const char *password)
-{
-	if (!pasn)
-		return;
-	pasn->password = password;
-}
-
-
-void pasn_set_wpa_key_mgmt(struct pasn_data *pasn, int key_mgmt)
-{
-	if (!pasn)
-		return;
-	pasn->wpa_key_mgmt = key_mgmt;
-}
-
-
-void pasn_set_rsn_pairwise(struct pasn_data *pasn, int rsn_pairwise)
-{
-	if (!pasn)
-		return;
-	pasn->rsn_pairwise = rsn_pairwise;
-}
-
-
-void pasn_set_rsnxe_caps(struct pasn_data *pasn, u16 rsnxe_capab)
-{
-	if (!pasn)
-		return;
-	pasn->rsnxe_capab = rsnxe_capab;
-}
-
-
-void pasn_set_rsnxe_ie(struct pasn_data *pasn, const u8 *rsnxe_ie)
-{
-	if (!pasn || !rsnxe_ie)
-		return;
-	pasn->rsnxe_ie = rsnxe_ie;
-}
-
-
-void pasn_set_custom_pmkid(struct pasn_data *pasn, const u8 *pmkid)
-{
-	if (!pasn || !pmkid)
-		return;
-	os_memcpy(pasn->custom_pmkid, pmkid, PMKID_LEN);
-	pasn->custom_pmkid_valid = true;
-}
-
-
-int pasn_set_extra_ies(struct pasn_data *pasn, const u8 *extra_ies,
-		       size_t extra_ies_len)
-{
-	if (!pasn || !extra_ies_len || !extra_ies)
-		return -1;
-
-	if (pasn->extra_ies) {
-		os_free((u8 *) pasn->extra_ies);
-		pasn->extra_ies_len = extra_ies_len;
-	}
-
-	pasn->extra_ies = os_memdup(extra_ies, extra_ies_len);
-	if (!pasn->extra_ies) {
-		wpa_printf(MSG_ERROR,
-			   "PASN: Extra IEs memory allocation failed");
-		return -1;
-	}
-	pasn->extra_ies_len = extra_ies_len;
-	return 0;
-}
-
-
-int pasn_get_akmp(struct pasn_data *pasn)
-{
-	if (!pasn)
-		return 0;
-	return pasn->akmp;
-}
-
-
-int pasn_get_cipher(struct pasn_data *pasn)
-{
-	if (!pasn)
-		return 0;
-	return pasn->cipher;
-}
-
-
-size_t pasn_get_pmk_len(struct pasn_data *pasn)
-{
-	if (!pasn)
-		return 0;
-	return pasn->pmk_len;
-}
-
-
-u8 * pasn_get_pmk(struct pasn_data *pasn)
-{
-	if (!pasn)
-		return NULL;
-	return pasn->pmk;
-}
-
-
-struct wpa_ptk * pasn_get_ptk(struct pasn_data *pasn)
-{
-	if (!pasn)
-		return NULL;
-	return &pasn->ptk;
-}
diff --git a/src/pasn/pasn_common.h b/src/pasn/pasn_common.h
index 36710c2..a4850a2 100644
--- a/src/pasn/pasn_common.h
+++ b/src/pasn/pasn_common.h
@@ -16,6 +16,8 @@
 extern "C" {
 #endif
 
+#ifdef CONFIG_PASN
+
 enum pasn_fils_state {
 	PASN_FILS_STATE_NONE = 0,
 	PASN_FILS_STATE_PENDING_AS,
@@ -33,46 +35,19 @@
 };
 
 struct pasn_data {
-	/* External modules access below variables using setter and getter
-	 * functions */
 	int akmp;
 	int cipher;
-	u8 own_addr[ETH_ALEN];
-	u8 peer_addr[ETH_ALEN];
-	u8 bssid[ETH_ALEN];
-	struct rsn_pmksa_cache *pmksa;
-	bool derive_kdk;
-	size_t kdk_len;
-	void *cb_ctx;
-
-#ifdef CONFIG_SAE
-	struct sae_pt *pt;
-#endif /* CONFIG_SAE */
-
-	/* Responder */
-	const char *password;
-	int wpa_key_mgmt;
-	int rsn_pairwise;
-	u16 rsnxe_capab;
-	const u8 *rsnxe_ie;
-	bool custom_pmkid_valid;
-	u8 custom_pmkid[PMKID_LEN];
-
-	/*
-	 * Extra elements to add into Authentication frames. These can be used,
-	 * e.g., for Wi-Fi Aware use cases.
-	 */
-	const u8 *extra_ies;
-	size_t extra_ies_len;
-
-	/* External modules do not access below variables */
 	u16 group;
 	bool secure_ltf;
 	int freq;
+	size_t kdk_len;
 
 	u8 trans_seq;
 	u8 status;
 
+	u8 own_addr[ETH_ALEN];
+	u8 peer_addr[ETH_ALEN];
+	u8 bssid[ETH_ALEN];
 	size_t pmk_len;
 	u8 pmk[PMK_LEN_MAX];
 	bool using_pmksa;
@@ -88,6 +63,7 @@
 
 #ifdef CONFIG_SAE
 	struct sae_data sae;
+	struct sae_pt *pt;
 #endif /* CONFIG_SAE */
 
 #ifdef CONFIG_FILS
@@ -105,12 +81,15 @@
 	 * differently for the PASN initiator (using RSN Supplicant
 	 * implementation) and PASN responser (using RSN Authenticator
 	 * implementation). Functions cannot be mixed between those cases. */
+	struct rsn_pmksa_cache *pmksa;
 	struct rsn_pmksa_cache_entry *pmksa_entry;
 	struct eapol_sm *eapol;
 	int fast_reauth;
 #ifdef CONFIG_TESTING_OPTIONS
 	int corrupt_mic;
 #endif /* CONFIG_TESTING_OPTIONS */
+	void *cb_ctx;
+	u16 rsnxe_capab;
 	int network_id;
 
 	u8 wrapped_data_format;
@@ -118,11 +97,16 @@
 
 	/* Responder */
 	bool noauth; /* Whether PASN without mutual authentication is enabled */
+	int wpa_key_mgmt;
+	int rsn_pairwise;
+	bool derive_kdk;
+	const char *password;
 	int disable_pmksa_caching;
 	int *pasn_groups;
 	struct wpabuf *wrapped_data;
 	int use_anti_clogging;
 	const u8 *rsn_ie;
+	const u8 *rsnxe_ie;
 	size_t rsn_ie_len;
 
 	u8 *comeback_key;
@@ -130,6 +114,16 @@
 	u16 comeback_idx;
 	u16 *comeback_pending_idx;
 
+	bool custom_pmkid_valid;
+	u8 custom_pmkid[PMKID_LEN];
+
+	/**
+	 * Extra elements to add into Authentication frames. These can be used,
+	 * e.g., for Wi-Fi Aware use cases.
+	 */
+	const u8 *extra_ies;
+	size_t extra_ies_len;
+
 	/**
 	 * send_mgmt - Function handler to transmit a Management frame
 	 * @ctx: Callback context from cb_ctx
@@ -153,6 +147,7 @@
 };
 
 /* Initiator */
+
 void wpa_pasn_reset(struct pasn_data *pasn);
 int wpas_pasn_start(struct pasn_data *pasn, const u8 *own_addr,
 		    const u8 *peer_addr, const u8 *bssid,
@@ -182,45 +177,7 @@
 			  const u8 *peer_addr,
 			  struct rsn_pmksa_cache_entry *pmksa, u16 status);
 
-struct pasn_data * pasn_data_init(void);
-void pasn_data_deinit(struct pasn_data *pasn);
-void pasn_register_callbacks(struct pasn_data *pasn, void *cb_ctx,
-			     int (*send_mgmt)(void *ctx, const u8 *data,
-					      size_t data_len, int noack,
-					      unsigned int freq,
-					      unsigned int wait),
-			     int (*validate_custom_pmkid)(void *ctx,
-							  const u8 *addr,
-							  const u8 *pmkid));
-void pasn_enable_kdk_derivation(struct pasn_data *pasn);
-void pasn_disable_kdk_derivation(struct pasn_data *pasn);
-
-void pasn_set_akmp(struct pasn_data *pasn, int akmp);
-void pasn_set_cipher(struct pasn_data *pasn, int cipher);
-void pasn_set_own_addr(struct pasn_data *pasn, const u8 *addr);
-void pasn_set_peer_addr(struct pasn_data *pasn, const u8 *addr);
-void pasn_set_bssid(struct pasn_data *pasn, const u8 *addr);
-void pasn_set_initiator_pmksa(struct pasn_data *pasn,
-			      struct rsn_pmksa_cache *pmksa);
-void pasn_set_responder_pmksa(struct pasn_data *pasn,
-			      struct rsn_pmksa_cache *pmksa);
-int pasn_set_pt(struct pasn_data *pasn, struct sae_pt *pt);
-
-/* Responder */
-void pasn_set_password(struct pasn_data *pasn, const char *password);
-void pasn_set_wpa_key_mgmt(struct pasn_data *pasn, int key_mgmt);
-void pasn_set_rsn_pairwise(struct pasn_data *pasn, int rsn_pairwise);
-void pasn_set_rsnxe_caps(struct pasn_data *pasn, u16 rsnxe_capab);
-void pasn_set_rsnxe_ie(struct pasn_data *pasn, const u8 *rsnxe_ie);
-void pasn_set_custom_pmkid(struct pasn_data *pasn, const u8 *pmkid);
-int pasn_set_extra_ies(struct pasn_data *pasn, const u8 *extra_ies,
-		       size_t extra_ies_len);
-
-int pasn_get_akmp(struct pasn_data *pasn);
-int pasn_get_cipher(struct pasn_data *pasn);
-size_t pasn_get_pmk_len(struct pasn_data *pasn);
-u8 * pasn_get_pmk(struct pasn_data *pasn);
-struct wpa_ptk * pasn_get_ptk(struct pasn_data *pasn);
+#endif /* CONFIG_PASN */
 
 #ifdef __cplusplus
 }
diff --git a/src/pasn/pasn_initiator.c b/src/pasn/pasn_initiator.c
index d273067..1f9a508 100644
--- a/src/pasn/pasn_initiator.c
+++ b/src/pasn/pasn_initiator.c
@@ -26,14 +26,6 @@
 #include "pasn_common.h"
 
 
-void pasn_set_initiator_pmksa(struct pasn_data *pasn,
-			      struct rsn_pmksa_cache *pmksa)
-{
-	if (pasn)
-		pasn->pmksa = pmksa;
-}
-
-
 #ifdef CONFIG_SAE
 
 static struct wpabuf * wpas_pasn_wd_sae_commit(struct pasn_data *pasn)
@@ -386,8 +378,8 @@
 		return -1;
 	}
 
-	fils_wd = ieee802_11_defrag(elems.wrapped_data, elems.wrapped_data_len,
-				    true);
+	fils_wd = ieee802_11_defrag(&elems, WLAN_EID_EXTENSION,
+				    WLAN_EID_EXT_WRAPPED_DATA);
 
 	if (!fils_wd) {
 		wpa_printf(MSG_DEBUG,
@@ -749,11 +741,6 @@
 	pasn->rsn_ie_len = 0;
 	pasn->rsnxe_ie = NULL;
 	pasn->custom_pmkid_valid = false;
-
-	if (pasn->extra_ies) {
-		os_free((u8 *) pasn->extra_ies);
-		pasn->extra_ies = NULL;
-	}
 }
 
 
@@ -1037,15 +1024,15 @@
 		return false;
 
 	/* Not our frame; do nothing */
-	if (!ether_addr_equal(mgmt->bssid, pasn->bssid))
+	if (os_memcmp(mgmt->bssid, pasn->bssid, ETH_ALEN) != 0)
 		return false;
 
-	if (rx && (!ether_addr_equal(mgmt->da, pasn->own_addr) ||
-		   !ether_addr_equal(mgmt->sa, pasn->peer_addr)))
+	if (rx && (os_memcmp(mgmt->da, pasn->own_addr, ETH_ALEN) != 0 ||
+		   os_memcmp(mgmt->sa, pasn->peer_addr, ETH_ALEN) != 0))
 		return false;
 
-	if (!rx && (!ether_addr_equal(mgmt->sa, pasn->own_addr) ||
-		    !ether_addr_equal(mgmt->da, pasn->peer_addr)))
+	if (!rx && (os_memcmp(mgmt->sa, pasn->own_addr, ETH_ALEN) != 0 ||
+		    os_memcmp(mgmt->da, pasn->peer_addr, ETH_ALEN) != 0))
 		return false;
 
 	/* Not PASN; do nothing */
@@ -1213,9 +1200,9 @@
 	}
 
 	if (pasn_params->wrapped_data_format != WPA_PASN_WRAPPED_DATA_NO) {
-		wrapped_data = ieee802_11_defrag(elems.wrapped_data,
-						 elems.wrapped_data_len,
-						 true);
+		wrapped_data = ieee802_11_defrag(&elems,
+						 WLAN_EID_EXTENSION,
+						 WLAN_EID_EXT_WRAPPED_DATA);
 
 		if (!wrapped_data) {
 			wpa_printf(MSG_DEBUG, "PASN: Missing wrapped data");
diff --git a/src/pasn/pasn_responder.c b/src/pasn/pasn_responder.c
index b991364..47be403 100644
--- a/src/pasn/pasn_responder.c
+++ b/src/pasn/pasn_responder.c
@@ -25,15 +25,6 @@
 #include "ap/pmksa_cache_auth.h"
 #include "pasn_common.h"
 
-
-void pasn_set_responder_pmksa(struct pasn_data *pasn,
-			      struct rsn_pmksa_cache *pmksa)
-{
-	if (pasn)
-		pasn->pmksa = pmksa;
-}
-
-
 #ifdef CONFIG_PASN
 #ifdef CONFIG_SAE
 
@@ -762,8 +753,9 @@
 
 	derive_keys = true;
 	if (pasn_params.wrapped_data_format != WPA_PASN_WRAPPED_DATA_NO) {
-		wrapped_data = ieee802_11_defrag(elems.wrapped_data,
-						 elems.wrapped_data_len, true);
+		wrapped_data = ieee802_11_defrag(&elems,
+						 WLAN_EID_EXTENSION,
+						 WLAN_EID_EXT_WRAPPED_DATA);
 		if (!wrapped_data) {
 			wpa_printf(MSG_DEBUG, "PASN: Missing wrapped data");
 			status = WLAN_STATUS_UNSPECIFIED_FAILURE;
@@ -987,9 +979,9 @@
 	}
 
 	if (pasn_params.wrapped_data_format != WPA_PASN_WRAPPED_DATA_NO) {
-		wrapped_data = ieee802_11_defrag(elems.wrapped_data,
-						 elems.wrapped_data_len,
-						 true);
+		wrapped_data = ieee802_11_defrag(&elems,
+						 WLAN_EID_EXTENSION,
+						 WLAN_EID_EXT_WRAPPED_DATA);
 
 		if (!wrapped_data) {
 			wpa_printf(MSG_DEBUG, "PASN: Missing wrapped data");
diff --git a/src/radius/radius_client.c b/src/radius/radius_client.c
index 2a7f361..ee9e46d 100644
--- a/src/radius/radius_client.c
+++ b/src/radius/radius_client.c
@@ -1,20 +1,18 @@
 /*
  * RADIUS client
- * Copyright (c) 2002-2024, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
  */
 
 #include "includes.h"
-#include <fcntl.h>
 #include <net/if.h>
 
 #include "common.h"
-#include "eloop.h"
-#include "crypto/tls.h"
 #include "radius.h"
 #include "radius_client.h"
+#include "eloop.h"
 
 /* Defaults for RADIUS retransmit values (exponential backoff) */
 
@@ -171,36 +169,36 @@
 	struct hostapd_radius_servers *conf;
 
 	/**
+	 * auth_serv_sock - IPv4 socket for RADIUS authentication messages
+	 */
+	int auth_serv_sock;
+
+	/**
+	 * acct_serv_sock - IPv4 socket for RADIUS accounting messages
+	 */
+	int acct_serv_sock;
+
+	/**
+	 * auth_serv_sock6 - IPv6 socket for RADIUS authentication messages
+	 */
+	int auth_serv_sock6;
+
+	/**
+	 * acct_serv_sock6 - IPv6 socket for RADIUS accounting messages
+	 */
+	int acct_serv_sock6;
+
+	/**
 	 * auth_sock - Currently used socket for RADIUS authentication server
 	 */
 	int auth_sock;
 
 	/**
-	 * auth_tls - Whether current authentication connection uses TLS
-	 */
-	bool auth_tls;
-
-	/**
-	 * auth_tls_ready - Whether authentication TLS is ready
-	 */
-	bool auth_tls_ready;
-
-	/**
 	 * acct_sock - Currently used socket for RADIUS accounting server
 	 */
 	int acct_sock;
 
 	/**
-	 * acct_tls - Whether current accounting connection uses TLS
-	 */
-	bool acct_tls;
-
-	/**
-	 * acct_tls_ready - Whether accounting TLS is ready
-	 */
-	bool acct_tls_ready;
-
-	/**
 	 * auth_handlers - Authentication message handlers
 	 */
 	struct radius_rx_handler *auth_handlers;
@@ -244,12 +242,6 @@
 	 * interim_error_cb_ctx - interim_error_cb() context data
 	 */
 	void *interim_error_cb_ctx;
-
-#ifdef CONFIG_RADIUS_TLS
-	void *tls_ctx;
-	struct tls_connection *auth_tls_conn;
-	struct tls_connection *acct_tls_conn;
-#endif /* CONFIG_RADIUS_TLS */
 };
 
 
@@ -257,7 +249,7 @@
 radius_change_server(struct radius_client_data *radius,
 		     struct hostapd_radius_server *nserv,
 		     struct hostapd_radius_server *oserv,
-		     int auth);
+		     int sock, int sock6, int auth);
 static int radius_client_init_acct(struct radius_client_data *radius);
 static int radius_client_init_auth(struct radius_client_data *radius);
 static void radius_client_auth_failover(struct radius_client_data *radius);
@@ -382,19 +374,9 @@
 	u8 *acct_delay_time;
 	size_t acct_delay_time_len;
 	int num_servers;
-#ifdef CONFIG_RADIUS_TLS
-	struct wpabuf *out = NULL;
-	struct tls_connection *conn = NULL;
-	bool acct = false;
-#endif /* CONFIG_RADIUS_TLS */
 
 	if (entry->msg_type == RADIUS_ACCT ||
 	    entry->msg_type == RADIUS_ACCT_INTERIM) {
-#ifdef CONFIG_RADIUS_TLS
-		acct = true;
-		if (radius->acct_tls)
-			conn = radius->acct_tls_conn;
-#endif /* CONFIG_RADIUS_TLS */
 		num_servers = conf->num_acct_servers;
 		if (radius->acct_sock < 0)
 			radius_client_init_acct(radius);
@@ -412,10 +394,6 @@
 			conf->acct_server->retransmissions++;
 		}
 	} else {
-#ifdef CONFIG_RADIUS_TLS
-		if (radius->auth_tls)
-			conn = radius->auth_tls_conn;
-#endif /* CONFIG_RADIUS_TLS */
 		num_servers = conf->num_auth_servers;
 		if (radius->auth_sock < 0)
 			radius_client_init_auth(radius);
@@ -451,15 +429,6 @@
 		return 1;
 	}
 
-#ifdef CONFIG_RADIUS_TLS
-	if ((acct && radius->acct_tls && !radius->acct_tls_ready) ||
-	    (!acct && radius->auth_tls && !radius->auth_tls_ready)) {
-		wpa_printf(MSG_DEBUG,
-			   "RADIUS: TLS connection not yet ready for TX");
-		goto not_ready;
-	}
-#endif /* CONFIG_RADIUS_TLS */
-
 	if (entry->msg_type == RADIUS_ACCT &&
 	    radius_msg_get_attr_ptr(entry->msg, RADIUS_ATTR_ACCT_DELAY_TIME,
 				    &acct_delay_time, &acct_delay_time_len,
@@ -504,37 +473,11 @@
 
 	os_get_reltime(&entry->last_attempt);
 	buf = radius_msg_get_buf(entry->msg);
-#ifdef CONFIG_RADIUS_TLS
-	if (conn) {
-		out = tls_connection_encrypt(radius->tls_ctx, conn, buf);
-		if (!out) {
-			wpa_printf(MSG_INFO,
-				   "RADIUS: Failed to encrypt RADIUS message (TLS)");
-			return -1;
-		}
-		wpa_printf(MSG_DEBUG,
-			   "RADIUS: TLS encryption of %zu bytes of plaintext to %zu bytes of ciphertext",
-			   wpabuf_len(buf), wpabuf_len(out));
-		buf = out;
-	}
-#endif /* CONFIG_RADIUS_TLS */
-
-	wpa_printf(MSG_DEBUG, "RADIUS: Send %zu bytes to the server",
-		   wpabuf_len(buf));
 	if (send(s, wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
 		if (radius_client_handle_send_error(radius, s, entry->msg_type)
-		    > 0) {
-#ifdef CONFIG_RADIUS_TLS
-			wpabuf_free(out);
-#endif /* CONFIG_RADIUS_TLS */
+		    > 0)
 			return 0;
-		}
 	}
-#ifdef CONFIG_RADIUS_TLS
-	wpabuf_free(out);
-
-not_ready:
-#endif /* CONFIG_RADIUS_TLS */
 
 	entry->next_try = now + entry->next_wait;
 	entry->next_wait *= 2;
@@ -655,7 +598,9 @@
 	if (next > &(conf->auth_servers[conf->num_auth_servers - 1]))
 		next = conf->auth_servers;
 	conf->auth_server = next;
-	radius_change_server(radius, next, old, 1);
+	radius_change_server(radius, next, old,
+			     radius->auth_serv_sock,
+			     radius->auth_serv_sock6, 1);
 }
 
 
@@ -683,7 +628,9 @@
 	if (next > &conf->acct_servers[conf->num_acct_servers - 1])
 		next = conf->acct_servers;
 	conf->acct_server = next;
-	radius_change_server(radius, next, old, 0);
+	radius_change_server(radius, next, old,
+			     radius->acct_serv_sock,
+			     radius->acct_serv_sock6, 0);
 }
 
 
@@ -772,52 +719,6 @@
 }
 
 
-static int radius_client_disable_pmtu_discovery(int s)
-{
-	int r = -1;
-#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
-	/* Turn off Path MTU discovery on IPv4/UDP sockets. */
-	int action = IP_PMTUDISC_DONT;
-	r = setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, &action,
-		       sizeof(action));
-	if (r == -1)
-		wpa_printf(MSG_ERROR, "RADIUS: Failed to set IP_MTU_DISCOVER: %s",
-			   strerror(errno));
-#endif
-	return r;
-}
-
-
-static void radius_close_auth_socket(struct radius_client_data *radius)
-{
-	if (radius->auth_sock >= 0) {
-#ifdef CONFIG_RADIUS_TLS
-		if (radius->conf->auth_server->tls)
-			eloop_unregister_sock(radius->auth_sock,
-					      EVENT_TYPE_WRITE);
-#endif /* CONFIG_RADIUS_TLS */
-		eloop_unregister_read_sock(radius->auth_sock);
-		close(radius->auth_sock);
-		radius->auth_sock = -1;
-	}
-}
-
-
-static void radius_close_acct_socket(struct radius_client_data *radius)
-{
-	if (radius->acct_sock >= 0) {
-#ifdef CONFIG_RADIUS_TLS
-		if (radius->conf->acct_server->tls)
-			eloop_unregister_sock(radius->acct_sock,
-					      EVENT_TYPE_WRITE);
-#endif /* CONFIG_RADIUS_TLS */
-		eloop_unregister_read_sock(radius->acct_sock);
-		close(radius->acct_sock);
-		radius->acct_sock = -1;
-	}
-}
-
-
 /**
  * radius_client_send - Send a RADIUS request
  * @radius: RADIUS client context from radius_client_init()
@@ -853,18 +754,8 @@
 	char *name;
 	int s, res;
 	struct wpabuf *buf;
-#ifdef CONFIG_RADIUS_TLS
-	struct wpabuf *out = NULL;
-	struct tls_connection *conn = NULL;
-	bool acct = false;
-#endif /* CONFIG_RADIUS_TLS */
 
 	if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) {
-#ifdef CONFIG_RADIUS_TLS
-		acct = true;
-		if (radius->acct_tls)
-			conn = radius->acct_tls_conn;
-#endif /* CONFIG_RADIUS_TLS */
 		if (conf->acct_server && radius->acct_sock < 0)
 			radius_client_init_acct(radius);
 
@@ -883,10 +774,6 @@
 		s = radius->acct_sock;
 		conf->acct_server->requests++;
 	} else {
-#ifdef CONFIG_RADIUS_TLS
-		if (radius->auth_tls)
-			conn = radius->auth_tls_conn;
-#endif /* CONFIG_RADIUS_TLS */
 		if (conf->auth_server && radius->auth_sock < 0)
 			radius_client_init_auth(radius);
 
@@ -912,42 +799,11 @@
 	if (conf->msg_dumps)
 		radius_msg_dump(msg);
 
-#ifdef CONFIG_RADIUS_TLS
-	if ((acct && radius->acct_tls && !radius->acct_tls_ready) ||
-	    (!acct && radius->auth_tls && !radius->auth_tls_ready)) {
-		wpa_printf(MSG_DEBUG,
-			   "RADIUS: TLS connection not yet ready for TX");
-		goto skip_send;
-	}
-#endif /* CONFIG_RADIUS_TLS */
-
 	buf = radius_msg_get_buf(msg);
-#ifdef CONFIG_RADIUS_TLS
-	if (conn) {
-		out = tls_connection_encrypt(radius->tls_ctx, conn, buf);
-		if (!out) {
-			wpa_printf(MSG_INFO,
-				   "RADIUS: Failed to encrypt RADIUS message (TLS)");
-			return -1;
-		}
-		wpa_printf(MSG_DEBUG,
-			   "RADIUS: TLS encryption of %zu bytes of plaintext to %zu bytes of ciphertext",
-			   wpabuf_len(buf), wpabuf_len(out));
-		buf = out;
-	}
-#endif /* CONFIG_RADIUS_TLS */
-	wpa_printf(MSG_DEBUG, "RADIUS: Send %zu bytes to the server",
-		   wpabuf_len(buf));
 	res = send(s, wpabuf_head(buf), wpabuf_len(buf), 0);
-#ifdef CONFIG_RADIUS_TLS
-	wpabuf_free(out);
-#endif /* CONFIG_RADIUS_TLS */
 	if (res < 0)
 		radius_client_handle_send_error(radius, s, msg_type);
 
-#ifdef CONFIG_RADIUS_TLS
-skip_send:
-#endif /* CONFIG_RADIUS_TLS */
 	radius_client_list_add(radius, msg, msg_type, shared_secret,
 			       shared_secret_len, addr);
 
@@ -955,137 +811,6 @@
 }
 
 
-#ifdef CONFIG_RADIUS_TLS
-
-static void radius_client_close_tcp(struct radius_client_data *radius,
-				    int sock, RadiusType msg_type)
-{
-	wpa_printf(MSG_DEBUG, "RADIUS: Closing TCP connection (sock %d)",
-		   sock);
-	if (msg_type == RADIUS_ACCT) {
-		radius->acct_tls_ready = false;
-		radius_close_acct_socket(radius);
-	} else {
-		radius->auth_tls_ready = false;
-		radius_close_auth_socket(radius);
-	}
-}
-
-
-static void
-radius_client_process_tls_handshake(struct radius_client_data *radius,
-				    int sock, RadiusType msg_type,
-				    u8 *buf, size_t len)
-{
-	struct wpabuf *in, *out = NULL, *appl;
-	struct tls_connection *conn;
-	int res;
-	bool ready = false;
-
-	wpa_printf(MSG_DEBUG,
-		   "RADIUS: Process %zu bytes of received TLS handshake message",
-		   len);
-
-	if (msg_type == RADIUS_ACCT)
-		conn = radius->acct_tls_conn;
-	else
-		conn = radius->auth_tls_conn;
-
-	in = wpabuf_alloc_copy(buf, len);
-	if (!in)
-		return;
-
-	appl = NULL;
-	out = tls_connection_handshake(radius->tls_ctx, conn, in, &appl);
-	wpabuf_free(in);
-	if (!out) {
-		wpa_printf(MSG_DEBUG,
-			   "RADIUS: Could not generate TLS handshake data");
-		goto fail;
-	}
-
-	if (tls_connection_get_failed(radius->tls_ctx, conn)) {
-		wpa_printf(MSG_INFO, "RADIUS: TLS handshake failed");
-		goto fail;
-	}
-
-	if (tls_connection_established(radius->tls_ctx, conn)) {
-		wpa_printf(MSG_DEBUG,
-			   "RADIUS: TLS connection established (sock=%d)",
-			   sock);
-		if (msg_type == RADIUS_ACCT)
-			radius->acct_tls_ready = true;
-		else
-			radius->auth_tls_ready = true;
-		ready = true;
-	}
-
-	wpa_printf(MSG_DEBUG, "RADIUS: Sending %zu bytes of TLS handshake",
-		   wpabuf_len(out));
-	res = send(sock, wpabuf_head(out), wpabuf_len(out), 0);
-	if (res < 0) {
-		wpa_printf(MSG_INFO, "RADIUS: send: %s", strerror(errno));
-		goto fail;
-	}
-	if ((size_t) res != wpabuf_len(out)) {
-		wpa_printf(MSG_INFO,
-			   "RADIUS: Could not send all data for TLS handshake: only %d bytes sent",
-			   res);
-		goto fail;
-	}
-	wpabuf_free(out);
-
-	if (ready) {
-		struct radius_msg_list *entry, *prev, *tmp;
-		struct os_reltime now;
-
-		/* Send all pending message of matching type since the TLS
-		 * tunnel has now been established. */
-
-		os_get_reltime(&now);
-
-		entry = radius->msgs;
-		prev = NULL;
-		while (entry) {
-			if (entry->msg_type != msg_type) {
-				prev = entry;
-				entry = entry->next;
-				continue;
-			}
-
-			if (radius_client_retransmit(radius, entry, now.sec)) {
-				if (prev)
-					prev->next = entry->next;
-				else
-					radius->msgs = entry->next;
-
-				tmp = entry;
-				entry = entry->next;
-				radius_client_msg_free(tmp);
-				radius->num_msgs--;
-				continue;
-			}
-
-			prev = entry;
-			entry = entry->next;
-		}
-	}
-
-	return;
-
-fail:
-	wpabuf_free(out);
-	tls_connection_deinit(radius->tls_ctx, conn);
-	if (msg_type == RADIUS_ACCT)
-		radius->acct_tls_conn = NULL;
-	else
-		radius->auth_tls_conn = NULL;
-	radius_client_close_tcp(radius, sock, msg_type);
-}
-
-#endif /* CONFIG_RADIUS_TLS */
-
-
 static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx)
 {
 	struct radius_client_data *radius = eloop_ctx;
@@ -1103,28 +828,12 @@
 	struct os_reltime now;
 	struct hostapd_radius_server *rconf;
 	int invalid_authenticator = 0;
-#ifdef CONFIG_RADIUS_TLS
-	struct tls_connection *conn = NULL;
-	bool tls, tls_ready;
-#endif /* CONFIG_RADIUS_TLS */
 
 	if (msg_type == RADIUS_ACCT) {
-#ifdef CONFIG_RADIUS_TLS
-		if (radius->acct_tls)
-			conn = radius->acct_tls_conn;
-		tls = radius->acct_tls;
-		tls_ready = radius->acct_tls_ready;
-#endif /* CONFIG_RADIUS_TLS */
 		handlers = radius->acct_handlers;
 		num_handlers = radius->num_acct_handlers;
 		rconf = conf->acct_server;
 	} else {
-#ifdef CONFIG_RADIUS_TLS
-		if (radius->auth_tls)
-			conn = radius->auth_tls_conn;
-		tls = radius->auth_tls;
-		tls_ready = radius->auth_tls_ready;
-#endif /* CONFIG_RADIUS_TLS */
 		handlers = radius->auth_handlers;
 		num_handlers = radius->num_auth_handlers;
 		rconf = conf->auth_server;
@@ -1140,52 +849,6 @@
 		wpa_printf(MSG_INFO, "recvmsg[RADIUS]: %s", strerror(errno));
 		return;
 	}
-#ifdef CONFIG_RADIUS_TLS
-	if (tls && len == 0) {
-		wpa_printf(MSG_DEBUG, "RADIUS: No TCP data available");
-		goto close_tcp;
-	}
-
-	if (tls && !tls_ready) {
-		radius_client_process_tls_handshake(radius, sock, msg_type,
-						    buf, len);
-		return;
-	}
-
-	if (conn) {
-		struct wpabuf *out, *in;
-
-		in = wpabuf_alloc_copy(buf, len);
-		if (!in)
-			return;
-		wpa_printf(MSG_DEBUG,
-			   "RADIUS: Process %d bytes of encrypted TLS data",
-			   len);
-		out = tls_connection_decrypt(radius->tls_ctx, conn, in);
-		wpabuf_free(in);
-		if (!out) {
-			wpa_printf(MSG_INFO,
-				   "RADIUS: Failed to decrypt TLS data");
-			goto close_tcp;
-		}
-		if (wpabuf_len(out) == 0) {
-			wpa_printf(MSG_DEBUG,
-				   "RADIUS: Full message not yet received - continue waiting for additional TLS data");
-			wpabuf_free(out);
-			return;
-		}
-		if (wpabuf_len(out) > RADIUS_MAX_MSG_LEN) {
-			wpa_printf(MSG_INFO,
-				   "RADIUS: Too long RADIUS message from TLS: %zu",
-				   wpabuf_len(out));
-			wpabuf_free(out);
-			goto close_tcp;
-		}
-		os_memcpy(buf, wpabuf_head(out), wpabuf_len(out));
-		len = wpabuf_len(out);
-		wpabuf_free(out);
-	}
-#endif /* CONFIG_RADIUS_TLS */
 
 	hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
 		       HOSTAPD_LEVEL_DEBUG, "Received %d bytes from RADIUS "
@@ -1301,121 +964,9 @@
 
  fail:
 	radius_msg_free(msg);
-	return;
-
-#ifdef CONFIG_RADIUS_TLS
-close_tcp:
-	radius_client_close_tcp(radius, sock, msg_type);
-#endif /* CONFIG_RADIUS_TLS */
 }
 
 
-#ifdef CONFIG_RADIUS_TLS
-static void radius_client_write_ready(int sock, void *eloop_ctx, void *sock_ctx)
-{
-	struct radius_client_data *radius = eloop_ctx;
-	RadiusType msg_type = (uintptr_t) sock_ctx;
-	struct tls_connection *conn = NULL;
-	struct wpabuf *in, *out = NULL, *appl;
-	int res = -1;
-	struct tls_connection_params params;
-	struct hostapd_radius_server *server;
-
-	wpa_printf(MSG_DEBUG, "RADIUS: TCP connection established - start TLS handshake (sock=%d)",
-		   sock);
-
-	if (msg_type == RADIUS_ACCT) {
-		eloop_unregister_sock(sock, EVENT_TYPE_WRITE);
-		eloop_register_read_sock(sock, radius_client_receive, radius,
-					 (void *) RADIUS_ACCT);
-		if (radius->acct_tls_conn) {
-			wpa_printf(MSG_DEBUG,
-				   "RADIUS: Deinit previously used TLS connection");
-			tls_connection_deinit(radius->tls_ctx,
-					      radius->acct_tls_conn);
-			radius->acct_tls_conn = NULL;
-		}
-		server = radius->conf->acct_server;
-	} else {
-		eloop_unregister_sock(sock, EVENT_TYPE_WRITE);
-		eloop_register_read_sock(sock, radius_client_receive, radius,
-					 (void *) RADIUS_AUTH);
-		if (radius->auth_tls_conn) {
-			wpa_printf(MSG_DEBUG,
-				   "RADIUS: Deinit previously used TLS connection");
-			tls_connection_deinit(radius->tls_ctx,
-					      radius->auth_tls_conn);
-			radius->auth_tls_conn = NULL;
-		}
-		server = radius->conf->auth_server;
-	}
-
-	if (!server)
-		goto fail;
-
-	conn = tls_connection_init(radius->tls_ctx);
-	if (!conn) {
-		wpa_printf(MSG_INFO,
-			   "RADIUS: Failed to initiate TLS connection");
-		goto fail;
-	}
-
-	os_memset(&params, 0, sizeof(params));
-	params.ca_cert = server->ca_cert;
-	params.client_cert = server->client_cert;
-	params.private_key = server->private_key;
-	params.private_key_passwd = server->private_key_passwd;
-	params.flags = TLS_CONN_DISABLE_TLSv1_0 | TLS_CONN_DISABLE_TLSv1_1;
-	if (tls_connection_set_params(radius->tls_ctx, conn, &params)) {
-		wpa_printf(MSG_INFO,
-			   "RADIUS: Failed to set TLS connection parameters");
-		goto fail;
-	}
-
-	in = NULL;
-	appl = NULL;
-	out = tls_connection_handshake(radius->tls_ctx, conn, in, &appl);
-	if (!out) {
-		wpa_printf(MSG_DEBUG,
-			   "RADIUS: Could not generate TLS handshake data");
-		goto fail;
-	}
-
-	if (tls_connection_get_failed(radius->tls_ctx, conn)) {
-		wpa_printf(MSG_INFO, "RADIUS: TLS handshake failed");
-		goto fail;
-	}
-
-	wpa_printf(MSG_DEBUG, "RADIUS: Sending %zu bytes of TLS handshake",
-		   wpabuf_len(out));
-	res = send(sock, wpabuf_head(out), wpabuf_len(out), 0);
-	if (res < 0) {
-		wpa_printf(MSG_INFO, "RADIUS: send: %s", strerror(errno));
-		goto fail;
-	}
-	if ((size_t) res != wpabuf_len(out)) {
-		wpa_printf(MSG_INFO,
-			   "RADIUS: Could not send all data for TLS handshake: only %d bytes sent",
-			   res);
-		goto fail;
-	}
-	wpabuf_free(out);
-
-	if (msg_type == RADIUS_ACCT)
-		radius->acct_tls_conn = conn;
-	else
-		radius->auth_tls_conn = conn;
-	return;
-
-fail:
-	wpa_printf(MSG_INFO, "RADIUS: Failed to perform TLS handshake");
-	tls_connection_deinit(radius->tls_ctx, conn);
-	wpabuf_free(out);
-	radius_client_close_tcp(radius, sock, msg_type);
-}
-#endif /* CONFIG_RADIUS_TLS */
-
-
 /**
  * radius_client_get_id - Get an identifier for a new RADIUS message
  * @radius: RADIUS client context from radius_client_init()
@@ -1520,7 +1071,7 @@
 radius_change_server(struct radius_client_data *radius,
 		     struct hostapd_radius_server *nserv,
 		     struct hostapd_radius_server *oserv,
-		     int auth)
+		     int sock, int sock6, int auth)
 {
 	struct sockaddr_in serv, claddr;
 #ifdef CONFIG_IPV6
@@ -1532,17 +1083,9 @@
 	int sel_sock;
 	struct radius_msg_list *entry;
 	struct hostapd_radius_servers *conf = radius->conf;
-	int type = SOCK_DGRAM;
-	bool tls = nserv->tls;
-
-	if (tls) {
-#ifdef CONFIG_RADIUS_TLS
-		type = SOCK_STREAM;
-#else /* CONFIG_RADIUS_TLS */
-		wpa_printf(MSG_ERROR, "RADIUS: TLS not supported");
-		return -1;
-#endif /* CONFIG_RADIUS_TLS */
-	}
+	struct sockaddr_in disconnect_addr = {
+		.sin_family = AF_UNSPEC,
+	};
 
 	hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
 		       HOSTAPD_LEVEL_INFO,
@@ -1601,9 +1144,7 @@
 		serv.sin_port = htons(nserv->port);
 		addr = (struct sockaddr *) &serv;
 		addrlen = sizeof(serv);
-		sel_sock = socket(PF_INET, type, 0);
-		if (sel_sock >= 0)
-			radius_client_disable_pmtu_discovery(sel_sock);
+		sel_sock = sock;
 		break;
 #ifdef CONFIG_IPV6
 	case AF_INET6:
@@ -1614,7 +1155,7 @@
 		serv6.sin6_port = htons(nserv->port);
 		addr = (struct sockaddr *) &serv6;
 		addrlen = sizeof(serv6);
-		sel_sock = socket(PF_INET6, type, 0);
+		sel_sock = sock6;
 		break;
 #endif /* CONFIG_IPV6 */
 	default:
@@ -1623,19 +1164,15 @@
 
 	if (sel_sock < 0) {
 		wpa_printf(MSG_INFO,
-			   "RADIUS: Failed to open server socket (af=%d auth=%d)",
-			   nserv->addr.af, auth);
+			   "RADIUS: No server socket available (af=%d sock=%d sock6=%d auth=%d",
+			   nserv->addr.af, sock, sock6, auth);
 		return -1;
 	}
 
-#ifdef CONFIG_RADIUS_TLS
-	if (tls && fcntl(sel_sock, F_SETFL, O_NONBLOCK) != 0) {
-		wpa_printf(MSG_DEBUG, "RADIUS: fnctl(O_NONBLOCK) failed: %s",
-			   strerror(errno));
-		close(sel_sock);
-		return -1;
-	}
-#endif /* CONFIG_RADIUS_TLS */
+	/* Force a reconnect by disconnecting the socket first */
+	if (connect(sel_sock, (struct sockaddr *) &disconnect_addr,
+		    sizeof(disconnect_addr)) < 0)
+		wpa_printf(MSG_INFO, "disconnect[radius]: %s", strerror(errno));
 
 #ifdef __linux__
 	if (conf->force_client_dev && conf->force_client_dev[0]) {
@@ -1677,29 +1214,19 @@
 			break;
 #endif /* CONFIG_IPV6 */
 		default:
-			close(sel_sock);
 			return -1;
 		}
 
 		if (bind(sel_sock, cl_addr, claddrlen) < 0) {
 			wpa_printf(MSG_INFO, "bind[radius]: %s",
 				   strerror(errno));
-			close(sel_sock);
-			return -2;
+			return -1;
 		}
 	}
 
 	if (connect(sel_sock, addr, addrlen) < 0) {
-		if (nserv->tls && errno == EINPROGRESS) {
-			wpa_printf(MSG_DEBUG,
-				   "RADIUS: TCP connection establishment in progress (sock %d)",
-				   sel_sock);
-		} else {
-			wpa_printf(MSG_INFO, "connect[radius]: %s",
-				   strerror(errno));
-			close(sel_sock);
-			return -2;
-		}
+		wpa_printf(MSG_INFO, "connect[radius]: %s", strerror(errno));
+		return -1;
 	}
 
 #ifndef CONFIG_NATIVE_WINDOWS
@@ -1729,34 +1256,10 @@
 	}
 #endif /* CONFIG_NATIVE_WINDOWS */
 
-	if (auth) {
-		radius_close_auth_socket(radius);
+	if (auth)
 		radius->auth_sock = sel_sock;
-	} else {
-		radius_close_acct_socket(radius);
+	else
 		radius->acct_sock = sel_sock;
-	}
-
-	if (!tls)
-		eloop_register_read_sock(sel_sock, radius_client_receive,
-					 radius,
-					 auth ? (void *) RADIUS_AUTH :
-					 (void *) RADIUS_ACCT);
-#ifdef CONFIG_RADIUS_TLS
-	if (tls)
-		eloop_register_sock(sel_sock, EVENT_TYPE_WRITE,
-				    radius_client_write_ready, radius,
-				    auth ? (void *) RADIUS_AUTH :
-				    (void *) RADIUS_ACCT);
-#endif /* CONFIG_RADIUS_TLS */
-
-	if (auth) {
-		radius->auth_tls = nserv->tls;
-		radius->auth_tls_ready = false;
-	} else {
-		radius->acct_tls = nserv->tls;
-		radius->acct_tls_ready = false;
-	}
 
 	return 0;
 }
@@ -1773,10 +1276,12 @@
 		oserv = conf->auth_server;
 		conf->auth_server = conf->auth_servers;
 		if (radius_change_server(radius, conf->auth_server, oserv,
-					 1) < 0) {
+					 radius->auth_serv_sock,
+					 radius->auth_serv_sock6, 1) < 0) {
 			conf->auth_server = oserv;
 			radius_change_server(radius, oserv, conf->auth_server,
-					     1);
+					     radius->auth_serv_sock,
+					     radius->auth_serv_sock6, 1);
 		}
 	}
 
@@ -1785,10 +1290,12 @@
 		oserv = conf->acct_server;
 		conf->acct_server = conf->acct_servers;
 		if (radius_change_server(radius, conf->acct_server, oserv,
-					 0) < 0) {
+					 radius->acct_serv_sock,
+					 radius->acct_serv_sock6, 0) < 0) {
 			conf->acct_server = oserv;
 			radius_change_server(radius, oserv, conf->acct_server,
-					     0);
+					     radius->acct_serv_sock,
+					     radius->acct_serv_sock6, 0);
 		}
 	}
 
@@ -1799,27 +1306,170 @@
 }
 
 
+static int radius_client_disable_pmtu_discovery(int s)
+{
+	int r = -1;
+#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
+	/* Turn off Path MTU discovery on IPv4/UDP sockets. */
+	int action = IP_PMTUDISC_DONT;
+	r = setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, &action,
+		       sizeof(action));
+	if (r == -1)
+		wpa_printf(MSG_ERROR, "RADIUS: Failed to set IP_MTU_DISCOVER: %s",
+			   strerror(errno));
+#endif
+	return r;
+}
+
+
+static void radius_close_auth_sockets(struct radius_client_data *radius)
+{
+	radius->auth_sock = -1;
+
+	if (radius->auth_serv_sock >= 0) {
+		eloop_unregister_read_sock(radius->auth_serv_sock);
+		close(radius->auth_serv_sock);
+		radius->auth_serv_sock = -1;
+	}
+#ifdef CONFIG_IPV6
+	if (radius->auth_serv_sock6 >= 0) {
+		eloop_unregister_read_sock(radius->auth_serv_sock6);
+		close(radius->auth_serv_sock6);
+		radius->auth_serv_sock6 = -1;
+	}
+#endif /* CONFIG_IPV6 */
+}
+
+
+static void radius_close_acct_sockets(struct radius_client_data *radius)
+{
+	radius->acct_sock = -1;
+
+	if (radius->acct_serv_sock >= 0) {
+		eloop_unregister_read_sock(radius->acct_serv_sock);
+		close(radius->acct_serv_sock);
+		radius->acct_serv_sock = -1;
+	}
+#ifdef CONFIG_IPV6
+	if (radius->acct_serv_sock6 >= 0) {
+		eloop_unregister_read_sock(radius->acct_serv_sock6);
+		close(radius->acct_serv_sock6);
+		radius->acct_serv_sock6 = -1;
+	}
+#endif /* CONFIG_IPV6 */
+}
+
+
 static int radius_client_init_auth(struct radius_client_data *radius)
 {
-	radius_close_auth_socket(radius);
-	return radius_change_server(radius, radius->conf->auth_server, NULL, 1);
+	struct hostapd_radius_servers *conf = radius->conf;
+	int ok = 0;
+
+	radius_close_auth_sockets(radius);
+
+	radius->auth_serv_sock = socket(PF_INET, SOCK_DGRAM, 0);
+	if (radius->auth_serv_sock < 0)
+		wpa_printf(MSG_INFO, "RADIUS: socket[PF_INET,SOCK_DGRAM]: %s",
+			   strerror(errno));
+	else {
+		radius_client_disable_pmtu_discovery(radius->auth_serv_sock);
+		ok++;
+	}
+
+#ifdef CONFIG_IPV6
+	radius->auth_serv_sock6 = socket(PF_INET6, SOCK_DGRAM, 0);
+	if (radius->auth_serv_sock6 < 0)
+		wpa_printf(MSG_INFO, "RADIUS: socket[PF_INET6,SOCK_DGRAM]: %s",
+			   strerror(errno));
+	else
+		ok++;
+#endif /* CONFIG_IPV6 */
+
+	if (ok == 0)
+		return -1;
+
+	radius_change_server(radius, conf->auth_server, NULL,
+			     radius->auth_serv_sock, radius->auth_serv_sock6,
+			     1);
+
+	if (radius->auth_serv_sock >= 0 &&
+	    eloop_register_read_sock(radius->auth_serv_sock,
+				     radius_client_receive, radius,
+				     (void *) RADIUS_AUTH)) {
+		wpa_printf(MSG_INFO, "RADIUS: Could not register read socket for authentication server");
+		radius_close_auth_sockets(radius);
+		return -1;
+	}
+
+#ifdef CONFIG_IPV6
+	if (radius->auth_serv_sock6 >= 0 &&
+	    eloop_register_read_sock(radius->auth_serv_sock6,
+				     radius_client_receive, radius,
+				     (void *) RADIUS_AUTH)) {
+		wpa_printf(MSG_INFO, "RADIUS: Could not register read socket for authentication server");
+		radius_close_auth_sockets(radius);
+		return -1;
+	}
+#endif /* CONFIG_IPV6 */
+
+	return 0;
 }
 
 
 static int radius_client_init_acct(struct radius_client_data *radius)
 {
-	radius_close_acct_socket(radius);
-	return radius_change_server(radius, radius->conf->acct_server, NULL, 0);
-}
+	struct hostapd_radius_servers *conf = radius->conf;
+	int ok = 0;
 
+	radius_close_acct_sockets(radius);
 
-#ifdef CONFIG_RADIUS_TLS
-static void radius_tls_event_cb(void *ctx, enum tls_event ev,
-				union tls_event_data *data)
-{
-	wpa_printf(MSG_DEBUG, "RADIUS: TLS event %d", ev);
+	radius->acct_serv_sock = socket(PF_INET, SOCK_DGRAM, 0);
+	if (radius->acct_serv_sock < 0)
+		wpa_printf(MSG_INFO, "RADIUS: socket[PF_INET,SOCK_DGRAM]: %s",
+			   strerror(errno));
+	else {
+		radius_client_disable_pmtu_discovery(radius->acct_serv_sock);
+		ok++;
+	}
+
+#ifdef CONFIG_IPV6
+	radius->acct_serv_sock6 = socket(PF_INET6, SOCK_DGRAM, 0);
+	if (radius->acct_serv_sock6 < 0)
+		wpa_printf(MSG_INFO, "RADIUS: socket[PF_INET6,SOCK_DGRAM]: %s",
+			   strerror(errno));
+	else
+		ok++;
+#endif /* CONFIG_IPV6 */
+
+	if (ok == 0)
+		return -1;
+
+	radius_change_server(radius, conf->acct_server, NULL,
+			     radius->acct_serv_sock, radius->acct_serv_sock6,
+			     0);
+
+	if (radius->acct_serv_sock >= 0 &&
+	    eloop_register_read_sock(radius->acct_serv_sock,
+				     radius_client_receive, radius,
+				     (void *) RADIUS_ACCT)) {
+		wpa_printf(MSG_INFO, "RADIUS: Could not register read socket for accounting server");
+		radius_close_acct_sockets(radius);
+		return -1;
+	}
+
+#ifdef CONFIG_IPV6
+	if (radius->acct_serv_sock6 >= 0 &&
+	    eloop_register_read_sock(radius->acct_serv_sock6,
+				     radius_client_receive, radius,
+				     (void *) RADIUS_ACCT)) {
+		wpa_printf(MSG_INFO, "RADIUS: Could not register read socket for accounting server");
+		radius_close_acct_sockets(radius);
+		return -1;
+	}
+#endif /* CONFIG_IPV6 */
+
+	return 0;
 }
-#endif /* CONFIG_RADIUS_TLS */
 
 
 /**
@@ -1843,14 +1493,16 @@
 
 	radius->ctx = ctx;
 	radius->conf = conf;
-	radius->auth_sock = radius->acct_sock = -1;
+	radius->auth_serv_sock = radius->acct_serv_sock =
+		radius->auth_serv_sock6 = radius->acct_serv_sock6 =
+		radius->auth_sock = radius->acct_sock = -1;
 
-	if (conf->auth_server && radius_client_init_auth(radius) == -1) {
+	if (conf->auth_server && radius_client_init_auth(radius)) {
 		radius_client_deinit(radius);
 		return NULL;
 	}
 
-	if (conf->acct_server && radius_client_init_acct(radius) == -1) {
+	if (conf->acct_server && radius_client_init_acct(radius)) {
 		radius_client_deinit(radius);
 		return NULL;
 	}
@@ -1860,22 +1512,6 @@
 				       radius_retry_primary_timer, radius,
 				       NULL);
 
-#ifdef CONFIG_RADIUS_TLS
-	if ((conf->auth_server && conf->auth_server->tls) ||
-	    (conf->acct_server && conf->acct_server->tls)) {
-		struct tls_config tls_conf;
-
-		os_memset(&tls_conf, 0, sizeof(tls_conf));
-		tls_conf.event_cb = radius_tls_event_cb;
-		radius->tls_ctx = tls_init(&tls_conf);
-		if (!radius->tls_ctx) {
-			radius_client_deinit(radius);
-			return NULL;
-		}
-	}
-#endif /* CONFIG_RADIUS_TLS */
-
-
 	return radius;
 }
 
@@ -1889,21 +1525,14 @@
 	if (!radius)
 		return;
 
-	radius_close_auth_socket(radius);
-	radius_close_acct_socket(radius);
+	radius_close_auth_sockets(radius);
+	radius_close_acct_sockets(radius);
 
 	eloop_cancel_timeout(radius_retry_primary_timer, radius, NULL);
 
 	radius_client_flush(radius, 0);
 	os_free(radius->auth_handlers);
 	os_free(radius->acct_handlers);
-#ifdef CONFIG_RADIUS_TLS
-	if (radius->tls_ctx) {
-		tls_connection_deinit(radius->tls_ctx, radius->auth_tls_conn);
-		tls_connection_deinit(radius->tls_ctx, radius->acct_tls_conn);
-		tls_deinit(radius->tls_ctx);
-	}
-#endif /* CONFIG_RADIUS_TLS */
 	os_free(radius);
 }
 
@@ -1927,7 +1556,7 @@
 	entry = radius->msgs;
 	while (entry) {
 		if (entry->msg_type == RADIUS_AUTH &&
-		    ether_addr_equal(entry->addr, addr)) {
+		    os_memcmp(entry->addr, addr, ETH_ALEN) == 0) {
 			hostapd_logger(radius->ctx, addr,
 				       HOSTAPD_MODULE_RADIUS,
 				       HOSTAPD_LEVEL_DEBUG,
diff --git a/src/radius/radius_client.h b/src/radius/radius_client.h
index db40637..687cd81 100644
--- a/src/radius/radius_client.h
+++ b/src/radius/radius_client.h
@@ -1,6 +1,6 @@
 /*
  * RADIUS client
- * Copyright (c) 2002-2024, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -36,11 +36,6 @@
 	int port;
 
 	/**
-	 * tls - Whether to use RADIUS/TLS instead of RADIUS/UDP
-	 */
-	bool tls;
-
-	/**
 	 * shared_secret - Shared secret for authenticating RADIUS messages
 	 */
 	u8 *shared_secret;
@@ -50,26 +45,6 @@
 	 */
 	size_t shared_secret_len;
 
-	/**
-	 * ca_cert - Path to trusted CA certificate(s) for RADIUS/TLS
-	 */
-	char *ca_cert;
-
-	/**
-	 * client_cert - Path to client certificate for RADIUS/TLS
-	 */
-	char *client_cert;
-
-	/**
-	 * private_key - Path to clienbt private key for RADIUS/TLS
-	 */
-	char *private_key;
-
-	/**
-	 * private_key_passwd - Password for the private key for RADIUS/TLS
-	 */
-	char *private_key_passwd;
-
 	/* Dynamic (not from configuration file) MIB data */
 
 	/**
diff --git a/src/rsn_supp/pmksa_cache.c b/src/rsn_supp/pmksa_cache.c
index a402cb6..b2c4809 100644
--- a/src/rsn_supp/pmksa_cache.c
+++ b/src/rsn_supp/pmksa_cache.c
@@ -302,8 +302,8 @@
 	pos = pmksa->pmksa;
 	prev = NULL;
 	while (pos) {
-		if (ether_addr_equal(entry->aa, pos->aa) &&
-		    ether_addr_equal(entry->spa, pos->spa)) {
+		if (os_memcmp(entry->aa, pos->aa, ETH_ALEN) == 0 &&
+		    os_memcmp(entry->spa, pos->spa, ETH_ALEN) == 0) {
 			if (pos->pmk_len == entry->pmk_len &&
 			    os_memcmp_const(pos->pmk, entry->pmk,
 					    entry->pmk_len) == 0 &&
@@ -489,8 +489,8 @@
 {
 	struct rsn_pmksa_cache_entry *entry = pmksa->pmksa;
 	while (entry) {
-		if ((aa == NULL || ether_addr_equal(entry->aa, aa)) &&
-		    (!spa || ether_addr_equal(entry->spa, spa)) &&
+		if ((aa == NULL || os_memcmp(entry->aa, aa, ETH_ALEN) == 0) &&
+		    (!spa || os_memcmp(entry->spa, spa, ETH_ALEN) == 0) &&
 		    (pmkid == NULL ||
 		     os_memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0) &&
 		    (!akmp || akmp == entry->akmp) &&
@@ -857,99 +857,4 @@
 	}
 }
 
-#else /* IEEE8021X_EAPOL */
-
-struct rsn_pmksa_cache *
-pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry,
-				 void *ctx, enum pmksa_free_reason reason),
-		 bool (*is_current_cb)(struct rsn_pmksa_cache_entry *entry,
-				       void *ctx),
-		 void (*notify_cb)(struct rsn_pmksa_cache_entry *entry,
-				   void *ctx),
-		 void *ctx, struct wpa_sm *sm)
-{
-	return (void *) -1;
-}
-
-
-void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa)
-{
-}
-
-
-struct rsn_pmksa_cache_entry *
-pmksa_cache_get(struct rsn_pmksa_cache *pmksa, const u8 *aa, const u8 *spa,
-		const u8 *pmkid, const void *network_ctx, int akmp)
-{
-	return NULL;
-}
-
-
-struct rsn_pmksa_cache_entry *
-pmksa_cache_get_current(struct wpa_sm *sm)
-{
-	return NULL;
-}
-
-
-int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len)
-{
-	return -1;
-}
-
-
-struct rsn_pmksa_cache_entry *
-pmksa_cache_head(struct rsn_pmksa_cache *pmksa)
-{
-	return NULL;
-}
-
-
-struct rsn_pmksa_cache_entry *
-pmksa_cache_add_entry(struct rsn_pmksa_cache *pmksa,
-		      struct rsn_pmksa_cache_entry *entry)
-{
-	return NULL;
-}
-
-
-struct rsn_pmksa_cache_entry *
-pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
-		const u8 *pmkid, const u8 *kck, size_t kck_len,
-		const u8 *aa, const u8 *spa, void *network_ctx, int akmp,
-		const u8 *cache_id)
-{
-	return NULL;
-}
-
-
-void pmksa_cache_clear_current(struct wpa_sm *sm)
-{
-}
-
-
-int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid, const u8 *bssid,
-			    void *network_ctx, int try_opportunistic,
-			    const u8 *fils_cache_id, int akmp, bool associated)
-{
-	return -1;
-}
-
-
-void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx,
-		       const u8 *pmk, size_t pmk_len, bool external_only)
-{
-}
-
-
-void pmksa_cache_remove(struct rsn_pmksa_cache *pmksa,
-			struct rsn_pmksa_cache_entry *entry)
-{
-}
-
-
-void pmksa_cache_reconfig(struct rsn_pmksa_cache *pmksa)
-{
-}
-
 #endif /* IEEE8021X_EAPOL */
diff --git a/src/rsn_supp/pmksa_cache.h b/src/rsn_supp/pmksa_cache.h
index b1203ad..6ba48f7 100644
--- a/src/rsn_supp/pmksa_cache.h
+++ b/src/rsn_supp/pmksa_cache.h
@@ -64,6 +64,8 @@
 	PMKSA_EXPIRE,
 };
 
+#if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA)
+
 struct rsn_pmksa_cache *
 pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry,
 				 void *ctx, enum pmksa_free_reason reason),
@@ -103,4 +105,95 @@
 			struct rsn_pmksa_cache_entry *entry);
 void pmksa_cache_reconfig(struct rsn_pmksa_cache *pmksa);
 
+#else /* IEEE8021X_EAPOL */
+
+static inline struct rsn_pmksa_cache *
+pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry,
+				 void *ctx, enum pmksa_free_reason reason),
+		 bool (*is_current_cb)(struct rsn_pmksa_cache_entry *entry,
+				       void *ctx),
+		 void (*notify_cb)(struct rsn_pmksa_cache_entry *entry,
+				   void *ctx),
+		 void *ctx, struct wpa_sm *sm)
+{
+	return (void *) -1;
+}
+
+static inline void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa)
+{
+}
+
+static inline struct rsn_pmksa_cache_entry *
+pmksa_cache_get(struct rsn_pmksa_cache *pmksa, const u8 *aa, const u8 *spa,
+		const u8 *pmkid, const void *network_ctx, int akmp)
+{
+	return NULL;
+}
+
+static inline struct rsn_pmksa_cache_entry *
+pmksa_cache_get_current(struct wpa_sm *sm)
+{
+	return NULL;
+}
+
+static inline int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf,
+				   size_t len)
+{
+	return -1;
+}
+
+static inline struct rsn_pmksa_cache_entry *
+pmksa_cache_head(struct rsn_pmksa_cache *pmksa)
+{
+	return NULL;
+}
+
+static inline struct rsn_pmksa_cache_entry *
+pmksa_cache_add_entry(struct rsn_pmksa_cache *pmksa,
+		      struct rsn_pmksa_cache_entry *entry)
+{
+	return NULL;
+}
+
+static inline struct rsn_pmksa_cache_entry *
+pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
+		const u8 *pmkid, const u8 *kck, size_t kck_len,
+		const u8 *aa, const u8 *spa, void *network_ctx, int akmp,
+		const u8 *cache_id)
+{
+	return NULL;
+}
+
+static inline void pmksa_cache_clear_current(struct wpa_sm *sm)
+{
+}
+
+static inline int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid,
+					  const u8 *bssid,
+					  void *network_ctx,
+					  int try_opportunistic,
+					  const u8 *fils_cache_id,
+					  int akmp, bool associated)
+{
+	return -1;
+}
+
+static inline void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa,
+				     void *network_ctx,
+				     const u8 *pmk, size_t pmk_len,
+				     bool external_only)
+{
+}
+
+static inline void pmksa_cache_remove(struct rsn_pmksa_cache *pmksa,
+				      struct rsn_pmksa_cache_entry *entry)
+{
+}
+
+static inline void pmksa_cache_reconfig(struct rsn_pmksa_cache *pmksa)
+{
+}
+
+#endif /* IEEE8021X_EAPOL */
+
 #endif /* PMKSA_CACHE_H */
diff --git a/src/rsn_supp/preauth.c b/src/rsn_supp/preauth.c
index 026a98d..1a28884 100644
--- a/src/rsn_supp/preauth.c
+++ b/src/rsn_supp/preauth.c
@@ -69,7 +69,7 @@
 
 	if (sm->preauth_eapol == NULL ||
 	    is_zero_ether_addr(sm->preauth_bssid) ||
-	    !ether_addr_equal(sm->preauth_bssid, src_addr)) {
+	    os_memcmp(sm->preauth_bssid, src_addr, ETH_ALEN) != 0) {
 		wpa_printf(MSG_WARNING, "RSN pre-auth frame received from "
 			   "unexpected source " MACSTR " - dropped",
 			   MAC2STR(src_addr));
@@ -333,7 +333,7 @@
 		struct rsn_pmksa_cache_entry *p = NULL;
 		p = pmksa_cache_get(sm->pmksa, candidate->bssid, sm->own_addr,
 				    NULL, NULL, 0);
-		if (!ether_addr_equal(sm->bssid, candidate->bssid) &&
+		if (os_memcmp(sm->bssid, candidate->bssid, ETH_ALEN) != 0 &&
 		    (p == NULL || p->opportunistic)) {
 			wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: PMKSA "
 				"candidate " MACSTR
@@ -395,7 +395,7 @@
 	cand = NULL;
 	dl_list_for_each(pos, &sm->pmksa_candidates,
 			 struct rsn_pmksa_candidate, list) {
-		if (ether_addr_equal(pos->bssid, bssid)) {
+		if (os_memcmp(pos->bssid, bssid, ETH_ALEN) == 0) {
 			cand = pos;
 			break;
 		}
@@ -487,7 +487,7 @@
 	    os_memcmp(ssid + 2, sm->ssid, sm->ssid_len) != 0)
 		return; /* Not for the current SSID */
 
-	if (ether_addr_equal(bssid, sm->bssid))
+	if (os_memcmp(bssid, sm->bssid, ETH_ALEN) == 0)
 		return; /* Ignore current AP */
 
 	if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie))
diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c
index 65960b7..e6f5877 100644
--- a/src/rsn_supp/tdls.c
+++ b/src/rsn_supp/tdls.c
@@ -161,8 +161,6 @@
 	int chan_switch_enabled;
 
 	int mld_link_id;
-	bool disc_resp_rcvd;
-	bool setup_req_rcvd;
 };
 
 
@@ -296,7 +294,7 @@
 		return 0; /* No retries */
 
 	for (peer = sm->tdls; peer; peer = peer->next) {
-		if (ether_addr_equal(peer->addr, dest))
+		if (os_memcmp(peer->addr, dest, ETH_ALEN) == 0)
 			break;
 	}
 
@@ -793,7 +791,7 @@
 
 	/* Find the node and free from the list */
 	for (peer = sm->tdls; peer; peer = peer->next) {
-		if (ether_addr_equal(peer->addr, addr))
+		if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
 			break;
 	}
 
@@ -882,7 +880,7 @@
 		return -1;
 
 	for (peer = sm->tdls; peer; peer = peer->next) {
-		if (ether_addr_equal(peer->addr, addr))
+		if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
 			break;
 	}
 
@@ -915,7 +913,7 @@
 	struct wpa_tdls_peer *peer;
 
 	for (peer = sm->tdls; peer; peer = peer->next) {
-		if (ether_addr_equal(peer->addr, addr))
+		if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
 			break;
 	}
 
@@ -951,7 +949,7 @@
 		return "disabled";
 
 	for (peer = sm->tdls; peer; peer = peer->next) {
-		if (ether_addr_equal(peer->addr, addr))
+		if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
 			break;
 	}
 
@@ -978,7 +976,7 @@
 
 	/* Find the node and free from the list */
 	for (peer = sm->tdls; peer; peer = peer->next) {
-		if (ether_addr_equal(peer->addr, src_addr))
+		if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0)
 			break;
 	}
 
@@ -1074,7 +1072,7 @@
 	if (existing)
 		*existing = 0;
 	for (peer = sm->tdls; peer; peer = peer->next) {
-		if (ether_addr_equal(peer->addr, addr)) {
+		if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0) {
 			if (existing)
 				*existing = 1;
 			return peer; /* re-use existing entry */
@@ -1566,14 +1564,15 @@
 	*link_id = -1;
 
 	if (!sm->mlo.valid_links) {
-		if (!ether_addr_equal(sm->bssid, lnkid->bssid))
+		if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0)
 			return false;
 	} else {
 		int i;
 
-		for_each_link(sm->mlo.valid_links, i) {
-			if (ether_addr_equal(lnkid->bssid,
-					     sm->mlo.links[i].bssid)) {
+		for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+			if ((sm->mlo.valid_links & BIT(i)) &&
+			    os_memcmp(lnkid->bssid, sm->mlo.links[i].bssid,
+				      ETH_ALEN) == 0) {
 				*link_id = i;
 				break;
 			}
@@ -2372,7 +2371,7 @@
 	wpa_printf(MSG_DEBUG, "TDLS: Received TDLS Setup Response / TPK M2 "
 		   "(Peer " MACSTR ")", MAC2STR(src_addr));
 	for (peer = sm->tdls; peer; peer = peer->next) {
-		if (ether_addr_equal(peer->addr, src_addr))
+		if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0)
 			break;
 	}
 	if (peer == NULL) {
@@ -2461,8 +2460,8 @@
 		    kde.lnkid, kde.lnkid_len);
 	lnkid = (struct wpa_tdls_lnkid *) kde.lnkid;
 
-	if (!ether_addr_equal(sm->bssid,
-			      wpa_tdls_get_link_bssid(sm, peer->mld_link_id))) {
+	if (os_memcmp(sm->bssid, wpa_tdls_get_link_bssid(sm, peer->mld_link_id),
+		      ETH_ALEN) != 0) {
 		wpa_printf(MSG_INFO, "TDLS: TPK M2 from different BSS");
 		status = WLAN_STATUS_NOT_IN_SAME_BSS;
 		goto error;
@@ -2669,7 +2668,7 @@
 	wpa_printf(MSG_DEBUG, "TDLS: Received TDLS Setup Confirm / TPK M3 "
 		   "(Peer " MACSTR ")", MAC2STR(src_addr));
 	for (peer = sm->tdls; peer; peer = peer->next) {
-		if (ether_addr_equal(peer->addr, src_addr))
+		if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0)
 			break;
 	}
 	if (peer == NULL) {
@@ -2714,8 +2713,8 @@
 		    (u8 *) kde.lnkid, kde.lnkid_len);
 	lnkid = (struct wpa_tdls_lnkid *) kde.lnkid;
 
-	if (!ether_addr_equal(wpa_tdls_get_link_bssid(sm, peer->mld_link_id),
-			      lnkid->bssid)) {
+	if (os_memcmp(wpa_tdls_get_link_bssid(sm, peer->mld_link_id),
+		      lnkid->bssid, ETH_ALEN) != 0) {
 		wpa_printf(MSG_INFO, "TDLS: TPK M3 from diff BSS");
 		goto error;
 	}
@@ -2869,12 +2868,6 @@
 		return 0;
 	}
 
-	if (sm->mlo.valid_links && !peer->disc_resp_rcvd) {
-		wpa_printf(MSG_DEBUG,
-			   "TDLS: MLO STA connection - defer the setup request since Discovery Resp not yet received");
-		peer->setup_req_rcvd = true;
-		return 0;
-	}
 	peer->initiator = 1;
 
 	/* add the peer to the driver as a "setup in progress" peer */
@@ -2906,7 +2899,7 @@
 		return;
 
 	for (peer = sm->tdls; peer; peer = peer->next) {
-		if (ether_addr_equal(peer->addr, addr))
+		if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
 			break;
 	}
 
@@ -2944,7 +2937,7 @@
 		return;
 	}
 
-	if (ether_addr_equal(src_addr, sm->own_addr)) {
+	if (os_memcmp(src_addr, sm->own_addr, ETH_ALEN) == 0) {
 		wpa_printf(MSG_DEBUG, "TDLS: Discard copy of own message");
 		return;
 	}
@@ -3194,7 +3187,7 @@
 					const u8 *buf, size_t len)
 {
 	struct ieee802_11_elems elems;
-	const struct wpa_tdls_lnkid *lnkid;
+	struct wpa_tdls_lnkid lnkid;
 	struct wpa_tdls_peer *peer;
 	size_t min_req_len = 1 /* Dialog Token */ + 2 /* Capability */ +
 		sizeof(struct wpa_tdls_lnkid);
@@ -3224,12 +3217,12 @@
 		return -1;
 	}
 
-	lnkid = (const struct wpa_tdls_lnkid *) (elems.link_id - 2);
+	os_memcpy(&lnkid.bssid[0], elems.link_id, sizeof(lnkid) - 2);
 
-	if (!wpa_tdls_is_lnkid_bss_valid(sm, lnkid, &link_id)) {
+	if (!wpa_tdls_is_lnkid_bss_valid(sm, &lnkid, &link_id)) {
 		wpa_printf(MSG_DEBUG,
 			   "TDLS: Discovery Response from different BSS "
-			   MACSTR, MAC2STR(lnkid->bssid));
+			   MACSTR, MAC2STR(lnkid.bssid));
 		return -1;
 	}
 
@@ -3241,14 +3234,7 @@
 
 	peer->mld_link_id = link_id;
 	wpa_printf(MSG_DEBUG, "TDLS: Link identifier BSS: " MACSTR
-		   " , link id: %u", MAC2STR(lnkid->bssid), link_id);
-
-	peer->disc_resp_rcvd = true;
-	if (peer->setup_req_rcvd) {
-		peer->setup_req_rcvd = false;
-		wpa_printf(MSG_DEBUG, "TDLS: Process the deferred TDLS start");
-		return wpa_tdls_start(sm, addr);
-	}
+		   " , link id: %u", MAC2STR(lnkid.bssid), link_id);
 
 	return 0;
 }
@@ -3277,7 +3263,7 @@
 	}
 
 	for (peer = sm->tdls; peer; peer = peer->next) {
-		if (ether_addr_equal(peer->addr, addr))
+		if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
 			break;
 	}
 
@@ -3311,7 +3297,7 @@
 		return -1;
 
 	for (peer = sm->tdls; peer; peer = peer->next) {
-		if (ether_addr_equal(peer->addr, addr))
+		if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
 			break;
 	}
 
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index f5e24f2..9f49cf9 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -233,12 +233,6 @@
 		return;
 	}
 
-	if (!sm->ptk_set) {
-		wpa_printf(MSG_INFO,
-			   "WPA: No PTK derived yet - cannot send EAPOL-Key Request");
-		return;
-	}
-
 	if (wpa_use_akm_defined(sm->key_mgmt))
 		ver = WPA_KEY_INFO_TYPE_AKM_DEFINED;
 	else if (wpa_key_mgmt_ft(sm->key_mgmt) ||
@@ -260,11 +254,10 @@
 		       sm->proto == WPA_PROTO_OSEN) ?
 		EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
 	key_info = WPA_KEY_INFO_REQUEST | ver;
-	key_info |= WPA_KEY_INFO_SECURE;
-	if (mic_len)
+	if (sm->ptk_set)
+		key_info |= WPA_KEY_INFO_SECURE;
+	if (sm->ptk_set && mic_len)
 		key_info |= WPA_KEY_INFO_MIC;
-	else
-		key_info |= WPA_KEY_INFO_ENCR_KEY_DATA;
 	if (error)
 		key_info |= WPA_KEY_INFO_ERROR;
 	if (pairwise)
@@ -529,14 +522,11 @@
 			       const u8 *wpa_ie, size_t wpa_ie_len,
 			       struct wpa_ptk *ptk)
 {
-	size_t mic_len, hdrlen, rlen, extra_len = 0;
+	size_t mic_len, hdrlen, rlen;
 	struct wpa_eapol_key *reply;
 	u8 *rbuf, *key_mic;
 	u8 *rsn_ie_buf = NULL;
 	u16 key_info;
-#ifdef CONFIG_TESTING_OPTIONS
-	size_t pad_len = 0;
-#endif /* CONFIG_TESTING_OPTIONS */
 
 	if (wpa_ie == NULL) {
 		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: No wpa_ie set - "
@@ -560,7 +550,7 @@
 			return -1;
 		os_memcpy(rsn_ie_buf, wpa_ie, wpa_ie_len);
 		res = wpa_insert_pmkid(rsn_ie_buf, &wpa_ie_len,
-				       sm->pmk_r1_name, !sm->ft_prepend_pmkid);
+				       sm->pmk_r1_name);
 		if (res < 0) {
 			os_free(rsn_ie_buf);
 			return -1;
@@ -584,21 +574,10 @@
 
 	wpa_hexdump(MSG_DEBUG, "WPA: WPA IE for msg 2/4", wpa_ie, wpa_ie_len);
 
-#ifdef CONFIG_TESTING_OPTIONS
-	if (sm->test_eapol_m2_elems)
-		extra_len = wpabuf_len(sm->test_eapol_m2_elems);
-	if (sm->encrypt_eapol_m2) {
-		pad_len = (wpa_ie_len + extra_len) % 8;
-		if (pad_len)
-			pad_len = 8 - pad_len;
-		extra_len += pad_len + 8;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
 	mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len);
 	hdrlen = sizeof(*reply) + mic_len + 2;
 	rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY,
-				  NULL, hdrlen + wpa_ie_len + extra_len,
+				  NULL, hdrlen + wpa_ie_len,
 				  &rlen, (void *) &reply);
 	if (rbuf == NULL) {
 		os_free(rsn_ie_buf);
@@ -615,10 +594,6 @@
 		key_info |= WPA_KEY_INFO_MIC;
 	else
 		key_info |= WPA_KEY_INFO_ENCR_KEY_DATA;
-#ifdef CONFIG_TESTING_OPTIONS
-	if (sm->encrypt_eapol_m2)
-		key_info |= WPA_KEY_INFO_ENCR_KEY_DATA;
-#endif /* CONFIG_TESTING_OPTIONS */
 	WPA_PUT_BE16(reply->key_info, key_info);
 	if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN)
 		WPA_PUT_BE16(reply->key_length, 0);
@@ -630,48 +605,9 @@
 		    WPA_REPLAY_COUNTER_LEN);
 
 	key_mic = (u8 *) (reply + 1);
-	/* Key Data Length */
-	WPA_PUT_BE16(key_mic + mic_len, wpa_ie_len + extra_len);
+	WPA_PUT_BE16(key_mic + mic_len, wpa_ie_len); /* Key Data Length */
 	os_memcpy(key_mic + mic_len + 2, wpa_ie, wpa_ie_len); /* Key Data */
 	os_free(rsn_ie_buf);
-#ifdef CONFIG_TESTING_OPTIONS
-	if (sm->test_eapol_m2_elems) {
-		os_memcpy(key_mic + mic_len + 2 + wpa_ie_len,
-			  wpabuf_head(sm->test_eapol_m2_elems),
-			  wpabuf_len(sm->test_eapol_m2_elems));
-	}
-
-	if (sm->encrypt_eapol_m2) {
-		u8 *plain;
-		size_t plain_len;
-
-		if (sm->test_eapol_m2_elems)
-			extra_len = wpabuf_len(sm->test_eapol_m2_elems);
-		else
-			extra_len = 0;
-		plain_len = wpa_ie_len + extra_len + pad_len;
-		plain = os_memdup(key_mic + mic_len + 2, plain_len);
-		if (!plain) {
-			os_free(rbuf);
-			return -1;
-		}
-		if (pad_len)
-			plain[plain_len - pad_len] = 0xdd;
-
-		wpa_hexdump_key(MSG_DEBUG, "RSN: AES-WRAP using KEK",
-				ptk->kek, ptk->kek_len);
-		if (aes_wrap(ptk->kek, ptk->kek_len, plain_len / 8, plain,
-			     key_mic + mic_len + 2)) {
-			os_free(plain);
-			os_free(rbuf);
-			return -1;
-		}
-		wpa_hexdump(MSG_DEBUG,
-			    "RSN: Encrypted Key Data from AES-WRAP",
-			    key_mic + mic_len + 2, plain_len + 8);
-		os_free(plain);
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
 
 	os_memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN);
 
@@ -801,8 +737,8 @@
 	int i;
 	unsigned int num_links = 0;
 
-	for_each_link(sm->mlo.req_links, i) {
-		if (sm->mlo.assoc_link_id != i)
+	for (i = 0; i < MAX_NUM_MLO_LINKS; i++) {
+		if (sm->mlo.assoc_link_id != i && (sm->mlo.req_links & BIT(i)))
 			num_links++;
 	}
 
@@ -815,8 +751,8 @@
 	int i;
 	u8 hdr[1 + ETH_ALEN];
 
-	for_each_link(sm->mlo.req_links, i) {
-		if (sm->mlo.assoc_link_id == i)
+	for (i = 0; i < MAX_NUM_MLO_LINKS; i++) {
+		if (sm->mlo.assoc_link_id == i || !(sm->mlo.req_links & BIT(i)))
 			continue;
 
 		wpa_printf(MSG_DEBUG,
@@ -833,7 +769,7 @@
 static bool is_valid_ap_mld_mac_kde(struct wpa_sm *sm, const u8 *mac_kde)
 {
 	return mac_kde &&
-		ether_addr_equal(mac_kde, sm->mlo.ap_mld_addr);
+		os_memcmp(mac_kde, sm->mlo.ap_mld_addr, ETH_ALEN) == 0;
 }
 
 
@@ -1551,7 +1487,10 @@
 {
 	u8 i;
 
-	for_each_link(sm->mlo.valid_links, i) {
+	for (i = 0; i < MAX_NUM_MLO_LINKS; i++) {
+		if (!(sm->mlo.valid_links & BIT(i)))
+			continue;
+
 		if (!ie->mlo_gtk[i]) {
 			wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
 				"MLO RSN: GTK not found for link ID %u", i);
@@ -1900,7 +1839,10 @@
 	    sm->mgmt_group_cipher == WPA_CIPHER_GTK_NOT_USED)
 		return 0;
 
-	for_each_link(sm->mlo.valid_links, i) {
+	for (i = 0; i < MAX_NUM_MLO_LINKS; i++) {
+		if (!(sm->mlo.valid_links & BIT(i)))
+			continue;
+
 		if (_mlo_ieee80211w_set_keys(sm, i, ie))
 			return -1;
 	}
@@ -2213,10 +2155,7 @@
 	struct wpa_eapol_key *reply;
 	u8 *rbuf, *key_mic;
 	u8 *kde = NULL;
-	size_t kde_len = 0, extra_len = 0;
-#ifdef CONFIG_TESTING_OPTIONS
-	size_t pad_len = 0;
-#endif /* CONFIG_TESTING_OPTIONS */
+	size_t kde_len = 0;
 
 	if (sm->mlo.valid_links) {
 		u8 *pos;
@@ -2233,22 +2172,10 @@
 		kde_len = pos - kde;
 	}
 
-#ifdef CONFIG_TESTING_OPTIONS
-	if (sm->test_eapol_m4_elems)
-		extra_len = wpabuf_len(sm->test_eapol_m4_elems);
-	if (sm->encrypt_eapol_m4) {
-		pad_len = (kde_len + extra_len) % 8;
-		if (pad_len)
-			pad_len = 8 - pad_len;
-		extra_len += pad_len + 8;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
 	mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len);
 	hdrlen = sizeof(*reply) + mic_len + 2;
 	rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
-				  hdrlen + kde_len + extra_len, &rlen,
-				  (void *) &reply);
+				  hdrlen + kde_len, &rlen, (void *) &reply);
 	if (!rbuf) {
 		os_free(kde);
 		return -1;
@@ -2263,10 +2190,6 @@
 		key_info |= WPA_KEY_INFO_MIC;
 	else
 		key_info |= WPA_KEY_INFO_ENCR_KEY_DATA;
-#ifdef CONFIG_TESTING_OPTIONS
-	if (sm->encrypt_eapol_m4)
-		key_info |= WPA_KEY_INFO_ENCR_KEY_DATA;
-#endif /* CONFIG_TESTING_OPTIONS */
 	WPA_PUT_BE16(reply->key_info, key_info);
 	if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN)
 		WPA_PUT_BE16(reply->key_length, 0);
@@ -2276,52 +2199,12 @@
 		  WPA_REPLAY_COUNTER_LEN);
 
 	key_mic = (u8 *) (reply + 1);
-	/* Key Data length */
-	WPA_PUT_BE16(key_mic + mic_len, kde_len + extra_len);
+	WPA_PUT_BE16(key_mic + mic_len, kde_len); /* Key Data length */
 	if (kde) {
 		os_memcpy(key_mic + mic_len + 2, kde, kde_len); /* Key Data */
 		os_free(kde);
 	}
 
-#ifdef CONFIG_TESTING_OPTIONS
-	if (sm->test_eapol_m4_elems) {
-		os_memcpy(key_mic + mic_len + 2 + kde_len,
-			  wpabuf_head(sm->test_eapol_m4_elems),
-			  wpabuf_len(sm->test_eapol_m4_elems));
-	}
-
-	if (sm->encrypt_eapol_m4) {
-		u8 *plain;
-		size_t plain_len;
-
-		if (sm->test_eapol_m4_elems)
-			extra_len = wpabuf_len(sm->test_eapol_m4_elems);
-		else
-			extra_len = 0;
-		plain_len = kde_len + extra_len + pad_len;
-		plain = os_memdup(key_mic + mic_len + 2, plain_len);
-		if (!plain) {
-			os_free(rbuf);
-			return -1;
-		}
-		if (pad_len)
-			plain[plain_len - pad_len] = 0xdd;
-
-		wpa_hexdump_key(MSG_DEBUG, "RSN: AES-WRAP using KEK",
-				ptk->kek, ptk->kek_len);
-		if (aes_wrap(ptk->kek, ptk->kek_len, plain_len / 8, plain,
-			     key_mic + mic_len + 2)) {
-			os_free(plain);
-			os_free(rbuf);
-			return -1;
-		}
-		wpa_hexdump(MSG_DEBUG,
-			    "RSN: Encrypted Key Data from AES-WRAP",
-			    key_mic + mic_len + 2, plain_len + 8);
-		os_free(plain);
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
 	wpa_dbg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Sending EAPOL-Key 4/4");
 	return wpa_eapol_key_send(sm, ptk, ver, dst, ETH_P_EAPOL, rbuf, rlen,
 				  key_mic);
@@ -2343,8 +2226,9 @@
 		return -1;
 	}
 
-	if (!ether_addr_equal(sm->mlo.links[link_id].bssid,
-			      &link_kde[RSN_MLO_LINK_KDE_LINK_MAC_INDEX])) {
+	if (os_memcmp(sm->mlo.links[link_id].bssid,
+		      &link_kde[RSN_MLO_LINK_KDE_LINK_MAC_INDEX],
+		      ETH_ALEN) != 0) {
 		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
 			"RSN: MLO Link %u MAC address (" MACSTR
 			") not matching association response (" MACSTR ")",
@@ -2435,7 +2319,7 @@
 	    (unsigned int) wpa_cipher_key_len(sm->mgmt_group_cipher)) {
 		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
 			"RSN MLO: Invalid IGTK KDE length %lu for link ID %u",
-			(unsigned long) ie->mlo_igtk_len[link_id], link_id);
+			(unsigned long) ie->mlo_igtk_len, link_id);
 		return -1;
 	}
 
@@ -2447,7 +2331,7 @@
 	    (unsigned int) wpa_cipher_key_len(sm->mgmt_group_cipher)) {
 		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
 			"RSN MLO: Invalid BIGTK KDE length %lu for link ID %u",
-			(unsigned long) ie->mlo_bigtk_len[link_id], link_id);
+			(unsigned long) ie->mlo_bigtk_len, link_id);
 		return -1;
 	}
 
@@ -2926,7 +2810,10 @@
 		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
 			"MLO RSN: Failed to configure MLO IGTK");
 
-	for_each_link(sm->mlo.valid_links, i) {
+	for (i = 0; i < MAX_NUM_MLO_LINKS; i++) {
+		if (!(sm->mlo.valid_links & BIT(i)))
+			continue;
+
 		/*
 		 * AP may send group keys for subset of the all links during
 		 * rekey
@@ -4154,8 +4041,6 @@
 #endif /* CONFIG_IEEE80211R */
 #ifdef CONFIG_TESTING_OPTIONS
 	wpabuf_free(sm->test_assoc_ie);
-	wpabuf_free(sm->test_eapol_m2_elems);
-	wpabuf_free(sm->test_eapol_m4_elems);
 #endif /* CONFIG_TESTING_OPTIONS */
 #ifdef CONFIG_FILS_SK_PFS
 	crypto_ecdh_deinit(sm->fils_ecdh);
@@ -4226,7 +4111,7 @@
 	os_memset(sm->rx_replay_counter, 0, WPA_REPLAY_COUNTER_LEN);
 	sm->rx_replay_counter_set = 0;
 	sm->renew_snonce = 1;
-	if (ether_addr_equal(sm->preauth_bssid, bssid))
+	if (os_memcmp(sm->preauth_bssid, bssid, ETH_ALEN) == 0)
 		rsn_preauth_deinit(sm);
 
 #ifdef CONFIG_IEEE80211R
@@ -4672,12 +4557,6 @@
 	case WPA_PARAM_DISABLE_EAPOL_G2_TX:
 		sm->disable_eapol_g2_tx = value;
 		break;
-	case WPA_PARAM_ENCRYPT_EAPOL_M2:
-		sm->encrypt_eapol_m2 = value;
-		break;
-	case WPA_PARAM_ENCRYPT_EAPOL_M4:
-		sm->encrypt_eapol_m4 = value;
-		break;
 #endif /* CONFIG_TESTING_OPTIONS */
 #ifdef CONFIG_DPP2
 	case WPA_PARAM_DPP_PFS:
@@ -4687,9 +4566,6 @@
 	case WPA_PARAM_WMM_ENABLED:
 		sm->wmm_enabled = value;
 		break;
-	case WPA_PARAM_FT_PREPEND_PMKID:
-		sm->ft_prepend_pmkid = value;
-		break;
 	default:
 		break;
 	}
@@ -5371,20 +5247,6 @@
 }
 
 
-void wpa_sm_set_test_eapol_m2_elems(struct wpa_sm *sm, struct wpabuf *buf)
-{
-	wpabuf_free(sm->test_eapol_m2_elems);
-	sm->test_eapol_m2_elems = buf;
-}
-
-
-void wpa_sm_set_test_eapol_m4_elems(struct wpa_sm *sm, struct wpabuf *buf)
-{
-	wpabuf_free(sm->test_eapol_m4_elems);
-	sm->test_eapol_m4_elems = buf;
-}
-
-
 const u8 * wpa_sm_get_anonce(struct wpa_sm *sm)
 {
 	return sm->anonce;
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index 7d790a6..d8d0a15 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -132,9 +132,6 @@
 	WPA_PARAM_OCI_FREQ_FT_ASSOC,
 	WPA_PARAM_OCI_FREQ_FILS_ASSOC,
 	WPA_PARAM_DISABLE_EAPOL_G2_TX,
-	WPA_PARAM_ENCRYPT_EAPOL_M2,
-	WPA_PARAM_ENCRYPT_EAPOL_M4,
-	WPA_PARAM_FT_PREPEND_PMKID,
 };
 
 struct rsn_supp_config {
@@ -608,8 +605,6 @@
 
 int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf);
 void wpa_sm_set_test_assoc_ie(struct wpa_sm *sm, struct wpabuf *buf);
-void wpa_sm_set_test_eapol_m2_elems(struct wpa_sm *sm, struct wpabuf *buf);
-void wpa_sm_set_test_eapol_m4_elems(struct wpa_sm *sm, struct wpabuf *buf);
 const u8 * wpa_sm_get_anonce(struct wpa_sm *sm);
 unsigned int wpa_sm_get_key_mgmt(struct wpa_sm *sm);
 
diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c
index 9a39749..3d1dbc6 100644
--- a/src/rsn_supp/wpa_ft.c
+++ b/src/rsn_supp/wpa_ft.c
@@ -607,7 +607,7 @@
 			goto fail;
 		}
 
-		if (!ether_addr_equal(target_ap, sm->target_ap)) {
+		if (os_memcmp(target_ap, sm->target_ap, ETH_ALEN) != 0) {
 			wpa_printf(MSG_DEBUG, "FT: No over-the-DS in progress "
 				   "with this Target AP - drop FT Action "
 				   "Response");
@@ -1348,7 +1348,7 @@
 	size_t i;
 
 	for (i = 0; i < sm->n_pasn_r1kh; i++)
-		if (ether_addr_equal(sm->pasn_r1kh[i].bssid, bssid))
+		if (os_memcmp(sm->pasn_r1kh[i].bssid, bssid, ETH_ALEN) == 0)
 			return &sm->pasn_r1kh[i];
 
 	return NULL;
diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h
index ca97c12..5fe6182 100644
--- a/src/rsn_supp/wpa_i.h
+++ b/src/rsn_supp/wpa_i.h
@@ -182,16 +182,12 @@
 
 #ifdef CONFIG_TESTING_OPTIONS
 	struct wpabuf *test_assoc_ie;
-	struct wpabuf *test_eapol_m2_elems;
-	struct wpabuf *test_eapol_m4_elems;
 	int ft_rsnxe_used;
 	unsigned int oci_freq_override_eapol;
 	unsigned int oci_freq_override_eapol_g2;
 	unsigned int oci_freq_override_ft_assoc;
 	unsigned int oci_freq_override_fils_assoc;
 	unsigned int disable_eapol_g2_tx;
-	bool encrypt_eapol_m2;
-	bool encrypt_eapol_m4;
 #endif /* CONFIG_TESTING_OPTIONS */
 
 #ifdef CONFIG_FILS
@@ -227,7 +223,6 @@
 
 	bool wmm_enabled;
 	bool driver_bss_selection;
-	bool ft_prepend_pmkid;
 };
 
 
diff --git a/src/tls/libtommath.c b/src/tls/libtommath.c
index ed595bd..7156744 100644
--- a/src/tls/libtommath.c
+++ b/src/tls/libtommath.c
@@ -59,6 +59,14 @@
 
 /* from tommath.h */
 
+#ifndef MIN
+   #define MIN(x,y) ((x)<(y)?(x):(y))
+#endif
+
+#ifndef MAX
+   #define MAX(x,y) ((x)>(y)?(x):(y))
+#endif
+
 #define  OPT_CAST(x)
 
 #ifdef __x86_64__
diff --git a/src/tls/pkcs1.c b/src/tls/pkcs1.c
index 7ea9cc7..49e439d 100644
--- a/src/tls/pkcs1.c
+++ b/src/tls/pkcs1.c
@@ -322,6 +322,8 @@
 		return -1;
 	}
 
+	os_free(decrypted);
+
 	if (hdr.payload + hdr.length != decrypted + decrypted_len) {
 		wpa_printf(MSG_INFO,
 			   "PKCS #1: Extra data after signature - reject");
@@ -330,12 +332,8 @@
 			    hdr.payload + hdr.length,
 			    decrypted + decrypted_len - hdr.payload -
 			    hdr.length);
-
-		os_free(decrypted);
 		return -1;
 	}
 
-	os_free(decrypted);
-
 	return 0;
 }
diff --git a/src/utils/common.h b/src/utils/common.h
index 14c90c9..bede21e 100644
--- a/src/utils/common.h
+++ b/src/utils/common.h
@@ -9,7 +9,6 @@
 #ifndef COMMON_H
 #define COMMON_H
 
-#include "includes.h"
 #include "os.h"
 
 #if defined(__linux__) || defined(__GLIBC__)
@@ -442,13 +441,6 @@
 #define BIT(x) (1U << (x))
 #endif
 
-#ifndef MIN
-#define MIN(a, b) ((a) < (b) ? (a) : (b))
-#endif
-#ifndef MAX
-#define MAX(a, b) (((a) > (b)) ? (a) : (b))
-#endif
-
 /*
  * Definitions for sparse validation
  * (http://kernel.org/pub/linux/kernel/people/josh/sparse/)
@@ -551,11 +543,6 @@
 	return a[0] & 0x01;
 }
 
-static inline bool ether_addr_equal(const u8 *a, const u8 *b)
-{
-	return os_memcmp(a, b, ETH_ALEN) == 0;
-}
-
 #define broadcast_ether_addr (const u8 *) "\xff\xff\xff\xff\xff\xff"
 
 #include "wpa_debug.h"
@@ -600,18 +587,6 @@
 u8 rssi_to_rcpi(int rssi);
 char * get_param(const char *cmd, const char *param);
 
-#define for_each_link(__links, __i)                            \
-	for ((__i) = 0; (__i) < MAX_NUM_MLD_LINKS; (__i)++)    \
-		if ((__links) & BIT(__i))
-
-/* Iterate all links, or, if no link is defined, iterate given index */
-#define for_each_link_default(_links, _i, _def_idx)	\
-	for ((_i) = (_links) ? 0 : (_def_idx);		\
-	     (_i) < MAX_NUM_MLD_LINKS ||		\
-		     (!(_links) && (_i) == (_def_idx));	\
-	     (_i)++)					\
-		if (!(_links) || (_links) & BIT(_i))
-
 void forced_memzero(void *ptr, size_t len);
 
 /*
diff --git a/src/utils/os.h b/src/utils/os.h
index 1bbaea3..21ba5c3 100644
--- a/src/utils/os.h
+++ b/src/utils/os.h
@@ -108,26 +108,6 @@
 }
 
 
-static inline void os_reltime_add_ms(struct os_reltime *ts, int ms)
-{
-	ts->usec += ms * 1000;
-	while (ts->usec >= 1000000) {
-		ts->sec++;
-		ts->usec -= 1000000;
-	}
-	while (ts->usec < 0) {
-		ts->sec--;
-		ts->usec += 1000000;
-	}
-}
-
-
-static inline int os_reltime_in_ms(struct os_reltime *ts)
-{
-	return ts->sec * 1000 + ts->usec / 1000;
-}
-
-
 static inline int os_reltime_initialized(struct os_reltime *t)
 {
 	return t->sec != 0 || t->usec != 0;
@@ -687,24 +667,14 @@
 
 
 #if defined(WPA_TRACE_BFD) && defined(CONFIG_TESTING_OPTIONS)
-#define TEST_FAIL() testing_test_fail(NULL, false)
-#define TEST_FAIL_TAG(tag) testing_test_fail(tag, false)
-int testing_test_fail(const char *tag, bool is_alloc);
-int testing_set_fail_pattern(bool is_alloc, char *patterns);
-int testing_get_fail_pattern(bool is_alloc, char *buf, size_t buflen);
+#define TEST_FAIL() testing_test_fail()
+int testing_test_fail(void);
+extern char wpa_trace_fail_func[256];
+extern unsigned int wpa_trace_fail_after;
+extern char wpa_trace_test_fail_func[256];
+extern unsigned int wpa_trace_test_fail_after;
 #else
 #define TEST_FAIL() 0
-#define TEST_FAIL_TAG(tag) 0
-static inline int testing_set_fail_pattern(bool is_alloc, char *patterns)
-{
-	return -1;
-}
-
-static inline int testing_get_fail_pattern(bool is_alloc, char *buf,
-					   size_t buflen)
-{
-	return -1;
-}
 #endif
 
 #endif /* OS_H */
diff --git a/src/utils/os_unix.c b/src/utils/os_unix.c
index e5b656a..e721df2 100644
--- a/src/utils/os_unix.c
+++ b/src/utils/os_unix.c
@@ -566,59 +566,39 @@
 #ifdef WPA_TRACE
 
 #if defined(WPA_TRACE_BFD) && defined(CONFIG_TESTING_OPTIONS)
-struct wpa_trace_test_fail {
-	unsigned int fail_after;
-	char pattern[256];
-} wpa_trace_test_fail[5][2];
+char wpa_trace_fail_func[256] = { 0 };
+unsigned int wpa_trace_fail_after;
 
-int testing_test_fail(const char *tag, bool is_alloc)
+static int testing_fail_alloc(void)
 {
-	const char *ignore_list[] = {
-		"os_malloc", "os_zalloc", "os_calloc", "os_realloc",
-		"os_realloc_array", "os_strdup", "os_memdup"
-	};
 	const char *func[WPA_TRACE_LEN];
-	size_t i, j, res, len, idx;
+	size_t i, res, len;
 	char *pos, *next;
 	int match;
 
-	is_alloc = !!is_alloc;
-
-	for (idx = 0; idx < ARRAY_SIZE(wpa_trace_test_fail[is_alloc]); idx++) {
-		if (wpa_trace_test_fail[is_alloc][idx].fail_after != 0)
-			break;
-	}
-	if (idx >= ARRAY_SIZE(wpa_trace_test_fail[is_alloc]))
+	if (!wpa_trace_fail_after)
 		return 0;
 
 	res = wpa_trace_calling_func(func, WPA_TRACE_LEN);
 	i = 0;
-
-	if (is_alloc) {
-		/* Skip our own stack frame */
+	if (i < res && os_strcmp(func[i], __func__) == 0)
+		i++;
+	if (i < res && os_strcmp(func[i], "os_malloc") == 0)
+		i++;
+	if (i < res && os_strcmp(func[i], "os_zalloc") == 0)
+		i++;
+	if (i < res && os_strcmp(func[i], "os_calloc") == 0)
+		i++;
+	if (i < res && os_strcmp(func[i], "os_realloc") == 0)
+		i++;
+	if (i < res && os_strcmp(func[i], "os_realloc_array") == 0)
+		i++;
+	if (i < res && os_strcmp(func[i], "os_strdup") == 0)
+		i++;
+	if (i < res && os_strcmp(func[i], "os_memdup") == 0)
 		i++;
 
-		/* Skip allocation helpers */
-		for (j = 0; j < ARRAY_SIZE(ignore_list) && i < res; j++) {
-			if (os_strcmp(func[i], ignore_list[j]) == 0)
-				i++;
-		}
-	} else {
-		/* Not allocation, we might have a tag, if so, replace our
-		 * own stack frame with the tag, otherwise skip it.
-		 */
-		if (tag)
-			func[0] = tag;
-		else
-			i++;
-	}
-
-	pos = wpa_trace_test_fail[is_alloc][idx].pattern;
-
-	/* The prefixes mean:
-	 * - '=': The function needs to be next in the backtrace
-	 * - '?': The function is optionally present in the backtrace
-	 */
+	pos = wpa_trace_fail_func;
 
 	match = 0;
 	while (i < res) {
@@ -658,10 +638,10 @@
 	if (!match)
 		return 0;
 
-	wpa_trace_test_fail[is_alloc][idx].fail_after--;
-	if (wpa_trace_test_fail[is_alloc][idx].fail_after == 0) {
-		wpa_printf(MSG_INFO, "TESTING: fail at %s",
-			   wpa_trace_test_fail[is_alloc][idx].pattern);
+	wpa_trace_fail_after--;
+	if (wpa_trace_fail_after == 0) {
+		wpa_printf(MSG_INFO, "TESTING: fail allocation at %s",
+			   wpa_trace_fail_func);
 		for (i = 0; i < res; i++)
 			wpa_printf(MSG_INFO, "backtrace[%d] = %s",
 				   (int) i, func[i]);
@@ -672,83 +652,90 @@
 }
 
 
-int testing_set_fail_pattern(bool is_alloc, char *patterns)
+char wpa_trace_test_fail_func[256] = { 0 };
+unsigned int wpa_trace_test_fail_after;
+
+int testing_test_fail(void)
 {
-#ifdef WPA_TRACE_BFD
-	char *token, *context = NULL;
-	size_t idx;
+	const char *func[WPA_TRACE_LEN];
+	size_t i, res, len;
+	char *pos, *next;
+	int match;
 
-	is_alloc = !!is_alloc;
+	if (!wpa_trace_test_fail_after)
+		return 0;
 
-	os_memset(wpa_trace_test_fail[is_alloc], 0,
-		  sizeof(wpa_trace_test_fail[is_alloc]));
+	res = wpa_trace_calling_func(func, WPA_TRACE_LEN);
+	i = 0;
+	if (i < res && os_strcmp(func[i], __func__) == 0)
+		i++;
 
-	idx = 0;
-	while ((token = str_token(patterns, " \n\r\t", &context)) &&
-	       idx < ARRAY_SIZE(wpa_trace_test_fail[is_alloc])) {
-		wpa_trace_test_fail[is_alloc][idx].fail_after = atoi(token);
-		token = os_strchr(token, ':');
-		if (!token) {
-			os_memset(wpa_trace_test_fail[is_alloc], 0,
-				  sizeof(wpa_trace_test_fail[is_alloc]));
-			return -1;
+	pos = wpa_trace_test_fail_func;
+
+	match = 0;
+	while (i < res) {
+		int allow_skip = 1;
+		int maybe = 0;
+
+		if (*pos == '=') {
+			allow_skip = 0;
+			pos++;
+		} else if (*pos == '?') {
+			maybe = 1;
+			pos++;
 		}
+		next = os_strchr(pos, ';');
+		if (next)
+			len = next - pos;
+		else
+			len = os_strlen(pos);
+		if (os_memcmp(pos, func[i], len) != 0) {
+			if (maybe && next) {
+				pos = next + 1;
+				continue;
+			}
+			if (allow_skip) {
+				i++;
+				continue;
+			}
+			return 0;
+		}
+		if (!next) {
+			match = 1;
+			break;
+		}
+		pos = next + 1;
+		i++;
+	}
+	if (!match)
+		return 0;
 
-		os_strlcpy(wpa_trace_test_fail[is_alloc][idx].pattern,
-			   token + 1,
-			   sizeof(wpa_trace_test_fail[is_alloc][0].pattern));
-		idx++;
+	wpa_trace_test_fail_after--;
+	if (wpa_trace_test_fail_after == 0) {
+		wpa_printf(MSG_INFO, "TESTING: fail at %s",
+			   wpa_trace_test_fail_func);
+		for (i = 0; i < res; i++)
+			wpa_printf(MSG_INFO, "backtrace[%d] = %s",
+				   (int) i, func[i]);
+		return 1;
 	}
 
 	return 0;
-#else /* WPA_TRACE_BFD */
-	return -1;
-#endif /* WPA_TRACE_BFD */
 }
 
+#else
 
-int testing_get_fail_pattern(bool is_alloc, char *buf, size_t buflen)
-{
-#ifdef WPA_TRACE_BFD
-	size_t idx, ret;
-	char *pos = buf;
-	char *end = buf + buflen;
-
-	is_alloc = !!is_alloc;
-
-	for (idx = 0; idx < ARRAY_SIZE(wpa_trace_test_fail[is_alloc]); idx++) {
-		if (wpa_trace_test_fail[is_alloc][idx].pattern[0] == '\0')
-			break;
-
-		ret = os_snprintf(pos, end - pos, "%s%u:%s",
-				  pos == buf ? "" : " ",
-				  wpa_trace_test_fail[is_alloc][idx].fail_after,
-				  wpa_trace_test_fail[is_alloc][idx].pattern);
-		if (os_snprintf_error(end - pos, ret))
-			break;
-		pos += ret;
-	}
-
-	return pos - buf;
-#else /* WPA_TRACE_BFD */
-	return -1;
-#endif /* WPA_TRACE_BFD */
-}
-
-#else /* defined(WPA_TRACE_BFD) && defined(CONFIG_TESTING_OPTIONS) */
-
-static inline int testing_test_fail(const char *tag, bool is_alloc)
+static inline int testing_fail_alloc(void)
 {
 	return 0;
 }
-
 #endif
 
 void * os_malloc(size_t size)
 {
 	struct os_alloc_trace *a;
 
-	if (testing_test_fail(NULL, true))
+	if (testing_fail_alloc())
 		return NULL;
 
 	a = malloc(sizeof(*a) + size);
diff --git a/src/utils/trace.c b/src/utils/trace.c
index 7c9a17f..8f12da8 100644
--- a/src/utils/trace.c
+++ b/src/utils/trace.c
@@ -197,7 +197,7 @@
 	if (abfd == NULL)
 		return;
 
-	data.pc = (uintptr_t) ((u8 *) pc - start_offset);
+	data.pc = (bfd_hostptr_t) ((u8 *) pc - start_offset);
 	data.found = FALSE;
 	bfd_map_over_sections(abfd, find_addr_sect, &data);
 
@@ -238,7 +238,7 @@
 	if (abfd == NULL)
 		return NULL;
 
-	data.pc = (uintptr_t) ((u8 *) pc - start_offset);
+	data.pc = (bfd_hostptr_t) ((u8 *) pc - start_offset);
 	data.found = FALSE;
 	bfd_map_over_sections(abfd, find_addr_sect, &data);
 
@@ -310,7 +310,7 @@
 	for (i = 0; i < btrace_num; i++) {
 		struct bfd_data data;
 
-		data.pc = (uintptr_t) ((u8 *) btrace_res[i] - start_offset);
+		data.pc = (bfd_hostptr_t) ((u8 *) btrace_res[i] - start_offset);
 		data.found = FALSE;
 		bfd_map_over_sections(abfd, find_addr_sect, &data);
 
diff --git a/src/wps/wps.c b/src/wps/wps.c
index fd5bd93..1fe3806 100644
--- a/src/wps/wps.c
+++ b/src/wps/wps.c
@@ -146,7 +146,6 @@
 	}
 
 	data->multi_ap_backhaul_sta = cfg->multi_ap_backhaul_sta;
-	data->multi_ap_profile = cfg->multi_ap_profile;
 
 	return data;
 }
@@ -337,9 +336,9 @@
 
 	pos = attr.authorized_macs;
 	for (i = 0; i < attr.authorized_macs_len / ETH_ALEN; i++) {
-		if (ether_addr_equal(pos, addr))
+		if (os_memcmp(pos, addr, ETH_ALEN) == 0)
 			return 2;
-		if (ether_addr_equal(pos, bcast))
+		if (os_memcmp(pos, bcast, ETH_ALEN) == 0)
 			return 1;
 		pos += ETH_ALEN;
 	}
diff --git a/src/wps/wps.h b/src/wps/wps.h
index b99ae94..fed3e28 100644
--- a/src/wps/wps.h
+++ b/src/wps/wps.h
@@ -195,11 +195,6 @@
 	 * enrollee
 	 */
 	int multi_ap_backhaul_sta;
-
-	/*
-	 * multi_ap_profile - Get the Multi-AP Profile
-	 */
-	int multi_ap_profile;
 };
 
 struct wps_data * wps_init(const struct wps_config *cfg);
diff --git a/src/wps/wps_enrollee.c b/src/wps/wps_enrollee.c
index af828e5..819cd43 100644
--- a/src/wps/wps_enrollee.c
+++ b/src/wps/wps_enrollee.c
@@ -715,7 +715,8 @@
 	    wps_process_cred(&attr, &wps->cred))
 		return -1;
 
-	if (!ether_addr_equal(wps->cred.mac_addr, wps->wps->dev.mac_addr)) {
+	if (os_memcmp(wps->cred.mac_addr, wps->wps->dev.mac_addr, ETH_ALEN) !=
+	    0) {
 		wpa_printf(MSG_DEBUG, "WPS: MAC Address in the Credential ("
 			   MACSTR ") does not match with own address (" MACSTR
 			   ")", MAC2STR(wps->cred.mac_addr),
@@ -814,7 +815,8 @@
 	wpa_printf(MSG_INFO, "WPS: Received new AP configuration from "
 		   "Registrar");
 
-	if (!ether_addr_equal(cred.mac_addr, wps->wps->dev.mac_addr)) {
+	if (os_memcmp(cred.mac_addr, wps->wps->dev.mac_addr, ETH_ALEN) !=
+	    0) {
 		wpa_printf(MSG_DEBUG, "WPS: MAC Address in the AP Settings ("
 			   MACSTR ") does not match with own address (" MACSTR
 			   ")", MAC2STR(cred.mac_addr),
diff --git a/src/wps/wps_er.c b/src/wps/wps_er.c
index dede64b..31d2e50 100644
--- a/src/wps/wps_er.c
+++ b/src/wps/wps_er.c
@@ -62,7 +62,7 @@
 	struct wps_er_sta *sta;
 	dl_list_for_each(sta, &ap->sta, struct wps_er_sta, list) {
 		if ((addr == NULL ||
-		     ether_addr_equal(sta->addr, addr)) &&
+		     os_memcmp(sta->addr, addr, ETH_ALEN) == 0) &&
 		    (uuid == NULL ||
 		     os_memcmp(uuid, sta->uuid, WPS_UUID_LEN) == 0))
 			return sta;
@@ -106,7 +106,7 @@
 		    (uuid == NULL ||
 		     os_memcmp(uuid, ap->uuid, WPS_UUID_LEN) == 0) &&
 		    (mac_addr == NULL ||
-		     ether_addr_equal(mac_addr, ap->mac_addr)))
+		     os_memcmp(mac_addr, ap->mac_addr, ETH_ALEN) == 0))
 			return ap;
 	}
 	return NULL;
diff --git a/src/wps/wps_i.h b/src/wps/wps_i.h
index 5486e2a..2cf22d4 100644
--- a/src/wps/wps_i.h
+++ b/src/wps/wps_i.h
@@ -127,7 +127,6 @@
 	struct wps_nfc_pw_token *nfc_pw_token;
 
 	int multi_ap_backhaul_sta;
-	int multi_ap_profile;
 };
 
 
diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c
index f49784f..9587293 100644
--- a/src/wps/wps_registrar.c
+++ b/src/wps/wps_registrar.c
@@ -238,7 +238,7 @@
 	wpa_printf(MSG_DEBUG, "WPS: Add authorized MAC " MACSTR,
 		   MAC2STR(addr));
 	for (i = 0; i < WPS_MAX_AUTHORIZED_MACS; i++)
-		if (ether_addr_equal(reg->authorized_macs[i], addr)) {
+		if (os_memcmp(reg->authorized_macs[i], addr, ETH_ALEN) == 0) {
 			wpa_printf(MSG_DEBUG, "WPS: Authorized MAC was "
 				   "already in the list");
 			return; /* already in list */
@@ -259,7 +259,7 @@
 	wpa_printf(MSG_DEBUG, "WPS: Remove authorized MAC " MACSTR,
 		   MAC2STR(addr));
 	for (i = 0; i < WPS_MAX_AUTHORIZED_MACS; i++) {
-		if (ether_addr_equal(reg->authorized_macs[i], addr))
+		if (os_memcmp(reg->authorized_macs, addr, ETH_ALEN) == 0)
 			break;
 	}
 	if (i == WPS_MAX_AUTHORIZED_MACS) {
@@ -296,7 +296,7 @@
 	struct wps_registrar_device *dev;
 
 	for (dev = reg->devices; dev; dev = dev->next) {
-		if (ether_addr_equal(dev->dev.mac_addr, addr))
+		if (os_memcmp(dev->dev.mac_addr, addr, ETH_ALEN) == 0)
 			return dev;
 	}
 	return NULL;
@@ -353,7 +353,7 @@
 
 	pbc = reg->pbc_sessions;
 	while (pbc) {
-		if (ether_addr_equal(pbc->addr, addr) &&
+		if (os_memcmp(pbc->addr, addr, ETH_ALEN) == 0 &&
 		    os_memcmp(pbc->uuid_e, uuid_e, WPS_UUID_LEN) == 0) {
 			if (prev)
 				prev->next = pbc->next;
@@ -405,7 +405,8 @@
 	while (pbc) {
 		if (os_memcmp(pbc->uuid_e, uuid_e, WPS_UUID_LEN) == 0 ||
 		    (p2p_dev_addr && !is_zero_ether_addr(reg->p2p_dev_addr) &&
-		     ether_addr_equal(reg->p2p_dev_addr, p2p_dev_addr))) {
+		     os_memcmp(reg->p2p_dev_addr, p2p_dev_addr, ETH_ALEN) ==
+		     0)) {
 			if (prev)
 				prev->next = pbc->next;
 			else
@@ -2610,7 +2611,7 @@
 	if (is_zero_ether_addr(reg->p2p_dev_addr))
 		return 1; /* no filtering in use */
 
-	if (!ether_addr_equal(reg->p2p_dev_addr, wps->p2p_dev_addr)) {
+	if (os_memcmp(reg->p2p_dev_addr, wps->p2p_dev_addr, ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG, "WPS: No match on P2P Device Address "
 			   "filtering for PBC: expected " MACSTR " was "
 			   MACSTR " - indicate PBC session overlap",
@@ -2631,7 +2632,7 @@
 	if (is_zero_ether_addr(reg->p2p_dev_addr))
 		return 0; /* no specific Enrollee selected */
 
-	if (ether_addr_equal(reg->p2p_dev_addr, wps->p2p_dev_addr)) {
+	if (os_memcmp(reg->p2p_dev_addr, wps->p2p_dev_addr, ETH_ALEN) == 0) {
 		wpa_printf(MSG_DEBUG, "WPS: Skip PBC overlap due to selected "
 			   "Enrollee match");
 		return 1;
diff --git a/wpa_supplicant/Android.bp b/wpa_supplicant/Android.bp
index 347ff39..e6ba165 100644
--- a/wpa_supplicant/Android.bp
+++ b/wpa_supplicant/Android.bp
@@ -331,7 +331,6 @@
         "src/common/sae.c",
         "src/common/sae_pk.c",
         "src/common/wpa_common.c",
-        "src/common/ptksa_cache.c",
         "src/crypto/aes-ctr.c",
         "src/crypto/aes-encblock.c",
         "src/crypto/aes-siv.c",
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index 952d1be..98152be 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -139,9 +139,11 @@
 OBJS += src/utils/bitfield.c
 OBJS += src/utils/ip_addr.c
 OBJS += src/utils/crc32.c
-OBJS += src/common/ptksa_cache.c
-OBJS += src/rsn_supp/pmksa_cache.c
+OBJS += wmm_ac.c
+OBJS += op_classes.c
+OBJS += rrm.c
 OBJS += twt.c
+OBJS += robust_av.c
 OBJS_p = wpa_passphrase.c
 OBJS_p += src/utils/common.c
 OBJS_p += src/utils/wpa_debug.c
@@ -322,12 +324,6 @@
 endif
 endif
 
-ifdef CONFIG_NAN_USD
-OBJS += src/common/nan_de.c
-OBJS += nan_usd.c
-L_CFLAGS += -DCONFIG_NAN_USD
-endif
-
 ifdef CONFIG_OWE
 L_CFLAGS += -DCONFIG_OWE
 NEED_ECC=y
@@ -356,10 +352,6 @@
 CONFIG_WNM=y
 endif
 
-ifdef CONFIG_BGSCAN_SIMPLE
-CONFIG_WNM=y
-endif
-
 ifdef CONFIG_WNM
 L_CFLAGS += -DCONFIG_WNM
 OBJS += wnm_sta.c
@@ -381,6 +373,7 @@
 ifndef CONFIG_NO_WPA
 OBJS += src/rsn_supp/wpa.c
 OBJS += src/rsn_supp/preauth.c
+OBJS += src/rsn_supp/pmksa_cache.c
 OBJS += src/rsn_supp/wpa_ie.c
 OBJS += src/common/wpa_common.c
 NEED_AES=y
@@ -433,8 +426,8 @@
 NEED_HMAC_SHA384_KDF=y
 NEED_SHA256=y
 NEED_SHA384=y
+OBJS += src/common/ptksa_cache.c
 OBJS += src/pasn/pasn_initiator.c
-OBJS += src/pasn/pasn_common.c
 OBJS += pasn_supplicant.c
 endif
 
@@ -473,28 +466,6 @@
 L_CFLAGS += -DCONFIG_NO_TKIP
 endif
 
-ifdef CONFIG_NO_RRM
-L_CFLAGS += -DCONFIG_NO_RRM
-else
-OBJS += rrm.c
-ifdef CONFIG_AP
-OBJS += src/ap/rrm.c
-endif
-OBJS += op_classes.c
-endif
-
-ifdef CONFIG_NO_WMM_AC
-L_CFLAGS += -DCONFIG_NO_WMM_AC
-else
-OBJS += wmm_ac.c
-endif
-
-ifdef CONFIG_NO_ROBUST_AV
-L_CFLAGS += -DCONFIG_NO_ROBUST_AV
-else
-OBJS += robust_av.c
-endif
-
 
 include $(LOCAL_PATH)/src/drivers/drivers.mk
 
@@ -978,6 +949,7 @@
 OBJS += src/ap/bss_load.c
 OBJS += src/ap/eap_user_db.c
 OBJS += src/ap/neighbor_db.c
+OBJS += src/ap/rrm.c
 OBJS += src/ap/ieee802_11_ht.c
 ifdef CONFIG_IEEE80211AC
 OBJS += src/ap/ieee802_11_vht.c
@@ -1038,9 +1010,6 @@
 OBJS += src/ap/gas_query_ap.c
 NEED_AP_GAS_SERV=y
 endif
-ifdef CONFIG_NAN_USD
-OBJS += src/ap/nan_usd_ap.c
-endif
 ifdef CONFIG_INTERWORKING
 NEED_AP_GAS_SERV=y
 endif
@@ -1059,7 +1028,6 @@
 
 ifdef CONFIG_TESTING_OPTIONS
 L_CFLAGS += -DCONFIG_TESTING_OPTIONS
-NEED_AES_WRAP=y
 endif
 
 ifdef NEED_RSN_AUTHENTICATOR
@@ -1847,9 +1815,8 @@
 
 PASNOBJS += src/common/ptksa_cache.c
 
-PASNOBJS += src/rsn_supp/pmksa_cache.c
-
 ifndef CONFIG_NO_WPA
+PASNOBJS += src/rsn_supp/pmksa_cache.c
 PASNOBJS += src/rsn_supp/wpa_ie.c
 endif
 
@@ -1935,7 +1902,6 @@
 
 PASNOBJS += src/pasn/pasn_initiator.c
 PASNOBJS += src/pasn/pasn_responder.c
-PASNOBJS += src/pasn/pasn_common.c
 
 ########################
 
diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
index 8bec178..8c417b8 100644
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -64,7 +64,6 @@
 CFLAGS += -DCONFIG_TESTING_OPTIONS
 CONFIG_WPS_TESTING=y
 CONFIG_TDLS_TESTING=y
-NEED_AES_WRAP=y
 endif
 
 mkconfig:
@@ -112,9 +111,10 @@
 OBJS += ../src/utils/bitfield.o
 OBJS += ../src/utils/ip_addr.o
 OBJS += ../src/utils/crc32.o
-OBJS += ../src/common/ptksa_cache.o
-OBJS += ../src/rsn_supp/pmksa_cache.o
+OBJS += op_classes.o
+OBJS += rrm.o
 OBJS += twt.o
+OBJS += robust_av.o
 OBJS_p = wpa_passphrase.o
 OBJS_p += ../src/utils/common.o
 OBJS_p += ../src/utils/wpa_debug.o
@@ -123,6 +123,7 @@
 OBJS_c += ../src/utils/wpa_debug.o
 OBJS_c += ../src/utils/common.o
 OBJS_c += ../src/common/cli.o
+OBJS += wmm_ac.o
 
 ifndef CONFIG_OS
 ifdef CONFIG_NATIVE_WINDOWS
@@ -191,7 +192,7 @@
 endif
 
 ifdef CONFIG_CODE_COVERAGE
-CFLAGS += -O0 -fprofile-arcs -ftest-coverage -U_FORTIFY_SOURCE
+CFLAGS += -O0 -fprofile-arcs -ftest-coverage
 LIBS += -lgcov
 LIBS_c += -lgcov
 LIBS_p += -lgcov
@@ -317,12 +318,6 @@
 endif
 endif
 
-ifdef CONFIG_NAN_USD
-OBJS += ../src/common/nan_de.o
-OBJS += nan_usd.o
-CFLAGS += -DCONFIG_NAN_USD
-endif
-
 ifdef CONFIG_OWE
 CFLAGS += -DCONFIG_OWE
 NEED_ECC=y
@@ -351,10 +346,6 @@
 CONFIG_WNM=y
 endif
 
-ifdef CONFIG_BGSCAN_SIMPLE
-CONFIG_WNM=y
-endif
-
 ifdef CONFIG_WNM
 CFLAGS += -DCONFIG_WNM
 OBJS += wnm_sta.o
@@ -376,6 +367,7 @@
 ifndef CONFIG_NO_WPA
 OBJS += ../src/rsn_supp/wpa.o
 OBJS += ../src/rsn_supp/preauth.o
+OBJS += ../src/rsn_supp/pmksa_cache.o
 OBJS += ../src/rsn_supp/wpa_ie.o
 OBJS += ../src/common/wpa_common.o
 NEED_AES=y
@@ -436,8 +428,8 @@
 NEED_HMAC_SHA384_KDF=y
 NEED_SHA256=y
 NEED_SHA384=y
+OBJS += ../src/common/ptksa_cache.o
 OBJS += ../src/pasn/pasn_initiator.o
-OBJS += ../src/pasn/pasn_common.o
 OBJS += pasn_supplicant.o
 endif
 
@@ -485,28 +477,6 @@
 CFLAGS += -DCONFIG_NO_LOAD_DYNAMIC_EAP
 endif
 
-ifdef CONFIG_NO_RRM
-CFLAGS += -DCONFIG_NO_RRM
-else
-OBJS += rrm.o
-ifdef CONFIG_AP
-OBJS += ../src/ap/rrm.o
-endif
-OBJS += op_classes.o
-endif
-
-ifdef CONFIG_NO_WMM_AC
-CFLAGS += -DCONFIG_NO_WMM_AC
-else
-OBJS += wmm_ac.o
-endif
-
-ifdef CONFIG_NO_ROBUST_AV
-CFLAGS += -DCONFIG_NO_ROBUST_AV
-else
-OBJS += robust_av.o
-endif
-
 include ../src/drivers/drivers.mak
 ifdef CONFIG_AP
 OBJS_d += $(DRV_BOTH_OBJS)
@@ -1013,6 +983,7 @@
 OBJS += ../src/ap/bss_load.o
 OBJS += ../src/ap/eap_user_db.o
 OBJS += ../src/ap/neighbor_db.o
+OBJS += ../src/ap/rrm.o
 OBJS += ../src/ap/ieee802_11_ht.o
 ifdef CONFIG_IEEE80211AC
 OBJS += ../src/ap/ieee802_11_vht.o
@@ -1073,9 +1044,6 @@
 OBJS += ../src/ap/gas_query_ap.o
 NEED_AP_GAS_SERV=y
 endif
-ifdef CONFIG_NAN_USD
-OBJS += ../src/ap/nan_usd_ap.o
-endif
 ifdef CONFIG_INTERWORKING
 NEED_AP_GAS_SERV=y
 endif
@@ -1090,7 +1058,6 @@
 ifdef CONFIG_MBO
 OBJS += mbo.o
 CFLAGS += -DCONFIG_MBO
-NEED_GAS=y
 endif
 
 ifdef NEED_RSN_AUTHENTICATOR
@@ -1109,20 +1076,17 @@
 
 ifdef CONFIG_PCSC
 # PC/SC interface for smartcards (USIM, GSM SIM)
-CFLAGS += -DPCSC_FUNCS
+CFLAGS += -DPCSC_FUNCS -I/usr/include/PCSC
 OBJS += ../src/utils/pcsc_funcs.o
 ifdef CONFIG_NATIVE_WINDOWS
 #Once MinGW gets support for WinScard, -lwinscard could be used instead of the
 #dynamic symbol loading that is now used in pcsc_funcs.c
 #LIBS += -lwinscard
-CFLAGS += -I/usr/include/PCSC
 else
 ifdef CONFIG_OSX
 LIBS += -framework PCSC
-CFLAGS += -I/usr/include/PCSC
 else
 LIBS += $(shell $(PKG_CONFIG) --libs libpcsclite)
-CFLAGS += $(shell $(PKG_CONFIG) --cflags libpcsclite)
 endif
 endif
 endif
@@ -1188,10 +1152,6 @@
 CFLAGS += -DCONFIG_TLSV12
 endif
 
-ifdef CONFIG_RADIUS_TLS
-TLS_FUNCS=y
-endif
-
 ifeq ($(CONFIG_TLS), wolfssl)
 ifdef TLS_FUNCS
 CFLAGS += -DWOLFSSL_DER_LOAD
@@ -1930,9 +1890,6 @@
 OBJS_t := $(OBJS) $(OBJS_l2) eapol_test.o
 OBJS_t += ../src/radius/radius_client.o
 OBJS_t += ../src/radius/radius.o
-ifdef CONFIG_RADIUS_TLS
-CFLAGS += -DCONFIG_RADIUS_TLS
-endif
 OBJS_t2 := $(OBJS) $(OBJS_l2) preauth_test.o
 
 OBJS_nfc := $(OBJS) $(OBJS_l2) nfc_pw_token.o
@@ -2227,9 +2184,9 @@
 endif
 
 LIBPASNSO += ../src/common/ptksa_cache.c
-LIBPASNSO += ../src/rsn_supp/pmksa_cache.c
 
 ifndef CONFIG_NO_WPA
+LIBPASNSO += ../src/rsn_supp/pmksa_cache.c
 LIBPASNSO += ../src/rsn_supp/wpa_ie.c
 endif
 
@@ -2324,7 +2281,6 @@
 
 LIBPASNSO += ../src/pasn/pasn_initiator.c
 LIBPASNSO += ../src/pasn/pasn_responder.c
-LIBPASNSO += ../src/pasn/pasn_common.c
 
 libpasn.so: $(LIBPASNSO)
 	@$(E) "  CC  $@ ($^)"
diff --git a/wpa_supplicant/README-NAN-USD b/wpa_supplicant/README-NAN-USD
deleted file mode 100644
index 5dfe6ee..0000000
--- a/wpa_supplicant/README-NAN-USD
+++ /dev/null
@@ -1,147 +0,0 @@
-Wi-Fi Aware unsynchronized service discovery (NAN USD)
-======================================================
-
-This document descibes how the unsynchronized service discovery defined
-in the Wi-Fi Aware specification v4.0 can be used with wpa_spplicant.
-
-More information about Wi-Fi Aware is available from this Wi-Fi
-Alliance web page:
-https://www.wi-fi.org/discover-wi-fi/wi-fi-aware
-
-Build config setup
-------------------
-
-The following parameters must be included in the config file used to
-compile hostapd and wpa_supplicant.
-
-wpa_supplicant build config
----------------------------
-
-Enable NAN USD in wpa_supplicant build config file
-
-CONFIG_NAN_USD=y
-
-Control interface commands and events
--------------------------------------
-
-Following control interface commands can be used:
-
-NAN_PUBLISH service_name=<name> [ttl=<time-to-live-in-sec>] [freq=<in MHz>] [freq_list=<comma separate list of MHz>] [srv_proto_type=<type>] [ssi=<service specific information (hexdump)>] [solicited=0] [unsolicited=0] [fsd=0]
-
-If ttl=0 or the parameter is not included, only one Publish message is
-transmitted.
-
-If freq is not included, the default frequency 2437 MHz (channel 6 on
-the 2.4 GHz band) is used.
-
-If freq_list is included, publisher iterates over all the listed
-channels. A special freq_list=all value can be used to generate the
-channel list automatically based on the list of allowed 2.4 and 5 GHz
-channels.
-
-srv_proto_type values are defined in the Service Protocol Types table in
-the Wi-Fi Aware specification.
-
-This command returns the assigned publish_id value or FAIL on failure.
-
-This command maps to the Publish() method in the NAN Discovery Engine.
-
-NAN_CANCEL_PUBLISH publish_id=<id from NAN_PUBLISH>
-
-This command maps to the CancelPublish() method in the NAN Discovery
-Engine.
-
-NAN_UPDATE_PUBLISH publish_id=<id from NAN_PUBLISH> [ssi=<service specific information (hexdump)>]
-
-This command maps to the UpdatePublish() method in the NAN Discovery
-Engine.
-
-NAN_SUBSCRIBE service_name=<name> [active=1] [ttl=<time-to-live-in-sec>] [freq=<in MHz>] [srv_proto_type=<type>] [ssi=<service specific information (hexdump)>]
-
-If ttl=0 or the parameter is not included, operation is terminated once
-the first matching publisher is found.
-
-If freq is not included, the default frequency 2437 MHz (channel 6 on
-the 2.4 GHz band) is used.
-
-srv_proto_type values are defined in the Service Protocol Types table in
-the Wi-Fi Aware specification.
-
-This command returns the assigned subscribe_id value or FAIL on failure.
-
-This command maps to the Subscribe() method in the NAN Discovery Engine.
-
-NAN_CANCEL_SUBSCRIBE subscribe_id=<id from NAN_SUBSCRIBE>
-
-This command maps to the CancelSubscribe() method in the NAN Discovery Engine.
-
-NAN_TRANSMIT handle=<id from NAN_PUBLISH or NAN_SUBSCRIBE> req_instance=<peer's id> address=<peer's MAC address> [ssi=<service specific information (hexdump)>]
-
-This command maps to the Transmit() method in the NAN Discovery Engine.
-
-Following control interface events are used:
-
-NAN-DISCOVERY-RESULT subscribe_id=<own id> publish_id=<peer's id> address=<peer MAC address> fsd=<0/1> fsd_gas=<0/1> srv_proto_type=<type> ssi=<service specific information (hexdump)>
-
-This event maps to the DiscoveryResult() event in the NAN Discovery
-Engine.
-
-NAN-REPLIED publish_id=<own id> address=<peer MAC address> subscribe_id=<peer id> srv_proto_type=<ype> ssi=<service specific information (hexdump)>
-
-This event maps to the Replied() event in the NAN Discovery Engine.
-
-NAN-PUBLISH-TERMINATED publish_id=<own id> reason=<timeout/user-request/failure>
-
-This event maps to the PublishTerminated() event in the NAN Discovery
-Engine.
-
-NAN-SUBSCRIBE-TERMINATED subscribe_id=<own id> reason=<timeout/user-request/failure>
-
-This event maps to the SubscribeTerminate() event in the NAN Discovery
-Engine.
-
-NAN-RECEIVE id=<own id> peer_instance_id=<peer id> address=<peer MAC adress> ssi=<service specific information (hexdump)>
-
-This event maps to the Receive() event in the NAN Discovery Engine.
-
-
-Example operation
------------------
-
-Start Subscribe and Publish functions:
-
-dev0: NAN_SUBSCRIBE service_name=_test srv_proto_type=3 ssi=1122334455
---> returns 7
-
-dev1: NAN_PUBLISH service_name=_test srv_proto_type=3 ssi=6677
---> returns 5
-
-Subscriber notification of a discovery:
-
-event on dev0: <3>NAN-DISCOVERY-RESULT subscribe_id=7 publish_id=5 address=02:00:00:00:01:00 fsd=1 fsd_gas=0 srv_proto_type=3 ssi=6677
-
-Publisher notification of a Follow-up message with no ssi (to enter
-paused state to continue exchange with the subscriber):
-
-event on dev1: <3>NAN-RECEIVE id=5 peer_instance_id=7 address=02:00:00:00:00:00 ssi=
-
-Subscriber sending a Follow-up message:
-
-dev0: NAN_TRANSMIT handle=7 req_instance_id=5 address=02:00:00:00:01:00 ssi=8899
-
-Publisher receiving the Follow-up message:
-
-event on dev1: <3>NAN-RECEIVE id=5 peer_instance_id=7 address=02:00:00:00:00:00 ssi=8899
-
-Publisher sending a Follow-up message:
-
-dev1: NAN_TRANSMIT handle=5 req_instance_id=7 address=02:00:00:00:00:00 ssi=aabbccdd
-
-Subscriber receiving the Follow-up message:
-
-event on dev0: <3>NAN-RECEIVE id=7 peer_instance_id=5 address=02:00:00:00:01:00 ssi=aabbccdd
-
-Stop Subscribe and Publish functions:
-
-dev0: NAN_CANCEL_SUBSCRIBE subscribe_id=7
-dev1: NAN_CANCEL_PUBLIST publish_id=5
diff --git a/wpa_supplicant/aidl/supplicant.cpp b/wpa_supplicant/aidl/supplicant.cpp
index ae1943f..1589dd2 100644
--- a/wpa_supplicant/aidl/supplicant.cpp
+++ b/wpa_supplicant/aidl/supplicant.cpp
@@ -413,7 +413,7 @@
 		// Request the current scan results from the driver and update
 		// the local BSS list wpa_s->bss. This is to avoid a full scan
 		// while processing the connect request on newly created interface.
-		wpa_supplicant_update_scan_results(wpa_s, NULL);
+		wpa_supplicant_update_scan_results(wpa_s);
 	}
 	// The supplicant core creates a corresponding aidl object via
 	// AidlManager when |wpa_supplicant_add_iface| is called.
@@ -472,7 +472,7 @@
 		// Request the current scan results from the driver and update
 		// the local BSS list wpa_s->bss. This is to avoid a full scan
 		// while processing the connect request on newly created interface.
-		wpa_supplicant_update_scan_results(wpa_s, NULL);
+		wpa_supplicant_update_scan_results(wpa_s);
 	}
 	// The supplicant core creates a corresponding aidl object via
 	// AidlManager when |wpa_supplicant_add_iface| is called.
diff --git a/wpa_supplicant/android.config b/wpa_supplicant/android.config
index 42e2237..4cc3808 100644
--- a/wpa_supplicant/android.config
+++ b/wpa_supplicant/android.config
@@ -564,19 +564,4 @@
 # WPA3-Personal (SAE) PK (Public Key) mode
 CONFIG_SAE_PK=y
 
-# Disable support for Radio Measurement (IEEE 802.11k) and supported operating
-# class indication. Removing these is not recommended since they can help the
-# AP manage the network and STA steering.
-#CONFIG_NO_RRM=y
-
-# Disable support for Robust AV streaming for consumer and enterprise Wi-Fi
-# applications; IEEE Std 802.11-2020, 4.3.24; SCS, MSCS, QoS Management
-#CONFIG_NO_ROBUST_AV=y
-
-# Disable support for WMM admission control
-#CONFIG_NO_WMM_AC=y
-
-# Wi-Fi Aware unsynchronized service discovery (NAN USD)
-#CONFIG_NAN_USD=y
-
 include $(wildcard $(LOCAL_PATH)/android_config_*.inc)
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index 69a0e5e..1b94fe5 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -440,14 +440,9 @@
 		}
 	}
 
-#ifdef CONFIG_P2P
-	if (ssid->p2p_group && wpa_s->p2p_go_no_pri_sec_switch) {
+	if (wpa_s->p2p_go_no_pri_sec_switch) {
 		conf->no_pri_sec_switch = 1;
-		return 0;
-	}
-#endif /* CONFIG_P2P */
-
-	if (conf->secondary_channel) {
+	} else if (conf->secondary_channel) {
 		struct wpa_supplicant *iface;
 
 		for (iface = wpa_s->global->ifaces; iface; iface = iface->next)
@@ -873,8 +868,7 @@
 
 
 static void ap_sta_authorized_cb(void *ctx, const u8 *mac_addr,
-				 int authorized, const u8 *p2p_dev_addr,
-				 const u8 *ip)
+				 int authorized, const u8 *p2p_dev_addr, const u8 *ip)
 {
 	wpas_notify_sta_authorized(ctx, mac_addr, authorized, p2p_dev_addr, ip);
 }
@@ -1854,8 +1848,6 @@
 	if (ret)
 		return ret;
 
-	settings.link_id = -1;
-
 	return ap_switch_channel(wpa_s, &settings);
 }
 #endif /* CONFIG_CTRL_IFACE */
diff --git a/wpa_supplicant/bgscan.h b/wpa_supplicant/bgscan.h
index 4388b4e..3df1550 100644
--- a/wpa_supplicant/bgscan.h
+++ b/wpa_supplicant/bgscan.h
@@ -51,7 +51,7 @@
 #else /* CONFIG_BGSCAN */
 
 static inline int bgscan_init(struct wpa_supplicant *wpa_s,
-			      struct wpa_ssid *ssid, const char *name)
+			      struct wpa_ssid *ssid, const char name)
 {
 	return 0;
 }
diff --git a/wpa_supplicant/bgscan_learn.c b/wpa_supplicant/bgscan_learn.c
index cab4ae2..9830c4a 100644
--- a/wpa_supplicant/bgscan_learn.c
+++ b/wpa_supplicant/bgscan_learn.c
@@ -57,7 +57,7 @@
 		return 0;
 
 	for (i = 0; i < array_len; i++) {
-		if (ether_addr_equal(array + i * ETH_ALEN, bssid))
+		if (os_memcmp(array + i * ETH_ALEN, bssid, ETH_ALEN) == 0)
 			return 1;
 	}
 
@@ -70,7 +70,7 @@
 {
 	u8 *n;
 
-	if (ether_addr_equal(bss->bssid, bssid))
+	if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0)
 		return;
 	if (bssid_in_array(bss->neigh, bss->num_neigh, bssid))
 		return;
@@ -91,7 +91,7 @@
 	struct bgscan_learn_bss *bss;
 
 	dl_list_for_each(bss, &data->bss, struct bgscan_learn_bss, list) {
-		if (ether_addr_equal(bss->bssid, bssid))
+		if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0)
 			return bss;
 	}
 	return NULL;
diff --git a/wpa_supplicant/bgscan_simple.c b/wpa_supplicant/bgscan_simple.c
index a90cf86..f398b85 100644
--- a/wpa_supplicant/bgscan_simple.c
+++ b/wpa_supplicant/bgscan_simple.c
@@ -15,16 +15,11 @@
 #include "wpa_supplicant_i.h"
 #include "driver_i.h"
 #include "scan.h"
-#include "config.h"
-#include "wnm_sta.h"
-#include "bss.h"
 #include "bgscan.h"
 
 struct bgscan_simple_data {
 	struct wpa_supplicant *wpa_s;
 	const struct wpa_ssid *ssid;
-	unsigned int use_btm_query;
-	unsigned int scan_action_count;
 	int scan_interval;
 	int signal_threshold;
 	int short_scan_count; /* counter for scans using short scan interval */
@@ -35,54 +30,12 @@
 };
 
 
-static void bgscan_simple_timeout(void *eloop_ctx, void *timeout_ctx);
-
-
-static bool bgscan_simple_btm_query(struct wpa_supplicant *wpa_s,
-				    struct bgscan_simple_data *data)
-{
-	unsigned int mod;
-
-	if (!data->use_btm_query || wpa_s->conf->disable_btm ||
-	    !wpa_s->current_bss ||
-	    !wpa_bss_ext_capab(wpa_s->current_bss,
-			       WLAN_EXT_CAPAB_BSS_TRANSITION))
-		return false;
-
-	/* Try BTM x times, scan on x + 1 */
-	data->scan_action_count++;
-	mod = data->scan_action_count % (data->use_btm_query + 1);
-	if (mod >= data->use_btm_query)
-		return false;
-
-	wpa_printf(MSG_DEBUG,
-		   "bgscan simple: Send BSS transition management query %d/%d",
-		   mod, data->use_btm_query);
-	if (wnm_send_bss_transition_mgmt_query(
-		    wpa_s, WNM_TRANSITION_REASON_BETTER_AP_FOUND, NULL, 0)) {
-		wpa_printf(MSG_DEBUG,
-			   "bgscan simple: Failed to send BSS transition management query");
-		/* Fall through and do regular scan */
-		return false;
-	}
-
-	/* Start a new timeout for the next one. We don't have scan callback to
-	 * otherwise trigger future progress when using BTM path. */
-	eloop_register_timeout(data->scan_interval, 0,
-			       bgscan_simple_timeout, data, NULL);
-	return true;
-}
-
-
 static void bgscan_simple_timeout(void *eloop_ctx, void *timeout_ctx)
 {
 	struct bgscan_simple_data *data = eloop_ctx;
 	struct wpa_supplicant *wpa_s = data->wpa_s;
 	struct wpa_driver_scan_params params;
 
-	if (bgscan_simple_btm_query(wpa_s, data))
-		goto scan_ok;
-
 	os_memset(&params, 0, sizeof(params));
 	params.num_ssids = 1;
 	params.ssids[0].ssid = data->ssid->ssid;
@@ -101,7 +54,6 @@
 		eloop_register_timeout(data->scan_interval, 0,
 				       bgscan_simple_timeout, data, NULL);
 	} else {
-	scan_ok:
 		if (data->scan_interval == data->short_interval) {
 			data->short_scan_count++;
 			if (data->short_scan_count >= data->max_short_scans) {
@@ -128,8 +80,6 @@
 {
 	const char *pos;
 
-	data->use_btm_query = 0;
-
 	data->short_interval = atoi(params);
 
 	pos = os_strchr(params, ':');
@@ -145,11 +95,6 @@
 	}
 	pos++;
 	data->long_interval = atoi(pos);
-	pos = os_strchr(pos, ':');
-	if (pos) {
-		pos++;
-		data->use_btm_query = atoi(pos);
-	}
 
 	return 0;
 }
@@ -189,7 +134,6 @@
 	data->scan_interval = data->short_interval;
 	data->max_short_scans = data->long_interval / data->short_interval + 1;
 	if (data->signal_threshold) {
-		wpa_s->signal_threshold = data->signal_threshold;
 		/* Poll for signal info to set initial scan interval */
 		struct wpa_signal_info siginfo;
 		if (wpa_drv_signal_poll(wpa_s, &siginfo) == 0 &&
@@ -217,10 +161,8 @@
 {
 	struct bgscan_simple_data *data = priv;
 	eloop_cancel_timeout(bgscan_simple_timeout, data, NULL);
-	if (data->signal_threshold) {
-		data->wpa_s->signal_threshold = 0;
+	if (data->signal_threshold)
 		wpa_drv_signal_monitor(data->wpa_s, 0, 0);
-	}
 	os_free(data);
 }
 
diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c
index 2890353..c1be660 100644
--- a/wpa_supplicant/bss.c
+++ b/wpa_supplicant/bss.c
@@ -13,12 +13,10 @@
 #include "common/ieee802_11_defs.h"
 #include "drivers/driver.h"
 #include "eap_peer/eap.h"
-#include "rsn_supp/wpa.h"
 #include "wpa_supplicant_i.h"
 #include "config.h"
 #include "notify.h"
 #include "scan.h"
-#include "bssid_ignore.h"
 #include "bss.h"
 
 static void wpa_bss_set_hessid(struct wpa_bss *bss)
@@ -265,7 +263,7 @@
 	if (bssid && !wpa_supplicant_filter_bssid_match(wpa_s, bssid))
 		return NULL;
 	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
-		if ((!bssid || ether_addr_equal(bss->bssid, bssid)) &&
+		if ((!bssid || os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0) &&
 		    bss->ssid_len == ssid_len &&
 		    os_memcmp(bss->ssid, ssid, ssid_len) == 0)
 			return bss;
@@ -360,11 +358,12 @@
 #ifdef CONFIG_P2P
 	u8 addr[ETH_ALEN];
 
-	if (ether_addr_equal(bss->bssid, wpa_s->pending_join_iface_addr))
+	if (os_memcmp(bss->bssid, wpa_s->pending_join_iface_addr,
+		      ETH_ALEN) == 0)
 		return true;
 	if (!is_zero_ether_addr(wpa_s->pending_join_dev_addr) &&
 	    p2p_parse_dev_addr(wpa_bss_ie_ptr(bss), bss->ie_len, addr) == 0 &&
-	    ether_addr_equal(addr, wpa_s->pending_join_dev_addr))
+	    os_memcmp(addr, wpa_s->pending_join_dev_addr, ETH_ALEN) == 0)
 		return true;
 #endif /* CONFIG_P2P */
 	return false;
@@ -400,11 +399,6 @@
 	if (bss == wpa_s->ml_connect_probe_bss)
 		return 1;
 
-#ifdef CONFIG_WNM
-	if (bss == wpa_s->wnm_target_bss)
-		return 1;
-#endif /* CONFIG_WNM */
-
 	if (wpa_s->current_bss &&
 	    (bss->ssid_len != wpa_s->current_bss->ssid_len ||
 	     os_memcmp(bss->ssid, wpa_s->current_bss->ssid,
@@ -412,15 +406,18 @@
 		return 0; /* SSID has changed */
 
 	if (!is_zero_ether_addr(bss->bssid) &&
-	    (ether_addr_equal(bss->bssid, wpa_s->bssid) ||
-	     ether_addr_equal(bss->bssid, wpa_s->pending_bssid)))
+	    (os_memcmp(bss->bssid, wpa_s->bssid, ETH_ALEN) == 0 ||
+	     os_memcmp(bss->bssid, wpa_s->pending_bssid, ETH_ALEN) == 0))
 		return 1;
 
 	if (!wpa_s->valid_links)
 		return 0;
 
-	for_each_link(wpa_s->valid_links, i) {
-		if (ether_addr_equal(bss->bssid, wpa_s->links[i].bssid))
+	for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+		if (!(wpa_s->valid_links & BIT(i)))
+			continue;
+
+		if (os_memcmp(bss->bssid, wpa_s->links[i].bssid, ETH_ALEN) == 0)
 			return 1;
 	}
 
@@ -720,8 +717,7 @@
 	dl_list_del(&bss->list);
 #ifdef CONFIG_P2P
 	if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) &&
-	    !wpa_scan_get_vendor_ie(res, P2P_IE_VENDOR_TYPE) &&
-	    !(changes & WPA_BSS_FREQ_CHANGED_FLAG)) {
+	    !wpa_scan_get_vendor_ie(res, P2P_IE_VENDOR_TYPE)) {
 		/*
 		 * This can happen when non-P2P station interface runs a scan
 		 * without P2P IE in the Probe Request frame. P2P GO would reply
@@ -1105,7 +1101,7 @@
 	if (!wpa_supplicant_filter_bssid_match(wpa_s, bssid))
 		return NULL;
 	dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, list) {
-		if (ether_addr_equal(bss->bssid, bssid))
+		if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0)
 			return bss;
 	}
 	return NULL;
@@ -1130,7 +1126,7 @@
 	if (!wpa_supplicant_filter_bssid_match(wpa_s, bssid))
 		return NULL;
 	dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, list) {
-		if (!ether_addr_equal(bss->bssid, bssid))
+		if (os_memcmp(bss->bssid, bssid, ETH_ALEN) != 0)
 			continue;
 		if (found == NULL ||
 		    os_reltime_before(&found->last_update, &bss->last_update))
@@ -1159,7 +1155,7 @@
 		u8 addr[ETH_ALEN];
 		if (p2p_parse_dev_addr(wpa_bss_ie_ptr(bss), bss->ie_len,
 				       addr) != 0 ||
-		    !ether_addr_equal(addr, dev_addr))
+		    os_memcmp(addr, dev_addr, ETH_ALEN) != 0)
 			continue;
 		if (!found ||
 		    os_reltime_before(&found->last_update, &bss->last_update))
@@ -1226,6 +1222,22 @@
 
 
 /**
+ * wpa_bss_get_ie_nth - Fetch a specified information element from a BSS entry
+ * @bss: BSS table entry
+ * @ie: Information element identitifier (WLAN_EID_*)
+ * @nth: Return the nth element of the requested type (2 returns the second)
+ * Returns: Pointer to the information element (id field) or %NULL if not found
+ *
+ * This function returns the nth matching information element in the BSS
+ * entry.
+ */
+const u8 * wpa_bss_get_ie_nth(const struct wpa_bss *bss, u8 ie, int nth)
+{
+	return get_ie_nth(wpa_bss_ie_ptr(bss), bss->ie_len, ie, nth);
+}
+
+
+/**
  * wpa_bss_get_ie_ext - Fetch a specified extended IE from a BSS entry
  * @bss: BSS table entry
  * @ext: Information element extension identifier (WLAN_EID_EXT_*)
@@ -1484,12 +1496,29 @@
 }
 
 
+/**
+ * wpa_bss_defrag_mle - Get a buffer holding a de-fragmented ML element
+ * @bss: BSS table entry
+ * @type: ML control type
+ */
+struct wpabuf * wpa_bss_defrag_mle(const struct wpa_bss *bss, u8 type)
+{
+	struct ieee802_11_elems elems;
+	const u8 *pos = wpa_bss_ie_ptr(bss);
+	size_t len = bss->ie_len;
+
+	if (ieee802_11_parse_elems(pos, len, &elems, 1) == ParseFailed)
+		return NULL;
+
+	return ieee802_11_defrag_mle(&elems, type);
+}
+
+
 static void
 wpa_bss_parse_ml_rnr_ap_info(struct wpa_supplicant *wpa_s,
 			     struct wpa_bss *bss, u8 mbssid_idx,
 			     const struct ieee80211_neighbor_ap_info *ap_info,
-			     size_t len, u16 *seen, u16 *missing,
-			     struct wpa_ssid *ssid)
+			     size_t len, u16 *seen, u16 *missing)
 {
 	const u8 *pos, *end;
 	const u8 *mld_params;
@@ -1513,46 +1542,38 @@
 	pos += sizeof(*ap_info);
 
 	for (i = 0; i < count; i++) {
-		u8 bss_params;
+		if (bss->n_mld_links >= MAX_NUM_MLD_LINKS)
+			return;
 
 		if (end - pos < ap_info->tbtt_info_len)
 			break;
 
-		bss_params = pos[1 + ETH_ALEN + 4];
 		mld_params = pos + mld_params_offset;
 
 		link_id = *(mld_params + 1) & EHT_ML_LINK_ID_MSK;
-		if (link_id >= MAX_NUM_MLD_LINKS)
-			return;
 
 		if (*mld_params != mbssid_idx) {
 			wpa_printf(MSG_DEBUG,
 				   "MLD: Reported link not part of MLD");
 		} else if (!(BIT(link_id) & *seen)) {
 			struct wpa_bss *neigh_bss =
-				wpa_bss_get_bssid(wpa_s, pos + 1);
+				wpa_bss_get_bssid(wpa_s, ap_info->data + 1);
 
 			*seen |= BIT(link_id);
 			wpa_printf(MSG_DEBUG, "MLD: mld ID=%u, link ID=%u",
 				   *mld_params, link_id);
 
-			if (!neigh_bss) {
-				*missing |= BIT(link_id);
-			} else if ((!ssid ||
-				    (bss_params & (RNR_BSS_PARAM_SAME_SSID |
-						   RNR_BSS_PARAM_CO_LOCATED)) ||
-				    wpa_scan_res_match(wpa_s, 0, neigh_bss,
-						       ssid, 1, 0)) &&
-				   !wpa_bssid_ignore_is_listed(
-					   wpa_s, neigh_bss->bssid)) {
+			if (neigh_bss) {
 				struct mld_link *l;
 
-				bss->valid_links |= BIT(link_id);
-				l = &bss->mld_links[link_id];
-				os_memcpy(l->bssid, pos + 1, ETH_ALEN);
+				l = &bss->mld_links[bss->n_mld_links];
+				l->link_id = link_id;
+				os_memcpy(l->bssid, ap_info->data + 1,
+					  ETH_ALEN);
 				l->freq = neigh_bss->freq;
-				l->disabled = mld_params[2] &
-					RNR_TBTT_INFO_MLD_PARAM2_LINK_DISABLED;
+				bss->n_mld_links++;
+			} else {
+				*missing |= BIT(link_id);
 			}
 		}
 
@@ -1569,8 +1590,6 @@
  * @link_info: Array to store link information (or %NULL),
  *   should be initialized and #MAX_NUM_MLD_LINKS elements long
  * @missing_links: Result bitmask of links that were not discovered (or %NULL)
- * @ssid: Target SSID (or %NULL)
- * @ap_mld_id: On return would hold the corresponding AP MLD ID (or %NULL)
  * Returns: 0 on success or -1 for non-MLD or parsing failures
  *
  * Parses the Basic Multi-Link element of the BSS into @link_info using the scan
@@ -1581,15 +1600,13 @@
 int wpa_bss_parse_basic_ml_element(struct wpa_supplicant *wpa_s,
 				   struct wpa_bss *bss,
 				   u8 *ap_mld_addr,
-				   u16 *missing_links,
-				   struct wpa_ssid *ssid,
-				   u8 *ap_mld_id)
+				   u16 *missing_links)
 {
 	struct ieee802_11_elems elems;
 	struct wpabuf *mlbuf;
 	const struct element *elem;
 	u8 mbssid_idx = 0;
-	size_t ml_ie_len;
+	u8 ml_ie_len;
 	const struct ieee80211_eht_ml *eht_ml;
 	const struct eht_ml_basic_common_info *ml_basic_common_info;
 	u8 i, link_id;
@@ -1616,7 +1633,7 @@
 		return ret;
 	}
 
-	mlbuf = ieee802_11_defrag(elems.basic_mle, elems.basic_mle_len, true);
+	mlbuf = ieee802_11_defrag_mle(&elems, MULTI_LINK_CONTROL_TYPE_BASIC);
 	if (!mlbuf) {
 		wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No Multi-Link element");
 		return ret;
@@ -1624,32 +1641,6 @@
 
 	ml_ie_len = wpabuf_len(mlbuf);
 
-	if (ssid) {
-		struct wpa_ie_data ie;
-
-		if (!elems.rsn_ie ||
-		    wpa_parse_wpa_ie(elems.rsn_ie - 2, 2 + elems.rsn_ie_len,
-				     &ie)) {
-			wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No RSN element");
-			goto out;
-		}
-
-		if (!(ie.capabilities & WPA_CAPABILITY_MFPC) ||
-		    wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION) {
-			wpa_dbg(wpa_s, MSG_DEBUG,
-				"MLD: No management frame protection");
-			goto out;
-		}
-
-		ie.key_mgmt &= ~(WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK |
-				 WPA_KEY_MGMT_PSK_SHA256);
-		if (!(ie.key_mgmt & ssid->key_mgmt)) {
-			wpa_dbg(wpa_s, MSG_DEBUG,
-				"MLD: No valid key management");
-			goto out;
-		}
-	}
-
 	/*
 	 * for ext ID + 2 control + common info len + MLD address +
 	 * link info
@@ -1678,15 +1669,15 @@
 		os_memcpy(ap_mld_addr, ml_basic_common_info->mld_addr,
 			  ETH_ALEN);
 
+	bss->n_mld_links = 0;
+	l = &bss->mld_links[bss->n_mld_links];
 	link_id = ml_basic_common_info->variable[0] & EHT_ML_LINK_ID_MSK;
-
-	bss->mld_link_id = link_id;
-	seen = bss->valid_links = BIT(link_id);
-
-	l = &bss->mld_links[link_id];
+	l->link_id = link_id;
 	os_memcpy(l->bssid, bss->bssid, ETH_ALEN);
 	l->freq = bss->freq;
 
+	seen = BIT(link_id);
+	bss->n_mld_links++;
 
 	/*
 	 * The AP MLD ID in the RNR corresponds to the MBSSID index, see
@@ -1729,27 +1720,25 @@
 
 			wpa_bss_parse_ml_rnr_ap_info(wpa_s, bss, mbssid_idx,
 						     ap_info, len, &seen,
-						     &missing, ssid);
+						     &missing);
 
 			pos += ap_info_len;
 			len -= ap_info_len;
 		}
 	}
 
-	wpa_printf(MSG_DEBUG, "MLD: valid_links=%04hx (unresolved: 0x%04hx)",
-		   bss->valid_links, missing);
+	wpa_printf(MSG_DEBUG, "MLD: n_mld_links=%u (unresolved: 0x%04hx)",
+		   bss->n_mld_links, missing);
 
-	for_each_link(bss->valid_links, i) {
+	for (i = 0; i < bss->n_mld_links; i++) {
 		wpa_printf(MSG_DEBUG, "MLD: link=%u, bssid=" MACSTR,
-			   i, MAC2STR(bss->mld_links[i].bssid));
+			   bss->mld_links[i].link_id,
+			   MAC2STR(bss->mld_links[i].bssid));
 	}
 
 	if (missing_links)
 		*missing_links = missing;
 
-	if (ap_mld_id)
-		*ap_mld_id = mbssid_idx;
-
 	ret = 0;
 out:
 	wpabuf_free(mlbuf);
@@ -1780,7 +1769,7 @@
 	if (!elems.reconf_mle || !elems.reconf_mle_len)
 		return 0;
 
-	mlbuf = ieee802_11_defrag(elems.reconf_mle, elems.reconf_mle_len, true);
+	mlbuf = ieee802_11_defrag_mle(&elems, MULTI_LINK_CONTROL_TYPE_RECONF);
 	if (!mlbuf)
 		return 0;
 
diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h
index cc04963..042b5d2 100644
--- a/wpa_supplicant/bss.h
+++ b/wpa_supplicant/bss.h
@@ -126,17 +126,13 @@
 	size_t beacon_ie_len;
 	/** MLD address of the AP */
 	u8 mld_addr[ETH_ALEN];
-	/** Link ID of this affiliated AP of the AP MLD */
-	u8 mld_link_id;
 
 	/** An array of MLD links */
-	u16 valid_links;
+	u8 n_mld_links;
 	struct mld_link {
+		u8 link_id;
 		u8 bssid[ETH_ALEN];
 		int freq;
-
-		/* Whether the link is valid but currently disabled */
-		bool disabled;
 	} mld_links[MAX_NUM_MLD_LINKS];
 
 	/* followed by ie_len octets of IEs */
@@ -175,6 +171,7 @@
 struct wpa_bss * wpa_bss_get_id_range(struct wpa_supplicant *wpa_s,
 				      unsigned int idf, unsigned int idl);
 const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie);
+const u8 * wpa_bss_get_ie_nth(const struct wpa_bss *bss, u8 ie, int nth);
 const u8 * wpa_bss_get_ie_ext(const struct wpa_bss *bss, u8 ext);
 const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type);
 const u8 * wpa_bss_get_vendor_ie_beacon(const struct wpa_bss *bss,
@@ -216,12 +213,11 @@
 			   unsigned int age_ms,
 			   struct os_reltime *update_time);
 
+struct wpabuf * wpa_bss_defrag_mle(const struct wpa_bss *bss, u8 type);
 int wpa_bss_parse_basic_ml_element(struct wpa_supplicant *wpa_s,
 				   struct wpa_bss *bss,
 				   u8 *ap_mld_addr,
-				   u16 *missing_links,
-				   struct wpa_ssid *ssid,
-				   u8 *ap_mld_id);
+				   u16 *missing_links);
 u16 wpa_bss_parse_reconf_ml_element(struct wpa_supplicant *wpa_s,
 				    struct wpa_bss *bss);
 
diff --git a/wpa_supplicant/bssid_ignore.c b/wpa_supplicant/bssid_ignore.c
index ab16fc5..e378577 100644
--- a/wpa_supplicant/bssid_ignore.c
+++ b/wpa_supplicant/bssid_ignore.c
@@ -37,7 +37,7 @@
 
 	e = wpa_s->bssid_ignore;
 	while (e) {
-		if (ether_addr_equal(e->bssid, bssid))
+		if (os_memcmp(e->bssid, bssid, ETH_ALEN) == 0)
 			return e;
 		e = e->next;
 	}
@@ -85,9 +85,9 @@
 			e->timeout_secs = 60;
 		else
 			e->timeout_secs = 10;
-		wpa_msg(wpa_s, MSG_INFO, "BSSID " MACSTR
-			" ignore list count incremented to %d, ignoring for %d seconds",
-			MAC2STR(bssid), e->count, e->timeout_secs);
+		wpa_printf(MSG_INFO, "BSSID " MACSTR
+			   " ignore list count incremented to %d, ignoring for %d seconds",
+			   MAC2STR(bssid), e->count, e->timeout_secs);
 		return e->count;
 	}
 
@@ -100,9 +100,9 @@
 	e->start = now;
 	e->next = wpa_s->bssid_ignore;
 	wpa_s->bssid_ignore = e;
-	wpa_msg(wpa_s, MSG_INFO, "Added BSSID " MACSTR
-		" into ignore list, ignoring for %d seconds",
-		MAC2STR(bssid), e->timeout_secs);
+	wpa_printf(MSG_DEBUG, "Added BSSID " MACSTR
+		   " into ignore list, ignoring for %d seconds",
+		   MAC2STR(bssid), e->timeout_secs);
 
 	return e->count;
 }
@@ -123,14 +123,14 @@
 
 	e = wpa_s->bssid_ignore;
 	while (e) {
-		if (ether_addr_equal(e->bssid, bssid)) {
+		if (os_memcmp(e->bssid, bssid, ETH_ALEN) == 0) {
 			if (prev == NULL) {
 				wpa_s->bssid_ignore = e->next;
 			} else {
 				prev->next = e->next;
 			}
-			wpa_msg(wpa_s, MSG_INFO, "Removed BSSID " MACSTR
-				" from ignore list", MAC2STR(bssid));
+			wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR
+				   " from ignore list", MAC2STR(bssid));
 			os_free(e);
 			return 0;
 		}
@@ -175,8 +175,8 @@
 	while (e) {
 		prev = e;
 		e = e->next;
-		wpa_msg(wpa_s, MSG_INFO, "Removed BSSID " MACSTR
-			" from ignore list (clear)", MAC2STR(prev->bssid));
+		wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR
+			   " from ignore list (clear)", MAC2STR(prev->bssid));
 		os_free(prev);
 	}
 }
@@ -209,9 +209,9 @@
 				wpa_s->bssid_ignore = e->next;
 				e = wpa_s->bssid_ignore;
 			}
-			wpa_msg(wpa_s, MSG_INFO, "Removed BSSID " MACSTR
-				" from ignore list (expired)",
-				MAC2STR(to_delete->bssid));
+			wpa_printf(MSG_INFO, "Removed BSSID " MACSTR
+				   " from ignore list (expired)",
+				   MAC2STR(to_delete->bssid));
 			os_free(to_delete);
 		} else {
 			prev = e;
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index c949bab..d1d8ca3 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -197,10 +197,9 @@
 #endif /* NO_CONFIG_WRITE */
 
 
-static int wpa_config_parse_int_impl(const struct parse_data *data,
-				     struct wpa_ssid *ssid,
-				     int line, const char *value,
-				     bool check_range)
+static int wpa_config_parse_int(const struct parse_data *data,
+				struct wpa_ssid *ssid,
+				int line, const char *value)
 {
 	int val, *dst;
 	char *end;
@@ -213,46 +212,31 @@
 		return -1;
 	}
 
-	if (check_range && val < (long) data->param3) {
-		wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d "
-			   "min_value=%ld)", line, data->name, val,
-			   (long) data->param3);
-		return -1;
-	}
-
-	if (check_range && val > (long) data->param4) {
-		wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d "
-			   "max_value=%ld)", line, data->name, val,
-			   (long) data->param4);
-		return -1;
-	}
-
 	if (*dst == val)
 		return 1;
-
 	*dst = val;
 	wpa_printf(MSG_MSGDUMP, "%s=%d (0x%x)", data->name, *dst, *dst);
 
+	if (data->param3 && *dst < (long) data->param3) {
+		wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d "
+			   "min_value=%ld)", line, data->name, *dst,
+			   (long) data->param3);
+		*dst = (long) data->param3;
+		return -1;
+	}
+
+	if (data->param4 && *dst > (long) data->param4) {
+		wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d "
+			   "max_value=%ld)", line, data->name, *dst,
+			   (long) data->param4);
+		*dst = (long) data->param4;
+		return -1;
+	}
+
 	return 0;
 }
 
 
-static int wpa_config_parse_int(const struct parse_data *data,
-				struct wpa_ssid *ssid,
-				int line, const char *value)
-{
-	return wpa_config_parse_int_impl(data, ssid, line, value, false);
-}
-
-
-static int wpa_config_parse_int_range(const struct parse_data *data,
-				      struct wpa_ssid *ssid,
-				      int line, const char *value)
-{
-	return wpa_config_parse_int_impl(data, ssid, line, value, true);
-}
-
-
 #ifndef NO_CONFIG_WRITE
 static char * wpa_config_write_int(const struct parse_data *data,
 				   struct wpa_ssid *ssid)
@@ -2384,7 +2368,7 @@
 	u8 mac_value[ETH_ALEN];
 
 	if (hwaddr_aton(value, mac_value) == 0) {
-		if (ether_addr_equal(mac_value, ssid->mac_value))
+		if (os_memcmp(mac_value, ssid->mac_value, ETH_ALEN) == 0)
 			return 1;
 		os_memcpy(ssid->mac_value, mac_value, ETH_ALEN);
 		return 0;
@@ -2473,14 +2457,7 @@
 #define INTe(f, m) _INTe(f, m), NULL, NULL, 0
 
 /* INT_RANGE: Define an integer variable with allowed value range */
-#ifdef NO_CONFIG_WRITE
-#define INT_RANGE(f, min, max) #f, wpa_config_parse_int_range, OFFSET(f), \
-	(void *) 0, (void *) (min), (void *) (max), 0
-#else /* NO_CONFIG_WRITE */
-#define INT_RANGE(f, min, max) #f, wpa_config_parse_int_range, \
-	wpa_config_write_int, OFFSET(f),	       \
-	(void *) 0, (void *) (min), (void *) (max), 0
-#endif /* NO_CONFIG_WRITE */
+#define INT_RANGE(f, min, max) _INT(f), (void *) (min), (void *) (max), 0
 
 /* FUNC: Define a configuration variable that uses a custom function for
  * parsing and writing the value. */
@@ -2675,7 +2652,7 @@
 #endif /* CONFIG_P2P */
 #ifdef CONFIG_HT_OVERRIDES
 	{ INT_RANGE(disable_ht, 0, 1) },
-	{ INT_RANGE(disable_ht40, 0, 1) },
+	{ INT_RANGE(disable_ht40, -1, 1) },
 	{ INT_RANGE(disable_sgi, 0, 1) },
 	{ INT_RANGE(disable_ldpc, 0, 1) },
 	{ INT_RANGE(ht40_intolerant, 0, 1) },
@@ -2748,8 +2725,6 @@
 	{ INT_RANGE(owe_ptk_workaround, 0, 1) },
 	{ INT_RANGE(multi_ap_backhaul_sta, 0, 1) },
 	{ INT_RANGE(ft_eap_pmksa_caching, 0, 1) },
-	{ INT_RANGE(multi_ap_profile, MULTI_AP_PROFILE_1,
-		    MULTI_AP_PROFILE_MAX) },
 	{ INT_RANGE(beacon_prot, 0, 1) },
 	{ INT_RANGE(transition_disable, 0, 255) },
 	{ INT_RANGE(sae_pk, 0, 2) },
@@ -4706,10 +4681,6 @@
 		config->driver_param = os_strdup(driver_param);
 	config->gas_rand_addr_lifetime = DEFAULT_RAND_ADDR_LIFETIME;
 
-#ifdef CONFIG_TESTING_OPTIONS
-	config->mld_connect_band_pref = DEFAULT_MLD_CONNECT_BAND_PREF;
-#endif /* CONFIG_TESTING_OPTIONS */
-
 	return config;
 }
 
@@ -4768,10 +4739,9 @@
 };
 
 
-static int
-wpa_global_config_parse_int_impl(const struct global_parse_data *data,
-				 struct wpa_config *config, int line,
-				 const char *pos, bool check_range)
+static int wpa_global_config_parse_int(const struct global_parse_data *data,
+				       struct wpa_config *config, int line,
+				       const char *pos)
 {
 	int val, *dst;
 	char *end;
@@ -4784,47 +4754,31 @@
 			   line, pos);
 		return -1;
 	}
-
-	if (check_range && val < (long) data->param2) {
-		wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d "
-			   "min_value=%ld)", line, data->name, val,
-			   (long) data->param2);
-		return -1;
-	}
-
-	if (check_range && val > (long) data->param3) {
-		wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d "
-			   "max_value=%ld)", line, data->name, val,
-			   (long) data->param3);
-		return -1;
-	}
-
 	same = *dst == val;
 	*dst = val;
 
 	wpa_printf(MSG_DEBUG, "%s=%d", data->name, *dst);
 
+	if (data->param2 && *dst < (long) data->param2) {
+		wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d "
+			   "min_value=%ld)", line, data->name, *dst,
+			   (long) data->param2);
+		*dst = (long) data->param2;
+		return -1;
+	}
+
+	if (data->param3 && *dst > (long) data->param3) {
+		wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d "
+			   "max_value=%ld)", line, data->name, *dst,
+			   (long) data->param3);
+		*dst = (long) data->param3;
+		return -1;
+	}
+
 	return same;
 }
 
 
-static int wpa_global_config_parse_int(const struct global_parse_data *data,
-				       struct wpa_config *config, int line,
-				       const char *pos)
-{
-	return wpa_global_config_parse_int_impl(data, config, line, pos, false);
-}
-
-
-static int
-wpa_global_config_parse_int_range(const struct global_parse_data *data,
-				  struct wpa_config *config, int line,
-				  const char *pos)
-{
-	return wpa_global_config_parse_int_impl(data, config, line, pos, true);
-}
-
-
 static int wpa_global_config_parse_str(const struct global_parse_data *data,
 				       struct wpa_config *config, int line,
 				       const char *pos)
@@ -5361,23 +5315,6 @@
 #endif /* CONFIG_P2P */
 
 
-#ifdef CONFIG_TESTING_OPTIONS
-static int wpa_config_process_mld_connect_bssid_pref(
-	const struct global_parse_data *data,
-	struct wpa_config *config, int line, const char *pos)
-{
-	if (hwaddr_aton2(pos, config->mld_connect_bssid_pref) < 0) {
-		wpa_printf(MSG_ERROR,
-			   "Line %d: Invalid mld_connect_bssid_pref '%s'",
-			   line, pos);
-		return -1;
-	}
-
-	return 0;
-}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-
 #ifdef OFFSET
 #undef OFFSET
 #endif /* OFFSET */
@@ -5388,8 +5325,7 @@
 #define FUNC_NO_VAR(f) #f, wpa_config_process_ ## f, NULL, NULL, NULL, NULL
 #define _INT(f) #f, wpa_global_config_parse_int, wpa_config_get_int, OFFSET(f)
 #define INT(f) _INT(f), NULL, NULL
-#define INT_RANGE(f, min, max) #f, wpa_global_config_parse_int_range, \
-	wpa_config_get_int, OFFSET(f), (void *) min, (void *) max
+#define INT_RANGE(f, min, max) _INT(f), (void *) min, (void *) max
 #define _STR(f) #f, wpa_global_config_parse_str, wpa_config_get_str, OFFSET(f)
 #define STR(f) _STR(f), NULL, NULL
 #define STR_RANGE(f, min, max) _STR(f), (void *) min, (void *) max
@@ -5595,15 +5531,6 @@
 	{ INT_RANGE(pasn_corrupt_mic, 0, 1), 0 },
 #endif /* CONFIG_TESTING_OPTIONS */
 #endif /* CONFIG_PASN */
-#ifdef CONFIG_TESTING_OPTIONS
-	{ INT_RANGE(mld_force_single_link, 0, 1), 0 },
-	{ INT_RANGE(mld_connect_band_pref, 0, MLD_CONNECT_BAND_PREF_MAX), 0 },
-	{ FUNC(mld_connect_bssid_pref), 0 },
-#endif /* CONFIG_TESTING_OPTIONS */
-	{ INT_RANGE(ft_prepend_pmkid, 0, 1), CFG_CHANGED_FT_PREPEND_PMKID },
-	/* NOTE: When adding new parameters here, add_interface() in
-	 * wpa_supplicant/dbus_new_introspect.c may need to be modified to
-	 * increase the size of the iface->xml buffer. */
 };
 
 #undef FUNC
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index 56d5c61..09bcbc8 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -48,7 +48,6 @@
 #define DEFAULT_EXTENDED_KEY_ID 0
 #define DEFAULT_BTM_OFFLOAD 0
 #define DEFAULT_SCAN_RES_VALID_FOR_CONNECT 5
-#define DEFAULT_MLD_CONNECT_BAND_PREF MLD_CONNECT_BAND_PREF_AUTO
 
 #include "config_ssid.h"
 #include "wps/wps.h"
@@ -452,8 +451,7 @@
 #define CFG_CHANGED_WOWLAN_TRIGGERS BIT(18)
 #define CFG_CHANGED_DISABLE_BTM BIT(19)
 #define CFG_CHANGED_BGSCAN BIT(20)
-#define CFG_CHANGED_FT_PREPEND_PMKID BIT(21)
-#define CFG_CHANGED_DISABLE_BTM_NOTIFY BIT(22)
+#define CFG_CHANGED_DISABLE_BTM_NOTIFY BIT(21)
 
 /**
  * struct wpa_config - wpa_supplicant configuration data
@@ -728,14 +726,6 @@
 	unsigned int dot11RSNAConfigSATimeout;
 
 	/**
-	 * ft_prepend_pmkid - Whether to prepend PMKR1Name with PMKIDs
-	 *
-	 * This control whether PMKR1Name is prepended to the PMKID list
-	 * insread of replacing the full list when constructing RSNE for
-	 * EAPOL-Key msg 2/4 for FT cases. */
-	bool ft_prepend_pmkid;
-
-	/**
 	 * update_config - Is wpa_supplicant allowed to update configuration
 	 *
 	 * This variable control whether wpa_supplicant is allow to re-write
@@ -1816,20 +1806,6 @@
 
 #endif /* CONFIG_TESTING_OPTIONS */
 #endif /* CONFIG_PASN*/
-
-#ifdef CONFIG_TESTING_OPTIONS
-	enum {
-		MLD_CONNECT_BAND_PREF_AUTO = 0,
-		MLD_CONNECT_BAND_PREF_2GHZ = 1,
-		MLD_CONNECT_BAND_PREF_5GHZ = 2,
-		MLD_CONNECT_BAND_PREF_6GHZ = 3,
-		MLD_CONNECT_BAND_PREF_MAX = 4,
-	}  mld_connect_band_pref;
-
-	u8 mld_connect_bssid_pref[ETH_ALEN];
-
-	int mld_force_single_link;
-#endif /* CONFIG_TESTING_OPTIONS */
 };
 
 
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 414ed22..ebad5f1 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -850,7 +850,6 @@
 	INT(owe_ptk_workaround);
 	INT(multi_ap_backhaul_sta);
 	INT(ft_eap_pmksa_caching);
-	INT(multi_ap_profile);
 	INT(beacon_prot);
 	INT(transition_disable);
 	INT(sae_pk);
@@ -1619,18 +1618,6 @@
 	if (config->wowlan_disconnect_on_deinit)
 		fprintf(f, "wowlan_disconnect_on_deinit=%d\n",
 			config->wowlan_disconnect_on_deinit);
-#ifdef CONFIG_TESTING_OPTIONS
-	if (config->mld_force_single_link)
-		fprintf(f, "mld_force_single_link=1\n");
-	if (config->mld_connect_band_pref != MLD_CONNECT_BAND_PREF_AUTO)
-		fprintf(f, "mld_connect_band_pref=%d\n",
-			config->mld_connect_band_pref);
-	if (!is_zero_ether_addr(config->mld_connect_bssid_pref))
-		fprintf(f, "mld_connect_bssid_pref=" MACSTR "\n",
-			MAC2STR(config->mld_connect_bssid_pref));
-#endif /* CONFIG_TESTING_OPTIONS */
-	if (config->ft_prepend_pmkid)
-		fprintf(f, "ft_prepend_pmkid=%d", config->ft_prepend_pmkid);
 }
 
 #endif /* CONFIG_NO_CONFIG_WRITE */
diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h
index 2043a80..785acc3 100644
--- a/wpa_supplicant/config_ssid.h
+++ b/wpa_supplicant/config_ssid.h
@@ -1187,11 +1187,6 @@
 	int ft_eap_pmksa_caching;
 
 	/**
-	 * multi_ap_profile - Supported Multi-AP profile
-	 */
-	int multi_ap_profile;
-
-	/**
 	 * beacon_prot - Whether Beacon protection is enabled
 	 *
 	 * This depends on management frame protection (ieee80211w) being
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index d0fda4c..a68802e 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / Control interface (shared code for all backends)
- * Copyright (c) 2004-2024, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2020, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -22,7 +22,6 @@
 #ifdef CONFIG_DPP
 #include "common/dpp.h"
 #endif /* CONFIG_DPP */
-#include "common/nan_de.h"
 #include "common/ptksa_cache.h"
 #include "crypto/tls.h"
 #include "ap/hostapd.h"
@@ -59,7 +58,6 @@
 #include "mesh.h"
 #include "dpp_supplicant.h"
 #include "sme.h"
-#include "nan_usd.h"
 
 #ifdef __NetBSD__
 #include <net/if_ether.h>
@@ -447,7 +445,7 @@
 
 	dl_list_for_each(tmp, &wpa_s->drv_signal_override,
 			 struct driver_signal_override, list) {
-		if (ether_addr_equal(bssid, tmp->bssid)) {
+		if (os_memcmp(bssid, tmp->bssid, ETH_ALEN) == 0) {
 			dso = tmp;
 			break;
 		}
@@ -741,12 +739,6 @@
 				wpa_s->ext_eapol_frame_io;
 		}
 #endif /* CONFIG_AP */
-	} else if (os_strcasecmp(cmd, "encrypt_eapol_m2") == 0) {
-		wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_ENCRYPT_EAPOL_M2,
-				 !!atoi(value));
-	} else if (os_strcasecmp(cmd, "encrypt_eapol_m4") == 0) {
-		wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_ENCRYPT_EAPOL_M4,
-				 !!atoi(value));
 	} else if (os_strcasecmp(cmd, "extra_roc_dur") == 0) {
 		wpa_s->extra_roc_dur = atoi(value);
 	} else if (os_strcasecmp(cmd, "test_failure") == 0) {
@@ -841,19 +833,15 @@
 			wpa_s->sae_commit_override = wpabuf_parse_bin(value);
 	} else if (os_strcasecmp(cmd, "driver_signal_override") == 0) {
 		ret = wpas_ctrl_iface_set_dso(wpa_s, value);
-#ifndef CONFIG_NO_ROBUST_AV
 	} else if (os_strcasecmp(cmd, "disable_scs_support") == 0) {
 		wpa_s->disable_scs_support = !!atoi(value);
 	} else if (os_strcasecmp(cmd, "disable_mscs_support") == 0) {
 		wpa_s->disable_mscs_support = !!atoi(value);
-#endif /* CONFIG_NO_ROBUST_AV */
 	} else if (os_strcasecmp(cmd, "disable_eapol_g2_tx") == 0) {
 		wpa_s->disable_eapol_g2_tx = !!atoi(value);
 		/* Populate value to wpa_sm if already associated. */
 		wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DISABLE_EAPOL_G2_TX,
 				 wpa_s->disable_eapol_g2_tx);
-	} else if (os_strcasecmp(cmd, "test_assoc_comeback_type") == 0) {
-		wpa_s->test_assoc_comeback_type = atoi(value);
 #ifdef CONFIG_DPP
 	} else if (os_strcasecmp(cmd, "dpp_config_obj_override") == 0) {
 		os_free(wpa_s->dpp_config_obj_override);
@@ -902,20 +890,9 @@
 			wpa_config_process_global(wpa_s->conf, cmd, -1);
 		}
 	} else if (os_strcasecmp(cmd, "mbo_cell_capa") == 0) {
-		int val = atoi(value);
-
-		if (val < MBO_CELL_CAPA_AVAILABLE ||
-		    val > MBO_CELL_CAPA_NOT_SUPPORTED)
-			return -1;
-
-		wpas_mbo_update_cell_capa(wpa_s, val);
+		wpas_mbo_update_cell_capa(wpa_s, atoi(value));
 	} else if (os_strcasecmp(cmd, "oce") == 0) {
-		int val = atoi(value);
-
-		if (val < 0 || val > 3)
-			return -1;
-
-		wpa_s->conf->oce = val;
+		wpa_s->conf->oce = atoi(value);
 		if (wpa_s->conf->oce) {
 			if ((wpa_s->conf->oce & OCE_STA) &&
 			    (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
@@ -955,10 +932,8 @@
 			return -1;
 		wnm_set_coloc_intf_elems(wpa_s, elems);
 #endif /* CONFIG_WNM */
-#ifndef CONFIG_NO_ROBUST_AV
 	} else if (os_strcasecmp(cmd, "enable_dscp_policy_capa") == 0) {
 		wpa_s->enable_dscp_policy_capa = !!atoi(value);
-#endif /* CONFIG_NO_ROBUST_AV */
 	} else {
 		value[-1] = '=';
 		ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
@@ -1285,8 +1260,6 @@
 #endif /* CONFIG_TDLS */
 
 
-#ifndef CONFIG_NO_WMM_AC
-
 static int wmm_ac_ctrl_addts(struct wpa_supplicant *wpa_s, char *cmd)
 {
 	char *token, *context = NULL;
@@ -1336,8 +1309,6 @@
 	return wpas_wmm_ac_delts(wpa_s, tsid);
 }
 
-#endif /* CONFIG_NO_WMM_AC */
-
 
 #ifdef CONFIG_IEEE80211R
 static int wpa_supplicant_ctrl_iface_ft_ds(
@@ -3647,7 +3618,7 @@
 #endif /* CONFIG_BGSCAN */
 
 	if (os_strcmp(name, "bssid") != 0 &&
-	    os_strncmp(name, "bssid_", 6) != 0 &&
+	    os_strcmp(name, "bssid_hint") != 0 &&
 	    os_strcmp(name, "scan_freq") != 0 &&
 	    os_strcmp(name, "priority") != 0) {
 		wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
@@ -3712,7 +3683,7 @@
 						       value);
 	if (ret == 0 &&
 	    (ssid->bssid_set != prev_bssid_set ||
-	     !ether_addr_equal(ssid->bssid, prev_bssid)))
+	     os_memcmp(ssid->bssid, prev_bssid, ETH_ALEN) != 0))
 		wpas_notify_network_bssid_set_changed(wpa_s, ssid);
 
 	if (prev_disabled != ssid->disabled &&
@@ -4888,15 +4859,6 @@
 	}
 #endif /* CONFIG_DPP */
 
-#ifdef CONFIG_NAN_USD
-	if (os_strcmp(field, "nan") == 0) {
-		res = os_snprintf(buf, buflen, "USD");
-		if (os_snprintf_error(buflen, res))
-			return -1;
-		return res;
-	}
-#endif /* CONFIG_NAN_USD */
-
 #ifdef CONFIG_SAE
 	if (os_strcmp(field, "sae") == 0 &&
 	    (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) {
@@ -4992,7 +4954,7 @@
 	ie_end = ie + 2 + ie[1];
 	ie += 2;
 	if (ie_end - ie < 2)
-		return 0;
+		return -1;
 
 	info = WPA_GET_LE16(ie);
 	ie += 2;
@@ -5004,7 +4966,7 @@
 	if (info & BIT(7)) {
 		/* Cache Identifier Included */
 		if (ie_end - ie < 2)
-			return 0;
+			return -1;
 		ret = os_snprintf(pos, end - pos, "fils_cache_id=%02x%02x\n",
 				  ie[0], ie[1]);
 		if (os_snprintf_error(end - pos, ret))
@@ -5016,7 +4978,7 @@
 	if (info & BIT(8)) {
 		/* HESSID Included */
 		if (ie_end - ie < ETH_ALEN)
-			return 0;
+			return -1;
 		ret = os_snprintf(pos, end - pos, "fils_hessid=" MACSTR "\n",
 				  MAC2STR(ie));
 		if (os_snprintf_error(end - pos, ret))
@@ -5028,7 +4990,7 @@
 	realms = (info & (BIT(3) | BIT(4) | BIT(5))) >> 3;
 	if (realms) {
 		if (ie_end - ie < realms * 2)
-			return 0;
+			return -1;
 		ret = os_snprintf(pos, end - pos, "fils_realms=");
 		if (os_snprintf_error(end - pos, ret))
 			return 0;
@@ -5282,7 +5244,7 @@
 		if (common_info_length < 1)
 			return 0;
 
-		ret = os_snprintf(pos, end - pos, ", MLD ID=0x%x", *ie);
+		ret = os_snprintf(pos, end - pos, ", MLD ID=0x%x\n", *ie);
 		if (os_snprintf_error(end - pos, ret))
 			return 0;
 		pos += ret;
@@ -5290,11 +5252,6 @@
 		common_info_length--;
 	}
 
-	ret = os_snprintf(pos, end - pos, "\n");
-	if (os_snprintf_error(end - pos, ret))
-		return 0;
-	pos += ret;
-
 	return pos - start;
 }
 
@@ -5429,13 +5386,13 @@
 		if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_H2E)) {
 			ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
 			if (os_snprintf_error(end - pos, ret))
-				return 0;
+				return -1;
 			pos += ret;
 		}
 		if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_PK)) {
 			ret = os_snprintf(pos, end - pos, "[SAE-PK]");
 			if (os_snprintf_error(end - pos, ret))
-				return 0;
+				return -1;
 			pos += ret;
 		}
 		osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
@@ -5734,6 +5691,8 @@
 #ifdef CONFIG_FILS
 	if (mask & WPA_BSS_MASK_FILS_INDICATION) {
 		ret = print_fils_indication(bss, pos, end);
+		if (ret < 0)
+			return 0;
 		pos += ret;
 	}
 #endif /* CONFIG_FILS */
@@ -6330,6 +6289,32 @@
 }
 
 
+static int parse_freq(int chwidth, int freq2)
+{
+	if (freq2 < 0)
+		return -1;
+	if (freq2)
+		return CONF_OPER_CHWIDTH_80P80MHZ;
+
+	switch (chwidth) {
+	case 0:
+	case 20:
+	case 40:
+		return CONF_OPER_CHWIDTH_USE_HT;
+	case 80:
+		return CONF_OPER_CHWIDTH_80MHZ;
+	case 160:
+		return CONF_OPER_CHWIDTH_160MHZ;
+	case 320:
+		return CONF_OPER_CHWIDTH_320MHZ;
+	default:
+		wpa_printf(MSG_DEBUG, "Unknown max oper bandwidth: %d",
+			   chwidth);
+		return -1;
+	}
+}
+
+
 static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
 			    char *buf, size_t buflen)
 {
@@ -6423,7 +6408,7 @@
 	if (pos2)
 		chwidth = atoi(pos2 + 18);
 
-	max_oper_chwidth = chwidth_freq2_to_ch_width(chwidth, freq2);
+	max_oper_chwidth = parse_freq(chwidth, freq2);
 	if (max_oper_chwidth < 0)
 		return -1;
 
@@ -7077,7 +7062,7 @@
 	if (pos)
 		chwidth = atoi(pos + 18);
 
-	max_oper_chwidth = chwidth_freq2_to_ch_width(chwidth, freq2);
+	max_oper_chwidth = parse_freq(chwidth, freq2);
 	if (max_oper_chwidth < 0)
 		return -1;
 
@@ -7153,8 +7138,8 @@
 		return -1;
 	}
 
-	return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0,
-					     vht_center_freq2, ht40, vht,
+	return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq,
+					     vht_center_freq2, 0, ht40, vht,
 					     vht_chwidth, he, edmg,
 					     NULL, 0, 0, allow_6ghz, 0,
 					     go_bssid);
@@ -7232,7 +7217,7 @@
 	}
 #endif /* CONFIG_ACS */
 
-	max_oper_chwidth = chwidth_freq2_to_ch_width(chwidth, freq2);
+	max_oper_chwidth = parse_freq(chwidth, freq2);
 	if (max_oper_chwidth < 0)
 		return -1;
 
@@ -7852,7 +7837,7 @@
 
 		dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss,
 					 list) {
-			if (ether_addr_equal(bss->bssid, bssid) &&
+			if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0 &&
 			    bss->ssid_len > 0) {
 				found = 1;
 				break;
@@ -8019,11 +8004,11 @@
 	dialog_token = atoi(pos);
 
 	if (wpa_s->last_gas_resp &&
-	    ether_addr_equal(addr, wpa_s->last_gas_addr) &&
+	    os_memcmp(addr, wpa_s->last_gas_addr, ETH_ALEN) == 0 &&
 	    dialog_token == wpa_s->last_gas_dialog_token)
 		resp = wpa_s->last_gas_resp;
 	else if (wpa_s->prev_gas_resp &&
-		 ether_addr_equal(addr, wpa_s->prev_gas_addr) &&
+		 os_memcmp(addr, wpa_s->prev_gas_addr, ETH_ALEN) == 0 &&
 		 dialog_token == wpa_s->prev_gas_dialog_token)
 		resp = wpa_s->prev_gas_resp;
 	else
@@ -8861,8 +8846,6 @@
 
 	wpa_s->next_ssid = NULL;
 
-	wnm_btm_reset(wpa_s);
-
 #ifdef CONFIG_INTERWORKING
 #ifdef CONFIG_HS20
 	hs20_cancel_fetch_osu(wpa_s);
@@ -8884,10 +8867,6 @@
 	wpa_s->ft_rsnxe_used = 0;
 	wpa_s->reject_btm_req_reason = 0;
 	wpa_sm_set_test_assoc_ie(wpa_s->wpa, NULL);
-	wpa_sm_set_test_eapol_m2_elems(wpa_s->wpa, NULL);
-	wpa_sm_set_test_eapol_m4_elems(wpa_s->wpa, NULL);
-	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_ENCRYPT_EAPOL_M2, 0);
-	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_ENCRYPT_EAPOL_M4, 0);
 	os_free(wpa_s->get_pref_freq_list_override);
 	wpa_s->get_pref_freq_list_override = NULL;
 	wpabuf_free(wpa_s->sae_commit_override);
@@ -8901,11 +8880,9 @@
 	wpabuf_free(wpa_s->rsnxe_override_eapol);
 	wpa_s->rsnxe_override_eapol = NULL;
 	wpas_clear_driver_signal_override(wpa_s);
-#ifndef CONFIG_NO_ROBUST_AV
 	wpa_s->disable_scs_support = 0;
 	wpa_s->disable_mscs_support = 0;
 	wpa_s->enable_dscp_policy_capa = 0;
-#endif /* CONFIG_NO_ROBUST_AV */
 	wpa_s->oci_freq_override_eapol = 0;
 	wpa_s->oci_freq_override_saquery_req = 0;
 	wpa_s->oci_freq_override_saquery_resp = 0;
@@ -8914,7 +8891,6 @@
 	wpa_s->oci_freq_override_fils_assoc = 0;
 	wpa_s->oci_freq_override_wnm_sleep = 0;
 	wpa_s->disable_eapol_g2_tx = 0;
-	wpa_s->test_assoc_comeback_type = -1;
 #ifdef CONFIG_DPP
 	os_free(wpa_s->dpp_config_obj_override);
 	wpa_s->dpp_config_obj_override = NULL;
@@ -8935,9 +8911,7 @@
 	wpa_s->next_scan_bssid_wildcard_ssid = 0;
 	os_free(wpa_s->select_network_scan_freqs);
 	wpa_s->select_network_scan_freqs = NULL;
-#ifndef CONFIG_NO_ROBUST_AV
 	os_memset(&wpa_s->robust_av, 0, sizeof(struct robust_av_data));
-#endif /* CONFIG_NO_ROBUST_AV */
 
 	wpa_bss_flush(wpa_s);
 	if (!dl_list_empty(&wpa_s->bss)) {
@@ -8964,9 +8938,7 @@
 
 	free_bss_tmp_disallowed(wpa_s);
 
-#ifndef CONFIG_NO_ROBUST_AV
 	os_memset(&wpa_s->robust_av, 0, sizeof(struct robust_av_data));
-#endif /* CONFIG_NO_ROBUST_AV */
 
 #ifdef CONFIG_PASN
 	wpas_pasn_auth_stop(wpa_s);
@@ -8976,10 +8948,6 @@
 		wpas_restore_permanent_mac_addr(wpa_s);
 
 	wpa_s->conf->ignore_old_scan_res = 0;
-
-#ifdef CONFIG_NAN_USD
-	wpas_nan_usd_flush(wpa_s);
-#endif /* CONFIG_NAN_USD */
 }
 
 
@@ -10166,6 +10134,72 @@
 }
 
 
+static int wpas_ctrl_test_alloc_fail(struct wpa_supplicant *wpa_s, char *cmd)
+{
+#ifdef WPA_TRACE_BFD
+	char *pos;
+
+	wpa_trace_fail_after = atoi(cmd);
+	pos = os_strchr(cmd, ':');
+	if (pos) {
+		pos++;
+		os_strlcpy(wpa_trace_fail_func, pos,
+			   sizeof(wpa_trace_fail_func));
+	} else {
+		wpa_trace_fail_after = 0;
+	}
+	return 0;
+#else /* WPA_TRACE_BFD */
+	return -1;
+#endif /* WPA_TRACE_BFD */
+}
+
+
+static int wpas_ctrl_get_alloc_fail(struct wpa_supplicant *wpa_s,
+				    char *buf, size_t buflen)
+{
+#ifdef WPA_TRACE_BFD
+	return os_snprintf(buf, buflen, "%u:%s", wpa_trace_fail_after,
+			   wpa_trace_fail_func);
+#else /* WPA_TRACE_BFD */
+	return -1;
+#endif /* WPA_TRACE_BFD */
+}
+
+
+static int wpas_ctrl_test_fail(struct wpa_supplicant *wpa_s, char *cmd)
+{
+#ifdef WPA_TRACE_BFD
+	char *pos;
+
+	wpa_trace_test_fail_after = atoi(cmd);
+	pos = os_strchr(cmd, ':');
+	if (pos) {
+		pos++;
+		os_strlcpy(wpa_trace_test_fail_func, pos,
+			   sizeof(wpa_trace_test_fail_func));
+	} else {
+		wpa_trace_test_fail_after = 0;
+	}
+	return 0;
+#else /* WPA_TRACE_BFD */
+	return -1;
+#endif /* WPA_TRACE_BFD */
+}
+
+
+static int wpas_ctrl_get_fail(struct wpa_supplicant *wpa_s,
+				    char *buf, size_t buflen)
+{
+#ifdef WPA_TRACE_BFD
+	return os_snprintf(buf, buflen, "%u:%s", wpa_trace_test_fail_after,
+			   wpa_trace_test_fail_func);
+#else /* WPA_TRACE_BFD */
+	return -1;
+#endif /* WPA_TRACE_BFD */
+}
+
+
 static void wpas_ctrl_event_test_cb(void *eloop_ctx, void *timeout_ctx)
 {
 	struct wpa_supplicant *wpa_s = eloop_ctx;
@@ -10193,12 +10227,13 @@
 }
 
 
-static int wpas_get_hex_buf(const char *val, struct wpabuf **ret)
+static int wpas_ctrl_test_assoc_ie(struct wpa_supplicant *wpa_s,
+				   const char *cmd)
 {
 	struct wpabuf *buf;
 	size_t len;
 
-	len = os_strlen(val);
+	len = os_strlen(cmd);
 	if (len & 1)
 		return -1;
 	len /= 2;
@@ -10207,56 +10242,20 @@
 		buf = NULL;
 	} else {
 		buf = wpabuf_alloc(len);
-		if (!buf)
+		if (buf == NULL)
 			return -1;
 
-		if (hexstr2bin(val, wpabuf_put(buf, len), len) < 0) {
+		if (hexstr2bin(cmd, wpabuf_put(buf, len), len) < 0) {
 			wpabuf_free(buf);
 			return -1;
 		}
 	}
 
-	*ret = buf;
-	return 0;
-}
-
-
-static int wpas_ctrl_test_assoc_ie(struct wpa_supplicant *wpa_s,
-				   const char *cmd)
-{
-	struct wpabuf *buf;
-
-	if (wpas_get_hex_buf(cmd, &buf) < 0)
-		return -1;
 	wpa_sm_set_test_assoc_ie(wpa_s->wpa, buf);
 	return 0;
 }
 
 
-static int wpas_ctrl_test_eapol_m2_elems(struct wpa_supplicant *wpa_s,
-					 const char *cmd)
-{
-	struct wpabuf *buf;
-
-	if (wpas_get_hex_buf(cmd, &buf) < 0)
-		return -1;
-	wpa_sm_set_test_eapol_m2_elems(wpa_s->wpa, buf);
-	return 0;
-}
-
-
-static int wpas_ctrl_test_eapol_m4_elems(struct wpa_supplicant *wpa_s,
-					 const char *cmd)
-{
-	struct wpabuf *buf;
-
-	if (wpas_get_hex_buf(cmd, &buf) < 0)
-		return -1;
-	wpa_sm_set_test_eapol_m4_elems(wpa_s->wpa, buf);
-	return 0;
-}
-
-
 static int wpas_ctrl_reset_pn(struct wpa_supplicant *wpa_s)
 {
 	u8 zero[WPA_TK_MAX_LEN];
@@ -10572,8 +10571,6 @@
 }
 
 
-#ifndef CONFIG_NO_RRM
-
 static void wpas_ctrl_neighbor_rep_cb(void *ctx, struct wpabuf *neighbor_rep)
 {
 	struct wpa_supplicant *wpa_s = ctx;
@@ -10717,8 +10714,6 @@
 	return ret;
 }
 
-#endif /* CONFIG_NO_RRM */
-
 
 static int wpas_ctrl_iface_erp_flush(struct wpa_supplicant *wpa_s)
 {
@@ -11072,7 +11067,6 @@
 }
 
 
-#ifndef CONFIG_NO_ROBUST_AV
 static int wpas_ctrl_iface_configure_mscs(struct wpa_supplicant *wpa_s,
 					  const char *cmd)
 {
@@ -11141,7 +11135,6 @@
 
 	return wpas_send_mscs_req(wpa_s);
 }
-#endif /* CONFIG_NO_ROBUST_AV */
 
 
 #ifdef CONFIG_PASN
@@ -11243,55 +11236,9 @@
 	return wpas_pasn_deauthenticate(wpa_s, wpa_s->own_addr, bssid);
 }
 
-
-#ifdef CONFIG_TESTING_OPTIONS
-static int wpas_ctrl_iface_pasn_driver(struct wpa_supplicant *wpa_s,
-				       const char *cmd)
-{
-	union wpa_event_data event;
-	const char *pos = cmd;
-	u8 addr[ETH_ALEN];
-
-	os_memset(&event, 0, sizeof(event));
-
-	if (os_strncmp(pos, "auth ", 5) == 0)
-		event.pasn_auth.action = PASN_ACTION_AUTH;
-	else if (os_strncmp(pos, "del ", 4) == 0)
-		event.pasn_auth.action =
-			PASN_ACTION_DELETE_SECURE_RANGING_CONTEXT;
-	else
-		return -1;
-
-	pos = os_strchr(pos, ' ');
-	if (!pos)
-		return -1;
-	pos++;
-	while (hwaddr_aton(pos, addr) == 0) {
-		struct pasn_peer *peer;
-
-		if (event.pasn_auth.num_peers == WPAS_MAX_PASN_PEERS)
-			return -1;
-		peer = &event.pasn_auth.peer[event.pasn_auth.num_peers];
-		os_memcpy(peer->own_addr, wpa_s->own_addr, ETH_ALEN);
-		os_memcpy(peer->peer_addr, addr, ETH_ALEN);
-		event.pasn_auth.num_peers++;
-
-		pos = os_strchr(pos, ' ');
-		if (!pos)
-			break;
-		pos++;
-	}
-
-	wpa_supplicant_event(wpa_s, EVENT_PASN_AUTH, &event);
-	return 0;
-}
-#endif /* CONFIG_TESTING_OPTIONS */
-
 #endif /* CONFIG_PASN */
 
 
-#ifndef CONFIG_NO_ROBUST_AV
-
 static int set_type4_frame_classifier(const char *cmd,
 				      struct type4_params *param)
 {
@@ -11988,8 +11935,6 @@
 	return wpas_send_dscp_query(wpa_s, pos + 12, os_strlen(pos + 12));
 }
 
-#endif /* CONFIG_NO_ROBUST_AV */
-
 
 static int wpas_ctrl_iface_mlo_signal_poll(struct wpa_supplicant *wpa_s,
 					   char *buf, size_t buflen)
@@ -12008,7 +11953,10 @@
 	pos = buf;
 	end = buf + buflen;
 
-	for_each_link(mlo_si.valid_links, i) {
+	for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+		if (!(mlo_si.valid_links & BIT(i)))
+			continue;
+
 		ret = os_snprintf(pos, end - pos,
 				  "LINK_ID=%d\nRSSI=%d\nLINKSPEED=%lu\n"
 				  "NOISE=%d\nFREQUENCY=%u\n",
@@ -12080,7 +12028,10 @@
 	pos = buf;
 	end = buf + buflen;
 
-	for_each_link(wpa_s->valid_links, i) {
+	for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+		if (!(wpa_s->valid_links & BIT(i)))
+			continue;
+
 		ret = os_snprintf(pos, end - pos, "link_id=%d\nfreq=%u\n"
 				  "ap_link_addr=" MACSTR
 				  "\nsta_link_addr=" MACSTR "\n",
@@ -12170,327 +12121,6 @@
 #endif /* CONFIG_TESTING_OPTIONS */
 
 
-#ifdef CONFIG_NAN_USD
-
-static int wpas_ctrl_nan_publish(struct wpa_supplicant *wpa_s, char *cmd,
-				 char *buf, size_t buflen)
-{
-	char *token, *context = NULL;
-	int publish_id;
-	struct nan_publish_params params;
-	const char *service_name = NULL;
-	struct wpabuf *ssi = NULL;
-	int ret = -1;
-	enum nan_service_protocol_type srv_proto_type = 0;
-	int *freq_list = NULL;
-
-	os_memset(&params, 0, sizeof(params));
-	/* USD shall use both solicited and unsolicited transmissions */
-	params.unsolicited = true;
-	params.solicited = true;
-	/* USD shall require FSD without GAS */
-	params.fsd = true;
-	params.freq = NAN_USD_DEFAULT_FREQ;
-
-	while ((token = str_token(cmd, " ", &context))) {
-		if (os_strncmp(token, "service_name=", 13) == 0) {
-			service_name = token + 13;
-			continue;
-		}
-
-		if (os_strncmp(token, "ttl=", 4) == 0) {
-			params.ttl = atoi(token + 4);
-			continue;
-		}
-
-		if (os_strncmp(token, "freq=", 5) == 0) {
-			params.freq = atoi(token + 5);
-			continue;
-		}
-
-		if (os_strncmp(token, "freq_list=", 10) == 0) {
-			char *pos = token + 10;
-
-			if (os_strcmp(pos, "all") == 0) {
-				os_free(freq_list);
-				freq_list = wpas_nan_usd_all_freqs(wpa_s);
-				params.freq_list = freq_list;
-				continue;
-			}
-
-			while (pos && pos[0]) {
-				int_array_add_unique(&freq_list, atoi(pos));
-				pos = os_strchr(pos, ',');
-				if (pos)
-					pos++;
-			}
-
-			params.freq_list = freq_list;
-			continue;
-		}
-
-		if (os_strncmp(token, "srv_proto_type=", 15) == 0) {
-			srv_proto_type = atoi(token + 15);
-			continue;
-		}
-
-		if (os_strncmp(token, "ssi=", 4) == 0) {
-			if (ssi)
-				goto fail;
-			ssi = wpabuf_parse_bin(token + 4);
-			if (!ssi)
-				goto fail;
-			continue;
-		}
-
-		if (os_strcmp(token, "solicited=0") == 0) {
-			params.solicited = false;
-			continue;
-		}
-
-		if (os_strcmp(token, "unsolicited=0") == 0) {
-			params.unsolicited = false;
-			continue;
-		}
-
-		if (os_strcmp(token, "fsd=0") == 0) {
-			params.fsd = false;
-			continue;
-		}
-
-		wpa_printf(MSG_INFO, "CTRL: Invalid NAN_PUBLISH parameter: %s",
-			   token);
-		goto fail;
-	}
-
-	publish_id = wpas_nan_usd_publish(wpa_s, service_name, srv_proto_type,
-					  ssi, &params);
-	if (publish_id > 0)
-		ret = os_snprintf(buf, buflen, "%d", publish_id);
-fail:
-	wpabuf_free(ssi);
-	os_free(freq_list);
-	return ret;
-}
-
-
-static int wpas_ctrl_nan_cancel_publish(struct wpa_supplicant *wpa_s,
-					char *cmd)
-{
-	char *token, *context = NULL;
-	int publish_id = 0;
-
-	while ((token = str_token(cmd, " ", &context))) {
-		if (sscanf(token, "publish_id=%i", &publish_id) == 1)
-			continue;
-		wpa_printf(MSG_INFO,
-			   "CTRL: Invalid NAN_CANCEL_PUBLISH parameter: %s",
-			   token);
-		return -1;
-	}
-
-	if (publish_id <= 0) {
-		wpa_printf(MSG_INFO,
-			   "CTRL: Invalid or missing NAN_CANCEL_PUBLISH publish_id");
-		return -1;
-	}
-
-	wpas_nan_usd_cancel_publish(wpa_s, publish_id);
-	return 0;
-}
-
-
-static int wpas_ctrl_nan_update_publish(struct wpa_supplicant *wpa_s,
-					char *cmd)
-{
-	char *token, *context = NULL;
-	int publish_id = 0;
-	struct wpabuf *ssi = NULL;
-	int ret = -1;
-
-	while ((token = str_token(cmd, " ", &context))) {
-		if (sscanf(token, "publish_id=%i", &publish_id) == 1)
-			continue;
-		if (os_strncmp(token, "ssi=", 4) == 0) {
-			if (ssi)
-				goto fail;
-			ssi = wpabuf_parse_bin(token + 4);
-			if (!ssi)
-				goto fail;
-			continue;
-		}
-		wpa_printf(MSG_INFO,
-			   "CTRL: Invalid NAN_UPDATE_PUBLISH parameter: %s",
-			   token);
-		goto fail;
-	}
-
-	if (publish_id <= 0) {
-		wpa_printf(MSG_INFO,
-			   "CTRL: Invalid or missing NAN_UPDATE_PUBLISH publish_id");
-		goto fail;
-	}
-
-	ret = wpas_nan_usd_update_publish(wpa_s, publish_id, ssi);
-fail:
-	wpabuf_free(ssi);
-	return ret;
-}
-
-
-static int wpas_ctrl_nan_subscribe(struct wpa_supplicant *wpa_s, char *cmd,
-				   char *buf, size_t buflen)
-{
-	char *token, *context = NULL;
-	int subscribe_id;
-	struct nan_subscribe_params params;
-	const char *service_name = NULL;
-	struct wpabuf *ssi = NULL;
-	int ret = -1;
-	enum nan_service_protocol_type srv_proto_type = 0;
-
-	os_memset(&params, 0, sizeof(params));
-	params.freq = NAN_USD_DEFAULT_FREQ;
-
-	while ((token = str_token(cmd, " ", &context))) {
-		if (os_strncmp(token, "service_name=", 13) == 0) {
-			service_name = token + 13;
-			continue;
-		}
-
-		if (os_strcmp(token, "active=1") == 0) {
-			params.active = true;
-			continue;
-		}
-
-		if (os_strncmp(token, "ttl=", 4) == 0) {
-			params.ttl = atoi(token + 4);
-			continue;
-		}
-
-		if (os_strncmp(token, "freq=", 5) == 0) {
-			params.freq = atoi(token + 5);
-			continue;
-		}
-
-		if (os_strncmp(token, "srv_proto_type=", 15) == 0) {
-			srv_proto_type = atoi(token + 15);
-			continue;
-		}
-
-		if (os_strncmp(token, "ssi=", 4) == 0) {
-			if (ssi)
-				goto fail;
-			ssi = wpabuf_parse_bin(token + 4);
-			if (!ssi)
-				goto fail;
-			continue;
-		}
-
-		wpa_printf(MSG_INFO,
-			   "CTRL: Invalid NAN_SUBSCRIBE parameter: %s",
-			   token);
-		goto fail;
-	}
-
-	subscribe_id = wpas_nan_usd_subscribe(wpa_s, service_name,
-					      srv_proto_type, ssi,
-					      &params);
-	if (subscribe_id > 0)
-		ret = os_snprintf(buf, buflen, "%d", subscribe_id);
-fail:
-	wpabuf_free(ssi);
-	return ret;
-}
-
-
-static int wpas_ctrl_nan_cancel_subscribe(struct wpa_supplicant *wpa_s,
-					  char *cmd)
-{
-	char *token, *context = NULL;
-	int subscribe_id = 0;
-
-	while ((token = str_token(cmd, " ", &context))) {
-		if (sscanf(token, "subscribe_id=%i", &subscribe_id) == 1)
-			continue;
-		wpa_printf(MSG_INFO,
-			   "CTRL: Invalid NAN_CANCEL_SUBSCRIBE parameter: %s",
-			   token);
-		return -1;
-	}
-
-	if (subscribe_id <= 0) {
-		wpa_printf(MSG_INFO,
-			   "CTRL: Invalid or missing NAN_CANCEL_SUBSCRIBE subscribe_id");
-		return -1;
-	}
-
-	wpas_nan_usd_cancel_subscribe(wpa_s, subscribe_id);
-	return 0;
-}
-
-
-static int wpas_ctrl_nan_transmit(struct wpa_supplicant *wpa_s, char *cmd)
-{
-	char *token, *context = NULL;
-	int handle = 0;
-	int req_instance_id = 0;
-	struct wpabuf *ssi = NULL;
-	u8 peer_addr[ETH_ALEN];
-	int ret = -1;
-
-	os_memset(peer_addr, 0, ETH_ALEN);
-
-	while ((token = str_token(cmd, " ", &context))) {
-		if (sscanf(token, "handle=%i", &handle) == 1)
-			continue;
-
-		if (sscanf(token, "req_instance_id=%i", &req_instance_id) == 1)
-			continue;
-
-		if (os_strncmp(token, "address=", 8) == 0) {
-			if (hwaddr_aton(token + 8, peer_addr) < 0)
-				return -1;
-			continue;
-		}
-
-		if (os_strncmp(token, "ssi=", 4) == 0) {
-			if (ssi)
-				goto fail;
-			ssi = wpabuf_parse_bin(token + 4);
-			if (!ssi)
-				goto fail;
-			continue;
-		}
-
-		wpa_printf(MSG_INFO,
-			   "CTRL: Invalid NAN_TRANSMIT parameter: %s",
-			   token);
-		goto fail;
-	}
-
-	if (handle <= 0) {
-		wpa_printf(MSG_INFO,
-			   "CTRL: Invalid or missing NAN_TRANSMIT handle");
-		goto fail;
-	}
-
-	if (is_zero_ether_addr(peer_addr)) {
-		wpa_printf(MSG_INFO,
-			   "CTRL: Invalid or missing NAN_TRANSMIT address");
-		goto fail;
-	}
-
-	ret = wpas_nan_usd_transmit(wpa_s, handle, ssi, NULL, peer_addr,
-				    req_instance_id);
-fail:
-	wpabuf_free(ssi);
-	return ret;
-}
-
-#endif /* CONFIG_NAN_USD */
-
-
 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
 					 char *buf, size_t *resp_len)
 {
@@ -13162,7 +12792,6 @@
 		reply_len = wpa_supplicant_ctrl_iface_tdls_link_status(
 			wpa_s, buf + 17, reply, reply_size);
 #endif /* CONFIG_TDLS */
-#ifndef CONFIG_NO_WMM_AC
 	} else if (os_strcmp(buf, "WMM_AC_STATUS") == 0) {
 		reply_len = wpas_wmm_ac_status(wpa_s, reply, reply_size);
 	} else if (os_strncmp(buf, "WMM_AC_ADDTS ", 13) == 0) {
@@ -13171,7 +12800,6 @@
 	} else if (os_strncmp(buf, "WMM_AC_DELTS ", 13) == 0) {
 		if (wmm_ac_ctrl_delts(wpa_s, buf + 13))
 			reply_len = -1;
-#endif /* CONFIG_NO_WMM_AC */
 	} else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) {
 		reply_len = wpa_supplicant_signal_poll(wpa_s, reply,
 						       reply_size);
@@ -13258,27 +12886,21 @@
 		if (wpas_ctrl_iface_data_test_frame(wpa_s, buf + 16) < 0)
 			reply_len = -1;
 	} else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) {
-		if (testing_set_fail_pattern(true, buf + 16) < 0)
+		if (wpas_ctrl_test_alloc_fail(wpa_s, buf + 16) < 0)
 			reply_len = -1;
 	} else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) {
-		reply_len = testing_get_fail_pattern(true, reply, reply_size);
+		reply_len = wpas_ctrl_get_alloc_fail(wpa_s, reply, reply_size);
 	} else if (os_strncmp(buf, "TEST_FAIL ", 10) == 0) {
-		if (testing_set_fail_pattern(false, buf + 10) < 0)
+		if (wpas_ctrl_test_fail(wpa_s, buf + 10) < 0)
 			reply_len = -1;
 	} else if (os_strcmp(buf, "GET_FAIL") == 0) {
-		reply_len = testing_get_fail_pattern(false, reply, reply_size);
+		reply_len = wpas_ctrl_get_fail(wpa_s, reply, reply_size);
 	} else if (os_strncmp(buf, "EVENT_TEST ", 11) == 0) {
 		if (wpas_ctrl_event_test(wpa_s, buf + 11) < 0)
 			reply_len = -1;
 	} else if (os_strncmp(buf, "TEST_ASSOC_IE ", 14) == 0) {
 		if (wpas_ctrl_test_assoc_ie(wpa_s, buf + 14) < 0)
 			reply_len = -1;
-	} else if (os_strncmp(buf, "TEST_EAPOL_M2_ELEMS ", 20) == 0) {
-		if (wpas_ctrl_test_eapol_m2_elems(wpa_s, buf + 20) < 0)
-			reply_len = -1;
-	} else if (os_strncmp(buf, "TEST_EAPOL_M4_ELEMS ", 20) == 0) {
-		if (wpas_ctrl_test_eapol_m4_elems(wpa_s, buf + 20) < 0)
-			reply_len = -1;
 	} else if (os_strcmp(buf, "RESET_PN") == 0) {
 		if (wpas_ctrl_reset_pn(wpa_s) < 0)
 			reply_len = -1;
@@ -13317,11 +12939,9 @@
 	} else if (os_strncmp(buf, "VENDOR_ELEM_REMOVE ", 19) == 0) {
 		if (wpas_ctrl_vendor_elem_remove(wpa_s, buf + 19) < 0)
 			reply_len = -1;
-#ifndef CONFIG_NO_RRM
 	} else if (os_strncmp(buf, "NEIGHBOR_REP_REQUEST", 20) == 0) {
 		if (wpas_ctrl_iface_send_neighbor_rep(wpa_s, buf + 20))
 			reply_len = -1;
-#endif /* CONFIG_NO_RRM */
 	} else if (os_strcmp(buf, "ERP_FLUSH") == 0) {
 		wpas_ctrl_iface_erp_flush(wpa_s);
 	} else if (os_strncmp(buf, "MAC_RAND_SCAN ", 14) == 0) {
@@ -13494,26 +13114,9 @@
 			reply_len = -1;
 #endif /* CONFIG_DPP3 */
 #endif /* CONFIG_DPP */
-#ifdef CONFIG_NAN_USD
-	} else if (os_strncmp(buf, "NAN_PUBLISH ", 12) == 0) {
-		reply_len = wpas_ctrl_nan_publish(wpa_s, buf + 12, reply,
-						  reply_size);
-	} else if (os_strncmp(buf, "NAN_CANCEL_PUBLISH ", 19) == 0) {
-		if (wpas_ctrl_nan_cancel_publish(wpa_s, buf + 19) < 0)
+	} else if (os_strncmp(buf, "MSCS ", 5) == 0) {
+		if (wpas_ctrl_iface_configure_mscs(wpa_s, buf + 5))
 			reply_len = -1;
-	} else if (os_strncmp(buf, "NAN_UPDATE_PUBLISH ", 19) == 0) {
-		if (wpas_ctrl_nan_update_publish(wpa_s, buf + 19) < 0)
-			reply_len = -1;
-	} else if (os_strncmp(buf, "NAN_SUBSCRIBE ", 14) == 0) {
-		reply_len = wpas_ctrl_nan_subscribe(wpa_s, buf + 14, reply,
-						    reply_size);
-	} else if (os_strncmp(buf, "NAN_CANCEL_SUBSCRIBE ", 21) == 0) {
-		if (wpas_ctrl_nan_cancel_subscribe(wpa_s, buf + 21) < 0)
-			reply_len = -1;
-	} else if (os_strncmp(buf, "NAN_TRANSMIT ", 13) == 0) {
-		if (wpas_ctrl_nan_transmit(wpa_s, buf + 13) < 0)
-			reply_len = -1;
-#endif /* CONFIG_NAN_USD */
 #ifdef CONFIG_PASN
 	} else if (os_strncmp(buf, "PASN_START ", 11) == 0) {
 		if (wpas_ctrl_iface_pasn_start(wpa_s, buf + 11) < 0)
@@ -13525,16 +13128,7 @@
 	} else if (os_strncmp(buf, "PASN_DEAUTH ", 12) == 0) {
 		if (wpas_ctrl_iface_pasn_deauthenticate(wpa_s, buf + 12) < 0)
 			reply_len = -1;
-#ifdef CONFIG_TESTING_OPTIONS
-	} else if (os_strncmp(buf, "PASN_DRIVER ", 12) == 0) {
-		if (wpas_ctrl_iface_pasn_driver(wpa_s, buf + 12) < 0)
-			reply_len = -1;
-#endif /* CONFIG_TESTING_OPTIONS */
 #endif /* CONFIG_PASN */
-#ifndef CONFIG_NO_ROBUST_AV
-	} else if (os_strncmp(buf, "MSCS ", 5) == 0) {
-		if (wpas_ctrl_iface_configure_mscs(wpa_s, buf + 5))
-			reply_len = -1;
 	} else if (os_strncmp(buf, "SCS ", 4) == 0) {
 		if (wpas_ctrl_iface_configure_scs(wpa_s, buf + 4))
 			reply_len = -1;
@@ -13544,7 +13138,6 @@
 	} else if (os_strncmp(buf, "DSCP_QUERY ", 11) == 0) {
 		if (wpas_ctrl_iface_send_dscp_query(wpa_s, buf + 11))
 			reply_len = -1;
-#endif /* CONFIG_NO_ROBUST_AV */
 	} else if (os_strcmp(buf, "MLO_STATUS") == 0) {
 		reply_len = wpas_ctrl_iface_mlo_status(wpa_s, reply,
 						       reply_size);
diff --git a/wpa_supplicant/dbus/dbus_dict_helpers.c b/wpa_supplicant/dbus/dbus_dict_helpers.c
index 27003eb..fdf7b12 100644
--- a/wpa_supplicant/dbus/dbus_dict_helpers.c
+++ b/wpa_supplicant/dbus/dbus_dict_helpers.c
@@ -706,59 +706,6 @@
 }
 
 
-#define UINT16_ARRAY_CHUNK_SIZE 18
-#define UINT16_ARRAY_ITEM_SIZE (sizeof(dbus_uint16_t))
-
-static dbus_bool_t _wpa_dbus_dict_entry_get_uint16_array(
-	DBusMessageIter *iter, struct wpa_dbus_dict_entry *entry)
-{
-	dbus_uint32_t count = 0;
-	dbus_uint16_t *buffer, *nbuffer;
-
-	entry->uint16array_value = NULL;
-	entry->array_type = DBUS_TYPE_UINT16;
-
-	buffer = os_calloc(UINT16_ARRAY_CHUNK_SIZE, UINT16_ARRAY_ITEM_SIZE);
-	if (!buffer)
-		return FALSE;
-
-	entry->array_len = 0;
-	while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_UINT16) {
-		dbus_uint16_t value;
-
-		if ((count % UINT16_ARRAY_CHUNK_SIZE) == 0 && count != 0) {
-			nbuffer = os_realloc_array(
-				buffer, count + UINT16_ARRAY_CHUNK_SIZE,
-				UINT16_ARRAY_ITEM_SIZE);
-			if (!nbuffer) {
-				os_free(buffer);
-				wpa_printf(MSG_ERROR,
-					   "dbus: %s out of memory trying to retrieve the uint16 array",
-					   __func__);
-				return FALSE;
-			}
-			buffer = nbuffer;
-		}
-
-		dbus_message_iter_get_basic(iter, &value);
-		buffer[count] = value;
-		entry->array_len = ++count;
-		dbus_message_iter_next(iter);
-	}
-	entry->uint16array_value = buffer;
-	wpa_hexdump_key(MSG_MSGDUMP, "dbus: uint16 array contents",
-			entry->bytearray_value, entry->array_len);
-
-	/* Zero-length arrays are valid. */
-	if (entry->array_len == 0) {
-		os_free(entry->uint16array_value);
-		entry->uint16array_value = NULL;
-	}
-
-	return TRUE;
-}
-
-
 #define STR_ARRAY_CHUNK_SIZE 8
 #define STR_ARRAY_ITEM_SIZE (sizeof(char *))
 
@@ -926,10 +873,6 @@
 		success = _wpa_dbus_dict_entry_get_byte_array(&iter_array,
 							      entry);
 		break;
-	case DBUS_TYPE_UINT16:
-		success = _wpa_dbus_dict_entry_get_uint16_array(&iter_array,
-								entry);
-		break;
 	case DBUS_TYPE_STRING:
 		success = _wpa_dbus_dict_entry_get_string_array(&iter_array,
 								array_type,
@@ -1138,9 +1081,6 @@
 		case DBUS_TYPE_BYTE:
 			os_free(entry->bytearray_value);
 			break;
-		case DBUS_TYPE_UINT16:
-			os_free(entry->uint16array_value);
-			break;
 		case DBUS_TYPE_STRING:
 			if (!entry->strarray_value)
 				break;
diff --git a/wpa_supplicant/dbus/dbus_dict_helpers.h b/wpa_supplicant/dbus/dbus_dict_helpers.h
index 1d33689..cc9e26f 100644
--- a/wpa_supplicant/dbus/dbus_dict_helpers.h
+++ b/wpa_supplicant/dbus/dbus_dict_helpers.h
@@ -139,7 +139,6 @@
 		dbus_uint64_t uint64_value;
 		double double_value;
 		char *bytearray_value;
-		dbus_uint16_t *uint16array_value;
 		char **strarray_value;
 		struct wpabuf **binarray_value;
 	};
diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c
index 8bd6a9a..8fc29b3 100644
--- a/wpa_supplicant/dbus/dbus_new.c
+++ b/wpa_supplicant/dbus/dbus_new.c
@@ -1023,40 +1023,6 @@
 	dbus_message_unref(msg);
 }
 
-
-void wpas_dbus_signal_anqp_query_done(struct wpa_supplicant *wpa_s,
-				      const u8 *dst, const char *result)
-{
-	struct wpas_dbus_priv *iface;
-	DBusMessage *msg;
-	DBusMessageIter iter;
-	char addr[WPAS_DBUS_OBJECT_PATH_MAX], *bssid;
-
-	os_snprintf(addr, WPAS_DBUS_OBJECT_PATH_MAX, MACSTR, MAC2STR(dst));
-	bssid = addr;
-
-	iface = wpa_s->global->dbus;
-
-	/* Do nothing if the control interface is not turned on */
-	if (!iface || !wpa_s->dbus_new_path)
-		return;
-
-	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
-				      WPAS_DBUS_NEW_IFACE_INTERFACE,
-				      "ANQPQueryDone");
-	if (!msg)
-		return;
-
-	dbus_message_iter_init_append(msg, &iter);
-
-	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &bssid) ||
-	    !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &result))
-		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
-	else
-		dbus_connection_send(iface->con, msg, NULL);
-	dbus_message_unref(msg);
-}
-
 #endif /* CONFIG_INTERWORKING */
 
 
@@ -2473,9 +2439,6 @@
 	case WPAS_DBUS_BSS_PROP_AGE:
 		prop = "Age";
 		break;
-	case WPAS_DBUS_BSS_PROP_ANQP:
-		prop = "ANQP";
-		break;
 	default:
 		wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
 			   __func__, property);
@@ -3014,11 +2977,6 @@
 	  NULL,
 	  NULL
 	},
-	{"ANQP", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
-	  wpas_dbus_getter_bss_anqp,
-	  NULL,
-	  NULL,
-	},
 	{ NULL, NULL, NULL, NULL, NULL, NULL }
 };
 
@@ -3758,13 +3716,6 @@
 		  END_ARGS
 	  }
 	},
-	{"ANQPGet", WPAS_DBUS_NEW_IFACE_INTERFACE,
-	  (WPADBusMethodHandler) wpas_dbus_handler_anqp_get,
-	  {
-		  { "args", "a{sv}", ARG_IN },
-		  END_ARGS
-	  },
-	},
 #endif /* CONFIG_INTERWORKING */
 	{ NULL, NULL, NULL, { END_ARGS } }
 };
@@ -4352,22 +4303,7 @@
 		  END_ARGS
 	  }
 	},
-	{"ANQPQueryDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
-	  {
-		  { "addr", "s", ARG_OUT },
-		  { "result", "s", ARG_OUT },
-		  END_ARGS
-	  }
-	},
 #endif /* CONFIG_INTERWORKING */
-#ifdef CONFIG_HS20
-	{ "HS20TermsAndConditions", WPAS_DBUS_NEW_IFACE_INTERFACE,
-	  {
-		  { "url", "s", ARG_OUT },
-		  END_ARGS
-	  }
-	},
-#endif /* CONFIG_HS20 */
 	{ NULL, NULL, { END_ARGS } }
 };
 
@@ -5206,39 +5142,3 @@
 }
 
 #endif /* CONFIG_P2P */
-
-
-#ifdef CONFIG_HS20
-/**
- * wpas_dbus_signal_hs20_t_c_acceptance - Signals a terms and conditions was
- * received.
- *
- * @wpa_s: %wpa_supplicant network interface data
- * @url: URL of the terms and conditions acceptance page.
- */
-void wpas_dbus_signal_hs20_t_c_acceptance(struct wpa_supplicant *wpa_s,
-					  const char *url)
-{
-	struct wpas_dbus_priv *iface;
-	DBusMessage *msg;
-
-	iface = wpa_s->global->dbus;
-
-	/* Do nothing if the control interface is not turned on */
-	if (!iface || !wpa_s->dbus_new_path)
-		return;
-
-	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
-				      WPAS_DBUS_NEW_IFACE_INTERFACE,
-				      "HS20TermsAndConditions");
-	if (!msg)
-		return;
-
-	if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &url,
-				     DBUS_TYPE_INVALID))
-		dbus_connection_send(iface->con, msg, NULL);
-	else
-		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
-	dbus_message_unref(msg);
-}
-#endif /* CONFIG_HS20 */
diff --git a/wpa_supplicant/dbus/dbus_new.h b/wpa_supplicant/dbus/dbus_new.h
index 952bb42..5c5d855 100644
--- a/wpa_supplicant/dbus/dbus_new.h
+++ b/wpa_supplicant/dbus/dbus_new.h
@@ -53,7 +53,6 @@
 	WPAS_DBUS_BSS_PROP_WPS,
 	WPAS_DBUS_BSS_PROP_IES,
 	WPAS_DBUS_BSS_PROP_AGE,
-	WPAS_DBUS_BSS_PROP_ANQP,
 };
 
 enum wpas_dbus_sta_prop {
@@ -280,10 +279,6 @@
 					    int bh, int bss_load,
 					    int conn_capab);
 void wpas_dbus_signal_interworking_select_done(struct wpa_supplicant *wpa_s);
-void wpas_dbus_signal_anqp_query_done(struct wpa_supplicant *wpa_s,
-				      const u8 *dst, const char *result);
-void wpas_dbus_signal_hs20_t_c_acceptance(struct wpa_supplicant *wpa_s,
-					  const char *url);
 
 #else /* CONFIG_CTRL_IFACE_DBUS_NEW */
 
@@ -655,18 +650,6 @@
 {
 }
 
-static inline
-void wpas_dbus_signal_anqp_query_done(struct wpa_supplicant *wpa_s,
-				      const u8 *dst, const char *result)
-{
-}
-
-static inline
-void wpas_dbus_signal_hs20_t_c_acceptance(struct wpa_supplicant *wpa_s,
-					  const char *url)
-{
-}
-
 #endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
 
 #endif /* CTRL_IFACE_DBUS_H_NEW */
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c
index 3897d98..6ad49a1 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers.c
@@ -1957,7 +1957,6 @@
 
 
 #ifdef CONFIG_INTERWORKING
-
 DBusMessage *
 wpas_dbus_handler_interworking_select(DBusMessage *message,
 				      struct wpa_supplicant *wpa_s)
@@ -1978,111 +1977,6 @@
 
 	return reply;
 }
-
-
-DBusMessage *
-wpas_dbus_handler_anqp_get(DBusMessage *message, struct wpa_supplicant *wpa_s)
-{
-	DBusMessageIter	iter, iter_dict;
-	struct wpa_dbus_dict_entry entry;
-	int ret;
-	u8 dst_addr[ETH_ALEN];
-	bool is_addr_present = false;
-	unsigned int freq = 0;
-#define MAX_ANQP_INFO_ID 100 /* Max info ID count from CLI implementation */
-	u16 id[MAX_ANQP_INFO_ID];
-	size_t num_id = 0;
-	u32 subtypes = 0;
-	u32 mbo_subtypes = 0;
-	size_t i;
-
-	dbus_message_iter_init(message, &iter);
-
-	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
-		return wpas_dbus_error_invalid_args(message, NULL);
-
-	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
-		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
-			return wpas_dbus_error_invalid_args(message, NULL);
-
-		if (os_strcmp(entry.key, "addr") == 0 &&
-		    entry.type == DBUS_TYPE_STRING) {
-			if (hwaddr_aton(entry.str_value, dst_addr)) {
-				wpa_printf(MSG_DEBUG,
-					   "%s[dbus]: Invalid address '%s'",
-					   __func__, entry.str_value);
-				wpa_dbus_dict_entry_clear(&entry);
-				return wpas_dbus_error_invalid_args(
-					message, "invalid address");
-			}
-
-			is_addr_present = true;
-		} else if (os_strcmp(entry.key, "freq") == 0 &&
-			   entry.type == DBUS_TYPE_UINT32) {
-			freq = entry.uint32_value;
-		} else if (os_strcmp(entry.key, "ids") == 0 &&
-			   entry.type == DBUS_TYPE_ARRAY &&
-			   entry.array_type == DBUS_TYPE_UINT16) {
-			for (i = 0; i < entry.array_len &&
-				     num_id < MAX_ANQP_INFO_ID; i++) {
-				id[num_id] = entry.uint16array_value[i];
-				num_id++;
-			}
-		} else if (os_strcmp(entry.key, "hs20_ids") == 0 &&
-			   entry.type == DBUS_TYPE_ARRAY &&
-			   entry.array_type == DBUS_TYPE_BYTE) {
-			for (i = 0; i < entry.array_len; i++) {
-				int num = entry.bytearray_value[i];
-
-				if (num <= 0 || num > 31) {
-					wpa_dbus_dict_entry_clear(&entry);
-					return wpas_dbus_error_invalid_args(
-						message,
-						"invalid HS20 ANQP id");
-				}
-				subtypes |= BIT(num);
-			}
-		} else if (os_strcmp(entry.key, "mbo_ids") == 0 &&
-			   entry.type == DBUS_TYPE_ARRAY &&
-			   entry.array_type == DBUS_TYPE_BYTE) {
-			for (i = 0; i < entry.array_len; i++) {
-				int num = entry.bytearray_value[i];
-
-				if (num <= 0 || num > MAX_MBO_ANQP_SUBTYPE) {
-					wpa_dbus_dict_entry_clear(&entry);
-					return wpas_dbus_error_invalid_args(
-						message, "invalid MBO ANQP id");
-				}
-				mbo_subtypes |= BIT(num);
-			}
-		} else {
-			wpa_dbus_dict_entry_clear(&entry);
-			return wpas_dbus_error_invalid_args(
-				message, "unsupported parameter");
-		}
-
-		wpa_dbus_dict_entry_clear(&entry);
-	}
-
-	if (!is_addr_present) {
-		wpa_printf(MSG_DEBUG,
-			   "%s[dbus]: address not provided", __func__);
-		return wpas_dbus_error_invalid_args(message,
-						    "address not provided");
-	}
-
-	ret = anqp_send_req(wpa_s, dst_addr, freq, id, num_id, subtypes,
-			    mbo_subtypes);
-	if (ret < 0) {
-		wpa_printf(MSG_ERROR, "%s[dbus]: failed to send ANQP request",
-			   __func__);
-		return wpas_dbus_error_unknown_error(
-			message, "error sending ANQP request");
-	}
-
-	return NULL;
-}
-
 #endif /* CONFIG_INTERWORKING */
 
 
@@ -5758,177 +5652,6 @@
 
 
 /**
- * wpas_dbus_getter_bss_anqp - Return all the ANQP fields of a BSS
- * @iter: Pointer to incoming dbus message iter
- * @error: Location to store error on failure
- * @user_data: Function specific data
- * Returns: TRUE on success, FALSE on failure
- *
- * Getter for "ANQP" property.
- */
-dbus_bool_t wpas_dbus_getter_bss_anqp(
-	const struct wpa_dbus_property_desc *property_desc,
-	DBusMessageIter *iter, DBusError *error, void *user_data)
-{
-	DBusMessageIter iter_dict, variant_iter;
-	struct bss_handler_args *args = user_data;
-	struct wpa_bss *bss;
-	struct wpa_bss_anqp *anqp;
-	struct wpa_bss_anqp_elem *elem;
-
-	bss = get_bss_helper(args, error, __func__);
-	if (!bss)
-		return FALSE;
-
-	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
-					      "a{sv}", &variant_iter) ||
-	    !wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
-		goto nomem;
-
-	anqp = bss->anqp;
-	if (anqp) {
-#ifdef CONFIG_INTERWORKING
-		if (anqp->capability_list &&
-		    !wpa_dbus_dict_append_byte_array(
-			    &iter_dict, "CapabilityList",
-			    wpabuf_head(anqp->capability_list),
-			    wpabuf_len(anqp->capability_list)))
-			goto nomem;
-		if (anqp->venue_name &&
-		    !wpa_dbus_dict_append_byte_array(
-			    &iter_dict, "VenueName",
-			    wpabuf_head(anqp->venue_name),
-			    wpabuf_len(anqp->venue_name)))
-			goto nomem;
-		if (anqp->network_auth_type &&
-		    !wpa_dbus_dict_append_byte_array(
-			    &iter_dict, "NetworkAuthType",
-			    wpabuf_head(anqp->network_auth_type),
-			    wpabuf_len(anqp->network_auth_type)))
-			goto nomem;
-		if (anqp->roaming_consortium &&
-		    !wpa_dbus_dict_append_byte_array(
-			    &iter_dict, "RoamingConsortium",
-			    wpabuf_head(anqp->roaming_consortium),
-			    wpabuf_len(anqp->roaming_consortium)))
-			goto nomem;
-		if (anqp->ip_addr_type_availability &&
-		    !wpa_dbus_dict_append_byte_array(
-			    &iter_dict, "IPAddrTypeAvailability",
-			    wpabuf_head(anqp->ip_addr_type_availability),
-			    wpabuf_len(anqp->ip_addr_type_availability)))
-			goto nomem;
-		if (anqp->nai_realm &&
-		    !wpa_dbus_dict_append_byte_array(
-			    &iter_dict, "NAIRealm",
-			    wpabuf_head(anqp->nai_realm),
-			    wpabuf_len(anqp->nai_realm)))
-			goto nomem;
-		if (anqp->anqp_3gpp &&
-		    !wpa_dbus_dict_append_byte_array(
-			    &iter_dict, "3GPP",
-			    wpabuf_head(anqp->anqp_3gpp),
-			    wpabuf_len(anqp->anqp_3gpp)))
-			goto nomem;
-		if (anqp->domain_name &&
-		    !wpa_dbus_dict_append_byte_array(
-			    &iter_dict, "DomainName",
-			    wpabuf_head(anqp->domain_name),
-			    wpabuf_len(anqp->domain_name)))
-			goto nomem;
-		if (anqp->fils_realm_info &&
-		    !wpa_dbus_dict_append_byte_array(
-			    &iter_dict, "FilsRealmInfo",
-			    wpabuf_head(anqp->fils_realm_info),
-			    wpabuf_len(anqp->fils_realm_info)))
-			goto nomem;
-
-#ifdef CONFIG_HS20
-		if (anqp->hs20_capability_list &&
-		    !wpa_dbus_dict_append_byte_array(
-			    &iter_dict, "HS20CapabilityList",
-			    wpabuf_head(anqp->hs20_capability_list),
-			    wpabuf_len(anqp->hs20_capability_list)))
-			goto nomem;
-		if (anqp->hs20_operator_friendly_name &&
-		    !wpa_dbus_dict_append_byte_array(
-			    &iter_dict, "HS20OperatorFriendlyName",
-			    wpabuf_head(anqp->hs20_operator_friendly_name),
-			    wpabuf_len(anqp->hs20_operator_friendly_name)))
-			goto nomem;
-		if (anqp->hs20_wan_metrics &&
-		    !wpa_dbus_dict_append_byte_array(
-			    &iter_dict, "HS20WanMetrics",
-			    wpabuf_head(anqp->hs20_wan_metrics),
-			    wpabuf_len(anqp->hs20_wan_metrics)))
-			goto nomem;
-		if (anqp->hs20_connection_capability &&
-		    !wpa_dbus_dict_append_byte_array(
-			    &iter_dict, "HS20ConnectionCapability",
-			    wpabuf_head(anqp->hs20_connection_capability),
-			    wpabuf_len(anqp->hs20_connection_capability)))
-			goto nomem;
-		if (anqp->hs20_operating_class &&
-		    !wpa_dbus_dict_append_byte_array(
-			    &iter_dict, "HS20OperatingClass",
-			    wpabuf_head(anqp->hs20_operating_class),
-			    wpabuf_len(anqp->hs20_operating_class)))
-			goto nomem;
-		if (anqp->hs20_osu_providers_list &&
-		    !wpa_dbus_dict_append_byte_array(
-			    &iter_dict, "HS20OSUProvidersList",
-			    wpabuf_head(anqp->hs20_osu_providers_list),
-			    wpabuf_len(anqp->hs20_osu_providers_list)))
-			goto nomem;
-		if (anqp->hs20_operator_icon_metadata &&
-		    !wpa_dbus_dict_append_byte_array(
-			    &iter_dict, "HS20OperatorIconMetadata",
-			    wpabuf_head(anqp->hs20_operator_icon_metadata),
-			    wpabuf_len(anqp->hs20_operator_icon_metadata)))
-			goto nomem;
-		if (anqp->hs20_osu_providers_nai_list &&
-		    !wpa_dbus_dict_append_byte_array(
-			    &iter_dict, "HS20OSUProvidersNAIList",
-			    wpabuf_head(anqp->hs20_osu_providers_nai_list),
-			    wpabuf_len(anqp->hs20_osu_providers_nai_list)))
-			goto nomem;
-#endif /* CONFIG_HS20 */
-
-		dl_list_for_each(elem, &anqp->anqp_elems,
-				 struct wpa_bss_anqp_elem, list) {
-			char title[32];
-
-			os_snprintf(title, sizeof(title), "anqp[%u]",
-				    elem->infoid);
-			if (!wpa_dbus_dict_append_byte_array(
-				    &iter_dict, title,
-				    wpabuf_head(elem->payload),
-				    wpabuf_len(elem->payload)))
-				goto nomem;
-
-			os_snprintf(title, sizeof(title),
-				    "protected-anqp-info[%u]", elem->infoid);
-			if (!wpa_dbus_dict_append_bool(
-				    &iter_dict, title,
-				    elem->protected_response))
-				goto nomem;
-		}
-#endif /* CONFIG_INTERWORKING */
-	}
-
-	if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
-	    !dbus_message_iter_close_container(iter, &variant_iter))
-		goto nomem;
-
-	return TRUE;
-
-nomem:
-	dbus_set_error(error, DBUS_ERROR_NO_MEMORY, "no memory");
-	return FALSE;
-}
-
-
-/**
  * wpas_dbus_getter_enabled - Check whether network is enabled or disabled
  * @iter: Pointer to incoming dbus message iter
  * @error: Location to store error on failure
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.h b/wpa_supplicant/dbus/dbus_new_handlers.h
index acd6af7..97fa337 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.h
+++ b/wpa_supplicant/dbus/dbus_new_handlers.h
@@ -157,9 +157,6 @@
 wpas_dbus_handler_interworking_select(DBusMessage *message,
 				      struct wpa_supplicant *wpa_s);
 
-DBusMessage *
-wpas_dbus_handler_anqp_get(DBusMessage *message, struct wpa_supplicant *wpa_s);
-
 DECLARE_ACCESSOR(wpas_dbus_getter_capabilities);
 DECLARE_ACCESSOR(wpas_dbus_getter_state);
 DECLARE_ACCESSOR(wpas_dbus_getter_scanning);
@@ -219,7 +216,6 @@
 DECLARE_ACCESSOR(wpas_dbus_getter_bss_wps);
 DECLARE_ACCESSOR(wpas_dbus_getter_bss_ies);
 DECLARE_ACCESSOR(wpas_dbus_getter_bss_age);
-DECLARE_ACCESSOR(wpas_dbus_getter_bss_anqp);
 DECLARE_ACCESSOR(wpas_dbus_getter_enabled);
 DECLARE_ACCESSOR(wpas_dbus_setter_enabled);
 DECLARE_ACCESSOR(wpas_dbus_getter_network_properties);
diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
index 16b2caa..a178d87 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
@@ -14,7 +14,6 @@
 #include "../wpa_supplicant_i.h"
 #include "../wps_supplicant.h"
 #include "../notify.h"
-#include "../bss.h"
 #include "dbus_new_helpers.h"
 #include "dbus_new.h"
 #include "dbus_new_handlers.h"
@@ -361,12 +360,6 @@
 	unsigned int group_id = 0;
 	struct wpa_ssid *ssid;
 	u8 go_bssid_buf[ETH_ALEN], *go_bssid = NULL;
-	bool allow_6ghz = false;
-	int vht = wpa_s->conf->p2p_go_vht;
-	int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
-	int he = wpa_s->conf->p2p_go_he;
-	int edmg = wpa_s->conf->p2p_go_edmg;
-	int max_oper_chwidth, chwidth = 0, freq2 = 0;
 
 	dbus_message_iter_init(message, &iter);
 
@@ -399,28 +392,6 @@
 			if (hwaddr_aton(entry.str_value, go_bssid_buf))
 				goto inv_args_clear;
 			go_bssid = go_bssid_buf;
-		} else if (os_strcmp(entry.key, "ht40") == 0 &&
-			   entry.type == DBUS_TYPE_BOOLEAN) {
-			ht40 = entry.bool_value;
-		} else if (os_strcmp(entry.key, "vht") == 0 &&
-			   entry.type == DBUS_TYPE_BOOLEAN) {
-			vht = entry.bool_value;
-			ht40 |= vht;
-		} else if (os_strcmp(entry.key, "he") == 0 &&
-			   entry.type == DBUS_TYPE_BOOLEAN) {
-			he = entry.bool_value;
-		} else if (os_strcmp(entry.key, "edmg") == 0 &&
-			   entry.type == DBUS_TYPE_BOOLEAN) {
-			edmg = entry.bool_value;
-		} else if (os_strcmp(entry.key, "allow_6ghz") == 0 &&
-			   entry.type == DBUS_TYPE_BOOLEAN) {
-			allow_6ghz = entry.bool_value;
-		} else if (os_strcmp(entry.key, "freq2") == 0 &&
-			   entry.type == DBUS_TYPE_INT32) {
-			freq2 = entry.int32_value;
-		} else if (os_strcmp(entry.key, "max_oper_chwidth") == 0 &&
-			   entry.type == DBUS_TYPE_INT32) {
-			chwidth = entry.int32_value;
 		} else {
 			goto inv_args_clear;
 		}
@@ -428,13 +399,6 @@
 		wpa_dbus_dict_entry_clear(&entry);
 	}
 
-	max_oper_chwidth = chwidth_freq2_to_ch_width(chwidth, freq2);
-	if (max_oper_chwidth < 0)
-		goto inv_args;
-
-	if (allow_6ghz && chwidth == 40)
-		max_oper_chwidth = CONF_OPER_CHWIDTH_40MHZ_6GHZ;
-
 	wpa_s = wpa_s->global->p2p_init_wpa_s;
 	if (!wpa_s) {
 		reply = wpas_dbus_error_no_p2p_mgmt_iface(message);
@@ -473,19 +437,17 @@
 		if (ssid == NULL || ssid->disabled != 2)
 			goto inv_args;
 
-		if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0,
-						  freq2, ht40, vht,
-						  max_oper_chwidth, he, edmg,
-						  NULL, 0, 0, allow_6ghz,
-						  retry_limit, go_bssid)) {
+		if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, 0, 0,
+						  0, 0, 0, 0, NULL, 0, 0,
+						  false, retry_limit,
+						  go_bssid)) {
 			reply = wpas_dbus_error_unknown_error(
 				message,
 				"Failed to reinvoke a persistent group");
 			goto out;
 		}
-	} else if (wpas_p2p_group_add(wpa_s, persistent_group, freq, freq2,
-				      ht40, vht, max_oper_chwidth, he, edmg,
-				      allow_6ghz))
+	} else if (wpas_p2p_group_add(wpa_s, persistent_group, freq, 0, 0, 0,
+				      0, 0, 0, false))
 		goto inv_args;
 
 out:
@@ -2465,9 +2427,9 @@
 	u8 *p_bssid;
 
 	if (role == WPAS_P2P_ROLE_CLIENT) {
-		if (!wpa_s->current_bss)
+		if (wpa_s->current_ssid == NULL)
 			return FALSE;
-		p_bssid = wpa_s->current_bss->bssid;
+		p_bssid = wpa_s->current_ssid->bssid;
 	} else {
 		if (wpa_s->ap_iface == NULL)
 			return FALSE;
@@ -2489,9 +2451,9 @@
 	u8 role = wpas_get_p2p_role(wpa_s);
 
 	if (role == WPAS_P2P_ROLE_CLIENT) {
-		if (!wpa_s->current_bss)
+		if (wpa_s->go_params == NULL)
 			return FALSE;
-		op_freq = wpa_s->current_bss->freq;
+		op_freq = wpa_s->go_params->freq;
 	} else {
 		if (wpa_s->ap_iface == NULL)
 			return FALSE;
diff --git a/wpa_supplicant/dbus/dbus_new_helpers.c b/wpa_supplicant/dbus/dbus_new_helpers.c
index 28f1aa4..7fb0669 100644
--- a/wpa_supplicant/dbus/dbus_new_helpers.c
+++ b/wpa_supplicant/dbus/dbus_new_helpers.c
@@ -671,27 +671,20 @@
 					    &interface) ||
 	    /* Changed properties dict */
 	    !dbus_message_iter_open_container(&signal_iter, DBUS_TYPE_ARRAY,
-					      "{sv}", &dict_iter))
-		goto fail;
-	if (!put_changed_properties(obj_dsc, interface, &dict_iter, 0)) {
-		dbus_message_iter_close_container(&signal_iter, &dict_iter);
-		goto fail;
-	}
-	if (!dbus_message_iter_close_container(&signal_iter, &dict_iter) ||
+					      "{sv}", &dict_iter) ||
+	    !put_changed_properties(obj_dsc, interface, &dict_iter, 0) ||
+	    !dbus_message_iter_close_container(&signal_iter, &dict_iter) ||
 	    /* Invalidated properties array (empty) */
 	    !dbus_message_iter_open_container(&signal_iter, DBUS_TYPE_ARRAY,
 					      "s", &dict_iter) ||
-	    !dbus_message_iter_close_container(&signal_iter, &dict_iter))
-		goto fail;
+	    !dbus_message_iter_close_container(&signal_iter, &dict_iter)) {
+		wpa_printf(MSG_DEBUG, "dbus: %s: Failed to construct signal",
+			   __func__);
+	} else {
+		dbus_connection_send(con, msg, NULL);
+	}
 
-	dbus_connection_send(con, msg, NULL);
-
-out:
 	dbus_message_unref(msg);
-	return;
-fail:
-	wpa_printf(MSG_DEBUG, "dbus: %s: Failed to construct signal", __func__);
-	goto out;
 }
 
 
@@ -709,23 +702,16 @@
 	dbus_message_iter_init_append(msg, &signal_iter);
 
 	if (!dbus_message_iter_open_container(&signal_iter, DBUS_TYPE_ARRAY,
-					      "{sv}", &dict_iter))
-		goto fail;
-	if (!put_changed_properties(obj_dsc, interface, &dict_iter, 1)) {
-		dbus_message_iter_close_container(&signal_iter, &dict_iter);
-		goto fail;
+					      "{sv}", &dict_iter) ||
+	    !put_changed_properties(obj_dsc, interface, &dict_iter, 1) ||
+	    !dbus_message_iter_close_container(&signal_iter, &dict_iter)) {
+		wpa_printf(MSG_DEBUG, "dbus: %s: Failed to construct signal",
+			   __func__);
+	} else {
+		dbus_connection_send(con, msg, NULL);
 	}
-	if (!dbus_message_iter_close_container(&signal_iter, &dict_iter))
-		goto fail;
 
-	dbus_connection_send(con, msg, NULL);
-
-out:
 	dbus_message_unref(msg);
-	return;
-fail:
-	wpa_printf(MSG_DEBUG, "dbus: %s: Failed to construct signal", __func__);
-	goto out;
 }
 
 
diff --git a/wpa_supplicant/dbus/dbus_new_introspect.c b/wpa_supplicant/dbus/dbus_new_introspect.c
index a8c0d28..6c721bf 100644
--- a/wpa_supplicant/dbus/dbus_new_introspect.c
+++ b/wpa_supplicant/dbus/dbus_new_introspect.c
@@ -38,7 +38,7 @@
 	if (!iface)
 		return NULL;
 	iface->dbus_interface = os_strdup(dbus_interface);
-	iface->xml = wpabuf_alloc(16000);
+	iface->xml = wpabuf_alloc(15000);
 	if (iface->dbus_interface == NULL || iface->xml == NULL) {
 		os_free(iface->dbus_interface);
 		wpabuf_free(iface->xml);
diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig
index c0192e0..1ae5a9f 100644
--- a/wpa_supplicant/defconfig
+++ b/wpa_supplicant/defconfig
@@ -677,17 +677,3 @@
 # production use.
 #CONFIG_PASN=y
 
-# Disable support for Radio Measurement (IEEE 802.11k) and supported operating
-# class indication. Removing these is not recommended since they can help the
-# AP manage the network and STA steering.
-#CONFIG_NO_RRM=y
-
-# Disable support for Robust AV streaming for consumer and enterprise Wi-Fi
-# applications; IEEE Std 802.11-2020, 4.3.24; SCS, MSCS, QoS Management
-#CONFIG_NO_ROBUST_AV=y
-
-# Disable support for WMM admission control
-#CONFIG_NO_WMM_AC=y
-
-# Wi-Fi Aware unsynchronized service discovery (NAN USD)
-#CONFIG_NAN_USD=y
diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c
index e223450..4f5be0a 100644
--- a/wpa_supplicant/dpp_supplicant.c
+++ b/wpa_supplicant/dpp_supplicant.c
@@ -238,12 +238,6 @@
 		wait_time = wpa_s->dpp_resp_retry_time;
 	else
 		wait_time = 1000;
-	if (wpa_s->dpp_tx_chan_change) {
-		wpa_s->dpp_tx_chan_change = false;
-		if (wait_time > 100)
-			wait_time = 100;
-	}
-
 	wpa_printf(MSG_DEBUG,
 		   "DPP: Schedule retransmission of Authentication Response frame in %u ms",
 		wait_time);
@@ -493,21 +487,6 @@
 }
 
 
-static void wpas_dpp_neg_freq_timeout(void *eloop_ctx, void *timeout_ctx)
-{
-	struct wpa_supplicant *wpa_s = eloop_ctx;
-	struct dpp_authentication *auth = wpa_s->dpp_auth;
-
-	if (!wpa_s->dpp_listen_on_tx_expire || !auth || !auth->neg_freq)
-		return;
-
-	wpa_printf(MSG_DEBUG,
-		   "DPP: Start listen on neg_freq %u MHz based on timeout for TX wait expiration",
-		   auth->neg_freq);
-	wpas_dpp_listen_start(wpa_s, auth->neg_freq);
-}
-
-
 static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s,
 			       unsigned int freq, const u8 *dst,
 			       const u8 *src, const u8 *bssid,
@@ -626,9 +605,7 @@
 			   wpa_s->dpp_auth->curr_freq,
 			   wpa_s->dpp_auth->neg_freq);
 		offchannel_send_action_done(wpa_s);
-		wpa_s->dpp_listen_on_tx_expire = true;
-		eloop_register_timeout(0, 100000, wpas_dpp_neg_freq_timeout,
-				       wpa_s, NULL);
+		wpas_dpp_listen_start(wpa_s, wpa_s->dpp_auth->neg_freq);
 	}
 
 	if (wpa_s->dpp_auth_ok_on_ack)
@@ -1058,8 +1035,6 @@
 	wpa_s->off_channel_freq = 0;
 	wpa_s->roc_waiting_drv_freq = lwork->freq;
 	wpa_drv_dpp_listen(wpa_s, true);
-	wpa_s->dpp_tx_auth_resp_on_roc_stop = false;
-	wpa_s->dpp_tx_chan_change = false;
 }
 
 
@@ -1159,58 +1134,11 @@
 }
 
 
-static void wpas_dpp_tx_auth_resp(struct wpa_supplicant *wpa_s)
-{
-	struct dpp_authentication *auth = wpa_s->dpp_auth;
-
-	if (!auth)
-		return;
-
-	wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
-		MAC2STR(auth->peer_mac_addr), auth->curr_freq,
-		DPP_PA_AUTHENTICATION_RESP);
-	offchannel_send_action(wpa_s, auth->curr_freq,
-			       auth->peer_mac_addr, wpa_s->own_addr, broadcast,
-			       wpabuf_head(auth->resp_msg),
-			       wpabuf_len(auth->resp_msg),
-			       500, wpas_dpp_tx_status, 0);
-}
-
-
-static void wpas_dpp_tx_auth_resp_roc_timeout(void *eloop_ctx,
-					      void *timeout_ctx)
-{
-	struct wpa_supplicant *wpa_s = eloop_ctx;
-	struct dpp_authentication *auth = wpa_s->dpp_auth;
-
-	if (!auth || !wpa_s->dpp_tx_auth_resp_on_roc_stop)
-		return;
-
-	wpa_s->dpp_tx_auth_resp_on_roc_stop = false;
-	wpa_s->dpp_tx_chan_change = true;
-	wpa_printf(MSG_DEBUG,
-		   "DPP: Send postponed Authentication Response on remain-on-channel termination timeout");
-	wpas_dpp_tx_auth_resp(wpa_s);
-}
-
-
 void wpas_dpp_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
 					  unsigned int freq)
 {
-	wpa_printf(MSG_DEBUG, "DPP: Remain on channel cancel for %u MHz", freq);
 	wpas_dpp_listen_work_done(wpa_s);
 
-	if (wpa_s->dpp_auth && wpa_s->dpp_tx_auth_resp_on_roc_stop) {
-		eloop_cancel_timeout(wpas_dpp_tx_auth_resp_roc_timeout,
-				     wpa_s, NULL);
-		wpa_s->dpp_tx_auth_resp_on_roc_stop = false;
-		wpa_s->dpp_tx_chan_change = true;
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Send postponed Authentication Response on remain-on-channel termination");
-		wpas_dpp_tx_auth_resp(wpa_s);
-		return;
-	}
-
 	if (wpa_s->dpp_auth && wpa_s->dpp_in_response_listen) {
 		unsigned int new_freq;
 
@@ -1328,17 +1256,17 @@
 		wpa_printf(MSG_DEBUG,
 			   "DPP: Stop listen on %u MHz to allow response on the request %u MHz",
 			   wpa_s->dpp_listen_freq, wpa_s->dpp_auth->curr_freq);
-		wpa_s->dpp_tx_auth_resp_on_roc_stop = true;
-		eloop_register_timeout(0, 100000,
-				       wpas_dpp_tx_auth_resp_roc_timeout,
-				       wpa_s, NULL);
 		wpas_dpp_listen_stop(wpa_s);
-		return;
 	}
-	wpa_s->dpp_tx_auth_resp_on_roc_stop = false;
-	wpa_s->dpp_tx_chan_change = false;
 
-	wpas_dpp_tx_auth_resp(wpa_s);
+	wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
+		MAC2STR(src), wpa_s->dpp_auth->curr_freq,
+		DPP_PA_AUTHENTICATION_RESP);
+	offchannel_send_action(wpa_s, wpa_s->dpp_auth->curr_freq,
+			       src, wpa_s->own_addr, broadcast,
+			       wpabuf_head(wpa_s->dpp_auth->resp_msg),
+			       wpabuf_len(wpa_s->dpp_auth->resp_msg),
+			       500, wpas_dpp_tx_status, 0);
 }
 
 
@@ -1347,15 +1275,6 @@
 	struct dpp_authentication *auth = wpa_s->dpp_auth;
 	int freq;
 
-	if (wpa_s->dpp_listen_on_tx_expire && auth && auth->neg_freq) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Start listen on neg_freq %u MHz based on TX wait expiration on the previous channel",
-			   auth->neg_freq);
-		eloop_cancel_timeout(wpas_dpp_neg_freq_timeout, wpa_s, NULL);
-		wpas_dpp_listen_start(wpa_s, auth->neg_freq);
-		return;
-	}
-
 	if (!wpa_s->dpp_gas_server || !auth) {
 		if (auth && auth->waiting_auth_resp &&
 		    eloop_is_timeout_registered(wpas_dpp_drv_wait_timeout,
@@ -1881,7 +1800,7 @@
 	wpa_s->dpp_gas_dialog_token = -1;
 
 	if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
-	    !ether_addr_equal(addr, auth->peer_mac_addr)) {
+	    os_memcmp(addr, auth->peer_mac_addr, ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
 		return;
 	}
@@ -2016,11 +1935,7 @@
 	offchannel_send_action_done(wpa_s);
 	wpas_dpp_listen_stop(wpa_s);
 
-#ifdef CONFIG_NO_RRM
-	supp_op_classes = NULL;
-#else /* CONFIG_NO_RRM */
 	supp_op_classes = wpas_supp_op_classes(wpa_s);
-#endif /* CONFIG_NO_RRM */
 	buf = dpp_build_conf_req_helper(auth, wpa_s->conf->dpp_name,
 					wpa_s->dpp_netrole,
 					wpa_s->conf->dpp_mud_url,
@@ -2101,7 +2016,7 @@
 	}
 
 	if (!is_zero_ether_addr(auth->peer_mac_addr) &&
-	    !ether_addr_equal(src, auth->peer_mac_addr)) {
+	    os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
 			   MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
 		return;
@@ -2156,7 +2071,7 @@
 		return;
 	}
 
-	if (!ether_addr_equal(src, auth->peer_mac_addr)) {
+	if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
 			   MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
 		return;
@@ -2260,7 +2175,7 @@
 
 	if (!auth || !auth->waiting_conf_result) {
 		if (auth &&
-		    ether_addr_equal(src, auth->peer_mac_addr) &&
+		    os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) == 0 &&
 		    gas_server_response_sent(wpa_s->gas_server,
 					     auth->gas_server_ctx)) {
 			/* This could happen if the TX status event gets delayed
@@ -2277,7 +2192,7 @@
 		}
 	}
 
-	if (!ether_addr_equal(src, auth->peer_mac_addr)) {
+	if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
 			   MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
 		return;
@@ -2693,7 +2608,7 @@
 		return;
 	}
 
-	if (!ether_addr_equal(src, auth->peer_mac_addr)) {
+	if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
 			   MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
 		return;
@@ -2737,7 +2652,7 @@
 		return;
 	}
 
-	if (!ether_addr_equal(src, auth->peer_mac_addr)) {
+	if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
 			   MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
 		return;
@@ -2775,7 +2690,7 @@
 	wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Response from " MACSTR,
 		   MAC2STR(src));
 	if (is_zero_ether_addr(wpa_s->dpp_intro_bssid) ||
-	    !ether_addr_equal(src, wpa_s->dpp_intro_bssid)) {
+	    os_memcmp(src, wpa_s->dpp_intro_bssid, ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG, "DPP: Not waiting for response from "
 			   MACSTR " - drop", MAC2STR(src));
 		return;
@@ -3939,7 +3854,7 @@
 	wpa_printf(MSG_DEBUG, "DPP: Private Peer Introduction Notify from "
 		   MACSTR, MAC2STR(src));
 	if (is_zero_ether_addr(wpa_s->dpp_intro_bssid) ||
-	    !ether_addr_equal(src, wpa_s->dpp_intro_bssid)) {
+	    os_memcmp(src, wpa_s->dpp_intro_bssid, ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG, "DPP: Not waiting for response from "
 			   MACSTR " - drop", MAC2STR(src));
 		return;
@@ -4230,7 +4145,7 @@
 	wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR,
 		   MAC2STR(sa));
 	if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
-	    !ether_addr_equal(sa, auth->peer_mac_addr)) {
+	    os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
 		return NULL;
 	}
@@ -4244,13 +4159,6 @@
 		 * exchange. */
 		dpp_notify_auth_success(auth, 1);
 		wpa_s->dpp_auth_ok_on_ack = 0;
-#ifdef CONFIG_TESTING_OPTIONS
-		if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
-			wpa_printf(MSG_INFO,
-				   "DPP: TESTING - stop at Authentication Confirm");
-			return NULL;
-		}
-#endif /* CONFIG_TESTING_OPTIONS */
 	}
 
 	wpa_hexdump(MSG_DEBUG,
@@ -4897,8 +4805,6 @@
 	eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s, NULL);
 	eloop_cancel_timeout(wpas_dpp_gas_client_timeout, wpa_s, NULL);
 	eloop_cancel_timeout(wpas_dpp_drv_wait_timeout, wpa_s, NULL);
-	eloop_cancel_timeout(wpas_dpp_tx_auth_resp_roc_timeout, wpa_s, NULL);
-	eloop_cancel_timeout(wpas_dpp_neg_freq_timeout, wpa_s, NULL);
 #ifdef CONFIG_DPP2
 	eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
 	eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
@@ -5710,7 +5616,6 @@
 	eloop_register_timeout(100, 0, wpas_dpp_push_button_expire,
 			       wpa_s, NULL);
 
-	wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_STATUS "started");
 	return 0;
 }
 
@@ -5772,7 +5677,6 @@
 	wpa_s->scan_req = MANUAL_SCAN_REQ;
 	wpa_s->scan_res_handler = wpas_dpp_pb_scan_res_handler;
 	wpa_supplicant_req_scan(wpa_s, 0, 0);
-	wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_STATUS "started");
 	return 0;
 }
 
@@ -5788,8 +5692,6 @@
 	if (wpa_s->dpp_pb_bi) {
 		char id[20];
 
-		if (wpa_s->dpp_pb_bi == wpa_s->dpp_pkex_bi)
-			wpa_s->dpp_pkex_bi = NULL;
 		os_snprintf(id, sizeof(id), "%u", wpa_s->dpp_pb_bi->id);
 		dpp_bootstrap_remove(wpa_s->dpp, id);
 		wpa_s->dpp_pb_bi = NULL;
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index d01b52b..dcf5764 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -128,7 +128,7 @@
 }
 
 struct wpa_scan_results *
-wpa_drv_get_scan_results(struct wpa_supplicant *wpa_s, const u8 *bssid);
+wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s);
 
 static inline int wpa_drv_get_bssid(struct wpa_supplicant *wpa_s, u8 *bssid)
 {
@@ -342,6 +342,14 @@
 	return -1;
 }
 
+static inline int wpa_drv_set_ap(struct wpa_supplicant *wpa_s,
+				 struct wpa_driver_ap_params *params)
+{
+	if (wpa_s->driver->set_ap)
+		return wpa_s->driver->set_ap(wpa_s->drv_priv, params);
+	return -1;
+}
+
 static inline int wpa_drv_sta_add(struct wpa_supplicant *wpa_s,
 				  struct hostapd_sta_add_params *params)
 {
@@ -1147,10 +1155,8 @@
 {
 	struct secure_ranging_params params;
 
-	/* Configure secure ranging context only to the drivers that support it.
-	 */
 	if (!wpa_s->driver->set_secure_ranging_ctx)
-		return 0;
+		return -1;
 
 	os_memset(&params, 0, sizeof(params));
 	params.action = action;
diff --git a/wpa_supplicant/eapol_test.c b/wpa_supplicant/eapol_test.c
index 95953de..9641062 100644
--- a/wpa_supplicant/eapol_test.c
+++ b/wpa_supplicant/eapol_test.c
@@ -670,10 +670,6 @@
 	wpa_s->eapol = NULL;
 	if (e->radius_conf && e->radius_conf->auth_server) {
 		os_free(e->radius_conf->auth_server->shared_secret);
-		os_free(e->radius_conf->auth_server->ca_cert);
-		os_free(e->radius_conf->auth_server->client_cert);
-		os_free(e->radius_conf->auth_server->private_key);
-		os_free(e->radius_conf->auth_server->private_key_passwd);
 		os_free(e->radius_conf->auth_server);
 	}
 	os_free(e->radius_conf);
@@ -1011,10 +1007,7 @@
 
 static void wpa_init_conf(struct eapol_test_data *e,
 			  struct wpa_supplicant *wpa_s, const char *authsrv,
-			  int port, bool tls, const char *secret,
-			  const char *ca_cert, const char *client_cert,
-			  const char *private_key,
-			  const char *private_key_passwd,
+			  int port, const char *secret,
 			  const char *cli_addr, const char *ifname)
 {
 	struct hostapd_radius_server *as;
@@ -1052,17 +1045,8 @@
 	}
 #endif /* CONFIG_NATIVE_WINDOWS or CONFIG_ANSI_C_EXTRA */
 	as->port = port;
-	as->tls = tls;
 	as->shared_secret = (u8 *) os_strdup(secret);
 	as->shared_secret_len = os_strlen(secret);
-	if (ca_cert)
-		as->ca_cert = os_strdup(ca_cert);
-	if (client_cert)
-		as->client_cert = os_strdup(client_cert);
-	if (private_key)
-		as->private_key = os_strdup(private_key);
-	if (private_key_passwd)
-		as->private_key_passwd = os_strdup(private_key_passwd);
 	e->radius_conf->auth_server = as;
 	e->radius_conf->auth_servers = as;
 	e->radius_conf->msg_dumps = 1;
@@ -1272,16 +1256,11 @@
 {
 	printf("usage:\n"
 	       "eapol_test [-enWSv] -c<conf> [-a<AS IP>] [-p<AS port>] "
-	       "[-s<AS secret>] \\\n"
-	       "           [-X<RADIUS protocol> \\\n"
+	       "[-s<AS secret>]\\\n"
 	       "           [-r<count>] [-t<timeout>] [-C<Connect-Info>] \\\n"
 	       "           [-M<client MAC address>] [-o<server cert file] \\\n"
 	       "           [-N<attr spec>] [-R<PC/SC reader>] "
 	       "[-P<PC/SC PIN>] \\\n"
-#ifdef CONFIG_RADIUS_TLS
-	       "           [-j<CA cert>] [-J<client cert>] \\\n"
-	       "[-k<private key] [-K<private key passwd>] \\\n"
-#endif /* CONFIG_RADIUS_TLS */
 	       "           [-A<client IP>] [-i<ifname>] [-T<ctrl_iface>]\n"
 	       "eapol_test scard\n"
 	       "eapol_test sim <PIN> <num triplets> [debug]\n"
@@ -1290,11 +1269,10 @@
 	       "  -c<conf> = configuration file\n"
 	       "  -a<AS IP> = IP address of the authentication server, "
 	       "default 127.0.0.1\n"
-	       "  -p<AS port> = Port of the authentication server,\n"
-	       "                default 1812 for RADIUS/UDP and 2083 for RADIUS/TLS\n"
-	       "  -s<AS secret> = shared secret with the authentication server,\n"
-	       "                  default 'radius' for RADIUS/UDP and 'radsec' for RADIUS/TLS\n"
-	       "  -X<RADIUS protocol> = RADIUS protocol to use: UDP (default) or TLS\n"
+	       "  -p<AS port> = UDP port of the authentication server, "
+	       "default 1812\n"
+	       "  -s<AS secret> = shared secret with the authentication "
+	       "server, default 'radius'\n"
 	       "  -A<client IP> = IP address of the client, default: select "
 	       "automatically\n"
 	       "  -r<count> = number of re-authentications\n"
@@ -1332,11 +1310,8 @@
 	struct wpa_supplicant wpa_s;
 	int c, ret = 1, wait_for_monitor = 0, save_config = 0;
 	char *as_addr = "127.0.0.1";
-	int as_port = -1;
-	char *as_secret = NULL;
-	char *ca_cert = NULL, *client_cert = NULL;
-	char *private_key = NULL, *private_key_passwd = NULL;
-	bool tls = false;
+	int as_port = 1812;
+	char *as_secret = "radius";
 	char *cli_addr = NULL;
 	char *conf = NULL;
 	int timeout = 30;
@@ -1359,8 +1334,7 @@
 	wpa_debug_show_keys = 1;
 
 	for (;;) {
-		c = getopt(argc, argv,
-			   "a:A:c:C:ei:j:J:k:K:M:nN:o:p:P:r:R:s:St:T:vWX:");
+		c = getopt(argc, argv, "a:A:c:C:ei:M:nN:o:p:P:r:R:s:St:T:vW");
 		if (c < 0)
 			break;
 		switch (c) {
@@ -1382,20 +1356,6 @@
 		case 'i':
 			ifname = optarg;
 			break;
-#ifdef CONFIG_RADIUS_TLS
-		case 'j':
-			ca_cert = optarg;
-			break;
-		case 'J':
-			client_cert = optarg;
-			break;
-		case 'k':
-			private_key = optarg;
-			break;
-		case 'K':
-			private_key_passwd = optarg;
-			break;
-#endif /* CONFIG_RADIUS_TLS */
 		case 'M':
 			if (hwaddr_aton(optarg, eapol_test.own_addr)) {
 				usage();
@@ -1446,16 +1406,6 @@
 		case 'W':
 			wait_for_monitor++;
 			break;
-		case 'X':
-			if (os_strcmp(optarg, "UDP") == 0) {
-				tls = false;
-			} else if (os_strcmp(optarg, "TLS") == 0) {
-				tls = true;
-			} else {
-				usage();
-				return -1;
-			}
-			break;
 		case 'N':
 			p1 = os_zalloc(sizeof(*p1));
 			if (p1 == NULL)
@@ -1490,11 +1440,6 @@
 		}
 	}
 
-	if (!as_secret)
-		as_secret = tls ? "radsec" : "radius";
-	if (as_port < 0)
-		as_port = tls ? 2083 : 1812;
-
 	if (argc > optind && os_strcmp(argv[optind], "scard") == 0) {
 		return scard_test(&eapol_test);
 	}
@@ -1544,8 +1489,7 @@
 		wpa_s.conf->pcsc_reader = os_strdup(eapol_test.pcsc_reader);
 	}
 
-	wpa_init_conf(&eapol_test, &wpa_s, as_addr, as_port, tls, as_secret,
-		      ca_cert, client_cert, private_key, private_key_passwd,
+	wpa_init_conf(&eapol_test, &wpa_s, as_addr, as_port, as_secret,
 		      cli_addr, ifname);
 	wpa_s.ctrl_iface = wpa_supplicant_ctrl_iface_init(&wpa_s);
 	if (wpa_s.ctrl_iface == NULL) {
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index ff18543..f386119 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -50,7 +50,6 @@
 #include "mesh.h"
 #include "mesh_mpm.h"
 #include "wmm_ac.h"
-#include "nan_usd.h"
 #include "dpp_supplicant.h"
 #include "rsn_supp/wpa_i.h"
 
@@ -164,7 +163,7 @@
 	struct wpa_bss *bss = wpa_supplicant_get_new_bss(wpa_s, bssid);
 
 	if (!bss) {
-		wpa_supplicant_update_scan_results(wpa_s, bssid);
+		wpa_supplicant_update_scan_results(wpa_s);
 
 		/* Get the BSS from the new scan results */
 		bss = wpa_supplicant_get_new_bss(wpa_s, bssid);
@@ -183,7 +182,7 @@
 	struct wpa_bss *bss = wpa_supplicant_get_new_bss(wpa_s, bssid);
 
 	if (!bss) {
-		wpa_supplicant_update_scan_results(wpa_s, bssid);
+		wpa_supplicant_update_scan_results(wpa_s);
 		bss = wpa_supplicant_get_new_bss(wpa_s, bssid);
 	}
 
@@ -384,13 +383,8 @@
 	wpa_s->key_mgmt = 0;
 	wpa_s->allowed_key_mgmts = 0;
 
-#ifndef CONFIG_NO_RRM
 	wpas_rrm_reset(wpa_s);
-#endif /* CONFIG_NO_RRM */
 	wpa_s->wnmsleep_used = 0;
-#ifdef CONFIG_WNM
-	wpa_s->wnm_mode = 0;
-#endif /* CONFIG_WNM */
 	wnm_clear_coloc_intf_reporting(wpa_s);
 	wpa_s->disable_mbo_oce = 0;
 
@@ -765,33 +759,15 @@
 		return 0;
 	}
 
-	wpa_ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
-
 	if (wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED &&
 	    (!(ssid->key_mgmt & WPA_KEY_MGMT_OWE) || ssid->owe_only)) {
-#ifdef CONFIG_OWE
-		if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) && ssid->owe_only &&
-		    !wpa_ie && !rsn_ie &&
-		    wpa_s->owe_transition_select &&
-		    wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE) &&
-		    ssid->owe_transition_bss_select_count + 1 <=
-		    MAX_OWE_TRANSITION_BSS_SELECT_COUNT) {
-			ssid->owe_transition_bss_select_count++;
-			if (debug_print)
-				wpa_dbg(wpa_s, MSG_DEBUG,
-					"   skip OWE open BSS (selection count %d does not exceed %d)",
-					ssid->owe_transition_bss_select_count,
-					MAX_OWE_TRANSITION_BSS_SELECT_COUNT);
-			wpa_s->owe_transition_search = 1;
-			return 0;
-		}
-#endif /* CONFIG_OWE */
 		if (debug_print)
 			wpa_dbg(wpa_s, MSG_DEBUG,
 				"   skip - MFP Required but network not MFP Capable");
 		return 0;
 	}
 
+	wpa_ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
 	while ((ssid->proto & WPA_PROTO_WPA) && wpa_ie) {
 		proto_match++;
 
@@ -1156,18 +1132,19 @@
 
 
 static bool wpas_valid_ml_bss(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
+
 {
 	u16 removed_links;
 
-	if (wpa_bss_parse_basic_ml_element(wpa_s, bss, NULL, NULL, NULL, NULL))
+	if (wpa_bss_parse_basic_ml_element(wpa_s, bss, NULL, NULL))
 		return true;
 
-	if (!bss->valid_links)
+	if (bss->n_mld_links == 0)
 		return true;
 
 	/* Check if the current BSS is going to be removed */
 	removed_links = wpa_bss_parse_reconf_ml_element(wpa_s, bss);
-	if (BIT(bss->mld_link_id) & removed_links)
+	if (BIT(bss->mld_links[0].link_id) & removed_links)
 		return false;
 
 	return true;
@@ -1308,7 +1285,7 @@
 #endif /* CONFIG_WPS */
 
 	if (ssid->bssid_set && ssid->ssid_len == 0 &&
-	    ether_addr_equal(bss->bssid, ssid->bssid))
+	    os_memcmp(bss->bssid, ssid->bssid, ETH_ALEN) == 0)
 		check_ssid = false;
 
 	if (check_ssid &&
@@ -1320,7 +1297,7 @@
 	}
 
 	if (ssid->bssid_set &&
-	    !ether_addr_equal(bss->bssid, ssid->bssid)) {
+	    os_memcmp(bss->bssid, ssid->bssid, ETH_ALEN) != 0) {
 		if (debug_print)
 			wpa_dbg(wpa_s, MSG_DEBUG, "   skip - BSSID mismatch");
 		return false;
@@ -1489,7 +1466,7 @@
 		}
 
 		if (p2p_parse_dev_addr_in_p2p_ie(p2p_ie, dev_addr) < 0 ||
-		    !ether_addr_equal(dev_addr, ssid->go_p2p_dev_addr)) {
+		    os_memcmp(dev_addr, ssid->go_p2p_dev_addr, ETH_ALEN) != 0) {
 			if (debug_print)
 				wpa_dbg(wpa_s, MSG_DEBUG,
 					"   skip - no matching GO P2P Device Address in P2P element");
@@ -1696,12 +1673,6 @@
 		return NULL;
 	}
 
-	if (wnm_is_bss_excluded(wpa_s, bss)) {
-		if (debug_print)
-			wpa_dbg(wpa_s, MSG_DEBUG, "   skip - BSSID excluded");
-		return NULL;
-	}
-
 	for (ssid = group; ssid; ssid = only_first_ssid ? NULL : ssid->pnext) {
 		if (wpa_scan_res_ok(wpa_s, ssid, match_ssid, match_ssid_len,
 				    bss, bssid_ignore_count, debug_print))
@@ -1806,12 +1777,10 @@
 				break;
 		}
 
-		if (!selected &&
-		    (wpa_s->bssid_ignore || wnm_active_bss_trans_mgmt(wpa_s)) &&
+		if (selected == NULL && wpa_s->bssid_ignore &&
 		    !wpa_s->countermeasures) {
 			wpa_dbg(wpa_s, MSG_DEBUG,
 				"No APs found - clear BSSID ignore list and try again");
-			wnm_btm_reset(wpa_s);
 			wpa_bssid_ignore_clear(wpa_s);
 			wpa_s->bssid_ignore_cleared = true;
 		} else if (selected == NULL)
@@ -1888,16 +1857,14 @@
 {
 	int *freqs;
 	u16 missing_links = 0, removed_links;
-	u8 ap_mld_id;
 
 	if (!((wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO) &&
 	      (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)))
 		return 0;
 
+	/* Try to resolve any missing link information */
 	if (wpa_bss_parse_basic_ml_element(wpa_s, selected, NULL,
-					   &missing_links, ssid,
-					   &ap_mld_id) ||
-	    !missing_links)
+					   &missing_links) || !missing_links)
 		return 0;
 
 	removed_links = wpa_bss_parse_reconf_ml_element(wpa_s, selected);
@@ -1928,36 +1895,7 @@
 	wpa_s->manual_scan_freqs = freqs;
 
 	os_memcpy(wpa_s->ml_probe_bssid, selected->bssid, ETH_ALEN);
-
-	/*
-	 * In case the ML probe request is intended to retrieve information from
-	 * the transmitted BSS, the AP MLD ID should be included and should be
-	 * set to zero.
-	 * In case the ML probe requested is intended to retrieve information
-	 * from a non-transmitted BSS, the AP MLD ID should not be included.
-	 */
-	if (ap_mld_id)
-		wpa_s->ml_probe_mld_id = -1;
-	else
-		wpa_s->ml_probe_mld_id = 0;
-
-	if (ssid && ssid->ssid_len) {
-		os_free(wpa_s->ssids_from_scan_req);
-		wpa_s->num_ssids_from_scan_req = 0;
-
-		wpa_s->ssids_from_scan_req =
-			os_zalloc(sizeof(struct wpa_ssid_value));
-		if (wpa_s->ssids_from_scan_req) {
-			wpa_printf(MSG_DEBUG,
-				   "MLD: ML probe: With direct SSID");
-
-			wpa_s->num_ssids_from_scan_req = 1;
-			wpa_s->ssids_from_scan_req[0].ssid_len = ssid->ssid_len;
-			os_memcpy(wpa_s->ssids_from_scan_req[0].ssid,
-				  ssid->ssid, ssid->ssid_len);
-		}
-	}
-
+	wpa_s->ml_probe_mld_id = -1;
 	wpa_s->ml_probe_links = missing_links;
 
 	wpa_s->normal_scans = 0;
@@ -2014,11 +1952,12 @@
 	 * the selected BSSID, do not trigger new attempt.
 	 */
 	if (wpa_s->reassociate ||
-	    (!ether_addr_equal(selected->bssid, wpa_s->bssid) &&
+	    (os_memcmp(selected->bssid, wpa_s->bssid, ETH_ALEN) != 0 &&
 	     ((wpa_s->wpa_state != WPA_ASSOCIATING &&
 	       wpa_s->wpa_state != WPA_AUTHENTICATING) ||
 	      (!is_zero_ether_addr(wpa_s->pending_bssid) &&
-	       !ether_addr_equal(selected->bssid, wpa_s->pending_bssid)) ||
+	       os_memcmp(selected->bssid, wpa_s->pending_bssid, ETH_ALEN) !=
+	       0) ||
 	      (is_zero_ether_addr(wpa_s->pending_bssid) &&
 	       ssid != wpa_s->current_ssid)))) {
 		if (wpa_supplicant_scard_init(wpa_s, ssid)) {
@@ -2131,22 +2070,11 @@
 }
 
 
-static int wpas_evaluate_band_score(int frequency)
-{
-	if (is_6ghz_freq(frequency))
-		return 2;
-	if (IS_5GHZ(frequency))
-		return 1;
-	return 0;
-}
-
-
 int wpa_supplicant_need_to_roam_within_ess(struct wpa_supplicant *wpa_s,
 					   struct wpa_bss *current_bss,
 					   struct wpa_bss *selected)
 {
 	int min_diff, diff;
-	int cur_band_score, sel_band_score;
 	int to_5ghz, to_6ghz;
 	int cur_level, sel_level;
 	unsigned int cur_est, sel_est;
@@ -2172,7 +2100,8 @@
 		selected->snr, selected->est_throughput);
 
 	if (wpa_s->current_ssid->bssid_set &&
-	    ether_addr_equal(selected->bssid, wpa_s->current_ssid->bssid)) {
+	    os_memcmp(selected->bssid, wpa_s->current_ssid->bssid, ETH_ALEN) ==
+	    0) {
 		wpa_dbg(wpa_s, MSG_DEBUG, "Allow reassociation - selected BSS "
 			"has preferred BSSID");
 		return 1;
@@ -2292,11 +2221,9 @@
 	else if (sel_est > cur_est)
 		min_diff--;
 
-	cur_band_score = wpas_evaluate_band_score(current_bss->freq);
-	sel_band_score = wpas_evaluate_band_score(selected->freq);
-	min_diff += (cur_band_score - sel_band_score) * 2;
-	if (wpa_s->signal_threshold && cur_level <= wpa_s->signal_threshold &&
-	    sel_level > wpa_s->signal_threshold)
+	if (to_5ghz)
+		min_diff -= 2;
+	if (to_6ghz)
 		min_diff -= 2;
 	diff = sel_level - cur_level;
 	if (diff < min_diff) {
@@ -2329,7 +2256,6 @@
 				       struct wpa_ssid *ssid)
 {
 	struct wpa_bss *current_bss = NULL;
-	const u8 *bssid;
 
 	if (wpa_s->reassociate)
 		return 1; /* explicit request to reassociate */
@@ -2343,17 +2269,12 @@
 	if (wpas_driver_bss_selection(wpa_s))
 		return 0; /* Driver-based roaming */
 
-	if (wpa_s->valid_links)
-		bssid = wpa_s->links[wpa_s->mlo_assoc_link_id].bssid;
-	else
-		bssid = wpa_s->bssid;
-
 	if (wpa_s->current_ssid->ssid)
-		current_bss = wpa_bss_get(wpa_s, bssid,
+		current_bss = wpa_bss_get(wpa_s, wpa_s->bssid,
 					  wpa_s->current_ssid->ssid,
 					  wpa_s->current_ssid->ssid_len);
 	if (!current_bss)
-		current_bss = wpa_bss_get_bssid(wpa_s, bssid);
+		current_bss = wpa_bss_get_bssid(wpa_s, wpa_s->bssid);
 
 	if (!current_bss)
 		return 1; /* current BSS not seen in scan results */
@@ -2408,7 +2329,7 @@
 
 	scan_res = wpa_supplicant_get_scan_results(wpa_s,
 						   data ? &data->scan_info :
-						   NULL, 1, NULL);
+						   NULL, 1);
 	if (scan_res == NULL) {
 		if (wpa_s->conf->ap_scan == 2 || ap ||
 		    wpa_s->scan_res_handler == scan_only_handler)
@@ -2497,17 +2418,15 @@
 		return 0;
 	}
 
-	if (wnm_scan_process(wpa_s, false) > 0)
+	if (wnm_scan_process(wpa_s, 1) > 0)
 		goto scan_work_done;
 
 	if (sme_proc_obss_scan(wpa_s) > 0)
 		goto scan_work_done;
 
-#ifndef CONFIG_NO_RRM
 	if (own_request && data &&
 	    wpas_beacon_rep_scan_process(wpa_s, scan_res, &data->scan_info) > 0)
 		goto scan_work_done;
-#endif /* CONFIG_NO_RRM */
 
 	if (ml_link_probe_scan(wpa_s))
 		goto scan_work_done;
@@ -2940,6 +2859,8 @@
 }
 
 
+#ifdef CONFIG_INTERWORKING
+
 static int wpas_qos_map_set(struct wpa_supplicant *wpa_s, const u8 *qos_map,
 			    size_t len)
 {
@@ -2972,6 +2893,8 @@
 	}
 }
 
+#endif /* CONFIG_INTERWORKING */
+
 
 static void wpa_supplicant_set_4addr_mode(struct wpa_supplicant *wpa_s)
 {
@@ -2997,24 +2920,25 @@
 					const u8 *ies, size_t ies_len)
 {
 	struct ieee802_11_elems elems;
-	struct multi_ap_params multi_ap;
-	u16 status;
+	const u8 *map_sub_elem, *pos;
+	size_t len;
 
 	wpa_s->multi_ap_ie = 0;
 
 	if (!ies ||
 	    ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed ||
-	    !elems.multi_ap)
+	    !elems.multi_ap || elems.multi_ap_len < 7)
 		return;
 
-	status = check_multi_ap_ie(elems.multi_ap + 4, elems.multi_ap_len - 4,
-				   &multi_ap);
-	if (status != WLAN_STATUS_SUCCESS)
+	pos = elems.multi_ap + 4;
+	len = elems.multi_ap_len - 4;
+
+	map_sub_elem = get_ie(pos, len, MULTI_AP_SUB_ELEM_TYPE);
+	if (!map_sub_elem || map_sub_elem[1] < 1)
 		return;
 
-	wpa_s->multi_ap_backhaul = !!(multi_ap.capability &
-				      MULTI_AP_BACKHAUL_BSS);
-	wpa_s->multi_ap_fronthaul = !!(multi_ap.capability &
+	wpa_s->multi_ap_backhaul = !!(map_sub_elem[2] & MULTI_AP_BACKHAUL_BSS);
+	wpa_s->multi_ap_fronthaul = !!(map_sub_elem[2] &
 				       MULTI_AP_FRONTHAUL_BSS);
 	wpa_s->multi_ap_ie = 1;
 }
@@ -3353,8 +3277,10 @@
 		wnm_process_assoc_resp(wpa_s, data->assoc_info.resp_ies,
 				       data->assoc_info.resp_ies_len);
 #endif /* CONFIG_WNM */
+#ifdef CONFIG_INTERWORKING
 		interworking_process_assoc_resp(wpa_s, data->assoc_info.resp_ies,
 						data->assoc_info.resp_ies_len);
+#endif /* CONFIG_INTERWORKING */
 		if (wpa_s->hw_capab == CAPAB_VHT &&
 		    get_ie(data->assoc_info.resp_ies,
 			   data->assoc_info.resp_ies_len, WLAN_EID_VHT_CAP))
@@ -3660,12 +3586,10 @@
 			     data->assoc_info.resp_ies_len);
 #endif /* CONFIG_IEEE80211R */
 
-#ifndef CONFIG_NO_ROBUST_AV
 	if (bssid_known)
 		wpas_handle_assoc_resp_mscs(wpa_s, bssid,
 					    data->assoc_info.resp_ies,
 					    data->assoc_info.resp_ies_len);
-#endif /* CONFIG_NO_ROBUST_AV */
 
 	/* WPA/RSN IE from Beacon/ProbeResp */
 	p = data->assoc_info.beacon_ies;
@@ -3710,29 +3634,18 @@
 	if (wpa_found || rsn_found)
 		wpa_s->ap_ies_from_associnfo = 1;
 
-	if (wpa_s->assoc_freq && data->assoc_info.freq) {
-		struct wpa_bss *bss;
-		unsigned int freq = 0;
-
-		if (bssid_known) {
-			bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
-			if (bss)
-				freq = bss->freq;
-		}
-		if (freq != data->assoc_info.freq) {
-			wpa_printf(MSG_DEBUG,
-				   "Operating frequency changed from %u to %u MHz",
-				   wpa_s->assoc_freq, data->assoc_info.freq);
-			wpa_supplicant_update_scan_results(wpa_s, bssid);
-		}
+	if (wpa_s->assoc_freq && data->assoc_info.freq &&
+	    wpa_s->assoc_freq != data->assoc_info.freq) {
+		wpa_printf(MSG_DEBUG, "Operating frequency changed from "
+			   "%u to %u MHz",
+			   wpa_s->assoc_freq, data->assoc_info.freq);
+		wpa_supplicant_update_scan_results(wpa_s);
 	}
 
 	wpa_s->assoc_freq = data->assoc_info.freq;
 
-#ifndef CONFIG_NO_ROBUST_AV
 	wpas_handle_assoc_resp_qos_mgmt(wpa_s, data->assoc_info.resp_ies,
 					data->assoc_info.resp_ies_len);
-#endif /* CONFIG_NO_ROBUST_AV */
 
 	return 0;
 }
@@ -3804,261 +3717,6 @@
 }
 
 
-static unsigned int wpas_ml_parse_assoc(struct wpa_supplicant *wpa_s,
-					struct ieee802_11_elems *elems,
-					struct ml_sta_link_info *ml_info)
-{
-	struct wpabuf *mlbuf;
-	struct ieee80211_eht_ml *ml;
-	size_t ml_len;
-	struct eht_ml_basic_common_info *common_info;
-	const u8 *pos;
-	u16 eml_capa = 0, mld_capa = 0;
-	const u16 control =
-		host_to_le16(MULTI_LINK_CONTROL_TYPE_BASIC |
-			     BASIC_MULTI_LINK_CTRL_PRES_LINK_ID |
-			     BASIC_MULTI_LINK_CTRL_PRES_BSS_PARAM_CH_COUNT);
-	u8 expected_common_info_len = 9;
-	unsigned int i = 0;
-	u16 ml_control;
-
-	if (!wpa_s->valid_links || !elems->basic_mle || !elems->basic_mle_len)
-		return 0;
-
-	mlbuf = ieee802_11_defrag(elems->basic_mle, elems->basic_mle_len, true);
-	if (!mlbuf)
-		return 0;
-
-	ml = (struct ieee80211_eht_ml *) wpabuf_head(mlbuf);
-	ml_len = wpabuf_len(mlbuf);
-	if (ml_len < sizeof(*ml))
-		goto out;
-
-	os_memset(ml_info, 0, sizeof(*ml_info) * MAX_NUM_MLD_LINKS);
-
-	ml_control = le_to_host16(ml->ml_control);
-
-	if ((ml_control & control) != control) {
-		wpa_printf(MSG_DEBUG, "MLD: Invalid presence BM=0x%x",
-			   ml_control);
-		goto out;
-	}
-
-	if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_EML_CAPA) {
-		wpa_printf(MSG_DEBUG, "MLD: EML capabilities included");
-		expected_common_info_len += 2;
-	}
-
-	if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_MLD_CAPA) {
-		wpa_printf(MSG_DEBUG, "MLD: MLD capabilities included");
-		expected_common_info_len += 2;
-	}
-
-	if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_MSD_INFO) {
-		wpa_printf(MSG_DEBUG,
-			   "MLD: Unexpected: medium sync delay info present");
-		expected_common_info_len += 2;
-	}
-
-	if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_AP_MLD_ID) {
-		wpa_printf(MSG_DEBUG,
-			   "MLD: Unexpected: MLD ID present");
-		expected_common_info_len++;
-	}
-
-	if (sizeof(*ml) + expected_common_info_len > ml_len) {
-		wpa_printf(MSG_DEBUG,
-			   "MLD: Not enough bytes for common info. ml_len=%zu",
-			   ml_len);
-		goto out;
-	}
-
-	common_info = (struct eht_ml_basic_common_info *) ml->variable;
-	if (common_info->len != expected_common_info_len) {
-		wpa_printf(MSG_DEBUG,
-			   "MLD: Invalid common info len=%u. expected=%u",
-			   common_info->len, expected_common_info_len);
-		goto out;
-	}
-
-	wpa_printf(MSG_DEBUG, "MLD: address: " MACSTR,
-		   MAC2STR(common_info->mld_addr));
-
-	if (!ether_addr_equal(wpa_s->ap_mld_addr, common_info->mld_addr)) {
-		wpa_printf(MSG_DEBUG, "MLD: Mismatching MLD address (expected "
-			   MACSTR ")", MAC2STR(wpa_s->ap_mld_addr));
-		goto out;
-	}
-
-	pos = common_info->variable;
-
-	/* Store the information for the association link */
-	ml_info[i].link_id = *pos;
-	pos++;
-
-	/* Skip the BSS Parameters Change Count */
-	pos++;
-
-	/* Skip the Medium Synchronization Delay Information if present  */
-	if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_MSD_INFO)
-		pos += 2;
-
-	if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_EML_CAPA) {
-		eml_capa = WPA_GET_LE16(pos);
-		pos += 2;
-	}
-
-	if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_MLD_CAPA) {
-		mld_capa = WPA_GET_LE16(pos);
-		pos += 2;
-	}
-
-	wpa_printf(MSG_DEBUG,
-		   "MLD: link_id=%u, eml=0x%x, mld=0x%x",
-		   ml_info[i].link_id, eml_capa, mld_capa);
-
-	i++;
-
-	pos = ((u8 *) common_info) + common_info->len;
-	ml_len -= sizeof(*ml) + common_info->len;
-	while (ml_len > 2 && i < MAX_NUM_MLD_LINKS) {
-		u8 sub_elem_len = pos[1];
-		u8 sta_info_len;
-		u8 nstr_bitmap_len = 0;
-		u16 ctrl;
-		const u8 *end;
-
-		wpa_printf(MSG_DEBUG, "MLD: Subelement len=%u", sub_elem_len);
-
-		if (sub_elem_len > ml_len - 2) {
-			wpa_printf(MSG_DEBUG,
-				   "MLD: Invalid link info len: %u > %zu",
-				   2 + sub_elem_len, ml_len);
-			goto out;
-		}
-
-		switch (*pos) {
-		case EHT_ML_SUB_ELEM_PER_STA_PROFILE:
-			break;
-		case EHT_ML_SUB_ELEM_FRAGMENT:
-		case EHT_ML_SUB_ELEM_VENDOR:
-			wpa_printf(MSG_DEBUG,
-				   "MLD: Skip subelement id=%u, len=%u",
-				   *pos, sub_elem_len);
-			pos += 2 + sub_elem_len;
-			ml_len -= 2 + sub_elem_len;
-			continue;
-		default:
-			wpa_printf(MSG_DEBUG, "MLD: Unknown subelement ID=%u",
-				   *pos);
-			goto out;
-		}
-
-		end = pos + 2 + sub_elem_len;
-
-		/* Skip the subelement ID and the length */
-		pos += 2;
-		ml_len -= 2;
-
-		if (end - pos < 2)
-			goto out;
-
-		/* Get the station control field */
-		ctrl = WPA_GET_LE16(pos);
-
-		pos += 2;
-		ml_len -= 2;
-
-		if (!(ctrl & EHT_PER_STA_CTRL_COMPLETE_PROFILE_MSK)) {
-			wpa_printf(MSG_DEBUG,
-				   "MLD: Per STA complete profile expected");
-			goto out;
-		}
-
-		if (!(ctrl & EHT_PER_STA_CTRL_MAC_ADDR_PRESENT_MSK)) {
-			wpa_printf(MSG_DEBUG,
-				   "MLD: Per STA MAC address not present");
-			goto out;
-		}
-
-		if (!(ctrl & EHT_PER_STA_CTRL_TSF_OFFSET_PRESENT_MSK)) {
-			wpa_printf(MSG_DEBUG,
-				   "MLD: Per STA TSF offset not present");
-			goto out;
-		}
-
-		if (!(ctrl & EHT_PER_STA_CTRL_BEACON_INTERVAL_PRESENT_MSK)) {
-			wpa_printf(MSG_DEBUG,
-				   "MLD: Beacon interval not present");
-			goto out;
-		}
-
-		if (!(ctrl & EHT_PER_STA_CTRL_DTIM_INFO_PRESENT_MSK)) {
-			wpa_printf(MSG_DEBUG,
-				   "MLD:  DTIM information not present");
-			goto out;
-		}
-
-		if (ctrl & EHT_PER_STA_CTRL_NSTR_LINK_PAIR_PRESENT_MSK) {
-			if (ctrl & EHT_PER_STA_CTRL_NSTR_BM_SIZE_MSK)
-				nstr_bitmap_len = 2;
-			else
-				nstr_bitmap_len = 1;
-		}
-
-		if (!(ctrl & EHT_PER_STA_CTRL_BSS_PARAM_CNT_PRESENT_MSK)) {
-			wpa_printf(MSG_DEBUG,
-				   "MLD:  BSS params change count not present");
-			goto out;
-		}
-
-		sta_info_len = 1 + ETH_ALEN + 8 + 2 + 2 + 1 + nstr_bitmap_len;
-		if (sta_info_len > ml_len || sta_info_len > end - pos ||
-		    sta_info_len + 2 > sub_elem_len ||
-		    sta_info_len != *pos) {
-			wpa_printf(MSG_DEBUG,
-				   "MLD: Invalid STA info len=%u, len=%u",
-				   sta_info_len, *pos);
-			goto out;
-		}
-
-		/* Get the link address */
-		wpa_printf(MSG_DEBUG,
-			   "MLD: link addr: " MACSTR " nstr BM len=%u",
-			   MAC2STR(pos + 1), nstr_bitmap_len);
-
-		ml_info[i].link_id = ctrl & EHT_PER_STA_CTRL_LINK_ID_MSK;
-		os_memcpy(ml_info[i].bssid, pos + 1, ETH_ALEN);
-
-		pos += sta_info_len;
-		ml_len -= sta_info_len;
-
-		wpa_printf(MSG_DEBUG, "MLD: sub_elem_len=%u, sta_info_len=%u",
-			   sub_elem_len, sta_info_len);
-
-		sub_elem_len -= sta_info_len + 2;
-		if (sub_elem_len < 4) {
-			wpa_printf(MSG_DEBUG, "MLD: Per STA profile too short");
-			goto out;
-		}
-
-		wpa_hexdump(MSG_MSGDUMP, "MLD: STA profile", pos, sub_elem_len);
-		ml_info[i].status = WPA_GET_LE16(pos + 2);
-
-		pos += sub_elem_len;
-		ml_len -= sub_elem_len;
-
-		i++;
-	}
-
-	wpabuf_free(mlbuf);
-	return i;
-out:
-	wpabuf_free(mlbuf);
-	return 0;
-}
-
-
 static int wpa_drv_get_mlo_info(struct wpa_supplicant *wpa_s)
 {
 	struct driver_sta_mlo_info mlo;
@@ -4078,25 +3736,32 @@
 		if (!mlo.valid_links)
 			return 0;
 
-		for_each_link(mlo.valid_links, i) {
-			if (!ether_addr_equal(wpa_s->links[i].addr,
-					      mlo.links[i].addr) ||
-			    !ether_addr_equal(wpa_s->links[i].bssid,
-					      mlo.links[i].bssid)) {
+		for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+			if (!(mlo.valid_links & BIT(i)))
+				continue;
+
+			if (os_memcmp(wpa_s->links[i].addr, mlo.links[i].addr,
+				      ETH_ALEN) != 0 ||
+			    os_memcmp(wpa_s->links[i].bssid, mlo.links[i].bssid,
+				      ETH_ALEN) != 0) {
 				match = false;
 				break;
 			}
 		}
 
 		if (match && wpa_s->mlo_assoc_link_id == mlo.assoc_link_id &&
-		    ether_addr_equal(wpa_s->ap_mld_addr, mlo.ap_mld_addr))
+		    os_memcmp(wpa_s->ap_mld_addr, mlo.ap_mld_addr,
+			      ETH_ALEN) == 0)
 			return 0;
 	}
 
 	wpa_s->valid_links = mlo.valid_links;
 	wpa_s->mlo_assoc_link_id = mlo.assoc_link_id;
 	os_memcpy(wpa_s->ap_mld_addr, mlo.ap_mld_addr, ETH_ALEN);
-	for_each_link(wpa_s->valid_links, i) {
+	for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+		if (!(wpa_s->valid_links & BIT(i)))
+			continue;
+
 		os_memcpy(wpa_s->links[i].addr, mlo.links[i].addr, ETH_ALEN);
 		os_memcpy(wpa_s->links[i].bssid, mlo.links[i].bssid, ETH_ALEN);
 		wpa_s->links[i].freq = mlo.links[i].freq;
@@ -4129,13 +3794,15 @@
 	wpa_mlo.valid_links = drv_mlo.valid_links;
 	wpa_mlo.req_links = drv_mlo.req_links;
 
-	for_each_link(drv_mlo.req_links, i) {
+	for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
 		struct wpa_bss *bss;
 
+		if (!(drv_mlo.req_links & BIT(i)))
+			continue;
+
 		bss = wpa_supplicant_get_new_bss(wpa_s, drv_mlo.links[i].bssid);
 		if (!bss) {
-			wpa_supplicant_update_scan_results(
-				wpa_s, drv_mlo.links[i].bssid);
+			wpa_supplicant_update_scan_results(wpa_s);
 			bss = wpa_supplicant_get_new_bss(
 				wpa_s, drv_mlo.links[i].bssid);
 		}
@@ -4272,7 +3939,7 @@
 #endif
 
 	wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATED);
-	if (!ether_addr_equal(bssid, wpa_s->bssid)) {
+	if (os_memcmp(bssid, wpa_s->bssid, ETH_ALEN) != 0) {
 		if (os_reltime_initialized(&wpa_s->session_start)) {
 			os_reltime_age(&wpa_s->session_start,
 				       &wpa_s->session_length);
@@ -4471,9 +4138,9 @@
 		os_get_reltime(&now);
 		os_reltime_sub(&now, &wpa_s->pending_eapol_rx_time, &age);
 		if (age.sec == 0 && age.usec < 200000 &&
-		    ether_addr_equal(wpa_s->pending_eapol_rx_src,
-				     wpa_s->valid_links ? wpa_s->ap_mld_addr :
-				     bssid)) {
+		    os_memcmp(wpa_s->pending_eapol_rx_src,
+			      wpa_s->valid_links ? wpa_s->ap_mld_addr : bssid,
+			      ETH_ALEN) == 0) {
 			wpa_dbg(wpa_s, MSG_DEBUG, "Process pending EAPOL "
 				"frame that was received just before "
 				"association notification");
@@ -4517,7 +4184,6 @@
 
 	wpas_wps_notify_assoc(wpa_s, bssid);
 
-#ifndef CONFIG_NO_WMM_AC
 	if (data) {
 		wmm_ac_notify_assoc(wpa_s, data->assoc_info.resp_ies,
 				    data->assoc_info.resp_ies_len,
@@ -4526,7 +4192,6 @@
 		if (wpa_s->reassoc_same_bss)
 			wmm_ac_restore_tspecs(wpa_s);
 	}
-#endif /* CONFIG_NO_WMM_AC */
 
 #if defined(CONFIG_FILS) || defined(CONFIG_MBO)
 	bss = wpa_bss_get_bssid(wpa_s, bssid);
@@ -4619,10 +4284,16 @@
 						 int locally_generated)
 {
 	const u8 *bssid;
+	int authenticating;
+	u8 prev_pending_bssid[ETH_ALEN];
 	struct wpa_bss *fast_reconnect = NULL;
 	struct wpa_ssid *fast_reconnect_ssid = NULL;
+	struct wpa_ssid *last_ssid;
 	struct wpa_bss *curr = NULL;
 
+	authenticating = wpa_s->wpa_state == WPA_AUTHENTICATING;
+	os_memcpy(prev_pending_bssid, wpa_s->pending_bssid, ETH_ALEN);
+
 	if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
 		/*
 		 * At least Host AP driver and a Prism3 card seemed to be
@@ -4652,7 +4323,7 @@
 			"pre-shared key may be incorrect");
 		if (wpas_p2p_4way_hs_failed(wpa_s) > 0)
 			return; /* P2P group removed */
-		wpas_auth_failed(wpa_s, "WRONG_KEY", wpa_s->pending_bssid);
+		wpas_auth_failed(wpa_s, "WRONG_KEY", prev_pending_bssid);
 		wpas_notify_psk_mismatch(wpa_s);
 #ifdef CONFIG_DPP2
 		wpas_dpp_send_conn_status_result(wpa_s,
@@ -4703,7 +4374,7 @@
 	if (is_zero_ether_addr(bssid))
 		bssid = wpa_s->pending_bssid;
 	if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
-		wpas_connection_failed(wpa_s, bssid, NULL);
+		wpas_connection_failed(wpa_s, bssid);
 	wpa_sm_notify_disassoc(wpa_s->wpa);
 	ptksa_cache_flush(wpa_s->ptksa, wpa_s->bssid, WPA_CIPHER_NONE);
 
@@ -4716,11 +4387,17 @@
 		wpa_dbg(wpa_s, MSG_DEBUG, "Disconnect event - remove keys");
 		wpa_clear_keys(wpa_s, wpa_s->bssid);
 	}
+	last_ssid = wpa_s->current_ssid;
 	wpa_supplicant_mark_disassoc(wpa_s);
 
 	if (curr)
 		wpa_bss_remove(wpa_s, curr, "Connection to AP lost");
 
+	if (authenticating && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)) {
+		sme_disassoc_while_authenticating(wpa_s, prev_pending_bssid);
+		wpa_s->current_ssid = last_ssid;
+	}
+
 	if (fast_reconnect &&
 	    !wpas_network_disabled(wpa_s, fast_reconnect_ssid) &&
 	    !disallowed_bssid(wpa_s, fast_reconnect->bssid) &&
@@ -5070,7 +4747,7 @@
 		MACSTR " TargetAP " MACSTR " status %u",
 		MAC2STR(sta_addr), MAC2STR(target_ap_addr), status);
 
-	if (!ether_addr_equal(sta_addr, wpa_s->own_addr)) {
+	if (os_memcmp(sta_addr, wpa_s->own_addr, ETH_ALEN) != 0) {
 		wpa_dbg(wpa_s, MSG_DEBUG, "FT: Foreign STA Address " MACSTR
 			" in FT Action Response", MAC2STR(sta_addr));
 		return;
@@ -5297,20 +4974,6 @@
 }
 
 
-static void wpas_beacon_hint(struct wpa_supplicant *wpa_s, const char *title,
-			     struct frequency_attrs *attrs)
-{
-	if (!attrs->freq)
-		return;
-	wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REGDOM_BEACON_HINT
-		"%s freq=%u max_tx_power=%u%s%s%s",
-		title, attrs->freq, attrs->max_tx_power,
-		attrs->disabled ? " disabled=1" : "",
-		attrs->no_ir ? " no_ir=1" : "",
-		attrs->radar ? " radar=1" : "");
-}
-
-
 void wpa_supplicant_update_channel_list(struct wpa_supplicant *wpa_s,
 					struct channel_list_changed *info)
 {
@@ -5332,13 +4995,6 @@
 			reg_init_str(info->initiator), reg_type_str(info->type),
 			info->alpha2[0] ? " alpha2=" : "",
 			info->alpha2[0] ? info->alpha2 : "");
-
-		if (info->initiator == REGDOM_BEACON_HINT) {
-			wpas_beacon_hint(ifs, "before",
-					 &info->beacon_hint_before);
-			wpas_beacon_hint(ifs, "after",
-					 &info->beacon_hint_after);
-		}
 	}
 
 	if (wpa_s->drv_priv == NULL)
@@ -5399,12 +5055,10 @@
 		" Category=%u DataLen=%d freq=%d MHz",
 		MAC2STR(mgmt->sa), category, (int) plen, freq);
 
-#ifndef CONFIG_NO_WMM_AC
 	if (category == WLAN_ACTION_WMM) {
 		wmm_ac_rx_action(wpa_s, mgmt->da, mgmt->sa, payload, plen);
 		return;
 	}
-#endif /* CONFIG_NO_WMM_AC */
 
 #ifdef CONFIG_IEEE80211R
 	if (category == WLAN_ACTION_FT) {
@@ -5468,7 +5122,7 @@
 		size_t qlen = plen - 1;
 		wpa_dbg(wpa_s, MSG_DEBUG, "Interworking: Received QoS Map Configure frame from "
 			MACSTR, MAC2STR(mgmt->sa));
-		if (ether_addr_equal(mgmt->sa, wpa_s->bssid) &&
+		if (os_memcmp(mgmt->sa, wpa_s->bssid, ETH_ALEN) == 0 &&
 		    qlen > 2 && pos[0] == WLAN_EID_QOS_MAP_SET &&
 		    pos[1] <= qlen - 2 && pos[1] >= 16)
 			wpas_qos_map_set(wpa_s, pos + 2, pos[1]);
@@ -5476,7 +5130,6 @@
 	}
 #endif /* CONFIG_INTERWORKING */
 
-#ifndef CONFIG_NO_RRM
 	if (category == WLAN_ACTION_RADIO_MEASUREMENT &&
 	    payload[0] == WLAN_RRM_RADIO_MEASUREMENT_REQUEST) {
 		wpas_rrm_handle_radio_measurement_request(wpa_s, mgmt->sa,
@@ -5499,7 +5152,6 @@
 							 rssi);
 		return;
 	}
-#endif /* CONFIG_NO_RRM */
 
 #ifdef CONFIG_FST
 	if (mgmt->u.action.category == WLAN_ACTION_FST && wpa_s->fst) {
@@ -5508,17 +5160,6 @@
 	}
 #endif /* CONFIG_FST */
 
-#ifdef CONFIG_NAN_USD
-	if (category == WLAN_ACTION_PUBLIC && plen >= 5 &&
-	    payload[0] == WLAN_PA_VENDOR_SPECIFIC &&
-	    WPA_GET_BE32(&payload[1]) == NAN_SDF_VENDOR_TYPE) {
-		payload += 5;
-		plen -= 5;
-		wpas_nan_usd_rx_sdf(wpa_s, mgmt->sa, freq, payload, plen);
-		return;
-	}
-#endif /* CONFIG_NAN_USD */
-
 #ifdef CONFIG_DPP
 	if (category == WLAN_ACTION_PUBLIC && plen >= 5 &&
 	    payload[0] == WLAN_PA_VENDOR_SPECIFIC &&
@@ -5531,7 +5172,6 @@
 	}
 #endif /* CONFIG_DPP */
 
-#ifndef CONFIG_NO_ROBUST_AV
 	if (category == WLAN_ACTION_ROBUST_AV_STREAMING &&
 	    payload[0] == ROBUST_AV_SCS_RESP) {
 		wpas_handle_robust_av_scs_recv_action(wpa_s, mgmt->sa,
@@ -5552,7 +5192,6 @@
 						 payload + 4, plen - 4);
 		return;
 	}
-#endif /* CONFIG_NO_ROBUST_AV */
 
 	wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid,
 			   category, payload, plen, freq);
@@ -5756,8 +5395,6 @@
 				    union wpa_event_data *data)
 {
 	const u8 *bssid = data->assoc_reject.bssid;
-	struct ieee802_11_elems elems;
-	const u8 *link_bssids[MAX_NUM_MLD_LINKS];
 #ifdef CONFIG_MBO
 	struct wpa_bss *reject_bss;
 #endif /* CONFIG_MBO */
@@ -5813,7 +5450,7 @@
 		if (!bss) {
 			bss = wpa_supplicant_get_new_bss(wpa_s, bssid);
 			if (!bss) {
-				wpas_connection_failed(wpa_s, bssid, NULL);
+				wpas_connection_failed(wpa_s, bssid);
 				wpa_supplicant_mark_disassoc(wpa_s);
 				return;
 			}
@@ -5848,7 +5485,7 @@
 		if (!bss || wpa_s->dpp_pfs_fallback) {
 			wpa_printf(MSG_DEBUG,
 				   "DPP: Updated PFS policy for next try");
-			wpas_connection_failed(wpa_s, bssid, NULL);
+			wpas_connection_failed(wpa_s, bssid);
 			wpa_supplicant_mark_disassoc(wpa_s);
 			return;
 		}
@@ -5885,34 +5522,8 @@
 	}
 #endif /* CONFIG_MBO */
 
-	/* Check for other failed links in the response */
-	os_memset(link_bssids, 0, sizeof(link_bssids));
-	if (ieee802_11_parse_elems(data->assoc_reject.resp_ies,
-				   data->assoc_reject.resp_ies_len,
-				   &elems, 1) != ParseFailed) {
-		struct ml_sta_link_info ml_info[MAX_NUM_MLD_LINKS];
-		unsigned int n_links, i, idx;
-
-		idx = 0;
-		n_links = wpas_ml_parse_assoc(wpa_s, &elems, ml_info);
-
-		for (i = 1; i < n_links; i++) {
-			/* The status cannot be success here.
-			 * Add the link to the failed list if it is reporting
-			 * an error. The only valid "non-error" status is
-			 * TX_LINK_NOT_ACCEPTED as that means this link may
-			 * still accept an association from us.
-			 */
-			if (ml_info[i].status !=
-			    WLAN_STATUS_DENIED_TX_LINK_NOT_ACCEPTED) {
-				link_bssids[idx] = ml_info[i].bssid;
-				idx++;
-			}
-		}
-	}
-
 	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) {
-		sme_event_assoc_reject(wpa_s, data, link_bssids);
+		sme_event_assoc_reject(wpa_s, data);
 		return;
 	}
 
@@ -5949,7 +5560,7 @@
 	}
 #endif /* CONFIG_FILS */
 
-	wpas_connection_failed(wpa_s, bssid, link_bssids);
+	wpas_connection_failed(wpa_s, bssid);
 	wpa_supplicant_mark_disassoc(wpa_s);
 }
 
@@ -5961,7 +5572,7 @@
 	int res;
 
 	if (!data || wpa_s->wpa_state != WPA_COMPLETED ||
-	    !ether_addr_equal(data->sa, wpa_s->bssid))
+	    os_memcmp(data->sa, wpa_s->bssid, ETH_ALEN) != 0)
 		return;
 	wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_UNPROT_BEACON MACSTR,
 		MAC2STR(data->sa));
@@ -6014,10 +5625,13 @@
 	pos += res;
 
 	if (!info->default_map) {
-		for_each_link(info->valid_links, i) {
+		for (i = 0; i < MAX_NUM_MLD_LINKS && end > pos; i++) {
 			char uplink_map_str[9];
 			char downlink_map_str[9];
 
+			if (!(info->valid_links & BIT(i)))
+				continue;
+
 			bitmap_to_str(info->t2lmap[i].uplink, uplink_map_str);
 			bitmap_to_str(info->t2lmap[i].downlink,
 				      downlink_map_str);
@@ -6048,7 +5662,7 @@
 		return;
 	}
 
-	if (!ether_addr_equal(bssid, wpa_s->bssid)) {
+	if (os_memcmp(bssid, wpa_s->bssid, ETH_ALEN) != 0) {
 		os_memcpy(wpa_s->bssid, bssid, ETH_ALEN);
 		wpa_supplicant_update_current_bss(wpa_s, wpa_s->bssid);
 		wpas_notify_bssid_changed(wpa_s);
@@ -6297,13 +5911,6 @@
 			" type=%d stype=%d",
 			MAC2STR(data->tx_status.dst),
 			data->tx_status.type, data->tx_status.stype);
-#ifdef CONFIG_WNM
-		if (data->tx_status.type == WLAN_FC_TYPE_MGMT &&
-		    data->tx_status.stype == WLAN_FC_STYPE_ACTION &&
-		    wnm_btm_resp_tx_status(wpa_s, data->tx_status.data,
-					   data->tx_status.data_len) == 0)
-			break;
-#endif /* CONFIG_WNM */
 #ifdef CONFIG_PASN
 		if (data->tx_status.type == WLAN_FC_TYPE_MGMT &&
 		    data->tx_status.stype == WLAN_FC_STYPE_AUTH &&
@@ -6340,8 +5947,8 @@
 		 */
 		if (data->tx_status.type == WLAN_FC_TYPE_MGMT &&
 		    data->tx_status.stype == WLAN_FC_STYPE_ACTION &&
-		    ether_addr_equal(wpa_s->p2pdev->pending_action_dst,
-				     data->tx_status.dst)) {
+		    os_memcmp(wpa_s->p2pdev->pending_action_dst,
+			      data->tx_status.dst, ETH_ALEN) == 0) {
 			offchannel_send_action_tx_status(
 				wpa_s->p2pdev, data->tx_status.dst,
 				data->tx_status.data,
@@ -6664,11 +6271,6 @@
 			wpa_s, data->remain_on_channel.freq,
 			data->remain_on_channel.duration);
 #endif /* CONFIG_DPP */
-#ifdef CONFIG_NAN_USD
-		wpas_nan_usd_remain_on_channel_cb(
-			wpa_s, data->remain_on_channel.freq,
-			data->remain_on_channel.duration);
-#endif /* CONFIG_NAN_USD */
 		break;
 	case EVENT_CANCEL_REMAIN_ON_CHANNEL:
 #ifdef CONFIG_OFFCHANNEL
@@ -6681,10 +6283,6 @@
 		wpas_dpp_cancel_remain_on_channel_cb(
 			wpa_s, data->remain_on_channel.freq);
 #endif /* CONFIG_DPP */
-#ifdef CONFIG_NAN_USD
-		wpas_nan_usd_cancel_remain_on_channel_cb(
-			wpa_s, data->remain_on_channel.freq);
-#endif /* CONFIG_NAN_USD */
 		break;
 	case EVENT_EAPOL_RX:
 		wpa_supplicant_rx_eapol(wpa_s, data->eapol_rx.src,
@@ -6723,7 +6321,7 @@
 					     wpa_s, NULL);
 			os_memcpy(addr, wpa_s->own_addr, ETH_ALEN);
 			wpa_supplicant_update_mac_addr(wpa_s);
-			if (!ether_addr_equal(addr, wpa_s->own_addr))
+			if (os_memcmp(addr, wpa_s->own_addr, ETH_ALEN) != 0)
 				wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
 			else
 				wpa_sm_pmksa_cache_reconfig(wpa_s->wpa);
@@ -6857,8 +6455,8 @@
 #endif /* CONFIG_IBSS_RSN */
 		break;
 	case EVENT_DRIVER_GTK_REKEY:
-		if (!ether_addr_equal(data->driver_gtk_rekey.bssid,
-				      wpa_s->bssid))
+		if (os_memcmp(data->driver_gtk_rekey.bssid,
+			      wpa_s->bssid, ETH_ALEN))
 			break;
 		if (!wpa_s->wpa)
 			break;
@@ -7020,9 +6618,6 @@
 #ifdef CONFIG_DPP
 		wpas_dpp_tx_wait_expire(wpa_s);
 #endif /* CONFIG_DPP */
-#ifdef CONFIG_NAN_USD
-		wpas_nan_usd_tx_wait_expire(wpa_s);
-#endif /* CONFIG_NAN_USD */
 		break;
 	case EVENT_TID_LINK_MAP:
 		if (data)
diff --git a/wpa_supplicant/gas_query.c b/wpa_supplicant/gas_query.c
index 7d29931..c301f74 100644
--- a/wpa_supplicant/gas_query.c
+++ b/wpa_supplicant/gas_query.c
@@ -199,16 +199,10 @@
 gas_query_get_pending(struct gas_query *gas, const u8 *addr, u8 dialog_token)
 {
 	struct gas_query_pending *q;
-	struct wpa_supplicant *wpa_s = gas->wpa_s;
-
 	dl_list_for_each(q, &gas->pending, struct gas_query_pending, list) {
-		if (ether_addr_equal(q->addr, addr) &&
+		if (os_memcmp(q->addr, addr, ETH_ALEN) == 0 &&
 		    q->dialog_token == dialog_token)
 			return q;
-		if (wpa_s->valid_links &&
-		    ether_addr_equal(wpa_s->ap_mld_addr, addr) &&
-		    wpas_ap_link_address(wpa_s, q->addr))
-			return q;
 	}
 	return NULL;
 }
@@ -249,7 +243,7 @@
 	wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
 		   " result=%d query=%p dialog_token=%u dur=%d ms",
 		   freq, MAC2STR(dst), result, query, query->dialog_token, dur);
-	if (!ether_addr_equal(dst, query->addr)) {
+	if (os_memcmp(dst, query->addr, ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG, "GAS: TX status for unexpected destination");
 		return;
 	}
@@ -306,7 +300,7 @@
 	    (!gas->wpa_s->conf->gas_address3 ||
 	     (gas->wpa_s->current_ssid &&
 	      gas->wpa_s->wpa_state >= WPA_ASSOCIATED &&
-	      ether_addr_equal(query->addr, gas->wpa_s->bssid))))
+	      os_memcmp(query->addr, gas->wpa_s->bssid, ETH_ALEN) == 0)))
 		bssid = query->addr;
 	else
 		bssid = wildcard_bssid;
@@ -674,7 +668,7 @@
 {
 	struct gas_query_pending *q;
 	dl_list_for_each(q, &gas->pending, struct gas_query_pending, list) {
-		if (ether_addr_equal(dst, q->addr) &&
+		if (os_memcmp(dst, q->addr, ETH_ALEN) == 0 &&
 		    dialog_token == q->dialog_token)
 			return 0;
 	}
diff --git a/wpa_supplicant/hs20_supplicant.c b/wpa_supplicant/hs20_supplicant.c
index c68167f..eaf0803 100644
--- a/wpa_supplicant/hs20_supplicant.c
+++ b/wpa_supplicant/hs20_supplicant.c
@@ -27,7 +27,6 @@
 #include "interworking.h"
 #include "hs20_supplicant.h"
 #include "base64.h"
-#include "notify.h"
 
 
 #define OSU_MAX_ITEMS 10
@@ -69,6 +68,7 @@
 void hs20_configure_frame_filters(struct wpa_supplicant *wpa_s)
 {
 	struct wpa_bss *bss = wpa_s->current_bss;
+	u8 *bssid = wpa_s->bssid;
 	const u8 *ie;
 	const u8 *ext_capa;
 	u32 filter = 0;
@@ -79,8 +79,9 @@
 			|| !is_hs20_config(wpa_s)
 #endif
 			) {
-		/* Not configuring frame filtering - BSS is not a Hotspot 2.0
-		 * network */
+		wpa_printf(MSG_DEBUG,
+			   "Not configuring frame filtering - BSS " MACSTR
+			   " is not a Hotspot 2.0 network", MAC2STR(bssid));
 		return;
 	}
 
@@ -335,7 +336,7 @@
 	struct icon_entry *icon;
 
 	dl_list_for_each(icon, &wpa_s->icon_head, struct icon_entry, list) {
-		if (ether_addr_equal(icon->bssid, bssid) &&
+		if (os_memcmp(icon->bssid, bssid, ETH_ALEN) == 0 &&
 		    os_strcmp(icon->file_name, file_name) == 0 && icon->image)
 			return icon;
 	}
@@ -411,7 +412,7 @@
 
 	dl_list_for_each_safe(icon, tmp, &wpa_s->icon_head, struct icon_entry,
 			      list) {
-		if ((!bssid || ether_addr_equal(icon->bssid, bssid)) &&
+		if ((!bssid || os_memcmp(icon->bssid, bssid, ETH_ALEN) == 0) &&
 		    (!file_name ||
 		     os_strcmp(icon->file_name, file_name) == 0)) {
 			dl_list_del(&icon->list);
@@ -457,7 +458,7 @@
 			      list) {
 		if (icon == new_icon)
 			continue;
-		if (ether_addr_equal(icon->bssid, new_icon->bssid) &&
+		if (os_memcmp(icon->bssid, new_icon->bssid, ETH_ALEN) == 0 &&
 		    os_strcmp(icon->file_name, new_icon->file_name) == 0) {
 			dl_list_del(&icon->list);
 			hs20_free_icon_entry(icon);
@@ -478,7 +479,7 @@
 
 	dl_list_for_each(icon, &wpa_s->icon_head, struct icon_entry, list) {
 		if (icon->dialog_token == dialog_token && !icon->image &&
-		    ether_addr_equal(icon->bssid, sa)) {
+		    os_memcmp(icon->bssid, sa, ETH_ALEN) == 0) {
 			icon->image = os_memdup(pos, slen);
 			if (!icon->image)
 				return -1;
@@ -1353,7 +1354,8 @@
 		return;
 	}
 
-	wpas_notify_hs20_t_c_acceptance(wpa_s, url);
+	wpa_msg(wpa_s, MSG_INFO, HS20_T_C_ACCEPTANCE "%s", url);
+	wpas_notify_hs20_rx_terms_and_conditions_acceptance(wpa_s, url);
 }
 
 
diff --git a/wpa_supplicant/ibss_rsn.c b/wpa_supplicant/ibss_rsn.c
index 554268a..5b31f7b 100644
--- a/wpa_supplicant/ibss_rsn.c
+++ b/wpa_supplicant/ibss_rsn.c
@@ -30,7 +30,7 @@
 	struct ibss_rsn_peer *peer;
 
 	for (peer = ibss_rsn->peers; peer; peer = peer->next)
-		if (ether_addr_equal(addr, peer->addr))
+		if (os_memcmp(addr, peer->addr, ETH_ALEN) == 0)
 			break;
 	return peer;
 }
@@ -672,7 +672,7 @@
 
 		for (prev = NULL, peer = ibss_rsn->peers; peer != NULL;
 		     prev = peer, peer = peer->next) {
-			if (ether_addr_equal(peermac, peer->addr)) {
+			if (os_memcmp(peermac, peer->addr, ETH_ALEN) == 0) {
 				if (prev == NULL)
 					ibss_rsn->peers = peer->next;
 				else
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index 5676f38..cb1165e 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -2674,7 +2674,7 @@
 			continue;
 		if (!(other->flags & WPA_BSS_ANQP_FETCH_TRIED))
 			continue;
-		if (!ether_addr_equal(bss->hessid, other->hessid))
+		if (os_memcmp(bss->hessid, other->hessid, ETH_ALEN) != 0)
 			continue;
 		if (bss->ssid_len != other->ssid_len ||
 		    os_memcmp(bss->ssid, other->ssid, bss->ssid_len) != 0)
@@ -2820,7 +2820,7 @@
 	struct wpa_bss *bss;
 	int res;
 
-	bss = wpa_bss_get_bssid_latest(wpa_s, dst);
+	bss = wpa_bss_get_bssid(wpa_s, dst);
 	if (!bss && !freq) {
 		wpa_printf(MSG_WARNING,
 			   "ANQP: Cannot send query without BSS freq info");
@@ -3169,13 +3169,13 @@
 	 */
 	dl_list_for_each_reverse(tmp, &wpa_s->bss, struct wpa_bss, list) {
 		if (tmp == wpa_s->interworking_gas_bss &&
-		    ether_addr_equal(tmp->bssid, dst)) {
+		    os_memcmp(tmp->bssid, dst, ETH_ALEN) == 0) {
 			bss = tmp;
 			break;
 		}
 	}
 	if (bss == NULL)
-		bss = wpa_bss_get_bssid_latest(wpa_s, dst);
+		bss = wpa_bss_get_bssid(wpa_s, dst);
 
 	pos = wpabuf_head(resp);
 	end = pos + wpabuf_len(resp);
@@ -3206,12 +3206,12 @@
 	}
 
 out_parse_done:
-	if (bss)
-		wpas_notify_bss_anqp_changed(wpa_s, bss->id);
 #ifdef CONFIG_HS20
 	hs20_notify_parse_done(wpa_s);
 #endif /* CONFIG_HS20 */
 out:
+	wpa_msg(wpa_s, MSG_INFO, ANQP_QUERY_DONE "addr=" MACSTR " result=%s",
+		MAC2STR(dst), anqp_result);
 	wpas_notify_anqp_query_done(wpa_s, dst, anqp_result, bss ? bss->anqp : NULL);
 }
 
@@ -3290,7 +3290,7 @@
 	u8 query_resp_len_limit = 0;
 
 	freq = wpa_s->assoc_freq;
-	bss = wpa_bss_get_bssid_latest(wpa_s, dst);
+	bss = wpa_bss_get_bssid(wpa_s, dst);
 	if (bss)
 		freq = bss->freq;
 	if (freq <= 0)
diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c
index 85c1ea8..486fc6a 100644
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -231,7 +231,7 @@
 		    hostapd_get_oper_centr_freq_seg0_idx(ifmsh->conf),
 		    hostapd_get_oper_centr_freq_seg1_idx(ifmsh->conf),
 		    ifmsh->conf->vht_capab,
-		    he_capab, NULL, 0)) {
+		    he_capab, NULL)) {
 		wpa_printf(MSG_ERROR, "Error updating mesh frequency params");
 		wpa_supplicant_mesh_deinit(wpa_s, true);
 		return -1;
diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c
index b2fc127..138c013 100644
--- a/wpa_supplicant/mesh_mpm.c
+++ b/wpa_supplicant/mesh_mpm.c
@@ -468,7 +468,6 @@
 	params.plink_state = state;
 	params.peer_aid = sta->peer_aid;
 	params.set = 1;
-	params.mld_link_id = -1;
 
 	ret = wpa_drv_sta_add(wpa_s, &params);
 	if (ret) {
@@ -698,7 +697,6 @@
 	params.addr = sta->addr;
 	params.flags = WPA_STA_AUTHENTICATED | WPA_STA_AUTHORIZED;
 	params.set = 1;
-	params.mld_link_id = -1;
 
 	wpa_msg(wpa_s, MSG_DEBUG, "MPM authenticating " MACSTR,
 		MAC2STR(sta->addr));
@@ -818,7 +816,6 @@
 	params.eht_capab_len = sta->eht_capab_len;
 	params.flags |= WPA_STA_WMM;
 	params.flags_mask |= WPA_STA_AUTHENTICATED;
-	params.mld_link_id = -1;
 	if (conf->security == MESH_CONF_SEC_NONE) {
 		params.flags |= WPA_STA_AUTHORIZED;
 		params.flags |= WPA_STA_AUTHENTICATED;
@@ -854,7 +851,7 @@
 
 	if (ssid && ssid->no_auto_peer &&
 	    (is_zero_ether_addr(data->mesh_required_peer) ||
-	     !ether_addr_equal(data->mesh_required_peer, addr))) {
+	     os_memcmp(data->mesh_required_peer, addr, ETH_ALEN) != 0)) {
 		wpa_msg(wpa_s, MSG_INFO, "will not initiate new peer link with "
 			MACSTR " because of no_auto_peer", MAC2STR(addr));
 		if (data->mesh_pending_auth) {
@@ -865,7 +862,7 @@
 			mgmt = wpabuf_head(data->mesh_pending_auth);
 			os_reltime_age(&data->mesh_pending_auth_time, &age);
 			if (age.sec < 2 &&
-			    ether_addr_equal(mgmt->sa, addr)) {
+			    os_memcmp(mgmt->sa, addr, ETH_ALEN) == 0) {
 				wpa_printf(MSG_DEBUG,
 					   "mesh: Process pending Authentication frame from %u.%06u seconds ago",
 					   (unsigned int) age.sec,
diff --git a/wpa_supplicant/mesh_rsn.c b/wpa_supplicant/mesh_rsn.c
index ada53c7..12dcc30 100644
--- a/wpa_supplicant/mesh_rsn.c
+++ b/wpa_supplicant/mesh_rsn.c
@@ -142,23 +142,6 @@
 }
 
 
-static int auth_for_each_sta(
-	void *ctx, int (*cb)(struct wpa_state_machine *sm, void *ctx),
-	void *cb_ctx)
-{
-	struct mesh_rsn *rsn = ctx;
-	struct hostapd_data *hapd;
-	struct sta_info *sta;
-
-	hapd = rsn->wpa_s->ifmsh->bss[0];
-	for (sta = hapd->sta_list; sta; sta = sta->next) {
-		if (sta->wpa_sm && cb(sta->wpa_sm, cb_ctx))
-			return 1;
-	}
-	return 0;
-}
-
-
 static int __mesh_rsn_auth_init(struct mesh_rsn *rsn, const u8 *addr,
 				enum mfp_options ieee80211w, int ocv)
 {
@@ -168,7 +151,6 @@
 		.get_psk = auth_get_psk,
 		.set_key = auth_set_key,
 		.start_ampe = auth_start_ampe,
-		.for_each_sta = auth_for_each_sta,
 	};
 	u8 seq[6] = {};
 
@@ -404,8 +386,7 @@
 			   " - try to use PMKSA caching instead of new SAE authentication",
 			   MAC2STR(sta->addr));
 		wpa_auth_pmksa_set_to_sm(pmksa, sta->wpa_sm, hapd->wpa_auth,
-					 sta->sae->pmkid, sta->sae->pmk,
-					 &sta->sae->pmk_len);
+					 sta->sae->pmkid, sta->sae->pmk);
 		sae_accept_sta(hapd, sta);
 		sta->mesh_sae_pmksa_caching = 1;
 		return 0;
diff --git a/wpa_supplicant/nan_usd.c b/wpa_supplicant/nan_usd.c
deleted file mode 100644
index 657b302..0000000
--- a/wpa_supplicant/nan_usd.c
+++ /dev/null
@@ -1,513 +0,0 @@
-/*
- * NAN unsynchronized service discovery (USD)
- * Copyright (c) 2024, Qualcomm Innovation Center, Inc.
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#include "utils/includes.h"
-
-#include "utils/common.h"
-#include "common/nan_de.h"
-#include "wpa_supplicant_i.h"
-#include "offchannel.h"
-#include "driver_i.h"
-#include "nan_usd.h"
-
-
-static const char *
-tx_status_result_txt(enum offchannel_send_action_result result)
-{
-	switch (result) {
-	case OFFCHANNEL_SEND_ACTION_SUCCESS:
-		return "success";
-	case OFFCHANNEL_SEND_ACTION_NO_ACK:
-		return "no-ack";
-	case OFFCHANNEL_SEND_ACTION_FAILED:
-		return "failed";
-	}
-
-	return "?";
-}
-
-
-static void wpas_nan_de_tx_status(struct wpa_supplicant *wpa_s,
-				  unsigned int freq, const u8 *dst,
-				  const u8 *src, const u8 *bssid,
-				  const u8 *data, size_t data_len,
-				  enum offchannel_send_action_result result)
-{
-	if (!wpa_s->nan_de)
-		return;
-
-	wpa_printf(MSG_DEBUG, "NAN: TX status A1=" MACSTR " A2=" MACSTR
-		   " A3=" MACSTR " freq=%d len=%zu result=%s",
-		   MAC2STR(dst), MAC2STR(src), MAC2STR(bssid), freq,
-		   data_len, tx_status_result_txt(result));
-
-	nan_de_tx_status(wpa_s->nan_de, freq, dst);
-}
-
-
-struct wpas_nan_usd_tx_work {
-	unsigned int freq;
-	unsigned int wait_time;
-	u8 dst[ETH_ALEN];
-	u8 src[ETH_ALEN];
-	u8 bssid[ETH_ALEN];
-	struct wpabuf *buf;
-};
-
-
-static void wpas_nan_usd_tx_work_free(struct wpas_nan_usd_tx_work *twork)
-{
-	if (!twork)
-		return;
-	wpabuf_free(twork->buf);
-	os_free(twork);
-}
-
-
-static void wpas_nan_usd_tx_work_done(struct wpa_supplicant *wpa_s)
-{
-	struct wpas_nan_usd_tx_work *twork;
-
-	if (!wpa_s->nan_usd_tx_work)
-		return;
-
-	twork = wpa_s->nan_usd_tx_work->ctx;
-	wpas_nan_usd_tx_work_free(twork);
-	radio_work_done(wpa_s->nan_usd_tx_work);
-	wpa_s->nan_usd_tx_work = NULL;
-}
-
-
-static int wpas_nan_de_tx_send(struct wpa_supplicant *wpa_s, unsigned int freq,
-			       unsigned int wait_time, const u8 *dst,
-			       const u8 *src, const u8 *bssid,
-			       const struct wpabuf *buf)
-{
-	wpa_printf(MSG_DEBUG, "NAN: TX NAN SDF A1=" MACSTR " A2=" MACSTR
-		   " A3=" MACSTR " freq=%d len=%zu",
-		   MAC2STR(dst), MAC2STR(src), MAC2STR(bssid), freq,
-		   wpabuf_len(buf));
-
-	return offchannel_send_action(wpa_s, freq, dst, src, bssid,
-				      wpabuf_head(buf), wpabuf_len(buf),
-				      wait_time, wpas_nan_de_tx_status, 1);
-}
-
-
-static void wpas_nan_usd_start_tx_cb(struct wpa_radio_work *work, int deinit)
-{
-	struct wpa_supplicant *wpa_s = work->wpa_s;
-	struct wpas_nan_usd_tx_work *twork = work->ctx;
-
-	if (deinit) {
-		if (work->started) {
-			wpa_s->nan_usd_tx_work = NULL;
-			offchannel_send_action_done(wpa_s);
-		}
-		wpas_nan_usd_tx_work_free(twork);
-		return;
-	}
-
-	wpa_s->nan_usd_tx_work = work;
-
-	if (wpas_nan_de_tx_send(wpa_s, twork->freq, twork->wait_time,
-				twork->dst, twork->src, twork->bssid,
-				twork->buf) < 0)
-		wpas_nan_usd_tx_work_done(wpa_s);
-}
-
-
-static int wpas_nan_de_tx(void *ctx, unsigned int freq, unsigned int wait_time,
-			  const u8 *dst, const u8 *src, const u8 *bssid,
-			  const struct wpabuf *buf)
-{
-	struct wpa_supplicant *wpa_s = ctx;
-	struct wpas_nan_usd_tx_work *twork;
-
-	if (wpa_s->nan_usd_tx_work || wpa_s->nan_usd_listen_work) {
-		/* Reuse ongoing radio work */
-		return wpas_nan_de_tx_send(wpa_s, freq, wait_time, dst, src,
-					   bssid, buf);
-	}
-
-	twork = os_zalloc(sizeof(*twork));
-	if (!twork)
-		return -1;
-	twork->freq = freq;
-	twork->wait_time = wait_time;
-	os_memcpy(twork->dst, dst, ETH_ALEN);
-	os_memcpy(twork->src, src, ETH_ALEN);
-	os_memcpy(twork->bssid, bssid, ETH_ALEN);
-	twork->buf = wpabuf_dup(buf);
-	if (!twork->buf) {
-		wpas_nan_usd_tx_work_free(twork);
-		return -1;
-	}
-
-	if (radio_add_work(wpa_s, freq, "nan-usd-tx", 0,
-			   wpas_nan_usd_start_tx_cb, twork) < 0) {
-		wpas_nan_usd_tx_work_free(twork);
-		return -1;
-	}
-
-	return 0;
-}
-
-
-struct wpas_nan_usd_listen_work {
-	unsigned int freq;
-	unsigned int duration;
-};
-
-
-static void wpas_nan_usd_listen_work_done(struct wpa_supplicant *wpa_s)
-{
-	struct wpas_nan_usd_listen_work *lwork;
-
-	if (!wpa_s->nan_usd_listen_work)
-		return;
-
-	lwork = wpa_s->nan_usd_listen_work->ctx;
-	os_free(lwork);
-	radio_work_done(wpa_s->nan_usd_listen_work);
-	wpa_s->nan_usd_listen_work = NULL;
-}
-
-
-static void wpas_nan_usd_start_listen_cb(struct wpa_radio_work *work,
-					 int deinit)
-{
-	struct wpa_supplicant *wpa_s = work->wpa_s;
-	struct wpas_nan_usd_listen_work *lwork = work->ctx;
-	unsigned int duration;
-
-	if (deinit) {
-		if (work->started) {
-			wpa_s->nan_usd_listen_work = NULL;
-			wpa_drv_cancel_remain_on_channel(wpa_s);
-		}
-		os_free(lwork);
-		return;
-	}
-
-	wpa_s->nan_usd_listen_work = work;
-
-	duration = lwork->duration;
-	if (duration > wpa_s->max_remain_on_chan)
-		duration = wpa_s->max_remain_on_chan;
-	wpa_printf(MSG_DEBUG, "NAN: Start listen on %u MHz for %u ms",
-		   lwork->freq, duration);
-	if (wpa_drv_remain_on_channel(wpa_s, lwork->freq, duration) < 0) {
-		wpa_printf(MSG_DEBUG,
-			   "NAN: Failed to request the driver to remain on channel (%u MHz) for listen",
-			   lwork->freq);
-		wpas_nan_usd_listen_work_done(wpa_s);
-		return;
-	}
-}
-
-
-static int wpas_nan_de_listen(void *ctx, unsigned int freq,
-			      unsigned int duration)
-{
-	struct wpa_supplicant *wpa_s = ctx;
-	struct wpas_nan_usd_listen_work *lwork;
-
-	lwork = os_zalloc(sizeof(*lwork));
-	if (!lwork)
-		return -1;
-	lwork->freq = freq;
-	lwork->duration = duration;
-
-	if (radio_add_work(wpa_s, freq, "nan-usd-listen", 0,
-			   wpas_nan_usd_start_listen_cb, lwork) < 0) {
-		os_free(lwork);
-		return -1;
-	}
-
-	return 0;
-}
-
-
-static void
-wpas_nan_de_discovery_result(void *ctx, int subscribe_id,
-			     enum nan_service_protocol_type srv_proto_type,
-			     const u8 *ssi, size_t ssi_len, int peer_publish_id,
-			     const u8 *peer_addr, bool fsd, bool fsd_gas)
-{
-	struct wpa_supplicant *wpa_s = ctx;
-	char *ssi_hex;
-
-	ssi_hex = os_zalloc(2 * ssi_len + 1);
-	if (!ssi_hex)
-		return;
-	if (ssi)
-		wpa_snprintf_hex(ssi_hex, 2 * ssi_len + 1, ssi, ssi_len);
-	wpa_msg(wpa_s, MSG_INFO, NAN_DISCOVERY_RESULT
-		"subscribe_id=%d publish_id=%d address=" MACSTR
-		" fsd=%d fsd_gas=%d srv_proto_type=%u ssi=%s",
-		subscribe_id, peer_publish_id, MAC2STR(peer_addr),
-		fsd, fsd_gas, srv_proto_type, ssi_hex);
-	os_free(ssi_hex);
-}
-
-
-static void wpas_nan_de_replied(void *ctx, int publish_id, const u8 *peer_addr,
-				int peer_subscribe_id,
-				enum nan_service_protocol_type srv_proto_type,
-				const u8 *ssi, size_t ssi_len)
-{
-	struct wpa_supplicant *wpa_s = ctx;
-	char *ssi_hex;
-
-	ssi_hex = os_zalloc(2 * ssi_len + 1);
-	if (!ssi_hex)
-		return;
-	if (ssi)
-		wpa_snprintf_hex(ssi_hex, 2 * ssi_len + 1, ssi, ssi_len);
-	wpa_msg(wpa_s, MSG_INFO, NAN_REPLIED
-		"publish_id=%d address=" MACSTR
-		" subscribe_id=%d srv_proto_type=%u ssi=%s",
-		publish_id, MAC2STR(peer_addr), peer_subscribe_id,
-		srv_proto_type, ssi_hex);
-	os_free(ssi_hex);
-}
-
-
-static const char * nan_reason_txt(enum nan_de_reason reason)
-{
-	switch (reason) {
-	case NAN_DE_REASON_TIMEOUT:
-		return "timeout";
-	case NAN_DE_REASON_USER_REQUEST:
-		return "user-request";
-	case NAN_DE_REASON_FAILURE:
-		return "failure";
-	}
-
-	return "unknown";
-}
-
-
-static void wpas_nan_de_publish_terminated(void *ctx, int publish_id,
-					   enum nan_de_reason reason)
-{
-	struct wpa_supplicant *wpa_s = ctx;
-
-	wpa_msg(wpa_s, MSG_INFO, NAN_PUBLISH_TERMINATED
-		"publish_id=%d reason=%s",
-		publish_id, nan_reason_txt(reason));
-}
-
-
-static void wpas_nan_de_subscribe_terminated(void *ctx, int subscribe_id,
-					     enum nan_de_reason reason)
-{
-	struct wpa_supplicant *wpa_s = ctx;
-
-	wpa_msg(wpa_s, MSG_INFO, NAN_SUBSCRIBE_TERMINATED
-		"subscribe_id=%d reason=%s",
-		subscribe_id, nan_reason_txt(reason));
-}
-
-
-static void wpas_nan_de_receive(void *ctx, int id, int peer_instance_id,
-				const u8 *ssi, size_t ssi_len,
-				const u8 *peer_addr)
-{
-	struct wpa_supplicant *wpa_s = ctx;
-	char *ssi_hex;
-
-	ssi_hex = os_zalloc(2 * ssi_len + 1);
-	if (!ssi_hex)
-		return;
-	if (ssi)
-		wpa_snprintf_hex(ssi_hex, 2 * ssi_len + 1, ssi, ssi_len);
-	wpa_msg(wpa_s, MSG_INFO, NAN_RECEIVE
-		"id=%d peer_instance_id=%d address=" MACSTR " ssi=%s",
-		id, peer_instance_id, MAC2STR(peer_addr), ssi_hex);
-	os_free(ssi_hex);
-}
-
-
-int wpas_nan_usd_init(struct wpa_supplicant *wpa_s)
-{
-	struct nan_callbacks cb;
-
-	os_memset(&cb, 0, sizeof(cb));
-	cb.ctx = wpa_s;
-	cb.tx = wpas_nan_de_tx;
-	cb.listen = wpas_nan_de_listen;
-	cb.discovery_result = wpas_nan_de_discovery_result;
-	cb.replied = wpas_nan_de_replied;
-	cb.publish_terminated = wpas_nan_de_publish_terminated;
-	cb.subscribe_terminated = wpas_nan_de_subscribe_terminated;
-	cb.receive = wpas_nan_de_receive;
-
-	wpa_s->nan_de = nan_de_init(wpa_s->own_addr, false, &cb);
-	if (!wpa_s->nan_de)
-		return -1;
-	return 0;
-}
-
-
-void wpas_nan_usd_deinit(struct wpa_supplicant *wpa_s)
-{
-	nan_de_deinit(wpa_s->nan_de);
-	wpa_s->nan_de = NULL;
-}
-
-
-void wpas_nan_usd_rx_sdf(struct wpa_supplicant *wpa_s, const u8 *src,
-			 unsigned int freq, const u8 *buf, size_t len)
-{
-	if (!wpa_s->nan_de)
-		return;
-	nan_de_rx_sdf(wpa_s->nan_de, src, freq, buf, len);
-}
-
-
-void wpas_nan_usd_flush(struct wpa_supplicant *wpa_s)
-{
-	if (!wpa_s->nan_de)
-		return;
-	nan_de_flush(wpa_s->nan_de);
-}
-
-
-int wpas_nan_usd_publish(struct wpa_supplicant *wpa_s, const char *service_name,
-			 enum nan_service_protocol_type srv_proto_type,
-			 const struct wpabuf *ssi,
-			 struct nan_publish_params *params)
-{
-	int publish_id;
-	struct wpabuf *elems = NULL;
-
-	if (!wpa_s->nan_de)
-		return -1;
-
-	publish_id = nan_de_publish(wpa_s->nan_de, service_name, srv_proto_type,
-				    ssi, elems, params);
-	wpabuf_free(elems);
-	return publish_id;
-}
-
-
-void wpas_nan_usd_cancel_publish(struct wpa_supplicant *wpa_s, int publish_id)
-{
-	if (!wpa_s->nan_de)
-		return;
-	nan_de_cancel_publish(wpa_s->nan_de, publish_id);
-}
-
-
-int wpas_nan_usd_update_publish(struct wpa_supplicant *wpa_s, int publish_id,
-				const struct wpabuf *ssi)
-{
-	if (!wpa_s->nan_de)
-		return -1;
-	return nan_de_update_publish(wpa_s->nan_de, publish_id, ssi);
-}
-
-
-int wpas_nan_usd_subscribe(struct wpa_supplicant *wpa_s,
-			   const char *service_name,
-			   enum nan_service_protocol_type srv_proto_type,
-			   const struct wpabuf *ssi,
-			   struct nan_subscribe_params *params)
-{
-	int subscribe_id;
-	struct wpabuf *elems = NULL;
-
-	if (!wpa_s->nan_de)
-		return -1;
-
-	subscribe_id = nan_de_subscribe(wpa_s->nan_de, service_name,
-					srv_proto_type, ssi, elems, params);
-	wpabuf_free(elems);
-	return subscribe_id;
-}
-
-
-void wpas_nan_usd_cancel_subscribe(struct wpa_supplicant *wpa_s,
-				   int subscribe_id)
-{
-	if (!wpa_s->nan_de)
-		return;
-	nan_de_cancel_subscribe(wpa_s->nan_de, subscribe_id);
-}
-
-
-int wpas_nan_usd_transmit(struct wpa_supplicant *wpa_s, int handle,
-			  const struct wpabuf *ssi, const struct wpabuf *elems,
-			  const u8 *peer_addr, u8 req_instance_id)
-{
-	if (!wpa_s->nan_de)
-		return -1;
-	return nan_de_transmit(wpa_s->nan_de, handle, ssi, elems, peer_addr,
-			       req_instance_id);
-}
-
-
-void wpas_nan_usd_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
-				       unsigned int freq, unsigned int duration)
-{
-	wpas_nan_usd_listen_work_done(wpa_s);
-
-	if (wpa_s->nan_de)
-		nan_de_listen_started(wpa_s->nan_de, freq, duration);
-}
-
-
-void wpas_nan_usd_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
-					      unsigned int freq)
-{
-	if (wpa_s->nan_de)
-		nan_de_listen_ended(wpa_s->nan_de, freq);
-}
-
-
-void wpas_nan_usd_tx_wait_expire(struct wpa_supplicant *wpa_s)
-{
-	wpas_nan_usd_tx_work_done(wpa_s);
-
-	if (wpa_s->nan_de)
-		nan_de_tx_wait_ended(wpa_s->nan_de);
-}
-
-
-int * wpas_nan_usd_all_freqs(struct wpa_supplicant *wpa_s)
-{
-	int i, j;
-	int *freqs = NULL;
-
-	if (!wpa_s->hw.modes)
-		return NULL;
-
-	for (i = 0; i < wpa_s->hw.num_modes; i++) {
-		struct hostapd_hw_modes *mode = &wpa_s->hw.modes[i];
-
-		for (j = 0; j < mode->num_channels; j++) {
-			struct hostapd_channel_data *chan = &mode->channels[j];
-
-			/* All 20 MHz channels on 2.4 and 5 GHz band */
-			if (chan->freq < 2412 || chan->freq > 5900)
-				continue;
-
-			/* that allow frames to be transmitted */
-			if (chan->flag & (HOSTAPD_CHAN_DISABLED |
-					  HOSTAPD_CHAN_NO_IR |
-					  HOSTAPD_CHAN_RADAR))
-				continue;
-
-			int_array_add_unique(&freqs, chan->freq);
-		}
-	}
-
-	return freqs;
-}
diff --git a/wpa_supplicant/nan_usd.h b/wpa_supplicant/nan_usd.h
deleted file mode 100644
index 149ac9e..0000000
--- a/wpa_supplicant/nan_usd.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * NAN unsynchronized service discovery (USD)
- * Copyright (c) 2024, Qualcomm Innovation Center, Inc.
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#ifndef NAN_USD_H
-#define NAN_USD_H
-
-struct nan_subscribe_params;
-struct nan_publish_params;
-enum nan_service_protocol_type;
-
-int wpas_nan_usd_init(struct wpa_supplicant *wpa_s);
-void wpas_nan_usd_deinit(struct wpa_supplicant *wpa_s);
-void wpas_nan_usd_rx_sdf(struct wpa_supplicant *wpa_s, const u8 *src,
-			 unsigned int freq, const u8 *buf, size_t len);
-void wpas_nan_usd_flush(struct wpa_supplicant *wpa_s);
-int wpas_nan_usd_publish(struct wpa_supplicant *wpa_s, const char *service_name,
-			 enum nan_service_protocol_type srv_proto_type,
-			 const struct wpabuf *ssi,
-			 struct nan_publish_params *params);
-void wpas_nan_usd_cancel_publish(struct wpa_supplicant *wpa_s, int publish_id);
-int wpas_nan_usd_update_publish(struct wpa_supplicant *wpa_s, int publish_id,
-				const struct wpabuf *ssi);
-int wpas_nan_usd_subscribe(struct wpa_supplicant *wpa_s,
-			   const char *service_name,
-			   enum nan_service_protocol_type srv_proto_type,
-			   const struct wpabuf *ssi,
-			   struct nan_subscribe_params *params);
-void wpas_nan_usd_cancel_subscribe(struct wpa_supplicant *wpa_s,
-				   int subscribe_id);
-int wpas_nan_usd_transmit(struct wpa_supplicant *wpa_s, int handle,
-			  const struct wpabuf *ssi, const struct wpabuf *elems,
-			  const u8 *peer_addr, u8 req_instance_id);
-void wpas_nan_usd_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
-				       unsigned int freq,
-				       unsigned int duration);
-void wpas_nan_usd_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
-					      unsigned int freq);
-void wpas_nan_usd_tx_wait_expire(struct wpa_supplicant *wpa_s);
-int * wpas_nan_usd_all_freqs(struct wpa_supplicant *wpa_s);
-
-#endif /* NAN_USD_H */
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index c930651..a1746da 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -627,15 +627,6 @@
 }
 
 
-void wpas_notify_bss_anqp_changed(struct wpa_supplicant *wpa_s, unsigned int id)
-{
-	if (wpa_s->p2p_mgmt)
-		return;
-
-	wpas_dbus_bss_signal_prop_changed(wpa_s, WPAS_DBUS_BSS_PROP_ANQP, id);
-}
-
-
 void wpas_notify_blob_added(struct wpa_supplicant *wpa_s, const char *name)
 {
 	if (wpa_s->p2p_mgmt)
@@ -944,8 +935,7 @@
 				const u8 *p2p_dev_addr, const u8 *ip)
 {
 	if (authorized)
-		wpas_notify_ap_sta_authorized(wpa_s, mac_addr, p2p_dev_addr,
-					      ip);
+		wpas_notify_ap_sta_authorized(wpa_s, mac_addr, p2p_dev_addr, ip);
 	else
 		wpas_notify_ap_sta_deauthorized(wpa_s, mac_addr, p2p_dev_addr);
 }
@@ -1067,14 +1057,11 @@
 				 const char *result,
 				 const struct wpa_bss_anqp *anqp)
 {
-	wpa_msg(wpa_s, MSG_INFO, ANQP_QUERY_DONE "addr=" MACSTR " result=%s",
-		MAC2STR(bssid), result);
 #ifdef CONFIG_INTERWORKING
 	if (!wpa_s || !bssid || !anqp)
 		return;
 
 	wpas_aidl_notify_anqp_query_done(wpa_s, bssid, result, anqp);
-	wpas_dbus_signal_anqp_query_done(wpa_s, bssid, result);
 #endif /* CONFIG_INTERWORKING */
 }
 
@@ -1116,6 +1103,15 @@
 #endif /* CONFIG_HS20 */
 }
 
+void wpas_notify_hs20_rx_terms_and_conditions_acceptance(
+		struct wpa_supplicant *wpa_s, const char *url) {
+#ifdef CONFIG_HS20
+	if (!wpa_s || !url)
+		return;
+
+	wpas_aidl_notify_hs20_rx_terms_and_conditions_acceptance(wpa_s, url);
+#endif /* CONFIG_HS20 */
+}
 
 #ifdef CONFIG_MESH
 
@@ -1372,7 +1368,6 @@
 	wpas_dbus_signal_interworking_select_done(wpa_s);
 }
 
-
 #endif /* CONFIG_INTERWORKING */
 
 void wpas_notify_eap_method_selected(struct wpa_supplicant *wpa_s,
@@ -1442,16 +1437,3 @@
 
 	wpas_aidl_notify_qos_policy_scs_response(wpa_s, num_scs_resp, scs_resp);
 }
-
-void wpas_notify_hs20_t_c_acceptance(struct wpa_supplicant *wpa_s,
-				     const char *url)
-{
-#ifdef CONFIG_HS20
-	if (!wpa_s || !url)
-		return;
-
-	wpa_msg(wpa_s, MSG_INFO, HS20_T_C_ACCEPTANCE "%s", url);
-	wpas_aidl_notify_hs20_rx_terms_and_conditions_acceptance(wpa_s, url);
-	wpas_dbus_signal_hs20_t_c_acceptance(wpa_s, url);
-#endif /* CONFIG_HS20 */
-}
diff --git a/wpa_supplicant/notify.h b/wpa_supplicant/notify.h
index a584884..260f439 100644
--- a/wpa_supplicant/notify.h
+++ b/wpa_supplicant/notify.h
@@ -89,8 +89,6 @@
 void wpas_notify_bss_rates_changed(struct wpa_supplicant *wpa_s,
 				   unsigned int id);
 void wpas_notify_bss_seen(struct wpa_supplicant *wpa_s, unsigned int id);
-void wpas_notify_bss_anqp_changed(struct wpa_supplicant *wpa_s,
-				  unsigned int id);
 void wpas_notify_blob_added(struct wpa_supplicant *wpa_s, const char *name);
 void wpas_notify_blob_removed(struct wpa_supplicant *wpa_s, const char *name);
 
@@ -184,6 +182,8 @@
 void wpas_notify_hs20_rx_deauth_imminent_notice(struct wpa_supplicant *wpa_s,
 						u8 code, u16 reauth_delay,
 						const char *url);
+void wpas_notify_hs20_rx_terms_and_conditions_acceptance(
+		struct wpa_supplicant *wpa_s, const char *url);
 void wpas_notify_dpp_config_received(struct wpa_supplicant *wpa_s,
 		struct wpa_ssid *ssid, bool conn_status_requested);
 void wpas_notify_dpp_config_sent(struct wpa_supplicant *wpa_s);
@@ -232,7 +232,5 @@
 		unsigned int num_scs_resp, int **scs_resp);
 void wpas_notify_mlo_info_change_reason(struct wpa_supplicant *wpa_s,
 					enum mlo_info_change_reason reason);
-void wpas_notify_hs20_t_c_acceptance(struct wpa_supplicant *wpa_s,
-				     const char *url);
 
 #endif /* NOTIFY_H */
diff --git a/wpa_supplicant/offchannel.c b/wpa_supplicant/offchannel.c
index 9e591d7..e40cf5b 100644
--- a/wpa_supplicant/offchannel.c
+++ b/wpa_supplicant/offchannel.c
@@ -23,12 +23,12 @@
 {
 	struct wpa_supplicant *iface;
 
-	if (ether_addr_equal(src, wpa_s->own_addr)) {
+	if (os_memcmp(src, wpa_s->own_addr, ETH_ALEN) == 0) {
 #ifdef CONFIG_P2P
 		if (wpa_s->p2p_mgmt && wpa_s != wpa_s->parent &&
 		    wpa_s->parent->ap_iface &&
-		    ether_addr_equal(wpa_s->parent->own_addr,
-				     wpa_s->own_addr) &&
+		    os_memcmp(wpa_s->parent->own_addr,
+			      wpa_s->own_addr, ETH_ALEN) == 0 &&
 		    wpabuf_len(wpa_s->pending_action_tx) >= 2 &&
 		    *wpabuf_head_u8(wpa_s->pending_action_tx) !=
 		    WLAN_ACTION_PUBLIC) {
@@ -52,7 +52,7 @@
 	 */
 	iface = wpa_s->global->ifaces;
 	while (iface) {
-		if (ether_addr_equal(src, iface->own_addr))
+		if (os_memcmp(src, iface->own_addr, ETH_ALEN) == 0)
 			break;
 		iface = iface->next;
 	}
@@ -186,7 +186,7 @@
 		return;
 	}
 
-	if (!ether_addr_equal(dst, wpa_s->pending_action_dst)) {
+	if (os_memcmp(dst, wpa_s->pending_action_dst, ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG, "Off-channel: Ignore Action TX status - "
 			   "unknown destination address");
 		return;
diff --git a/wpa_supplicant/op_classes.c b/wpa_supplicant/op_classes.c
index ff11d20..b4ad3ca 100644
--- a/wpa_supplicant/op_classes.c
+++ b/wpa_supplicant/op_classes.c
@@ -22,12 +22,13 @@
 				       unsigned int *flags)
 {
 	int i;
-	bool is_6ghz = is_6ghz_op_class(op_class);
+	bool is_6ghz = op_class >= 131 && op_class <= 136;
 
 	for (i = 0; i < mode->num_channels; i++) {
 		bool chan_is_6ghz;
 
-		chan_is_6ghz = is_6ghz_freq(mode->channels[i].freq);
+		chan_is_6ghz = mode->channels[i].freq >= 5935 &&
+			mode->channels[i].freq <= 7115;
 		if (is_6ghz == chan_is_6ghz && mode->channels[i].chan == chan)
 			break;
 	}
@@ -186,69 +187,6 @@
 }
 
 
-static int get_center_320mhz(struct hostapd_hw_modes *mode, u8 channel,
-			     const u8 *center_channels, size_t num_chan)
-{
-	unsigned int i;
-
-	if (mode->mode != HOSTAPD_MODE_IEEE80211A || !mode->is_6ghz)
-		return 0;
-
-	for (i = 0; i < num_chan; i++) {
-		/*
-		* In 320 MHz, the bandwidth "spans" 60 channels (e.g., 65-125),
-		* so the center channel is 30 channels away from the start/end.
-		*/
-		if (channel >= center_channels[i] - 30 &&
-		    channel <= center_channels[i] + 30)
-			return center_channels[i];
-	}
-
-	return 0;
-}
-
-
-static enum chan_allowed verify_320mhz(struct hostapd_hw_modes *mode,
-				       u8 op_class, u8 channel)
-{
-	u8 center_chan;
-	unsigned int i;
-	bool no_ir = false;
-	const u8 *center_channels;
-	size_t num_chan;
-	const u8 center_channels_6ghz[] = { 31, 63, 95, 127, 159, 191 };
-
-	center_channels = center_channels_6ghz;
-	num_chan = ARRAY_SIZE(center_channels_6ghz);
-
-	center_chan = get_center_320mhz(mode, channel, center_channels,
-					num_chan);
-	if (!center_chan)
-		return NOT_ALLOWED;
-
-	/* Check all the channels are available */
-	for (i = 0; i < 16; i++) {
-		unsigned int flags;
-		u8 adj_chan = center_chan - 30 + i * 4;
-
-		if (allow_channel(mode, op_class, adj_chan, &flags) ==
-		    NOT_ALLOWED)
-			return NOT_ALLOWED;
-
-		if (!(flags & HOSTAPD_CHAN_EHT_320MHZ_SUBCHANNEL))
-			return NOT_ALLOWED;
-
-		if (flags & HOSTAPD_CHAN_NO_IR)
-			no_ir = true;
-	}
-
-	if (no_ir)
-		return NO_IR;
-
-	return ALLOWED;
-}
-
-
 enum chan_allowed verify_channel(struct hostapd_hw_modes *mode, u8 op_class,
 				 u8 channel, u8 bw)
 {
@@ -290,13 +228,6 @@
 		 * result and use only the 80 MHz specific version.
 		 */
 		res2 = res = verify_80mhz(mode, op_class, channel);
-	} else if (bw == BW320) {
-		/*
-		 * channel is a center channel and as such, not necessarily a
-		 * valid 20 MHz channels. Override earlier allow_channel()
-		 * result and use only the 320 MHz specific version.
-		 */
-		res2= res = verify_320mhz(mode, op_class, channel);
 	}
 
 	if (res == NOT_ALLOWED || res2 == NOT_ALLOWED)
@@ -320,7 +251,6 @@
 	int z;
 	int freq2 = 0;
 	int freq5 = 0;
-	bool freq6 = false;
 
 	mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, op_class->mode,
 			is_6ghz_op_class(op_class->op_class));
@@ -335,9 +265,7 @@
 
 			if (f == 0)
 				break; /* end of list */
-			if (is_6ghz_freq(f))
-				freq6 = true;
-			else if (f > 4000 && f < 6000)
+			if (f > 4000 && f < 6000)
 				freq5 = 1;
 			else if (f > 2400 && f < 2500)
 				freq2 = 1;
@@ -346,11 +274,8 @@
 		/* No frequencies specified, can use anything hardware supports.
 		 */
 		freq2 = freq5 = 1;
-		freq6 = true;
 	}
 
-	if (is_6ghz_op_class(op_class->op_class) && !freq6)
-		return 0;
 	if (op_class->op_class >= 115 && op_class->op_class <= 130 && !freq5)
 		return 0;
 	if (op_class->op_class >= 81 && op_class->op_class <= 84 && !freq2)
@@ -528,7 +453,6 @@
 	u8 op, current, chan;
 	u8 *ie_len;
 	size_t res;
-	bool op128 = false, op130 = false, op133 = false, op135 = false;
 
 	/*
 	 * Determine the current operating class correct mode based on
@@ -556,50 +480,8 @@
 	wpabuf_put_u8(buf, current);
 
 	for (op = 0; global_op_class[op].op_class; op++) {
-		bool supp;
-		u8 op_class = global_op_class[op].op_class;
-
-		supp = wpas_op_class_supported(wpa_s, ssid,
-					       &global_op_class[op]);
-		if (!supp)
-			continue;
-		switch (op_class) {
-		case 128:
-			op128 = true;
-			break;
-		case 130:
-			op130 = true;
-			break;
-		case 133:
-			op133 = true;
-			break;
-		case 135:
-			op135 = true;
-			break;
-		}
-		if (is_80plus_op_class(op_class))
-			continue;
-
-		/* Add a 1-octet operating class to the Operating Class field */
-		wpabuf_put_u8(buf, global_op_class[op].op_class);
-	}
-
-	/* Add the 2-octet operating classes (i.e., 80+80 MHz cases), if any */
-	if ((op128 && op130) || (op133 && op135)) {
-		/* Operating Class Duple Sequence field */
-
-		/* Zero Delimiter */
-		wpabuf_put_u8(buf, 0);
-
-		/* Operating Class Duple List */
-		if (op128 && op130) {
-			wpabuf_put_u8(buf, 130);
-			wpabuf_put_u8(buf, 128);
-		}
-		if (op133 && op135) {
-			wpabuf_put_u8(buf, 135);
-			wpabuf_put_u8(buf, 133);
-		}
+		if (wpas_op_class_supported(wpa_s, ssid, &global_op_class[op]))
+			wpabuf_put_u8(buf, global_op_class[op].op_class);
 	}
 
 	*ie_len = wpabuf_len(buf) - 2;
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 9c20ee5..c150863 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -1103,8 +1103,6 @@
 
 	os_memset(wpa_s->go_dev_addr, 0, ETH_ALEN);
 
-	wpa_s->p2p_go_no_pri_sec_switch = 0;
-
 	return 0;
 }
 
@@ -1189,7 +1187,7 @@
 		   "group (GO Dev Addr " MACSTR ")", MAC2STR(go_dev_addr));
 	for (s = wpa_s->conf->ssid; s; s = s->next) {
 		if (s->disabled == 2 &&
-		    ether_addr_equal(go_dev_addr, s->bssid) &&
+		    os_memcmp(go_dev_addr, s->bssid, ETH_ALEN) == 0 &&
 		    s->ssid_len == ssid->ssid_len &&
 		    os_memcmp(ssid->ssid, s->ssid, ssid->ssid_len) == 0)
 			break;
@@ -1295,8 +1293,8 @@
 		return;
 
 	for (i = 0; s->p2p_client_list && i < s->num_p2p_clients; i++) {
-		if (!ether_addr_equal(s->p2p_client_list + i * 2 * ETH_ALEN,
-				      addr))
+		if (os_memcmp(s->p2p_client_list + i * 2 * ETH_ALEN, addr,
+			      ETH_ALEN) != 0)
 			continue;
 
 		if (i == s->num_p2p_clients - 1)
@@ -1597,8 +1595,8 @@
 
 	if (result != OFFCHANNEL_SEND_ACTION_SUCCESS &&
 	    wpa_s->pending_pd_before_join &&
-	    (ether_addr_equal(dst, wpa_s->pending_join_dev_addr) ||
-	     ether_addr_equal(dst, wpa_s->pending_join_iface_addr)) &&
+	    (os_memcmp(dst, wpa_s->pending_join_dev_addr, ETH_ALEN) == 0 ||
+	     os_memcmp(dst, wpa_s->pending_join_iface_addr, ETH_ALEN) == 0) &&
 	    wpa_s->p2p_fallback_to_go_neg) {
 		wpa_s->pending_pd_before_join = 0;
 		wpa_dbg(wpa_s, MSG_DEBUG, "P2P: No ACK for PD Req "
@@ -2939,8 +2937,8 @@
 	char params[20];
 
 	if (wpa_s->pending_pd_before_join &&
-	    (ether_addr_equal(peer, wpa_s->pending_join_dev_addr) ||
-	     ether_addr_equal(peer, wpa_s->pending_join_iface_addr))) {
+	    (os_memcmp(peer, wpa_s->pending_join_dev_addr, ETH_ALEN) == 0 ||
+	     os_memcmp(peer, wpa_s->pending_join_iface_addr, ETH_ALEN) == 0)) {
 		wpa_s->pending_pd_before_join = 0;
 		wpa_printf(MSG_DEBUG, "P2P: Starting pending "
 			   "join-existing-group operation");
@@ -3234,8 +3232,9 @@
 			   " to join an active group (SSID: %s)",
 			   MAC2STR(sa), wpa_ssid_txt(ssid, ssid_len));
 		if (!is_zero_ether_addr(wpa_s->p2p_auth_invite) &&
-		    (ether_addr_equal(go_dev_addr, wpa_s->p2p_auth_invite) ||
-		     ether_addr_equal(sa, wpa_s->p2p_auth_invite))) {
+		    (os_memcmp(go_dev_addr, wpa_s->p2p_auth_invite, ETH_ALEN)
+		     == 0 ||
+		     os_memcmp(sa, wpa_s->p2p_auth_invite, ETH_ALEN) == 0)) {
 			wpa_printf(MSG_DEBUG, "P2P: Accept previously "
 				   "authorized invitation");
 			goto accept_inv;
@@ -3272,7 +3271,7 @@
 	}
 
 	if (!is_zero_ether_addr(wpa_s->p2p_auth_invite) &&
-	    ether_addr_equal(sa, wpa_s->p2p_auth_invite)) {
+	    os_memcmp(sa, wpa_s->p2p_auth_invite, ETH_ALEN) == 0) {
 		wpa_printf(MSG_DEBUG, "P2P: Accept previously initiated "
 			   "invitation to re-invoke a persistent group");
 		os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
@@ -3281,7 +3280,7 @@
 
 	for (s = wpa_s->conf->ssid; s; s = s->next) {
 		if (s->disabled == 2 &&
-		    ether_addr_equal(s->bssid, go_dev_addr) &&
+		    os_memcmp(s->bssid, go_dev_addr, ETH_ALEN) == 0 &&
 		    s->ssid_len == ssid_len &&
 		    os_memcmp(ssid, s->ssid, ssid_len) == 0)
 			break;
@@ -3483,13 +3482,13 @@
 		return;
 
 	for (i = 0; ssid->p2p_client_list && i < ssid->num_p2p_clients; i++) {
-		if (ether_addr_equal(ssid->p2p_client_list + i * 2 * ETH_ALEN,
-				     peer))
+		if (os_memcmp(ssid->p2p_client_list + i * 2 * ETH_ALEN, peer,
+			      ETH_ALEN) == 0)
 			break;
 	}
 	if (i >= ssid->num_p2p_clients || !ssid->p2p_client_list) {
 		if (ssid->mode != WPAS_MODE_P2P_GO &&
-		    ether_addr_equal(ssid->bssid, peer)) {
+		    os_memcmp(ssid->bssid, peer, ETH_ALEN) == 0) {
 			wpa_printf(MSG_DEBUG, "P2P: Remove persistent group %d "
 				   "due to invitation result", ssid->id);
 			wpas_notify_network_removed(wpa_s, ssid);
@@ -4186,7 +4185,7 @@
 	struct wpa_supplicant *wpa_s = ctx;
 
 	for (wpa_s = wpa_s->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
-		if (ether_addr_equal(wpa_s->own_addr, interface_addr))
+		if (os_memcmp(wpa_s->own_addr, interface_addr, ETH_ALEN) == 0)
 			break;
 	}
 	if (wpa_s == NULL)
@@ -4225,7 +4224,7 @@
 		struct wpa_ssid *ssid = wpa_s->current_ssid;
 		if (ssid && (ssid->mode != WPAS_MODE_INFRA || !ssid->p2p_group))
 			continue;
-		if (ether_addr_equal(wpa_s->go_dev_addr, peer_dev_addr))
+		if (os_memcmp(wpa_s->go_dev_addr, peer_dev_addr, ETH_ALEN) == 0)
 			return wpa_s;
 	}
 
@@ -4436,7 +4435,7 @@
 	while ((s = wpas_p2p_get_persistent(wpa_s, peer, NULL, 0))) {
 		if (go && ssid && ssid_len &&
 		    s->ssid_len == ssid_len &&
-		    ether_addr_equal(go, s->bssid) &&
+		    os_memcmp(go, s->bssid, ETH_ALEN) == 0 &&
 		    os_memcmp(ssid, s->ssid, ssid_len) == 0)
 			break;
 
@@ -4452,8 +4451,8 @@
 		}
 
 		for (i = 0; i < s->num_p2p_clients; i++) {
-			if (!ether_addr_equal(s->p2p_client_list +
-					      i * 2 * ETH_ALEN, peer))
+			if (os_memcmp(s->p2p_client_list + i * 2 * ETH_ALEN,
+				      peer, ETH_ALEN) != 0)
 				continue;
 
 			os_memmove(s->p2p_client_list + i * 2 * ETH_ALEN,
@@ -4607,7 +4606,7 @@
 			break;
 
 		if (s && s->ssid_len == stale->ssid_len &&
-		    ether_addr_equal(stale->bssid, s->bssid) &&
+		    os_memcmp(stale->bssid, s->bssid, ETH_ALEN) == 0 &&
 		    os_memcmp(stale->ssid, s->ssid, s->ssid_len) == 0)
 			break;
 
@@ -4623,8 +4622,9 @@
 			size_t i;
 
 			for (i = 0; i < stale->num_p2p_clients; i++) {
-				if (ether_addr_equal(stale->p2p_client_list +
-						     i * ETH_ALEN, dev)) {
+				if (os_memcmp(stale->p2p_client_list +
+					      i * ETH_ALEN,
+					      dev, ETH_ALEN) == 0) {
 					os_memmove(stale->p2p_client_list +
 						   i * ETH_ALEN,
 						   stale->p2p_client_list +
@@ -5474,8 +5474,8 @@
 	    p2p_get_interface_addr(wpa_s->global->p2p,
 				   wpa_s->pending_join_dev_addr,
 				   iface_addr) == 0 &&
-	    !ether_addr_equal(iface_addr, wpa_s->pending_join_dev_addr) &&
-	    !wpa_bss_get_bssid(wpa_s, wpa_s->pending_join_iface_addr)) {
+	    os_memcmp(iface_addr, wpa_s->pending_join_dev_addr, ETH_ALEN) != 0
+	    && !wpa_bss_get_bssid(wpa_s, wpa_s->pending_join_iface_addr)) {
 		wpa_printf(MSG_DEBUG, "P2P: Overwrite pending interface "
 			   "address for join from " MACSTR " to " MACSTR
 			   " based on newly discovered P2P peer entry",
@@ -5515,9 +5515,10 @@
 			   wpa_ssid_txt(bss->ssid, bss->ssid_len));
 		if (p2p_parse_dev_addr(wpa_bss_ie_ptr(bss), bss->ie_len,
 				       dev_addr) == 0 &&
-		    ether_addr_equal(wpa_s->pending_join_dev_addr,
-				     wpa_s->pending_join_iface_addr) &&
-		    !ether_addr_equal(dev_addr, wpa_s->pending_join_dev_addr)) {
+		    os_memcmp(wpa_s->pending_join_dev_addr,
+			      wpa_s->pending_join_iface_addr, ETH_ALEN) == 0 &&
+		    os_memcmp(dev_addr, wpa_s->pending_join_dev_addr,
+			      ETH_ALEN) != 0) {
 			wpa_printf(MSG_DEBUG,
 				   "P2P: Update target GO device address based on BSS entry: " MACSTR " (was " MACSTR ")",
 				   MAC2STR(dev_addr),
@@ -7005,8 +7006,7 @@
 			return -1;
 	}
 
-	if (wpas_p2p_init_go_params(wpa_s, &params, selected_freq,
-				    vht_center_freq2,
+	if (wpas_p2p_init_go_params(wpa_s, &params, selected_freq, vht_center_freq2,
 				    ht40, vht, max_oper_chwidth, he, edmg,
 				    NULL))
 		return -1;
@@ -7100,7 +7100,7 @@
 	 * fetch time on the same radio so it reflects the actual time the last
 	 * scan result event occurred.
 	 */
-	wpa_supplicant_update_scan_results(wpa_s, go_bssid);
+	wpa_supplicant_update_scan_results(wpa_s);
 	dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
 			 radio_list) {
 		if (ifs == wpa_s)
@@ -7504,10 +7504,9 @@
 }
 
 
-static void wpas_p2p_clear_pending_action_tx(struct wpa_supplicant *wpa_s,
-					     bool force)
+static void wpas_p2p_clear_pending_action_tx(struct wpa_supplicant *wpa_s)
 {
-	if (!offchannel_pending_action_tx(wpa_s) && !force)
+	if (!offchannel_pending_action_tx(wpa_s))
 		return;
 
 	if (wpa_s->p2p_send_action_work) {
@@ -7517,8 +7516,6 @@
 		offchannel_send_action_done(wpa_s);
 	}
 
-	if (!offchannel_pending_action_tx(wpa_s))
-		return;
 	wpa_printf(MSG_DEBUG, "P2P: Drop pending Action TX due to new "
 		   "operation request");
 	offchannel_clear_pending_action_tx(wpa_s);
@@ -7532,7 +7529,7 @@
 		  u8 seek_cnt, const char **seek_string, int freq,
 		  bool include_6ghz)
 {
-	wpas_p2p_clear_pending_action_tx(wpa_s, false);
+	wpas_p2p_clear_pending_action_tx(wpa_s);
 	wpa_s->global->p2p_long_listen = 0;
 
 	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL ||
@@ -7578,7 +7575,7 @@
 
 static void wpas_p2p_stop_find_oper(struct wpa_supplicant *wpa_s)
 {
-	wpas_p2p_clear_pending_action_tx(wpa_s, true);
+	wpas_p2p_clear_pending_action_tx(wpa_s);
 	wpa_s->global->p2p_long_listen = 0;
 	eloop_cancel_timeout(wpas_p2p_long_listen_timeout, wpa_s, NULL);
 	eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL);
@@ -7623,7 +7620,7 @@
 	}
 
 	wpa_supplicant_cancel_sched_scan(wpa_s);
-	wpas_p2p_clear_pending_action_tx(wpa_s, false);
+	wpas_p2p_clear_pending_action_tx(wpa_s);
 
 	if (timeout == 0) {
 		/*
@@ -8743,13 +8740,13 @@
 				return s;
 			continue;
 		}
-		if (ether_addr_equal(s->bssid, addr))
+		if (os_memcmp(s->bssid, addr, ETH_ALEN) == 0)
 			return s; /* peer is GO in the persistent group */
 		if (s->mode != WPAS_MODE_P2P_GO || s->p2p_client_list == NULL)
 			continue;
 		for (i = 0; i < s->num_p2p_clients; i++) {
-			if (ether_addr_equal(s->p2p_client_list +
-					     i * 2 * ETH_ALEN, addr))
+			if (os_memcmp(s->p2p_client_list + i * 2 * ETH_ALEN,
+				      addr, ETH_ALEN) == 0)
 				return s; /* peer is P2P client in persistent
 					   * group */
 		}
@@ -8891,9 +8888,9 @@
 	dl_list_for_each_safe(psk, tmp, &s->psk_list, struct psk_list_entry,
 			      list) {
 		if ((iface_addr && !psk->p2p &&
-		     ether_addr_equal(addr, psk->addr)) ||
+		     os_memcmp(addr, psk->addr, ETH_ALEN) == 0) ||
 		    (!iface_addr && psk->p2p &&
-		     ether_addr_equal(addr, psk->addr))) {
+		     os_memcmp(addr, psk->addr, ETH_ALEN) == 0)) {
 			wpa_dbg(wpa_s, MSG_DEBUG,
 				"P2P: Remove persistent group PSK list entry for "
 				MACSTR " p2p=%u",
@@ -9032,9 +9029,9 @@
 	prev = NULL;
 	psk = hapd->conf->ssid.wpa_psk;
 	while (psk) {
-		if ((iface_addr && ether_addr_equal(peer, psk->addr)) ||
+		if ((iface_addr && os_memcmp(peer, psk->addr, ETH_ALEN) == 0) ||
 		    (!iface_addr &&
-		     ether_addr_equal(peer, psk->p2p_dev_addr))) {
+		     os_memcmp(peer, psk->p2p_dev_addr, ETH_ALEN) == 0)) {
 			wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Remove operating group PSK entry for "
 				MACSTR " iface_addr=%d",
 				MAC2STR(peer), iface_addr);
@@ -9888,7 +9885,6 @@
 	os_memset(&csa_settings, 0, sizeof(csa_settings));
 	csa_settings.cs_count = P2P_GO_CSA_COUNT;
 	csa_settings.block_tx = P2P_GO_CSA_BLOCK_TX;
-	csa_settings.link_id = -1;
 	csa_settings.freq_params.freq = params.freq;
 	csa_settings.freq_params.sec_channel_offset = conf->secondary_channel;
 	csa_settings.freq_params.ht_enabled = conf->ieee80211n;
diff --git a/wpa_supplicant/pasn_supplicant.c b/wpa_supplicant/pasn_supplicant.c
index 1bb38f7..edecfde 100644
--- a/wpa_supplicant/pasn_supplicant.c
+++ b/wpa_supplicant/pasn_supplicant.c
@@ -166,7 +166,7 @@
 
 	bss = wpa_bss_get_bssid(wpa_s, peer_addr);
 	if (!bss) {
-		wpa_supplicant_update_scan_results(wpa_s, peer_addr);
+		wpa_supplicant_update_scan_results(wpa_s);
 		bss = wpa_bss_get_bssid(wpa_s, peer_addr);
 		if (!bss) {
 			wpa_printf(MSG_DEBUG, "PASN: BSS not found");
@@ -320,7 +320,7 @@
 		return -1;
 	}
 
-	if (!ether_addr_equal(entry->own_addr, own_addr)) {
+	if (os_memcmp(entry->own_addr, own_addr, ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG,
 			   "PASN: own addr " MACSTR " and PTKSA entry own addr "
 			   MACSTR " differ",
@@ -352,7 +352,7 @@
 	while (wpa_s->pasn_count < pasn_params->num_peers) {
 		peer = &pasn_params->peer[wpa_s->pasn_count];
 
-		if (ether_addr_equal(wpa_s->bssid, peer->peer_addr)) {
+		if (os_memcmp(wpa_s->bssid, peer->peer_addr, ETH_ALEN) == 0) {
 			wpa_printf(MSG_DEBUG,
 				   "PASN: Associated peer is not expected");
 			peer->status = PASN_STATUS_FAILURE;
@@ -426,7 +426,6 @@
 }
 
 
-#ifdef CONFIG_FILS
 static void wpas_pasn_initiate_eapol(struct pasn_data *pasn,
 				     struct wpa_ssid *ssid)
 {
@@ -444,7 +443,6 @@
 
 	eapol_sm_notify_config(pasn->eapol, &ssid->eap, &eapol_conf);
 }
-#endif /* CONFIG_FILS */
 
 
 static void wpas_pasn_reset(struct wpa_supplicant *wpa_s)
@@ -468,13 +466,13 @@
 	struct wpa_ie_data rsne_data;
 	int ret;
 
-	if (ether_addr_equal(wpa_s->bssid, peer_addr)) {
+	if (os_memcmp(wpa_s->bssid, peer_addr, ETH_ALEN) == 0) {
 		wpa_printf(MSG_DEBUG,
 			   "PASN: Not doing authentication with current BSS");
 		return NULL;
 	}
 
-	bss = wpa_bss_get_bssid_latest(wpa_s, peer_addr);
+	bss = wpa_bss_get_bssid(wpa_s, peer_addr);
 	if (!bss) {
 		wpa_printf(MSG_DEBUG, "PASN: BSS not found");
 		return NULL;
@@ -511,10 +509,8 @@
 	struct wpa_ssid *ssid;
 	struct wpa_bss *bss;
 	const u8 *rsne, *rsnxe;
-#ifdef CONFIG_FILS
 	const u8 *indic;
 	u16 fils_info;
-#endif /* CONFIG_FILS */
 	u16 capab = 0;
 	bool derive_kdk;
 	int ret;
@@ -560,10 +556,9 @@
 		derive_kdk = wpa_s->conf->force_kdk_derivation;
 #endif /* CONFIG_TESTING_OPTIONS */
 	if (derive_kdk)
-		pasn_enable_kdk_derivation(pasn);
+		pasn->kdk_len = WPA_KDK_MAX_LEN;
 	else
-		pasn_disable_kdk_derivation(pasn);
-
+		pasn->kdk_len = 0;
 	wpa_printf(MSG_DEBUG, "PASN: kdk_len=%zu", pasn->kdk_len);
 
 	if ((wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF_STA) &&
@@ -583,8 +578,9 @@
 		capab |= BIT(WLAN_RSNX_CAPAB_SECURE_RTT);
 	if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_PROT_RANGE_NEG_STA)
 		capab |= BIT(WLAN_RSNX_CAPAB_URNM_MFPR);
-	pasn_set_rsnxe_caps(pasn, capab);
-	pasn_register_callbacks(pasn, wpa_s, wpas_pasn_send_mlme, NULL);
+	pasn->rsnxe_capab = capab;
+	pasn->send_mgmt = wpas_pasn_send_mlme;
+
 	ssid = wpa_config_get_network(wpa_s->conf, awork->network_id);
 
 #ifdef CONFIG_SAE
@@ -594,7 +590,7 @@
 				   "PASN: No network profile found for SAE");
 			goto fail;
 		}
-		pasn_set_pt(pasn, wpas_pasn_sae_derive_pt(ssid, awork->group));
+		pasn->pt = wpas_pasn_sae_derive_pt(ssid, awork->group);
 		if (!pasn->pt) {
 			wpa_printf(MSG_DEBUG, "PASN: Failed to derive PT");
 			goto fail;
@@ -629,7 +625,8 @@
 	}
 #endif /* CONFIG_FILS */
 
-	pasn_set_initiator_pmksa(pasn, wpa_sm_get_pmksa_cache(wpa_s->wpa));
+	pasn->cb_ctx = wpa_s;
+	pasn->pmksa = wpa_sm_get_pmksa_cache(wpa_s->wpa);
 
 	if (wpa_key_mgmt_ft(awork->akmp)) {
 #ifdef CONFIG_IEEE80211R
@@ -752,8 +749,7 @@
 
 	wpa_printf(MSG_DEBUG, "PASN: Stopping authentication");
 
-	wpas_pasn_auth_status(wpa_s, pasn->peer_addr, pasn_get_akmp(pasn),
-			      pasn_get_cipher(pasn),
+	wpas_pasn_auth_status(wpa_s, pasn->peer_addr, pasn->akmp, pasn->cipher,
 			      pasn->status, pasn->comeback,
 			      pasn->comeback_after);
 
@@ -765,8 +761,8 @@
 				     struct pasn_data *pasn,
 				     struct wpa_pasn_params_data *params)
 {
-	int akmp = pasn_get_akmp(pasn);
-	int cipher = pasn_get_cipher(pasn);
+	int akmp = pasn->akmp;
+	int cipher = pasn->cipher;
 	u16 group = pasn->group;
 	u8 own_addr[ETH_ALEN];
 	u8 peer_addr[ETH_ALEN];
@@ -806,22 +802,20 @@
 	if (!wpa_s->pasn_auth_work)
 		return -2;
 
-	pasn_register_callbacks(pasn, wpa_s, wpas_pasn_send_mlme, NULL);
+	pasn->cb_ctx = wpa_s;
 	ret = wpa_pasn_auth_rx(pasn, (const u8 *) mgmt, len, &pasn_data);
 	if (ret == 0) {
 		ptksa_cache_add(wpa_s->ptksa, pasn->own_addr, pasn->peer_addr,
-				pasn_get_cipher(pasn),
-				dot11RSNAConfigPMKLifetime,
-				pasn_get_ptk(pasn),
+				pasn->cipher, dot11RSNAConfigPMKLifetime,
+				&pasn->ptk,
 				wpa_s->pasn_params ? wpas_pasn_deauth_cb : NULL,
-				wpa_s->pasn_params ? wpa_s : NULL,
-				pasn_get_akmp(pasn));
+				wpa_s->pasn_params ? wpa_s : NULL, pasn->akmp);
 
 		if (pasn->pmksa_entry)
 			wpa_sm_set_cur_pmksa(wpa_s->wpa, pasn->pmksa_entry);
 	}
 
-	forced_memzero(pasn_get_ptk(pasn), sizeof(pasn->ptk));
+	forced_memzero(&pasn->ptk, sizeof(pasn->ptk));
 
 	if (ret == -1) {
 		wpas_pasn_auth_stop(wpa_s);
@@ -911,8 +905,7 @@
 	}
 
 	wpas_pasn_set_keys_from_cache(wpa_s, pasn->own_addr, pasn->peer_addr,
-				      pasn_get_cipher(pasn),
-				      pasn_get_akmp(pasn));
+				      pasn->cipher, pasn->akmp);
 	wpas_pasn_auth_stop(wpa_s);
 	wpas_pasn_auth_work_done(wpa_s, PASN_STATUS_SUCCESS);
 
@@ -928,7 +921,7 @@
 	struct ieee80211_mgmt *deauth;
 	int ret;
 
-	if (ether_addr_equal(wpa_s->bssid, peer_addr)) {
+	if (os_memcmp(wpa_s->bssid, peer_addr, ETH_ALEN) == 0) {
 		wpa_printf(MSG_DEBUG,
 			   "PASN: Cannot deauthenticate from current BSS");
 		return -1;
diff --git a/wpa_supplicant/robust_av.c b/wpa_supplicant/robust_av.c
index 658103d..58edd9b 100644
--- a/wpa_supplicant/robust_av.c
+++ b/wpa_supplicant/robust_av.c
@@ -665,91 +665,17 @@
 }
 
 
-/* Element ID Extension(1) + Request Type(1) + User Priority Control(2) +
- * Stream Timeout(4) */
-#define MSCS_DESCRIPTOR_FIXED_LEN 8
-
-static void wpas_parse_mscs_resp(struct wpa_supplicant *wpa_s,
-				 u16 status, const u8 *bssid,
-				 const u8 *mscs_desc_ie)
-{
-	struct robust_av_data robust_av;
-	const u8 *pos;
-
-	/* The MSCS Descriptor element is optional in the MSCS Response frame */
-	if (!mscs_desc_ie)
-		goto event_mscs_result;
-
-	if (mscs_desc_ie[1] < MSCS_DESCRIPTOR_FIXED_LEN) {
-		wpa_printf(MSG_INFO,
-			   "MSCS: Drop received frame: invalid MSCS Descriptor element length: %d",
-			   mscs_desc_ie[1]);
-		return;
-	}
-
-	os_memset(&robust_av, 0, sizeof(struct robust_av_data));
-
-	/* Skip Element ID, Length, and Element ID Extension */
-	pos = &mscs_desc_ie[3];
-
-	robust_av.request_type = *pos++;
-
-	switch (robust_av.request_type) {
-	case SCS_REQ_CHANGE:
-		/*
-		 * Inform the suggested set of parameters that could be accepted
-		 * by the AP in response to a subsequent request by the station.
-		 */
-		robust_av.up_bitmap = *pos++;
-		robust_av.up_limit = *pos++ & 0x07;
-		robust_av.stream_timeout = WPA_GET_LE32(pos);
-		wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_MSCS_RESULT "bssid=" MACSTR
-			" status_code=%u change up_bitmap=%u up_limit=%u stream_timeout=%u",
-			MAC2STR(bssid), status, robust_av.up_bitmap,
-			robust_av.up_limit, robust_av.stream_timeout);
-		wpa_s->mscs_setup_done = false;
-		return;
-	case SCS_REQ_ADD:
-		/*
-		 * This type is used in (Re)Association Response frame MSCS
-		 * Descriptor element if no change is required.
-		 */
-		break;
-	default:
-		wpa_printf(MSG_INFO,
-			   "MSCS: Drop received frame with unknown Request Type: %u",
-			   robust_av.request_type);
-		return;
-	}
-
-event_mscs_result:
-	wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_MSCS_RESULT "bssid=" MACSTR
-		" status_code=%u", MAC2STR(bssid), status);
-	wpa_s->mscs_setup_done = status == WLAN_STATUS_SUCCESS;
-}
-
-
 void wpas_handle_robust_av_recv_action(struct wpa_supplicant *wpa_s,
 				       const u8 *src, const u8 *buf, size_t len)
 {
 	u8 dialog_token;
 	u16 status_code;
-	const u8 *mscs_desc_ie;
 
 	if (len < 3)
 		return;
 
 	dialog_token = *buf++;
-	len--;
-
-	/* AP sets dialog token to 0 for unsolicited response */
-	if (!dialog_token && !wpa_s->mscs_setup_done) {
-		wpa_printf(MSG_INFO,
-			   "MSCS: Drop unsolicited received frame: inactive");
-		return;
-	}
-
-	if (dialog_token && dialog_token != wpa_s->robust_av.dialog_token) {
+	if (dialog_token != wpa_s->robust_av.dialog_token) {
 		wpa_printf(MSG_INFO,
 			   "MSCS: Drop received frame due to dialog token mismatch: received:%u expected:%u",
 			   dialog_token, wpa_s->robust_av.dialog_token);
@@ -757,11 +683,9 @@
 	}
 
 	status_code = WPA_GET_LE16(buf);
-	buf += 2;
-	len -= 2;
-
-	mscs_desc_ie = get_ie_ext(buf, len, WLAN_EID_EXT_MSCS_DESCRIPTOR);
-	wpas_parse_mscs_resp(wpa_s, status_code, src, mscs_desc_ie);
+	wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_MSCS_RESULT "bssid=" MACSTR
+		" status_code=%u", MAC2STR(src), status_code);
+	wpa_s->mscs_setup_done = status_code == WLAN_STATUS_SUCCESS;
 }
 
 
@@ -777,19 +701,21 @@
 		return;
 
 	mscs_desc_ie = get_ie_ext(ies, ies_len, WLAN_EID_EXT_MSCS_DESCRIPTOR);
-	if (!mscs_desc_ie || mscs_desc_ie[1] <= MSCS_DESCRIPTOR_FIXED_LEN)
+	if (!mscs_desc_ie || mscs_desc_ie[1] <= 8)
 		return;
 
-	/* Subelements start after element header and fixed fields */
-	mscs_status = get_ie(&mscs_desc_ie[2 + MSCS_DESCRIPTOR_FIXED_LEN],
-			     mscs_desc_ie[1] - MSCS_DESCRIPTOR_FIXED_LEN,
+	/* Subelements start after (ie_id(1) + ie_len(1) + ext_id(1) +
+	 * request type(1) + upc(2) + stream timeout(4) =) 10.
+	 */
+	mscs_status = get_ie(&mscs_desc_ie[10], mscs_desc_ie[1] - 8,
 			     MCSC_SUBELEM_STATUS);
 	if (!mscs_status || mscs_status[1] < 2)
 		return;
 
 	status = WPA_GET_LE16(mscs_status + 2);
-
-	wpas_parse_mscs_resp(wpa_s, status, bssid, mscs_desc_ie);
+	wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_MSCS_RESULT "bssid=" MACSTR
+		" status_code=%u", MAC2STR(bssid), status);
+	wpa_s->mscs_setup_done = status == WLAN_STATUS_SUCCESS;
 }
 
 
diff --git a/wpa_supplicant/rrm.c b/wpa_supplicant/rrm.c
index 2ec4310..8e51717 100644
--- a/wpa_supplicant/rrm.c
+++ b/wpa_supplicant/rrm.c
@@ -515,8 +515,6 @@
 		num_primary_channels = 4;
 	else if (op->bw == BW160)
 		num_primary_channels = 8;
-	else if (op->bw == BW320)
-		num_primary_channels = 16;
 	else
 		num_primary_channels = 1;
 
@@ -563,7 +561,6 @@
 	u8 channels_80mhz_6ghz[] = { 7, 23, 39, 55, 71, 87, 103, 119, 135, 151,
 				     167, 183, 199, 215 };
 	u8 channels_160mhz_6ghz[] = { 15, 47, 79, 111, 143, 175, 207 };
-	u8 channels_320mhz_6ghz[] = { 31, 63, 95, 127, 159, 191 };
 	const u8 *channels = NULL;
 	size_t num_chan = 0;
 	bool is_6ghz = is_6ghz_op_class(op->op_class);
@@ -582,9 +579,6 @@
 			channels_160mhz_5ghz;
 		num_chan =  is_6ghz ? ARRAY_SIZE(channels_160mhz_6ghz) :
 			ARRAY_SIZE(channels_160mhz_5ghz);
-	} else if (op->bw == BW320) {
-		channels = channels_320mhz_6ghz;
-		num_chan = ARRAY_SIZE(channels_320mhz_6ghz);
 	}
 
 	return wpas_add_channels(op, mode, channels, num_chan);
@@ -778,7 +772,6 @@
 
 
 static int wpas_beacon_rep_add_frame_body(struct bitfield *eids,
-					  struct bitfield *ext_eids,
 					  enum beacon_report_detail detail,
 					  struct wpa_bss *bss, u8 *buf,
 					  size_t buf_len, const u8 **ies_buf,
@@ -835,9 +828,7 @@
 	 */
 	while (ies_len > 2 && 2U + ies[1] <= ies_len && rem_len > 0) {
 		if (detail == BEACON_REPORT_DETAIL_ALL_FIELDS_AND_ELEMENTS ||
-		    (eids && bitfield_is_set(eids, ies[0])) ||
-		    (ext_eids && ies[0] == WLAN_EID_EXTENSION && ies[1] &&
-		     bitfield_is_set(ext_eids, ies[2]))) {
+		    (eids && bitfield_is_set(eids, ies[0]))) {
 			u8 elen = ies[1];
 
 			if (2 + elen > buf + buf_len - pos ||
@@ -885,8 +876,7 @@
 
 	os_memcpy(buf, rep, sizeof(*rep));
 
-	ret = wpas_beacon_rep_add_frame_body(data->eids, data->ext_eids,
-					     data->report_detail,
+	ret = wpas_beacon_rep_add_frame_body(data->eids, data->report_detail,
 					     bss, buf + sizeof(*rep),
 					     14 + *ie_len, ie, ie_len,
 					     idx == 0);
@@ -942,8 +932,8 @@
 	struct rrm_measurement_beacon_report rep;
 	u8 idx = 0;
 
-	if (!ether_addr_equal(data->bssid, broadcast_ether_addr) &&
-	    !ether_addr_equal(data->bssid, bss->bssid))
+	if (os_memcmp(data->bssid, broadcast_ether_addr, ETH_ALEN) != 0 &&
+	    os_memcmp(data->bssid, bss->bssid, ETH_ALEN) != 0)
 		return 0;
 
 	if (data->ssid_len &&
@@ -1053,7 +1043,6 @@
 					     struct beacon_rep_data *data,
 					     u8 sid, u8 slen, const u8 *subelem)
 {
-	struct bitfield *eids;
 	u8 report_info, i;
 
 	switch (sid) {
@@ -1107,7 +1096,6 @@
 
 		break;
 	case WLAN_BEACON_REQUEST_SUBELEM_REQUEST:
-	case WLAN_BEACON_REQUEST_SUBELEM_EXT_REQUEST:
 		if (data->report_detail !=
 		    BEACON_REPORT_DETAIL_REQUESTED_ONLY) {
 			wpa_printf(MSG_DEBUG,
@@ -1123,46 +1111,20 @@
 			return -1;
 		}
 
-		if (sid == WLAN_BEACON_REQUEST_SUBELEM_EXT_REQUEST) {
-			if (slen < 2) {
-				wpa_printf(MSG_DEBUG,
-					   "Invalid extended request");
-				return -1;
-			}
-			if (subelem[0] != WLAN_EID_EXTENSION) {
-				wpa_printf(MSG_DEBUG,
-					   "Skip unknown Requested Element ID %u in Extended Request subelement",
-					   subelem[0]);
-				break;
-			}
-
-			/* Skip the Requested Element ID field */
-			subelem++;
-			slen--;
-		}
-
-		if ((sid == WLAN_BEACON_REQUEST_SUBELEM_REQUEST &&
-		     data->eids) ||
-		    (sid == WLAN_BEACON_REQUEST_SUBELEM_EXT_REQUEST &&
-		    data->ext_eids)) {
+		if (data->eids) {
 			wpa_printf(MSG_DEBUG,
-				   "Beacon Request: Request sub elements appear more than once");
+				   "Beacon Request: Request subelement appears more than once");
 			return -1;
 		}
 
-		eids = bitfield_alloc(255);
-		if (!eids) {
+		data->eids = bitfield_alloc(255);
+		if (!data->eids) {
 			wpa_printf(MSG_DEBUG, "Failed to allocate EIDs bitmap");
 			return -1;
 		}
 
-		if (sid == WLAN_BEACON_REQUEST_SUBELEM_REQUEST)
-			data->eids = eids;
-		else
-			data->ext_eids = eids;
-
 		for (i = 0; i < slen; i++)
-			bitfield_set(eids, subelem[i]);
+			bitfield_set(data->eids, subelem[i]);
 		break;
 	case WLAN_BEACON_REQUEST_SUBELEM_AP_CHANNEL:
 		/* Skip - it will be processed when freqs are added */
@@ -1518,26 +1480,6 @@
 }
 
 
-static bool wpas_beacon_rep_scan_match(struct wpa_supplicant *wpa_s,
-				       const u8 *bssid)
-{
-	u8 i;
-
-	if (!wpa_s->valid_links)
-		return ether_addr_equal(wpa_s->current_bss->bssid, bssid);
-
-	for_each_link(wpa_s->valid_links, i) {
-		if (ether_addr_equal(wpa_s->links[i].bssid, bssid))
-			return true;
-	}
-
-	wpa_printf(MSG_DEBUG, "RRM: MLD: no match for TSF BSSID=" MACSTR,
-		   MAC2STR(bssid));
-
-	return false;
-}
-
-
 int wpas_beacon_rep_scan_process(struct wpa_supplicant *wpa_s,
 				 struct wpa_scan_results *scan_res,
 				 struct scan_info *info)
@@ -1559,7 +1501,8 @@
 		   MAC2STR(info->scan_start_tsf_bssid),
 		   MAC2STR(wpa_s->current_bss->bssid));
 	if ((wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_SUPPORT_BEACON_REPORT) &&
-	    !wpas_beacon_rep_scan_match(wpa_s, info->scan_start_tsf_bssid)) {
+	    os_memcmp(info->scan_start_tsf_bssid, wpa_s->current_bss->bssid,
+		      ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG,
 			   "RRM: Ignore scan results due to mismatching TSF BSSID");
 		goto out;
@@ -1574,8 +1517,8 @@
 
 		if ((wpa_s->drv_rrm_flags &
 		     WPA_DRIVER_FLAGS_SUPPORT_BEACON_REPORT) &&
-		    !wpas_beacon_rep_scan_match(wpa_s,
-						scan_res->res[i]->tsf_bssid)) {
+		    os_memcmp(scan_res->res[i]->tsf_bssid,
+			      wpa_s->current_bss->bssid, ETH_ALEN) != 0) {
 			wpa_printf(MSG_DEBUG,
 				   "RRM: Ignore scan result for " MACSTR
 				   " due to mismatching TSF BSSID" MACSTR,
@@ -1644,7 +1587,6 @@
 
 	eloop_cancel_timeout(wpas_rrm_scan_timeout, wpa_s, NULL);
 	bitfield_free(data->eids);
-	bitfield_free(data->ext_eids);
 	os_free(data->scan_params.freqs);
 	os_memset(data, 0, sizeof(*data));
 }
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index ccd694b..bab6a23 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -261,10 +261,8 @@
 			wpa_s->scan_res_handler = NULL;
 		}
 
-#ifndef CONFIG_NO_RRM
 		if (wpa_s->beacon_rep_data.token)
 			wpas_rrm_refuse_request(wpa_s);
-#endif /* CONFIG_NO_RRM */
 
 		return;
 	}
@@ -698,7 +696,10 @@
 	else
 		wpa_printf(MSG_DEBUG, "MLD: Probing links 0x%04x", links);
 
-	for_each_link(links, link_id) {
+	for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
+		if (!(links & BIT(link_id)))
+			continue;
+
 		wpabuf_put_u8(extra_ie, EHT_ML_SUB_ELEM_PER_STA_PROFILE);
 
 		/* Subelement length includes only the control */
@@ -2252,6 +2253,7 @@
 static int wpas_channel_width_tx_pwr(const u8 *ies, size_t ies_len,
 				     enum chan_width cw)
 {
+#define MIN(a, b) (a < b ? a : b)
 	int offset = wpas_channel_width_offset(cw);
 	const struct element *elem;
 	int max_tx_power = TX_POWER_NO_CONSTRAINT, tx_pwr = 0;
@@ -2327,6 +2329,7 @@
 	}
 
 	return max_tx_power;
+#undef MIN
 }
 
 
@@ -2368,6 +2371,7 @@
  * better. */
 static int wpa_scan_result_compar(const void *a, const void *b)
 {
+#define MIN(a,b) a < b ? a : b
 	struct wpa_scan_res **_wa = (void *) a;
 	struct wpa_scan_res **_wb = (void *) b;
 	struct wpa_scan_res *wa = *_wa;
@@ -2375,7 +2379,6 @@
 	int wpa_a, wpa_b;
 	int snr_a, snr_b, snr_a_full, snr_b_full;
 	size_t ies_len;
-	const u8 *rsne_a, *rsne_b;
 
 	/* WPA/WPA2 support preferred */
 	wpa_a = wpa_scan_get_vendor_ie(wa, WPA_IE_VENDOR_TYPE) != NULL ||
@@ -2419,32 +2422,6 @@
 		snr_b = snr_b_full = wb->level;
 	}
 
-	/* If SNR of a SAE BSS is good or at least as high as the PSK BSS,
-	 * prefer SAE over PSK for mixed WPA3-Personal transition mode and
-	 * WPA2-Personal deployments */
-	rsne_a = wpa_scan_get_ie(wa, WLAN_EID_RSN);
-	rsne_b = wpa_scan_get_ie(wb, WLAN_EID_RSN);
-	if (rsne_a && rsne_b) {
-		struct wpa_ie_data data;
-		bool psk_a = false, psk_b = false, sae_a = false, sae_b = false;
-
-		if (wpa_parse_wpa_ie_rsn(rsne_a, 2 + rsne_a[1], &data) == 0) {
-			psk_a = wpa_key_mgmt_wpa_psk_no_sae(data.key_mgmt);
-			sae_a = wpa_key_mgmt_sae(data.key_mgmt);
-		}
-		if (wpa_parse_wpa_ie_rsn(rsne_b, 2 + rsne_b[1], &data) == 0) {
-			psk_b = wpa_key_mgmt_wpa_psk_no_sae(data.key_mgmt);
-			sae_b = wpa_key_mgmt_sae(data.key_mgmt);
-		}
-
-		if (sae_a && !sae_b && psk_b &&
-		    (snr_a >= GREAT_SNR || snr_a >= snr_b))
-			return -1;
-		if (sae_b && !sae_a && psk_a &&
-		    (snr_b >= GREAT_SNR || snr_b >= snr_a))
-			return 1;
-	}
-
 	/* If SNR is close, decide by max rate or frequency band. For cases
 	 * involving the 6 GHz band, use the throughput estimate irrespective
 	 * of the SNR difference since the LPI/VLP rules may result in
@@ -2471,6 +2448,7 @@
 	if (snr_b_full == snr_a_full)
 		return wb->qual - wa->qual;
 	return snr_b_full - snr_a_full;
+#undef MIN
 }
 
 
@@ -2595,7 +2573,8 @@
 		return 1;
 
 	for (i = 0; i < wpa_s->bssid_filter_count; i++) {
-		if (ether_addr_equal(wpa_s->bssid_filter + i * ETH_ALEN, bssid))
+		if (os_memcmp(wpa_s->bssid_filter + i * ETH_ALEN, bssid,
+			      ETH_ALEN) == 0)
 			return 1;
 	}
 
@@ -2603,8 +2582,8 @@
 }
 
 
-static void filter_scan_res(struct wpa_supplicant *wpa_s,
-			    struct wpa_scan_results *res)
+void filter_scan_res(struct wpa_supplicant *wpa_s,
+		     struct wpa_scan_results *res)
 {
 	size_t i, j;
 
@@ -2899,7 +2878,6 @@
 	 * been taken into account.
 	 */
 	int adjusted_snr;
-	bool ht40 = false, vht80 = false, vht160 = false;
 
 	/* Limit based on estimated SNR */
 	if (rate > 1 * 2 && snr < 1)
@@ -2955,14 +2933,11 @@
 		}
 	}
 
-	ie = get_ie(ies, ies_len, WLAN_EID_HT_OPERATION);
-	if (ie && ie[1] >= 2 &&
-	    (ie[3] & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK))
-		ht40 = true;
-
 	if (hw_mode &&
 	    (hw_mode->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) {
-		if (ht40) {
+		ie = get_ie(ies, ies_len, WLAN_EID_HT_OPERATION);
+		if (ie && ie[1] >= 2 &&
+		    (ie[3] & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK)) {
 			*max_cw = CHAN_WIDTH_40;
 			adjusted_snr = snr +
 				wpas_channel_width_rssi_bump(ies, ies_len,
@@ -2973,36 +2948,22 @@
 		}
 	}
 
-	/* Determine VHT BSS bandwidth based on IEEE Std 802.11-2020,
-	 * Table 11-23 (VHT BSS bandwidth) */
-	ie = get_ie(ies, ies_len, WLAN_EID_VHT_OPERATION);
-	if (ie && ie[1] >= 3) {
-		u8 cw = ie[2] & VHT_OPMODE_CHANNEL_WIDTH_MASK;
-		u8 seg0 = ie[3];
-		u8 seg1 = ie[4];
-
-		if (cw)
-			vht80 = true;
-		if (cw == 2 ||
-		    (cw == 3 && (seg1 > 0 && abs(seg1 - seg0) == 16)))
-			vht160 = true;
-		if (cw == 1 &&
-		    ((seg1 > 0 && abs(seg1 - seg0) == 8) ||
-		     (seg1 > 0 && abs(seg1 - seg0) == 16)))
-			vht160 = true;
-	}
-
 	if (hw_mode && hw_mode->vht_capab) {
 		/* Use +1 to assume VHT is always faster than HT */
 		ie = get_ie(ies, ies_len, WLAN_EID_VHT_CAP);
 		if (ie) {
+			bool vht80 = false, vht160 = false;
+
 			if (*max_cw == CHAN_WIDTH_UNKNOWN)
 				*max_cw = CHAN_WIDTH_20;
 			tmp = max_ht20_rate(snr, true) + 1;
 			if (tmp > est)
 				est = tmp;
 
-			if (ht40) {
+			ie = get_ie(ies, ies_len, WLAN_EID_HT_OPERATION);
+			if (ie && ie[1] >= 2 &&
+			    (ie[3] &
+			     HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK)) {
 				*max_cw = CHAN_WIDTH_40;
 				adjusted_snr = snr +
 					wpas_channel_width_rssi_bump(
@@ -3012,6 +2973,26 @@
 					est = tmp;
 			}
 
+			/* Determine VHT BSS bandwidth based on IEEE Std
+			 * 802.11-2020, Table 11-23 (VHT BSs bandwidth) */
+			ie = get_ie(ies, ies_len, WLAN_EID_VHT_OPERATION);
+			if (ie && ie[1] >= 3) {
+				u8 cw = ie[2] & VHT_OPMODE_CHANNEL_WIDTH_MASK;
+				u8 seg0 = ie[3];
+				u8 seg1 = ie[4];
+
+				if (cw)
+					vht80 = true;
+				if (cw == 2 ||
+				    (cw == 3 &&
+				     (seg1 > 0 && abs(seg1 - seg0) == 16)))
+					vht160 = true;
+				if (cw == 1 &&
+				    ((seg1 > 0 && abs(seg1 - seg0) == 8) ||
+				     (seg1 > 0 && abs(seg1 - seg0) == 16)))
+					vht160 = true;
+			}
+
 			if (vht80) {
 				*max_cw = CHAN_WIDTH_80;
 				adjusted_snr = snr +
@@ -3071,10 +3052,9 @@
 
 		cw = he->he_phy_capab_info[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
 			own_he->phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX];
-		if ((cw &
-		     (IS_2P4GHZ(freq) ?
-		      HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_IN_2G :
-		      HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G)) && ht40) {
+		if (cw &
+		    (IS_2P4GHZ(freq) ? HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_IN_2G :
+		     HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G)) {
 			if (*max_cw == CHAN_WIDTH_UNKNOWN ||
 			    *max_cw < CHAN_WIDTH_40)
 				*max_cw = CHAN_WIDTH_40;
@@ -3087,8 +3067,7 @@
 		}
 
 		if (!IS_2P4GHZ(freq) &&
-		    (cw & HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G) &&
-		    (!IS_5GHZ(freq) || vht80)) {
+		    (cw & HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G)) {
 			if (*max_cw == CHAN_WIDTH_UNKNOWN ||
 			    *max_cw < CHAN_WIDTH_80)
 				*max_cw = CHAN_WIDTH_80;
@@ -3102,8 +3081,7 @@
 
 		if (!IS_2P4GHZ(freq) &&
 		    (cw & (HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G |
-			   HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G)) &&
-		    (!IS_5GHZ(freq) || vht160)) {
+			   HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G))) {
 			if (*max_cw == CHAN_WIDTH_UNKNOWN ||
 			    *max_cw < CHAN_WIDTH_160)
 				*max_cw = CHAN_WIDTH_160;
@@ -3166,7 +3144,6 @@
  * @wpa_s: Pointer to wpa_supplicant data
  * @info: Information about what was scanned or %NULL if not available
  * @new_scan: Whether a new scan was performed
- * @bssid: Return BSS entries only for a single BSSID, %NULL for all
  * Returns: Scan results, %NULL on failure
  *
  * This function request the current scan results from the driver and updates
@@ -3175,14 +3152,13 @@
  */
 struct wpa_scan_results *
 wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s,
-				struct scan_info *info, int new_scan,
-				const u8 *bssid)
+				struct scan_info *info, int new_scan)
 {
 	struct wpa_scan_results *scan_res;
 	size_t i;
 	int (*compar)(const void *, const void *) = wpa_scan_result_compar;
 
-	scan_res = wpa_drv_get_scan_results(wpa_s, bssid);
+	scan_res = wpa_drv_get_scan_results2(wpa_s);
 	if (scan_res == NULL) {
 		wpa_dbg(wpa_s, MSG_DEBUG, "Failed to get scan results");
 		return NULL;
@@ -3240,7 +3216,6 @@
 /**
  * wpa_supplicant_update_scan_results - Update scan results from the driver
  * @wpa_s: Pointer to wpa_supplicant data
- * @bssid: Update BSS entries only for a single BSSID, %NULL for all
  * Returns: 0 on success, -1 on failure
  *
  * This function updates the BSS table within wpa_supplicant based on the
@@ -3250,11 +3225,10 @@
  * needed information to complete the connection (e.g., to perform validation
  * steps in 4-way handshake).
  */
-int wpa_supplicant_update_scan_results(struct wpa_supplicant *wpa_s,
-				       const u8 *bssid)
+int wpa_supplicant_update_scan_results(struct wpa_supplicant *wpa_s)
 {
 	struct wpa_scan_results *scan_res;
-	scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0, bssid);
+	scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
 	if (scan_res == NULL)
 		return -1;
 	wpa_scan_results_free(scan_res);
@@ -3351,7 +3325,6 @@
 	params->duration = src->duration;
 	params->duration_mandatory = src->duration_mandatory;
 	params->oce_scan = src->oce_scan;
-	params->link_id = src->link_id;
 
 	if (src->sched_scan_plans_num > 0) {
 		params->sched_scan_plans =
diff --git a/wpa_supplicant/scan.h b/wpa_supplicant/scan.h
index d4c06c1..f1739fa 100644
--- a/wpa_supplicant/scan.h
+++ b/wpa_supplicant/scan.h
@@ -38,6 +38,9 @@
  */
 #define TX_POWER_NO_CONSTRAINT 64
 
+#define IS_2P4GHZ(n) (n >= 2412 && n <= 2484)
+#define IS_5GHZ(n) (n > 4000 && n < 5895)
+
 int wpa_supplicant_enabled_networks(struct wpa_supplicant *wpa_s);
 void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec);
 int wpa_supplicant_delayed_sched_scan(struct wpa_supplicant *wpa_s,
@@ -54,10 +57,8 @@
 				bool default_ies, bool next);
 struct wpa_scan_results *
 wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s,
-				struct scan_info *info, int new_scan,
-				const u8 *bssid);
-int wpa_supplicant_update_scan_results(struct wpa_supplicant *wpa_s,
-				       const u8 *bssid);
+				struct scan_info *info, int new_scan);
+int wpa_supplicant_update_scan_results(struct wpa_supplicant *wpa_s);
 const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie);
 const u8 * wpa_scan_get_ml_ie(const struct wpa_scan_res *res, u8 type);
 const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res,
@@ -88,6 +89,8 @@
 int wpas_mac_addr_rand_scan_get_mask(struct wpa_supplicant *wpa_s,
 				     unsigned int type, u8 *mask);
 int wpas_abort_ongoing_scan(struct wpa_supplicant *wpa_s);
+void filter_scan_res(struct wpa_supplicant *wpa_s,
+		     struct wpa_scan_results *res);
 void scan_snr(struct wpa_scan_res *res);
 void scan_est_throughput(struct wpa_supplicant *wpa_s,
 			 struct wpa_scan_res *res);
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index be0bc0d..df2c68f 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -1,6 +1,6 @@
 /*
  * wpa_supplicant - SME
- * Copyright (c) 2009-2024, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2009-2014, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -28,7 +28,6 @@
 #include "p2p_supplicant.h"
 #include "notify.h"
 #include "bss.h"
-#include "bssid_ignore.h"
 #include "scan.h"
 #include "sme.h"
 #include "hs20_supplicant.h"
@@ -166,7 +165,7 @@
 	}
 
 	if (reuse && wpa_s->sme.sae.tmp &&
-	    ether_addr_equal(addr, wpa_s->sme.sae.tmp->bssid)) {
+	    os_memcmp(addr, wpa_s->sme.sae.tmp->bssid, ETH_ALEN) == 0) {
 		wpa_printf(MSG_DEBUG,
 			   "SAE: Reuse previously generated PWE on a retry with the same AP");
 		use_pt = wpa_s->sme.sae.h2e;
@@ -182,7 +181,7 @@
 	if (!bss) {
 		wpa_printf(MSG_DEBUG,
 			   "SAE: BSS not available, update scan result to get BSS");
-		wpa_supplicant_update_scan_results(wpa_s, bssid);
+		wpa_supplicant_update_scan_results(wpa_s);
 		bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
 	}
 	if (bss) {
@@ -243,7 +242,7 @@
 				  wpa_s->sme.sae_rejected_groups, NULL) < 0)
 		goto fail;
 	if (!use_pt &&
-	    sae_prepare_commit(wpa_s->own_addr, addr,
+	    sae_prepare_commit(wpa_s->own_addr, bssid,
 			       (u8 *) password, os_strlen(password),
 			       &wpa_s->sme.sae) < 0) {
 		wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE");
@@ -379,6 +378,220 @@
 }
 
 
+static void wpas_process_tbtt_info(struct wpa_supplicant *wpa_s, const u8 *data)
+{
+	struct wpa_bss *neigh_bss;
+	const u8 *bssid;
+	u8 bss_params;
+	u8 link_id;
+
+	/* TBTT Information field
+	 * Neighbor AP TBTT Offset[1]
+	 * BSSID[6]
+	 * Short SSID[4]
+	 * BSS parameters[1]
+	 * 20 MHz PSD[1]
+	 * MLD Parameters[3]
+	 *   B0..B7: AP MLD ID
+	 *   B7..B11: Link ID
+	 *   B12..B19: BSS Parameters Change Count
+	 *   B20: All Updates Included
+	 *   B21: Disabled Link Indication */
+
+	bssid = data + 1;
+	bss_params = data[1 + ETH_ALEN + 4];
+
+	data += 13; /* MLD Parameters */
+	link_id = *(data + 1) & 0xF;
+
+	wpa_dbg(wpa_s, MSG_DEBUG,
+		"MLD: mld ID=%u, link ID=%u, bssid=" MACSTR ", bss_params=0x%x",
+		*data, link_id, MAC2STR(bssid), bss_params);
+
+	if (*data) {
+		wpa_printf(MSG_DEBUG, "MLD: Reported link not part of MLD");
+		return;
+	}
+
+	neigh_bss = wpa_bss_get_bssid(wpa_s, bssid);
+	if (!neigh_bss) {
+		wpa_printf(MSG_DEBUG, "MLD: Neighbor not found in scan");
+		return;
+	}
+
+	if (!((bss_params & RNR_BSS_PARAM_SAME_SSID) &&
+	      (bss_params & RNR_BSS_PARAM_CO_LOCATED)) &&
+	    !wpa_scan_res_match(wpa_s, 0, neigh_bss, wpa_s->current_ssid,
+				1, 0)) {
+		wpa_printf(MSG_DEBUG,
+			   "MLD: Neighbor doesn't match current SSID - skip link");
+		return;
+	}
+
+	wpa_s->valid_links |= BIT(link_id);
+	os_memcpy(wpa_s->links[link_id].bssid, bssid, ETH_ALEN);
+	wpa_s->links[link_id].freq = neigh_bss->freq;
+}
+
+
+static void wpas_process_rnr(struct wpa_supplicant *wpa_s, const u8 *pos,
+			     size_t rnr_ie_len)
+{
+	while (rnr_ie_len > sizeof(struct ieee80211_neighbor_ap_info)) {
+		const struct ieee80211_neighbor_ap_info *ap_info =
+			(const struct ieee80211_neighbor_ap_info *) pos;
+		/* The first TBTT Information field */
+		const u8 *data = ap_info->data;
+		u8 tbtt_count;
+		size_t len;
+		int tbtt_i;
+
+		if (rnr_ie_len < sizeof(struct ieee80211_neighbor_ap_info))
+			break;
+
+		tbtt_count = (ap_info->tbtt_info_hdr >> 4) + 1;
+		len = sizeof(struct ieee80211_neighbor_ap_info) +
+			ap_info->tbtt_info_len * tbtt_count;
+
+		wpa_printf(MSG_DEBUG, "MLD: op_class=%u, channel=%u",
+			   ap_info->op_class, ap_info->channel);
+
+		if (len > rnr_ie_len)
+			break;
+
+		if (ap_info->tbtt_info_len < 16) {
+			rnr_ie_len -= len;
+			pos += len;
+			continue;
+		}
+
+		for (tbtt_i = 0; tbtt_i < tbtt_count; tbtt_i++) {
+			wpas_process_tbtt_info(wpa_s, data);
+			data += ap_info->tbtt_info_len;
+		}
+
+		rnr_ie_len -= len;
+		pos += len;
+	}
+}
+
+
+static bool wpas_ml_element(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
+			    struct wpa_ssid *ssid)
+{
+	struct wpabuf *mlbuf;
+	const u8 *rnr_ie, *rsn_ie;
+	struct wpa_ie_data ie;
+	u8 ml_ie_len;
+	const struct ieee80211_eht_ml *eht_ml;
+	const struct eht_ml_basic_common_info *ml_basic_common_info;
+	u8 i;
+	const u16 control =
+		host_to_le16(MULTI_LINK_CONTROL_TYPE_BASIC |
+			     BASIC_MULTI_LINK_CTRL_PRES_LINK_ID |
+			     BASIC_MULTI_LINK_CTRL_PRES_BSS_PARAM_CH_COUNT |
+			     BASIC_MULTI_LINK_CTRL_PRES_MLD_CAPA);
+	bool ret = false;
+	int rnr_idx;
+
+	if (!(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO))
+		return false;
+
+	mlbuf = wpa_bss_defrag_mle(bss, MULTI_LINK_CONTROL_TYPE_BASIC);
+	if (!mlbuf) {
+		wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No ML element");
+		return false;
+	}
+
+	rsn_ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
+	if (!rsn_ie || wpa_parse_wpa_ie(rsn_ie, 2 + rsn_ie[1], &ie)) {
+		wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No RSN element");
+		goto out;
+	}
+
+	if (!(ie.capabilities & WPA_CAPABILITY_MFPC) ||
+	    wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION) {
+		wpa_dbg(wpa_s, MSG_DEBUG,
+			"MLD: No management frame protection");
+		goto out;
+	}
+
+	ie.key_mgmt &= ~(WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK |
+			 WPA_KEY_MGMT_PSK_SHA256);
+	if (!(ie.key_mgmt & ssid->key_mgmt)) {
+		wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No valid key management");
+		goto out;
+	}
+
+	ml_ie_len = wpabuf_len(mlbuf);
+
+	/* control + common info len + MLD address + MLD link information */
+	if (ml_ie_len < 2 + 1 + ETH_ALEN + 1)
+		goto out;
+
+	eht_ml = wpabuf_head(mlbuf);
+	if ((eht_ml->ml_control & control) != control) {
+		wpa_printf(MSG_DEBUG, "MLD: Unexpected ML element control=0x%x",
+			   eht_ml->ml_control);
+		goto out;
+	}
+
+	ml_basic_common_info =
+		(const struct eht_ml_basic_common_info *) eht_ml->variable;
+
+	/* common info length should be valid (self, mld_addr, link_id) */
+	if (ml_basic_common_info->len < 1 + ETH_ALEN + 1)
+		goto out;
+
+	/* get the MLD address and MLD link ID */
+	os_memcpy(wpa_s->ap_mld_addr, ml_basic_common_info->mld_addr,
+		  ETH_ALEN);
+	wpa_s->mlo_assoc_link_id = ml_basic_common_info->variable[0] &
+		EHT_ML_LINK_ID_MSK;
+
+	os_memcpy(wpa_s->links[wpa_s->mlo_assoc_link_id].bssid, bss->bssid,
+		  ETH_ALEN);
+	wpa_s->links[wpa_s->mlo_assoc_link_id].freq = bss->freq;
+
+	wpa_printf(MSG_DEBUG, "MLD: address=" MACSTR ", link ID=%u",
+		   MAC2STR(wpa_s->ap_mld_addr), wpa_s->mlo_assoc_link_id);
+
+	wpa_s->valid_links = BIT(wpa_s->mlo_assoc_link_id);
+
+	ret = true;
+
+	/* Process all Reduced Neighbor Report elements */
+	for (rnr_idx = 1; ; rnr_idx++) {
+		rnr_ie = wpa_bss_get_ie_nth(bss,
+					    WLAN_EID_REDUCED_NEIGHBOR_REPORT,
+					    rnr_idx);
+		if (!rnr_ie) {
+			if (rnr_idx == 0) {
+				wpa_dbg(wpa_s, MSG_DEBUG,
+					"MLD: No RNR element");
+				goto out;
+			}
+			break;
+		}
+		wpas_process_rnr(wpa_s, rnr_ie + 2, rnr_ie[1]);
+	}
+
+	wpa_printf(MSG_DEBUG, "MLD: valid_links=0x%x", wpa_s->valid_links);
+
+	for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+		if (!(wpa_s->valid_links & BIT(i)))
+			continue;
+
+		wpa_printf(MSG_DEBUG, "MLD: link=%u, bssid=" MACSTR,
+			   i, MAC2STR(wpa_s->links[i].bssid));
+	}
+
+out:
+	wpabuf_free(mlbuf);
+	return ret;
+}
+
+
 static void wpas_ml_handle_removed_links(struct wpa_supplicant *wpa_s,
 					 struct wpa_bss *bss)
 {
@@ -388,92 +601,16 @@
 }
 
 
-#ifdef CONFIG_TESTING_OPTIONS
-static struct wpa_bss * wpas_ml_connect_pref(struct wpa_supplicant *wpa_s,
-					     struct wpa_bss *bss)
-{
-	unsigned int low, high, i;
-
-	wpa_printf(MSG_DEBUG,
-		   "MLD: valid_links=%d, band_pref=%u, bssid_pref=" MACSTR,
-		   wpa_s->valid_links,
-		   wpa_s->conf->mld_connect_band_pref,
-		   MAC2STR(wpa_s->conf->mld_connect_bssid_pref));
-
-	/* Check if there are more than one link */
-	if (!(wpa_s->valid_links & (wpa_s->valid_links - 1)))
-		return bss;
-
-	if (!is_zero_ether_addr(wpa_s->conf->mld_connect_bssid_pref)) {
-		for_each_link(wpa_s->valid_links, i) {
-			if (wpa_s->mlo_assoc_link_id == i)
-				continue;
-
-			if (ether_addr_equal(
-				    wpa_s->links[i].bssid,
-				    wpa_s->conf->mld_connect_bssid_pref))
-				goto found;
-		}
-	}
-
-	if (wpa_s->conf->mld_connect_band_pref == MLD_CONNECT_BAND_PREF_AUTO)
-		return bss;
-
-	switch (wpa_s->conf->mld_connect_band_pref) {
-	case MLD_CONNECT_BAND_PREF_2GHZ:
-		low = 2412;
-		high = 2472;
-		break;
-	case MLD_CONNECT_BAND_PREF_5GHZ:
-		low = 5180;
-		high = 5985;
-		break;
-	case MLD_CONNECT_BAND_PREF_6GHZ:
-		low = 5955;
-		high = 7125;
-		break;
-	default:
-		return bss;
-	}
-
-	for_each_link(wpa_s->valid_links, i) {
-		if (wpa_s->mlo_assoc_link_id == i)
-			continue;
-
-		if (wpa_s->links[i].freq >= low && wpa_s->links[i].freq <= high)
-			goto found;
-	}
-
-found:
-	if (i == MAX_NUM_MLD_LINKS) {
-		wpa_printf(MSG_DEBUG, "MLD: No match for connect/band pref");
-		return bss;
-	}
-
-	wpa_printf(MSG_DEBUG,
-		   "MLD: Change BSS for connect: " MACSTR " -> " MACSTR,
-		   MAC2STR(wpa_s->links[wpa_s->mlo_assoc_link_id].bssid),
-		   MAC2STR(wpa_s->links[i].bssid));
-
-	/* Get the BSS entry and do the switch */
-	bss = wpa_bss_get_bssid(wpa_s, wpa_s->links[i].bssid);
-	wpa_s->mlo_assoc_link_id = i;
-
-	return bss;
-}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-
-static int wpas_sme_ml_auth(struct wpa_supplicant *wpa_s,
-			    union wpa_event_data *data,
-			    int ie_offset)
+static void wpas_sme_ml_auth(struct wpa_supplicant *wpa_s,
+			     union wpa_event_data *data,
+			     int ie_offset)
 {
 	struct ieee802_11_elems elems;
 	const u8 *mld_addr;
 	u16 status_code = data->auth.status_code;
 
 	if (!wpa_s->valid_links)
-		return 0;
+		return;
 
 	if (ieee802_11_parse_elems(data->auth.ies + ie_offset,
 				   data->auth.ies_len - ie_offset,
@@ -491,7 +628,7 @@
 			goto out;
 		/* Accept missing Multi-Link element in failed authentication
 		 * cases. */
-		return 0;
+		return;
 	}
 
 	mld_addr = get_basic_mle_mld_addr(elems.basic_mle, elems.basic_mle_len);
@@ -500,41 +637,16 @@
 
 	wpa_printf(MSG_DEBUG, "MLD: mld_address=" MACSTR, MAC2STR(mld_addr));
 
-	if (!ether_addr_equal(wpa_s->ap_mld_addr, mld_addr)) {
+	if (os_memcmp(wpa_s->ap_mld_addr, mld_addr, ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG, "MLD: Unexpected MLD address (expected "
 			   MACSTR ")", MAC2STR(wpa_s->ap_mld_addr));
 		goto out;
 	}
 
-	return 0;
+	return;
 out:
 	wpa_printf(MSG_DEBUG, "MLD: Authentication - clearing MLD state");
 	wpas_reset_mlo_info(wpa_s);
-	return -1;
-}
-
-
-static void wpas_sme_set_mlo_links(struct wpa_supplicant *wpa_s,
-				   struct wpa_bss *bss)
-{
-	u8 i;
-
-	wpa_s->valid_links = 0;
-	wpa_s->mlo_assoc_link_id = bss->mld_link_id;
-
-	for_each_link(bss->valid_links, i) {
-		const u8 *bssid = bss->mld_links[i].bssid;
-
-		wpa_s->valid_links |= BIT(i);
-		os_memcpy(wpa_s->links[i].bssid, bssid, ETH_ALEN);
-		wpa_s->links[i].freq = bss->mld_links[i].freq;
-		wpa_s->links[i].disabled = bss->mld_links[i].disabled;
-
-		if (bss->mld_link_id == i)
-			wpa_s->links[i].bss = bss;
-		else
-			wpa_s->links[i].bss = wpa_bss_get_bssid(wpa_s, bssid);
-	}
 }
 
 
@@ -569,33 +681,11 @@
 		return;
 	}
 
-	os_memset(&params, 0, sizeof(params));
-
-	if ((wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO) &&
-	    !wpa_bss_parse_basic_ml_element(wpa_s, bss, wpa_s->ap_mld_addr,
-					    NULL, ssid, NULL) &&
-	    bss->valid_links) {
-		wpa_printf(MSG_DEBUG, "MLD: In authentication");
-		wpas_sme_set_mlo_links(wpa_s, bss);
-
-#ifdef CONFIG_TESTING_OPTIONS
-		bss = wpas_ml_connect_pref(wpa_s, bss);
-
-		if (wpa_s->conf->mld_force_single_link) {
-			wpa_printf(MSG_DEBUG, "MLD: Force single link");
-			wpa_s->valid_links = BIT(wpa_s->mlo_assoc_link_id);
-		}
-#endif /* CONFIG_TESTING_OPTIONS */
-		params.mld = true;
-		params.mld_link_id = wpa_s->mlo_assoc_link_id;
-		params.ap_mld_addr = wpa_s->ap_mld_addr;
-		wpas_ml_handle_removed_links(wpa_s, bss);
-	}
-
 	skip_auth = wpa_s->conf->reassoc_same_bss_optim &&
 		wpa_s->reassoc_same_bss;
 	wpa_s->current_bss = bss;
 
+	os_memset(&params, 0, sizeof(params));
 	wpa_s->reassociate = 0;
 
 	params.freq = bss->freq;
@@ -604,6 +694,14 @@
 	params.ssid_len = bss->ssid_len;
 	params.p2p = ssid->p2p_group;
 
+	if (wpas_ml_element(wpa_s, bss, ssid)) {
+		wpa_printf(MSG_DEBUG, "MLD: In authentication");
+		params.mld = true;
+		params.mld_link_id = wpa_s->mlo_assoc_link_id;
+		params.ap_mld_addr = wpa_s->ap_mld_addr;
+		wpas_ml_handle_removed_links(wpa_s, bss);
+	}
+
 	if (wpa_s->sme.ssid_len != params.ssid_len ||
 	    os_memcmp(wpa_s->sme.ssid, params.ssid, params.ssid_len) != 0)
 		wpa_s->sme.prev_bssid_set = 0;
@@ -872,12 +970,10 @@
 
 	sme_auth_handle_rrm(wpa_s, bss);
 
-#ifndef CONFIG_NO_RRM
 	wpa_s->sme.assoc_req_ie_len += wpas_supp_op_class_ie(
 		wpa_s, ssid, bss,
 		wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
 		sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len);
-#endif /* CONFIG_NO_RRM */
 
 	if (params.p2p)
 		wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
@@ -1026,7 +1122,7 @@
 		else
 			resp = sme_auth_build_sae_confirm(wpa_s, 0);
 		if (resp == NULL) {
-			wpas_connection_failed(wpa_s, bss->bssid, NULL);
+			wpas_connection_failed(wpa_s, bss->bssid);
 			return;
 		}
 		params.auth_data = wpabuf_head(resp);
@@ -1162,7 +1258,7 @@
 			if (wpas_p2p_handle_frequency_conflicts(wpa_s,
 								params.freq,
 								ssid) < 0) {
-				wpas_connection_failed(wpa_s, bss->bssid, NULL);
+				wpas_connection_failed(wpa_s, bss->bssid);
 				wpa_supplicant_mark_disassoc(wpa_s);
 				wpabuf_free(resp);
 				wpas_connect_work_done(wpa_s);
@@ -1185,7 +1281,7 @@
 	if (wpa_drv_authenticate(wpa_s, &params) < 0) {
 		wpa_msg(wpa_s, MSG_INFO, "SME: Authentication request to the "
 			"driver failed");
-		wpas_connection_failed(wpa_s, bss->bssid, NULL);
+		wpas_connection_failed(wpa_s, bss->bssid);
 		wpa_supplicant_mark_disassoc(wpa_s);
 		wpabuf_free(resp);
 		wpas_connect_work_done(wpa_s);
@@ -1623,7 +1719,8 @@
 
 	wpa_printf(MSG_DEBUG, "MLD: mld_address=" MACSTR, MAC2STR(mld_addr));
 
-	if (!ether_addr_equal(wpa_s->sme.ext_auth_ap_mld_addr, mld_addr)) {
+	if (os_memcmp(wpa_s->sme.ext_auth_ap_mld_addr, mld_addr, ETH_ALEN) !=
+	    0) {
 		wpa_printf(MSG_DEBUG, "MLD: Unexpected MLD address (expected "
 			   MACSTR ")",
 			   MAC2STR(wpa_s->sme.ext_auth_ap_mld_addr));
@@ -1901,7 +1998,7 @@
 		}
 		if (wpa_insert_pmkid(wpa_s->sme.assoc_req_ie,
 				     &wpa_s->sme.assoc_req_ie_len,
-				     wpa_s->sme.sae.pmkid, true) < 0)
+				     wpa_s->sme.sae.pmkid) < 0)
 			return -1;
 		wpa_hexdump(MSG_DEBUG,
 			    "SME: Updated Association Request IEs",
@@ -1978,9 +2075,9 @@
 		return;
 	}
 
-	if (!ether_addr_equal(wpa_s->pending_bssid, data->auth.peer) &&
+	if (os_memcmp(wpa_s->pending_bssid, data->auth.peer, ETH_ALEN) != 0 &&
 	    !(wpa_s->valid_links &&
-	      ether_addr_equal(wpa_s->ap_mld_addr, data->auth.peer))) {
+	      os_memcmp(wpa_s->ap_mld_addr, data->auth.peer, ETH_ALEN) == 0)) {
 		wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication with "
 			"unexpected peer " MACSTR,
 			MAC2STR(data->auth.peer));
@@ -2006,8 +2103,7 @@
 				   data->auth.ies_len, 0, data->auth.peer,
 				   &ie_offset);
 		if (res < 0) {
-			wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
-					       NULL);
+			wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
 			wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
 
 		}
@@ -2051,8 +2147,7 @@
 		    WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG ||
 		    wpa_s->sme.auth_alg == data->auth.auth_type ||
 		    wpa_s->current_ssid->auth_alg == WPA_AUTH_ALG_LEAP) {
-			wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
-					       NULL);
+			wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
 			wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
 			return;
 		}
@@ -2101,8 +2196,7 @@
 				" reason=%d locally_generated=1",
 				MAC2STR(wpa_s->pending_bssid),
 				WLAN_REASON_DEAUTH_LEAVING);
-			wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
-					       NULL);
+			wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
 			wpa_supplicant_mark_disassoc(wpa_s);
 			return;
 		}
@@ -2126,8 +2220,7 @@
 				" reason=%d locally_generated=1",
 				MAC2STR(wpa_s->pending_bssid),
 				WLAN_REASON_DEAUTH_LEAVING);
-			wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
-					       NULL);
+			wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
 			wpa_supplicant_mark_disassoc(wpa_s);
 			return;
 		}
@@ -2141,8 +2234,7 @@
 				" reason=%d locally_generated=1",
 				MAC2STR(wpa_s->pending_bssid),
 				WLAN_REASON_DEAUTH_LEAVING);
-			wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
-					       NULL);
+			wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
 			wpa_supplicant_mark_disassoc(wpa_s);
 			return;
 		}
@@ -2150,19 +2242,9 @@
 #endif /* CONFIG_FILS */
 
 	/* TODO: Support additional auth_type values as well */
-	if ((data->auth.auth_type == WLAN_AUTH_OPEN ||
-	     data->auth.auth_type == WLAN_AUTH_SAE) &&
-	    wpas_sme_ml_auth(wpa_s, data, ie_offset) < 0) {
-		wpa_dbg(wpa_s, MSG_DEBUG,
-			"MLD: Failed to parse ML Authentication frame");
-		wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid=" MACSTR
-			" reason=%d locally_generated=1",
-			MAC2STR(wpa_s->pending_bssid),
-			WLAN_REASON_DEAUTH_LEAVING);
-		wpas_connection_failed(wpa_s, wpa_s->pending_bssid, NULL);
-		wpa_supplicant_mark_disassoc(wpa_s);
-		return;
-	}
+	if (data->auth.auth_type == WLAN_AUTH_OPEN ||
+	    data->auth.auth_type == WLAN_AUTH_SAE)
+		wpas_sme_ml_auth(wpa_s, data, ie_offset);
 
 	sme_associate(wpa_s, ssid->mode, data->auth.peer,
 		      data->auth.auth_type);
@@ -2205,9 +2287,6 @@
 
 	os_memset(&params, 0, sizeof(params));
 
-	/* Save auth type, in case we need to retry after comeback timer. */
-	wpa_s->sme.assoc_auth_type = auth_type;
-
 #ifdef CONFIG_FILS
 	if (auth_type == WLAN_AUTH_FILS_SK ||
 	    auth_type == WLAN_AUTH_FILS_SK_PFS) {
@@ -2374,7 +2453,6 @@
 pfs_fail:
 #endif /* CONFIG_DPP2 */
 
-#ifndef CONFIG_NO_ROBUST_AV
 	wpa_s->mscs_setup_done = false;
 	if (wpa_bss_ext_capab(wpa_s->current_bss, WLAN_EXT_CAPAB_MSCS) &&
 	    wpa_s->robust_av.valid_config) {
@@ -2408,20 +2486,15 @@
 		wpabuf_free(mscs_ie);
 	}
 mscs_fail:
-#endif /* CONFIG_NO_ROBUST_AV */
 
 	if (ssid && ssid->multi_ap_backhaul_sta) {
 		size_t multi_ap_ie_len;
-		struct multi_ap_params multi_ap = { 0 };
-
-		multi_ap.capability = MULTI_AP_BACKHAUL_STA;
-		multi_ap.profile = ssid->multi_ap_profile;
 
 		multi_ap_ie_len = add_multi_ap_ie(
 			wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
 			sizeof(wpa_s->sme.assoc_req_ie) -
 			wpa_s->sme.assoc_req_ie_len,
-			&multi_ap);
+			MULTI_AP_BACKHAUL_STA);
 		if (multi_ap_ie_len == 0) {
 			wpa_printf(MSG_ERROR,
 				   "Multi-AP: Failed to build Multi-AP IE");
@@ -2601,53 +2674,27 @@
 		params.mld_params.mld_addr = wpa_s->ap_mld_addr;
 		params.mld_params.valid_links = wpa_s->valid_links;
 		params.mld_params.assoc_link_id = wpa_s->mlo_assoc_link_id;
-		for_each_link(wpa_s->valid_links, i) {
+		for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+			if (!(wpa_s->valid_links & BIT(i)))
+				continue;
+
 			params.mld_params.mld_links[i].bssid =
 				wpa_s->links[i].bssid;
 			params.mld_params.mld_links[i].freq =
 				wpa_s->links[i].freq;
-			params.mld_params.mld_links[i].disabled =
-				wpa_s->links[i].disabled;
 
-			wpa_printf(MSG_DEBUG,
-				   "MLD: id=%u, freq=%d, disabled=%u, " MACSTR,
+			wpa_printf(MSG_DEBUG, "MLD: id=%u, freq=%d, " MACSTR,
 				   i, wpa_s->links[i].freq,
-				   wpa_s->links[i].disabled,
 				   MAC2STR(wpa_s->links[i].bssid));
 		}
 	}
 
 	if (wpa_drv_associate(wpa_s, &params) < 0) {
-		unsigned int n_failed_links = 0;
-		int i;
-
 		wpa_msg(wpa_s, MSG_INFO, "SME: Association request to the "
 			"driver failed");
-
-		/* Prepare list of failed links for error report */
-		for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
-			if (!(wpa_s->valid_links & BIT(i)) ||
-			    wpa_s->mlo_assoc_link_id == i ||
-			    !params.mld_params.mld_links[i].error)
-				continue;
-
-			wpa_bssid_ignore_add(wpa_s, wpa_s->links[i].bssid);
-			n_failed_links++;
-		}
-
-		if (n_failed_links) {
-			/* Deauth and connect (possibly to the same AP MLD) */
-			wpa_drv_deauthenticate(wpa_s, wpa_s->ap_mld_addr,
-					       WLAN_REASON_DEAUTH_LEAVING);
-			wpas_connect_work_done(wpa_s);
-			wpa_supplicant_mark_disassoc(wpa_s);
-			wpas_request_connection(wpa_s);
-		} else {
-			wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
-					       NULL);
-			wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
-			os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
-		}
+		wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
+		wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
+		os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
 		return;
 	}
 
@@ -2687,26 +2734,20 @@
 }
 
 
-static void sme_deauth(struct wpa_supplicant *wpa_s, const u8 **link_bssids)
+static void sme_deauth(struct wpa_supplicant *wpa_s)
 {
 	int bssid_changed;
-	const u8 *bssid;
 
 	bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
 
-	if (wpa_s->valid_links)
-		bssid = wpa_s->ap_mld_addr;
-	else
-		bssid = wpa_s->pending_bssid;
-
-	if (wpa_drv_deauthenticate(wpa_s, bssid,
+	if (wpa_drv_deauthenticate(wpa_s, wpa_s->pending_bssid,
 				   WLAN_REASON_DEAUTH_LEAVING) < 0) {
 		wpa_msg(wpa_s, MSG_INFO, "SME: Deauth request to the driver "
 			"failed");
 	}
 	wpa_s->sme.prev_bssid_set = 0;
 
-	wpas_connection_failed(wpa_s, wpa_s->pending_bssid, link_bssids);
+	wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
 	wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
 	os_memset(wpa_s->bssid, 0, ETH_ALEN);
 	os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
@@ -2715,115 +2756,14 @@
 }
 
 
-static void sme_assoc_comeback_timer(void *eloop_ctx, void *timeout_ctx)
-{
-	struct wpa_supplicant *wpa_s = eloop_ctx;
-
-	if (!wpa_s->current_bss || !wpa_s->current_ssid) {
-		wpa_msg(wpa_s, MSG_DEBUG,
-			"SME: Comeback timeout expired; SSID/BSSID cleared; ignoring");
-		return;
-	}
-
-	wpa_msg(wpa_s, MSG_DEBUG,
-		"SME: Comeback timeout expired; retry associating with "
-		MACSTR "; mode=%d auth_type=%u",
-		MAC2STR(wpa_s->current_bss->bssid),
-		wpa_s->current_ssid->mode,
-		wpa_s->sme.assoc_auth_type);
-
-	/* Authentication state was completed already; just try association
-	 * again. */
-	sme_associate(wpa_s, wpa_s->current_ssid->mode,
-		      wpa_s->current_bss->bssid,
-		      wpa_s->sme.assoc_auth_type);
-}
-
-
-static bool sme_try_assoc_comeback(struct wpa_supplicant *wpa_s,
-				   union wpa_event_data *data)
-{
-	struct ieee802_11_elems elems;
-	u32 timeout_interval;
-	unsigned long comeback_usec;
-	u8 type = WLAN_TIMEOUT_ASSOC_COMEBACK;
-
-#ifdef CONFIG_TESTING_OPTIONS
-	if (wpa_s->test_assoc_comeback_type != -1)
-		type = wpa_s->test_assoc_comeback_type;
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	if (ieee802_11_parse_elems(data->assoc_reject.resp_ies,
-				   data->assoc_reject.resp_ies_len,
-				   &elems, 0) == ParseFailed) {
-		wpa_msg(wpa_s, MSG_INFO,
-			"SME: Temporary assoc reject: failed to parse (Re)Association Response frame elements");
-		return false;
-	}
-
-	if (!elems.timeout_int) {
-		wpa_msg(wpa_s, MSG_INFO,
-			"SME: Temporary assoc reject: missing timeout interval IE");
-		return false;
-	}
-
-	if (elems.timeout_int[0] != type) {
-		wpa_msg(wpa_s, MSG_INFO,
-			"SME: Temporary assoc reject: missing association comeback time");
-		return false;
-	}
-
-	timeout_interval = WPA_GET_LE32(&elems.timeout_int[1]);
-	if (timeout_interval > 60000) {
-		/* This is unprotected information and there is no point in
-		 * getting stuck waiting for very long duration based on it */
-		wpa_msg(wpa_s, MSG_DEBUG,
-			"SME: Ignore overly long association comeback interval: %u TUs",
-			timeout_interval);
-		return false;
-	}
-	wpa_msg(wpa_s, MSG_DEBUG, "SME: Association comeback interval: %u TUs",
-		timeout_interval);
-
-	comeback_usec = timeout_interval * 1024;
-	eloop_register_timeout(comeback_usec / 1000000, comeback_usec % 1000000,
-			       sme_assoc_comeback_timer, wpa_s, NULL);
-	return true;
-}
-
-
 void sme_event_assoc_reject(struct wpa_supplicant *wpa_s,
-			    union wpa_event_data *data,
-			    const u8 **link_bssids)
+			    union wpa_event_data *data)
 {
-	const u8 *bssid;
-
-	if (wpa_s->valid_links)
-		bssid = wpa_s->ap_mld_addr;
-	else
-		bssid = wpa_s->pending_bssid;
-
 	wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association with " MACSTR " failed: "
 		"status code %d", MAC2STR(wpa_s->pending_bssid),
 		data->assoc_reject.status_code);
 
 	eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
-	eloop_cancel_timeout(sme_assoc_comeback_timer, wpa_s, NULL);
-
-	/* Authentication phase has been completed at this point. Check whether
-	 * the AP rejected association temporarily due to still holding a
-	 * security associationis with us (MFP). If so, we must wait for the
-	 * AP's association comeback timeout period before associating again. */
-	if (data->assoc_reject.status_code ==
-	    WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) {
-		wpa_msg(wpa_s, MSG_DEBUG,
-			"SME: Temporary association reject from BSS " MACSTR,
-			MAC2STR(bssid));
-		if (sme_try_assoc_comeback(wpa_s, data)) {
-			/* Break out early; comeback error is not a failure. */
-			return;
-		}
-	}
 
 #ifdef CONFIG_SAE
 	if (wpa_s->sme.sae_pmksa_caching && wpa_s->current_ssid &&
@@ -2836,7 +2776,7 @@
 			struct wpa_bss *bss = wpa_s->current_bss;
 			struct wpa_ssid *ssid = wpa_s->current_ssid;
 
-			wpa_drv_deauthenticate(wpa_s, bssid,
+			wpa_drv_deauthenticate(wpa_s, wpa_s->pending_bssid,
 					       WLAN_REASON_DEAUTH_LEAVING);
 			wpas_connect_work_done(wpa_s);
 			wpa_supplicant_mark_disassoc(wpa_s);
@@ -2881,7 +2821,7 @@
 	 * benefit from using the previous authentication, so this could be
 	 * optimized in the future.
 	 */
-	sme_deauth(wpa_s, link_bssids);
+	sme_deauth(wpa_s);
 }
 
 
@@ -2889,7 +2829,7 @@
 			      union wpa_event_data *data)
 {
 	wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication timed out");
-	wpas_connection_failed(wpa_s, wpa_s->pending_bssid, NULL);
+	wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
 	wpa_supplicant_mark_disassoc(wpa_s);
 }
 
@@ -2898,7 +2838,7 @@
 			       union wpa_event_data *data)
 {
 	wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association timed out");
-	wpas_connection_failed(wpa_s, wpa_s->pending_bssid, NULL);
+	wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
 	wpa_supplicant_mark_disassoc(wpa_s);
 }
 
@@ -2927,7 +2867,7 @@
 	struct wpa_supplicant *wpa_s = eloop_ctx;
 	if (wpa_s->wpa_state == WPA_AUTHENTICATING) {
 		wpa_msg(wpa_s, MSG_DEBUG, "SME: Authentication timeout");
-		sme_deauth(wpa_s, NULL);
+		sme_deauth(wpa_s);
 	}
 }
 
@@ -2937,7 +2877,7 @@
 	struct wpa_supplicant *wpa_s = eloop_ctx;
 	if (wpa_s->wpa_state == WPA_ASSOCIATING) {
 		wpa_msg(wpa_s, MSG_DEBUG, "SME: Association timeout");
-		sme_deauth(wpa_s, NULL);
+		sme_deauth(wpa_s);
 	}
 }
 
@@ -2945,15 +2885,35 @@
 void sme_state_changed(struct wpa_supplicant *wpa_s)
 {
 	/* Make sure timers are cleaned up appropriately. */
-	if (wpa_s->wpa_state != WPA_ASSOCIATING) {
+	if (wpa_s->wpa_state != WPA_ASSOCIATING)
 		eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
-		eloop_cancel_timeout(sme_assoc_comeback_timer, wpa_s, NULL);
-	}
 	if (wpa_s->wpa_state != WPA_AUTHENTICATING)
 		eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
 }
 
 
+void sme_disassoc_while_authenticating(struct wpa_supplicant *wpa_s,
+				       const u8 *prev_pending_bssid)
+{
+	/*
+	 * mac80211-workaround to force deauth on failed auth cmd,
+	 * requires us to remain in authenticating state to allow the
+	 * second authentication attempt to be continued properly.
+	 */
+	wpa_dbg(wpa_s, MSG_DEBUG, "SME: Allow pending authentication "
+		"to proceed after disconnection event");
+	wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING);
+	os_memcpy(wpa_s->pending_bssid, prev_pending_bssid, ETH_ALEN);
+
+	/*
+	 * Re-arm authentication timer in case auth fails for whatever reason.
+	 */
+	eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
+	eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s,
+			       NULL);
+}
+
+
 void sme_clear_on_disassoc(struct wpa_supplicant *wpa_s)
 {
 	wpa_s->sme.prev_bssid_set = 0;
@@ -2981,7 +2941,6 @@
 	eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
 	eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
 	eloop_cancel_timeout(sme_obss_scan_timeout, wpa_s, NULL);
-	eloop_cancel_timeout(sme_assoc_comeback_timer, wpa_s, NULL);
 }
 
 
@@ -3415,7 +3374,7 @@
 	ssid = wpa_s->current_ssid;
 	if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION)
 		return;
-	if (!ether_addr_equal(sa, wpa_s->bssid))
+	if (os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0)
 		return;
 	if (reason_code != WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA &&
 	    reason_code != WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA)
@@ -3520,7 +3479,7 @@
 	wpa_dbg(wpa_s, MSG_DEBUG, "SME: Received SA Query response from "
 		MACSTR " (trans_id %02x%02x)", MAC2STR(sa), data[1], data[2]);
 
-	if (!ether_addr_equal(sa, wpa_s->bssid))
+	if (os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0)
 		return;
 
 	for (i = 0; i < wpa_s->sme.sa_query_count; i++) {
diff --git a/wpa_supplicant/sme.h b/wpa_supplicant/sme.h
index f8fd06b..c797d2e 100644
--- a/wpa_supplicant/sme.h
+++ b/wpa_supplicant/sme.h
@@ -19,8 +19,7 @@
 int sme_update_ft_ies(struct wpa_supplicant *wpa_s, const u8 *md,
 		      const u8 *ies, size_t ies_len);
 void sme_event_assoc_reject(struct wpa_supplicant *wpa_s,
-			    union wpa_event_data *data,
-			    const u8 **link_bssids);
+			    union wpa_event_data *data);
 void sme_event_auth_timed_out(struct wpa_supplicant *wpa_s,
 			      union wpa_event_data *data);
 void sme_event_assoc_timed_out(struct wpa_supplicant *wpa_s,
@@ -33,6 +32,8 @@
 void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *da, const u8 *sa,
 		     const u8 *data, size_t len);
 void sme_state_changed(struct wpa_supplicant *wpa_s);
+void sme_disassoc_while_authenticating(struct wpa_supplicant *wpa_s,
+				       const u8 *prev_pending_bssid);
 void sme_clear_on_disassoc(struct wpa_supplicant *wpa_s);
 void sme_deinit(struct wpa_supplicant *wpa_s);
 
@@ -64,8 +65,7 @@
 
 
 static inline void sme_event_assoc_reject(struct wpa_supplicant *wpa_s,
-					  union wpa_event_data *data,
-					  const u8 **link_bssids)
+					  union wpa_event_data *data)
 {
 }
 
@@ -98,6 +98,12 @@
 {
 }
 
+static inline void
+sme_disassoc_while_authenticating(struct wpa_supplicant *wpa_s,
+				  const u8 *prev_pending_bssid)
+{
+}
+
 static inline void sme_clear_on_disassoc(struct wpa_supplicant *wpa_s)
 {
 }
diff --git a/wpa_supplicant/wmm_ac.c b/wpa_supplicant/wmm_ac.c
index 37e2ed4..d0fdd55 100644
--- a/wpa_supplicant/wmm_ac.c
+++ b/wpa_supplicant/wmm_ac.c
@@ -678,7 +678,7 @@
 	}
 
 	/* make sure the params are the same */
-	if (!ether_addr_equal(req->address, sa) ||
+	if (os_memcmp(req->address, sa, ETH_ALEN) != 0 ||
 	    tsid != wmm_ac_get_tsid(&req->tspec) ||
 	    up != wmm_ac_get_user_priority(&req->tspec) ||
 	    dir != wmm_ac_get_direction(&req->tspec)) {
@@ -755,13 +755,13 @@
 	}
 
 	/* WMM AC action frame */
-	if (!ether_addr_equal(da, wpa_s->own_addr)) {
+	if (os_memcmp(da, wpa_s->own_addr, ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG, "WMM AC: frame destination addr="MACSTR
 			   " is other than ours, ignoring frame", MAC2STR(da));
 		return;
 	}
 
-	if (!ether_addr_equal(sa, wpa_s->bssid)) {
+	if (os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG, "WMM AC: ignore frame with sa " MACSTR
 			   " different other than our bssid", MAC2STR(da));
 		return;
diff --git a/wpa_supplicant/wnm_sta.c b/wpa_supplicant/wnm_sta.c
index ea79ae6..56183ff 100644
--- a/wpa_supplicant/wnm_sta.c
+++ b/wpa_supplicant/wnm_sta.c
@@ -418,7 +418,7 @@
 }
 
 
-void wnm_btm_reset(struct wpa_supplicant *wpa_s)
+void wnm_deallocate_memory(struct wpa_supplicant *wpa_s)
 {
 	int i;
 
@@ -431,17 +431,8 @@
 	os_free(wpa_s->wnm_neighbor_report_elements);
 	wpa_s->wnm_neighbor_report_elements = NULL;
 
-	wpa_s->wnm_cand_valid_until.sec = 0;
-	wpa_s->wnm_cand_valid_until.usec = 0;
-
-	wpa_s->wnm_mode = 0;
-	wpa_s->wnm_dialog_token = 0;
-	wpa_s->wnm_reply = 0;
-
-#ifdef CONFIG_MBO
-	wpa_s->wnm_mbo_trans_reason_present = 0;
-	wpa_s->wnm_mbo_transition_reason = 0;
-#endif /* CONFIG_MBO */
+	wpabuf_free(wpa_s->coloc_intf_elems);
+	wpa_s->coloc_intf_elems = NULL;
 }
 
 
@@ -695,8 +686,9 @@
 	if (reason) {
 		for (i = 0; i < info->num; i++) {
 			if (first_candidate_bssid &&
-			    ether_addr_equal(first_candidate_bssid,
-					     info->candidates[i].bssid)) {
+			    os_memcmp(first_candidate_bssid,
+				      info->candidates[i].bssid, ETH_ALEN) == 0)
+			{
 				*reason = info->candidates[i].reject_reason;
 				break;
 			}
@@ -790,11 +782,22 @@
 			}
 		}
 
-		/*
-		 * TODO: Could consider allowing transition to another ESS if
-		 * PMF was enabled for the association.
-		 */
-		if (!wpa_scan_res_match(wpa_s, 0, target, wpa_s->current_ssid,
+		if (bss->ssid_len != target->ssid_len ||
+		    os_memcmp(bss->ssid, target->ssid, bss->ssid_len) != 0) {
+			/*
+			 * TODO: Could consider allowing transition to another
+			 * ESS if PMF was enabled for the association.
+			 */
+			wpa_printf(MSG_DEBUG, "Candidate BSS " MACSTR
+				   " (pref %d) in different ESS",
+				   MAC2STR(nei->bssid),
+				   nei->preference_present ? nei->preference :
+				   -1);
+			continue;
+		}
+
+		if (wpa_s->current_ssid &&
+		    !wpa_scan_res_match(wpa_s, 0, target, wpa_s->current_ssid,
 					1, 0)) {
 			wpa_printf(MSG_DEBUG, "Candidate BSS " MACSTR
 				   " (pref %d) does not match the current network profile",
@@ -804,6 +807,14 @@
 			continue;
 		}
 
+		if (wpa_is_bss_tmp_disallowed(wpa_s, target)) {
+			wpa_printf(MSG_DEBUG,
+				   "MBO: Candidate BSS " MACSTR
+				   " retry delay is not over yet",
+				   MAC2STR(nei->bssid));
+			continue;
+		}
+
 		if (target->level < bss->level && target->level < -80) {
 			wpa_printf(MSG_DEBUG, "Candidate BSS " MACSTR
 				   " (pref %d) does not have sufficient signal level (%d)",
@@ -1035,8 +1046,8 @@
 
 #define BTM_RESP_MIN_SIZE	5 + ETH_ALEN
 
-static int wnm_send_bss_transition_mgmt_resp(
-	struct wpa_supplicant *wpa_s,
+static void wnm_send_bss_transition_mgmt_resp(
+	struct wpa_supplicant *wpa_s, u8 dialog_token,
 	enum bss_trans_mgmt_status_code status,
 	enum mbo_transition_reject_reason reason,
 	u8 delay, const u8 *target_bssid)
@@ -1044,24 +1055,21 @@
 	struct wpabuf *buf;
 	int res;
 
-	wpa_s->wnm_reply = 0;
-
 	wpa_printf(MSG_DEBUG,
 		   "WNM: Send BSS Transition Management Response to " MACSTR
 		   " dialog_token=%u status=%u reason=%u delay=%d",
-		   MAC2STR(wpa_s->bssid), wpa_s->wnm_dialog_token, status,
-		   reason, delay);
+		   MAC2STR(wpa_s->bssid), dialog_token, status, reason, delay);
 	if (!wpa_s->current_bss) {
 		wpa_printf(MSG_DEBUG,
 			   "WNM: Current BSS not known - drop response");
-		return -1;
+		return;
 	}
 
 	buf = wpabuf_alloc(BTM_RESP_MIN_SIZE);
 	if (!buf) {
 		wpa_printf(MSG_DEBUG,
 			   "WNM: Failed to allocate memory for BTM response");
-		return -1;
+		return;
 	}
 
 	wpa_s->bss_tm_status = status;
@@ -1069,7 +1077,7 @@
 
 	wpabuf_put_u8(buf, WLAN_ACTION_WNM);
 	wpabuf_put_u8(buf, WNM_BSS_TRANS_MGMT_RESP);
-	wpabuf_put_u8(buf, wpa_s->wnm_dialog_token);
+	wpabuf_put_u8(buf, dialog_token);
 	wpabuf_put_u8(buf, status);
 	wpabuf_put_u8(buf, delay);
 	if (target_bssid) {
@@ -1083,7 +1091,7 @@
 		wpabuf_put_data(buf, "\0\0\0\0\0\0", ETH_ALEN);
 	}
 
-	if (status == WNM_BSS_TM_ACCEPT && target_bssid)
+	if (status == WNM_BSS_TM_ACCEPT)
 		wnm_add_cand_list(wpa_s, &buf);
 
 #ifdef CONFIG_MBO
@@ -1099,7 +1107,7 @@
 				wpabuf_free(buf);
 				wpa_printf(MSG_DEBUG,
 					   "WNM: Failed to allocate memory for MBO IE");
-				return -1;
+				return;
 			}
 
 			wpabuf_put_data(buf, mbo, ret);
@@ -1116,8 +1124,6 @@
 	}
 
 	wpabuf_free(buf);
-
-	return res;
 }
 
 
@@ -1135,24 +1141,19 @@
 
 	/* Send the BSS Management Response - Accept */
 	if (wpa_s->wnm_reply) {
-		wpa_s->wnm_target_bss = bss;
+		wpa_s->wnm_reply = 0;
 		wpa_printf(MSG_DEBUG,
 			   "WNM: Sending successful BSS Transition Management Response");
-
-		/* This function will be called again from the TX handler to
-		 * start the actual reassociation after this response has been
-		 * delivered to the current AP. */
-		if (wnm_send_bss_transition_mgmt_resp(
-			    wpa_s, WNM_BSS_TM_ACCEPT,
-			    MBO_TRANSITION_REJECT_REASON_UNSPECIFIED, 0,
-			    bss->bssid) >= 0)
-			return;
+		wnm_send_bss_transition_mgmt_resp(
+			wpa_s, wpa_s->wnm_dialog_token, WNM_BSS_TM_ACCEPT,
+			MBO_TRANSITION_REJECT_REASON_UNSPECIFIED, 0,
+			bss->bssid);
 	}
 
 	if (bss == wpa_s->current_bss) {
 		wpa_printf(MSG_DEBUG,
 			   "WNM: Already associated with the preferred candidate");
-		wnm_btm_reset(wpa_s);
+		wnm_deallocate_memory(wpa_s);
 		return;
 	}
 
@@ -1168,10 +1169,11 @@
 	 */
 	if (!already_connecting && radio_work_pending(wpa_s, "sme-connect"))
 		wpa_s->bss_trans_mgmt_in_progress = true;
+	wnm_deallocate_memory(wpa_s);
 }
 
 
-int wnm_scan_process(struct wpa_supplicant *wpa_s, bool pre_scan_check)
+int wnm_scan_process(struct wpa_supplicant *wpa_s, int reply_on_fail)
 {
 	struct wpa_bss *bss;
 	struct wpa_ssid *ssid = wpa_s->current_ssid;
@@ -1179,51 +1181,27 @@
 	enum mbo_transition_reject_reason reason =
 		MBO_TRANSITION_REJECT_REASON_UNSPECIFIED;
 
-	if (!wpa_s->wnm_dialog_token)
+	if (!wpa_s->wnm_neighbor_report_elements)
 		return 0;
 
 	wpa_dbg(wpa_s, MSG_DEBUG,
 		"WNM: Process scan results for BSS Transition Management");
-	if (!pre_scan_check &&
-	    os_reltime_initialized(&wpa_s->wnm_cand_valid_until) &&
-	    os_reltime_before(&wpa_s->wnm_cand_valid_until,
+	if (os_reltime_before(&wpa_s->wnm_cand_valid_until,
 			      &wpa_s->scan_trigger_time)) {
 		wpa_printf(MSG_DEBUG, "WNM: Previously stored BSS transition candidate list is not valid anymore - drop it");
-		goto send_bss_resp_fail;
+		wnm_deallocate_memory(wpa_s);
+		return 0;
+	}
+
+	if (!wpa_s->current_bss ||
+	    os_memcmp(wpa_s->wnm_cand_from_bss, wpa_s->current_bss->bssid,
+		      ETH_ALEN) != 0) {
+		wpa_printf(MSG_DEBUG, "WNM: Stored BSS transition candidate list not from the current BSS - ignore it");
+		return 0;
 	}
 
 	/* Compare the Neighbor Report and scan results */
 	bss = compare_scan_neighbor_results(wpa_s, 0, &reason);
-
-	/*
-	 * If this is a pre-scan check, returning 0 will trigger a scan and
-	 * another call. In that case, reject "bad" candidates in the hope of
-	 * finding a better candidate after scanning.
-	 *
-	 * Use a simple heuristic to check whether the selection is reasonable
-	 * or a scan is a good idea. For that, we need to have found a
-	 * candidate BSS (which might be the current one), it is up-to-date,
-	 * and we don't want to immediately roam back again.
-	 */
-	if (pre_scan_check) {
-		struct os_reltime age;
-
-		if (!bss)
-			return 0;
-
-		os_reltime_age(&bss->last_update, &age);
-		if (age.sec >= 10)
-			return 0;
-
-#ifndef CONFIG_NO_ROAMING
-		if (wpa_s->current_bss && bss != wpa_s->current_bss &&
-		    wpa_supplicant_need_to_roam_within_ess(wpa_s,
-							   wpa_s->current_bss,
-							   bss))
-			return 0;
-#endif /* CONFIG_NO_ROAMING */
-	}
-
 	if (!bss) {
 		wpa_printf(MSG_DEBUG, "WNM: No BSS transition candidate match found");
 		status = WNM_BSS_TM_REJECT_NO_SUITABLE_CANDIDATES;
@@ -1235,13 +1213,18 @@
 	return 1;
 
 send_bss_resp_fail:
+	if (!reply_on_fail)
+		return 0;
+
 	/* Send reject response for all the failures */
 
-	if (wpa_s->wnm_reply)
-		wnm_send_bss_transition_mgmt_resp(wpa_s, status, reason,
-						  0, NULL);
-
-	wnm_btm_reset(wpa_s);
+	if (wpa_s->wnm_reply) {
+		wpa_s->wnm_reply = 0;
+		wnm_send_bss_transition_mgmt_resp(wpa_s,
+						  wpa_s->wnm_dialog_token,
+						  status, reason, 0, NULL);
+	}
+	wnm_deallocate_memory(wpa_s);
 
 	return 0;
 }
@@ -1348,10 +1331,6 @@
 		struct neighbor_report *nei;
 
 		nei = &wpa_s->wnm_neighbor_report_elements[i];
-
-		if (nei->preference_present && nei->preference == 0)
-			continue;
-
 		if (nei->freq <= 0) {
 			wpa_printf(MSG_DEBUG,
 				   "WNM: Unknown neighbor operating frequency for "
@@ -1376,6 +1355,79 @@
 }
 
 
+static int wnm_fetch_scan_results(struct wpa_supplicant *wpa_s)
+{
+	struct wpa_scan_results *scan_res;
+	struct wpa_bss *bss;
+	struct wpa_ssid *ssid = wpa_s->current_ssid;
+	u8 i, found = 0;
+	size_t j;
+
+	wpa_dbg(wpa_s, MSG_DEBUG,
+		"WNM: Fetch current scan results from the driver for checking transition candidates");
+	scan_res = wpa_drv_get_scan_results2(wpa_s);
+	if (!scan_res) {
+		wpa_dbg(wpa_s, MSG_DEBUG, "WNM: Failed to get scan results");
+		return 0;
+	}
+
+	if (scan_res->fetch_time.sec == 0)
+		os_get_reltime(&scan_res->fetch_time);
+
+	filter_scan_res(wpa_s, scan_res);
+
+	for (i = 0; i < wpa_s->wnm_num_neighbor_report; i++) {
+		struct neighbor_report *nei;
+
+		nei = &wpa_s->wnm_neighbor_report_elements[i];
+		if (nei->preference_present && nei->preference == 0)
+			continue;
+
+		for (j = 0; j < scan_res->num; j++) {
+			struct wpa_scan_res *res;
+			const u8 *ssid_ie;
+
+			res = scan_res->res[j];
+			if (os_memcmp(nei->bssid, res->bssid, ETH_ALEN) != 0 ||
+			    res->age > WNM_SCAN_RESULT_AGE * 1000)
+				continue;
+			bss = wpa_s->current_bss;
+			ssid_ie = wpa_scan_get_ie(res, WLAN_EID_SSID);
+			if (bss && ssid_ie && ssid_ie[1] &&
+			    (bss->ssid_len != ssid_ie[1] ||
+			     os_memcmp(bss->ssid, ssid_ie + 2,
+				       bss->ssid_len) != 0))
+				continue; /* Skip entries for other ESSs */
+
+			/* Potential candidate found */
+			found = 1;
+			scan_snr(res);
+			scan_est_throughput(wpa_s, res);
+			wpa_bss_update_scan_res(wpa_s, res,
+						&scan_res->fetch_time);
+		}
+	}
+
+	wpa_scan_results_free(scan_res);
+	if (!found) {
+		wpa_dbg(wpa_s, MSG_DEBUG,
+			"WNM: No transition candidate matches existing scan results");
+		return 0;
+	}
+
+	bss = compare_scan_neighbor_results(wpa_s, WNM_SCAN_RESULT_AGE, NULL);
+	if (!bss) {
+		wpa_dbg(wpa_s, MSG_DEBUG,
+			"WNM: Comparison of scan results against transition candidates did not find matches");
+		return 0;
+	}
+
+	/* Associate to the network */
+	wnm_bss_tm_connect(wpa_s, bss, ssid, 0);
+	return 1;
+}
+
+
 static void ieee802_11_rx_bss_trans_mgmt_req(struct wpa_supplicant *wpa_s,
 					     const u8 *pos, const u8 *end,
 					     int reply)
@@ -1385,7 +1437,6 @@
 #ifdef CONFIG_MBO
 	const u8 *vendor;
 #endif /* CONFIG_MBO */
-	bool disassoc_imminent;
 
 	if (wpa_s->disable_mbo_oce || wpa_s->conf->disable_btm)
 		return;
@@ -1394,6 +1445,8 @@
 		return;
 
 #ifdef CONFIG_MBO
+	wpa_s->wnm_mbo_trans_reason_present = 0;
+	wpa_s->wnm_mbo_transition_reason = 0;
 	wpa_s->wnm_mbo_cell_pref_present = 0;
 	wpa_s->wnm_mbo_cell_preference = 0;
 	wpa_s->wnm_mbo_assoc_retry_delay_present = 0;
@@ -1405,12 +1458,9 @@
 	else
 		beacon_int = 100; /* best guess */
 
-	wnm_btm_reset(wpa_s);
-
 	wpa_s->wnm_dialog_token = pos[0];
 	wpa_s->wnm_mode = pos[1];
 	wpa_s->wnm_dissoc_timer = WPA_GET_LE16(pos + 2);
-	wpa_s->wnm_link_removal = false;
 	valid_int = pos[4];
 	wpa_s->wnm_reply = reply;
 
@@ -1426,7 +1476,8 @@
 			   "WNM: Testing - reject BSS Transition Management Request: reject_btm_req_reason=%d",
 			   wpa_s->reject_btm_req_reason);
 		wnm_send_bss_transition_mgmt_resp(
-			wpa_s, wpa_s->reject_btm_req_reason,
+			wpa_s, wpa_s->wnm_dialog_token,
+			wpa_s->reject_btm_req_reason,
 			MBO_TRANSITION_REJECT_REASON_UNSPECIFIED, 0, NULL);
 		return;
 	}
@@ -1481,45 +1532,7 @@
 		return;
 	}
 
-	disassoc_imminent = wpa_s->wnm_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
-
-	/*
-	 * Based on IEEE P802.11be/D5.0, when a station is a non-AP MLD with
-	 * more than one affiliated link, the Link Removal Imminent field is
-	 * set to 1, and the BSS Termination Included field is set to 1, only
-	 * one of the links is removed and the other links remain associated.
-	 * Ignore the Disassociation Imminent field in such a case.
-	 *
-	 * TODO: We should check if the AP has more than one link.
-	 * TODO: We should pass the RX link and use that
-	 */
-	if (disassoc_imminent && wpa_s->valid_links &&
-	    (wpa_s->wnm_mode & WNM_BSS_TM_REQ_LINK_REMOVAL_IMMINENT) &&
-	    (wpa_s->wnm_mode & WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED)) {
-		/* If we still have a link, then just accept the request */
-		if (wpa_s->valid_links & (wpa_s->valid_links - 1)) {
-			wpa_printf(MSG_INFO,
-				   "WNM: BTM request for a single MLO link - ignore disassociation imminent since other links remain associated");
-			disassoc_imminent = false;
-
-			wnm_send_bss_transition_mgmt_resp(
-				wpa_s, WNM_BSS_TM_ACCEPT, 0, 0, NULL);
-
-			return;
-		}
-
-		/* The last link is being removed (which must be the assoc link)
-		 */
-		wpa_s->wnm_link_removal = true;
-		os_memcpy(wpa_s->wnm_dissoc_addr,
-			  wpa_s->links[wpa_s->mlo_assoc_link_id].bssid,
-			  ETH_ALEN);
-	} else {
-		os_memcpy(wpa_s->wnm_dissoc_addr, wpa_s->valid_links ?
-			  wpa_s->ap_mld_addr : wpa_s->bssid, ETH_ALEN);
-	}
-
-	if (disassoc_imminent) {
+	if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT) {
 		wpa_msg(wpa_s, MSG_INFO, "WNM: Disassociation Imminent - "
 			"Disassociation Timer %u", wpa_s->wnm_dissoc_timer);
 		if (wpa_s->wnm_dissoc_timer && !wpa_s->scanning &&
@@ -1533,6 +1546,7 @@
 		unsigned int valid_ms;
 
 		wpa_msg(wpa_s, MSG_INFO, "WNM: Preferred List Available");
+		wnm_deallocate_memory(wpa_s);
 		wpa_s->wnm_neighbor_report_elements = os_calloc(
 			WNM_MAX_NEIGHBOR_REPORT,
 			sizeof(struct neighbor_report));
@@ -1558,7 +1572,8 @@
 				wnm_parse_neighbor_report(wpa_s, pos, len, rep);
 				if ((wpa_s->wnm_mode &
 				     WNM_BSS_TM_REQ_DISASSOC_IMMINENT) &&
-				    ether_addr_equal(rep->bssid, wpa_s->bssid))
+				    os_memcmp(rep->bssid, wpa_s->bssid,
+					      ETH_ALEN) == 0)
 					rep->disassoc_imminent = 1;
 
 				wpa_s->wnm_num_neighbor_report++;
@@ -1580,7 +1595,8 @@
 			wpa_printf(MSG_DEBUG,
 				   "WNM: Candidate list included bit is set, but no candidates found");
 			wnm_send_bss_transition_mgmt_resp(
-				wpa_s, WNM_BSS_TM_REJECT_NO_SUITABLE_CANDIDATES,
+				wpa_s, wpa_s->wnm_dialog_token,
+				WNM_BSS_TM_REJECT_NO_SUITABLE_CANDIDATES,
 				MBO_TRANSITION_REJECT_REASON_UNSPECIFIED, 0,
 				NULL);
 			return;
@@ -1590,7 +1606,8 @@
 			wpa_printf(MSG_DEBUG,
 				   "WNM: Configuration prevents roaming (BSSID set)");
 			wnm_send_bss_transition_mgmt_resp(
-				wpa_s, WNM_BSS_TM_REJECT_NO_SUITABLE_CANDIDATES,
+				wpa_s, wpa_s->wnm_dialog_token,
+				WNM_BSS_TM_REJECT_NO_SUITABLE_CANDIDATES,
 				MBO_TRANSITION_REJECT_REASON_UNSPECIFIED, 0,
 				NULL);
 			return;
@@ -1607,21 +1624,35 @@
 		wpa_s->wnm_cand_valid_until.sec +=
 			wpa_s->wnm_cand_valid_until.usec / 1000000;
 		wpa_s->wnm_cand_valid_until.usec %= 1000000;
+		os_memcpy(wpa_s->wnm_cand_from_bss, wpa_s->bssid, ETH_ALEN);
 
 		/*
-		* Try fetching the latest scan results from the kernel.
-		* This can help in finding more up-to-date information should
-		* the driver have done some internal scanning operations after
-		* the last scan result update in wpa_supplicant.
-		*
-		* It is not a new scan, this does not update the last_scan
-		* timestamp nor will it expire old BSSs.
-		*/
-		wpa_supplicant_update_scan_results(wpa_s, NULL);
-		if (wnm_scan_process(wpa_s, true) > 0)
+		 * Fetch the latest scan results from the kernel and check for
+		 * candidates based on those results first. This can help in
+		 * finding more up-to-date information should the driver has
+		 * done some internal scanning operations after the last scan
+		 * result update in wpa_supplicant.
+		 */
+		if (wnm_fetch_scan_results(wpa_s) > 0)
 			return;
-		wpa_printf(MSG_DEBUG,
-			   "WNM: No valid match in previous scan results - try a new scan");
+
+		/*
+		 * Try to use previously received scan results, if they are
+		 * recent enough to use for a connection.
+		 */
+		if (wpa_s->last_scan_res_used > 0) {
+			struct os_reltime now;
+
+			os_get_reltime(&now);
+			if (!os_reltime_expired(&now, &wpa_s->last_scan, 10)) {
+				wpa_printf(MSG_DEBUG,
+					   "WNM: Try to use recent scan results");
+				if (wnm_scan_process(wpa_s, 0) > 0)
+					return;
+				wpa_printf(MSG_DEBUG,
+					   "WNM: No match in previous scan results - try a new scan");
+			}
+		}
 
 		wnm_set_scan_freqs(wpa_s);
 		if (wpa_s->wnm_num_neighbor_report == 1) {
@@ -1635,54 +1666,19 @@
 		wpa_supplicant_req_scan(wpa_s, 0, 0);
 	} else if (reply) {
 		enum bss_trans_mgmt_status_code status;
-
-		if ((wpa_s->wnm_mode & WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT) ||
-		    wpa_s->wnm_link_removal)
+		if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT)
 			status = WNM_BSS_TM_ACCEPT;
 		else {
 			wpa_msg(wpa_s, MSG_INFO, "WNM: BSS Transition Management Request did not include candidates");
 			status = WNM_BSS_TM_REJECT_UNSPECIFIED;
 		}
 		wnm_send_bss_transition_mgmt_resp(
-			wpa_s, status,
+			wpa_s, wpa_s->wnm_dialog_token, status,
 			MBO_TRANSITION_REJECT_REASON_UNSPECIFIED, 0, NULL);
 	}
 }
 
 
-int wnm_btm_resp_tx_status(struct wpa_supplicant *wpa_s, const u8 *data,
-			   size_t data_len)
-{
-	const struct ieee80211_mgmt *frame =
-		(const struct ieee80211_mgmt *) data;
-
-	if (data_len <
-	    IEEE80211_HDRLEN + sizeof(frame->u.action.u.bss_tm_resp) ||
-	    frame->u.action.category != WLAN_ACTION_WNM ||
-	    frame->u.action.u.bss_tm_resp.action != WNM_BSS_TRANS_MGMT_RESP ||
-	    frame->u.action.u.bss_tm_resp.status_code != WNM_BSS_TM_ACCEPT)
-		return -1;
-
-	/*
-	 * If disassoc imminent bit was set in the request, the response may
-	 * indicate accept even if no candidate was found, so bail out here.
-	 */
-	if (!wpa_s->wnm_target_bss) {
-		wpa_printf(MSG_DEBUG, "WNM: Target BSS is not set");
-		return 0;
-	}
-
-	if (!wpa_s->current_ssid)
-		return 0;
-
-	wnm_bss_tm_connect(wpa_s, wpa_s->wnm_target_bss, wpa_s->current_ssid,
-			   0);
-
-	wpa_s->wnm_target_bss = NULL;
-	return 0;
-}
-
-
 #define BTM_QUERY_MIN_SIZE	4
 
 int wnm_send_bss_transition_mgmt_query(struct wpa_supplicant *wpa_s,
@@ -1894,9 +1890,7 @@
 		    pos, end - pos);
 
 	if (wpa_s->wpa_state != WPA_COMPLETED ||
-	    (!ether_addr_equal(sa, wpa_s->bssid) &&
-	     (!wpa_s->valid_links ||
-	      !ether_addr_equal(sa, wpa_s->ap_mld_addr)))) {
+	    os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0) {
 		wpa_dbg(wpa_s, MSG_DEBUG, "WNM: WNM-Notification frame not "
 			"from our AP - ignore it");
 		return;
@@ -1940,9 +1934,7 @@
 		return; /* only nonzero values are used for request */
 
 	if (wpa_s->wpa_state != WPA_COMPLETED ||
-	    (!ether_addr_equal(sa, wpa_s->bssid) &&
-	     (!wpa_s->valid_links ||
-	      !ether_addr_equal(sa, wpa_s->ap_mld_addr)))) {
+	    os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0) {
 		wpa_dbg(wpa_s, MSG_DEBUG,
 			"WNM: Collocated Interference Request frame not from current AP - ignore it");
 		return;
@@ -1972,9 +1964,7 @@
 	wpa_printf(MSG_DEBUG, "WNM: RX action %u from " MACSTR,
 		   act, MAC2STR(mgmt->sa));
 	if (wpa_s->wpa_state < WPA_ASSOCIATED ||
-	    (!ether_addr_equal(mgmt->sa, wpa_s->bssid) &&
-	     (!wpa_s->valid_links ||
-	      !ether_addr_equal(mgmt->sa, wpa_s->ap_mld_addr)))) {
+	    os_memcmp(mgmt->sa, wpa_s->bssid, ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG, "WNM: Ignore unexpected WNM Action "
 			   "frame");
 		return;
@@ -2035,14 +2025,14 @@
 void wnm_set_coloc_intf_elems(struct wpa_supplicant *wpa_s,
 			      struct wpabuf *elems)
 {
+	wpabuf_free(wpa_s->coloc_intf_elems);
 	if (elems && wpabuf_len(elems) == 0) {
 		wpabuf_free(elems);
 		elems = NULL;
 	}
+	wpa_s->coloc_intf_elems = elems;
 
-	/* NOTE: The elements are not stored as they are only send out once */
-
-	if (wpa_s->conf->coloc_intf_reporting && elems &&
+	if (wpa_s->conf->coloc_intf_reporting && wpa_s->coloc_intf_elems &&
 	    wpa_s->coloc_intf_dialog_token &&
 	    (wpa_s->coloc_intf_auto_report == 1 ||
 	     wpa_s->coloc_intf_auto_report == 3)) {
@@ -2051,38 +2041,15 @@
 		 */
 		wnm_send_coloc_intf_report(wpa_s,
 					   wpa_s->coloc_intf_dialog_token,
-					   elems);
+					   wpa_s->coloc_intf_elems);
 	}
-
-	wpabuf_free(elems);
 }
 
 
 void wnm_clear_coloc_intf_reporting(struct wpa_supplicant *wpa_s)
 {
+#ifdef CONFIG_WNM
 	wpa_s->coloc_intf_dialog_token = 0;
 	wpa_s->coloc_intf_auto_report = 0;
-}
-
-
-bool wnm_is_bss_excluded(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
-{
-	if (!(wpa_s->wnm_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT))
-		return false;
-
-	/*
-	 * In case disassociation imminent is set, do no try to use a BSS to
-	 * which we are connected.
-	 */
-	if (wpa_s->wnm_link_removal ||
-	    !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO) ||
-	    is_zero_ether_addr(bss->mld_addr)) {
-		if (ether_addr_equal(bss->bssid, wpa_s->wnm_dissoc_addr))
-			return true;
-	} else {
-		if (ether_addr_equal(bss->mld_addr, wpa_s->wnm_dissoc_addr))
-			return true;
-	}
-
-	return false;
+#endif /* CONFIG_WNM */
 }
diff --git a/wpa_supplicant/wnm_sta.h b/wpa_supplicant/wnm_sta.h
index 235a838..e4957e4 100644
--- a/wpa_supplicant/wnm_sta.h
+++ b/wpa_supplicant/wnm_sta.h
@@ -65,28 +65,18 @@
 				       const char *btm_candidates,
 				       int cand_list);
 
+void wnm_deallocate_memory(struct wpa_supplicant *wpa_s);
 int wnm_send_coloc_intf_report(struct wpa_supplicant *wpa_s, u8 dialog_token,
 			       const struct wpabuf *elems);
 void wnm_set_coloc_intf_elems(struct wpa_supplicant *wpa_s,
 			      struct wpabuf *elems);
 
-int wnm_btm_resp_tx_status(struct wpa_supplicant *wpa_s, const u8 *data,
-			   size_t data_len);
 
 #ifdef CONFIG_WNM
 
-int wnm_scan_process(struct wpa_supplicant *wpa_s, bool pre_scan_check);
+int wnm_scan_process(struct wpa_supplicant *wpa_s, int reply_on_fail);
 void wnm_clear_coloc_intf_reporting(struct wpa_supplicant *wpa_s);
 
-bool wnm_is_bss_excluded(struct wpa_supplicant *wpa_s, struct wpa_bss *bss);
-
-void wnm_btm_reset(struct wpa_supplicant *wpa_s);
-
-static inline bool wnm_active_bss_trans_mgmt(struct wpa_supplicant *wpa_s)
-{
-	return !!wpa_s->wnm_dialog_token;
-}
-
 #else /* CONFIG_WNM */
 
 static inline int wnm_scan_process(struct wpa_supplicant *wpa_s,
@@ -99,21 +89,6 @@
 {
 }
 
-static inline bool
-wnm_is_bss_excluded(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
-{
-	return false;
-}
-
-static inline void wnm_btm_reset(struct wpa_supplicant *wpa_s)
-{
-}
-
-static inline bool wnm_active_bss_trans_mgmt(struct wpa_supplicant *wpa_s)
-{
-	return false;
-}
-
 #endif /* CONFIG_WNM */
 
 #endif /* WNM_STA_H */
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index 60f8562..65078ed 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -2847,8 +2847,6 @@
 }
 
 
-#ifndef CONFIG_NO_WMM_AC
-
 static int wpa_cli_cmd_wmm_ac_addts(struct wpa_ctrl *ctrl, int argc,
 				    char *argv[])
 {
@@ -2869,8 +2867,6 @@
 	return wpa_ctrl_command(ctrl, "WMM_AC_STATUS");
 }
 
-#endif /* CONFIG_NO_WMM_AC */
-
 
 static int wpa_cli_cmd_tdls_chan_switch(struct wpa_ctrl *ctrl, int argc,
 					char *argv[])
@@ -3893,7 +3889,6 @@
 	{ "tdls_link_status", wpa_cli_cmd_tdls_link_status, NULL,
 	  cli_cmd_flag_none,
 	  "<addr> = TDLS link status with <addr>" },
-#ifndef CONFIG_NO_WMM_AC
 	{ "wmm_ac_addts", wpa_cli_cmd_wmm_ac_addts, NULL,
 	  cli_cmd_flag_none,
 	  "<uplink/downlink/bidi> <tsid=0..7> <up=0..7> [nominal_msdu_size=#] "
@@ -3905,7 +3900,6 @@
 	{ "wmm_ac_status", wpa_cli_cmd_wmm_ac_status, NULL,
 	  cli_cmd_flag_none,
 	  "= show status for Wireless Multi-Media Admission-Control" },
-#endif /* CONFIG_NO_WMM_AC */
 	{ "tdls_chan_switch", wpa_cli_cmd_tdls_chan_switch, NULL,
 	  cli_cmd_flag_none,
 	  "<addr> <oper class> <freq> [sec_channel_offset=] [center_freq1=] "
@@ -5129,7 +5123,7 @@
 
 	eloop_register_signal_terminate(wpa_cli_terminate, NULL);
 
-	if (!ctrl_ifname && !global)
+	if (ctrl_ifname == NULL)
 		ctrl_ifname = wpa_cli_get_default_ifname();
 
 	if (reconnect && action_file && ctrl_ifname) {
diff --git a/wpa_supplicant/wpa_priv.c b/wpa_supplicant/wpa_priv.c
index 88f3f2a..31a9af6 100644
--- a/wpa_supplicant/wpa_priv.c
+++ b/wpa_supplicant/wpa_priv.c
@@ -187,10 +187,7 @@
 	int val;
 	size_t i;
 
-	if (iface->driver->get_scan_results)
-		res = iface->driver->get_scan_results(iface->drv_priv, NULL);
-	else
-		res = iface->driver->get_scan_results2(iface->drv_priv);
+	res = iface->driver->get_scan_results2(iface->drv_priv);
 	if (res == NULL)
 		goto fail;
 
@@ -234,7 +231,7 @@
 	if (iface->drv_priv == NULL)
 		return;
 
-	if (iface->driver->get_scan_results || iface->driver->get_scan_results2)
+	if (iface->driver->get_scan_results2)
 		wpa_priv_get_scan_results2(iface, from, fromlen);
 	else
 		sendto(iface->fd, "", 0, 0, (struct sockaddr *) from, fromlen);
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 3fde0a8..d4401ff 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant
- * Copyright (c) 2003-2024, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2022, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -65,7 +65,6 @@
 #include "wpas_kay.h"
 #include "mesh.h"
 #include "dpp_supplicant.h"
-#include "nan_usd.h"
 #ifdef CONFIG_MESH
 #include "ap/ap_config.h"
 #include "ap/hostapd.h"
@@ -585,9 +584,7 @@
 	wpa_tdls_deinit(wpa_s->wpa);
 #endif /* CONFIG_TDLS */
 
-#ifndef CONFIG_NO_WMM_AC
 	wmm_ac_clear_saved_tspecs(wpa_s);
-#endif /* CONFIG_NO_WMM_AC */
 	pmksa_candidate_free(wpa_s->wpa);
 	ptksa_cache_deinit(wpa_s->ptksa);
 	wpa_s->ptksa = NULL;
@@ -678,7 +675,9 @@
 	wpa_s->disallow_aps_ssid = NULL;
 
 	wnm_bss_keep_alive_deinit(wpa_s);
-	wnm_btm_reset(wpa_s);
+#ifdef CONFIG_WNM
+	wnm_deallocate_memory(wpa_s);
+#endif /* CONFIG_WNM */
 
 	ext_password_deinit(wpa_s->ext_pw);
 	wpa_s->ext_pw = NULL;
@@ -702,9 +701,7 @@
 		wpa_s->vendor_elem[i] = NULL;
 	}
 
-#ifndef CONFIG_NO_WMM_AC
 	wmm_ac_notify_disassoc(wpa_s);
-#endif /* CONFIG_NO_WMM_AC */
 
 	wpa_s->sched_scan_plans_num = 0;
 	os_free(wpa_s->sched_scan_plans);
@@ -720,9 +717,7 @@
 
 	wpabuf_free(wpa_s->lci);
 	wpa_s->lci = NULL;
-#ifndef CONFIG_NO_RRM
 	wpas_clear_beacon_rep_data(wpa_s);
-#endif /* CONFIG_NO_RRM */
 
 #ifdef CONFIG_PMKSA_CACHE_EXTERNAL
 #ifdef CONFIG_MESH
@@ -751,17 +746,11 @@
 	wpa_s->dpp = NULL;
 #endif /* CONFIG_DPP */
 
-#ifdef CONFIG_NAN_USD
-	wpas_nan_usd_deinit(wpa_s);
-#endif /* CONFIG_NAN_USD */
-
 #ifdef CONFIG_PASN
 	wpas_pasn_auth_stop(wpa_s);
 #endif /* CONFIG_PASN */
-#ifndef CONFIG_NO_ROBUST_AV
 	wpas_scs_deinit(wpa_s);
 	wpas_dscp_deinit(wpa_s);
-#endif /* CONFIG_NO_ROBUST_AV */
 
 #ifdef CONFIG_OWE
 	os_free(wpa_s->owe_trans_scan_freq);
@@ -892,7 +881,7 @@
 			struct wpa_scan_results *scan_res;
 			wpa_s->bgscan_ssid = wpa_s->current_ssid;
 			scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
-								   0, NULL);
+								   0);
 			if (scan_res) {
 				bgscan_notify_scan(wpa_s, scan_res);
 				wpa_scan_results_free(scan_res);
@@ -1079,14 +1068,8 @@
 	if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
 		wpa_supplicant_start_autoscan(wpa_s);
 
-	if (state == WPA_COMPLETED || state == WPA_INTERFACE_DISABLED ||
-	    state == WPA_INACTIVE)
-		wnm_btm_reset(wpa_s);
-
-#ifndef CONFIG_NO_WMM_AC
 	if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
 		wmm_ac_notify_disassoc(wpa_s);
-#endif /* CONFIG_NO_WMM_AC */
 
 	if (wpa_s->wpa_state != old_state) {
 		wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
@@ -2026,7 +2009,7 @@
 		(wpa_s->connection_ht || wpa_s->connection_vht ||
 		 wpa_s->connection_he || wpa_s->connection_eht);
 	if (!wmm && bss)
-		wmm = !!wpa_bss_get_vendor_ie(bss, WMM_IE_VENDOR_TYPE);
+		wmm = wpa_bss_get_vendor_ie(bss, WMM_IE_VENDOR_TYPE);
 	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_WMM_ENABLED, wmm);
 
 	if (!skip_default_rsne) {
@@ -2128,9 +2111,7 @@
 static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx,
 				struct wpa_bss *bss)
 {
-#ifndef CONFIG_NO_ROBUST_AV
 	bool scs = true, mscs = true;
-#endif /* CONFIG_NO_ROBUST_AV */
 
 	*pos = 0x00;
 
@@ -2146,9 +2127,7 @@
 	case 2: /* Bits 16-23 */
 #ifdef CONFIG_WNM
 		*pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
-		if ((wpas_driver_bss_selection(wpa_s) ||
-		     !wpa_s->disable_mbo_oce) &&
-		    !wpa_s->conf->disable_btm)
+		if (!wpa_s->disable_mbo_oce && !wpa_s->conf->disable_btm)
 			*pos |= 0x08; /* Bit 19 - BSS Transition */
 #endif /* CONFIG_WNM */
 		break;
@@ -2177,7 +2156,6 @@
 #endif /* CONFIG_MBO */
 		break;
 	case 6: /* Bits 48-55 */
-#ifndef CONFIG_NO_ROBUST_AV
 #ifdef CONFIG_TESTING_OPTIONS
 		if (wpa_s->disable_scs_support)
 			scs = false;
@@ -2191,7 +2169,6 @@
 		}
 		if (scs)
 			*pos |= 0x40; /* Bit 54 - SCS */
-#endif /* CONFIG_NO_ROBUST_AV */
 		break;
 	case 7: /* Bits 56-63 */
 		break;
@@ -2208,7 +2185,6 @@
 #endif /* CONFIG_FILS */
 		break;
 	case 10: /* Bits 80-87 */
-#ifndef CONFIG_NO_ROBUST_AV
 #ifdef CONFIG_TESTING_OPTIONS
 		if (wpa_s->disable_mscs_support)
 			mscs = false;
@@ -2222,7 +2198,6 @@
 		}
 		if (mscs)
 			*pos |= 0x20; /* Bit 85 - Mirrored SCS */
-#endif /* CONFIG_NO_ROBUST_AV */
 		break;
 	}
 }
@@ -2340,7 +2315,8 @@
 		if (style == WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS) {
 			/* Pregenerated addresses do not expire but their value
 			 * might have changed, so let's check that. */
-			if (ether_addr_equal(wpa_s->own_addr, ssid->mac_value))
+			if (os_memcmp(wpa_s->own_addr, ssid->mac_value,
+				      ETH_ALEN) == 0)
 				return 0;
 		} else if ((wpa_s->last_mac_addr_change.sec != 0 ||
 			    wpa_s->last_mac_addr_change.usec != 0) &&
@@ -2519,13 +2495,7 @@
 
 	wpa_s->eapol_failed = 0;
 	wpa_s->multi_ap_ie = 0;
-#ifndef CONFIG_NO_WMM_AC
 	wmm_ac_clear_saved_tspecs(wpa_s);
-#endif /* CONFIG_NO_WMM_AC */
-#ifdef CONFIG_WNM
-	wpa_s->wnm_mode = 0;
-	wpa_s->wnm_target_bss = NULL;
-#endif /* CONFIG_WNM */
 	wpa_s->reassoc_same_bss = 0;
 	wpa_s->reassoc_same_ess = 0;
 #ifdef CONFIG_TESTING_OPTIONS
@@ -2536,9 +2506,7 @@
 		wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
 		wpa_s->reassoc_same_ess = 1;
 		if (wpa_s->current_bss && wpa_s->current_bss == bss) {
-#ifndef CONFIG_NO_WMM_AC
 			wmm_ac_save_tspecs(wpa_s);
-#endif /* CONFIG_NO_WMM_AC */
 			wpa_s->reassoc_same_bss = 1;
 		} else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
 			os_get_reltime(&wpa_s->roam_start);
@@ -2922,8 +2890,7 @@
 	if (obss_scan) {
 		struct wpa_scan_results *scan_res;
 
-		scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0,
-							   NULL);
+		scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
 		if (scan_res == NULL) {
 			/* Back to HT20 */
 			freq->sec_channel_offset = 0;
@@ -3087,7 +3054,7 @@
 				    freq->sec_channel_offset,
 				    chwidth, seg0, seg1, vht_caps,
 				    &mode->he_capab[ieee80211_mode],
-				    &mode->eht_capab[ieee80211_mode], 0) != 0)
+				    &mode->eht_capab[ieee80211_mode]) != 0)
 		return false;
 
 	*freq = vht_freq;
@@ -3107,7 +3074,7 @@
 	struct hostapd_hw_modes *mode = NULL;
 	int i, obss_scan = 1;
 	u8 channel;
-	bool is_6ghz, is_24ghz;
+	bool is_6ghz;
 
 	freq->freq = ssid->frequency;
 
@@ -3136,9 +3103,6 @@
 	if (!mode)
 		return;
 
-	is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
-		hw_mode == HOSTAPD_MODE_IEEE80211B;
-
 	is_6ghz = is_6ghz_freq(freq->freq);
 
 	freq->ht_enabled = 0;
@@ -3150,7 +3114,7 @@
 		freq->ht_enabled = ibss_mesh_can_use_ht(wpa_s, ssid, mode);
 	if (freq->ht_enabled)
 		freq->vht_enabled = ibss_mesh_can_use_vht(wpa_s, ssid, mode);
-	if (freq->vht_enabled || (freq->ht_enabled && is_24ghz) || is_6ghz)
+	if (freq->vht_enabled || is_6ghz)
 		freq->he_enabled = ibss_mesh_can_use_he(wpa_s, ssid, mode,
 							ieee80211_mode);
 	freq->channel = channel;
@@ -3292,10 +3256,8 @@
 	size_t wfa_ie_len, buf_len;
 
 	os_memset(wfa_capa, 0, sizeof(wfa_capa));
-#ifndef CONFIG_NO_ROBUST_AV
 	if (wpa_s->enable_dscp_policy_capa)
 		wfa_capa[0] |= WFA_CAPA_QM_DSCP_POLICY;
-#endif /* CONFIG_NO_ROBUST_AV */
 
 	if (wpa_is_non_eht_scs_traffic_desc_supported(bss))
 		wfa_capa[0] |= WFA_CAPA_QM_NON_EHT_SCS_TRAFFIC_DESC;
@@ -3559,14 +3521,12 @@
 	os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
 #endif /* CONFIG_P2P */
 
-#ifndef CONFIG_NO_RRM
 	if (bss) {
 		wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
 						    wpa_ie + wpa_ie_len,
 						    max_wpa_ie_len -
 						    wpa_ie_len);
 	}
-#endif /* CONFIG_NO_RRM */
 
 	/*
 	 * Workaround: Add Extended Capabilities element only if the AP
@@ -3793,7 +3753,6 @@
 		wpa_ie_len += wpa_s->rsnxe_len;
 	}
 
-#ifndef CONFIG_NO_ROBUST_AV
 #ifdef CONFIG_TESTING_OPTIONS
 	if (wpa_s->disable_mscs_support)
 		goto mscs_end;
@@ -3828,21 +3787,16 @@
 		wpabuf_free(mscs_ie);
 	}
 mscs_end:
-#endif /* CONFIG_NO_ROBUST_AV */
 
 	wpa_ie_len = wpas_populate_wfa_capa(wpa_s, bss, wpa_ie, wpa_ie_len,
 					    max_wpa_ie_len);
 
 	if (ssid->multi_ap_backhaul_sta) {
 		size_t multi_ap_ie_len;
-		struct multi_ap_params multi_ap = { 0 };
-
-		multi_ap.capability = MULTI_AP_BACKHAUL_STA;
-		multi_ap.profile = ssid->multi_ap_profile;
 
 		multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
 						  max_wpa_ie_len - wpa_ie_len,
-						  &multi_ap);
+						  MULTI_AP_BACKHAUL_STA);
 		if (multi_ap_ie_len == 0) {
 			wpa_printf(MSG_ERROR,
 				   "Multi-AP: Failed to build Multi-AP IE");
@@ -4117,9 +4071,7 @@
 	wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
 	wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
 	wpa_s->rsnxe_len = 0;
-#ifndef CONFIG_NO_ROBUST_AV
 	wpa_s->mscs_setup_done = false;
-#endif /* CONFIG_NO_ROBUST_AV */
 
 	wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
 	if (!wpa_ie) {
@@ -4514,8 +4466,7 @@
 			 * can stop right here; the association will not
 			 * succeed.
 			 */
-			wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
-					       NULL);
+			wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
 			wpa_s->assoc_status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
 			wpas_notify_assoc_status_code(wpa_s, wpa_s->pending_bssid, 0, NULL, 0);
 			wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
@@ -4611,10 +4562,8 @@
 	if (old_ssid != wpa_s->current_ssid)
 		wpas_notify_network_changed(wpa_s);
 
-#ifndef CONFIG_NO_ROBUST_AV
 	wpas_scs_deinit(wpa_s);
 	wpas_dscp_deinit(wpa_s);
-#endif /* CONFIG_NO_ROBUST_AV */
 	eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
 }
 
@@ -5394,14 +5343,14 @@
 		       os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
 		     wired) &&
 		    (!entry->bssid_set ||
-		     ether_addr_equal(bssid, entry->bssid)))
+		     os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
 			return entry;
 #ifdef CONFIG_WPS
 		if (!wpas_network_disabled(wpa_s, entry) &&
 		    (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
 		    (entry->ssid == NULL || entry->ssid_len == 0) &&
 		    (!entry->bssid_set ||
-		     ether_addr_equal(bssid, entry->bssid)))
+		     os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
 			return entry;
 #endif /* CONFIG_WPS */
 
@@ -5411,13 +5360,13 @@
 		     owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
 					  entry->ssid_len)) &&
 		    (!entry->bssid_set ||
-		     ether_addr_equal(bssid, entry->bssid)))
+		     os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
 			return entry;
 #endif /* CONFIG_OWE */
 
 		if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
 		    entry->ssid_len == 0 &&
-		    ether_addr_equal(bssid, entry->bssid))
+		    os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
 			return entry;
 
 		entry = entry->next;
@@ -5545,7 +5494,7 @@
 #ifdef CONFIG_AP
 	     !wpa_s->ap_iface &&
 #endif /* CONFIG_AP */
-	     !ether_addr_equal(src_addr, connected_addr))) {
+	     os_memcmp(src_addr, connected_addr, ETH_ALEN) != 0)) {
 		/*
 		 * There is possible race condition between receiving the
 		 * association event and the EAPOL frame since they are coming
@@ -5575,7 +5524,7 @@
 	}
 
 	wpa_s->last_eapol_matches_bssid =
-		ether_addr_equal(src_addr, connected_addr);
+		os_memcmp(src_addr, connected_addr, ETH_ALEN) == 0;
 
 #ifdef CONFIG_AP
 	if (wpa_s->ap_iface) {
@@ -5732,7 +5681,7 @@
 		fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
 #endif /* CONFIG_FST */
 
-	if (!ether_addr_equal(prev_mac_addr, wpa_s->own_addr))
+	if (os_memcmp(prev_mac_addr, wpa_s->own_addr, ETH_ALEN) != 0)
 		wpas_notify_mac_address_changed(wpa_s);
 
 	return 0;
@@ -5749,7 +5698,7 @@
 		return;
 	eth = (const struct l2_ethhdr *) buf;
 
-	if (!ether_addr_equal(eth->h_dest, wpa_s->own_addr) &&
+	if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
 	    !(eth->h_dest[0] & 0x01)) {
 		wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
 			" (bridge - not for this interface - ignore)",
@@ -5924,11 +5873,8 @@
 	dl_list_init(&wpa_s->fils_hlp_req);
 #ifdef CONFIG_TESTING_OPTIONS
 	dl_list_init(&wpa_s->drv_signal_override);
-	wpa_s->test_assoc_comeback_type = -1;
 #endif /* CONFIG_TESTING_OPTIONS */
-#ifndef CONFIG_NO_ROBUST_AV
 	dl_list_init(&wpa_s->active_scs_ids);
-#endif /* CONFIG_NO_ROBUST_AV */
 	wpa_s->ml_probe_mld_id = -1;
 
 	return wpa_s;
@@ -6441,7 +6387,7 @@
 {
 	struct wpa_supplicant *wpa_s = ctx;
 
-	if (!ether_addr_equal(wpa_s->bssid, da)) {
+	if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
 		wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
 			   __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
 		return -1;
@@ -6457,7 +6403,7 @@
 {
 	struct wpa_supplicant *wpa_s = ctx;
 
-	WPA_ASSERT(ether_addr_equal(wpa_s->bssid, addr));
+	WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
 	return wpa_s->received_mb_ies;
 }
 
@@ -6468,7 +6414,7 @@
 	struct wpa_supplicant *wpa_s = ctx;
 	struct mb_ies_info info;
 
-	WPA_ASSERT(ether_addr_equal(wpa_s->bssid, addr));
+	WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
 
 	if (!mb_ies_info_by_ies(&info, buf, size)) {
 		wpabuf_free(wpa_s->received_mb_ies);
@@ -7257,9 +7203,6 @@
 		return -1;
 	}
 
-	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_PREPEND_PMKID,
-			 wpa_s->conf->ft_prepend_pmkid);
-
 	wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
 						      &wpa_s->hw.num_modes,
 						      &wpa_s->hw.flags,
@@ -7308,9 +7251,7 @@
 		wpa_s->extended_capa_len = capa.extended_capa_len;
 		wpa_s->num_multichan_concurrent =
 			capa.num_multichan_concurrent;
-#ifndef CONFIG_NO_WMM_AC
 		wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
-#endif /* CONFIG_NO_WMM_AC */
 		wpa_s->max_num_akms = capa.max_num_akms;
 
 		if (capa.mac_addr_rand_scan_supported)
@@ -7398,11 +7339,6 @@
 		return -1;
 #endif /* CONFIG_DPP */
 
-#ifdef CONFIG_NAN_USD
-	if (wpas_nan_usd_init(wpa_s) < 0)
-		return -1;
-#endif /* CONFIG_NAN_USD */
-
 	if (wpa_supplicant_init_eapol(wpa_s) < 0)
 		return -1;
 	wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
@@ -7472,9 +7408,7 @@
 	if (wpas_init_ext_pw(wpa_s) < 0)
 		return -1;
 
-#ifndef CONFIG_NO_RRM
 	wpas_rrm_reset(wpa_s);
-#endif /* CONFIG_NO_RRM */
 
 	wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
 
@@ -8239,10 +8173,6 @@
 	if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
 		wpa_supplicant_set_default_scan_ies(wpa_s);
 
-	if (wpa_s->conf->changed_parameters & CFG_CHANGED_FT_PREPEND_PMKID)
-		wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_PREPEND_PMKID,
-				 wpa_s->conf->ft_prepend_pmkid);
-
 #ifdef CONFIG_BGSCAN
 	/*
 	 * We default to global bgscan parameters only when per-network bgscan
@@ -8311,8 +8241,7 @@
 }
 
 
-void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid,
-			    const u8 **link_bssids)
+void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
 {
 	int timeout;
 	int count;
@@ -8347,12 +8276,6 @@
 		return;
 	}
 
-	/* Also mark links as failed */
-	while (link_bssids && *link_bssids) {
-		wpa_bssid_ignore_add(wpa_s, *link_bssids);
-		link_bssids++;
-	}
-
 	/*
 	 * Add the failed BSSID into the ignore list and speed up next scan
 	 * attempt if there could be other APs that could accept association.
@@ -8769,16 +8692,9 @@
 int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
 {
 	if (wpa_s->current_ssid == NULL ||
-	    wpa_s->wpa_state < WPA_4WAY_HANDSHAKE)
+	    wpa_s->wpa_state < WPA_4WAY_HANDSHAKE ||
+	    os_memcmp(addr, wpa_s->bssid, ETH_ALEN) != 0)
 		return 0;
-	if (wpa_s->valid_links) {
-		if (!ether_addr_equal(addr, wpa_s->ap_mld_addr) &&
-		    !wpas_ap_link_address(wpa_s, addr))
-			return 0;
-	} else {
-		if (!ether_addr_equal(addr, wpa_s->bssid))
-			return 0;
-	}
 	return wpa_sm_pmf_enabled(wpa_s->wpa);
 }
 
@@ -8903,8 +8819,8 @@
 		return 0;
 
 	for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
-		if (ether_addr_equal(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
-				     bssid))
+		if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
+			      bssid, ETH_ALEN) == 0)
 			return 1;
 	}
 
@@ -9181,7 +9097,8 @@
 		if (modes[i].mode != mode ||
 		    !modes[i].num_channels || !modes[i].channels)
 			continue;
-		if (is_6ghz == modes[i].is_6ghz)
+		if ((!is_6ghz && !is_6ghz_freq(modes[i].channels[0].freq)) ||
+		    (is_6ghz && is_6ghz_freq(modes[i].channels[0].freq)))
 			return &modes[i];
 	}
 
@@ -9213,7 +9130,7 @@
 
 	dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
 			 struct wpa_bss_tmp_disallowed, list) {
-		if (ether_addr_equal(bssid, bss->bssid))
+		if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
 			return bss;
 	}
 
@@ -9296,7 +9213,7 @@
 
 	dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
 			 struct wpa_bss_tmp_disallowed, list) {
-		if (ether_addr_equal(bss->bssid, tmp->bssid)) {
+		if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
 			disallowed = tmp;
 			break;
 		}
@@ -9394,7 +9311,8 @@
 
 		dl_list_for_each(dso, &wpa_s->drv_signal_override,
 				 struct driver_signal_override, list) {
-			if (!ether_addr_equal(wpa_s->bssid, dso->bssid))
+			if (os_memcmp(wpa_s->bssid, dso->bssid,
+				      ETH_ALEN) != 0)
 				continue;
 			wpa_printf(MSG_DEBUG,
 				   "Override driver signal_poll information: current_signal: %d->%d avg_signal: %d->%d avg_beacon_signal: %d->%d current_noise: %d->%d",
@@ -9420,21 +9338,17 @@
 
 
 struct wpa_scan_results *
-wpa_drv_get_scan_results(struct wpa_supplicant *wpa_s, const u8 *bssid)
+wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s)
 {
 	struct wpa_scan_results *scan_res;
 #ifdef CONFIG_TESTING_OPTIONS
 	size_t idx;
 #endif /* CONFIG_TESTING_OPTIONS */
 
-	if (wpa_s->driver->get_scan_results)
-		scan_res = wpa_s->driver->get_scan_results(wpa_s->drv_priv,
-							   bssid);
-	else if (wpa_s->driver->get_scan_results2)
-		scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
-	else
+	if (!wpa_s->driver->get_scan_results2)
 		return NULL;
 
+	scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
 
 #ifdef CONFIG_TESTING_OPTIONS
 	for (idx = 0; scan_res && idx < scan_res->num; idx++) {
@@ -9443,7 +9357,7 @@
 
 		dl_list_for_each(dso, &wpa_s->drv_signal_override,
 				 struct driver_signal_override, list) {
-			if (!ether_addr_equal(res->bssid, dso->bssid))
+			if (os_memcmp(res->bssid, dso->bssid, ETH_ALEN) != 0)
 				continue;
 			wpa_printf(MSG_DEBUG,
 				   "Override driver scan signal level %d->%d for "
@@ -9465,15 +9379,18 @@
 }
 
 
-bool wpas_ap_link_address(struct wpa_supplicant *wpa_s, const u8 *addr)
+static bool wpas_ap_link_address(struct wpa_supplicant *wpa_s, const u8 *addr)
 {
 	int i;
 
 	if (!wpa_s->valid_links)
 		return false;
 
-	for_each_link(wpa_s->valid_links, i) {
-		if (ether_addr_equal(wpa_s->links[i].bssid, addr))
+	for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+		if (!(wpa_s->valid_links & BIT(i)))
+			continue;
+
+		if (os_memcmp(wpa_s->links[i].bssid, addr, ETH_ALEN) == 0)
 			return true;
 	}
 
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index 89c5d03..f6e4f83 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -982,11 +982,9 @@
 # parameter uses following format: "<bgscan module name>:<module parameters>"
 # Following bgscan modules are available:
 # simple - Periodic background scans based on signal strength
-# send_btm_query > 0 means do this many BTM queries before attempting a scan.
 # bgscan="simple:<short bgscan interval in seconds>:<signal strength threshold>:
-# <long interval>[:<send_btm_query>]"
+# <long interval>"
 # bgscan="simple:30:-45:300"
-# bgscan="simple:30:-45:300:3"
 # learn - Learn channels used by the network and try to avoid bgscans on other
 # channels (experimental)
 # bgscan="learn:<short bgscan interval in seconds>:<signal strength threshold>:
@@ -1717,12 +1715,6 @@
 # support Multi-AP, and sets 4-address mode if it does. Thus, the netdev can be
 # added to a bridge to allow forwarding frames over this backhaul link.
 
-# Multi-AP Profile
-# Indicate the supported Multi-AP profile
-# 1 = Supports Multi-AP profile 1 as defined in Wi-Fi EasyMesh specification
-# 2 = Supports Multi-AP profile 2 as defined in Wi-Fi EasyMesh specification
-#multi_ap_profile=2
-
 ##### Fast Session Transfer (FST) support #####################################
 #
 # The options in this section are only available when the build configuration
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 0fea5cc..0890110 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -1,6 +1,6 @@
 /*
  * wpa_supplicant - Internal definitions
- * Copyright (c) 2003-2024, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -494,7 +494,6 @@
 	u8 bssid[ETH_ALEN];
 	enum beacon_report_detail report_detail;
 	struct bitfield *eids;
-	struct bitfield *ext_eids;
 };
 
 
@@ -679,13 +678,6 @@
 };
 
 
-struct ml_sta_link_info {
-	u8 link_id;
-	u8 bssid[ETH_ALEN];
-	u16 status;
-};
-
-
 /**
  * struct wpa_supplicant - Internal data for wpa_supplicant interface
  *
@@ -748,12 +740,11 @@
 	u8 ap_mld_addr[ETH_ALEN];
 	u8 mlo_assoc_link_id;
 	u16 valid_links; /* bitmap of valid MLO link IDs */
-	struct {
+	struct ml_sta_link_info {
 		u8 addr[ETH_ALEN];
 		u8 bssid[ETH_ALEN];
 		unsigned int freq;
 		struct wpa_bss *bss;
-		bool disabled;
 	} links[MAX_NUM_MLD_LINKS];
 	u8 *last_con_fail_realm;
 	size_t last_con_fail_realm_len;
@@ -1055,7 +1046,6 @@
 		bool ext_ml_auth;
 		int *sae_rejected_groups;
 #endif /* CONFIG_SAE */
-		u16 assoc_auth_type;
 	} sme;
 #endif /* CONFIG_SME */
 
@@ -1217,7 +1207,6 @@
 	struct wpa_ssid *bgscan_ssid;
 	const struct bgscan_ops *bgscan;
 	void *bgscan_priv;
-	int signal_threshold;
 
 	const struct autoscan_ops *autoscan;
 	struct wpa_driver_scan_params *autoscan_params;
@@ -1326,15 +1315,14 @@
 	u8 wnm_reply;
 	u8 wnm_num_neighbor_report;
 	u8 wnm_mode;
-	bool wnm_link_removal;
-	u8 wnm_dissoc_addr[ETH_ALEN];
 	u16 wnm_dissoc_timer;
 	u8 wnm_bss_termination_duration[12];
 	struct neighbor_report *wnm_neighbor_report_elements;
 	struct os_reltime wnm_cand_valid_until;
-	struct wpa_bss *wnm_target_bss;
+	u8 wnm_cand_from_bss[ETH_ALEN];
 	enum bss_trans_mgmt_status_code bss_tm_status;
 	bool bss_trans_mgmt_in_progress;
+	struct wpabuf *coloc_intf_elems;
 	u8 coloc_intf_dialog_token;
 	u8 coloc_intf_auto_report;
 	u8 coloc_intf_timeout;
@@ -1393,7 +1381,6 @@
 	unsigned int oci_freq_override_fils_assoc;
 	unsigned int oci_freq_override_wnm_sleep;
 	unsigned int disable_eapol_g2_tx;
-	int test_assoc_comeback_type;
 #endif /* CONFIG_TESTING_OPTIONS */
 
 	struct wmm_ac_assoc_data *wmm_ac_assoc_info;
@@ -1500,9 +1487,6 @@
 	int dpp_netrole;
 	int dpp_auth_ok_on_ack;
 	int dpp_in_response_listen;
-	bool dpp_tx_auth_resp_on_roc_stop;
-	bool dpp_tx_chan_change;
-	bool dpp_listen_on_tx_expire;
 	int dpp_gas_client;
 	int dpp_gas_server;
 	int dpp_gas_dialog_token;
@@ -1583,24 +1567,8 @@
 	unsigned int multi_ap_ie:1;
 	unsigned int multi_ap_backhaul:1;
 	unsigned int multi_ap_fronthaul:1;
-
-#ifndef CONFIG_NO_ROBUST_AV
 	struct robust_av_data robust_av;
 	bool mscs_setup_done;
-	struct scs_robust_av_data scs_robust_av_req;
-	u8 scs_dialog_token;
-	struct dl_list active_scs_ids;
-	bool ongoing_scs_req;
-	u8 dscp_req_dialog_token;
-	u8 dscp_query_dialog_token;
-	unsigned int enable_dscp_policy_capa:1;
-	unsigned int connection_dscp:1;
-	unsigned int wait_for_dscp_req:1;
-#ifdef CONFIG_TESTING_OPTIONS
-	unsigned int disable_scs_support:1;
-	unsigned int disable_mscs_support:1;
-#endif /* CONFIG_TESTING_OPTIONS */
-#endif /* CONFIG_NO_ROBUST_AV */
 
 	bool wps_scan_done; /* Set upon receiving scan results event */
 	bool supp_pbc_active; /* Set for interface when PBC is triggered */
@@ -1612,7 +1580,19 @@
 	unsigned int pasn_count;
 	struct pasn_auth *pasn_params;
 #endif /* CONFIG_PASN */
-
+	struct scs_robust_av_data scs_robust_av_req;
+	u8 scs_dialog_token;
+#ifdef CONFIG_TESTING_OPTIONS
+	unsigned int disable_scs_support:1;
+	unsigned int disable_mscs_support:1;
+#endif /* CONFIG_TESTING_OPTIONS */
+	struct dl_list active_scs_ids;
+	bool ongoing_scs_req;
+	u8 dscp_req_dialog_token;
+	u8 dscp_query_dialog_token;
+	unsigned int enable_dscp_policy_capa:1;
+	unsigned int connection_dscp:1;
+	unsigned int wait_for_dscp_req:1;
 	bool is_6ghz_enabled;
 	bool crossed_6ghz_dom;
 	bool last_scan_all_chan;
@@ -1629,12 +1609,6 @@
 	 * owe_transition_search == 1 */
 	int *owe_trans_scan_freq;
 #endif /* CONFIG_OWE */
-
-#ifdef CONFIG_NAN_USD
-	struct nan_de *nan_de;
-	struct wpa_radio_work *nan_usd_listen_work;
-	struct wpa_radio_work *nan_usd_tx_work;
-#endif /* CONFIG_NAN_USD */
 };
 
 
@@ -1741,8 +1715,7 @@
 			     enum frame_encryption encrypted);
 void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s);
 void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s);
-void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid,
-			    const u8 **link_bssids);
+void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid);
 void fils_connection_failure(struct wpa_supplicant *wpa_s);
 void fils_pmksa_cache_flush(struct wpa_supplicant *wpa_s);
 int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s);
@@ -2042,6 +2015,5 @@
 bool wpas_is_6ghz_supported(struct wpa_supplicant *wpa_s, bool only_enabled);
 
 bool wpa_is_non_eht_scs_traffic_desc_supported(struct wpa_bss *bss);
-bool wpas_ap_link_address(struct wpa_supplicant *wpa_s, const u8 *addr);
 
 #endif /* WPA_SUPPLICANT_I_H */
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index 2fea640..9804b91 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -418,7 +418,7 @@
 	const u8 *ie;
 
 	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
-		if (!ether_addr_equal(bss->bssid, wpa_s->bssid))
+		if (os_memcmp(bss->bssid, wpa_s->bssid, ETH_ALEN) != 0)
 			continue;
 		if (ssid == NULL ||
 		    ((bss->ssid_len == ssid->ssid_len &&
@@ -465,7 +465,7 @@
 
 	/* No WPA/RSN IE found in the cached scan results. Try to get updated
 	 * scan results from the driver. */
-	if (wpa_supplicant_update_scan_results(wpa_s, wpa_s->bssid) < 0)
+	if (wpa_supplicant_update_scan_results(wpa_s) < 0)
 		return -1;
 
 	return wpa_get_beacon_ie(wpa_s);
diff --git a/wpa_supplicant/wpas_module_tests.c b/wpa_supplicant/wpas_module_tests.c
index 9e7a57c..ce5398c 100644
--- a/wpa_supplicant/wpas_module_tests.c
+++ b/wpa_supplicant/wpas_module_tests.c
@@ -17,12 +17,9 @@
 static int wpas_bssid_ignore_module_tests(void)
 {
 	struct wpa_supplicant wpa_s;
-	struct wpa_global global;
 	int ret = -1;
 
 	os_memset(&wpa_s, 0, sizeof(wpa_s));
-	os_memset(&global, 0, sizeof(global));
-	wpa_s.global = &global;
 
 	wpa_bssid_ignore_clear(&wpa_s);
 
diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c
index f103237..cd94b64 100644
--- a/wpa_supplicant/wps_supplicant.c
+++ b/wpa_supplicant/wps_supplicant.c
@@ -295,7 +295,8 @@
 		if (ssid->bssid_set || new_ssid->bssid_set) {
 			if (ssid->bssid_set != new_ssid->bssid_set)
 				continue;
-			if (!ether_addr_equal(ssid->bssid, new_ssid->bssid))
+			if (os_memcmp(ssid->bssid, new_ssid->bssid, ETH_ALEN) !=
+			    0)
 				continue;
 		}
 
@@ -1061,7 +1062,7 @@
 		 */
 #ifndef CONFIG_P2P
 		dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
-			if (!ether_addr_equal(bssid, bss->bssid))
+			if (os_memcmp(bssid, bss->bssid, ETH_ALEN) != 0)
 				continue;
 
 			os_free(ssid->ssid);
@@ -1208,19 +1209,14 @@
 		}
 	}
 #endif /* CONFIG_P2P */
-	if (multi_ap_backhaul_sta)
-		os_snprintf(phase1, sizeof(phase1), "pbc=1 multi_ap=%d",
-			    multi_ap_backhaul_sta);
-	else
-		os_snprintf(phase1, sizeof(phase1), "pbc=1");
+	os_snprintf(phase1, sizeof(phase1), "pbc=1%s",
+		    multi_ap_backhaul_sta ? " multi_ap=1" : "");
 	if (wpa_config_set_quoted(ssid, "phase1", phase1) < 0)
 		return -1;
 	if (wpa_s->wps_fragment_size)
 		ssid->eap.fragment_size = wpa_s->wps_fragment_size;
-	if (multi_ap_backhaul_sta) {
+	if (multi_ap_backhaul_sta)
 		ssid->multi_ap_backhaul_sta = 1;
-		ssid->multi_ap_profile = multi_ap_backhaul_sta;
-	}
 	wpa_s->supp_pbc_active = true;
 	wpa_s->wps_overlap = false;
 	wpa_supplicant_wps_event(wpa_s, WPS_EV_PBC_ACTIVE, NULL);
@@ -1816,7 +1812,7 @@
 	}
 
 	if (!ret && ssid->bssid_set &&
-	    ether_addr_equal(ssid->bssid, bss->bssid)) {
+	    os_memcmp(ssid->bssid, bss->bssid, ETH_ALEN) == 0) {
 		/* allow wildcard SSID due to hardcoded BSSID match */
 		ret = 1;
 	}
@@ -1855,11 +1851,11 @@
 				    const u8 *sel_uuid)
 {
 	if (!ap->pbc_active ||
-	    ether_addr_equal(selected->bssid, ap->bssid))
+	    os_memcmp(selected->bssid, ap->bssid, ETH_ALEN) == 0)
 		return false;
 
 	if (!is_zero_ether_addr(ssid->bssid) &&
-	    !ether_addr_equal(ap->bssid, ssid->bssid)) {
+	    os_memcmp(ap->bssid, ssid->bssid, ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG, "WPS: Ignore another BSS " MACSTR
 			   " in active PBC mode due to local BSSID limitation",
 			   MAC2STR(ap->bssid));
@@ -2947,7 +2943,7 @@
 
 	for (i = 0; i < wpa_s->num_wps_ap; i++) {
 		struct wps_ap_info *ap = &wpa_s->wps_ap[i];
-		if (ether_addr_equal(ap->bssid, bssid))
+		if (os_memcmp(ap->bssid, bssid, ETH_ALEN) == 0)
 			return ap;
 	}