Revert "Revert "[wpa_supplicant] cumilative patch from commit 4b..."

Revert submission 28102966-revert-26533062-Supplicant_merge_June24-CUATTSRBBR

Fixed the regression issue (ag/28389573)
Bug: 329004037

Reverted changes: /q/submissionid:28102966-revert-26533062-Supplicant_merge_June24-CUATTSRBBR

Test: Turn ON/OFF SoftAp

Change-Id: Ie7ea1ee7f8b1311fce280907d37a2e321542f547
diff --git a/hostapd/Android.bp b/hostapd/Android.bp
index 93151f2..8b79dd5 100644
--- a/hostapd/Android.bp
+++ b/hostapd/Android.bp
@@ -224,6 +224,7 @@
         "src/common/ieee802_11_common.c",
         "src/common/wpa_common.c",
         "src/common/hw_features_common.c",
+        "src/common/ptksa_cache.c",
         "src/eapol_auth/eapol_auth_sm.c",
         "src/eapol_auth/eapol_auth_dump.c",
         "src/ap/vlan_init.c",
@@ -315,6 +316,7 @@
         "src/ap/ap_list.c",
         "src/ap/comeback_token.c",
         "src/pasn/pasn_responder.c",
+        "src/pasn/pasn_common.c",
         "src/ap/ieee802_11.c",
         "src/ap/hw_features.c",
         "src/ap/dfs.c",
diff --git a/hostapd/Android.mk b/hostapd/Android.mk
index d916488..d5d1190 100644
--- a/hostapd/Android.mk
+++ b/hostapd/Android.mk
@@ -170,6 +170,7 @@
 OBJS += src/common/ieee802_11_common.c
 OBJS += src/common/wpa_common.c
 OBJS += src/common/hw_features_common.c
+OBJS += src/common/ptksa_cache.c
 
 OBJS += src/eapol_auth/eapol_auth_sm.c
 
@@ -614,7 +615,6 @@
 NEED_HMAC_SHA384_KDF=y
 NEED_SHA256=y
 NEED_SHA384=y
-OBJS += src/common/ptksa_cache.c
 endif
 
 ifdef CONFIG_EAP_IKEV2
@@ -667,6 +667,11 @@
 OBJS += src/eap_common/chap.c
 endif
 
+ifdef CONFIG_RADIUS_TLS
+TLS_FUNCS=y
+L_CFLAGS += -DCONFIG_RADIUS_TLS
+endif
+
 ifdef TLS_FUNCS
 NEED_DES=y
 # Shared TLS functions (needed for EAP_TLS, EAP_PEAP, and EAP_TTLS)
@@ -1066,6 +1071,7 @@
 OBJS += src/ap/ap_list.c
 OBJS += src/ap/comeback_token.c
 OBJS += src/pasn/pasn_responder.c
+OBJS += src/pasn/pasn_common.c
 OBJS += src/ap/ieee802_11.c
 OBJS += src/ap/hw_features.c
 OBJS += src/ap/dfs.c
diff --git a/hostapd/Makefile b/hostapd/Makefile
index 274a82d..489922c 100644
--- a/hostapd/Makefile
+++ b/hostapd/Makefile
@@ -84,6 +84,7 @@
 OBJS += ../src/ap/bss_load.o
 OBJS += ../src/ap/neighbor_db.o
 OBJS += ../src/ap/rrm.o
+OBJS += ../src/common/ptksa_cache.o
 
 OBJS_c = hostapd_cli.o
 OBJS_c += ../src/common/wpa_ctrl.o
@@ -624,7 +625,6 @@
 NEED_HMAC_SHA384_KDF=y
 NEED_SHA256=y
 NEED_SHA384=y
-OBJS += ../src/common/ptksa_cache.o
 endif
 
 ifdef CONFIG_EAP_IKEV2
@@ -686,6 +686,11 @@
 OBJS += ../src/eap_common/chap.o
 endif
 
