]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - net/bluetooth/mgmt.c
Bluetooth: Use unresolvable private address for active scanning
[mirror_ubuntu-artful-kernel.git] / net / bluetooth / mgmt.c
index 8c94841072a8f02601072cce9b7ff750142c6608..5d309d4ab527ebc98944d553adbc3cb3c73d0199 100644 (file)
@@ -81,6 +81,8 @@ static const u16 mgmt_commands[] = {
        MGMT_OP_SET_SCAN_PARAMS,
        MGMT_OP_SET_SECURE_CONN,
        MGMT_OP_SET_DEBUG_KEYS,
+       MGMT_OP_SET_PRIVACY,
+       MGMT_OP_LOAD_IRKS,
 };
 
 static const u16 mgmt_events[] = {
@@ -105,6 +107,7 @@ static const u16 mgmt_events[] = {
        MGMT_EV_DEVICE_UNBLOCKED,
        MGMT_EV_DEVICE_UNPAIRED,
        MGMT_EV_PASSKEY_NOTIFY,
+       MGMT_EV_NEW_IRK,
 };
 
 #define CACHE_TIMEOUT  msecs_to_jiffies(2 * 1000)
@@ -388,6 +391,7 @@ static u32 get_supported_settings(struct hci_dev *hdev)
        if (lmp_le_capable(hdev)) {
                settings |= MGMT_SETTING_LE;
                settings |= MGMT_SETTING_ADVERTISING;
+               settings |= MGMT_SETTING_PRIVACY;
        }
 
        return settings;
@@ -436,6 +440,9 @@ static u32 get_current_settings(struct hci_dev *hdev)
        if (test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags))
                settings |= MGMT_SETTING_DEBUG_KEYS;
 
+       if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
+               settings |= MGMT_SETTING_PRIVACY;
+
        return settings;
 }
 
@@ -810,6 +817,54 @@ static void update_class(struct hci_request *req)
        hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
 }
 
+static u8 get_adv_type(struct hci_dev *hdev)
+{
+       struct pending_cmd *cmd;
+       bool connectable;
+
+       /* If there's a pending mgmt command the flag will not yet have
+        * it's final value, so check for this first.
+        */
+       cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
+       if (cmd) {
+               struct mgmt_mode *cp = cmd->param;
+               connectable = !!cp->val;
+       } else {
+               connectable = test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
+       }
+
+       return connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
+}
+
+static void enable_advertising(struct hci_request *req)
+{
+       struct hci_dev *hdev = req->hdev;
+       struct hci_cp_le_set_adv_param cp;
+       u8 own_addr_type, enable = 0x01;
+
+       memset(&cp, 0, sizeof(cp));
+
+       if (hci_update_random_address(req, false, &own_addr_type) < 0)
+               return;
+
+       cp.min_interval = __constant_cpu_to_le16(0x0800);
+       cp.max_interval = __constant_cpu_to_le16(0x0800);
+       cp.type = get_adv_type(hdev);
+       cp.own_address_type = own_addr_type;
+       cp.channel_map = hdev->le_adv_channel_map;
+
+       hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
+
+       hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
+}
+
+static void disable_advertising(struct hci_request *req)
+{
+       u8 enable = 0x00;
+
+       hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
+}
+
 static void service_cache_off(struct work_struct *work)
 {
        struct hci_dev *hdev = container_of(work, struct hci_dev,
@@ -831,12 +886,39 @@ static void service_cache_off(struct work_struct *work)
        hci_req_run(&req, NULL);
 }
 
+static void rpa_expired(struct work_struct *work)
+{
+       struct hci_dev *hdev = container_of(work, struct hci_dev,
+                                           rpa_expired.work);
+       struct hci_request req;
+
+       BT_DBG("");
+
+       set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
+
+       if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags) ||
+           hci_conn_num(hdev, LE_LINK) > 0)
+               return;
+
+       /* The generation of a new RPA and programming it into the
+        * controller happens in the enable_advertising() function.
+        */
+
+       hci_req_init(&req, hdev);
+
+       disable_advertising(&req);
+       enable_advertising(&req);
+
+       hci_req_run(&req, NULL);
+}
+
 static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
 {
        if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
                return;
 
        INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
+       INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
 
        /* Non-mgmt controlled devices get this bit set
         * implicitly so that pairing works for them, however
@@ -1343,50 +1425,6 @@ static void write_fast_connectable(struct hci_request *req, bool enable)
                hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
 }
 
-static u8 get_adv_type(struct hci_dev *hdev)
-{
-       struct pending_cmd *cmd;
-       bool connectable;
-
-       /* If there's a pending mgmt command the flag will not yet have
-        * it's final value, so check for this first.
-        */
-       cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
-       if (cmd) {
-               struct mgmt_mode *cp = cmd->param;
-               connectable = !!cp->val;
-       } else {
-               connectable = test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
-       }
-
-       return connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
-}
-
-static void enable_advertising(struct hci_request *req)
-{
-       struct hci_dev *hdev = req->hdev;
-       struct hci_cp_le_set_adv_param cp;
-       u8 enable = 0x01;
-
-       memset(&cp, 0, sizeof(cp));
-       cp.min_interval = __constant_cpu_to_le16(0x0800);
-       cp.max_interval = __constant_cpu_to_le16(0x0800);
-       cp.type = get_adv_type(hdev);
-       cp.own_address_type = hdev->own_addr_type;
-       cp.channel_map = 0x07;
-
-       hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
-
-       hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
-}
-
-static void disable_advertising(struct hci_request *req)
-{
-       u8 enable = 0x00;
-
-       hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
-}
-
 static void set_connectable_complete(struct hci_dev *hdev, u8 status)
 {
        struct pending_cmd *cmd;
@@ -2072,7 +2110,7 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
        }
 
        if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
