@@ -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
@@ -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_enabled") == 0) {
+ int val = atoi(pos);
+
+ if (val > 3 || val < 0) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: Invalid multi_ap_enabled '%s'",
+ line, buf);
+ return -1;
+ }
+
+ bss->multi_ap_enabled = val;
+#endif /*CONFIG_MULTI_AP */
} else {
wpa_printf(MSG_ERROR,
"Line %d: unknown configuration item '%s'",
@@ -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
@@ -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:Enable Multi-AP as BACKHAUL_BSS
+#2:Enable Multi-AP as FRONTHAUL_BSS
+#3:Enable Multi-AP as BACKHAUL_BSS and FRONTHAUL_BSS
+#multi_ap_enabled=0
+
# Static WEP key configuration
#
# The key number to use when transmitting.
@@ -686,6 +686,10 @@ struct hostapd_bss_config {
#endif /* CONFIG_OWE */
int coloc_intf_reporting;
+
+#ifdef CONFIG_MULTI_AP
+ int multi_ap_enabled;
+#endif /*CONFIG_MULTI_AP */
};
/**
@@ -62,6 +62,34 @@ 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)
+{
+ u8 *pos = eid;
+
+#ifdef CONFIG_MULTI_AP
+ struct multi_ap_ie *map = (struct multi_ap_ie *) (pos + 2);
+ int multi_ap_enabled = hapd->conf->multi_ap_enabled;
+
+ if (!multi_ap_enabled)
+ return eid;
+
+ eid[0] = WLAN_EID_VENDOR_SPECIFIC;
+ eid[1] = 7; /* len */
+ WPA_PUT_BE24(map->oui, OUI_WFA);
+ map->oui_type = MULTI_AP_OUI_TYPE;
+ map->sub_elem_id = MULTI_AP_SUB_ELEM_TYPE;
+ map->sub_elem_len = 0x1;
+ if (multi_ap_enabled & BACKHAUL_BSS)
+ map->sub_elem_val |= MULTI_AP_BACKHAUL_BSS;
+ if (multi_ap_enabled & FRONTHAUL_BSS)
+ map->sub_elem_val |= MULTI_AP_FRONTHAUL_BSS;
+
+ pos = (u8 *) (map + 1);
+#endif /* CONFIG_MULTI_AP */
+
+ return pos;
+}
+
u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid)
{
u8 *pos = eid;
@@ -2210,6 +2238,21 @@ 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,
+ const u8 *multi_ap_ie)
+{
+ sta->flags &= ~WLAN_STA_MULTI_AP;
+
+ if (multi_ap_ie) {
+ struct multi_ap_ie *map = (struct multi_ap_ie *)multi_ap_ie;
+ if (map->sub_elem_id != MULTI_AP_SUB_ELEM_TYPE)
+ return WLAN_STATUS_UNSPECIFIED_FAILURE;
+ 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 +2509,15 @@ 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
+ if (hapd->conf->multi_ap_enabled) {
+ resp = hostapd_validate_multi_ap_ie(hapd, sta, elems.multi_ap);
+ 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 +3047,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 +4282,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];
@@ -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)
@@ -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)
@@ -126,6 +126,17 @@ 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:
+ if (elen < 7) {
+ wpa_printf(MSG_MSGDUMP, "short Multi-AP "
+ "information element ignored "
+ "(len=%lu)",
+ (unsigned long) elen);
+ return -1;
+ }
+ elems->multi_ap = pos;
+ elems->multi_ap_len = elen;
+ break;
default:
wpa_printf(MSG_MSGDUMP, "Unknown WFA "
"information element ignored "
@@ -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;
};
@@ -1210,6 +1210,31 @@ 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 BACKHAUL_BSS 1
+#define FRONTHAUL_BSS 2
+
+/*MAP Information Element (used in (Re)Association Request frames)
+ */
+struct multi_ap_ie {
+ /* Element ID: 221 (0xdd); Length: 7 */
+ u8 oui[3]; /* OUI_WFA 50:6F:9A */
+ u8 oui_type; /* 0x1B */
+ u8 sub_elem_id; /* 0x06 */
+ u8 sub_elem_len; /* 1 */
+ u8 sub_elem_val; /* BIT(7):Backhaul STA
+ * BIT(6):Backhaul BSS
+ * BIT(5):Fronthaul BSS
+ * BIT(3) to BIT(0) reserved
+ */
+
+} STRUCT_PACKED;
+#endif /* CONFIG_MULTI_AP */
#define WMM_OUI_TYPE 2
#define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0