+ifdef CONFIG_RADIUS_TLS
+TLS_FUNCS=y
+CFLAGS += -DCONFIG_RADIUS_TLS
+endif
+
 ifdef TLS_FUNCS
 NEED_DES=y
 # Shared TLS functions (needed for EAP_TLS, EAP_PEAP, and EAP_TTLS)
@@ -1196,6 +1201,7 @@
 OBJS += ../src/ap/ap_list.o
 OBJS += ../src/ap/comeback_token.o
 OBJS += ../src/pasn/pasn_responder.o
+OBJS += ../src/pasn/pasn_common.o
 OBJS += ../src/ap/ieee802_11.o
 OBJS += ../src/ap/hw_features.o
 OBJS += ../src/ap/dfs.o
diff --git a/hostapd/android.config b/hostapd/android.config
index 9d20c8d..4040d41 100644
--- a/hostapd/android.config
+++ b/hostapd/android.config
@@ -126,6 +126,9 @@
 # Build IPv6 support for RADIUS operations
 CONFIG_IPV6=y
 
+# Include support fo RADIUS/TLS into the RADIUS client
+#CONFIG_RADIUS_TLS=y
+
 # IEEE Std 802.11r-2008 (Fast BSS Transition)
 #CONFIG_IEEE80211R=y
 
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 79cc1c2..76e9249 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -1678,6 +1678,8 @@
 	return 0;
 }
 
+#endif /* CONFIG_INTERWORKING */
+
 
 static int parse_qos_map_set(struct hostapd_bss_config *bss,
 			     char *buf, int line)
@@ -1719,8 +1721,6 @@
 	return 0;
 }
 