-               err = hci_uuids_clear(hdev);
+               hci_uuids_clear(hdev);
 
                if (enable_service_cache(hdev)) {
                        err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
@@ -2317,10 +2355,20 @@ static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
                goto unlock;
        }
 
-       if (cp->addr.type == BDADDR_BREDR)
+       if (cp->addr.type == BDADDR_BREDR) {
                err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
-       else
-               err = hci_remove_ltk(hdev, &cp->addr.bdaddr);
+       } else {
+               u8 addr_type;
+
+               if (cp->addr.type == BDADDR_LE_PUBLIC)
+                       addr_type = ADDR_LE_DEV_PUBLIC;
+               else
+                       addr_type = ADDR_LE_DEV_RANDOM;
+
+               hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
+
+               err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
+       }
 
        if (err < 0) {
                err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
@@ -2644,6 +2692,16 @@ static void pairing_complete(struct pending_cmd *cmd, u8 status)
        mgmt_pending_remove(cmd);
 }
 
+void mgmt_smp_complete(struct hci_conn *conn, bool complete)
+{
+       u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
+       struct pending_cmd *cmd;
+
+       cmd = find_pairing(conn);
+       if (cmd)
+               pairing_complete(cmd, status);
+}
+
 static void pairing_complete_cb(struct hci_conn *conn, u8 status)
 {
        struct pending_cmd *cmd;
@@ -2657,7 +2715,7 @@ static void pairing_complete_cb(struct hci_conn *conn, u8 status)
                pairing_complete(cmd, mgmt_status(status));
 }
 
-static void le_connect_complete_cb(struct hci_conn *conn, u8 status)
+static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
 {
        struct pending_cmd *cmd;
 
@@ -2744,13 +2802,16 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
        }
 
        /* For LE, just connecting isn't a proof that the pairing finished */
-       if (cp->addr.type == BDADDR_BREDR)
+       if (cp->addr.type == BDADDR_BREDR) {
                conn->connect_cfm_cb = pairing_complete_cb;
-       else
-               conn->connect_cfm_cb = le_connect_complete_cb;
+               conn->security_cfm_cb = pairing_complete_cb;
+               conn->disconn_cfm_cb = pairing_complete_cb;
+       } else {
+               conn->connect_cfm_cb = le_pairing_complete_cb;
+               conn->security_cfm_cb = le_pairing_complete_cb;
+               conn->disconn_cfm_cb = le_pairing_complete_cb;
+       }
 
