diff mbox series

[v2,26/44] AP/wpa_supplicant/driver: Add link id to send eapol callbacks

Message ID 20230522193412.658666-27-andrei.otcheretianski@intel.com
State Accepted
Headers show
Series Add basic MLO support for AP | expand

Commit Message

Andrei Otcheretianski May 22, 2023, 7:33 p.m. UTC
EAPOL frames may need to be transmitted from the link address and not
MLD address. For example, in case of authentication between MLD AP and
legacy STA. Add link_id parameter to eapol send API's.

Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
---
 src/ap/ap_drv_ops.h          |  4 ++--
 src/ap/ieee802_1x.c          |  7 ++++++-
 src/ap/wpa_auth_glue.c       | 15 +++++++++++++--
 src/drivers/driver.h         |  6 ++++--
 src/drivers/driver_nl80211.c | 12 ++++++++----
 wpa_supplicant/driver_i.h    |  9 +++++----
 wpa_supplicant/ibss_rsn.c    |  4 ++--
 wpa_supplicant/wpas_glue.c   |  2 +-
 8 files changed, 41 insertions(+), 18 deletions(-)
diff mbox series

Patch

diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
index 2aa76385e1..a2c67e0446 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -201,13 +201,13 @@  static inline int hostapd_drv_sta_remove(struct hostapd_data *hapd,
 static inline int hostapd_drv_hapd_send_eapol(struct hostapd_data *hapd,
 					      const u8 *addr, const u8 *data,
 					      size_t data_len, int encrypt,
-					      u32 flags)
+					      u32 flags, int link_id)
 {
 	if (hapd->driver == NULL || hapd->driver->hapd_send_eapol == NULL)
 		return 0;
 	return hapd->driver->hapd_send_eapol(hapd->drv_priv, addr, data,
 					     data_len, encrypt,
-					     hapd->own_addr, flags);
+					     hapd->own_addr, flags, link_id);
 }
 
 static inline int hostapd_drv_read_sta_data(
diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
index 33d47802f6..bacc588de1 100644
--- a/src/ap/ieee802_1x.c
+++ b/src/ap/ieee802_1x.c
@@ -95,9 +95,14 @@  static void ieee802_1x_send(struct hostapd_data *hapd, struct sta_info *sta,
 	if (sta->flags & WLAN_STA_PREAUTH) {
 		rsn_preauth_send(hapd, sta, buf, len);
 	} else {
+		int link = -1;
+
+#ifdef CONFIG_IEEE80211BE
+		link = hapd->conf->mld_ap ? hapd->mld_link_id : -1;
+#endif /* CONFIG_IEEE80211BE */
 		hostapd_drv_hapd_send_eapol(
 			hapd, sta->addr, buf, len,
-			encrypt, hostapd_sta_flags_to_drv(sta->flags));
+			encrypt, hostapd_sta_flags_to_drv(sta->flags), link);
 	}
 
 	os_free(buf);
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index a87d2f3899..8517f6954a 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -522,6 +522,11 @@  int hostapd_wpa_auth_send_eapol(void *ctx, const u8 *addr,
 	struct hostapd_data *hapd = ctx;
 	struct sta_info *sta;
 	u32 flags = 0;
+	int link = -1;
+
+#ifdef CONFIG_IEEE80211BE
+	link = hapd->conf->mld_ap ? hapd->mld_link_id : -1;
+#endif
 
 #ifdef CONFIG_TESTING_OPTIONS
 	if (hapd->ext_eapol_frame_io) {
@@ -539,11 +544,17 @@  int hostapd_wpa_auth_send_eapol(void *ctx, const u8 *addr,
 #endif /* CONFIG_TESTING_OPTIONS */
 
 	sta = ap_get_sta(hapd, addr);
-	if (sta)
+	if (sta) {
 		flags = hostapd_sta_flags_to_drv(sta->flags);
+#ifdef CONFIG_IEEE80211BE
+		if (sta->mld_info.mld_sta &&
+		    (sta->flags & WLAN_STA_AUTHORIZED))
+			link = -1;
+#endif
+	}
 
 	return hostapd_drv_hapd_send_eapol(hapd, addr, data, data_len,
-					   encrypt, flags);
+					   encrypt, flags, link);
 }
 
 
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index b39d04a6fd..785ffd8e80 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -3528,6 +3528,7 @@  struct wpa_driver_ops {
 	 * @buf: Frame payload starting from IEEE 802.1X header
 	 * @len: Frame payload length
 	 * @no_encrypt: Do not encrypt frame
+	 * @link_id: Link ID to use for TX, or -1 if not set
 	 *
 	 * Returns 0 on success, else an error
 	 *
@@ -3545,7 +3546,7 @@  struct wpa_driver_ops {
 	 */
 	int (*tx_control_port)(void *priv, const u8 *dest,
 			       u16 proto, const u8 *buf, size_t len,
-			       int no_encrypt);
+			       int no_encrypt, int link_id);
 
 	/**
 	 * hapd_send_eapol - Send an EAPOL packet (AP only)
@@ -3556,12 +3557,13 @@  struct wpa_driver_ops {
 	 * @encrypt: Whether the frame should be encrypted
 	 * @own_addr: Source MAC address
 	 * @flags: WPA_STA_* flags for the destination station
+	 * @link_id: Link ID to use for TX, or -1 if not set
 	 *
 	 * Returns: 0 on success, -1 on failure
 	 */
 	int (*hapd_send_eapol)(void *priv, const u8 *addr, const u8 *data,
 			       size_t data_len, int encrypt,
-			       const u8 *own_addr, u32 flags);
+			       const u8 *own_addr, u32 flags, int link_id);
 
 	/**
 	 * sta_deauth - Deauthenticate a station (AP only)
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index cb33c92ec7..b6b57de00f 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -6097,7 +6097,7 @@  static void nl80211_teardown_ap(struct i802_bss *bss)
 
 static int nl80211_tx_control_port(void *priv, const u8 *dest,
 				   u16 proto, const u8 *buf, size_t len,
-				   int no_encrypt)
+				   int no_encrypt, int link_id)
 {
 	struct nl80211_ack_ext_arg ext_arg;
 	struct i802_bss *bss = priv;
@@ -6116,7 +6116,9 @@  static int nl80211_tx_control_port(void *priv, const u8 *dest,
 	    nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, dest) ||
 	    nla_put(msg, NL80211_ATTR_FRAME, len, buf) ||
 	    (no_encrypt &&
-	     nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT))) {
+	     nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT)) ||
+	    (link_id != NL80211_DRV_LINK_ID_NA &&
+	     nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id))) {
 		nlmsg_free(msg);
 		return -ENOBUFS;
 	}
@@ -6174,7 +6176,8 @@  static const u8 rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
 
 static int wpa_driver_nl80211_hapd_send_eapol(
 	void *priv, const u8 *addr, const u8 *data,
-	size_t data_len, int encrypt, const u8 *own_addr, u32 flags)
+	size_t data_len, int encrypt, const u8 *own_addr, u32 flags,
+	int link_id)
 {
 	struct i802_bss *bss = priv;
 	struct wpa_driver_nl80211_data *drv = bss->drv;
@@ -6189,7 +6192,8 @@  static int wpa_driver_nl80211_hapd_send_eapol(
 	if (drv->control_port_ap &&
 	    (drv->capa.flags & WPA_DRIVER_FLAGS_CONTROL_PORT))
 		return nl80211_tx_control_port(bss, addr, ETH_P_EAPOL,
-					       data, data_len, !encrypt);
+					       data, data_len, !encrypt,
+					       link_id);
 
 	if (drv->device_ap_sme || !drv->use_monitor)
 		return nl80211_send_eapol_data(bss, addr, data, data_len);
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index 03f413c014..df9fd0a0f2 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -372,23 +372,24 @@  static inline int wpa_drv_sta_remove(struct wpa_supplicant *wpa_s,
 static inline int wpa_drv_tx_control_port(struct wpa_supplicant *wpa_s,
 					  const u8 *dest, u16 proto,
 					  const u8 *buf, size_t len,
-					  int no_encrypt)
+					  int no_encrypt, int link_id)
 {
 	if (!wpa_s->driver->tx_control_port)
 		return -1;
 	return wpa_s->driver->tx_control_port(wpa_s->drv_priv, dest, proto,
-					      buf, len, no_encrypt);
+					      buf, len, no_encrypt, link_id);
 }
 
 static inline int wpa_drv_hapd_send_eapol(struct wpa_supplicant *wpa_s,
 					  const u8 *addr, const u8 *data,
 					  size_t data_len, int encrypt,
-					  const u8 *own_addr, u32 flags)
+					  const u8 *own_addr, u32 flags,
+					  int link_id)
 {
 	if (wpa_s->driver->hapd_send_eapol)
 		return wpa_s->driver->hapd_send_eapol(wpa_s->drv_priv, addr,
 						      data, data_len, encrypt,
-						      own_addr, flags);
+						      own_addr, flags, link_id);
 	return -1;
 }
 
diff --git a/wpa_supplicant/ibss_rsn.c b/wpa_supplicant/ibss_rsn.c
index 5b31f7bb0e..65284ab913 100644
--- a/wpa_supplicant/ibss_rsn.c
+++ b/wpa_supplicant/ibss_rsn.c
@@ -73,7 +73,7 @@  static int supp_ether_send(void *ctx, const u8 *dest, u16 proto, const u8 *buf,
 
 	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT)
 		return wpa_drv_tx_control_port(wpa_s, dest, proto, buf, len,
-					       !encrypt);
+					       !encrypt, -1);
 
 	if (wpa_s->l2)
 		return l2_packet_send(wpa_s->l2, dest, proto, buf, len);
@@ -303,7 +303,7 @@  static int auth_send_eapol(void *ctx, const u8 *addr, const u8 *data,
 
 	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT)
 		return wpa_drv_tx_control_port(wpa_s, addr, ETH_P_EAPOL,
-					       data, data_len, !encrypt);
+					       data, data_len, !encrypt, -1);
 
 	if (wpa_s->l2)
 		return l2_packet_send(wpa_s->l2, addr, ETH_P_EAPOL, data,
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index c4cfca50e6..d322829ad2 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -118,7 +118,7 @@  int wpa_ether_send(struct wpa_supplicant *wpa_s, const u8 *dest,
 			wpa_sm_has_ptk_installed(wpa_s->wpa);
 
 		return wpa_drv_tx_control_port(wpa_s, dest, proto, buf, len,
-					       !encrypt);
+					       !encrypt, -1);
 	}
 
 	if (wpa_s->l2) {