Skip to content

Commit 6a45f9d

Browse files
committed
bluetooth: host: Add feature to support bonding with same peer
This commit adds a new Kconfig option by enabling which Host will keep bonding with the same Central instead of rejecting pairing. Brief implementation details: This implementation adds a new flag to bt_keys struct: BT_KEYS_ID_CONFLICT. The flag is set, when: - bonding with the same peer and conflict identified - when loading conflicting keys from persistent storage. When bonding and conflict is identified, the new keys aren't added to the Resolving List immediately. Instead, the old keys stay in the Resolving List. When start advertising, Host finds conflicting keys that are already added to the Resolving List and substitues them. If, however, there is another advertiser already started for the added keys, the new request is reject and advertising start function returns -EPERM. This is supported by Peripheral role only for now. Signed-off-by: Pavel Vasilyev <[email protected]>
1 parent d07064e commit 6a45f9d

File tree

9 files changed

+385
-21
lines changed

9 files changed

+385
-21
lines changed

subsys/bluetooth/host/Kconfig

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,24 @@ config BT_ID_UNPAIR_MATCHING_BONDS
631631
link-layer. The Host does not have control over this acknowledgment,
632632
and the order of distribution is fixed by the specification.
633633

634+
config BT_ID_AUTO_SWAP_MATCHING_BONDS
635+
bool "Automatically swap conflicting entries in the Resolving List"
636+
depends on !BT_ID_UNPAIR_MATCHING_BONDS
637+
depends on BT_PRIVACY && BT_PERIPHERAL && !BT_CENTRAL
638+
select EXPERIMENTAL
639+
help
640+
If this option is enabled, the Host will not add a new bond with
641+
the same peer address (or IRK) to the Resolving List if there is
642+
already a bond with the same peer address (or IRK) on another local
643+
identity.
644+
645+
In case of Peripheral, the Host will swap the existing entry in the
646+
Resolving List with the new one, so that the new bond will be used for
647+
address resolution for the new local identity if the device starts
648+
advertising with the new local identity.
649+
650+
Important: this option is only supported by Peripheral role.
651+
634652
config BT_ID_ALLOW_UNAUTH_OVERWRITE
635653
bool "Allow unauthenticated pairing with same peer with other local identity"
636654
depends on !BT_SMP_ALLOW_UNAUTH_OVERWRITE

subsys/bluetooth/host/adv.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,25 @@ struct bt_le_ext_adv *bt_hci_adv_lookup_handle(uint8_t handle)
272272
#endif /* CONFIG_BT_BROADCASTER */
273273
#endif /* defined(CONFIG_BT_EXT_ADV) */
274274

275+
struct bt_le_ext_adv *bt_adv_lookup_by_id(uint8_t id)
276+
{
277+
#if defined(CONFIG_BT_EXT_ADV)
278+
for (size_t i = 0; i < ARRAY_SIZE(adv_pool); i++) {
279+
if (atomic_test_bit(adv_pool[i].flags, BT_ADV_CREATED) &&
280+
adv_pool[i].id == id) {
281+
return &adv_pool[i];
282+
}
283+
}
284+
#else
285+
if (atomic_test_bit(bt_dev.adv.flags, BT_ADV_CREATED)) {
286+
return &bt_dev.adv;
287+
}
288+
#endif
289+
290+
return NULL;
291+
}
292+
293+
275294
void bt_le_ext_adv_foreach(void (*func)(struct bt_le_ext_adv *adv, void *data),
276295
void *data)
277296
{
@@ -1021,6 +1040,14 @@ int bt_le_adv_start_legacy(struct bt_le_ext_adv *adv,
10211040
adv->id = param->id;
10221041
bt_dev.adv_conn_id = adv->id;
10231042

1043+
if (IS_ENABLED(CONFIG_BT_ID_AUTO_SWAP_MATCHING_BONDS)) {
1044+
err = bt_id_resolving_list_check_and_update(adv->id, param->peer);
1045+
if (err) {
1046+
LOG_ERR("Failed to check and update resolving list: %d", err);
1047+
return err;
1048+
}
1049+
}
1050+
10241051
err = bt_id_set_adv_own_addr(adv, param->options, dir_adv,
10251052
&set_param.own_addr_type);
10261053
if (err) {
@@ -1336,6 +1363,15 @@ int bt_le_adv_start_ext(struct bt_le_ext_adv *adv,
13361363
}
13371364

13381365
adv->id = param->id;
1366+
1367+
if (IS_ENABLED(CONFIG_BT_ID_AUTO_SWAP_MATCHING_BONDS)) {
1368+
err = bt_id_resolving_list_check_and_update(adv->id, param->peer);
1369+
if (err) {
1370+
LOG_ERR("Failed to check and update resolving list: %d", err);
1371+
return err;
1372+
}
1373+
}
1374+
13391375
err = le_ext_adv_param_set(adv, param, sd != NULL);
13401376
if (err) {
13411377
return err;
@@ -1691,6 +1727,22 @@ int bt_le_ext_adv_start(struct bt_le_ext_adv *adv,
16911727
return -EALREADY;
16921728
}
16931729

1730+
if (IS_ENABLED(CONFIG_BT_ID_AUTO_SWAP_MATCHING_BONDS)) {
1731+
bt_addr_le_t *peer;
1732+
1733+
if (bt_addr_le_eq(&adv->target_addr, BT_ADDR_LE_ANY)) {
1734+
peer = NULL;
1735+
} else {
1736+
peer = &adv->target_addr;
1737+
}
1738+
1739+
err = bt_id_resolving_list_check_and_update(adv->id, peer);
1740+
if (err) {
1741+
LOG_ERR("Failed to check and update resolving list: %d", err);
1742+
return err;
1743+
}
1744+
}
1745+
16941746
if (IS_ENABLED(CONFIG_BT_PERIPHERAL) &&
16951747
atomic_test_bit(adv->flags, BT_ADV_CONNECTABLE)) {
16961748
err = le_adv_start_add_conn(adv, &conn);

subsys/bluetooth/host/adv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@ int bt_le_adv_set_enable_ext(struct bt_le_ext_adv *adv,
2525
int bt_le_adv_set_enable_legacy(struct bt_le_ext_adv *adv, bool enable);
2626
int bt_le_lim_adv_cancel_timeout(struct bt_le_ext_adv *adv);
2727
void bt_adv_reset_adv_pool(void);
28+
struct bt_le_ext_adv *bt_adv_lookup_by_id(uint8_t id);

subsys/bluetooth/host/hci_core.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,8 @@ struct bt_keys;
500500
void bt_id_add(struct bt_keys *keys);
501501
void bt_id_del(struct bt_keys *keys);
502502

503-
struct bt_keys *bt_id_find_conflict(struct bt_keys *candidate);
503+
struct bt_keys *bt_id_find_conflict(struct bt_keys *candidate, bool all);
504+
bool bt_id_find_conflict_multiple(struct bt_keys *candidate, struct bt_keys **first_conflict);
504505

505506
int bt_setup_random_id_addr(void);
506507
int bt_setup_public_id_addr(void);

0 commit comments

Comments
 (0)