From e9c4cfa0a52bd59565f0fe0e55441abe3bc1f1b0 Mon Sep 17 00:00:00 2001 From: Akshat Agrawal Date: Wed, 10 Jun 2026 18:07:48 +0530 Subject: [PATCH] Add pairing followup timeout and post CONFIRM Failure --- .../esp_wifi/include/esp_wifi_types_generic.h | 7 +- .../include/injected/esp_wifi_types_generic.h | 7 +- .../esp_wifi/wifi_apps/nan_app/src/nan_app.c | 3 + .../esp_wifi/wifi_apps/nan_app/src/nan_i.h | 5 ++ .../wifi_apps/nan_app/src/nan_pairing.c | 80 ++++++++++++++++++- 5 files changed, 93 insertions(+), 9 deletions(-) diff --git a/components/esp_wifi/include/esp_wifi_types_generic.h b/components/esp_wifi/include/esp_wifi_types_generic.h index 412c1a22b2e..fc80352a68c 100644 --- a/components/esp_wifi/include/esp_wifi_types_generic.h +++ b/components/esp_wifi/include/esp_wifi_types_generic.h @@ -1307,7 +1307,7 @@ typedef enum { WIFI_EVENT_NAN_BOOTSTRAP_INDICATION, /**< Received NAN Pairing Bootstrapping Request from a Peer */ WIFI_EVENT_NAN_BOOTSTRAP_COMPLETED, /**< NAN Pairing Bootstrapping completed (success/failure) */ WIFI_EVENT_NAN_PAIRING_INDICATION, /**< Received NAN Pairing indication (reserved) */ - WIFI_EVENT_NAN_PAIRING_CONFIRM, /**< NAN PASN pairwise key installation completed */ + WIFI_EVENT_NAN_PAIRING_CONFIRM, /**< NAN pairing completed after NIK follow-up exchange */ WIFI_EVENT_NAN_CLUSTER_JOIN, /**< NAN Cluster joined/started successfully */ WIFI_EVENT_MAX, /**< Invalid Wi-Fi event ID */ } wifi_event_t; @@ -1668,11 +1668,10 @@ typedef struct { uint32_t cookie; /**< Comeback cookie from responder (0 if none) */ } wifi_event_nan_bootstrap_complete_t; +#define WIFI_NAN_PAIRING_REASON_NIK_FUP_TIMEOUT 1 /**< Peer NIK follow-up not received (Wi-Fi Aware v4.0 §7.6.4.2) */ + /** * @brief Argument structure for WIFI_EVENT_NAN_PAIRING_CONFIRM event - * - * Posted when PASN pairwise key installation completes. - * Distinct from WIFI_EVENT_NAN_BOOTSTRAP_COMPLETED (NPBA follow-up bootstrapping). */ typedef struct { uint8_t status; /**< 0=Accepted, 1=Rejected (wifi_nan_pairing_status_t) */ diff --git a/components/esp_wifi/remote/include/injected/esp_wifi_types_generic.h b/components/esp_wifi/remote/include/injected/esp_wifi_types_generic.h index 266a5027bf3..cf66ba38bfb 100644 --- a/components/esp_wifi/remote/include/injected/esp_wifi_types_generic.h +++ b/components/esp_wifi/remote/include/injected/esp_wifi_types_generic.h @@ -1307,7 +1307,7 @@ typedef enum { WIFI_EVENT_NAN_BOOTSTRAP_INDICATION, /**< Received NAN Pairing Bootstrapping Request from a Peer */ WIFI_EVENT_NAN_BOOTSTRAP_COMPLETED, /**< NAN Pairing Bootstrapping completed (success/failure) */ WIFI_EVENT_NAN_PAIRING_INDICATION, /**< Received NAN Pairing indication (reserved) */ - WIFI_EVENT_NAN_PAIRING_CONFIRM, /**< NAN PASN pairwise key installation completed */ + WIFI_EVENT_NAN_PAIRING_CONFIRM, /**< NAN pairing completed after NIK follow-up exchange */ WIFI_EVENT_NAN_CLUSTER_JOIN, /**< NAN Cluster joined/started successfully */ WIFI_EVENT_MAX, /**< Invalid Wi-Fi event ID */ } wifi_event_t; @@ -1668,11 +1668,10 @@ typedef struct { uint32_t cookie; /**< Comeback cookie from responder (0 if none) */ } wifi_event_nan_bootstrap_complete_t; +#define WIFI_NAN_PAIRING_REASON_NIK_FUP_TIMEOUT 1 /**< Peer NIK follow-up not received (Wi-Fi Aware v4.0 §7.6.4.2) */ + /** * @brief Argument structure for WIFI_EVENT_NAN_PAIRING_CONFIRM event - * - * Posted when PASN pairwise key installation completes. - * Distinct from WIFI_EVENT_NAN_BOOTSTRAP_COMPLETED (NPBA follow-up bootstrapping). */ typedef struct { uint8_t status; /**< 0=Accepted, 1=Rejected (wifi_nan_pairing_status_t) */ diff --git a/components/esp_wifi/wifi_apps/nan_app/src/nan_app.c b/components/esp_wifi/wifi_apps/nan_app/src/nan_app.c index 347b643c92f..91e89555a88 100644 --- a/components/esp_wifi/wifi_apps/nan_app/src/nan_app.c +++ b/components/esp_wifi/wifi_apps/nan_app/src/nan_app.c @@ -414,6 +414,9 @@ static void nan_reset_service(uint8_t svc_id, bool reset_all) while (idx < ESP_WIFI_NAN_MAX_SVC_SUPPORTED) { p_own_svc = &s_nan_ctx.own_svc[idx++]; if (reset_all || (svc_id && p_own_svc->svc_id == svc_id)) { +#ifdef CONFIG_ESP_WIFI_NAN_PAIRING + nan_pairing_cancel_svc_pending(p_own_svc); +#endif SLIST_FOREACH_SAFE(p_peer_svc, &(p_own_svc->peer_list), next, temp) { SLIST_REMOVE(&(p_own_svc->peer_list), p_peer_svc, peer_svc_info, next); os_free(p_peer_svc); diff --git a/components/esp_wifi/wifi_apps/nan_app/src/nan_i.h b/components/esp_wifi/wifi_apps/nan_app/src/nan_i.h index c58587ec7aa..40976b5e45c 100644 --- a/components/esp_wifi/wifi_apps/nan_app/src/nan_i.h +++ b/components/esp_wifi/wifi_apps/nan_app/src/nan_i.h @@ -223,6 +223,10 @@ struct own_svc_info { #endif uint8_t num_peer_records; SLIST_HEAD(peer_list_t, peer_svc_info) peer_list; +#if CONFIG_ESP_WIFI_NAN_PAIRING + bool nik_fup_pending; + uint8_t nik_fup_pending_peer_nmi[MACADDR_LEN]; +#endif }; /* Per-NDP link state */ @@ -340,6 +344,7 @@ void nan_app_bootstrap_completed(uint8_t status, uint8_t peer_svc_id, uint8_t su uint8_t reason_code); bool nan_app_parse_npba_from_receive(uint8_t own_svc_id, uint8_t peer_svc_id, uint8_t peer_nmi[6], const struct nan_cb_npba_t *npba); +void nan_pairing_cancel_svc_pending(struct own_svc_info *own); #endif /* CONFIG_ESP_WIFI_NAN_PAIRING */ #ifdef CONFIG_ESP_WIFI_NAN_SECURITY diff --git a/components/esp_wifi/wifi_apps/nan_app/src/nan_pairing.c b/components/esp_wifi/wifi_apps/nan_app/src/nan_pairing.c index 73fcc571539..d20763947f7 100644 --- a/components/esp_wifi/wifi_apps/nan_app/src/nan_pairing.c +++ b/components/esp_wifi/wifi_apps/nan_app/src/nan_pairing.c @@ -400,6 +400,7 @@ int esp_nan_construct_nira(uint8_t *frm) #define NAN_PAIRING_SRV_PORT 3333 #define NAN_PAIRING_SRV_HOSTNAME "ESP-SRV-1234" #define NAN_PAIRING_SSI_BUF_LEN 64 +#define NAN_PAIRING_NIK_FUP_TIMEOUT_SEC 2 struct nan_pairing_fup_ctx { uint8_t svc_id; @@ -437,6 +438,56 @@ static struct peer_svc_info *nan_find_peer_svc_exact(uint8_t own_svc_id, uint8_t return NULL; } +static void nan_pairing_nik_fup_timeout_cb(void *eloop_data, void *user_ctx); + +void nan_pairing_cancel_svc_pending(struct own_svc_info *own) +{ + if (!own || !own->nik_fup_pending) { + return; + } + + eloop_cancel_timeout(nan_pairing_nik_fup_timeout_cb, NULL, own); + own->nik_fup_pending = false; +} + +static void nan_pairing_arm_pending(struct own_svc_info *own, const uint8_t *peer_mac) +{ + if (!own || !peer_mac) { + return; + } + + nan_pairing_cancel_svc_pending(own); + MACADDR_COPY(own->nik_fup_pending_peer_nmi, peer_mac); + own->nik_fup_pending = true; + + if (eloop_register_timeout(NAN_PAIRING_NIK_FUP_TIMEOUT_SEC, 0, + nan_pairing_nik_fup_timeout_cb, NULL, + own) != 0) { + own->nik_fup_pending = false; + } +} + +static void nan_pairing_nik_fup_timeout_cb(void *eloop_data, void *user_ctx) +{ + struct own_svc_info *own = user_ctx; + wifi_event_nan_pairing_complete_t evt = {0}; + + (void)eloop_data; + + if (!own || !own->nik_fup_pending) { + return; + } + + own->nik_fup_pending = false; + evt.status = WIFI_NAN_PAIRING_STATUS_REJECTED; + evt.reason_code = WIFI_NAN_PAIRING_REASON_NIK_FUP_TIMEOUT; + MACADDR_COPY(evt.peer_nmi, own->nik_fup_pending_peer_nmi); + esp_nan_disable_pairing(own->svc_id); + nan_app_post_event(WIFI_EVENT_NAN_PAIRING_CONFIRM, &evt, sizeof(evt)); + ESP_LOGW(TAG, "Pairing NIK follow-up timed out for peer " MACSTR, + MAC2STR(own->nik_fup_pending_peer_nmi)); +} + /** * Build the WFA OUI + GSP protocol header that prefixes a Generic Service * Protocol SSI (Wi-Fi Aware v4.0 §4.2.7). Ported from esp-nsd @@ -828,13 +879,35 @@ static void nan_pairing_key_installed_cb(const uint8_t *peer_nmi, MACADDR_COPY(ctx->peer_mac, peer_nmi); ctx->shared_key_attr_len = 0; + struct own_svc_info *own = nan_find_own_svc(ctx->svc_id); + if (own) { + nan_pairing_arm_pending(own, peer_nmi); + } + if (eloop_register_timeout(0, 0, nan_app_send_pairing_followup_eloop, NULL, ctx) != 0) { ESP_LOGW(TAG, "Pairing key installed: failed to schedule initiator follow-up"); + if (own) { + nan_pairing_cancel_svc_pending(own); + } os_free(ctx); } return; } - (void)role; + + if (role == NAN_ROLE_PAIRING_RESPONDER) { + struct own_svc_info *own = NULL; + + NAN_DATA_LOCK(); + struct peer_svc_info *peer = nan_find_peer_svc(0, 0, (uint8_t *)peer_nmi); + if (peer) { + own = nan_find_own_svc(peer->own_svc_id); + } + NAN_DATA_UNLOCK(); + + if (own) { + nan_pairing_arm_pending(own, peer_nmi); + } + } } void nan_app_receive_pairing_followup(uint8_t svc_id, uint8_t peer_svc_id, @@ -903,6 +976,11 @@ void nan_app_receive_pairing_followup(uint8_t svc_id, uint8_t peer_svc_id, /* Invoke blocking calls outside NAN_DATA_LOCK to avoid deadlock. */ if (pairing_completed) { wifi_event_nan_pairing_complete_t evt = {0}; + + struct own_svc_info *own = nan_find_own_svc(own_svc_id_to_disable); + if (own) { + nan_pairing_cancel_svc_pending(own); + } evt.status = WIFI_NAN_PAIRING_STATUS_ACCEPTED; evt.reason_code = 0; MACADDR_COPY(evt.peer_nmi, peer_mac);