diff options
Diffstat (limited to 'net/bluetooth/l2cap.c')
-rw-r--r-- | net/bluetooth/l2cap.c | 134 |
1 files changed, 40 insertions, 94 deletions
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 123efb46d3f5..eadf09231866 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) | |||
263 | { | 263 | { |
264 | struct l2cap_conn *conn = l2cap_pi(sk)->conn; | 264 | struct l2cap_conn *conn = l2cap_pi(sk)->conn; |
265 | 265 | ||
266 | if ((l2cap_pi(sk)->link_mode & L2CAP_LM_ENCRYPT) || | 266 | if (l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE) |
267 | (l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE)) | 267 | return hci_conn_security(conn->hcon, BT_SECURITY_HIGH); |
268 | return hci_conn_encrypt(conn->hcon); | 268 | |
269 | if (l2cap_pi(sk)->link_mode & L2CAP_LM_ENCRYPT) | ||
270 | return hci_conn_security(conn->hcon, BT_SECURITY_MEDIUM); | ||
269 | 271 | ||
270 | if (l2cap_pi(sk)->link_mode & L2CAP_LM_AUTH) | 272 | if (l2cap_pi(sk)->link_mode & L2CAP_LM_AUTH) |
271 | return hci_conn_auth(conn->hcon); | 273 | return hci_conn_security(conn->hcon, BT_SECURITY_LOW); |
274 | |||
275 | if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) | ||
276 | return hci_conn_security(conn->hcon, BT_SECURITY_SDP); | ||
272 | 277 | ||
273 | return 1; | 278 | return 1; |
274 | } | 279 | } |
@@ -803,6 +808,7 @@ static int l2cap_do_connect(struct sock *sk) | |||
803 | struct l2cap_conn *conn; | 808 | struct l2cap_conn *conn; |
804 | struct hci_conn *hcon; | 809 | struct hci_conn *hcon; |
805 | struct hci_dev *hdev; | 810 | struct hci_dev *hdev; |
811 | __u8 sec_level; | ||
806 | __u8 auth_type; | 812 | __u8 auth_type; |
807 | int err = 0; | 813 | int err = 0; |
808 | 814 | ||
@@ -815,21 +821,37 @@ static int l2cap_do_connect(struct sock *sk) | |||
815 | 821 | ||
816 | err = -ENOMEM; | 822 | err = -ENOMEM; |
817 | 823 | ||
818 | if (l2cap_pi(sk)->link_mode & L2CAP_LM_AUTH || | 824 | if (l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE) |
819 | l2cap_pi(sk)->link_mode & L2CAP_LM_ENCRYPT || | 825 | sec_level = BT_SECURITY_HIGH; |
820 | l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE) { | 826 | else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) |
821 | if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) | 827 | sec_level = BT_SECURITY_SDP; |
822 | auth_type = HCI_AT_NO_BONDING_MITM; | 828 | else if (l2cap_pi(sk)->link_mode & L2CAP_LM_ENCRYPT) |
829 | sec_level = BT_SECURITY_MEDIUM; | ||
830 | else | ||
831 | sec_level = BT_SECURITY_LOW; | ||
832 | |||
833 | if (sk->sk_type == SOCK_RAW) { | ||
834 | if (l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE) | ||
835 | auth_type = HCI_AT_DEDICATED_BONDING_MITM; | ||
836 | else if (l2cap_pi(sk)->link_mode & L2CAP_LM_ENCRYPT) | ||
837 | auth_type = HCI_AT_DEDICATED_BONDING; | ||
823 | else | 838 | else |
824 | auth_type = HCI_AT_GENERAL_BONDING_MITM; | ||
825 | } else { | ||
826 | if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) | ||
827 | auth_type = HCI_AT_NO_BONDING; | 839 | auth_type = HCI_AT_NO_BONDING; |
840 | } else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) { | ||
841 | if (l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE) | ||
842 | auth_type = HCI_AT_NO_BONDING_MITM; | ||
828 | else | 843 | else |
844 | auth_type = HCI_AT_NO_BONDING; | ||
845 | } else { | ||
846 | if (l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE) | ||
847 | auth_type = HCI_AT_GENERAL_BONDING_MITM; | ||
848 | else if (l2cap_pi(sk)->link_mode & L2CAP_LM_ENCRYPT) | ||
829 | auth_type = HCI_AT_GENERAL_BONDING; | 849 | auth_type = HCI_AT_GENERAL_BONDING; |
850 | else | ||
851 | auth_type = HCI_AT_NO_BONDING; | ||
830 | } | 852 | } |
831 | 853 | ||
832 | hcon = hci_connect(hdev, ACL_LINK, dst, auth_type); | 854 | hcon = hci_connect(hdev, ACL_LINK, dst, sec_level, auth_type); |
833 | if (!hcon) | 855 | if (!hcon) |
834 | goto done; | 856 | goto done; |
835 | 857 | ||
@@ -1402,11 +1424,6 @@ static void l2cap_chan_ready(struct sock *sk) | |||
1402 | */ | 1424 | */ |
1403 | parent->sk_data_ready(parent, 0); | 1425 | parent->sk_data_ready(parent, 0); |
1404 | } | 1426 | } |
1405 | |||
1406 | if (l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE) { | ||
1407 | struct l2cap_conn *conn = l2cap_pi(sk)->conn; | ||
1408 | hci_conn_change_link_key(conn->hcon); | ||
1409 | } | ||
1410 | } | 1427 | } |
1411 | 1428 | ||
1412 | /* Copy frame to all raw sockets on that connection */ | 1429 | /* Copy frame to all raw sockets on that connection */ |
@@ -2323,77 +2340,7 @@ static int l2cap_disconn_ind(struct hci_conn *hcon, u8 reason) | |||
2323 | return 0; | 2340 | return 0; |
2324 | } | 2341 | } |
2325 | 2342 | ||
2326 | static int l2cap_auth_cfm(struct hci_conn *hcon, u8 status) | 2343 | static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) |
2327 | { | ||
2328 | struct l2cap_chan_list *l; | ||
2329 | struct l2cap_conn *conn = hcon->l2cap_data; | ||
2330 | struct sock *sk; | ||
2331 | |||
2332 | if (!conn) | ||
2333 | return 0; | ||
2334 | |||
2335 | l = &conn->chan_list; | ||
2336 | |||
2337 | BT_DBG("conn %p", conn); | ||
2338 | |||
2339 | read_lock(&l->lock); | ||
2340 | |||
2341 | for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { | ||
2342 | struct l2cap_pinfo *pi = l2cap_pi(sk); | ||
2343 | |||
2344 | bh_lock_sock(sk); | ||
2345 | |||
2346 | if ((pi->link_mode & (L2CAP_LM_ENCRYPT | L2CAP_LM_SECURE)) && | ||
2347 | !(hcon->link_mode & HCI_LM_ENCRYPT) && | ||
2348 | !status) { | ||
2349 | bh_unlock_sock(sk); | ||
2350 | continue; | ||
2351 | } | ||
2352 | |||
2353 | if (sk->sk_state == BT_CONNECT) { | ||
2354 | if (!status) { | ||
2355 | struct l2cap_conn_req req; | ||
2356 | req.scid = cpu_to_le16(l2cap_pi(sk)->scid); | ||
2357 | req.psm = l2cap_pi(sk)->psm; | ||
2358 | |||
2359 | l2cap_pi(sk)->ident = l2cap_get_ident(conn); | ||
2360 | |||
2361 | l2cap_send_cmd(conn, l2cap_pi(sk)->ident, | ||
2362 | L2CAP_CONN_REQ, sizeof(req), &req); | ||
2363 | } else { | ||
2364 | l2cap_sock_clear_timer(sk); | ||
2365 | l2cap_sock_set_timer(sk, HZ / 10); | ||
2366 | } | ||
2367 | } else if (sk->sk_state == BT_CONNECT2) { | ||
2368 | struct l2cap_conn_rsp rsp; | ||
2369 | __u16 result; | ||
2370 | |||
2371 | if (!status) { | ||
2372 | sk->sk_state = BT_CONFIG; | ||
2373 | result = L2CAP_CR_SUCCESS; | ||
2374 | } else { | ||
2375 | sk->sk_state = BT_DISCONN; | ||
2376 | l2cap_sock_set_timer(sk, HZ / 10); | ||
2377 | result = L2CAP_CR_SEC_BLOCK; | ||
2378 | } | ||
2379 | |||
2380 | rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); | ||
2381 | rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); | ||
2382 | rsp.result = cpu_to_le16(result); | ||
2383 | rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); | ||
2384 | l2cap_send_cmd(conn, l2cap_pi(sk)->ident, | ||
2385 | L2CAP_CONN_RSP, sizeof(rsp), &rsp); | ||
2386 | } | ||
2387 | |||
2388 | bh_unlock_sock(sk); | ||
2389 | } | ||
2390 | |||
2391 | read_unlock(&l->lock); | ||
2392 | |||
2393 | return 0; | ||
2394 | } | ||
2395 | |||
2396 | static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) | ||
2397 | { | 2344 | { |
2398 | struct l2cap_chan_list *l; | 2345 | struct l2cap_chan_list *l; |
2399 | struct l2cap_conn *conn = hcon->l2cap_data; | 2346 | struct l2cap_conn *conn = hcon->l2cap_data; |
@@ -2413,10 +2360,10 @@ static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) | |||
2413 | 2360 | ||
2414 | bh_lock_sock(sk); | 2361 | bh_lock_sock(sk); |
2415 | 2362 | ||
2416 | if ((pi->link_mode & (L2CAP_LM_ENCRYPT | L2CAP_LM_SECURE)) && | 2363 | if (!status && encrypt == 0x00 && |
2364 | (pi->link_mode & L2CAP_LM_SECURE) && | ||
2417 | (sk->sk_state == BT_CONNECTED || | 2365 | (sk->sk_state == BT_CONNECTED || |
2418 | sk->sk_state == BT_CONFIG) && | 2366 | sk->sk_state == BT_CONFIG)) { |
2419 | !status && encrypt == 0x00) { | ||
2420 | __l2cap_sock_close(sk, ECONNREFUSED); | 2367 | __l2cap_sock_close(sk, ECONNREFUSED); |
2421 | bh_unlock_sock(sk); | 2368 | bh_unlock_sock(sk); |
2422 | continue; | 2369 | continue; |
@@ -2608,8 +2555,7 @@ static struct hci_proto l2cap_hci_proto = { | |||
2608 | .connect_ind = l2cap_connect_ind, | 2555 | .connect_ind = l2cap_connect_ind, |
2609 | .connect_cfm = l2cap_connect_cfm, | 2556 | .connect_cfm = l2cap_connect_cfm, |
2610 | .disconn_ind = l2cap_disconn_ind, | 2557 | .disconn_ind = l2cap_disconn_ind, |
2611 | .auth_cfm = l2cap_auth_cfm, | 2558 | .security_cfm = l2cap_security_cfm, |
2612 | .encrypt_cfm = l2cap_encrypt_cfm, | ||
2613 | .recv_acldata = l2cap_recv_acldata | 2559 | .recv_acldata = l2cap_recv_acldata |
2614 | }; | 2560 | }; |
2615 | 2561 | ||