Revert "[wpa_supplicant] cumilative patch from commit 3a5d1a7e6"

Revert submission 26533062-Supplicant_merge_June24

Reason for revert: https://b.corp.google.com/issues/349780869

Reverted changes: /q/submissionid:26533062-Supplicant_merge_June24
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:eb83e2a5c5a7873beda5b25580232d1392c42bb2)
Merged-In: I4a7a5b8ccb6b4822353bacc29649587cd5a3cb80
Change-Id: I4a7a5b8ccb6b4822353bacc29649587cd5a3cb80
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 445d963..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.
@@ -165,7 +165,6 @@
 
 #ifdef CONFIG_TESTING_OPTIONS
 	bss->sae_commit_status = -1;
-	bss->test_assoc_comeback_type = -1;
 #endif /* CONFIG_TESTING_OPTIONS */
 
 #ifdef CONFIG_PASN
@@ -284,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
@@ -302,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;
 }
 
@@ -702,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;
@@ -861,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
@@ -961,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);
@@ -1150,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;
@@ -1576,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) {
@@ -1772,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 69db16d..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)
@@ -957,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 */
 };
 
@@ -1156,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 */
 
@@ -1205,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 */
@@ -1274,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 */
@@ -1307,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);
@@ -1352,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 60d66e4..8f9cc5b 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -265,35 +265,9 @@
 }
 
 
-static 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,
@@ -832,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_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);
 }
 
@@ -854,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_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);
 }
 
@@ -882,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.
@@ -905,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
@@ -914,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_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);
 }
 
 
@@ -943,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);
 }
 
 
@@ -1095,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_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/beacon.c b/src/ap/beacon.c
index e50f0a0..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 : hapd->conf->mld_id;
-
-	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);
diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
index 5378671..a6fcb7e 100644
--- a/src/ap/ctrl_iface_ap.c
+++ b/src/ap/ctrl_iface_ap.c
@@ -830,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 */
 
@@ -1105,7 +1094,7 @@
 		return -1;
 
 	return wpa_auth_pmksa_add2(hapd->wpa_auth, spa, pmk, pmk_len,
-				   pmkid, expiration, akmp, NULL);
+				   pmkid, expiration, akmp);
 }
 
 
@@ -1326,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 5e4c810..9a5d3c8 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -188,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;
 	}
 
@@ -551,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");
@@ -985,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;
@@ -1051,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;
@@ -1126,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,
@@ -1190,7 +1183,7 @@
 		}
 	} 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);
 	}
 
 	return 0;
@@ -1324,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;
 	}
 
@@ -1486,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;
diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c
index 3f89bc2..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,
@@ -3962,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 533cc54..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,7 +509,7 @@
 			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_addr,
@@ -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);
@@ -1181,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 */
@@ -1289,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);
@@ -1607,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) ==
@@ -1623,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 */
 
@@ -1677,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];
 	}
 
@@ -1731,7 +1682,7 @@
 
 #ifdef CONFIG_IEEE80211BE
 	if (hapd->conf->mld_ap &&
-	    ether_addr_equal(hapd->mld_addr, bssid))
+	    os_memcmp(hapd->mld_addr, bssid, ETH_ALEN) == 0)
 		is_mld = true;
 #endif /* CONFIG_IEEE80211BE */
 
@@ -1803,7 +1754,8 @@
 		hapd = tmp_hapd;
 #ifdef CONFIG_IEEE80211BE
 	} else if (hapd->conf->mld_ap &&
-		   ether_addr_equal(hapd->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 {
@@ -1851,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];
 	}
 
@@ -1867,40 +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];
-		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, 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,
@@ -1913,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) {
@@ -2235,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,
@@ -2435,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,
@@ -2473,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:
@@ -2511,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 ddbcabc..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"
@@ -414,61 +413,6 @@
 }
 
 
