Commit cafae4cd authored by Luiz Augusto von Dentz's avatar Luiz Augusto von Dentz Committed by Marcel Holtmann

Bluetooth: Fix handling of LE Enhanced Connection Complete

LE Enhanced Connection Complete contains the Local RPA used in the
connection which must be used when set otherwise there could problems
when pairing since the address used by the remote stack could be the
Local RPA:

BLUETOOTH CORE SPECIFICATION Version 5.2 | Vol 4, Part E
page 2396

  'Resolvable Private Address being used by the local device for this
  connection. This is only valid when the Own_Address_Type (from the
  HCI_LE_Create_Connection, HCI_LE_Set_Advertising_Parameters,
  HCI_LE_Set_Extended_Advertising_Parameters, or
  HCI_LE_Extended_Create_Connection commands) is set to 0x02 or
  0x03, and the Controller generated a resolvable private address for the
  local device using a non-zero local IRK. For other Own_Address_Type
  values, the Controller shall return all zeros.'
Signed-off-by: default avatarLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent 0ea53674
...@@ -5161,9 +5161,64 @@ static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev, ...@@ -5161,9 +5161,64 @@ static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
} }
#endif #endif
static void le_conn_update_addr(struct hci_conn *conn, bdaddr_t *bdaddr,
u8 bdaddr_type, bdaddr_t *local_rpa)
{
if (conn->out) {
conn->dst_type = bdaddr_type;
conn->resp_addr_type = bdaddr_type;
bacpy(&conn->resp_addr, bdaddr);
/* Check if the controller has set a Local RPA then it must be
* used instead or hdev->rpa.
*/
if (local_rpa && bacmp(local_rpa, BDADDR_ANY)) {
conn->init_addr_type = ADDR_LE_DEV_RANDOM;
bacpy(&conn->init_addr, local_rpa);
} else if (hci_dev_test_flag(conn->hdev, HCI_PRIVACY)) {
conn->init_addr_type = ADDR_LE_DEV_RANDOM;
bacpy(&conn->init_addr, &conn->hdev->rpa);
} else {
hci_copy_identity_address(conn->hdev, &conn->init_addr,
&conn->init_addr_type);
}
} else {
conn->resp_addr_type = conn->hdev->adv_addr_type;
/* Check if the controller has set a Local RPA then it must be
* used instead or hdev->rpa.
*/
if (local_rpa && bacmp(local_rpa, BDADDR_ANY)) {
conn->resp_addr_type = ADDR_LE_DEV_RANDOM;
bacpy(&conn->resp_addr, local_rpa);
} else if (conn->hdev->adv_addr_type == ADDR_LE_DEV_RANDOM) {
/* In case of ext adv, resp_addr will be updated in
* Adv Terminated event.
*/
if (!ext_adv_capable(conn->hdev))
bacpy(&conn->resp_addr,
&conn->hdev->random_addr);
} else {
bacpy(&conn->resp_addr, &conn->hdev->bdaddr);
}
conn->init_addr_type = bdaddr_type;
bacpy(&conn->init_addr, bdaddr);
/* For incoming connections, set the default minimum
* and maximum connection interval. They will be used
* to check if the parameters are in range and if not
* trigger the connection update procedure.
*/
conn->le_conn_min_interval = conn->hdev->le_conn_min_interval;
conn->le_conn_max_interval = conn->hdev->le_conn_max_interval;
}
}
static void le_conn_complete_evt(struct hci_dev *hdev, u8 status, static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
bdaddr_t *bdaddr, u8 bdaddr_type, u8 role, u16 handle, bdaddr_t *bdaddr, u8 bdaddr_type,
u16 interval, u16 latency, u16 supervision_timeout) bdaddr_t *local_rpa, u8 role, u16 handle,
u16 interval, u16 latency,
u16 supervision_timeout)
{ {
struct hci_conn_params *params; struct hci_conn_params *params;
struct hci_conn *conn; struct hci_conn *conn;
...@@ -5211,32 +5266,7 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status, ...@@ -5211,32 +5266,7 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
cancel_delayed_work(&conn->le_conn_timeout); cancel_delayed_work(&conn->le_conn_timeout);
} }
if (!conn->out) { le_conn_update_addr(conn, bdaddr, bdaddr_type, local_rpa);
/* Set the responder (our side) address type based on
* the advertising address type.
*/
conn->resp_addr_type = hdev->adv_addr_type;
if (hdev->adv_addr_type == ADDR_LE_DEV_RANDOM) {
/* In case of ext adv, resp_addr will be updated in
* Adv Terminated event.
*/
if (!ext_adv_capable(hdev))
bacpy(&conn->resp_addr, &hdev->random_addr);
} else {
bacpy(&conn->resp_addr, &hdev->bdaddr);
}
conn->init_addr_type = bdaddr_type;
bacpy(&conn->init_addr, bdaddr);
/* For incoming connections, set the default minimum
* and maximum connection interval. They will be used
* to check if the parameters are in range and if not
* trigger the connection update procedure.
*/
conn->le_conn_min_interval = hdev->le_conn_min_interval;
conn->le_conn_max_interval = hdev->le_conn_max_interval;
}
/* Lookup the identity address from the stored connection /* Lookup the identity address from the stored connection
* address and address type. * address and address type.
...@@ -5347,7 +5377,7 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -5347,7 +5377,7 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
le_conn_complete_evt(hdev, ev->status, &ev->bdaddr, ev->bdaddr_type, le_conn_complete_evt(hdev, ev->status, &ev->bdaddr, ev->bdaddr_type,
ev->role, le16_to_cpu(ev->handle), NULL, ev->role, le16_to_cpu(ev->handle),
le16_to_cpu(ev->interval), le16_to_cpu(ev->interval),
le16_to_cpu(ev->latency), le16_to_cpu(ev->latency),
le16_to_cpu(ev->supervision_timeout)); le16_to_cpu(ev->supervision_timeout));
...@@ -5361,7 +5391,7 @@ static void hci_le_enh_conn_complete_evt(struct hci_dev *hdev, ...@@ -5361,7 +5391,7 @@ static void hci_le_enh_conn_complete_evt(struct hci_dev *hdev,
BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
le_conn_complete_evt(hdev, ev->status, &ev->bdaddr, ev->bdaddr_type, le_conn_complete_evt(hdev, ev->status, &ev->bdaddr, ev->bdaddr_type,
ev->role, le16_to_cpu(ev->handle), &ev->local_rpa, ev->role, le16_to_cpu(ev->handle),
le16_to_cpu(ev->interval), le16_to_cpu(ev->interval),
le16_to_cpu(ev->latency), le16_to_cpu(ev->latency),
le16_to_cpu(ev->supervision_timeout)); le16_to_cpu(ev->supervision_timeout));
...@@ -5397,7 +5427,8 @@ static void hci_le_ext_adv_term_evt(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -5397,7 +5427,8 @@ static void hci_le_ext_adv_term_evt(struct hci_dev *hdev, struct sk_buff *skb)
if (conn) { if (conn) {
struct adv_info *adv_instance; struct adv_info *adv_instance;
if (hdev->adv_addr_type != ADDR_LE_DEV_RANDOM) if (hdev->adv_addr_type != ADDR_LE_DEV_RANDOM ||
bacmp(&conn->resp_addr, BDADDR_ANY))
return; return;
if (!ev->handle) { if (!ev->handle) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment