[RFC 35/56] NAN: Add support for terminating an NDP

Andrei Otcheretianski andrei.otcheretianski at intel.com
Sun Dec 7 03:18:44 PST 2025


From: Ilan Peer <ilan.peer at intel.com>

Add support for locally terminating an NDP.

Signed-off-by: Ilan Peer <ilan.peer at intel.com>
---
 src/nan/nan.c     |  7 ++--
 src/nan/nan_i.h   |  2 ++
 src/nan/nan_ndp.c | 90 ++++++++++++++++++++++++++++++++++++++++-------
 3 files changed, 85 insertions(+), 14 deletions(-)

diff --git a/src/nan/nan.c b/src/nan/nan.c
index 8869bd8b29..b99d3ca8ac 100644
--- a/src/nan/nan.c
+++ b/src/nan/nan.c
@@ -1595,9 +1595,12 @@ int nan_handle_ndp_setup(struct nan_data *nan, struct nan_ndp_params *params)
 		break;
 
 	case NAN_NDP_ACTION_TERM:
-		wpa_printf(MSG_DEBUG, "TODO: Support terminate");
 		naf_oui = NAN_SUBTYPE_DATA_PATH_TERMINATION;
-		return -1;
+		timeout = NAN_NDP_SETUP_TIMEOUT_SHORT;
+		ret = nan_ndp_term_req(nan, peer, &params->ndp_id);
+		if (ret)
+			return ret;
+		break;
 	default:
 		wpa_printf(MSG_DEBUG, "NAN: Unsupported NDP setup type=%u",
 			   params->type);
diff --git a/src/nan/nan_i.h b/src/nan/nan_i.h
index 632e68b765..6733870cf1 100644
--- a/src/nan/nan_i.h
+++ b/src/nan/nan_i.h
@@ -406,6 +406,8 @@ int nan_ndp_naf_sent(struct nan_data *nan, struct nan_peer *peer,
 		     enum nan_subtype subtype);
 int nan_parse_device_attrs(struct nan_data *nan, struct nan_peer *peer,
 			   const u8 *attrs_data, size_t attrs_len);
