[PATCH] mbssid: process known BSSID element

Aloka Dixit quic_alokad at quicinc.com
Wed May 11 13:49:29 PDT 2022


Process the known BSSID elements if included by non-AP stations.
The format is described in IEEE Std 802.11ax-2021 9.4.2.261.

Non-AP stations may include this element in directed probe requests
to indicate which of the multiple BSSIDs they have already discovered.
AP should exclude these profiles from the probe response.

Signed-off-by: Aloka Dixit <quic_alokad at quicinc.com>
---
 src/ap/beacon.c                | 26 ++++++++++++++++----------
 src/ap/ieee802_11.c            | 31 +++++++++++++++++++++++++------
 src/ap/ieee802_11.h            |  7 ++++---
 src/common/ieee802_11_common.c |  4 ++++
 src/common/ieee802_11_common.h |  2 ++
 src/common/ieee802_11_defs.h   |  1 +
 6 files changed, 52 insertions(+), 19 deletions(-)

diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index 85871693db3c..b43be6a374ae 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -479,7 +479,8 @@ static int ieee802_11_build_ap_params_mbssid(struct hostapd_data *hapd,
 		goto fail;
 
 	tx_bss = hostapd_mbssid_get_tx_bss(hapd);
-	len = hostapd_eid_mbssid_len(tx_bss, WLAN_FC_STYPE_BEACON, &elem_count);
+	len = hostapd_eid_mbssid_len(tx_bss, WLAN_FC_STYPE_BEACON, &elem_count,
+				     NULL, 0);
 	if (!len || (iface->conf->mbssid == ENHANCED_MBSSID_ENABLED &&
 		     elem_count > iface->ema_max_periodicity))
 		goto fail;
@@ -493,7 +494,7 @@ static int ieee802_11_build_ap_params_mbssid(struct hostapd_data *hapd,
 		goto fail;
 
 	end = hostapd_eid_mbssid(tx_bss, elem, elem + len, WLAN_FC_STYPE_BEACON,
-				 elem_count, elem_offset);
+				 elem_count, elem_offset, NULL, 0);
 
 	params->mbssid_tx_iface = tx_bss->conf->iface;
 	params->mbssid_index = hostapd_mbssid_get_bss_index(hapd);
@@ -523,7 +524,8 @@ fail:
 static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
 				   const struct ieee80211_mgmt *req,
 				   int is_p2p, size_t *resp_len,
-				   bool bcast_probe_resp)
+				   bool bcast_probe_resp, const u8 *known_bss,
+				   u8 known_bss_len)
 {
 	struct ieee80211_mgmt *resp;
 	u8 *pos, *epos, *csa_pos, *ext_cap_pos;
@@ -577,7 +579,8 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
 	}
 #endif /* CONFIG_IEEE80211BE */
 
-	buflen += hostapd_eid_mbssid_len(hapd, WLAN_FC_STYPE_PROBE_RESP, NULL);
+	buflen += hostapd_eid_mbssid_len(hapd, WLAN_FC_STYPE_PROBE_RESP, NULL,
+					 known_bss, known_bss_len);
 	buflen += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_PROBE_RESP);
 	buflen += hostapd_mbo_ie_len(hapd);
 	buflen += hostapd_eid_owe_trans_len(hapd);
@@ -650,13 +653,15 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
 	pos = hostapd_eid_ht_capabilities(hapd, pos);
 	pos = hostapd_eid_ht_operation(hapd, pos);
 	pos = hostapd_eid_mbssid(hapd, pos, epos, WLAN_FC_STYPE_PROBE_RESP, 0,
-				 NULL);
+				 NULL, known_bss, known_bss_len);
 
 	ext_cap_pos = pos;
 	pos = hostapd_eid_ext_capab(hapd, pos);
