Skip to content

Commit 28a667c

Browse files
Jakub Pawlowskiholtmann
authored andcommitted
Bluetooth: advertisement handling in new connect procedure
Currently, when trying to connect to already paired device that just rotated its RPA MAC address, old address would be used and connection would fail. In order to fix that, kernel must scan and receive advertisement with fresh RPA before connecting. This path makes sure that after advertisement is received from device that we try to connect to, it is properly handled in check_pending_le_conn and trigger connect attempt. It also modifies hci_le_connect to make sure that connect attempt will be properly continued. Signed-off-by: Jakub Pawlowski <[email protected]> Signed-off-by: Marcel Holtmann <[email protected]>
1 parent f75113a commit 28a667c

File tree

3 files changed

+72
-37
lines changed

3 files changed

+72
-37
lines changed

net/bluetooth/hci_conn.c

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -679,15 +679,18 @@ static void create_le_conn_complete(struct hci_dev *hdev, u8 status, u16 opcode)
679679
{
680680
struct hci_conn *conn;
681681

682-
if (status == 0)
683-
return;
682+
hci_dev_lock(hdev);
683+
684+
conn = hci_lookup_le_connect(hdev);
685+
686+
if (!status) {
687+
hci_connect_le_scan_cleanup(conn);
688+
goto done;
689+
}
684690

685691
BT_ERR("HCI request failed to create LE connection: status 0x%2.2x",
686692
status);
687693

688-
hci_dev_lock(hdev);
689-
690-
conn = hci_lookup_le_connect(hdev);
691694
if (!conn)
692695
goto done;
693696

@@ -727,6 +730,7 @@ static void hci_req_add_le_create_conn(struct hci_request *req,
727730
hci_req_add(req, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp);
728731

729732
conn->state = BT_CONNECT;
733+
clear_bit(HCI_CONN_SCANNING, &conn->flags);
730734
}
731735

732736
static void hci_req_directed_advertising(struct hci_request *req,
@@ -770,7 +774,7 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
770774
u8 role)
771775
{
772776
struct hci_conn_params *params;
773-
struct hci_conn *conn;
777+
struct hci_conn *conn, *conn_unfinished;
774778
struct smp_irk *irk;
775779
struct hci_request req;
776780
int err;
@@ -793,9 +797,17 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
793797
* and return the object found.
794798
*/
795799
conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst);
800+
conn_unfinished = NULL;
796801
if (conn) {
797-
conn->pending_sec_level = sec_level;
798-
goto done;
802+
if (conn->state == BT_CONNECT &&
803+
test_bit(HCI_CONN_SCANNING, &conn->flags)) {
804+
BT_DBG("will continue unfinished conn %pMR", dst);
805+
conn_unfinished = conn;
806+
} else {
807+
if (conn->pending_sec_level < sec_level)
808+
conn->pending_sec_level = sec_level;
809+
goto done;
810+
}
799811
}
800812

801813
/* Since the controller supports only one LE connection attempt at a
@@ -808,10 +820,6 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
808820
* resolving key, the connection needs to be established
809821
* to a resolvable random address.
810822
*
811-
* This uses the cached random resolvable address from
812-
* a previous scan. When no cached address is available,
813-
* try connecting to the identity address instead.
814-
*
815823
* Storing the resolvable random address is required here
816824
* to handle connection failures. The address will later
817825
* be resolved back into the original identity address
@@ -823,15 +831,23 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
823831
dst_type = ADDR_LE_DEV_RANDOM;
824832
}
825833

826-
conn = hci_conn_add(hdev, LE_LINK, dst, role);
834+
if (conn_unfinished) {
835+
conn = conn_unfinished;
836+
bacpy(&conn->dst, dst);
837+
} else {
838+
conn = hci_conn_add(hdev, LE_LINK, dst, role);
839+
}
840+
827841
if (!conn)
828842
return ERR_PTR(-ENOMEM);
829843

830844
conn->dst_type = dst_type;
831845
conn->sec_level = BT_SECURITY_LOW;
832-
conn->pending_sec_level = sec_level;
833846
conn->conn_timeout = conn_timeout;
834847

848+
if (!conn_unfinished)
849+
conn->pending_sec_level = sec_level;
850+
835851
hci_req_init(&req, hdev);
836852

837853
/* Disable advertising if we're active. For master role
@@ -896,7 +912,13 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
896912
}
897913

898914
done:
899-
hci_conn_hold(conn);
915+
/* If this is continuation of connect started by hci_connect_le_scan,
916+
* it already called hci_conn_hold and calling it again would mess the
917+
* counter.
918+
*/
919+
if (!conn_unfinished)
920+
hci_conn_hold(conn);
921+
900922
return conn;
901923
}
902924

