mirror of
https://github.com/hanwckf/immortalwrt-mt798x.git
synced 2025-01-09 02:43:53 +08:00
hostapd: add Multi-AP patches and config options
Cherry-pick Multi-AP commits from uptream: 9c06f0f6a hostapd: Add Multi-AP protocol support 5abc7823b wpa_supplicant: Add Multi-AP backhaul STA support a1debd338 tests: Refactor test_multi_ap bfcdac1c8 Multi-AP: Don't reject backhaul STA on fronthaul BSS cb3c156e7 tests: Update multi_ap_fronthaul_on_ap to match implementation 56a2d788f WPS: Add multi_ap_subelem to wps_build_wfa_ext() 83ebf5586 wpa_supplicant: Support Multi-AP backhaul STA onboarding with WPS 66819b07b hostapd: Support Multi-AP backhaul STA onboarding with WPS 8682f384c hostapd: Add README-MULTI-AP b1daf498a tests: Multi-AP WPS provisioning Add support for Multi-AP to the UCI configuration. Every wifi-iface gets an option 'multi_ap'. For APs, its value can be 0 (multi-AP support disabled), 1 (backhaul AP), 2 (fronthaul AP), or 3 (fronthaul + backhaul AP). For STAs, it can be 0 (not a backhaul STA) or 1 (backhaul STA, can only associate with backhaul AP). Also add new optional parameter to wps_start ubus call of wpa_supplicant to indicate that a Multi-AP backhaul link is required. Signed-off-by: Daniel Golle <daniel@makrotopia.org> Signed-off-by: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>
This commit is contained in:
parent
8554982e1f
commit
2e0f41e73a
@ -59,7 +59,7 @@
|
||||
static void rt2800_bbp_core_soft_reset(struct rt2x00_dev *rt2x00dev,
|
||||
bool set_bw, bool is_ht40)
|
||||
{
|
||||
@@ -8943,6 +8995,7 @@ static void rt2800_init_rfcsr_6352(struc
|
||||
@@ -8956,6 +9008,7 @@ static void rt2800_init_rfcsr_6352(struc
|
||||
rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x00);
|
||||
rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x7C);
|
||||
|
||||
|
@ -161,7 +161,7 @@
|
||||
static void rt2800_bbp_core_soft_reset(struct rt2x00_dev *rt2x00dev,
|
||||
bool set_bw, bool is_ht40)
|
||||
{
|
||||
@@ -8995,6 +9149,7 @@ static void rt2800_init_rfcsr_6352(struc
|
||||
@@ -9008,6 +9162,7 @@ static void rt2800_init_rfcsr_6352(struc
|
||||
rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x00);
|
||||
rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x7C);
|
||||
|
||||
|
@ -72,7 +72,7 @@
|
||||
static void rt2800_bbp_core_soft_reset(struct rt2x00_dev *rt2x00dev,
|
||||
bool set_bw, bool is_ht40)
|
||||
{
|
||||
@@ -9151,6 +9216,7 @@ static void rt2800_init_rfcsr_6352(struc
|
||||
@@ -9164,6 +9229,7 @@ static void rt2800_init_rfcsr_6352(struc
|
||||
|
||||
rt2800_r_calibration(rt2x00dev);
|
||||
rt2800_rf_self_txdc_cal(rt2x00dev);
|
||||
|
@ -387,7 +387,7 @@
|
||||
static void rt2800_bbp_core_soft_reset(struct rt2x00_dev *rt2x00dev,
|
||||
bool set_bw, bool is_ht40)
|
||||
{
|
||||
@@ -9219,6 +9599,7 @@ static void rt2800_init_rfcsr_6352(struc
|
||||
@@ -9232,6 +9612,7 @@ static void rt2800_init_rfcsr_6352(struc
|
||||
rt2800_rxdcoc_calibration(rt2x00dev);
|
||||
rt2800_bw_filter_calibration(rt2x00dev, true);
|
||||
rt2800_bw_filter_calibration(rt2x00dev, false);
|
||||
|
@ -958,7 +958,7 @@
|
||||
static void rt2800_bbp_core_soft_reset(struct rt2x00_dev *rt2x00dev,
|
||||
bool set_bw, bool is_ht40)
|
||||
{
|
||||
@@ -9599,6 +10550,7 @@ static void rt2800_init_rfcsr_6352(struc
|
||||
@@ -9612,6 +10563,7 @@ static void rt2800_init_rfcsr_6352(struc
|
||||
rt2800_rxdcoc_calibration(rt2x00dev);
|
||||
rt2800_bw_filter_calibration(rt2x00dev, true);
|
||||
rt2800_bw_filter_calibration(rt2x00dev, false);
|
||||
|
@ -7,7 +7,7 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=hostapd
|
||||
PKG_RELEASE:=1
|
||||
PKG_RELEASE:=2
|
||||
|
||||
PKG_SOURCE_URL:=http://w1.fi/hostap.git
|
||||
PKG_SOURCE_PROTO:=git
|
||||
|
@ -212,9 +212,12 @@ hostapd_common_add_bss_config() {
|
||||
|
||||
config_add_string wpa_psk_file
|
||||
|
||||
config_add_int multi_ap
|
||||
|
||||
config_add_boolean wps_pushbutton wps_label ext_registrar wps_pbc_in_m1
|
||||
config_add_int wps_ap_setup_locked wps_independent
|
||||
config_add_string wps_device_type wps_device_name wps_manufacturer wps_pin
|
||||
config_add_string multi_ap_backhaul_ssid multi_ap_backhaul_key
|
||||
|
||||
config_add_boolean ieee80211v wnm_sleep_mode bss_transition
|
||||
config_add_int time_advertisement
|
||||
@ -261,7 +264,8 @@ hostapd_set_bss_options() {
|
||||
macfilter ssid utf8_ssid wmm uapsd hidden short_preamble rsn_preauth \
|
||||
iapp_interface eapol_version dynamic_vlan ieee80211w nasid \
|
||||
acct_server acct_secret acct_port acct_interval \
|
||||
bss_load_update_period chan_util_avg_period sae_require_mfp
|
||||
bss_load_update_period chan_util_avg_period sae_require_mfp \
|
||||
multi_ap multi_ap_backhaul_ssid multi_ap_backhaul_key
|
||||
|
||||
set_default isolate 0
|
||||
set_default maxassoc 0
|
||||
@ -278,7 +282,8 @@ hostapd_set_bss_options() {
|
||||
set_default bss_load_update_period 60
|
||||
set_default chan_util_avg_period 600
|
||||
set_default utf8_ssid 1
|
||||
|
||||
set_default multi_ap 0
|
||||
|
||||
append bss_conf "ctrl_interface=/var/run/hostapd"
|
||||
if [ "$isolate" -gt 0 ]; then
|
||||
append bss_conf "ap_isolate=$isolate" "$N"
|
||||
@ -298,6 +303,7 @@ hostapd_set_bss_options() {
|
||||
append bss_conf "ignore_broadcast_ssid=$hidden" "$N"
|
||||
append bss_conf "uapsd_advertisement_enabled=$uapsd" "$N"
|
||||
append bss_conf "utf8_ssid=$utf8_ssid" "$N"
|
||||
append bss_conf "multi_ap=$multi_ap" "$N"
|
||||
|
||||
[ "$tdls_prohibit" -gt 0 ] && append bss_conf "tdls_prohibit=$tdls_prohibit" "$N"
|
||||
|
||||
@ -420,6 +426,9 @@ hostapd_set_bss_options() {
|
||||
[ "$wps_pushbutton" -gt 0 ] && append config_methods push_button
|
||||
[ "$wps_label" -gt 0 ] && append config_methods label
|
||||
|
||||
# WPS not possible on Multi-AP backhaul-only SSID
|
||||
[ "$multi_ap" = 1 ] && wps_possible=
|
||||
|
||||
[ -n "$wps_possible" -a -n "$config_methods" ] && {
|
||||
set_default ext_registrar 0
|
||||
set_default wps_device_type "6-0050F204-1"
|
||||
@ -442,6 +451,19 @@ hostapd_set_bss_options() {
|
||||
append bss_conf "wps_independent=$wps_independent" "$N"
|
||||
[ -n "$wps_ap_setup_locked" ] && append bss_conf "ap_setup_locked=$wps_ap_setup_locked" "$N"
|
||||
[ "$wps_pbc_in_m1" -gt 0 ] && append bss_conf "pbc_in_m1=$wps_pbc_in_m1" "$N"
|
||||
[ "$multi_ap" -gt 0 ] && [ -n "$multi_ap_backhaul_ssid" ] && {
|
||||
append bss_conf "multi_ap_backhaul_ssid=\"$multi_ap_backhaul_ssid\"" "$N"
|
||||
if [ -z "$multi_ap_backhaul_key" ]; then
|
||||
:
|
||||
elif [ ${#multi_ap_backhaul_key} -lt 8 ]; then
|
||||
wireless_setup_vif_failed INVALID_WPA_PSK
|
||||
return 1
|
||||
elif [ ${#multi_ap_backhaul_key} -eq 64 ]; then
|
||||
append bss_conf "multi_ap_backhaul_wpa_psk=$multi_ap_backhaul_key" "$N"
|
||||
else
|
||||
append bss_conf "multi_ap_backhaul_wpa_passphrase=$multi_ap_backhaul_key" "$N"
|
||||
fi
|
||||
}
|
||||
}
|
||||
|
||||
append bss_conf "ssid=$ssid" "$N"
|
||||
@ -640,7 +662,7 @@ wpa_supplicant_prepare_interface() {
|
||||
|
||||
_wpa_supplicant_common "$1"
|
||||
|
||||
json_get_vars mode wds
|
||||
json_get_vars mode wds multi_ap
|
||||
|
||||
[ -n "$network_bridge" ] && {
|
||||
fail=
|
||||
@ -649,7 +671,7 @@ wpa_supplicant_prepare_interface() {
|
||||
fail=1
|
||||
;;
|
||||
sta)
|
||||
[ "$wds" = 1 ] || fail=1
|
||||
[ "$wds" = 1 -o "$multi_ap" = 1 ] || fail=1
|
||||
;;
|
||||
esac
|
||||
|
||||
@ -675,6 +697,12 @@ wpa_supplicant_prepare_interface() {
|
||||
country_str="country=$country"
|
||||
}
|
||||
|
||||
multiap_flag_file="${_config}.is_multiap"
|
||||
if [ "$multi_ap" = "1" ]; then
|
||||
touch "$multiap_flag_file"
|
||||
else
|
||||
[ -e "$multiap_flag_file" ] && rm "$multiap_flag_file"
|
||||
fi
|
||||
wpa_supplicant_teardown_interface "$ifname"
|
||||
cat > "$_config" <<EOF
|
||||
$ap_scan
|
||||
@ -716,9 +744,11 @@ wpa_supplicant_add_network() {
|
||||
json_get_vars \
|
||||
ssid bssid key \
|
||||
basic_rate mcast_rate \
|
||||
ieee80211w ieee80211r
|
||||
ieee80211w ieee80211r \
|
||||
multi_ap
|
||||
|
||||
set_default ieee80211r 0
|
||||
set_default multi_ap 0
|
||||
|
||||
local key_mgmt='NONE'
|
||||
local enc_str=
|
||||
@ -752,6 +782,8 @@ wpa_supplicant_add_network() {
|
||||
|
||||
[ "$_w_mode" = "adhoc" -o "$_w_mode" = "mesh" ] && append network_data "$_w_modestr" "$N$T"
|
||||
|
||||
[ "$multi_ap" = 1 -a "$_w_mode" = "sta" ] && append network_data "multi_ap_backhaul_sta=1" "$N$T"
|
||||
|
||||
case "$auth_type" in
|
||||
none) ;;
|
||||
owe)
|
||||
|
@ -48,7 +48,13 @@ if [ "$ACTION" = "pressed" -a "$BUTTON" = "wps" ]; then
|
||||
wps_done=0
|
||||
ubusobjs="$( ubus -S list wpa_supplicant.* )"
|
||||
for ubusobj in $ubusobjs; do
|
||||
ubus -S call $ubusobj wps_start && wps_done=1
|
||||
ifname="$(echo $ubusobj | cut -d'.' -f2 )"
|
||||
multi_ap=""
|
||||
if [ -e "/var/run/wpa_supplicant-${ifname}.conf.is_multiap" ]; then
|
||||
ubus -S call $ubusobj wps_start '{ "multi_ap": true }' && wps_done=1
|
||||
else
|
||||
ubus -S call $ubusobj wps_start && wps_done=1
|
||||
fi
|
||||
done
|
||||
[ $wps_done = 0 ] || wps_catch_credentials &
|
||||
fi
|
||||
|
@ -0,0 +1,306 @@
|
||||
From 9c06f0f6aed26c1628acaa74df0232dd7b345e9a Mon Sep 17 00:00:00 2001
|
||||
From: Venkateswara Naralasetty <vnaralas@codeaurora.org>
|
||||
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 <vnaralas@codeaurora.org>
|
||||
Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
|
||||
Signed-off-by: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>
|
||||
---
|
||||
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
|
@ -0,0 +1,311 @@
|
||||
From 5abc7823bd01f69b8afbe1fd19f65fff86137c44 Mon Sep 17 00:00:00 2001
|
||||
From: Venkateswara Naralasetty <vnaralas@codeaurora.org>
|
||||
Date: Wed, 5 Dec 2018 11:23:53 +0100
|
||||
Subject: [PATCH] wpa_supplicant: Add Multi-AP backhaul STA support
|
||||
|
||||
Advertise vendor specific Multi-AP IE in (Re)Association Request frames
|
||||
and process Multi-AP IE from (Re)Association Response frames if the user
|
||||
enables Multi-AP fuctionality. If the (Re)Association Response frame
|
||||
does not contain the Multi-AP IE, disassociate.
|
||||
|
||||
This adds a new configuration parameter 'multi_ap_backhaul_sta' to
|
||||
enable/disable Multi-AP functionality.
|
||||
|
||||
Enable 4-address mode after association (if the Association Response
|
||||
frame contains the Multi-AP IE). Also enable the bridge in that case.
|
||||
This is necessary because wpa_supplicant only enables the bridge in
|
||||
wpa_drv_if_add(), which only gets called when an interface is added
|
||||
through the control interface, not when it is configured from the
|
||||
command line.
|
||||
|
||||
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>
|
||||
---
|
||||
src/drivers/driver.h | 9 ++++++
|
||||
src/drivers/driver_nl80211.c | 44 ++++++++++++++++++++++++++
|
||||
wpa_supplicant/config.c | 1 +
|
||||
wpa_supplicant/config_ssid.h | 7 +++++
|
||||
wpa_supplicant/driver_i.h | 8 +++++
|
||||
wpa_supplicant/events.c | 50 ++++++++++++++++++++++++++++++
|
||||
wpa_supplicant/sme.c | 16 ++++++++++
|
||||
wpa_supplicant/wpa_supplicant.c | 18 +++++++++++
|
||||
wpa_supplicant/wpa_supplicant.conf | 7 +++++
|
||||
wpa_supplicant/wpa_supplicant_i.h | 1 +
|
||||
10 files changed, 161 insertions(+)
|
||||
|
||||
--- a/src/drivers/driver.h
|
||||
+++ b/src/drivers/driver.h
|
||||
@@ -4100,6 +4100,15 @@ struct wpa_driver_ops {
|
||||
*/
|
||||
int (*send_external_auth_status)(void *priv,
|
||||
struct external_auth *params);
|
||||
+
|
||||
+ /**
|
||||
+ * set_4addr_mode - Set 4-address mode
|
||||
+ * @priv: Private driver interface data
|
||||
+ * @bridge_ifname: Bridge interface name
|
||||
+ * @val: 0 - disable 4addr mode, 1 - enable 4addr mode
|
||||
+ * Returns: 0 on success, < 0 on failure
|
||||
+ */
|
||||
+ int (*set_4addr_mode)(void *priv, const char *bridge_ifname, int val);
|
||||
};
|
||||
|
||||
/**
|
||||
--- a/src/drivers/driver_nl80211.c
|
||||
+++ b/src/drivers/driver_nl80211.c
|
||||
@@ -10728,6 +10728,49 @@ fail:
|
||||
}
|
||||
|
||||
|
||||
+static int nl80211_set_4addr_mode(void *priv, const char *bridge_ifname,
|
||||
+ int val)
|
||||
+{
|
||||
+ struct i802_bss *bss = priv;
|
||||
+ struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||
+ struct nl_msg *msg;
|
||||
+ int ret = -ENOBUFS;
|
||||
+
|
||||
+ wpa_printf(MSG_DEBUG, "nl80211: %s 4addr mode (bridge_ifname: %s)",
|
||||
+ val ? "Enable" : "Disable", bridge_ifname);
|
||||
+
|
||||
+ msg = nl80211_cmd_msg(drv->first_bss, 0, NL80211_CMD_SET_INTERFACE);
|
||||
+ if (!msg || nla_put_u8(msg, NL80211_ATTR_4ADDR, val))
|
||||
+ goto fail;
|
||||
+
|
||||
+ if (bridge_ifname[0] && bss->added_if_into_bridge && !val) {
|
||||
+ if (linux_br_del_if(drv->global->ioctl_sock,
|
||||
+ bridge_ifname, bss->ifname)) {
|
||||
+ wpa_printf(MSG_ERROR,
|
||||
+ "nl80211: Failed to remove interface %s from bridge %s",
|
||||
+ bss->ifname, bridge_ifname);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ bss->added_if_into_bridge = 0;
|
||||
+ }
|
||||
+
|
||||
+ ret = send_and_recv_msgs(drv, msg, NULL, NULL);
|
||||
+ msg = NULL;
|
||||
+ if (!ret) {
|
||||
+ if (bridge_ifname[0] && val &&
|
||||
+ i802_check_bridge(drv, bss, bridge_ifname, bss->ifname) < 0)
|
||||
+ return -1;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+fail:
|
||||
+ nlmsg_free(msg);
|
||||
+ wpa_printf(MSG_ERROR, "nl80211: Failed to enable/disable 4addr");
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+
|
||||
const struct wpa_driver_ops wpa_driver_nl80211_ops = {
|
||||
.name = "nl80211",
|
||||
.desc = "Linux nl80211/cfg80211",
|
||||
@@ -10856,4 +10899,5 @@ const struct wpa_driver_ops wpa_driver_n
|
||||
.get_ext_capab = nl80211_get_ext_capab,
|
||||
.update_connect_params = nl80211_update_connection_params,
|
||||
.send_external_auth_status = nl80211_send_external_auth_status,
|
||||
+ .set_4addr_mode = nl80211_set_4addr_mode,
|
||||
};
|
||||
--- a/wpa_supplicant/config.c
|
||||
+++ b/wpa_supplicant/config.c
|
||||
@@ -2416,6 +2416,7 @@ static const struct parse_data ssid_fiel
|
||||
#endif /* CONFIG_DPP */
|
||||
{ INT_RANGE(owe_group, 0, 65535) },
|
||||
{ INT_RANGE(owe_only, 0, 1) },
|
||||
+ { INT_RANGE(multi_ap_backhaul_sta, 0, 1) },
|
||||
};
|
||||
|
||||
#undef OFFSET
|
||||
--- a/wpa_supplicant/config_ssid.h
|
||||
+++ b/wpa_supplicant/config_ssid.h
|
||||
@@ -950,6 +950,13 @@ struct wpa_ssid {
|
||||
* the selection attempts for OWE BSS exceed the configured threshold.
|
||||
*/
|
||||
int owe_transition_bss_select_count;
|
||||
+
|
||||
+ /**
|
||||
+ * multi_ap_backhaul_sta - Multi-AP backhaul STA
|
||||
+ * 0 = normal (non-Multi-AP) station
|
||||
+ * 1 = Multi-AP backhaul station
|
||||
+ */
|
||||
+ int multi_ap_backhaul_sta;
|
||||
};
|
||||
|
||||
#endif /* CONFIG_SSID_H */
|
||||
--- a/wpa_supplicant/driver_i.h
|
||||
+++ b/wpa_supplicant/driver_i.h
|
||||
@@ -1046,4 +1046,12 @@ wpa_drv_send_external_auth_status(struct
|
||||
params);
|
||||
}
|
||||
|
||||
+static inline int wpa_drv_set_4addr_mode(struct wpa_supplicant *wpa_s, int val)
|
||||
+{
|
||||
+ if (!wpa_s->driver->set_4addr_mode)
|
||||
+ return -1;
|
||||
+ return wpa_s->driver->set_4addr_mode(wpa_s->drv_priv,
|
||||
+ wpa_s->bridge_ifname, val);
|
||||
+}
|
||||
+
|
||||
#endif /* DRIVER_I_H */
|
||||
--- a/wpa_supplicant/events.c
|
||||
+++ b/wpa_supplicant/events.c
|
||||
@@ -324,6 +324,9 @@ void wpa_supplicant_mark_disassoc(struct
|
||||
os_memset(wpa_s->last_tk, 0, sizeof(wpa_s->last_tk));
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
wpa_s->ieee80211ac = 0;
|
||||
+
|
||||
+ if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
|
||||
+ wpa_s->enabled_4addr_mode = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -2267,6 +2270,50 @@ static void interworking_process_assoc_r
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
|
||||
|
||||
+static void multi_ap_process_assoc_resp(struct wpa_supplicant *wpa_s,
|
||||
+ const u8 *ies, size_t ies_len)
|
||||
+{
|
||||
+ struct ieee802_11_elems elems;
|
||||
+ const u8 *map_sub_elem, *pos;
|
||||
+ size_t len;
|
||||
+
|
||||
+ if (!wpa_s->current_ssid ||
|
||||
+ !wpa_s->current_ssid->multi_ap_backhaul_sta ||
|
||||
+ !ies ||
|
||||
+ ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed)
|
||||
+ return;
|
||||
+
|
||||
+ if (!elems.multi_ap || elems.multi_ap_len < 7) {
|
||||
+ wpa_printf(MSG_INFO, "AP doesn't support Multi-AP protocol");
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ pos = elems.multi_ap + 4;
|
||||
+ len = elems.multi_ap_len - 4;
|
||||
+
|
||||
+ map_sub_elem = get_ie(pos, len, MULTI_AP_SUB_ELEM_TYPE);
|
||||
+ if (!map_sub_elem || map_sub_elem[1] < 1) {
|
||||
+ wpa_printf(MSG_INFO, "invalid Multi-AP sub elem type");
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ if (!(map_sub_elem[2] & MULTI_AP_BACKHAUL_BSS)) {
|
||||
+ wpa_printf(MSG_INFO, "AP doesn't support backhaul BSS");
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ if (wpa_drv_set_4addr_mode(wpa_s, 1) < 0) {
|
||||
+ wpa_printf(MSG_ERROR, "Failed to set 4addr mode");
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ wpa_s->enabled_4addr_mode = 1;
|
||||
+ return;
|
||||
+
|
||||
+fail:
|
||||
+ wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
|
||||
+}
|
||||
+
|
||||
+
|
||||
#ifdef CONFIG_FST
|
||||
static int wpas_fst_update_mbie(struct wpa_supplicant *wpa_s,
|
||||
const u8 *ie, size_t ie_len)
|
||||
@@ -2343,6 +2390,9 @@ static int wpa_supplicant_event_associnf
|
||||
get_ie(data->assoc_info.resp_ies,
|
||||
data->assoc_info.resp_ies_len, WLAN_EID_VHT_CAP))
|
||||
wpa_s->ieee80211ac = 1;
|
||||
+
|
||||
+ multi_ap_process_assoc_resp(wpa_s, data->assoc_info.resp_ies,
|
||||
+ data->assoc_info.resp_ies_len);
|
||||
}
|
||||
if (data->assoc_info.beacon_ies)
|
||||
wpa_hexdump(MSG_DEBUG, "beacon_ies",
|
||||
--- a/wpa_supplicant/sme.c
|
||||
+++ b/wpa_supplicant/sme.c
|
||||
@@ -1552,6 +1552,22 @@ void sme_associate(struct wpa_supplicant
|
||||
}
|
||||
#endif /* CONFIG_OWE */
|
||||
|
||||
+ if (wpa_s->current_ssid && wpa_s->current_ssid->multi_ap_backhaul_sta) {
|
||||
+ size_t multi_ap_ie_len;
|
||||
+
|
||||
+ multi_ap_ie_len = add_multi_ap_ie(
|
||||
+ wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
|
||||
+ sizeof(wpa_s->sme.assoc_req_ie) -
|
||||
+ wpa_s->sme.assoc_req_ie_len,
|
||||
+ MULTI_AP_BACKHAUL_STA);
|
||||
+ if (multi_ap_ie_len == 0) {
|
||||
+ wpa_printf(MSG_ERROR,
|
||||
+ "Multi-AP: Failed to build Multi-AP IE");
|
||||
+ return;
|
||||
+ }
|
||||
+ wpa_s->sme.assoc_req_ie_len += multi_ap_ie_len;
|
||||
+ }
|
||||
+
|
||||
params.bssid = bssid;
|
||||
params.ssid = wpa_s->sme.ssid;
|
||||
params.ssid_len = wpa_s->sme.ssid_len;
|
||||
--- a/wpa_supplicant/wpa_supplicant.c
|
||||
+++ b/wpa_supplicant/wpa_supplicant.c
|
||||
@@ -2893,6 +2893,21 @@ static u8 * wpas_populate_assoc_ies(
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
+ if (ssid->multi_ap_backhaul_sta) {
|
||||
+ size_t multi_ap_ie_len;
|
||||
+
|
||||
+ multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
|
||||
+ max_wpa_ie_len - wpa_ie_len,
|
||||
+ MULTI_AP_BACKHAUL_STA);
|
||||
+ if (multi_ap_ie_len == 0) {
|
||||
+ wpa_printf(MSG_ERROR,
|
||||
+ "Multi-AP: Failed to build Multi-AP IE");
|
||||
+ os_free(wpa_ie);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ wpa_ie_len += multi_ap_ie_len;
|
||||
+ }
|
||||
+
|
||||
params->wpa_ie = wpa_ie;
|
||||
params->wpa_ie_len = wpa_ie_len;
|
||||
params->auth_alg = algs;
|
||||
@@ -3377,6 +3392,9 @@ void wpa_supplicant_deauthenticate(struc
|
||||
zero_addr = 1;
|
||||
}
|
||||
|
||||
+ if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
|
||||
+ wpa_s->enabled_4addr_mode = 0;
|
||||
+
|
||||
#ifdef CONFIG_TDLS
|
||||
wpa_tdls_teardown_peers(wpa_s->wpa);
|
||||
#endif /* CONFIG_TDLS */
|
||||
--- a/wpa_supplicant/wpa_supplicant.conf
|
||||
+++ b/wpa_supplicant/wpa_supplicant.conf
|
||||
@@ -1399,6 +1399,13 @@ fast_reauth=1
|
||||
# 2: MCS 0-9
|
||||
# 3: not supported
|
||||
|
||||
+# multi_ap_backhaul_sta: Multi-AP backhaul STA functionality
|
||||
+# 0 = normal STA (default)
|
||||
+# 1 = backhaul STA
|
||||
+# A backhaul STA sends the Multi-AP IE, fails to associate if the AP does not
|
||||
+# support Multi-AP, and sets 4-address mode if it does. Thus, the netdev can be
|
||||
+# added to a bridge to allow forwarding frames over this backhaul link.
|
||||
+
|
||||
##### Fast Session Transfer (FST) support #####################################
|
||||
#
|
||||
# The options in this section are only available when the build configuration
|
||||
--- a/wpa_supplicant/wpa_supplicant_i.h
|
||||
+++ b/wpa_supplicant/wpa_supplicant_i.h
|
||||
@@ -1242,6 +1242,7 @@ struct wpa_supplicant {
|
||||
unsigned int disable_fils:1;
|
||||
#endif /* CONFIG_FILS */
|
||||
unsigned int ieee80211ac:1;
|
||||
+ unsigned int enabled_4addr_mode:1;
|
||||
};
|
||||
|
||||
|
@ -0,0 +1,100 @@
|
||||
From 7488e0ade6dffb6df4c1fb6526a9f3ede0eb18ef Mon Sep 17 00:00:00 2001
|
||||
From: Jouni Malinen <jouni@codeaurora.org>
|
||||
Date: Thu, 20 Dec 2018 12:41:00 +0200
|
||||
Subject: [PATCH] tests: Multi-AP association
|
||||
|
||||
Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
|
||||
---
|
||||
tests/hwsim/test_multi_ap.py | 73 ++++++++++++++++++++++++++++++++++++
|
||||
tests/hwsim/wpasupplicant.py | 3 +-
|
||||
2 files changed, 75 insertions(+), 1 deletion(-)
|
||||
create mode 100644 tests/hwsim/test_multi_ap.py
|
||||
|
||||
--- /dev/null
|
||||
+++ b/tests/hwsim/test_multi_ap.py
|
||||
@@ -0,0 +1,73 @@
|
||||
+# Test cases for Multi-AP
|
||||
+# Copyright (c) 2018, The Linux Foundation
|
||||
+#
|
||||
+# This software may be distributed under the terms of the BSD license.
|
||||
+# See README for more details.
|
||||
+
|
||||
+import hostapd
|
||||
+
|
||||
+def test_multi_ap_association(dev, apdev):
|
||||
+ """Multi-AP association in backhaul BSS"""
|
||||
+ run_multi_ap_association(dev, apdev, 1)
|
||||
+ dev[1].connect("multi-ap", psk="12345678", scan_freq="2412",
|
||||
+ wait_connect=False)
|
||||
+ ev = dev[1].wait_event([ "CTRL-EVENT-DISCONNECTED",
|
||||
+ "CTRL-EVENT-CONNECTED",
|
||||
+ "CTRL-EVENT-ASSOC-REJECT" ],
|
||||
+ timeout=5)
|
||||
+ dev[1].request("DISCONNECT")
|
||||
+ if ev is None:
|
||||
+ raise Exception("Connection result not reported")
|
||||
+ if "CTRL-EVENT-ASSOC-REJECT" not in ev:
|
||||
+ raise Exception("Association rejection not reported")
|
||||
+ if "status_code=12" not in ev:
|
||||
+ raise Exception("Unexpected association status code: " + ev)
|
||||
+
|
||||
+def test_multi_ap_association_shared_bss(dev, apdev):
|
||||
+ """Multi-AP association in backhaul BSS (with fronthaul BSS enabled)"""
|
||||
+ run_multi_ap_association(dev, apdev, 3)
|
||||
+ dev[1].connect("multi-ap", psk="12345678", scan_freq="2412")
|
||||
+
|
||||
+def run_multi_ap_association(dev, apdev, multi_ap):
|
||||
+ params = hostapd.wpa2_params(ssid="multi-ap", passphrase="12345678")
|
||||
+ params["multi_ap"] = str(multi_ap)
|
||||
+ hapd = hostapd.add_ap(apdev[0], params)
|
||||
+
|
||||
+ dev[0].connect("multi-ap", psk="12345678", multi_ap_backhaul_sta="1",
|
||||
+ scan_freq="2412")
|
||||
+
|
||||
+def test_multi_ap_disabled_on_ap(dev, apdev):
|
||||
+ """Multi-AP association attempt when disabled on AP"""
|
||||
+ params = hostapd.wpa2_params(ssid="multi-ap", passphrase="12345678")
|
||||
+ hapd = hostapd.add_ap(apdev[0], params)
|
||||
+
|
||||
+ dev[0].connect("multi-ap", psk="12345678", multi_ap_backhaul_sta="1",
|
||||
+ scan_freq="2412", wait_connect=False)
|
||||
+ ev = dev[0].wait_event([ "CTRL-EVENT-DISCONNECTED",
|
||||
+ "CTRL-EVENT-CONNECTED" ],
|
||||
+ timeout=5)
|
||||
+ dev[0].request("DISCONNECT")
|
||||
+ if ev is None:
|
||||
+ raise Exception("Connection result not reported")
|
||||
+ if "CTRL-EVENT-DISCONNECTED" not in ev:
|
||||
+ raise Exception("Unexpected connection result")
|
||||
+
|
||||
+def test_multi_ap_fronthaul_on_ap(dev, apdev):
|
||||
+ """Multi-AP association attempt when only fronthaul BSS on AP"""
|
||||
+ params = hostapd.wpa2_params(ssid="multi-ap", passphrase="12345678")
|
||||
+ params["multi_ap"] = "2"
|
||||
+ hapd = hostapd.add_ap(apdev[0], params)
|
||||
+
|
||||
+ dev[0].connect("multi-ap", psk="12345678", multi_ap_backhaul_sta="1",
|
||||
+ scan_freq="2412", wait_connect=False)
|
||||
+ ev = dev[0].wait_event([ "CTRL-EVENT-DISCONNECTED",
|
||||
+ "CTRL-EVENT-CONNECTED",
|
||||
+ "CTRL-EVENT-ASSOC-REJECT" ],
|
||||
+ timeout=5)
|
||||
+ dev[0].request("DISCONNECT")
|
||||
+ if ev is None:
|
||||
+ raise Exception("Connection result not reported")
|
||||
+ if "CTRL-EVENT-ASSOC-REJECT" not in ev:
|
||||
+ raise Exception("Association rejection not reported")
|
||||
+ if "status_code=12" not in ev:
|
||||
+ raise Exception("Unexpected association status code: " + ev)
|
||||
--- a/tests/hwsim/wpasupplicant.py
|
||||
+++ b/tests/hwsim/wpasupplicant.py
|
||||
@@ -1031,7 +1031,8 @@ class WpaSupplicant:
|
||||
"dpp_csign", "dpp_csign_expiry",
|
||||
"dpp_netaccesskey", "dpp_netaccesskey_expiry",
|
||||
"group_mgmt", "owe_group",
|
||||
- "roaming_consortium_selection" ]
|
||||
+ "roaming_consortium_selection", "multi_ap_backhaul_sta" ]
|
||||
+
|
||||
for field in not_quoted:
|
||||
if field in kwargs and kwargs[field]:
|
||||
self.set_network(id, field, kwargs[field])
|
@ -0,0 +1,72 @@
|
||||
From 0f5029ff41ef286aa7b3e4a3efd3f1a16be925e8 Mon Sep 17 00:00:00 2001
|
||||
From: "Arnout Vandecappelle (Essensium/Mind)" <arnout@mind.be>
|
||||
Date: Wed, 9 Jan 2019 18:41:08 +0100
|
||||
Subject: [PATCH] tests: refactor test_multi_ap
|
||||
|
||||
With just one additional argument, the run_multi_ap_association function
|
||||
can be used for all tests.
|
||||
|
||||
While we're at it, also move it to the top of the file.
|
||||
|
||||
Signed-off-by: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>
|
||||
---
|
||||
v4: new patch
|
||||
---
|
||||
tests/hwsim/test_multi_ap.py | 30 +++++++++++-------------------
|
||||
1 file changed, 11 insertions(+), 19 deletions(-)
|
||||
|
||||
--- a/tests/hwsim/test_multi_ap.py
|
||||
+++ b/tests/hwsim/test_multi_ap.py
|
||||
@@ -6,6 +6,15 @@
|
||||
|
||||
import hostapd
|
||||
|
||||
+def run_multi_ap_association(dev, apdev, multi_ap, wait_connect=True):
|
||||
+ params = hostapd.wpa2_params(ssid="multi-ap", passphrase="12345678")
|
||||
+ if multi_ap:
|
||||
+ params["multi_ap"] = str(multi_ap)
|
||||
+ hapd = hostapd.add_ap(apdev[0], params)
|
||||
+
|
||||
+ dev[0].connect("multi-ap", psk="12345678", scan_freq="2412",
|
||||
+ multi_ap_backhaul_sta="1", wait_connect=wait_connect)
|
||||
+
|
||||
def test_multi_ap_association(dev, apdev):
|
||||
"""Multi-AP association in backhaul BSS"""
|
||||
run_multi_ap_association(dev, apdev, 1)
|
||||
@@ -28,21 +37,9 @@ def test_multi_ap_association_shared_bss
|
||||
run_multi_ap_association(dev, apdev, 3)
|
||||
dev[1].connect("multi-ap", psk="12345678", scan_freq="2412")
|
||||
|
||||
-def run_multi_ap_association(dev, apdev, multi_ap):
|
||||
- params = hostapd.wpa2_params(ssid="multi-ap", passphrase="12345678")
|
||||
- params["multi_ap"] = str(multi_ap)
|
||||
- hapd = hostapd.add_ap(apdev[0], params)
|
||||
-
|
||||
- dev[0].connect("multi-ap", psk="12345678", multi_ap_backhaul_sta="1",
|
||||
- scan_freq="2412")
|
||||
-
|
||||
def test_multi_ap_disabled_on_ap(dev, apdev):
|
||||
"""Multi-AP association attempt when disabled on AP"""
|
||||
- params = hostapd.wpa2_params(ssid="multi-ap", passphrase="12345678")
|
||||
- hapd = hostapd.add_ap(apdev[0], params)
|
||||
-
|
||||
- dev[0].connect("multi-ap", psk="12345678", multi_ap_backhaul_sta="1",
|
||||
- scan_freq="2412", wait_connect=False)
|
||||
+ run_multi_ap_association(dev, apdev, 0, wait_connect=False)
|
||||
ev = dev[0].wait_event([ "CTRL-EVENT-DISCONNECTED",
|
||||
"CTRL-EVENT-CONNECTED" ],
|
||||
timeout=5)
|
||||
@@ -54,12 +51,7 @@ def test_multi_ap_disabled_on_ap(dev, ap
|
||||
|
||||
def test_multi_ap_fronthaul_on_ap(dev, apdev):
|
||||
"""Multi-AP association attempt when only fronthaul BSS on AP"""
|
||||
- params = hostapd.wpa2_params(ssid="multi-ap", passphrase="12345678")
|
||||
- params["multi_ap"] = "2"
|
||||
- hapd = hostapd.add_ap(apdev[0], params)
|
||||
-
|
||||
- dev[0].connect("multi-ap", psk="12345678", multi_ap_backhaul_sta="1",
|
||||
- scan_freq="2412", wait_connect=False)
|
||||
+ run_multi_ap_association(dev, apdev, 2, wait_connect=False)
|
||||
ev = dev[0].wait_event([ "CTRL-EVENT-DISCONNECTED",
|
||||
"CTRL-EVENT-CONNECTED",
|
||||
"CTRL-EVENT-ASSOC-REJECT" ],
|
@ -0,0 +1,106 @@
|
||||
From 71b061b8a13791a1ed858d924e401541c8584030 Mon Sep 17 00:00:00 2001
|
||||
From: "Arnout Vandecappelle (Essensium/Mind)" <arnout@mind.be>
|
||||
Date: Wed, 9 Jan 2019 19:08:00 +0100
|
||||
Subject: [PATCH] multi_ap: don't reject backhaul STA on fronhaul BSS
|
||||
|
||||
The Multi-AP specification only specifies that information elements have
|
||||
to be added to the association requests and responses; it doesn't
|
||||
specify anything about what should be done in case they are missing.
|
||||
Currently, we reject non-backhaul associations on a backhaul-only BSS,
|
||||
and non-fronthaul associations on a fronthaul-only BSS.
|
||||
|
||||
However, this makes WPS fail when fronthaul and backhaul are separate
|
||||
SSIDs. Indeed, WPS for the backhaul link is performed on the *fronthaul*
|
||||
SSID. Thus, the association request used for WPS *will* contain the
|
||||
Multi-AP IE indicating a backhaul STA. Rejecting that association makes
|
||||
WPS fail.
|
||||
|
||||
Therefore, accept a multi-AP backhaul STA association request on a
|
||||
fronthaul-only BSS. Still issue a warning about it, but only at level
|
||||
DEBUG intead of INFO. Also change the condition checking to make it
|
||||
clearer.
|
||||
|
||||
While we're at it, also fix the handling of unexpected bits in the
|
||||
Multi-AP IE. 4 bits are reserved in the specification, so these
|
||||
certainly have to be ignored. The specification also doesn't say that
|
||||
setting one of the other bits is not allowed. Therefore, only report
|
||||
unexpected values in the Multi-AP IE, don't reject because of it.
|
||||
Note that a malformed IE (containing more than one byte) still triggers
|
||||
a rejection.
|
||||
|
||||
Signed-off-by: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>
|
||||
---
|
||||
v4: new patch
|
||||
|
||||
Cfr. discussion on http://lists.infradead.org/pipermail/hostap/2019-January/039232.html
|
||||
and follow-ups.
|
||||
---
|
||||
src/ap/ieee802_11.c | 38 +++++++++++++++++++-----------------
|
||||
tests/hwsim/test_multi_ap.py | 6 ++----
|
||||
2 files changed, 22 insertions(+), 22 deletions(-)
|
||||
|
||||
--- a/src/ap/ieee802_11.c
|
||||
+++ b/src/ap/ieee802_11.c
|
||||
@@ -2253,28 +2253,30 @@ static u16 check_multi_ap(struct hostapd
|
||||
}
|
||||
}
|
||||
|
||||
- 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;
|
||||
+ if (multi_ap_value && multi_ap_value != MULTI_AP_BACKHAUL_STA)
|
||||
+ hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
+ HOSTAPD_LEVEL_INFO,
|
||||
+ "Multi-AP IE with unexpected value 0x%02x",
|
||||
+ multi_ap_value);
|
||||
+
|
||||
+ if (!(multi_ap_value & MULTI_AP_BACKHAUL_STA)) {
|
||||
+ if (hapd->conf->multi_ap & FRONTHAUL_BSS)
|
||||
+ 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;
|
||||
}
|
||||
|
||||
- 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;
|
||||
+ if (!(hapd->conf->multi_ap & BACKHAUL_BSS))
|
||||
+ hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
+ HOSTAPD_LEVEL_DEBUG,
|
||||
+ "Backhaul STA tries to associate with fronthaul-only BSS");
|
||||
+
|
||||
+ sta->flags |= WLAN_STA_MULTI_AP;
|
||||
+ return WLAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
--- a/tests/hwsim/test_multi_ap.py
|
||||
+++ b/tests/hwsim/test_multi_ap.py
|
||||
@@ -59,7 +59,5 @@ def test_multi_ap_fronthaul_on_ap(dev, a
|
||||
dev[0].request("DISCONNECT")
|
||||
if ev is None:
|
||||
raise Exception("Connection result not reported")
|
||||
- if "CTRL-EVENT-ASSOC-REJECT" not in ev:
|
||||
- raise Exception("Association rejection not reported")
|
||||
- if "status_code=12" not in ev:
|
||||
- raise Exception("Unexpected association status code: " + ev)
|
||||
+ if "CTRL-EVENT-DISCONNECTED" not in ev:
|
||||
+ raise Exception("Unexpected connection result")
|
@ -0,0 +1,342 @@
|
||||
From ad3c6faca118c23cdafef418dc27b3cee7d0e06e Mon Sep 17 00:00:00 2001
|
||||
From: "Arnout Vandecappelle (Essensium/Mind)" <arnout@mind.be>
|
||||
Date: Wed, 9 Jan 2019 19:19:26 +0100
|
||||
Subject: [PATCH] WPS: wps_build_wfa_ext(): add multi_ap_subelem parameter
|
||||
|
||||
The Multi-AP specification adds a new subelement to the WFA extension
|
||||
element in the WPS exchange. Add an additional parameter to
|
||||
wps_build_wfa_ext() to add this subelement. The subelement is only added
|
||||
if the parameter is non-0. Note that we don't reuse the existing
|
||||
MULTI_AP_SUB_ELEM_TYPE definition here, but rather define a new
|
||||
WFA_ELEM_MULTI_AP, to make sure the enum of WFA subelement types remains
|
||||
complete.
|
||||
|
||||
For now, all callers set the multi_ap_subelem parameter to 0.
|
||||
|
||||
Signed-off-by: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>
|
||||
---
|
||||
v4: Split off from supplicant WPS patch
|
||||
|
||||
Since the original patch from Davina Lyu didn't have this extra
|
||||
argument, I kept myself as the author of this patch.
|
||||
---
|
||||
src/p2p/p2p_build.c | 2 +-
|
||||
src/wps/wps.c | 6 +++---
|
||||
src/wps/wps_attr_build.c | 11 ++++++++++-
|
||||
src/wps/wps_common.c | 16 ++++++++--------
|
||||
src/wps/wps_defs.h | 3 ++-
|
||||
src/wps/wps_enrollee.c | 10 +++++-----
|
||||
src/wps/wps_er.c | 4 ++--
|
||||
src/wps/wps_i.h | 3 ++-
|
||||
src/wps/wps_registrar.c | 14 +++++++-------
|
||||
src/wps/wps_upnp.c | 2 +-
|
||||
10 files changed, 41 insertions(+), 30 deletions(-)
|
||||
|
||||
--- a/src/p2p/p2p_build.c
|
||||
+++ b/src/p2p/p2p_build.c
|
||||
@@ -802,7 +802,7 @@ int p2p_build_wps_ie(struct p2p_data *p2
|
||||
wpabuf_put_be16(buf, p2p->cfg->config_methods);
|
||||
}
|
||||
|
||||
- if (wps_build_wfa_ext(buf, 0, NULL, 0) < 0)
|
||||
+ if (wps_build_wfa_ext(buf, 0, NULL, 0, 0) < 0)
|
||||
return -1;
|
||||
|
||||
if (all_attr && p2p->cfg->num_sec_dev_types) {
|
||||
--- a/src/wps/wps.c
|
||||
+++ b/src/wps/wps.c
|
||||
@@ -430,7 +430,7 @@ struct wpabuf * wps_build_assoc_req_ie(e
|
||||
|
||||
if (wps_build_version(ie) ||
|
||||
wps_build_req_type(ie, req_type) ||
|
||||
- wps_build_wfa_ext(ie, 0, NULL, 0)) {
|
||||
+ wps_build_wfa_ext(ie, 0, NULL, 0, 0)) {
|
||||
wpabuf_free(ie);
|
||||
return NULL;
|
||||
}
|
||||
@@ -464,7 +464,7 @@ struct wpabuf * wps_build_assoc_resp_ie(
|
||||
|
||||
if (wps_build_version(ie) ||
|
||||
wps_build_resp_type(ie, WPS_RESP_AP) ||
|
||||
- wps_build_wfa_ext(ie, 0, NULL, 0)) {
|
||||
+ wps_build_wfa_ext(ie, 0, NULL, 0, 0)) {
|
||||
wpabuf_free(ie);
|
||||
return NULL;
|
||||
}
|
||||
@@ -516,7 +516,7 @@ struct wpabuf * wps_build_probe_req_ie(u
|
||||
wps_build_model_name(dev, ie) ||
|
||||
wps_build_model_number(dev, ie) ||
|
||||
wps_build_dev_name(dev, ie) ||
|
||||
- wps_build_wfa_ext(ie, req_type == WPS_REQ_ENROLLEE, NULL, 0) ||
|
||||
+ wps_build_wfa_ext(ie, req_type == WPS_REQ_ENROLLEE, NULL, 0, 0) ||
|
||||
wps_build_req_dev_type(dev, ie, num_req_dev_types, req_dev_types)
|
||||
||
|
||||
wps_build_secondary_dev_type(dev, ie)
|
||||
--- a/src/wps/wps_attr_build.c
|
||||
+++ b/src/wps/wps_attr_build.c
|
||||
@@ -203,7 +203,8 @@ int wps_build_version(struct wpabuf *msg
|
||||
|
||||
|
||||
int wps_build_wfa_ext(struct wpabuf *msg, int req_to_enroll,
|
||||
- const u8 *auth_macs, size_t auth_macs_count)
|
||||
+ const u8 *auth_macs, size_t auth_macs_count,
|
||||
+ u8 multi_ap_subelem)
|
||||
{
|
||||
u8 *len;
|
||||
|
||||
@@ -244,6 +245,14 @@ int wps_build_wfa_ext(struct wpabuf *msg
|
||||
MAC2STR(&auth_macs[i * ETH_ALEN]));
|
||||
}
|
||||
|
||||
+ if (multi_ap_subelem) {
|
||||
+ wpa_printf(MSG_DEBUG, "WPS: * Multi-AP (0x%x)",
|
||||
+ multi_ap_subelem);
|
||||
+ wpabuf_put_u8(msg, WFA_ELEM_MULTI_AP);
|
||||
+ wpabuf_put_u8(msg, 1); /* length */
|
||||
+ wpabuf_put_u8(msg, multi_ap_subelem);
|
||||
+ }
|
||||
+
|
||||
WPA_PUT_BE16(len, (u8 *) wpabuf_put(msg, 0) - len - 2);
|
||||
|
||||
#ifdef CONFIG_WPS_TESTING
|
||||
--- a/src/wps/wps_common.c
|
||||
+++ b/src/wps/wps_common.c
|
||||
@@ -374,7 +374,7 @@ struct wpabuf * wps_get_oob_cred(struct
|
||||
(rf_band && wps_build_rf_bands_attr(plain, rf_band)) ||
|
||||
(channel && wps_build_ap_channel(plain, channel)) ||
|
||||
wps_build_mac_addr(plain, wps->dev.mac_addr) ||
|
||||
- wps_build_wfa_ext(plain, 0, NULL, 0)) {
|
||||
+ wps_build_wfa_ext(plain, 0, NULL, 0, 0)) {
|
||||
os_free(data.new_psk);
|
||||
wpabuf_clear_free(plain);
|
||||
return NULL;
|
||||
@@ -421,7 +421,7 @@ struct wpabuf * wps_build_nfc_pw_token(u
|
||||
|
||||
if (wps_build_oob_dev_pw(data, dev_pw_id, pubkey,
|
||||
wpabuf_head(dev_pw), wpabuf_len(dev_pw)) ||
|
||||
- wps_build_wfa_ext(data, 0, NULL, 0)) {
|
||||
+ wps_build_wfa_ext(data, 0, NULL, 0, 0)) {
|
||||
wpa_printf(MSG_ERROR, "WPS: Failed to build NFC password "
|
||||
"token");
|
||||
wpabuf_clear_free(data);
|
||||
@@ -586,7 +586,7 @@ struct wpabuf * wps_build_wsc_ack(struct
|
||||
wps_build_msg_type(msg, WPS_WSC_ACK) ||
|
||||
wps_build_enrollee_nonce(wps, msg) ||
|
||||
wps_build_registrar_nonce(wps, msg) ||
|
||||
- wps_build_wfa_ext(msg, 0, NULL, 0)) {
|
||||
+ wps_build_wfa_ext(msg, 0, NULL, 0, 0)) {
|
||||
wpabuf_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
@@ -610,7 +610,7 @@ struct wpabuf * wps_build_wsc_nack(struc
|
||||
wps_build_enrollee_nonce(wps, msg) ||
|
||||
wps_build_registrar_nonce(wps, msg) ||
|
||||
wps_build_config_error(msg, wps->config_error) ||
|
||||
- wps_build_wfa_ext(msg, 0, NULL, 0)) {
|
||||
+ wps_build_wfa_ext(msg, 0, NULL, 0, 0)) {
|
||||
wpabuf_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
@@ -726,7 +726,7 @@ struct wpabuf * wps_build_nfc_handover_r
|
||||
if (wps_build_oob_dev_pw(msg, DEV_PW_NFC_CONNECTION_HANDOVER,
|
||||
nfc_dh_pubkey, NULL, 0) ||
|
||||
wps_build_uuid_e(msg, ctx->uuid) ||
|
||||
- wps_build_wfa_ext(msg, 0, NULL, 0)) {
|
||||
+ wps_build_wfa_ext(msg, 0, NULL, 0, 0)) {
|
||||
wpabuf_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
@@ -809,7 +809,7 @@ struct wpabuf * wps_build_nfc_handover_s
|
||||
wps_build_ssid(msg, ctx) ||
|
||||
wps_build_ap_freq(msg, freq) ||
|
||||
(bssid && wps_build_mac_addr(msg, bssid)) ||
|
||||
- wps_build_wfa_ext(msg, 0, NULL, 0)) {
|
||||
+ wps_build_wfa_ext(msg, 0, NULL, 0, 0)) {
|
||||
wpabuf_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
@@ -848,7 +848,7 @@ struct wpabuf * wps_build_nfc_handover_r
|
||||
wps_build_rf_bands(&ctx->dev, msg, 0) ||
|
||||
wps_build_serial_number(&ctx->dev, msg) ||
|
||||
wps_build_uuid_e(msg, ctx->uuid) ||
|
||||
- wps_build_wfa_ext(msg, 0, NULL, 0)) {
|
||||
+ wps_build_wfa_ext(msg, 0, NULL, 0, 0)) {
|
||||
wpabuf_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
@@ -900,7 +900,7 @@ struct wpabuf * wps_build_nfc_handover_s
|
||||
wps_build_rf_bands(&ctx->dev, msg, 0) ||
|
||||
wps_build_serial_number(&ctx->dev, msg) ||
|
||||
wps_build_uuid_e(msg, ctx->uuid) ||
|
||||
- wps_build_wfa_ext(msg, 0, NULL, 0)) {
|
||||
+ wps_build_wfa_ext(msg, 0, NULL, 0, 0)) {
|
||||
wpabuf_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
--- a/src/wps/wps_defs.h
|
||||
+++ b/src/wps/wps_defs.h
|
||||
@@ -152,7 +152,8 @@ enum {
|
||||
WFA_ELEM_NETWORK_KEY_SHAREABLE = 0x02,
|
||||
WFA_ELEM_REQUEST_TO_ENROLL = 0x03,
|
||||
WFA_ELEM_SETTINGS_DELAY_TIME = 0x04,
|
||||
- WFA_ELEM_REGISTRAR_CONFIGURATION_METHODS = 0x05
|
||||
+ WFA_ELEM_REGISTRAR_CONFIGURATION_METHODS = 0x05,
|
||||
+ WFA_ELEM_MULTI_AP = 0x06
|
||||
};
|
||||
|
||||
/* Device Password ID */
|
||||
--- a/src/wps/wps_enrollee.c
|
||||
+++ b/src/wps/wps_enrollee.c
|
||||
@@ -152,7 +152,7 @@ static struct wpabuf * wps_build_m1(stru
|
||||
wps_build_dev_password_id(msg, wps->dev_pw_id) ||
|
||||
wps_build_config_error(msg, WPS_CFG_NO_ERROR) ||
|
||||
wps_build_os_version(&wps->wps->dev, msg) ||
|
||||
- wps_build_wfa_ext(msg, 0, NULL, 0) ||
|
||||
+ wps_build_wfa_ext(msg, 0, NULL, 0, 0) ||
|
||||
wps_build_vendor_ext_m1(&wps->wps->dev, msg)) {
|
||||
wpabuf_free(msg);
|
||||
return NULL;
|
||||
@@ -190,7 +190,7 @@ static struct wpabuf * wps_build_m3(stru
|
||||
wps_build_msg_type(msg, WPS_M3) ||
|
||||
wps_build_registrar_nonce(wps, msg) ||
|
||||
wps_build_e_hash(wps, msg) ||
|
||||
- wps_build_wfa_ext(msg, 0, NULL, 0) ||
|
||||
+ wps_build_wfa_ext(msg, 0, NULL, 0, 0) ||
|
||||
wps_build_authenticator(wps, msg)) {
|
||||
wpabuf_free(msg);
|
||||
return NULL;
|
||||
@@ -223,7 +223,7 @@ static struct wpabuf * wps_build_m5(stru
|
||||
wps_build_e_snonce1(wps, plain) ||
|
||||
wps_build_key_wrap_auth(wps, plain) ||
|
||||
wps_build_encr_settings(wps, msg, plain) ||
|
||||
- wps_build_wfa_ext(msg, 0, NULL, 0) ||
|
||||
+ wps_build_wfa_ext(msg, 0, NULL, 0, 0) ||
|
||||
wps_build_authenticator(wps, msg)) {
|
||||
wpabuf_clear_free(plain);
|
||||
wpabuf_free(msg);
|
||||
@@ -393,7 +393,7 @@ static struct wpabuf * wps_build_m7(stru
|
||||
(wps->wps->ap && wps_build_ap_settings(wps, plain)) ||
|
||||
wps_build_key_wrap_auth(wps, plain) ||
|
||||
wps_build_encr_settings(wps, msg, plain) ||
|
||||
- wps_build_wfa_ext(msg, 0, NULL, 0) ||
|
||||
+ wps_build_wfa_ext(msg, 0, NULL, 0, 0) ||
|
||||
wps_build_authenticator(wps, msg)) {
|
||||
wpabuf_clear_free(plain);
|
||||
wpabuf_free(msg);
|
||||
@@ -430,7 +430,7 @@ static struct wpabuf * wps_build_wsc_don
|
||||
wps_build_msg_type(msg, WPS_WSC_DONE) ||
|
||||
wps_build_enrollee_nonce(wps, msg) ||
|
||||
wps_build_registrar_nonce(wps, msg) ||
|
||||
- wps_build_wfa_ext(msg, 0, NULL, 0)) {
|
||||
+ wps_build_wfa_ext(msg, 0, NULL, 0, 0)) {
|
||||
wpabuf_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
--- a/src/wps/wps_er.c
|
||||
+++ b/src/wps/wps_er.c
|
||||
@@ -1530,7 +1530,7 @@ void wps_er_set_sel_reg(struct wps_er *e
|
||||
wps_er_build_selected_registrar(msg, sel_reg) ||
|
||||
wps_er_build_dev_password_id(msg, dev_passwd_id) ||
|
||||
wps_er_build_sel_reg_config_methods(msg, sel_reg_config_methods) ||
|
||||
- wps_build_wfa_ext(msg, 0, auth_macs, count) ||
|
||||
+ wps_build_wfa_ext(msg, 0, auth_macs, count, 0) ||
|
||||
wps_er_build_uuid_r(msg, er->wps->uuid)) {
|
||||
wpabuf_free(msg);
|
||||
return;
|
||||
@@ -2048,7 +2048,7 @@ struct wpabuf * wps_er_config_token_from
|
||||
data.wps = wps;
|
||||
data.use_cred = cred;
|
||||
if (wps_build_cred(&data, ret) ||
|
||||
- wps_build_wfa_ext(ret, 0, NULL, 0)) {
|
||||
+ wps_build_wfa_ext(ret, 0, NULL, 0, 0)) {
|
||||
wpabuf_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
--- a/src/wps/wps_i.h
|
||||
+++ b/src/wps/wps_i.h
|
||||
@@ -163,7 +163,8 @@ int wps_build_encr_settings(struct wps_d
|
||||
struct wpabuf *plain);
|
||||
int wps_build_version(struct wpabuf *msg);
|
||||
int wps_build_wfa_ext(struct wpabuf *msg, int req_to_enroll,
|
||||
- const u8 *auth_macs, size_t auth_macs_count);
|
||||
+ const u8 *auth_macs, size_t auth_macs_count,
|
||||
+ u8 multi_ap_subelem);
|
||||
int wps_build_msg_type(struct wpabuf *msg, enum wps_msg_type msg_type);
|
||||
int wps_build_enrollee_nonce(struct wps_data *wps, struct wpabuf *msg);
|
||||
int wps_build_registrar_nonce(struct wps_data *wps, struct wpabuf *msg);
|
||||
--- a/src/wps/wps_registrar.c
|
||||
+++ b/src/wps/wps_registrar.c
|
||||
@@ -1281,7 +1281,7 @@ static int wps_set_ie(struct wps_registr
|
||||
wps_build_sel_reg_config_methods(reg, beacon) ||
|
||||
wps_build_sel_pbc_reg_uuid_e(reg, beacon) ||
|
||||
(reg->dualband && wps_build_rf_bands(®->wps->dev, beacon, 0)) ||
|
||||
- wps_build_wfa_ext(beacon, 0, auth_macs, count) ||
|
||||
+ wps_build_wfa_ext(beacon, 0, auth_macs, count, 0) ||
|
||||
wps_build_vendor_ext(®->wps->dev, beacon)) {
|
||||
wpabuf_free(beacon);
|
||||
wpabuf_free(probe);
|
||||
@@ -1311,7 +1311,7 @@ static int wps_set_ie(struct wps_registr
|
||||
wps_build_device_attrs(®->wps->dev, probe) ||
|
||||
wps_build_probe_config_methods(reg, probe) ||
|
||||
(reg->dualband && wps_build_rf_bands(®->wps->dev, probe, 0)) ||
|
||||
- wps_build_wfa_ext(probe, 0, auth_macs, count) ||
|
||||
+ wps_build_wfa_ext(probe, 0, auth_macs, count, 0) ||
|
||||
wps_build_vendor_ext(®->wps->dev, probe)) {
|
||||
wpabuf_free(beacon);
|
||||
wpabuf_free(probe);
|
||||
@@ -1845,7 +1845,7 @@ static struct wpabuf * wps_build_m2(stru
|
||||
wps_build_config_error(msg, WPS_CFG_NO_ERROR) ||
|
||||
wps_build_dev_password_id(msg, wps->dev_pw_id) ||
|
||||
wps_build_os_version(&wps->wps->dev, msg) ||
|
||||
- wps_build_wfa_ext(msg, 0, NULL, 0)) {
|
||||
+ wps_build_wfa_ext(msg, 0, NULL, 0, 0)) {
|
||||
wpabuf_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
@@ -1913,7 +1913,7 @@ static struct wpabuf * wps_build_m2d(str
|
||||
wps_build_assoc_state(wps, msg) ||
|
||||
wps_build_config_error(msg, err) ||
|
||||
wps_build_os_version(&wps->wps->dev, msg) ||
|
||||
- wps_build_wfa_ext(msg, 0, NULL, 0)) {
|
||||
+ wps_build_wfa_ext(msg, 0, NULL, 0, 0)) {
|
||||
wpabuf_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
@@ -1949,7 +1949,7 @@ static struct wpabuf * wps_build_m4(stru
|
||||
wps_build_r_snonce1(wps, plain) ||
|
||||
wps_build_key_wrap_auth(wps, plain) ||
|
||||
wps_build_encr_settings(wps, msg, plain) ||
|
||||
- wps_build_wfa_ext(msg, 0, NULL, 0) ||
|
||||
+ wps_build_wfa_ext(msg, 0, NULL, 0, 0) ||
|
||||
wps_build_authenticator(wps, msg)) {
|
||||
wpabuf_clear_free(plain);
|
||||
wpabuf_free(msg);
|
||||
@@ -1984,7 +1984,7 @@ static struct wpabuf * wps_build_m6(stru
|
||||
wps_build_r_snonce2(wps, plain) ||
|
||||
wps_build_key_wrap_auth(wps, plain) ||
|
||||
wps_build_encr_settings(wps, msg, plain) ||
|
||||
- wps_build_wfa_ext(msg, 0, NULL, 0) ||
|
||||
+ wps_build_wfa_ext(msg, 0, NULL, 0, 0) ||
|
||||
wps_build_authenticator(wps, msg)) {
|
||||
wpabuf_clear_free(plain);
|
||||
wpabuf_free(msg);
|
||||
@@ -2021,7 +2021,7 @@ static struct wpabuf * wps_build_m8(stru
|
||||
(!wps->wps->ap && !wps->er && wps_build_ap_settings(wps, plain)) ||
|
||||
wps_build_key_wrap_auth(wps, plain) ||
|
||||
wps_build_encr_settings(wps, msg, plain) ||
|
||||
- wps_build_wfa_ext(msg, 0, NULL, 0) ||
|
||||
+ wps_build_wfa_ext(msg, 0, NULL, 0, 0) ||
|
||||
wps_build_authenticator(wps, msg)) {
|
||||
wpabuf_clear_free(plain);
|
||||
wpabuf_clear_free(msg);
|
||||
--- a/src/wps/wps_upnp.c
|
||||
+++ b/src/wps/wps_upnp.c
|
||||
@@ -599,7 +599,7 @@ static struct wpabuf * build_fake_wsc_ac
|
||||
wpabuf_put_be16(msg, ATTR_REGISTRAR_NONCE);
|
||||
wpabuf_put_be16(msg, WPS_NONCE_LEN);
|
||||
wpabuf_put(msg, WPS_NONCE_LEN);
|
||||
- if (wps_build_wfa_ext(msg, 0, NULL, 0)) {
|
||||
+ if (wps_build_wfa_ext(msg, 0, NULL, 0, 0)) {
|
||||
wpabuf_free(msg);
|
||||
return NULL;
|
||||
}
|
@ -0,0 +1,217 @@
|
||||
From 6c4c98db9420a3321bbf091cfc254de5eba4b404 Mon Sep 17 00:00:00 2001
|
||||
From: Davina Lu <ylu@quantenna.com>
|
||||
Date: Tue, 15 Jan 2019 19:17:51 +0100
|
||||
Subject: [PATCH] wpa_supplicant: support Multi-AP backhaul STA onboarding
|
||||
|
||||
The Wi-Fi Alliance Multi-AP Specification v1.0 allows onboarding of a
|
||||
backhaul STA through WPS. To enable this, the backhaul STA needs to add
|
||||
a Multi-AP IE to the WFA vendor extension element in the WSC M1 message
|
||||
that indicates it supports the Multi-AP backhaul STA role. The registrar
|
||||
(if it support Multi-AP onboarding) will respond to that with a WSC M8
|
||||
message that also contains the Multi-AP IE, and that contains the
|
||||
credentials for the backhaul SSID (which may be different from the SSID
|
||||
on which WPS is performed).
|
||||
|
||||
Introduce a new parameter to wpas_wps_start_pbc() and allow it to be
|
||||
set via control interface's new multi_ap=1 parameter of WPS_PBC call.
|
||||
multi_ap_backhaul_sta is set to 1 in the automatically created SSID.
|
||||
Thus, if the AP does not support Multi-AP, association will fail and
|
||||
WPS will be terminated.
|
||||
|
||||
Only wps_pbc is supported.
|
||||
|
||||
The multi_ap argument is only added to the socket interface, not to the
|
||||
dbus interface.
|
||||
|
||||
Signed-off-by: Davina Lu <ylu@quantenna.com>
|
||||
Signed-off-by: Igor Mitsyanko <igor.mitsyanko.os@quantenna.com>
|
||||
Signed-off-by: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
---
|
||||
v4: use argument to wps_pbc instead of a global configuration option
|
||||
(requested by Jouni)
|
||||
---
|
||||
src/eap_peer/eap_wsc.c | 3 +++
|
||||
src/wps/wps.h | 6 ++++++
|
||||
src/wps/wps_enrollee.c | 6 +++++-
|
||||
wpa_supplicant/ctrl_iface.c | 5 ++++-
|
||||
wpa_supplicant/dbus/dbus_new_handlers_wps.c | 2 +-
|
||||
wpa_supplicant/dbus/dbus_old_handlers_wps.c | 4 ++--
|
||||
wpa_supplicant/events.c | 2 +-
|
||||
wpa_supplicant/p2p_supplicant.c | 2 +-
|
||||
wpa_supplicant/wps_supplicant.c | 9 +++++++--
|
||||
wpa_supplicant/wps_supplicant.h | 2 +-
|
||||
10 files changed, 31 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/src/eap_peer/eap_wsc.c
|
||||
+++ b/src/eap_peer/eap_wsc.c
|
||||
@@ -274,6 +274,9 @@ static void * eap_wsc_init(struct eap_sm
|
||||
cfg.pin, cfg.pin_len, 0);
|
||||
}
|
||||
|
||||
+ if (os_strstr(phase1, "multi_ap=1"))
|
||||
+ wps->multi_ap_backhaul_sta = 1;
|
||||
+
|
||||
/* Use reduced client timeout for WPS to avoid long wait */
|
||||
if (sm->ClientTimeout > 30)
|
||||
sm->ClientTimeout = 30;
|
||||
--- a/src/wps/wps.h
|
||||
+++ b/src/wps/wps.h
|
||||
@@ -613,6 +613,12 @@ struct wps_context {
|
||||
int ap_setup_locked;
|
||||
|
||||
/**
|
||||
+ * multi_ap_backhaul_sta - Whether this is a Multi-AP backhaul STA
|
||||
+ * enrollee
|
||||
+ */
|
||||
+ int multi_ap_backhaul_sta;
|
||||
+
|
||||
+ /**
|
||||
* uuid - Own UUID
|
||||
*/
|
||||
u8 uuid[16];
|
||||
--- a/src/wps/wps_enrollee.c
|
||||
+++ b/src/wps/wps_enrollee.c
|
||||
@@ -105,6 +105,7 @@ static struct wpabuf * wps_build_m1(stru
|
||||
{
|
||||
struct wpabuf *msg;
|
||||
u16 config_methods;
|
||||
+ u8 multi_ap_backhaul_sta = 0;
|
||||
|
||||
if (random_get_bytes(wps->nonce_e, WPS_NONCE_LEN) < 0)
|
||||
return NULL;
|
||||
@@ -134,6 +135,9 @@ static struct wpabuf * wps_build_m1(stru
|
||||
WPS_CONFIG_PHY_PUSHBUTTON);
|
||||
}
|
||||
|
||||
+ if (wps->wps->multi_ap_backhaul_sta)
|
||||
+ multi_ap_backhaul_sta = MULTI_AP_BACKHAUL_STA;
|
||||
+
|
||||
if (wps_build_version(msg) ||
|
||||
wps_build_msg_type(msg, WPS_M1) ||
|
||||
wps_build_uuid_e(msg, wps->uuid_e) ||
|
||||
@@ -152,7 +156,7 @@ static struct wpabuf * wps_build_m1(stru
|
||||
wps_build_dev_password_id(msg, wps->dev_pw_id) ||
|
||||
wps_build_config_error(msg, WPS_CFG_NO_ERROR) ||
|
||||
wps_build_os_version(&wps->wps->dev, msg) ||
|
||||
- wps_build_wfa_ext(msg, 0, NULL, 0, 0) ||
|
||||
+ wps_build_wfa_ext(msg, 0, NULL, 0, multi_ap_backhaul_sta) ||
|
||||
wps_build_vendor_ext_m1(&wps->wps->dev, msg)) {
|
||||
wpabuf_free(msg);
|
||||
return NULL;
|
||||
--- a/wpa_supplicant/ctrl_iface.c
|
||||
+++ b/wpa_supplicant/ctrl_iface.c
|
||||
@@ -1167,6 +1167,7 @@ static int wpa_supplicant_ctrl_iface_wps
|
||||
#ifdef CONFIG_AP
|
||||
u8 *_p2p_dev_addr = NULL;
|
||||
#endif /* CONFIG_AP */
|
||||
+ int multi_ap = 0;
|
||||
|
||||
if (cmd == NULL || os_strcmp(cmd, "any") == 0) {
|
||||
_bssid = NULL;
|
||||
@@ -1184,6 +1185,8 @@ static int wpa_supplicant_ctrl_iface_wps
|
||||
wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
|
||||
cmd);
|
||||
return -1;
|
||||
+ } else if (os_strncmp(cmd, "multi_ap=", 9) == 0) {
|
||||
+ multi_ap = atoi(cmd + 9);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_AP
|
||||
@@ -1191,7 +1194,7 @@ static int wpa_supplicant_ctrl_iface_wps
|
||||
return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr);
|
||||
#endif /* CONFIG_AP */
|
||||
|
||||
- return wpas_wps_start_pbc(wpa_s, _bssid, 0);
|
||||
+ return wpas_wps_start_pbc(wpa_s, _bssid, 0, multi_ap);
|
||||
}
|
||||
|
||||
|
||||
--- a/wpa_supplicant/dbus/dbus_new_handlers_wps.c
|
||||
+++ b/wpa_supplicant/dbus/dbus_new_handlers_wps.c
|
||||
@@ -289,7 +289,7 @@ DBusMessage * wpas_dbus_handler_wps_star
|
||||
if (ret > 0)
|
||||
os_snprintf(npin, sizeof(npin), "%08d", ret);
|
||||
} else {
|
||||
- ret = wpas_wps_start_pbc(wpa_s, params.bssid, 0);
|
||||
+ ret = wpas_wps_start_pbc(wpa_s, params.bssid, 0, 0);
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
--- a/wpa_supplicant/dbus/dbus_old_handlers_wps.c
|
||||
+++ b/wpa_supplicant/dbus/dbus_old_handlers_wps.c
|
||||
@@ -37,9 +37,9 @@ DBusMessage * wpas_dbus_iface_wps_pbc(DB
|
||||
return wpas_dbus_new_invalid_opts_error(message, NULL);
|
||||
|
||||
if (os_strcmp(arg_bssid, "any") == 0)
|
||||
- ret = wpas_wps_start_pbc(wpa_s, NULL, 0);
|
||||
+ ret = wpas_wps_start_pbc(wpa_s, NULL, 0, 0);
|
||||
else if (!hwaddr_aton(arg_bssid, bssid))
|
||||
- ret = wpas_wps_start_pbc(wpa_s, bssid, 0);
|
||||
+ ret = wpas_wps_start_pbc(wpa_s, bssid, 0, 0);
|
||||
else {
|
||||
return wpas_dbus_new_invalid_opts_error(message,
|
||||
"Invalid BSSID");
|
||||
--- a/wpa_supplicant/events.c
|
||||
+++ b/wpa_supplicant/events.c
|
||||
@@ -4816,7 +4816,7 @@ void supplicant_event(void *ctx, enum wp
|
||||
break;
|
||||
case EVENT_WPS_BUTTON_PUSHED:
|
||||
#ifdef CONFIG_WPS
|
||||
- wpas_wps_start_pbc(wpa_s, NULL, 0);
|
||||
+ wpas_wps_start_pbc(wpa_s, NULL, 0, 0);
|
||||
#endif /* CONFIG_WPS */
|
||||
break;
|
||||
case EVENT_AVOID_FREQUENCIES:
|
||||
--- a/wpa_supplicant/p2p_supplicant.c
|
||||
+++ b/wpa_supplicant/p2p_supplicant.c
|
||||
@@ -1649,7 +1649,7 @@ static void wpas_start_wps_enrollee(stru
|
||||
wpa_supplicant_ap_deinit(wpa_s);
|
||||
wpas_copy_go_neg_results(wpa_s, res);
|
||||
if (res->wps_method == WPS_PBC) {
|
||||
- wpas_wps_start_pbc(wpa_s, res->peer_interface_addr, 1);
|
||||
+ wpas_wps_start_pbc(wpa_s, res->peer_interface_addr, 1, 0);
|
||||
#ifdef CONFIG_WPS_NFC
|
||||
} else if (res->wps_method == WPS_NFC) {
|
||||
wpas_wps_start_nfc(wpa_s, res->peer_device_addr,
|
||||
--- a/wpa_supplicant/wps_supplicant.c
|
||||
+++ b/wpa_supplicant/wps_supplicant.c
|
||||
@@ -1137,9 +1137,10 @@ static void wpas_wps_reassoc(struct wpa_
|
||||
|
||||
|
||||
int wpas_wps_start_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
||||
- int p2p_group)
|
||||
+ int p2p_group, int multi_ap_backhaul_sta)
|
||||
{
|
||||
struct wpa_ssid *ssid;
|
||||
+ char phase1[32];
|
||||
|
||||
#ifdef CONFIG_AP
|
||||
if (wpa_s->ap_iface) {
|
||||
@@ -1177,10 +1178,14 @@ int wpas_wps_start_pbc(struct wpa_suppli
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
- if (wpa_config_set(ssid, "phase1", "\"pbc=1\"", 0) < 0)
|
||||
+ if (os_snprintf(phase1, sizeof(phase1), "pbc=1%s",
|
||||
+ multi_ap_backhaul_sta ? " multi_ap=1" : "") ||
|
||||
+ wpa_config_set_quoted(ssid, "phase1", phase1) < 0)
|
||||
return -1;
|
||||
if (wpa_s->wps_fragment_size)
|
||||
ssid->eap.fragment_size = wpa_s->wps_fragment_size;
|
||||
+ if (multi_ap_backhaul_sta)
|
||||
+ ssid->multi_ap_backhaul_sta = 1;
|
||||
wpa_supplicant_wps_event(wpa_s, WPS_EV_PBC_ACTIVE, NULL);
|
||||
eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout,
|
||||
wpa_s, NULL);
|
||||
--- a/wpa_supplicant/wps_supplicant.h
|
||||
+++ b/wpa_supplicant/wps_supplicant.h
|
||||
@@ -30,7 +30,7 @@ void wpas_wps_deinit(struct wpa_supplica
|
||||
int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s);
|
||||
enum wps_request_type wpas_wps_get_req_type(struct wpa_ssid *ssid);
|
||||
int wpas_wps_start_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
||||
- int p2p_group);
|
||||
+ int p2p_group, int multi_ap_backhaul_sta);
|
||||
int wpas_wps_start_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
||||
const char *pin, int p2p_group, u16 dev_pw_id);
|
||||
void wpas_wps_pbc_overlap(struct wpa_supplicant *wpa_s);
|
@ -0,0 +1,339 @@
|
||||
From 8b04a4cddbd6dbadb24279713af7ac677e80d342 Mon Sep 17 00:00:00 2001
|
||||
From: Davina Lu <ylu@quantenna.com>
|
||||
Date: Tue, 2 Oct 2018 18:34:14 -0700
|
||||
Subject: [PATCH] hostapd: support Multi-AP backhaul STA onboarding
|
||||
|
||||
The Wi-Fi Alliance Multi-AP Specification v1.0 allows onboarding of a
|
||||
backhaul STA through WPS. To enable this, the WPS registrar offers a
|
||||
different set of credentials (backhaul credentials instead of fronthaul
|
||||
credentials) when the Multi-AP subelement is present in the WFA vendor
|
||||
extension element of the WSC M1 message.
|
||||
|
||||
Add 3 new configuration options to specify the backhaul credentials for
|
||||
the hostapd internal registrar: multi_ap_backhaul_ssid,
|
||||
multi_ap_backhaul_wpa_psk, multi_ap_backhaul_wpa_passphrase. These are
|
||||
only relevant for a fronthaul SSID, i.e. where multi_ap is set to 2 or
|
||||
3. When these options are set, pass the backhaul credentials instead of
|
||||
the normal credentials when the Multi-AP subelement is present.
|
||||
|
||||
Ignore the Multi-AP subelement if the backhaul config options are not
|
||||
set. Note that for an SSID which is fronthaul and backhaul at the same
|
||||
time (i.e., multi_ap == 3), this results in the correct credentials
|
||||
being sent anyway.
|
||||
|
||||
The security to be used for the backaul BSS is fixed to WPA2PSK. The
|
||||
Multi-AP Specification only allows Open and WPA2PSK networks to be
|
||||
configured. Although not stated explicitly, the backhaul link is
|
||||
intended to be always encrypted, hence WPA2PSK.
|
||||
|
||||
To build the credentials, the credential-building code is essentially
|
||||
copied and simplified. Indeed, the backhaul credentials are always
|
||||
WPA2PSK and never use per-device PSK. All the options set for the
|
||||
fronthaul BSS WPS are simply ignored.
|
||||
|
||||
Signed-off-by: Davina Lu <ylu@quantenna.com>
|
||||
Signed-off-by: Igor Mitsyanko <igor.mitsyanko.os@quantenna.com>
|
||||
Signed-off-by: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>
|
||||
---
|
||||
v4: no change
|
||||
---
|
||||
hostapd/config_file.c | 47 ++++++++++++++++++++++++++++++++++++++++
|
||||
hostapd/hostapd.conf | 9 ++++++++
|
||||
src/ap/ap_config.c | 2 ++
|
||||
src/ap/ap_config.h | 1 +
|
||||
src/ap/wps_hostapd.c | 26 ++++++++++++++++++++++
|
||||
src/wps/wps.h | 32 +++++++++++++++++++++++++++
|
||||
src/wps/wps_attr_parse.c | 11 ++++++++++
|
||||
src/wps/wps_attr_parse.h | 1 +
|
||||
src/wps/wps_dev_attr.c | 5 +++++
|
||||
src/wps/wps_dev_attr.h | 1 +
|
||||
src/wps/wps_registrar.c | 25 ++++++++++++++++++++-
|
||||
11 files changed, 159 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/hostapd/config_file.c
|
||||
+++ b/hostapd/config_file.c
|
||||
@@ -3479,6 +3479,53 @@ static int hostapd_config_fill(struct ho
|
||||
line, pos);
|
||||
return 1;
|
||||
}
|
||||
+ } else if (os_strcmp(buf, "multi_ap_backhaul_ssid") == 0) {
|
||||
+ size_t slen;
|
||||
+ char *str = wpa_config_parse_string(pos, &slen);
|
||||
+
|
||||
+ if (str == NULL || slen < 1 || slen > SSID_MAX_LEN) {
|
||||
+ wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'",
|
||||
+ line, pos);
|
||||
+ os_free(str);
|
||||
+ return 1;
|
||||
+ }
|
||||
+ os_memcpy(bss->multi_ap_backhaul_ssid.ssid, str, slen);
|
||||
+ bss->multi_ap_backhaul_ssid.ssid_len = slen;
|
||||
+ bss->multi_ap_backhaul_ssid.ssid_set = 1;
|
||||
+ os_free(str);
|
||||
+ } else if (os_strcmp(buf, "multi_ap_backhaul_wpa_passphrase") == 0) {
|
||||
+ int len = os_strlen(pos);
|
||||
+
|
||||
+ if (len < 8 || len > 63) {
|
||||
+ wpa_printf(MSG_ERROR,
|
||||
+ "Line %d: invalid WPA passphrase length %d (expected 8..63)",
|
||||
+ line, len);
|
||||
+ return 1;
|
||||
+ }
|
||||
+ os_free(bss->multi_ap_backhaul_ssid.wpa_passphrase);
|
||||
+ bss->multi_ap_backhaul_ssid.wpa_passphrase = os_strdup(pos);
|
||||
+ if (bss->multi_ap_backhaul_ssid.wpa_passphrase) {
|
||||
+ hostapd_config_clear_wpa_psk(&bss->multi_ap_backhaul_ssid.wpa_psk);
|
||||
+ bss->multi_ap_backhaul_ssid.wpa_passphrase_set = 1;
|
||||
+ }
|
||||
+ } else if (os_strcmp(buf, "multi_ap_backhaul_wpa_psk") == 0) {
|
||||
+ hostapd_config_clear_wpa_psk(&bss->multi_ap_backhaul_ssid.wpa_psk);
|
||||
+ bss->multi_ap_backhaul_ssid.wpa_psk =
|
||||
+ os_zalloc(sizeof(struct hostapd_wpa_psk));
|
||||
+ if (bss->multi_ap_backhaul_ssid.wpa_psk == NULL)
|
||||
+ return 1;
|
||||
+ if (hexstr2bin(pos, bss->multi_ap_backhaul_ssid.wpa_psk->psk,
|
||||
+ PMK_LEN) ||
|
||||
+ pos[PMK_LEN * 2] != '\0') {
|
||||
+ wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.",
|
||||
+ line, pos);
|
||||
+ hostapd_config_clear_wpa_psk(&bss->multi_ap_backhaul_ssid.wpa_psk);
|
||||
+ return 1;
|
||||
+ }
|
||||
+ bss->multi_ap_backhaul_ssid.wpa_psk->group = 1;
|
||||
+ os_free(bss->multi_ap_backhaul_ssid.wpa_passphrase);
|
||||
+ bss->multi_ap_backhaul_ssid.wpa_passphrase = NULL;
|
||||
+ bss->multi_ap_backhaul_ssid.wpa_psk_set = 1;
|
||||
} else if (os_strcmp(buf, "upnp_iface") == 0) {
|
||||
os_free(bss->upnp_iface);
|
||||
bss->upnp_iface = os_strdup(pos);
|
||||
--- a/hostapd/hostapd.conf
|
||||
+++ b/hostapd/hostapd.conf
|
||||
@@ -1852,6 +1852,15 @@ own_ip_addr=127.0.0.1
|
||||
# attribute.
|
||||
#ap_settings=hostapd.ap_settings
|
||||
|
||||
+# Multi-AP backhaul BSS config
|
||||
+# Used in WPS when multi_ap=2 or 3. Defines "backhaul BSS" credentials.
|
||||
+# These are passed in WPS M8 instead of the normal (fronthaul) credentials
|
||||
+# if the enrollee has the Multi-AP subelement set. Backhaul SSID is formatted
|
||||
+# like ssid2. The key is set like wpa_psk or wpa_passphrase.
|
||||
+#multi_ap_backhaul_ssid="backhaul"
|
||||
+#multi_ap_backhaul_wpa_psk=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
|
||||
+#multi_ap_backhaul_wpa_passphrase=secret passphrase
|
||||
+
|
||||
# WPS UPnP interface
|
||||
# If set, support for external Registrars is enabled.
|
||||
#upnp_iface=br0
|
||||
--- a/src/ap/ap_config.c
|
||||
+++ b/src/ap/ap_config.c
|
||||
@@ -582,6 +582,8 @@ void hostapd_config_free_bss(struct host
|
||||
os_free(conf->ap_pin);
|
||||
os_free(conf->extra_cred);
|
||||
os_free(conf->ap_settings);
|
||||
+ hostapd_config_clear_wpa_psk(&conf->multi_ap_backhaul_ssid.wpa_psk);
|
||||
+ str_clear_free(conf->multi_ap_backhaul_ssid.wpa_passphrase);
|
||||
os_free(conf->upnp_iface);
|
||||
os_free(conf->friendly_name);
|
||||
os_free(conf->manufacturer_url);
|
||||
--- a/src/ap/ap_config.h
|
||||
+++ b/src/ap/ap_config.h
|
||||
@@ -456,6 +456,7 @@ struct hostapd_bss_config {
|
||||
int force_per_enrollee_psk;
|
||||
u8 *ap_settings;
|
||||
size_t ap_settings_len;
|
||||
+ struct hostapd_ssid multi_ap_backhaul_ssid;
|
||||
char *upnp_iface;
|
||||
char *friendly_name;
|
||||
char *manufacturer_url;
|
||||
--- a/src/ap/wps_hostapd.c
|
||||
+++ b/src/ap/wps_hostapd.c
|
||||
@@ -962,6 +962,7 @@ static void hostapd_free_wps(struct wps_
|
||||
wpabuf_free(wps->dev.vendor_ext[i]);
|
||||
wps_device_data_free(&wps->dev);
|
||||
os_free(wps->network_key);
|
||||
+ os_free(wps->multi_ap_backhaul_network_key);
|
||||
hostapd_wps_nfc_clear(wps);
|
||||
wpabuf_free(wps->dh_pubkey);
|
||||
wpabuf_free(wps->dh_privkey);
|
||||
@@ -1131,6 +1132,31 @@ int hostapd_init_wps(struct hostapd_data
|
||||
wps->encr_types_wpa = WPS_ENCR_AES | WPS_ENCR_TKIP;
|
||||
}
|
||||
|
||||
+ if (hapd->conf->multi_ap & FRONTHAUL_BSS &&
|
||||
+ hapd->conf->multi_ap_backhaul_ssid.ssid_len) {
|
||||
+ wps->multi_ap_backhaul_ssid_len =
|
||||
+ hapd->conf->multi_ap_backhaul_ssid.ssid_len;
|
||||
+ os_memcpy(wps->multi_ap_backhaul_ssid,
|
||||
+ hapd->conf->multi_ap_backhaul_ssid.ssid,
|
||||
+ wps->multi_ap_backhaul_ssid_len);
|
||||
+ if (conf->multi_ap_backhaul_ssid.wpa_passphrase) {
|
||||
+ wps->multi_ap_backhaul_network_key =
|
||||
+ (u8 *) os_strdup(conf->multi_ap_backhaul_ssid.wpa_passphrase);
|
||||
+ wps->multi_ap_backhaul_network_key_len =
|
||||
+ os_strlen(conf->multi_ap_backhaul_ssid.wpa_passphrase);
|
||||
+ } else if (conf->multi_ap_backhaul_ssid.wpa_psk) {
|
||||
+ wps->multi_ap_backhaul_network_key =
|
||||
+ os_malloc(2 * PMK_LEN + 1);
|
||||
+ if (wps->multi_ap_backhaul_network_key == NULL)
|
||||
+ goto fail;
|
||||
+ wpa_snprintf_hex((char *) wps->multi_ap_backhaul_network_key,
|
||||
+ 2 * PMK_LEN + 1,
|
||||
+ conf->multi_ap_backhaul_ssid.wpa_psk->psk,
|
||||
+ PMK_LEN);
|
||||
+ wps->multi_ap_backhaul_network_key_len = 2 * PMK_LEN;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
wps->ap_settings = conf->ap_settings;
|
||||
wps->ap_settings_len = conf->ap_settings_len;
|
||||
|
||||
--- a/src/wps/wps.h
|
||||
+++ b/src/wps/wps.h
|
||||
@@ -100,6 +100,7 @@ struct wps_device_data {
|
||||
struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
|
||||
|
||||
int p2p;
|
||||
+ u8 multi_ap_ext;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -730,6 +731,37 @@ struct wps_context {
|
||||
int psk_set;
|
||||
|
||||
/**
|
||||
+ * multi_ap_backhaul_ssid - SSID to supply to a Multi-AP backhaul
|
||||
+ * enrollee
|
||||
+ *
|
||||
+ * This SSID is used by the Registrar to fill in information for
|
||||
+ * Credentials when the enrollee advertises it is a Multi-AP backhaul
|
||||
+ * STA.
|
||||
+ */
|
||||
+ u8 multi_ap_backhaul_ssid[SSID_MAX_LEN];
|
||||
+
|
||||
+ /**
|
||||
+ * multi_ap_backhaul_ssid_len - Length of multi_ap_backhaul_ssid in
|
||||
+ * octets
|
||||
+ */
|
||||
+ size_t multi_ap_backhaul_ssid_len;
|
||||
+
|
||||
+ /**
|
||||
+ * multi_ap_backhaul_network_key - The Network Key (PSK) for the
|
||||
+ * Multi-AP backhaul enrollee.
|
||||
+ *
|
||||
+ * This key can be either the ASCII passphrase (8..63 characters) or the
|
||||
+ * 32-octet PSK (64 hex characters).
|
||||
+ */
|
||||
+ u8 *multi_ap_backhaul_network_key;
|
||||
+
|
||||
+ /**
|
||||
+ * multi_ap_backhaul_network_key_len - Length of
|
||||
+ * multi_ap_backhaul_network_key in octets
|
||||
+ */
|
||||
+ size_t multi_ap_backhaul_network_key_len;
|
||||
+
|
||||
+ /**
|
||||
* ap_settings - AP Settings override for M7 (only used at AP)
|
||||
*
|
||||
* If %NULL, AP Settings attributes will be generated based on the
|
||||
--- a/src/wps/wps_attr_parse.c
|
||||
+++ b/src/wps/wps_attr_parse.c
|
||||
@@ -67,6 +67,17 @@ static int wps_set_vendor_ext_wfa_subele
|
||||
}
|
||||
attr->registrar_configuration_methods = pos;
|
||||
break;
|
||||
+ case WFA_ELEM_MULTI_AP:
|
||||
+ if (len != 1) {
|
||||
+ wpa_printf(MSG_DEBUG,
|
||||
+ "WPS: Invalid Multi-AP Extension length %u",
|
||||
+ len);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ attr->multi_ap_ext = *pos;
|
||||
+ wpa_printf(MSG_DEBUG, "WPS: Multi-AP Extension 0x%02x",
|
||||
+ attr->multi_ap_ext);
|
||||
+ break;
|
||||
default:
|
||||
wpa_printf(MSG_MSGDUMP, "WPS: Skipped unknown WFA Vendor "
|
||||
"Extension subelement %u", id);
|
||||
--- a/src/wps/wps_attr_parse.h
|
||||
+++ b/src/wps/wps_attr_parse.h
|
||||
@@ -97,6 +97,7 @@ struct wps_parse_attr {
|
||||
const u8 *cred[MAX_CRED_COUNT];
|
||||
const u8 *req_dev_type[MAX_REQ_DEV_TYPE_COUNT];
|
||||
const u8 *vendor_ext[MAX_WPS_PARSE_VENDOR_EXT];
|
||||
+ u8 multi_ap_ext;
|
||||
};
|
||||
|
||||
int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr);
|
||||
--- a/src/wps/wps_dev_attr.c
|
||||
+++ b/src/wps/wps_dev_attr.c
|
||||
@@ -389,6 +389,11 @@ int wps_process_os_version(struct wps_de
|
||||
return 0;
|
||||
}
|
||||
|
||||
+void wps_process_vendor_ext_m1(struct wps_device_data *dev, const u8 ext)
|
||||
+{
|
||||
+ dev->multi_ap_ext = ext;
|
||||
+ wpa_printf(MSG_DEBUG, "WPS: Multi-AP extension value %02x", dev->multi_ap_ext);
|
||||
+}
|
||||
|
||||
int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands)
|
||||
{
|
||||
--- a/src/wps/wps_dev_attr.h
|
||||
+++ b/src/wps/wps_dev_attr.h
|
||||
@@ -29,6 +29,7 @@ int wps_build_dev_name(struct wps_device
|
||||
int wps_process_device_attrs(struct wps_device_data *dev,
|
||||
struct wps_parse_attr *attr);
|
||||
int wps_process_os_version(struct wps_device_data *dev, const u8 *ver);
|
||||
+void wps_process_vendor_ext_m1(struct wps_device_data *dev, const u8 ext);
|
||||
int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands);
|
||||
void wps_device_data_free(struct wps_device_data *dev);
|
||||
int wps_build_vendor_ext(struct wps_device_data *dev, struct wpabuf *msg);
|
||||
--- a/src/wps/wps_registrar.c
|
||||
+++ b/src/wps/wps_registrar.c
|
||||
@@ -1588,7 +1588,6 @@ int wps_build_credential_wrap(struct wpa
|
||||
return 0;
|
||||
}
|
||||
|
||||
-
|
||||
int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
|
||||
{
|
||||
struct wpabuf *cred;
|
||||
@@ -1603,6 +1602,29 @@ int wps_build_cred(struct wps_data *wps,
|
||||
}
|
||||
os_memset(&wps->cred, 0, sizeof(wps->cred));
|
||||
|
||||
+ if (wps->peer_dev.multi_ap_ext == MULTI_AP_BACKHAUL_STA &&
|
||||
+ wps->wps->multi_ap_backhaul_ssid_len) {
|
||||
+ wpa_printf(MSG_DEBUG, "WPS: Use backhaul STA credentials");
|
||||
+ os_memcpy(wps->cred.ssid, wps->wps->multi_ap_backhaul_ssid,
|
||||
+ wps->wps->multi_ap_backhaul_ssid_len);
|
||||
+ wps->cred.ssid_len = wps->wps->multi_ap_backhaul_ssid_len;
|
||||
+ /* Backhaul is always WPA2PSK */
|
||||
+ wps->cred.auth_type = WPS_AUTH_WPA2PSK;
|
||||
+ wps->cred.encr_type = WPS_ENCR_AES;
|
||||
+ /* Set MAC address in the Credential to be the Enrollee's MAC
|
||||
+ * address
|
||||
+ */
|
||||
+ os_memcpy(wps->cred.mac_addr, wps->mac_addr_e, ETH_ALEN);
|
||||
+ if (wps->wps->multi_ap_backhaul_network_key) {
|
||||
+ os_memcpy(wps->cred.key,
|
||||
+ wps->wps->multi_ap_backhaul_network_key,
|
||||
+ wps->wps->multi_ap_backhaul_network_key_len);
|
||||
+ wps->cred.key_len =
|
||||
+ wps->wps->multi_ap_backhaul_network_key_len;
|
||||
+ }
|
||||
+ goto use_provided;
|
||||
+ }
|
||||
+
|
||||
os_memcpy(wps->cred.ssid, wps->wps->ssid, wps->wps->ssid_len);
|
||||
wps->cred.ssid_len = wps->wps->ssid_len;
|
||||
|
||||
@@ -2705,6 +2727,7 @@ static enum wps_process_res wps_process_
|
||||
wps->use_psk_key = 1;
|
||||
}
|
||||
#endif /* WPS_WORKAROUNDS */
|
||||
+ wps_process_vendor_ext_m1(&wps->peer_dev, attr->multi_ap_ext);
|
||||
|
||||
wps->state = SEND_M2;
|
||||
return WPS_CONTINUE;
|
@ -0,0 +1,181 @@
|
||||
From bd733055a22c8ca3bcd7648bf716da2713b3d9f1 Mon Sep 17 00:00:00 2001
|
||||
From: "Arnout Vandecappelle (Essensium/Mind)" <arnout@mind.be>
|
||||
Date: Mon, 21 Jan 2019 16:44:06 +0100
|
||||
Subject: [PATCH] hostapd: add README-MULTI-AP
|
||||
|
||||
Document what hostapd and wpa_supplicant do for Multi-AP.
|
||||
|
||||
This is only included in hostapd, since a Multi-AP device is always an
|
||||
access point so it should have hostapd.
|
||||
|
||||
Signed-off-by: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>
|
||||
---
|
||||
v4: wps_pbc has multi_ap as a parameter instead of config option.
|
||||
---
|
||||
hostapd/README-MULTI-AP | 160 ++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 160 insertions(+)
|
||||
create mode 100644 hostapd/README-MULTI-AP
|
||||
|
||||
--- /dev/null
|
||||
+++ b/hostapd/README-MULTI-AP
|
||||
@@ -0,0 +1,160 @@
|
||||
+hostapd, wpa_supplicant and the Multi-AP Specification
|
||||
+======================================================
|
||||
+
|
||||
+This document describes how hostapd and wpa_supplicant can be configured to
|
||||
+support the Multi-AP Specification.
|
||||
+
|
||||
+Introduction to Multi-AP
|
||||
+------------------------
|
||||
+
|
||||
+The Wi-Fi Alliance Multi-AP Specification is the technical specification for
|
||||
+Wi-Fi CERTIFIED EasyMesh(TM) [1], the Wi-Fi Alliance® certification program for
|
||||
+Multi-AP. It defines control protocols between Wi-Fi® access points (APs) to
|
||||
+join them into a network with centralized control and operation. It is targeted
|
||||
+only at routers (repeaters, gateways, ...), not at clients. Clients are not
|
||||
+involved at all in the protocols.
|
||||
+
|
||||
+Most of the Multi-AP specification falls outside of the scope of
|
||||
+hostapd/wpa_supplicant. hostapd/wpa_supplicant is only involved for the items
|
||||
+summarized below. The rest of the protocol must be implemented by a separate
|
||||
+daemon, e.g. prplMesh [2]. That daemon also needs to communicate with hostapd,
|
||||
+e.g. to get a list of associated clients, but this can be done using the normal
|
||||
+hostapd interfaces.
|
||||
+
|
||||
+hostapd/wpa_supplicant needs to be configured specifically to support:
|
||||
+- the WPS onboarding process;
|
||||
+- configuring backhaul links.
|
||||
+
|
||||
+The text below refers to "Multi-AP Specification v1.0" [3].
|
||||
+
|
||||
+
|
||||
+Fronthaul and backhaul links
|
||||
+----------------------------
|
||||
+
|
||||
+In a Multi-AP network, the central controller can configure the SSIDs on the
|
||||
+devices that are joined into the network. These are called fronthaul SSIDs.
|
||||
+From the point of view of hostapd, there is nothing special about these
|
||||
+fronthaul SSIDs.
|
||||
+
|
||||
+In addition to fronthaul SSIDs, the controller can also configure backhaul
|
||||
+links. A backhaul link is a link between two access point devices, giving
|
||||
+internet access to access point devices that don't have a wired link. The
|
||||
+Multi-AP specification doesn't dictate this, but typically the backhaul link
|
||||
+will be bridged into a LAN together with (one of) the fronthaul SSID(s) and the
|
||||
+wired Ethernet ports.
|
||||
+
|
||||
+A backhaul link must be treated specially by hostapd and wpa_supplicant. One
|
||||
+side of the backhaul link is configured through the Multi-AP protocol as the
|
||||
+"backhaul STA", i.e. the client side of the link. A backhaul STA is like any
|
||||
+station and is handled appropriately by wpa_supplicant, but two additional
|
||||
+features are required. It must send an additional information element in each
|
||||
+(Re-)Association Request ([3], section 5.2, paragraph 4). In addition, it must
|
||||
+use 4-address mode for all frames sent over this link ([3], section 14).
|
||||
+Therefore, wpa_supplicant must be configured explicitly as the backhaul STA
|
||||
+role, by setting 'multi_ap_backhaul_sta=1' in the network configuration block
|
||||
+or when configuring the SSID through the client socket. When
|
||||
+'multi_ap_backhaul_sta=1', wpa_supplicant includes the Multi-AP IE in
|
||||
+(Re-)Association Request messages and verifies that it is included in the
|
||||
+(Re-)Association Response. If it is not, association fails. If it is,
|
||||
+wpa_supplicant sets 4-address mode for this interface through a driver
|
||||
+callback.
|
||||
+
|
||||
+The AP side of the backhaul link is called a "backhaul SSID". Such an SSID must
|
||||
+be handled specially by hostapd, because it must add an additional information
|
||||
+element in each (Re-)Association Response, but only to stations that have
|
||||
+identified themselves as backhaul stations ([3], section 5.2, paragraph 5-6).
|
||||
+This is important because it is possible to use the same BSS and SSID for
|
||||
+fronthaul and backhaul at the same time. The additional information element must
|
||||
+only be used for frames sent to a backhaul STA, not to a normal STA. Also,
|
||||
+frames sent to a backhaul STA must use 4-address mode, while frames sent to a
|
||||
+normal STA (fronthaul, when it's a fronthaul and backhaul SSID) must use
|
||||
+3-address mode.
|
||||
+
|
||||
+An SSID is configured in Multi-AP mode in hostapd by setting the 'multi_ap'
|
||||
+configuration option to 1 (backhaul SSID), 2 (fronthaul SSID) or 3
|
||||
+(simultaneous backhaul and fronthaul SSID). If this option is set, hostapd
|
||||
+parses the Multi-AP information element in the Association Request. If the
|
||||
+station is a backhaul STA and the SSID is configured as a backhaul SSID,
|
||||
+hostapd sets up 4-address mode. Since there may be multiple stations connected
|
||||
+simultaneously, and each of them has a different RA (receiver address), a VLAN
|
||||
+is created for each backhaul STA and it is automatically added to a bridge.
|
||||
+This is the same behavior as for WDS, and the relevant option ('bridge' or
|
||||
+'wds_bridge') applies here as well.
|
||||
+
|
||||
+If 'multi_ap' is 1 (backhaul SSID only), any station that tries to associate
|
||||
+without the Multi-AP information element will be denied.
|
||||
+
|
||||
+If 'multi_ap' is 2 (fronthaul SSID only), any station that tries to associate
|
||||
+with the Multi-AP information element will be denied. That is also the only
|
||||
+difference with 'multi_ap' set to 0: in the latter case, the Multi-AP
|
||||
+information element is simply ignored.
|
||||
+
|
||||
+In summary, this is the end-to-end behaviour for a backhaul BSS (i.e.,
|
||||
+multi_ap_backhaul_sta=1 in wpa_supplicant on STA, and multi_ap=1 or 3 in
|
||||
+hostapd on AP). Note that point 1 means that hostapd must not be configured
|
||||
+with WPS support on the backhaul BSS (multi_ap=1). hostapd does not check for
|
||||
+that.
|
||||
+
|
||||
+1. Backhaul BSS beacons do not advertise WPS support (other than that, nothing
|
||||
+ multi-ap specific).
|
||||
+2. STA sends authentication req (nothing multi-ap specific).
|
||||
+3. AP sends authentication resp (nothing multi-ap specific).
|
||||
+4. STA sends association req with Multi-AP IE.
|
||||
+5. AP send association resp with Multi-AP IE.
|
||||
+6. STA and AP both use 4-address mode for data.
|
||||
+
|
||||
+
|
||||
+WPS support
|
||||
+-----------
|
||||
+
|
||||
+WPS requires more special handling. WPS must only be advertised on fronthaul
|
||||
+SSIDs, not on backhaul SSIDs, so WPS should not be enabled on a backhaul-only
|
||||
+SSID in hostapd.conf. The WPS configuration purely works on the fronthaul SSID.
|
||||
+When a WPS M1 message has an additional subelement that indicates a request for
|
||||
+a multi-AP backhaul link, hostapd must not respond with the normal fronthaul
|
||||
+SSID credentials; instead, it should respond with the (potentially different)
|
||||
+backhaul SSID credentials.
|
||||
+
|
||||
+To support this, hostapd has the 'multi_ap_backhaul_ssid',
|
||||
+'multi_ap_backhaul_wpa_psk' and 'multi_ap_backhaul_wpa_passphrase' options.
|
||||
+When these are set on an SSID with WPS, they are used instead of the normal
|
||||
+credentials when hostapd receives a WPS M1 message with the Multi-AP IE. Only
|
||||
+WPA2 Personal is supported in the Multi-AP specification, so there is no need
|
||||
+to specify authentication or encryption options. For the backhaul credentials,
|
||||
+per-device PSK is not supported.
|
||||
+
|
||||
+If the SSID is a simultaneous backhaul and fronthaul SSID, there is no need to
|
||||
+specify the backhaul credentials, since the backhaul and fronthaul credentials
|
||||
+are identical.
|
||||
+
|
||||
+To enable the Multi-AP backhaul STA feature when it performs WPS, a new
|
||||
+parameter has been introduced to the WPS_PBC control interface call.
|
||||
+When this option is set, it adds the multi-AP backhaul subelement to
|
||||
+the association and M1 messages. It then configures the new SSID with
|
||||
+'multi_ap_backhaul_sta=1'. Note that this means that if the AP does not
|
||||
+follow the Multi-AP specification, wpa_supplicant will fail to
|
||||
+associate.
|
||||
+
|
||||
+In summary, this is the end-to-end behaviour for WPS of a backhaul link (i.e.,
|
||||
+multi_ap=1 option is given in the wps_pbc call on the STA side, and multi_ap=2
|
||||
+and multi_ap_backhaul_ssid and either multi_ap_backhaul_wpa_psk or
|
||||
+multi_ap_backhaul_wpa_passphrase are set to the credentials of a backhaul SSID
|
||||
+in hostapd on registrar AP).
|
||||
+
|
||||
+1. Fronthaul BSS beacons advertise WPS support (nothing multi-ap specific).
|
||||
+2. Enrollee sends authentication req (nothing multi-ap specific).
|
||||
+3. AP sends authentication resp (nothing multi-ap specific).
|
||||
+4. Enrollee sends association req with Multi-AP IE.
|
||||
+5. AP send association resp with Multi-AP IE.
|
||||
+6. Enrollee sends M1 with additional Multi-AP subelement
|
||||
+7. AP sends M8 with backhaul instead of fronthaul credentials.
|
||||
+8. Enrollee sends Deauth.
|
||||
+
|
||||
+
|
||||
+References
|
||||
+----------
|
||||
+
|
||||
+[1] https://www.wi-fi.org/discover-wi-fi/wi-fi-easymesh
|
||||
+[2] https://github.com/prplfoundation/prplMesh
|
||||
+[3] https://www.wi-fi.org/file/multi-ap-specification-v10
|
||||
+ (requires registration)
|
@ -0,0 +1,182 @@
|
||||
From 0729e01f5830ebf4701f0b1b7ff1bd2a2eedae40 Mon Sep 17 00:00:00 2001
|
||||
From: "Arnout Vandecappelle (Essensium/Mind)" <arnout@mind.be>
|
||||
Date: Tue, 12 Feb 2019 11:02:42 +0100
|
||||
Subject: [PATCH] tests: add WPS tests to multi_ap hwsim tests
|
||||
|
||||
Signed-off-by: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>
|
||||
---
|
||||
v4: new patch
|
||||
---
|
||||
tests/hwsim/test_multi_ap.py | 164 +++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 164 insertions(+)
|
||||
|
||||
--- a/tests/hwsim/test_multi_ap.py
|
||||
+++ b/tests/hwsim/test_multi_ap.py
|
||||
@@ -61,3 +61,167 @@ def test_multi_ap_fronthaul_on_ap(dev, a
|
||||
raise Exception("Connection result not reported")
|
||||
if "CTRL-EVENT-DISCONNECTED" not in ev:
|
||||
raise Exception("Unexpected connection result")
|
||||
+
|
||||
+def run_multi_ap_wps(dev, apdev, params, multi_ap_bssid = None):
|
||||
+ """Helper for running Multi-AP WPS tests
|
||||
+
|
||||
+ dev[0] does multi_ap WPS, dev[1] does normal WPS. apdev[0] is the fronthaul
|
||||
+ BSS. If there is a separate backhaul BSS, it must have been set up by the
|
||||
+ caller. params are the normal SSID parameters, they will be extended with
|
||||
+ the WPS parameters. multi_ap_bssid must be given if it is not equal to the
|
||||
+ fronthaul BSSID."""
|
||||
+
|
||||
+ if multi_ap_bssid is None:
|
||||
+ multi_ap_bssid = apdev[0]['bssid']
|
||||
+ params.update({"wps_state": "2", "eap_server": "1"})
|
||||
+
|
||||
+ # WPS with multi-ap station dev[0]
|
||||
+ hapd = hostapd.add_ap(apdev[0], params)
|
||||
+ hapd.request("WPS_PBC")
|
||||
+ if "PBC Status: Active" not in hapd.request("WPS_GET_STATUS"):
|
||||
+ raise Exception("PBC status not shown correctly")
|
||||
+
|
||||
+ dev[0].request("WPS_PBC multi_ap=1")
|
||||
+ dev[0].wait_connected(timeout=20)
|
||||
+ status = dev[0].get_status()
|
||||
+ if status['wpa_state'] != 'COMPLETED' or status['bssid'] != multi_ap_bssid:
|
||||
+ raise Exception("Not fully connected")
|
||||
+ if status['ssid'] != params['multi_ap_backhaul_ssid'].strip('"'):
|
||||
+ raise Exception("Unexpected SSID %s != %s" % (status['ssid'], params["multi_ap_backhaul_ssid"]))
|
||||
+ if status['pairwise_cipher'] != 'CCMP':
|
||||
+ raise Exception("Unexpected encryption configuration %s" % status['pairwise_cipher'])
|
||||
+ if status['key_mgmt'] != 'WPA2-PSK':
|
||||
+ raise Exception("Unexpected key_mgmt")
|
||||
+
|
||||
+ status = hapd.request("WPS_GET_STATUS")
|
||||
+ if "PBC Status: Disabled" not in status:
|
||||
+ raise Exception("PBC status not shown correctly")
|
||||
+ if "Last WPS result: Success" not in status:
|
||||
+ raise Exception("Last WPS result not shown correctly")
|
||||
+ if "Peer Address: " + dev[0].p2p_interface_addr() not in status:
|
||||
+ raise Exception("Peer address not shown correctly")
|
||||
+
|
||||
+ if len(dev[0].list_networks()) != 1:
|
||||
+ raise Exception("Unexpected number of network blocks")
|
||||
+
|
||||
+ # WPS with non-multi-ap station dev[1]
|
||||
+ hapd.request("WPS_PBC")
|
||||
+ if "PBC Status: Active" not in hapd.request("WPS_GET_STATUS"):
|
||||
+ raise Exception("PBC status not shown correctly")
|
||||
+
|
||||
+ dev[1].request("WPS_PBC")
|
||||
+ dev[1].wait_connected(timeout=20)
|
||||
+ status = dev[1].get_status()
|
||||
+ if status['wpa_state'] != 'COMPLETED' or status['bssid'] != apdev[0]['bssid']:
|
||||
+ raise Exception("Not fully connected")
|
||||
+ if status['ssid'] != params["ssid"]:
|
||||
+ raise Exception("Unexpected SSID")
|
||||
+ # Fronthaul may be something else than WPA2-PSK so don't test it.
|
||||
+
|
||||
+ status = hapd.request("WPS_GET_STATUS")
|
||||
+ if "PBC Status: Disabled" not in status:
|
||||
+ raise Exception("PBC status not shown correctly")
|
||||
+ if "Last WPS result: Success" not in status:
|
||||
+ raise Exception("Last WPS result not shown correctly")
|
||||
+ if "Peer Address: " + dev[1].p2p_interface_addr() not in status:
|
||||
+ raise Exception("Peer address not shown correctly")
|
||||
+
|
||||
+ if len(dev[1].list_networks()) != 1:
|
||||
+ raise Exception("Unexpected number of network blocks")
|
||||
+
|
||||
+
|
||||
+def test_multi_ap_wps_shared(dev, apdev):
|
||||
+ """WPS on shared fronthaul/backhaul AP"""
|
||||
+ ssid = "multi-ap-wps"
|
||||
+ passphrase = "12345678"
|
||||
+ params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
|
||||
+ params.update({"multi_ap": "3",
|
||||
+ "multi_ap_backhaul_ssid": '"%s"' % ssid,
|
||||
+ "multi_ap_backhaul_wpa_passphrase": passphrase})
|
||||
+ run_multi_ap_wps(dev, apdev, params)
|
||||
+
|
||||
+def test_multi_ap_wps_shared_psk(dev, apdev):
|
||||
+ """WPS on shared fronthaul/backhaul AP using PSK"""
|
||||
+ ssid = "multi-ap-wps"
|
||||
+ psk = "1234567890abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
+ params = hostapd.wpa2_params(ssid=ssid)
|
||||
+ params.update({"wpa_psk": psk, "multi_ap": "3",
|
||||
+ "multi_ap_backhaul_ssid": '"%s"' % ssid,
|
||||
+ "multi_ap_backhaul_wpa_psk": psk})
|
||||
+ run_multi_ap_wps(dev, apdev, params)
|
||||
+
|
||||
+def test_multi_ap_wps_split(dev, apdev):
|
||||
+ """WPS on split fronthaul and backhaul AP"""
|
||||
+ backhaul_ssid = "multi-ap-backhaul-wps"
|
||||
+ backhaul_passphrase = "87654321"
|
||||
+ params = hostapd.wpa2_params(ssid="multi-ap-fronthaul-wps", passphrase="12345678")
|
||||
+ params.update({"multi_ap": "2",
|
||||
+ "multi_ap_backhaul_ssid": '"%s"' % backhaul_ssid,
|
||||
+ "multi_ap_backhaul_wpa_passphrase": backhaul_passphrase})
|
||||
+ params_backhaul = hostapd.wpa2_params(ssid=backhaul_ssid, passphrase=backhaul_passphrase)
|
||||
+ params_backhaul.update({"multi_ap": "1"})
|
||||
+ hapd_backhaul = hostapd.add_ap(apdev[1], params_backhaul)
|
||||
+
|
||||
+ run_multi_ap_wps(dev, apdev, params, hapd_backhaul.own_addr())
|
||||
+
|
||||
+def test_multi_ap_wps_split_psk(dev, apdev):
|
||||
+ """WPS on split fronthaul and backhaul AP"""
|
||||
+ backhaul_ssid = "multi-ap-backhaul-wps"
|
||||
+ backhaul_psk = "1234567890abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
+ params = hostapd.wpa2_params(ssid="multi-ap-fronthaul-wps", passphrase="12345678")
|
||||
+ params.update({"multi_ap": "2",
|
||||
+ "multi_ap_backhaul_ssid": '"%s"' % backhaul_ssid,
|
||||
+ "multi_ap_backhaul_wpa_psk": backhaul_psk})
|
||||
+ params_backhaul = hostapd.wpa2_params(ssid=backhaul_ssid)
|
||||
+ params_backhaul.update({"multi_ap": "1", "wpa_psk": backhaul_psk})
|
||||
+ hapd_backhaul = hostapd.add_ap(apdev[1], params_backhaul)
|
||||
+
|
||||
+ run_multi_ap_wps(dev, apdev, params, hapd_backhaul.own_addr())
|
||||
+
|
||||
+def test_multi_ap_wps_split_mixed(dev, apdev):
|
||||
+ """WPS on split fronthaul and backhaul AP with mixed-mode fronthaul"""
|
||||
+ backhaul_ssid = "multi-ap-backhaul-wps"
|
||||
+ backhaul_passphrase = "87654321"
|
||||
+ params = hostapd.wpa_mixed_params(ssid="multi-ap-fronthaul-wps", passphrase="12345678")
|
||||
+ params.update({"multi_ap": "2",
|
||||
+ "multi_ap_backhaul_ssid": '"%s"' % backhaul_ssid,
|
||||
+ "multi_ap_backhaul_wpa_passphrase": backhaul_passphrase})
|
||||
+ params_backhaul = hostapd.wpa2_params(ssid=backhaul_ssid, passphrase=backhaul_passphrase)
|
||||
+ params_backhaul.update({"multi_ap": "1"})
|
||||
+ hapd_backhaul = hostapd.add_ap(apdev[1], params_backhaul)
|
||||
+
|
||||
+ run_multi_ap_wps(dev, apdev, params, hapd_backhaul.own_addr())
|
||||
+
|
||||
+def test_multi_ap_wps_split_open(dev, apdev):
|
||||
+ """WPS on split fronthaul and backhaul AP with open fronthaul"""
|
||||
+ backhaul_ssid = "multi-ap-backhaul-wps"
|
||||
+ backhaul_passphrase = "87654321"
|
||||
+ params = {"ssid": "multi-ap-wps-fronthaul", "multi_ap": "2",
|
||||
+ "multi_ap_backhaul_ssid": '"%s"' % backhaul_ssid,
|
||||
+ "multi_ap_backhaul_wpa_passphrase": backhaul_passphrase}
|
||||
+ params_backhaul = hostapd.wpa2_params(ssid=backhaul_ssid, passphrase=backhaul_passphrase)
|
||||
+ params_backhaul.update({"multi_ap": "1"})
|
||||
+ hapd_backhaul = hostapd.add_ap(apdev[1], params_backhaul)
|
||||
+
|
||||
+ run_multi_ap_wps(dev, apdev, params, hapd_backhaul.own_addr())
|
||||
+
|
||||
+def test_multi_ap_wps_fail_non_multi_ap(dev, apdev):
|
||||
+ """Multi-AP WPS on non-WPS AP fails"""
|
||||
+
|
||||
+ params = hostapd.wpa2_params(ssid="non-multi-ap-wps", passphrase="12345678")
|
||||
+ params.update({"wps_state": "2", "eap_server": "1"})
|
||||
+
|
||||
+ hapd = hostapd.add_ap(apdev[0], params)
|
||||
+ hapd.request("WPS_PBC")
|
||||
+ if "PBC Status: Active" not in hapd.request("WPS_GET_STATUS"):
|
||||
+ raise Exception("PBC status not shown correctly")
|
||||
+
|
||||
+ dev[0].request("WPS_PBC multi_ap=1")
|
||||
+ # Since we will fail to associate and WPS doesn't even get started, there
|
||||
+ # isn't much we can do except wait for timeout. For PBC, it is not possible
|
||||
+ # to change the timeout from 2 minutes. Instead of waiting for the timeout,
|
||||
+ # just check that WPS doesn't finish within reasonable time.
|
||||
+ ev = dev[0].wait_event(["WPS-SUCCESS", "WPS-FAIL"], timeout=20)
|
||||
+ if ev:
|
||||
+ raise Exception("WPS operation completed: " + ev)
|
||||
+ dev[0].request("WPS_CANCEL")
|
@ -92,7 +92,7 @@
|
||||
__func__, driver, drv_priv);
|
||||
--- a/src/ap/ieee802_11.c
|
||||
+++ b/src/ap/ieee802_11.c
|
||||
@@ -1743,12 +1743,13 @@ ieee802_11_set_radius_info(struct hostap
|
||||
@@ -1759,12 +1759,13 @@ ieee802_11_set_radius_info(struct hostap
|
||||
|
||||
|
||||
static void handle_auth(struct hostapd_data *hapd,
|
||||
@ -108,7 +108,7 @@
|
||||
u16 fc;
|
||||
const u8 *challenge = NULL;
|
||||
u32 session_timeout, acct_interim_interval;
|
||||
@@ -1759,6 +1760,11 @@ static void handle_auth(struct hostapd_d
|
||||
@@ -1775,6 +1776,11 @@ static void handle_auth(struct hostapd_d
|
||||
char *identity = NULL;
|
||||
char *radius_cui = NULL;
|
||||
u16 seq_ctrl;
|
||||
@ -120,7 +120,7 @@
|
||||
|
||||
if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
|
||||
wpa_printf(MSG_INFO, "handle_auth - too short payload (len=%lu)",
|
||||
@@ -1919,6 +1925,13 @@ static void handle_auth(struct hostapd_d
|
||||
@@ -1935,6 +1941,13 @@ static void handle_auth(struct hostapd_d
|
||||
resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
goto fail;
|
||||
}
|
||||
@ -134,7 +134,7 @@
|
||||
if (res == HOSTAPD_ACL_PENDING)
|
||||
return;
|
||||
|
||||
@@ -3210,12 +3223,12 @@ void fils_hlp_timeout(void *eloop_ctx, v
|
||||
@@ -3287,12 +3300,12 @@ void fils_hlp_timeout(void *eloop_ctx, v
|
||||
|
||||
static void handle_assoc(struct hostapd_data *hapd,
|
||||
const struct ieee80211_mgmt *mgmt, size_t len,
|
||||
@ -149,7 +149,7 @@
|
||||
struct sta_info *sta;
|
||||
u8 *tmp = NULL;
|
||||
struct hostapd_sta_wpa_psk_short *psk = NULL;
|
||||
@@ -3224,6 +3237,11 @@ static void handle_assoc(struct hostapd_
|
||||
@@ -3301,6 +3314,11 @@ static void handle_assoc(struct hostapd_
|
||||
#ifdef CONFIG_FILS
|
||||
int delay_assoc = 0;
|
||||
#endif /* CONFIG_FILS */
|
||||
@ -161,7 +161,7 @@
|
||||
|
||||
if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_req) :
|
||||
sizeof(mgmt->u.assoc_req))) {
|
||||
@@ -3395,6 +3413,14 @@ static void handle_assoc(struct hostapd_
|
||||
@@ -3472,6 +3490,14 @@ static void handle_assoc(struct hostapd_
|
||||
}
|
||||
#endif /* CONFIG_MBO */
|
||||
|
||||
@ -176,7 +176,7 @@
|
||||
/*
|
||||
* sta->capability is used in check_assoc_ies() for RRM enabled
|
||||
* capability element.
|
||||
@@ -3608,6 +3634,7 @@ static void handle_disassoc(struct hosta
|
||||
@@ -3685,6 +3711,7 @@ static void handle_disassoc(struct hosta
|
||||
wpa_printf(MSG_DEBUG, "disassocation: STA=" MACSTR " reason_code=%d",
|
||||
MAC2STR(mgmt->sa),
|
||||
le_to_host16(mgmt->u.disassoc.reason_code));
|
||||
@ -184,7 +184,7 @@
|
||||
|
||||
sta = ap_get_sta(hapd, mgmt->sa);
|
||||
if (sta == NULL) {
|
||||
@@ -3673,6 +3700,8 @@ static void handle_deauth(struct hostapd
|
||||
@@ -3750,6 +3777,8 @@ static void handle_deauth(struct hostapd
|
||||
" reason_code=%d",
|
||||
MAC2STR(mgmt->sa), le_to_host16(mgmt->u.deauth.reason_code));
|
||||
|
||||
@ -193,7 +193,7 @@
|
||||
sta = ap_get_sta(hapd, mgmt->sa);
|
||||
if (sta == NULL) {
|
||||
wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR " trying "
|
||||
@@ -4000,7 +4029,7 @@ int ieee802_11_mgmt(struct hostapd_data
|
||||
@@ -4077,7 +4106,7 @@ int ieee802_11_mgmt(struct hostapd_data
|
||||
|
||||
|
||||
if (stype == WLAN_FC_STYPE_PROBE_REQ) {
|
||||
@ -202,7 +202,7 @@
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -4020,17 +4049,17 @@ int ieee802_11_mgmt(struct hostapd_data
|
||||
@@ -4097,17 +4126,17 @@ int ieee802_11_mgmt(struct hostapd_data
|
||||
switch (stype) {
|
||||
case WLAN_FC_STYPE_AUTH:
|
||||
wpa_printf(MSG_DEBUG, "mgmt::auth");
|
||||
@ -368,7 +368,7 @@
|
||||
CFLAGS += -DCONFIG_WNM_AP
|
||||
--- a/wpa_supplicant/wpa_supplicant.c
|
||||
+++ b/wpa_supplicant/wpa_supplicant.c
|
||||
@@ -6062,6 +6062,8 @@ struct wpa_supplicant * wpa_supplicant_a
|
||||
@@ -6080,6 +6080,8 @@ struct wpa_supplicant * wpa_supplicant_a
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
@ -377,7 +377,7 @@
|
||||
return wpa_s;
|
||||
}
|
||||
|
||||
@@ -6088,6 +6090,8 @@ int wpa_supplicant_remove_iface(struct w
|
||||
@@ -6106,6 +6108,8 @@ int wpa_supplicant_remove_iface(struct w
|
||||
struct wpa_supplicant *parent = wpa_s->parent;
|
||||
#endif /* CONFIG_MESH */
|
||||
|
||||
|
@ -96,6 +96,15 @@ wpas_bss_get_features(struct ubus_context *ctx, struct ubus_object *obj,
|
||||
}
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
enum {
|
||||
WPS_START_MULTI_AP,
|
||||
__WPS_START_MAX
|
||||
};
|
||||
|
||||
static const struct blobmsg_policy wps_start_policy[] = {
|
||||
[WPS_START_MULTI_AP] = { "multi_ap", BLOBMSG_TYPE_BOOL },
|
||||
};
|
||||
|
||||
static int
|
||||
wpas_bss_wps_start(struct ubus_context *ctx, struct ubus_object *obj,
|
||||
struct ubus_request_data *req, const char *method,
|
||||
@ -103,8 +112,15 @@ wpas_bss_wps_start(struct ubus_context *ctx, struct ubus_object *obj,
|
||||
{
|
||||
int rc;
|
||||
struct wpa_supplicant *wpa_s = get_wpas_from_object(obj);
|
||||
struct blob_attr *tb[__WPS_START_MAX], *cur;
|
||||
int multi_ap = 0;
|
||||
|
||||
rc = wpas_wps_start_pbc(wpa_s, NULL, 0);
|
||||
blobmsg_parse(wps_start_policy, __WPS_START_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg));
|
||||
|
||||
if (tb[WPS_START_MULTI_AP])
|
||||
multi_ap = blobmsg_get_bool(tb[WPS_START_MULTI_AP]);
|
||||
|
||||
rc = wpas_wps_start_pbc(wpa_s, NULL, 0, multi_ap);
|
||||
|
||||
if (rc != 0)
|
||||
return UBUS_STATUS_NOT_SUPPORTED;
|
||||
|
Loading…
x
Reference in New Issue
Block a user