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(
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);
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) {
#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);
}
* @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
*
*/
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)
* @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)
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];
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;
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;
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;
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;
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;
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;
}
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;
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);
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;
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,
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;
}