-#endif /* CONFIG_INTERWORKING */
-
 
 #ifdef CONFIG_HS20
 static int hs20_parse_conn_capab(struct hostapd_bss_config *bss, char *buf,
@@ -2869,6 +2869,37 @@
 		os_free(bss->radius->auth_server->shared_secret);
 		bss->radius->auth_server->shared_secret = (u8 *) os_strdup(pos);
 		bss->radius->auth_server->shared_secret_len = len;
+	} else if (bss->radius->auth_server &&
+		   os_strcmp(buf, "auth_server_type") == 0) {
+		if (os_strcmp(pos, "UDP") == 0) {
+			bss->radius->auth_server->tls = false;
+#ifdef CONFIG_RADIUS_TLS
+		} else if (os_strcmp(pos, "TLS") == 0) {
+			bss->radius->auth_server->tls = true;
+#endif /* CONFIG_RADIUS_TLS */
+		} else {
+			wpa_printf(MSG_ERROR, "Line %d: unsupported RADIUS type '%s'",
+				   line, pos);
+			return 1;
+		}
+#ifdef CONFIG_RADIUS_TLS
+	} else if (bss->radius->auth_server &&
+		   os_strcmp(buf, "auth_server_ca_cert") == 0) {
+		os_free(bss->radius->auth_server->ca_cert);
+		bss->radius->auth_server->ca_cert = os_strdup(pos);
+	} else if (bss->radius->auth_server &&
+		   os_strcmp(buf, "auth_server_client_cert") == 0) {
+		os_free(bss->radius->auth_server->client_cert);
+		bss->radius->auth_server->client_cert = os_strdup(pos);
+	} else if (bss->radius->auth_server &&
+		   os_strcmp(buf, "auth_server_private_key") == 0) {
+		os_free(bss->radius->auth_server->private_key);
+		bss->radius->auth_server->private_key = os_strdup(pos);
+	} else if (bss->radius->auth_server &&
+		   os_strcmp(buf, "auth_server_private_key_passwd") == 0) {
+		os_free(bss->radius->auth_server->private_key_passwd);
+		bss->radius->auth_server->private_key_passwd = os_strdup(pos);
+#endif /* CONFIG_RADIUS_TLS */
 	} else if (os_strcmp(buf, "acct_server_addr") == 0) {
 		if (hostapd_config_read_radius_addr(
 			    &bss->radius->acct_servers,
@@ -2903,6 +2934,37 @@
 		os_free(bss->radius->acct_server->shared_secret);
 		bss->radius->acct_server->shared_secret = (u8 *) os_strdup(pos);
 		bss->radius->acct_server->shared_secret_len = len;
+	} else if (bss->radius->acct_server &&
+		   os_strcmp(buf, "acct_server_type") == 0) {
+		if (os_strcmp(pos, "UDP") == 0) {
+			bss->radius->acct_server->tls = false;
+#ifdef CONFIG_RADIUS_TLS
+		} else if (os_strcmp(pos, "TLS") == 0) {
+			bss->radius->acct_server->tls = true;
+#endif /* CONFIG_RADIUS_TLS */
+		} else {
+			wpa_printf(MSG_ERROR, "Line %d: unsupported RADIUS type '%s'",
+				   line, pos);
+			return 1;
+		}
+#ifdef CONFIG_RADIUS_TLS
+	} else if (bss->radius->acct_server &&
+		   os_strcmp(buf, "acct_server_ca_cert") == 0) {
+		os_free(bss->radius->acct_server->ca_cert);
+		bss->radius->acct_server->ca_cert = os_strdup(pos);
+	} else if (bss->radius->acct_server &&
+		   os_strcmp(buf, "acct_server_client_cert") == 0) {
+		os_free(bss->radius->acct_server->client_cert);
+		bss->radius->acct_server->client_cert = os_strdup(pos);
+	} else if (bss->radius->acct_server &&
+		   os_strcmp(buf, "acct_server_private_key") == 0) {
+		os_free(bss->radius->acct_server->private_key);
+		bss->radius->acct_server->private_key = os_strdup(pos);
+	} else if (bss->radius->acct_server &&
+		   os_strcmp(buf, "acct_server_private_key_passwd") == 0) {
+		os_free(bss->radius->acct_server->private_key_passwd);
+		bss->radius->acct_server->private_key_passwd = os_strdup(pos);
+#endif /* CONFIG_RADIUS_TLS */
 	} else if (os_strcmp(buf, "radius_retry_primary_interval") == 0) {
 		bss->radius->retry_primary_interval = atoi(pos);
 	} else if (os_strcmp(buf, "radius_acct_interim_interval") == 0) {
@@ -4196,10 +4258,10 @@
 		bss->gas_frag_limit = val;
 	} else if (os_strcmp(buf, "gas_comeback_delay") == 0) {
 		bss->gas_comeback_delay = atoi(pos);
+#endif /* CONFIG_INTERWORKING */
 	} else if (os_strcmp(buf, "qos_map_set") == 0) {
 		if (parse_qos_map_set(bss, pos, line) < 0)
 			return 1;
-#endif /* CONFIG_INTERWORKING */
 #ifdef CONFIG_RADIUS_TEST
 	} else if (os_strcmp(buf, "dump_msk_file") == 0) {
 		os_free(bss->dump_msk_file);
@@ -4604,6 +4666,10 @@
 				WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE |
 				WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE |
 				WLAN_RRM_CAPS_BEACON_REPORT_TABLE;
+	} else if (os_strcmp(buf, "rrm_link_measurement_report") == 0) {
+		if (atoi(pos))
+			bss->radio_measurements[0] |=
+				WLAN_RRM_CAPS_LINK_MEASUREMENT;
 	} else if (os_strcmp(buf, "gas_address3") == 0) {
 		bss->gas_address3 = atoi(pos);
 	} else if (os_strcmp(buf, "stationary_ap") == 0) {
@@ -4744,6 +4810,36 @@
 		}
 
 		bss->multi_ap = val;
+	} else if (os_strcmp(buf, "multi_ap_profile") == 0) {
+		int val = atoi(pos);
+
+		if (val < MULTI_AP_PROFILE_1 || val > MULTI_AP_PROFILE_MAX) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: Invalid multi_ap_profile '%s'",
+				   line, buf);
+			return -1;
+		}
+		bss->multi_ap_profile = val;
+	} else if (os_strcmp(buf, "multi_ap_client_disallow") == 0) {
+		int val = atoi(pos);
+
+		if (val < 0 || val > 3) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: Invalid multi_ap_client_allow '%s'",
+				   line, buf);
+			return -1;
+		}
+		bss->multi_ap_client_disallow = val;
+	} else if (os_strcmp(buf, "multi_ap_vlanid") == 0) {
+		int val = atoi(pos);
+
+		if (val < 0 || val > MAX_VLAN_ID) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: Invalid multi_ap_vlan_id '%s'",
+				   line, buf);
+			return -1;
+		}
+		bss->multi_ap_vlanid = val;
 	} else if (os_strcmp(buf, "rssi_reject_assoc_rssi") == 0) {
 		conf->rssi_reject_assoc_rssi = atoi(pos);
 	} else if (os_strcmp(buf, "rssi_reject_assoc_timeout") == 0) {
@@ -4956,8 +5052,6 @@
 		conf->punct_acs_threshold = val;
 	} else if (os_strcmp(buf, "mld_ap") == 0) {
 		bss->mld_ap = !!atoi(pos);
-	} else if (os_strcmp(buf, "mld_id") == 0) {
-		bss->mld_id = atoi(pos);
 	} else if (os_strcmp(buf, "mld_addr") == 0) {
 		if (hwaddr_aton(pos, bss->mld_addr)) {
 			wpa_printf(MSG_ERROR, "Line %d: Invalid mld_addr",
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index a6b16c2..d07567d 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -1309,6 +1309,8 @@
 			hostapd_disassoc_deny_mac(hapd);
 		} else if (os_strcasecmp(cmd, "accept_mac_file") == 0) {
 			hostapd_disassoc_accept_mac(hapd);
+		} else if (os_strcasecmp(cmd, "ssid") == 0) {
+			hostapd_neighbor_sync_own_report(hapd);
 		} else if (os_strncmp(cmd, "wme_ac_", 7) == 0 ||
 			   os_strncmp(cmd, "wmm_ac_", 7) == 0) {
 			hapd->parameter_set_count++;
@@ -1946,7 +1948,7 @@
 
 #ifdef CONFIG_IEEE80211BE
 	if (hapd->conf->mld_ap)
-		addr = hapd->mld_addr;
+		addr = hapd->mld->mld_addr;
 #endif /* CONFIG_IEEE80211BE */
 	hapd->l2_test = l2_packet_init(ifname, addr,
 					ETHERTYPE_IP, hostapd_data_test_rx,
@@ -2642,6 +2644,8 @@
 	unsigned int i;
 	int bandwidth;
 	u8 chan;
+	unsigned int num_err = 0;
+	int err = 0;
 
 	ret = hostapd_parse_csa_settings(pos, &settings);
 	if (ret)
@@ -2715,6 +2719,7 @@
 			   settings.freq_params.center_freq1);
 
 		/* Perform CAC and switch channel */
+		iface->is_ch_switch_dfs = true;
 		hostapd_switch_channel_fallback(iface, &settings.freq_params);
 		return 0;
 	}
@@ -2725,15 +2730,14 @@
 		hostapd_chan_switch_config(iface->bss[i],
 					   &settings.freq_params);
 
-		ret = hostapd_switch_channel(iface->bss[i], &settings);
-		if (ret) {
-			/* FIX: What do we do if CSA fails in the middle of
-			 * submitting multi-BSS CSA requests? */
-			return ret;
+		err = hostapd_switch_channel(iface->bss[i], &settings);
+		if (err) {
+			ret = err;
+			num_err++;
 		}
 	}
 
-	return 0;
+	return (iface->num_bss == num_err) ? ret : 0;
 #else /* NEED_AP_MLME */
 	return -1;
 #endif /* NEED_AP_MLME */
@@ -3207,6 +3211,26 @@
 }
 
 
+static int hostapd_ctrl_iface_req_link_measurement(struct hostapd_data *hapd,
+						   const char *cmd, char *reply,
+						   size_t reply_size)
+{
+	u8 addr[ETH_ALEN];
+	int ret;
+
+	if (hwaddr_aton(cmd, addr)) {
+		wpa_printf(MSG_ERROR,
+			   "CTRL: REQ_LINK_MEASUREMENT: Invalid MAC address");
+		return -1;
+	}
+
+	ret = hostapd_send_link_measurement_req(hapd, addr);
+	if (ret >= 0)
+		ret = os_snprintf(reply, reply_size, "%d", ret);
+	return ret;
+}
+
+
 static int hostapd_ctrl_iface_show_neighbor(struct hostapd_data *hapd,
 					    char *buf, size_t buflen)
 {
@@ -3477,10 +3501,8 @@
 	for (i = 0; i < iface->interfaces->count; ++i) {
 		struct hostapd_iface *h_iface = iface->interfaces->iface[i];
 		struct hostapd_data *h_hapd = h_iface->bss[0];
-		struct hostapd_bss_config *h_conf = h_hapd->conf;
 
-		if (!h_conf->mld_ap ||
-		    h_conf->mld_id != iface->bss[0]->conf->mld_id)
+		if (!hostapd_is_ml_partner(h_hapd, iface->bss[0]))
 			continue;
 
 		if (hostapd_enable_iface(h_iface)) {
@@ -3504,7 +3526,6 @@
 static int hostapd_ctrl_iface_disable_mld(struct hostapd_iface *iface)
 {
 	unsigned int i;
-	struct hostapd_iface *first_iface = NULL;
 
 	if (!iface || !iface->bss[0]->conf->mld_ap) {
 		wpa_printf(MSG_ERROR,
@@ -3518,32 +3539,19 @@
 	for (i = 0; i < iface->interfaces->count; ++i) {
 		struct hostapd_iface *h_iface = iface->interfaces->iface[i];
 		struct hostapd_data *h_hapd = h_iface->bss[0];
-		struct hostapd_bss_config *h_conf = h_hapd->conf;
 
-		if (!h_conf->mld_ap ||
-		    h_conf->mld_id != iface->bss[0]->conf->mld_id)
+		if (!hostapd_is_ml_partner(h_hapd, iface->bss[0]))
 			continue;
 
-		if (!h_hapd->mld_first_bss) {
-			first_iface = h_iface;
-			continue;
-		}
 		hostapd_disable_iface_bss(iface);
 	}
 
-	if (first_iface)
-		hostapd_disable_iface_bss(first_iface);
-
 	/* Then, fully disable interfaces */
-
 	for (i = 0; i < iface->interfaces->count; ++i) {
 		struct hostapd_iface *h_iface = iface->interfaces->iface[i];
 		struct hostapd_data *h_hapd = h_iface->bss[0];
-		struct hostapd_bss_config *h_conf = h_hapd->conf;
 
-		if (!h_conf->mld_ap ||
-		    h_conf->mld_id != iface->bss[0]->conf->mld_id ||
-		    !h_hapd->mld_first_bss)
+		if (!hostapd_is_ml_partner(h_hapd, iface->bss[0]))
 			continue;
 
 		if (hostapd_disable_iface(h_iface)) {
@@ -3552,11 +3560,6 @@
 		}
 	}
 
-	if (first_iface && hostapd_disable_iface(first_iface)) {
-		wpa_printf(MSG_ERROR, "Disabling AP MLD failed");
-		return -1;
-	}
-
 	return 0;
 }
 
@@ -4206,6 +4209,9 @@
 	} else if (os_strncmp(buf, "REQ_BEACON ", 11) == 0) {
 		reply_len = hostapd_ctrl_iface_req_beacon(hapd, buf + 11,
 							  reply, reply_size);
+	} else if (os_strncmp(buf, "REQ_LINK_MEASUREMENT ", 21) == 0) {
+		reply_len = hostapd_ctrl_iface_req_link_measurement(
+			hapd, buf + 21, reply, reply_size);
 	} else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) {
 		reply_len = hostapd_ctrl_driver_flags(hapd->iface, reply,
 						      reply_size);
@@ -5362,7 +5368,7 @@
 			reply_len = -1;
 	} else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
 		reply_len = hostapd_global_ctrl_iface_interfaces(
-			interfaces, buf + 10, reply, sizeof(buffer));
+			interfaces, buf + 10, reply, reply_size);
 	} else if (os_strcmp(buf, "TERMINATE") == 0) {
 		eloop_terminate();
 	} else {
diff --git a/hostapd/defconfig b/hostapd/defconfig
index 5d769e9..43cf99f 100644
--- a/hostapd/defconfig
+++ b/hostapd/defconfig
@@ -141,6 +141,9 @@
 # Build IPv6 support for RADIUS operations
 CONFIG_IPV6=y
 
+# Include support fo RADIUS/TLS into the RADIUS client
+#CONFIG_RADIUS_TLS=y
+
 # IEEE Std 802.11r-2008 (Fast BSS Transition)
 #CONFIG_IEEE80211R=y
 
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index 1357649..e34d75c 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -1071,9 +1071,6 @@
 # 1 = yes (MLO)
 #mld_ap=0
 
-# MLD ID - Affiliated MLD ID
-#mld_id=1
-
 # AP MLD MAC address
 # The configured address will be set as the interface hardware address and used
 # as the AP MLD MAC address. If not set, the current interface hardware address
@@ -1581,6 +1578,16 @@
 #acct_server_port=1813
 #acct_server_shared_secret=secret2
 
+# RADIUS/TLS instead of RADIUS/UDP
+#auth_server_addr=127.0.0.1
+#auth_server_port=2083
+#auth_server_type=TLS
+#auth_server_shared_secret=radsec
+#auth_server_ca_cert=<path to trusted CA certificate(s)>
+#auth_server_client_cert=<path to client certificate>
+#auth_server_private_key=<path to private key>
+#auth_server_private_key_passwd=<password for decrypting private key>
+
 # Retry interval for trying to return to the primary RADIUS server (in
 # seconds). RADIUS client code will automatically try to use the next server
 # when the current server is not replying to requests. If this interval is set,
@@ -2555,6 +2562,23 @@
 #multi_ap_backhaul_wpa_psk=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
 #multi_ap_backhaul_wpa_passphrase=secret passphrase
 
+# Multi-AP Profile
+# Indicate the supported Multi-AP profile (default: 2)
+# 1 = Supports Multi-AP profile 1 as defined in Wi-Fi EasyMesh specification
+# 2 = Supports Multi-AP profile 2 as defined in Wi-Fi EasyMesh specification
+#multi_ap_profile=2
+
+# Multi-AP client disallow
+# Used to disallow profile specific backhaul STA association
+# Bitmap of the disallowed Profile-X profiles
+# 1 = Profile-1 Backhaul STA association disallowed
+# 2 = Profile-2 Backhaul STA association disallowed
+#multi_ap_client_disallow=0
+
+# Multi-AP VLAN ID
+# A valid non-zero VLAN ID will be used to update Default IEEE 802.1Q Setting
+#multi_ap_vlanid=0
+
 # WPS UPnP interface
 # If set, support for external Registrars is enabled.
 #upnp_iface=br0
@@ -3088,6 +3112,9 @@
 # Enable neighbor report via radio measurements
 #rrm_neighbor_report=1
 
+# Enable link measurement report via radio measurements
+#rrm_link_measurement_report=1
+
 # Enable beacon report via radio measurements
 #rrm_beacon_report=1
 
diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
index 8fb6119..e1fe286 100644
--- a/hostapd/hostapd_cli.c
+++ b/hostapd/hostapd_cli.c
@@ -1215,14 +1215,14 @@
 
 
 static int hostapd_cli_cmd_enable(struct wpa_ctrl *ctrl, int argc,
-				      char *argv[])
+				  char *argv[])
 {
 	return wpa_ctrl_command(ctrl, "ENABLE");
 }
 
 
 static int hostapd_cli_cmd_reload(struct wpa_ctrl *ctrl, int argc,
-				      char *argv[])
+				  char *argv[])
 {
 	return wpa_ctrl_command(ctrl, "RELOAD");
 }
@@ -1243,7 +1243,7 @@
 
 
 static int hostapd_cli_cmd_disable(struct wpa_ctrl *ctrl, int argc,
-				      char *argv[])
+				   char *argv[])
 {
 	return wpa_ctrl_command(ctrl, "DISABLE");
 }
