[RFC v2 33/99] NAN: Add API to request/response/terminate an NDP
Andrei Otcheretianski
andrei.otcheretianski at intel.com
Tue Dec 23 03:51:37 PST 2025
From: Ilan Peer <ilan.peer at intel.com>
Add APIs to allow establishing a NDP with a specific
peer.
Set timeouts for the NDP setup exchange for each peer.
If the timeout expires, stop the NDP establishment.
Signed-off-by: Ilan Peer <ilan.peer at intel.com>
---
src/nan/nan.c | 170 +++++++++++++++++++++++++++++++++++++++++++++++---
src/nan/nan.h | 1 +
2 files changed, 162 insertions(+), 9 deletions(-)
diff --git a/src/nan/nan.c b/src/nan/nan.c
index 396a3af37a..f619647ba1 100644
--- a/src/nan/nan.c
+++ b/src/nan/nan.c
@@ -10,10 +10,18 @@
#include "common.h"
#include "nan.h"
#include "nan_i.h"
+#include "eloop.h"
#define NAN_MAX_PEERS 32
#define NAN_MAX_NAF_LEN 1024
+#define NAN_NDP_SETUP_TIMEOUT_LONG 30
+#define NAN_NDP_SETUP_TIMEOUT_SHORT 2
+
+static void nan_peer_state_timeout(void *eloop_ctx, void *timeout_ctx);
+static void nan_ndp_disconnected(struct nan_data *nan, struct nan_peer *peer,
+ enum nan_reason reason);
+
struct nan_data * nan_init(const struct nan_config *cfg)
{
struct nan_data *nan;
@@ -69,6 +77,17 @@ static void nan_peer_flush_elem_container(struct nan_peer_info *info)
}
+static void nan_ndp_setup_stop(struct nan_data *nan, struct nan_peer *peer)
+{
+ eloop_cancel_timeout(nan_peer_state_timeout, nan, peer);
+ nan_ndp_setup_reset(nan, peer);
+
+ /* need to also remove the NDL if no active NDPs */
+ if (dl_list_empty(&peer->ndps))
+ nan_ndl_reset(nan, peer);
+}
+
+
static void nan_del_peer(struct nan_data *nan, struct nan_peer *peer)
{
if (!peer)
@@ -94,7 +113,8 @@ static void nan_del_peer(struct nan_data *nan, struct nan_peer *peer)
if (peer->ndp_setup.ndp) {
wpa_printf(MSG_DEBUG,
"NAN: Peer delete while ndp setup is WIP");
- nan_ndp_setup_reset(nan, peer);
+
+ nan_ndp_setup_stop(nan, peer);
}
dl_list_del(&peer->list);
@@ -1089,6 +1109,34 @@ static bool nan_ndp_supported(struct nan_data *nan)
}
+static void nan_peer_state_timeout(void *eloop_ctx, void *timeout_ctx)
+{
+ struct nan_data *nan = eloop_ctx;
+ struct nan_peer *peer = timeout_ctx;
+
+ wpa_printf(MSG_DEBUG,
+ "NAN: timeout expired: " MACSTR, MAC2STR(peer->nmi_addr));
+
+ if (!peer->ndp_setup.ndp)
+ return;
+
+ nan_ndp_disconnected(nan, peer,
+ NAN_REASON_UNSPECIFIED_REASON);
+}
+
+
+static void nan_set_peer_timeout(struct nan_data *nan, struct nan_peer *peer,
+ unsigned int sec, unsigned int usec)
+{
+ wpa_printf(MSG_DEBUG,
+ "NAN: set timeout: " MACSTR " %u.%06u sec",
+ MAC2STR(peer->nmi_addr), sec, usec);
+
+ eloop_cancel_timeout(nan_peer_state_timeout, nan, peer);
+ eloop_register_timeout(sec, usec, nan_peer_state_timeout, nan, peer);
+}
+
+
static void nan_ndp_action_notif(struct nan_data *nan, struct nan_peer *peer)
{
struct nan_ndp_action_notif_params notify;
@@ -1118,6 +1166,7 @@ static void nan_ndp_action_notif(struct nan_data *nan, struct nan_peer *peer)
notify.ndl_status);
nan->cfg->ndp_action_notif(nan->cfg->cb_ctx, ¬ify);
+ nan_set_peer_timeout(nan, peer, NAN_NDP_SETUP_TIMEOUT_LONG, 0);
}
@@ -1152,7 +1201,7 @@ static void nan_ndp_connected(struct nan_data *nan, struct nan_peer *peer)
dl_list_add(&peer->ndps, &peer->ndp_setup.ndp->list);
peer->ndp_setup.ndp = NULL;
- nan_ndp_setup_reset(nan, peer);
+ nan_ndp_setup_stop(nan, peer);
}
@@ -1183,12 +1232,7 @@ static void nan_ndp_disconnected(struct nan_data *nan, struct nan_peer *peer,
nan->cfg->ndp_disconnected(nan->cfg->cb_ctx, &ndp_id,
local_ndi, peer_ndi, reason);
- /* Reset the NDP setup data */
- nan_ndp_setup_reset(nan, peer);
-
- /* Need to also remove the NDL if no active peers */
- if (dl_list_empty(&peer->ndps))
- nan_ndl_reset(nan, peer);
+ nan_ndp_setup_stop(nan, peer);
}
@@ -1219,7 +1263,7 @@ static int nan_action_rx_ndp(struct nan_data *nan, struct nan_peer *peer,
ret = nan_ndl_handle_ndl_attr(nan, peer, msg);
if (ret || !peer->ndl) {
- nan_ndp_setup_reset(nan, peer);
+ nan_ndp_setup_stop(nan, peer);
return -1;
}
@@ -1290,6 +1334,8 @@ static int nan_action_rx_ndp(struct nan_data *nan, struct nan_peer *peer,
nan_ndp_disconnected(nan, peer, NAN_REASON_UNSPECIFIED_REASON);
}
+ nan_set_peer_timeout(nan, peer, NAN_NDP_SETUP_TIMEOUT_SHORT, 0);
+
return 0;
}
@@ -1463,3 +1509,109 @@ int nan_tx_status(struct nan_data *nan, const u8 *dst, const u8 *data,
return 0;
}
+
+
+int nan_handle_ndp_setup(struct nan_data *nan, struct nan_ndp_params *params)
+{
+ struct nan_peer *peer;
+ enum nan_subtype naf_oui = NAN_SUBTYPE_INVALID;
+ unsigned int timeout;
+ int ret;
+
+ if (!nan_ndp_supported(nan))
+ return -1;
+
+ peer = nan_get_peer(nan, params->ndp_id.peer_nmi);
+ if (!peer) {
+ wpa_printf(MSG_DEBUG, "NAN: NDP Peer not found");
+ return -1;
+ }
+
+ switch (params->type) {
+ case NAN_NDP_ACTION_REQ:
+ params->ndp_id.id = ++nan->ndp_id_counter;
+ ret = nan_ndp_setup_req(nan, peer, params);
+ if (ret)
+ return ret;
+
+ ret = nan_ndl_setup(nan, peer, params);
+ if (ret) {
+ nan_ndp_setup_stop(nan, peer);
+ return ret;
+ }
+
+ naf_oui = NAN_SUBTYPE_DATA_PATH_REQUEST;
+ timeout = NAN_NDP_SETUP_TIMEOUT_LONG;
+ break;
+ case NAN_NDP_ACTION_RESP:
+ /*
+ * NDL establishment as part of the NDP establishment. It is
+ * possible that this would use an already existing NDL or start
+ * a new NDL setup.
+ */
+ ret = nan_ndp_setup_resp(nan, peer, params);
+ if (ret) {
+ nan_ndp_setup_stop(nan, peer);
+ return ret;
+ }
+
+ if (peer->ndp_setup.status != NAN_NDP_STATUS_REJECTED) {
+ ret = nan_ndl_setup(nan, peer, params);
+ if (ret) {
+ if (peer->ndl && peer->ndl->send_naf_on_error) {
+ nan_ndp_setup_failure(nan, peer,
+ NAN_REASON_NDL_UNACCEPTABLE,
+ 0);
+ } else {
+ nan_ndp_setup_stop(nan, peer);
+ return ret;
+ }
+ }
+ } else if (peer->ndl && dl_list_empty(&peer->ndps)) {
+ peer->ndl->status = NAN_NDL_STATUS_REJECTED;
+ }
+
+ naf_oui = NAN_SUBTYPE_DATA_PATH_RESPONSE;
+ timeout = NAN_NDP_SETUP_TIMEOUT_SHORT;
+ break;
+ case NAN_NDP_ACTION_CONF:
+ ret = nan_ndl_setup(nan, peer, params);
+ if (ret) {
+ if (peer->ndl && peer->ndl->send_naf_on_error) {
+ nan_ndp_setup_failure(nan, peer,
+ NAN_REASON_NDL_UNACCEPTABLE,
+ 0);
+ } else {
+ nan_ndp_setup_stop(nan, peer);
+ return ret;
+ }
+ }
+
+ naf_oui = NAN_SUBTYPE_DATA_PATH_CONFIRM;
+ timeout = NAN_NDP_SETUP_TIMEOUT_SHORT;
+ break;
+
+ case NAN_NDP_ACTION_TERM:
+ wpa_printf(MSG_DEBUG, "TODO: Support terminate");
+ naf_oui = NAN_SUBTYPE_DATA_PATH_TERMINATION;
+ return -1;
+ default:
+ wpa_printf(MSG_DEBUG, "NAN: Unsupported NDP setup type=%u",
+ params->type);
+ return -1;
+ }
+
+ ret = nan_action_send(nan, peer, naf_oui);
+ if (ret)
+ wpa_printf(MSG_DEBUG,
+ "NAN: Failed sending NAF. Resetting: ret=%d",
+ ret);
+
+ if (ret || peer->ndp_setup.status == NAN_NDP_STATUS_REJECTED) {
+ nan_ndp_disconnected(nan, peer, peer->ndp_setup.reason);
+ return 0;
+ }
+
+ nan_set_peer_timeout(nan, peer, timeout, 0);
+ return ret;
+}
diff --git a/src/nan/nan.h b/src/nan/nan.h
index 99dd962df0..f508c805b1 100644
--- a/src/nan/nan.h
+++ b/src/nan/nan.h
@@ -417,4 +417,5 @@ int nan_action_rx(struct nan_data *nan, const struct ieee80211_mgmt *mgmt,
size_t len);
int nan_tx_status(struct nan_data *nan, const u8 *dst, const u8 *data,
size_t data_len, u8 acked);
+int nan_handle_ndp_setup(struct nan_data *nan, struct nan_ndp_params *params);
#endif /* NAN_H */
--
2.49.0
More information about the Hostap
mailing list