-#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)
-{
-	struct hostapd_data *hapd = (struct hostapd_data *) eloop_data;
-
-	if (hapd->eht_mld_link_removal_count == 0)
-		return;
-	hapd->eht_mld_link_removal_count--;
-
-	wpa_printf(MSG_DEBUG, "MLD: Remove link_id=%u in %u beacons",
-		   hapd->mld_link_id,
-		   hapd->eht_mld_link_removal_count);
-
-	ieee802_11_set_beacon(hapd);
-
-	if (!hapd->eht_mld_link_removal_count) {
-		hostapd_disable_iface(hapd->iface);
-		return;
-	}
-
-	eloop_register_timeout(0, TU_TO_USEC(hapd->iconf->beacon_int),
-			       hostapd_link_remove_timeout_handler,
-			       hapd, 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);
@@ -497,24 +441,6 @@
 	hostapd_acl_deinit(hapd);
 #ifndef CONFIG_NO_RADIUS
 	if (!hapd->mld_first_bss) {
-		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;
-			}
-		}
 		radius_client_deinit(hapd->radius);
 		radius_das_deinit(hapd->radius_das);
 	}
@@ -529,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);
 
@@ -579,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
@@ -604,12 +525,6 @@
 
 #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 */
 }
 
@@ -1520,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;
 
@@ -3207,31 +3117,6 @@
 		return -1;
 	}
 
-#ifdef CONFIG_IEEE80211BE
-	if (hapd_iface->bss[0]->conf->mld_ap &&
-	    !hapd_iface->bss[0]->mld_first_bss) {
-		/* Do not allow mld_first_bss disabling before other BSSs */
-		for (j = 0; j < hapd_iface->interfaces->count; ++j) {
-			struct hostapd_iface *h_iface =
-				hapd_iface->interfaces->iface[j];
-			struct hostapd_data *h_hapd = h_iface->bss[0];
-			struct hostapd_bss_config *h_conf = h_hapd->conf;
-
-			if (!h_conf->mld_ap ||
-			    h_conf->mld_id !=
-			    hapd_iface->bss[0]->conf->mld_id ||
-			    h_iface == hapd_iface)
-				continue;
-
-			if (h_iface->state != HAPD_IFACE_DISABLED) {
-				wpa_printf(MSG_INFO,
-					   "Do not allow disable mld_first_bss first");
-				return -1;
-			}
-		}
-	}
-#endif /* CONFIG_IEEE80211BE */
-
 	wpa_msg(hapd_iface->bss[0]->msg_ctx, MSG_INFO, AP_EVENT_DISABLED);
 	driver = hapd_iface->bss[0]->driver;
 	drv_priv = hapd_iface->bss[0]->drv_priv;
@@ -3651,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 */
@@ -3883,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) {
@@ -3959,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);
 
@@ -4064,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;
 }
@@ -4164,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;
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index bcf980f..7f703be 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -469,17 +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;
-#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 */
 };
 
 
@@ -782,25 +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);
-
-#ifdef CONFIG_IEEE80211BE
-#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 &&		\
-				_link->conf->mld_id == _mld_id;		\
-			    _link = NULL)
-#else /* CONFIG_IEEE80211BE */
-#define for_each_mld_link(_link, _bss_idx, _iface_idx, _ifaces, _mld_id) \
-	if (false)
-#endif /* CONFIG_IEEE80211BE */
 
 #endif /* HOSTAPD_H */
diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index 596f2f0..9edbb5a 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -1001,7 +1001,7 @@
 {
 	int secondary_freq;
 	struct hostapd_channel_data *pri_chan;
-	int err, err2;
+	int err;
 
 	if (!iface->current_mode)
 		return 0;
@@ -1044,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;
 	}
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 8b8c1f0..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"
 
 
@@ -408,7 +407,7 @@
 	 * the MLD MAC address. Thus, use the MLD address instead of translating
 	 * the addresses.
 	 */
-	if (ap_sta_is_mld(hapd, sta)) {
+	if (hapd->conf->mld_ap && sta && sta->mld_info.mld_sta) {
 		sa = hapd->mld_addr;
 
 		ml_resp = hostapd_ml_auth_resp(hapd);
@@ -557,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;
@@ -609,7 +608,7 @@
 	const u8 *own_addr = hapd->own_addr;
 
 #ifdef CONFIG_IEEE80211BE
-	if (ap_sta_is_mld(hapd, sta))
+	if (hapd->conf->mld_ap && sta->mld_info.mld_sta)
 		own_addr = hapd->mld_addr;
 #endif /* CONFIG_IEEE80211BE */
 
@@ -878,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 */
@@ -903,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 */
@@ -1278,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;
@@ -1287,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),
@@ -1559,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");
@@ -1672,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,
@@ -1703,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;
 	}
 
@@ -2029,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;
 		}
@@ -2157,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");
 			}
@@ -2529,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");
@@ -2621,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",
@@ -2648,10 +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 */
 
 	if (ieee802_11_parse_elems(mgmt->u.auth.variable,
 				   len - offsetof(struct ieee80211_mgmt,
@@ -2701,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;
@@ -2917,7 +2906,7 @@
 		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;
@@ -2925,8 +2914,8 @@
 	}
 
 	if (mld_sta &&
-	    (ether_addr_equal(sa, hapd->own_addr) ||
-	     ether_addr_equal(sa, hapd->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));
@@ -3079,13 +3068,12 @@
 
 #ifdef CONFIG_IEEE80211BE
 	if (auth_transaction == 1) {
-		ap_sta_free_sta_profile(&sta->mld_info);
 		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;
 
 			/*
@@ -3248,7 +3236,7 @@
 	  * 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_addr;
 	}
@@ -3293,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++) {
@@ -3667,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;
 }
@@ -3739,7 +3727,7 @@
 		goto end;
 	}
 #ifdef CONFIG_IEEE80211BE
-	if (ap_sta_is_mld(hapd, sta))
+	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 */
@@ -4021,7 +4009,7 @@
 			}
 
 #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,
@@ -4321,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);
@@ -4375,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));
@@ -4418,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;
 
@@ -4438,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);
@@ -4490,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));
 }
 
 
@@ -4525,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
@@ -4565,29 +4536,22 @@
 				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;
 }
 
 
@@ -4625,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;
@@ -4736,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;
@@ -4786,7 +4750,7 @@
 	 * 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)
+	if (hapd->conf->mld_ap && sta && sta->mld_info.mld_sta)
 		sa = hapd->mld_addr;
 #endif /* CONFIG_IEEE80211BE */
 
@@ -4929,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);
 	}
@@ -5152,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;
@@ -5188,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)
@@ -5246,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))) {
@@ -5304,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) {
@@ -5602,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))
@@ -5648,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);
 
 	/*
@@ -5744,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,
@@ -5762,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++) {
@@ -6035,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);
@@ -6072,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,
@@ -6161,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;
@@ -6180,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. */
@@ -6206,9 +6110,9 @@
 #endif /* CONFIG_MESH */
 #ifdef CONFIG_IEEE80211BE
 	    !(hapd->conf->mld_ap &&
-	      ether_addr_equal(hapd->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;
@@ -6229,12 +6133,9 @@
 	     stype != WLAN_FC_STYPE_ACTION) &&
 #ifdef CONFIG_IEEE80211BE
 	    !(hapd->conf->mld_ap &&
-	      ether_addr_equal(hapd->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",
@@ -6384,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,
@@ -6406,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:
@@ -6443,7 +6340,7 @@
 			struct hostapd_data *tmp_hapd =
 				hapd->iface->interfaces->iface[i]->bss[0];
 
-			if (!tmp_hapd->conf->mld_ap ||
+			if (tmp_hapd->conf->mld_ap ||
 			    hapd->conf->mld_id != tmp_hapd->conf->mld_id)
 				continue;
 
@@ -6482,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,
@@ -6692,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 &&
@@ -6748,7 +6643,6 @@
 	}
 #endif /* CONFIG_HS20 */
 
-#ifndef CONFIG_NO_RRM
 	if (len < 24 + 5 + sizeof(*report))
 		return;
 	report = (const struct rrm_measurement_report_element *)
@@ -6759,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 */
 }
 
 
@@ -6971,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;
@@ -7070,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 */
@@ -7513,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;
 	}
@@ -7523,98 +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 (reporting_hapd->conf->mld_ap &&
-		    bss->conf->mld_id == reporting_hapd->conf->mld_id)
-			*eid++ = 0;
-		else
-			*eid++ = hapd->conf->mld_id;
-
-		*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
@@ -7649,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;
@@ -7729,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;
 
@@ -7760,18 +7610,7 @@
 					  size_t known_bss_len)
 {
 	struct hostapd_data *tx_bss = hostapd_mbssid_get_tx_bss(hapd);
-	size_t len, i;
-
-	/* 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];
@@ -7824,9 +7663,7 @@
 	}
 
 	*bss_index = i;
-
-	/* Add 2 octets to get the full size of the element */
-	return len + 2;
+	return len;
 }
 
 
