]> Gentwo Git Trees - linux/.git/commitdiff
Bluetooth: HCI: Always use the identity address when initializing a connection
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Fri, 26 Sep 2025 19:56:43 +0000 (15:56 -0400)
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Mon, 1 Dec 2025 21:00:06 +0000 (16:00 -0500)
This makes sure hci_conn is initialized with the identity address if
a matching IRK exists which avoids the trouble of having to do it at
multiple places which seems to be missing (e.g. CIS, BIS and PA).

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
include/net/bluetooth/hci_core.h
net/bluetooth/hci_conn.c
net/bluetooth/hci_event.c
net/bluetooth/hci_sync.c

index 1f74722f3f4da38d64ae93e32e705b1560dce290..858b58206e8022a0a41c63a71723a6ad3b3ccbfc 100644 (file)
@@ -1571,9 +1571,9 @@ int hci_le_create_cis_pending(struct hci_dev *hdev);
 int hci_conn_check_create_cis(struct hci_conn *conn);
 
 struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
-                             u8 role, u16 handle);
+                             u8 dst_type, u8 role, u16 handle);
 struct hci_conn *hci_conn_add_unset(struct hci_dev *hdev, int type,
-                                   bdaddr_t *dst, u8 role);
+                                   bdaddr_t *dst, u8 dst_type, u8 role);
 void hci_conn_del(struct hci_conn *conn);
 void hci_conn_hash_flush(struct hci_dev *hdev);
 
index 4f9dc1435cccb4f4cab91abb5d96c25dba1c7503..c3f7828bf9d54a686171b3d5a94a5fbb4c1ccddd 100644 (file)
@@ -922,10 +922,12 @@ static int hci_conn_hash_alloc_unset(struct hci_dev *hdev)
                               U16_MAX, GFP_ATOMIC);
 }
 
-static struct hci_conn *__hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
+static struct hci_conn *__hci_conn_add(struct hci_dev *hdev, int type,
+                                      bdaddr_t *dst, u8 dst_type,
                                       u8 role, u16 handle)
 {
        struct hci_conn *conn;
+       struct smp_irk *irk = NULL;
 
        switch (type) {
        case ACL_LINK:
@@ -937,12 +939,14 @@ static struct hci_conn *__hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t
        case PA_LINK:
                if (!hdev->iso_mtu)
                        return ERR_PTR(-ECONNREFUSED);
+               irk = hci_get_irk(hdev, dst, dst_type);
                break;
        case LE_LINK:
                if (hdev->le_mtu && hdev->le_mtu < HCI_MIN_LE_MTU)
                        return ERR_PTR(-ECONNREFUSED);
                if (!hdev->le_mtu && hdev->acl_mtu < HCI_MIN_LE_MTU)
                        return ERR_PTR(-ECONNREFUSED);
+               irk = hci_get_irk(hdev, dst, dst_type);
                break;
        case SCO_LINK:
        case ESCO_LINK:
@@ -960,7 +964,15 @@ static struct hci_conn *__hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t
        if (!conn)
                return ERR_PTR(-ENOMEM);
 
-       bacpy(&conn->dst, dst);
+       /* If and IRK exists use its identity address */
+       if (!irk) {
+               bacpy(&conn->dst, dst);
+               conn->dst_type = dst_type;
+       } else {
+               bacpy(&conn->dst, &irk->bdaddr);
+               conn->dst_type = irk->addr_type;
+       }
+
        bacpy(&conn->src, &hdev->bdaddr);
        conn->handle = handle;
        conn->hdev  = hdev;
@@ -1059,7 +1071,7 @@ static struct hci_conn *__hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t
 }
 
 struct hci_conn *hci_conn_add_unset(struct hci_dev *hdev, int type,
-                                   bdaddr_t *dst, u8 role)
+                                   bdaddr_t *dst, u8 dst_type, u8 role)
 {
        int handle;
 
@@ -1069,16 +1081,16 @@ struct hci_conn *hci_conn_add_unset(struct hci_dev *hdev, int type,
        if (unlikely(handle < 0))
                return ERR_PTR(-ECONNREFUSED);
 
-       return __hci_conn_add(hdev, type, dst, role, handle);
+       return __hci_conn_add(hdev, type, dst, dst_type, role, handle);
 }
 
 struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
-                             u8 role, u16 handle)
+                             u8 dst_type, u8 role, u16 handle)
 {
        if (handle > HCI_CONN_HANDLE_MAX)
                return ERR_PTR(-EINVAL);
 
-       return __hci_conn_add(hdev, type, dst, role, handle);
+       return __hci_conn_add(hdev, type, dst, dst_type, role, handle);
 }
 
 static void hci_conn_cleanup_child(struct hci_conn *conn, u8 reason)
@@ -1410,14 +1422,13 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
        if (conn) {
                bacpy(&conn->dst, dst);
        } else {
-               conn = hci_conn_add_unset(hdev, LE_LINK, dst, role);
+               conn = hci_conn_add_unset(hdev, LE_LINK, dst, dst_type, role);
                if (IS_ERR(conn))
                        return conn;
                hci_conn_hold(conn);
                conn->pending_sec_level = sec_level;
        }
 
-       conn->dst_type = dst_type;
        conn->sec_level = BT_SECURITY_LOW;
        conn->conn_timeout = conn_timeout;
        conn->le_adv_phy = phy;
@@ -1587,7 +1598,7 @@ static struct hci_conn *hci_add_bis(struct hci_dev *hdev, bdaddr_t *dst,
                     memcmp(conn->le_per_adv_data, base, base_len)))
                return ERR_PTR(-EADDRINUSE);
 
-       conn = hci_conn_add_unset(hdev, BIS_LINK, dst, HCI_ROLE_MASTER);
+       conn = hci_conn_add_unset(hdev, BIS_LINK, dst, 0, HCI_ROLE_MASTER);
        if (IS_ERR(conn))
                return conn;
 
@@ -1633,7 +1644,8 @@ struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst,
 
        BT_DBG("requesting refresh of dst_addr");
 
-       conn = hci_conn_add_unset(hdev, LE_LINK, dst, HCI_ROLE_MASTER);
+       conn = hci_conn_add_unset(hdev, LE_LINK, dst, dst_type,
+                                 HCI_ROLE_MASTER);
        if (IS_ERR(conn))
                return conn;
 
@@ -1644,7 +1656,6 @@ struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst,
 
        conn->state = BT_CONNECT;
        set_bit(HCI_CONN_SCANNING, &conn->flags);
-       conn->dst_type = dst_type;
        conn->sec_level = BT_SECURITY_LOW;
        conn->pending_sec_level = sec_level;
        conn->conn_timeout = conn_timeout;
@@ -1681,7 +1692,8 @@ struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
 
        acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
        if (!acl) {
-               acl = hci_conn_add_unset(hdev, ACL_LINK, dst, HCI_ROLE_MASTER);
+               acl = hci_conn_add_unset(hdev, ACL_LINK, dst, 0,
+                                        HCI_ROLE_MASTER);
                if (IS_ERR(acl))
                        return acl;
        }
