[PATCH 07/35] NAN: Integrate the NAN module with the wpa_supplicant

Andrei Otcheretianski andrei.otcheretianski at intel.com
Mon Oct 20 05:27:42 PDT 2025


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

Integrate the NAN module with the wpa_supplicant.

- Introduce a new NAN device interface that can be used for
  NAN management flows. Support creating this interface dynamically.
- Support setting NAN configuration, and support starting/stopping
  NAN Device operation.

Signed-off-by: Ilan Peer <ilan.peer at intel.com>
---
 wpa_supplicant/Android.mk         |   6 ++
 wpa_supplicant/Makefile           |   6 ++
 wpa_supplicant/ctrl_iface.c       |   3 +
 wpa_supplicant/defconfig          |   3 +
 wpa_supplicant/driver_i.h         |  19 +++++
 wpa_supplicant/events.c           |   9 ++-
 wpa_supplicant/nan_supplicant.c   | 111 ++++++++++++++++++++++++++++++
 wpa_supplicant/nan_supplicant.h   |  45 ++++++++++++
 wpa_supplicant/wpa_cli.c          |  19 ++++-
 wpa_supplicant/wpa_supplicant.c   |  19 +++--
 wpa_supplicant/wpa_supplicant_i.h |  11 +++
 11 files changed, 245 insertions(+), 6 deletions(-)
 create mode 100644 wpa_supplicant/nan_supplicant.c
 create mode 100644 wpa_supplicant/nan_supplicant.h

diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index e09768a9d9..cf3b3062a7 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -283,6 +283,12 @@ L_CFLAGS += -DCONFIG_DPP3
 endif
 endif
 
+ifdef CONFIG_NAN
+OBJS += nan_supplicant.o
+OBJS += src/nan/nan.o
+CFLAGS += -DCONFIG_NAN
+endif
+
 ifdef CONFIG_NAN_USD
 OBJS += src/common/nan_de.c
 OBJS += nan_usd.c
diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
index b72d9399e1..b15a87d241 100644
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -317,6 +317,12 @@ CFLAGS += -DCONFIG_DPP3
 endif
 endif
 
+ifdef CONFIG_NAN
+OBJS += nan_supplicant.o
+OBJS += ../src/nan/nan.o
+CFLAGS += -DCONFIG_NAN
+endif
+
 ifdef CONFIG_NAN_USD
 OBJS += ../src/common/nan_de.o
 OBJS += nan_usd.o
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 688d2034b2..c415047e79 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -14292,6 +14292,9 @@ static int wpa_supplicant_global_iface_add(struct wpa_global *global,
 				type = WPA_IF_STATION;
 			} else if (os_strcmp(pos, "ap") == 0) {
 				type = WPA_IF_AP_BSS;
+			} else if (os_strcmp(pos, "nan") == 0) {
+				type = WPA_IF_NAN;
+				iface.nan_mgmt = 1;
 			} else {
 				wpa_printf(MSG_DEBUG,
 					   "INTERFACE_ADD unsupported interface type: '%s'",
diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig
index 52befd8f15..6bbd8c4b65 100644
--- a/wpa_supplicant/defconfig
+++ b/wpa_supplicant/defconfig
@@ -686,3 +686,6 @@ CONFIG_DPP2=y
 
 # Wi-Fi Aware unsynchronized service discovery (NAN USD)
 #CONFIG_NAN_USD=y
+
+# Wi-Fi Aware (NAN) support
+#CONFIG_NAN=y
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index ccebd2cbed..4b253e7c9b 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -1267,4 +1267,23 @@ wpas_drv_nan_cancel_subscribe(struct wpa_supplicant *wpa_s, int subscribe_id)
 						   subscribe_id);
 }
 
+#ifdef CONFIG_NAN
+
+static inline int wpa_drv_nan_start(struct wpa_supplicant *wpa_s,
+				    struct nan_cluster_config *conf)
+{
+	if (!wpa_s->driver->nan_start)
+		return -1;
+	return wpa_s->driver->nan_start(wpa_s->drv_priv, conf);
+}
+
+static inline void wpa_drv_nan_stop(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s->driver->nan_stop)
+		return;
+	wpa_s->driver->nan_stop(wpa_s->drv_priv);
+}
+
+#endif /* CONFIG_NAN */
+
 #endif /* DRIVER_I_H */
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 7ea1199cb7..a3e3a35f88 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -54,6 +54,7 @@
 #include "nan_usd.h"
 #include "dpp_supplicant.h"
 #include "pr_supplicant.h"
+#include "nan_supplicant.h"
 
 
 #define MAX_OWE_TRANSITION_BSS_SELECT_COUNT 5
@@ -6924,7 +6925,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
 			else
 				wpa_sm_pmksa_cache_reconfig(wpa_s->wpa);
 			wpa_supplicant_set_default_scan_ies(wpa_s);
