From patchwork Mon Jun 12 19:59:48 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrei Otcheretianski X-Patchwork-Id: 1794049 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org 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=) 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=B1//UG8M; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=ec/Fs0P2; dkim-atps=neutral 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 (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4Qg2cz3RRJz20Wl for ; Tue, 13 Jun 2023 06:01:23 +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: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:In-Reply-To:References: List-Owner; bh=ZKC9zB9pmx+NLLrebEOPSl4MNGjZBlEEWY403ydx158=; b=B1//UG8MWZtbUZ UV4KT/ebmG5LhGB7YNnKHAZBmrDcxup0EjkqKEti0wFhmC7sCPcfzn05q54PcywEUt6RulW8yJyEF LN/N9Dq2VSv0mjQv04tR/QgPgpcY+8BZWVvx+NeVmgAVsQRMXrTF1nsnErswM/s74zf8ffckxPwD8 00tio3aKJzYxMNl8J3ANrj7PiG6csRN7wbPr3oCNlSMT40jFhGKSxFEYbvAmmrhYcLKS8mp5wuNSM 2OEAjj5zTn3FTjNs0fa3o52rYNPjB+dwqDXs0fSU3U0Qf24gA3/uFCAdyinvmnbaRdvx02PyfW1PJ HC+9/nK3Ieh+YvY9f0zg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1q8nht-005CZL-37; Mon, 12 Jun 2023 20:00:05 +0000 Received: from mga02.intel.com ([134.134.136.20]) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1q8nhp-005CY8-1y for hostap@lists.infradead.org; Mon, 12 Jun 2023 20:00:03 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1686600001; x=1718136001; h=from:to:cc:subject:date:message-id:mime-version: content-transfer-encoding; bh=vlUOZSF38RlZM8lYoc4N5dWk/UzWdWxGsT2NFCCSmQc=; b=ec/Fs0P2jURIAQ0/aoC76RHO4EafBl/dWsMzBqlC9ARI5e0jwGp3Inlu 2GbnHVtkzrnW7ZMs9dJxvL3bHrabatEnjrbxLkpU014e+enDGCDzOaiGn 1RKYziFo06fDBPFLJ6lF8F8FFt151Ziw4EPJaHblHCfNSFyN9iLlTrbDz omRD3pGo+rU5pCBU2Tb7sbkdCt7muvrcFkDOea5tO59SUPF4AfMc5MCvm IJ7ez6F1AbiWMI0Wqzz/eTICyQgf688KX3LqJY/O5hHdlNZaLSJRfywMo GfbrU5LJgJc2ZVQVdtjYwFgKiN4IvJXfPrEKlHd/V3daJgw/uCC/cLiAS w==; X-IronPort-AV: E=McAfee;i="6600,9927,10739"; a="347800438" X-IronPort-AV: E=Sophos;i="6.00,236,1681196400"; d="scan'208";a="347800438" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Jun 2023 12:59:59 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10739"; a="741156428" X-IronPort-AV: E=Sophos;i="6.00,236,1681196400"; d="scan'208";a="741156428" Received: from masharut-mobl.ger.corp.intel.com (HELO aotchere-desk.intel.com) ([10.254.152.129]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Jun 2023 12:59:58 -0700 From: Andrei Otcheretianski To: hostap@lists.infradead.org Cc: Ilan Peer Subject: [PATCH 1/3] nl80211: Add support for minimal probe request content Date: Mon, 12 Jun 2023 22:59:48 +0300 Message-Id: <20230612195950.60468-1-andrei.otcheretianski@intel.com> X-Mailer: git-send-email 2.38.1 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230612_130001_742811_8D23359B X-CRM114-Status: GOOD ( 15.56 ) X-Spam-Score: -2.7 (--) 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: From: Ilan Peer Extend 'struct wpa_driver_scan_params' to allow higher layer to indicate if minimal probe request content should be included by the driver as part of the scan logic. Content analysis details: (-2.7 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at https://www.dnswl.org/, medium trust [134.134.136.20 listed in list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 SPF_NONE SPF: sender does not publish an SPF Record -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 -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.0 RCVD_IN_MSPIKE_H3 RBL: Good reputation (+3) [134.134.136.20 listed in wl.mailspike.net] 0.0 RCVD_IN_MSPIKE_WL Mailspike good senders -0.2 DKIMWL_WL_HIGH DKIMwl.org - High trust sender 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 From: Ilan Peer Extend 'struct wpa_driver_scan_params' to allow higher layer to indicate if minimal probe request content should be included by the driver as part of the scan logic. Implement this with driver_nl80211, by setting NL80211_SCAN_FLAG_MIN_PREQ_CONTENT. Signed-off-by: Ilan Peer --- src/drivers/driver.h | 9 +++++++++ src/drivers/driver_nl80211_capa.c | 4 ++++ src/drivers/driver_nl80211_scan.c | 8 ++++++++ wpa_supplicant/scan.c | 1 + 4 files changed, 22 insertions(+) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 12371a7d81..651a5f76d9 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -685,6 +685,13 @@ struct wpa_driver_scan_params { */ unsigned int non_coloc_6ghz:1; + /** + * min_probe_req_content - Minimize probe request content to only have + * minimal requirement elements, e.g., supported rates etc., and no + * additional elements other then those provided by user space. + */ + unsigned int min_probe_req_content:1; + /* * NOTE: Whenever adding new parameters here, please make sure * wpa_scan_clone_params() and wpa_scan_free_params() get updated with @@ -2238,6 +2245,8 @@ struct wpa_driver_capa { #define WPA_DRIVER_FLAGS2_PROT_RANGE_NEG_STA 0x0000000000002000ULL /** Driver supports MLO in station/AP mode */ #define WPA_DRIVER_FLAGS2_MLO 0x0000000000004000ULL +/** Driver supports minimal scan request probe content */ +#define WPA_DRIVER_FLAGS2_SCAN_MIN_PREQ 0x0000000000008000ULL u64 flags2; #define FULL_AP_CLIENT_STATE_SUPP(drv_flags) \ diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c index b904398ca3..4148f502c2 100644 --- a/src/drivers/driver_nl80211_capa.c +++ b/src/drivers/driver_nl80211_capa.c @@ -697,6 +697,10 @@ static void wiphy_info_ext_feature_flags(struct wiphy_info_data *info, capa->flags2 |= WPA_DRIVER_FLAGS2_PROT_RANGE_NEG_STA; capa->flags2 |= WPA_DRIVER_FLAGS2_PROT_RANGE_NEG_AP; } + + if (ext_feature_isset(ext_features, len, + NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT)) + capa->flags2 |= WPA_DRIVER_FLAGS2_SCAN_MIN_PREQ; } diff --git a/src/drivers/driver_nl80211_scan.c b/src/drivers/driver_nl80211_scan.c index 4d33b149d0..7ae6cecbcd 100644 --- a/src/drivers/driver_nl80211_scan.c +++ b/src/drivers/driver_nl80211_scan.c @@ -315,6 +315,14 @@ nl80211_scan_common(struct i802_bss *bss, u8 cmd, NL80211_SCAN_FLAG_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION; } + if (params->min_probe_req_content) { + if (drv->capa.flags2 & WPA_DRIVER_FLAGS2_SCAN_MIN_PREQ) + scan_flags |= NL80211_SCAN_FLAG_MIN_PREQ_CONTENT; + else + wpa_printf(MSG_DEBUG, + "nl80211: NL80211_SCAN_FLAG_MIN_PREQ_CONTENT not supported"); + } + if (scan_flags && nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, scan_flags)) goto fail; diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index c3984a40c9..166751a1f2 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -3045,6 +3045,7 @@ wpa_scan_clone_params(const struct wpa_driver_scan_params *src) params->relative_adjust_rssi = src->relative_adjust_rssi; params->p2p_include_6ghz = src->p2p_include_6ghz; params->non_coloc_6ghz = src->non_coloc_6ghz; + params->min_probe_req_content = src->min_probe_req_content; return params; failed: From patchwork Mon Jun 12 19:59:49 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrei Otcheretianski X-Patchwork-Id: 1794051 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org 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=) 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=XbSRFzna; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=KJMdKlpb; dkim-atps=neutral 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 (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4Qg2cz5FWLz20XX for ; Tue, 13 Jun 2023 06:01:23 +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=MWrGP0K/m7DpKMsx2GCVHl6pt/vZL0VAmWOsZuKA+1E=; b=XbSRFznazG6ST+ YudnQF/vx2XpkEiezf41EdE14hw7r2iR9AAqVJs/WWQUiJWhRsiLE8JqParJwvtYXObnKjBFH9fPl 5rkE8EwzASdvxgZ22LNLWfxOJOR8ti784UUI89rKRxGT1pKQapfMWrt3aDEm1/NQ2UcpQz6SMkpLJ KCuQpbIKM3172qiQCMcdUBwhBzRXAaSVk4gs2+Jrl+KoAP8hAlvTLQXCzksVmS3RCkyTh4IS3NdXZ C9oX+DU8A1G3Egc0vfYmx7A6xe944BNmCOjZc5ETdNb1gyciPWJIsFWZLR4nuBnu+wiQbY5kFMhLI P/oGaW/gKzG1r4g70oEw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1q8ni2-005Cbp-0O; Mon, 12 Jun 2023 20:00:14 +0000 Received: from mga02.intel.com ([134.134.136.20]) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1q8nhx-005Caa-2H for hostap@lists.infradead.org; Mon, 12 Jun 2023 20:00:12 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1686600009; x=1718136009; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=QL5k+7YAOCMRdlkStpVs5dFjQqN/KbG5FtT4+Xm+tRk=; b=KJMdKlpbdNGSRUmvFVa+edfbmEcT34gmFUas0yUvXXU75ENDU/z5Wkw/ oiKRTmMJVLXnhFM/Vp/Wp26wGsUONwLrL3ekcLe5zdKFE3sSfx0//ziMu z9qx/vXlvu8zLJZgxc/rV7pGD75C+YLjnscSVhzZaPfAJTfWG+CAfLnZN xPmlIAJD99fmXtTOEZ8iXS3vdMrjec39Ag6Hbga1VodWqegO7IxY6rtfy 39Gy/qN/Fzw5dVDsZ/380A+f7fB0bIDvYn8mZYQtM3w3dbWYB9fanV8bX ba8VgJhCWwh2OhKFVoOjgbGBxlbykYYSnxqYUMxZInjVWNf0DOatFyVDh w==; X-IronPort-AV: E=McAfee;i="6600,9927,10739"; a="347800468" X-IronPort-AV: E=Sophos;i="6.00,236,1681196400"; d="scan'208";a="347800468" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Jun 2023 13:00:09 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10739"; a="741156648" X-IronPort-AV: E=Sophos;i="6.00,236,1681196400"; d="scan'208";a="741156648" Received: from masharut-mobl.ger.corp.intel.com (HELO aotchere-desk.intel.com) ([10.254.152.129]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Jun 2023 13:00:07 -0700 From: Andrei Otcheretianski To: hostap@lists.infradead.org Cc: Andrei Otcheretianski , Benjamin Berg , Ilan Peer Subject: [PATCH 2/3] wpa_supplicant: Support ML probe request Date: Mon, 12 Jun 2023 22:59:49 +0300 Message-Id: <20230612195950.60468-2-andrei.otcheretianski@intel.com> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20230612195950.60468-1-andrei.otcheretianski@intel.com> References: <20230612195950.60468-1-andrei.otcheretianski@intel.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230612_130009_882507_81396682 X-CRM114-Status: GOOD ( 32.11 ) X-Spam-Score: -2.7 (--) 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 building and sending ML probe requests and add a control interface to trigger ML probes for testing purposes. During connect, try to send an ML probe request if we are going to connect [...] Content analysis details: (-2.7 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RCVD_IN_MSPIKE_H3 RBL: Good reputation (+3) [134.134.136.20 listed in wl.mailspike.net] -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at https://www.dnswl.org/, medium trust [134.134.136.20 listed in list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 SPF_NONE SPF: sender does not publish an SPF Record -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 -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.0 RCVD_IN_MSPIKE_WL Mailspike good senders -0.2 DKIMWL_WL_HIGH DKIMwl.org - High trust sender 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 building and sending ML probe requests and add a control interface to trigger ML probes for testing purposes. During connect, try to send an ML probe request if we are going to connect to an MLD AP and the BSS information for some of the links is missing. Signed-off-by: Benjamin Berg Signed-off-by: Ilan Peer Signed-off-by: Andrei Otcheretianski --- src/common/ieee802_11_defs.h | 15 ++ src/utils/common.c | 15 ++ src/utils/common.h | 1 + wpa_supplicant/bss.c | 229 ++++++++++++++++++++++++++++++ wpa_supplicant/bss.h | 14 +- wpa_supplicant/ctrl_iface.c | 77 ++++++++++ wpa_supplicant/events.c | 79 +++++++++++ wpa_supplicant/notify.c | 4 + wpa_supplicant/scan.c | 82 +++++++++++ wpa_supplicant/wpa_cli.c | 9 ++ wpa_supplicant/wpa_supplicant.c | 3 + wpa_supplicant/wpa_supplicant_i.h | 7 + 12 files changed, 534 insertions(+), 1 deletion(-) diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 12789227c4..e36f6db139 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -2451,9 +2451,14 @@ struct ieee80211_he_mu_edca_parameter_set { */ #define RNR_HEADER_LEN 2 #define RNR_TBTT_HEADER_LEN 4 +#define RNR_TBTT_INFO_HDR_TYPE_MSK 0x03 +#define RNR_TBTT_INFO_HDR_FILTERED_AP 0x04 +#define RNR_TBTT_INFO_HDR_CNT_MSK 0xf0 #define RNR_TBTT_INFO_COUNT(x) (((x) & 0xf) << 4) #define RNR_TBTT_INFO_COUNT_MAX 16 +#define RNR_TBTT_INFO_COUNT_VAL(x) (((x) & 0xf0) >> 4) #define RNR_TBTT_INFO_LEN 13 +#define RNR_TBTT_INFO_MLD_LEN 16 #define RNR_NEIGHBOR_AP_OFFSET_UNKNOWN 255 /* Figure 9-632a - BSS Parameters subfield format */ #define RNR_BSS_PARAM_OCT_RECOMMENDED BIT(0) @@ -2659,6 +2664,16 @@ struct eht_ml_basic_common_info { #define EHT_ML_MLD_CAPA_FREQ_SEP_FOR_STR_MASK 0x0f80 #define EHT_ML_MLD_CAPA_AAR_SUPP 0x1000 +#define EHT_PER_STA_CTRL_LINK_ID_MSK 0x000f +#define EHT_PER_STA_CTRL_COMPLETE_PROFILE_MSK 0x0010 +#define EHT_PER_STA_CTRL_MAC_ADDR_PRESENT_MSK 0x0020 +#define EHT_PER_STA_CTRL_BEACON_INTERVAL_PRESENT_MSK 0x0040 +#define EHT_PER_STA_CTRL_TSF_OFFSET_PRESENT_MSK 0x0080 +#define EHT_PER_STA_CTRL_DTIM_INFO_PRESENT_MSK 0x0100 +#define EHT_PER_STA_CTRL_NSTR_LINK_PAIR_PRESENT_MSK 0x0200 +#define EHT_PER_STA_CTRL_NSTR_BM_SIZE_MSK 0x0400 +#define EHT_PER_STA_CTRL_BSS_PARAM_CNT_PRESENT_MSK 0x0800 + /* IEEE P802.11be/D2.0, 9.4.2.312.2.4 - Per-STA Profile subelement format */ struct ieee80211_eht_per_sta_profile { le16 sta_control; diff --git a/src/utils/common.c b/src/utils/common.c index 6acfcbd898..4a90ba8cf5 100644 --- a/src/utils/common.c +++ b/src/utils/common.c @@ -1259,6 +1259,21 @@ u8 rssi_to_rcpi(int rssi) return (rssi + 110) * 2; } +/** + * popcount - count the number of bits set in a byte + * + * This function returns the number of bits set in a byte. + */ +u8 popcount(u8 x) +{ + const u8 m1 = 0x55; + const u8 m2 = 0x33; + const u8 m4 = 0x0f; + + x = (x & m1) + ((x >> 1) & m1); + x = (x & m2) + ((x >> 2) & m2); + return (x & m4) + ((x >> 4) & m4); +} char * get_param(const char *cmd, const char *param) { diff --git a/src/utils/common.h b/src/utils/common.h index 435a9a84ca..4ca573a7d7 100644 --- a/src/utils/common.h +++ b/src/utils/common.h @@ -576,6 +576,7 @@ u8 rssi_to_rcpi(int rssi); char * get_param(const char *cmd, const char *param); void forced_memzero(void *ptr, size_t len); +u8 popcount(u8 x); /* * gcc 4.4 ends up generating strict-aliasing warnings about some very common diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c index 320441426b..1aa490bcbc 100644 --- a/wpa_supplicant/bss.c +++ b/wpa_supplicant/bss.c @@ -385,6 +385,9 @@ static int wpa_bss_in_use(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) if (bss == wpa_s->current_bss) return 1; + if (bss == wpa_s->ml_connect_probe_bss) + return 1; + if (wpa_s->current_bss && (bss->ssid_len != wpa_s->current_bss->ssid_len || os_memcmp(bss->ssid, wpa_s->current_bss->ssid, @@ -736,8 +739,13 @@ wpa_bss_update(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, break; } } + if (wpa_s->current_bss == bss) wpa_s->current_bss = nbss; + + if (wpa_s->ml_connect_probe_bss == bss) + wpa_s->ml_connect_probe_bss = nbss; + wpa_bss_update_pending_connect(wpa_s, bss, nbss); bss = nbss; os_memcpy(bss->ies, res + 1, @@ -1468,3 +1476,224 @@ struct wpabuf * wpa_bss_defrag_mle(const struct wpa_bss *bss, u8 type) return ieee802_11_defrag_mle(&elems, type); } + + +static void +wpa_bss_parse_ml_rnr_ap_info(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss, u8 mbssid_idx, + struct ieee80211_neighbor_ap_info *ap_info, + u16 *seen, u16 *missing) +{ + const u8 *pos; + const u8 *mld_params; + u8 count, mld_params_offset; + u8 i, type, link_id; + + count = RNR_TBTT_INFO_COUNT_VAL(ap_info->tbtt_info_hdr) + 1; + type = ap_info->tbtt_info_hdr & RNR_TBTT_INFO_HDR_TYPE_MSK; + + /* MLD information is at offset 13 or at start */ + if (type == 0 && + ap_info->tbtt_info_len >= RNR_TBTT_INFO_MLD_LEN) { + /* MLD info is appended */ + mld_params_offset = RNR_TBTT_INFO_LEN; + } else { + /* TODO: Support NSTR AP */ + return; + } + + pos = (const u8 *)ap_info + sizeof(*ap_info); + + for (i = 0; i < count; i++) { + if (bss->n_mld_links >= MAX_NUM_MLD_LINKS) + return; + + mld_params = pos + mld_params_offset; + + link_id = *(mld_params + 1) & EHT_ML_LINK_ID_MSK; + + if (*mld_params != mbssid_idx) { + wpa_printf(MSG_DEBUG, + "MLD: reported link not part of MLD"); + } else if (!(BIT(link_id) & *seen)) { + struct wpa_bss *neigh_bss = + wpa_bss_get_bssid(wpa_s, ap_info->data + 1); + + *seen |= BIT(link_id); + wpa_printf(MSG_DEBUG, "MLD: mld ID=%u, link ID=%u", + *mld_params, link_id); + + if (neigh_bss) { + bss->mld_links[bss->n_mld_links].link_id = link_id; + os_memcpy(bss->mld_links[bss->n_mld_links].bssid, + ap_info->data + 1, ETH_ALEN); + bss->mld_links[bss->n_mld_links].freq = neigh_bss->freq; + bss->n_mld_links++; + } else if (neigh_bss) { + bss->n_mld_links++; + } else { + *missing |= BIT(link_id); + } + } + + pos += ap_info->tbtt_info_len; + } +} + + +/** + * wpa_bss_parse_basic_ml_element - Parse the basic ML element + * @wpa_s: Pointer to wpa_supplicant data + * @bss: BSS table entry + * @mld_addr: AP MLD address (or %NULL) + * @link_info: Array to store link information (or %NULL), + * should be initialized and #MAX_NUM_MLD_LINKS elements long + * @missing_links: Result bitmask of links that were not discovered (or %NULL) + * Returns: The number of configured links (or 0 for non-MLD) + * + * Parses the basic ML element of the BSS into @link_info using the scan + * information stored in the wpa_supplicant data to fill in information for + * links where possible. The @missing_links out parameter will contain any links + * for which no corresponding BSS was found. + */ +int wpa_bss_parse_basic_ml_element(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss, + u8 *ap_mld_addr, + u16 *missing_links) +{ + struct ieee802_11_elems elems; + struct wpabuf *mlbuf; + const struct element *elem; + u8 mbssid_idx = 0; + u8 ml_ie_len; + struct ieee80211_eht_ml *eht_ml; + struct eht_ml_basic_common_info *ml_basic_common_info; + u8 i; + const u16 control_mask = + MULTI_LINK_CONTROL_TYPE_MASK | + BASIC_MULTI_LINK_CTRL_PRES_LINK_ID | + BASIC_MULTI_LINK_CTRL_PRES_BSS_PARAM_CH_COUNT | + BASIC_MULTI_LINK_CTRL_PRES_MLD_CAPA; + const u16 control = + MULTI_LINK_CONTROL_TYPE_BASIC | + BASIC_MULTI_LINK_CTRL_PRES_LINK_ID | + BASIC_MULTI_LINK_CTRL_PRES_BSS_PARAM_CH_COUNT | + BASIC_MULTI_LINK_CTRL_PRES_MLD_CAPA; + u16 missing = 0; + u16 seen; + const u8 *ies_pos = wpa_bss_ie_ptr(bss); + size_t ies_len = bss->ie_len ? bss->ie_len : bss->beacon_ie_len; + int ret = -1; + + + if (ieee802_11_parse_elems(ies_pos, ies_len, &elems, 1) == ParseFailed) { + wpa_dbg(wpa_s, MSG_DEBUG, "MLD: failed to parse elements"); + return ret; + } + + mlbuf = ieee802_11_defrag_mle(&elems, MULTI_LINK_CONTROL_TYPE_BASIC); + if (!mlbuf) { + wpa_dbg(wpa_s, MSG_DEBUG, "MLD: no ML element"); + return ret; + } + + ml_ie_len = wpabuf_len(mlbuf); + + /* + * for ext ID + 2 control + common info len + MLD address + + * link info + */ + if (ml_ie_len < 2UL + 1UL + ETH_ALEN + 1UL) + goto out; + + eht_ml = (struct ieee80211_eht_ml *)wpabuf_head(mlbuf); + if ((le_to_host16(eht_ml->ml_control) & control_mask) != control) { + wpa_printf(MSG_DEBUG, "MLD: unexpected ML element control=0x%x", + le_to_host16(eht_ml->ml_control)); + goto out; + } + + ml_basic_common_info = + (struct eht_ml_basic_common_info *)eht_ml->variable; + + /* common info length should be valid */ + if (ml_basic_common_info->len < ETH_ALEN + 1UL) + goto out; + + /* get the MLD address and MLD link ID */ + if (ap_mld_addr) + os_memcpy(ap_mld_addr, ml_basic_common_info->mld_addr, + ETH_ALEN); + + bss->n_mld_links = 0; + bss->mld_links[bss->n_mld_links].link_id = + ml_basic_common_info->variable[0] & EHT_ML_LINK_ID_MSK; + os_memcpy(bss->mld_links[bss->n_mld_links].bssid, bss->bssid, ETH_ALEN); + bss->mld_links[bss->n_mld_links].freq = bss->freq; + + seen = BIT(ml_basic_common_info->variable[0] & EHT_ML_LINK_ID_MSK); + bss->n_mld_links++; + + /* + * The AP MLD ID in the RNR corresponds to the MBSSID index see + * 802.11beD3.0 section 9.4.2.170.2. + * + * For the transmitting BSSID it is clear that both the MBSSID index + * and the AP MLD ID in the RNR are zero. + * + * For nontransmitted BSSIDs we will have a BSS generated from the + * MBSSID element(s) using inheritance rules. Included in the elements + * is the MBSSID Index Element. The RNR is copied from the beacon/probe + * response that was send by the transmitting BSSID. As such, the + * reported AP MLD ID in the RNR will match the value in the MBSSID + * Index Element. + */ + elem = (void *)wpa_bss_get_ie(bss, WLAN_EID_MULTIPLE_BSSID_INDEX); + if (elem && elem->datalen >= 1) + mbssid_idx = elem->data[0]; + + for_each_element_id(elem, WLAN_EID_REDUCED_NEIGHBOR_REPORT, + wpa_bss_ie_ptr(bss), + bss->ie_len ? bss->ie_len : bss->beacon_ie_len) { + struct ieee80211_neighbor_ap_info *ap_info; + const u8 *pos = elem->data; + size_t len = elem->datalen; + + /* RNR IE may contain more than one NEIGHBOR_AP_INFO */ + while (sizeof(*ap_info) <= len) { + size_t ap_info_len = sizeof(*ap_info); + u8 count; + + ap_info = (void *)pos; + count = RNR_TBTT_INFO_COUNT_VAL(ap_info->tbtt_info_hdr) + 1; + ap_info_len += count * ap_info->tbtt_info_len; + + if (ap_info_len > len) + goto out; + + wpa_bss_parse_ml_rnr_ap_info(wpa_s, bss, mbssid_idx, + ap_info, &seen, + &missing); + + pos += ap_info_len; + len -= ap_info_len; + } + } + + wpa_printf(MSG_DEBUG, "MLD: n_mld_links=%u (unresolved: 0x%04hx)", + bss->n_mld_links, missing); + + for (i = 0; i < bss->n_mld_links; i++) { + wpa_printf(MSG_DEBUG, "MLD: link=%u, bssid=" MACSTR, + bss->mld_links[i].link_id, + MAC2STR(bss->mld_links[i].bssid)); + } + + if (missing_links) + *missing_links = missing; + + ret = 0; +out: + wpabuf_free(mlbuf); + return ret; +} diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h index 611da88444..291f02b912 100644 --- a/wpa_supplicant/bss.h +++ b/wpa_supplicant/bss.h @@ -124,6 +124,15 @@ struct wpa_bss { size_t beacon_ie_len; /** MLD address of the AP */ u8 mld_addr[ETH_ALEN]; + + /** An array of MLD links */ + u8 n_mld_links; + struct + { + u8 link_id; + u8 bssid[ETH_ALEN]; + int freq; + } mld_links [MAX_NUM_MLD_LINKS]; /* followed by ie_len octets of IEs */ /* followed by beacon_ie_len octets of IEs */ u8 ies[]; @@ -202,5 +211,8 @@ void calculate_update_time(const struct os_reltime *fetch_time, struct os_reltime *update_time); struct wpabuf * wpa_bss_defrag_mle(const struct wpa_bss *bss, u8 type); - +int wpa_bss_parse_basic_ml_element(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss, + u8 *ap_mld_addr, + u16 *missing_links); #endif /* BSS_H */ diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 9abfeb2168..e9d04ce70e 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -11913,6 +11913,80 @@ static int wpas_ctrl_iface_mlo_status(struct wpa_supplicant *wpa_s, } +#ifdef CONFIG_TESTING_OPTIONS +static int wpas_ctrl_ml_probe(struct wpa_supplicant *wpa_s, char *cmd) +{ + char *token, *context = NULL; + u8 bssid[ETH_ALEN]; + int mld_id = -1, link_id = -1; + struct wpa_bss *bss; + + os_memset(bssid, 0, sizeof(bssid)); + + while ((token = str_token(cmd, " ", &context))) { + if (os_strncmp(token, "bssid=", 6) == 0) { + if (hwaddr_aton(token + 6, bssid)) + return -1; + } else if (os_strncmp(token, "mld_id=", 7) == 0) { + mld_id = atoi(token + 7); + } else if (os_strncmp(token, "link_id=", 8) == 0) { + link_id = atoi(token + 8); + } + } + + if (mld_id < 0 || is_zero_ether_addr(bssid)) { + wpa_printf(MSG_DEBUG, + "MLD: failed parsing ML probe request args"); + return -1; + } + + bss = wpa_bss_get_bssid(wpa_s, bssid); + if (!bss) { + wpa_printf(MSG_DEBUG, + "MLD: unknown BSS for " MACSTR, MAC2STR(bssid)); + return -1; + } + + if (!wpa_s->sched_scanning && !wpa_s->scanning && + ((wpa_s->wpa_state <= WPA_SCANNING) || + (wpa_s->wpa_state == WPA_COMPLETED))) { + int *freqs = os_malloc(sizeof(int) * 2); + + if (!freqs) + return -1; + + freqs[0] = bss->freq; + freqs[1] = 0; + + wpa_s->manual_scan_passive = 0; + wpa_s->manual_scan_use_id = 0; + wpa_s->manual_scan_only_new = 0; + wpa_s->scan_id_count = 0; + wpa_s->scan_res_handler = scan_only_handler; + os_free(wpa_s->manual_scan_freqs); + wpa_s->manual_scan_freqs = freqs; + + os_memcpy(wpa_s->ml_probe_bssid, bssid, ETH_ALEN); + wpa_s->ml_probe_mld_id = mld_id; + if (link_id >= 0) + wpa_s->ml_probe_links = BIT(link_id); + + wpa_s->normal_scans = 0; + wpa_s->scan_req = MANUAL_SCAN_REQ; + wpa_s->after_wps = 0; + wpa_s->known_wps_freq = 0; + wpa_supplicant_req_scan(wpa_s, 0, 0); + } else { + wpa_printf(MSG_DEBUG, + "MLO: Ongoing scan: reject ML probe request"); + return -1; + } + + return 0; +} +#endif /* CONFIG_TESTING_OPTIONS */ + + char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, char *buf, size_t *resp_len) { @@ -12718,6 +12792,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, } else if (os_strcmp(buf, "TWT_TEARDOWN") == 0) { if (wpas_ctrl_iface_send_twt_teardown(wpa_s, "")) reply_len = -1; + } else if (os_strncmp(buf, "ML_PROBE_REQ ", 8) == 0) { + if (wpas_ctrl_ml_probe(wpa_s, buf + 13)) + reply_len = -1; #endif /* CONFIG_TESTING_OPTIONS */ } else if (os_strncmp(buf, "VENDOR_ELEM_ADD ", 16) == 0) { if (wpas_ctrl_vendor_elem_add(wpa_s, buf + 16) < 0) diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index e7aaa1a128..b666d7b202 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -1831,6 +1831,78 @@ static void wpa_supplicant_req_new_scan(struct wpa_supplicant *wpa_s, } +static u32 ml_link_probe_scan(struct wpa_supplicant *wpa_s) +{ + if (!wpa_s->ml_connect_probe_ssid || !wpa_s->ml_connect_probe_bss) + return 0; + + wpa_msg(wpa_s, MSG_DEBUG, + "Request association with " MACSTR " after ML probe", + MAC2STR(wpa_s->ml_connect_probe_bss->bssid)); + + wpa_supplicant_associate(wpa_s, + wpa_s->ml_connect_probe_bss, + wpa_s->ml_connect_probe_ssid); + + wpa_s->ml_connect_probe_ssid = NULL; + wpa_s->ml_connect_probe_bss = NULL; + + return 1; +} + + +static int wpa_supplicant_connect_ml_missing(struct wpa_supplicant *wpa_s, + struct wpa_bss *selected, + struct wpa_ssid *ssid) +{ + int *freqs; + u16 missing_links = 0; + + if (!((wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO) && + (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))) + return 0; + + /* Try to resolve any missing link information */ + if (wpa_bss_parse_basic_ml_element(wpa_s, selected, NULL, + &missing_links) || !missing_links) + return 0; + + wpa_dbg(wpa_s, MSG_DEBUG, + "MLD: Doing an ML probe for missing links 0x%04x", + missing_links); + + freqs = os_malloc(sizeof(int) * 2); + if (!freqs) + return 0; + + wpa_s->ml_connect_probe_ssid = ssid; + wpa_s->ml_connect_probe_bss = selected; + + freqs[0] = selected->freq; + freqs[1] = 0; + + wpa_s->manual_scan_passive = 0; + wpa_s->manual_scan_use_id = 0; + wpa_s->manual_scan_only_new = 0; + wpa_s->scan_id_count = 0; + os_free(wpa_s->manual_scan_freqs); + wpa_s->manual_scan_freqs = freqs; + + os_memcpy(wpa_s->ml_probe_bssid, selected->bssid, + ETH_ALEN); + wpa_s->ml_probe_mld_id = -1; + wpa_s->ml_probe_links = missing_links; + + wpa_s->normal_scans = 0; + wpa_s->scan_req = MANUAL_SCAN_REQ; + wpa_s->after_wps = 0; + wpa_s->known_wps_freq = 0; + wpa_supplicant_req_scan(wpa_s, 0, 0); + + return 1; +} + + int wpa_supplicant_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *selected, struct wpa_ssid *ssid) @@ -1887,6 +1959,10 @@ int wpa_supplicant_connect(struct wpa_supplicant *wpa_s, wpa_supplicant_req_new_scan(wpa_s, 10, 0); return 0; } + + if (wpa_supplicant_connect_ml_missing(wpa_s, selected, ssid)) + return 0; + wpa_msg(wpa_s, MSG_DEBUG, "Request association with " MACSTR, MAC2STR(selected->bssid)); wpa_supplicant_associate(wpa_s, selected, ssid); @@ -2308,6 +2384,9 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, wpas_beacon_rep_scan_process(wpa_s, scan_res, &data->scan_info) > 0) goto scan_work_done; + if (ml_link_probe_scan(wpa_s) > 0) + goto scan_work_done; + if ((wpa_s->conf->ap_scan == 2 && !wpas_wps_searching(wpa_s))) goto scan_work_done; diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c index 4b4a34b52d..ae00ee9d28 100644 --- a/wpa_supplicant/notify.c +++ b/wpa_supplicant/notify.c @@ -396,6 +396,10 @@ void wpas_notify_network_removed(struct wpa_supplicant *wpa_s, wpa_s->last_ssid = NULL; if (wpa_s->current_ssid == ssid) wpa_s->current_ssid = NULL; + if (wpa_s->ml_connect_probe_ssid == ssid) { + wpa_s->ml_connect_probe_ssid = NULL; + wpa_s->ml_connect_probe_bss = NULL; + } #if defined(CONFIG_SME) && defined(CONFIG_SAE) if (wpa_s->sme.ext_auth_wpa_ssid == ssid) wpa_s->sme.ext_auth_wpa_ssid = NULL; diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index 166751a1f2..a38d1ae32c 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -649,6 +649,69 @@ void wpa_supplicant_set_default_scan_ies(struct wpa_supplicant *wpa_s) } +static struct wpabuf * wpa_supplicant_ml_probe_ie(int mld_id, u16 links) +{ + struct wpabuf *extra_ie; + u16 control = MULTI_LINK_CONTROL_TYPE_PROBE_REQ; + u8 len = 4; + u8 link_id; + + if (mld_id >= 0) { + control |= EHT_ML_PRES_BM_PROBE_REQ_AP_MLD_ID; + len += 1; + } + + len += 4 * (popcount(links & 0xff) + popcount((links >> 8) & 0xff)); + + extra_ie = wpabuf_alloc(len + 2); + if (!extra_ie) + return NULL; + + wpabuf_put_u8(extra_ie, WLAN_EID_EXTENSION); + wpabuf_put_u8(extra_ie, len); + wpabuf_put_u8(extra_ie, WLAN_EID_EXT_MULTI_LINK); + + wpabuf_put_le16(extra_ie, control); + + /* common info length and MLD ID (if requested) */ + if (mld_id >= 0) { + wpabuf_put_u8(extra_ie, 2); + wpabuf_put_u8(extra_ie, mld_id); + + wpa_printf(MSG_DEBUG, + "MLD: ML probe targeted at MLD ID %d", mld_id); + } else { + wpabuf_put_u8(extra_ie, 1); + + wpa_printf(MSG_DEBUG, + "MLD: ML probe targeted at receiving AP"); + } + + if (!links) + wpa_printf(MSG_DEBUG, + "MLD: Probing all links"); + else + wpa_printf(MSG_DEBUG, + "MLD: Probing links 0x%04x", links); + + for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) { + if (!(links & BIT(link_id))) + continue; + + wpabuf_put_u8(extra_ie, EHT_ML_SUB_ELEM_PER_STA_PROFILE); + + /* sub-element length includes only the control */ + wpabuf_put_u8(extra_ie, 2); + + control = link_id | EHT_PER_STA_CTRL_COMPLETE_PROFILE_MSK; + + wpabuf_put_le16(extra_ie, control); + } + + return extra_ie; +} + + static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s) { struct wpabuf *extra_ie = NULL; @@ -659,6 +722,15 @@ static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s) enum wps_request_type req_type = WPS_REQ_ENROLLEE_INFO; #endif /* CONFIG_WPS */ + if (!is_zero_ether_addr(wpa_s->ml_probe_bssid)) { + extra_ie = wpa_supplicant_ml_probe_ie(wpa_s->ml_probe_mld_id, + wpa_s->ml_probe_links); + + /* No other elements should be included in the probe request */ + wpa_printf(MSG_DEBUG, "MLD: scan: including only ML element"); + return extra_ie; + } + #ifdef CONFIG_P2P if (wpa_s->p2p_group_interface == P2P_GROUP_INTERFACE_CLIENT) wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT); @@ -1397,8 +1469,13 @@ ssid_list_set: "Scan a previously specified BSSID " MACSTR, MAC2STR(params.bssid)); } + } else if (!is_zero_ether_addr(wpa_s->ml_probe_bssid)) { + wpa_printf(MSG_DEBUG, "Scanning for ML probe request"); + params.bssid = wpa_s->ml_probe_bssid; + params.min_probe_req_content = true; } + if (wpa_s->last_scan_req == MANUAL_SCAN_REQ && wpa_s->manual_non_coloc_6ghz) { wpa_dbg(wpa_s, MSG_DEBUG, "Collocated 6 GHz logic is disabled"); @@ -1480,6 +1557,11 @@ scan: if (params.bssid) os_memset(wpa_s->next_scan_bssid, 0, ETH_ALEN); } + + wpa_s->ml_probe_mld_id = -1; + wpa_s->ml_probe_links = 0; + os_memset(wpa_s->ml_probe_bssid, 0, + sizeof(wpa_s->ml_probe_bssid)); } diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index effc7b3bc2..43ee050f41 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -2095,6 +2095,13 @@ static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return wpa_ctrl_command(ctrl, "DROP_SA"); } + + +static int wpa_cli_cmd_ml_probe_req(struct wpa_ctrl *ctrl, + int argc, char *argv[]) +{ + return wpa_cli_cmd(ctrl, "ML_PROBE_REQ", 2, argc, argv); +} #endif /* CONFIG_TESTING_OPTIONS */ @@ -3673,6 +3680,8 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = { #ifdef CONFIG_TESTING_OPTIONS { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none, "= drop SA without deauth/disassoc (test command)" }, + { "ml_probe_req", wpa_cli_cmd_ml_probe_req, NULL, cli_cmd_flag_none, + "= send Multi-Link Probe request [link_id=id] (test command)" }, #endif /* CONFIG_TESTING_OPTIONS */ { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss, cli_cmd_flag_none, diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index e0f3240e87..0092c024b1 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -4429,6 +4429,8 @@ static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s, { struct wpa_ssid *old_ssid; + wpa_s->ml_connect_probe_ssid = NULL; + wpa_s->ml_connect_probe_bss = NULL; wpas_connect_work_done(wpa_s); wpa_clear_keys(wpa_s, addr); old_ssid = wpa_s->current_ssid; @@ -5741,6 +5743,7 @@ wpa_supplicant_alloc(struct wpa_supplicant *parent) dl_list_init(&wpa_s->drv_signal_override); #endif /* CONFIG_TESTING_OPTIONS */ dl_list_init(&wpa_s->active_scs_ids); + wpa_s->ml_probe_mld_id = -1; return wpa_s; } diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index d5b3dab67f..89bc2882d0 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -869,6 +869,10 @@ struct wpa_supplicant { unsigned int suitable_network; unsigned int no_suitable_network; + u8 ml_probe_bssid[ETH_ALEN]; + int ml_probe_mld_id; + u16 ml_probe_links; + u64 drv_flags; u64 drv_flags2; unsigned int drv_enc; @@ -1529,6 +1533,9 @@ struct wpa_supplicant { unsigned int wait_for_dscp_req:1; struct wpa_signal_info last_signal_info; + + struct wpa_ssid *ml_connect_probe_ssid; + struct wpa_bss *ml_connect_probe_bss; }; From patchwork Mon Jun 12 19:59:50 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrei Otcheretianski X-Patchwork-Id: 1794050 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org 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=) 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=yeSuvRnF; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=L511Nrnr; dkim-atps=neutral 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 (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4Qg2cz51lGz20XR for ; Tue, 13 Jun 2023 06:01:23 +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=4LNnaUM5CHZgNyDUZCSa7TG+VQENJIZH/sgyrHsfvp8=; b=yeSuvRnF18lL6V VEXa9nD1bfGcm/0ce8Va0CRMqnrX9CD+/SfROs/od3Ih/vu+cvhkakTGIT36665rWIneaxZLSDYlN ik1hAEZZ1uRJnufg7MrlVBRvk24vY89L+MylgFXc4Kijc1TfWPmvnCNXksUnJ/ub2+gZ3fpl+1/S8 q6NBVz7hPGjNe89NPBN5Jw7k35mK3no//YorNdYmz17GaxNnCCmPdIIDfojb63Y7A9g3J2NxfNoea 4aLXinsmgPIdSsHYzYRumt/3RbOHub26CgEoZs9y3hDBSmuGM/FOhr9L7VkrUjCbPErjvTu1c8Nfa FNH1L3gyE01mOoljjjZA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1q8niC-005Ce9-0C; Mon, 12 Jun 2023 20:00:24 +0000 Received: from mga02.intel.com ([134.134.136.20]) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1q8ni8-005Caa-2e for hostap@lists.infradead.org; Mon, 12 Jun 2023 20:00:22 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1686600020; x=1718136020; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=TDsW51Ay21NK77FwqtNydPKAN5qaPpL1tZF2k2MNNY4=; b=L511Nrnrkq1y1xRa37L2O3V4L+u87gyZoMOP/kvQUdAIGIMBCY80wtGV Pl6zAIeSJ7hOMzJNN7RJ8e3ou6hn9zcB7QzyQSPDSSFycqghKe3XuMlfW LEI/f+58+4q8ASmrVTDa0Lw/m85uktCGW1M6VjLSLdDbWfZYSWMOGMUI/ qQKMsUckNjY91y+qia8BiPFKvmLA8926ivuVSgt1JpxQrB9uWgJ0zG+t0 sIqnGUAwaznFBm80Mzd26ffoorIZmkY7HSASWYDco2ULt5u9wQ1ytjS53 ihaC8uC00txXGVu6cFHloGcn1ebk/9aLk0o9WWwk/QG9eus+vOK+kWC4U Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10739"; a="347800479" X-IronPort-AV: E=Sophos;i="6.00,236,1681196400"; d="scan'208";a="347800479" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Jun 2023 13:00:16 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10739"; a="741156717" X-IronPort-AV: E=Sophos;i="6.00,236,1681196400"; d="scan'208";a="741156717" Received: from masharut-mobl.ger.corp.intel.com (HELO aotchere-desk.intel.com) ([10.254.152.129]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Jun 2023 13:00:11 -0700 From: Andrei Otcheretianski To: hostap@lists.infradead.org Cc: Andrei Otcheretianski , Ilan Peer Subject: [PATCH 3/3] SME: MLD: Handle reconfiguration Multi-Link element Date: Mon, 12 Jun 2023 22:59:50 +0300 Message-Id: <20230612195950.60468-3-andrei.otcheretianski@intel.com> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20230612195950.60468-1-andrei.otcheretianski@intel.com> References: <20230612195950.60468-1-andrei.otcheretianski@intel.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230612_130020_939588_2AF1F492 X-CRM114-Status: GOOD ( 21.33 ) X-Spam-Score: -2.7 (--) 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: Parse the reconfiguration Multi-Link element and: - Don't select a BSS for connection if it is part of an MLD and is going to be removed. - Don't scan for missing links that are to be removed. - Don't include removed links in association. Content analysis details: (-2.7 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RCVD_IN_MSPIKE_H3 RBL: Good reputation (+3) [134.134.136.20 listed in wl.mailspike.net] -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at https://www.dnswl.org/, medium trust [134.134.136.20 listed in list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 SPF_NONE SPF: sender does not publish an SPF Record -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 -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.0 RCVD_IN_MSPIKE_WL Mailspike good senders -0.2 DKIMWL_WL_HIGH DKIMwl.org - High trust sender 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 Parse the reconfiguration Multi-Link element and: - Don't select a BSS for connection if it is part of an MLD and is going to be removed. - Don't scan for missing links that are to be removed. - Don't include removed links in association. Signed-off-by: Ilan Peer Signed-off-by: Andrei Otcheretianski --- src/common/ieee802_11_defs.h | 9 ++++ wpa_supplicant/bss.c | 80 ++++++++++++++++++++++++++++++++++++ wpa_supplicant/bss.h | 2 + wpa_supplicant/events.c | 36 +++++++++++++++- wpa_supplicant/sme.c | 10 +++++ 5 files changed, 136 insertions(+), 1 deletion(-) diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index e36f6db139..a93d5e742d 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -2674,6 +2674,15 @@ struct eht_ml_basic_common_info { #define EHT_PER_STA_CTRL_NSTR_BM_SIZE_MSK 0x0400 #define EHT_PER_STA_CTRL_BSS_PARAM_CNT_PRESENT_MSK 0x0800 +#define RECONF_MULTI_LINK_CTRL_PRES_MLD_MAC_ADDR 0x0001 + +#define EHT_PER_STA_RECONF_CTRL_LINK_ID_MSK 0x000f +#define EHT_PER_STA_RECONF_CTRL_COMPLETE_PROFILE 0x0010 +#define EHT_PER_STA_RECONF_CTRL_MAC_ADDR 0x0020 +#define EHT_PER_STA_RECONF_CTRL_AP_REMOVAL_TIMER 0x0040 +#define EHT_PER_STA_RECONF_CTRL_OP_UPDATE_TYPE_MSK 0x0780 +#define EHT_PER_STA_RECONF_CTRL_OP_PARAMS 0x0800 + /* IEEE P802.11be/D2.0, 9.4.2.312.2.4 - Per-STA Profile subelement format */ struct ieee80211_eht_per_sta_profile { le16 sta_control; diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c index 1aa490bcbc..9d3f0fe308 100644 --- a/wpa_supplicant/bss.c +++ b/wpa_supplicant/bss.c @@ -1697,3 +1697,83 @@ out: wpabuf_free(mlbuf); return ret; } + + +/* + * wpa_bss_parse_reconf_ml_element - Parse the reconfiguration ML element + * @wpa_s: Pointer to wpa_supplicant data + * @bss: BSS table entry + * Returns: The bitmap of links that are going to be removed + */ +u16 wpa_bss_parse_reconf_ml_element(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss) +{ + struct ieee802_11_elems elems; + struct wpabuf *mlbuf; + const u8 *pos = wpa_bss_ie_ptr(bss); + size_t len = bss->ie_len ? bss->ie_len : bss->beacon_ie_len; + struct ieee80211_eht_ml *ml; + u16 removed_links = 0; + u8 ml_common_len; + + if (ieee802_11_parse_elems(pos, len, &elems, 1) == ParseFailed) + return 0; + + if (!elems.reconf_mle || !elems.reconf_mle_len) + return 0; + + mlbuf = ieee802_11_defrag_mle(&elems, MULTI_LINK_CONTROL_TYPE_RECONF); + if (!mlbuf) + return 0; + + ml = (struct ieee80211_eht_ml *)wpabuf_head(mlbuf); + len = wpabuf_len(mlbuf); + + if (len < sizeof(*ml)) + goto out; + + ml_common_len = 1; + if (ml->ml_control & RECONF_MULTI_LINK_CTRL_PRES_MLD_MAC_ADDR) + ml_common_len += ETH_ALEN; + + if (len < sizeof(*ml) + ml_common_len) { + wpa_printf(MSG_DEBUG, + "MLD: unexpected reconf ML element length: (%zu != %zu)", + len, sizeof(*ml) + ml_common_len); + goto out; + } + + pos = ml->variable + ml_common_len; + len -= sizeof(*ml) + ml_common_len; + + while (len >= 2 + sizeof(struct ieee80211_eht_per_sta_profile)) { + size_t sub_elem_len = *(pos + 1); + + if (2 + sub_elem_len > len) { + wpa_printf(MSG_DEBUG, + "MLD: invalid link info len: %zu %zu", + 2 + sub_elem_len, len); + goto out; + } + + if (*pos == EHT_ML_SUB_ELEM_PER_STA_PROFILE) { + struct ieee80211_eht_per_sta_profile *sta_prof = + (struct ieee80211_eht_per_sta_profile *) + (pos + 2); + u16 control = le_to_host16(sta_prof->sta_control); + u8 link_id = control & + EHT_PER_STA_RECONF_CTRL_LINK_ID_MSK; + + removed_links |= BIT(link_id); + } + + pos += 2 + sub_elem_len; + len -= 2 + sub_elem_len; + } + + wpa_printf(MSG_DEBUG, "MLD: reconfiguration: removed_links=0x%x", + removed_links); +out: + wpabuf_free(mlbuf); + return removed_links; +} diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h index 291f02b912..b93a5eea46 100644 --- a/wpa_supplicant/bss.h +++ b/wpa_supplicant/bss.h @@ -215,4 +215,6 @@ int wpa_bss_parse_basic_ml_element(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, u8 *ap_mld_addr, u16 *missing_links); +u16 wpa_bss_parse_reconf_ml_element(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss); #endif /* BSS_H */ diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index b666d7b202..b8e59c727d 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -1176,6 +1176,27 @@ static void owe_trans_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, } +static int wpas_valid_ml_bss(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss) + +{ + u16 removed_links; + + if (wpa_bss_parse_basic_ml_element(wpa_s, bss, NULL, NULL)) + return 0; + + if (bss->n_mld_links == 0) + return 0; + + /* Check if the current BSS is going to be removed */ + removed_links = wpa_bss_parse_reconf_ml_element(wpa_s, bss); + if (BIT(bss->mld_links[0].link_id) & removed_links) + return -1; + + return 0; +} + + int disabled_freq(struct wpa_supplicant *wpa_s, int freq) { int i, j; @@ -1578,6 +1599,13 @@ skip_assoc_disallow: return false; } + if (wpas_valid_ml_bss(wpa_s, bss) < 0) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - ML BSS going to be removed"); + return false; + } + /* Matching configuration found */ return true; } @@ -1856,7 +1884,7 @@ static int wpa_supplicant_connect_ml_missing(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) { int *freqs; - u16 missing_links = 0; + u16 missing_links = 0, removed_links; if (!((wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO) && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))) @@ -1867,6 +1895,12 @@ static int wpa_supplicant_connect_ml_missing(struct wpa_supplicant *wpa_s, &missing_links) || !missing_links) return 0; + removed_links = wpa_bss_parse_reconf_ml_element(wpa_s, selected); + missing_links &= ~removed_links; + + if (!missing_links) + return 0; + wpa_dbg(wpa_s, MSG_DEBUG, "MLD: Doing an ML probe for missing links 0x%04x", missing_links); diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index 4ed0a3003f..1acd415bc5 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -541,6 +541,15 @@ out: } +static void wpas_ml_handle_removed_links(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss) +{ + u16 removed_links = wpa_bss_parse_reconf_ml_element(wpa_s, bss); + + wpa_s->valid_links &= ~removed_links; +} + + static void wpas_sme_ml_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data, int ie_offset) @@ -639,6 +648,7 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s, params.mld = true; params.mld_link_id = wpa_s->mlo_assoc_link_id; params.ap_mld_addr = wpa_s->ap_mld_addr; + wpas_ml_handle_removed_links(wpa_s, bss); } if (wpa_s->sme.ssid_len != params.ssid_len ||