From patchwork Fri Jul 19 04:39:58 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shivani Baranwal X-Patchwork-Id: 1962292 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; secure) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20210309 header.b=u0yhV7rV; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=quicinc.com header.i=@quicinc.com header.a=rsa-sha256 header.s=qcppdkim1 header.b=J9A/eloy; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:3::133; helo=bombadil.infradead.org; envelope-from=hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=patchwork.ozlabs.org) Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:3::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WQH7k1Rj2z20Mw for ; Fri, 19 Jul 2024 14:41:38 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=oOV9gs0m0LBex25o1klAiAZl5IvnrFsBByXlNStUAw0=; b=u0yhV7rVYl6kpt tLraezAzxsG8AbvzIrMOGKaXugdsfAh63ZrQH1eU6x+6FGDw19g67CLyJSlpAUObOlAdL3Q1kIuSu jtFcp3+BzLH+PC99oskCIxT3bywXZy3JODUkOzioiBlfaU13iB7JpCllRVuauaZ+IaScDQ/G2mS/f 0OzS+OCCDf0EN5e8qZuQIqS+dWzX2V/F03X02bL/O4TtjgGEKycSEpTW18dFvW44hsOByl9wGnZiq hpDAkzospxjYovGUrQimZJ2KRFrPOaCe8WM/SjDm/4eRwbbokKSSMdX8gBiLd7vVl6qRGEI4t2NvP bRHVwUb6H7p/Rd1PnTDQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1sUfQj-00000001XRp-03e9; Fri, 19 Jul 2024 04:41:17 +0000 Received: from mx0b-0031df01.pphosted.com ([205.220.180.131]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sUfQS-00000001XJR-3cjc for hostap@lists.infradead.org; Fri, 19 Jul 2024 04:41:04 +0000 Received: from pps.filterd (m0279868.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 46J0x0Tg017260 for ; Fri, 19 Jul 2024 04:41:00 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-type:date:from:in-reply-to:message-id:mime-version :references:subject:to; s=qcppdkim1; bh=kEvHr4Bhzasj/izXNzOMXjvZ hTpruASjkf0v4g60q98=; b=J9A/eloydCoNvqF8T/L+DYFOTf+GWPLl5M3skVT2 Ez4eNLvU0FNG9jhayOgLRoIgB9XTxduK2T9gLxQNfyMeQ1m3/s/K+nKMAw6eZ7FP 0587+PDWfDFX4YTpgGS73jmULDFA2zsJOrQ3GT8GXurOn7yBs+zAOno1iGpqAa9n oOrsQCCV7Nhh3pwd67fiM3QOsu3Ue1xkiStwYrwuJoy8u67AQyDQENW6MOnLV8YZ HBNiJxdvJYhtist3lCMLTj9uPG726slU05XrrvOaju2OQiyL6HbifmKU9n7VTNnp E8JnYQJSTYyyGSaFITdU25eDEM1Qz9HJ4nFLMup1Ztoxnw== Received: from nalasppmta03.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 40fe2y0bx3-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Fri, 19 Jul 2024 04:40:59 +0000 (GMT) Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA03.qualcomm.com (8.17.1.19/8.17.1.19) with ESMTPS id 46J4ewjg024873 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Fri, 19 Jul 2024 04:40:58 GMT Received: from hu-shivbara-hyd.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Thu, 18 Jul 2024 21:40:57 -0700 From: Shivani Baranwal To: CC: Subject: [PATCH v2 06/14] P2P: Add bootstrapping support with pd frames Date: Fri, 19 Jul 2024 10:09:58 +0530 Message-ID: <1721364006-21658-7-git-send-email-quic_shivbara@quicinc.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1721364006-21658-1-git-send-email-quic_shivbara@quicinc.com> References: <1721364006-21658-1-git-send-email-quic_shivbara@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To nalasex01a.na.qualcomm.com (10.47.209.196) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: l8-EABpluBchK8F-OcufMtPvqPD8L_2_ X-Proofpoint-ORIG-GUID: l8-EABpluBchK8F-OcufMtPvqPD8L_2_ X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.28.16 definitions=2024-07-19_01,2024-07-18_01,2024-05-17_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 clxscore=1015 impostorscore=0 bulkscore=0 mlxscore=0 adultscore=0 phishscore=0 spamscore=0 mlxlogscore=999 lowpriorityscore=0 suspectscore=0 malwarescore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2407110000 definitions=main-2407190035 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240718_214101_175757_A0BB4A8A X-CRM114-Status: GOOD ( 28.46 ) X-Spam-Score: -2.1 (--) X-Spam-Report: Spam detection software, running on the system "bombadil.infradead.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Add support for p2p2 bootstrapping with comeback mechanism using provision discovery frames. Add control iface to extend p2p_connect to allow p2p2 bootstrapping handshake Signed-off-by: Shivani Baranwal --- src/common/ieee802_11_defs.h | 16 ++ src/p2p/p2p.c | 28 ++- src/p2p/p2p.h | 30 ++- src/p2p/p2p_build.c | 4 +- src/p2p/p2p_go_neg.c | 2 + [...] Content analysis details: (-2.1 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -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 -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] X-BeenThere: hostap@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Hostap" Errors-To: hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org Add support for p2p2 bootstrapping with comeback mechanism using provision discovery frames. Add control iface to extend p2p_connect to allow p2p2 bootstrapping handshake Signed-off-by: Shivani Baranwal --- src/common/ieee802_11_defs.h | 16 ++ src/p2p/p2p.c | 28 ++- src/p2p/p2p.h | 30 ++- src/p2p/p2p_build.c | 4 +- src/p2p/p2p_go_neg.c | 2 + src/p2p/p2p_i.h | 40 ++- src/p2p/p2p_pd.c | 363 +++++++++++++++++++++++++++- wpa_supplicant/ctrl_iface.c | 28 ++- wpa_supplicant/dbus/dbus_new_handlers_p2p.c | 2 +- wpa_supplicant/p2p_supplicant.c | 78 +++++- wpa_supplicant/p2p_supplicant.h | 3 +- wpa_supplicant/wpa_supplicant_i.h | 3 + 12 files changed, 563 insertions(+), 34 deletions(-) diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 0549535..ee45b12 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -1785,6 +1785,21 @@ enum p2p_attr_id { #define P2P_PCEA_PASN_TYPE BIT(11) #define P2P_PCEA_TWT_POWER_MGMT BIT(12) + +/* P2P Pairing Bootstrapping Method attribute - Bootstrapping Method */ +#define P2P_PBMA_OPPORTUNISTIC BIT(0) +#define P2P_PBMA_PIN_CODE_DISPLAY BIT(1) +#define P2P_PBMA_PASSPHRASE_DISPLAY BIT(2) +#define P2P_PBMA_QR_DISPLAY BIT(3) +#define P2P_PBMA_NFC_TAG BIT(4) +#define P2P_PBMA_PIN_CODE_KEYPAD BIT(5) +#define P2P_PBMA_PASSPHRASE_KEYPAD BIT(6) +#define P2P_PBMA_QR_SCAN BIT(7) +#define P2P_PBMA_NFC_READER BIT(8) +#define P2P_PBMA_SERVICE_MANAGED BIT(14) +#define P2P_PBMA_HANDSHAKE_SHIP BIT(15) + + /* P2PS Coordination Protocol Transport Bitmap */ #define P2PS_FEATURE_CAPAB_UDP_TRANSPORT BIT(0) #define P2PS_FEATURE_CAPAB_MAC_TRANSPORT BIT(1) @@ -1816,6 +1831,7 @@ enum p2p_status_code { P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD = 10, P2P_SC_FAIL_REJECTED_BY_USER = 11, P2P_SC_SUCCESS_DEFERRED = 12, + P2P_SC_COMEBACK = 13, }; enum p2p_role_indication { diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index 0a5c35f..980b4da 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -955,6 +955,11 @@ static void p2p_device_free(struct p2p_data *p2p, struct p2p_device *dev) dev->info.wps_vendor_ext[i] = NULL; } + if (dev->bootstrap_params) { + os_free(dev->bootstrap_params); + dev->bootstrap_params = NULL; + } + wpabuf_free(dev->info.wfd_subelems); wpabuf_free(dev->info.vendor_elems); wpabuf_free(dev->go_neg_conf); @@ -1600,7 +1605,8 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr, int go_intent, const u8 *own_interface_addr, unsigned int force_freq, int persistent_group, const u8 *force_ssid, size_t force_ssid_len, - int pd_before_go_neg, unsigned int pref_freq, u16 oob_pw_id) + int pd_before_go_neg, unsigned int pref_freq, u16 oob_pw_id, + bool p2p2, u16 bootstrap, const char *password) { struct p2p_device *dev; @@ -1684,6 +1690,12 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr, dev->wps_method = wps_method; dev->oob_pw_id = oob_pw_id; + dev->p2p2 = p2p2; + dev->req_bootstrap_method = bootstrap; + if (password) { + strcpy(dev->password, password); + dev->password_len = strlen(password); + } dev->status = P2P_SC_SUCCESS; if (p2p->p2p_scan_running) { @@ -1702,7 +1714,8 @@ int p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr, int go_intent, const u8 *own_interface_addr, unsigned int force_freq, int persistent_group, const u8 *force_ssid, size_t force_ssid_len, - unsigned int pref_freq, u16 oob_pw_id) + unsigned int pref_freq, u16 oob_pw_id, u16 bootstrap, + const char *password) { struct p2p_device *dev; @@ -1736,6 +1749,12 @@ int p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr, dev->flags &= ~P2P_DEV_USER_REJECTED; dev->go_neg_req_sent = 0; dev->go_state = UNKNOWN_GO; + dev->req_bootstrap_method = bootstrap; + + if (password) { + strcpy(dev->password, password); + dev->password_len = strlen(password); + } p2p_set_dev_persistent(dev, persistent_group); p2p->go_intent = go_intent; os_memcpy(p2p->intended_addr, own_interface_addr, ETH_ALEN); @@ -1928,7 +1947,7 @@ static void p2p_rx_p2p_action(struct p2p_data *p2p, const u8 *sa, p2p_handle_prov_disc_req(p2p, sa, data + 1, len - 1, rx_freq); break; case P2P_PROV_DISC_RESP: - p2p_handle_prov_disc_resp(p2p, sa, data + 1, len - 1); + p2p_handle_prov_disc_resp(p2p, sa, data + 1, len - 1, rx_freq); break; case P2P_DEV_DISC_REQ: p2p_process_dev_disc_req(p2p, sa, data + 1, len - 1, rx_freq); @@ -3437,7 +3456,7 @@ static void p2p_retry_pd(struct p2p_data *p2p) if (!ether_addr_equal(p2p->pending_pd_devaddr, dev->info.p2p_device_addr)) continue; - if (!dev->req_config_methods) + if (!dev->req_config_methods && !dev->req_bootstrap_method) continue; p2p_dbg(p2p, "Send pending Provision Discovery Request to " @@ -5801,6 +5820,7 @@ void p2p_process_usd_elems(struct p2p_data *p2p, const u8 *ies, u16 ies_len, return; } + dev->p2p2 = true; /* Reset info from old IEs */ dev->info.reg_info = 0; memset(&dev->info.pairing_config, 0, sizeof(struct p2p_pairing_config)); diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index 8e46506..1fbd93d 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -659,6 +659,13 @@ struct p2p_config { bool twt_power_mgmt; /** + * comeback_after - Bootstrap request unauthorised for peer, + * ask to comeback after given time in ms + */ + u16 comeback_after; + + + /** * cb_ctx - Context to use with callback functions */ void *cb_ctx; @@ -1205,6 +1212,19 @@ struct p2p_config { int (*get_pref_freq_list)(void *ctx, int go, unsigned int *len, struct weighted_pcl *freq_list); + + /** + * register_bootstrap_comeback - register timeout to initiate bootstrap + * comeback request + * @ctx: Callback context from cb_ctx + * @addr: p2p device address to which comeback request to be sent + * @comeback_after: time in ms after which comeback request is sent + * + * This function can be used to send comeback request after given + * timeout. + */ + void (*register_bootstrap_comeback)(void *ctx, const u8 *addr, + u16 comeback_after); }; @@ -1388,6 +1408,10 @@ void p2p_stop_listen(struct p2p_data *p2p); * formation * @pref_freq: Preferred operating frequency in MHz or 0 (this is only used if * force_freq == 0) + * @oob_pw_id: oob password identifier + * @p2p2: Device supports p2p2 features + * @bootstrap: Bootstrapping method requested for p2p2 provision discovery + * @password: p2p2 pairing password or NULL for opportunistic method * Returns: 0 on success, -1 on failure */ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr, @@ -1395,7 +1419,8 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr, int go_intent, const u8 *own_interface_addr, unsigned int force_freq, int persistent_group, const u8 *force_ssid, size_t force_ssid_len, - int pd_before_go_neg, unsigned int pref_freq, u16 oob_pw_id); + int pd_before_go_neg, unsigned int pref_freq, u16 oob_pw_id, + bool p2p2, u16 bootstrap, const char *password); /** * p2p_authorize - Authorize P2P group formation (GO negotiation) @@ -1423,7 +1448,8 @@ int p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr, int go_intent, const u8 *own_interface_addr, unsigned int force_freq, int persistent_group, const u8 *force_ssid, size_t force_ssid_len, - unsigned int pref_freq, u16 oob_pw_id); + unsigned int pref_freq, u16 oob_pw_id, u16 bootstrap, + const char *password); /** * p2p_reject - Reject peer device (explicitly block connection attempts) diff --git a/src/p2p/p2p_build.c b/src/p2p/p2p_build.c index 92bcc6b..980db05 100644 --- a/src/p2p/p2p_build.c +++ b/src/p2p/p2p_build.c @@ -784,9 +784,6 @@ void p2p_buf_add_pbma(struct wpabuf *buf, u16 bootstrap, const u8 *cookie, { u8 *len; - if (!bootstrap) - return; - /* P2P Pairing and Bootstrapping methods */ wpabuf_put_u8(buf, P2P_ATTR_PAIRING_AND_BOOTSTRAPPING); /* Length to be filled */ @@ -798,6 +795,7 @@ void p2p_buf_add_pbma(struct wpabuf *buf, u16 bootstrap, const u8 *cookie, wpabuf_put_u8(buf, cookie_len); wpabuf_put_data(buf, cookie, cookie_len); } + wpabuf_put_le16(buf, bootstrap); /* Update attribute length */ diff --git a/src/p2p/p2p_go_neg.c b/src/p2p/p2p_go_neg.c index 30901b3..04e5139 100644 --- a/src/p2p/p2p_go_neg.c +++ b/src/p2p/p2p_go_neg.c @@ -244,6 +244,8 @@ int p2p_connect_send(struct p2p_data *p2p, struct p2p_device *dev) config_method = WPS_CONFIG_PUSHBUTTON; else if (dev->wps_method == WPS_P2PS) config_method = WPS_CONFIG_P2PS; + else if (dev->p2p2 && dev->req_bootstrap_method) + config_method = WPS_NOT_READY; else return -1; return p2p_prov_disc_req(p2p, dev->info.p2p_device_addr, diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h index 2b10877..5463f4b 100644 --- a/src/p2p/p2p_i.h +++ b/src/p2p/p2p_i.h @@ -41,6 +41,28 @@ enum p2p_go_state { REMOTE_GO }; + +/** + * struct bootstrap_params - P2P Device bootstrap request params + */ + +struct p2p_bootstrap_params { + /* bootstrap method */ + u16 bootstrap_method; + + /* status code */ + enum p2p_status_code status; + + /* cookie for comeback */ + u8 cookie[50]; + + /* cookie length */ + size_t cookie_len; + + /* Comeback time in TUs after which receiver is requested to retry */ + int comeback_after; +}; + /** * struct p2p_device - P2P Device data (internal to P2P module) */ @@ -155,6 +177,22 @@ struct p2p_device { int sd_pending_bcast_queries; bool support_6ghz; + + /* support p2p2 */ + bool p2p2; + + /* requested bootstrap method */ + u16 req_bootstrap_method; + + /* bootstrap params received from peer */ + struct p2p_bootstrap_params *bootstrap_params; + + /* password for p2p2 go negotiation */ + char password[100]; + /** + * password length. Non zero if valid + */ + u16 password_len; }; struct p2p_sd_query { @@ -887,7 +925,7 @@ void p2p_check_pref_chan(struct p2p_data *p2p, int go, void p2p_handle_prov_disc_req(struct p2p_data *p2p, const u8 *sa, const u8 *data, size_t len, int rx_freq); void p2p_handle_prov_disc_resp(struct p2p_data *p2p, const u8 *sa, - const u8 *data, size_t len); + const u8 *data, size_t len, int rx_freq); int p2p_send_prov_disc_req(struct p2p_data *p2p, struct p2p_device *dev, int join, int force_freq); void p2p_reset_pending_pd(struct p2p_data *p2p); diff --git a/src/p2p/p2p_pd.c b/src/p2p/p2p_pd.c index 23bba08..f0ba601 100644 --- a/src/p2p/p2p_pd.c +++ b/src/p2p/p2p_pd.c @@ -14,6 +14,7 @@ #include "wps/wps_defs.h" #include "p2p_i.h" #include "p2p.h" +#include "crypto/random.h" /* @@ -180,6 +181,61 @@ static void p2ps_add_pd_req_attrs(struct p2p_data *p2p, struct p2p_device *dev, } } +static struct wpabuf * p2p_build_prov_disc_bootstrap_req(struct p2p_data *p2p, + struct p2p_device *dev) +{ + struct wpabuf *buf; + u8 *len; + size_t cookie_len = 0; + const u8 *cookie = NULL; + u8 dialog_token = dev->dialog_token; + u8 group_capab; + + buf = wpabuf_alloc(1000); + if (buf == NULL) + return NULL; + + p2p_buf_add_public_action_hdr(buf, P2P_PROV_DISC_REQ, dialog_token); + + len = p2p_buf_add_ie_hdr(buf); + + group_capab = 0; + + if (p2p->num_groups) { + group_capab |= P2P_GROUP_CAPAB_GROUP_OWNER; + if ((p2p->dev_capab & P2P_DEV_CAPAB_CONCURRENT_OPER) && + (p2p->dev_capab & P2P_DEV_CAPAB_INFRA_MANAGED) && + p2p->cross_connect) + group_capab |= P2P_GROUP_CAPAB_CROSS_CONN; + } + if (p2p->cfg->p2p_intra_bss) + group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST; + + p2p_buf_add_capability(buf, p2p->dev_capab & + ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY, + group_capab); + p2p_buf_add_device_info(buf, p2p, NULL); + + if (dev->bootstrap_params) { + cookie = dev->bootstrap_params->cookie; + cookie_len = dev->bootstrap_params->cookie_len; + + if (dev->bootstrap_params->status == P2P_SC_COMEBACK) + p2p_buf_add_status(buf, dev->bootstrap_params->status); + } + + p2p_buf_update_ie_hdr(buf, len); + + len = p2p_buf_add_p2p2_ie_hdr(buf); + + p2p_buf_add_pcea(buf, p2p); + p2p_buf_add_pbma(buf, dev->req_bootstrap_method, cookie, cookie_len, 0); + + p2p_buf_update_p2p2_ie_hdr(buf, len); + + wpa_printf(MSG_DEBUG, "P2P2: Added PCEA and PBMA in PD req"); + return buf; +} static struct wpabuf * p2p_build_prov_disc_req(struct p2p_data *p2p, struct p2p_device *dev, @@ -248,6 +304,39 @@ static struct wpabuf * p2p_build_prov_disc_req(struct p2p_data *p2p, return buf; } +static struct wpabuf * p2p_build_prov_disc_bootstrap_resp(struct p2p_data *p2p, + struct p2p_device *dev, + u8 dialog_token, + enum p2p_status_code status) +{ + struct wpabuf *buf; + u8 *cookie = NULL; + size_t cookie_len = 0; + int comeback_after = 0; + + buf = wpabuf_alloc(1000); + if (!buf) + return NULL; + + if (status == P2P_SC_COMEBACK && dev->bootstrap_params) { + cookie = dev->bootstrap_params->cookie; + cookie_len = dev->bootstrap_params->cookie_len; + comeback_after = dev->bootstrap_params->comeback_after; + } + + p2p_buf_add_public_action_hdr(buf, P2P_PROV_DISC_RESP, dialog_token); + + u8 *len = p2p_buf_add_p2p2_ie_hdr(buf); + + p2p_buf_add_status(buf, status); + p2p_buf_add_pcea(buf, p2p); + p2p_buf_add_pbma(buf, dev->req_bootstrap_method, cookie, cookie_len, + comeback_after); + + p2p_buf_update_p2p2_ie_hdr(buf, len); + + return buf; +} static struct wpabuf * p2p_build_prov_disc_resp(struct p2p_data *p2p, struct p2p_device *dev, @@ -600,6 +689,159 @@ void p2p_process_pcea(struct p2p_data *p2p, struct p2p_message *msg, } +static void p2p_process_prov_disc_bootstrap_req(struct p2p_data *p2p, + struct p2p_message *msg, + const u8 *sa, const u8 *data, + size_t len, int rx_freq) +{ + struct p2p_device *dev; + int freq; + struct wpabuf *resp; + u16 bootstrap; + size_t cookie_len = 0; + const u8 *pos, *cookie; + enum p2p_status_code status = P2P_SC_FAIL_INVALID_PARAMS; + + p2p_dbg(p2p, "Received Provision Discovery Request from " MACSTR + " with bootstrapping Attribute (freq=%d)", + MAC2STR(sa), rx_freq); + + dev = p2p_get_device(p2p, sa); + if (!dev) { + p2p_dbg(p2p, "Provision Discovery Request from unknown peer " + MACSTR, MAC2STR(sa)); + + if (p2p_add_device(p2p, sa, rx_freq, NULL, 0, data + 1, len - 1, + 0)) { + p2p_dbg(p2p, "Provision Discovery Request add device failed " + MACSTR, MAC2STR(sa)); + goto out; + } + + dev = p2p_get_device(p2p, sa); + if (!dev) { + p2p_dbg(p2p, + "Provision Discovery device not found " + MACSTR, MAC2STR(sa)); + goto out; + } + } + dev->p2p2 = true; + + p2p_update_peer_6ghz_capab(dev, msg); + + if (msg->pcea_info && msg->pcea_info_len >= 2) + p2p_process_pcea(p2p, msg, dev); + + pos = msg->pbma_info; + + if (msg->pbma_info_len > 2 && msg->status && + *msg->status == P2P_SC_COMEBACK) { + /* PBMA comeback request */ + cookie_len = *pos++; + cookie = pos; + + if (!dev->bootstrap_params || + dev->bootstrap_params->cookie_len != cookie_len || + memcmp(cookie, dev->bootstrap_params->cookie, cookie_len)) { + status = P2P_SC_FAIL_REJECTED_BY_USER; + goto out; + } + + bootstrap = dev->bootstrap_params->bootstrap_method; + + if (!dev->req_bootstrap_method) { + status = P2P_SC_COMEBACK; + goto out; + } + } else { + /* PBMA request */ + bootstrap = WPA_GET_LE16(pos); + + if (dev->bootstrap_params) { + os_free(dev->bootstrap_params); + dev->bootstrap_params = NULL; + } + + if (!dev->req_bootstrap_method) { + dev->bootstrap_params = + os_zalloc(sizeof(struct p2p_bootstrap_params)); + if (!dev->bootstrap_params) + return; + dev->bootstrap_params->bootstrap_method = bootstrap; + dev->bootstrap_params->cookie_len = 4; + random_get_bytes(dev->bootstrap_params->cookie, + dev->bootstrap_params->cookie_len); + dev->bootstrap_params->comeback_after = + p2p->cfg->comeback_after; + status = P2P_SC_COMEBACK; + goto out; + } + } + + if (bootstrap == P2P_PBMA_PIN_CODE_DISPLAY && + dev->req_bootstrap_method == P2P_PBMA_PIN_CODE_KEYPAD) + status = P2P_SC_SUCCESS; + else if (bootstrap == P2P_PBMA_PIN_CODE_KEYPAD && + dev->req_bootstrap_method == P2P_PBMA_PIN_CODE_DISPLAY) + status = P2P_SC_SUCCESS; + else if (bootstrap == P2P_PBMA_PASSPHRASE_DISPLAY && + dev->req_bootstrap_method == P2P_PBMA_PASSPHRASE_KEYPAD) + status = P2P_SC_SUCCESS; + else if (bootstrap == P2P_PBMA_PASSPHRASE_KEYPAD && + dev->req_bootstrap_method == P2P_PBMA_PASSPHRASE_DISPLAY) + status = P2P_SC_SUCCESS; + else if (bootstrap == P2P_PBMA_NFC_TAG && + dev->req_bootstrap_method == P2P_PBMA_NFC_READER) + status = P2P_SC_SUCCESS; + else if (bootstrap == P2P_PBMA_NFC_READER && + dev->req_bootstrap_method == P2P_PBMA_NFC_TAG) + status = P2P_SC_SUCCESS; + else if (bootstrap == P2P_PBMA_QR_DISPLAY && + dev->req_bootstrap_method == P2P_PBMA_QR_SCAN) + status = P2P_SC_SUCCESS; + else if (bootstrap == P2P_PBMA_QR_SCAN && + dev->req_bootstrap_method == P2P_PBMA_QR_DISPLAY) + status = P2P_SC_SUCCESS; + else if (bootstrap == P2P_PBMA_OPPORTUNISTIC && + dev->req_bootstrap_method == P2P_PBMA_OPPORTUNISTIC) + status = P2P_SC_SUCCESS; + else + status = P2P_SC_FAIL_INVALID_PARAMS; + + wpa_printf(MSG_ERROR, "Bootstrap received %d", bootstrap); + +out: + /* + * Send PD Bootstrapping Response for the PD Request + */ + resp = p2p_build_prov_disc_bootstrap_resp(p2p, dev, msg->dialog_token, + status); + if (!resp) + return; + + p2p_dbg(p2p, "Sending Provision Discovery Bootstrap Response"); + if (rx_freq > 0) + freq = rx_freq; + else + freq = p2p_channel_to_freq(p2p->cfg->reg_class, + p2p->cfg->channel); + if (freq < 0) { + p2p_dbg(p2p, "Unknown regulatory class/channel"); + wpabuf_free(resp); + return; + } + p2p->pending_action_state = P2P_PENDING_PD_RESPONSE; + if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr, + p2p->cfg->dev_addr, wpabuf_head(resp), + wpabuf_len(resp), 50) < 0) + p2p_dbg(p2p, "Failed to send Action frame"); + else + p2p->send_action_in_progress = 1; + + wpabuf_free(resp); +} + static void p2p_process_prov_disc_req(struct p2p_data *p2p, struct p2p_message *msg, const u8 *sa, const u8 *data, size_t len, int rx_freq) @@ -1242,7 +1484,13 @@ void p2p_handle_prov_disc_req(struct p2p_data *p2p, const u8 *sa, if (p2p_parse(data, len, &msg)) return; - p2p_process_prov_disc_req(p2p, &msg, sa, data + 1, len - 1, rx_freq); + if (msg.pcea_info && msg.pbma_info) + p2p_process_prov_disc_bootstrap_req(p2p, &msg, sa, data + 1, + len - 1, rx_freq); + else + p2p_process_prov_disc_req(p2p, &msg, sa, data + 1, len - 1, + rx_freq); + p2p_parse_free(&msg); } @@ -1345,6 +1593,88 @@ static int p2p_validate_p2ps_pd_resp(struct p2p_data *p2p, } +static void p2p_process_prov_disc_bootstrap_resp(struct p2p_data *p2p, + struct p2p_message *msg, + const u8 *sa, const u8 *data, + size_t len, int rx_freq) +{ + struct p2p_device *dev; + u8 status = P2P_SC_SUCCESS; + size_t cookie_len = 0; + const u8 *pos, *cookie; + u16 comeback_after; + + /* Parse the P2P status present */ + if (msg->status) + status = *msg->status; + + p2p_dbg(p2p, "Received Provision Discovery Bootstrap Response from " MACSTR, + MAC2STR(sa)); + + dev = p2p_get_device(p2p, sa); + if (!dev || !dev->req_bootstrap_method) { + p2p_dbg(p2p, "Ignore Provision Discovery Response from " MACSTR + " with no pending request", MAC2STR(sa)); + return; + } + + p2p_update_peer_6ghz_capab(dev, msg); + + if (dev->dialog_token != msg->dialog_token) { + p2p_dbg(p2p, "Ignore Provision Discovery Response with unexpected Dialog Token %u (expected %u)", + msg->dialog_token, dev->dialog_token); + return; + } + + if (p2p->pending_action_state == P2P_PENDING_PD) { + os_memset(p2p->pending_pd_devaddr, 0, ETH_ALEN); + p2p->pending_action_state = P2P_NO_PENDING_ACTION; + } + + if (dev->bootstrap_params) { + os_free(dev->bootstrap_params); + dev->bootstrap_params = NULL; + } + + /* + * If the response is from the peer to whom a user initiated request + * was sent earlier, we reset that state info here. + */ + if (p2p->user_initiated_pd && + ether_addr_equal(p2p->pending_pd_devaddr, sa)) + p2p_reset_pending_pd(p2p); + + if (status == P2P_SC_COMEBACK) { + /* PBMA comeback response */ + pos = msg->pbma_info; + comeback_after = WPA_GET_LE16(pos); + pos += 2; + cookie_len = *pos++; + cookie = pos; + + dev->bootstrap_params = + os_zalloc(sizeof(struct p2p_bootstrap_params)); + if (!dev->bootstrap_params) + return; + dev->bootstrap_params->cookie_len = cookie_len; + memcpy(dev->bootstrap_params->cookie, cookie, cookie_len); + dev->bootstrap_params->comeback_after = comeback_after; + dev->bootstrap_params->bootstrap_method = + dev->req_bootstrap_method; + dev->bootstrap_params->status = status; + + p2p->cfg->register_bootstrap_comeback(p2p->cfg->cb_ctx, sa, + comeback_after); + p2p->cfg->send_action_done(p2p->cfg->cb_ctx); + return; + } + + p2p->cfg->send_action_done(p2p->cfg->cb_ctx); + if (dev->flags & P2P_DEV_PD_BEFORE_GO_NEG) + dev->flags &= ~P2P_DEV_PD_BEFORE_GO_NEG; +} + + static void p2p_process_prov_disc_resp(struct p2p_data *p2p, struct p2p_message *msg, const u8 *sa, const u8 *data, size_t len) @@ -1635,14 +1965,19 @@ out: void p2p_handle_prov_disc_resp(struct p2p_data *p2p, const u8 *sa, - const u8 *data, size_t len) + const u8 *data, size_t len, int rx_freq) { struct p2p_message msg; if (p2p_parse(data, len, &msg)) return; - p2p_process_prov_disc_resp(p2p, &msg, sa, data + 1, len - 1); + if (msg.pcea_info && msg.pbma_info) + p2p_process_prov_disc_bootstrap_resp(p2p, &msg, sa, data + 1, + len - 1, rx_freq); + else + p2p_process_prov_disc_resp(p2p, &msg, sa, data + 1, len - 1); + p2p_parse_free(&msg); } @@ -1676,7 +2011,7 @@ int p2p_send_prov_disc_req(struct p2p_data *p2p, struct p2p_device *dev, /* TODO: use device discoverability request through GO */ } - if (p2p->p2ps_prov) { + if (!dev->p2p2 && p2p->p2ps_prov) { if (p2p->p2ps_prov->status == P2P_SC_SUCCESS_DEFERRED) { if (p2p->p2ps_prov->method == WPS_CONFIG_DISPLAY) dev->req_config_methods = WPS_CONFIG_KEYPAD; @@ -1706,7 +2041,11 @@ int p2p_send_prov_disc_req(struct p2p_data *p2p, struct p2p_device *dev, return -1; } - req = p2p_build_prov_disc_req(p2p, dev, join); + if (dev->p2p2) + req = p2p_build_prov_disc_bootstrap_req(p2p, dev); + else + req = p2p_build_prov_disc_req(p2p, dev, join); + if (req == NULL) return -1; @@ -1745,13 +2084,22 @@ int p2p_prov_disc_req(struct p2p_data *p2p, const u8 *peer_addr, return -1; } + if (dev->p2p2 && dev->req_bootstrap_method) { + p2p_dbg(p2p, "Provision Discovery Request with " MACSTR + " (bootstrap methods 0x%x)", + MAC2STR(peer_addr), dev->req_bootstrap_method); + goto out; + } + p2p_dbg(p2p, "Provision Discovery Request with " MACSTR " (config methods 0x%x)", MAC2STR(peer_addr), config_methods); + if (config_methods == 0 && !p2ps_prov) { os_free(p2ps_prov); return -1; } + dev->req_config_methods = config_methods; if (p2ps_prov && p2ps_prov->status == P2P_SC_SUCCESS_DEFERRED && p2p->p2ps_prov) { @@ -1759,12 +2107,12 @@ int p2p_prov_disc_req(struct p2p_data *p2p, const u8 *peer_addr, p2ps_prov->method = p2p->p2ps_prov->method; } +out: /* Reset provisioning info */ dev->wps_prov_info = 0; p2ps_prov_free(p2p); p2p->p2ps_prov = p2ps_prov; - dev->req_config_methods = config_methods; if (join) dev->flags |= P2P_DEV_PD_FOR_JOIN; else @@ -1773,8 +2121,7 @@ int p2p_prov_disc_req(struct p2p_data *p2p, const u8 *peer_addr, if (p2p->state != P2P_IDLE && p2p->state != P2P_SEARCH && p2p->state != P2P_LISTEN_ONLY) { p2p_dbg(p2p, "Busy with other operations; postpone Provision Discovery Request with " - MACSTR " (config methods 0x%x)", - MAC2STR(peer_addr), config_methods); + MACSTR, MAC2STR(peer_addr)); return 0; } diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 2b6d2e5..fc7f32f 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -6376,6 +6376,10 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd, size_t group_ssid_len = 0; int he; bool allow_6ghz; + bool p2p2; + u16 bootstrap = 0; + const char *password = NULL; + char *token, *context = NULL; if (!wpa_s->global->p2p_init_wpa_s) return -1; @@ -6388,7 +6392,9 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd, /* <"pbc" | "pin" | PIN> [label|display|keypad|p2ps] * [persistent|persistent=] * [join] [auth] [go_intent=<0..15>] [freq=] [provdisc] - * [ht40] [vht] [he] [edmg] [auto] [ssid=] */ + * [ht40] [vht] [he] [edmg] [auto] [ssid=] + * [p2p2] [bstrapmethod=] [password=] + */ if (hwaddr_aton(cmd, addr)) return -1; @@ -6422,6 +6428,7 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd, vht; he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he; edmg = (os_strstr(cmd, " edmg") != NULL) || wpa_s->conf->p2p_go_edmg; + p2p2 = os_strstr(pos, "p2p2") != NULL; pos2 = os_strstr(pos, " go_intent="); if (pos2) { @@ -6477,6 +6484,8 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd, wps_method = WPS_PBC; } else if (os_strstr(pos, "p2ps") != NULL) { wps_method = WPS_P2PS; + } else if (p2p2) { + wps_method = WPS_NOT_READY; } else { pin = pos; pos = os_strchr(pin, ' '); @@ -6492,11 +6501,26 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd, } } + pos2 = os_strstr(pos, "bstrapmethod="); + if (pos2) { + pos2 += 13; + bootstrap = atoi(pos2); + pd = true; + } + + while ((token = str_token(pos, " ", &context))) { + if (os_strncmp(token, "password=", 9) == 0) { + password = token + 9; + continue; + } + } + new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method, persistent_group, automatic, join, auth, go_intent, freq, freq2, persistent_id, pd, ht40, vht, max_oper_chwidth, he, edmg, - group_ssid, group_ssid_len, allow_6ghz); + group_ssid, group_ssid_len, allow_6ghz, p2p2, + bootstrap, password); if (new_pin == -2) { os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25); return 25; diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c index 5d55ede..0011cf0 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c +++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c @@ -706,7 +706,7 @@ DBusMessage * wpas_dbus_handler_p2p_connect(DBusMessage *message, new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method, persistent_group, 0, join, authorize_only, go_intent, freq, 0, -1, 0, 0, 0, 0, 0, 0, - NULL, 0, false); + NULL, 0, false, 0, 0, NULL); if (new_pin >= 0) { char npin[9]; diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index b31e910..70480f6 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -4822,6 +4822,38 @@ static int wpas_p2p_get_pref_freq_list(void *ctx, int go, WPA_IF_P2P_CLIENT, len, freq_list); } +static void wpas_p2p_send_bootstrap_comeback(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_supplicant *wpa_s = eloop_ctx; + + wpas_p2p_connect(wpa_s, wpa_s->p2p_bootstrap_dev_addr, wpa_s->p2p_pin, + wpa_s->p2p_wps_method, wpa_s->p2p_persistent_group, 0, + 0, 0, wpa_s->p2p_go_intent, wpa_s->p2p_connect_freq, + wpa_s->p2p_go_vht_center_freq2, + wpa_s->p2p_persistent_id, + wpa_s->p2p_pd_before_go_neg, + wpa_s->p2p_go_ht40, + wpa_s->p2p_go_vht, + wpa_s->p2p_go_max_oper_chwidth, + wpa_s->p2p_go_he, + wpa_s->p2p_go_edmg, + NULL, 0, is_p2p_allow_6ghz(wpa_s->global->p2p), + wpa_s->p2p2, wpa_s->p2p_bootstrap, NULL); +} + +static void wpas_p2p_register_bootstrap_comeback(void *ctx, const u8 *addr, + u16 comeback_after) +{ + unsigned int timeout_us; + struct wpa_supplicant *wpa_s = ctx; + + timeout_us = comeback_after * 1024; + memcpy(wpa_s->p2p_bootstrap_dev_addr, addr, ETH_ALEN); + + eloop_cancel_timeout(wpas_p2p_send_bootstrap_comeback, wpa_s, NULL); + eloop_register_timeout(0, timeout_us, wpas_p2p_send_bootstrap_comeback, + wpa_s, NULL); +} int wpas_p2p_mac_setup(struct wpa_supplicant *wpa_s) { @@ -4942,6 +4974,7 @@ int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s) p2p.p2ps_group_capability = p2ps_group_capability; p2p.get_pref_freq_list = wpas_p2p_get_pref_freq_list; p2p.p2p_6ghz_disable = wpa_s->conf->p2p_6ghz_disable; + p2p.register_bootstrap_comeback = wpas_p2p_register_bootstrap_comeback; os_memcpy(wpa_s->global->p2p_dev_addr, wpa_s->own_addr, ETH_ALEN); os_memcpy(p2p.dev_addr, wpa_s->global->p2p_dev_addr, ETH_ALEN); @@ -5193,7 +5226,8 @@ static int wpas_p2p_start_go_neg(struct wpa_supplicant *wpa_s, enum p2p_wps_method wps_method, int go_intent, const u8 *own_interface_addr, unsigned int force_freq, int persistent_group, - struct wpa_ssid *ssid, unsigned int pref_freq) + struct wpa_ssid *ssid, unsigned int pref_freq, + bool p2p2, u16 bootstrap, const char *password) { if (persistent_group && wpa_s->conf->persistent_reconnect) persistent_group = 2; @@ -5211,7 +5245,7 @@ static int wpas_p2p_start_go_neg(struct wpa_supplicant *wpa_s, ssid ? ssid->ssid_len : 0, wpa_s->p2p_pd_before_go_neg, pref_freq, wps_method == WPS_NFC ? wpa_s->p2p_oob_dev_pw_id : - 0); + 0, p2p2, bootstrap, password); } @@ -5220,7 +5254,8 @@ static int wpas_p2p_auth_go_neg(struct wpa_supplicant *wpa_s, enum p2p_wps_method wps_method, int go_intent, const u8 *own_interface_addr, unsigned int force_freq, int persistent_group, - struct wpa_ssid *ssid, unsigned int pref_freq) + struct wpa_ssid *ssid, unsigned int pref_freq, + u16 bootstrap, const char *password) { if (persistent_group && wpa_s->conf->persistent_reconnect) persistent_group = 2; @@ -5230,7 +5265,7 @@ static int wpas_p2p_auth_go_neg(struct wpa_supplicant *wpa_s, persistent_group, ssid ? ssid->ssid : NULL, ssid ? ssid->ssid_len : 0, pref_freq, wps_method == WPS_NFC ? wpa_s->p2p_oob_dev_pw_id : - 0); + 0, bootstrap, password); } @@ -5414,7 +5449,9 @@ static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s, wpa_s->p2p_go_he, wpa_s->p2p_go_edmg, NULL, 0, - is_p2p_allow_6ghz(wpa_s->global->p2p)); + is_p2p_allow_6ghz(wpa_s->global->p2p), + wpa_s->p2p2, wpa_s->p2p_bootstrap, + NULL); return; } @@ -5908,6 +5945,9 @@ static bool is_p2p_6ghz_supported(struct wpa_supplicant *wpa_s, HOSTAPD_MODE_IEEE80211A, true)) return false; + if (wpa_s->p2p2) + return true; + if (!p2p_wfd_enabled(wpa_s->global->p2p)) return false; if (peer_addr && !p2p_peer_wfd_enabled(wpa_s->global->p2p, peer_addr)) @@ -5959,6 +5999,10 @@ static int wpas_p2p_check_6ghz(struct wpa_supplicant *wpa_s, * @group_ssid: Specific Group SSID for join or %NULL if not set * @group_ssid_len: Length of @group_ssid in octets * @allow_6ghz: Allow P2P connection on 6 GHz channels + * @p2p2: Device in P2P R2 mode + * @bootstrap: Requested bootstrap method for pairing in p2p2 + * @password: Password for pairing setup or NULL for oppurtunistic method + * in p2p2 * Returns: 0 or new PIN (if pin was %NULL) on success, -1 on unspecified * failure, -2 on failure due to channel not currently available, * -3 if forced channel is not supported @@ -5970,7 +6014,8 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr, int persistent_id, int pd, int ht40, int vht, unsigned int vht_chwidth, int he, int edmg, const u8 *group_ssid, size_t group_ssid_len, - bool allow_6ghz) + bool allow_6ghz, bool p2p2, u16 bootstrap, + const char *password) { int force_freq = 0, pref_freq = 0; int ret = 0, res; @@ -5990,6 +6035,8 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr, return -1; } + wpa_s->p2p2 = p2p2; + if (wpas_p2p_check_6ghz(wpa_s, peer_addr, allow_6ghz, freq)) return -2; @@ -6020,6 +6067,7 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr, wpa_s->p2p_go_max_oper_chwidth = vht_chwidth; wpa_s->p2p_go_he = !!he; wpa_s->p2p_go_edmg = !!edmg; + wpa_s->p2p_bootstrap = bootstrap; if (pin) os_strlcpy(wpa_s->p2p_pin, pin, sizeof(wpa_s->p2p_pin)); @@ -6105,14 +6153,15 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr, if (wpas_p2p_auth_go_neg(wpa_s, peer_addr, wps_method, go_intent, if_addr, force_freq, persistent_group, ssid, - pref_freq) < 0) + pref_freq, bootstrap, password) < 0) return -1; return ret; } if (wpas_p2p_start_go_neg(wpa_s, peer_addr, wps_method, go_intent, if_addr, force_freq, - persistent_group, ssid, pref_freq) < 0) { + persistent_group, ssid, pref_freq, p2p2, + bootstrap, password) < 0) { if (wpa_s->create_p2p_iface) wpas_p2p_remove_pending_group_interface(wpa_s); return -1; @@ -8740,7 +8789,8 @@ static int wpas_p2p_fallback_to_go_neg(struct wpa_supplicant *wpa_s, wpa_s->p2p_go_max_oper_chwidth, wpa_s->p2p_go_he, wpa_s->p2p_go_edmg, - NULL, 0, is_p2p_allow_6ghz(wpa_s->global->p2p)); + NULL, 0, is_p2p_allow_6ghz(wpa_s->global->p2p), + wpa_s->p2p2, wpa_s->p2p_bootstrap, NULL); return ret; } @@ -9278,7 +9328,8 @@ static int wpas_p2p_nfc_join_group(struct wpa_supplicant *wpa_s, -1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth, wpa_s->p2p_go_he, wpa_s->p2p_go_edmg, params->go_ssid_len ? params->go_ssid : NULL, - params->go_ssid_len, false); + params->go_ssid_len, false, wpa_s->p2p2, + wpa_s->p2p_bootstrap, NULL); } @@ -9357,7 +9408,8 @@ static int wpas_p2p_nfc_init_go_neg(struct wpa_supplicant *wpa_s, forced_freq, wpa_s->p2p_go_vht_center_freq2, -1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth, wpa_s->p2p_go_he, wpa_s->p2p_go_edmg, - NULL, 0, false); + NULL, 0, false, wpa_s->p2p2, + wpa_s->p2p_bootstrap, NULL); } @@ -9374,7 +9426,9 @@ static int wpas_p2p_nfc_resp_go_neg(struct wpa_supplicant *wpa_s, forced_freq, wpa_s->p2p_go_vht_center_freq2, -1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth, wpa_s->p2p_go_he, wpa_s->p2p_go_edmg, - NULL, 0, false); + NULL, 0, false, wpa_s->p2p2, + wpa_s->p2p_bootstrap, NULL); + if (res) return res; diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h index 441e063..a2cb78d 100644 --- a/wpa_supplicant/p2p_supplicant.h +++ b/wpa_supplicant/p2p_supplicant.h @@ -39,7 +39,8 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr, int persistent_id, int pd, int ht40, int vht, unsigned int vht_chwidth, int he, int edmg, const u8 *group_ssid, size_t group_ssid_len, - bool allow_6ghz); + bool allow_6ghz, bool p2p2, u16 bootstrap, + const char *password); int wpas_p2p_handle_frequency_conflicts(struct wpa_supplicant *wpa_s, int freq, struct wpa_ssid *ssid); int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group, diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 57082ab..6a9be8e 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1111,6 +1111,7 @@ struct wpa_supplicant { int pending_pd_before_join; u8 pending_join_iface_addr[ETH_ALEN]; u8 pending_join_dev_addr[ETH_ALEN]; + u8 p2p_bootstrap_dev_addr[ETH_ALEN]; int pending_join_wps_method; u8 p2p_join_ssid[SSID_MAX_LEN]; size_t p2p_join_ssid_len; @@ -1165,6 +1166,8 @@ struct wpa_supplicant { unsigned int p2ps_method_config_any:1; unsigned int p2p_cli_probe:1; unsigned int p2p_go_allow_dfs:1; + unsigned int p2p2:1; + u16 p2p_bootstrap; enum hostapd_hw_mode p2p_go_acs_band; int p2p_persistent_go_freq; int p2p_persistent_id;