static inline int l2cap_check_security(struct sock *sk)
{
struct l2cap_conn *conn = l2cap_pi(sk)->conn;
+ __u8 auth_type;
- return hci_conn_security(conn->hcon, l2cap_pi(sk)->sec_level);
+ switch (l2cap_pi(sk)->sec_level) {
+ case BT_SECURITY_HIGH:
+ auth_type = HCI_AT_GENERAL_BONDING_MITM;
+ break;
+ case BT_SECURITY_MEDIUM:
+ auth_type = HCI_AT_GENERAL_BONDING;
+ break;
+ default:
+ auth_type = HCI_AT_NO_BONDING;
+ break;
+ }
+
+ return hci_conn_security(conn->hcon, l2cap_pi(sk)->sec_level,
+ auth_type);
}
static inline u8 l2cap_get_ident(struct l2cap_conn *conn)
struct l2cap_conn *conn = l2cap_pi(sk)->conn;
if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
+ if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
+ return;
+
if (l2cap_check_security(sk)) {
struct l2cap_conn_req req;
req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
conn->info_ident = 0;
+ conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
+
l2cap_conn_start(conn);
}
cmd->ident == conn->info_ident) {
conn->info_ident = 0;
del_timer(&conn->info_timer);
+
+ conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
+
l2cap_conn_start(conn);
}
l2cap_pi(sk)->ident = cmd->ident;
- if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
+ if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
if (l2cap_check_security(sk)) {
if (bt_sk(sk)->defer_setup) {
sk->sk_state = BT_CONNECT2;
del_timer(&conn->info_timer);
- if (type == L2CAP_IT_FEAT_MASK)
+ if (type == L2CAP_IT_FEAT_MASK) {
conn->feat_mask = get_unaligned_le32(rsp->data);
- l2cap_conn_start(conn);
+ conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
+
+ l2cap_conn_start(conn);
+ }
return 0;
}