diff mbox series

[v3,01/12] hostapd: Add Multi-AP protocol support

Message ID 20181205102401.17810-2-arnout@mind.be
State Accepted
Headers show
Series [v3,01/12] hostapd: Add Multi-AP protocol support | expand

Commit Message

Arnout Vandecappelle Dec. 5, 2018, 10:23 a.m. UTC
From: Venkateswara Naralasetty <vnaralas@codeaurora.org>

The purpose of Multi-AP specification is to enable inter-operability
across Wi-Fi access points (APs) from different vendors.

This patch introduces one new configuration parameter 'multi_ap' to
enable Multi-AP functionality and to configure the BSS as a backhaul
and/or fronthaul BSS.

Advertise vendor specific Multi-AP capabilities in (Re)Association
Response frame, if the user enables Multi-AP functionality through the
configuration parameter.

A backhaul AP must support receiving both 3addr and 4addr frames from a
backhaul STA, so create a VLAN for it just like is done for WDS, i.e.
by calling hostapd_set_wds_sta(). Since Multi-AP requires WPA2 (never
WEP), we can safely call hostapd_set_wds_encryption() as well and we
can reuse the entire WDS condition.

To parse the Multi-AP Extension subelement, we use get_ie(): even
though that function is meant for parsing IEs, it works for subelements

Signed-off-by: Venkateswara Naralasetty <vnaralas@codeaurora.org>
Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
Signed-off-by: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>
---
v3 (Arnout): Improve commit message

v2:
 * changed to multi_ap subelemt from fixed to dynamic
 * added few more checks
---
 hostapd/Makefile               |  4 +++
 hostapd/config_file.c          | 13 +++++++
 hostapd/defconfig              |  3 ++
 hostapd/hostapd.conf           |  7 ++++
 src/ap/ap_config.h             |  4 +++
 src/ap/ieee802_11.c            | 64 +++++++++++++++++++++++++++++++++-
 src/ap/sta_info.c              |  2 +-
 src/ap/sta_info.h              |  1 +
 src/common/ieee802_11_common.c |  4 +++
 src/common/ieee802_11_common.h |  2 ++
 src/common/ieee802_11_defs.h   | 10 ++++++
 11 files changed, 112 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/hostapd/Makefile b/hostapd/Makefile
index 2ce8b7ded..4db3d3491 100644
--- a/hostapd/Makefile
+++ b/hostapd/Makefile
@@ -61,6 +61,10 @@  CFLAGS += -DCONFIG_NATIVE_WINDOWS
 LIBS += -lws2_32
 endif
 