@@ -1750,7 +1762,7 @@ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst,
 
        sco = hci_conn_hash_lookup_ba(hdev, type, dst);
        if (!sco) {
-               sco = hci_conn_add_unset(hdev, type, dst, HCI_ROLE_MASTER);
+               sco = hci_conn_add_unset(hdev, type, dst, 0, HCI_ROLE_MASTER);
                if (IS_ERR(sco)) {
                        hci_conn_drop(acl);
                        return sco;
@@ -1942,7 +1954,7 @@ struct hci_conn *hci_bind_cis(struct hci_dev *hdev, bdaddr_t *dst,
        cis = hci_conn_hash_lookup_cis(hdev, dst, dst_type, qos->ucast.cig,
                                       qos->ucast.cis);
        if (!cis) {
-               cis = hci_conn_add_unset(hdev, CIS_LINK, dst,
+               cis = hci_conn_add_unset(hdev, CIS_LINK, dst, dst_type,
                                         HCI_ROLE_MASTER);
                if (IS_ERR(cis))
                        return cis;
@@ -2133,12 +2145,11 @@ struct hci_conn *hci_pa_create_sync(struct hci_dev *hdev, bdaddr_t *dst,
 
        bt_dev_dbg(hdev, "dst %pMR type %d sid %d", dst, dst_type, sid);
 
-       conn = hci_conn_add_unset(hdev, PA_LINK, dst, HCI_ROLE_SLAVE);
+       conn = hci_conn_add_unset(hdev, PA_LINK, dst, dst_type, HCI_ROLE_SLAVE);
        if (IS_ERR(conn))
                return conn;
 
        conn->iso_qos = *qos;
-       conn->dst_type = dst_type;
        conn->sid = sid;
        conn->state = BT_LISTEN;
        conn->conn_timeout = msecs_to_jiffies(qos->bcast.sync_timeout * 10);
index af34c9938509fff45401b9a5b5844fbb48204e32..7c4ca14f13e52c2880f074557019fd0ee68de9da 100644 (file)
@@ -2267,7 +2267,7 @@ static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
        } else {
                if (!conn) {
                        conn = hci_conn_add_unset(hdev, ACL_LINK, &cp->bdaddr,
-                                                 HCI_ROLE_MASTER);
+                                                 0, HCI_ROLE_MASTER);
                        if (IS_ERR(conn))
                                bt_dev_err(hdev, "connection err: %ld", PTR_ERR(conn));
                }
@@ -3123,7 +3123,8 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
                                                      &ev->bdaddr,
                                                      BDADDR_BREDR)) {
                        conn = hci_conn_add_unset(hdev, ev->link_type,
-                                                 &ev->bdaddr, HCI_ROLE_SLAVE);
+                                                 &ev->bdaddr, 0,
+                                                 HCI_ROLE_SLAVE);
                        if (IS_ERR(conn)) {
                                bt_dev_err(hdev, "connection err: %ld", PTR_ERR(conn));
                                goto unlock;
@@ -3299,7 +3300,7 @@ static void hci_conn_request_evt(struct hci_dev *hdev, void *data,
        conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
                        &ev->bdaddr);
        if (!conn) {
-               conn = hci_conn_add_unset(hdev, ev->link_type, &ev->bdaddr,
+               conn = hci_conn_add_unset(hdev, ev->link_type, &ev->bdaddr, 0,
                                          HCI_ROLE_SLAVE);
                if (IS_ERR(conn)) {
                        bt_dev_err(hdev, "connection err: %ld", PTR_ERR(conn));
@@ -5670,14 +5671,13 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
                if (status)
                        goto unlock;
 
-               conn = hci_conn_add_unset(hdev, LE_LINK, bdaddr, role);
+               conn = hci_conn_add_unset(hdev, LE_LINK, bdaddr, bdaddr_type,
+                                         role);
                if (IS_ERR(conn)) {
                        bt_dev_err(hdev, "connection err: %ld", PTR_ERR(conn));
                        goto unlock;
                }
 
-               conn->dst_type = bdaddr_type;
-
                /* If we didn't have a hci_conn object previously
                 * but we're in central role this must be something
                 * initiated using an accept list. Since accept list based
@@ -5982,7 +5982,7 @@ static void hci_le_past_received_evt(struct hci_dev *hdev, void *data,
                goto unlock;
 
        /* Add connection to indicate PA sync event */
-       pa_sync = hci_conn_add_unset(hdev, PA_LINK, BDADDR_ANY,
+       pa_sync = hci_conn_add_unset(hdev, PA_LINK, BDADDR_ANY, 0,
                                     HCI_ROLE_SLAVE);
 
        if (IS_ERR(pa_sync))
@@ -6515,7 +6515,7 @@ static void hci_le_pa_sync_established_evt(struct hci_dev *hdev, void *data,
                goto unlock;
 
        /* Add connection to indicate PA sync event */
-       pa_sync = hci_conn_add_unset(hdev, PA_LINK, BDADDR_ANY,
+       pa_sync = hci_conn_add_unset(hdev, PA_LINK, BDADDR_ANY, 0,
                                     HCI_ROLE_SLAVE);
 
        if (IS_ERR(pa_sync))
@@ -6956,7 +6956,7 @@ static void hci_le_cis_req_evt(struct hci_dev *hdev, void *data,
 
        cis = hci_conn_hash_lookup_handle(hdev, cis_handle);
        if (!cis) {
-               cis = hci_conn_add(hdev, CIS_LINK, &acl->dst,
+               cis = hci_conn_add(hdev, CIS_LINK, &acl->dst, acl->dst_type,
                                   HCI_ROLE_SLAVE, cis_handle);
                if (IS_ERR(cis)) {
                        hci_le_reject_cis(hdev, ev->cis_handle);
@@ -7073,7 +7073,7 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data,
                                bt_dev_dbg(hdev, "ignore too large handle %u", handle);
                                continue;
                        }
-                       bis = hci_conn_add(hdev, BIS_LINK, BDADDR_ANY,
+                       bis = hci_conn_add(hdev, BIS_LINK, BDADDR_ANY, 0,
                                           HCI_ROLE_SLAVE, handle);
                        if (IS_ERR(bis))
                                continue;
index 65f2701beb497de9bc692a7a71ede3fc08e9bbbb..a36d2414a3cafaac84dbd63251b4d2b1dcc85815 100644 (file)
@@ -7013,7 +7013,7 @@ static void create_pa_complete(struct hci_dev *hdev, void *data, int err)
                goto unlock;
 
        /* Add connection to indicate PA sync error */
-       pa_sync = hci_conn_add_unset(hdev, PA_LINK, BDADDR_ANY,
+       pa_sync = hci_conn_add_unset(hdev, PA_LINK, BDADDR_ANY, 0,
                                     HCI_ROLE_SLAVE);
 
        if (IS_ERR(pa_sync))