+int nan_ndp_term_req(struct nan_data *nan, struct nan_peer *peer,
+		     struct nan_ndp_id *ndp_id);
 int nan_ndl_setup(struct nan_data *nan, struct nan_peer *peer,
 		  struct nan_ndp_params *params);
 void nan_ndl_setup_failure(struct nan_data *nan, struct nan_peer *peer,
diff --git a/src/nan/nan_ndp.c b/src/nan/nan_ndp.c
index 51a2b60854..3a37751a7a 100644
--- a/src/nan/nan_ndp.c
+++ b/src/nan/nan_ndp.c
@@ -469,6 +469,21 @@ static int nan_ndp_attr_handle_confirm(struct nan_data *nan,
 }
 
 
+static struct nan_ndp * nan_ndp_find_ndp(struct nan_peer *peer,
+					 u8 ndp_id, u8 *init_ndi)
+{
+	struct nan_ndp *pndp;
+
+	dl_list_for_each(pndp, &peer->ndps, struct nan_ndp, list) {
+		if (pndp->ndp_id == ndp_id &&
+		    os_memcmp(pndp->init_ndi, init_ndi, ETH_ALEN) == 0)
+			return pndp;
+	}
+
+	return NULL;
+}
+
+
 static int nan_ndp_attr_handle_term(struct nan_data *nan, struct nan_peer *peer,
 				    struct ieee80211_ndp *ndp_attr, u8 status)
 {
@@ -476,7 +491,6 @@ static int nan_ndp_attr_handle_term(struct nan_data *nan, struct nan_peer *peer,
 	struct nan_ndp_id ndp_id;
 	const u8 *local_ndi, *peer_ndi;
 	struct nan_ndp *pndp;
-	bool found;
 
 	wpa_printf(MSG_DEBUG,
 		   "NAN: NDP: Termination peer=" MACSTR " ndp_id=%u, init_ndi=" MACSTR,
@@ -501,17 +515,9 @@ static int nan_ndp_attr_handle_term(struct nan_data *nan, struct nan_peer *peer,
 	}
 
 	/* Find the NDP in the list of active NDPs */
-	found = false;
-	dl_list_for_each(pndp, &peer->ndps, struct nan_ndp, list) {
-		if (pndp->ndp_id == ndp_attr->ndp_id &&
-		    os_memcmp(pndp->init_ndi, ndp_attr->initiator_ndi,
-			      ETH_ALEN) == 0) {
-			found = 1;
-			break;
-		}
-	}
-
-	if (!found) {
+	pndp = nan_ndp_find_ndp(peer, ndp_attr->ndp_id,
+				ndp_attr->initiator_ndi);
+	if (!pndp) {
 		wpa_printf(MSG_DEBUG, "NAN: NDP: termination but NDP does not exist");
 		return 1;
 	}
@@ -653,6 +659,11 @@ int nan_ndp_add_ndp_attr(struct nan_data *nan, struct nan_peer *peer,
 		type = NAN_NDP_TYPE_SECURITY_INSTALL;
 		break;
 	case NAN_NDP_STATE_NONE:
+		if (ndp_setup->status == NAN_NDP_STATUS_REJECTED)
+			type = NAN_NDP_TYPE_TERMINATE;
+		else
+			return -1;
+		break;
 	case NAN_NDP_STATE_REQ_SENT:
 	case NAN_NDP_STATE_RES_SENT:
 	case NAN_NDP_STATE_CON_SENT:
@@ -805,3 +816,58 @@ int nan_ndp_naf_sent(struct nan_data *nan, struct nan_peer *peer,
 
 	return 0;
 }
+
+
+/*
+ * nan_ndp_term_req - Handle local NDP termination request
+ *
+ * @nan: NAN module context from nan_init()
+ * @peer: The peer with whom the NDP is being setup
+ * @ndp_id: NDP identifier
+ */
+int nan_ndp_term_req(struct nan_data *nan, struct nan_peer *peer,
+		     struct nan_ndp_id *ndp_id)
+{
+	struct nan_ndp_setup *ndp_setup = &peer->ndp_setup;
+	struct nan_ndp *pndp;
+
+	wpa_printf(MSG_DEBUG,
+		   "NAN: NDP: terminate request with peer=" MACSTR " ndp_id=%u, init_ndi=" MACSTR,
+		   MAC2STR(peer->nmi_addr), ndp_id->id,
+		   MAC2STR(ndp_id->init_ndi));
+
+	if (ndp_setup->ndp) {
+		if (ndp_setup->ndp->ndp_id == ndp_id->id &&
+		    os_memcmp(ndp_setup->ndp->init_ndi, ndp_id->init_ndi,
+			      ETH_ALEN) == 0) {
+			wpa_printf(MSG_DEBUG,
+				   "NAN: NDP: WIP with peer. Terminate");
+
+			nan_ndp_set_state(nan, &peer->ndp_setup,
+					  NAN_NDP_STATE_DONE);
+			ndp_setup->status = NAN_NDP_STATUS_REJECTED;
+			ndp_setup->reason = NAN_REASON_UNSPECIFIED_REASON;
+			return 0;
+		}
+
+		wpa_printf(MSG_DEBUG,
+			   "NAN: NDP: cannot terminate NDP while NDP establishment is WIP");
+		return -1;
+	}
+
+	/* Find the NDP in the list of active NDPs */
+	pndp = nan_ndp_find_ndp(peer, ndp_id->id, ndp_id->init_ndi);
+	if (!pndp) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN: NDP: termination request for unknown NDP");
+		return -1;
+	}
+
+	/* Remove the NDP from the list and setup data for the termination */
+	dl_list_del(&pndp->list);
+
+	peer->ndp_setup.ndp = pndp;
+	peer->ndp_setup.status = NAN_NDP_STATUS_REJECTED;
+	peer->ndp_setup.reason = NAN_REASON_UNSPECIFIED_REASON;
+	return 0;
+}
-- 
2.49.0




More information about the Hostap mailing list