123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- From 9c06f0f6aed26c1628acaa74df0232dd7b345e9a Mon Sep 17 00:00:00 2001
- From: Venkateswara Naralasetty <[email protected]>
- Date: Wed, 5 Dec 2018 11:23:51 +0100
- Subject: [PATCH] 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 <[email protected]>
- Signed-off-by: Jouni Malinen <[email protected]>
- Signed-off-by: Arnout Vandecappelle (Essensium/Mind) <[email protected]>
- ---
- hostapd/config_file.c | 10 +++++
- hostapd/hostapd.conf | 7 ++++
- src/ap/ap_config.h | 4 ++
- src/ap/ieee802_11.c | 77 +++++++++++++++++++++++++++++++++-
- src/ap/sta_info.c | 2 +-
- src/ap/sta_info.h | 1 +
- src/common/ieee802_11_common.c | 24 +++++++++++
- src/common/ieee802_11_common.h | 4 ++
- src/common/ieee802_11_defs.h | 7 ++++
- 9 files changed, 134 insertions(+), 2 deletions(-)
- --- a/hostapd/config_file.c
- +++ b/hostapd/config_file.c
- @@ -4115,6 +4115,16 @@ static int hostapd_config_fill(struct ho
- } else if (os_strcmp(buf, "coloc_intf_reporting") == 0) {
- bss->coloc_intf_reporting = atoi(pos);
- #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 {
- wpa_printf(MSG_ERROR,
- "Line %d: unknown configuration item '%s'",
- --- 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 = 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
- #
- # The key number to use when transmitting.
- --- a/src/ap/ap_config.h
- +++ b/src/ap/ap_config.h
- @@ -688,6 +688,10 @@ struct hostapd_bss_config {
- #endif /* CONFIG_OWE */
-
- int coloc_intf_reporting;
- +
- +#define BACKHAUL_BSS 1
- +#define FRONTHAUL_BSS 2
- + int multi_ap; /* bitmap of BACKHAUL_BSS, FRONTHAUL_BSS */
- };
-
- /**
- --- a/src/ap/ieee802_11.c
- +++ b/src/ap/ieee802_11.c
- @@ -62,6 +62,22 @@ prepare_auth_resp_fils(struct hostapd_da
- int *is_pub);
- #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 *pos = eid;
- @@ -2210,6 +2226,57 @@ static u16 check_wmm(struct hostapd_data
- 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,
- struct ieee802_11_elems *elems)
- @@ -2466,6 +2533,11 @@ static u16 check_assoc_ies(struct hostap
- resp = copy_supp_rates(hapd, sta, &elems);
- if (resp != WLAN_STATUS_SUCCESS)
- 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
- resp = copy_sta_ht_capab(hapd, sta, elems.ht_capabilities);
- if (resp != WLAN_STATUS_SUCCESS)
- @@ -2996,6 +3068,9 @@ static u16 send_assoc_resp(struct hostap
- }
- #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;
- @@ -4236,7 +4311,7 @@ static void handle_assoc_cb(struct hosta
- 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];
-
- --- a/src/ap/sta_info.c
- +++ b/src/ap/sta_info.c
- @@ -166,7 +166,7 @@ void ap_free_sta(struct hostapd_data *ha
- /* 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)
- --- 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)
- --- a/src/common/ieee802_11_common.c
- +++ b/src/common/ieee802_11_common.c
- @@ -126,6 +126,10 @@ static int ieee802_11_parse_vendor_speci
- 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 "
- @@ -1519,6 +1523,26 @@ size_t mbo_add_ie(u8 *buf, size_t len, c
- }
-
-
- +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[] = {
- { 1, 115 },
- { 2, 118 },
- --- 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;
- };
- @@ -189,6 +191,8 @@ const u8 * get_ie_ext(const u8 *ies, siz
-
- 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 {
- u8 country_op_class;
- u8 global_op_class;
- --- a/src/common/ieee802_11_defs.h
- +++ b/src/common/ieee802_11_defs.h
- @@ -1210,6 +1210,13 @@ 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
- +
- +#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_SUBTYPE_INFORMATION_ELEMENT 0
|