diff options
author | David S. Miller <davem@davemloft.net> | 2008-07-19 03:30:39 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-07-19 03:30:39 -0400 |
commit | 407d819cf0fd54c6fc1138a509225696aecafd15 (patch) | |
tree | b653a5c8c09f7c316f5f98947be262e27a4ca33a /net/bluetooth/l2cap.c | |
parent | 7abbcd6a4c8d6179121f2915a761b1133bf1cd99 (diff) | |
parent | b1235d79611e78a07629b4cbe53291c9cffd1834 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/holtmann/bluetooth-2.6
Diffstat (limited to 'net/bluetooth/l2cap.c')
-rw-r--r-- | net/bluetooth/l2cap.c | 337 |
1 files changed, 234 insertions, 103 deletions
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 6e180d255505..c1239852834a 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c | |||
@@ -55,7 +55,7 @@ | |||
55 | #define BT_DBG(D...) | 55 | #define BT_DBG(D...) |
56 | #endif | 56 | #endif |
57 | 57 | ||
58 | #define VERSION "2.9" | 58 | #define VERSION "2.10" |
59 | 59 | ||
60 | static u32 l2cap_feat_mask = 0x0000; | 60 | static u32 l2cap_feat_mask = 0x0000; |
61 | 61 | ||
@@ -76,11 +76,21 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, | |||
76 | static void l2cap_sock_timeout(unsigned long arg) | 76 | static void l2cap_sock_timeout(unsigned long arg) |
77 | { | 77 | { |
78 | struct sock *sk = (struct sock *) arg; | 78 | struct sock *sk = (struct sock *) arg; |
79 | int reason; | ||
79 | 80 | ||
80 | BT_DBG("sock %p state %d", sk, sk->sk_state); | 81 | BT_DBG("sock %p state %d", sk, sk->sk_state); |
81 | 82 | ||
82 | bh_lock_sock(sk); | 83 | bh_lock_sock(sk); |
83 | __l2cap_sock_close(sk, ETIMEDOUT); | 84 | |
85 | if (sk->sk_state == BT_CONNECT && | ||
86 | (l2cap_pi(sk)->link_mode & (L2CAP_LM_AUTH | | ||
87 | L2CAP_LM_ENCRYPT | L2CAP_LM_SECURE))) | ||
88 | reason = ECONNREFUSED; | ||
89 | else | ||
90 | reason = ETIMEDOUT; | ||
91 | |||
92 | __l2cap_sock_close(sk, reason); | ||
93 | |||
84 | bh_unlock_sock(sk); | 94 | bh_unlock_sock(sk); |
85 | 95 | ||
86 | l2cap_sock_kill(sk); | 96 | l2cap_sock_kill(sk); |
@@ -240,7 +250,7 @@ static void l2cap_chan_del(struct sock *sk, int err) | |||
240 | hci_conn_put(conn->hcon); | 250 | hci_conn_put(conn->hcon); |
241 | } | 251 | } |
242 | 252 | ||
243 | sk->sk_state = BT_CLOSED; | 253 | sk->sk_state = BT_CLOSED; |
244 | sock_set_flag(sk, SOCK_ZAPPED); | 254 | sock_set_flag(sk, SOCK_ZAPPED); |
245 | 255 | ||
246 | if (err) | 256 | if (err) |
@@ -253,6 +263,21 @@ static void l2cap_chan_del(struct sock *sk, int err) | |||
253 | sk->sk_state_change(sk); | 263 | sk->sk_state_change(sk); |
254 | } | 264 | } |
255 | 265 | ||
266 | /* Service level security */ | ||
267 | static inline int l2cap_check_link_mode(struct sock *sk) | ||
268 | { | ||
269 | struct l2cap_conn *conn = l2cap_pi(sk)->conn; | ||
270 | |||
271 | if ((l2cap_pi(sk)->link_mode & L2CAP_LM_ENCRYPT) || | ||
272 | (l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE)) | ||
273 | return hci_conn_encrypt(conn->hcon); | ||
274 | |||
275 | if (l2cap_pi(sk)->link_mode & L2CAP_LM_AUTH) | ||
276 | return hci_conn_auth(conn->hcon); | ||
277 | |||
278 | return 1; | ||
279 | } | ||
280 | |||
256 | static inline u8 l2cap_get_ident(struct l2cap_conn *conn) | 281 | static inline u8 l2cap_get_ident(struct l2cap_conn *conn) |
257 | { | 282 | { |
258 | u8 id; | 283 | u8 id; |
@@ -287,6 +312,36 @@ static inline int l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 | |||
287 | return hci_send_acl(conn->hcon, skb, 0); | 312 | return hci_send_acl(conn->hcon, skb, 0); |
288 | } | 313 | } |
289 | 314 | ||
315 | static void l2cap_do_start(struct sock *sk) | ||
316 | { | ||
317 | struct l2cap_conn *conn = l2cap_pi(sk)->conn; | ||
318 | |||
319 | if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) { | ||
320 | if (l2cap_check_link_mode(sk)) { | ||
321 | struct l2cap_conn_req req; | ||
322 | req.scid = cpu_to_le16(l2cap_pi(sk)->scid); | ||
323 | req.psm = l2cap_pi(sk)->psm; | ||
324 | |||
325 | l2cap_pi(sk)->ident = l2cap_get_ident(conn); | ||
326 | |||
327 | l2cap_send_cmd(conn, l2cap_pi(sk)->ident, | ||
328 | L2CAP_CONN_REQ, sizeof(req), &req); | ||
329 | } | ||
330 | } else { | ||
331 | struct l2cap_info_req req; | ||
332 | req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); | ||
333 | |||
334 | conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; | ||
335 | conn->info_ident = l2cap_get_ident(conn); | ||
336 | |||
337 | mod_timer(&conn->info_timer, jiffies + | ||
338 | msecs_to_jiffies(L2CAP_INFO_TIMEOUT)); | ||
339 | |||
340 | l2cap_send_cmd(conn, conn->info_ident, | ||
341 | L2CAP_INFO_REQ, sizeof(req), &req); | ||
342 | } | ||
343 | } | ||
344 | |||
290 | /* ---- L2CAP connections ---- */ | 345 | /* ---- L2CAP connections ---- */ |
291 | static void l2cap_conn_start(struct l2cap_conn *conn) | 346 | static void l2cap_conn_start(struct l2cap_conn *conn) |
292 | { | 347 | { |
@@ -301,16 +356,37 @@ static void l2cap_conn_start(struct l2cap_conn *conn) | |||
301 | bh_lock_sock(sk); | 356 | bh_lock_sock(sk); |
302 | 357 | ||
303 | if (sk->sk_type != SOCK_SEQPACKET) { | 358 | if (sk->sk_type != SOCK_SEQPACKET) { |
304 | l2cap_sock_clear_timer(sk); | 359 | bh_unlock_sock(sk); |
305 | sk->sk_state = BT_CONNECTED; | 360 | continue; |
306 | sk->sk_state_change(sk); | 361 | } |
307 | } else if (sk->sk_state == BT_CONNECT) { | 362 | |
308 | struct l2cap_conn_req req; | 363 | if (sk->sk_state == BT_CONNECT) { |
309 | l2cap_pi(sk)->ident = l2cap_get_ident(conn); | 364 | if (l2cap_check_link_mode(sk)) { |
310 | req.scid = cpu_to_le16(l2cap_pi(sk)->scid); | 365 | struct l2cap_conn_req req; |
311 | req.psm = l2cap_pi(sk)->psm; | 366 | req.scid = cpu_to_le16(l2cap_pi(sk)->scid); |
312 | l2cap_send_cmd(conn, l2cap_pi(sk)->ident, | 367 | req.psm = l2cap_pi(sk)->psm; |
368 | |||
369 | l2cap_pi(sk)->ident = l2cap_get_ident(conn); | ||
370 | |||
371 | l2cap_send_cmd(conn, l2cap_pi(sk)->ident, | ||
313 | L2CAP_CONN_REQ, sizeof(req), &req); | 372 | L2CAP_CONN_REQ, sizeof(req), &req); |
373 | } | ||
374 | } else if (sk->sk_state == BT_CONNECT2) { | ||
375 | struct l2cap_conn_rsp rsp; | ||
376 | rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); | ||
377 | rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); | ||
378 | |||
379 | if (l2cap_check_link_mode(sk)) { | ||
380 | sk->sk_state = BT_CONFIG; | ||
381 | rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); | ||
382 | rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); | ||
383 | } else { | ||
384 | rsp.result = cpu_to_le16(L2CAP_CR_PEND); | ||
385 | rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND); | ||
386 | } | ||
387 | |||
388 | l2cap_send_cmd(conn, l2cap_pi(sk)->ident, | ||
389 | L2CAP_CONN_RSP, sizeof(rsp), &rsp); | ||
314 | } | 390 | } |
315 | 391 | ||
316 | bh_unlock_sock(sk); | 392 | bh_unlock_sock(sk); |
@@ -321,22 +397,27 @@ static void l2cap_conn_start(struct l2cap_conn *conn) | |||
321 | 397 | ||
322 | static void l2cap_conn_ready(struct l2cap_conn *conn) | 398 | static void l2cap_conn_ready(struct l2cap_conn *conn) |
323 | { | 399 | { |
324 | BT_DBG("conn %p", conn); | 400 | struct l2cap_chan_list *l = &conn->chan_list; |
401 | struct sock *sk; | ||
325 | 402 | ||
326 | if (conn->chan_list.head || !hlist_empty(&l2cap_sk_list.head)) { | 403 | BT_DBG("conn %p", conn); |
327 | struct l2cap_info_req req; | ||
328 | 404 | ||
329 | req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); | 405 | read_lock(&l->lock); |
330 | 406 | ||
331 | conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; | 407 | for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { |
332 | conn->info_ident = l2cap_get_ident(conn); | 408 | bh_lock_sock(sk); |
333 | 409 | ||
334 | mod_timer(&conn->info_timer, | 410 | if (sk->sk_type != SOCK_SEQPACKET) { |
335 | jiffies + msecs_to_jiffies(L2CAP_INFO_TIMEOUT)); | 411 | l2cap_sock_clear_timer(sk); |
412 | sk->sk_state = BT_CONNECTED; | ||
413 | sk->sk_state_change(sk); | ||
414 | } else if (sk->sk_state == BT_CONNECT) | ||
415 | l2cap_do_start(sk); | ||
336 | 416 | ||
337 | l2cap_send_cmd(conn, conn->info_ident, | 417 | bh_unlock_sock(sk); |
338 | L2CAP_INFO_REQ, sizeof(req), &req); | ||
339 | } | 418 | } |
419 | |||
420 | read_unlock(&l->lock); | ||
340 | } | 421 | } |
341 | 422 | ||
342 | /* Notify sockets that we cannot guaranty reliability anymore */ | 423 | /* Notify sockets that we cannot guaranty reliability anymore */ |
@@ -388,7 +469,8 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status) | |||
388 | 469 | ||
389 | conn->feat_mask = 0; | 470 | conn->feat_mask = 0; |
390 | 471 | ||
391 | setup_timer(&conn->info_timer, l2cap_info_timeout, (unsigned long)conn); | 472 | setup_timer(&conn->info_timer, l2cap_info_timeout, |
473 | (unsigned long) conn); | ||
392 | 474 | ||
393 | spin_lock_init(&conn->lock); | 475 | spin_lock_init(&conn->lock); |
394 | rwlock_init(&conn->chan_list.lock); | 476 | rwlock_init(&conn->chan_list.lock); |
@@ -500,7 +582,7 @@ static void l2cap_sock_cleanup_listen(struct sock *parent) | |||
500 | while ((sk = bt_accept_dequeue(parent, NULL))) | 582 | while ((sk = bt_accept_dequeue(parent, NULL))) |
501 | l2cap_sock_close(sk); | 583 | l2cap_sock_close(sk); |
502 | 584 | ||
503 | parent->sk_state = BT_CLOSED; | 585 | parent->sk_state = BT_CLOSED; |
504 | sock_set_flag(parent, SOCK_ZAPPED); | 586 | sock_set_flag(parent, SOCK_ZAPPED); |
505 | } | 587 | } |
506 | 588 | ||
@@ -543,9 +625,8 @@ static void __l2cap_sock_close(struct sock *sk, int reason) | |||
543 | req.scid = cpu_to_le16(l2cap_pi(sk)->scid); | 625 | req.scid = cpu_to_le16(l2cap_pi(sk)->scid); |
544 | l2cap_send_cmd(conn, l2cap_get_ident(conn), | 626 | l2cap_send_cmd(conn, l2cap_get_ident(conn), |
545 | L2CAP_DISCONN_REQ, sizeof(req), &req); | 627 | L2CAP_DISCONN_REQ, sizeof(req), &req); |
546 | } else { | 628 | } else |
547 | l2cap_chan_del(sk, reason); | 629 | l2cap_chan_del(sk, reason); |
548 | } | ||
549 | break; | 630 | break; |
550 | 631 | ||
551 | case BT_CONNECT: | 632 | case BT_CONNECT: |
@@ -614,9 +695,9 @@ static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int p | |||
614 | sock_reset_flag(sk, SOCK_ZAPPED); | 695 | sock_reset_flag(sk, SOCK_ZAPPED); |
615 | 696 | ||
616 | sk->sk_protocol = proto; | 697 | sk->sk_protocol = proto; |
617 | sk->sk_state = BT_OPEN; | 698 | sk->sk_state = BT_OPEN; |
618 | 699 | ||
619 | setup_timer(&sk->sk_timer, l2cap_sock_timeout, (unsigned long)sk); | 700 | setup_timer(&sk->sk_timer, l2cap_sock_timeout, (unsigned long) sk); |
620 | 701 | ||
621 | bt_sock_link(&l2cap_sk_list, sk); | 702 | bt_sock_link(&l2cap_sk_list, sk); |
622 | return sk; | 703 | return sk; |
@@ -729,22 +810,11 @@ static int l2cap_do_connect(struct sock *sk) | |||
729 | l2cap_sock_set_timer(sk, sk->sk_sndtimeo); | 810 | l2cap_sock_set_timer(sk, sk->sk_sndtimeo); |
730 | 811 | ||
731 | if (hcon->state == BT_CONNECTED) { | 812 | if (hcon->state == BT_CONNECTED) { |
732 | if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)) { | 813 | if (sk->sk_type != SOCK_SEQPACKET) { |
733 | l2cap_conn_ready(conn); | ||
734 | goto done; | ||
735 | } | ||
736 | |||
737 | if (sk->sk_type == SOCK_SEQPACKET) { | ||
738 | struct l2cap_conn_req req; | ||
739 | l2cap_pi(sk)->ident = l2cap_get_ident(conn); | ||
740 | req.scid = cpu_to_le16(l2cap_pi(sk)->scid); | ||
741 | req.psm = l2cap_pi(sk)->psm; | ||
742 | l2cap_send_cmd(conn, l2cap_pi(sk)->ident, | ||
743 | L2CAP_CONN_REQ, sizeof(req), &req); | ||
744 | } else { | ||
745 | l2cap_sock_clear_timer(sk); | 814 | l2cap_sock_clear_timer(sk); |
746 | sk->sk_state = BT_CONNECTED; | 815 | sk->sk_state = BT_CONNECTED; |
747 | } | 816 | } else |
817 | l2cap_do_start(sk); | ||
748 | } | 818 | } |
749 | 819 | ||
750 | done: | 820 | done: |
@@ -1145,7 +1215,8 @@ static int l2cap_sock_shutdown(struct socket *sock, int how) | |||
1145 | __l2cap_sock_close(sk, 0); | 1215 | __l2cap_sock_close(sk, 0); |
1146 | 1216 | ||
1147 | if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) | 1217 | if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) |
1148 | err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime); | 1218 | err = bt_sock_wait_state(sk, BT_CLOSED, |
1219 | sk->sk_lingertime); | ||
1149 | } | 1220 | } |
1150 | release_sock(sk); | 1221 | release_sock(sk); |
1151 | return err; | 1222 | return err; |
@@ -1189,6 +1260,11 @@ static void l2cap_chan_ready(struct sock *sk) | |||
1189 | */ | 1260 | */ |
1190 | parent->sk_data_ready(parent, 0); | 1261 | parent->sk_data_ready(parent, 0); |
1191 | } | 1262 | } |
1263 | |||
1264 | if (l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE) { | ||
1265 | struct l2cap_conn *conn = l2cap_pi(sk)->conn; | ||
1266 | hci_conn_change_link_key(conn->hcon); | ||
1267 | } | ||
1192 | } | 1268 | } |
1193 | 1269 | ||
1194 | /* Copy frame to all raw sockets on that connection */ | 1270 | /* Copy frame to all raw sockets on that connection */ |
@@ -1477,7 +1553,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
1477 | struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; | 1553 | struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; |
1478 | struct l2cap_conn_rsp rsp; | 1554 | struct l2cap_conn_rsp rsp; |
1479 | struct sock *sk, *parent; | 1555 | struct sock *sk, *parent; |
1480 | int result = 0, status = 0; | 1556 | int result, status = 0; |
1481 | 1557 | ||
1482 | u16 dcid = 0, scid = __le16_to_cpu(req->scid); | 1558 | u16 dcid = 0, scid = __le16_to_cpu(req->scid); |
1483 | __le16 psm = req->psm; | 1559 | __le16 psm = req->psm; |
@@ -1526,25 +1602,24 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
1526 | 1602 | ||
1527 | l2cap_sock_set_timer(sk, sk->sk_sndtimeo); | 1603 | l2cap_sock_set_timer(sk, sk->sk_sndtimeo); |
1528 | 1604 | ||
1529 | /* Service level security */ | ||
1530 | result = L2CAP_CR_PEND; | ||
1531 | status = L2CAP_CS_AUTHEN_PEND; | ||
1532 | sk->sk_state = BT_CONNECT2; | ||
1533 | l2cap_pi(sk)->ident = cmd->ident; | 1605 | l2cap_pi(sk)->ident = cmd->ident; |
1534 | 1606 | ||
1535 | if ((l2cap_pi(sk)->link_mode & L2CAP_LM_ENCRYPT) || | 1607 | if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) { |
1536 | (l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE)) { | 1608 | if (l2cap_check_link_mode(sk)) { |
1537 | if (!hci_conn_encrypt(conn->hcon)) | 1609 | sk->sk_state = BT_CONFIG; |
1538 | goto done; | 1610 | result = L2CAP_CR_SUCCESS; |
1539 | } else if (l2cap_pi(sk)->link_mode & L2CAP_LM_AUTH) { | 1611 | status = L2CAP_CS_NO_INFO; |
1540 | if (!hci_conn_auth(conn->hcon)) | 1612 | } else { |
1541 | goto done; | 1613 | sk->sk_state = BT_CONNECT2; |
1614 | result = L2CAP_CR_PEND; | ||
1615 | status = L2CAP_CS_AUTHEN_PEND; | ||
1616 | } | ||
1617 | } else { | ||
1618 | sk->sk_state = BT_CONNECT2; | ||
1619 | result = L2CAP_CR_PEND; | ||
1620 | status = L2CAP_CS_NO_INFO; | ||
1542 | } | 1621 | } |
1543 | 1622 | ||
1544 | sk->sk_state = BT_CONFIG; | ||
1545 | result = status = 0; | ||
1546 | |||
1547 | done: | ||
1548 | write_unlock_bh(&list->lock); | 1623 | write_unlock_bh(&list->lock); |
1549 | 1624 | ||
1550 | response: | 1625 | response: |
@@ -1556,6 +1631,21 @@ sendresp: | |||
1556 | rsp.result = cpu_to_le16(result); | 1631 | rsp.result = cpu_to_le16(result); |
1557 | rsp.status = cpu_to_le16(status); | 1632 | rsp.status = cpu_to_le16(status); |
1558 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); | 1633 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); |
1634 | |||
1635 | if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) { | ||
1636 | struct l2cap_info_req info; | ||
1637 | info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); | ||
1638 | |||
1639 | conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; | ||
1640 | conn->info_ident = l2cap_get_ident(conn); | ||
1641 | |||
1642 | mod_timer(&conn->info_timer, jiffies + | ||
1643 | msecs_to_jiffies(L2CAP_INFO_TIMEOUT)); | ||
1644 | |||
1645 | l2cap_send_cmd(conn, conn->info_ident, | ||
1646 | L2CAP_INFO_REQ, sizeof(info), &info); | ||
1647 | } | ||
1648 | |||
1559 | return 0; | 1649 | return 0; |
1560 | } | 1650 | } |
1561 | 1651 | ||
@@ -1664,9 +1754,9 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
1664 | } | 1754 | } |
1665 | 1755 | ||
1666 | if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) { | 1756 | if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) { |
1667 | u8 req[64]; | 1757 | u8 buf[64]; |
1668 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, | 1758 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, |
1669 | l2cap_build_conf_req(sk, req), req); | 1759 | l2cap_build_conf_req(sk, buf), buf); |
1670 | } | 1760 | } |
1671 | 1761 | ||
1672 | unlock: | 1762 | unlock: |
@@ -1708,7 +1798,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
1708 | 1798 | ||
1709 | default: | 1799 | default: |
1710 | sk->sk_state = BT_DISCONN; | 1800 | sk->sk_state = BT_DISCONN; |
1711 | sk->sk_err = ECONNRESET; | 1801 | sk->sk_err = ECONNRESET; |
1712 | l2cap_sock_set_timer(sk, HZ * 5); | 1802 | l2cap_sock_set_timer(sk, HZ * 5); |
1713 | { | 1803 | { |
1714 | struct l2cap_disconn_req req; | 1804 | struct l2cap_disconn_req req; |
@@ -2080,10 +2170,8 @@ static int l2cap_disconn_ind(struct hci_conn *hcon, u8 reason) | |||
2080 | static int l2cap_auth_cfm(struct hci_conn *hcon, u8 status) | 2170 | static int l2cap_auth_cfm(struct hci_conn *hcon, u8 status) |
2081 | { | 2171 | { |
2082 | struct l2cap_chan_list *l; | 2172 | struct l2cap_chan_list *l; |
2083 | struct l2cap_conn *conn = conn = hcon->l2cap_data; | 2173 | struct l2cap_conn *conn = hcon->l2cap_data; |
2084 | struct l2cap_conn_rsp rsp; | ||
2085 | struct sock *sk; | 2174 | struct sock *sk; |
2086 | int result; | ||
2087 | 2175 | ||
2088 | if (!conn) | 2176 | if (!conn) |
2089 | return 0; | 2177 | return 0; |
@@ -2095,45 +2183,65 @@ static int l2cap_auth_cfm(struct hci_conn *hcon, u8 status) | |||
2095 | read_lock(&l->lock); | 2183 | read_lock(&l->lock); |
2096 | 2184 | ||
2097 | for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { | 2185 | for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { |
2186 | struct l2cap_pinfo *pi = l2cap_pi(sk); | ||
2187 | |||
2098 | bh_lock_sock(sk); | 2188 | bh_lock_sock(sk); |
2099 | 2189 | ||
2100 | if (sk->sk_state != BT_CONNECT2 || | 2190 | if ((pi->link_mode & (L2CAP_LM_ENCRYPT | L2CAP_LM_SECURE)) && |
2101 | (l2cap_pi(sk)->link_mode & L2CAP_LM_ENCRYPT) || | 2191 | !(hcon->link_mode & HCI_LM_ENCRYPT) && |
2102 | (l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE)) { | 2192 | !status) { |
2103 | bh_unlock_sock(sk); | 2193 | bh_unlock_sock(sk); |
2104 | continue; | 2194 | continue; |
2105 | } | 2195 | } |
2106 | 2196 | ||
2107 | if (!status) { | 2197 | if (sk->sk_state == BT_CONNECT) { |
2108 | sk->sk_state = BT_CONFIG; | 2198 | if (!status) { |
2109 | result = 0; | 2199 | struct l2cap_conn_req req; |
2110 | } else { | 2200 | req.scid = cpu_to_le16(l2cap_pi(sk)->scid); |
2111 | sk->sk_state = BT_DISCONN; | 2201 | req.psm = l2cap_pi(sk)->psm; |
2112 | l2cap_sock_set_timer(sk, HZ/10); | ||
2113 | result = L2CAP_CR_SEC_BLOCK; | ||
2114 | } | ||
2115 | 2202 | ||
2116 | rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); | 2203 | l2cap_pi(sk)->ident = l2cap_get_ident(conn); |
2117 | rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); | 2204 | |
2118 | rsp.result = cpu_to_le16(result); | 2205 | l2cap_send_cmd(conn, l2cap_pi(sk)->ident, |
2119 | rsp.status = cpu_to_le16(0); | 2206 | L2CAP_CONN_REQ, sizeof(req), &req); |
2120 | l2cap_send_cmd(conn, l2cap_pi(sk)->ident, | 2207 | } else { |
2121 | L2CAP_CONN_RSP, sizeof(rsp), &rsp); | 2208 | l2cap_sock_clear_timer(sk); |
2209 | l2cap_sock_set_timer(sk, HZ / 10); | ||
2210 | } | ||
2211 | } else if (sk->sk_state == BT_CONNECT2) { | ||
2212 | struct l2cap_conn_rsp rsp; | ||
2213 | __u16 result; | ||
2214 | |||
2215 | if (!status) { | ||
2216 | sk->sk_state = BT_CONFIG; | ||
2217 | result = L2CAP_CR_SUCCESS; | ||
2218 | } else { | ||
2219 | sk->sk_state = BT_DISCONN; | ||
2220 | l2cap_sock_set_timer(sk, HZ / 10); | ||
2221 | result = L2CAP_CR_SEC_BLOCK; | ||
2222 | } | ||
2223 | |||
2224 | rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); | ||
2225 | rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); | ||
2226 | rsp.result = cpu_to_le16(result); | ||
2227 | rsp.status = cpu_to_le16(0); | ||
2228 | l2cap_send_cmd(conn, l2cap_pi(sk)->ident, | ||
2229 | L2CAP_CONN_RSP, sizeof(rsp), &rsp); | ||
2230 | } | ||
2122 | 2231 | ||
2123 | bh_unlock_sock(sk); | 2232 | bh_unlock_sock(sk); |
2124 | } | 2233 | } |
2125 | 2234 | ||
2126 | read_unlock(&l->lock); | 2235 | read_unlock(&l->lock); |
2236 | |||
2127 | return 0; | 2237 | return 0; |
2128 | } | 2238 | } |
2129 | 2239 | ||
2130 | static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status) | 2240 | static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) |
2131 | { | 2241 | { |
2132 | struct l2cap_chan_list *l; | 2242 | struct l2cap_chan_list *l; |
2133 | struct l2cap_conn *conn = hcon->l2cap_data; | 2243 | struct l2cap_conn *conn = hcon->l2cap_data; |
2134 | struct l2cap_conn_rsp rsp; | ||
2135 | struct sock *sk; | 2244 | struct sock *sk; |
2136 | int result; | ||
2137 | 2245 | ||
2138 | if (!conn) | 2246 | if (!conn) |
2139 | return 0; | 2247 | return 0; |
@@ -2145,36 +2253,59 @@ static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status) | |||
2145 | read_lock(&l->lock); | 2253 | read_lock(&l->lock); |
2146 | 2254 | ||
2147 | for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { | 2255 | for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { |
2256 | struct l2cap_pinfo *pi = l2cap_pi(sk); | ||
2257 | |||
2148 | bh_lock_sock(sk); | 2258 | bh_lock_sock(sk); |
2149 | 2259 | ||
2150 | if (sk->sk_state != BT_CONNECT2) { | 2260 | if ((pi->link_mode & (L2CAP_LM_ENCRYPT | L2CAP_LM_SECURE)) && |
2261 | (sk->sk_state == BT_CONNECTED || | ||
2262 | sk->sk_state == BT_CONFIG) && | ||
2263 | !status && encrypt == 0x00) { | ||
2264 | __l2cap_sock_close(sk, ECONNREFUSED); | ||
2151 | bh_unlock_sock(sk); | 2265 | bh_unlock_sock(sk); |
2152 | continue; | 2266 | continue; |
2153 | } | 2267 | } |
2154 | 2268 | ||
2155 | if (!status) { | 2269 | if (sk->sk_state == BT_CONNECT) { |
2156 | sk->sk_state = BT_CONFIG; | 2270 | if (!status) { |
2157 | result = 0; | 2271 | struct l2cap_conn_req req; |
2158 | } else { | 2272 | req.scid = cpu_to_le16(l2cap_pi(sk)->scid); |
2159 | sk->sk_state = BT_DISCONN; | 2273 | req.psm = l2cap_pi(sk)->psm; |
2160 | l2cap_sock_set_timer(sk, HZ/10); | 2274 | |
2161 | result = L2CAP_CR_SEC_BLOCK; | 2275 | l2cap_pi(sk)->ident = l2cap_get_ident(conn); |
2162 | } | ||
2163 | 2276 | ||
2164 | rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); | 2277 | l2cap_send_cmd(conn, l2cap_pi(sk)->ident, |
2165 | rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); | 2278 | L2CAP_CONN_REQ, sizeof(req), &req); |
2166 | rsp.result = cpu_to_le16(result); | 2279 | } else { |
2167 | rsp.status = cpu_to_le16(0); | 2280 | l2cap_sock_clear_timer(sk); |
2168 | l2cap_send_cmd(conn, l2cap_pi(sk)->ident, | 2281 | l2cap_sock_set_timer(sk, HZ / 10); |
2169 | L2CAP_CONN_RSP, sizeof(rsp), &rsp); | 2282 | } |
2283 | } else if (sk->sk_state == BT_CONNECT2) { | ||
2284 | struct l2cap_conn_rsp rsp; | ||
2285 | __u16 result; | ||
2286 | |||
2287 | if (!status) { | ||
2288 | sk->sk_state = BT_CONFIG; | ||
2289 | result = L2CAP_CR_SUCCESS; | ||
2290 | } else { | ||
2291 | sk->sk_state = BT_DISCONN; | ||
2292 | l2cap_sock_set_timer(sk, HZ / 10); | ||
2293 | result = L2CAP_CR_SEC_BLOCK; | ||
2294 | } | ||
2170 | 2295 | ||
2171 | if (l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE) | 2296 | rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); |
2172 | hci_conn_change_link_key(hcon); | 2297 | rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); |
2298 | rsp.result = cpu_to_le16(result); | ||
2299 | rsp.status = cpu_to_le16(0); | ||
2300 | l2cap_send_cmd(conn, l2cap_pi(sk)->ident, | ||
2301 | L2CAP_CONN_RSP, sizeof(rsp), &rsp); | ||
2302 | } | ||
2173 | 2303 | ||
2174 | bh_unlock_sock(sk); | 2304 | bh_unlock_sock(sk); |
2175 | } | 2305 | } |
2176 | 2306 | ||
2177 | read_unlock(&l->lock); | 2307 | read_unlock(&l->lock); |
2308 | |||
2178 | return 0; | 2309 | return 0; |
2179 | } | 2310 | } |
2180 | 2311 | ||
@@ -2301,9 +2432,9 @@ static const struct proto_ops l2cap_sock_ops = { | |||
2301 | .sendmsg = l2cap_sock_sendmsg, | 2432 | .sendmsg = l2cap_sock_sendmsg, |
2302 | .recvmsg = bt_sock_recvmsg, | 2433 | .recvmsg = bt_sock_recvmsg, |
2303 | .poll = bt_sock_poll, | 2434 | .poll = bt_sock_poll, |
2435 | .ioctl = bt_sock_ioctl, | ||
2304 | .mmap = sock_no_mmap, | 2436 | .mmap = sock_no_mmap, |
2305 | .socketpair = sock_no_socketpair, | 2437 | .socketpair = sock_no_socketpair, |
2306 | .ioctl = sock_no_ioctl, | ||
2307 | .shutdown = l2cap_sock_shutdown, | 2438 | .shutdown = l2cap_sock_shutdown, |
2308 | .setsockopt = l2cap_sock_setsockopt, | 2439 | .setsockopt = l2cap_sock_setsockopt, |
2309 | .getsockopt = l2cap_sock_getsockopt | 2440 | .getsockopt = l2cap_sock_getsockopt |