Bluetooth: Fix mgmt pairing failure when authentication fails
authorJohan Hedberg <johan.hedberg@intel.com>
Tue, 9 Sep 2014 00:09:49 +0000 (17:09 -0700)
committerMarcel Holtmann <marcel@holtmann.org>
Tue, 9 Sep 2014 01:12:15 +0000 (03:12 +0200)
Whether through HCI with BR/EDR or SMP with LE when authentication fails
we should also notify any pending Pair Device mgmt command. This patch
updates the mgmt_auth_failed function to take the actual hci_conn object
and makes sure that any pending pairing command is notified and cleaned
up appropriately.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
include/net/bluetooth/hci_core.h
net/bluetooth/hci_event.c
net/bluetooth/mgmt.c
net/bluetooth/smp.c

index 045d9133d1805fed32fb07ad5c7313c4987fd0da..206b92bfeebbdd301d01764d9328b64e06fe4415 100644 (file)
@@ -1342,8 +1342,7 @@ int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
 int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
                             u8 link_type, u8 addr_type, u32 passkey,
                             u8 entered);
-void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
-                     u8 addr_type, u8 status);
+void mgmt_auth_failed(struct hci_conn *conn, u8 status);
 void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status);
 void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status);
 void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status);
index e6a496ae0318daab653674a0120297c21e63244a..3a8381ab992f0c79691b52d022707895804a67a6 100644 (file)
@@ -2320,8 +2320,7 @@ static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
                        conn->sec_level = conn->pending_sec_level;
                }
        } else {
-               mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
-                                ev->status);
+               mgmt_auth_failed(conn, ev->status);
        }
 
        clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
@@ -3900,8 +3899,7 @@ static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
         * event gets always produced as initiator and is also mapped to
         * the mgmt_auth_failed event */
        if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
-               mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
-                                ev->status);
+               mgmt_auth_failed(conn, ev->status);
 
        hci_conn_drop(conn);
 
index ab9521ae3c639fbb1ae9f5c8d497439402f51ccb..efb71b022ab6520527b3087dbf917ddcb925438e 100644 (file)
@@ -6485,16 +6485,23 @@ int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
        return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
 }
 
-void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
-                     u8 addr_type, u8 status)
+void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
 {
        struct mgmt_ev_auth_failed ev;
+       struct pending_cmd *cmd;
+       u8 status = mgmt_status(hci_status);
 
-       bacpy(&ev.addr.bdaddr, bdaddr);
-       ev.addr.type = link_to_bdaddr(link_type, addr_type);
-       ev.status = mgmt_status(status);
+       bacpy(&ev.addr.bdaddr, &conn->dst);
+       ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
+       ev.status = status;
 
-       mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
+       cmd = find_pairing(conn);
+
+       mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
+                   cmd ? cmd->sk : NULL);
+
+       if (cmd)
+               pairing_complete(cmd, status);
 }
 
 void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
index 560f78a9f960a59b64330c2618539ba29cf3d8ea..25c9040e0b1297e6ecc114d1d3405b37b707b07c 100644 (file)
@@ -420,8 +420,7 @@ static void smp_failure(struct l2cap_conn *conn, u8 reason)
                             &reason);
 
        clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags);
-       mgmt_auth_failed(hcon->hdev, &hcon->dst, hcon->type, hcon->dst_type,
-                        HCI_ERROR_AUTH_FAILURE);
+       mgmt_auth_failed(hcon, HCI_ERROR_AUTH_FAILURE);
 
        if (chan->data)
                smp_chan_destroy(conn);