@@ -1257,19 +1257,26 @@
 
 
 static int hostapd_cli_cmd_disable_mld(struct wpa_ctrl *ctrl, int argc,
-				      char *argv[])
+				       char *argv[])
 {
 	return wpa_ctrl_command(ctrl, "DISABLE_MLD");
 }
 
 
 static int hostapd_cli_cmd_update_beacon(struct wpa_ctrl *ctrl, int argc,
-				      char *argv[])
+					 char *argv[])
 {
 	return wpa_ctrl_command(ctrl, "UPDATE_BEACON");
 }
 
 
+static int hostapd_cli_cmd_stop_ap(struct wpa_ctrl *ctrl, int argc,
+				   char *argv[])
+{
+	return wpa_ctrl_command(ctrl, "STOP_AP");
+}
+
+
 static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
 	char cmd[256];
@@ -1598,6 +1605,13 @@
 }
 
 
+static int hostapd_cli_cmd_req_link_measurement(struct wpa_ctrl *ctrl, int argc,
+						char *argv[])
+{
+	return hostapd_cli_cmd(ctrl, "REQ_LINK_MEASUREMENT", 1, argc, argv);
+}
+
+
 static int hostapd_cli_cmd_reload_wpa_psk(struct wpa_ctrl *ctrl, int argc,
 					  char *argv[])
 {
@@ -1759,6 +1773,8 @@
 	  "= disable AP MLD to which the interface is affiliated" },
 	{ "update_beacon", hostapd_cli_cmd_update_beacon, NULL,
 	  "= update Beacon frame contents\n"},
