[PATCH V2 5/7] multiple_bssid: add the new IE
John Crispin
john at phrozen.org
Mon Jul 6 08:50:29 EDT 2020
For multiple bssid to work we need to add a new IE to the beacon and probe
responses that includes the information on the non-transmitting BSSs. If
all the information does not fit into the 255 bytes, we need to split it
up over multiple IEs of the same type.
Signed-off-by: John Crispin <john at phrozen.org>
---
src/ap/beacon.c | 10 +++-
src/ap/ieee802_11.c | 101 +++++++++++++++++++++++++++++++++++
src/ap/ieee802_11.h | 3 ++
src/ap/ieee802_11_shared.c | 2 +
src/common/ieee802_11_defs.h | 2 +
5 files changed, 117 insertions(+), 1 deletion(-)
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index 4988ee2a1..2ba374c68 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -293,7 +293,7 @@ static const u8 * hostapd_vendor_wpa_ie(struct hostapd_data *hapd,
}
-static u8 * hostapd_get_rsne(struct hostapd_data *hapd, u8 *pos, size_t len)
+u8 * hostapd_get_rsne(struct hostapd_data *hapd, u8 *pos, size_t len)
{
const u8 *ie;
@@ -472,6 +472,7 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
buflen += hostapd_mbo_ie_len(hapd);
buflen += hostapd_eid_owe_trans_len(hapd);
buflen += hostapd_eid_dpp_cc_len(hapd);
+ buflen += hostapd_eid_multiple_bssid_len(hapd);
resp = os_zalloc(buflen);
if (resp == NULL)
@@ -527,6 +528,9 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
pos = hostapd_eid_rm_enabled_capab(hapd, pos, epos - pos);
pos = hostapd_get_mde(hapd, pos, epos - pos);
+ if (hapd->iconf->multiple_bssid)
+ pos = hostapd_eid_multiple_bssid(hapd, pos, epos);
+
/* eCSA IE */
csa_pos = hostapd_eid_ecsa(hapd, pos);
if (csa_pos != pos)
@@ -1177,6 +1181,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
tail_len += hostapd_mbo_ie_len(hapd);
tail_len += hostapd_eid_owe_trans_len(hapd);
tail_len += hostapd_eid_dpp_cc_len(hapd);
+ tail_len += hostapd_eid_multiple_bssid_len(hapd);
tailpos = tail = os_malloc(tail_len);
if (head == NULL || tail == NULL) {
@@ -1249,6 +1254,9 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
tailend - tailpos);
tailpos = hostapd_get_mde(hapd, tailpos, tailend - tailpos);
+ if (hapd->iconf->multiple_bssid)
+ tailpos = hostapd_eid_multiple_bssid(hapd, tailpos, tailend);
+
/* eCSA IE */
csa_pos = hostapd_eid_ecsa(hapd, tailpos);
if (csa_pos != tailpos)
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index b91640070..de4a7dfa3 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -6,6 +6,7 @@
* See README for more details.
*/
+#include <math.h>
#include "utils/includes.h"
#ifndef CONFIG_NATIVE_WINDOWS
@@ -5617,4 +5618,104 @@ u8 * hostapd_eid_wb_chsw_wrapper(struct hostapd_data *hapd, u8 *eid)
return eid;
}
+
+static int hostapd_eid_multiple_bssid_chunk_len(struct hostapd_data *hapd,
+ int *count)
+{
+ /* ID + size + count */
+ int i, len = 3;
+
+ for (i = *count; i < hapd->iface->num_bss; i++) {
+ struct hostapd_data *bss = hapd->iface->bss[i];
+ /* 11 mbssid + ssid len + 32 RSN */
+ int ssid_len = 11 + bss->conf->ssid.ssid_len + 32;
+
+ if (len + ssid_len > 255) {
+ goto multiple_bssid_too_big;
+ }
+ len += ssid_len;
+ }
+
+multiple_bssid_too_big:
+ *count = i;
+
+ return len;
+}
+
+
+int hostapd_eid_multiple_bssid_len(struct hostapd_data *hapd)
+{
+ int count = 1, len = 0;
+
+ while (count < hapd->iface->num_bss)
+ len += hostapd_eid_multiple_bssid_chunk_len(hapd, &count);
+
+ return len;
+}
+
+
+static u8 * hostapd_eid_multiple_bssid_chunk(struct hostapd_data *hapd,
+ u8 *eid, u8 *end, int *count)
+{
+ u8 *size_offset, *num_offset, num = 0;
+ int i;
+
+ *eid++ = WLAN_EID_MULTIPLE_BSSID;
+ size_offset = eid++;
+ num_offset = eid++;
+
+ for (i = *count; i < hapd->iface->num_bss; i++) {
+ struct hostapd_data *bss = hapd->iface->bss[i];
+ u8 *bss_size_offset, *pos = eid;
+ u16 capab_info;
+
+ *eid++ = WLAN_EID_SUBELEMENT_NONTRANSMITTED_BSSID_PROFILE;
+ bss_size_offset = 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++ = bss->conf->ssid.ssid_len;
+ os_memcpy(eid, bss->conf->ssid.ssid, bss->conf->ssid.ssid_len);
+ eid += bss->conf->ssid.ssid_len;
+
+ *eid++ = WLAN_EID_MULTIPLE_BSSID_INDEX;
+ *eid++ = 1;
+ *eid++ = i;
+
+ eid = hostapd_get_rsne(bss, eid, end - eid);
+ *bss_size_offset = (eid - bss_size_offset) - 1;
+
+ if ((eid - size_offset) - 1 > 255) {
+ eid = pos;
+ goto multiple_bssid_too_big;
+ }
+ num++;
+ }
+
+multiple_bssid_too_big:
+ *count = i;
+ *num_offset = (u8)ceil(log2(num));
+ if (*num_offset < 2)
+ *num_offset = 2;
+ *size_offset = (eid - size_offset) - 1;
+
+ return eid;
+}
+
+
+u8 * hostapd_eid_multiple_bssid(struct hostapd_data *hapd, u8 *eid, u8 *end)
+{
+ int count = 1;
+
+ while (count < hapd->iface->num_bss)
+ eid = hostapd_eid_multiple_bssid_chunk(hapd, eid, end, &count);
+
+ return eid;
+}
+
#endif /* CONFIG_NATIVE_WINDOWS */
diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
index ea8c60846..466938f59 100644
--- a/src/ap/ieee802_11.h
+++ b/src/ap/ieee802_11.h
@@ -119,6 +119,8 @@ u8 * hostapd_eid_time_zone(struct hostapd_data *hapd, u8 *eid);
int hostapd_update_time_adv(struct hostapd_data *hapd);
void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr);
u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid);
+u8 * hostapd_eid_multiple_bssid(struct hostapd_data *hapd, u8 *eid, u8 *end);
+int hostapd_eid_multiple_bssid_len(struct hostapd_data *hapd);
int auth_sae_init_committed(struct hostapd_data *hapd, struct sta_info *sta);
#ifdef CONFIG_SAE
@@ -194,5 +196,6 @@ int get_tx_parameters(struct sta_info *sta, int ap_max_chanwidth,
void auth_sae_process_commit(void *eloop_ctx, void *user_ctx);
u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len);
+u8 * hostapd_get_rsne(struct hostapd_data *hapd, u8 *pos, size_t len);
#endif /* IEEE802_11_H */
diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c
index 79ed450e2..961e91e66 100644
--- a/src/ap/ieee802_11_shared.c
+++ b/src/ap/ieee802_11_shared.c
@@ -356,6 +356,8 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
*pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
if (hapd->conf->bss_transition)
*pos |= 0x08; /* Bit 19 - BSS Transition */
+ if (hapd->iconf->multiple_bssid)
+ *pos |= 0x40; /* Bit 22 - Multiple BSSID */
break;
case 3: /* Bits 24-31 */
#ifdef CONFIG_WNM_AP
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index 4d3037eee..7d1287763 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -452,6 +452,8 @@
#define WLAN_EID_RSNX 244
#define WLAN_EID_EXTENSION 255
+#define WLAN_EID_SUBELEMENT_NONTRANSMITTED_BSSID_PROFILE 0
+
/* Element ID Extension (EID 255) values */
#define WLAN_EID_EXT_ASSOC_DELAY_INFO 1
#define WLAN_EID_EXT_FILS_REQ_PARAMS 2
--
2.25.1
More information about the Hostap
mailing list