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@xxxxxxxxx> --- 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 5b4b931736..29a6bdd770 100644 --- a/src/ap/ap_drv_ops.h +++ b/src/ap/ap_drv_ops.h @@ -195,13 +195,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 0e3d1772a2..c6cbf76a25 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->conf->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..9090ba7840 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->conf->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 e838b54ae0..af59510c7b 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -3475,6 +3475,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 * @@ -3492,7 +3493,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) @@ -3503,12 +3504,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 a728799f64..112e59530e 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -5999,7 +5999,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; @@ -6018,7 +6018,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; } @@ -6076,7 +6078,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; @@ -6091,7 +6094,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 f23f78064e..d6d4d5429b 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 e5a4053c83..262147ab18 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 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap