diff options
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/l2cap.c | 44 |
1 files changed, 41 insertions, 3 deletions
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index a3dfee97ab9d..e366be0792cb 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c | |||
@@ -74,6 +74,7 @@ static void __l2cap_sock_close(struct sock *sk, int reason); | |||
74 | static void l2cap_sock_close(struct sock *sk); | 74 | static void l2cap_sock_close(struct sock *sk); |
75 | static void l2cap_sock_kill(struct sock *sk); | 75 | static void l2cap_sock_kill(struct sock *sk); |
76 | 76 | ||
77 | static int l2cap_build_conf_req(struct sock *sk, void *data); | ||
77 | static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, | 78 | static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, |
78 | u8 code, u8 ident, u16 dlen, void *data); | 79 | u8 code, u8 ident, u16 dlen, void *data); |
79 | 80 | ||
@@ -548,6 +549,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) | |||
548 | } | 549 | } |
549 | } else if (sk->sk_state == BT_CONNECT2) { | 550 | } else if (sk->sk_state == BT_CONNECT2) { |
550 | struct l2cap_conn_rsp rsp; | 551 | struct l2cap_conn_rsp rsp; |
552 | char buf[128]; | ||
551 | rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); | 553 | rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); |
552 | rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); | 554 | rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); |
553 | 555 | ||
@@ -570,6 +572,17 @@ static void l2cap_conn_start(struct l2cap_conn *conn) | |||
570 | 572 | ||
571 | l2cap_send_cmd(conn, l2cap_pi(sk)->ident, | 573 | l2cap_send_cmd(conn, l2cap_pi(sk)->ident, |
572 | L2CAP_CONN_RSP, sizeof(rsp), &rsp); | 574 | L2CAP_CONN_RSP, sizeof(rsp), &rsp); |
575 | |||
576 | if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT || | ||
577 | rsp.result != L2CAP_CR_SUCCESS) { | ||
578 | bh_unlock_sock(sk); | ||
579 | continue; | ||
580 | } | ||
581 | |||
582 | l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; | ||
583 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, | ||
584 | l2cap_build_conf_req(sk, buf), buf); | ||
585 | l2cap_pi(sk)->num_conf_req++; | ||
573 | } | 586 | } |
574 | 587 | ||
575 | bh_unlock_sock(sk); | 588 | bh_unlock_sock(sk); |
@@ -1897,6 +1910,8 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct ms | |||
1897 | 1910 | ||
1898 | if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) { | 1911 | if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) { |
1899 | struct l2cap_conn_rsp rsp; | 1912 | struct l2cap_conn_rsp rsp; |
1913 | struct l2cap_conn *conn = l2cap_pi(sk)->conn; | ||
1914 | u8 buf[128]; | ||
1900 | 1915 | ||
1901 | sk->sk_state = BT_CONFIG; | 1916 | sk->sk_state = BT_CONFIG; |
1902 | 1917 | ||
@@ -1907,6 +1922,16 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct ms | |||
1907 | l2cap_send_cmd(l2cap_pi(sk)->conn, l2cap_pi(sk)->ident, | 1922 | l2cap_send_cmd(l2cap_pi(sk)->conn, l2cap_pi(sk)->ident, |
1908 | L2CAP_CONN_RSP, sizeof(rsp), &rsp); | 1923 | L2CAP_CONN_RSP, sizeof(rsp), &rsp); |
1909 | 1924 | ||
1925 | if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) { | ||
1926 | release_sock(sk); | ||
1927 | return 0; | ||
1928 | } | ||
1929 | |||
1930 | l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; | ||
1931 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, | ||
1932 | l2cap_build_conf_req(sk, buf), buf); | ||
1933 | l2cap_pi(sk)->num_conf_req++; | ||
1934 | |||
1910 | release_sock(sk); | 1935 | release_sock(sk); |
1911 | return 0; | 1936 | return 0; |
1912 | } | 1937 | } |
@@ -2613,7 +2638,7 @@ static int l2cap_parse_conf_req(struct sock *sk, void *data) | |||
2613 | } | 2638 | } |
2614 | } | 2639 | } |
2615 | 2640 | ||
2616 | if (pi->num_conf_rsp || pi->num_conf_req) | 2641 | if (pi->num_conf_rsp || pi->num_conf_req > 1) |
2617 | goto done; | 2642 | goto done; |
2618 | 2643 | ||
2619 | switch (pi->mode) { | 2644 | switch (pi->mode) { |
@@ -2857,7 +2882,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
2857 | struct l2cap_chan_list *list = &conn->chan_list; | 2882 | struct l2cap_chan_list *list = &conn->chan_list; |
2858 | struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; | 2883 | struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; |
2859 | struct l2cap_conn_rsp rsp; | 2884 | struct l2cap_conn_rsp rsp; |
2860 | struct sock *sk, *parent; | 2885 | struct sock *parent, *uninitialized_var(sk); |
2861 | int result, status = L2CAP_CS_NO_INFO; | 2886 | int result, status = L2CAP_CS_NO_INFO; |
2862 | 2887 | ||
2863 | u16 dcid = 0, scid = __le16_to_cpu(req->scid); | 2888 | u16 dcid = 0, scid = __le16_to_cpu(req->scid); |
@@ -2966,6 +2991,15 @@ sendresp: | |||
2966 | L2CAP_INFO_REQ, sizeof(info), &info); | 2991 | L2CAP_INFO_REQ, sizeof(info), &info); |
2967 | } | 2992 | } |
2968 | 2993 | ||
2994 | if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) && | ||
2995 | result == L2CAP_CR_SUCCESS) { | ||
2996 | u8 buf[128]; | ||
2997 | l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; | ||
2998 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, | ||
2999 | l2cap_build_conf_req(sk, buf), buf); | ||
3000 | l2cap_pi(sk)->num_conf_req++; | ||
3001 | } | ||
3002 | |||
2969 | return 0; | 3003 | return 0; |
2970 | } | 3004 | } |
2971 | 3005 | ||
@@ -2998,9 +3032,13 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
2998 | sk->sk_state = BT_CONFIG; | 3032 | sk->sk_state = BT_CONFIG; |
2999 | l2cap_pi(sk)->ident = 0; | 3033 | l2cap_pi(sk)->ident = 0; |
3000 | l2cap_pi(sk)->dcid = dcid; | 3034 | l2cap_pi(sk)->dcid = dcid; |
3001 | l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; | ||
3002 | l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND; | 3035 | l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND; |
3003 | 3036 | ||
3037 | if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) | ||
3038 | break; | ||
3039 | |||
3040 | l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; | ||
3041 | |||
3004 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, | 3042 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, |
3005 | l2cap_build_conf_req(sk, req), req); | 3043 | l2cap_build_conf_req(sk, req), req); |
3006 | l2cap_pi(sk)->num_conf_req++; | 3044 | l2cap_pi(sk)->num_conf_req++; |