[PATCH v4 04/15] mbssid: add multiple BSSID elements
Aloka Dixit
quic_alokad at quicinc.com
Wed Nov 30 19:18:36 PST 2022
Add multiple BSSID element data as per IEEE Std 802.11ax-2021, 9.4.2.45.
Split the BSSes into multiple elements if the data does not fit in
the 255 bytes allowed for a single element.
Store the total count of elements created and the offset to the start
of each element in the provided buffer.
Set the DTIM periods of non-transmitted profiles equal to the EMA
profile periodicity if those are not a multiple of the latter already
as recommended in IEEE P802.11ax/D8.0, October 2020, Multiple BSSID
configuration examples, AA.1 Introduction.
Signed-off-by: Aloka Dixit <quic_alokad at quicinc.com>
Co-developed-by: John Crispin <john at phrozen.org>
Signed-off-by: John Crispin <john at phrozen.org>
---
src/ap/ieee802_11.c | 215 +++++++++++++++++++++++++++++++++++
src/ap/ieee802_11.h | 4 +
src/common/ieee802_11_defs.h | 2 +
3 files changed, 221 insertions(+)
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index f0e3c55a985c..72b961bb2244 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -3115,6 +3115,23 @@ static void handle_auth(struct hostapd_data *hapd,
}
+static u8 hostapd_max_bssid_indicator(struct hostapd_data *hapd)
+{
+ size_t num_bss_nontx;
+ u8 max_bssid_ind = 0;
+
+ if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1)
+ return 0;
+
+ num_bss_nontx = hapd->iface->num_bss - 1;
+ while (num_bss_nontx > 0) {
+ max_bssid_ind++;
+ num_bss_nontx >>= 1;
+ }
+ return max_bssid_ind;
+}
+
+
int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta)
{
int i, j = 32, aid;
@@ -6704,4 +6721,202 @@ u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type)
return eid;
}
+
+static size_t hostapd_eid_mbssid_elem_len(struct hostapd_data *hapd,
+ u32 frame_type, size_t *bss_index)
+{
+ size_t len = 3, i;
+
+ for (i = *bss_index; i < hapd->iface->num_bss; i++) {
+ struct hostapd_data *bss = hapd->iface->bss[i];
+ const u8 *auth, *rsn, *rsnx;
+ size_t nontx_profile_len, auth_len;
+
+ if (!bss || !bss->conf || !bss->started)
+ continue;
+
+ /*
+ * Sublement ID: 1 byte
+ * Length: 1 byte
+ * Nontransmitted capabilities: 4 bytes
+ * SSID element: 2 + variable
+ * Multiple BSSID Index Element: 3 bytes (+2 bytes in beacons)
+ * Fixed length = 1 + 1 + 4 + 2 + 3 = 11
+ */
+ nontx_profile_len = 11 + bss->conf->ssid.ssid_len;
+
+ if (frame_type == WLAN_FC_STYPE_BEACON)
+ nontx_profile_len += 2;
+
+ auth = wpa_auth_get_wpa_ie(bss->wpa_auth, &auth_len);
+ if (auth) {
+ rsn = get_ie(auth, auth_len, WLAN_EID_RSN);
+ if (rsn)
+ nontx_profile_len += (2 + rsn[1]);
+
+ rsnx = get_ie(auth, auth_len, WLAN_EID_RSNX);
+ if (rsnx)
+ nontx_profile_len += (2 + rsnx[1]);
+ }
+
+ if ((len + nontx_profile_len) > 255)
+ goto mbssid_too_big;
+
+ len += nontx_profile_len;
+ }
+
+mbssid_too_big:
+ *bss_index = i;
+ return len;
+}
+
+
+size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
+ u8 *elem_count)
+{
+ size_t len = 0, bss_index = 1;
+
+ if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1 ||
+ (frame_type != WLAN_FC_STYPE_BEACON &&
+ frame_type != WLAN_FC_STYPE_PROBE_RESP))
+ return 0;
+
+ if (frame_type == WLAN_FC_STYPE_BEACON) {
+ if (!elem_count) {
+ wpa_printf(MSG_ERROR,
+ "MBSSID: Insufficient data for beacons");
+ return 0;
+ }
+ *elem_count = 0;
+ }
+
+ while (bss_index < hapd->iface->num_bss) {
+ len += hostapd_eid_mbssid_elem_len(hapd, frame_type,
+ &bss_index);
+
+ if (frame_type == WLAN_FC_STYPE_BEACON)
+ *elem_count += 1;
+ }
+ return len;
+}
+
+
+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 i;
+ u8 *eid_len_offset, *max_bssid_indicator_offset;
+
+ *eid++ = WLAN_EID_MULTIPLE_BSSID;
+ eid_len_offset = eid++;
+ max_bssid_indicator_offset = eid++;
+
+ for (i = *bss_index; i < hapd->iface->num_bss; i++) {
+ struct hostapd_data *bss = hapd->iface->bss[i];
+ struct hostapd_bss_config *conf;
+ u8 *eid_len_pos, *nontx_bss_start = eid;
+ const u8 *auth, *rsn, *rsnx;
+ size_t auth_len = 0;
+ u16 capab_info;
+
+ if (!bss || !bss->conf || !bss->started)
+ continue;
+ conf = bss->conf;
+
+ *eid++ = WLAN_EID_SUBELEMENT_NONTRANSMITTED_BSSID_PROFILE;
+ eid_len_pos = eid++;
+
+ *eid++ = WLAN_EID_NONTRANSMITTED_BSSID_CAPA;
+ *eid++ = sizeof(capab_info);
+ capab_info = host_to_le16(hostapd_own_capab_info(bss));
+ os_memcpy(eid, (const void *)&capab_info, sizeof(capab_info));
+ eid += sizeof(capab_info);
+
+ *eid++ = WLAN_EID_SSID;
+ *eid++ = conf->ssid.ssid_len;
+ os_memcpy(eid, conf->ssid.ssid, conf->ssid.ssid_len);
+ eid += conf->ssid.ssid_len;
+
+ *eid++ = WLAN_EID_MULTIPLE_BSSID_INDEX;
+ if (frame_type == WLAN_FC_STYPE_BEACON) {
+ *eid++ = 3;
+ *eid++ = i;
+ if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED &&
+ (conf->dtim_period % elem_count))
+ conf->dtim_period = elem_count;
+ *eid++ = conf->dtim_period;
+ *eid++ = 0xFF;
+ } else {
+ *eid++ = 1;
+ *eid++ = i;
+ }
+
+ auth = wpa_auth_get_wpa_ie(bss->wpa_auth, &auth_len);
+ if (auth) {
+ rsn = get_ie(auth, auth_len, WLAN_EID_RSN);
+ if (rsn) {
+ os_memcpy(eid, rsn, 2 + rsn[1]);
+ eid += (2 + rsn[1]);
+ }
+
+ rsnx = get_ie(auth, auth_len, WLAN_EID_RSNX);
+ if (rsnx) {
+ os_memcpy(eid, rsnx, 2 + rsnx[1]);
+ eid += (2 + rsnx[1]);
+ }
+ }
+
+ *eid_len_pos = (eid - eid_len_pos) - 1;
+
+ if (((eid - eid_len_offset) - 1) > 255) {
+ eid = nontx_bss_start;
+ goto mbssid_too_big;
+ }
+ }
+
+mbssid_too_big:
+ *bss_index = i;
+ *max_bssid_indicator_offset = max_bssid_indicator;
+ if (*max_bssid_indicator_offset < 1)
+ *max_bssid_indicator_offset = 1;
+ *eid_len_offset = (eid - eid_len_offset) - 1;
+ return eid;
+}
+
+
+u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
+ u32 frame_type, u8 elem_count, u8 **elem_offset)
+{
+ size_t bss_index = 1;
+ u8 elem_index = 0;
+
+ if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1 ||
+ (frame_type != WLAN_FC_STYPE_BEACON &&
+ frame_type != WLAN_FC_STYPE_PROBE_RESP))
+ return eid;
+
+ if (frame_type == WLAN_FC_STYPE_BEACON && !elem_offset) {
+ wpa_printf(MSG_ERROR, "MBSSID: Insufficient data for beacons");
+ return eid;
+ }
+
+ while (bss_index < hapd->iface->num_bss) {
+ if (frame_type == WLAN_FC_STYPE_BEACON) {
+ if (elem_index == elem_count) {
+ wpa_printf(MSG_WARNING,
+ "MBSSID: More number of elements than provided array");
+ break;
+ }
+
+ elem_offset[elem_index] = eid;
+ elem_index = elem_index + 1;
+ }
+ eid = hostapd_eid_mbssid_elem(hapd, eid, end, frame_type,
+ hostapd_max_bssid_indicator(hapd),
+ &bss_index, elem_count);
+ }
+ return eid;
+}
+
#endif /* CONFIG_NATIVE_WINDOWS */
diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
index fa1f47b957e4..1c545eff23e6 100644
--- a/src/ap/ieee802_11.h
+++ b/src/ap/ieee802_11.h
@@ -214,5 +214,9 @@ u16 copy_sta_eht_capab(struct hostapd_data *hapd, struct sta_info *sta,
enum ieee80211_op_mode opmode,
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 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
+ u32 frame_type, u8 elem_count, u8 **elem_offset);
#endif /* IEEE802_11_H */
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index 310b7660e2ff..65d18e67c41f 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -497,6 +497,8 @@
#define WLAN_EID_EXT_MULTI_LINK_TRAFFIC_INDICATION 110
#define WLAN_EID_EXT_AKM_SUITE_SELECTOR 114
+#define WLAN_EID_SUBELEMENT_NONTRANSMITTED_BSSID_PROFILE 0
+
/* Extended Capabilities field */
#define WLAN_EXT_CAPAB_20_40_COEX 0
#define WLAN_EXT_CAPAB_GLK 1
--
2.25.1
More information about the Hostap
mailing list