+ifdef CONFIG_MULTI_AP
+CFLAGS += -DCONFIG_MULTI_AP
+endif
+
 OBJS += main.o
 OBJS += config_file.o
 
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index b26da71a8..744c4feb0 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -4111,6 +4111,19 @@  static int hostapd_config_fill(struct hostapd_config *conf,
 	} else if (os_strcmp(buf, "coloc_intf_reporting") == 0) {
 		bss->coloc_intf_reporting = atoi(pos);
 #endif /* CONFIG_OWE */
+#ifdef CONFIG_MULTI_AP
+	} else if (os_strcmp(buf, "multi_ap") == 0) {
+		int val = atoi(pos);
+
+		if (val > 3 || val < 0) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: Invalid multi_ap '%s'",
+				   line, buf);
+			return -1;
+		}
+
+		bss->multi_ap = val;
+#endif /*CONFIG_MULTI_AP */
 	} else {
 		wpa_printf(MSG_ERROR,
 			   "Line %d: unknown configuration item '%s'",
diff --git a/hostapd/defconfig b/hostapd/defconfig
index c67c6622d..123b060ba 100644
--- a/hostapd/defconfig
+++ b/hostapd/defconfig
@@ -373,3 +373,6 @@  CONFIG_IPV6=y
 # Override default value for the wpa_disable_eapol_key_retries configuration
 # parameter. See that parameter in hostapd.conf for more details.
 #CFLAGS += -DDEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES=1
+
+#Multi-AP protocol support
+CONFIG_MULTI_AP=y
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index a00521711..22792564c 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -438,6 +438,13 @@  wmm_ac_vo_txop_limit=47
 wmm_ac_vo_acm=0
 # Note: for IEEE 802.11b mode: cWmin=3 cWmax=4 burst=102
 
+#Enable Multi-AP functionality.
+#0:default
+#1:AP support BACKHAUL_BSS
+#2:AP support FRONTHAUL_BSS
+#3:AP support both BACKHAUL_BSS and FRONTHAUL_BSS
+#multi_ap=0
+
 # Static WEP key configuration
 #
 # The key number to use when transmitting.
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 778366d49..797212e4e 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -686,6 +686,10 @@  struct hostapd_bss_config {
 #endif /* CONFIG_OWE */
 
 	int coloc_intf_reporting;
+
+#ifdef CONFIG_MULTI_AP
+	int multi_ap;
+#endif /*CONFIG_MULTI_AP */
 };
 
 /**
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index d2d6b1767..8a73be507 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -62,6 +62,30 @@  prepare_auth_resp_fils(struct hostapd_data *hapd,
 		       int *is_pub);
 #endif /* CONFIG_FILS */
 
+u8 * hostapd_eid_multi_ap(struct hostapd_data *hapd, u8 *eid)
+{
+#ifdef CONFIG_MULTI_AP
+	u8 sub_elem_val = 0;
+
+	*eid++ = WLAN_EID_VENDOR_SPECIFIC;
+	*eid++ = 7; /* len */
+	WPA_PUT_BE24(eid, OUI_WFA);
+	eid += 3;
+	*eid++ = MULTI_AP_OUI_TYPE;
+	*eid++ = MULTI_AP_SUB_ELEM_TYPE;
+	*eid++ = 1; /* sub elem len */
+
+	if (hapd->conf->multi_ap & BACKHAUL_BSS)
+		sub_elem_val |= MULTI_AP_BACKHAUL_BSS;
+	if (hapd->conf->multi_ap & FRONTHAUL_BSS)
+		sub_elem_val |= MULTI_AP_FRONTHAUL_BSS;
+	*eid++ = sub_elem_val;
+
+#endif /* CONFIG_MULTI_AP */
+
+	return eid;
+}
+
 u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid)
 {
 	u8 *pos = eid;
@@ -2210,6 +2234,34 @@  static u16 check_wmm(struct hostapd_data *hapd, struct sta_info *sta,
 	return WLAN_STATUS_SUCCESS;
 }
 
+#ifdef CONFIG_MULTI_AP
+static u16 hostapd_validate_multi_ap_ie(struct hostapd_data *hapd,
+					struct sta_info *sta,
+					struct ieee802_11_elems *elems)
+{
+	const u8 *pos, *map_sub_elem;
+	size_t len;
+
+	if (!hapd->conf->multi_ap || !elems->multi_ap)
+		return WLAN_STATUS_SUCCESS;
+
+	pos = elems->multi_ap + 4;/* OUI[3] and OUT_TYPE 1 */
+	len = elems->multi_ap_len - 4;
+
+	sta->flags &= ~WLAN_STA_MULTI_AP;
+
+	map_sub_elem = get_ie(pos, len, MULTI_AP_SUB_ELEM_TYPE);
+
+	if (map_sub_elem) {
+		if (map_sub_elem[1] < 1)
+			return WLAN_STATUS_UNSPECIFIED_FAILURE;
+		if (map_sub_elem[2] & MULTI_AP_BACKHAUL_STA)
+			sta->flags |= WLAN_STA_MULTI_AP;
+	}
+
+	return WLAN_STATUS_SUCCESS;
+}
+#endif /* CONFIG_MULTI_AP */
 
 static u16 copy_supp_rates(struct hostapd_data *hapd, struct sta_info *sta,
 			   struct ieee802_11_elems *elems)
@@ -2466,6 +2518,13 @@  static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
 	resp = copy_supp_rates(hapd, sta, &elems);
 	if (resp != WLAN_STATUS_SUCCESS)
 		return resp;
+
+#ifdef CONFIG_MULTI_AP
+	resp = hostapd_validate_multi_ap_ie(hapd, sta, &elems);
+	if (resp != WLAN_STATUS_SUCCESS)
+		return resp;
+#endif /* CONFIG_MULTI_AP */
+
 #ifdef CONFIG_IEEE80211N
 	resp = copy_sta_ht_capab(hapd, sta, elems.ht_capabilities);
 	if (resp != WLAN_STATUS_SUCCESS)
@@ -2995,6 +3054,9 @@  static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
 	}
 #endif /* CONFIG_WPS */
 
+	if (sta && (sta->flags & WLAN_STA_MULTI_AP))
+		p = hostapd_eid_multi_ap(hapd, p);
+
 #ifdef CONFIG_P2P
 	if (sta && sta->p2p_ie && hapd->p2p_group) {
 		struct wpabuf *p2p_resp_ie;
@@ -4227,7 +4289,7 @@  static void handle_assoc_cb(struct hostapd_data *hapd,
 		sta->flags |= WLAN_STA_WDS;
 	}
 
-	if (sta->flags & WLAN_STA_WDS) {
+	if (sta->flags & (WLAN_STA_WDS | WLAN_STA_MULTI_AP)) {
 		int ret;
 		char ifname_wds[IFNAMSIZ + 1];
 
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index 179cf43b6..6d683f7db 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -166,7 +166,7 @@  void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
 	/* just in case */
 	ap_sta_set_authorized(hapd, sta, 0);
 
-	if (sta->flags & WLAN_STA_WDS)
+	if (sta->flags & (WLAN_STA_WDS | WLAN_STA_MULTI_AP))
 		hostapd_set_wds_sta(hapd, NULL, sta->addr, sta->aid, 0);
 
 	if (sta->ipaddr)
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index 9cac6f157..2b60e92b5 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -36,6 +36,7 @@ 
 #define WLAN_STA_VHT_OPMODE_ENABLED BIT(20)
 #define WLAN_STA_VENDOR_VHT BIT(21)
 #define WLAN_STA_PENDING_FILS_ERP BIT(22)
+#define WLAN_STA_MULTI_AP BIT(23)
 #define WLAN_STA_PENDING_DISASSOC_CB BIT(29)
 #define WLAN_STA_PENDING_DEAUTH_CB BIT(30)
 #define WLAN_STA_NONERP BIT(31)
diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
index e1ef27795..397de8516 100644
--- a/src/common/ieee802_11_common.c
+++ b/src/common/ieee802_11_common.c
@@ -126,6 +126,10 @@  static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
 			elems->roaming_cons_sel = pos;
 			elems->roaming_cons_sel_len = elen;
 			break;
+		case MULTI_AP_OUI_TYPE:
+			elems->multi_ap = pos;
+			elems->multi_ap_len = elen;
+			break;
 		default:
 			wpa_printf(MSG_MSGDUMP, "Unknown WFA "
 				   "information element ignored "
diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
index ff7e51de3..f602f8799 100644
--- a/src/common/ieee802_11_common.h
+++ b/src/common/ieee802_11_common.h
@@ -84,6 +84,7 @@  struct ieee802_11_elems {
 	const u8 *power_capab;
 	const u8 *roaming_cons_sel;
 	const u8 *password_id;
+	const u8 *multi_ap;
 
 	u8 ssid_len;
 	u8 supp_rates_len;
@@ -130,6 +131,7 @@  struct ieee802_11_elems {
 	u8 power_capab_len;
 	u8 roaming_cons_sel_len;
 	u8 password_id_len;
+	u8 multi_ap_len;
 
 	struct mb_ies_info mb_ies;
 };
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index 762e731ab..b340cc8da 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -1210,6 +1210,16 @@  struct ieee80211_ampe_ie {
 #define MBO_OUI_TYPE 22
 #define OWE_IE_VENDOR_TYPE 0x506f9a1c
 #define OWE_OUI_TYPE 28
+#define MULTI_AP_OUI_TYPE 0x1B
+
+#ifdef CONFIG_MULTI_AP
+#define MULTI_AP_SUB_ELEM_TYPE 0x06
+#define MULTI_AP_BACKHAUL_BSS 0x40
+#define MULTI_AP_FRONTHAUL_BSS 0x20
+#define MULTI_AP_BACKHAUL_STA 0x80
+#define BACKHAUL_BSS 1
+#define FRONTHAUL_BSS 2
+#endif /* CONFIG_MULTI_AP */
 
 #define WMM_OUI_TYPE 2
 #define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0