hostapd: add multiple_bssid support
authorJohn Crispin <john@phrozen.org>
Wed, 7 Oct 2020 12:02:44 +0000 (14:02 +0200)
committerJohn Crispin <john@phrozen.org>
Wed, 7 Oct 2020 12:06:43 +0000 (14:06 +0200)
Signed-off-by: John Crispin <john@phrozen.org>
package/network/services/hostapd/files/hostapd.sh
package/network/services/hostapd/patches/801-multiple_bssid-add-support.patch [new file with mode: 0644]

index 3290358ed21ea571ac7b7683f6900b749064b1b9..f9318f7927231901cc7d5a58ae346c524ed19429 100644 (file)
@@ -101,6 +101,7 @@ hostapd_common_add_device_config() {
 
        config_add_string acs_chan_bias
        config_add_array hostapd_options
+       config_add_boolean multiple_bssid ema_beacon
 
        hostapd_add_log_config
 }
@@ -113,7 +114,8 @@ hostapd_prepare_device_config() {
        local base_cfg=
 
        json_get_vars country country_ie beacon_int:100 dtim_period:2 doth require_mode legacy_rates \
-               acs_chan_bias local_pwr_constraint spectrum_mgmt_required airtime_mode
+               acs_chan_bias local_pwr_constraint spectrum_mgmt_required airtime_mode \
+               multiple_bssid ema_beacon
 
        hostapd_set_log_options base_cfg
 
@@ -122,6 +124,8 @@ hostapd_prepare_device_config() {
        set_default doth 1
        set_default legacy_rates 1
        set_default airtime_mode 0
+       set_default multiple_bssid 0
+        set_default ema_beacon 0
 
        [ "$hwmode" = "b" ] && legacy_rates=1
 
@@ -169,6 +173,8 @@ hostapd_prepare_device_config() {
        append base_cfg "beacon_int=$beacon_int" "$N"
        append base_cfg "dtim_period=$dtim_period" "$N"
        [ "$airtime_mode" -gt 0 ] && append base_cfg "airtime_mode=$airtime_mode" "$N"
+       append base_cfg "multiple_bssid=$multiple_bssid" "$N"
+       append base_cfg "ema_beacon=$ema_beacon" "$N"
 
        json_get_values opts hostapd_options
        for val in $opts; do
diff --git a/package/network/services/hostapd/patches/801-multiple_bssid-add-support.patch b/package/network/services/hostapd/patches/801-multiple_bssid-add-support.patch
new file mode 100644 (file)
index 0000000..fc610e4
--- /dev/null
@@ -0,0 +1,579 @@
+From 21f73324487638c89ee2f09986c8c40e3a146837 Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Tue, 6 Oct 2020 12:13:00 +0200
+Subject: [PATCH] multiple_bssid: add support
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ hostapd/config_file.c        |   4 ++
+ hostapd/ctrl_iface.c         |   3 +
+ src/ap/ap_config.h           |   3 +
+ src/ap/beacon.c              |  37 +++++++++-
+ src/ap/hostapd.c             |  20 ++++++
+ src/ap/hostapd.h             |   2 +
+ src/ap/ieee802_11.c          | 132 ++++++++++++++++++++++++++++++++++-
+ src/ap/ieee802_11.h          |   5 ++
+ src/ap/ieee802_11_shared.c   |   2 +
+ src/common/ieee802_11_defs.h |   3 +
+ src/drivers/driver.h         |  42 +++++++++++
+ src/drivers/driver_nl80211.c |  32 ++++++++-
+ src/drivers/nl80211_copy.h   |  19 +++++
+ 13 files changed, 299 insertions(+), 5 deletions(-)
+
+Index: hostapd-2020-06-08-5a8b3662/hostapd/config_file.c
+===================================================================
+--- hostapd-2020-06-08-5a8b3662.orig/hostapd/config_file.c
++++ hostapd-2020-06-08-5a8b3662/hostapd/config_file.c
+@@ -4669,6 +4669,10 @@ static int hostapd_config_fill(struct ho
+               }
+               bss->mka_psk_set |= MKA_PSK_SET_CKN;
+ #endif /* CONFIG_MACSEC */
++      } else if (os_strcmp(buf, "multiple_bssid") == 0) {
++              conf->multiple_bssid = atoi(pos);
++      } else if (os_strcmp(buf, "ema_beacon") == 0) {
++              conf->ema_beacon = atoi(pos);
+       } else {
+               wpa_printf(MSG_ERROR,
+                          "Line %d: unknown configuration item '%s'",
+Index: hostapd-2020-06-08-5a8b3662/hostapd/ctrl_iface.c
+===================================================================
+--- hostapd-2020-06-08-5a8b3662.orig/hostapd/ctrl_iface.c
++++ hostapd-2020-06-08-5a8b3662/hostapd/ctrl_iface.c
+@@ -2729,6 +2729,9 @@ static int hostapd_ctrl_iface_chan_switc
+                        * submitting multi-BSS CSA requests? */
+                       return ret;
+               }
++
++              if (iface->bss[i]->iconf->multiple_bssid)
++                      break;
+       }
+       return 0;
+Index: hostapd-2020-06-08-5a8b3662/src/ap/ap_config.h
+===================================================================
+--- hostapd-2020-06-08-5a8b3662.orig/src/ap/ap_config.h
++++ hostapd-2020-06-08-5a8b3662/src/ap/ap_config.h
+@@ -1000,6 +1000,9 @@ struct hostapd_config {
+       u8 vht_oper_centr_freq_seg1_idx;
+       u8 ht40_plus_minus_allowed;
++      u8 multiple_bssid;
++      u8 ema_beacon;
++
+       /* Use driver-generated interface addresses when adding multiple BSSs */
+       u8 use_driver_iface_addr;
+Index: hostapd-2020-06-08-5a8b3662/src/ap/beacon.c
+===================================================================
+--- hostapd-2020-06-08-5a8b3662.orig/src/ap/beacon.c
++++ hostapd-2020-06-08-5a8b3662/src/ap/beacon.c
+@@ -293,7 +293,7 @@ static const u8 * hostapd_vendor_wpa_ie(
+ }
+-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;
+@@ -436,6 +436,9 @@ static u8 * hostapd_gen_probe_resp(struc
+       u8 *pos, *epos, *csa_pos;
+       size_t buflen;
++      if (hapd->iconf->multiple_bssid)
++              hapd = hostapd_get_primary_bss(hapd);
++
+ #define MAX_PROBERESP_LEN 768
+       buflen = MAX_PROBERESP_LEN;
+ #ifdef CONFIG_WPS
+@@ -472,6 +475,8 @@ static u8 * hostapd_gen_probe_resp(struc
+       buflen += hostapd_mbo_ie_len(hapd);
+       buflen += hostapd_eid_owe_trans_len(hapd);
+       buflen += hostapd_eid_dpp_cc_len(hapd);
++      if (hapd->iconf->multiple_bssid)
++              buflen += hostapd_eid_multiple_bssid_len(hapd);
+       resp = os_zalloc(buflen);
+       if (resp == NULL)
+@@ -527,6 +532,9 @@ static u8 * hostapd_gen_probe_resp(struc
+       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, 0, NULL, 0, 0);
++
+       /* eCSA IE */
+       csa_pos = hostapd_eid_ecsa(hapd, pos);
+       if (csa_pos != pos)
+@@ -821,6 +829,10 @@ void handle_probe_req(struct hostapd_dat
+               .elems = &elems,
+       };
++        if (hapd->iconf->multiple_bssid &&
++          hapd != hostapd_get_primary_bss(hapd))
++              return;
++
+       if (len < IEEE80211_HDRLEN)
+               return;
+       ie = ((const u8 *) mgmt) + IEEE80211_HDRLEN;
+@@ -1070,7 +1082,7 @@ void handle_probe_req(struct hostapd_dat
+                               hapd->cs_c_off_ecsa_proberesp;
+       }
+-      ret = hostapd_drv_send_mlme(hapd, resp, resp_len, noack,
++      ret = hostapd_drv_send_mlme(hostapd_get_primary_bss(hapd), resp, resp_len, noack,
+                                   csa_offs_len ? csa_offs : NULL,
+                                   csa_offs_len, 0);
+@@ -1467,6 +1479,8 @@ void ieee802_11_free_ap_params(struct wp
+       params->head = NULL;
+       os_free(params->proberesp);
+       params->proberesp = NULL;
++      os_free(params->multiple_bssid_ies);
++      params->multiple_bssid_ies = NULL;
+ }
+@@ -1507,6 +1521,25 @@ int ieee802_11_set_beacon(struct hostapd
+       params.twt_responder = hostapd_get_he_twt_responder(hapd,
+                                                           IEEE80211_MODE_AP);
+ #endif /* CONFIG_IEEE80211AX */
++        if (hapd->iconf->multiple_bssid) {
++              int len = hostapd_eid_multiple_bssid_len(hapd);
++              u8 *end;
++
++              params.multiple_bssid_index = hostapd_get_bss_index(hapd);
++              params.multiple_bssid_count = iface->num_bss;
++              params.ema_beacon = hapd->iconf->ema_beacon;
++              if (hapd != hapd->iface->bss[0])
++                      params.multiple_bssid_parent = hapd->iface->bss[0]->conf->iface;
++              params.multiple_bssid_ies = os_zalloc(len);
++              if (params.multiple_bssid_ies == NULL)
++                      goto fail;
++              end = hostapd_eid_multiple_bssid(hapd, params.multiple_bssid_ies,
++                                               params.multiple_bssid_ies + len,
++                                               1, params.multiple_bssid_ie_offsets,
++                                               &params.multiple_bssid_ie_count,
++                                               MULTIPLE_BSSID_IE_MAX);
++              params.multiple_bssid_ie_len = end - params.multiple_bssid_ies;
++      }
+       hapd->reenable_beacon = 0;
+       if (cmode &&
+Index: hostapd-2020-06-08-5a8b3662/src/ap/hostapd.c
+===================================================================
+--- hostapd-2020-06-08-5a8b3662.orig/src/ap/hostapd.c
++++ hostapd-2020-06-08-5a8b3662/src/ap/hostapd.c
+@@ -87,6 +87,26 @@ int hostapd_for_each_interface(struct ha
+ }
++int hostapd_get_bss_index(struct hostapd_data *hapd)
++{
++      size_t i;
++
++      for (i = 1; i < hapd->iface->num_bss; i++)
++              if (hapd->iface->bss[i] == hapd)
++                      return i;
++      return 0;
++}
++
++
++struct hostapd_data * hostapd_get_primary_bss(struct hostapd_data *hapd)
++{
++      if (hapd->iconf->multiple_bssid)
++              return hapd->iface->bss[0];
++
++      return hapd;
++}
++
++
+ void hostapd_reconfig_encryption(struct hostapd_data *hapd)
+ {
+       if (hapd->wpa_auth)
+Index: hostapd-2020-06-08-5a8b3662/src/ap/hostapd.h
+===================================================================
+--- hostapd-2020-06-08-5a8b3662.orig/src/ap/hostapd.h
++++ hostapd-2020-06-08-5a8b3662/src/ap/hostapd.h
+@@ -601,6 +601,8 @@ struct hostapd_iface {
+ int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
+                              int (*cb)(struct hostapd_iface *iface,
+                                        void *ctx), void *ctx);
++int hostapd_get_bss_index(struct hostapd_data *hapd);
++struct hostapd_data * hostapd_get_primary_bss(struct hostapd_data *hapd);
+ int hostapd_reload_config(struct hostapd_iface *iface, int reconf);
+ void hostapd_reconfig_encryption(struct hostapd_data *hapd);
+ struct hostapd_data *
+Index: hostapd-2020-06-08-5a8b3662/src/ap/ieee802_11.c
+===================================================================
+--- hostapd-2020-06-08-5a8b3662.orig/src/ap/ieee802_11.c
++++ hostapd-2020-06-08-5a8b3662/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
+@@ -2739,7 +2740,11 @@ int hostapd_get_aid(struct hostapd_data
+       }
+       if (j == 32)
+               return -1;
+-      aid = i * 32 + j + 1;
++      aid = i * 32 + j;
++      if (hapd->iconf->multiple_bssid)
++              aid += hapd->iface->num_bss;
++      else
++              aid += 1;
+       if (aid > 2007)
+               return -1;
+@@ -4404,7 +4409,7 @@ static void handle_assoc(struct hostapd_
+               goto fail;
+       omit_rsnxe = !get_ie(pos, left, WLAN_EID_RSNX);
+-      if (hostapd_get_aid(hapd, sta) < 0) {
++      if (hostapd_get_aid(hostapd_get_primary_bss(hapd), sta) < 0) {
+               hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
+                              HOSTAPD_LEVEL_INFO, "No room for more AIDs");
+               resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
+@@ -5612,4 +5617,127 @@ void ieee802_11_rx_from_unknown(struct h
+ }
++
++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 is_beacon)
++{
++      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, *index_size_offset, *pos = eid, *rsn;
++              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;
++              index_size_offset = eid++;
++              *eid++ = i;
++              if (is_beacon) {
++                      *eid++ = bss->conf->dtim_period;
++                      *eid++ = 0xFF;
++              }
++              *index_size_offset = (eid - index_size_offset) - 1;
++
++              rsn = hostapd_get_rsne(bss, eid, end - eid);
++              if (rsn == eid) {
++                      /* add RSN non-inheritance IE */
++                      *eid++ = WLAN_EID_EXTENSION;
++                      *eid++ = 3;
++                      *eid++ = WLAN_EID_EXT_NON_INHERITANCE;
++                      *eid++ = 1;
++                      *eid++ = WLAN_EID_RSN;
++              } else {
++                      eid = rsn;
++              }
++              *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(hapd->iface->num_bss));
++      if (*num_offset < 1)
++              *num_offset = 1;
++      *size_offset = (eid - size_offset) - 1;
++
++      return eid;
++}
++
++
++u8 * hostapd_eid_multiple_bssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
++                              u8 is_beacon, u8 **eid_offsets, int *eid_count,
++                              int eid_max)
++{
++      int count = 1;
++
++      while (count < hapd->iface->num_bss) {
++              if (eid_offsets && *eid_count < eid_max) {
++                      eid_offsets[*eid_count] = eid;
++                      *eid_count = *eid_count + 1;
++              }
++              eid = hostapd_eid_multiple_bssid_chunk(hapd, eid, end, &count,
++                                                     is_beacon);
++      }
++      return eid;
++}
++
+ #endif /* CONFIG_NATIVE_WINDOWS */
+Index: hostapd-2020-06-08-5a8b3662/src/ap/ieee802_11.h
+===================================================================
+--- hostapd-2020-06-08-5a8b3662.orig/src/ap/ieee802_11.h
++++ hostapd-2020-06-08-5a8b3662/src/ap/ieee802_11.h
+@@ -119,6 +119,10 @@ u8 * hostapd_eid_time_zone(struct hostap
+ 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,
++                              u8 is_beacon, u8 **eid_offsets, int *eid_count,
++                              int eid_max);
++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 +198,6 @@ int get_tx_parameters(struct sta_info *s
+ 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 */
+Index: hostapd-2020-06-08-5a8b3662/src/ap/ieee802_11_shared.c
+===================================================================
+--- hostapd-2020-06-08-5a8b3662.orig/src/ap/ieee802_11_shared.c
++++ hostapd-2020-06-08-5a8b3662/src/ap/ieee802_11_shared.c
+@@ -356,6 +356,8 @@ static void hostapd_ext_capab_byte(struc
+                       *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
+Index: hostapd-2020-06-08-5a8b3662/src/common/ieee802_11_defs.h
+===================================================================
+--- hostapd-2020-06-08-5a8b3662.orig/src/common/ieee802_11_defs.h
++++ hostapd-2020-06-08-5a8b3662/src/common/ieee802_11_defs.h
+@@ -451,6 +451,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
+@@ -473,6 +475,7 @@
+ #define WLAN_EID_EXT_HE_MU_EDCA_PARAMS 38
+ #define WLAN_EID_EXT_SPATIAL_REUSE 39
+ #define WLAN_EID_EXT_OCV_OCI 54
++#define WLAN_EID_EXT_NON_INHERITANCE 56
+ #define WLAN_EID_EXT_SHORT_SSID_LIST 58
+ #define WLAN_EID_EXT_HE_6GHZ_BAND_CAP 59
+ #define WLAN_EID_EXT_EDMG_CAPABILITIES 61
+Index: hostapd-2020-06-08-5a8b3662/src/drivers/driver.h
+===================================================================
+--- hostapd-2020-06-08-5a8b3662.orig/src/drivers/driver.h
++++ hostapd-2020-06-08-5a8b3662/src/drivers/driver.h
+@@ -1215,6 +1215,8 @@ struct wowlan_triggers {
+       u8 rfkill_release;
+ };
++#define MULTIPLE_BSSID_IE_MAX 8
++
+ struct wpa_driver_ap_params {
+       /**
+        * head - Beacon head from IEEE 802.11 header to IEs before TIM IE
+@@ -1511,6 +1513,46 @@ struct wpa_driver_ap_params {
+        * twt_responder - Whether Target Wait Time responder is enabled
+        */
+       int twt_responder;
++
++      /**
++       * multiple_bssid_parent - The transmitting iface
++       */
++      const char *multiple_bssid_parent;
++
++      /**
++       * multiple_bssid_index - The index of this BSS in the group
++       */
++      unsigned int multiple_bssid_index;
++
++      /**
++       * multiple_bssid_count - The number of BSSs in the group
++       */
++      unsigned int multiple_bssid_count;
++
++      /**
++       * multiple_bssid_ies - This buffer contains all of the IEs
++       */
++      u8 *multiple_bssid_ies;
++
++      /**
++       * multiple_bssid_ie_len - The IE buffer length
++       */
++      int multiple_bssid_ie_len;
++
++      /**
++       * multiple_bssid_ie_offsets - The offsets to the IEs inside multiple_bssid_ies
++       */
++      u8 *multiple_bssid_ie_offsets[MULTIPLE_BSSID_IE_MAX];
++
++      /**
++       * multiple_bssid_ie_count - The the number of offsets inside multiple_bssid_ie_offsets
++       */
++      int multiple_bssid_ie_count;
++
++      /**
++       * ema_beacon - should the multiple_bssid beacons be sent out in EMA mode
++       */
++      int ema_beacon;
+ };
+ struct wpa_driver_mesh_bss_params {
+Index: hostapd-2020-06-08-5a8b3662/src/drivers/driver_nl80211.c
+===================================================================
+--- hostapd-2020-06-08-5a8b3662.orig/src/drivers/driver_nl80211.c
++++ hostapd-2020-06-08-5a8b3662/src/drivers/driver_nl80211.c
+@@ -4488,6 +4488,37 @@ static int wpa_driver_nl80211_set_ap(voi
+       }
+ #endif /* CONFIG_IEEE80211AX */
++      if (params->multiple_bssid_count) {
++              nla_put_u8(msg, NL80211_ATTR_MULTIPLE_BSSID_INDEX,
++                         params->multiple_bssid_index);
++              nla_put_u8(msg, NL80211_ATTR_MULTIPLE_BSSID_COUNT,
++                         params->multiple_bssid_count);
++              if (params->ema_beacon)
++                      nla_put_flag(msg, NL80211_ATTR_MULTIPLE_BSSID_EMA);
++      }
++
++      if (params->multiple_bssid_parent) {
++              int ifidx = if_nametoindex(params->multiple_bssid_parent);
++              if (ifidx <= 0)
++                      goto fail;
++              nla_put_u32(msg, NL80211_ATTR_MULTIPLE_BSSID_PARENT,
++                          ifidx);
++      }
++
++      if (params->multiple_bssid_ie_len) {
++              struct nlattr *ies = nla_nest_start(msg, NL80211_ATTR_MULTIPLE_BSSID_IES);
++              u8 **offs = params->multiple_bssid_ie_offsets;
++              int i;
++
++              for (i = 0; i < params->multiple_bssid_ie_count - 1; i++)
++                      nla_put(msg, i + 1,
++                              offs[i + 1] - offs[i], offs[i]);
++              nla_put(msg, i + 1,
++                      *offs + params->multiple_bssid_ie_len - offs[i],
++                      offs[i]);
++              nla_nest_end(msg, ies);
++      }
++
+       ret = send_and_recv_msgs_owner(drv, msg, get_connect_handle(bss), 1,
+                                      NULL, NULL);
+       if (ret) {
+@@ -5080,7 +5111,6 @@ const char * nl80211_iftype_str(enum nl8
+       }
+ }
+-
+ static int nl80211_create_iface_once(struct wpa_driver_nl80211_data *drv,
+                                    const char *ifname,
+                                    enum nl80211_iftype iftype,
+Index: hostapd-2020-06-08-5a8b3662/src/drivers/nl80211_copy.h
+===================================================================
+--- hostapd-2020-06-08-5a8b3662.orig/src/drivers/nl80211_copy.h
++++ hostapd-2020-06-08-5a8b3662/src/drivers/nl80211_copy.h
+@@ -2484,6 +2484,19 @@ enum nl80211_commands {
+  * @NL80211_ATTR_RECEIVE_MULTICAST: multicast flag for the
+  *    %NL80211_CMD_REGISTER_FRAME command, see the description there.
+  *
++ * @NL80211_ATTR_MULTIPLE_BSSID_PARENT: If this is a Non-Transmitted BSSID, define
++ *      the parent (transmitting) interface.
++ *
++ * @NL80211_ATTR_MULTIPLE_BSSID_INDEX: The index of this BSS inside the multi bssid
++ *      element.
++ *
++ * @NL80211_ATTR_MULTIPLE_BSSID_COUNT: The number of BSSs inside the multi bssid element.
++ *
++ * @NL80211_ATTR_MULTIPLE_BSSID_IES: The Elements that describe our multiple BSS group.
++ *      these get passed separately as the kernel might need to split them up for EMA VAP.
++ *
++ * @NL80211_ATTR_MULTIPLE_BSSID_EMA: Shall the multiple BSS beacons be sent out in EMA mode. 
++ *
+  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
+  * @NL80211_ATTR_MAX: highest attribute number currently defined
+  * @__NL80211_ATTR_AFTER_LAST: internal use
+@@ -2961,6 +2974,20 @@ enum nl80211_attrs {
+       NL80211_ATTR_RECEIVE_MULTICAST,
++      NL80211_ATTR_WIPHY_FREQ_OFFSET,
++      NL80211_ATTR_CENTER_FREQ1_OFFSET,
++      NL80211_ATTR_SCAN_FREQ_KHZ,
++
++      NL80211_ATTR_HE_6GHZ_CAPABILITY,
++
++      NL80211_ATTR_WIPHY_ANTENNA_GAIN,
++
++      NL80211_ATTR_MULTIPLE_BSSID_PARENT,
++      NL80211_ATTR_MULTIPLE_BSSID_INDEX,
++      NL80211_ATTR_MULTIPLE_BSSID_COUNT,
++      NL80211_ATTR_MULTIPLE_BSSID_IES,
++      NL80211_ATTR_MULTIPLE_BSSID_EMA,
++
+       /* add attributes here, update the policy in nl80211.c */
+       __NL80211_ATTR_AFTER_LAST,