-			if (wpa_s->p2p_mgmt) {
+			if (wpa_s->p2p_mgmt || wpa_s->nan_mgmt) {
 				wpa_supplicant_set_state(wpa_s,
 							 WPA_DISCONNECTED);
 				break;
@@ -6947,6 +6948,12 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
 		break;
 	case EVENT_INTERFACE_DISABLED:
 		wpa_dbg(wpa_s, MSG_DEBUG, "Interface was disabled");
+		if (wpa_s->nan_mgmt) {
+			wpas_nan_flush(wpa_s);
+			wpa_supplicant_set_state(wpa_s,
+						 WPA_INTERFACE_DISABLED);
+			break;
+		}
 #ifdef CONFIG_P2P
 		if (wpa_s->p2p_group_interface == P2P_GROUP_INTERFACE_GO ||
 		    (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group &&
diff --git a/wpa_supplicant/nan_supplicant.c b/wpa_supplicant/nan_supplicant.c
new file mode 100644
index 0000000000..612f387adf
--- /dev/null
+++ b/wpa_supplicant/nan_supplicant.c
@@ -0,0 +1,111 @@
+/*
+ * wpa_supplicant - NAN
+ * Copyright (C) 2025 Intel Corporation
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "wpa_supplicant_i.h"
+#include "driver_i.h"
+#include "nan/nan.h"
+#include "config.h"
+
+#define DEFAULT_NAN_MASTER_PREF 2
+#define DEFAULT_NAN_DUAL_BAND   0
+
+
+static int wpas_nan_start_cb(void *ctx, struct nan_cluster_config *config)
+{
+	struct wpa_supplicant *wpa_s = ctx;
+
+	return wpa_drv_nan_start(wpa_s, config);
+}
+
+
+static void wpas_nan_stop_cb(void *ctx)
+{
+	struct wpa_supplicant *wpa_s = ctx;
+
+	wpa_drv_nan_stop(wpa_s);
+}
+
+
+int wpas_nan_init(struct wpa_supplicant *wpa_s)
+{
+	struct nan_config nan;
+
+	if (!(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SUPPORT_NAN)) {
+		wpa_printf(MSG_DEBUG, "NAN: NAN is not supported");
+		return -1;
+	}
+
+	os_memset(&nan, 0, sizeof(nan));
+	nan.cb_ctx = wpa_s;
+
+	nan.start = wpas_nan_start_cb;
+	nan.stop = wpas_nan_stop_cb;
+
+	wpa_s->nan = nan_init(&nan);
+	if (!wpa_s->nan) {
+		wpa_printf(MSG_DEBUG, "NAN: Failed to init");
+		return -1;
+	}
+
+	return 0;
+}
+
+
+void wpas_nan_deinit(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s || !wpa_s->nan)
+		return;
+
+	nan_deinit(wpa_s->nan);
+	wpa_s->nan = NULL;
+}
+
+
+static int wpas_nan_ready(struct wpa_supplicant *wpa_s)
+{
+	return wpa_s->nan_mgmt && wpa_s->nan &&
+	       wpa_s->wpa_state != WPA_INTERFACE_DISABLED;
+}
+
+
+/* Join a cluster using current configuration */
+int wpas_nan_start(struct wpa_supplicant *wpa_s)
+{
+	struct nan_cluster_config cluster_config;
+
+	if (!wpas_nan_ready(wpa_s))
+		return -1;
+
+	cluster_config.master_pref = DEFAULT_NAN_MASTER_PREF;
+	cluster_config.dual_band = DEFAULT_NAN_DUAL_BAND;
+
+	return nan_start(wpa_s->nan, &cluster_config);
+}
+
+
+int wpas_nan_stop(struct wpa_supplicant *wpa_s)
+{
+	if (!wpas_nan_ready(wpa_s))
+		return -1;
+
+	nan_stop(wpa_s->nan);
+
+	return 0;
+}
+
+
+void wpas_nan_flush(struct wpa_supplicant *wpa_s)
+{
+	if (!wpas_nan_ready(wpa_s))
+		return;
+
+	nan_flush(wpa_s->nan);
+}
diff --git a/wpa_supplicant/nan_supplicant.h b/wpa_supplicant/nan_supplicant.h
new file mode 100644
index 0000000000..615c6f64aa
--- /dev/null
+++ b/wpa_supplicant/nan_supplicant.h
@@ -0,0 +1,45 @@
+/*
+ * wpa_supplicant - NAN
+ * Copyright (C) 2025 Intel Corporation
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef NAN_SUPPLICANT_H
+#define NAN_SUPPLICANT_H
+
+#ifdef CONFIG_NAN
+
+int wpas_nan_init(struct wpa_supplicant *wpa_s);
+void wpas_nan_deinit(struct wpa_supplicant *wpa_s);
+int wpas_nan_start(struct wpa_supplicant *wpa_s);
+int wpas_nan_stop(struct wpa_supplicant *wpa_s);
+void wpas_nan_flush(struct wpa_supplicant *wpa_s);
+
+#else /* CONFIG_NAN */
+
+static inline int wpas_nan_init(struct wpa_supplicant *wpa_s)
+{
+	return -1;
+}
+
+static inline void wpas_nan_deinit(struct wpa_supplicant *wpa_s)
+{}
+
+static inline int wpas_nan_start(struct wpa_supplicant *wpa_s)
+{
+	return -1;
+}
+
+static inline int wpas_nan_stop(struct wpa_supplicant *wpa_s)
+{
+	return -1;
+}
+
+static inline void wpas_nan_flush(struct wpa_supplicant *wpa_s)
+{}
+
+#endif /* CONFIG_NAN */
+
+#endif /* NAN_SUPPLICANT_H */
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index caa4170491..e62ea2ddf0 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -3391,13 +3391,30 @@ static int wpa_cli_cmd_nan_flush(struct wpa_ctrl *ctrl, int argc,
 #endif /* CONFIG_NAN_USD */
 
 
+#ifdef CONFIG_NAN
+
+static int wpa_cli_cmd_nan_start(struct wpa_ctrl *ctrl, int argc,
+				 char *argv[])
+{
+	return wpa_cli_cmd(ctrl, "NAN_START", 0, argc, argv);
+}
+
+
+static int wpa_cli_cmd_nan_stop(struct wpa_ctrl *ctrl, int argc,
+				char *argv[])
+{
+	return wpa_cli_cmd(ctrl, "NAN_STOP", 0, argc, argv);
+}
+
+#endif /* CONFIG_NAN */
+
+
 static int wpa_cli_cmd_generate_new_mac(struct wpa_ctrl *ctrl, int argc,
 					char *argv[])
 {
 	return wpa_ctrl_command(ctrl, "NEW_RANDOM_MAC_ADDRESS");
 }
 
-
 enum wpa_cli_cmd_flags {
 	cli_cmd_flag_none		= 0x00,
 	cli_cmd_flag_sensitive		= 0x01
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 317ca3d57d..2edabec56c 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -67,6 +67,7 @@
 #include "dpp_supplicant.h"
 #include "nan_usd.h"
 #include "pr_supplicant.h"
+#include "nan_supplicant.h"
 #ifdef CONFIG_MESH
 #include "ap/ap_config.h"
 #include "ap/hostapd.h"
@@ -6180,7 +6181,8 @@ int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
 
 	if ((!wpa_s->p2p_mgmt ||
 	     !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
-	    !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
+	    !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE) &&
+	    !wpa_s->nan_mgmt) {
 		l2_packet_deinit(wpa_s->l2);
 		wpa_s->l2 = l2_packet_init(wpa_s->ifname,
 					   wpa_drv_get_mac_addr(wpa_s),
@@ -7874,6 +7876,8 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
 	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
 		wpa_s->p2p_mgmt = iface->p2p_mgmt;
 
+	wpa_s->nan_mgmt = iface->nan_mgmt;
+
 	if (wpa_s->num_multichan_concurrent == 0)
 		wpa_s->num_multichan_concurrent = 1;
 
@@ -7881,7 +7885,7 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
 		return -1;
 
 #ifdef CONFIG_TDLS
-	if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
+	if (!iface->p2p_mgmt && !iface->nan_mgmt && wpa_tdls_init(wpa_s->wpa))
 		return -1;
 #endif /* CONFIG_TDLS */
 
@@ -8031,6 +8035,11 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
 
 	wpa_supplicant_set_default_scan_ies(wpa_s);
 
+	if (wpa_s->nan_mgmt && wpas_nan_init(wpa_s) < 0) {
+		wpa_msg(wpa_s, MSG_ERROR, "Failed to init NAN");
+		return -1;
+	}
+
 	return 0;
 }
 
@@ -8082,6 +8091,8 @@ static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
 	wpa_supplicant_cleanup(wpa_s);
 	wpas_p2p_deinit_iface(wpa_s);
 
+	wpas_nan_deinit(wpa_s);
+
 	wpas_ctrl_radio_work_flush(wpa_s);
 	radio_remove_interface(wpa_s);
 
@@ -8249,7 +8260,7 @@ struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
 		return NULL;
 	}
 
-	if (iface->p2p_mgmt == 0) {
+	if (iface->p2p_mgmt == 0 && iface->nan_mgmt == 0) {
 		/* Notify the control interfaces about new iface */
 		if (wpas_notify_iface_added(wpa_s)) {
 			wpa_supplicant_deinit_iface(wpa_s, 1, 0);
@@ -8267,7 +8278,7 @@ struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
 	wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
 
 #ifdef CONFIG_P2P
-	if (wpa_s->global->p2p == NULL &&
+	if (!wpa_s->global->p2p && !iface->nan_mgmt &&
 	    !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
 	    (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
 	    wpas_p2p_add_p2pdev_interface(
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 9780822dfc..22450c3316 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -135,6 +135,11 @@ struct wpa_interface {
 		WPA_IFACE_MATCHED
 	} matched;
 #endif /* CONFIG_MATCH_IFACE */
+
+	/**
+	 * nan_mgmt - Interface used for NAN management (NAN Device operations)
+	 */
+	bool nan_mgmt;
 };
 
 /**
@@ -1641,6 +1646,12 @@ struct wpa_supplicant {
 	unsigned int next_beacon_check;
 
 	bool scs_reconfigure;
+
+	bool nan_mgmt;
+
+#ifdef CONFIG_NAN
+	struct nan_data *nan;
+#endif
 };
 
 
-- 
2.49.0




More information about the Hostap mailing list