+	{ "stop_ap", hostapd_cli_cmd_stop_ap, NULL,
+	  "= stop AP\n"},
 	{ "erp_flush", hostapd_cli_cmd_erp_flush, NULL,
 	  "= drop all ERP keys"},
 	{ "log_level", hostapd_cli_cmd_log_level, NULL,
@@ -1838,6 +1854,8 @@
 	  "<addr> = poll a STA to check connectivity with a QoS null frame" },
 	{ "req_beacon", hostapd_cli_cmd_req_beacon, NULL,
 	  "<addr> [req_mode=] <measurement request hexdump>  = send a Beacon report request to a station" },
+	{ "req_link_measurement", hostapd_cli_cmd_req_link_measurement, NULL,
+	  "<addr> = send a link measurement report request to a station"},
 	{ "reload_wpa_psk", hostapd_cli_cmd_reload_wpa_psk, NULL,
 	  "= reload wpa_psk_file only" },
 #ifdef CONFIG_IEEE80211R_AP
diff --git a/hostapd/main.c b/hostapd/main.c
index 0fe2d74..3a14381 100644
--- a/hostapd/main.c
+++ b/hostapd/main.c
@@ -177,9 +177,15 @@
 			continue;
 		}
 
-		if (!hconf->mld_ap || hconf->mld_id != conf->mld_id) {
+		if (!hconf->mld_ap) {
 			wpa_printf(MSG_DEBUG,
-				   "MLD: Skip non matching mld_id");
+				   "MLD: Skip non-MLD");
+			continue;
+		}
+
+		if (!hostapd_is_ml_partner(hapd, h_hapd)) {
+			wpa_printf(MSG_DEBUG,
+				   "MLD: Skip non matching MLD vif name");
 			continue;
 		}
 
