diff --git a/subsys/bluetooth/host/conn.c b/subsys/bluetooth/host/conn.c index f027f98162c..a3236ef8d4a 100644 --- a/subsys/bluetooth/host/conn.c +++ b/subsys/bluetooth/host/conn.c @@ -2126,6 +2126,10 @@ int bt_conn_create_auto_le(const struct bt_le_conn_param *param) return -EINVAL; } + if (!bt_le_scan_random_addr_check()) { + return -EINVAL; + } + conn = bt_conn_add_le(BT_ID_DEFAULT, BT_ADDR_LE_NONE); if (!conn) { return -ENOMEM; @@ -2204,6 +2208,10 @@ struct bt_conn *bt_conn_create_le(const bt_addr_le_t *peer, return NULL; } + if (!bt_le_scan_random_addr_check()) { + return NULL; + } + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, peer); if (conn) { /* Connection object already exists. @@ -2272,6 +2280,10 @@ int bt_le_set_auto_conn(const bt_addr_le_t *addr, return -EINVAL; } + if (!bt_le_scan_random_addr_check()) { + return -EINVAL; + } + /* Only default identity is supported */ conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, addr); if (!conn) { diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index 6a08e39274b..d4a153523a8 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -609,6 +609,78 @@ static int le_set_private_addr(u8_t id) } #endif +bool bt_le_scan_random_addr_check(void) +{ + /* If the advertiser is not enabled or not active there is no issue */ + if (!IS_ENABLED(CONFIG_BT_BROADCASTER) || + !atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) { + return true; + } + + /* When privacy is enabled the random address will not be set + * immediately before starting the role, because the RPA might still be + * valid and only updated on RPA timeout. + */ + if (IS_ENABLED(CONFIG_BT_PRIVACY)) { + /* Cannot start scannor or initiator if the random address is + * used by the advertiser for an RPA with a different identity + * or for a random static identity address. + */ + if ((atomic_test_bit(bt_dev.flags, + BT_DEV_ADVERTISING_IDENTITY) && + bt_dev.id_addr[bt_dev.adv_id].type == BT_ADDR_LE_RANDOM) || + bt_dev.adv_id != BT_ID_DEFAULT) { + return false; + } + } + + /* If privacy is not enabled then the random address will be attempted + * to be set before enabling the role. If another role is already using + * the random address then this command will fail, and should return + * the error code to the application. + */ + return true; +} + +static bool bt_le_adv_random_addr_check(const struct bt_le_adv_param *param) +{ + /* If scanner roles are not enabled or not active there is no issue. + * Passive scanner does not have an active address, unless it is a + * passive scanner that will start the initiator. + */ + if (IS_ENABLED(CONFIG_BT_OBSERVER) || + !(atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING) || + (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING) && + (!atomic_test_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN) || + atomic_test_bit(bt_dev.flags, BT_DEV_ACTIVE_SCAN))))) { + return true; + } + + /* When privacy is enabled the random address will not be set + * immediately before starting the role, because the RPA might still be + * valid and only updated on RPA timeout. + */ + if (IS_ENABLED(CONFIG_BT_PRIVACY)) { + /* Cannot start an advertiser with random static identity or + * using an RPA generated for a different identity than scanner + * roles. + */ + if (((param->options & BT_LE_ADV_OPT_USE_IDENTITY) && + bt_dev.id_addr[param->id].type == BT_ADDR_LE_RANDOM) || + param->id != BT_ID_DEFAULT) { + return false; + } + } + + /* If privacy is not enabled then the random address will be attempted + * to be set before enabling the role. If another role is already using + * the random address then this command will fail, and should return + * the error code to the application. + */ + return true; +} + + #if defined(CONFIG_BT_OBSERVER) static int set_le_scan_enable(u8_t enable) { @@ -5803,6 +5875,10 @@ int bt_le_adv_start_internal(const struct bt_le_adv_param *param, return -EALREADY; } + if (!bt_le_adv_random_addr_check(param)) { + return -EINVAL; + } + (void)memset(&set_param, 0, sizeof(set_param)); set_param.min_interval = sys_cpu_to_le16(param->interval_min); @@ -5967,6 +6043,9 @@ int bt_le_adv_start_internal(const struct bt_le_adv_param *param, atomic_set_bit_to(bt_dev.flags, BT_DEV_ADVERTISING_CONNECTABLE, param->options & BT_LE_ADV_OPT_CONNECTABLE); + atomic_set_bit_to(bt_dev.flags, BT_DEV_ADVERTISING_IDENTITY, + param->options & BT_LE_ADV_OPT_USE_IDENTITY); + return 0; } @@ -6100,6 +6179,9 @@ int bt_le_scan_start(const struct bt_le_scan_param *param, bt_le_scan_cb_t cb) return -EINVAL; } + if (param->type && !bt_le_scan_random_addr_check()) { + return -EINVAL; + } /* Return if active scan is already enabled */ if (atomic_test_and_set_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN)) { return -EALREADY; diff --git a/subsys/bluetooth/host/hci_core.h b/subsys/bluetooth/host/hci_core.h index 56b76f1b688..5a27b9f17f6 100644 --- a/subsys/bluetooth/host/hci_core.h +++ b/subsys/bluetooth/host/hci_core.h @@ -36,6 +36,7 @@ enum { BT_DEV_ADVERTISING, BT_DEV_ADVERTISING_NAME, BT_DEV_ADVERTISING_CONNECTABLE, + BT_DEV_ADVERTISING_IDENTITY, BT_DEV_KEEP_ADVERTISING, BT_DEV_SCANNING, BT_DEV_EXPLICIT_SCAN, @@ -210,3 +211,4 @@ int bt_le_adv_start_internal(const struct bt_le_adv_param *param, const struct bt_data *sd, size_t sd_len, const bt_addr_le_t *peer); void bt_le_adv_resume(void); +bool bt_le_scan_random_addr_check(void);