[PATCH 54/97] NAN: Terminate all NDPs with peer if security upgrade fails

Andrei Otcheretianski andrei.otcheretianski at intel.com
Tue Apr 28 13:05:55 PDT 2026


When new NDP is created, it may be needed to "upgrade" the existing NDPs
with the same peer. However, this security upgrade is not trivial and if
it fails, it might be difficult to restore the previous state, thus all
the NDPs should be terminated.

Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski at intel.com>
---
 src/nan/nan.c                   | 46 ++++++++++++++++++++++++++++++---
 src/nan/nan.h                   |  5 +++-
 wpa_supplicant/nan_supplicant.c | 15 ++++++++---
 3 files changed, 58 insertions(+), 8 deletions(-)

diff --git a/src/nan/nan.c b/src/nan/nan.c
index 4f69f85c01..1e2f625405 100644
--- a/src/nan/nan.c
+++ b/src/nan/nan.c
@@ -1639,9 +1639,39 @@ static bool nan_peer_ndi_in_use(struct nan_peer *peer, const u8 *peer_ndi)
 }
 
 
+static void nan_terminate_ndps_for_ndi(struct nan_data *nan,
+				       struct nan_peer *peer,
+				       const u8 *peer_ndi)
+{
+	struct nan_ndp *ndp, *tndp, *curr_ndp;
+
+	curr_ndp = peer->ndp_setup.ndp;
+
+	dl_list_for_each_safe(ndp, tndp, &peer->ndps, struct nan_ndp, list) {
+		const u8 *ndp_peer_ndi = ndp->initiator ?
+			ndp->resp_ndi : ndp->init_ndi;
+
+		if (!ether_addr_equal(ndp_peer_ndi, peer_ndi))
+			continue;
+
+		dl_list_del(&ndp->list);
+
+		/* Temporarily set the NDP being disconnected */
+		peer->ndp_setup.ndp = ndp;
+		nan_ndp_disconnected(nan, peer,
+				     NAN_REASON_UNSPECIFIED_REASON,
+				     true);
+	}
+
+	/* Restore the current NDP */
+	peer->ndp_setup.ndp = curr_ndp;
+}
+
+
 static int nan_ndp_connected(struct nan_data *nan, struct nan_peer *peer)
 {
 	struct nan_ndp_connection_params params;
+	int ret;
 
 	os_memset(&params, 0, sizeof(params));
 
@@ -1685,10 +1715,18 @@ static int nan_ndp_connected(struct nan_data *nan, struct nan_peer *peer)
 	}
 
 	params.new_ndi_sta = !nan_peer_ndi_in_use(peer, params.peer_ndi);
-	if (nan->cfg->ndp_connected &&
-	    nan->cfg->ndp_connected(nan->cfg->cb_ctx, &params)) {
-		wpa_printf(MSG_DEBUG, "NAN: NDP connected notification failed");
-		return -1;
+	if (nan->cfg->ndp_connected) {
+		ret = nan->cfg->ndp_connected(nan->cfg->cb_ctx, &params);
+		if (ret) {
+			wpa_printf(MSG_DEBUG,
+				   "NAN: NDP connected notification failed ret=%d",
+				   ret);
+			if (ret == -2)
+				nan_terminate_ndps_for_ndi(nan, peer,
+							   params.peer_ndi);
+
+			return ret;
+		}
 	}
 
 	/* Move the NDP to the list of tracked NDPs */
diff --git a/src/nan/nan.h b/src/nan/nan.h
index 8b23f1ae93..1cded92519 100644
--- a/src/nan/nan.h
+++ b/src/nan/nan.h
@@ -512,7 +512,10 @@ struct nan_config {
 	 * ndp_connected - Notify that NDP was successfully connected
 	 * @ctx: Callback context from cb_ctx
 	 * @params: NDP connection parameters
-	 * Returns: 0 on success, -1 on failure
+	 * Returns: 0 on success, negative on failure. Note that new NDPs
+	 * may trigger security upgrade for the peer NDI station.
+	 * If this fails, -2 is returned and the caller should cleanup
+	 * all the existing NDPs with this peer NDI.
 	 */
 	int (*ndp_connected)(void *ctx,
 			     struct nan_ndp_connection_params *params);
diff --git a/wpa_supplicant/nan_supplicant.c b/wpa_supplicant/nan_supplicant.c
index 774012da21..e2f49f24b6 100644
--- a/wpa_supplicant/nan_supplicant.c
+++ b/wpa_supplicant/nan_supplicant.c
@@ -679,9 +679,16 @@ out_success:
 	return 0;
 
 remove_sta:
+	/*
+	 * Cleanup the NDI station if it was newly added for this NDP.
+	 * For existing stations, we assume that the caller will
+	 * tear down other NDPs with this station on failure as
+	 * it may be now in some inconsistent state that is too hard
+	 * to rollback here.
+	 */
 	if (params->new_ndi_sta)
 		wpa_drv_sta_remove(ndi_wpa_s, params->peer_ndi);
-	return -1;
+	return -2;
 }
 
 
@@ -737,11 +744,13 @@ static int wpas_nan_ndp_connected_cb(void *ctx,
 				     struct nan_ndp_connection_params *params)
 {
 	struct wpa_supplicant *wpa_s = ctx;
+	int ret;
 
-	if (wpas_nan_add_ndi_sta(wpa_s, params) < 0) {
+	ret = wpas_nan_add_ndi_sta(wpa_s, params);
+	if (ret) {
 		wpa_printf(MSG_INFO,
 			   "NAN: Failed to add NDI station for NDP connection");
-		return -1;
+		return ret;
 	}
 
 	wpas_notify_nan_ndp_connected(wpa_s, params->ndp_id.peer_nmi,
-- 
2.53.0




More information about the Hostap mailing list