Commit 76b13996 authored by Manish Mandlik's avatar Manish Mandlik Committed by Johan Hedberg

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: default avatarManish Mandlik <mmandlik@google.com>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
Signed-off-by: default avatarJohan Hedberg <johan.hedberg@intel.com>
parent 8208f5a9
...@@ -564,6 +564,12 @@ struct hci_dev { ...@@ -564,6 +564,12 @@ struct hci_dev {
#define HCI_PHY_HANDLE(handle) (handle & 0xff) #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 hci_conn {
struct list_head list; struct list_head list;
...@@ -615,6 +621,8 @@ struct hci_conn { ...@@ -615,6 +621,8 @@ struct hci_conn {
__s8 max_tx_power; __s8 max_tx_power;
unsigned long flags; unsigned long flags;
enum conn_reasons conn_reason;
__u32 clock; __u32 clock;
__u16 clock_accuracy; __u16 clock_accuracy;
...@@ -1040,12 +1048,14 @@ struct hci_chan *hci_chan_lookup_handle(struct hci_dev *hdev, __u16 handle); ...@@ -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, struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst,
u8 dst_type, u8 sec_level, 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, struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
u8 dst_type, u8 sec_level, u16 conn_timeout, u8 dst_type, u8 sec_level, u16 conn_timeout,
u8 role, bdaddr_t *direct_rpa); u8 role, bdaddr_t *direct_rpa);
struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, 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, struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst,
__u16 setting); __u16 setting);
int hci_conn_check_link_mode(struct hci_conn *conn); 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, ...@@ -1174,7 +1174,8 @@ static int hci_explicit_conn_params_set(struct hci_dev *hdev,
/* This function requires the caller holds hdev->lock */ /* This function requires the caller holds hdev->lock */
struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst, struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst,
u8 dst_type, u8 sec_level, u8 dst_type, u8 sec_level,
u16 conn_timeout) u16 conn_timeout,
enum conn_reasons conn_reason)
{ {
struct hci_conn *conn; struct hci_conn *conn;
...@@ -1219,6 +1220,7 @@ struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst, ...@@ -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->sec_level = BT_SECURITY_LOW;
conn->pending_sec_level = sec_level; conn->pending_sec_level = sec_level;
conn->conn_timeout = conn_timeout; conn->conn_timeout = conn_timeout;
conn->conn_reason = conn_reason;
hci_update_background_scan(hdev); hci_update_background_scan(hdev);
...@@ -1228,7 +1230,8 @@ struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst, ...@@ -1228,7 +1230,8 @@ struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst,
} }
struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, 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; struct hci_conn *acl;
...@@ -1248,6 +1251,7 @@ struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, ...@@ -1248,6 +1251,7 @@ struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
hci_conn_hold(acl); hci_conn_hold(acl);
acl->conn_reason = conn_reason;
if (acl->state == BT_OPEN || acl->state == BT_CLOSED) { if (acl->state == BT_OPEN || acl->state == BT_CLOSED) {
acl->sec_level = BT_SECURITY_LOW; acl->sec_level = BT_SECURITY_LOW;
acl->pending_sec_level = sec_level; 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, ...@@ -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 *acl;
struct hci_conn *sco; 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)) if (IS_ERR(acl))
return acl; return acl;
......
...@@ -7893,11 +7893,13 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, ...@@ -7893,11 +7893,13 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
else else
hcon = hci_connect_le_scan(hdev, dst, dst_type, hcon = hci_connect_le_scan(hdev, dst, dst_type,
chan->sec_level, chan->sec_level,
HCI_LE_CONN_TIMEOUT); HCI_LE_CONN_TIMEOUT,
CONN_REASON_L2CAP_CHAN);
} else { } else {
u8 auth_type = l2cap_get_auth_type(chan); 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)) { if (IS_ERR(hcon)) {
......
...@@ -2931,7 +2931,7 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -2931,7 +2931,7 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
if (cp->addr.type == BDADDR_BREDR) { if (cp->addr.type == BDADDR_BREDR) {
conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level, conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
auth_type); auth_type, CONN_REASON_PAIR_DEVICE);
} else { } else {
u8 addr_type = le_addr_type(cp->addr.type); u8 addr_type = le_addr_type(cp->addr.type);
struct hci_conn_params *p; struct hci_conn_params *p;
...@@ -2950,9 +2950,9 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -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) if (p->auto_connect == HCI_AUTO_CONN_EXPLICIT)
p->auto_connect = HCI_AUTO_CONN_DISABLED; p->auto_connect = HCI_AUTO_CONN_DISABLED;
conn = hci_connect_le_scan(hdev, &cp->addr.bdaddr, conn = hci_connect_le_scan(hdev, &cp->addr.bdaddr, addr_type,
addr_type, sec_level, sec_level, HCI_LE_CONN_TIMEOUT,
HCI_LE_CONN_TIMEOUT); CONN_REASON_PAIR_DEVICE);
} }
if (IS_ERR(conn)) { if (IS_ERR(conn)) {
...@@ -3053,6 +3053,20 @@ static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -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, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
addr, sizeof(*addr)); 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: unlock:
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
return err; return err;
......
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