From 2fbb5f3daed46dcab59fa48615213b67778a89bf Mon Sep 17 00:00:00 2001
From: Aloka Dixit <alokad@codeaurora.org>
Date: Sat, 26 Sep 2020 17:33:55 -0700
Subject: [PATCH] hostapd: Add EMA configuration option

This patch adds new configuration option to enable EMA (Enhanced
Multiple BSSID Advertisements) AP.

As this is an enhancement, 'multiple_bssid' must be enabled to use this
option.

In multiple_bssid only mode, hostapd adds more that one MBSSID IEs
in beacons if length of one element goes beyond 255.

Signed-off-by: Aloka Dixit <alokad@codeaurora.org>
---
 hostapd/config_file.c      |  2 ++
 src/ap/ap_config.c         |  6 ++++++
 src/ap/ap_config.h         |  1 +
 src/ap/beacon.c            | 12 ++++++------
 src/ap/ieee802_11.c        |  5 +++--
 src/ap/ieee802_11.h        |  2 +-
 src/ap/ieee802_11_shared.c |  8 +++-----
 7 files changed, 22 insertions(+), 14 deletions(-)

Index: hostapd-2021-02-18/hostapd/config_file.c
===================================================================
--- hostapd-2021-02-18.orig/hostapd/config_file.c
+++ hostapd-2021-02-18/hostapd/config_file.c
@@ -4672,6 +4672,8 @@ static int hostapd_config_fill(struct ho
 #endif /* CONFIG_MACSEC */
 	} else if (os_strcmp(buf, "multiple_bssid") == 0) {
 		conf->multiple_bssid = atoi(pos);
+	} else if (os_strcmp(buf, "ema") == 0) {
+		conf->ema = atoi(pos);
 	} else if (os_strcmp(buf, "rnr_beacon") == 0) {
 		bss->rnr_beacon = atoi(pos);
 	} else if (os_strcmp(buf, "disable_11n") == 0) {
Index: hostapd-2021-02-18/src/ap/ap_config.c
===================================================================
--- hostapd-2021-02-18.orig/src/ap/ap_config.c
+++ hostapd-2021-02-18/src/ap/ap_config.c
@@ -1486,6 +1486,12 @@ int hostapd_config_check(struct hostapd_
 			return -1;
 	}
 
+	if (conf->ema && !conf->multiple_bssid) {
+		wpa_printf(MSG_ERROR,
+			   "Cannot enable ema without enabling multiple_bssid");
+		return -1;
+	}
+
 	for (i = 0; i < conf->num_bss; i++) {
 		if (hostapd_config_check_bss(conf->bss[i], conf, full_config))
 			return -1;
Index: hostapd-2021-02-18/src/ap/ap_config.h
===================================================================
--- hostapd-2021-02-18.orig/src/ap/ap_config.h
+++ hostapd-2021-02-18/src/ap/ap_config.h
@@ -1017,6 +1017,7 @@ struct hostapd_config {
 	u8 ht40_plus_minus_allowed;
 
 	u8 multiple_bssid;
+	u8 ema;
 
 	/* Use driver-generated interface addresses when adding multiple BSSs */
 	u8 use_driver_iface_addr;
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
@@ -535,7 +535,7 @@ static u8 * hostapd_gen_probe_resp(struc
 	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);
+		pos = hostapd_eid_multiple_bssid(hapd, pos, epos, 0, NULL, 0, 0, 0);
 
 	/* eCSA IE */
 	csa_pos = hostapd_eid_ecsa(hapd, pos);
@@ -549,8 +549,7 @@ static u8 * hostapd_gen_probe_resp(struc
 
 	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))
+	if ((pos - ext_cap_pos >= 13) && (ext_cap_pos[12] & 0x08))
 		ext_cap_pos[12] |= 0x01;
 
 	pos = hostapd_eid_time_adv(hapd, pos);
@@ -2051,10 +2050,11 @@ int ieee802_11_build_ap_params(struct ho
 						 params->multiple_bssid_ies + len,
 						 1, params->multiple_bssid_ie_offsets,
 						 &params->multiple_bssid_ie_count,
-						 MULTIPLE_BSSID_IE_MAX);
+						 MULTIPLE_BSSID_IE_MAX,
+						 hapd->iconf->ema);
 		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))
+		if ((params->multiple_bssid_ie_count <= 1) &&
+		    (ext_cap_len >= 13) && (ext_cap_pos[12] & 0x08))
 			ext_cap_pos[12] |= 0x01;
 	}
 
Index: hostapd-2021-02-18/src/ap/ieee802_11.c
===================================================================
--- hostapd-2021-02-18.orig/src/ap/ieee802_11.c
+++ hostapd-2021-02-18/src/ap/ieee802_11.c
@@ -7076,12 +7076,13 @@ multiple_bssid_too_big:
 
 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 eid_max, u8 ema_beacon)
 {
 	int count = 1;
 
 	while (count < hapd->iface->num_bss) {
-		if (eid_offsets && *eid_count < eid_max) {
+		if (eid_offsets && eid_count && *eid_count < eid_max &&
+		    (ema_beacon || count == 1)) {
 			eid_offsets[*eid_count] = eid;
 			*eid_count = *eid_count + 1;
 		}
Index: hostapd-2021-02-18/src/ap/ieee802_11.h
===================================================================
--- hostapd-2021-02-18.orig/src/ap/ieee802_11.h
+++ hostapd-2021-02-18/src/ap/ieee802_11.h
@@ -121,7 +121,7 @@ void hostapd_client_poll_ok(struct hosta
 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 eid_max, u8 ema_beacon);
 int hostapd_eid_multiple_bssid_len(struct hostapd_data *hapd);
 u8 * hostapd_eid_reduced_neighbor_report(struct hostapd_data *hapd, u8 *eid);
 size_t hostapd_eid_reduced_neighbor_report_len(struct hostapd_data *hapd);
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,9 +427,8 @@ 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)
+		/* Bit 83 - EMA AP Support */
+		if (hapd->iconf->ema)
                         *pos |= 0x08;
 		if (hapd->conf->beacon_prot &&
 		    (hapd->iface->drv_flags &
@@ -502,7 +501,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 || hapd->iconf->multiple_bssid) &&
+	if (len < 11 && (hapd->conf->beacon_prot || hapd->iconf->ema) &&
 	    (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_BEACON_PROTECTION))
 		len = 11;
 #ifdef CONFIG_SAE_PK
