[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