@@ -191,6 +197,7 @@
 		}
 
 		hapd->drv_priv = h_hapd->drv_priv;
+		hapd->interface_added = h_hapd->interface_added;
 
 		/*
 		 * All interfaces participating in the AP MLD would have
@@ -200,20 +207,15 @@
 		 * is not configured, and otherwise it would be the
 		 * configured BSSID.
 		 */
-		os_memcpy(hapd->mld_addr, h_hapd->mld_addr, ETH_ALEN);
 		if (is_zero_ether_addr(b)) {
-			os_memcpy(hapd->own_addr, h_hapd->mld_addr, ETH_ALEN);
+			os_memcpy(hapd->own_addr, h_hapd->mld->mld_addr,
+				  ETH_ALEN);
 			random_mac_addr_keep_oui(hapd->own_addr);
 		} else {
 			os_memcpy(hapd->own_addr, b, ETH_ALEN);
 		}
 
-		/*
-		 * Mark the interface as a secondary interface, as this
-		 * is needed for the de-initialization flow
-		 */
-		hapd->mld_first_bss = h_hapd;
-		hapd->mld_link_id = hapd->mld_first_bss->mld_next_link_id++;
+		hostapd_mld_add_link(hapd);
 
 		goto setup_mld;
 	}
@@ -290,13 +292,14 @@
 	 * configured, and otherwise it would be the configured BSSID.
 	 */
 	if (hapd->conf->mld_ap) {
-		os_memcpy(hapd->mld_addr, hapd->own_addr, ETH_ALEN);
-		hapd->mld_next_link_id = 0;
-		hapd->mld_link_id = hapd->mld_next_link_id++;
+		os_memcpy(hapd->mld->mld_addr, hapd->own_addr, ETH_ALEN);
+
 		if (!b)
 			random_mac_addr_keep_oui(hapd->own_addr);
 		else
 			os_memcpy(hapd->own_addr, b, ETH_ALEN);
+
+		hostapd_mld_add_link(hapd);
 	}
 
 setup_mld:
