summaryrefslogtreecommitdiffstats
path: root/net/bluetooth/l2cap.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/bluetooth/l2cap.c')
-rw-r--r--net/bluetooth/l2cap.c134
1 files changed, 40 insertions, 94 deletions
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 123efb46d3f..eadf0923186 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -263,12 +263,17 @@ static inline int l2cap_check_link_mode(struct sock *sk)
{
struct l2cap_conn *conn = l2cap_pi(sk)->conn;
- if ((l2cap_pi(sk)->link_mode & L2CAP_LM_ENCRYPT) ||
- (l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE))
- return hci_conn_encrypt(conn->hcon);
+ if (l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE)
+ return hci_conn_security(conn->hcon, BT_SECURITY_HIGH);
+
+ if (l2cap_pi(sk)->link_mode & L2CAP_LM_ENCRYPT)
+ return hci_conn_security(conn->hcon, BT_SECURITY_MEDIUM);
if (l2cap_pi(sk)->link_mode & L2CAP_LM_AUTH)
- return hci_conn_auth(conn->hcon);
+ return hci_conn_security(conn->hcon, BT_SECURITY_LOW);
+
+ if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001))
+ return hci_conn_security(conn->hcon, BT_SECURITY_SDP);
return 1;
}
@@ -803,6 +808,7 @@ static int l2cap_do_connect(struct sock *sk)
struct l2cap_conn *conn;
struct hci_conn *hcon;
struct hci_dev *hdev;
+ __u8 sec_level;
__u8 auth_type;
int err = 0;
@@ -815,21 +821,37 @@ static int l2cap_do_connect(struct sock *sk)
err = -ENOMEM;
- if (l2cap_pi(sk)->link_mode & L2CAP_LM_AUTH ||
- l2cap_pi(sk)->link_mode & L2CAP_LM_ENCRYPT ||
- l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE) {
- if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001))
- auth_type = HCI_AT_NO_BONDING_MITM;
+ if (l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE)
+ sec_level = BT_SECURITY_HIGH;
+ else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001))
+ sec_level = BT_SECURITY_SDP;
+ else if (l2cap_pi(sk)->link_mode & L2CAP_LM_ENCRYPT)
+ sec_level = BT_SECURITY_MEDIUM;
+ else
+ sec_level = BT_SECURITY_LOW;
+
+ if (sk->sk_type == SOCK_RAW) {
+ if (l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE)
+ auth_type = HCI_AT_DEDICATED_BONDING_MITM;
+ else if (l2cap_pi(sk)->link_mode & L2CAP_LM_ENCRYPT)
+ auth_type = HCI_AT_DEDICATED_BONDING;
else
- auth_type = HCI_AT_GENERAL_BONDING_MITM;
- } else {
- if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001))
auth_type = HCI_AT_NO_BONDING;
+ } else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) {
+ if (l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE)
+ auth_type = HCI_AT_NO_BONDING_MITM;
else
+ auth_type = HCI_AT_NO_BONDING;
+ } else {
+ if (l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE)
+ auth_type = HCI_AT_GENERAL_BONDING_MITM;
+ else if (l2cap_pi(sk)->link_mode & L2CAP_LM_ENCRYPT)
auth_type = HCI_AT_GENERAL_BONDING;
+ else
+ auth_type = HCI_AT_NO_BONDING;
}
- hcon = hci_connect(hdev, ACL_LINK, dst, auth_type);
+ hcon = hci_connect(hdev, ACL_LINK, dst, sec_level, auth_type);
if (!hcon)
goto done;
@@ -1402,11 +1424,6 @@ static void l2cap_chan_ready(struct sock *sk)
*/
parent->sk_data_ready(parent, 0);
}
-
- if (l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE) {
- struct l2cap_conn *conn = l2cap_pi(sk)->conn;
- hci_conn_change_link_key(conn->hcon);
- }
}
/* Copy frame to all raw sockets on that connection */
@@ -2323,77 +2340,7 @@ static int l2cap_disconn_ind(struct hci_conn *hcon, u8 reason)
return 0;
}
-static int l2cap_auth_cfm(struct hci_conn *hcon, u8 status)
-{
- struct l2cap_chan_list *l;
- struct l2cap_conn *conn = hcon->l2cap_data;
- struct sock *sk;
-
- if (!conn)
- return 0;
-
- l = &conn->chan_list;
-
- BT_DBG("conn %p", conn);
-
- read_lock(&l->lock);
-
- for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
- struct l2cap_pinfo *pi = l2cap_pi(sk);
-
- bh_lock_sock(sk);
-
- if ((pi->link_mode & (L2CAP_LM_ENCRYPT | L2CAP_LM_SECURE)) &&
- !(hcon->link_mode & HCI_LM_ENCRYPT) &&
- !status) {
- bh_unlock_sock(sk);
- continue;
- }
-
- if (sk->sk_state == BT_CONNECT) {
- if (!status) {
- struct l2cap_conn_req req;
- req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
- req.psm = l2cap_pi(sk)->psm;
-
- l2cap_pi(sk)->ident = l2cap_get_ident(conn);
-
- l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
- L2CAP_CONN_REQ, sizeof(req), &req);
- } else {
- l2cap_sock_clear_timer(sk);
- l2cap_sock_set_timer(sk, HZ / 10);
- }
- } else if (sk->sk_state == BT_CONNECT2) {
- struct l2cap_conn_rsp rsp;
- __u16 result;
-
- if (!status) {
- sk->sk_state = BT_CONFIG;
- result = L2CAP_CR_SUCCESS;
- } else {
- sk->sk_state = BT_DISCONN;
- l2cap_sock_set_timer(sk, HZ / 10);
- result = L2CAP_CR_SEC_BLOCK;
- }
-
- rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
- rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
- rsp.result = cpu_to_le16(result);
- rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
- l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
- L2CAP_CONN_RSP, sizeof(rsp), &rsp);
- }
-
- bh_unlock_sock(sk);
- }
-
- read_unlock(&l->lock);
-
- return 0;
-}
-
-static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
+static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
{
struct l2cap_chan_list *l;
struct l2cap_conn *conn = hcon->l2cap_data;
@@ -2413,10 +2360,10 @@ static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
bh_lock_sock(sk);
- if ((pi->link_mode & (L2CAP_LM_ENCRYPT | L2CAP_LM_SECURE)) &&
+ if (!status && encrypt == 0x00 &&
+ (pi->link_mode & L2CAP_LM_SECURE) &&
(sk->sk_state == BT_CONNECTED ||
- sk->sk_state == BT_CONFIG) &&
- !status && encrypt == 0x00) {
+ sk->sk_state == BT_CONFIG)) {
__l2cap_sock_close(sk, ECONNREFUSED);
bh_unlock_sock(sk);
continue;
@@ -2608,8 +2555,7 @@ static struct hci_proto l2cap_hci_proto = {
.connect_ind = l2cap_connect_ind,
.connect_cfm = l2cap_connect_cfm,
.disconn_ind = l2cap_disconn_ind,
- .auth_cfm = l2cap_auth_cfm,
- .encrypt_cfm = l2cap_encrypt_cfm,
+ .security_cfm = l2cap_security_cfm,
.recv_acldata = l2cap_recv_acldata
};