-       conn->security_cfm_cb = pairing_complete_cb;
-       conn->disconn_cfm_cb = pairing_complete_cb;
        conn->io_capability = cp->io_cap;
        cmd->user_data = conn;
 
@@ -3234,7 +3295,7 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
        struct hci_request req;
        /* General inquiry access code (GIAC) */
        u8 lap[3] = { 0x33, 0x8b, 0x9e };
-       u8 status;
+       u8 status, own_addr_type;
        int err;
 
        BT_DBG("%s", hdev->name);
@@ -3327,10 +3388,23 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
                }
 
                memset(&param_cp, 0, sizeof(param_cp));
+
+               /* All active scans will be done with either a resolvable
+                * private address (when privacy feature has been enabled)
+                * or unresolvable private address.
+                */
+               err = hci_update_random_address(&req, true, &own_addr_type);
+               if (err < 0) {
+                       err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
+                                        MGMT_STATUS_FAILED);
+                       mgmt_pending_remove(cmd);
+                       goto failed;
+               }
+
                param_cp.type = LE_SCAN_ACTIVE;
                param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
                param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
-               param_cp.own_address_type = hdev->own_addr_type;
+               param_cp.own_address_type = own_addr_type;
                hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
                            &param_cp);
 
@@ -4043,7 +4117,7 @@ static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
 {
        struct mgmt_mode *cp = data;
        struct pending_cmd *cmd;
-       u8 status;
+       u8 val, status;
        int err;
 
        BT_DBG("request for %s", hdev->name);
@@ -4058,7 +4132,7 @@ static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
                return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
                                  MGMT_STATUS_NOT_SUPPORTED);
 
-       if (cp->val != 0x00 && cp->val != 0x01)
+       if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
                return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
                                  MGMT_STATUS_INVALID_PARAMS);
 
@@ -4067,12 +4141,18 @@ static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
        if (!hdev_is_powered(hdev)) {
                bool changed;
 
-               if (cp->val)
+               if (cp->val) {
                        changed = !test_and_set_bit(HCI_SC_ENABLED,
                                                    &hdev->dev_flags);
-               else
+                       if (cp->val == 0x02)
+                               set_bit(HCI_SC_ONLY, &hdev->dev_flags);
+                       else
+                               clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
+               } else {
                        changed = test_and_clear_bit(HCI_SC_ENABLED,
                                                     &hdev->dev_flags);
+                       clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
+               }
 
                err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
                if (err < 0)
@@ -4090,7 +4170,10 @@ static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
                goto failed;
        }
 
-       if (!!cp->val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags)) {
+       val = !!cp->val;
+
+       if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
+           (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
                err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
                goto failed;
        }
@@ -4101,12 +4184,17 @@ static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
                goto failed;
        }
 
-       err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &cp->val);
+       err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
        if (err < 0) {
                mgmt_pending_remove(cmd);
                goto failed;
        }
 
+       if (cp->val == 0x02)
+               set_bit(HCI_SC_ONLY, &hdev->dev_flags);
+       else
+               clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
+
 failed:
        hci_dev_unlock(hdev);
        return err;
@@ -4144,13 +4232,144 @@ unlock:
        return err;
 }
 
