Bluetooth: Fix LE Pairing time-out
Timer that was started at beginning of LE Pairing did not correctly terminate pairing process when it fired, and was not properly cleaned up on pairing completion. Change-Id: Idf51bc8bf85cd6939d1d42fc16c7ee3071ab2420 Signed-off-by: Brian Gix <bgix@codeaurora.org>
This commit is contained in:
@@ -337,6 +337,8 @@ struct hci_conn {
|
|||||||
__u8 sec_req;
|
__u8 sec_req;
|
||||||
__u8 auth;
|
__u8 auth;
|
||||||
void *smp_conn;
|
void *smp_conn;
|
||||||
|
struct timer_list smp_timer;
|
||||||
|
|
||||||
|
|
||||||
void (*connect_cfm_cb) (struct hci_conn *conn, u8 status);
|
void (*connect_cfm_cb) (struct hci_conn *conn, u8 status);
|
||||||
void (*security_cfm_cb) (struct hci_conn *conn, u8 status);
|
void (*security_cfm_cb) (struct hci_conn *conn, u8 status);
|
||||||
|
|||||||
@@ -452,8 +452,6 @@ struct l2cap_conn {
|
|||||||
|
|
||||||
__u8 disc_reason;
|
__u8 disc_reason;
|
||||||
|
|
||||||
struct timer_list security_timer;
|
|
||||||
|
|
||||||
struct l2cap_chan_list chan_list;
|
struct l2cap_chan_list chan_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -126,5 +126,6 @@ struct smp_cmd_security_req {
|
|||||||
int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level);
|
int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level);
|
||||||
int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb);
|
int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb);
|
||||||
int smp_link_encrypt_cmplt(struct l2cap_conn *conn, __u8 status, __u8 encrypt);
|
int smp_link_encrypt_cmplt(struct l2cap_conn *conn, __u8 status, __u8 encrypt);
|
||||||
|
void smp_timeout(unsigned long l2cap_conn);
|
||||||
|
|
||||||
#endif /* __SMP_H */
|
#endif /* __SMP_H */
|
||||||
|
|||||||
@@ -1724,6 +1724,9 @@ static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff
|
|||||||
if (conn->type == ACL_LINK || conn->type == LE_LINK)
|
if (conn->type == ACL_LINK || conn->type == LE_LINK)
|
||||||
mgmt_disconnected(hdev->id, &conn->dst);
|
mgmt_disconnected(hdev->id, &conn->dst);
|
||||||
|
|
||||||
|
if (conn->type == LE_LINK)
|
||||||
|
del_timer(&conn->smp_timer);
|
||||||
|
|
||||||
hci_proto_disconn_cfm(conn, ev->reason);
|
hci_proto_disconn_cfm(conn, ev->reason);
|
||||||
hci_conn_del(conn);
|
hci_conn_del(conn);
|
||||||
|
|
||||||
|
|||||||
@@ -1058,13 +1058,6 @@ static void l2cap_info_timeout(unsigned long arg)
|
|||||||
l2cap_conn_start(conn);
|
l2cap_conn_start(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void security_timeout(unsigned long arg)
|
|
||||||
{
|
|
||||||
struct l2cap_conn *conn = (void *) arg;
|
|
||||||
|
|
||||||
l2cap_conn_del(conn->hcon, ETIMEDOUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
|
static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
|
||||||
{
|
{
|
||||||
struct l2cap_conn *conn = hcon->l2cap_data;
|
struct l2cap_conn *conn = hcon->l2cap_data;
|
||||||
@@ -1095,7 +1088,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
|
|||||||
rwlock_init(&conn->chan_list.lock);
|
rwlock_init(&conn->chan_list.lock);
|
||||||
|
|
||||||
if (hcon->type == LE_LINK)
|
if (hcon->type == LE_LINK)
|
||||||
setup_timer(&conn->security_timer, security_timeout,
|
setup_timer(&hcon->smp_timer, smp_timeout,
|
||||||
(unsigned long) conn);
|
(unsigned long) conn);
|
||||||
else
|
else
|
||||||
setup_timer(&conn->info_timer, l2cap_info_timeout,
|
setup_timer(&conn->info_timer, l2cap_info_timeout,
|
||||||
@@ -7263,7 +7256,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
|
|||||||
if (!status && encrypt)
|
if (!status && encrypt)
|
||||||
l2cap_pi(sk)->sec_level = hcon->sec_level;
|
l2cap_pi(sk)->sec_level = hcon->sec_level;
|
||||||
|
|
||||||
del_timer(&conn->security_timer);
|
del_timer(&hcon->smp_timer);
|
||||||
l2cap_chan_ready(sk);
|
l2cap_chan_ready(sk);
|
||||||
smp_link_encrypt_cmplt(conn, status, encrypt);
|
smp_link_encrypt_cmplt(conn, status, encrypt);
|
||||||
|
|
||||||
|
|||||||
@@ -437,6 +437,7 @@ int le_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, void *cp)
|
|||||||
BT_DBG("smp_send_cmd: SMP_CMD_PAIRING_FAIL");
|
BT_DBG("smp_send_cmd: SMP_CMD_PAIRING_FAIL");
|
||||||
smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
|
smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
|
||||||
&reason);
|
&reason);
|
||||||
|
del_timer(&hcon->smp_timer);
|
||||||
hci_conn_put(hcon);
|
hci_conn_put(hcon);
|
||||||
} else if (hcon->cfm_pending) {
|
} else if (hcon->cfm_pending) {
|
||||||
BT_DBG("send_pairing_confirm");
|
BT_DBG("send_pairing_confirm");
|
||||||
@@ -490,8 +491,7 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
|
|||||||
|
|
||||||
smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
|
smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
|
||||||
|
|
||||||
mod_timer(&conn->security_timer, jiffies +
|
mod_timer(&hcon->smp_timer, jiffies + msecs_to_jiffies(SMP_TIMEOUT));
|
||||||
msecs_to_jiffies(SMP_TIMEOUT));
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -569,8 +569,7 @@ static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
|
|||||||
hcon->cfm_pending = TRUE;
|
hcon->cfm_pending = TRUE;
|
||||||
|
|
||||||
|
|
||||||
mod_timer(&conn->security_timer, jiffies +
|
mod_timer(&hcon->smp_timer, jiffies + msecs_to_jiffies(SMP_TIMEOUT));
|
||||||
msecs_to_jiffies(SMP_TIMEOUT));
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -682,8 +681,7 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
|
|||||||
|
|
||||||
smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
|
smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
|
||||||
|
|
||||||
mod_timer(&conn->security_timer, jiffies +
|
mod_timer(&hcon->smp_timer, jiffies + msecs_to_jiffies(SMP_TIMEOUT));
|
||||||
msecs_to_jiffies(SMP_TIMEOUT));
|
|
||||||
|
|
||||||
set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
|
set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
|
||||||
|
|
||||||
@@ -750,7 +748,7 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
|
|||||||
hcon->preq[0] = SMP_CMD_PAIRING_REQ;
|
hcon->preq[0] = SMP_CMD_PAIRING_REQ;
|
||||||
memcpy(&hcon->preq[1], &cp, sizeof(cp));
|
memcpy(&hcon->preq[1], &cp, sizeof(cp));
|
||||||
|
|
||||||
mod_timer(&conn->security_timer, jiffies +
|
mod_timer(&hcon->smp_timer, jiffies +
|
||||||
msecs_to_jiffies(SMP_TIMEOUT));
|
msecs_to_jiffies(SMP_TIMEOUT));
|
||||||
|
|
||||||
smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
|
smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
|
||||||
@@ -846,6 +844,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
|
|||||||
case SMP_CMD_PAIRING_FAIL:
|
case SMP_CMD_PAIRING_FAIL:
|
||||||
reason = 0;
|
reason = 0;
|
||||||
err = -EPERM;
|
err = -EPERM;
|
||||||
|
del_timer(&hcon->smp_timer);
|
||||||
hci_conn_put(hcon);
|
hci_conn_put(hcon);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -893,6 +892,7 @@ done:
|
|||||||
BT_ERR("SMP_CMD_PAIRING_FAIL: %d", reason);
|
BT_ERR("SMP_CMD_PAIRING_FAIL: %d", reason);
|
||||||
smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
|
smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
|
||||||
&reason);
|
&reason);
|
||||||
|
del_timer(&hcon->smp_timer);
|
||||||
hci_conn_put(hcon);
|
hci_conn_put(hcon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -984,6 +984,8 @@ static int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
|
|||||||
if (hcon->out || rsp->resp_key_dist) {
|
if (hcon->out || rsp->resp_key_dist) {
|
||||||
if (hcon->disconn_cfm_cb)
|
if (hcon->disconn_cfm_cb)
|
||||||
hcon->disconn_cfm_cb(hcon, 0);
|
hcon->disconn_cfm_cb(hcon, 0);
|
||||||
|
|
||||||
|
del_timer(&hcon->smp_timer);
|
||||||
hci_conn_put(hcon);
|
hci_conn_put(hcon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1005,3 +1007,14 @@ int smp_link_encrypt_cmplt(struct l2cap_conn *conn, u8 status, u8 encrypt)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void smp_timeout(unsigned long arg)
|
||||||
|
{
|
||||||
|
struct l2cap_conn *conn = (void *) arg;
|
||||||
|
u8 reason = SMP_UNSPECIFIED;
|
||||||
|
|
||||||
|
BT_DBG("%p", conn);
|
||||||
|
|
||||||
|
smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason);
|
||||||
|
hci_conn_put(conn->hcon);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user