@@ -308,6 +311,7 @@
 
 		iface->drv_flags = capa.flags;
 		iface->drv_flags2 = capa.flags2;
+		iface->drv_rrm_flags = capa.rrm_flags;
 		iface->probe_resp_offloads = capa.probe_resp_offloads;
 		/*
 		 * Use default extended capa values from per-radio information
@@ -350,7 +354,7 @@
 		wpa_printf(MSG_DEBUG,
 			   "MLD: Set link_id=%u, mld_addr=" MACSTR
 			   ", own_addr=" MACSTR,
-			   hapd->mld_link_id, MAC2STR(hapd->mld_addr),
+			   hapd->mld_link_id, MAC2STR(hapd->mld->mld_addr),
 			   MAC2STR(hapd->own_addr));
 
 		hostapd_drv_link_add(hapd, hapd->mld_link_id,
@@ -758,6 +762,29 @@
 }
 
 
+static void hostapd_global_cleanup_mld(struct hapd_interfaces *interfaces)
+{
+#ifdef CONFIG_IEEE80211BE
+	size_t i;
+
+	if (!interfaces || !interfaces->mld)
+		return;
+
+	for (i = 0; i < interfaces->mld_count; i++) {
+		if (!interfaces->mld[i])
+			continue;
+
+		os_free(interfaces->mld[i]);
+		interfaces->mld[i] = NULL;
+	}
+
+	os_free(interfaces->mld);
+	interfaces->mld = NULL;
+	interfaces->mld_count = 0;
+#endif /* CONFIG_IEEE80211BE */
+}
+
+
 int main(int argc, char *argv[])
 {
 	struct hapd_interfaces interfaces;
@@ -1043,6 +1070,8 @@
 	interfaces.iface = NULL;
 	interfaces.count = 0;
 
+	hostapd_global_cleanup_mld(&interfaces);
+
 #ifdef CONFIG_DPP
 	dpp_global_deinit(interfaces.dpp);
 #endif /* CONFIG_DPP */