[PATCH 83/97] wpa_supplicant: Send response when pairing is aborted

Andrei Otcheretianski andrei.otcheretianski at intel.com
Tue Apr 28 13:06:24 PDT 2026


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

When the user calls pairing abort, send a response to the peer with
failure so it won't keep waiting for a response.
Modify the pairing abort hwsim test so that only the publisher aborts
the pairing in response to the pairing request. The subscriber should
receive pairing result with failure status.

Signed-off-by: Avraham Stern <avraham.stern at intel.com>
---
 src/nan/nan.c           |  21 ++++++++
 src/nan/nan_i.h         |   1 +
 src/nan/nan_ndl.c       |   6 +--
 src/nan/nan_pairing.c   | 115 ++++++++++++++++++++++++++++++----------
 tests/hwsim/test_nan.py |   9 +++-
 5 files changed, 118 insertions(+), 34 deletions(-)

diff --git a/src/nan/nan.c b/src/nan/nan.c
index dafc59e250..7badf419cf 100644
--- a/src/nan/nan.c
+++ b/src/nan/nan.c
@@ -1695,6 +1695,27 @@ int nan_configure_peer_schedule(struct nan_data *nan, struct nan_peer *peer,
 }
 
 
+int nan_clear_peer_schedule(struct nan_data *nan, struct nan_peer *peer)
+{
+	int ret;
+
+	wpa_printf(MSG_DEBUG, "NAN: Clear peer schedule, peer->configured=%d",
+		   peer->configured);
+
+	if (!peer->configured)
+		return 0;
+
+	ret = nan->cfg->set_peer_schedule(nan->cfg->cb_ctx, peer->nmi_addr,
+					  false, 0, peer->info.seq_id, 0, NULL,
+					  NULL);
+	if (ret)
+		wpa_printf(MSG_DEBUG, "NAN: Failed to clear peer schedule");
+
+	peer->configured = false;
+	return 0;
+}
+
+
 /**
  * nan_process_followup - Process a received NAN Follow-up Action frame
  * @nan: NAN module context from nan_init()
diff --git a/src/nan/nan_i.h b/src/nan/nan_i.h
index 9ce0b99789..501d5f17f9 100644
--- a/src/nan/nan_i.h
+++ b/src/nan/nan_i.h
@@ -847,6 +847,7 @@ int nan_configure_peer_schedule(struct nan_data *nan, struct nan_peer *peer,
 				const struct nan_schedule *local_sched);
 bool nan_is_ndpe_supported(struct nan_data *nan, struct nan_peer *peer);
 void nan_add_kde_hdr(struct wpabuf *buf, u32 kde, size_t data_len);
+int nan_clear_peer_schedule(struct nan_data *nan, struct nan_peer *peer);
 #ifdef CONFIG_PASN
 int nan_nira_get_tag_nonce(const struct nan_config *nan, u8 *nonce, u8 *tag);
 void nan_pairing_deinit_peer(struct nan_peer *peer);
diff --git a/src/nan/nan_ndl.c b/src/nan/nan_ndl.c
index 0eb7c798fb..c09b1f9fba 100644
--- a/src/nan/nan_ndl.c
+++ b/src/nan/nan_ndl.c
@@ -119,11 +119,7 @@ static void nan_ndl_clear(struct nan_data *nan, struct nan_peer *peer)
 		   MAC2STR(peer->nmi_addr),
 		   nan_ndl_state_str(peer->ndl->state), peer->ndl->state);
 
-	if (peer->configured) {
-		nan->cfg->set_peer_schedule(nan->cfg->cb_ctx, peer->nmi_addr,
-					    false, 0, 0, 0, NULL, NULL);
-		peer->configured = false;
-	}
+	nan_clear_peer_schedule(nan, peer);
 
 	os_free(ndl->ndc_sched);
 	ndl->ndc_sched = NULL;
diff --git a/src/nan/nan_pairing.c b/src/nan/nan_pairing.c
index 00df9d5b96..f201cbe7aa 100644
--- a/src/nan/nan_pairing.c
+++ b/src/nan/nan_pairing.c
@@ -93,32 +93,6 @@ void nan_pairing_deinit_peer(struct nan_peer *peer)
 }
 
 
-int nan_pairing_abort(struct nan_data *nan_data, const u8 *peer_addr)
-{
-	struct nan_peer *peer;
-
-	peer = nan_get_peer(nan_data, peer_addr);
-	if (!peer) {
-		wpa_printf(MSG_DEBUG,
-			   "NAN: Pairing abort: Peer " MACSTR " not found",
-			   MAC2STR(peer_addr));
-		return -1;
-	}
-
-	if (!peer->pairing.pasn && !peer->pairing.pending_auth1) {
-		wpa_printf(MSG_DEBUG,
-			   "NAN: Pairing abort: No PASN in progress with peer "
-			   MACSTR, MAC2STR(peer_addr));
-		return -1;
-	}
-
-	wpa_printf(MSG_DEBUG, "NAN: Aborting pairing with peer " MACSTR,
-		   MAC2STR(peer_addr));
-	nan_pairing_deinit_peer(peer);
-	return 0;
-}
-
-
 static bool nan_pairing_is_supported(struct nan_data *nan_data,
 				     struct nan_peer *peer, u8 auth_mode)
 {
@@ -846,12 +820,20 @@ int nan_pairing_pasn_auth_tx_status(struct nan_data *nan, const u8 *data,
 		return -1;
 
 	peer = nan_get_peer(nan, mgmt->da);
-	if (!peer || !peer->pairing.pasn) {
+	if (!peer) {
 		wpa_printf(MSG_DEBUG, "NAN: Pairing: Peer not found " MACSTR,
 			   MAC2STR(mgmt->da));
 		return -1;
 	}
 
+	/* Pairing was rejected. Clear peer schedule if no active NDPs */
+	if (!peer->pairing.pasn) {
+		if (dl_list_empty(&peer->ndps) && !peer->ndp_setup.ndp)
+			nan_clear_peer_schedule(nan, peer);
+
+		return 0;
+	}
+
 	pasn = peer->pairing.pasn;
 
 	ret = wpa_pasn_auth_tx_status(pasn, data, data_len, acked);
