hostapd: Add Multi-AP protocol support
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 Multi-AP functionality is enabled 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>
This commit is contained in:
parent
3006241e43
commit
9c06f0f6ae
9 changed files with 134 additions and 2 deletions
|
@ -4130,6 +4130,16 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
||||||
} else if (os_strcmp(buf, "coloc_intf_reporting") == 0) {
|
} else if (os_strcmp(buf, "coloc_intf_reporting") == 0) {
|
||||||
bss->coloc_intf_reporting = atoi(pos);
|
bss->coloc_intf_reporting = atoi(pos);
|
||||||
#endif /* CONFIG_OWE */
|
#endif /* CONFIG_OWE */
|
||||||
|
} else if (os_strcmp(buf, "multi_ap") == 0) {
|
||||||
|
int val = atoi(pos);
|
||||||
|
|
||||||
|
if (val < 0 || val > 3) {
|
||||||
|
wpa_printf(MSG_ERROR, "Line %d: Invalid multi_ap '%s'",
|
||||||
|
line, buf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bss->multi_ap = val;
|
||||||
} else {
|
} else {
|
||||||
wpa_printf(MSG_ERROR,
|
wpa_printf(MSG_ERROR,
|
||||||
"Line %d: unknown configuration item '%s'",
|
"Line %d: unknown configuration item '%s'",
|
||||||
|
|
|
@ -438,6 +438,13 @@ wmm_ac_vo_txop_limit=47
|
||||||
wmm_ac_vo_acm=0
|
wmm_ac_vo_acm=0
|
||||||
# Note: for IEEE 802.11b mode: cWmin=3 cWmax=4 burst=102
|
# Note: for IEEE 802.11b mode: cWmin=3 cWmax=4 burst=102
|
||||||
|
|
||||||
|
# Enable Multi-AP functionality
|
||||||
|
# 0 = disabled (default)
|
||||||
|
# 1 = AP support backhaul BSS
|
||||||
|
# 2 = AP support fronthaul BSS
|
||||||
|
# 3 = AP supports both backhaul BSS and fronthaul BSS
|
||||||
|
#multi_ap=0
|
||||||
|
|
||||||
# Static WEP key configuration
|
# Static WEP key configuration
|
||||||
#
|
#
|
||||||
# The key number to use when transmitting.
|
# The key number to use when transmitting.
|
||||||
|
|
|
@ -694,6 +694,10 @@ struct hostapd_bss_config {
|
||||||
int coloc_intf_reporting;
|
int coloc_intf_reporting;
|
||||||
|
|
||||||
u8 send_probe_response;
|
u8 send_probe_response;
|
||||||
|
|
||||||
|
#define BACKHAUL_BSS 1
|
||||||
|
#define FRONTHAUL_BSS 2
|
||||||
|
int multi_ap; /* bitmap of BACKHAUL_BSS, FRONTHAUL_BSS */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -63,6 +63,22 @@ prepare_auth_resp_fils(struct hostapd_data *hapd,
|
||||||
int *is_pub);
|
int *is_pub);
|
||||||
#endif /* CONFIG_FILS */
|
#endif /* CONFIG_FILS */
|
||||||
|
|
||||||
|
|
||||||
|
u8 * hostapd_eid_multi_ap(struct hostapd_data *hapd, u8 *eid)
|
||||||
|
{
|
||||||
|
u8 multi_ap_val = 0;
|
||||||
|
|
||||||
|
if (!hapd->conf->multi_ap)
|
||||||
|
return eid;
|
||||||
|
if (hapd->conf->multi_ap & BACKHAUL_BSS)
|
||||||
|
multi_ap_val |= MULTI_AP_BACKHAUL_BSS;
|
||||||
|
if (hapd->conf->multi_ap & FRONTHAUL_BSS)
|
||||||
|
multi_ap_val |= MULTI_AP_FRONTHAUL_BSS;
|
||||||
|
|
||||||
|
return eid + add_multi_ap_ie(eid, 9, multi_ap_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid)
|
u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid)
|
||||||
{
|
{
|
||||||
u8 *pos = eid;
|
u8 *pos = eid;
|
||||||
|
@ -2211,6 +2227,57 @@ static u16 check_wmm(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
return WLAN_STATUS_SUCCESS;
|
return WLAN_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u16 check_multi_ap(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
|
const u8 *multi_ap_ie, size_t multi_ap_len)
|
||||||
|
{
|
||||||
|
u8 multi_ap_value = 0;
|
||||||
|
|
||||||
|
sta->flags &= ~WLAN_STA_MULTI_AP;
|
||||||
|
|
||||||
|
if (!hapd->conf->multi_ap)
|
||||||
|
return WLAN_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
if (multi_ap_ie) {
|
||||||
|
const u8 *multi_ap_subelem;
|
||||||
|
|
||||||
|
multi_ap_subelem = get_ie(multi_ap_ie + 4,
|
||||||
|
multi_ap_len - 4,
|
||||||
|
MULTI_AP_SUB_ELEM_TYPE);
|
||||||
|
if (multi_ap_subelem && multi_ap_subelem[1] == 1) {
|
||||||
|
multi_ap_value = multi_ap_subelem[2];
|
||||||
|
} else {
|
||||||
|
hostapd_logger(hapd, sta->addr,
|
||||||
|
HOSTAPD_MODULE_IEEE80211,
|
||||||
|
HOSTAPD_LEVEL_INFO,
|
||||||
|
"Multi-AP IE has missing or invalid Multi-AP subelement");
|
||||||
|
return WLAN_STATUS_INVALID_IE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (multi_ap_value == MULTI_AP_BACKHAUL_STA)
|
||||||
|
sta->flags |= WLAN_STA_MULTI_AP;
|
||||||
|
|
||||||
|
if ((hapd->conf->multi_ap & BACKHAUL_BSS) &&
|
||||||
|
multi_ap_value == MULTI_AP_BACKHAUL_STA)
|
||||||
|
return WLAN_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
if (hapd->conf->multi_ap & FRONTHAUL_BSS) {
|
||||||
|
if (multi_ap_value == MULTI_AP_BACKHAUL_STA) {
|
||||||
|
hostapd_logger(hapd, sta->addr,
|
||||||
|
HOSTAPD_MODULE_IEEE80211,
|
||||||
|
HOSTAPD_LEVEL_INFO,
|
||||||
|
"Backhaul STA tries to associate with fronthaul-only BSS");
|
||||||
|
return WLAN_STATUS_ASSOC_DENIED_UNSPEC;
|
||||||
|
}
|
||||||
|
return WLAN_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||||
|
HOSTAPD_LEVEL_INFO,
|
||||||
|
"Non-Multi-AP STA tries to associate with backhaul-only BSS");
|
||||||
|
return WLAN_STATUS_ASSOC_DENIED_UNSPEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static u16 copy_supp_rates(struct hostapd_data *hapd, struct sta_info *sta,
|
static u16 copy_supp_rates(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
struct ieee802_11_elems *elems)
|
struct ieee802_11_elems *elems)
|
||||||
|
@ -2467,6 +2534,11 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
resp = copy_supp_rates(hapd, sta, &elems);
|
resp = copy_supp_rates(hapd, sta, &elems);
|
||||||
if (resp != WLAN_STATUS_SUCCESS)
|
if (resp != WLAN_STATUS_SUCCESS)
|
||||||
return resp;
|
return resp;
|
||||||
|
|
||||||
|
resp = check_multi_ap(hapd, sta, elems.multi_ap, elems.multi_ap_len);
|
||||||
|
if (resp != WLAN_STATUS_SUCCESS)
|
||||||
|
return resp;
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211N
|
#ifdef CONFIG_IEEE80211N
|
||||||
resp = copy_sta_ht_capab(hapd, sta, elems.ht_capabilities);
|
resp = copy_sta_ht_capab(hapd, sta, elems.ht_capabilities);
|
||||||
if (resp != WLAN_STATUS_SUCCESS)
|
if (resp != WLAN_STATUS_SUCCESS)
|
||||||
|
@ -3040,6 +3112,9 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_WPS */
|
#endif /* CONFIG_WPS */
|
||||||
|
|
||||||
|
if (sta && (sta->flags & WLAN_STA_MULTI_AP))
|
||||||
|
p = hostapd_eid_multi_ap(hapd, p);
|
||||||
|
|
||||||
#ifdef CONFIG_P2P
|
#ifdef CONFIG_P2P
|
||||||
if (sta && sta->p2p_ie && hapd->p2p_group) {
|
if (sta && sta->p2p_ie && hapd->p2p_group) {
|
||||||
struct wpabuf *p2p_resp_ie;
|
struct wpabuf *p2p_resp_ie;
|
||||||
|
@ -4291,7 +4366,7 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
|
||||||
sta->flags |= WLAN_STA_WDS;
|
sta->flags |= WLAN_STA_WDS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sta->flags & WLAN_STA_WDS) {
|
if (sta->flags & (WLAN_STA_WDS | WLAN_STA_MULTI_AP)) {
|
||||||
int ret;
|
int ret;
|
||||||
char ifname_wds[IFNAMSIZ + 1];
|
char ifname_wds[IFNAMSIZ + 1];
|
||||||
|
|
||||||
|
|
|
@ -166,7 +166,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
||||||
/* just in case */
|
/* just in case */
|
||||||
ap_sta_set_authorized(hapd, sta, 0);
|
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);
|
hostapd_set_wds_sta(hapd, NULL, sta->addr, sta->aid, 0);
|
||||||
|
|
||||||
if (sta->ipaddr)
|
if (sta->ipaddr)
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#define WLAN_STA_VHT_OPMODE_ENABLED BIT(20)
|
#define WLAN_STA_VHT_OPMODE_ENABLED BIT(20)
|
||||||
#define WLAN_STA_VENDOR_VHT BIT(21)
|
#define WLAN_STA_VENDOR_VHT BIT(21)
|
||||||
#define WLAN_STA_PENDING_FILS_ERP BIT(22)
|
#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_DISASSOC_CB BIT(29)
|
||||||
#define WLAN_STA_PENDING_DEAUTH_CB BIT(30)
|
#define WLAN_STA_PENDING_DEAUTH_CB BIT(30)
|
||||||
#define WLAN_STA_NONERP BIT(31)
|
#define WLAN_STA_NONERP BIT(31)
|
||||||
|
|
|
@ -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 = pos;
|
||||||
elems->roaming_cons_sel_len = elen;
|
elems->roaming_cons_sel_len = elen;
|
||||||
break;
|
break;
|
||||||
|
case MULTI_AP_OUI_TYPE:
|
||||||
|
elems->multi_ap = pos;
|
||||||
|
elems->multi_ap_len = elen;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
wpa_printf(MSG_MSGDUMP, "Unknown WFA "
|
wpa_printf(MSG_MSGDUMP, "Unknown WFA "
|
||||||
"information element ignored "
|
"information element ignored "
|
||||||
|
@ -1558,6 +1562,26 @@ size_t mbo_add_ie(u8 *buf, size_t len, const u8 *attr, size_t attr_len)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t add_multi_ap_ie(u8 *buf, size_t len, u8 value)
|
||||||
|
{
|
||||||
|
u8 *pos = buf;
|
||||||
|
|
||||||
|
if (len < 9)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||||
|
*pos++ = 7; /* len */
|
||||||
|
WPA_PUT_BE24(pos, OUI_WFA);
|
||||||
|
pos += 3;
|
||||||
|
*pos++ = MULTI_AP_OUI_TYPE;
|
||||||
|
*pos++ = MULTI_AP_SUB_ELEM_TYPE;
|
||||||
|
*pos++ = 1; /* len */
|
||||||
|
*pos++ = value;
|
||||||
|
|
||||||
|
return pos - buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static const struct country_op_class us_op_class[] = {
|
static const struct country_op_class us_op_class[] = {
|
||||||
{ 1, 115 },
|
{ 1, 115 },
|
||||||
{ 2, 118 },
|
{ 2, 118 },
|
||||||
|
|
|
@ -86,6 +86,7 @@ struct ieee802_11_elems {
|
||||||
const u8 *roaming_cons_sel;
|
const u8 *roaming_cons_sel;
|
||||||
const u8 *password_id;
|
const u8 *password_id;
|
||||||
const u8 *oci;
|
const u8 *oci;
|
||||||
|
const u8 *multi_ap;
|
||||||
|
|
||||||
u8 ssid_len;
|
u8 ssid_len;
|
||||||
u8 supp_rates_len;
|
u8 supp_rates_len;
|
||||||
|
@ -133,6 +134,7 @@ struct ieee802_11_elems {
|
||||||
u8 roaming_cons_sel_len;
|
u8 roaming_cons_sel_len;
|
||||||
u8 password_id_len;
|
u8 password_id_len;
|
||||||
u8 oci_len;
|
u8 oci_len;
|
||||||
|
u8 multi_ap_len;
|
||||||
|
|
||||||
struct mb_ies_info mb_ies;
|
struct mb_ies_info mb_ies;
|
||||||
};
|
};
|
||||||
|
@ -194,6 +196,8 @@ const u8 * get_ie_ext(const u8 *ies, size_t len, u8 ext);
|
||||||
|
|
||||||
size_t mbo_add_ie(u8 *buf, size_t len, const u8 *attr, size_t attr_len);
|
size_t mbo_add_ie(u8 *buf, size_t len, const u8 *attr, size_t attr_len);
|
||||||
|
|
||||||
|
size_t add_multi_ap_ie(u8 *buf, size_t len, u8 value);
|
||||||
|
|
||||||
struct country_op_class {
|
struct country_op_class {
|
||||||
u8 country_op_class;
|
u8 country_op_class;
|
||||||
u8 global_op_class;
|
u8 global_op_class;
|
||||||
|
|
|
@ -1213,6 +1213,13 @@ struct ieee80211_ampe_ie {
|
||||||
#define MBO_OUI_TYPE 22
|
#define MBO_OUI_TYPE 22
|
||||||
#define OWE_IE_VENDOR_TYPE 0x506f9a1c
|
#define OWE_IE_VENDOR_TYPE 0x506f9a1c
|
||||||
#define OWE_OUI_TYPE 28
|
#define OWE_OUI_TYPE 28
|
||||||
|
#define MULTI_AP_OUI_TYPE 0x1B
|
||||||
|
|
||||||
|
#define MULTI_AP_SUB_ELEM_TYPE 0x06
|
||||||
|
#define MULTI_AP_TEAR_DOWN BIT(4)
|
||||||
|
#define MULTI_AP_FRONTHAUL_BSS BIT(5)
|
||||||
|
#define MULTI_AP_BACKHAUL_BSS BIT(6)
|
||||||
|
#define MULTI_AP_BACKHAUL_STA BIT(7)
|
||||||
|
|
||||||
#define WMM_OUI_TYPE 2
|
#define WMM_OUI_TYPE 2
|
||||||
#define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0
|
#define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0
|
||||||
|
|
Loading…
Reference in a new issue