fix(nimble): Added a change to handle unpair after add was deferred

This commit is contained in:
Rahul Tank
2026-07-03 11:07:20 +05:30
parent d750d6baeb
commit 37599327e2
+44 -4
View File
@@ -4858,6 +4858,23 @@ ble_gap_apply_deferred_pvcy_add(void)
ble_gap_deferred_pvcy_add = false;
ble_gap_deferred_pvcy_replace = false;
/* The bond may have been removed (ble_gap_unpair) after the add was
* deferred but before the connection finished tearing down. Do not
* resurrect a deleted bond in the controller resolving list: only apply
* the deferred add if the peer security record (with IRK) still exists.
* This also guards every other caller of this function. */
{
struct ble_store_key_sec chk_key;
struct ble_store_value_sec chk_val;
memset(&chk_key, 0, sizeof chk_key);
chk_key.peer_addr = addr;
if (ble_store_read_peer_sec(&chk_key, &chk_val) != 0 ||
!chk_val.irk_present) {
return;
}
}
if (replace) {
/* Entry is expected to be present (e.g. already loaded by
* ble_hs_misc_restore_irks at startup); use replace_entry which
@@ -10059,6 +10076,9 @@ ble_gap_unpair(const ble_addr_t *peer_addr)
union ble_store_value value;
union ble_store_key key;
ble_addr_t *new_addr = (ble_addr_t *) peer_addr;
#if MYNEWT_VAL(BLE_DEFER_CONN_EVENTS) && MYNEWT_VAL(BLE_HS_PVCY) && !MYNEWT_VAL(BLE_HOST_BASED_PRIVACY)
int defer_add_pending = 0;
#endif
if (!ble_hs_is_enabled()) {
return BLE_HS_EDISABLED;
}
@@ -10080,6 +10100,17 @@ ble_gap_unpair(const ble_addr_t *peer_addr)
conn = ble_hs_conn_find_by_addr(peer_addr);
if (conn != NULL) {
#if MYNEWT_VAL(BLE_DEFER_CONN_EVENTS) && MYNEWT_VAL(BLE_HS_PVCY) && !MYNEWT_VAL(BLE_HOST_BASED_PRIVACY)
/* The peer IRK add was deferred and has not been pushed to the
* controller resolving list yet. Cancel the pending deferred add so it
* is not resurrected at disconnect, and remember that there is nothing
* to remove from the controller resolving list. */
if (conn->bhc_deferred_pvcy_add) {
conn->bhc_deferred_pvcy_add = 0;
conn->bhc_deferred_pvcy_replace = 0;
defer_add_pending = 1;
}
#endif
ble_gap_terminate_with_conn(conn, BLE_ERR_REM_USER_CONN_TERM);
}
@@ -10111,10 +10142,19 @@ ble_gap_unpair(const ble_addr_t *peer_addr)
if (!rc) {
if (value.sec.irk_present) {
#if MYNEWT_VAL(BLE_HS_PVCY)
// Delete the IRK as it is Distributed
rc = ble_hs_pvcy_remove_entry(key.sec.peer_addr.type,key.sec.peer_addr.val);
if (rc != 0) {
BLE_HS_LOG(ERROR, "Error while removing IRK , rc = %x\n",rc);
#if MYNEWT_VAL(BLE_DEFER_CONN_EVENTS) && !MYNEWT_VAL(BLE_HOST_BASED_PRIVACY)
/* If the peer IRK add was deferred and never applied to the
* controller resolving list, there is nothing to remove; issuing
* the HCI remove would only fail with Unknown Connection
* Identifier (0x02). Skip it in that case. */
if (!defer_add_pending)
#endif
{
// Delete the IRK as it is Distributed
rc = ble_hs_pvcy_remove_entry(key.sec.peer_addr.type,key.sec.peer_addr.val);
if (rc != 0) {
BLE_HS_LOG(ERROR, "Error while removing IRK , rc = %x\n",rc);
}
}
#endif
}