[PATCH 2/2] RRM: Report driver-triggered Neighbor Report responses

Chung-Hsien Hsu chung-hsien.hsu at infineon.com
Tue May 12 06:25:03 PDT 2026


Neighbor Report Request can be initiated either by wpa_supplicant or by
the driver/firmware. The current processing path assumes that every
Neighbor Report Response corresponds to a pending wpa_supplicant request
and validates the dialog token against the locally generated token
before checking for the registered callback.

This drops Neighbor Report Responses for requests that were triggered by
the driver/firmware since wpa_supplicant does not have a pending
callback or matching dialog token for such requests.

Accept Neighbor Report Responses only when they are received from the
currently associated AP. For MLO connections, accept a source address
that matches the AP MLD address or any valid affiliated link BSSID.

Use the shared Neighbor Report notification helper to report unsolicited
Neighbor Report Responses through the control interface while keeping
the existing dialog token validation and timeout handling for
wpa_supplicant-triggered requests.

Signed-off-by: Chung-Hsien Hsu <chung-hsien.hsu at infineon.com>
---
 wpa_supplicant/rrm.c | 79 ++++++++++++++++++++++++++++++++++----------
 1 file changed, 62 insertions(+), 17 deletions(-)

diff --git a/wpa_supplicant/rrm.c b/wpa_supplicant/rrm.c
index 07e952dfe6fc..f0e0ffb994c9 100644
--- a/wpa_supplicant/rrm.c
+++ b/wpa_supplicant/rrm.c
@@ -164,6 +164,38 @@ out:
 }
 
 
+/*
+ * wpas_rrm_neighbor_rep_from_assoc_ap - Check Neighbor Report Response source
+ * @wpa_s: Pointer to wpa_supplicant
+ * @src: Source address of the received Neighbor Report Response frame
+ */
+static bool wpas_rrm_neighbor_rep_from_assoc_ap(struct wpa_supplicant *wpa_s,
+						const u8 *src)
+{
+	int i;
+
+	if (os_memcmp(src, wpa_s->bssid, ETH_ALEN) == 0)
+		return true;
+
+	if (!wpa_s->valid_links)
+		return false;
+
+	if (!is_zero_ether_addr(wpa_s->ap_mld_addr) &&
+	    os_memcmp(src, wpa_s->ap_mld_addr, ETH_ALEN) == 0)
+		return true;
+
+	for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+		if (!(wpa_s->valid_links & BIT(i)))
+			continue;
+
+		if (os_memcmp(src, wpa_s->links[i].bssid, ETH_ALEN) == 0)
+			return true;
+	}
+
+	return false;
+}
+
+
 /*
  * wpas_rrm_process_neighbor_rep - Handle incoming neighbor report
  * @wpa_s: Pointer to wpa_supplicant
@@ -186,38 +218,51 @@ void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s,
 		return;
 	}
 
+	if (!wpas_rrm_neighbor_rep_from_assoc_ap(wpa_s, sa)) {
+		wpa_dbg(wpa_s, MSG_DEBUG,
+			"RRM: Ignore Neighbor Report Response from " MACSTR
+			" (BSSID " MACSTR " AP MLD " MACSTR
+			" valid_links=0x%x)",
+			MAC2STR(sa), MAC2STR(wpa_s->bssid),
+			MAC2STR(wpa_s->ap_mld_addr), wpa_s->valid_links);
+		return;
+	}
+
 	wpa_hexdump(MSG_DEBUG, "RRM: New Neighbor Report", report, report_len);
 	if (report_len < 1)
 		return;
 
-	if (report[0] != wpa_s->rrm.next_neighbor_rep_token - 1) {
-		wpa_printf(MSG_DEBUG,
-			   "RRM: Discarding neighbor report with token %d (expected %d)",
-			   report[0], wpa_s->rrm.next_neighbor_rep_token - 1);
-		return;
-	}
+	if (wpa_s->rrm.notify_neighbor_rep) {
+		if (report[0] != wpa_s->rrm.next_neighbor_rep_token - 1) {
+			wpa_printf(MSG_DEBUG,
+				   "RRM: Discarding neighbor report with token %d (expected %d)",
+				   report[0],
+				   wpa_s->rrm.next_neighbor_rep_token - 1);
+			return;
+		}
 
-	eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
-			     NULL);
-
-	if (!wpa_s->rrm.notify_neighbor_rep) {
-		wpa_msg(wpa_s, MSG_INFO, "RRM: Unexpected neighbor report");
-		return;
+		eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler,
+				     &wpa_s->rrm, NULL);
 	}
 
 	/* skipping the first byte, which is only an id (dialog token) */
 	neighbor_rep = wpabuf_alloc(report_len - 1);
 	if (!neighbor_rep) {
-		wpas_rrm_neighbor_rep_timeout_handler(&wpa_s->rrm, NULL);
+		if (wpa_s->rrm.notify_neighbor_rep)
+			wpas_rrm_neighbor_rep_timeout_handler(&wpa_s->rrm, NULL);
 		return;
 	}
 	wpabuf_put_data(neighbor_rep, report + 1, report_len - 1);
 	wpa_dbg(wpa_s, MSG_DEBUG, "RRM: Notifying neighbor report (token = %d)",
 		report[0]);
-	wpa_s->rrm.notify_neighbor_rep(wpa_s->rrm.neighbor_rep_cb_ctx,
-				       neighbor_rep);
-	wpa_s->rrm.notify_neighbor_rep = NULL;
-	wpa_s->rrm.neighbor_rep_cb_ctx = NULL;
+	if (wpa_s->rrm.notify_neighbor_rep) {
+		wpa_s->rrm.notify_neighbor_rep(wpa_s->rrm.neighbor_rep_cb_ctx,
+					       neighbor_rep);
+		wpa_s->rrm.notify_neighbor_rep = NULL;
+		wpa_s->rrm.neighbor_rep_cb_ctx = NULL;
+	} else {
+		wpas_rrm_notify_neighbor_rep(wpa_s, neighbor_rep);
+	}
 }
 
 
-- 
2.25.1




More information about the Hostap mailing list