@@ -7955,14 +7792,13 @@
 				eid += 2 + rsnx[1];
 			}
 		}
-		/* 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;
diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
index 5fd380a..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);
@@ -255,13 +245,5 @@
 			      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 840fc20..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,33 +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 = conf->punct_bitmap;
+	size_t elen = 1 + 4 + 3;
 
 	if (!hapd->iface->current_mode)
 		return eid;
 
-#ifdef CONFIG_TESTING_OPTIONS
-	if (!punct_bitmap && hapd->conf->eht_oper_puncturing_override) {
-		wpa_printf(MSG_DEBUG, "EHT: Puncturing mask override=0x%x",
-			   hapd->conf->eht_oper_puncturing_override);
-		punct_bitmap = hapd->conf->eht_oper_puncturing_override;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	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;
@@ -238,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;
@@ -249,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) {
@@ -286,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;
@@ -366,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;
@@ -382,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;
 
@@ -407,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)) {
@@ -447,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;
@@ -481,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 */
@@ -517,12 +489,12 @@
 		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;
 
 		/*
@@ -530,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)
@@ -566,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);
 
@@ -581,10 +552,9 @@
 		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) {
@@ -594,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;
@@ -655,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);
@@ -1016,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;
 	}
@@ -1070,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)
@@ -1163,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;
 
@@ -1245,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 ")",
@@ -1255,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;
@@ -1286,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 */
@@ -1395,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 4b693a7..548a448 100644
--- a/src/ap/ieee802_11_he.c
+++ b/src/ap/ieee802_11_he.c
@@ -254,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 0c38483..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_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_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,
@@ -1159,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_1x.c b/src/ap/ieee802_1x.c
index f13c60a..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");
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/neighbor_db.c b/src/ap/neighbor_db.c
index 2a25ae2..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,
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/sta_info.c b/src/ap/sta_info.c
index 2178d65..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;
@@ -303,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
@@ -350,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);
@@ -421,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);
@@ -851,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
@@ -876,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;
@@ -919,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) {
@@ -932,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;
@@ -947,105 +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++) {
-		for (i = 0; i < interfaces->count; i++) {
-			struct sta_info *tmp_sta;
-
-			if (!assoc_sta->mld_info.links[link_id].valid)
-				continue;
-
-			tmp_hapd = interfaces->iface[i]->bss[0];
-
-			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;
-			     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)
@@ -1395,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
@@ -1420,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 */
-	u8 *ip_ptr = NULL;
-
 #ifdef CONFIG_P2P
 	if (hapd->p2p_group == NULL) {
 		if (sta->p2p_ie != NULL &&
@@ -1523,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)
 {
@@ -1723,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,
-			  hapd->conf->mld_id) {
-		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;
@@ -1765,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 */
 
@@ -1799,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 b136ff7..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,24 +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);
-
 #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 b77e21b..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_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 3002d91..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,7 +3178,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, "RSN: MLD: Invalid MLD address");
 		return -1;
 	}
@@ -3366,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)",
@@ -3401,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;
@@ -3411,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;
@@ -3520,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");
@@ -3704,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,
@@ -3738,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);
 }
 
 
@@ -3752,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;
@@ -3776,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)
@@ -3809,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;
@@ -3974,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];
 
@@ -4001,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;
@@ -4020,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 */
@@ -4065,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);
@@ -4098,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);
@@ -4138,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);
@@ -4437,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;
@@ -4457,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");
@@ -4556,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) ?
@@ -4618,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;
@@ -4952,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 {
@@ -5133,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;
 }
 
@@ -5317,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:
@@ -5330,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;
 
@@ -5420,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;
@@ -5579,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);
 	}
@@ -5933,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);
@@ -6061,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);
 }
@@ -6586,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 b286a77..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);
@@ -1561,8 +1540,7 @@
 
 			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 ||
-			    !iface->bss[0]->wpa_auth)
+			    link_id != iface->bss[0]->mld_link_id)
 				continue;
 
 			wpa_auth_ml_get_rsn_info(iface->bss[0]->wpa_auth,
@@ -1604,8 +1582,7 @@
 
 			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 ||
-			    !iface->bss[0]->wpa_auth)
+			    link_id != iface->bss[0]->mld_link_id)
 				continue;
 
 			wpa_auth_ml_get_key_info(iface->bss[0]->wpa_auth,
@@ -1698,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;
 		}