diff options
-rw-r--r-- | net/bluetooth/mgmt.c | 3 | ||||
-rw-r--r-- | net/bluetooth/smp.c | 26 | ||||
-rw-r--r-- | net/bluetooth/smp.h | 1 |
3 files changed, 30 insertions, 0 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 3fa4cafc2c03..7ace4663b7ba 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -3127,6 +3127,9 @@ static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data, goto done; } + /* Abort any ongoing SMP pairing */ + smp_cancel_pairing(conn); + /* Defer clearing up the connection parameters until closing to * give a chance of keeping them if a repairing happens. */ diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 94f9c4ca68f1..c91353841e40 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -2380,6 +2380,32 @@ unlock: return ret; } +void smp_cancel_pairing(struct hci_conn *hcon) +{ + struct l2cap_conn *conn = hcon->l2cap_data; + struct l2cap_chan *chan; + struct smp_chan *smp; + + if (!conn) + return; + + chan = conn->smp; + if (!chan) + return; + + l2cap_chan_lock(chan); + + smp = chan->data; + if (smp) { + if (test_bit(SMP_FLAG_COMPLETE, &smp->flags)) + smp_failure(conn, 0); + else + smp_failure(conn, SMP_UNSPECIFIED); + } + + l2cap_chan_unlock(chan); +} + static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb) { struct smp_cmd_encrypt_info *rp = (void *) skb->data; diff --git a/net/bluetooth/smp.h b/net/bluetooth/smp.h index 6cf872563ea7..ffcc70b6b199 100644 --- a/net/bluetooth/smp.h +++ b/net/bluetooth/smp.h @@ -180,6 +180,7 @@ enum smp_key_pref { }; /* SMP Commands */ +void smp_cancel_pairing(struct hci_conn *hcon); bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level, enum smp_key_pref key_pref); int smp_conn_security(struct hci_conn *hcon, __u8 sec_level); |