+static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
+                      u16 len)
+{
+       struct mgmt_cp_set_privacy *cp = cp_data;
+       bool changed;
+       int err;
+
+       BT_DBG("request for %s", hdev->name);
+
+       if (!lmp_le_capable(hdev))
+               return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
+                                 MGMT_STATUS_NOT_SUPPORTED);
+
+       if (cp->privacy != 0x00 && cp->privacy != 0x01)
+               return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
+                                 MGMT_STATUS_INVALID_PARAMS);
+
+       if (hdev_is_powered(hdev))
+               return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
+                                 MGMT_STATUS_REJECTED);
+
+       hci_dev_lock(hdev);
+
+       if (cp->privacy) {
+               changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
+               memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
+               set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
+       } else {
+               changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
+               memset(hdev->irk, 0, sizeof(hdev->irk));
+               clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
+       }
+
+       err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
+       if (err < 0)
+               goto unlock;
+
+       if (changed)
+               err = new_settings(hdev, sk);
+
+unlock:
+       hci_dev_unlock(hdev);
+       return err;
+}
+
+static bool irk_is_valid(struct mgmt_irk_info *irk)
+{
+       switch (irk->addr.type) {
+       case BDADDR_LE_PUBLIC:
+               return true;
+
+       case BDADDR_LE_RANDOM:
+               /* Two most significant bits shall be set */
+               if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
+                       return false;
+               return true;
+       }
+
+       return false;
+}
+
+static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
+                    u16 len)
+{
+       struct mgmt_cp_load_irks *cp = cp_data;
+       u16 irk_count, expected_len;
+       int i, err;
+
+       BT_DBG("request for %s", hdev->name);
+
+       if (!lmp_le_capable(hdev))
+               return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
+                                 MGMT_STATUS_NOT_SUPPORTED);
+
+       irk_count = __le16_to_cpu(cp->irk_count);
+
+       expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
+       if (expected_len != len) {
+               BT_ERR("load_irks: expected %u bytes, got %u bytes",
+                      len, expected_len);
+               return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
+                                 MGMT_STATUS_INVALID_PARAMS);
+       }
+
+       BT_DBG("%s irk_count %u", hdev->name, irk_count);
+
+       for (i = 0; i < irk_count; i++) {
+               struct mgmt_irk_info *key = &cp->irks[i];
+
+               if (!irk_is_valid(key))
+                       return cmd_status(sk, hdev->id,
+                                         MGMT_OP_LOAD_IRKS,
+                                         MGMT_STATUS_INVALID_PARAMS);
+       }
+
+       hci_dev_lock(hdev);
+
+       hci_smp_irks_clear(hdev);
+
+       for (i = 0; i < irk_count; i++) {
+               struct mgmt_irk_info *irk = &cp->irks[i];
+               u8 addr_type;
+
+               if (irk->addr.type == BDADDR_LE_PUBLIC)
+                       addr_type = ADDR_LE_DEV_PUBLIC;
+               else
+                       addr_type = ADDR_LE_DEV_RANDOM;
+
+               hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
+                           BDADDR_ANY);
+       }
+
+       set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
+
+       err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
+
+       hci_dev_unlock(hdev);
+
+       return err;
+}
+
 static bool ltk_is_valid(struct mgmt_ltk_info *key)
 {
        if (key->master != 0x00 && key->master != 0x01)
                return false;
-       if (!bdaddr_type_is_le(key->addr.type))
-               return false;
-       return true;
+
+       switch (key->addr.type) {
+       case BDADDR_LE_PUBLIC:
+               return true;
+
+       case BDADDR_LE_RANDOM:
+               /* Two most significant bits shall be set */
+               if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
+                       return false;
+               return true;
+       }
+
+       return false;
 }
 
 static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
@@ -4206,9 +4425,9 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
                else
                        type = HCI_SMP_LTK_SLAVE;
 
-               hci_add_ltk(hdev, &key->addr.bdaddr, addr_type,
-                           type, 0, key->type, key->val,
-                           key->enc_size, key->ediv, key->rand);
+               hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
+                           key->type, key->val, key->enc_size, key->ediv,
+                           key->rand);
        }
 
        err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
@@ -4272,6 +4491,8 @@ static const struct mgmt_handler {
        { set_scan_params,        false, MGMT_SET_SCAN_PARAMS_SIZE },
        { set_secure_conn,        false, MGMT_SETTING_SIZE },
        { set_debug_keys,         false, MGMT_SETTING_SIZE },
+       { set_privacy,            false, MGMT_SET_PRIVACY_SIZE },
+       { load_irks,              true,  MGMT_LOAD_IRKS_SIZE },
 };
 
 
