Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <jpawlowski@google.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>

authored by

Jakub Pawlowski and committed by
Marcel Holtmann
28a667c9 f75113a2

+72 -37
+37 -15
net/bluetooth/hci_conn.c
··· 679 679 { 680 680 struct hci_conn *conn; 681 681 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 + } 684 690 685 691 BT_ERR("HCI request failed to create LE connection: status 0x%2.2x", 686 692 status); 687 693 688 - hci_dev_lock(hdev); 689 - 690 - conn = hci_lookup_le_connect(hdev); 691 694 if (!conn) 692 695 goto done; 693 696 ··· 730 727 hci_req_add(req, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp); 731 728 732 729 conn->state = BT_CONNECT; 730 + clear_bit(HCI_CONN_SCANNING, &conn->flags); 733 731 } 734 732 735 733 static void hci_req_directed_advertising(struct hci_request *req, ··· 774 770 u8 role) 775 771 { 776 772 struct hci_conn_params *params; 777 - struct hci_conn *conn; 773 + struct hci_conn *conn, *conn_unfinished; 778 774 struct smp_irk *irk; 779 775 struct hci_request req; 780 776 int err; ··· 797 793 * and return the object found. 798 794 */ 799 795 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst); 796 + conn_unfinished = NULL; 800 797 if (conn) { 801 - conn->pending_sec_level = sec_level; 802 - goto done; 798 + if (conn->state == BT_CONNECT && 799 + test_bit(HCI_CONN_SCANNING, &conn->flags)) { 800 + BT_DBG("will continue unfinished conn %pMR", dst); 801 + conn_unfinished = conn; 802 + } else { 803 + if (conn->pending_sec_level < sec_level) 804 + conn->pending_sec_level = sec_level; 805 + goto done; 806 + } 803 807 } 804 808 805 809 /* Since the controller supports only one LE connection attempt at a ··· 820 808 * resolving key, the connection needs to be established 821 809 * to a resolvable random address. 822 810 * 823 - * This uses the cached random resolvable address from 824 - * a previous scan. When no cached address is available, 825 - * try connecting to the identity address instead. 826 - * 827 811 * Storing the resolvable random address is required here 828 812 * to handle connection failures. The address will later 829 813 * be resolved back into the original identity address ··· 831 823 dst_type = ADDR_LE_DEV_RANDOM; 832 824 } 833 825 834 - conn = hci_conn_add(hdev, LE_LINK, dst, role); 826 + if (conn_unfinished) { 827 + conn = conn_unfinished; 828 + bacpy(&conn->dst, dst); 829 + } else { 830 + conn = hci_conn_add(hdev, LE_LINK, dst, role); 831 + } 832 + 835 833 if (!conn) 836 834 return ERR_PTR(-ENOMEM); 837 835 838 836 conn->dst_type = dst_type; 839 837 conn->sec_level = BT_SECURITY_LOW; 840 - conn->pending_sec_level = sec_level; 841 838 conn->conn_timeout = conn_timeout; 839 + 840 + if (!conn_unfinished) 841 + conn->pending_sec_level = sec_level; 842 842 843 843 hci_req_init(&req, hdev); 844 844 ··· 912 896 } 913 897 914 898 done: 915 - hci_conn_hold(conn); 899 + /* If this is continuation of connect started by hci_connect_le_scan, 900 + * it already called hci_conn_hold and calling it again would mess the 901 + * counter. 902 + */ 903 + if (!conn_unfinished) 904 + hci_conn_hold(conn); 905 + 916 906 return conn; 917 907 } 918 908
+29 -22
net/bluetooth/hci_event.c
··· 4640 4640 /* If we're not connectable only connect devices that we have in 4641 4641 * our pend_le_conns list. 4642 4642 */ 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 + 4645 4645 if (!params) 4646 4646 return NULL; 4647 4647 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: 4655 4667 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 + } 4667 4669 } 4668 4670 4669 4671 conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW, 4670 4672 HCI_LE_AUTOCONN_TIMEOUT, HCI_ROLE_MASTER); 4671 4673 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 4673 4677 * other owner of the object besides the params that 4674 4678 * triggered it. This way we can abort the connection if 4675 4679 * the parameters get removed and keep the reference 4676 4680 * count consistent once the connection is established. 4677 4681 */ 4678 - params->conn = hci_conn_get(conn); 4682 + 4683 + if (!params->explicit_connect) 4684 + params->conn = hci_conn_get(conn); 4685 + 4679 4686 return conn; 4680 4687 } 4681 4688
+6
net/bluetooth/mgmt.c
··· 6107 6107 switch (auto_connect) { 6108 6108 case HCI_AUTO_CONN_DISABLED: 6109 6109 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 + 6110 6116 __hci_update_background_scan(req); 6111 6117 break; 6112 6118 case HCI_AUTO_CONN_REPORT: