[PATCH 6/9] BSS: Verify the ML common info for links

Benjamin Berg benjamin at sipsolutions.net
Wed Jun 18 05:35:28 PDT 2025


From: Benjamin Berg <benjamin.berg at intel.com>

Add a check that the AP MLD ADDR, the link ID, the MLD Capabilities and
Operations the Extended MLD Capabilities as well as the EML Capabilities
match between links.
If this is not the case, then refuse to use the offending link.

Signed-off-by: Benjamin Berg <benjamin.berg at intel.com>
---
 wpa_supplicant/bss.c | 78 ++++++++++++++++++++++++++++++++++++++++++--
 wpa_supplicant/bss.h |  6 ++++
 2 files changed, 81 insertions(+), 3 deletions(-)

diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c
index b5b6305f13..ce250655a5 100644
--- a/wpa_supplicant/bss.c
+++ b/wpa_supplicant/bss.c
@@ -1790,6 +1790,7 @@ u16 wpa_bss_get_usable_links(struct wpa_supplicant *wpa_s,
 
 	for_each_link(bss->valid_links, link_id) {
 		struct wpa_bss *neigh_bss;
+		u16 ext_mld_capa_mask;
 
 		if (link_id == bss->mld_link_id)
 			continue;
@@ -1809,6 +1810,55 @@ u16 wpa_bss_get_usable_links(struct wpa_supplicant *wpa_s,
 			continue;
 		}
 
+		/* Check that the links is MLD and the information matches */
+		if (!neigh_bss->valid_links) {
+			wpa_dbg(wpa_s, MSG_DEBUG,
+				"MLD: neighbor without Multi-Link support");
+			continue;
+		}
+
+		if (neigh_bss->mld_link_id != link_id) {
+			wpa_dbg(wpa_s, MSG_DEBUG,
+				"MLD: neighbor has unexpected link ID");
+			continue;
+		}
+
+		if (!ether_addr_equal(bss->mld_addr, neigh_bss->mld_addr)) {
+			wpa_dbg(wpa_s, MSG_DEBUG,
+				"MLD: neighbor has a different MLD addr");
+			continue;
+		}
+
+		if (bss->mld_capa != neigh_bss->mld_capa) {
+			wpa_dbg(wpa_s, MSG_DEBUG,
+				"MLD: neighbors MLD Capabilities are not matching");
+			continue;
+		}
+
+		if (bss->eml_capa != neigh_bss->eml_capa) {
+			wpa_dbg(wpa_s, MSG_DEBUG,
+				"MLD: neighbors EML Capabilities are not matching");
+			continue;
+		}
+
+		/*
+		 * Check well-defined values in Extended MLD Capabilities.
+		 * In particular the Recommended Max Simultaneous Links
+		 * subfield may change over time and is reserved depending on
+		 * the frame that it is carried in.
+		 * See IEEE P802.11be/D7.0, Table 9-417o.
+		 */
+		ext_mld_capa_mask =
+			EHT_ML_EXT_MLD_CAPA_OP_PARAM_UPDATE |
+			EHT_ML_EXT_MLD_CAPA_NSTR_UPDATE |
+			EHT_ML_EXT_MLD_CAPA_EMLSR_ENA_ONE_LINK;
+		if ((bss->ext_mld_capa & ext_mld_capa_mask) !=
+		    (neigh_bss->ext_mld_capa & ext_mld_capa_mask)) {
+			wpa_dbg(wpa_s, MSG_DEBUG,
+				"MLD: neighbors Extended MLD Capabilities are not matching");
+			continue;
+		}
+
 		if (ssid) {
 			int neigh_key_mgmt;
 
@@ -1921,17 +1971,25 @@ void wpa_bss_parse_basic_ml_element(struct wpa_supplicant *wpa_s,
 	    sizeof(*ml_basic_common_info) + 1 + 1 + 2)
 		goto out;
 
-	/* LINK_ID, BSS_PARAM_CH_COUNT, MLD_CAPA (see control/control_mask) */
+	/* LINK_ID, BSS_PARAM_CH_COUNT (see control/control_mask) */
 	link_id = ml_basic_common_info->variable[0] & EHT_ML_LINK_ID_MSK;
-	pos = 1 + 1 + 2;
+	pos = 1 + 1;
 
 	if (le_to_host16(eht_ml->ml_control) &
 	    BASIC_MULTI_LINK_CTRL_PRES_MSD_INFO)
 		pos += 2;
 
+	bss->eml_capa = 0;
 	if (le_to_host16(eht_ml->ml_control) &
-	    BASIC_MULTI_LINK_CTRL_PRES_EML_CAPA)
+	    BASIC_MULTI_LINK_CTRL_PRES_EML_CAPA) {
+		bss->eml_capa =
+			WPA_GET_LE16(&ml_basic_common_info->variable[pos]);
 		pos += 2;
+	}
+
+	/* MLD_CAPA (always present, see control/control_mask) */
+	bss->mld_capa = WPA_GET_LE16(&ml_basic_common_info->variable[pos]);
+	pos += 2;
 
 	/* AP MLD ID from ML-Element if present (see comment below) */
 	if (le_to_host16(eht_ml->ml_control) &
@@ -1947,6 +2005,20 @@ void wpa_bss_parse_basic_ml_element(struct wpa_supplicant *wpa_s,
 		ap_mld_id = 0;
 	}
 
+	/* Extended MLD Capabilities */
+	bss->ext_mld_capa = 0;
+	if (le_to_host16(eht_ml->ml_control) &
+	    BASIC_MULTI_LINK_CTRL_PRES_EXT_MLD_CAP) {
+		if (ml_basic_common_info->len <
+		    sizeof(*ml_basic_common_info) + pos + 2)
+			goto out;
+
+		bss->ext_mld_capa =
+			WPA_GET_LE16(&ml_basic_common_info->variable[pos]);
+
+		pos += 2;
+	}
+
 	if (ml_basic_common_info->len < sizeof(*ml_basic_common_info) + pos)
 		goto out;
 
diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h
index 4bd752fda2..8a86489a04 100644
--- a/wpa_supplicant/bss.h
+++ b/wpa_supplicant/bss.h
@@ -127,6 +127,12 @@ struct wpa_bss {
 	u8 mld_link_id;
 	/** For MLD, denotes if BSS is non-TX; useful for ML probe */
 	bool mld_bss_non_transmitted;
+	/** MLD Capabilities and Operations */
+	u16 mld_capa;
+	/** Extended MLD Capabilities and Operations */
+	u16 ext_mld_capa;
+	/** EML Capabilities */
+	u16 eml_capa;
 
 	/** An array of MLD links, any link found in the RNR is "valid" */
 	u16 valid_links;
-- 
2.49.0




More information about the Hostap mailing list