net/bluetooth/hci_event.c

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4640,42 +4640,49 @@ static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev,
46404640
/* If we're not connectable only connect devices that we have in
46414641
* our pend_le_conns list.
46424642
*/
4643-
params = hci_pend_le_action_lookup(&hdev->pend_le_conns,
4644-
addr, addr_type);
4643+
params = hci_explicit_connect_lookup(hdev, addr, addr_type);
4644+
46454645
if (!params)
46464646
return NULL;
46474647

4648-
switch (params->auto_connect) {
4649-
case HCI_AUTO_CONN_DIRECT:
4650-
/* Only devices advertising with ADV_DIRECT_IND are
4651-
* triggering a connection attempt. This is allowing
4652-
* incoming connections from slave devices.
4653-
*/
4654-
if (adv_type != LE_ADV_DIRECT_IND)
4648+
if (!params->explicit_connect) {
4649+
switch (params->auto_connect) {
4650+
case HCI_AUTO_CONN_DIRECT:
4651+
/* Only devices advertising with ADV_DIRECT_IND are
4652+
* triggering a connection attempt. This is allowing
4653+
* incoming connections from slave devices.
4654+
*/
4655+
if (adv_type != LE_ADV_DIRECT_IND)
4656+
return NULL;
4657+
break;
4658+
case HCI_AUTO_CONN_ALWAYS:
4659+
/* Devices advertising with ADV_IND or ADV_DIRECT_IND
4660+
* are triggering a connection attempt. This means
4661+
* that incoming connectioms from slave device are
4662+
* accepted and also outgoing connections to slave
4663+
* devices are established when found.
4664+
*/
4665+
break;
4666+
default:
46554667
return NULL;
4656-
break;
4657-
case HCI_AUTO_CONN_ALWAYS:
4658-
/* Devices advertising with ADV_IND or ADV_DIRECT_IND
4659-
* are triggering a connection attempt. This means
4660-
* that incoming connectioms from slave device are
4661-
* accepted and also outgoing connections to slave
4662-
* devices are established when found.
4663-
*/
4664-
break;
4665-
default:
4666-
return NULL;
4668+
}
46674669
}
46684670

46694671
conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW,
46704672
HCI_LE_AUTOCONN_TIMEOUT, HCI_ROLE_MASTER);
46714673
if (!IS_ERR(conn)) {
4672-
/* Store the pointer since we don't really have any
4674+
/* If HCI_AUTO_CONN_EXPLICIT is set, conn is already owned
4675+
* by higher layer that tried to connect, if no then
4676+
* store the pointer since we don't really have any
46734677
* other owner of the object besides the params that
46744678
* triggered it. This way we can abort the connection if
46754679
* the parameters get removed and keep the reference
46764680
* count consistent once the connection is established.
46774681
*/
4678-
params->conn = hci_conn_get(conn);
4682+
4683+
if (!params->explicit_connect)
4684+
params->conn = hci_conn_get(conn);
4685+
46794686
return conn;
46804687
}
46814688

net/bluetooth/mgmt.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6107,6 +6107,12 @@ static int hci_conn_params_set(struct hci_request *req, bdaddr_t *addr,
61076107
switch (auto_connect) {
61086108
case HCI_AUTO_CONN_DISABLED:
61096109
case HCI_AUTO_CONN_LINK_LOSS:
6110+
/* If auto connect is being disabled when we're trying to
6111+
* connect to device, keep connecting.
6112+
*/
6113+
if (params->explicit_connect)
6114+
list_add(&params->action, &hdev->pend_le_conns);
6115+
61106116
__hci_update_background_scan(req);
61116117
break;
61126118
case HCI_AUTO_CONN_REPORT:

0 commit comments

Comments
 (0)