[PATCH 25/92] NAN: Add control interface for triggering NAN pairing

Andrei Otcheretianski andrei.otcheretianski at intel.com
Wed Apr 22 05:23:16 PDT 2026


From: Avraham Stern <avraham.stern at intel.com>

Add control interface support for triggering NAN pairing.
Supported parameters are the authentication mode (SAE, PASN or
pairing verification), the cipher to use and the publish ID.
Add wpa_cli support as well.

Signed-off-by: Avraham Stern <avraham.stern at intel.com>
---
 wpa_supplicant/ctrl_iface.c     |  5 ++
 wpa_supplicant/nan_supplicant.c | 90 +++++++++++++++++++++++++++++++++
 wpa_supplicant/nan_supplicant.h |  1 +
 wpa_supplicant/wpa_cli.c        | 12 +++++
 4 files changed, 108 insertions(+)

diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 690241a6f0..013cc98567 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -14430,6 +14430,11 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
 	} else if (os_strncmp(buf, "NAN_BOOTSTRAP_RESET ", 20) == 0) {
 		if (wpas_nan_bootstrap_reset(wpa_s, buf + 20) < 0)
 			reply_len = -1;
+#ifdef CONFIG_PASN
+	} else if (os_strncmp(buf, "NAN_PAIR ", 9) == 0) {
+		if (wpas_nan_pairing_start(wpa_s, buf + 9) < 0)
+			reply_len = -1;
+#endif /* CONFIG_PASN */
 #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 0eb134a247..9c4b532303 100644
--- a/wpa_supplicant/nan_supplicant.c
+++ b/wpa_supplicant/nan_supplicant.c
@@ -2575,6 +2575,96 @@ int wpas_nan_pair(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
 
 	return ret;
 }
+
+
+/*
+ * Format: NAN_PAIR <peer_nmi> <handle=<id>>
+ *	<peer_instance_id=<id>> <auth=<0|1|2>> <cipher=<CCMP|GCMP-256>>
+ *	[responder] [password=<password>]
+ */
+int wpas_nan_pairing_start(struct wpa_supplicant *wpa_s, char *cmd)
+{
+	char *token, *context = NULL;
+	u8 addr[ETH_ALEN];
+	u8 auth_mode = 0;
+	u8 peer_instance_id = 0;
+	int handle = 0;
+	int cipher = WPA_CIPHER_NONE;
+	char *password = NULL;
+	bool responder = false;
+	char *pos;
+
+	/* Parse peer address first */
+	if (hwaddr_aton(cmd, addr) < 0)
+		return -1;
+
+	/* Move past the peer_mac address */
+	pos = os_strchr(cmd, ' ');
+	if (!pos)
+		return -1;
+	pos++;
+
+	while ((token = str_token(pos, " ", &context))) {
+		if (os_strncmp(token, "auth=", 5) == 0) {
+			auth_mode = atoi(token + 5);
+			if (auth_mode > 2) {
+				wpa_printf(MSG_DEBUG,
+					   "NAN_PAIR: Invalid auth mode: %u",
+					   auth_mode);
+				return -1;
+			}
+		} else if (os_strncmp(token, "handle=", 7) == 0) {
+			handle = atoi(token + 7);
+		} else if (os_strncmp(token, "peer_instance_id=", 17) == 0) {
+			peer_instance_id = atoi(token + 17);
+		} else if (os_strncmp(token, "cipher=", 7) == 0) {
+			if (os_strcmp(token + 7, "CCMP") == 0) {
+				cipher = WPA_CIPHER_CCMP;
+			} else if (os_strcmp(token + 7, "GCMP-256") == 0) {
+				cipher = WPA_CIPHER_GCMP_256;
+			} else {
+				wpa_printf(MSG_DEBUG,
+					   "NAN_PAIR: Invalid cipher: '%s'",
+					   token + 7);
+				return -1;
+			}
+		} else if (os_strncmp(token, "responder", 9) == 0) {
+			responder = true;
+		} else if (os_strncmp(token, "password=", 9) == 0) {
+			password = token + 9;
+		} else {
+			wpa_printf(MSG_DEBUG,
+				   "NAN_PAIR: Invalid parameter: '%s'",
+				   token);
+			return -1;
+		}
+	}
+
+	if (handle <= 0) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN_PAIR: missing or invalid handle");
+		return -1;
+	}
+
+	if (!peer_instance_id) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN_PAIR: missing or invalid peer_instance_id");
+		return -1;
+	}
+
+	if (cipher == WPA_CIPHER_NONE) {
+		wpa_printf(MSG_DEBUG, "NAN_PAIR: missing cipher");
+		return -1;
+	}
+
+	if (wpas_nan_pair(wpa_s, addr, auth_mode, cipher, handle,
+			  peer_instance_id, responder, password) < 0) {
+		wpa_printf(MSG_DEBUG, "NAN_PAIR: Pairing initiation failed");
+		return -1;
+	}
+
+	return 0;
+}
 #endif /* CONFIG_PASN */
 #endif /* CONFIG_NAN */
 
diff --git a/wpa_supplicant/nan_supplicant.h b/wpa_supplicant/nan_supplicant.h
index 3568366b83..3722b3eab0 100644
--- a/wpa_supplicant/nan_supplicant.h
+++ b/wpa_supplicant/nan_supplicant.h
@@ -39,6 +39,7 @@ int wpas_nan_bootstrap_reset(struct wpa_supplicant *wpa_s, char *cmd);
 int wpas_nan_pair(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
 		  u8 auth_mode, int cipher, int handle, u8 peer_instance_id,
 		  bool responder, const char *password);
+int wpas_nan_pairing_start(struct wpa_supplicant *wpa_s, char *cmd);
 #endif /* CONFIG_PASN */
 
 #else /* CONFIG_NAN */
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index a4eab29c07..aec6ac2099 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -3469,6 +3469,13 @@ static int wpa_cli_cmd_nan_bootstrap_reset(struct wpa_ctrl *ctrl,
 	return wpa_cli_cmd(ctrl, "NAN_BOOTSTRAP_RESET", 1, argc, argv);
 }
 
+#ifdef CONFIG_PASN
+static int wpa_cli_cmd_nan_pair_start(struct wpa_ctrl *ctrl, int argc,
+				      char *argv[])
+{
+	return wpa_cli_cmd(ctrl, "NAN_PAIR", 5, argc, argv);
+}
+#endif /* CONFIG_PASN */
 #endif /* CONFIG_NAN */
 
 
@@ -4281,6 +4288,11 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = {
 	{ "nan_bootstrap_reset", wpa_cli_cmd_nan_bootstrap_reset, NULL,
 	  cli_cmd_flag_none,
 	  " = <peer_mac> = Reset NAN boostrapping with peer" },
+#ifdef CONFIG_PASN
+	{ "nan_pair", wpa_cli_cmd_nan_pair_start, NULL,
+	  cli_cmd_flag_none,
+	  " = <peer_mac> <handle=<service handle>> <peer_instance_id=<peer requestor id>> <auth=<0|1|2>> <cipher=<CCMP|GCMP-256>> [password=<password>] [responder] = Request or authorize NAN pairing with peer" },
+#endif /* CONFIG_PASN */
 #endif /* CONFIG_NAN */
 	{ "new_random_mac_address", wpa_cli_cmd_generate_new_mac, NULL,
 	  cli_cmd_flag_none, "= Generate new random MAC address" },
-- 
2.53.0




More information about the Hostap mailing list