hostapd: answer a frame from an unknown station on its own link

The class 3 deauth went out on the link whose address equals the AP MLD
address, where a station on another link never takes it.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
Felix Fietkau committed 2026-10-08 09:50:37 +02:00
1 parent 80d75155ad
commit 86d3d90753
2 files changed
+45 -1

No files matched your search

@@ -0,0 +1,44 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Mon, 28 Sep 2026 03:10:00 +0200
Subject: [PATCH] AP MLD: answer a frame from an unknown station on its own link
EVENT_RX_FROM_UNKNOWN carries the link on which the driver received a
class 3 frame from a station it does not know, and the event handler
switches to the BSS of that link. hostapd_rx_from_unknown_sta() then
looks the BSS up again by the address of the MLD netdev with no link.
That address matches no link BSS by its link address, so the lookup
returns the partner link whose own address equals the AP MLD address,
or none. The Deauthentication frame with reason 7 goes out on that
partner link, where a non-AP MLD that set up the other link alone does
not take it, or it is not sent at all. The station then never starts an
SA Query and keeps its association.
Pass the link of the event to get_hapd_bssid(), as hostapd_mgmt_rx()
does for a received management frame.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -1962,9 +1962,9 @@ static struct hostapd_data * get_hapd_bs
static void hostapd_rx_from_unknown_sta(struct hostapd_data *hapd,
const u8 *bssid, const u8 *addr,
- int wds)
+ int wds, int link_id)
{
- hapd = get_hapd_bssid(hapd->iface, bssid, -1);
+ hapd = get_hapd_bssid(hapd->iface, bssid, link_id);
if (hapd == NULL || hapd == HAPD_BROADCAST)
return;
@@ -2702,7 +2702,8 @@ void wpa_supplicant_event(void *ctx, enu
hapd = switch_link_hapd(hapd, data->rx_from_unknown.link_id);
hostapd_rx_from_unknown_sta(hapd, data->rx_from_unknown.bssid,
data->rx_from_unknown.addr,
- data->rx_from_unknown.wds);
+ data->rx_from_unknown.wds,
+ data->rx_from_unknown.link_id);
break;
#endif /* NEED_AP_MLME */
case EVENT_RX_MGMT:
@@ -105,7 +105,7 @@ This allows building both hostapd and wpa_supplicant as a single binary
{
struct hostapd_data *hapd = ctx;
struct sta_info *sta;
@@ -2982,7 +2982,7 @@ void wpa_supplicant_event(void *ctx, enu
@@ -2983,7 +2983,7 @@ void wpa_supplicant_event(void *ctx, enu
}