@@ -1548,3 +1530,82 @@ void nan_pairing_unpair_peer(struct nan_data *nan_data, const u8 *peer_addr)
 	peer->pairing.flags &= ~NAN_PAIRING_FLAG_PAIRED;
 	nan_pairing_deinit_peer(peer);
 }
+
+
+int nan_pairing_abort(struct nan_data *nan_data, const u8 *peer_addr)
+{
+	struct nan_peer *peer;
+	int cipher;
+	struct wpabuf *extra_ies;
+	int ret = -1;
+
+	peer = nan_get_peer(nan_data, peer_addr);
+	if (!peer) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN: Pairing abort: Peer " MACSTR " not found",
+			   MAC2STR(peer_addr));
+		return -1;
+	}
+
+	if (!peer->pairing.pasn && !peer->pairing.pending_auth1) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN: Pairing abort: No PASN in progress with peer "
+			   MACSTR, MAC2STR(peer_addr));
+		return -1;
+	}
+
+	wpa_printf(MSG_DEBUG, "NAN: Aborting pairing with peer " MACSTR,
+		   MAC2STR(peer_addr));
+
+	if (!peer->pairing.pending_auth1) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN: Pairing abort: No pending Auth1 frame for peer "
+			   MACSTR, MAC2STR(peer_addr));
+		ret = 0;
+		goto done;
+	}
+
+	/* The auth mode and cipher are not important when rejecting.
+	 * Just make sure to use a supported cipher so
+	 * nan_pairing_pasn_initialize won't fail.
+	 */
+	cipher = (nan_data->cfg->pairing_cfg.cipher_suites &
+		  NAN_PAIRING_PASN_128) ? WPA_CIPHER_CCMP : WPA_CIPHER_GCMP_256;
+
+	if (nan_pairing_pasn_initialize(nan_data, peer, NAN_PASN_AUTH_MODE_PASN,
+					cipher, "",
+					NAN_PAIRING_ROLE_RESPONDER)) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN: Pairing: Initialize failed");
+		goto done;
+	}
+
+	extra_ies = wpabuf_alloc(NAN_ELEMENT_MAX_SIZE);
+	if (!extra_ies) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN: Pairing: Failed to allocate buffer for extra IEs");
+		goto done;
+	}
+
+	nan_pairing_prepare_pasn_elems(nan_data, peer, extra_ies,
+				       peer->pairing.peer_instance_id,
+				       NAN_PASN_AUTH_MODE_PASN);
+	pasn_set_extra_ies(peer->pairing.pasn, wpabuf_head_u8(extra_ies),
+			   wpabuf_len(extra_ies));
+	wpabuf_free(extra_ies);
+
+	nan_configure_peer_schedule(nan_data, peer, &nan_data->sched);
+
+	ret = handle_auth_pasn_resp(peer->pairing.pasn, nan_data->cfg->nmi_addr,
+				    peer_addr, NULL,
+				    WLAN_STATUS_UNSPECIFIED_FAILURE);
+	if (ret < 0) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN: Pairing abort: Failed to send response");
+		nan_clear_peer_schedule(nan_data, peer);
+	}
+
+done:
+	nan_pairing_deinit_peer(peer);
+	return ret;
+}
diff --git a/tests/hwsim/test_nan.py b/tests/hwsim/test_nan.py
index 53ceb3bad9..8b3dff57d8 100644
--- a/tests/hwsim/test_nan.py
+++ b/tests/hwsim/test_nan.py
@@ -1534,11 +1534,16 @@ def test_nan_pair_abort(dev, apdev, params):
         if ev_pub is None:
             raise Exception("PASN pairing request not seen on publisher")
 
-        if "OK" not in sub.pair_abort(paddr):
-            raise Exception("NAN_PAIR_ABORT failed on subscriber")
         if "OK" not in pub.pair_abort(saddr):
             raise Exception("NAN_PAIR_ABORT failed on publisher")
 
+        # The subscriber should get a failure result
+        ev_sub = sub.wpas.wait_event(["NAN-PAIRING-STATUS"], timeout=5)
+        if ev_sub is None:
+            raise Exception("PASN result not seen on subscriber")
+        if "status=failure" not in ev_sub:
+            raise Exception("NAN pairing failed status not seen on subscriber after abort")
+
         # After abort, we should be able to restart pairing successfully
         sub.pairing_request(pub, sid, pid, "SAE", responder=False, password="password123")
         ev_pub = pub.wpas.wait_event(["NAN-PAIRING-REQUEST"], timeout=2)
-- 
2.53.0




More information about the Hostap mailing list