mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 12:42:02 +00:00
Bluetooth: Terminate the link if pairing is cancelled
If user decides to cancel the ongoing pairing process (e.g. by clicking the cancel button on pairing/passkey window), abort any ongoing pairing and then terminate the link if it was created because of the pair device action. Signed-off-by: Manish Mandlik <mmandlik@google.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
parent
8208f5a9d4
commit
76b1399655
@ -564,6 +564,12 @@ struct hci_dev {
|
||||
|
||||
#define HCI_PHY_HANDLE(handle) (handle & 0xff)
|
||||
|
||||
enum conn_reasons {
|
||||
CONN_REASON_PAIR_DEVICE,
|
||||
CONN_REASON_L2CAP_CHAN,
|
||||
CONN_REASON_SCO_CONNECT,
|
||||
};
|
||||
|
||||
struct hci_conn {
|
||||
struct list_head list;
|
||||
|
||||
@ -615,6 +621,8 @@ struct hci_conn {
|
||||
__s8 max_tx_power;
|
||||
unsigned long flags;
|
||||
|
||||
enum conn_reasons conn_reason;
|
||||
|
||||
__u32 clock;
|
||||
__u16 clock_accuracy;
|
||||
|
||||
@ -1040,12 +1048,14 @@ struct hci_chan *hci_chan_lookup_handle(struct hci_dev *hdev, __u16 handle);
|
||||
|
||||
struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst,
|
||||
u8 dst_type, u8 sec_level,
|
||||
u16 conn_timeout);
|
||||
u16 conn_timeout,
|
||||
enum conn_reasons conn_reason);
|
||||
struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
|
||||
u8 dst_type, u8 sec_level, u16 conn_timeout,
|
||||
u8 role, bdaddr_t *direct_rpa);
|
||||
struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
|
||||
u8 sec_level, u8 auth_type);
|
||||
u8 sec_level, u8 auth_type,
|
||||
enum conn_reasons conn_reason);
|
||||
struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst,
|
||||
__u16 setting);
|
||||
int hci_conn_check_link_mode(struct hci_conn *conn);
|
||||
|
@ -1174,7 +1174,8 @@ static int hci_explicit_conn_params_set(struct hci_dev *hdev,
|
||||
/* This function requires the caller holds hdev->lock */
|
||||
struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst,
|
||||
u8 dst_type, u8 sec_level,
|
||||
u16 conn_timeout)
|
||||
u16 conn_timeout,
|
||||
enum conn_reasons conn_reason)
|
||||
{
|
||||
struct hci_conn *conn;
|
||||
|
||||
@ -1219,6 +1220,7 @@ struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst,
|
||||
conn->sec_level = BT_SECURITY_LOW;
|
||||
conn->pending_sec_level = sec_level;
|
||||
conn->conn_timeout = conn_timeout;
|
||||
conn->conn_reason = conn_reason;
|
||||
|
||||
hci_update_background_scan(hdev);
|
||||
|
||||
@ -1228,7 +1230,8 @@ done:
|
||||
}
|
||||
|
||||
struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
|
||||
u8 sec_level, u8 auth_type)
|
||||
u8 sec_level, u8 auth_type,
|
||||
enum conn_reasons conn_reason)
|
||||
{
|
||||
struct hci_conn *acl;
|
||||
|
||||
@ -1248,6 +1251,7 @@ struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
|
||||
|
||||
hci_conn_hold(acl);
|
||||
|
||||
acl->conn_reason = conn_reason;
|
||||
if (acl->state == BT_OPEN || acl->state == BT_CLOSED) {
|
||||
acl->sec_level = BT_SECURITY_LOW;
|
||||
acl->pending_sec_level = sec_level;
|
||||
@ -1264,7 +1268,8 @@ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst,
|
||||
struct hci_conn *acl;
|
||||
struct hci_conn *sco;
|
||||
|
||||
acl = hci_connect_acl(hdev, dst, BT_SECURITY_LOW, HCI_AT_NO_BONDING);
|
||||
acl = hci_connect_acl(hdev, dst, BT_SECURITY_LOW, HCI_AT_NO_BONDING,
|
||||
CONN_REASON_SCO_CONNECT);
|
||||
if (IS_ERR(acl))
|
||||
return acl;
|
||||
|
||||
|
@ -7893,11 +7893,13 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
|
||||
else
|
||||
hcon = hci_connect_le_scan(hdev, dst, dst_type,
|
||||
chan->sec_level,
|
||||
HCI_LE_CONN_TIMEOUT);
|
||||
HCI_LE_CONN_TIMEOUT,
|
||||
CONN_REASON_L2CAP_CHAN);
|
||||
|
||||
} else {
|
||||
u8 auth_type = l2cap_get_auth_type(chan);
|
||||
hcon = hci_connect_acl(hdev, dst, chan->sec_level, auth_type);
|
||||
hcon = hci_connect_acl(hdev, dst, chan->sec_level, auth_type,
|
||||
CONN_REASON_L2CAP_CHAN);
|
||||
}
|
||||
|
||||
if (IS_ERR(hcon)) {
|
||||
|
@ -2931,7 +2931,7 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
|
||||
|
||||
if (cp->addr.type == BDADDR_BREDR) {
|
||||
conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
|
||||
auth_type);
|
||||
auth_type, CONN_REASON_PAIR_DEVICE);
|
||||
} else {
|
||||
u8 addr_type = le_addr_type(cp->addr.type);
|
||||
struct hci_conn_params *p;
|
||||
@ -2950,9 +2950,9 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
|
||||
if (p->auto_connect == HCI_AUTO_CONN_EXPLICIT)
|
||||
p->auto_connect = HCI_AUTO_CONN_DISABLED;
|
||||
|
||||
conn = hci_connect_le_scan(hdev, &cp->addr.bdaddr,
|
||||
addr_type, sec_level,
|
||||
HCI_LE_CONN_TIMEOUT);
|
||||
conn = hci_connect_le_scan(hdev, &cp->addr.bdaddr, addr_type,
|
||||
sec_level, HCI_LE_CONN_TIMEOUT,
|
||||
CONN_REASON_PAIR_DEVICE);
|
||||
}
|
||||
|
||||
if (IS_ERR(conn)) {
|
||||
@ -3053,6 +3053,20 @@ static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
|
||||
|
||||
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
|
||||
addr, sizeof(*addr));
|
||||
|
||||
/* Since user doesn't want to proceed with the connection, abort any
|
||||
* ongoing pairing and then terminate the link if it was created
|
||||
* because of the pair device action.
|
||||
*/
|
||||
if (addr->type == BDADDR_BREDR)
|
||||
hci_remove_link_key(hdev, &addr->bdaddr);
|
||||
else
|
||||
smp_cancel_and_remove_pairing(hdev, &addr->bdaddr,
|
||||
le_addr_type(addr->type));
|
||||
|
||||
if (conn->conn_reason == CONN_REASON_PAIR_DEVICE)
|
||||
hci_abort_conn(conn, HCI_ERROR_REMOTE_USER_TERM);
|
||||
|
||||
unlock:
|
||||
hci_dev_unlock(hdev);
|
||||
return err;
|
||||
|
Loading…
Reference in New Issue
Block a user