mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
bluetooth pull request for net:
Core: - hci_core: Initialize IRK before publication - hci_core: Initialize link key before publication - hci_core: Initialize LTK before publication - hci_core: Fix queuing rx_work while workqueue is drained - hci_core: Keep link-key filtering inside RCU - hci_core: Initialize advertising RPA work only once - hci_sync: Fix invalid Supervision_Timeout in LE Set Default Rate - hci_sync: re-enable legacy advertising on resume - hci_sync: pause advertising for the scan address update - hci_sync: Update the CIS host feature when enabling LE - hci_sync: Copy the LE accept list under hdev->lock - hci_sync: Protect resolving-list lookups - hci_sync: Copy the resolving-list IRK under RCU - hci_event: Clear explicit connect state on LE connection - L2CAP: Hold incoming data until encryption key size is known - L2CAP: Ignore connection responses with wrong ident - SMP: Protect link keys during LTK derivation - SMP: Protect LTK encryption with RCU - MGMT: Return RFKILLED for Set Powered on a blocked controller - MGMT: Clear disabled connection parameters when loading none - MGMT: Fix discovery stuck after a failed Stop Discovery - validate retained LE Create CIS command length - validate retained LE Set CIG Parameters command length Drivers: - btintel: fix buffer over-read in fw payload - btmtk: drop zero-length ISO packets from endpoint padding - btmtk: bound the ISO payload length by the controller's MTU - btmtk: derive the firmware ISO setting from MTK_ISO_THRESHOLD - btmtk: fix error handling in btmtk_usb_isointf_init() - qca: Fix the WCN3950 NVM baud rate offset -----BEGIN PGP SIGNATURE----- iQJNBAABCgA3FiEE7E6oRXp8w05ovYr/9JCA4xAyCykFAmrpClsZHGx1aXoudm9u LmRlbnR6QGludGVsLmNvbQAKCRD0kIDjEDILKX8dD/44mBWlS5mLxxsDlraw3Ew4 IxZjzmkv3Lgf/5oTDeemBfiUCGmOoZTxCfARMoi4iYGZSYsYKqxOxnuue3+ganm1 iAe2ZPxhlggajzvT6pSGatk2U5cpdLtCe3Ivc0XCcjFsTALCAbUr4XGHfg2wxnoe Lv+20pj2Re8e0b1yo/4ABLczVzi8yy+UbXVq9LspqnuhNr76h5OidnB6FhHz8jqy SwiInk0hWRfkxZFNf+0W+AVWEqKGAdvQnGQAqMADOgNWIi2EKqOjLRCeHCwfaz03 yPRXXXvsXF5cREN3U8FNp805E/fu+qKU0WQCiKJT4AeA9YC7mFeE45WxeTkgrKxK 2ryMsuv0cV8Rr6Wvvy5N5c0pxfMp+ShkzCLktnSpNY02kq3m50ywOoynVijGDg/l ILAhmC0jbw9rRwLSRaGe4K5n2aFkK7Uwp7V1LzlWAIOB1HTu2ZfubWJVTWhXYb8n Gwf1AkhdRiL1n8/0pxV+syAwIZwfYEulFc6NzUXe0Bzj0vKXleuiyH9JvTIM7020 WPdXZA2/NSa6bgf3lbqAJ8r1lrQMtZ11FQdBCoUFvGG1pHVgDcHbQDCyEwlVdhPk QsCPUqL4qiXcKqAa44p49nSSESa6jOipj59jdy7WFixQmd9TLk7dFA88T0iigyvq nZcqwFNS/1z7SDrAMOh7tw== =RKn1 -----END PGP SIGNATURE----- Merge tag 'for-net-2026-11-02' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth Luiz Augusto von Dentz says: ==================== bluetooth pull request for net: Core: - hci_core: Initialize IRK before publication - hci_core: Initialize link key before publication - hci_core: Initialize LTK before publication - hci_core: Fix queuing rx_work while workqueue is drained - hci_core: Keep link-key filtering inside RCU - hci_core: Initialize advertising RPA work only once - hci_sync: Fix invalid Supervision_Timeout in LE Set Default Rate - hci_sync: re-enable legacy advertising on resume - hci_sync: pause advertising for the scan address update - hci_sync: Update the CIS host feature when enabling LE - hci_sync: Copy the LE accept list under hdev->lock - hci_sync: Protect resolving-list lookups - hci_sync: Copy the resolving-list IRK under RCU - hci_event: Clear explicit connect state on LE connection - L2CAP: Hold incoming data until encryption key size is known - L2CAP: Ignore connection responses with wrong ident - SMP: Protect link keys during LTK derivation - SMP: Protect LTK encryption with RCU - MGMT: Return RFKILLED for Set Powered on a blocked controller - MGMT: Clear disabled connection parameters when loading none - MGMT: Fix discovery stuck after a failed Stop Discovery - validate retained LE Create CIS command length - validate retained LE Set CIG Parameters command length Drivers: - btintel: fix buffer over-read in fw payload - btmtk: drop zero-length ISO packets from endpoint padding - btmtk: bound the ISO payload length by the controller's MTU - btmtk: derive the firmware ISO setting from MTK_ISO_THRESHOLD - btmtk: fix error handling in btmtk_usb_isointf_init() - qca: Fix the WCN3950 NVM baud rate offset * tag 'for-net-2026-11-02' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth: (30 commits) Bluetooth: MGMT: Fix discovery stuck after a failed Stop Discovery Bluetooth: validate retained LE Set CIG Parameters command length Bluetooth: validate retained LE Create CIS command length Bluetooth: hci_core: Initialize advertising RPA work only once Bluetooth: L2CAP: Ignore connection responses with wrong ident Bluetooth: MGMT: Clear disabled connection parameters when loading none Bluetooth: hci_sync: Copy the resolving-list IRK under RCU Bluetooth: SMP: Protect LTK encryption with RCU Bluetooth: SMP: Protect link keys during LTK derivation Bluetooth: hci_core: Keep link-key filtering inside RCU Bluetooth: btmtk: fix error handling in btmtk_usb_isointf_init() Bluetooth: qca: Fix the WCN3950 NVM baud rate offset Bluetooth: MGMT: Return RFKILLED for Set Powered on a blocked controller Bluetooth: hci_sync: Protect resolving-list lookups Bluetooth: hci_sync: Copy the LE accept list under hdev->lock Bluetooth: btmtk: derive the firmware ISO setting from MTK_ISO_THRESHOLD Bluetooth: btmtk: bound the ISO payload length by the controller's MTU Bluetooth: btmtk: drop zero-length ISO packets from endpoint padding Bluetooth: hci_sync: Update the CIS host feature when enabling LE Bluetooth: L2CAP: Hold incoming data until encryption key size is known ... ==================== Link: https://patch.msgid.link/20261102222018.2610820-1-luiz.dentz@gmail.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
commit
03d3676329
|
|
@ -1201,7 +1201,29 @@ static int btintel_download_firmware_payload(struct hci_dev *hdev,
|
|||
err = -EINVAL;
|
||||
|
||||
while (fw_ptr - fw->data < fw->size) {
|
||||
struct hci_command_hdr *cmd = (void *)(fw_ptr + frag_len);
|
||||
struct hci_command_hdr *cmd;
|
||||
size_t remain = fw->size - (fw_ptr - fw->data);
|
||||
|
||||
/* Ensure the header fits before dereferencing */
|
||||
if (frag_len + sizeof(*cmd) > remain) {
|
||||
bt_dev_err(hdev,
|
||||
"Firmware buffer overrun at header (frag_len %u, need %zu, remain %zu)",
|
||||
frag_len, frag_len + sizeof(*cmd), remain);
|
||||
err = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
cmd = (void *)(fw_ptr + frag_len);
|
||||
|
||||
/* Ensure the full command (header + payload) fits before use */
|
||||
if (frag_len + sizeof(*cmd) + cmd->plen > remain) {
|
||||
bt_dev_err(hdev,
|
||||
"Firmware buffer overrun at payload (frag_len %u, plen %u, need %zu, remain %zu)",
|
||||
frag_len, cmd->plen,
|
||||
frag_len + sizeof(*cmd) + cmd->plen, remain);
|
||||
err = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
frag_len += sizeof(*cmd) + cmd->plen;
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include <linux/usb.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/overflow.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/unaligned.h>
|
||||
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
|
|
@ -30,7 +31,7 @@
|
|||
#define BTMTK_CBMCU_FLAG_ENABLE_PATCH 0xF1
|
||||
|
||||
/* It is for mt79xx iso data transmission setting */
|
||||
#define MTK_ISO_THRESHOLD 264
|
||||
#define MTK_ISO_THRESHOLD 342
|
||||
|
||||
struct btmtk_patch_header {
|
||||
u8 datetime[16];
|
||||
|
|
@ -1556,8 +1557,15 @@ static int btmtk_recv_isopkt(struct hci_dev *hdev, void *buffer, int count)
|
|||
struct btmtk_data *btmtk_data = hci_get_priv(hdev);
|
||||
struct sk_buff *skb;
|
||||
unsigned long flags;
|
||||
unsigned int iso_mtu;
|
||||
int err = 0;
|
||||
|
||||
/* The controller reports the largest Data_Total_Length it will send in
|
||||
* LE Read Buffer Size [v2]. Fall back to HCI_MAX_ISO_SIZE while that
|
||||
* command has not completed yet.
|
||||
*/
|
||||
iso_mtu = hdev->iso_mtu ? hdev->iso_mtu : HCI_MAX_ISO_SIZE;
|
||||
|
||||
spin_lock_irqsave(&btmtk_data->isorxlock, flags);
|
||||
skb = btmtk_data->isopkt_skb;
|
||||
|
||||
|
|
@ -1565,7 +1573,16 @@ static int btmtk_recv_isopkt(struct hci_dev *hdev, void *buffer, int count)
|
|||
int len;
|
||||
|
||||
if (!skb) {
|
||||
skb = bt_skb_alloc(HCI_MAX_ISO_SIZE, GFP_ATOMIC);
|
||||
/* Drop the endpoint's zero-filled padding before
|
||||
* allocating an skb for it; a zero Data_Total_Length
|
||||
* check below would miss a padding remainder
|
||||
* shorter than an ISO header.
|
||||
*/
|
||||
if (mem_is_zero(buffer, count))
|
||||
break;
|
||||
|
||||
skb = bt_skb_alloc(HCI_ISO_HDR_SIZE + iso_mtu,
|
||||
GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
err = -ENOMEM;
|
||||
break;
|
||||
|
|
@ -1588,7 +1605,24 @@ static int btmtk_recv_isopkt(struct hci_dev *hdev, void *buffer, int count)
|
|||
/* Complete ISO header */
|
||||
hci_skb_expect(skb) = __le16_to_cpu(dlen);
|
||||
|
||||
if (skb_tailroom(skb) < hci_skb_expect(skb)) {
|
||||
if (!hci_skb_expect(skb)) {
|
||||
/* Zero padding was ruled out above, so a
|
||||
* zero Data_Total_Length here is invalid.
|
||||
*/
|
||||
kfree_skb(skb);
|
||||
skb = NULL;
|
||||
|
||||
err = -EILSEQ;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Reject a length the controller said it would never
|
||||
* send. The skb_tailroom() test is kept because a
|
||||
* fragment started before hdev->iso_mtu was populated
|
||||
* sits in a smaller skb than iso_mtu now allows.
|
||||
*/
|
||||
if (hci_skb_expect(skb) > iso_mtu ||
|
||||
skb_tailroom(skb) < hci_skb_expect(skb)) {
|
||||
kfree_skb(skb);
|
||||
skb = NULL;
|
||||
|
||||
|
|
@ -1707,13 +1741,15 @@ static int btmtk_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags)
|
|||
static int btmtk_usb_isointf_init(struct hci_dev *hdev)
|
||||
{
|
||||
struct btmtk_data *btmtk_data = hci_get_priv(hdev);
|
||||
u8 iso_param[2] = { 0x08, 0x01 };
|
||||
__le16 iso_param = cpu_to_le16(MTK_ISO_THRESHOLD);
|
||||
struct sk_buff *skb;
|
||||
int err;
|
||||
|
||||
spin_lock_init(&btmtk_data->isorxlock);
|
||||
|
||||
__set_mtk_intr_interface(hdev);
|
||||
err = __set_mtk_intr_interface(hdev);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = btmtk_submit_intr_urb(hdev, GFP_KERNEL);
|
||||
if (err < 0) {
|
||||
|
|
@ -1722,9 +1758,10 @@ static int btmtk_usb_isointf_init(struct hci_dev *hdev)
|
|||
return err;
|
||||
}
|
||||
|
||||
skb = __hci_cmd_sync(hdev, 0xfd98, sizeof(iso_param), iso_param,
|
||||
skb = __hci_cmd_sync(hdev, 0xfd98, sizeof(iso_param), &iso_param,
|
||||
HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
usb_kill_anchored_urbs(&btmtk_data->isopkt_anchor);
|
||||
bt_dev_err(hdev, "Failed to apply iso setting (%ld)", PTR_ERR(skb));
|
||||
return PTR_ERR(skb);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -426,7 +426,8 @@ static int qca_tlv_check_data(struct hci_dev *hdev,
|
|||
tlv_nvm->data[0] |= 0x80;
|
||||
|
||||
/* UART Baud Rate */
|
||||
if (soc_type >= QCA_WCN3991)
|
||||
if (soc_type == QCA_WCN3950 ||
|
||||
soc_type >= QCA_WCN3991)
|
||||
tlv_nvm->data[1] = nvm_baud_rate;
|
||||
else
|
||||
tlv_nvm->data[2] = nvm_baud_rate;
|
||||
|
|
|
|||
|
|
@ -680,6 +680,45 @@ enum conn_reasons {
|
|||
CONN_REASON_ISO_CONNECT,
|
||||
};
|
||||
|
||||
enum {
|
||||
HCI_CONN_AUTH_PEND,
|
||||
HCI_CONN_ENCRYPT_PEND,
|
||||
HCI_CONN_RSWITCH_PEND,
|
||||
HCI_CONN_MODE_CHANGE_PEND,
|
||||
HCI_CONN_SCO_SETUP_PEND,
|
||||
HCI_CONN_MGMT_CONNECTED,
|
||||
HCI_CONN_SSP_ENABLED,
|
||||
HCI_CONN_SC_ENABLED,
|
||||
HCI_CONN_AES_CCM,
|
||||
HCI_CONN_POWER_SAVE,
|
||||
HCI_CONN_FLUSH_KEY,
|
||||
HCI_CONN_ENCRYPT,
|
||||
HCI_CONN_AUTH,
|
||||
HCI_CONN_SECURE,
|
||||
HCI_CONN_FIPS,
|
||||
HCI_CONN_STK_ENCRYPT,
|
||||
HCI_CONN_AUTH_INITIATOR,
|
||||
HCI_CONN_DROP,
|
||||
HCI_CONN_CANCEL,
|
||||
HCI_CONN_PARAM_REMOVAL_PEND,
|
||||
HCI_CONN_NEW_LINK_KEY,
|
||||
HCI_CONN_SCANNING,
|
||||
HCI_CONN_AUTH_FAILURE,
|
||||
HCI_CONN_PER_ADV,
|
||||
HCI_CONN_BIG_CREATED,
|
||||
HCI_CONN_CREATE,
|
||||
HCI_CONN_CREATE_CIS,
|
||||
HCI_CONN_CREATE_BIG_SYNC,
|
||||
HCI_CONN_BIG_SYNC,
|
||||
HCI_CONN_BIG_SYNC_FAILED,
|
||||
HCI_CONN_CREATE_PA_SYNC,
|
||||
HCI_CONN_PA_SYNC,
|
||||
HCI_CONN_PA_SYNC_FAILED,
|
||||
HCI_CONN_ENC_KEY_SIZE_PEND,
|
||||
|
||||
__HCI_CONN_NUM_FLAGS,
|
||||
};
|
||||
|
||||
struct hci_conn {
|
||||
struct list_head list;
|
||||
|
||||
|
|
@ -750,7 +789,7 @@ struct hci_conn {
|
|||
__u8 num_bis;
|
||||
__u8 bis[HCI_MAX_ISO_BIS];
|
||||
|
||||
unsigned long flags;
|
||||
DECLARE_BITMAP(flags, __HCI_CONN_NUM_FLAGS);
|
||||
|
||||
enum conn_reasons conn_reason;
|
||||
__u8 abort_reason;
|
||||
|
|
@ -980,55 +1019,18 @@ u32 hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data,
|
|||
bool name_known);
|
||||
void hci_inquiry_cache_flush(struct hci_dev *hdev);
|
||||
|
||||
/* ----- HCI Connections ----- */
|
||||
enum {
|
||||
HCI_CONN_AUTH_PEND,
|
||||
HCI_CONN_ENCRYPT_PEND,
|
||||
HCI_CONN_RSWITCH_PEND,
|
||||
HCI_CONN_MODE_CHANGE_PEND,
|
||||
HCI_CONN_SCO_SETUP_PEND,
|
||||
HCI_CONN_MGMT_CONNECTED,
|
||||
HCI_CONN_SSP_ENABLED,
|
||||
HCI_CONN_SC_ENABLED,
|
||||
HCI_CONN_AES_CCM,
|
||||
HCI_CONN_POWER_SAVE,
|
||||
HCI_CONN_FLUSH_KEY,
|
||||
HCI_CONN_ENCRYPT,
|
||||
HCI_CONN_AUTH,
|
||||
HCI_CONN_SECURE,
|
||||
HCI_CONN_FIPS,
|
||||
HCI_CONN_STK_ENCRYPT,
|
||||
HCI_CONN_AUTH_INITIATOR,
|
||||
HCI_CONN_DROP,
|
||||
HCI_CONN_CANCEL,
|
||||
HCI_CONN_PARAM_REMOVAL_PEND,
|
||||
HCI_CONN_NEW_LINK_KEY,
|
||||
HCI_CONN_SCANNING,
|
||||
HCI_CONN_AUTH_FAILURE,
|
||||
HCI_CONN_PER_ADV,
|
||||
HCI_CONN_BIG_CREATED,
|
||||
HCI_CONN_CREATE,
|
||||
HCI_CONN_CREATE_CIS,
|
||||
HCI_CONN_CREATE_BIG_SYNC,
|
||||
HCI_CONN_BIG_SYNC,
|
||||
HCI_CONN_BIG_SYNC_FAILED,
|
||||
HCI_CONN_CREATE_PA_SYNC,
|
||||
HCI_CONN_PA_SYNC,
|
||||
HCI_CONN_PA_SYNC_FAILED,
|
||||
};
|
||||
|
||||
static inline bool hci_conn_ssp_enabled(struct hci_conn *conn)
|
||||
{
|
||||
struct hci_dev *hdev = conn->hdev;
|
||||
return hci_dev_test_flag(hdev, HCI_SSP_ENABLED) &&
|
||||
test_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
|
||||
test_bit(HCI_CONN_SSP_ENABLED, conn->flags);
|
||||
}
|
||||
|
||||
static inline bool hci_conn_sc_enabled(struct hci_conn *conn)
|
||||
{
|
||||
struct hci_dev *hdev = conn->hdev;
|
||||
return hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
|
||||
test_bit(HCI_CONN_SC_ENABLED, &conn->flags);
|
||||
test_bit(HCI_CONN_SC_ENABLED, conn->flags);
|
||||
}
|
||||
|
||||
static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c)
|
||||
|
|
@ -1219,7 +1221,7 @@ hci_conn_hash_lookup_create_pa_sync(struct hci_dev *hdev)
|
|||
if (c->type != PA_LINK)
|
||||
continue;
|
||||
|
||||
if (!test_bit(HCI_CONN_CREATE_PA_SYNC, &c->flags))
|
||||
if (!test_bit(HCI_CONN_CREATE_PA_SYNC, c->flags))
|
||||
continue;
|
||||
|
||||
rcu_read_unlock();
|
||||
|
|
@ -1245,7 +1247,7 @@ hci_conn_hash_lookup_per_adv_bis(struct hci_dev *hdev,
|
|||
|
||||
list_for_each_entry_rcu(c, &h->list, list) {
|
||||
if (bacmp(&c->dst, ba) || c->type != BIS_LINK ||
|
||||
!test_bit(HCI_CONN_PER_ADV, &c->flags))
|
||||
!test_bit(HCI_CONN_PER_ADV, c->flags))
|
||||
continue;
|
||||
|
||||
if (c->iso_qos.bcast.big == big &&
|
||||
|
|
@ -1502,7 +1504,7 @@ hci_conn_hash_lookup_pa_sync_big_handle(struct hci_dev *hdev, __u8 big)
|
|||
|
||||
list_for_each_entry_rcu(c, &h->list, list) {
|
||||
if (c->type != BIS_LINK ||
|
||||
!test_bit(HCI_CONN_PA_SYNC, &c->flags))
|
||||
!test_bit(HCI_CONN_PA_SYNC, c->flags))
|
||||
continue;
|
||||
|
||||
if (c->iso_qos.bcast.big == big) {
|
||||
|
|
@ -1580,7 +1582,7 @@ static inline void hci_conn_hash_list_flag(struct hci_dev *hdev,
|
|||
rcu_read_lock();
|
||||
|
||||
list_for_each_entry_rcu(c, &h->list, list) {
|
||||
if (c->type == type && test_bit(flag, &c->flags))
|
||||
if (c->type == type && test_bit(flag, c->flags))
|
||||
func(c, data);
|
||||
}
|
||||
|
||||
|
|
@ -1598,7 +1600,7 @@ static inline struct hci_conn *hci_lookup_le_connect(struct hci_dev *hdev)
|
|||
|
||||
list_for_each_entry_rcu(c, &h->list, list) {
|
||||
if (c->type == LE_LINK && c->state == BT_CONNECT &&
|
||||
!test_bit(HCI_CONN_SCANNING, &c->flags)) {
|
||||
!test_bit(HCI_CONN_SCANNING, c->flags)) {
|
||||
rcu_read_unlock();
|
||||
return c;
|
||||
}
|
||||
|
|
@ -1619,7 +1621,7 @@ static inline bool hci_is_le_conn_scanning(struct hci_dev *hdev)
|
|||
|
||||
list_for_each_entry_rcu(c, &h->list, list) {
|
||||
if (c->type == LE_LINK && c->state == BT_CONNECT &&
|
||||
test_bit(HCI_CONN_SCANNING, &c->flags)) {
|
||||
test_bit(HCI_CONN_SCANNING, c->flags)) {
|
||||
rcu_read_unlock();
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2239,10 +2241,10 @@ static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
|
|||
struct hci_cb *cb;
|
||||
__u8 encrypt;
|
||||
|
||||
if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags))
|
||||
if (test_bit(HCI_CONN_ENCRYPT_PEND, conn->flags))
|
||||
return;
|
||||
|
||||
encrypt = test_bit(HCI_CONN_ENCRYPT, &conn->flags) ? 0x01 : 0x00;
|
||||
encrypt = test_bit(HCI_CONN_ENCRYPT, conn->flags) ? 0x01 : 0x00;
|
||||
|
||||
mutex_lock(&hci_cb_list_lock);
|
||||
list_for_each_entry(cb, &hci_cb_list, list) {
|
||||
|
|
@ -2271,9 +2273,9 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!test_bit(HCI_CONN_ENCRYPT, &conn->flags))
|
||||
if (!test_bit(HCI_CONN_ENCRYPT, conn->flags))
|
||||
encrypt = 0x00;
|
||||
else if (test_bit(HCI_CONN_AES_CCM, &conn->flags))
|
||||
else if (test_bit(HCI_CONN_AES_CCM, conn->flags))
|
||||
encrypt = 0x02;
|
||||
else
|
||||
encrypt = 0x01;
|
||||
|
|
@ -2426,6 +2428,8 @@ void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb);
|
|||
void hci_send_iso(struct hci_conn *conn, struct sk_buff *skb);
|
||||
|
||||
void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode);
|
||||
void *hci_sent_cmd_data_len(struct hci_dev *hdev, __u16 opcode,
|
||||
size_t *len);
|
||||
void *hci_recv_event_data(struct hci_dev *hdev, __u8 event);
|
||||
|
||||
u32 hci_conn_get_phy(struct hci_conn *conn);
|
||||
|
|
|
|||
|
|
@ -138,10 +138,10 @@ static void hci_conn_cleanup(struct hci_conn *conn)
|
|||
{
|
||||
struct hci_dev *hdev = conn->hdev;
|
||||
|
||||
if (test_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags))
|
||||
if (test_bit(HCI_CONN_PARAM_REMOVAL_PEND, conn->flags))
|
||||
hci_conn_params_del(conn->hdev, &conn->dst, conn->dst_type);
|
||||
|
||||
if (test_and_clear_bit(HCI_CONN_FLUSH_KEY, &conn->flags))
|
||||
if (test_and_clear_bit(HCI_CONN_FLUSH_KEY, conn->flags))
|
||||
hci_remove_link_key(hdev, &conn->dst);
|
||||
|
||||
hci_chan_list_flush(conn);
|
||||
|
|
@ -685,7 +685,7 @@ static void hci_conn_idle(struct work_struct *work)
|
|||
hci_send_cmd(hdev, HCI_OP_SNIFF_SUBRATE, sizeof(cp), &cp);
|
||||
}
|
||||
|
||||
if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags)) {
|
||||
if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, conn->flags)) {
|
||||
struct hci_cp_sniff_mode cp;
|
||||
cp.handle = cpu_to_le16(conn->handle);
|
||||
cp.max_interval = cpu_to_le16(hdev->sniff_max_interval);
|
||||
|
|
@ -814,7 +814,7 @@ static int hci_le_terminate_big(struct hci_dev *hdev, struct hci_conn *conn)
|
|||
|
||||
d->big = conn->iso_qos.bcast.big;
|
||||
d->bis = conn->iso_qos.bcast.bis;
|
||||
d->big_term = test_and_clear_bit(HCI_CONN_BIG_CREATED, &conn->flags);
|
||||
d->big_term = test_and_clear_bit(HCI_CONN_BIG_CREATED, conn->flags);
|
||||
|
||||
ret = hci_cmd_sync_queue(hdev, terminate_big_sync, d,
|
||||
terminate_big_destroy);
|
||||
|
|
@ -867,7 +867,7 @@ static int hci_le_big_terminate(struct hci_dev *hdev, struct hci_conn *conn)
|
|||
d->sync_handle = conn->sync_handle;
|
||||
|
||||
if (conn->type == PA_LINK &&
|
||||
test_and_clear_bit(HCI_CONN_PA_SYNC, &conn->flags)) {
|
||||
test_and_clear_bit(HCI_CONN_PA_SYNC, conn->flags)) {
|
||||
hci_conn_hash_list_flag(hdev, find_bis, PA_LINK,
|
||||
HCI_CONN_PA_SYNC, d);
|
||||
|
||||
|
|
@ -877,7 +877,7 @@ static int hci_le_big_terminate(struct hci_dev *hdev, struct hci_conn *conn)
|
|||
d->count = 0;
|
||||
}
|
||||
|
||||
if (test_and_clear_bit(HCI_CONN_BIG_SYNC, &conn->flags)) {
|
||||
if (test_and_clear_bit(HCI_CONN_BIG_SYNC, conn->flags)) {
|
||||
hci_conn_hash_list_flag(hdev, find_bis, BIS_LINK,
|
||||
HCI_CONN_BIG_SYNC, d);
|
||||
|
||||
|
|
@ -912,7 +912,7 @@ static void bis_cleanup(struct hci_conn *conn)
|
|||
bt_dev_dbg(hdev, "conn %p", conn);
|
||||
|
||||
if (conn->role == HCI_ROLE_MASTER) {
|
||||
if (!test_and_clear_bit(HCI_CONN_PER_ADV, &conn->flags))
|
||||
if (!test_and_clear_bit(HCI_CONN_PER_ADV, conn->flags))
|
||||
return;
|
||||
|
||||
/* Check if ISO connection is a BIS and terminate advertising
|
||||
|
|
@ -1087,7 +1087,7 @@ static struct hci_conn *__hci_conn_add(struct hci_dev *hdev, int type,
|
|||
conn->sync_handle = HCI_SYNC_HANDLE_INVALID;
|
||||
conn->sid = HCI_SID_INVALID;
|
||||
|
||||
set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
|
||||
set_bit(HCI_CONN_POWER_SAVE, conn->flags);
|
||||
conn->disc_timeout = HCI_DISCONN_TIMEOUT;
|
||||
|
||||
/* Set Default Authenticated payload timeout to 30s */
|
||||
|
|
@ -1217,8 +1217,8 @@ static void hci_conn_cleanup_child(struct hci_conn *conn, u8 reason)
|
|||
case BIS_LINK:
|
||||
case PA_LINK:
|
||||
if ((conn->state != BT_CONNECTED &&
|
||||
!test_bit(HCI_CONN_CREATE_CIS, &conn->flags)) ||
|
||||
test_bit(HCI_CONN_BIG_CREATED, &conn->flags))
|
||||
!test_bit(HCI_CONN_CREATE_CIS, conn->flags)) ||
|
||||
test_bit(HCI_CONN_BIG_CREATED, conn->flags))
|
||||
hci_conn_failed(conn, reason);
|
||||
break;
|
||||
}
|
||||
|
|
@ -1234,8 +1234,8 @@ static void hci_conn_unlink(struct hci_conn *conn)
|
|||
struct hci_link *link, *t;
|
||||
|
||||
conn->sec_level = BT_SECURITY_SDP;
|
||||
clear_bit(HCI_CONN_ENCRYPT, &conn->flags);
|
||||
clear_bit(HCI_CONN_AES_CCM, &conn->flags);
|
||||
clear_bit(HCI_CONN_ENCRYPT, conn->flags);
|
||||
clear_bit(HCI_CONN_AES_CCM, conn->flags);
|
||||
/* mgmt_security_level_changed() reports the reset only if
|
||||
* this connection was actually reported to userspace as
|
||||
* connected (it checks HCI_CONN_MGMT_CONNECTED itself), so it
|
||||
|
|
@ -1254,7 +1254,7 @@ static void hci_conn_unlink(struct hci_conn *conn)
|
|||
*/
|
||||
if (test_bit(HCI_UP, &hdev->flags))
|
||||
mgmt_security_level_changed(conn);
|
||||
clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags);
|
||||
clear_bit(HCI_CONN_MGMT_CONNECTED, conn->flags);
|
||||
|
||||
list_for_each_entry_safe(link, t, &conn->link_list, list) {
|
||||
struct hci_conn *child = link->conn;
|
||||
|
|
@ -1458,8 +1458,8 @@ void hci_conn_failed(struct hci_conn *conn, u8 status)
|
|||
/* In case of BIG/PA sync failed, clear conn flags so that
|
||||
* the conns will be correctly cleaned up by ISO layer
|
||||
*/
|
||||
test_and_clear_bit(HCI_CONN_BIG_SYNC_FAILED, &conn->flags);
|
||||
test_and_clear_bit(HCI_CONN_PA_SYNC_FAILED, &conn->flags);
|
||||
test_and_clear_bit(HCI_CONN_BIG_SYNC_FAILED, conn->flags);
|
||||
test_and_clear_bit(HCI_CONN_PA_SYNC_FAILED, conn->flags);
|
||||
|
||||
conn->state = BT_CLOSED;
|
||||
hci_connect_cfm(conn, status);
|
||||
|
|
@ -1524,9 +1524,8 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
|
|||
* to connect.
|
||||
*/
|
||||
conn = hci_conn_hash_lookup_le(hdev, dst, dst_type);
|
||||
if (conn && !test_bit(HCI_CONN_SCANNING, &conn->flags)) {
|
||||
if (conn && !test_bit(HCI_CONN_SCANNING, conn->flags))
|
||||
return ERR_PTR(-EBUSY);
|
||||
}
|
||||
|
||||
/* Check if the destination address has been resolved by the controller
|
||||
* since if it did then the identity address shall be used.
|
||||
|
|
@ -1614,8 +1613,9 @@ static int hci_explicit_conn_params_set(struct hci_dev *hdev,
|
|||
if (!params)
|
||||
return -ENOMEM;
|
||||
|
||||
/* If we created new params, mark them to be deleted in
|
||||
* hci_connect_le_scan_cleanup. It's different case than
|
||||
/* If we created new params, mark them to be deleted once the
|
||||
* explicit connect is done, see le_conn_complete_evt() and
|
||||
* hci_connect_le_scan_cleanup(). It's different case than
|
||||
* existing disabled params, those will stay after cleanup.
|
||||
*/
|
||||
params->auto_connect = HCI_AUTO_CONN_EXPLICIT;
|
||||
|
|
@ -1797,7 +1797,7 @@ struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst,
|
|||
}
|
||||
|
||||
conn->state = BT_CONNECT;
|
||||
set_bit(HCI_CONN_SCANNING, &conn->flags);
|
||||
set_bit(HCI_CONN_SCANNING, conn->flags);
|
||||
conn->sec_level = BT_SECURITY_LOW;
|
||||
conn->pending_sec_level = sec_level;
|
||||
conn->conn_timeout = conn_timeout;
|
||||
|
|
@ -1923,12 +1923,12 @@ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst,
|
|||
|
||||
if (acl->state == BT_CONNECTED &&
|
||||
(sco->state == BT_OPEN || sco->state == BT_CLOSED)) {
|
||||
set_bit(HCI_CONN_POWER_SAVE, &acl->flags);
|
||||
set_bit(HCI_CONN_POWER_SAVE, acl->flags);
|
||||
hci_conn_enter_active_mode(acl, BT_POWER_FORCE_ACTIVE_ON);
|
||||
|
||||
if (test_bit(HCI_CONN_MODE_CHANGE_PEND, &acl->flags)) {
|
||||
if (test_bit(HCI_CONN_MODE_CHANGE_PEND, acl->flags)) {
|
||||
/* defer SCO setup until mode change completed */
|
||||
set_bit(HCI_CONN_SCO_SETUP_PEND, &acl->flags);
|
||||
set_bit(HCI_CONN_SCO_SETUP_PEND, acl->flags);
|
||||
return sco;
|
||||
}
|
||||
|
||||
|
|
@ -2220,7 +2220,7 @@ int hci_le_create_cis_pending(struct hci_dev *hdev)
|
|||
rcu_read_lock();
|
||||
|
||||
list_for_each_entry_rcu(conn, &hdev->conn_hash.list, list) {
|
||||
if (test_bit(HCI_CONN_CREATE_CIS, &conn->flags)) {
|
||||
if (test_bit(HCI_CONN_CREATE_CIS, conn->flags)) {
|
||||
rcu_read_unlock();
|
||||
return -EBUSY;
|
||||
}
|
||||
|
|
@ -2448,7 +2448,7 @@ static void bis_mark_per_adv(struct hci_conn *conn, void *data)
|
|||
d->bis != conn->iso_qos.bcast.bis)
|
||||
return;
|
||||
|
||||
set_bit(HCI_CONN_PER_ADV, &conn->flags);
|
||||
set_bit(HCI_CONN_PER_ADV, conn->flags);
|
||||
}
|
||||
|
||||
struct hci_conn *hci_connect_bis(struct hci_dev *hdev, bdaddr_t *dst,
|
||||
|
|
@ -2568,7 +2568,7 @@ int hci_conn_check_link_mode(struct hci_conn *conn)
|
|||
*/
|
||||
if (hci_dev_test_flag(conn->hdev, HCI_SC_ONLY)) {
|
||||
if (!hci_conn_sc_enabled(conn) ||
|
||||
!test_bit(HCI_CONN_AES_CCM, &conn->flags) ||
|
||||
!test_bit(HCI_CONN_AES_CCM, conn->flags) ||
|
||||
conn->key_type != HCI_LK_AUTH_COMBINATION_P256)
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2584,14 +2584,14 @@ int hci_conn_check_link_mode(struct hci_conn *conn)
|
|||
* not shortened)
|
||||
*/
|
||||
if (conn->sec_level == BT_SECURITY_FIPS &&
|
||||
!test_bit(HCI_CONN_AES_CCM, &conn->flags)) {
|
||||
!test_bit(HCI_CONN_AES_CCM, conn->flags)) {
|
||||
bt_dev_err(conn->hdev,
|
||||
"Invalid security: Missing AES-CCM usage");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (hci_conn_ssp_enabled(conn) &&
|
||||
!test_bit(HCI_CONN_ENCRYPT, &conn->flags))
|
||||
!test_bit(HCI_CONN_ENCRYPT, conn->flags))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
|
|
@ -2607,7 +2607,7 @@ static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
|
|||
|
||||
if (sec_level > conn->sec_level)
|
||||
conn->pending_sec_level = sec_level;
|
||||
else if (test_bit(HCI_CONN_AUTH, &conn->flags))
|
||||
else if (test_bit(HCI_CONN_AUTH, conn->flags))
|
||||
return 1;
|
||||
|
||||
/* Make sure we preserve an existing MITM requirement*/
|
||||
|
|
@ -2615,7 +2615,7 @@ static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
|
|||
|
||||
conn->auth_type = auth_type;
|
||||
|
||||
if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
|
||||
if (!test_and_set_bit(HCI_CONN_AUTH_PEND, conn->flags)) {
|
||||
struct hci_cp_auth_requested cp;
|
||||
|
||||
cp.handle = cpu_to_le16(conn->handle);
|
||||
|
|
@ -2625,8 +2625,8 @@ static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
|
|||
/* Set the ENCRYPT_PEND to trigger encryption after
|
||||
* authentication.
|
||||
*/
|
||||
if (!test_bit(HCI_CONN_ENCRYPT, &conn->flags))
|
||||
set_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
|
||||
if (!test_bit(HCI_CONN_ENCRYPT, conn->flags))
|
||||
set_bit(HCI_CONN_ENCRYPT_PEND, conn->flags);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -2637,7 +2637,7 @@ static void hci_conn_encrypt(struct hci_conn *conn)
|
|||
{
|
||||
BT_DBG("hcon %p", conn);
|
||||
|
||||
if (!test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
|
||||
if (!test_and_set_bit(HCI_CONN_ENCRYPT_PEND, conn->flags)) {
|
||||
struct hci_cp_set_conn_encrypt cp;
|
||||
cp.handle = cpu_to_le16(conn->handle);
|
||||
cp.encrypt = 0x01;
|
||||
|
|
@ -2665,7 +2665,7 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type,
|
|||
return 1;
|
||||
|
||||
/* For other security levels we need the link key. */
|
||||
if (!test_bit(HCI_CONN_AUTH, &conn->flags))
|
||||
if (!test_bit(HCI_CONN_AUTH, conn->flags))
|
||||
goto auth;
|
||||
|
||||
switch (conn->key_type) {
|
||||
|
|
@ -2705,17 +2705,17 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type,
|
|||
}
|
||||
|
||||
auth:
|
||||
if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags))
|
||||
if (test_bit(HCI_CONN_ENCRYPT_PEND, conn->flags))
|
||||
return 0;
|
||||
|
||||
if (initiator)
|
||||
set_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags);
|
||||
set_bit(HCI_CONN_AUTH_INITIATOR, conn->flags);
|
||||
|
||||
if (!hci_conn_auth(conn, sec_level, auth_type))
|
||||
return 0;
|
||||
|
||||
encrypt:
|
||||
if (test_bit(HCI_CONN_ENCRYPT, &conn->flags)) {
|
||||
if (test_bit(HCI_CONN_ENCRYPT, conn->flags)) {
|
||||
/* Ensure that the encryption key size has been read,
|
||||
* otherwise stall the upper layer responses.
|
||||
*/
|
||||
|
|
@ -2758,7 +2758,7 @@ int hci_conn_switch_role(struct hci_conn *conn, __u8 role)
|
|||
if (role == conn->role)
|
||||
return 1;
|
||||
|
||||
if (!test_and_set_bit(HCI_CONN_RSWITCH_PEND, &conn->flags)) {
|
||||
if (!test_and_set_bit(HCI_CONN_RSWITCH_PEND, conn->flags)) {
|
||||
struct hci_cp_switch_role cp;
|
||||
bacpy(&cp.bdaddr, &conn->dst);
|
||||
cp.role = role;
|
||||
|
|
@ -2779,10 +2779,10 @@ void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active)
|
|||
if (conn->mode != HCI_CM_SNIFF)
|
||||
goto timer;
|
||||
|
||||
if (!test_bit(HCI_CONN_POWER_SAVE, &conn->flags) && !force_active)
|
||||
if (!test_bit(HCI_CONN_POWER_SAVE, conn->flags) && !force_active)
|
||||
goto timer;
|
||||
|
||||
if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags)) {
|
||||
if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, conn->flags)) {
|
||||
struct hci_cp_exit_sniff_mode cp;
|
||||
cp.handle = cpu_to_le16(conn->handle);
|
||||
hci_send_cmd(hdev, HCI_OP_EXIT_SNIFF_MODE, sizeof(cp), &cp);
|
||||
|
|
@ -2822,16 +2822,16 @@ static u32 get_link_mode(struct hci_conn *conn)
|
|||
if (conn->role == HCI_ROLE_MASTER)
|
||||
link_mode |= HCI_LM_MASTER;
|
||||
|
||||
if (test_bit(HCI_CONN_ENCRYPT, &conn->flags))
|
||||
if (test_bit(HCI_CONN_ENCRYPT, conn->flags))
|
||||
link_mode |= HCI_LM_ENCRYPT;
|
||||
|
||||
if (test_bit(HCI_CONN_AUTH, &conn->flags))
|
||||
if (test_bit(HCI_CONN_AUTH, conn->flags))
|
||||
link_mode |= HCI_LM_AUTH;
|
||||
|
||||
if (test_bit(HCI_CONN_SECURE, &conn->flags))
|
||||
if (test_bit(HCI_CONN_SECURE, conn->flags))
|
||||
link_mode |= HCI_LM_SECURE;
|
||||
|
||||
if (test_bit(HCI_CONN_FIPS, &conn->flags))
|
||||
if (test_bit(HCI_CONN_FIPS, conn->flags))
|
||||
link_mode |= HCI_LM_FIPS;
|
||||
|
||||
return link_mode;
|
||||
|
|
@ -2945,7 +2945,7 @@ struct hci_chan *hci_chan_create(struct hci_conn *conn)
|
|||
|
||||
BT_DBG("%s hcon %p", hdev->name, conn);
|
||||
|
||||
if (test_bit(HCI_CONN_DROP, &conn->flags)) {
|
||||
if (test_bit(HCI_CONN_DROP, conn->flags)) {
|
||||
BT_DBG("Refusing to create new hci_chan");
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -2975,7 +2975,7 @@ void hci_chan_del(struct hci_chan *chan)
|
|||
synchronize_rcu();
|
||||
|
||||
/* Prevent new hci_chan's to be created for this hci_conn */
|
||||
set_bit(HCI_CONN_DROP, &conn->flags);
|
||||
set_bit(HCI_CONN_DROP, conn->flags);
|
||||
|
||||
hci_conn_put(conn);
|
||||
|
||||
|
|
|
|||
|
|
@ -1075,17 +1075,16 @@ struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
|
|||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(k, &hdev->link_keys, list) {
|
||||
if (bacmp(bdaddr, &k->bdaddr) == 0) {
|
||||
rcu_read_unlock();
|
||||
|
||||
if (hci_is_blocked_key(hdev,
|
||||
HCI_BLOCKED_KEY_TYPE_LINKKEY,
|
||||
k->val)) {
|
||||
bt_dev_warn_ratelimited(hdev,
|
||||
"Link key blocked for %pMR",
|
||||
&k->bdaddr);
|
||||
return NULL;
|
||||
k = NULL;
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
return k;
|
||||
}
|
||||
}
|
||||
|
|
@ -1252,7 +1251,6 @@ struct link_key *hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn,
|
|||
key = kzalloc_obj(*key);
|
||||
if (!key)
|
||||
return NULL;
|
||||
list_add_rcu(&key->list, &hdev->link_keys);
|
||||
}
|
||||
|
||||
BT_DBG("%s key for %pMR type %u", hdev->name, bdaddr, type);
|
||||
|
|
@ -1276,6 +1274,9 @@ struct link_key *hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn,
|
|||
else
|
||||
key->type = type;
|
||||
|
||||
if (!old_key)
|
||||
list_add_rcu(&key->list, &hdev->link_keys);
|
||||
|
||||
if (persistent)
|
||||
*persistent = hci_persistent_key(hdev, conn, type,
|
||||
old_key_type);
|
||||
|
|
@ -1297,7 +1298,6 @@ struct smp_ltk *hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
|||
key = kzalloc_obj(*key);
|
||||
if (!key)
|
||||
return NULL;
|
||||
list_add_rcu(&key->list, &hdev->long_term_keys);
|
||||
}
|
||||
|
||||
bacpy(&key->bdaddr, bdaddr);
|
||||
|
|
@ -1309,15 +1309,19 @@ struct smp_ltk *hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
|||
key->enc_size = enc_size;
|
||||
key->type = type;
|
||||
|
||||
if (!old_key)
|
||||
list_add_rcu(&key->list, &hdev->long_term_keys);
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
struct smp_irk *hci_add_irk(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
||||
u8 addr_type, u8 val[16], bdaddr_t *rpa)
|
||||
{
|
||||
struct smp_irk *irk;
|
||||
struct smp_irk *irk, *old_irk;
|
||||
|
||||
irk = hci_find_irk_by_addr(hdev, bdaddr, addr_type);
|
||||
old_irk = hci_find_irk_by_addr(hdev, bdaddr, addr_type);
|
||||
irk = old_irk;
|
||||
if (!irk) {
|
||||
irk = kzalloc_obj(*irk);
|
||||
if (!irk)
|
||||
|
|
@ -1326,12 +1330,14 @@ struct smp_irk *hci_add_irk(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
|||
bacpy(&irk->bdaddr, bdaddr);
|
||||
irk->addr_type = addr_type;
|
||||
|
||||
list_add_rcu(&irk->list, &hdev->identity_resolving_keys);
|
||||
}
|
||||
|
||||
memcpy(irk->val, val, 16);
|
||||
bacpy(&irk->rpa, rpa);
|
||||
|
||||
if (!old_irk)
|
||||
list_add_rcu(&irk->list, &hdev->identity_resolving_keys);
|
||||
|
||||
return irk;
|
||||
}
|
||||
|
||||
|
|
@ -1694,6 +1700,9 @@ struct adv_info *hci_add_adv_instance(struct hci_dev *hdev, u8 instance,
|
|||
if (!adv)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
INIT_DELAYED_WORK(&adv->rpa_expired_cb,
|
||||
adv_instance_rpa_expired);
|
||||
|
||||
adv->pending = true;
|
||||
adv->instance = instance;
|
||||
|
||||
|
|
@ -1730,8 +1739,6 @@ struct adv_info *hci_add_adv_instance(struct hci_dev *hdev, u8 instance,
|
|||
else
|
||||
adv->duration = duration;
|
||||
|
||||
INIT_DELAYED_WORK(&adv->rpa_expired_cb, adv_instance_rpa_expired);
|
||||
|
||||
BT_DBG("%s for %dMR", hdev->name, instance);
|
||||
|
||||
return adv;
|
||||
|
|
@ -2897,8 +2904,14 @@ int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
{
|
||||
u8 dev_pkt_type;
|
||||
|
||||
/* Pairs with synchronize_rcu() in hci_dev_close_sync(), so rx_work is
|
||||
* not queued once the workqueue is being drained.
|
||||
*/
|
||||
rcu_read_lock();
|
||||
|
||||
if (!hdev || (!test_bit(HCI_UP, &hdev->flags)
|
||||
&& !test_bit(HCI_INIT, &hdev->flags))) {
|
||||
rcu_read_unlock();
|
||||
kfree_skb(skb);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
|
@ -2934,6 +2947,7 @@ int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
case HCI_DRV_PKT:
|
||||
break;
|
||||
default:
|
||||
rcu_read_unlock();
|
||||
kfree_skb(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -2947,6 +2961,8 @@ int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
skb_queue_tail(&hdev->rx_q, skb);
|
||||
queue_work(hdev->workqueue, &hdev->rx_work);
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(hci_recv_frame);
|
||||
|
|
@ -3159,7 +3175,8 @@ int __hci_cmd_send(struct hci_dev *hdev, u16 opcode, u32 plen,
|
|||
EXPORT_SYMBOL(__hci_cmd_send);
|
||||
|
||||
/* Get data from the previously sent command */
|
||||
static void *hci_cmd_data(struct sk_buff *skb, __u16 opcode)
|
||||
static void *hci_cmd_data(struct sk_buff *skb, __u16 opcode,
|
||||
size_t *len)
|
||||
{
|
||||
struct hci_command_hdr *hdr;
|
||||
|
||||
|
|
@ -3171,21 +3188,30 @@ static void *hci_cmd_data(struct sk_buff *skb, __u16 opcode)
|
|||
if (hdr->opcode != cpu_to_le16(opcode))
|
||||
return NULL;
|
||||
|
||||
if (len)
|
||||
*len = skb->len - HCI_COMMAND_HDR_SIZE;
|
||||
|
||||
return skb->data + HCI_COMMAND_HDR_SIZE;
|
||||
}
|
||||
|
||||
/* Get data from the previously sent command */
|
||||
void *hci_sent_cmd_data_len(struct hci_dev *hdev, __u16 opcode, size_t *len)
|
||||
{
|
||||
void *data;
|
||||
|
||||
/* Check if opcode matches last sent command */
|
||||
data = hci_cmd_data(hdev->sent_cmd, opcode, len);
|
||||
if (!data)
|
||||
/* Check if opcode matches last request */
|
||||
data = hci_cmd_data(hdev->req_skb, opcode, len);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/* Get data from the previously sent command */
|
||||
void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode)
|
||||
{
|
||||
void *data;
|
||||
|
||||
/* Check if opcode matches last sent command */
|
||||
data = hci_cmd_data(hdev->sent_cmd, opcode);
|
||||
if (!data)
|
||||
/* Check if opcode matches last request */
|
||||
data = hci_cmd_data(hdev->req_skb, opcode);
|
||||
|
||||
return data;
|
||||
return hci_sent_cmd_data_len(hdev, opcode, NULL);
|
||||
}
|
||||
|
||||
/* Get data from last received event */
|
||||
|
|
|
|||
|
|
@ -724,6 +724,8 @@ static u8 hci_cc_read_enc_key_size(struct hci_dev *hdev, void *data,
|
|||
goto done;
|
||||
}
|
||||
|
||||
clear_bit(HCI_CONN_ENC_KEY_SIZE_PEND, conn->flags);
|
||||
|
||||
/* While unexpected, the read_enc_key_size command may fail. The most
|
||||
* secure approach is to then assume the key size is 0 to force a
|
||||
* disconnection.
|
||||
|
|
@ -732,8 +734,8 @@ static u8 hci_cc_read_enc_key_size(struct hci_dev *hdev, void *data,
|
|||
bt_dev_err(hdev, "failed to read key size for handle %u",
|
||||
handle);
|
||||
conn->enc_key_size = 0;
|
||||
clear_bit(HCI_CONN_ENCRYPT, &conn->flags);
|
||||
clear_bit(HCI_CONN_AES_CCM, &conn->flags);
|
||||
clear_bit(HCI_CONN_ENCRYPT, conn->flags);
|
||||
clear_bit(HCI_CONN_AES_CCM, conn->flags);
|
||||
/* Downgrade to reflect the connection no longer being
|
||||
* encrypted, instead of advertising a stale elevated
|
||||
* security level alongside MGMT_CONN_SEC_ENCRYPT_NONE.
|
||||
|
|
@ -761,8 +763,8 @@ static u8 hci_cc_read_enc_key_size(struct hci_dev *hdev, void *data,
|
|||
* state at a later time.
|
||||
*/
|
||||
status = HCI_ERROR_AUTH_FAILURE;
|
||||
clear_bit(HCI_CONN_ENCRYPT, &conn->flags);
|
||||
clear_bit(HCI_CONN_AES_CCM, &conn->flags);
|
||||
clear_bit(HCI_CONN_ENCRYPT, conn->flags);
|
||||
clear_bit(HCI_CONN_AES_CCM, conn->flags);
|
||||
/* Downgrade to reflect the connection no longer being
|
||||
* encrypted, instead of advertising a stale elevated
|
||||
* security level alongside MGMT_CONN_SEC_ENCRYPT_NONE.
|
||||
|
|
@ -1817,6 +1819,8 @@ static void store_pending_adv_report(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
|||
|
||||
static void le_set_scan_enable_complete(struct hci_dev *hdev, u8 enable)
|
||||
{
|
||||
bool timeout_pending;
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
switch (enable) {
|
||||
|
|
@ -1846,10 +1850,18 @@ static void le_set_scan_enable_complete(struct hci_dev *hdev, u8 enable)
|
|||
/* Cancel this timer so that we don't try to disable scanning
|
||||
* when it's already disabled.
|
||||
*/
|
||||
cancel_delayed_work(&hdev->le_scan_disable);
|
||||
timeout_pending = cancel_delayed_work(&hdev->le_scan_disable);
|
||||
|
||||
hci_dev_clear_flag(hdev, HCI_LE_SCAN);
|
||||
|
||||
/* The scan of a discovery was disabled before its timeout,
|
||||
* for example by a Stop Discovery that timed out and still
|
||||
* completed, so nothing else would end the discovery.
|
||||
*/
|
||||
if (timeout_pending &&
|
||||
hdev->discovery.state == DISCOVERY_FINDING)
|
||||
hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
|
||||
|
||||
if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
|
||||
hci_test_quirk(hdev, HCI_QUIRK_SIMULTANEOUS_DISCOVERY) &&
|
||||
!test_bit(HCI_INQUIRY, &hdev->flags) &&
|
||||
|
|
@ -2595,10 +2607,10 @@ static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
|
|||
if (!hci_outgoing_auth_needed(hdev, conn))
|
||||
goto unlock;
|
||||
|
||||
if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
|
||||
if (!test_and_set_bit(HCI_CONN_AUTH_PEND, conn->flags)) {
|
||||
struct hci_cp_auth_requested auth_cp;
|
||||
|
||||
set_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags);
|
||||
set_bit(HCI_CONN_AUTH_INITIATOR, conn->flags);
|
||||
|
||||
auth_cp.handle = __cpu_to_le16(conn->handle);
|
||||
hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED,
|
||||
|
|
@ -2738,9 +2750,9 @@ static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
|
|||
|
||||
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
|
||||
if (conn) {
|
||||
clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
|
||||
clear_bit(HCI_CONN_MODE_CHANGE_PEND, conn->flags);
|
||||
|
||||
if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
|
||||
if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, conn->flags))
|
||||
hci_sco_setup(conn, status);
|
||||
}
|
||||
|
||||
|
|
@ -2765,9 +2777,9 @@ static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
|
|||
|
||||
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
|
||||
if (conn) {
|
||||
clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
|
||||
clear_bit(HCI_CONN_MODE_CHANGE_PEND, conn->flags);
|
||||
|
||||
if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
|
||||
if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, conn->flags))
|
||||
hci_sco_setup(conn, status);
|
||||
}
|
||||
|
||||
|
|
@ -2824,10 +2836,10 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
|
|||
* still needs it set to know whether to report the security level
|
||||
* reset, so it is consumed there instead of here.
|
||||
*/
|
||||
mgmt_conn = test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags);
|
||||
mgmt_conn = test_bit(HCI_CONN_MGMT_CONNECTED, conn->flags);
|
||||
|
||||
if (conn->type == ACL_LINK) {
|
||||
if (test_and_clear_bit(HCI_CONN_FLUSH_KEY, &conn->flags))
|
||||
if (test_and_clear_bit(HCI_CONN_FLUSH_KEY, conn->flags))
|
||||
hci_remove_link_key(hdev, &conn->dst);
|
||||
}
|
||||
|
||||
|
|
@ -3078,7 +3090,7 @@ static void hci_cs_switch_role(struct hci_dev *hdev, u8 status)
|
|||
|
||||
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
|
||||
if (conn)
|
||||
clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
|
||||
clear_bit(HCI_CONN_RSWITCH_PEND, conn->flags);
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
}
|
||||
|
|
@ -3190,6 +3202,7 @@ static int hci_read_enc_key_size(struct hci_dev *hdev, struct hci_conn *conn)
|
|||
{
|
||||
struct hci_cp_read_enc_key_size cp;
|
||||
u8 *key_enc_size = hci_conn_key_enc_size(conn);
|
||||
int err;
|
||||
|
||||
if (!read_key_size_capable(hdev)) {
|
||||
conn->enc_key_size = HCI_LINK_KEY_SIZE;
|
||||
|
|
@ -3211,7 +3224,14 @@ static int hci_read_enc_key_size(struct hci_dev *hdev, struct hci_conn *conn)
|
|||
else
|
||||
conn->enc_key_size = hdev->min_enc_key_size;
|
||||
|
||||
return hci_send_cmd(hdev, HCI_OP_READ_ENC_KEY_SIZE, sizeof(cp), &cp);
|
||||
/* L2CAP holds incoming data back until the key size is known */
|
||||
set_bit(HCI_CONN_ENC_KEY_SIZE_PEND, conn->flags);
|
||||
|
||||
err = hci_send_cmd(hdev, HCI_OP_READ_ENC_KEY_SIZE, sizeof(cp), &cp);
|
||||
if (err)
|
||||
clear_bit(HCI_CONN_ENC_KEY_SIZE_PEND, conn->flags);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
|
||||
|
|
@ -3309,19 +3329,19 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
|
|||
hci_conn_add_sysfs(conn);
|
||||
|
||||
if (test_bit(HCI_AUTH, &hdev->flags))
|
||||
set_bit(HCI_CONN_AUTH, &conn->flags);
|
||||
set_bit(HCI_CONN_AUTH, conn->flags);
|
||||
|
||||
if (test_bit(HCI_ENCRYPT, &hdev->flags))
|
||||
set_bit(HCI_CONN_ENCRYPT, &conn->flags);
|
||||
set_bit(HCI_CONN_ENCRYPT, conn->flags);
|
||||
|
||||
/* "Link key request" completed ahead of "connect request" completes */
|
||||
if (ev->encr_mode == 1 && !test_bit(HCI_CONN_ENCRYPT, &conn->flags) &&
|
||||
if (ev->encr_mode == 1 && !test_bit(HCI_CONN_ENCRYPT, conn->flags) &&
|
||||
ev->link_type == ACL_LINK) {
|
||||
struct link_key *key;
|
||||
|
||||
key = hci_find_link_key(hdev, &ev->bdaddr);
|
||||
if (key) {
|
||||
set_bit(HCI_CONN_ENCRYPT, &conn->flags);
|
||||
set_bit(HCI_CONN_ENCRYPT, conn->flags);
|
||||
hci_read_enc_key_size(hdev, conn);
|
||||
hci_encrypt_cfm(conn, ev->status);
|
||||
}
|
||||
|
|
@ -3525,9 +3545,9 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, void *data,
|
|||
* still needs it set to know whether to report the security level
|
||||
* reset, so it is consumed there instead of here.
|
||||
*/
|
||||
mgmt_connected = test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags);
|
||||
mgmt_connected = test_bit(HCI_CONN_MGMT_CONNECTED, conn->flags);
|
||||
|
||||
if (test_bit(HCI_CONN_AUTH_FAILURE, &conn->flags))
|
||||
if (test_bit(HCI_CONN_AUTH_FAILURE, conn->flags))
|
||||
reason = MGMT_DEV_DISCONN_AUTH_FAILURE;
|
||||
else
|
||||
reason = hci_to_mgmt_reason(ev->reason);
|
||||
|
|
@ -3536,7 +3556,7 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, void *data,
|
|||
reason, mgmt_connected);
|
||||
|
||||
if (conn->type == ACL_LINK) {
|
||||
if (test_and_clear_bit(HCI_CONN_FLUSH_KEY, &conn->flags))
|
||||
if (test_and_clear_bit(HCI_CONN_FLUSH_KEY, conn->flags))
|
||||
hci_remove_link_key(hdev, &conn->dst);
|
||||
|
||||
hci_update_scan(hdev);
|
||||
|
|
@ -3607,8 +3627,8 @@ static void hci_auth_complete_evt(struct hci_dev *hdev, void *data,
|
|||
goto unlock;
|
||||
|
||||
if (!ev->status) {
|
||||
clear_bit(HCI_CONN_AUTH_FAILURE, &conn->flags);
|
||||
set_bit(HCI_CONN_AUTH, &conn->flags);
|
||||
clear_bit(HCI_CONN_AUTH_FAILURE, conn->flags);
|
||||
set_bit(HCI_CONN_AUTH, conn->flags);
|
||||
/* Authentication alone does not imply encryption: for SSP
|
||||
* capable devices, encryption is only requested below, and
|
||||
* for legacy devices it is requested by a separate
|
||||
|
|
@ -3621,12 +3641,12 @@ static void hci_auth_complete_evt(struct hci_dev *hdev, void *data,
|
|||
conn->sec_level = conn->pending_sec_level;
|
||||
} else {
|
||||
if (ev->status == HCI_ERROR_PIN_OR_KEY_MISSING)
|
||||
set_bit(HCI_CONN_AUTH_FAILURE, &conn->flags);
|
||||
set_bit(HCI_CONN_AUTH_FAILURE, conn->flags);
|
||||
|
||||
mgmt_auth_failed(conn, ev->status);
|
||||
}
|
||||
|
||||
clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
|
||||
clear_bit(HCI_CONN_AUTH_PEND, conn->flags);
|
||||
|
||||
if (conn->state == BT_CONFIG) {
|
||||
if (!ev->status && hci_conn_ssp_enabled(conn)) {
|
||||
|
|
@ -3648,7 +3668,7 @@ static void hci_auth_complete_evt(struct hci_dev *hdev, void *data,
|
|||
hci_conn_drop(conn);
|
||||
}
|
||||
|
||||
if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
|
||||
if (test_bit(HCI_CONN_ENCRYPT_PEND, conn->flags)) {
|
||||
if (!ev->status) {
|
||||
struct hci_cp_set_conn_encrypt cp;
|
||||
cp.handle = ev->handle;
|
||||
|
|
@ -3656,7 +3676,7 @@ static void hci_auth_complete_evt(struct hci_dev *hdev, void *data,
|
|||
hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
|
||||
&cp);
|
||||
} else {
|
||||
clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
|
||||
clear_bit(HCI_CONN_ENCRYPT_PEND, conn->flags);
|
||||
hci_encrypt_cfm(conn, ev->status);
|
||||
}
|
||||
}
|
||||
|
|
@ -3693,10 +3713,10 @@ static void hci_remote_name_evt(struct hci_dev *hdev, void *data,
|
|||
if (!hci_outgoing_auth_needed(hdev, conn))
|
||||
goto unlock;
|
||||
|
||||
if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
|
||||
if (!test_and_set_bit(HCI_CONN_AUTH_PEND, conn->flags)) {
|
||||
struct hci_cp_auth_requested cp;
|
||||
|
||||
set_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags);
|
||||
set_bit(HCI_CONN_AUTH_INITIATOR, conn->flags);
|
||||
|
||||
cp.handle = __cpu_to_le16(conn->handle);
|
||||
hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
|
||||
|
|
@ -3723,17 +3743,17 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, void *data,
|
|||
if (!ev->status) {
|
||||
if (ev->encrypt) {
|
||||
/* Encryption implies authentication */
|
||||
set_bit(HCI_CONN_AUTH, &conn->flags);
|
||||
set_bit(HCI_CONN_ENCRYPT, &conn->flags);
|
||||
set_bit(HCI_CONN_AUTH, conn->flags);
|
||||
set_bit(HCI_CONN_ENCRYPT, conn->flags);
|
||||
conn->sec_level = conn->pending_sec_level;
|
||||
|
||||
/* P-256 authentication key implies FIPS */
|
||||
if (conn->key_type == HCI_LK_AUTH_COMBINATION_P256)
|
||||
set_bit(HCI_CONN_FIPS, &conn->flags);
|
||||
set_bit(HCI_CONN_FIPS, conn->flags);
|
||||
|
||||
if ((conn->type == ACL_LINK && ev->encrypt == 0x02) ||
|
||||
conn->type == LE_LINK)
|
||||
set_bit(HCI_CONN_AES_CCM, &conn->flags);
|
||||
set_bit(HCI_CONN_AES_CCM, conn->flags);
|
||||
|
||||
/* For ACL links the encryption key size is still
|
||||
* validated below via hci_read_enc_key_size(). Its
|
||||
|
|
@ -3745,8 +3765,8 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, void *data,
|
|||
if (conn->type != ACL_LINK)
|
||||
mgmt_security_level_changed(conn);
|
||||
} else {
|
||||
clear_bit(HCI_CONN_ENCRYPT, &conn->flags);
|
||||
clear_bit(HCI_CONN_AES_CCM, &conn->flags);
|
||||
clear_bit(HCI_CONN_ENCRYPT, conn->flags);
|
||||
clear_bit(HCI_CONN_AES_CCM, conn->flags);
|
||||
/* Elevated security levels (MEDIUM and above) require
|
||||
* encryption, so downgrade to reflect the connection
|
||||
* no longer being encrypted before reporting, instead
|
||||
|
|
@ -3767,7 +3787,7 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, void *data,
|
|||
hci_adv_instances_set_rpa_expired(hdev, true);
|
||||
}
|
||||
|
||||
clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
|
||||
clear_bit(HCI_CONN_ENCRYPT_PEND, conn->flags);
|
||||
|
||||
/* Check link security requirements are met */
|
||||
if (!hci_conn_check_link_mode(conn))
|
||||
|
|
@ -3775,7 +3795,7 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, void *data,
|
|||
|
||||
if (ev->status && conn->state == BT_CONNECTED) {
|
||||
if (ev->status == HCI_ERROR_PIN_OR_KEY_MISSING)
|
||||
set_bit(HCI_CONN_AUTH_FAILURE, &conn->flags);
|
||||
set_bit(HCI_CONN_AUTH_FAILURE, conn->flags);
|
||||
|
||||
/* Notify upper layers so they can cleanup before
|
||||
* disconnecting.
|
||||
|
|
@ -3813,8 +3833,8 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, void *data,
|
|||
* type can be either LE or ACL and controller must support LMP Ping.
|
||||
* Ensure for AES-CCM encryption as well.
|
||||
*/
|
||||
if (test_bit(HCI_CONN_ENCRYPT, &conn->flags) &&
|
||||
test_bit(HCI_CONN_AES_CCM, &conn->flags) &&
|
||||
if (test_bit(HCI_CONN_ENCRYPT, conn->flags) &&
|
||||
test_bit(HCI_CONN_AES_CCM, conn->flags) &&
|
||||
((conn->type == ACL_LINK && lmp_ping_capable(hdev)) ||
|
||||
(conn->type == LE_LINK && (hdev->le_features[0] & HCI_LE_PING)))) {
|
||||
struct hci_cp_write_auth_payload_to cp;
|
||||
|
|
@ -3846,9 +3866,9 @@ static void hci_change_link_key_complete_evt(struct hci_dev *hdev, void *data,
|
|||
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
|
||||
if (conn) {
|
||||
if (!ev->status)
|
||||
set_bit(HCI_CONN_SECURE, &conn->flags);
|
||||
set_bit(HCI_CONN_SECURE, conn->flags);
|
||||
|
||||
clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
|
||||
clear_bit(HCI_CONN_AUTH_PEND, conn->flags);
|
||||
|
||||
hci_key_change_cfm(conn, ev->status);
|
||||
}
|
||||
|
|
@ -3975,13 +3995,16 @@ static u8 hci_cc_le_set_cig_params(struct hci_dev *hdev, void *data,
|
|||
struct hci_conn *conn;
|
||||
u8 status = rp->status;
|
||||
bool pending = false;
|
||||
size_t len;
|
||||
int i;
|
||||
|
||||
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
|
||||
|
||||
cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_CIG_PARAMS);
|
||||
cp = hci_sent_cmd_data_len(hdev, HCI_OP_LE_SET_CIG_PARAMS, &len);
|
||||
if (!rp->status &&
|
||||
(!cp || rp->num_handles != cp->num_cis ||
|
||||
(!cp || len < sizeof(*cp) ||
|
||||
len < struct_size(cp, cis, cp->num_cis) ||
|
||||
rp->num_handles != cp->num_cis ||
|
||||
rp->cig_id != cp->cig_id ||
|
||||
skb->len < array_size(rp->num_handles, sizeof(*rp->handle)))) {
|
||||
bt_dev_err(hdev, "unexpected Set CIG Parameters response data");
|
||||
|
|
@ -4074,7 +4097,7 @@ static u8 hci_cc_le_setup_iso_path(struct hci_dev *hdev, void *data,
|
|||
hci_connect_cfm(conn, rp->status);
|
||||
|
||||
/* Notify device connected in case it is a BIG Sync */
|
||||
if (!rp->status && test_bit(HCI_CONN_BIG_SYNC, &conn->flags))
|
||||
if (!rp->status && test_bit(HCI_CONN_BIG_SYNC, conn->flags))
|
||||
mgmt_device_connected(hdev, conn, NULL, 0);
|
||||
|
||||
break;
|
||||
|
|
@ -4481,6 +4504,7 @@ static void hci_cs_le_create_cis(struct hci_dev *hdev, u8 status)
|
|||
{
|
||||
struct hci_cp_le_create_cis *cp;
|
||||
bool pending = false;
|
||||
size_t len;
|
||||
int i;
|
||||
|
||||
bt_dev_dbg(hdev, "status 0x%2.2x", status);
|
||||
|
|
@ -4488,10 +4512,14 @@ static void hci_cs_le_create_cis(struct hci_dev *hdev, u8 status)
|
|||
if (!status)
|
||||
return;
|
||||
|
||||
cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CIS);
|
||||
cp = hci_sent_cmd_data_len(hdev, HCI_OP_LE_CREATE_CIS, &len);
|
||||
if (!cp)
|
||||
return;
|
||||
|
||||
if (len < sizeof(*cp) ||
|
||||
len < struct_size(cp, cis, cp->num_cis))
|
||||
return;
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
/* Remove connection if command failed */
|
||||
|
|
@ -4504,7 +4532,7 @@ static void hci_cs_le_create_cis(struct hci_dev *hdev, u8 status)
|
|||
conn = hci_conn_hash_lookup_handle(hdev, handle);
|
||||
if (conn) {
|
||||
if (test_and_clear_bit(HCI_CONN_CREATE_CIS,
|
||||
&conn->flags))
|
||||
conn->flags))
|
||||
pending = true;
|
||||
conn->state = BT_CLOSED;
|
||||
hci_connect_cfm(conn, status);
|
||||
|
|
@ -4625,7 +4653,7 @@ static void hci_role_change_evt(struct hci_dev *hdev, void *data,
|
|||
if (!ev->status)
|
||||
conn->role = ev->role;
|
||||
|
||||
clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
|
||||
clear_bit(HCI_CONN_RSWITCH_PEND, conn->flags);
|
||||
|
||||
hci_role_switch_cfm(conn, ev->status, ev->role);
|
||||
}
|
||||
|
|
@ -4737,12 +4765,12 @@ static void hci_mode_change_evt(struct hci_dev *hdev, void *data,
|
|||
conn->mode = ev->mode;
|
||||
|
||||
if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
|
||||
&conn->flags)) {
|
||||
assign_bit(HCI_CONN_POWER_SAVE, &conn->flags,
|
||||
conn->flags)) {
|
||||
assign_bit(HCI_CONN_POWER_SAVE, conn->flags,
|
||||
conn->mode == HCI_CM_ACTIVE);
|
||||
}
|
||||
|
||||
if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
|
||||
if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, conn->flags))
|
||||
hci_sco_setup(conn, ev->status);
|
||||
}
|
||||
|
||||
|
|
@ -4770,7 +4798,7 @@ static void hci_pin_code_request_evt(struct hci_dev *hdev, void *data,
|
|||
}
|
||||
|
||||
if (!hci_dev_test_flag(hdev, HCI_BONDABLE) &&
|
||||
!test_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags)) {
|
||||
!test_bit(HCI_CONN_AUTH_INITIATOR, conn->flags)) {
|
||||
hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
|
||||
sizeof(ev->bdaddr), &ev->bdaddr);
|
||||
} else if (hci_dev_test_flag(hdev, HCI_MGMT)) {
|
||||
|
|
@ -4845,7 +4873,7 @@ static void hci_link_key_request_evt(struct hci_dev *hdev, void *data,
|
|||
|
||||
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
|
||||
if (conn) {
|
||||
clear_bit(HCI_CONN_NEW_LINK_KEY, &conn->flags);
|
||||
clear_bit(HCI_CONN_NEW_LINK_KEY, conn->flags);
|
||||
|
||||
if ((key->type == HCI_LK_UNAUTH_COMBINATION_P192 ||
|
||||
key->type == HCI_LK_UNAUTH_COMBINATION_P256) &&
|
||||
|
|
@ -4908,7 +4936,7 @@ static void hci_link_key_notify_evt(struct hci_dev *hdev, void *data,
|
|||
conn->disc_timeout = HCI_DISCONN_TIMEOUT;
|
||||
hci_conn_drop(conn);
|
||||
|
||||
set_bit(HCI_CONN_NEW_LINK_KEY, &conn->flags);
|
||||
set_bit(HCI_CONN_NEW_LINK_KEY, conn->flags);
|
||||
conn_set_key(conn, ev->key_type, conn->pin_length);
|
||||
|
||||
if (!hci_dev_test_flag(hdev, HCI_MGMT))
|
||||
|
|
@ -4939,7 +4967,7 @@ static void hci_link_key_notify_evt(struct hci_dev *hdev, void *data,
|
|||
goto unlock;
|
||||
}
|
||||
|
||||
assign_bit(HCI_CONN_FLUSH_KEY, &conn->flags, !persistent);
|
||||
assign_bit(HCI_CONN_FLUSH_KEY, conn->flags, !persistent);
|
||||
|
||||
unlock:
|
||||
hci_dev_unlock(hdev);
|
||||
|
|
@ -5117,7 +5145,7 @@ static void hci_remote_ext_features_evt(struct hci_dev *hdev, void *data,
|
|||
ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
|
||||
|
||||
if (ev->features[0] & LMP_HOST_SSP) {
|
||||
set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
|
||||
set_bit(HCI_CONN_SSP_ENABLED, conn->flags);
|
||||
} else {
|
||||
/* It is mandatory by the Bluetooth specification that
|
||||
* Extended Inquiry Results are only used when Secure
|
||||
|
|
@ -5127,17 +5155,17 @@ static void hci_remote_ext_features_evt(struct hci_dev *hdev, void *data,
|
|||
* To make these devices work, the internal SSP
|
||||
* enabled flag needs to be cleared if the remote host
|
||||
* features do not indicate SSP support */
|
||||
clear_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
|
||||
clear_bit(HCI_CONN_SSP_ENABLED, conn->flags);
|
||||
}
|
||||
|
||||
if (ev->features[0] & LMP_HOST_SC)
|
||||
set_bit(HCI_CONN_SC_ENABLED, &conn->flags);
|
||||
set_bit(HCI_CONN_SC_ENABLED, conn->flags);
|
||||
}
|
||||
|
||||
if (conn->state != BT_CONFIG)
|
||||
goto unlock;
|
||||
|
||||
if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
|
||||
if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, conn->flags)) {
|
||||
struct hci_cp_remote_name_req cp;
|
||||
memset(&cp, 0, sizeof(cp));
|
||||
bacpy(&cp.bdaddr, &conn->dst);
|
||||
|
|
@ -5373,7 +5401,7 @@ static void hci_key_refresh_complete_evt(struct hci_dev *hdev, void *data,
|
|||
mgmt_security_level_changed(conn);
|
||||
}
|
||||
|
||||
clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
|
||||
clear_bit(HCI_CONN_ENCRYPT_PEND, conn->flags);
|
||||
|
||||
if (ev->status && conn->state == BT_CONNECTED) {
|
||||
hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
|
||||
|
|
@ -5474,7 +5502,7 @@ static void hci_io_capa_request_evt(struct hci_dev *hdev, void *data,
|
|||
goto unlock;
|
||||
|
||||
/* Assume remote supports SSP since it has triggered this event */
|
||||
set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
|
||||
set_bit(HCI_CONN_SSP_ENABLED, conn->flags);
|
||||
|
||||
hci_conn_hold(conn);
|
||||
|
||||
|
|
@ -5485,7 +5513,7 @@ static void hci_io_capa_request_evt(struct hci_dev *hdev, void *data,
|
|||
* pairing or if the remote is not requesting bonding.
|
||||
*/
|
||||
if (hci_dev_test_flag(hdev, HCI_BONDABLE) ||
|
||||
test_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags) ||
|
||||
test_bit(HCI_CONN_AUTH_INITIATOR, conn->flags) ||
|
||||
(conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
|
||||
struct hci_cp_io_capability_reply cp;
|
||||
|
||||
|
|
@ -5595,7 +5623,7 @@ static void hci_user_confirm_request_evt(struct hci_dev *hdev, void *data,
|
|||
* local IO capability is not NoInputNoOutput, use JUST_WORKS
|
||||
* method (mgmt_user_confirm with confirm_hint set to 1).
|
||||
*/
|
||||
if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) &&
|
||||
if (!test_bit(HCI_CONN_AUTH_PEND, conn->flags) &&
|
||||
conn->io_capability != HCI_IO_NO_INPUT_OUTPUT) {
|
||||
bt_dev_dbg(hdev, "Confirming auto-accept as acceptor");
|
||||
confirm_hint = 1;
|
||||
|
|
@ -5738,7 +5766,7 @@ static void hci_simple_pair_complete_evt(struct hci_dev *hdev, void *data,
|
|||
* initiated the authentication. A traditional auth_complete
|
||||
* 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)
|
||||
if (!test_bit(HCI_CONN_AUTH_PEND, conn->flags) && ev->status)
|
||||
mgmt_auth_failed(conn, ev->status);
|
||||
|
||||
hci_conn_drop(conn);
|
||||
|
|
@ -5984,7 +6012,7 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
|
|||
goto unlock;
|
||||
|
||||
/* Drop the connection if it has been aborted */
|
||||
if (test_bit(HCI_CONN_CANCEL, &conn->flags)) {
|
||||
if (test_bit(HCI_CONN_CANCEL, conn->flags)) {
|
||||
hci_conn_drop(conn);
|
||||
goto unlock;
|
||||
}
|
||||
|
|
@ -6041,6 +6069,28 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
|
|||
hci_conn_put(params->conn);
|
||||
params->conn = NULL;
|
||||
}
|
||||
|
||||
/* An explicit connect request is complete once connected, so
|
||||
* clean it up here: hci_connect_le_scan_cleanup() no longer
|
||||
* finds the params since they have just been removed from
|
||||
* pend_le_conns.
|
||||
*/
|
||||
if (params->explicit_connect) {
|
||||
params->explicit_connect = false;
|
||||
|
||||
switch (params->auto_connect) {
|
||||
case HCI_AUTO_CONN_EXPLICIT:
|
||||
hci_conn_params_del(hdev, &conn->dst,
|
||||
conn->dst_type);
|
||||
break;
|
||||
case HCI_AUTO_CONN_REPORT:
|
||||
hci_pend_le_list_add(params,
|
||||
&hdev->pend_le_reports);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If we are central and have subrate parameters stored, queue a
|
||||
|
|
@ -6101,8 +6151,8 @@ static void hci_le_pa_sync_lost_evt(struct hci_dev *hdev, void *data,
|
|||
/* Delete the pa sync connection */
|
||||
conn = hci_conn_hash_lookup_pa_sync_handle(hdev, handle);
|
||||
if (conn) {
|
||||
clear_bit(HCI_CONN_BIG_SYNC, &conn->flags);
|
||||
clear_bit(HCI_CONN_PA_SYNC, &conn->flags);
|
||||
clear_bit(HCI_CONN_BIG_SYNC, conn->flags);
|
||||
clear_bit(HCI_CONN_PA_SYNC, conn->flags);
|
||||
hci_disconn_cfm(conn, HCI_ERROR_REMOTE_USER_TERM);
|
||||
hci_conn_del(conn);
|
||||
}
|
||||
|
|
@ -6236,7 +6286,7 @@ static void hci_le_past_received_evt(struct hci_dev *hdev, void *data,
|
|||
pa_sync->sync_handle = le16_to_cpu(ev->sync_handle);
|
||||
|
||||
if (ev->status) {
|
||||
set_bit(HCI_CONN_PA_SYNC_FAILED, &pa_sync->flags);
|
||||
set_bit(HCI_CONN_PA_SYNC_FAILED, pa_sync->flags);
|
||||
|
||||
/* Notify iso layer */
|
||||
hci_connect_cfm(pa_sync, ev->status);
|
||||
|
|
@ -6758,7 +6808,7 @@ static void hci_le_pa_sync_established_evt(struct hci_dev *hdev, void *data,
|
|||
goto unlock;
|
||||
}
|
||||
|
||||
clear_bit(HCI_CONN_CREATE_PA_SYNC, &conn->flags);
|
||||
clear_bit(HCI_CONN_CREATE_PA_SYNC, conn->flags);
|
||||
|
||||
conn->sync_handle = le16_to_cpu(ev->handle);
|
||||
conn->sid = HCI_SID_INVALID;
|
||||
|
|
@ -6783,7 +6833,7 @@ static void hci_le_pa_sync_established_evt(struct hci_dev *hdev, void *data,
|
|||
pa_sync->sync_handle = le16_to_cpu(ev->handle);
|
||||
|
||||
if (ev->status) {
|
||||
set_bit(HCI_CONN_PA_SYNC_FAILED, &pa_sync->flags);
|
||||
set_bit(HCI_CONN_PA_SYNC_FAILED, pa_sync->flags);
|
||||
|
||||
/* Notify iso layer */
|
||||
hci_connect_cfm(pa_sync, ev->status);
|
||||
|
|
@ -6827,7 +6877,7 @@ static void hci_le_per_adv_report_evt(struct hci_dev *hdev, void *data,
|
|||
goto unlock;
|
||||
|
||||
if (ev->data_status == LE_PA_DATA_COMPLETE &&
|
||||
!test_and_set_bit(HCI_CONN_PA_SYNC, &pa_sync->flags)) {
|
||||
!test_and_set_bit(HCI_CONN_PA_SYNC, pa_sync->flags)) {
|
||||
/* Notify iso layer */
|
||||
hci_connect_cfm(pa_sync, 0);
|
||||
|
||||
|
|
@ -6940,11 +6990,11 @@ static void hci_le_ltk_request_evt(struct hci_dev *hdev, void *data,
|
|||
* using a distributed LTK.
|
||||
*/
|
||||
if (ltk->type == SMP_STK) {
|
||||
set_bit(HCI_CONN_STK_ENCRYPT, &conn->flags);
|
||||
set_bit(HCI_CONN_STK_ENCRYPT, conn->flags);
|
||||
list_del_rcu(<k->list);
|
||||
kfree_rcu(ltk, rcu);
|
||||
} else {
|
||||
clear_bit(HCI_CONN_STK_ENCRYPT, &conn->flags);
|
||||
clear_bit(HCI_CONN_STK_ENCRYPT, conn->flags);
|
||||
}
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
|
|
@ -7140,7 +7190,7 @@ static void hci_le_cis_established_evt(struct hci_dev *hdev, void *data,
|
|||
|
||||
qos = &conn->iso_qos;
|
||||
|
||||
pending = test_and_clear_bit(HCI_CONN_CREATE_CIS, &conn->flags);
|
||||
pending = test_and_clear_bit(HCI_CONN_CREATE_CIS, conn->flags);
|
||||
|
||||
/* BLUETOOTH CORE SPECIFICATION Version 5.4 | Vol 6, Part G
|
||||
* page 3075:
|
||||
|
|
@ -7337,7 +7387,7 @@ static void hci_le_create_big_complete_evt(struct hci_dev *hdev, void *data,
|
|||
}
|
||||
|
||||
conn->state = BT_CONNECTED;
|
||||
set_bit(HCI_CONN_BIG_CREATED, &conn->flags);
|
||||
set_bit(HCI_CONN_BIG_CREATED, conn->flags);
|
||||
hci_debugfs_create_conn(conn);
|
||||
hci_conn_add_sysfs(conn);
|
||||
hci_iso_setup_path(conn);
|
||||
|
|
@ -7382,7 +7432,7 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data,
|
|||
goto unlock;
|
||||
}
|
||||
|
||||
clear_bit(HCI_CONN_CREATE_BIG_SYNC, &conn->flags);
|
||||
clear_bit(HCI_CONN_CREATE_BIG_SYNC, conn->flags);
|
||||
|
||||
conn->num_bis = 0;
|
||||
memset(conn->bis, 0, sizeof(conn->bis));
|
||||
|
|
@ -7405,7 +7455,7 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data,
|
|||
|
||||
if (ev->status != 0x42)
|
||||
/* Mark PA sync as established */
|
||||
set_bit(HCI_CONN_PA_SYNC, &bis->flags);
|
||||
set_bit(HCI_CONN_PA_SYNC, bis->flags);
|
||||
|
||||
bis->sync_handle = conn->sync_handle;
|
||||
bis->iso_qos.bcast.big = ev->handle;
|
||||
|
|
@ -7418,7 +7468,7 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data,
|
|||
|
||||
if (!ev->status) {
|
||||
bis->state = BT_CONNECTED;
|
||||
set_bit(HCI_CONN_BIG_SYNC, &bis->flags);
|
||||
set_bit(HCI_CONN_BIG_SYNC, bis->flags);
|
||||
hci_debugfs_create_conn(bis);
|
||||
hci_conn_add_sysfs(bis);
|
||||
hci_iso_setup_path(bis);
|
||||
|
|
@ -7436,7 +7486,7 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data,
|
|||
if (!bis)
|
||||
continue;
|
||||
|
||||
set_bit(HCI_CONN_BIG_SYNC_FAILED, &bis->flags);
|
||||
set_bit(HCI_CONN_BIG_SYNC_FAILED, bis->flags);
|
||||
hci_connect_cfm(bis, ev->status);
|
||||
}
|
||||
|
||||
|
|
@ -7466,13 +7516,13 @@ static void hci_le_big_sync_lost_evt(struct hci_dev *hdev, void *data,
|
|||
* it is consumed there instead of here.
|
||||
*/
|
||||
mgmt_conn = test_bit(HCI_CONN_MGMT_CONNECTED,
|
||||
&bis->flags);
|
||||
bis->flags);
|
||||
mgmt_device_disconnected(hdev, &bis->dst, bis->type,
|
||||
bis->dst_type, ev->reason,
|
||||
mgmt_conn);
|
||||
}
|
||||
|
||||
clear_bit(HCI_CONN_BIG_SYNC, &bis->flags);
|
||||
clear_bit(HCI_CONN_BIG_SYNC, bis->flags);
|
||||
hci_disconn_cfm(bis, ev->reason);
|
||||
hci_conn_del(bis);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -376,8 +376,18 @@ static void le_scan_disable(struct work_struct *work)
|
|||
bt_dev_dbg(hdev, "");
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
if (!hci_dev_test_flag(hdev, HCI_LE_SCAN))
|
||||
if (!hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
|
||||
/* The scan of a discovery can be disabled while this work
|
||||
* waits for the lock, for example by a Stop Discovery that
|
||||
* timed out and still completed, so end the discovery as
|
||||
* le_set_scan_enable_complete() does when it cancels this
|
||||
* work.
|
||||
*/
|
||||
if (hdev->discovery.state == DISCOVERY_FINDING)
|
||||
goto discov_stopped;
|
||||
|
||||
goto _return;
|
||||
}
|
||||
|
||||
status = hci_cmd_sync_queue(hdev, scan_disable_sync, NULL, NULL);
|
||||
if (status) {
|
||||
|
|
@ -2448,15 +2458,17 @@ static int hci_le_del_resolve_list_sync(struct hci_dev *hdev,
|
|||
bdaddr_t *bdaddr, u8 bdaddr_type)
|
||||
{
|
||||
struct hci_cp_le_del_from_resolv_list cp;
|
||||
struct bdaddr_list_with_irk *entry;
|
||||
bool exists;
|
||||
|
||||
if (!ll_privacy_capable(hdev))
|
||||
return 0;
|
||||
|
||||
/* Check if the IRK has been programmed */
|
||||
entry = hci_bdaddr_list_lookup_with_irk(&hdev->le_resolv_list, bdaddr,
|
||||
bdaddr_type);
|
||||
if (!entry)
|
||||
hci_dev_lock(hdev);
|
||||
exists = hci_bdaddr_list_lookup_with_irk(&hdev->le_resolv_list,
|
||||
bdaddr, bdaddr_type);
|
||||
hci_dev_unlock(hdev);
|
||||
if (!exists)
|
||||
return 0;
|
||||
|
||||
cp.bdaddr_type = bdaddr_type;
|
||||
|
|
@ -2512,8 +2524,8 @@ static int hci_le_add_resolve_list_sync(struct hci_dev *hdev,
|
|||
{
|
||||
struct hci_cp_le_add_to_resolv_list cp;
|
||||
struct smp_irk *irk;
|
||||
struct bdaddr_list_with_irk *entry;
|
||||
struct hci_conn_params *p;
|
||||
bool exists;
|
||||
|
||||
if (!ll_privacy_capable(hdev))
|
||||
return 0;
|
||||
|
|
@ -2531,20 +2543,28 @@ static int hci_le_add_resolve_list_sync(struct hci_dev *hdev,
|
|||
} else if (!(params->flags & HCI_CONN_FLAG_ADDRESS_RESOLUTION))
|
||||
return 0;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
irk = hci_find_irk_by_addr(hdev, ¶ms->addr, params->addr_type);
|
||||
if (!irk)
|
||||
if (!irk) {
|
||||
rcu_read_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(cp.peer_irk, irk->val, 16);
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
/* Check if the IK has _not_ been programmed yet. */
|
||||
entry = hci_bdaddr_list_lookup_with_irk(&hdev->le_resolv_list,
|
||||
¶ms->addr,
|
||||
params->addr_type);
|
||||
if (entry)
|
||||
hci_dev_lock(hdev);
|
||||
exists = hci_bdaddr_list_lookup_with_irk(
|
||||
&hdev->le_resolv_list, ¶ms->addr, params->addr_type);
|
||||
hci_dev_unlock(hdev);
|
||||
if (exists)
|
||||
return 0;
|
||||
|
||||
cp.bdaddr_type = params->addr_type;
|
||||
bacpy(&cp.bdaddr, ¶ms->addr);
|
||||
memcpy(cp.peer_irk, irk->val, 16);
|
||||
|
||||
/* Default privacy mode is always Network */
|
||||
params->privacy_mode = HCI_NETWORK_PRIVACY;
|
||||
|
|
@ -2733,7 +2753,7 @@ static int hci_pause_advertising_sync(struct hci_dev *hdev)
|
|||
static int hci_resume_advertising_sync(struct hci_dev *hdev)
|
||||
{
|
||||
struct adv_info *adv, *tmp;
|
||||
int err;
|
||||
int err = 0;
|
||||
|
||||
/* If advertising has not been paused there is nothing to do. */
|
||||
if (!hdev->advertising_paused)
|
||||
|
|
@ -2766,13 +2786,19 @@ static int hci_resume_advertising_sync(struct hci_dev *hdev)
|
|||
*/
|
||||
if (hci_dev_test_and_clear_flag(hdev, HCI_LE_ADV_0))
|
||||
err = hci_enable_ext_advertising_sync(hdev, 0x00);
|
||||
} else {
|
||||
} else if (hdev->cur_adv_instance) {
|
||||
/* Schedule for most recent instance to be restarted and begin
|
||||
* the software rotation loop
|
||||
*/
|
||||
err = hci_schedule_adv_instance_sync(hdev,
|
||||
hdev->cur_adv_instance,
|
||||
true);
|
||||
} else if (hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
|
||||
!hci_dev_test_flag(hdev, HCI_LE_ADV)) {
|
||||
/* hci_schedule_adv_instance_sync() rejects instance 0x00 while
|
||||
* HCI_ADVERTISING is set, so enable it directly.
|
||||
*/
|
||||
err = hci_start_adv_sync(hdev, 0x00);
|
||||
}
|
||||
|
||||
hdev->advertising_paused = false;
|
||||
|
|
@ -2879,6 +2905,31 @@ static struct conn_params *conn_params_copy(struct list_head *list, size_t *n)
|
|||
return p;
|
||||
}
|
||||
|
||||
static struct conn_params *le_accept_list_copy(struct hci_dev *hdev,
|
||||
size_t *n)
|
||||
{
|
||||
struct bdaddr_list *entry;
|
||||
struct conn_params *params;
|
||||
size_t i = 0;
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
*n = list_count_nodes(&hdev->le_accept_list);
|
||||
params = kvzalloc_objs(struct conn_params, *n);
|
||||
if (!params)
|
||||
goto unlock;
|
||||
|
||||
list_for_each_entry(entry, &hdev->le_accept_list, list) {
|
||||
bacpy(¶ms[i].addr, &entry->bdaddr);
|
||||
params[i].addr_type = entry->bdaddr_type;
|
||||
i++;
|
||||
}
|
||||
|
||||
unlock:
|
||||
hci_dev_unlock(hdev);
|
||||
return params;
|
||||
}
|
||||
|
||||
/* Clear LE Accept List */
|
||||
static int hci_le_clear_accept_list_sync(struct hci_dev *hdev)
|
||||
{
|
||||
|
|
@ -2909,7 +2960,6 @@ static int hci_le_clear_accept_list_sync(struct hci_dev *hdev)
|
|||
static u8 hci_update_accept_list_sync(struct hci_dev *hdev)
|
||||
{
|
||||
struct conn_params *params;
|
||||
struct bdaddr_list *b, *t;
|
||||
u8 num_entries = 0;
|
||||
bool pend_conn, pend_report;
|
||||
u8 filter_policy;
|
||||
|
|
@ -2974,20 +3024,27 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev)
|
|||
* report. If not present in either list, then remove it from
|
||||
* the controller.
|
||||
*/
|
||||
list_for_each_entry_safe(b, t, &hdev->le_accept_list, list) {
|
||||
params = le_accept_list_copy(hdev, &n);
|
||||
if (!params) {
|
||||
err = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
rcu_read_lock();
|
||||
|
||||
if (hci_conn_hash_lookup_le(hdev, &b->bdaddr, b->bdaddr_type)) {
|
||||
if (hci_conn_hash_lookup_le(hdev, ¶ms[i].addr,
|
||||
params[i].addr_type)) {
|
||||
rcu_read_unlock();
|
||||
continue;
|
||||
}
|
||||
|
||||
pend_conn = hci_pend_le_action_lookup(&hdev->pend_le_conns,
|
||||
&b->bdaddr,
|
||||
b->bdaddr_type);
|
||||
pend_report = hci_pend_le_action_lookup(&hdev->pend_le_reports,
|
||||
&b->bdaddr,
|
||||
b->bdaddr_type);
|
||||
¶ms[i].addr,
|
||||
params[i].addr_type);
|
||||
pend_report = hci_pend_le_action_lookup(
|
||||
&hdev->pend_le_reports, ¶ms[i].addr,
|
||||
params[i].addr_type);
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
|
|
@ -2995,14 +3052,16 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev)
|
|||
* remove it from the acceptlist.
|
||||
*/
|
||||
if (!pend_conn && !pend_report) {
|
||||
hci_le_del_accept_list_sync(hdev, &b->bdaddr,
|
||||
b->bdaddr_type);
|
||||
hci_le_del_accept_list_sync(hdev, ¶ms[i].addr,
|
||||
params[i].addr_type);
|
||||
continue;
|
||||
}
|
||||
|
||||
num_entries++;
|
||||
}
|
||||
|
||||
kvfree(params);
|
||||
|
||||
/* Since all no longer valid accept list entries have been
|
||||
* removed, walk through the list of pending connections
|
||||
* and ensure that any new device gets programmed into
|
||||
|
|
@ -3505,9 +3564,13 @@ int hci_write_ssp_mode_sync(struct hci_dev *hdev, u8 mode)
|
|||
return hci_write_sc_support_sync(hdev, 0x01);
|
||||
}
|
||||
|
||||
static int hci_le_set_host_feature_sync(struct hci_dev *hdev, u16 bit,
|
||||
u8 value);
|
||||
|
||||
int hci_write_le_host_supported_sync(struct hci_dev *hdev, u8 le, u8 simul)
|
||||
{
|
||||
struct hci_cp_write_le_host_supported cp;
|
||||
int err;
|
||||
|
||||
if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) ||
|
||||
!lmp_bredr_capable(hdev))
|
||||
|
|
@ -3525,8 +3588,16 @@ int hci_write_le_host_supported_sync(struct hci_dev *hdev, u8 le, u8 simul)
|
|||
cp.le = le;
|
||||
cp.simul = simul;
|
||||
|
||||
return __hci_cmd_sync_status(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED,
|
||||
sizeof(cp), &cp, HCI_CMD_TIMEOUT);
|
||||
err = __hci_cmd_sync_status(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED,
|
||||
sizeof(cp), &cp, HCI_CMD_TIMEOUT);
|
||||
if (err || !cis_capable(hdev))
|
||||
return err;
|
||||
|
||||
/* The CIS host feature is set during init based on LE being enabled,
|
||||
* which is not repeated when LE is enabled afterwards, e.g. while the
|
||||
* controller is still auto powered on, so update it here.
|
||||
*/
|
||||
return hci_le_set_host_feature_sync(hdev, 32, iso_enabled(hdev));
|
||||
}
|
||||
|
||||
static int hci_powered_update_adv_sync(struct hci_dev *hdev)
|
||||
|
|
@ -4828,6 +4899,9 @@ static int hci_le_set_def_rate_sync(struct hci_dev *hdev)
|
|||
struct hci_cp_le_set_def_rate cp;
|
||||
u16 interval_min = 0x000a; /* 1.25 ms */
|
||||
u16 interval_max = 0x0078; /* 15 ms */
|
||||
u16 subrate_max = 0x0004;
|
||||
u16 max_latency = 0x0000;
|
||||
u32 supv_timeout;
|
||||
|
||||
if (!le_sci_capable(hdev))
|
||||
return 0;
|
||||
|
|
@ -4852,10 +4926,31 @@ static int hci_le_set_def_rate_sync(struct hci_dev *hdev)
|
|||
cp.interval_min = cpu_to_le16(interval_min);
|
||||
cp.interval_max = cpu_to_le16(interval_max);
|
||||
cp.subrate_min = cpu_to_le16(0x0001);
|
||||
cp.subrate_max = cpu_to_le16(0x0004);
|
||||
cp.max_latency = cpu_to_le16(0x0000);
|
||||
cp.subrate_max = cpu_to_le16(subrate_max);
|
||||
cp.max_latency = cpu_to_le16(max_latency);
|
||||
cp.cont_num = cpu_to_le16(0x0001);
|
||||
cp.supv_timeout = cpu_to_le16(0x000c); /* 120 ms */
|
||||
|
||||
/* HOGP v1.2 recommends a Supervision_Timeout greater than or equal to
|
||||
* (1 + Max_Latency) x Subrate_Max x Connection_Interval_Max x 2, but
|
||||
* the Core spec treats the equality as invalid:
|
||||
*
|
||||
* BLUETOOTH CORE SPECIFICATION Version 6.3 | Vol 4, Part E
|
||||
* 7.8.158. LE Set Default Rate Parameters command
|
||||
*
|
||||
* If Connection_Interval_Max x Subrate_Max x (Max_Latency + 1) is
|
||||
* greater than or equal to Supervision_Timeout x 40, the Controller
|
||||
* shall return the error code Invalid HCI Command Parameters (0x12).
|
||||
*
|
||||
* So default to 2 s, 10x lower than the 20 s used for non-SCI
|
||||
* connections while still well above the minimum required, but make
|
||||
* sure it stays strictly above the minimum in case interval_max has
|
||||
* been raised.
|
||||
*/
|
||||
supv_timeout = (u32)interval_max * subrate_max * (max_latency + 1);
|
||||
supv_timeout = supv_timeout / 40 + 1;
|
||||
supv_timeout = clamp_t(u32, max_t(u32, supv_timeout, 0x00c8),
|
||||
0x000a, 0x0c80);
|
||||
cp.supv_timeout = cpu_to_le16(supv_timeout);
|
||||
|
||||
/* The connection event length recommended in requests by a Peripheral
|
||||
* uses units of 125 us with a valid range of 0x0001 to 0x7CFF
|
||||
|
|
@ -5637,6 +5732,11 @@ int hci_dev_close_sync(struct hci_dev *hdev)
|
|||
return err;
|
||||
}
|
||||
|
||||
/* Wait for hci_recv_frame() callers that still saw HCI_UP, so that
|
||||
* none of them queues rx_work while the workqueue is drained below.
|
||||
*/
|
||||
synchronize_rcu();
|
||||
|
||||
hci_leds_update_powered(hdev, false);
|
||||
|
||||
/* Flush RX and TX works */
|
||||
|
|
@ -5830,11 +5930,15 @@ int hci_stop_discovery_sync(struct hci_dev *hdev)
|
|||
}
|
||||
|
||||
if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
|
||||
cancel_delayed_work(&hdev->le_scan_disable);
|
||||
|
||||
err = hci_scan_disable_sync(hdev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Only cancel the LE scan timeout once the scan is
|
||||
* disabled, so that the discovery still ends if
|
||||
* stopping it failed.
|
||||
*/
|
||||
cancel_delayed_work(&hdev->le_scan_disable);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
|
@ -5913,11 +6017,11 @@ static int hci_le_connect_cancel_sync(struct hci_dev *hdev,
|
|||
/* Return reason if scanning since the connection shall probably be
|
||||
* cleanup directly.
|
||||
*/
|
||||
if (test_bit(HCI_CONN_SCANNING, &conn->flags))
|
||||
if (test_bit(HCI_CONN_SCANNING, conn->flags))
|
||||
return reason;
|
||||
|
||||
if (conn->role == HCI_ROLE_SLAVE ||
|
||||
test_and_set_bit(HCI_CONN_CANCEL, &conn->flags))
|
||||
test_and_set_bit(HCI_CONN_CANCEL, conn->flags))
|
||||
return 0;
|
||||
|
||||
return __hci_cmd_sync_status(hdev, HCI_OP_LE_CREATE_CONN_CANCEL,
|
||||
|
|
@ -5939,7 +6043,7 @@ static int hci_connect_cancel_sync(struct hci_dev *hdev, struct hci_conn *conn,
|
|||
* then an HCI_LE_CIS_Established event shall also be sent for
|
||||
* this CIS with the Status Operation Cancelled by Host (0x44).
|
||||
*/
|
||||
if (test_bit(HCI_CONN_CREATE_CIS, &conn->flags))
|
||||
if (test_bit(HCI_CONN_CREATE_CIS, conn->flags))
|
||||
return hci_disconnect_sync(hdev, conn, reason);
|
||||
|
||||
/* CIS with no Create CIS sent have nothing to cancel */
|
||||
|
|
@ -6310,6 +6414,7 @@ static int hci_active_scan_sync(struct hci_dev *hdev, uint16_t interval)
|
|||
u8 filter_policy = 0x00;
|
||||
/* Default is to enable duplicates filter */
|
||||
u8 filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
|
||||
bool paused;
|
||||
int err;
|
||||
|
||||
bt_dev_dbg(hdev, "");
|
||||
|
|
@ -6333,6 +6438,12 @@ static int hci_active_scan_sync(struct hci_dev *hdev, uint16_t interval)
|
|||
if (err)
|
||||
goto failed;
|
||||
|
||||
/* LE Set Random Address is disallowed while advertising is enabled. */
|
||||
paused = !hdev->advertising_paused;
|
||||
err = hci_pause_advertising_sync(hdev);
|
||||
if (err)
|
||||
goto failed;
|
||||
|
||||
/* All active scans will be done with either a resolvable private
|
||||
* address (when privacy feature has been enabled) or non-resolvable
|
||||
* private address.
|
||||
|
|
@ -6342,6 +6453,9 @@ static int hci_active_scan_sync(struct hci_dev *hdev, uint16_t interval)
|
|||
if (err < 0)
|
||||
own_addr_type = ADDR_LE_DEV_PUBLIC;
|
||||
|
||||
if (paused)
|
||||
hci_resume_advertising_sync(hdev);
|
||||
|
||||
if (hci_is_adv_monitoring(hdev) ||
|
||||
(hci_test_quirk(hdev, HCI_QUIRK_STRICT_DUPLICATE_FILTER) &&
|
||||
hdev->discovery.result_filtering)) {
|
||||
|
|
@ -6365,9 +6479,8 @@ static int hci_active_scan_sync(struct hci_dev *hdev, uint16_t interval)
|
|||
return err;
|
||||
|
||||
failed:
|
||||
/* Resume advertising if it was paused */
|
||||
if (ll_privacy_capable(hdev))
|
||||
hci_resume_advertising_sync(hdev);
|
||||
/* No-op when advertising was not paused. */
|
||||
hci_resume_advertising_sync(hdev);
|
||||
|
||||
/* Resume passive scanning */
|
||||
hci_update_passive_scan_sync(hdev);
|
||||
|
|
@ -6460,6 +6573,12 @@ static int hci_pause_discovery_sync(struct hci_dev *hdev)
|
|||
return 0;
|
||||
|
||||
hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
|
||||
|
||||
/* Cancel the LE scan timeout first, so that it does not run while
|
||||
* suspended if the scan cannot be disabled.
|
||||
*/
|
||||
cancel_delayed_work(&hdev->le_scan_disable);
|
||||
|
||||
err = hci_stop_discovery_sync(hdev);
|
||||
if (err)
|
||||
return err;
|
||||
|
|
@ -6928,7 +7047,7 @@ static int hci_le_create_conn_sync(struct hci_dev *hdev, void *data)
|
|||
|
||||
bt_dev_dbg(hdev, "conn %p", conn);
|
||||
|
||||
clear_bit(HCI_CONN_SCANNING, &conn->flags);
|
||||
clear_bit(HCI_CONN_SCANNING, conn->flags);
|
||||
conn->state = BT_CONNECT;
|
||||
|
||||
/* If requested to connect as peripheral use directed advertising */
|
||||
|
|
@ -6995,7 +7114,7 @@ static int hci_le_create_conn_sync(struct hci_dev *hdev, void *data)
|
|||
/* Mark create connection in flight so hci_cancel_connect_sync() can
|
||||
* cancel it while blocking on the connection complete event.
|
||||
*/
|
||||
set_bit(HCI_CONN_CREATE, &conn->flags);
|
||||
set_bit(HCI_CONN_CREATE, conn->flags);
|
||||
|
||||
/* Send command LE Extended Create Connection if supported */
|
||||
if (use_ext_conn(hdev)) {
|
||||
|
|
@ -7032,7 +7151,7 @@ static int hci_le_create_conn_sync(struct hci_dev *hdev, void *data)
|
|||
conn->conn_timeout, NULL);
|
||||
|
||||
done:
|
||||
clear_bit(HCI_CONN_CREATE, &conn->flags);
|
||||
clear_bit(HCI_CONN_CREATE, conn->flags);
|
||||
|
||||
if (err == -ETIMEDOUT)
|
||||
hci_le_connect_cancel_sync(hdev, conn, 0x00);
|
||||
|
|
@ -7079,7 +7198,7 @@ int hci_le_create_cis_sync(struct hci_dev *hdev)
|
|||
|
||||
/* Wait until previous Create CIS has completed */
|
||||
list_for_each_entry_rcu(conn, &hdev->conn_hash.list, list) {
|
||||
if (test_bit(HCI_CONN_CREATE_CIS, &conn->flags))
|
||||
if (test_bit(HCI_CONN_CREATE_CIS, conn->flags))
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
|
@ -7115,7 +7234,7 @@ int hci_le_create_cis_sync(struct hci_dev *hdev)
|
|||
conn->iso_qos.ucast.cig != cig)
|
||||
continue;
|
||||
|
||||
set_bit(HCI_CONN_CREATE_CIS, &conn->flags);
|
||||
set_bit(HCI_CONN_CREATE_CIS, conn->flags);
|
||||
cis->acl_handle = cpu_to_le16(conn->parent->handle);
|
||||
cis->cis_handle = cpu_to_le16(conn->handle);
|
||||
timeout = conn->conn_timeout;
|
||||
|
|
@ -7318,14 +7437,14 @@ static int hci_acl_create_conn_sync(struct hci_dev *hdev, void *data)
|
|||
/* Mark create connection in flight so hci_cancel_connect_sync() can
|
||||
* cancel it while blocking on the connection complete event.
|
||||
*/
|
||||
set_bit(HCI_CONN_CREATE, &conn->flags);
|
||||
set_bit(HCI_CONN_CREATE, conn->flags);
|
||||
|
||||
err = __hci_cmd_sync_status_sk(hdev, HCI_OP_CREATE_CONN,
|
||||
sizeof(cp), &cp,
|
||||
HCI_EV_CONN_COMPLETE,
|
||||
conn->conn_timeout, NULL);
|
||||
|
||||
clear_bit(HCI_CONN_CREATE, &conn->flags);
|
||||
clear_bit(HCI_CONN_CREATE, conn->flags);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
@ -7414,7 +7533,7 @@ static int hci_acl_cancel_create_conn_sync(struct hci_dev *hdev,
|
|||
mutex_lock(&hdev->cmd_sync_work_lock);
|
||||
|
||||
/* In flight: this connection owns the pending request, cancel it. */
|
||||
if (test_bit(HCI_CONN_CREATE, &conn->flags)) {
|
||||
if (test_bit(HCI_CONN_CREATE, conn->flags)) {
|
||||
hci_cmd_sync_cancel(hdev, ECANCELED);
|
||||
goto unlock;
|
||||
}
|
||||
|
|
@ -7445,7 +7564,7 @@ static int hci_le_cancel_create_conn_sync(struct hci_dev *hdev,
|
|||
*/
|
||||
mutex_lock(&hdev->cmd_sync_work_lock);
|
||||
|
||||
if (test_bit(HCI_CONN_CREATE, &conn->flags)) {
|
||||
if (test_bit(HCI_CONN_CREATE, conn->flags)) {
|
||||
hci_cmd_sync_cancel(hdev, ECANCELED);
|
||||
goto unlock;
|
||||
}
|
||||
|
|
@ -7472,7 +7591,7 @@ static int hci_cis_cancel_create_conn_sync(struct hci_dev *hdev,
|
|||
*/
|
||||
mutex_lock(&hdev->cmd_sync_work_lock);
|
||||
|
||||
if (test_bit(HCI_CONN_CREATE_CIS, &conn->flags))
|
||||
if (test_bit(HCI_CONN_CREATE_CIS, conn->flags))
|
||||
hci_cmd_sync_cancel(hdev, ECANCELED);
|
||||
|
||||
mutex_unlock(&hdev->cmd_sync_work_lock);
|
||||
|
|
@ -7609,7 +7728,7 @@ static void create_pa_complete(struct hci_dev *hdev, void *data, int err)
|
|||
hci_dev_lock(hdev);
|
||||
|
||||
if (hci_conn_valid(hdev, conn))
|
||||
clear_bit(HCI_CONN_CREATE_PA_SYNC, &conn->flags);
|
||||
clear_bit(HCI_CONN_CREATE_PA_SYNC, conn->flags);
|
||||
|
||||
if (!err)
|
||||
goto unlock;
|
||||
|
|
@ -7621,7 +7740,7 @@ static void create_pa_complete(struct hci_dev *hdev, void *data, int err)
|
|||
if (IS_ERR(pa_sync))
|
||||
goto unlock;
|
||||
|
||||
set_bit(HCI_CONN_PA_SYNC_FAILED, &pa_sync->flags);
|
||||
set_bit(HCI_CONN_PA_SYNC_FAILED, pa_sync->flags);
|
||||
|
||||
/* Notify iso layer */
|
||||
hci_connect_cfm(pa_sync, bt_status(err));
|
||||
|
|
@ -7694,7 +7813,7 @@ static int hci_le_pa_create_sync(struct hci_dev *hdev, void *data)
|
|||
* program the address in the allow list so PA advertisements can be
|
||||
* received.
|
||||
*/
|
||||
set_bit(HCI_CONN_CREATE_PA_SYNC, &conn->flags);
|
||||
set_bit(HCI_CONN_CREATE_PA_SYNC, conn->flags);
|
||||
|
||||
hci_update_passive_scan_sync(hdev);
|
||||
|
||||
|
|
@ -7797,7 +7916,7 @@ static void create_big_complete(struct hci_dev *hdev, void *data, int err)
|
|||
if (err == -ECANCELED)
|
||||
goto done;
|
||||
|
||||
clear_bit(HCI_CONN_CREATE_BIG_SYNC, &conn->flags);
|
||||
clear_bit(HCI_CONN_CREATE_BIG_SYNC, conn->flags);
|
||||
|
||||
done:
|
||||
hci_conn_put(conn);
|
||||
|
|
@ -7814,7 +7933,7 @@ static int hci_le_big_create_sync(struct hci_dev *hdev, void *data)
|
|||
if (!hci_conn_valid(hdev, conn))
|
||||
return -ECANCELED;
|
||||
|
||||
set_bit(HCI_CONN_CREATE_BIG_SYNC, &conn->flags);
|
||||
set_bit(HCI_CONN_CREATE_BIG_SYNC, conn->flags);
|
||||
|
||||
memset(cp, 0, sizeof(*cp));
|
||||
cp->handle = qos->bcast.big;
|
||||
|
|
|
|||
|
|
@ -912,7 +912,7 @@ static void iso_sock_disconn(struct sock *sk)
|
|||
struct sock *bis_sk;
|
||||
struct hci_conn *hcon = iso_pi(sk)->conn->hcon;
|
||||
|
||||
if (test_bit(HCI_CONN_BIG_CREATED, &hcon->flags)) {
|
||||
if (test_bit(HCI_CONN_BIG_CREATED, hcon->flags)) {
|
||||
bis_sk = iso_get_sock_big(sk, &iso_pi(sk)->src,
|
||||
&iso_pi(sk)->dst,
|
||||
iso_pi(sk)->qos.bcast.big);
|
||||
|
|
@ -957,8 +957,8 @@ static void __iso_sock_close(struct sock *sk)
|
|||
|
||||
case BT_CONNECT2:
|
||||
if (iso_pi(sk)->conn->hcon &&
|
||||
(test_bit(HCI_CONN_PA_SYNC, &iso_pi(sk)->conn->hcon->flags) ||
|
||||
test_bit(HCI_CONN_PA_SYNC_FAILED, &iso_pi(sk)->conn->hcon->flags)))
|
||||
(test_bit(HCI_CONN_PA_SYNC, iso_pi(sk)->conn->hcon->flags) ||
|
||||
test_bit(HCI_CONN_PA_SYNC_FAILED, iso_pi(sk)->conn->hcon->flags)))
|
||||
iso_sock_disconn(sk);
|
||||
else
|
||||
iso_chan_del(sk, ECONNRESET);
|
||||
|
|
@ -2289,7 +2289,7 @@ static void iso_conn_ready(struct iso_conn *conn)
|
|||
|
||||
hdev = hcon->hdev;
|
||||
|
||||
if (test_bit(HCI_CONN_BIG_SYNC, &hcon->flags)) {
|
||||
if (test_bit(HCI_CONN_BIG_SYNC, hcon->flags)) {
|
||||
/* A BIS slave hcon is notified to the ISO layer
|
||||
* after the Command Complete for the LE Setup
|
||||
* ISO Data Path command is received. Get the
|
||||
|
|
@ -2298,7 +2298,7 @@ static void iso_conn_ready(struct iso_conn *conn)
|
|||
parent = iso_get_sock(hdev, &hcon->src, &hcon->dst,
|
||||
BT_LISTEN, iso_match_big_hcon,
|
||||
hcon);
|
||||
} else if (test_bit(HCI_CONN_BIG_SYNC_FAILED, &hcon->flags)) {
|
||||
} else if (test_bit(HCI_CONN_BIG_SYNC_FAILED, hcon->flags)) {
|
||||
ev = hci_recv_event_data(hcon->hdev,
|
||||
HCI_EVT_LE_BIG_SYNC_ESTABLISHED);
|
||||
|
||||
|
|
@ -2312,7 +2312,7 @@ static void iso_conn_ready(struct iso_conn *conn)
|
|||
&hcon->dst,
|
||||
BT_LISTEN,
|
||||
iso_match_big, ev);
|
||||
} else if (test_bit(HCI_CONN_PA_SYNC_FAILED, &hcon->flags)) {
|
||||
} else if (test_bit(HCI_CONN_PA_SYNC_FAILED, hcon->flags)) {
|
||||
ev2 = hci_recv_event_data(hcon->hdev,
|
||||
HCI_EV_LE_PA_SYNC_ESTABLISHED);
|
||||
if (ev2)
|
||||
|
|
@ -2320,7 +2320,7 @@ static void iso_conn_ready(struct iso_conn *conn)
|
|||
&hcon->dst,
|
||||
BT_LISTEN,
|
||||
iso_match_sid, ev2);
|
||||
} else if (test_bit(HCI_CONN_PA_SYNC, &hcon->flags)) {
|
||||
} else if (test_bit(HCI_CONN_PA_SYNC, hcon->flags)) {
|
||||
ev3 = hci_recv_event_data(hcon->hdev,
|
||||
HCI_EV_LE_PER_ADV_REPORT);
|
||||
if (ev3)
|
||||
|
|
@ -2376,7 +2376,7 @@ static void iso_conn_ready(struct iso_conn *conn)
|
|||
hcon->dst_type = le_addr_type(iso_pi(parent)->dst_type);
|
||||
}
|
||||
|
||||
if (test_bit(HCI_CONN_PA_SYNC, &hcon->flags)) {
|
||||
if (test_bit(HCI_CONN_PA_SYNC, hcon->flags)) {
|
||||
iso_pi(sk)->qos = iso_pi(parent)->qos;
|
||||
hcon->iso_qos = iso_pi(sk)->qos;
|
||||
iso_pi(sk)->bc_sid = iso_pi(parent)->bc_sid;
|
||||
|
|
@ -2676,8 +2676,8 @@ static void iso_connect_cfm(struct hci_conn *hcon, __u8 status)
|
|||
* into the accept queue of the listening socket and wake up
|
||||
* userspace, to inform the user about the event.
|
||||
*/
|
||||
if (!status || test_bit(HCI_CONN_BIG_SYNC_FAILED, &hcon->flags) ||
|
||||
test_bit(HCI_CONN_PA_SYNC_FAILED, &hcon->flags)) {
|
||||
if (!status || test_bit(HCI_CONN_BIG_SYNC_FAILED, hcon->flags) ||
|
||||
test_bit(HCI_CONN_PA_SYNC_FAILED, hcon->flags)) {
|
||||
struct iso_conn *conn;
|
||||
|
||||
conn = iso_conn_add(hcon);
|
||||
|
|
|
|||
|
|
@ -1575,7 +1575,7 @@ static bool l2cap_check_enc_key_size(struct hci_conn *hcon,
|
|||
if (chan->sec_level == BT_SECURITY_FIPS)
|
||||
min_key_size = 16;
|
||||
|
||||
return (!test_bit(HCI_CONN_ENCRYPT, &hcon->flags) ||
|
||||
return (!test_bit(HCI_CONN_ENCRYPT, hcon->flags) ||
|
||||
hcon->enc_key_size >= min_key_size);
|
||||
}
|
||||
|
||||
|
|
@ -4480,11 +4480,11 @@ static int l2cap_connect_create_rsp(struct l2cap_conn *conn,
|
|||
|
||||
lockdep_assert_held(&chan->conn->lock);
|
||||
|
||||
/* Only accept a response to a connection request we sent and that
|
||||
* is still outstanding. A channel waiting in BT_CONNECT for security
|
||||
* or the feature mask has not sent one yet.
|
||||
/* Only accept a response matching a connection request we sent and
|
||||
* that is still outstanding. A channel waiting in BT_CONNECT for
|
||||
* security or the feature mask has not sent one yet.
|
||||
*/
|
||||
if (!l2cap_chan_connect_pending(chan))
|
||||
if (!l2cap_chan_connect_pending(chan) || chan->ident != cmd->ident)
|
||||
goto done;
|
||||
|
||||
switch (result) {
|
||||
|
|
@ -7389,7 +7389,11 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
|
|||
u16 cid, len;
|
||||
__le16 psm;
|
||||
|
||||
if (hcon->state != BT_CONNECTED) {
|
||||
/* Also hold data back while the encryption key size is read, as
|
||||
* the security of the link, e.g. for SMP over BR/EDR, depends on it.
|
||||
*/
|
||||
if (hcon->state != BT_CONNECTED ||
|
||||
test_bit(HCI_CONN_ENC_KEY_SIZE_PEND, hcon->flags)) {
|
||||
BT_DBG("queueing pending rx skb");
|
||||
skb_queue_tail(&conn->pending_rx, skb);
|
||||
return;
|
||||
|
|
@ -7452,7 +7456,11 @@ static void process_pending_rx(struct work_struct *work)
|
|||
|
||||
mutex_lock(&conn->lock);
|
||||
|
||||
while ((skb = skb_dequeue(&conn->pending_rx)))
|
||||
/* l2cap_recv_frame() would queue it all again while the encryption
|
||||
* key size is read, l2cap_security_cfm() schedules this once known.
|
||||
*/
|
||||
while (!test_bit(HCI_CONN_ENC_KEY_SIZE_PEND, conn->hcon->flags) &&
|
||||
(skb = skb_dequeue(&conn->pending_rx)))
|
||||
l2cap_recv_frame(conn, skb);
|
||||
|
||||
mutex_unlock(&conn->lock);
|
||||
|
|
@ -8041,6 +8049,10 @@ static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
|
|||
}
|
||||
|
||||
mutex_unlock(&conn->lock);
|
||||
|
||||
/* Process data held back while the encryption key size was read */
|
||||
if (!skb_queue_empty(&conn->pending_rx))
|
||||
queue_work(hcon->hdev->workqueue, &conn->pending_rx_work);
|
||||
}
|
||||
|
||||
/* Append fragment into frame respecting the maximum len of rx_skb */
|
||||
|
|
|
|||
|
|
@ -304,6 +304,8 @@ static u8 mgmt_errno_status(int err)
|
|||
return MGMT_STATUS_DISCONNECTED;
|
||||
case -ECANCELED:
|
||||
return MGMT_STATUS_CANCELLED;
|
||||
case -ERFKILL:
|
||||
return MGMT_STATUS_RFKILLED;
|
||||
}
|
||||
|
||||
return MGMT_STATUS_FAILED;
|
||||
|
|
@ -3241,7 +3243,7 @@ static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
|
|||
/* Defer clearing up the connection parameters until closing to
|
||||
* give a chance of keeping them if a repairing happens.
|
||||
*/
|
||||
set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
|
||||
set_bit(HCI_CONN_PARAM_REMOVAL_PEND, conn->flags);
|
||||
|
||||
/* Disable auto-connection parameters if present */
|
||||
params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr, addr_type);
|
||||
|
|
@ -3416,7 +3418,7 @@ static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
|
|||
|
||||
i = 0;
|
||||
list_for_each_entry(c, &hdev->conn_hash.list, list) {
|
||||
if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
|
||||
if (test_bit(HCI_CONN_MGMT_CONNECTED, c->flags))
|
||||
i++;
|
||||
}
|
||||
|
||||
|
|
@ -3428,7 +3430,7 @@ static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
|
|||
|
||||
i = 0;
|
||||
list_for_each_entry(c, &hdev->conn_hash.list, list) {
|
||||
if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
|
||||
if (!test_bit(HCI_CONN_MGMT_CONNECTED, c->flags))
|
||||
continue;
|
||||
bacpy(&rp->addr[i].bdaddr, &c->dst);
|
||||
rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
|
||||
|
|
@ -3628,7 +3630,7 @@ static int pairing_complete(struct mgmt_pending_cmd *cmd, u8 status)
|
|||
/* The device is paired so there is no need to remove
|
||||
* its connection parameters anymore.
|
||||
*/
|
||||
clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
|
||||
clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, conn->flags);
|
||||
|
||||
hci_conn_put(conn);
|
||||
|
||||
|
|
@ -6316,12 +6318,29 @@ static void stop_discovery_complete(struct hci_dev *hdev, void *data, int err)
|
|||
|
||||
bt_dev_dbg(hdev, "err %d", err);
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
/* Change the state before replying, so that a client acting on the
|
||||
* reply sees it, and only while the discovery is still stopping, as
|
||||
* Inquiry Cancel may already have stopped it and a new Start Discovery
|
||||
* may have followed. Go back to DISCOVERY_FINDING when stopping failed
|
||||
* while the inquiry or the active LE scan of the discovery is still
|
||||
* running, so that it can be stopped again.
|
||||
*/
|
||||
if (hdev->discovery.state == DISCOVERY_STOPPING) {
|
||||
if (err && (test_bit(HCI_INQUIRY, &hdev->flags) ||
|
||||
(hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
|
||||
hdev->le_scan_type == LE_SCAN_ACTIVE)))
|
||||
hci_discovery_set_state(hdev, DISCOVERY_FINDING);
|
||||
else
|
||||
hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
|
||||
}
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
|
||||
mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(err),
|
||||
cmd->param, 1);
|
||||
mgmt_pending_free(cmd);
|
||||
|
||||
if (!err)
|
||||
hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
|
||||
}
|
||||
|
||||
static int stop_discovery_sync(struct hci_dev *hdev, void *data)
|
||||
|
|
@ -8173,7 +8192,11 @@ static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
|
|||
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
if (param_count > 1)
|
||||
/* A single entry may be an update for one device, so keep the other
|
||||
* disabled parameters then, but clear them otherwise, including when
|
||||
* no entries are loaded.
|
||||
*/
|
||||
if (param_count != 1)
|
||||
hci_conn_params_clear_disabled(hdev);
|
||||
|
||||
for (i = 0; i < param_count; i++) {
|
||||
|
|
@ -10128,7 +10151,7 @@ void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
|
|||
u16 eir_len = 0;
|
||||
u32 flags = 0;
|
||||
|
||||
if (test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
|
||||
if (test_and_set_bit(HCI_CONN_MGMT_CONNECTED, conn->flags))
|
||||
return;
|
||||
|
||||
/* allocate buff for LE or BR/EDR adv */
|
||||
|
|
@ -10177,7 +10200,7 @@ void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
|
|||
* since userspace did not know about them yet, so report it now.
|
||||
* Unencrypted connections have no change to report.
|
||||
*/
|
||||
if (test_bit(HCI_CONN_ENCRYPT, &conn->flags))
|
||||
if (test_bit(HCI_CONN_ENCRYPT, conn->flags))
|
||||
mgmt_security_level_changed(conn);
|
||||
}
|
||||
|
||||
|
|
@ -10289,7 +10312,7 @@ void mgmt_connect_failed(struct hci_dev *hdev, struct hci_conn *conn, u8 status)
|
|||
* still needs it set to know whether to report the security level
|
||||
* reset, so it is consumed there instead of here.
|
||||
*/
|
||||
if (test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
|
||||
if (test_bit(HCI_CONN_MGMT_CONNECTED, conn->flags)) {
|
||||
mgmt_device_disconnected(hdev, &conn->dst, conn->type,
|
||||
conn->dst_type,
|
||||
hci_to_mgmt_reason(status), true);
|
||||
|
|
@ -10930,7 +10953,7 @@ void mgmt_security_level_changed(struct hci_conn *conn)
|
|||
u8 *tlv_data;
|
||||
u8 tlv_len;
|
||||
|
||||
if (!test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
|
||||
if (!test_bit(HCI_CONN_MGMT_CONNECTED, conn->flags))
|
||||
return;
|
||||
|
||||
/* Only ACL, LE and BIS links are tracked as mgmt connections, so
|
||||
|
|
@ -10961,9 +10984,9 @@ void mgmt_security_level_changed(struct hci_conn *conn)
|
|||
tlv = (void *)tlv_data;
|
||||
tlv->type = cpu_to_le16(MGMT_SEC_LEVEL_CHANGED_PARAM_ENC_TYPE);
|
||||
tlv->length = sizeof(__u8);
|
||||
if (!test_bit(HCI_CONN_ENCRYPT, &conn->flags))
|
||||
if (!test_bit(HCI_CONN_ENCRYPT, conn->flags))
|
||||
tlv->value[0] = MGMT_CONN_SEC_ENCRYPT_NONE;
|
||||
else if (test_bit(HCI_CONN_AES_CCM, &conn->flags))
|
||||
else if (test_bit(HCI_CONN_AES_CCM, conn->flags))
|
||||
tlv->value[0] = MGMT_CONN_SEC_ENCRYPT_AES_CCM;
|
||||
else
|
||||
tlv->value[0] = MGMT_CONN_SEC_ENCRYPT_E0;
|
||||
|
|
|
|||
|
|
@ -984,12 +984,12 @@ static u8 smp_random(struct smp_chan *smp)
|
|||
|
||||
smp_s1(smp->tk, smp->rrnd, smp->prnd, stk);
|
||||
|
||||
if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags))
|
||||
if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, hcon->flags))
|
||||
return SMP_UNSPECIFIED;
|
||||
|
||||
hci_le_start_enc(hcon, ediv, rand, stk, smp->enc_key_size);
|
||||
hcon->enc_key_size = smp->enc_key_size;
|
||||
set_bit(HCI_CONN_STK_ENCRYPT, &hcon->flags);
|
||||
set_bit(HCI_CONN_STK_ENCRYPT, hcon->flags);
|
||||
} else {
|
||||
u8 stk[16], auth;
|
||||
__le64 rand = 0;
|
||||
|
|
@ -1028,7 +1028,7 @@ static void smp_notify_keys(struct l2cap_conn *conn)
|
|||
persistent = false;
|
||||
else
|
||||
persistent = !test_bit(HCI_CONN_FLUSH_KEY,
|
||||
&hcon->flags);
|
||||
hcon->flags);
|
||||
} else {
|
||||
/* The LTKs, IRKs and CSRKs should be persistent only if
|
||||
* both sides had the bonding bit set in their
|
||||
|
|
@ -1186,9 +1186,13 @@ static void sc_generate_ltk(struct smp_chan *smp)
|
|||
struct hci_conn *hcon = smp->conn->hcon;
|
||||
struct hci_dev *hdev = hcon->hdev;
|
||||
struct link_key *key;
|
||||
int err;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
key = hci_find_link_key(hdev, &hcon->dst);
|
||||
if (!key) {
|
||||
rcu_read_unlock();
|
||||
bt_dev_err(hdev, "no Link Key found to generate LTK");
|
||||
return;
|
||||
}
|
||||
|
|
@ -1200,16 +1204,19 @@ static void sc_generate_ltk(struct smp_chan *smp)
|
|||
/* SALT = 0x000000000000000000000000746D7032 */
|
||||
const u8 salt[16] = { 0x32, 0x70, 0x6d, 0x74 };
|
||||
|
||||
if (smp_h7(key->val, salt, smp->tk))
|
||||
return;
|
||||
err = smp_h7(key->val, salt, smp->tk);
|
||||
} else {
|
||||
/* From core spec. Spells out in ASCII as 'tmp2'. */
|
||||
const u8 tmp2[4] = { 0x32, 0x70, 0x6d, 0x74 };
|
||||
|
||||
if (smp_h6(key->val, tmp2, smp->tk))
|
||||
return;
|
||||
err = smp_h6(key->val, tmp2, smp->tk);
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
if (err)
|
||||
return;
|
||||
|
||||
if (smp_h6(smp->tk, brle, smp->tk))
|
||||
return;
|
||||
|
||||
|
|
@ -1753,7 +1760,7 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
|
|||
/* SMP over BR/EDR requires special treatment */
|
||||
if (conn->hcon->type == ACL_LINK) {
|
||||
/* We must have a BR/EDR SC link */
|
||||
if (!test_bit(HCI_CONN_AES_CCM, &conn->hcon->flags) &&
|
||||
if (!test_bit(HCI_CONN_AES_CCM, conn->hcon->flags) &&
|
||||
!hci_dev_test_flag(hdev, HCI_FORCE_BREDR_SMP))
|
||||
return SMP_CROSS_TRANSP_NOT_ALLOWED;
|
||||
|
||||
|
|
@ -2202,24 +2209,30 @@ static bool smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level)
|
|||
{
|
||||
struct smp_ltk *key;
|
||||
struct hci_conn *hcon = conn->hcon;
|
||||
bool ret = false;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
key = hci_find_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, hcon->role);
|
||||
if (!key)
|
||||
return false;
|
||||
goto unlock;
|
||||
|
||||
if (smp_ltk_sec_level(key) < sec_level)
|
||||
return false;
|
||||
goto unlock;
|
||||
|
||||
if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags))
|
||||
return true;
|
||||
ret = true;
|
||||
if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, hcon->flags))
|
||||
goto unlock;
|
||||
|
||||
hci_le_start_enc(hcon, key->ediv, key->rand, key->val, key->enc_size);
|
||||
hcon->enc_key_size = key->enc_size;
|
||||
|
||||
/* We never store STKs for initiator role, so clear this flag */
|
||||
clear_bit(HCI_CONN_STK_ENCRYPT, &hcon->flags);
|
||||
clear_bit(HCI_CONN_STK_ENCRYPT, hcon->flags);
|
||||
|
||||
return true;
|
||||
unlock:
|
||||
rcu_read_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level,
|
||||
|
|
@ -2235,7 +2248,7 @@ bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level,
|
|||
* don't have an LTK (e.g. because of key distribution bits).
|
||||
*/
|
||||
if (key_pref == SMP_USE_LTK &&
|
||||
test_bit(HCI_CONN_STK_ENCRYPT, &hcon->flags) &&
|
||||
test_bit(HCI_CONN_STK_ENCRYPT, hcon->flags) &&
|
||||
hci_find_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, hcon->role))
|
||||
return false;
|
||||
|
||||
|
|
@ -3084,11 +3097,11 @@ static void bredr_pairing(struct l2cap_chan *chan)
|
|||
bt_dev_dbg(hdev, "chan %p", chan);
|
||||
|
||||
/* Only new pairings are interesting */
|
||||
if (!test_bit(HCI_CONN_NEW_LINK_KEY, &hcon->flags))
|
||||
if (!test_bit(HCI_CONN_NEW_LINK_KEY, hcon->flags))
|
||||
return;
|
||||
|
||||
/* Don't bother if we're not encrypted */
|
||||
if (!test_bit(HCI_CONN_ENCRYPT, &hcon->flags))
|
||||
if (!test_bit(HCI_CONN_ENCRYPT, hcon->flags))
|
||||
return;
|
||||
|
||||
/* Only initiator may initiate SMP over BR/EDR */
|
||||
|
|
@ -3100,7 +3113,7 @@ static void bredr_pairing(struct l2cap_chan *chan)
|
|||
return;
|
||||
|
||||
/* BR/EDR must use Secure Connections for SMP */
|
||||
if (!test_bit(HCI_CONN_AES_CCM, &hcon->flags) &&
|
||||
if (!test_bit(HCI_CONN_AES_CCM, hcon->flags) &&
|
||||
!hci_dev_test_flag(hdev, HCI_FORCE_BREDR_SMP))
|
||||
return;
|
||||
|
||||
|
|
@ -3149,7 +3162,7 @@ static void smp_resume_cb(struct l2cap_chan *chan)
|
|||
if (!smp)
|
||||
return;
|
||||
|
||||
if (!test_bit(HCI_CONN_ENCRYPT, &hcon->flags))
|
||||
if (!test_bit(HCI_CONN_ENCRYPT, hcon->flags))
|
||||
return;
|
||||
|
||||
cancel_delayed_work(&smp->security_timer);
|
||||
|
|
@ -3172,7 +3185,7 @@ static void smp_ready_cb(struct l2cap_chan *chan)
|
|||
*/
|
||||
conn->smp = chan;
|
||||
|
||||
if (hcon->type == ACL_LINK && test_bit(HCI_CONN_ENCRYPT, &hcon->flags))
|
||||
if (hcon->type == ACL_LINK && test_bit(HCI_CONN_ENCRYPT, hcon->flags))
|
||||
bredr_pairing(chan);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user