blob: 517f40c4b80a1781e1b039f5f8731a0bebf78663 [file] [log] [blame]
developer81939a52023-03-25 15:31:11 +08001From 832350b2c16a9ad2f65c32d32584e7cdb06b074a Mon Sep 17 00:00:00 2001
developer0b9a6392023-03-02 17:16:47 +08002From: mtk20656 <chank.chen@mediatek.com>
3Date: Thu, 2 Mar 2023 10:51:43 +0800
developer81939a52023-03-25 15:31:11 +08004Subject: [PATCH 21/24] hostapd: mtk: add 11v_mbss and ema support for hostapd
developer0b9a6392023-03-02 17:16:47 +08005
6Signed-off-by: mtk20656 <chank.chen@mediatek.com>
7---
8 hostapd/config_file.c | 9 +
9 hostapd/hostapd.conf | 58 +++++++
10 hostapd/main.c | 3 +
11 src/ap/ap_config.c | 12 ++
12 src/ap/ap_config.h | 6 +
13 src/ap/beacon.c | 124 ++++++++++++--
developera5e13c92023-03-03 15:51:12 +080014 src/ap/hostapd.c | 72 +++++++-
developer0b9a6392023-03-02 17:16:47 +080015 src/ap/hostapd.h | 7 +
16 src/ap/ieee802_11.c | 276 +++++++++++++++++++++++++++++-
17 src/ap/ieee802_11.h | 7 +-
18 src/ap/ieee802_11_shared.c | 11 ++
19 src/common/ieee802_11_common.c | 4 +
20 src/common/ieee802_11_common.h | 3 +
21 src/common/ieee802_11_defs.h | 5 +
22 src/drivers/driver.h | 42 +++++
23 src/drivers/driver_nl80211.c | 52 ++++++
24 src/drivers/driver_nl80211_capa.c | 27 +++
developera5e13c92023-03-03 15:51:12 +080025 17 files changed, 698 insertions(+), 20 deletions(-)
developer0b9a6392023-03-02 17:16:47 +080026
27diff --git a/hostapd/config_file.c b/hostapd/config_file.c
developera5e13c92023-03-03 15:51:12 +080028index 649618b..3f26191 100644
developer0b9a6392023-03-02 17:16:47 +080029--- a/hostapd/config_file.c
30+++ b/hostapd/config_file.c
31@@ -3663,6 +3663,15 @@ static int hostapd_config_fill(struct hostapd_config *conf,
32 return 1;
33 }
34 bss->unsol_bcast_probe_resp_interval = val;
35+ } else if (os_strcmp(buf, "mbssid") == 0) {
36+ int mbssid = atoi(pos);
37+ if (mbssid < 0 || mbssid > ENHANCED_MBSSID_ENABLED) {
38+ wpa_printf(MSG_ERROR,
39+ "Line %d: invalid mbssid (%d): '%s'.",
40+ line, mbssid, pos);
41+ return 1;
42+ }
43+ conf->mbssid = mbssid;
44 } else if (os_strcmp(buf, "mu_onoff") == 0) {
45 int val = atoi(pos);
46 if (val < 0 || val > 15) {
47diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
developera5e13c92023-03-03 15:51:12 +080048index e3a5eb3..f926029 100644
developer0b9a6392023-03-02 17:16:47 +080049--- a/hostapd/hostapd.conf
50+++ b/hostapd/hostapd.conf
51@@ -3123,3 +3123,61 @@ own_ip_addr=127.0.0.1
52 #bss=wlan0_1
53 #bssid=00:13:10:95:fe:0b
54 # ...
55+#
56+# Multiple BSSID Advertisement in 802.11ax
57+# IEEE Std 802.11ax-2021 added a feature where instead of multiple interfaces
58+# on a common radio transmitting individual beacons, those can form a set with
59+# a common beacon is transmitted for all. The interface which is brought up
60+# first is called as the transmitting profile of the MBSSID set which transmits
61+# the beacons. The remaining interfaces are called as the non-transmitting
62+# profiles and these are advertised inside the multiple BSSID element in the
63+# beacons and probe response frames.
64+# The transmitting interface is visible to all clients in the vicinity, however
65+# the clients which do not support parsing of the multiple BSSID element will
66+# not be able to connect to the non-transmitting interfaces.
67+#
68+# Enhanced Multiple BSSID Advertisements (EMA)
69+# When enabled, the non-transmitting interfaces are split into multiple
70+# beacons. The number of beacons required to cover all the non-transmitting
71+# profiles is called as the profile periodicity.
72+#
73+# Refer to IEEE Std 802.11-2020 for details regarding the procedure and
74+# required MAC address assignment.
75+#
76+# Following configuration is per radio.
77+# 0 = Disabled (Default)
78+# 1 = Multiple BSSID advertisements enabled.
79+# 2 = Enhanced multiple BSSID advertisements enabled.
80+#mbssid=0
81+#
82+# The transmitting interface should be added with 'interface' option while
83+# the non-transmitting interfaces should be added using 'bss' option.
84+# Security configuration should be added separately per interface, if required.
85+#
86+# Example:
87+#mbssid=2
88+#interface=wlan2
89+#ctrl_interface=/var/run/hostapd
90+#wpa_passphrase=0123456789
91+#ieee80211w=2
92+#sae_pwe=1
93+#auth_algs=1
94+#wpa=2
95+#wpa_pairwise=CCMP
96+#ssid=<SSID-0>
97+#bridge=br-lan
98+#wpa_key_mgmt=SAE
99+#bssid=00:03:7f:12:84:84
100+#
101+#bss=wlan2-1
102+#ctrl_interface=/var/run/hostapd
103+#wpa_passphrase=0123456789
104+#ieee80211w=2
105+#sae_pwe=1
106+#auth_algs=1
107+#wpa=2
108+#wpa_pairwise=CCMP
109+#ssid=<SSID-1>
110+#bridge=br-lan
111+#wpa_key_mgmt=SAE
112+#bssid=00:03:7f:12:84:85
113diff --git a/hostapd/main.c b/hostapd/main.c
developera5e13c92023-03-03 15:51:12 +0800114index 70a4b32..1b6474a 100644
developer0b9a6392023-03-02 17:16:47 +0800115--- a/hostapd/main.c
116+++ b/hostapd/main.c
117@@ -253,6 +253,9 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
118 wpa_printf(MSG_ERROR, "set_wowlan failed");
119 }
120 os_free(triggs);
121+
122+ iface->mbssid_max_interfaces = capa.mbssid_max_interfaces;
123+ iface->ema_max_periodicity = capa.ema_max_periodicity;
124 }
125
126 return 0;
127diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
developera5e13c92023-03-03 15:51:12 +0800128index 4e46a62..7d9d5cb 100644
developer0b9a6392023-03-02 17:16:47 +0800129--- a/src/ap/ap_config.c
130+++ b/src/ap/ap_config.c
131@@ -1462,6 +1462,12 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
132 }
133 #endif /* CONFIG_IEEE80211BE */
134
135+ if (full_config && bss->ignore_broadcast_ssid && conf->mbssid) {
136+ wpa_printf(MSG_ERROR,
137+ "Hidden SSID is not suppored when MBSSID is enabled");
138+ return -1;
139+ }
140+
141 return 0;
142 }
143
144@@ -1545,6 +1551,12 @@ int hostapd_config_check(struct hostapd_config *conf, int full_config)
145 }
146 #endif /* CONFIG_IEEE80211BE */
147
148+ if (full_config && conf->mbssid && !conf->ieee80211ax) {
149+ wpa_printf(MSG_ERROR,
150+ "Cannot enable multiple BSSID support without ieee80211ax");
151+ return -1;
152+ }
153+
154 for (i = 0; i < conf->num_bss; i++) {
155 if (hostapd_config_check_bss(conf->bss[i], conf, full_config))
156 return -1;
157diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
developera5e13c92023-03-03 15:51:12 +0800158index 7aeb176..51476b8 100644
developer0b9a6392023-03-02 17:16:47 +0800159--- a/src/ap/ap_config.h
160+++ b/src/ap/ap_config.h
161@@ -923,6 +923,8 @@ struct hostapd_bss_config {
162 u8 ext_capa[EXT_CAPA_MAX_LEN];
163
164 u8 rnr;
165+
166+ bool xrates_supported;
167 };
168
169 /**
170@@ -1163,6 +1165,10 @@ struct hostapd_config {
171 u8 ibf_enable;
172 u8 dfs_detect_mode;
173 u8 amsdu;
174+
175+#define MBSSID_ENABLED 1
176+#define ENHANCED_MBSSID_ENABLED 2
177+ u8 mbssid;
178 };
179
180 enum three_wire_mode {
181diff --git a/src/ap/beacon.c b/src/ap/beacon.c
developera5e13c92023-03-03 15:51:12 +0800182index f3ea5c2..51db23a 100644
developer0b9a6392023-03-02 17:16:47 +0800183--- a/src/ap/beacon.c
184+++ b/src/ap/beacon.c
185@@ -462,15 +462,77 @@ static u8 * hostapd_eid_supported_op_classes(struct hostapd_data *hapd, u8 *eid)
186 }
187
188
189+static int ieee802_11_build_ap_params_mbssid(struct hostapd_data *hapd,
190+ struct wpa_driver_ap_params *params,
191+ u8 **eid)
192+{
193+ struct hostapd_iface *iface = hapd->iface;
194+ struct hostapd_data *tx_bss;
195+ size_t len;
196+ u8 elem_count = 0, *elem = NULL, **elem_offset = NULL, *end;
197+ u8 *tailpos = *eid;
198+
199+ if (!iface->mbssid_max_interfaces ||
200+ iface->num_bss > iface->mbssid_max_interfaces ||
201+ (iface->conf->mbssid == ENHANCED_MBSSID_ENABLED &&
202+ !iface->ema_max_periodicity))
203+ goto fail;
204+
205+ tx_bss = hostapd_mbssid_get_tx_bss(hapd);
206+ len = hostapd_eid_mbssid_len(tx_bss, WLAN_FC_STYPE_BEACON, &elem_count,
207+ NULL, 0);
208+ if (!len || (iface->conf->mbssid == ENHANCED_MBSSID_ENABLED &&
209+ elem_count > iface->ema_max_periodicity))
210+ goto fail;
211+
212+ elem = os_zalloc(len);
213+ if (!elem)
214+ goto fail;
215+
216+ elem_offset = os_zalloc(elem_count * sizeof(u8 *));
217+ if (!elem_offset)
218+ goto fail;
219+
220+ end = hostapd_eid_mbssid(tx_bss, elem, elem + len, WLAN_FC_STYPE_BEACON,
221+ elem_count, elem_offset, NULL, 0);
222+
223+ params->mbssid_tx_iface = tx_bss->conf->iface;
224+ params->mbssid_index = hostapd_mbssid_get_bss_index(hapd);
225+ params->mbssid_elem = elem;
226+ params->mbssid_elem_len = end - elem;
227+ params->mbssid_elem_count = elem_count;
228+ params->mbssid_elem_offset = elem_offset;
229+ if (iface->conf->mbssid == ENHANCED_MBSSID_ENABLED) {
230+ params->ema = true;
231+ *tailpos++ = WLAN_EID_EXTENSION;
232+ *tailpos++ = 3;
233+ *tailpos++ = WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION;
234+ *tailpos++ = iface->num_bss;
235+ *tailpos++ = params->mbssid_elem_count;
236+ *eid = tailpos;
237+ }
238+
239+ return 0;
240+
241+fail:
242+ os_free(elem);
243+ wpa_printf(MSG_ERROR, "MBSSID: Configuration failed");
244+ return -1;
245+}
246+
247+
248 static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
249 const struct ieee80211_mgmt *req,
250 int is_p2p, size_t *resp_len,
251- bool bcast_probe_resp)
252+ bool bcast_probe_resp, const u8 *known_bss,
253+ u8 known_bss_len)
254 {
255 struct ieee80211_mgmt *resp;
256- u8 *pos, *epos, *csa_pos;
257+ u8 *pos, *epos, *csa_pos, *ext_cap_pos;
258 size_t buflen;
259
260+ hapd = hostapd_mbssid_get_tx_bss(hapd);
261+
262 #define MAX_PROBERESP_LEN 768
263 buflen = MAX_PROBERESP_LEN;
264 #ifdef CONFIG_WPS
265@@ -517,6 +579,8 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
266 }
267 #endif /* CONFIG_IEEE80211BE */
268
269+ buflen += hostapd_eid_mbssid_len(hapd, WLAN_FC_STYPE_PROBE_RESP, NULL,
270+ known_bss, known_bss_len);
271 buflen += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_PROBE_RESP);
272 buflen += hostapd_mbo_ie_len(hapd);
273 buflen += hostapd_eid_owe_trans_len(hapd);
274@@ -588,8 +652,16 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
275 pos = hostapd_eid_supported_op_classes(hapd, pos);
276 pos = hostapd_eid_ht_capabilities(hapd, pos);
277 pos = hostapd_eid_ht_operation(hapd, pos);
278+ pos = hostapd_eid_mbssid(hapd, pos, epos, WLAN_FC_STYPE_PROBE_RESP, 0,
279+ NULL, known_bss, known_bss_len);
280
281+ ext_cap_pos = pos;
282 pos = hostapd_eid_ext_capab(hapd, pos);
283+ if (hapd->iconf->mbssid >= MBSSID_ENABLED && !known_bss_len)
284+ ext_cap_pos[12] |= 0x01; /* Probe responses always include all
285+ * non-tx profiles except when a list
286+ * of known BSSes is included in the
287+ * probe request. */
288
289 pos = hostapd_eid_time_adv(hapd, pos);
290 pos = hostapd_eid_time_zone(hapd, pos);
291@@ -1153,16 +1225,23 @@ void handle_probe_req(struct hostapd_data *hapd,
292 }
293 #endif /* CONFIG_TESTING_OPTIONS */
294
295+ /* Do not send probe response from a non-transmitting multiple BSSID
296+ * profile unless the probe request is directed at that paticular BSS */
297+ if (hapd != hostapd_mbssid_get_tx_bss(hapd) && res != EXACT_SSID_MATCH)
298+ return;
299+
300 wpa_msg_ctrl(hapd->msg_ctx, MSG_INFO, RX_PROBE_REQUEST "sa=" MACSTR
301 " signal=%d", MAC2STR(mgmt->sa), ssi_signal);
302
303 if (is_6ghz_op_class(hapd->iconf->op_class) &&
304 is_broadcast_ether_addr(mgmt->da))
305 resp = hostapd_gen_probe_resp(hapd, NULL, elems.p2p != NULL,
306- &resp_len, true);
developerf8c237a2023-03-28 16:08:27 +0800307+ &resp_len, true, elems.mbssid_known_bss,
developera5e13c92023-03-03 15:51:12 +0800308+ elems.mbssid_known_bss_len);
developer0b9a6392023-03-02 17:16:47 +0800309 else
310 resp = hostapd_gen_probe_resp(hapd, mgmt, elems.p2p != NULL,
311- &resp_len, false);
developera5e13c92023-03-03 15:51:12 +0800312+ &resp_len, false, elems.mbssid_known_bss,
313+ elems.mbssid_known_bss_len);
developer0b9a6392023-03-02 17:16:47 +0800314 if (resp == NULL)
315 return;
316
317@@ -1184,7 +1263,8 @@ void handle_probe_req(struct hostapd_data *hapd,
318 hapd->cs_c_off_ecsa_proberesp;
319 }
320
321- ret = hostapd_drv_send_mlme(hapd, resp, resp_len, noack,
322+ ret = hostapd_drv_send_mlme(hostapd_mbssid_get_tx_bss(hapd), resp,
323+ resp_len, noack,
324 csa_offs_len ? csa_offs : NULL,
325 csa_offs_len, 0);
326
327@@ -1231,7 +1311,7 @@ static u8 * hostapd_probe_resp_offloads(struct hostapd_data *hapd,
328 "this");
329
330 /* Generate a Probe Response template for the non-P2P case */
331- return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len, false);
332+ return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len, false, NULL, 0);
333 }
334
335 #endif /* NEED_AP_MLME */
336@@ -1250,7 +1330,7 @@ static u8 * hostapd_unsol_bcast_probe_resp(struct hostapd_data *hapd,
337
338 return hostapd_gen_probe_resp(hapd, NULL, 0,
339 &params->unsol_bcast_probe_resp_tmpl_len,
340- true);
341+ true, NULL, 0);
342 }
343 #endif /* CONFIG_IEEE80211AX */
344
345@@ -1533,8 +1613,12 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
346 size_t resp_len = 0;
347 #ifdef NEED_AP_MLME
348 u16 capab_info;
349- u8 *pos, *tailpos, *tailend, *csa_pos;
350+ u8 *pos, *tailpos, *tailend, *csa_pos, *ext_cap_pos;
351+#endif /* NEED_AP_MLME */
352
353+ os_memset(params, 0, sizeof(*params));
354+
355+#ifdef NEED_AP_MLME
356 #define BEACON_HEAD_BUF_SIZE 256
357 #define BEACON_TAIL_BUF_SIZE 512
358 head = os_zalloc(BEACON_HEAD_BUF_SIZE);
359@@ -1586,6 +1670,9 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
360 }
361 #endif /* CONFIG_IEEE80211BE */
362
363+ if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED &&
364+ hapd == hostapd_mbssid_get_tx_bss(hapd))
365+ tail_len += 5; /* Multiple BSSID Configuration element */
366 tail_len += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_BEACON);
367 tail_len += hostapd_mbo_ie_len(hapd);
368 tail_len += hostapd_eid_owe_trans_len(hapd);
369@@ -1671,9 +1758,23 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
370 tailpos = hostapd_eid_supported_op_classes(hapd, tailpos);
371 tailpos = hostapd_eid_ht_capabilities(hapd, tailpos);
372 tailpos = hostapd_eid_ht_operation(hapd, tailpos);
373-
374+ ext_cap_pos = tailpos;
375 tailpos = hostapd_eid_ext_capab(hapd, tailpos);
376
377+ if (hapd->iconf->mbssid && hapd->iconf->num_bss > 1) {
378+ if (ieee802_11_build_ap_params_mbssid(hapd, params, &tailpos)) {
379+ os_free(head);
380+ os_free(tail);
381+ wpa_printf(MSG_ERROR, "Failed to set beacon data");
382+ return -1;
383+ } else if (hapd->iconf->mbssid == MBSSID_ENABLED ||
384+ (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED &&
385+ params->mbssid_elem_count == 1)) {
386+ /* Set the extended capability bit for "complete list
387+ * of non-tx profiles" */
388+ ext_cap_pos[12] |= 0x01;
389+ }
390+ }
391 /*
392 * TODO: Time Advertisement element should only be included in some
393 * DTIM Beacon frames.
394@@ -1794,7 +1895,6 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
395 resp = hostapd_probe_resp_offloads(hapd, &resp_len);
396 #endif /* NEED_AP_MLME */
397
398- os_memset(params, 0, sizeof(*params));
399 params->head = (u8 *) head;
400 params->head_len = head_len;
401 params->tail = tail;
402@@ -1897,6 +1997,10 @@ void ieee802_11_free_ap_params(struct wpa_driver_ap_params *params)
403 params->head = NULL;
404 os_free(params->proberesp);
405 params->proberesp = NULL;
406+ os_free(params->mbssid_elem);
407+ params->mbssid_elem = NULL;
408+ os_free(params->mbssid_elem_offset);
409+ params->mbssid_elem_offset = NULL;
410 #ifdef CONFIG_FILS
411 os_free(params->fd_frame_tmpl);
412 params->fd_frame_tmpl = NULL;
413diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
developera5e13c92023-03-03 15:51:12 +0800414index 42e8ed7..82cc155 100644
developer0b9a6392023-03-02 17:16:47 +0800415--- a/src/ap/hostapd.c
416+++ b/src/ap/hostapd.c
417@@ -91,6 +91,29 @@ int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
418 }
419
420
421+struct hostapd_data * hostapd_mbssid_get_tx_bss(struct hostapd_data *hapd)
422+{
423+ if (hapd->iconf->mbssid)
424+ return hapd->iface->bss[0];
425+
426+ return hapd;
427+}
428+
429+
430+int hostapd_mbssid_get_bss_index(struct hostapd_data *hapd)
431+{
432+ if (hapd->iconf->mbssid) {
433+ size_t i;
434+
435+ for (i = 1; i < hapd->iface->num_bss; i++)
436+ if (hapd->iface->bss[i] == hapd)
437+ return i;
438+ }
439+
440+ return 0;
441+}
442+
443+
444 void hostapd_reconfig_encryption(struct hostapd_data *hapd)
445 {
446 if (hapd->wpa_auth)
447@@ -1179,19 +1202,37 @@ static int db_table_create_radius_attributes(sqlite3 *db)
448
449 #endif /* CONFIG_NO_RADIUS */
450
451+static int hostapd_start_beacon(struct hostapd_data *hapd)
452+{
453+ struct hostapd_bss_config *conf = hapd->conf;
454+
455+ if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0)
456+ return -1;
457+
458+ if (hapd->driver && hapd->driver->set_operstate)
459+ hapd->driver->set_operstate(hapd->drv_priv, 1);
460+
461+ return 0;
462+}
463
464 /**
465 * hostapd_setup_bss - Per-BSS setup (initialization)
466 * @hapd: Pointer to BSS data
467 * @first: Whether this BSS is the first BSS of an interface; -1 = not first,
468 * but interface may exist
469+ * @start_beacon: Whether beacons should be configured and transmission started
470+ * at this time. This is used when MBSSID IE is enabled where the
471+ * information regarding all BSSes should be retrieved before configuring
472+ * the beacons. The calling functions are responsible to configure the
473+ * beacon explicitly if this is set to 'false'.
474 *
475 * This function is used to initialize all per-BSS data structures and
476 * resources. This gets called in a loop for each BSS when an interface is
477 * initialized. Most of the modules that are initialized here will be
478 * deinitialized in hostapd_cleanup().
479 */
480-static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
481+static int hostapd_setup_bss(struct hostapd_data *hapd, int first,
482+ bool start_beacon)
483 {
484 struct hostapd_bss_config *conf = hapd->conf;
485 u8 ssid[SSID_MAX_LEN + 1];
developera5e13c92023-03-03 15:51:12 +0800486@@ -1464,9 +1505,6 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
developer0b9a6392023-03-02 17:16:47 +0800487 return -1;
488 }
489
490- if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0)
491- return -1;
492-
493 if (flush_old_stations && !conf->start_disabled &&
494 conf->broadcast_deauth) {
495 u8 addr[ETH_ALEN];
developera5e13c92023-03-03 15:51:12 +0800496@@ -1485,8 +1523,8 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
developer0b9a6392023-03-02 17:16:47 +0800497 if (hapd->wpa_auth && wpa_init_keys(hapd->wpa_auth) < 0)
498 return -1;
499
500- if (hapd->driver && hapd->driver->set_operstate)
501- hapd->driver->set_operstate(hapd->drv_priv, 1);
developere2a629e2023-03-27 09:50:19 +0800502+ if (start_beacon && hostapd_start_beacon(hapd) < 0)
503+ return -1;
developer0b9a6392023-03-02 17:16:47 +0800504
505 hostapd_ubus_add_bss(hapd);
506
developera5e13c92023-03-03 15:51:12 +0800507@@ -2214,7 +2252,7 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
developer0b9a6392023-03-02 17:16:47 +0800508 hapd = iface->bss[j];
509 if (j)
510 os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN);
511- if (hostapd_setup_bss(hapd, j == 0)) {
512+ if (hostapd_setup_bss(hapd, j == 0, !iface->conf->mbssid)) {
513 for (;;) {
514 hapd = iface->bss[j];
515 hostapd_bss_deinit_no_free(hapd);
developera5e13c92023-03-03 15:51:12 +0800516@@ -2228,6 +2266,24 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
developer0b9a6392023-03-02 17:16:47 +0800517 if (is_zero_ether_addr(hapd->conf->bssid))
518 prev_addr = hapd->own_addr;
519 }
520+
521+ if (hapd->iconf->mbssid) {
522+ for (j = 0; j < iface->num_bss; j++) {
523+ hapd = iface->bss[j];
524+ if (hostapd_start_beacon(hapd)) {
525+ for (;;) {
526+ hapd = iface->bss[j];
527+ hostapd_bss_deinit_no_free(hapd);
528+ hostapd_free_hapd_data(hapd);
529+ if (j == 0)
530+ break;
531+ j--;
532+ }
533+ goto fail;
534+ }
535+ }
536+ }
537+
538 hapd = iface->bss[0];
539
540 hostapd_tx_queue_params(iface);
developera5e13c92023-03-03 15:51:12 +0800541@@ -3130,7 +3186,7 @@ int hostapd_add_iface(struct hapd_interfaces *interfaces, char *buf)
developer0b9a6392023-03-02 17:16:47 +0800542
543 if (start_ctrl_iface_bss(hapd) < 0 ||
544 (hapd_iface->state == HAPD_IFACE_ENABLED &&
545- hostapd_setup_bss(hapd, -1))) {
546+ hostapd_setup_bss(hapd, -1, true))) {
547 hostapd_cleanup(hapd);
548 hapd_iface->bss[hapd_iface->num_bss - 1] = NULL;
549 hapd_iface->conf->num_bss--;
550diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
developera5e13c92023-03-03 15:51:12 +0800551index 56d96a5..093c28a 100644
developer0b9a6392023-03-02 17:16:47 +0800552--- a/src/ap/hostapd.h
553+++ b/src/ap/hostapd.h
554@@ -660,6 +660,11 @@ struct hostapd_iface {
555 /* Previous WMM element information */
556 struct hostapd_wmm_ac_params prev_wmm[WMM_AC_NUM];
557
558+ /* Maximum number of interfaces supported for MBSSID advertisements */
559+ u8 mbssid_max_interfaces;
560+ /* Maximum profile periodicity for enhanced MBSSID advertisements */
561+ u8 ema_max_periodicity;
562+
563 int (*enable_iface_cb)(struct hostapd_iface *iface);
564 int (*disable_iface_cb)(struct hostapd_iface *iface);
565 };
566@@ -762,5 +767,7 @@ void fst_hostapd_fill_iface_obj(struct hostapd_data *hapd,
567 #endif /* CONFIG_FST */
568
569 int hostapd_set_acl(struct hostapd_data *hapd);
570+struct hostapd_data * hostapd_mbssid_get_tx_bss(struct hostapd_data *hapd);
571+int hostapd_mbssid_get_bss_index(struct hostapd_data *hapd);
572
573 #endif /* HOSTAPD_H */
574diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
developera5e13c92023-03-03 15:51:12 +0800575index 098793e..30bfa30 100644
developer0b9a6392023-03-02 17:16:47 +0800576--- a/src/ap/ieee802_11.c
577+++ b/src/ap/ieee802_11.c
578@@ -165,6 +165,7 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
579 int i, num, count;
580 int h2e_required;
581
582+ hapd->conf->xrates_supported = 0;
583 if (hapd->iface->current_rates == NULL)
584 return eid;
585
586@@ -214,6 +215,7 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
587 *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_SAE_H2E_ONLY;
588 }
589
590+ hapd->conf->xrates_supported = 1;
591 return pos;
592 }
593
594@@ -3979,6 +3981,23 @@ static void handle_auth(struct hostapd_data *hapd,
595 }
596
597
598+static u8 hostapd_max_bssid_indicator(struct hostapd_data *hapd)
599+{
600+ size_t num_bss_nontx;
601+ u8 max_bssid_ind = 0;
602+
603+ if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1)
604+ return 0;
605+
606+ num_bss_nontx = hapd->iface->num_bss - 1;
607+ while (num_bss_nontx > 0) {
608+ max_bssid_ind++;
609+ num_bss_nontx >>= 1;
610+ }
611+ return max_bssid_ind;
612+}
613+
614+
615 int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta)
616 {
617 int i, j = 32, aid;
618@@ -4004,7 +4023,10 @@ int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta)
619 }
620 if (j == 32)
621 return -1;
622- aid = i * 32 + j + 1;
623+ aid = i * 32 + j;
624+
625+ aid += (1 << hostapd_max_bssid_indicator(hapd));
626+
627 if (aid > 2007)
628 return -1;
629
630@@ -7579,4 +7601,256 @@ u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type)
631 return eid;
632 }
633
634+
635+static size_t hostapd_eid_mbssid_elem_len(struct hostapd_data *hapd,
636+ u32 frame_type, size_t *bss_index,
637+ const u8 *known_bss,
638+ size_t known_bss_len)
639+{
640+ struct hostapd_data *tx_bss = hostapd_mbssid_get_tx_bss(hapd);
641+ size_t len = 3, i;
642+
643+ for (i = *bss_index; i < hapd->iface->num_bss; i++) {
644+ struct hostapd_data *bss = hapd->iface->bss[i];
645+ const u8 *auth, *rsn = NULL, *rsnx = NULL;
646+ size_t nontx_profile_len, auth_len;
647+ u8 ie_count = 0;
648+
649+ if (known_bss && (known_bss_len > (i / 8))) {
650+ known_bss = &known_bss[i / 8];
651+ if (*known_bss & (u8)(BIT(i % 8)))
652+ continue;
653+ }
654+
655+ if (!bss || !bss->conf || !bss->started)
656+ continue;
657+
658+ /*
659+ * Sublement ID: 1 byte
660+ * Length: 1 byte
661+ * Nontransmitted capabilities: 4 bytes
662+ * SSID element: 2 + variable
663+ * Multiple BSSID Index Element: 3 bytes (+2 bytes in beacons)
664+ * Fixed length = 1 + 1 + 4 + 2 + 3 = 11
665+ */
666+ nontx_profile_len = 11 + bss->conf->ssid.ssid_len;
667+
668+ if (frame_type == WLAN_FC_STYPE_BEACON)
669+ nontx_profile_len += 2;
670+
671+ auth = wpa_auth_get_wpa_ie(bss->wpa_auth, &auth_len);
672+ if (auth) {
673+ rsn = get_ie(auth, auth_len, WLAN_EID_RSN);
674+ if (rsn)
675+ nontx_profile_len += (2 + rsn[1]);
676+
677+ rsnx = get_ie(auth, auth_len, WLAN_EID_RSNX);
678+ if (rsnx)
679+ nontx_profile_len += (2 + rsnx[1]);
680+ }
681+ if (!rsn && hostapd_wpa_ie(tx_bss, WLAN_EID_RSN))
682+ ie_count++;
683+ if (!rsnx && hostapd_wpa_ie(tx_bss, WLAN_EID_RSNX))
684+ ie_count++;
685+ if (bss->conf->xrates_supported)
686+ nontx_profile_len += 8;
687+ else if (hapd->conf->xrates_supported)
688+ ie_count++;
689+ if (ie_count)
690+ nontx_profile_len += (4 + ie_count);
691+
692+ if ((len + nontx_profile_len) > 255)
693+ goto mbssid_too_big;
694+
695+ len += nontx_profile_len;
696+ }
697+
698+mbssid_too_big:
699+ *bss_index = i;
700+ return len;
701+}
702+
703+
704+size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
705+ u8 *elem_count, const u8 *known_bss,
706+ size_t known_bss_len)
707+{
708+ size_t len = 0, bss_index = 1;
709+
710+ if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1 ||
711+ (frame_type != WLAN_FC_STYPE_BEACON &&
712+ frame_type != WLAN_FC_STYPE_PROBE_RESP))
713+ return 0;
714+
715+ if (frame_type == WLAN_FC_STYPE_BEACON) {
716+ if (!elem_count) {
717+ wpa_printf(MSG_ERROR,
718+ "MBSSID: Insufficient data for beacons");
719+ return 0;
720+ }
721+ *elem_count = 0;
722+ }
723+
724+ while (bss_index < hapd->iface->num_bss) {
725+ len += hostapd_eid_mbssid_elem_len(hapd, frame_type,
726+ &bss_index, known_bss,
727+ known_bss_len);
728+
729+ if (frame_type == WLAN_FC_STYPE_BEACON)
730+ *elem_count += 1;
731+ }
732+ return len;
733+}
734+
735+
736+static u8 * hostapd_eid_mbssid_elem(struct hostapd_data *hapd, u8 *eid, u8 *end,
737+ u32 frame_type, u8 max_bssid_indicator,
738+ size_t *bss_index, u8 elem_count,
739+ const u8 *known_bss, size_t known_bss_len)
740+{
741+ struct hostapd_data *tx_bss = hostapd_mbssid_get_tx_bss(hapd);
742+ size_t i;
743+ u8 *eid_len_offset, *max_bssid_indicator_offset;
744+
745+ *eid++ = WLAN_EID_MULTIPLE_BSSID;
746+ eid_len_offset = eid++;
747+ max_bssid_indicator_offset = eid++;
748+
749+ for (i = *bss_index; i < hapd->iface->num_bss; i++) {
750+ struct hostapd_data *bss = hapd->iface->bss[i];
751+ struct hostapd_bss_config *conf;
752+ u8 *eid_len_pos, *nontx_bss_start = eid;
753+ const u8 *auth, *rsn = NULL, *rsnx = NULL;
754+ u8 ie_count = 0, non_inherit_ie[3];
755+ size_t auth_len = 0;
756+ u16 capab_info;
757+
758+ if (known_bss && (known_bss_len > (i / 8))) {
759+ known_bss = &known_bss[i / 8];
760+ if (*known_bss & (u8)(BIT(i % 8)))
761+ continue;
762+ }
763+
764+ if (!bss || !bss->conf || !bss->started)
765+ continue;
766+ conf = bss->conf;
767+
768+ *eid++ = WLAN_EID_SUBELEMENT_NONTRANSMITTED_BSSID_PROFILE;
769+ eid_len_pos = eid++;
770+
771+ *eid++ = WLAN_EID_NONTRANSMITTED_BSSID_CAPA;
772+ *eid++ = sizeof(capab_info);
773+ capab_info = host_to_le16(hostapd_own_capab_info(bss));
774+ os_memcpy(eid, (const void *)&capab_info, sizeof(capab_info));
775+ eid += sizeof(capab_info);
776+
777+ *eid++ = WLAN_EID_SSID;
778+ *eid++ = conf->ssid.ssid_len;
779+ os_memcpy(eid, conf->ssid.ssid, conf->ssid.ssid_len);
780+ eid += conf->ssid.ssid_len;
781+
782+ *eid++ = WLAN_EID_MULTIPLE_BSSID_INDEX;
783+ if (frame_type == WLAN_FC_STYPE_BEACON) {
784+ *eid++ = 3;
785+ *eid++ = i;
786+ if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED &&
787+ (conf->dtim_period % elem_count))
788+ conf->dtim_period = elem_count;
789+ *eid++ = conf->dtim_period;
790+ *eid++ = 0xFF;
791+ } else {
792+ *eid++ = 1;
793+ *eid++ = i;
794+ }
795+
796+ auth = wpa_auth_get_wpa_ie(bss->wpa_auth, &auth_len);
797+ if (auth) {
798+ rsn = get_ie(auth, auth_len, WLAN_EID_RSN);
799+ if (rsn) {
800+ os_memcpy(eid, rsn, 2 + rsn[1]);
801+ eid += (2 + rsn[1]);
802+ }
803+
804+ rsnx = get_ie(auth, auth_len, WLAN_EID_RSNX);
805+ if (rsnx) {
806+ os_memcpy(eid, rsnx, 2 + rsnx[1]);
807+ eid += (2 + rsnx[1]);
808+ }
809+ }
810+ if (!rsn && hostapd_wpa_ie(tx_bss, WLAN_EID_RSN)) {
811+ non_inherit_ie[ie_count] = WLAN_EID_RSN;
812+ ie_count++;
813+ }
814+ if (!rsnx && hostapd_wpa_ie(tx_bss, WLAN_EID_RSNX)) {
815+ non_inherit_ie[ie_count] = WLAN_EID_RSNX;
816+ ie_count++;
817+ }
818+ if (hapd->conf->xrates_supported &&
819+ !bss->conf->xrates_supported) {
820+ non_inherit_ie[ie_count] = WLAN_EID_EXT_SUPP_RATES;
821+ ie_count++;
822+ }
823+ if (ie_count) {
824+ *eid++ = WLAN_EID_EXTENSION;
825+ *eid++ = 2 + ie_count;
826+ *eid++ = WLAN_EID_EXT_NON_INHERITANCE;
827+ *eid++ = ie_count;
828+ os_memcpy(eid, non_inherit_ie, ie_count);
829+ eid += ie_count;
830+ }
831+
832+ *eid_len_pos = (eid - eid_len_pos) - 1;
833+
834+ if (((eid - eid_len_offset) - 1) > 255) {
835+ eid = nontx_bss_start;
836+ goto mbssid_too_big;
837+ }
838+ }
839+
840+mbssid_too_big:
841+ *bss_index = i;
842+ *max_bssid_indicator_offset = max_bssid_indicator;
843+ if (*max_bssid_indicator_offset < 1)
844+ *max_bssid_indicator_offset = 1;
845+ *eid_len_offset = (eid - eid_len_offset) - 1;
846+ return eid;
847+}
848+
849+
850+u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
851+ u32 frame_type, u8 elem_count, u8 **elem_offset,
852+ const u8 *known_bss, size_t known_bss_len)
853+{
854+ size_t bss_index = 1;
855+ u8 elem_index = 0;
856+
857+ if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1 ||
858+ (frame_type != WLAN_FC_STYPE_BEACON &&
859+ frame_type != WLAN_FC_STYPE_PROBE_RESP))
860+ return eid;
861+
862+ if (frame_type == WLAN_FC_STYPE_BEACON && !elem_offset) {
863+ wpa_printf(MSG_ERROR, "MBSSID: Insufficient data for beacons");
864+ return eid;
865+ }
866+
867+ while (bss_index < hapd->iface->num_bss) {
868+ if (frame_type == WLAN_FC_STYPE_BEACON) {
869+ if (elem_index == elem_count) {
870+ wpa_printf(MSG_WARNING,
871+ "MBSSID: More number of elements than provided array");
872+ break;
873+ }
874+
875+ elem_offset[elem_index] = eid;
876+ elem_index = elem_index + 1;
877+ }
878+ eid = hostapd_eid_mbssid_elem(hapd, eid, end, frame_type,
879+ hostapd_max_bssid_indicator(hapd),
880+ &bss_index, elem_count,
881+ known_bss, known_bss_len);
882+ }
883+ return eid;
884+}
885+
886 #endif /* CONFIG_NATIVE_WINDOWS */
887diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
developera5e13c92023-03-03 15:51:12 +0800888index fa1f47b..bb454bb 100644
developer0b9a6392023-03-02 17:16:47 +0800889--- a/src/ap/ieee802_11.h
890+++ b/src/ap/ieee802_11.h
891@@ -214,5 +214,10 @@ u16 copy_sta_eht_capab(struct hostapd_data *hapd, struct sta_info *sta,
892 enum ieee80211_op_mode opmode,
893 const u8 *he_capab, size_t he_capab_len,
894 const u8 *eht_capab, size_t eht_capab_len);
895-
896+size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
897+ u8 *elem_count, const u8 *known_bss,
898+ size_t known_bss_len);
899+u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
900+ u32 frame_type, u8 elem_count, u8 **elem_offset,
901+ const u8 *known_bss, size_t known_bss_len);
902 #endif /* IEEE802_11_H */
903diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c
developera5e13c92023-03-03 15:51:12 +0800904index 4f85d78..7f5b475 100644
developer0b9a6392023-03-02 17:16:47 +0800905--- a/src/ap/ieee802_11_shared.c
906+++ b/src/ap/ieee802_11_shared.c
907@@ -364,6 +364,8 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
908 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
909 if (hapd->conf->bss_transition)
910 *pos |= 0x08; /* Bit 19 - BSS Transition */
911+ if (hapd->iconf->mbssid)
912+ *pos |= 0x40; /* Bit 22 - Multiple BSSID */
913 break;
914 case 3: /* Bits 24-31 */
915 #ifdef CONFIG_WNM_AP
916@@ -436,6 +438,8 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
917 (hapd->iface->drv_flags &
918 WPA_DRIVER_FLAGS_BEACON_PROTECTION))
919 *pos |= 0x10; /* Bit 84 - Beacon Protection Enabled */
920+ if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED)
921+ *pos |= 0x08; /* Bit 83 - Enhanced multiple BSSID */
922 break;
923 case 11: /* Bits 88-95 */
924 #ifdef CONFIG_SAE_PK
925@@ -471,6 +475,13 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
926 *pos &= ~hapd->conf->ext_capa_mask[i];
927 *pos |= hapd->conf->ext_capa[i];
928 }
929+
930+ /* Clear bits 83 and 22 if EMA and MBSSID are not enabled
931+ * otherwise association fails with some clients */
932+ if (i == 10 && hapd->iconf->mbssid < ENHANCED_MBSSID_ENABLED)
933+ *pos &= ~0x08;
934+ if (i == 2 && !hapd->iconf->mbssid)
935+ *pos &= ~0x40;
936 }
937
938 while (len > 0 && eid[1 + len] == 0) {
939diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
developera5e13c92023-03-03 15:51:12 +0800940index c8ee90c..2fab7c3 100644
developer0b9a6392023-03-02 17:16:47 +0800941--- a/src/common/ieee802_11_common.c
942+++ b/src/common/ieee802_11_common.c
943@@ -315,6 +315,10 @@ static int ieee802_11_parse_extension(const u8 *pos, size_t elen,
944 elems->eht_operation = pos;
945 elems->eht_operation_len = elen;
946 break;
947+ case WLAN_EID_EXT_KNOWN_BSSID:
948+ elems->mbssid_known_bss = pos;
949+ elems->mbssid_known_bss_len = elen;
950+ break;
951 default:
952 if (show_errors) {
953 wpa_printf(MSG_MSGDUMP,
954diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
developera5e13c92023-03-03 15:51:12 +0800955index 94e1d7b..1e4e27d 100644
developer0b9a6392023-03-02 17:16:47 +0800956--- a/src/common/ieee802_11_common.h
957+++ b/src/common/ieee802_11_common.h
958@@ -119,6 +119,7 @@ struct ieee802_11_elems {
959 const u8 *pasn_params;
960 const u8 *eht_capabilities;
961 const u8 *eht_operation;
962+ const u8 *mbssid_known_bss;
963
964 u8 ssid_len;
965 u8 supp_rates_len;
966@@ -176,6 +177,8 @@ struct ieee802_11_elems {
967 u8 eht_capabilities_len;
968 u8 eht_operation_len;
969
970+ u8 mbssid_known_bss_len;
971+
972 struct mb_ies_info mb_ies;
973 struct frag_ies_info frag_ies;
974 };
975diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
developera5e13c92023-03-03 15:51:12 +0800976index 62088bd..0bbbca9 100644
developer0b9a6392023-03-02 17:16:47 +0800977--- a/src/common/ieee802_11_defs.h
978+++ b/src/common/ieee802_11_defs.h
979@@ -481,6 +481,9 @@
980 #define WLAN_EID_EXT_SPATIAL_REUSE 39
981 #define WLAN_EID_EXT_COLOR_CHANGE_ANNOUNCEMENT 42
982 #define WLAN_EID_EXT_OCV_OCI 54
983+#define WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION 55
984+#define WLAN_EID_EXT_NON_INHERITANCE 56
985+#define WLAN_EID_EXT_KNOWN_BSSID 57
986 #define WLAN_EID_EXT_SHORT_SSID_LIST 58
987 #define WLAN_EID_EXT_HE_6GHZ_BAND_CAP 59
988 #define WLAN_EID_EXT_EDMG_CAPABILITIES 61
989@@ -497,6 +500,8 @@
990 #define WLAN_EID_EXT_MULTI_LINK_TRAFFIC_INDICATION 110
991 #define WLAN_EID_EXT_AKM_SUITE_SELECTOR 114
992
993+#define WLAN_EID_SUBELEMENT_NONTRANSMITTED_BSSID_PROFILE 0
994+
995 /* Extended Capabilities field */
996 #define WLAN_EXT_CAPAB_20_40_COEX 0
997 #define WLAN_EXT_CAPAB_GLK 1
998diff --git a/src/drivers/driver.h b/src/drivers/driver.h
developera5e13c92023-03-03 15:51:12 +0800999index 82daef0..36f465c 100644
developer0b9a6392023-03-02 17:16:47 +08001000--- a/src/drivers/driver.h
1001+++ b/src/drivers/driver.h
1002@@ -1633,6 +1633,43 @@ struct wpa_driver_ap_params {
1003 * ibf_enable=<val>
1004 */
1005 u8 ibf_enable;
1006+
1007+ /**
1008+ * mbssid_tx_iface - Transmitting interface of the MBSSID set
1009+ */
1010+ const char *mbssid_tx_iface;
1011+
1012+ /**
1013+ * mbssid_index - The index of this BSS in the MBSSID set
1014+ */
1015+ unsigned int mbssid_index;
1016+
1017+ /**
1018+ * mbssid_elem - Buffer containing all MBSSID elements
1019+ */
1020+ u8 *mbssid_elem;
1021+
1022+ /**
1023+ * mbssid_elem_len - Total length of all MBSSID elements
1024+ */
1025+ size_t mbssid_elem_len;
1026+
1027+ /**
1028+ * mbssid_elem_count - The number of MBSSID elements
1029+ */
1030+ u8 mbssid_elem_count;
1031+
1032+ /**
1033+ * mbssid_elem_offset - Offsets to elements in mbssid_elem.
1034+ * Kernel will use these offsets to generate multiple BSSID beacons.
1035+ */
1036+ u8 **mbssid_elem_offset;
1037+
1038+ /**
1039+ * ema - Enhanced MBSSID advertisements support.
1040+ */
1041+ bool ema;
1042+
1043 };
1044
1045 struct wpa_driver_mesh_bss_params {
1046@@ -2197,6 +2234,11 @@ struct wpa_driver_capa {
1047
1048 /* Maximum number of supported CSA counters */
1049 u16 max_csa_counters;
1050+
1051+ /* Maximum number of interfaces supported for MBSSID advertisements */
1052+ u8 mbssid_max_interfaces;
1053+ /* Maximum profile periodicity for enhanced MBSSID advertisements */
1054+ u8 ema_max_periodicity;
1055 };
1056
1057
1058diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
developera5e13c92023-03-03 15:51:12 +08001059index 6c65901..3753409 100644
developer0b9a6392023-03-02 17:16:47 +08001060--- a/src/drivers/driver_nl80211.c
1061+++ b/src/drivers/driver_nl80211.c
1062@@ -4540,6 +4540,55 @@ static int nl80211_unsol_bcast_probe_resp(struct i802_bss *bss,
1063 nla_nest_end(msg, attr);
1064 return 0;
1065 }
1066+
1067+
1068+static int nl80211_mbssid(struct nl_msg *msg,
1069+ struct wpa_driver_ap_params *params)
1070+{
1071+ struct nlattr *config, *elems;
1072+ int ifidx;
1073+
1074+ if (!params->mbssid_tx_iface)
1075+ return 0;
1076+
1077+ config = nla_nest_start(msg, NL80211_ATTR_MBSSID_CONFIG);
1078+ if (!config)
1079+ return -1;
1080+
1081+ nla_put_u8(msg, NL80211_MBSSID_CONFIG_ATTR_INDEX, params->mbssid_index);
1082+ if (params->mbssid_tx_iface) {
1083+ ifidx = if_nametoindex(params->mbssid_tx_iface);
1084+ if (ifidx <= 0)
1085+ return -1;
1086+ nla_put_u32(msg,
1087+ NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX,
1088+ ifidx);
1089+ }
1090+
1091+ if (params->ema)
1092+ nla_put_flag(msg, NL80211_MBSSID_CONFIG_ATTR_EMA);
1093+
1094+ nla_nest_end(msg, config);
1095+
1096+ if (params->mbssid_elem_count && params->mbssid_elem_len &&
1097+ params->mbssid_elem_offset && *params->mbssid_elem_offset) {
1098+ u8 i, **offs = params->mbssid_elem_offset;
1099+
1100+ elems = nla_nest_start(msg, NL80211_ATTR_MBSSID_ELEMS);
1101+ if (!elems)
1102+ return -1;
1103+
1104+ for (i = 0; i < params->mbssid_elem_count - 1; i++)
1105+ nla_put(msg, i + 1, offs[i + 1] - offs[i], offs[i]);
1106+
1107+ nla_put(msg, i + 1,
1108+ *offs + params->mbssid_elem_len - offs[i],
1109+ offs[i]);
1110+
1111+ nla_nest_end(msg, elems);
1112+ }
1113+ return 0;
1114+}
1115 #endif /* CONFIG_IEEE80211AX */
1116
1117
1118@@ -4838,6 +4887,9 @@ static int wpa_driver_nl80211_set_ap(void *priv,
1119 if (params->unsol_bcast_probe_resp_interval &&
1120 nl80211_unsol_bcast_probe_resp(bss, msg, params) < 0)
1121 goto fail;
1122+
1123+ if (nl80211_mbssid(msg, params) < 0)
1124+ goto fail;
1125 #endif /* CONFIG_IEEE80211AX */
1126
1127 #ifdef CONFIG_SAE
1128diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
developera5e13c92023-03-03 15:51:12 +08001129index 06a52db..d8078bc 100644
developer0b9a6392023-03-02 17:16:47 +08001130--- a/src/drivers/driver_nl80211_capa.c
1131+++ b/src/drivers/driver_nl80211_capa.c
1132@@ -857,6 +857,30 @@ err:
1133 }
1134
1135
1136+static void wiphy_info_mbssid(struct wpa_driver_capa *cap, struct nlattr *attr)
1137+{
1138+ struct nlattr *config[NL80211_MBSSID_CONFIG_ATTR_MAX + 1];
1139+
1140+ if (nla_parse_nested(config, NL80211_MBSSID_CONFIG_ATTR_MAX, attr,
1141+ NULL))
1142+ return;
1143+
1144+ if (!config[NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES])
1145+ return;
1146+
1147+ cap->mbssid_max_interfaces =
1148+ nla_get_u8(config[NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES]);
1149+
1150+ if (config[NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY])
1151+ cap->ema_max_periodicity =
1152+ nla_get_u8(config[NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY]);
1153+
1154+ wpa_printf(MSG_DEBUG,
1155+ "multiple_bssid: max interfaces %u, max profile periodicity %u\n",
1156+ cap->mbssid_max_interfaces, cap->ema_max_periodicity);
1157+}
1158+
1159+
1160 static int wiphy_info_handler(struct nl_msg *msg, void *arg)
1161 {
1162 struct nlattr *tb[NL80211_ATTR_MAX + 1];
1163@@ -1106,6 +1130,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
1164 if (tb[NL80211_ATTR_WIPHY_SELF_MANAGED_REG])
1165 capa->flags |= WPA_DRIVER_FLAGS_SELF_MANAGED_REGULATORY;
1166
1167+ if (tb[NL80211_ATTR_MBSSID_CONFIG])
1168+ wiphy_info_mbssid(capa, tb[NL80211_ATTR_MBSSID_CONFIG]);
1169+
1170 return NL_SKIP;
1171 }
1172
1173--
11742.18.0
1175