From 023032c7b62efc8ec0d532590308940dde732c20 Mon Sep 17 00:00:00 2001
From: Aloka Dixit <alokad@codeaurora.org>
Date: Thu, 17 Sep 2020 11:03:29 -0700
Subject: [PATCH] multiple_bssid: Set extended capabilities

Extended capabilites element has 2 bits corresponding to EMA (Enhanced
Multiple BSSID Advertisements):

(1) Bit 83: EMA support.
    This change sets this to 1 whenever multiple_bssid option is set and
    the driver announces the capability.

(2) Bit 80: Complete list of non-transmitted BSSIDs.
    With current design, probe responses always carry complete list hence
    this patch always sets it if EMA support is available..
    For beacons, hostapd sets this bit if the driver advertises EMA
    capability and all profiles fit into a single MBSSID IE.

Signed-off-by: Aloka Dixit <alokad@codeaurora.org>
---
 src/ap/beacon.c            | 48 +++++++++++++++++++++++---------------
 src/ap/ieee802_11_shared.c |  7 +++++-
 2 files changed, 35 insertions(+), 20 deletions(-)

Index: hostapd-2021-02-18/src/ap/beacon.c
===================================================================
--- hostapd-2021-02-18.orig/src/ap/beacon.c
+++ hostapd-2021-02-18/src/ap/beacon.c
@@ -433,7 +433,7 @@ static u8 * hostapd_gen_probe_resp(struc
 				   int is_p2p, size_t *resp_len)
 {
 	struct ieee80211_mgmt *resp;
-	u8 *pos, *epos, *csa_pos;
+	u8 *pos, *epos, *csa_pos, *ext_cap_pos;
 	size_t buflen;
 
 	if (hapd->iconf->multiple_bssid)
@@ -547,7 +547,11 @@ static u8 * hostapd_gen_probe_resp(struc
 	pos = hostapd_eid_ht_capabilities(hapd, pos);
 	pos = hostapd_eid_ht_operation(hapd, pos);
 
+	ext_cap_pos = pos;
 	pos = hostapd_eid_ext_capab(hapd, pos);
+	if (hapd->iconf->multiple_bssid && (pos - ext_cap_pos >= 13) &&
+	    (ext_cap_pos[12] & 0x08))
+		ext_cap_pos[12] |= 0x01;
 
 	pos = hostapd_eid_time_adv(hapd, pos);
 	pos = hostapd_eid_time_zone(hapd, pos);
@@ -1701,12 +1705,12 @@ int ieee802_11_build_ap_params(struct ho
 {
 	struct ieee80211_mgmt *head = NULL;
 	u8 *tail = NULL;
-	size_t head_len = 0, tail_len = 0;
+	size_t head_len = 0, tail_len = 0, ext_cap_len;
 	u8 *resp = NULL;
 	size_t resp_len = 0;
 #ifdef NEED_AP_MLME
 	u16 capab_info;
-	u8 *pos, *tailpos, *tailend, *csa_pos;
+	u8 *pos, *tailpos, *tailend, *csa_pos, *ext_cap_pos;
 
 #define BEACON_HEAD_BUF_SIZE 256
 #define BEACON_TAIL_BUF_SIZE 512
@@ -1832,7 +1836,9 @@ int ieee802_11_build_ap_params(struct ho
 	tailpos = hostapd_eid_ht_capabilities(hapd, tailpos);
 	tailpos = hostapd_eid_ht_operation(hapd, tailpos);
 
+	ext_cap_pos = tailpos;
 	tailpos = hostapd_eid_ext_capab(hapd, tailpos);
+	ext_cap_len = tailpos - ext_cap_pos;
 
 	/*
 	 * TODO: Time Advertisement element should only be included in some
@@ -2032,6 +2038,26 @@ int ieee802_11_build_ap_params(struct ho
 		}
 	}
 
+	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 = hapd->iface->num_bss;
+		params->multiple_bssid_ies = os_zalloc(len);
+		if (params->multiple_bssid_ies == NULL)
+			return -1;
+		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;
+		if ((ext_cap_len >= 13) && (ext_cap_pos[12] & 0x08) &&
+		    (params->multiple_bssid_ie_count <= 1))
+			ext_cap_pos[12] |= 0x01;
+	}
+
 	return 0;
 }
 
@@ -2107,22 +2133,6 @@ int ieee802_11_set_beacon(struct hostapd
 	params.unsol_bcast_probe_resp_tmpl =
 		hostapd_unsol_bcast_probe_resp(hapd, &params);
 #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.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;
 #ifdef CONFIG_SAE
 	params.sae_pwe = hapd->conf->sae_pwe;
Index: hostapd-2021-02-18/src/ap/ieee802_11_shared.c
===================================================================
--- hostapd-2021-02-18.orig/src/ap/ieee802_11_shared.c
+++ hostapd-2021-02-18/src/ap/ieee802_11_shared.c
@@ -427,6 +427,10 @@ static void hostapd_ext_capab_byte(struc
 					       * Identifiers Used Exclusively */
 		}
 #endif /* CONFIG_SAE */
+		/* Bit 83 - EMA AP Support.
+		 * Currently enabled by default if MBSSID IE is enabled */
+		if (hapd->iconf->multiple_bssid)
+                        *pos |= 0x08;
 		if (hapd->conf->beacon_prot &&
 		    (hapd->iface->drv_flags &
 		     WPA_DRIVER_FLAGS_BEACON_PROTECTION))
@@ -498,7 +502,7 @@ u8 * hostapd_eid_ext_capab(struct hostap
 	    hostapd_sae_pw_id_in_use(hapd->conf))
 		len = 11;
 #endif /* CONFIG_SAE */
-	if (len < 11 && hapd->conf->beacon_prot &&
+	if (len < 11 && (hapd->conf->beacon_prot || hapd->iconf->multiple_bssid) &&
 	    (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_BEACON_PROTECTION))
 		len = 11;
 #ifdef CONFIG_SAE_PK
