[RFC 34/56] NAN: Support handling NDP termination from peer in NDP SM
Andrei Otcheretianski
andrei.otcheretianski at intel.com
Sun Dec 7 03:18:43 PST 2025
From: Ilan Peer <ilan.peer at intel.com>
Add support for terminating an NDP whose setup
is complete. In case there are no more NDPs with the
peer, the NDL is also torn down.
Signed-off-by: Ilan Peer <ilan.peer at intel.com>
---
src/nan/nan.c | 18 +++++++++-
src/nan/nan_i.h | 3 ++
src/nan/nan_ndp.c | 90 ++++++++++++++++++++++++++++++++++++-----------
3 files changed, 89 insertions(+), 22 deletions(-)
diff --git a/src/nan/nan.c b/src/nan/nan.c
index f619647ba1..8869bd8b29 100644
--- a/src/nan/nan.c
+++ b/src/nan/nan.c
@@ -1250,8 +1250,11 @@ static int nan_action_rx_ndp(struct nan_data *nan, struct nan_peer *peer,
int ret;
ret = nan_ndp_handle_ndp_attr(nan, peer, msg);
- if (ret)
+ if (ret) {
+ if (ret > 0)
+ ret = 0;
return ret;
+ }
/*
* NDP request: Also process the NDL/NDC/QoS attributes and store the
@@ -1615,3 +1618,16 @@ int nan_handle_ndp_setup(struct nan_data *nan, struct nan_ndp_params *params)
nan_set_peer_timeout(nan, peer, timeout, 0);
return ret;
}
+
+
+void nan_ndp_terminated(struct nan_data *nan, struct nan_peer *peer,
+ struct nan_ndp_id *ndp_id, const u8 *local_ndi,
+ const u8 *peer_ndi, enum nan_reason reason)
+{
+ nan->cfg->ndp_disconnected(nan->cfg->cb_ctx, ndp_id, local_ndi, peer_ndi,
+ reason);
+
+ /* Need to also remove the NDL if it is not needed */
+ if (dl_list_empty(&peer->ndps) && !peer->ndp_setup.ndp)
+ nan_ndl_reset(nan, peer);
+}
diff --git a/src/nan/nan_i.h b/src/nan/nan_i.h
index baccfa6467..632e68b765 100644
--- a/src/nan/nan_i.h
+++ b/src/nan/nan_i.h
@@ -463,4 +463,7 @@ nan_sched_bf_covered_by_avail_entries_and_chan(struct nan_data *nan,
struct bitfield * nan_avail_entries_to_bf(struct nan_data *nan,
const struct dl_list *avail_entries,
u8 op_class, u16 cbm, u16 pri_cbm);
+void nan_ndp_terminated(struct nan_data *nan, struct nan_peer *peer,
+ struct nan_ndp_id *ndp_id, const u8 *local_ndi,
+ const u8 *peer_ndi, enum nan_reason reason);
#endif
diff --git a/src/nan/nan_ndp.c b/src/nan/nan_ndp.c
index c18e9e8ef5..51a2b60854 100644
--- a/src/nan/nan_ndp.c
+++ b/src/nan/nan_ndp.c
@@ -473,33 +473,79 @@ static int nan_ndp_attr_handle_term(struct nan_data *nan, struct nan_peer *peer,
struct ieee80211_ndp *ndp_attr, u8 status)
{
struct nan_ndp_setup *ndp_setup = &peer->ndp_setup;
+ 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,
+ MAC2STR(peer->nmi_addr), ndp_attr->ndp_id,
+ MAC2STR(ndp_attr->initiator_ndi));
/*
- * This should not really happen, but just in case,
- * terminate the establishment.
+ * This should not really happen, but just in case, terminate the
+ * establishment. Since the NDP establishment is not yet done, the NDP
+ * is not added to the list of NDPs, so just reject the establishment.
*/
- if (ndp_setup->ndp) {
- if (ndp_setup->ndp->ndp_id == ndp_attr->ndp_id &&
- os_memcmp(ndp_setup->ndp->init_ndi,
- ndp_attr->initiator_ndi,
- ETH_ALEN) == 0) {
- wpa_printf(MSG_DEBUG,
- "NAN: NDP: term: WIP with peer. Terminate");
+ if (ndp_setup->ndp && ndp_setup->ndp->ndp_id == ndp_attr->ndp_id &&
+ os_memcmp(ndp_setup->ndp->init_ndi, ndp_attr->initiator_ndi,
+ ETH_ALEN) == 0) {
+ wpa_printf(MSG_DEBUG,
+ "NAN: NDP: Termination while NDP is in progress");
- 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;
- } else {
- wpa_printf(MSG_DEBUG,
- "NAN: NDP: term: different NDP WIP with peer. Ignore");
- }
+ 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;
}
- /* TODO: handle already established NDPs */
- wpa_printf(MSG_DEBUG, "NAN: NDP: Terminate established NDP");
- return 0;
+ /* 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) {
+ wpa_printf(MSG_DEBUG, "NAN: NDP: termination but NDP does not exist");
+ return 1;
+ }
+
+ wpa_printf(MSG_DEBUG, "NAN: NDP: Terminating");
+
+ os_memcpy(ndp_id.peer_nmi, peer->nmi_addr, ETH_ALEN);
+ os_memcpy(ndp_id.init_ndi, pndp->init_ndi, ETH_ALEN);
+ ndp_id.id = pndp->ndp_id;
+
+ if (pndp->initiator) {
+ local_ndi = pndp->init_ndi;
+ peer_ndi = pndp->resp_ndi;
+ } else {
+ local_ndi = pndp->resp_ndi;
+ peer_ndi = pndp->init_ndi;
+ }
+
+ /*
+ * Remove the NDP from the list of active NDPs before calling
+ * nan_ndp_terminated() as the functions checks the list of NDPs to
+ * determine if the NDL should be reset as well.
+ * Free the NDP only after the call as the NDI addresses are still
+ * referenced.
+ */
+ dl_list_del(&pndp->list);
+
+ nan_ndp_terminated(nan, peer, &ndp_id, local_ndi, peer_ndi,
+ ndp_attr->reason_code);
+
+ os_free(pndp);
+
+ /* Indicate that no further processing is needed */
+ return 1;
}
@@ -509,7 +555,9 @@ static int nan_ndp_attr_handle_term(struct nan_data *nan, struct nan_peer *peer,
* @nan: NAN module context from nan_init()
* @peer: The peer from which the original message was received
* @msg: Parsed nan action frame
- * Returns: 0 on success, negative on failure
+ * Returns: 0 on success processing indicating that processing can continue; 1
+ * in case of successful processing but no further processing is needed;
+ * negative on failure.
*/
int nan_ndp_handle_ndp_attr(struct nan_data *nan, struct nan_peer *peer,
struct nan_msg *msg)
--
2.49.0
More information about the Hostap
mailing list