@@ -4437,11 +4658,6 @@ static int powered_update_hci(struct hci_dev *hdev)
        }
 
        if (lmp_le_capable(hdev)) {
-               /* Set random address to static address if configured */
-               if (bacmp(&hdev->static_addr, BDADDR_ANY))
-                       hci_req_add(&req, HCI_OP_LE_SET_RANDOM_ADDR, 6,
-                                   &hdev->static_addr);
-
                /* Make sure the controller has a good default for
                 * advertising data. This also applies to the case
                 * where BR/EDR was toggled during the AUTO_OFF phase.
@@ -4639,13 +4855,29 @@ void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
        mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
 }
 
-void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent)
+void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key)
 {
        struct mgmt_ev_new_long_term_key ev;
 
        memset(&ev, 0, sizeof(ev));
 
-       ev.store_hint = persistent;
+       /* Devices using resolvable or non-resolvable random addresses
+        * without providing an indentity resolving key don't require
+        * to store long term keys. Their addresses will change the
+        * next time around.
+        *
+        * Only when a remote device provides an identity address
+        * make sure the long term key is stored. If the remote
+        * identity is known, the long term keys are internally
+        * mapped to the identity address. So allow static random
+        * and public addresses here.
+        */
+       if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
+           (key->bdaddr.b[5] & 0xc0) != 0xc0)
+               ev.store_hint = 0x00;
+       else
+               ev.store_hint = 0x01;
+
        bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
        ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
        ev.key.type = key->authenticated;
@@ -4661,6 +4893,36 @@ void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent)
        mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
 }
 
+void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
+{
+       struct mgmt_ev_new_irk ev;
+
+       memset(&ev, 0, sizeof(ev));
+
+       /* For identity resolving keys from devices that are already
+        * using a public address or static random address, do not
+        * ask for storing this key. The identity resolving key really
+        * is only mandatory for devices using resovlable random
+        * addresses.
+        *
+        * Storing all identity resolving keys has the downside that
+        * they will be also loaded on next boot of they system. More
+        * identity resolving keys, means more time during scanning is
+        * needed to actually resolve these addresses.
+        */
+       if (bacmp(&irk->rpa, BDADDR_ANY))
+               ev.store_hint = 0x01;
+       else
+               ev.store_hint = 0x00;
+
+       bacpy(&ev.rpa, &irk->rpa);
+       bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
+       ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
+       memcpy(ev.irk.val, irk->val, sizeof(irk->val));
+
+       mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
+}
+
 static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
                                  u8 data_len)
 {
@@ -5063,19 +5325,24 @@ void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
        if (status) {
                u8 mgmt_err = mgmt_status(status);
 
-               if (enable && test_and_clear_bit(HCI_SC_ENABLED,
-                                                &hdev->dev_flags))
-                       new_settings(hdev, NULL);
+               if (enable) {
+                       if (test_and_clear_bit(HCI_SC_ENABLED,
+                                              &hdev->dev_flags))
+                               new_settings(hdev, NULL);
+                       clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
+               }
 
                mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
                                     cmd_status_rsp, &mgmt_err);
                return;
        }
 
-       if (enable)
+       if (enable) {
                changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
-       else
+       } else {
                changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
+               clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
+       }
 
        mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
                             settings_rsp, &match);
@@ -5194,6 +5461,7 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
 {
        char buf[512];
        struct mgmt_ev_device_found *ev = (void *) buf;
+       struct smp_irk *irk;
        size_t ev_size;
 
        if (!hci_discovery_active(hdev))
@@ -5205,8 +5473,15 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
 
        memset(buf, 0, sizeof(buf));
 
-       bacpy(&ev->addr.bdaddr, bdaddr);
-       ev->addr.type = link_to_bdaddr(link_type, addr_type);
+       irk = hci_get_irk(hdev, bdaddr, addr_type);
+       if (irk) {
+               bacpy(&ev->addr.bdaddr, &irk->bdaddr);
+               ev->addr.type = link_to_bdaddr(link_type, irk->addr_type);
+       } else {
+               bacpy(&ev->addr.bdaddr, bdaddr);
+               ev->addr.type = link_to_bdaddr(link_type, addr_type);
+       }
+
        ev->rssi = rssi;
        if (cfm_name)
                ev->flags |= __constant_cpu_to_le32(MGMT_DEV_FOUND_CONFIRM_NAME);