Skip to content

Bluetooth: Host: Bonding with the same Central using multiple identities #2963

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions include/zephyr/bluetooth/bluetooth.h
Original file line number Diff line number Diff line change
Expand Up @@ -1489,6 +1489,10 @@ struct bt_le_per_adv_param {
* This error code is only guaranteed when using Zephyr
* controller, for other controllers code returned in
* this case may be -EIO.
* @return -EPERM When @kconfig{CONFIG_BT_PRIVACY} and
* @kconfig{CONFIG_BT_ID_AUTO_SWAP_MATCHING_BONDS} are enabled and connectable
* advertising is requested, and the given local identity has a conflicting
* key with another local identity for which advertising is already started.
*/
int bt_le_adv_start(const struct bt_le_adv_param *param,
const struct bt_data *ad, size_t ad_len,
Expand Down Expand Up @@ -1616,6 +1620,12 @@ struct bt_le_ext_adv_start_param {
*
* @param adv Advertising set object.
* @param param Advertise start parameters.
*
* @return Zero on success or (negative) error code otherwise.
* @return -EPERM When @kconfig{CONFIG_BT_PRIVACY} and
* @kconfig{CONFIG_BT_ID_AUTO_SWAP_MATCHING_BONDS} are enabled and connectable
* advertising is requested, and the given local identity has a conflicting
* key with another local identity for which advertising is already started.
*/
int bt_le_ext_adv_start(struct bt_le_ext_adv *adv,
const struct bt_le_ext_adv_start_param *param);
Expand Down
18 changes: 18 additions & 0 deletions subsys/bluetooth/host/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,24 @@ config BT_ID_UNPAIR_MATCHING_BONDS
link-layer. The Host does not have control over this acknowledgment,
and the order of distribution is fixed by the specification.

config BT_ID_AUTO_SWAP_MATCHING_BONDS
bool "Automatically swap conflicting entries in the Resolving List"
depends on !BT_ID_UNPAIR_MATCHING_BONDS
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think "!BT_CENTRAL" is unnecessary. You may have central which is dealing with other non-private connections with other peripherals, and that would work without any issues.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't even want to think what will happen if BT_CENTRAL is enabled. The current use case is for Peripheral role only. Therefore it is easier to prevent compiling with BT_CENTRAL. If a customer comes with request to support Central role as well, we will look at this again.

depends on BT_PRIVACY && BT_PERIPHERAL && !BT_CENTRAL
help
If this option is enabled, the Host will not add a new bond with
the same peer address (or IRK) to the Resolving List if there is
already a bond with the same peer address (or IRK) on another local
identity.

In case of Peripheral, the Host will swap the existing entry in the
Resolving List with the new one, so that the new bond will be used for
address resolution for the new local identity if the device starts
advertising with the new local identity.

Important: this option is supported exclusively in the Peripheral
role. Excluding the Central role.

config BT_ID_ALLOW_UNAUTH_OVERWRITE
bool "Allow unauthenticated pairing with same peer with other local identity"
depends on !BT_SMP_ALLOW_UNAUTH_OVERWRITE
Expand Down
52 changes: 52 additions & 0 deletions subsys/bluetooth/host/adv.c
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,25 @@
#endif /* CONFIG_BT_BROADCASTER */
#endif /* defined(CONFIG_BT_EXT_ADV) */

struct bt_le_ext_adv *bt_adv_lookup_by_id(uint8_t id)
{
#if defined(CONFIG_BT_EXT_ADV)
for (size_t i = 0; i < ARRAY_SIZE(adv_pool); i++) {
if (atomic_test_bit(adv_pool[i].flags, BT_ADV_CREATED) &&
adv_pool[i].id == id) {
return &adv_pool[i];

Check notice on line 281 in subsys/bluetooth/host/adv.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

subsys/bluetooth/host/adv.c:281 - if (atomic_test_bit(adv_pool[i].flags, BT_ADV_CREATED) && - adv_pool[i].id == id) { + if (atomic_test_bit(adv_pool[i].flags, BT_ADV_CREATED) && adv_pool[i].id == id) {
}
}
#else
if (atomic_test_bit(bt_dev.adv.flags, BT_ADV_CREATED) && bt_dev.adv.id == id) {
return &bt_dev.adv;
}
#endif

return NULL;
}


Check notice on line 293 in subsys/bluetooth/host/adv.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

subsys/bluetooth/host/adv.c:293 -
void bt_le_ext_adv_foreach(void (*func)(struct bt_le_ext_adv *adv, void *data),
void *data)
{
Expand Down Expand Up @@ -1021,6 +1040,14 @@
adv->id = param->id;
bt_dev.adv_conn_id = adv->id;

if (IS_ENABLED(CONFIG_BT_ID_AUTO_SWAP_MATCHING_BONDS)) {
err = bt_id_resolving_list_check_and_update(adv->id, param->peer);
if (err) {
LOG_ERR("Failed to check and update resolving list: %d", err);
return err;
}
}

err = bt_id_set_adv_own_addr(adv, param->options, dir_adv,
&set_param.own_addr_type);
if (err) {
Expand Down Expand Up @@ -1336,6 +1363,15 @@
}

adv->id = param->id;

if (IS_ENABLED(CONFIG_BT_ID_AUTO_SWAP_MATCHING_BONDS)) {
err = bt_id_resolving_list_check_and_update(adv->id, param->peer);
if (err) {
LOG_ERR("Failed to check and update resolving list: %d", err);
return err;
}
}

err = le_ext_adv_param_set(adv, param, sd != NULL);
if (err) {
return err;
Expand Down Expand Up @@ -1691,6 +1727,22 @@
return -EALREADY;
}

if (IS_ENABLED(CONFIG_BT_ID_AUTO_SWAP_MATCHING_BONDS)) {
const bt_addr_le_t *peer;

if (bt_addr_le_eq(&adv->target_addr, BT_ADDR_LE_ANY)) {
peer = NULL;
} else {
peer = &adv->target_addr;
}

err = bt_id_resolving_list_check_and_update(adv->id, peer);
if (err) {
LOG_ERR("Failed to check and update resolving list: %d", err);
return err;
}
}

if (IS_ENABLED(CONFIG_BT_PERIPHERAL) &&
atomic_test_bit(adv->flags, BT_ADV_CONNECTABLE)) {
err = le_adv_start_add_conn(adv, &conn);
Expand Down
1 change: 1 addition & 0 deletions subsys/bluetooth/host/adv.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ int bt_le_adv_set_enable_ext(struct bt_le_ext_adv *adv,
int bt_le_adv_set_enable_legacy(struct bt_le_ext_adv *adv, bool enable);
int bt_le_lim_adv_cancel_timeout(struct bt_le_ext_adv *adv);
void bt_adv_reset_adv_pool(void);
struct bt_le_ext_adv *bt_adv_lookup_by_id(uint8_t id);
23 changes: 22 additions & 1 deletion subsys/bluetooth/host/hci_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,28 @@ struct bt_keys;
void bt_id_add(struct bt_keys *keys);
void bt_id_del(struct bt_keys *keys);

struct bt_keys *bt_id_find_conflict(struct bt_keys *candidate);
/** @brief Find a conflict in the resolving list for a candidate IRK.
*
* @param candidate The candidate keys to check for conflicts.
* @param all If true, check all IRKs, otherwise check only added keys.
*
* @return The conflicting key if there is one, or NULL if no conflict was found.
*/
struct bt_keys *bt_id_find_conflict(struct bt_keys *candidate, bool all);

/** * @brief Find multiple conflicts in the resolving list for a candidate IRK.
*
* This function iterates over all keys (added and not added to the Resolving List). If there are
* multiple conflicts, this function will return true. Otherwise, it will return false.
*
* If @c firt_conflict is not NULL, it will be set to the first found conflict.
*
* @param candidate The candidate key to check for conflicts.
* @param first_conflict Pointer to store the first found conflict, if any. Can be NULL.
*
* @return True if there are multiple conflicts, otherwise it returns false.
*/
bool bt_id_find_conflict_multiple(struct bt_keys *candidate, struct bt_keys **first_conflict);

int bt_setup_random_id_addr(void);
int bt_setup_public_id_addr(void);
Expand Down
Loading
Loading