Commit 9ffd2e9a authored by John W. Linville's avatar John W. Linville

Merge branch 'for-upstream' of...

Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
parents 3e3831c4 81ad6fd9
...@@ -126,6 +126,8 @@ enum { ...@@ -126,6 +126,8 @@ enum {
HCI_SSP_ENABLED, HCI_SSP_ENABLED,
HCI_SC_ENABLED, HCI_SC_ENABLED,
HCI_SC_ONLY, HCI_SC_ONLY,
HCI_PRIVACY,
HCI_RPA_EXPIRED,
HCI_RPA_RESOLVING, HCI_RPA_RESOLVING,
HCI_HS_ENABLED, HCI_HS_ENABLED,
HCI_LE_ENABLED, HCI_LE_ENABLED,
...@@ -138,6 +140,7 @@ enum { ...@@ -138,6 +140,7 @@ enum {
HCI_FAST_CONNECTABLE, HCI_FAST_CONNECTABLE,
HCI_BREDR_ENABLED, HCI_BREDR_ENABLED,
HCI_6LOWPAN_ENABLED, HCI_6LOWPAN_ENABLED,
HCI_LE_SCAN_INTERRUPTED,
}; };
/* A mask for the flags that are supposed to remain when a reset happens /* A mask for the flags that are supposed to remain when a reset happens
...@@ -180,6 +183,8 @@ enum { ...@@ -180,6 +183,8 @@ enum {
#define HCI_CMD_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */ #define HCI_CMD_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */
#define HCI_ACL_TX_TIMEOUT msecs_to_jiffies(45000) /* 45 seconds */ #define HCI_ACL_TX_TIMEOUT msecs_to_jiffies(45000) /* 45 seconds */
#define HCI_AUTO_OFF_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */ #define HCI_AUTO_OFF_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */
#define HCI_POWER_OFF_TIMEOUT msecs_to_jiffies(5000) /* 5 seconds */
#define HCI_LE_CONN_TIMEOUT msecs_to_jiffies(20000) /* 20 seconds */
/* HCI data types */ /* HCI data types */
#define HCI_COMMAND_PKT 0x01 #define HCI_COMMAND_PKT 0x01
...@@ -354,6 +359,7 @@ enum { ...@@ -354,6 +359,7 @@ enum {
/* ---- HCI Error Codes ---- */ /* ---- HCI Error Codes ---- */
#define HCI_ERROR_AUTH_FAILURE 0x05 #define HCI_ERROR_AUTH_FAILURE 0x05
#define HCI_ERROR_MEMORY_EXCEEDED 0x07
#define HCI_ERROR_CONNECTION_TIMEOUT 0x08 #define HCI_ERROR_CONNECTION_TIMEOUT 0x08
#define HCI_ERROR_REJ_BAD_ADDR 0x0f #define HCI_ERROR_REJ_BAD_ADDR 0x0f
#define HCI_ERROR_REMOTE_USER_TERM 0x13 #define HCI_ERROR_REMOTE_USER_TERM 0x13
...@@ -1178,6 +1184,9 @@ struct hci_cp_le_set_scan_enable { ...@@ -1178,6 +1184,9 @@ struct hci_cp_le_set_scan_enable {
__u8 filter_dup; __u8 filter_dup;
} __packed; } __packed;
#define HCI_LE_USE_PEER_ADDR 0x00
#define HCI_LE_USE_WHITELIST 0x01
#define HCI_OP_LE_CREATE_CONN 0x200d #define HCI_OP_LE_CREATE_CONN 0x200d
struct hci_cp_le_create_conn { struct hci_cp_le_create_conn {
__le16 scan_interval; __le16 scan_interval;
...@@ -1202,6 +1211,20 @@ struct hci_rp_le_read_white_list_size { ...@@ -1202,6 +1211,20 @@ struct hci_rp_le_read_white_list_size {
__u8 size; __u8 size;
} __packed; } __packed;
#define HCI_OP_LE_CLEAR_WHITE_LIST 0x2010
#define HCI_OP_LE_ADD_TO_WHITE_LIST 0x2011
struct hci_cp_le_add_to_white_list {
__u8 bdaddr_type;
bdaddr_t bdaddr;
} __packed;
#define HCI_OP_LE_DEL_FROM_WHITE_LIST 0x2012
struct hci_cp_le_del_from_white_list {
__u8 bdaddr_type;
bdaddr_t bdaddr;
} __packed;
#define HCI_OP_LE_CONN_UPDATE 0x2013 #define HCI_OP_LE_CONN_UPDATE 0x2013
struct hci_cp_le_conn_update { struct hci_cp_le_conn_update {
__le16 handle; __le16 handle;
...@@ -1216,7 +1239,7 @@ struct hci_cp_le_conn_update { ...@@ -1216,7 +1239,7 @@ struct hci_cp_le_conn_update {
#define HCI_OP_LE_START_ENC 0x2019 #define HCI_OP_LE_START_ENC 0x2019
struct hci_cp_le_start_enc { struct hci_cp_le_start_enc {
__le16 handle; __le16 handle;
__u8 rand[8]; __le64 rand;
__le16 ediv; __le16 ediv;
__u8 ltk[16]; __u8 ltk[16];
} __packed; } __packed;
...@@ -1628,7 +1651,7 @@ struct hci_ev_le_conn_complete { ...@@ -1628,7 +1651,7 @@ struct hci_ev_le_conn_complete {
#define HCI_EV_LE_LTK_REQ 0x05 #define HCI_EV_LE_LTK_REQ 0x05
struct hci_ev_le_ltk_req { struct hci_ev_le_ltk_req {
__le16 handle; __le16 handle;
__u8 random[8]; __le64 rand;
__le16 ediv; __le16 ediv;
} __packed; } __packed;
......
...@@ -99,7 +99,7 @@ struct smp_ltk { ...@@ -99,7 +99,7 @@ struct smp_ltk {
u8 type; u8 type;
u8 enc_size; u8 enc_size;
__le16 ediv; __le16 ediv;
u8 rand[8]; __le64 rand;
u8 val[16]; u8 val[16];
}; };
...@@ -130,6 +130,9 @@ struct oob_data { ...@@ -130,6 +130,9 @@ struct oob_data {
#define HCI_MAX_SHORT_NAME_LENGTH 10 #define HCI_MAX_SHORT_NAME_LENGTH 10
/* Default LE RPA expiry time, 15 minutes */
#define HCI_DEFAULT_RPA_TIMEOUT (15 * 60)
struct amp_assoc { struct amp_assoc {
__u16 len; __u16 len;
__u16 offset; __u16 offset;
...@@ -153,7 +156,7 @@ struct hci_dev { ...@@ -153,7 +156,7 @@ struct hci_dev {
bdaddr_t bdaddr; bdaddr_t bdaddr;
bdaddr_t random_addr; bdaddr_t random_addr;
bdaddr_t static_addr; bdaddr_t static_addr;
__u8 own_addr_type; __u8 adv_addr_type;
__u8 dev_name[HCI_MAX_NAME_LENGTH]; __u8 dev_name[HCI_MAX_NAME_LENGTH];
__u8 short_name[HCI_MAX_SHORT_NAME_LENGTH]; __u8 short_name[HCI_MAX_SHORT_NAME_LENGTH];
__u8 eir[HCI_MAX_EIR_LENGTH]; __u8 eir[HCI_MAX_EIR_LENGTH];
...@@ -281,7 +284,9 @@ struct hci_dev { ...@@ -281,7 +284,9 @@ struct hci_dev {
struct list_head long_term_keys; struct list_head long_term_keys;
struct list_head identity_resolving_keys; struct list_head identity_resolving_keys;
struct list_head remote_oob_data; struct list_head remote_oob_data;
struct list_head le_white_list;
struct list_head le_conn_params; struct list_head le_conn_params;
struct list_head pend_le_conns;
struct hci_dev_stats stat; struct hci_dev_stats stat;
...@@ -303,6 +308,11 @@ struct hci_dev { ...@@ -303,6 +308,11 @@ struct hci_dev {
__u8 scan_rsp_data[HCI_MAX_AD_LENGTH]; __u8 scan_rsp_data[HCI_MAX_AD_LENGTH];
__u8 scan_rsp_data_len; __u8 scan_rsp_data_len;
__u8 irk[16];
__u32 rpa_timeout;
struct delayed_work rpa_expired;
bdaddr_t rpa;
int (*open)(struct hci_dev *hdev); int (*open)(struct hci_dev *hdev);
int (*close)(struct hci_dev *hdev); int (*close)(struct hci_dev *hdev);
int (*flush)(struct hci_dev *hdev); int (*flush)(struct hci_dev *hdev);
...@@ -322,6 +332,10 @@ struct hci_conn { ...@@ -322,6 +332,10 @@ struct hci_conn {
__u8 dst_type; __u8 dst_type;
bdaddr_t src; bdaddr_t src;
__u8 src_type; __u8 src_type;
bdaddr_t init_addr;
__u8 init_addr_type;
bdaddr_t resp_addr;
__u8 resp_addr_type;
__u16 handle; __u16 handle;
__u16 state; __u16 state;
__u8 mode; __u8 mode;
...@@ -361,6 +375,7 @@ struct hci_conn { ...@@ -361,6 +375,7 @@ struct hci_conn {
struct delayed_work disc_work; struct delayed_work disc_work;
struct delayed_work auto_accept_work; struct delayed_work auto_accept_work;
struct delayed_work idle_work; struct delayed_work idle_work;
struct delayed_work le_conn_timeout;
struct device dev; struct device dev;
...@@ -394,6 +409,12 @@ struct hci_conn_params { ...@@ -394,6 +409,12 @@ struct hci_conn_params {
u16 conn_min_interval; u16 conn_min_interval;
u16 conn_max_interval; u16 conn_max_interval;
enum {
HCI_AUTO_CONN_DISABLED,
HCI_AUTO_CONN_ALWAYS,
HCI_AUTO_CONN_LINK_LOSS,
} auto_connect;
}; };
extern struct list_head hci_dev_list; extern struct list_head hci_dev_list;
...@@ -554,6 +575,13 @@ static inline unsigned int hci_conn_num(struct hci_dev *hdev, __u8 type) ...@@ -554,6 +575,13 @@ static inline unsigned int hci_conn_num(struct hci_dev *hdev, __u8 type)
} }
} }
static inline unsigned int hci_conn_count(struct hci_dev *hdev)
{
struct hci_conn_hash *c = &hdev->conn_hash;
return c->acl_num + c->amp_num + c->sco_num + c->le_num;
}
static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev, static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev,
__u16 handle) __u16 handle)
{ {
...@@ -627,8 +655,10 @@ void hci_chan_del(struct hci_chan *chan); ...@@ -627,8 +655,10 @@ void hci_chan_del(struct hci_chan *chan);
void hci_chan_list_flush(struct hci_conn *conn); void hci_chan_list_flush(struct hci_conn *conn);
struct hci_chan *hci_chan_lookup_handle(struct hci_dev *hdev, __u16 handle); struct hci_chan *hci_chan_lookup_handle(struct hci_dev *hdev, __u16 handle);
struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
__u8 dst_type, __u8 sec_level, __u8 auth_type); u8 dst_type, u8 sec_level, u8 auth_type);
struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
u8 sec_level, u8 auth_type);
struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst, struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst,
__u16 setting); __u16 setting);
int hci_conn_check_link_mode(struct hci_conn *conn); int hci_conn_check_link_mode(struct hci_conn *conn);
...@@ -639,6 +669,8 @@ int hci_conn_switch_role(struct hci_conn *conn, __u8 role); ...@@ -639,6 +669,8 @@ int hci_conn_switch_role(struct hci_conn *conn, __u8 role);
void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active); void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active);
void hci_le_conn_failed(struct hci_conn *conn, u8 status);
/* /*
* hci_conn_get() and hci_conn_put() are used to control the life-time of an * hci_conn_get() and hci_conn_put() are used to control the life-time of an
* "hci_conn" object. They do not guarantee that the hci_conn object is running, * "hci_conn" object. They do not guarantee that the hci_conn object is running,
...@@ -770,28 +802,42 @@ int hci_inquiry(void __user *arg); ...@@ -770,28 +802,42 @@ int hci_inquiry(void __user *arg);
struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev,
bdaddr_t *bdaddr, u8 type); bdaddr_t *bdaddr, u8 type);
void hci_blacklist_clear(struct hci_dev *hdev);
int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
struct bdaddr_list *hci_white_list_lookup(struct hci_dev *hdev,
bdaddr_t *bdaddr, u8 type);
void hci_white_list_clear(struct hci_dev *hdev);
int hci_white_list_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
int hci_white_list_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
struct hci_conn_params *hci_conn_params_lookup(struct hci_dev *hdev, struct hci_conn_params *hci_conn_params_lookup(struct hci_dev *hdev,
bdaddr_t *addr, u8 addr_type); bdaddr_t *addr, u8 addr_type);
void hci_conn_params_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type, int hci_conn_params_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,
u16 conn_min_interval, u16 conn_max_interval); u8 auto_connect, u16 conn_min_interval,
u16 conn_max_interval);
void hci_conn_params_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type); void hci_conn_params_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type);
void hci_conn_params_clear(struct hci_dev *hdev); void hci_conn_params_clear(struct hci_dev *hdev);
struct bdaddr_list *hci_pend_le_conn_lookup(struct hci_dev *hdev,
bdaddr_t *addr, u8 addr_type);
void hci_pend_le_conn_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type);
void hci_pend_le_conn_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type);
void hci_pend_le_conns_clear(struct hci_dev *hdev);
void hci_update_background_scan(struct hci_dev *hdev);
void hci_uuids_clear(struct hci_dev *hdev); void hci_uuids_clear(struct hci_dev *hdev);
void hci_link_keys_clear(struct hci_dev *hdev); void hci_link_keys_clear(struct hci_dev *hdev);
struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr); struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len); bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len);
struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8], struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, __le64 rand,
bool master); bool master);
struct smp_ltk *hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, struct smp_ltk *hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 addr_type, u8 type, u8 authenticated, u8 addr_type, u8 type, u8 authenticated,
u8 tk[16], u8 enc_size, __le16 ediv, u8 rand[8]); u8 tk[16], u8 enc_size, __le16 ediv, __le64 rand);
struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr, struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 addr_type, bool master); u8 addr_type, bool master);
int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 bdaddr_type); int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 bdaddr_type);
...@@ -1115,6 +1161,9 @@ void hci_req_add_ev(struct hci_request *req, u16 opcode, u32 plen, ...@@ -1115,6 +1161,9 @@ void hci_req_add_ev(struct hci_request *req, u16 opcode, u32 plen,
const void *param, u8 event); const void *param, u8 event);
void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status); void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status);
void hci_req_add_le_scan_disable(struct hci_request *req);
void hci_req_add_le_passive_scan(struct hci_request *req);
struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen, struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen,
const void *param, u32 timeout); const void *param, u32 timeout);
struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen, struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen,
...@@ -1160,6 +1209,7 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered); ...@@ -1160,6 +1209,7 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered);
void mgmt_discoverable_timeout(struct hci_dev *hdev); void mgmt_discoverable_timeout(struct hci_dev *hdev);
void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable); void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable);
void mgmt_connectable(struct hci_dev *hdev, u8 connectable); void mgmt_connectable(struct hci_dev *hdev, u8 connectable);
void mgmt_advertising(struct hci_dev *hdev, u8 advertising);
void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status); void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status);
void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
bool persistent); bool persistent);
...@@ -1167,7 +1217,8 @@ void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, ...@@ -1167,7 +1217,8 @@ void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
u8 addr_type, u32 flags, u8 *name, u8 name_len, u8 addr_type, u32 flags, u8 *name, u8 name_len,
u8 *dev_class); u8 *dev_class);
void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 link_type, u8 addr_type, u8 reason); u8 link_type, u8 addr_type, u8 reason,
bool mgmt_connected);
void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 link_type, u8 addr_type, u8 status); u8 link_type, u8 addr_type, u8 status);
void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
...@@ -1247,9 +1298,14 @@ struct hci_sec_filter { ...@@ -1247,9 +1298,14 @@ struct hci_sec_filter {
void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
u16 latency, u16 to_multiplier); u16 latency, u16 to_multiplier);
void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8], void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __le64 rand,
__u8 ltk[16]); __u8 ltk[16]);
int hci_update_random_address(struct hci_request *req, bool require_privacy,
u8 *own_addr_type);
void hci_copy_identity_address(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 *bdaddr_type);
#define SCO_AIRMODE_MASK 0x0003 #define SCO_AIRMODE_MASK 0x0003
#define SCO_AIRMODE_CVSD 0x0000 #define SCO_AIRMODE_CVSD 0x0000
#define SCO_AIRMODE_TRANSP 0x0003 #define SCO_AIRMODE_TRANSP 0x0003
......
...@@ -96,6 +96,7 @@ struct mgmt_rp_read_index_list { ...@@ -96,6 +96,7 @@ struct mgmt_rp_read_index_list {
#define MGMT_SETTING_ADVERTISING 0x00000400 #define MGMT_SETTING_ADVERTISING 0x00000400
#define MGMT_SETTING_SECURE_CONN 0x00000800 #define MGMT_SETTING_SECURE_CONN 0x00000800
#define MGMT_SETTING_DEBUG_KEYS 0x00001000 #define MGMT_SETTING_DEBUG_KEYS 0x00001000
#define MGMT_SETTING_PRIVACY 0x00002000
#define MGMT_OP_READ_INFO 0x0004 #define MGMT_OP_READ_INFO 0x0004
#define MGMT_READ_INFO_SIZE 0 #define MGMT_READ_INFO_SIZE 0
...@@ -186,7 +187,7 @@ struct mgmt_ltk_info { ...@@ -186,7 +187,7 @@ struct mgmt_ltk_info {
__u8 master; __u8 master;
__u8 enc_size; __u8 enc_size;
__le16 ediv; __le16 ediv;
__u8 rand[8]; __le64 rand;
__u8 val[16]; __u8 val[16];
} __packed; } __packed;
...@@ -389,6 +390,13 @@ struct mgmt_cp_set_scan_params { ...@@ -389,6 +390,13 @@ struct mgmt_cp_set_scan_params {
#define MGMT_OP_SET_DEBUG_KEYS 0x002E #define MGMT_OP_SET_DEBUG_KEYS 0x002E
#define MGMT_OP_SET_PRIVACY 0x002F
struct mgmt_cp_set_privacy {
__u8 privacy;
__u8 irk[16];
} __packed;
#define MGMT_SET_PRIVACY_SIZE 17
struct mgmt_irk_info { struct mgmt_irk_info {
struct mgmt_addr_info addr; struct mgmt_addr_info addr;
__u8 val[16]; __u8 val[16];
......
...@@ -231,7 +231,7 @@ void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, ...@@ -231,7 +231,7 @@ void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
hci_send_cmd(hdev, HCI_OP_LE_CONN_UPDATE, sizeof(cp), &cp); hci_send_cmd(hdev, HCI_OP_LE_CONN_UPDATE, sizeof(cp), &cp);
} }
void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8], void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __le64 rand,
__u8 ltk[16]) __u8 ltk[16])
{ {
struct hci_dev *hdev = conn->hdev; struct hci_dev *hdev = conn->hdev;
...@@ -242,9 +242,9 @@ void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8], ...@@ -242,9 +242,9 @@ void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
memset(&cp, 0, sizeof(cp)); memset(&cp, 0, sizeof(cp));
cp.handle = cpu_to_le16(conn->handle); cp.handle = cpu_to_le16(conn->handle);
memcpy(cp.ltk, ltk, sizeof(cp.ltk)); cp.rand = rand;
cp.ediv = ediv; cp.ediv = ediv;
memcpy(cp.rand, rand, sizeof(cp.rand)); memcpy(cp.ltk, ltk, sizeof(cp.ltk));
hci_send_cmd(hdev, HCI_OP_LE_START_ENC, sizeof(cp), &cp); hci_send_cmd(hdev, HCI_OP_LE_START_ENC, sizeof(cp), &cp);
} }
...@@ -363,6 +363,16 @@ static void hci_conn_auto_accept(struct work_struct *work) ...@@ -363,6 +363,16 @@ static void hci_conn_auto_accept(struct work_struct *work)
&conn->dst); &conn->dst);
} }
static void le_conn_timeout(struct work_struct *work)
{
struct hci_conn *conn = container_of(work, struct hci_conn,
le_conn_timeout.work);
BT_DBG("");
hci_le_create_connection_cancel(conn);
}
struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
{ {
struct hci_conn *conn; struct hci_conn *conn;
...@@ -410,6 +420,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) ...@@ -410,6 +420,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
INIT_DELAYED_WORK(&conn->disc_work, hci_conn_timeout); INIT_DELAYED_WORK(&conn->disc_work, hci_conn_timeout);
INIT_DELAYED_WORK(&conn->auto_accept_work, hci_conn_auto_accept); INIT_DELAYED_WORK(&conn->auto_accept_work, hci_conn_auto_accept);
INIT_DELAYED_WORK(&conn->idle_work, hci_conn_idle); INIT_DELAYED_WORK(&conn->idle_work, hci_conn_idle);
INIT_DELAYED_WORK(&conn->le_conn_timeout, le_conn_timeout);
atomic_set(&conn->refcnt, 0); atomic_set(&conn->refcnt, 0);
...@@ -442,6 +453,8 @@ int hci_conn_del(struct hci_conn *conn) ...@@ -442,6 +453,8 @@ int hci_conn_del(struct hci_conn *conn)
/* Unacked frames */ /* Unacked frames */
hdev->acl_cnt += conn->sent; hdev->acl_cnt += conn->sent;
} else if (conn->type == LE_LINK) { } else if (conn->type == LE_LINK) {
cancel_delayed_work_sync(&conn->le_conn_timeout);
if (hdev->le_pkts) if (hdev->le_pkts)
hdev->le_cnt += conn->sent; hdev->le_cnt += conn->sent;
else else
...@@ -515,7 +528,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src) ...@@ -515,7 +528,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
EXPORT_SYMBOL(hci_get_route); EXPORT_SYMBOL(hci_get_route);
/* This function requires the caller holds hdev->lock */ /* This function requires the caller holds hdev->lock */
static void le_conn_failed(struct hci_conn *conn, u8 status) void hci_le_conn_failed(struct hci_conn *conn, u8 status)
{ {
struct hci_dev *hdev = conn->hdev; struct hci_dev *hdev = conn->hdev;
...@@ -527,6 +540,11 @@ static void le_conn_failed(struct hci_conn *conn, u8 status) ...@@ -527,6 +540,11 @@ static void le_conn_failed(struct hci_conn *conn, u8 status)
hci_proto_connect_cfm(conn, status); hci_proto_connect_cfm(conn, status);
hci_conn_del(conn); hci_conn_del(conn);
/* Since we may have temporarily stopped the background scanning in
* favor of connection establishment, we should restart it.
*/
hci_update_background_scan(hdev);
} }
static void create_le_conn_complete(struct hci_dev *hdev, u8 status) static void create_le_conn_complete(struct hci_dev *hdev, u8 status)
...@@ -545,50 +563,55 @@ static void create_le_conn_complete(struct hci_dev *hdev, u8 status) ...@@ -545,50 +563,55 @@ static void create_le_conn_complete(struct hci_dev *hdev, u8 status)
if (!conn) if (!conn)
goto done; goto done;
le_conn_failed(conn, status); hci_le_conn_failed(conn, status);
done: done:
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
} }
static int hci_create_le_conn(struct hci_conn *conn) static void hci_req_add_le_create_conn(struct hci_request *req,
struct hci_conn *conn)
{ {
struct hci_dev *hdev = conn->hdev;
struct hci_cp_le_create_conn cp; struct hci_cp_le_create_conn cp;
struct hci_request req; struct hci_dev *hdev = conn->hdev;
int err; u8 own_addr_type;
hci_req_init(&req, hdev);
memset(&cp, 0, sizeof(cp)); memset(&cp, 0, sizeof(cp));
/* Update random address, but set require_privacy to false so
* that we never connect with an unresolvable address.
*/
if (hci_update_random_address(req, false, &own_addr_type))
return;
/* Save the address type used for this connnection attempt so we able
* to retrieve this information if we need it.
*/
conn->src_type = own_addr_type;
cp.scan_interval = cpu_to_le16(hdev->le_scan_interval); cp.scan_interval = cpu_to_le16(hdev->le_scan_interval);
cp.scan_window = cpu_to_le16(hdev->le_scan_window); cp.scan_window = cpu_to_le16(hdev->le_scan_window);
bacpy(&cp.peer_addr, &conn->dst); bacpy(&cp.peer_addr, &conn->dst);
cp.peer_addr_type = conn->dst_type; cp.peer_addr_type = conn->dst_type;
cp.own_address_type = conn->src_type; cp.own_address_type = own_addr_type;
cp.conn_interval_min = cpu_to_le16(conn->le_conn_min_interval); cp.conn_interval_min = cpu_to_le16(conn->le_conn_min_interval);
cp.conn_interval_max = cpu_to_le16(conn->le_conn_max_interval); cp.conn_interval_max = cpu_to_le16(conn->le_conn_max_interval);
cp.supervision_timeout = __constant_cpu_to_le16(0x002a); cp.supervision_timeout = __constant_cpu_to_le16(0x002a);
cp.min_ce_len = __constant_cpu_to_le16(0x0000); cp.min_ce_len = __constant_cpu_to_le16(0x0000);
cp.max_ce_len = __constant_cpu_to_le16(0x0000); cp.max_ce_len = __constant_cpu_to_le16(0x0000);
hci_req_add(&req, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp); hci_req_add(req, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp);
err = hci_req_run(&req, create_le_conn_complete); conn->state = BT_CONNECT;
if (err) {
hci_conn_del(conn);
return err;
}
return 0;
} }
static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
u8 dst_type, u8 sec_level, u8 auth_type) u8 dst_type, u8 sec_level, u8 auth_type)
{ {
struct hci_conn_params *params; struct hci_conn_params *params;
struct hci_conn *conn; struct hci_conn *conn;
struct smp_irk *irk; struct smp_irk *irk;
struct hci_request req;
int err; int err;
if (test_bit(HCI_ADVERTISING, &hdev->flags)) if (test_bit(HCI_ADVERTISING, &hdev->flags))
...@@ -617,12 +640,6 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, ...@@ -617,12 +640,6 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
if (conn) if (conn)
return ERR_PTR(-EBUSY); return ERR_PTR(-EBUSY);
/* Convert from L2CAP channel address type to HCI address type */
if (dst_type == BDADDR_LE_PUBLIC)
dst_type = ADDR_LE_DEV_PUBLIC;
else
dst_type = ADDR_LE_DEV_RANDOM;
/* When given an identity address with existing identity /* When given an identity address with existing identity
* resolving key, the connection needs to be established * resolving key, the connection needs to be established
* to a resolvable random address. * to a resolvable random address.
...@@ -647,9 +664,7 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, ...@@ -647,9 +664,7 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
conn->dst_type = dst_type; conn->dst_type = dst_type;
conn->src_type = hdev->own_addr_type;
conn->state = BT_CONNECT;
conn->out = true; conn->out = true;
conn->link_mode |= HCI_LM_MASTER; conn->link_mode |= HCI_LM_MASTER;
conn->sec_level = BT_SECURITY_LOW; conn->sec_level = BT_SECURITY_LOW;
...@@ -665,17 +680,34 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, ...@@ -665,17 +680,34 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
conn->le_conn_max_interval = hdev->le_conn_max_interval; conn->le_conn_max_interval = hdev->le_conn_max_interval;
} }
err = hci_create_le_conn(conn); hci_req_init(&req, hdev);
if (err)
/* If controller is scanning, we stop it since some controllers are
* not able to scan and connect at the same time. Also set the
* HCI_LE_SCAN_INTERRUPTED flag so that the command complete
* handler for scan disabling knows to set the correct discovery
* state.
*/
if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
hci_req_add_le_scan_disable(&req);
set_bit(HCI_LE_SCAN_INTERRUPTED, &hdev->dev_flags);
}
hci_req_add_le_create_conn(&req, conn);
err = hci_req_run(&req, create_le_conn_complete);
if (err) {
hci_conn_del(conn);
return ERR_PTR(err); return ERR_PTR(err);
}
done: done:
hci_conn_hold(conn); hci_conn_hold(conn);
return conn; return conn;
} }
static struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
u8 sec_level, u8 auth_type) u8 sec_level, u8 auth_type)
{ {
struct hci_conn *acl; struct hci_conn *acl;
...@@ -744,22 +776,6 @@ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst, ...@@ -744,22 +776,6 @@ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst,
return sco; return sco;
} }
/* Create SCO, ACL or LE connection. */
struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
__u8 dst_type, __u8 sec_level, __u8 auth_type)
{
BT_DBG("%s dst %pMR type 0x%x", hdev->name, dst, type);
switch (type) {
case LE_LINK:
return hci_connect_le(hdev, dst, dst_type, sec_level, auth_type);
case ACL_LINK:
return hci_connect_acl(hdev, dst, sec_level, auth_type);
}
return ERR_PTR(-EINVAL);
}
/* Check link security requirement */ /* Check link security requirement */
int hci_conn_check_link_mode(struct hci_conn *conn) int hci_conn_check_link_mode(struct hci_conn *conn)
{ {
......
This diff is collapsed.
This diff is collapsed.
...@@ -2434,6 +2434,14 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, ...@@ -2434,6 +2434,14 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
if (IS_ERR(skb)) if (IS_ERR(skb))
return PTR_ERR(skb); return PTR_ERR(skb);
/* Channel lock is released before requesting new skb and then
* reacquired thus we need to recheck channel state.
*/
if (chan->state != BT_CONNECTED) {
kfree_skb(skb);
return -ENOTCONN;
}
l2cap_do_send(chan, skb); l2cap_do_send(chan, skb);
return len; return len;
} }
...@@ -2483,6 +2491,14 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, ...@@ -2483,6 +2491,14 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
if (IS_ERR(skb)) if (IS_ERR(skb))
return PTR_ERR(skb); return PTR_ERR(skb);
/* Channel lock is released before requesting new skb and then
* reacquired thus we need to recheck channel state.
*/
if (chan->state != BT_CONNECTED) {
kfree_skb(skb);
return -ENOTCONN;
}
l2cap_do_send(chan, skb); l2cap_do_send(chan, skb);
err = len; err = len;
break; break;
...@@ -7092,12 +7108,19 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, ...@@ -7092,12 +7108,19 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
auth_type = l2cap_get_auth_type(chan); auth_type = l2cap_get_auth_type(chan);
if (bdaddr_type_is_le(dst_type)) if (bdaddr_type_is_le(dst_type)) {
hcon = hci_connect(hdev, LE_LINK, dst, dst_type, /* Convert from L2CAP channel address type to HCI address type
chan->sec_level, auth_type); */
else if (dst_type == BDADDR_LE_PUBLIC)
hcon = hci_connect(hdev, ACL_LINK, dst, dst_type, dst_type = ADDR_LE_DEV_PUBLIC;
chan->sec_level, auth_type); else
dst_type = ADDR_LE_DEV_RANDOM;
hcon = hci_connect_le(hdev, dst, dst_type, chan->sec_level,
auth_type);
} else {
hcon = hci_connect_acl(hdev, dst, chan->sec_level, auth_type);
}
if (IS_ERR(hcon)) { if (IS_ERR(hcon)) {
err = PTR_ERR(hcon); err = PTR_ERR(hcon);
...@@ -7251,7 +7274,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) ...@@ -7251,7 +7274,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
if (hcon->type == LE_LINK) { if (hcon->type == LE_LINK) {
if (!status && encrypt) if (!status && encrypt)
smp_distribute_keys(conn, 0); smp_distribute_keys(conn);
cancel_delayed_work(&conn->security_timer); cancel_delayed_work(&conn->security_timer);
} }
......
This diff is collapsed.
This diff is collapsed.
...@@ -78,7 +78,7 @@ struct smp_cmd_encrypt_info { ...@@ -78,7 +78,7 @@ struct smp_cmd_encrypt_info {
#define SMP_CMD_MASTER_IDENT 0x07 #define SMP_CMD_MASTER_IDENT 0x07
struct smp_cmd_master_ident { struct smp_cmd_master_ident {
__le16 ediv; __le16 ediv;
__u8 rand[8]; __le64 rand;
} __packed; } __packed;
#define SMP_CMD_IDENT_INFO 0x08 #define SMP_CMD_IDENT_INFO 0x08
...@@ -118,7 +118,10 @@ struct smp_cmd_security_req { ...@@ -118,7 +118,10 @@ struct smp_cmd_security_req {
#define SMP_FLAG_TK_VALID 1 #define SMP_FLAG_TK_VALID 1
#define SMP_FLAG_CFM_PENDING 2 #define SMP_FLAG_CFM_PENDING 2
#define SMP_FLAG_MITM_AUTH 3 #define SMP_FLAG_MITM_AUTH 3
#define SMP_FLAG_COMPLETE 4 #define SMP_FLAG_LTK_ENCRYPT 4
#define SMP_FLAG_COMPLETE 5
#define SMP_REENCRYPT_TIMEOUT msecs_to_jiffies(250)
struct smp_chan { struct smp_chan {
struct l2cap_conn *conn; struct l2cap_conn *conn;
...@@ -139,18 +142,20 @@ struct smp_chan { ...@@ -139,18 +142,20 @@ struct smp_chan {
unsigned long smp_flags; unsigned long smp_flags;
struct work_struct confirm; struct work_struct confirm;
struct work_struct random; struct work_struct random;
struct delayed_work reencrypt;
}; };
/* SMP Commands */ /* SMP Commands */
bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level); bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level);
int smp_conn_security(struct hci_conn *hcon, __u8 sec_level); int smp_conn_security(struct hci_conn *hcon, __u8 sec_level);
int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb); int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb);
int smp_distribute_keys(struct l2cap_conn *conn, __u8 force); int smp_distribute_keys(struct l2cap_conn *conn);
int smp_user_confirm_reply(struct hci_conn *conn, u16 mgmt_op, __le32 passkey); int smp_user_confirm_reply(struct hci_conn *conn, u16 mgmt_op, __le32 passkey);
void smp_chan_destroy(struct l2cap_conn *conn); void smp_chan_destroy(struct l2cap_conn *conn);
bool smp_irk_matches(struct crypto_blkcipher *tfm, u8 irk[16], bool smp_irk_matches(struct crypto_blkcipher *tfm, u8 irk[16],
bdaddr_t *bdaddr); bdaddr_t *bdaddr);
int smp_generate_rpa(struct crypto_blkcipher *tfm, u8 irk[16], bdaddr_t *rpa);
#endif /* __SMP_H */ #endif /* __SMP_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment