diff mbox series

[2/4] ctrl: enable roaming between OWE APs

Message ID 20240331195643.47587-2-mail@david-bauer.net
State Superseded, archived
Headers show
Series [1/4] wpa_supplicant: reduce OWE transition network code duplication | expand

Commit Message

David Bauer March 31, 2024, 7:56 p.m. UTC
This allows to use the roam command with wpa_cli to force roaming on a
transition network. Previously, this was not possible, as the open SSID
is stored for the connection profile. Add a new function to also return
OWE transition networks if the profile SSID is set as the
transition-ssid for the OWE RSN network.

Signed-off-by: David Bauer <mail@david-bauer.net>
---
 wpa_supplicant/bss.c        | 43 +++++++++++++++++++++++++++++++++++++
 wpa_supplicant/bss.h        |  2 ++
 wpa_supplicant/ctrl_iface.c |  2 +-
 3 files changed, 46 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c
index c213d15ad..85eb6e431 100644
--- a/wpa_supplicant/bss.c
+++ b/wpa_supplicant/bss.c
@@ -273,6 +273,49 @@  struct wpa_bss * wpa_bss_get(struct wpa_supplicant *wpa_s, const u8 *bssid,
 	return NULL;
 }
 
+/**
+ * wpa_bss_get_connection - Fetch a BSS table entry based on BSSID and SSID.
+ * This function is similar to wpa_bss_get() but it will also return OWE-TM
+ * encrypted networks which transition-element matches @ssid.
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @bssid: BSSID, or %NULL to match any BSSID
+ * @ssid: SSID
+ * @ssid_len: Length of @ssid
+ * Returns: Pointer to the BSS entry or %NULL if not found
+ */
+struct wpa_bss * wpa_bss_get_connection(struct wpa_supplicant *wpa_s, const u8 *bssid,
+					const u8 *ssid, size_t ssid_len)
+{
+	struct wpa_bss *bss;
+	const u8 *owe, *owe_bssid, *owe_ssid;
+	size_t owe_ssid_len;
+
+	if (bssid && !wpa_supplicant_filter_bssid_match(wpa_s, bssid))
+		return NULL;
+	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
+		if (bssid && os_memcmp(bss->bssid, bssid, ETH_ALEN) != 0)
+			continue;
+
+		if (bss->ssid_len == ssid_len &&
+		    os_memcmp(bss->ssid, ssid, ssid_len) == 0)
+			return bss;
+
+		/* Check if OWE-TM element is present and matches the SSID */
+		owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
+		if (!owe)
+			continue;
+
+		if (wpa_bss_get_owe_trans_network(wpa_s, owe, &owe_bssid, &owe_ssid,
+						  &owe_ssid_len))
+			continue;
+
+		if (owe_ssid_len == ssid_len &&
+		    os_memcmp(owe_ssid, ssid, ssid_len) == 0)
+			return bss;
+	}
+	return NULL;
+}
+
 
 void calculate_update_time(const struct os_reltime *fetch_time,
 			   unsigned int age_ms,
diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h
index 8acedbce7..fa72d7406 100644
--- a/wpa_supplicant/bss.h
+++ b/wpa_supplicant/bss.h
@@ -165,6 +165,8 @@  void wpa_bss_flush(struct wpa_supplicant *wpa_s);
 void wpa_bss_flush_by_age(struct wpa_supplicant *wpa_s, int age);
 struct wpa_bss * wpa_bss_get(struct wpa_supplicant *wpa_s, const u8 *bssid,
 			     const u8 *ssid, size_t ssid_len);
+struct wpa_bss * wpa_bss_get_connection(struct wpa_supplicant *wpa_s, const u8 *bssid,
+					const u8 *ssid, size_t ssid_len);
 struct wpa_bss * wpa_bss_get_bssid(struct wpa_supplicant *wpa_s,
 				   const u8 *bssid);
 struct wpa_bss * wpa_bss_get_bssid_latest(struct wpa_supplicant *wpa_s,
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index d0fda4cd9..ebe212cd7 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -6011,7 +6011,7 @@  static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s,
 		return -1;
 	}
 
-	bss = wpa_bss_get(wpa_s, bssid, ssid->ssid, ssid->ssid_len);
+	bss = wpa_bss_get_connection(wpa_s, bssid, ssid->ssid, ssid->ssid_len);
 	if (!bss) {
 		wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found "
 			   "from BSS table");