diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h index 971e02866..073715178 100644 --- a/src/ap/ap_drv_ops.h +++ b/src/ap/ap_drv_ops.h @@ -200,13 +200,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 bc1f47d2b..5688f1a9e 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_id = -1; + +#ifdef CONFIG_IEEE80211BE + link_id = 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_id); } os_free(buf); diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index a87d2f389..14ac4e785 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_id = -1; + +#ifdef CONFIG_IEEE80211BE + link_id = hapd->conf->mld_ap ? hapd->mld_link_id : -1; +#endif /* CONFIG_IEEE80211BE */ #ifdef CONFIG_TESTING_OPTIONS if (hapd->ext_eapol_frame_io) { @@ -539,11 +544,16 @@ 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_id = -1; +#endif /* CONFIG_IEEE80211BE */ + } return hostapd_drv_hapd_send_eapol(hapd, addr, data, data_len, - encrypt, flags); + encrypt, flags, link_id); } diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 10bf2d4e8..52b14fe80 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -3541,6 +3541,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 * @@ -3558,7 +3559,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) @@ -3569,12 +3570,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_atheros.c b/src/drivers/driver_atheros.c index d8def7936..22c8ff30c 100644 --- a/src/drivers/driver_atheros.c +++ b/src/drivers/driver_atheros.c @@ -1644,7 +1644,7 @@ atheros_wireless_event_init(struct atheros_driver_data *drv) static int atheros_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len, - int encrypt, const u8 *own_addr, u32 flags) + int encrypt, const u8 *own_addr, u32 flags, int link_id) { struct atheros_driver_data *drv = priv; unsigned char buf[3000]; diff --git a/src/drivers/driver_bsd.c b/src/drivers/driver_bsd.c index b64cdc3f5..13fcab5a1 100644 --- a/src/drivers/driver_bsd.c +++ b/src/drivers/driver_bsd.c @@ -558,7 +558,7 @@ no_ie: static int bsd_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len, - int encrypt, const u8 *own_addr, u32 flags) + int encrypt, const u8 *own_addr, u32 flags, int link_id) { struct bsd_driver_data *drv = priv; diff --git a/src/drivers/driver_hostap.c b/src/drivers/driver_hostap.c index de97037df..cf3b01e51 100644 --- a/src/drivers/driver_hostap.c +++ b/src/drivers/driver_hostap.c @@ -281,7 +281,7 @@ static int hostap_send_mlme(void *priv, const u8 *msg, size_t len, int noack, static int hostap_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len, int encrypt, const u8 *own_addr, - u32 flags) + u32 flags, int link_id) { struct hostap_driver_data *drv = priv; struct ieee80211_hdr *hdr; diff --git a/src/drivers/driver_macsec_linux.c b/src/drivers/driver_macsec_linux.c index c79e8733a..c86715498 100644 --- a/src/drivers/driver_macsec_linux.c +++ b/src/drivers/driver_macsec_linux.c @@ -1640,7 +1640,7 @@ static void macsec_drv_hapd_deinit(void *priv) static int macsec_drv_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) { struct macsec_drv_data *drv = priv; struct ieee8023_hdr *hdr; diff --git a/src/drivers/driver_macsec_qca.c b/src/drivers/driver_macsec_qca.c index eccaf6375..58c48c2f5 100644 --- a/src/drivers/driver_macsec_qca.c +++ b/src/drivers/driver_macsec_qca.c @@ -366,7 +366,7 @@ static void macsec_qca_hapd_deinit(void *priv) static int macsec_qca_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) { struct macsec_qca_data *drv = priv; struct ieee8023_hdr *hdr; diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 8c57f6276..2222fb5dd 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -6104,7 +6104,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; @@ -6123,7 +6123,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; } @@ -6181,7 +6183,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; @@ -6196,7 +6199,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/src/drivers/driver_wired.c b/src/drivers/driver_wired.c index c7537b7c3..03366b8e4 100644 --- a/src/drivers/driver_wired.c +++ b/src/drivers/driver_wired.c @@ -285,7 +285,7 @@ static int wired_init_sockets(struct wpa_driver_wired_data *drv, u8 *own_addr) static int wired_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) { struct wpa_driver_wired_data *drv = priv; struct ieee8023_hdr *hdr; diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h index 03f413c01..459a8e4ff 100644 --- a/wpa_supplicant/driver_i.h +++ b/wpa_supplicant/driver_i.h @@ -377,7 +377,7 @@ static inline int wpa_drv_tx_control_port(struct wpa_supplicant *wpa_s, 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, -1); } static inline int wpa_drv_hapd_send_eapol(struct wpa_supplicant *wpa_s, @@ -388,7 +388,7 @@ static inline int wpa_drv_hapd_send_eapol(struct wpa_supplicant *wpa_s, 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, -1); return -1; }