-	if (hapd->iconf->mbssid >= MBSSID_ENABLED)
+	if (hapd->iconf->mbssid >= MBSSID_ENABLED && !known_bss_len)
 		ext_cap_pos[12] |= 0x01; /* Probe responses always include all
-					  * non-tx profiles */
+					  * non-tx profiles except when a list
+					  * of known BSSes is included in the
+					  * probe request. */
 
 	pos = hostapd_eid_time_adv(hapd, pos);
 	pos = hostapd_eid_time_zone(hapd, pos);
@@ -1217,7 +1222,8 @@ void handle_probe_req(struct hostapd_data *hapd,
 		     " signal=%d", MAC2STR(mgmt->sa), ssi_signal);
 
 	resp = hostapd_gen_probe_resp(hapd, mgmt, elems.p2p != NULL,
-				      &resp_len, false);
+				      &resp_len, false, elems.mbssid_known_bss,
+				      elems.mbssid_known_bss_len);
 	if (resp == NULL)
 		return;
 
@@ -1287,7 +1293,7 @@ static u8 * hostapd_probe_resp_offloads(struct hostapd_data *hapd,
 			   "this");
 
 	/* Generate a Probe Response template for the non-P2P case */
-	return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len, false);
+	return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len, false, NULL, 0);
 }
 
 #endif /* NEED_AP_MLME */
@@ -1306,7 +1312,7 @@ static u8 * hostapd_unsol_bcast_probe_resp(struct hostapd_data *hapd,
 
 	return hostapd_gen_probe_resp(hapd, NULL, 0,
 				      &params->unsol_bcast_probe_resp_tmpl_len,
-				      true);
+				      true, NULL, 0);
 }
 #endif /* CONFIG_IEEE80211AX */
 
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 41bc450dc168..bcdd032e15bf 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -7567,7 +7567,9 @@ u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type)
 
 
 static size_t hostapd_eid_mbssid_elem_len(struct hostapd_data *hapd,
-					  u32 frame_type, size_t *bss_index)
+					  u32 frame_type, size_t *bss_index,
+					  const u8 *known_bss,
+					  size_t known_bss_len)
 {
 	struct hostapd_data *tx_bss = hostapd_mbssid_get_tx_bss(hapd);
 	size_t len = 3, i;
@@ -7578,6 +7580,12 @@ static size_t hostapd_eid_mbssid_elem_len(struct hostapd_data *hapd,
 		size_t nontx_profile_len, auth_len;
 		u8 ie_count = 0;
 
+		if (known_bss && (known_bss_len > (i / 8))) {
+			known_bss = &known_bss[i / 8];
+			if (*known_bss & (u8)(BIT(i % 8)))
+				continue;
+		}
+
 		if (!bss || !bss->conf || !bss->started)
 			continue;
 
@@ -7628,7 +7636,8 @@ mbssid_too_big:
 
 
 size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
-			      u8 *elem_count)
+			      u8 *elem_count, const u8 *known_bss,
+			      size_t known_bss_len)
 {
 	size_t len = 0, bss_index = 1;
 
@@ -7648,7 +7657,8 @@ size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
 
 	while (bss_index < hapd->iface->num_bss) {
 		len += hostapd_eid_mbssid_elem_len(hapd, frame_type,
-						   &bss_index);
+						   &bss_index, known_bss,
+						   known_bss_len);
 
 		if (frame_type == WLAN_FC_STYPE_BEACON)
 			*elem_count += 1;
@@ -7659,7 +7669,8 @@ size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
 
 static u8 * hostapd_eid_mbssid_elem(struct hostapd_data *hapd, u8 *eid, u8 *end,
 				    u32 frame_type, u8 max_bssid_indicator,
-				    size_t *bss_index, u8 elem_count)
+				    size_t *bss_index, u8 elem_count,
+				    const u8 *known_bss, size_t known_bss_len)
 {
 	struct hostapd_data *tx_bss = hostapd_mbssid_get_tx_bss(hapd);
 	size_t i;
@@ -7678,6 +7689,12 @@ static u8 * hostapd_eid_mbssid_elem(struct hostapd_data *hapd, u8 *eid, u8 *end,
 		size_t auth_len = 0;
 		u16 capab_info;
 
+		if (known_bss && (known_bss_len > (i / 8))) {
+			known_bss = &known_bss[i / 8];
+			if (*known_bss & (u8)(BIT(i % 8)))
+				continue;
+		}
+
 		if (!bss || !bss->conf || !bss->started)
 			continue;
 		conf = bss->conf;
@@ -7765,7 +7782,8 @@ mbssid_too_big:
 
 
 u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
-			u32 frame_type, u8 elem_count, u8 **elem_offset)
+			u32 frame_type, u8 elem_count, u8 **elem_offset,
+			const u8 *known_bss, size_t known_bss_len)
 {
 	size_t bss_index = 1;
 	u8 elem_index = 0;
@@ -7793,7 +7811,8 @@ u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
 		}
 		eid = hostapd_eid_mbssid_elem(hapd, eid, end, frame_type,
 					      hostapd_max_bssid_indicator(hapd),
-					      &bss_index, elem_count);
+					      &bss_index, elem_count,
+					      known_bss, known_bss_len);
 	}
 	return eid;
 }
diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
index 1c545eff23e6..bb454bbd63a6 100644
--- a/src/ap/ieee802_11.h
+++ b/src/ap/ieee802_11.h
@@ -215,8 +215,9 @@ u16 copy_sta_eht_capab(struct hostapd_data *hapd, struct sta_info *sta,
 		       const u8 *he_capab, size_t he_capab_len,
 		       const u8 *eht_capab, size_t eht_capab_len);
 size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
-			      u8 *elem_count);
+			      u8 *elem_count, const u8 *known_bss,
+			      size_t known_bss_len);
 u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
-			u32 frame_type, u8 elem_count, u8 **elem_offset);
-
+			u32 frame_type, u8 elem_count, u8 **elem_offset,
+			const u8 *known_bss, size_t known_bss_len);
 #endif /* IEEE802_11_H */
diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
index 9e348a21c375..efeddbbec4b2 100644
--- a/src/common/ieee802_11_common.c
+++ b/src/common/ieee802_11_common.c
@@ -315,6 +315,10 @@ static int ieee802_11_parse_extension(const u8 *pos, size_t elen,
 		elems->eht_operation = pos;
 		elems->eht_operation_len = elen;
 		break;
+	case WLAN_EID_EXT_KNOWN_BSSID:
+		elems->mbssid_known_bss = pos;
+		elems->mbssid_known_bss_len = elen;
+		break;
 	default:
 		if (show_errors) {
 			wpa_printf(MSG_MSGDUMP,
diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
index 743c5a03cbd7..9b23f0a1a44e 100644
--- a/src/common/ieee802_11_common.h
+++ b/src/common/ieee802_11_common.h
@@ -119,6 +119,7 @@ struct ieee802_11_elems {
 	const u8 *pasn_params;
 	const u8 *eht_capabilities;
 	const u8 *eht_operation;
+	const u8 *mbssid_known_bss;
 
 	u8 ssid_len;
 	u8 supp_rates_len;
@@ -175,6 +176,7 @@ struct ieee802_11_elems {
 	u8 pasn_params_len;
 	u8 eht_capabilities_len;
 	u8 eht_operation_len;
+	u8 mbssid_known_bss_len;
 
 	struct mb_ies_info mb_ies;
 	struct frag_ies_info frag_ies;
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index 26b4970fff20..e784b75d38a8 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -483,6 +483,7 @@
 #define WLAN_EID_EXT_OCV_OCI 54
 #define WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION 55
 #define WLAN_EID_EXT_NON_INHERITANCE 56
+#define WLAN_EID_EXT_KNOWN_BSSID 57
 #define WLAN_EID_EXT_SHORT_SSID_LIST 58
 #define WLAN_EID_EXT_HE_6GHZ_BAND_CAP 59
 #define WLAN_EID_EXT_EDMG_CAPABILITIES 61
-- 
2.31.1




More information about the Hostap mailing list