[PATCH 1/7] wifi: cfg80211: report authorized connect and roam events

Jason Huang <[email protected]> Tue, 4 Aug 2026 11:04:48 +0800
Newsgroups org.kernel.vger.linux-wireless,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
From: Jason Huang <[email protected]>

Drivers that offload the 802.1X/FT key exchange can know that
the link is ready for data traffic when reporting a successful
connect or roam event. Carry that state through cfg80211 and
include NL80211_ATTR_PORT_AUTHORIZED in the corresponding nl80211
notification when the driver provides it.

This lets userspace avoid restarting authentication state machines
after firmware has already completed the security exchange during
offloaded roaming.

Assisted-by: GitHub Copilot CLI:gpt-5.5
Signed-off-by: Chung-Hsien Hsu <[email protected]>
Signed-off-by: Chi-hsien Lin <[email protected]>
Signed-off-by: Jason Huang <[email protected]>
---
 include/net/cfg80211.h       | 6 ++++++
 include/uapi/linux/nl80211.h | 4 +++-
 net/wireless/nl80211.c       | 6 +++++-
 net/wireless/sme.c           | 2 ++
 4 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 97c16d4ff127..7f576bb7325c 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -9103,6 +9103,8 @@ struct cfg80211_fils_resp_params {
  * @assoc_encrypted: The driver should set this flag to indicate that the
  *	(Re)Association Request/Response frames are transmitted encrypted over
  *	the air.
+ * @authorized: Indicates whether the connection is ready to transport data
+ *	packets.
  */
 struct cfg80211_connect_resp_params {
 	int status;
@@ -9113,6 +9115,7 @@ struct cfg80211_connect_resp_params {
 	struct cfg80211_fils_resp_params fils;
 	enum nl80211_timeout_reason timeout_reason;
 	bool assoc_encrypted;
+	bool authorized;
 
 	const u8 *ap_mld_addr;
 	u16 valid_links;
@@ -9281,6 +9284,8 @@ cfg80211_connect_timeout(struct net_device *dev, const u8 *bssid,
  * @links.bss: For MLO roaming, entry of new bss to which STA link got
  *	roamed. For non-MLO roaming, links[0].bss points to entry of bss to
  *	which STA got roamed (may be %NULL if %links.bssid is set)
+ * @authorized: Indicates whether the new connection is ready to transport data
+ *	packets.
  */
 struct cfg80211_roam_info {
 	const u8 *req_ie;
@@ -9297,6 +9302,7 @@ struct cfg80211_roam_info {
 		struct ieee80211_channel *channel;
 		struct cfg80211_bss *bss;
 	} links[IEEE80211_MLD_MAX_NUM_LINKS];
+	bool authorized;
 };
 
 /**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 020387d76412..66b4cfd8de86 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2705,7 +2705,9 @@ enum nl80211_commands {
  *	in %NL80211_CMD_CONNECT to indicate that for 802.1X authentication it
  *	wants to use the supported offload of the 4-way handshake.
  * @NL80211_ATTR_PMKR0_NAME: PMK-R0 Name for offloaded FT.
- * @NL80211_ATTR_PORT_AUTHORIZED: (reserved)
+ * @NL80211_ATTR_PORT_AUTHORIZED: flag attribute used in %NL80211_CMD_CONNECT
+ *	or %NL80211_CMD_ROAM notifications to indicate that 802.1X
+ *	authentication was done by the driver or is not needed.
  *
  * @NL80211_ATTR_EXTERNAL_AUTH_ACTION: Identify the requested external
  *     authentication operation (u32 attribute with an
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 44f2bad08670..55161ddb56b4 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -21198,6 +21198,8 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
 	     (nla_put_flag(msg, NL80211_ATTR_TIMED_OUT) ||
 	      nla_put_u32(msg, NL80211_ATTR_TIMEOUT_REASON,
 			  cr->timeout_reason))) ||
+	    (cr->authorized &&
+	     nla_put_flag(msg, NL80211_ATTR_PORT_AUTHORIZED)) ||
 	    (cr->req_ie &&
 	     nla_put(msg, NL80211_ATTR_REQ_IE, cr->req_ie_len, cr->req_ie)) ||
 	    (cr->resp_ie &&
@@ -21321,7 +21323,9 @@ void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
 	    (info->fils.pmk &&
 	     nla_put(msg, NL80211_ATTR_PMK, info->fils.pmk_len, info->fils.pmk)) ||
 	    (info->fils.pmkid &&
-	     nla_put(msg, NL80211_ATTR_PMKID, WLAN_PMKID_LEN, info->fils.pmkid)))
+	     nla_put(msg, NL80211_ATTR_PMKID, WLAN_PMKID_LEN, info->fils.pmkid)) ||
+	    (info->authorized &&
+	     nla_put_flag(msg, NL80211_ATTR_PORT_AUTHORIZED)))
 		goto nla_put_failure;
 
 	if (info->valid_links) {
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 2a719b5c487e..974e79f57392 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -1067,6 +1067,7 @@ void cfg80211_connect_done(struct net_device *dev,
 	ev->cr.status = params->status;
 	ev->cr.timeout_reason = params->timeout_reason;
 	ev->cr.assoc_encrypted = params->assoc_encrypted;
+	ev->cr.authorized = params->authorized;
 
 	spin_lock_irqsave(&wdev->event_lock, flags);
 	list_add_tail(&ev->list, &wdev->event_list);
@@ -1253,6 +1254,7 @@ void cfg80211_roamed(struct net_device *dev, struct cfg80211_roam_info *info,
 		next += ETH_ALEN;
 	}
 	ev->rm.valid_links = info->valid_links;
+	ev->rm.authorized = info->authorized;
 	for_each_valid_link(info, link) {
 		ev->rm.links[link].bss = info->links[link].bss;
 
-- 
2.25.1