[RFC v2 68/99] wpa_supplicant: Add support for NDP_RESPONSE command
Andrei Otcheretianski
andrei.otcheretianski at intel.com
Tue Dec 23 03:52:12 PST 2025
This allows to accept or reject NDP request.
Upper layer is expected to create the corresponding NAN data interface
and configure a compliant NAN schedule prior to accepting an NDP request
received via NAN-NDP-REQUEST event.
Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski at intel.com>
---
wpa_supplicant/ctrl_iface.c | 3 +
wpa_supplicant/nan_supplicant.c | 168 ++++++++++++++++++++++++++++++++
wpa_supplicant/nan_supplicant.h | 1 +
3 files changed, 172 insertions(+)
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 3a8b3298cc..05debdb418 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -14353,6 +14353,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
} else if (os_strncmp(buf, "NAN_NDP_REQUEST ", 16) == 0) {
if (wpas_nan_ndp_request(wpa_s, buf + 16) < 0)
reply_len = -1;
+ } else if (os_strncmp(buf, "NAN_NDP_RESPONSE ", 17) == 0) {
+ if (wpas_nan_ndp_response(wpa_s, buf + 17) < 0)
+ reply_len = -1;
#endif /* CONFIG_NAN */
} else {
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
diff --git a/wpa_supplicant/nan_supplicant.c b/wpa_supplicant/nan_supplicant.c
index b231628b5f..11f8844bac 100644
--- a/wpa_supplicant/nan_supplicant.c
+++ b/wpa_supplicant/nan_supplicant.c
@@ -1406,6 +1406,174 @@ fail:
}
+/* Command format NAN_NDP_RESPONSE accept|reject peer_nmi=<nmi>
+ [reason_code=<reject_reason>]
+ [ndi=<ifname> handle=<service_handle> init_ndi=<ndi>
+ ndp_id=<id> [ssi=<hexdata>] [qos=<slots:latency>]] */
+int wpas_nan_ndp_response(struct wpa_supplicant *wpa_s, char *cmd)
+{
+ struct nan_ndp_params ndp;
+ struct wpabuf *ssi_buf = NULL;
+ char *token, *context = NULL;
+ char *pos;
+ int ret = -1;
+
+ os_memset(&ndp, 0, sizeof(ndp));
+
+ if (!wpas_nan_ready(wpa_s))
+ return -1;
+
+ ndp.type = NAN_NDP_ACTION_RESP;
+ ndp.qos.min_slots = NAN_QOS_MIN_SLOTS_NO_PREF;
+ ndp.qos.max_latency = NAN_QOS_MAX_LATENCY_NO_PREF;
+
+ /* Parse accept/reject status - first parameter is mandatory */
+ token = str_token(cmd, " ", &context);
+ if (!token) {
+ wpa_printf(MSG_DEBUG, "NAN: Missing accept/reject parameter");
+ return -1;
+ }
+
+ if (os_strcmp(token, "accept") == 0) {
+ ndp.u.resp.status = NAN_NDP_STATUS_ACCEPTED;
+ } else if (os_strcmp(token, "reject") == 0) {
+ ndp.u.resp.status = NAN_NDP_STATUS_REJECTED;
+ } else {
+ wpa_printf(MSG_DEBUG, "NAN: Invalid accept/reject parameter: %s", token);
+ return -1;
+ }
+
+ /* Parse optional parameters */
+ while ((token = str_token(cmd, " ", &context))) {
+ pos = os_strchr(token, '=');
+ if (!pos) {
+ wpa_printf(MSG_DEBUG,
+ "NAN: Invalid parameter format: %s",
+ token);
+ goto fail;
+ }
+ *pos++ = '\0';
+
+ if (os_strcmp(token, "reason_code") == 0) {
+ ndp.u.resp.reason_code = atoi(pos);
+ } else if (os_strcmp(token, "ndi") == 0) {
+ struct wpa_supplicant *ndi_wpa_s;
+
+ ndi_wpa_s = wpa_supplicant_get_iface(wpa_s->global, pos);
+ if (!ndi_wpa_s) {
+ wpa_printf(MSG_DEBUG,
+ "NAN: NDI interface not found: %s",
+ pos);
+ goto fail;
+ }
+
+ if (!ndi_wpa_s->nan_data) {
+ wpa_printf(MSG_DEBUG,
+ "NAN: Interface %s is not a NAN data interface",
+ pos);
+ goto fail;
+ }
+
+ os_memcpy(ndp.u.resp.resp_ndi, ndi_wpa_s->own_addr,
+ ETH_ALEN);
+
+ } else if (os_strcmp(token, "peer_nmi") == 0) {
+ if (hwaddr_aton(pos, ndp.ndp_id.peer_nmi) < 0) {
+ wpa_printf(MSG_DEBUG,
+ "NAN: Invalid peer NMI address: %s",
+ pos);
+ goto fail;
+ }
+ } else if (os_strcmp(token, "ndp_id") == 0) {
+ ndp.ndp_id.id = atoi(pos);
+
+ } else if (os_strcmp(token, "init_ndi") == 0) {
+ if (hwaddr_aton(pos, ndp.ndp_id.init_ndi) < 0) {
+ wpa_printf(MSG_DEBUG,
+ "NAN: Invalid initiator NDI address: %s",
+ pos);
+ goto fail;
+ }
+
+ } else if (os_strcmp(token, "ssi") == 0) {
+ ssi_buf = wpabuf_parse_bin(pos);
+ if (!ssi_buf) {
+ wpa_printf(MSG_DEBUG,
+ "NAN: Invalid SSI data: %s", pos);
+ goto fail;
+ }
+
+ ndp.ssi_len = wpabuf_len(ssi_buf);
+ ndp.ssi = wpabuf_head(ssi_buf);
+ } else if (os_strcmp(token, "qos") == 0) {
+ if (sscanf(pos, "%hhu:%hu",
+ &ndp.qos.min_slots,
+ &ndp.qos.max_latency) != 2) {
+ wpa_printf(MSG_DEBUG,
+ "NAN: Invalid QoS parameter: %s",
+ pos);
+ goto fail;
+ }
+ } else {
+ wpa_printf(MSG_DEBUG, "NAN: Unknown parameter: %s",
+ token);
+ }
+ }
+
+ /* Validate required parameters for accept case */
+ if (ndp.u.resp.status == NAN_NDP_STATUS_ACCEPTED) {
+ if (is_zero_ether_addr(ndp.u.resp.resp_ndi)) {
+ wpa_printf(MSG_DEBUG,
+ "NAN: Missing required parameter for accept: ndi");
+ goto fail;
+ }
+ }
+
+ /* Validate common required parameters */
+ if (is_zero_ether_addr(ndp.ndp_id.peer_nmi)) {
+ wpa_printf(MSG_DEBUG,
+ "NAN: Missing required parameter: peer_nmi");
+ goto fail;
+ }
+
+ if (is_zero_ether_addr(ndp.ndp_id.init_ndi)) {
+ wpa_printf(MSG_DEBUG,
+ "NAN: Missing required parameter: init_ndi");
+ goto fail;
+ }
+
+ if (!ndp.ndp_id.id) {
+ wpa_printf(MSG_DEBUG,
+ "NAN: Missing required parameter: ndp_id");
+ goto fail;
+ }
+
+ wpa_printf(MSG_DEBUG, "NAN: %s NDP response for peer " MACSTR
+ " ndp_id=%u",
+ ndp.u.resp.status == NAN_NDP_STATUS_ACCEPTED ? "Accepting" : "Rejecting",
+ MAC2STR(ndp.ndp_id.peer_nmi), ndp.ndp_id.id);
+
+ if (wpas_nan_set_ndp_schedule(wpa_s, &ndp) < 0) {
+ wpa_printf(MSG_DEBUG,
+ "NAN: Failed to set NDP schedule");
+ goto fail;
+ }
+
+ /* If we initiated the NDP setup, this must be the confirmation */
+ if (ether_addr_equal(ndp.u.resp.resp_ndi, ndp.ndp_id.init_ndi))
+ ndp.type = NAN_NDP_ACTION_CONF;
+
+ ret = nan_handle_ndp_setup(wpa_s->nan, &ndp);
+ if (ret < 0)
+ wpa_printf(MSG_DEBUG, "NAN: Failed to handle NDP response");
+
+fail:
+ wpabuf_free(ndp.sched.elems);
+ wpabuf_free(ssi_buf);
+ return ret;
+}
+
+
void wpas_nan_cluster_join(struct wpa_supplicant *wpa_s,
const u8 *cluster_id,
bool new_cluster)
diff --git a/wpa_supplicant/nan_supplicant.h b/wpa_supplicant/nan_supplicant.h
index d7c0cc2800..61a0a5c4d5 100644
--- a/wpa_supplicant/nan_supplicant.h
+++ b/wpa_supplicant/nan_supplicant.h
@@ -28,6 +28,7 @@ int wpas_nan_sched_config_map(struct wpa_supplicant *wpa_s, const char *cmd);
int wpas_nan_ndp_request(struct wpa_supplicant *wpa_s, char *cmd);
void wpas_nan_rx_naf(struct wpa_supplicant *wpa_s,
const struct ieee80211_mgmt *mgmt, size_t len);
+int wpas_nan_ndp_response(struct wpa_supplicant *wpa_s, char *cmd);
#else /* CONFIG_NAN */
--
2.49.0
More information about the Hostap
mailing list