From patchwork Wed Dec 5 10:24:00 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnout Vandecappelle X-Patchwork-Id: 1008154 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=mind.be Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="ZSKiOO3n"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=mind-be.20150623.gappssmtp.com header.i=@mind-be.20150623.gappssmtp.com header.b="r/l+MpW8"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 438w1D5dyCz9s8F for ; Wed, 5 Dec 2018 21:28:16 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=k2NwIY/1ank0kzJ/iGR6WxeOHnGAPicvA7WNUgaJDIE=; b=ZSKiOO3nuuFFhr JG1eZEMLKwGQgFvHa04t4a3mQNCfakqqG5T+f/eXsGFkDRz1sX3p/ho+oAIvAtel6l4+zgmhuHNiN mNTRXSPuEi6QGEZkv/lz2jRPDsY/Sum+6IicLT18MM2qmqr+h8KRXLQTUA8P4Ix7gUzlyOUrbcaMB RuaVoD8fTzcsq5w0JgTsYNzX87zFog3bVLv9EGTE4w/PRZxUyhblPBsi3di4r8ONOeOWtVo4uKHbs rLQlwIHWKyKPHJ8eZKTCB0JmEnZNb+H0LoJG7Ga0FmybA5Q1ZzcjcjjgOGfK/+LalVouSUSdq36J6 hP6T4SBvhH6fyVkm9hIQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gUUPT-0007PM-AU; Wed, 05 Dec 2018 10:28:03 +0000 Received: from mail-ed1-x542.google.com ([2a00:1450:4864:20::542]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1gUUOi-0006QT-5b for hostap@lists.infradead.org; Wed, 05 Dec 2018 10:27:20 +0000 Received: by mail-ed1-x542.google.com with SMTP id z28so16532765edi.8 for ; Wed, 05 Dec 2018 02:27:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mind-be.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=59fwh+YZyFbiZ7jEAUgpD2ir3Ym5rIe1mH/MRTqOpQA=; b=r/l+MpW8xcBcak2jaEkwWLeqzOovEpKANQxw2ZqRcz6pIRz4TwVAON0dnfEu5JYpyS ogVLniJB8GQ6QJz+M/FKarBL+LmpfVglo4i9E0xM1GqEY3WfU5B5MadAvXCr4qvDF2kD wqokyBKZ64O8JkZCaR7rRx/whPJ5xe4crim9zysANkIUMXJ3jifcpHS2zIHzyD7lEVRh OVciHF5upTu31HT4UpLcajQdMMQBX1sY+Ju+ZLQwBAT6GeIQpAb04fO904tGsn/CxZN4 w8GvsXzoMUW0YAF154BBa+MZmKlmiDlrP9hfjx/5zE6gRCxe8yLgzu87+M5t4LMcf+en fjMQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=59fwh+YZyFbiZ7jEAUgpD2ir3Ym5rIe1mH/MRTqOpQA=; b=UYVwiO7kmOA37qqmOCRrnw11Vv7qZae+goGOPM6EV2YJNd7wM1KxwsLw2PBhdpVVha ErhsDfLKIacsSe9vISqVHgsB0oCtFj49CwXWAMuhIzyHk68v5CtrPl5DEqc8DcXFvySx gT95L2UbH9QKVthN77gur2vk/POOtAfiW84LbVRVW6Md3FEdJYtmWzNPOoYNXjqxfibH KWyBFgBA1SPwFHxDyJrntW7T+yF8phSf8GN2XCMHy70MlcZ7iR+9lW4AxkGC9/VFL9q8 QJl7PIG3gzMdT0diiEUdioyI7Xa6Zs+moDEkPkzS7lB0kbR653PnlU05JZHlK/iwvHOs nMTQ== X-Gm-Message-State: AA+aEWaVzeSsjXa7pnlp4dCxeEw8X2oBFr7T9rj6Uzsr0Gs9s0GPHMVx GOSF0h6LbVHz9xQWv0/5DFwJU/Yxmpo= X-Google-Smtp-Source: AFSGD/XU9aMfmMCMi18wdvJwnb1xXY8rtpA/IykXCOUrT8dLc448eAHO1F59W9JQfAKCRXmSVIx1iw== X-Received: by 2002:a50:b1db:: with SMTP id n27mr21506722edd.65.1544005624088; Wed, 05 Dec 2018 02:27:04 -0800 (PST) Received: from localhost.localdomain (ip-188-118-3-185.reverse.destiny.be. [188.118.3.185]) by smtp.gmail.com with ESMTPSA id z2sm5438020edd.4.2018.12.05.02.27.03 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Wed, 05 Dec 2018 02:27:03 -0800 (PST) From: "Arnout Vandecappelle (Essensium/Mind)" To: hostap@lists.infradead.org Subject: [PATCH v3 10/12] wpa_supplicant: support Multi-AP backhaul STA onboarding Date: Wed, 5 Dec 2018 11:24:00 +0100 Message-Id: <20181205102401.17810-11-arnout@mind.be> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20181205102401.17810-1-arnout@mind.be> References: <20181205102401.17810-1-arnout@mind.be> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181205_022716_524222_1A5E5D2E X-CRM114-Status: GOOD ( 20.03 ) X-Spam-Score: 1.0 (+) X-Spam-Report: SpamAssassin version 3.4.2 on bombadil.infradead.org summary: Content analysis details: (1.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [2a00:1450:4864:20:0:0:0:542 listed in] [list.dnswl.org] 1.0 SPF_SOFTFAIL SPF: sender does not match SPF record (softfail) 0.0 HEADER_FROM_DIFFERENT_DOMAINS From and EnvelopeFrom 2nd level mail domains are different -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid 0.0 DKIMWL_WL_MED DKIMwl.org - Whitelisted Medium sender X-BeenThere: hostap@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Igor Mitsyanko , Arnout Vandecappelle , Davina Lu Sender: "Hostap" Errors-To: hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Davina Lu 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, global configuration option multi_ap_backhaul_sta to enable this feature. It has to be separate from the per-SSID multi_ap_backhaul_sta option since no SSID exists yet when WPS is performed. 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. Extend wps_build_wfa_ext() with an extra argument to add the additional subelement to a WPS message, and use this when building M1. 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. Signed-off-by: Davina Lu Signed-off-by: Igor Mitsyanko Signed-off-by: Arnout Vandecappelle (Essensium/Mind) --- src/p2p/p2p_build.c | 2 +- src/wps/wps.c | 6 +++--- src/wps/wps.h | 6 ++++++ src/wps/wps_attr_build.c | 10 +++++++++- src/wps/wps_common.c | 16 ++++++++-------- src/wps/wps_defs.h | 3 ++- src/wps/wps_enrollee.c | 14 +++++++++----- src/wps/wps_er.c | 4 ++-- src/wps/wps_i.h | 3 ++- src/wps/wps_registrar.c | 14 +++++++------- src/wps/wps_upnp.c | 2 +- wpa_supplicant/config.c | 1 + wpa_supplicant/config.h | 2 ++ wpa_supplicant/config_file.c | 4 ++++ wpa_supplicant/wpa_supplicant.conf | 5 +++++ wpa_supplicant/wps_supplicant.c | 13 ++++++++++++- 16 files changed, 74 insertions(+), 31 deletions(-) diff --git a/src/p2p/p2p_build.c b/src/p2p/p2p_build.c index 2882c6ad0..63eb2e84c 100644 --- a/src/p2p/p2p_build.c +++ b/src/p2p/p2p_build.c @@ -802,7 +802,7 @@ int p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, int pw_id, 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) { diff --git a/src/wps/wps.c b/src/wps/wps.c index 8d228270f..c162e793d 100644 --- a/src/wps/wps.c +++ b/src/wps/wps.c @@ -430,7 +430,7 @@ struct wpabuf * wps_build_assoc_req_ie(enum wps_request_type req_type) 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(void) 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(u16 pw_id, struct wps_device_data *dev, 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) diff --git a/src/wps/wps.h b/src/wps/wps.h index 2505d2d9f..129f27ab4 100644 --- a/src/wps/wps.h +++ b/src/wps/wps.h @@ -612,6 +612,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 */ diff --git a/src/wps/wps_attr_build.c b/src/wps/wps_attr_build.c index 770f5e90c..22b33e8c3 100644 --- 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,13 @@ int wps_build_wfa_ext(struct wpabuf *msg, int req_to_enroll, 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 diff --git a/src/wps/wps_common.c b/src/wps/wps_common.c index bcae1ba58..747dc4710 100644 --- a/src/wps/wps_common.c +++ b/src/wps/wps_common.c @@ -374,7 +374,7 @@ struct wpabuf * wps_get_oob_cred(struct wps_context *wps, int rf_band, (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(u16 dev_pw_id, 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_data *wps) 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(struct wps_data *wps) 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_req(struct wps_context *ctx, 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_sel(struct wps_context *ctx, 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_req_p2p(struct wps_context *ctx, 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_sel_p2p(struct wps_context *ctx, 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; } diff --git a/src/wps/wps_defs.h b/src/wps/wps_defs.h index 301864da4..9fccb4eeb 100644 --- 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 */ diff --git a/src/wps/wps_enrollee.c b/src/wps/wps_enrollee.c index 417507740..e175770f1 100644 --- a/src/wps/wps_enrollee.c +++ b/src/wps/wps_enrollee.c @@ -105,6 +105,7 @@ static struct wpabuf * wps_build_m1(struct wps_data *wps) { 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(struct wps_data *wps) 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(struct wps_data *wps) 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, multi_ap_backhaul_sta) || wps_build_vendor_ext_m1(&wps->wps->dev, msg)) { wpabuf_free(msg); return NULL; @@ -190,7 +194,7 @@ static struct wpabuf * wps_build_m3(struct wps_data *wps) 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 +227,7 @@ static struct wpabuf * wps_build_m5(struct wps_data *wps) 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 +397,7 @@ static struct wpabuf * wps_build_m7(struct wps_data *wps) (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 +434,7 @@ static struct wpabuf * wps_build_wsc_done(struct wps_data *wps) 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; } diff --git a/src/wps/wps_er.c b/src/wps/wps_er.c index affd6a4af..06a8fdaf3 100644 --- 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 *er, int sel_reg, u16 dev_passwd_id, 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_cred(struct wps_context *wps, 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; } diff --git a/src/wps/wps_i.h b/src/wps/wps_i.h index fe0c60bd1..7972fc225 100644 --- a/src/wps/wps_i.h +++ b/src/wps/wps_i.h @@ -163,7 +163,8 @@ int wps_build_encr_settings(struct wps_data *wps, struct wpabuf *msg, 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); diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c index 379925e3f..b5ac29bea 100644 --- a/src/wps/wps_registrar.c +++ b/src/wps/wps_registrar.c @@ -1281,7 +1281,7 @@ static int wps_set_ie(struct wps_registrar *reg) 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_registrar *reg) 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(struct wps_data *wps) 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(struct wps_data *wps) 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(struct wps_data *wps) 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(struct wps_data *wps) 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(struct wps_data *wps) (!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); diff --git a/src/wps/wps_upnp.c b/src/wps/wps_upnp.c index 0c458c6ad..ca893a43c 100644 --- a/src/wps/wps_upnp.c +++ b/src/wps/wps_upnp.c @@ -599,7 +599,7 @@ static struct wpabuf * build_fake_wsc_ack(void) 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; } diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 4ff93f62f..6cbc21fd8 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -4652,6 +4652,7 @@ static const struct global_parse_data global_fields[] = { { STR(config_methods), CFG_CHANGED_CONFIG_METHODS }, { INT_RANGE(wps_cred_processing, 0, 2), 0 }, { FUNC(wps_vendor_ext_m1), CFG_CHANGED_VENDOR_EXTENSION }, + { INT_RANGE(multi_ap_backhaul_sta, 0, 1), CFG_CHANGED_MULTI_AP_BACKHAUL_STA }, #endif /* CONFIG_WPS */ #ifdef CONFIG_P2P { FUNC(sec_device_type), CFG_CHANGED_SEC_DEVICE_TYPE }, diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index cd7571f59..c8857016f 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -374,6 +374,7 @@ struct wpa_cred { #define CFG_CHANGED_P2P_PASSPHRASE_LEN BIT(16) #define CFG_CHANGED_SCHED_SCAN_PLANS BIT(17) #define CFG_CHANGED_WOWLAN_TRIGGERS BIT(18) +#define CFG_CHANGED_MULTI_AP_BACKHAUL_STA BIT(19) /** * struct wpa_config - wpa_supplicant configuration data @@ -768,6 +769,7 @@ struct wpa_config { int p2p_optimize_listen_chan; struct wpabuf *wps_vendor_ext_m1; + int multi_ap_backhaul_sta; #define MAX_WPS_VENDOR_EXT 10 /** diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index 09115e19d..e78f273b1 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -1183,6 +1183,10 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config) fprintf(f, "\n"); } } + + if (config->multi_ap_backhaul_sta) + fprintf(f, "multi_ap_backhaul_sta=%d\n", config->multi_ap_backhaul_sta); + #endif /* CONFIG_WPS */ #ifdef CONFIG_P2P { diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index e5dee2236..d22f76664 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -286,6 +286,11 @@ fast_reauth=1 # The vendor attribute contents to be added in M1 (hex string) #wps_vendor_ext_m1=000137100100020001 +# Multi-AP STA config +# When set to 1, the Multi-AP vendor extension is added to WPS M1 and the +# Multi-AP IE is sent to the driver for inclusion in association request frames. +#multi_ap_backhaul_sta=1 + # NFC password token for WPS # These parameters can be used to configure a fixed NFC password token for the # station. This can be generated, e.g., with nfc_pw_token. When these diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c index 1a2677b8e..de3943912 100644 --- a/wpa_supplicant/wps_supplicant.c +++ b/wpa_supplicant/wps_supplicant.c @@ -473,6 +473,11 @@ static int wpa_supplicant_wps_cred(void *ctx, wpa_config_set_network_defaults(ssid); ssid->wps_run = wpa_s->wps_run; + if (wpa_s->conf->multi_ap_backhaul_sta) + ssid->multi_ap_backhaul_sta = 1; + else + ssid->multi_ap_backhaul_sta = 0; + os_free(ssid->ssid); ssid->ssid = os_malloc(cred->ssid_len); if (ssid->ssid) { @@ -1181,6 +1186,8 @@ int wpas_wps_start_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid, return -1; if (wpa_s->wps_fragment_size) ssid->eap.fragment_size = wpa_s->wps_fragment_size; + if (wpa_s->conf->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); @@ -1527,7 +1534,6 @@ static void wpas_wps_set_vendor_ext_m1(struct wpa_supplicant *wpa_s, } } - int wpas_wps_init(struct wpa_supplicant *wpa_s) { struct wps_context *wps; @@ -1569,6 +1575,8 @@ int wpas_wps_init(struct wpa_supplicant *wpa_s) wpas_wps_set_vendor_ext_m1(wpa_s, wps); + wps->multi_ap_backhaul_sta = wpa_s->conf->multi_ap_backhaul_sta; + wps->dev.os_version = WPA_GET_BE32(wpa_s->conf->os_version); modes = wpa_s->hw.modes; if (modes) { @@ -2205,6 +2213,9 @@ void wpas_wps_update_config(struct wpa_supplicant *wpa_s) if (wpa_s->conf->changed_parameters & CFG_CHANGED_VENDOR_EXTENSION) wpas_wps_set_vendor_ext_m1(wpa_s, wps); + if (wpa_s->conf->changed_parameters & CFG_CHANGED_MULTI_AP_BACKHAUL_STA) + wps->multi_ap_backhaul_sta = wpa_s->conf->multi_ap_backhaul_sta; + if (wpa_s->conf->changed_parameters & CFG_CHANGED_OS_VERSION) wps->dev.os_version = WPA_GET_BE32(wpa_s->conf->os_version);