From 628b3bc4165bd2459b19d834a47c452ba988b25d Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Tue, 10 Mar 2020 14:16:43 +0100 Subject: [PATCH] Bluetooth: host: Allow get local OOB data while advertiser is enabled Allow to get local OOB data while advertiser, scanner or whitelist initiator is active. If direct initiator is active or the advertiser is using the random address as a random static identity address then the function will return error. Signed-off-by: Joakim Andersson --- include/bluetooth/bluetooth.h | 8 ++++ subsys/bluetooth/host/hci_core.c | 80 +++++++++++++++++++++++--------- 2 files changed, 65 insertions(+), 23 deletions(-) diff --git a/include/bluetooth/bluetooth.h b/include/bluetooth/bluetooth.h index 076a1531154..3f09f70e38c 100644 --- a/include/bluetooth/bluetooth.h +++ b/include/bluetooth/bluetooth.h @@ -652,6 +652,14 @@ struct bt_le_oob { * :option:`CONFIG_BT_RPA_TIMEOUT` seconds. This address will be used for * advertising, active scanning and connection creation. * + * @note If privacy is enabled the RPA cannot be refreshed in the following + * cases: + * - Creating a connection in progress, wait for the connected callback. + * - Advertiser is enabled using a Random Static Identity Address for a + * different local identity. + * - The local identity conflicts with the local identity used by other + * roles. + * * @param[in] id Local identity, in most cases BT_ID_DEFAULT. * @param[out] oob LE OOB information * diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index c1b21f2fbce..298c9581423 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -537,6 +537,22 @@ static int le_set_private_addr(u8_t id) return err; } +#else +static int le_set_private_addr(u8_t id) +{ + bt_addr_t nrpa; + int err; + + err = bt_rand(nrpa.val, sizeof(nrpa.val)); + if (err) { + return err; + } + + nrpa.val[5] &= 0x3f; + + return set_random_address(&nrpa); +} +#endif /* defined(CONFIG_BT_PRIVACY) */ static void le_update_private_addr(void) { @@ -590,6 +606,7 @@ static void le_update_private_addr(void) #endif } +#if defined(CONFIG_BT_PRIVACY) static void rpa_timeout(struct k_work *work) { BT_DBG(""); @@ -619,21 +636,6 @@ static void rpa_timeout(struct k_work *work) le_update_private_addr(); } -#else -static int le_set_private_addr(u8_t id) -{ - bt_addr_t nrpa; - int err; - - err = bt_rand(nrpa.val, sizeof(nrpa.val)); - if (err) { - return err; - } - - nrpa.val[5] &= 0x3f; - - return set_random_address(&nrpa); -} #endif /* defined(CONFIG_BT_PRIVACY) */ bool bt_le_scan_random_addr_check(void) @@ -911,9 +913,7 @@ int bt_le_create_conn(const struct bt_conn *conn) * triggered while direct initiator is active. */ atomic_clear_bit(bt_dev.flags, BT_DEV_RPA_VALID); -#if defined(CONFIG_BT_PRIVACY) le_update_private_addr(); -#endif } if (BT_FEAT_LE_PRIVACY(bt_dev.le.features)) { @@ -6850,14 +6850,48 @@ int bt_le_oob_get_local(u8_t id, struct bt_le_oob *oob) return -EINVAL; } - if (IS_ENABLED(CONFIG_BT_PRIVACY)) { + if (IS_ENABLED(CONFIG_BT_PRIVACY) && + !(atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING) && + atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING_IDENTITY) && + bt_dev.adv_id == id && + bt_dev.id_addr[id].type == BT_ADDR_LE_RANDOM)) { + if (IS_ENABLED(CONFIG_BT_CENTRAL) && + atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING)) { + struct bt_conn *conn; + + conn = bt_conn_lookup_state_le(BT_ID_DEFAULT, NULL, + BT_CONN_CONNECT_SCAN); + if (conn) { + /* Cannot set new RPA while creating + * connections. + */ + bt_conn_unref(conn); + return -EINVAL; + } + } + + if (atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING) && + atomic_test_bit(bt_dev.flags, + BT_DEV_ADVERTISING_IDENTITY) && + (bt_dev.id_addr[id].type == BT_ADDR_LE_RANDOM)) { + /* Cannot set a new RPA address while advertising with + * random static identity address for a different + * identity. + */ + return -EINVAL; + } + + if (IS_ENABLED(CONFIG_BT_OBSERVER) && + id != BT_ID_DEFAULT && + (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING) || + atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING))) { + /* Cannot switch identity of scanner or initiator */ + return -EINVAL; + } + /* Invalidate RPA so a new one is generated */ atomic_clear_bit(bt_dev.flags, BT_DEV_RPA_VALID); - - err = le_set_private_addr(id); - if (err) { - return err; - } + le_update_private_addr(); bt_addr_le_copy(&oob->addr, &bt_dev.random_addr); } else {