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

Andrei Otcheretianski andrei.otcheretianski at intel.com
Mon May 22 12:33:54 PDT 2023


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 at 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 --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) {
-- 
2.38.1




More information about the Hostap mailing list