Bluetooth: host: Fix directed advertising from privacy-disabled peer

Fix directed advertising from privacy disabled peer. In this case we
need to have the local IRK in the controllers resolving list in order to
have the controller resolve the initiator address of the directed
advertising pdu (ADV_DIR_IND).

Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
This commit is contained in:
Joakim Andersson 2020-03-20 19:42:53 +01:00 committed by Johan Hedberg
commit 6c6bd8c49e
3 changed files with 32 additions and 6 deletions

View file

@ -1339,7 +1339,12 @@ static void enh_conn_complete(struct bt_hci_evt_le_enh_conn_complete *evt)
#if defined(CONFIG_BT_SMP)
if (atomic_test_and_clear_bit(bt_dev.flags, BT_DEV_ID_PENDING)) {
bt_keys_foreach(BT_KEYS_IRK, update_pending_id, NULL);
if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
IS_ENABLED(CONFIG_BT_PRIVACY)) {
bt_keys_foreach(BT_KEYS_ALL, update_pending_id, NULL);
} else {
bt_keys_foreach(BT_KEYS_IRK, update_pending_id, NULL);
}
}
#endif
@ -3178,7 +3183,9 @@ done:
static void keys_add_id(struct bt_keys *keys, void *data)
{
hci_id_add(keys->id, &keys->addr, keys->irk.val);
if (keys != (struct bt_keys *)data) {
hci_id_add(keys->id, &keys->addr, keys->irk.val);
}
}
void bt_id_del(struct bt_keys *keys)
@ -3229,8 +3236,12 @@ void bt_id_del(struct bt_keys *keys)
/* We checked size + 1 earlier, so here we know we can fit again */
if (bt_dev.le.rl_entries > bt_dev.le.rl_size) {
bt_dev.le.rl_entries--;
keys->keys &= ~BT_KEYS_IRK;
bt_keys_foreach(BT_KEYS_IRK, keys_add_id, NULL);
if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
IS_ENABLED(CONFIG_BT_PRIVACY)) {
bt_keys_foreach(BT_KEYS_ALL, keys_add_id, keys);
} else {
bt_keys_foreach(BT_KEYS_IRK, keys_add_id, keys);
}
goto done;
}

View file

@ -236,7 +236,8 @@ void bt_keys_clear(struct bt_keys *keys)
{
BT_DBG("%s (keys 0x%04x)", bt_addr_le_str(&keys->addr), keys->keys);
if (keys->keys & BT_KEYS_IRK) {
if ((IS_ENABLED(CONFIG_BT_CENTRAL) && IS_ENABLED(CONFIG_BT_PRIVACY)) ||
keys->keys & BT_KEYS_IRK) {
bt_id_del(keys);
}
@ -393,7 +394,11 @@ static int keys_commit(void)
* called multiple times for the same address, especially if
* the keys were already removed.
*/
bt_keys_foreach(BT_KEYS_IRK, id_add, NULL);
if (IS_ENABLED(CONFIG_BT_CENTRAL) && IS_ENABLED(CONFIG_BT_PRIVACY)) {
bt_keys_foreach(BT_KEYS_ALL, id_add, NULL);
} else {
bt_keys_foreach(BT_KEYS_IRK, id_add, NULL);
}
return 0;
}

View file

@ -4405,6 +4405,16 @@ static void bt_smp_encrypt_change(struct bt_l2cap_chan *chan,
atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_SIGNING_INFO);
}
if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
IS_ENABLED(CONFIG_BT_PRIVACY) &&
!(smp->remote_dist & BT_SMP_DIST_ID_KEY)) {
/* To resolve directed advertising we need our local IRK
* in the controllers resolving list, add it now since the
* peer has no identity key.
*/
bt_id_add(conn->le.keys);
}
atomic_set_bit(smp->flags, SMP_FLAG_KEYS_DISTR);
/* Slave distributes it's keys first */