diff options
-rw-r--r-- | include/net/bluetooth/l2cap.h | 28 | ||||
-rw-r--r-- | net/bluetooth/l2cap.c | 262 |
2 files changed, 255 insertions, 35 deletions
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 06b072fd6d54..6fc76986d70a 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h | |||
@@ -27,8 +27,9 @@ | |||
27 | 27 | ||
28 | /* L2CAP defaults */ | 28 | /* L2CAP defaults */ |
29 | #define L2CAP_DEFAULT_MTU 672 | 29 | #define L2CAP_DEFAULT_MTU 672 |
30 | #define L2CAP_DEFAULT_MIN_MTU 48 | ||
30 | #define L2CAP_DEFAULT_FLUSH_TO 0xffff | 31 | #define L2CAP_DEFAULT_FLUSH_TO 0xffff |
31 | #define L2CAP_DEFAULT_RX_WINDOW 1 | 32 | #define L2CAP_DEFAULT_TX_WINDOW 1 |
32 | #define L2CAP_DEFAULT_MAX_RECEIVE 1 | 33 | #define L2CAP_DEFAULT_MAX_RECEIVE 1 |
33 | #define L2CAP_DEFAULT_RETRANS_TO 300 /* 300 milliseconds */ | 34 | #define L2CAP_DEFAULT_RETRANS_TO 300 /* 300 milliseconds */ |
34 | #define L2CAP_DEFAULT_MONITOR_TO 1000 /* 1 second */ | 35 | #define L2CAP_DEFAULT_MONITOR_TO 1000 /* 1 second */ |
@@ -272,6 +273,9 @@ struct l2cap_pinfo { | |||
272 | __u16 omtu; | 273 | __u16 omtu; |
273 | __u16 flush_to; | 274 | __u16 flush_to; |
274 | __u8 mode; | 275 | __u8 mode; |
276 | __u8 num_conf_req; | ||
277 | __u8 num_conf_rsp; | ||
278 | |||
275 | __u8 fcs; | 279 | __u8 fcs; |
276 | __u8 sec_level; | 280 | __u8 sec_level; |
277 | __u8 role_switch; | 281 | __u8 role_switch; |
@@ -280,10 +284,15 @@ struct l2cap_pinfo { | |||
280 | __u8 conf_req[64]; | 284 | __u8 conf_req[64]; |
281 | __u8 conf_len; | 285 | __u8 conf_len; |
282 | __u8 conf_state; | 286 | __u8 conf_state; |
283 | __u8 conf_retry; | ||
284 | 287 | ||
285 | __u8 ident; | 288 | __u8 ident; |
286 | 289 | ||
290 | __u8 remote_tx_win; | ||
291 | __u8 remote_max_tx; | ||
292 | __u16 retrans_timeout; | ||
293 | __u16 monitor_timeout; | ||
294 | __u16 max_pdu_size; | ||
295 | |||
287 | __le16 sport; | 296 | __le16 sport; |
288 | 297 | ||
289 | struct l2cap_conn *conn; | 298 | struct l2cap_conn *conn; |
@@ -291,12 +300,17 @@ struct l2cap_pinfo { | |||
291 | struct sock *prev_c; | 300 | struct sock *prev_c; |
292 | }; | 301 | }; |
293 | 302 | ||
294 | #define L2CAP_CONF_REQ_SENT 0x01 | 303 | #define L2CAP_CONF_REQ_SENT 0x01 |
295 | #define L2CAP_CONF_INPUT_DONE 0x02 | 304 | #define L2CAP_CONF_INPUT_DONE 0x02 |
296 | #define L2CAP_CONF_OUTPUT_DONE 0x04 | 305 | #define L2CAP_CONF_OUTPUT_DONE 0x04 |
297 | #define L2CAP_CONF_CONNECT_PEND 0x80 | 306 | #define L2CAP_CONF_MTU_DONE 0x08 |
307 | #define L2CAP_CONF_MODE_DONE 0x10 | ||
308 | #define L2CAP_CONF_CONNECT_PEND 0x20 | ||
309 | #define L2CAP_CONF_STATE2_DEVICE 0x80 | ||
310 | |||
311 | #define L2CAP_CONF_MAX_CONF_REQ 2 | ||
312 | #define L2CAP_CONF_MAX_CONF_RSP 2 | ||
298 | 313 | ||
299 | #define L2CAP_CONF_MAX_RETRIES 2 | ||
300 | 314 | ||
301 | void l2cap_load(void); | 315 | void l2cap_load(void); |
302 | 316 | ||
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 7ce1a24735c8..af0fbf9ebfeb 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c | |||
@@ -966,6 +966,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al | |||
966 | case L2CAP_MODE_BASIC: | 966 | case L2CAP_MODE_BASIC: |
967 | break; | 967 | break; |
968 | case L2CAP_MODE_ERTM: | 968 | case L2CAP_MODE_ERTM: |
969 | case L2CAP_MODE_STREAMING: | ||
969 | if (enable_ertm) | 970 | if (enable_ertm) |
970 | break; | 971 | break; |
971 | /* fall through */ | 972 | /* fall through */ |
@@ -1029,6 +1030,7 @@ static int l2cap_sock_listen(struct socket *sock, int backlog) | |||
1029 | case L2CAP_MODE_BASIC: | 1030 | case L2CAP_MODE_BASIC: |
1030 | break; | 1031 | break; |
1031 | case L2CAP_MODE_ERTM: | 1032 | case L2CAP_MODE_ERTM: |
1033 | case L2CAP_MODE_STREAMING: | ||
1032 | if (enable_ertm) | 1034 | if (enable_ertm) |
1033 | break; | 1035 | break; |
1034 | /* fall through */ | 1036 | /* fall through */ |
@@ -1739,15 +1741,65 @@ static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val) | |||
1739 | *ptr += L2CAP_CONF_OPT_SIZE + len; | 1741 | *ptr += L2CAP_CONF_OPT_SIZE + len; |
1740 | } | 1742 | } |
1741 | 1743 | ||
1744 | static int l2cap_mode_supported(__u8 mode, __u32 feat_mask) | ||
1745 | { | ||
1746 | u32 local_feat_mask = l2cap_feat_mask; | ||
1747 | if (enable_ertm) | ||
1748 | local_feat_mask |= L2CAP_FEAT_ERTM; | ||
1749 | |||
1750 | switch (mode) { | ||
1751 | case L2CAP_MODE_ERTM: | ||
1752 | return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask; | ||
1753 | case L2CAP_MODE_STREAMING: | ||
1754 | return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask; | ||
1755 | default: | ||
1756 | return 0x00; | ||
1757 | } | ||
1758 | } | ||
1759 | |||
1760 | static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask) | ||
1761 | { | ||
1762 | switch (mode) { | ||
1763 | case L2CAP_MODE_STREAMING: | ||
1764 | case L2CAP_MODE_ERTM: | ||
1765 | if (l2cap_mode_supported(mode, remote_feat_mask)) | ||
1766 | return mode; | ||
1767 | /* fall through */ | ||
1768 | default: | ||
1769 | return L2CAP_MODE_BASIC; | ||
1770 | } | ||
1771 | } | ||
1772 | |||
1742 | static int l2cap_build_conf_req(struct sock *sk, void *data) | 1773 | static int l2cap_build_conf_req(struct sock *sk, void *data) |
1743 | { | 1774 | { |
1744 | struct l2cap_pinfo *pi = l2cap_pi(sk); | 1775 | struct l2cap_pinfo *pi = l2cap_pi(sk); |
1745 | struct l2cap_conf_req *req = data; | 1776 | struct l2cap_conf_req *req = data; |
1746 | struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; | 1777 | struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_ERTM }; |
1747 | void *ptr = req->data; | 1778 | void *ptr = req->data; |
1748 | 1779 | ||
1749 | BT_DBG("sk %p", sk); | 1780 | BT_DBG("sk %p", sk); |
1750 | 1781 | ||
1782 | if (pi->num_conf_req || pi->num_conf_rsp) | ||
1783 | goto done; | ||
1784 | |||
1785 | switch (pi->mode) { | ||
1786 | case L2CAP_MODE_STREAMING: | ||
1787 | case L2CAP_MODE_ERTM: | ||
1788 | pi->conf_state |= L2CAP_CONF_STATE2_DEVICE; | ||
1789 | if (!l2cap_mode_supported(pi->mode, pi->conn->feat_mask)) { | ||
1790 | struct l2cap_disconn_req req; | ||
1791 | req.dcid = cpu_to_le16(pi->dcid); | ||
1792 | req.scid = cpu_to_le16(pi->scid); | ||
1793 | l2cap_send_cmd(pi->conn, l2cap_get_ident(pi->conn), | ||
1794 | L2CAP_DISCONN_REQ, sizeof(req), &req); | ||
1795 | } | ||
1796 | break; | ||
1797 | default: | ||
1798 | pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask); | ||
1799 | break; | ||
1800 | } | ||
1801 | |||
1802 | done: | ||
1751 | switch (pi->mode) { | 1803 | switch (pi->mode) { |
1752 | case L2CAP_MODE_BASIC: | 1804 | case L2CAP_MODE_BASIC: |
1753 | if (pi->imtu != L2CAP_DEFAULT_MTU) | 1805 | if (pi->imtu != L2CAP_DEFAULT_MTU) |
@@ -1756,10 +1808,22 @@ static int l2cap_build_conf_req(struct sock *sk, void *data) | |||
1756 | 1808 | ||
1757 | case L2CAP_MODE_ERTM: | 1809 | case L2CAP_MODE_ERTM: |
1758 | rfc.mode = L2CAP_MODE_ERTM; | 1810 | rfc.mode = L2CAP_MODE_ERTM; |
1759 | rfc.txwin_size = L2CAP_DEFAULT_RX_WINDOW; | 1811 | rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW; |
1760 | rfc.max_transmit = L2CAP_DEFAULT_MAX_RECEIVE; | 1812 | rfc.max_transmit = L2CAP_DEFAULT_MAX_RECEIVE; |
1761 | rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); | 1813 | rfc.retrans_timeout = 0; |
1762 | rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); | 1814 | rfc.monitor_timeout = 0; |
1815 | rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_RX_APDU); | ||
1816 | |||
1817 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, | ||
1818 | sizeof(rfc), (unsigned long) &rfc); | ||
1819 | break; | ||
1820 | |||
1821 | case L2CAP_MODE_STREAMING: | ||
1822 | rfc.mode = L2CAP_MODE_STREAMING; | ||
1823 | rfc.txwin_size = 0; | ||
1824 | rfc.max_transmit = 0; | ||
1825 | rfc.retrans_timeout = 0; | ||
1826 | rfc.monitor_timeout = 0; | ||
1763 | rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_RX_APDU); | 1827 | rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_RX_APDU); |
1764 | 1828 | ||
1765 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, | 1829 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, |
@@ -1825,30 +1889,83 @@ static int l2cap_parse_conf_req(struct sock *sk, void *data) | |||
1825 | } | 1889 | } |
1826 | } | 1890 | } |
1827 | 1891 | ||
1892 | if (pi->num_conf_rsp || pi->num_conf_req) | ||
1893 | goto done; | ||
1894 | |||
1895 | switch (pi->mode) { | ||
1896 | case L2CAP_MODE_STREAMING: | ||
1897 | case L2CAP_MODE_ERTM: | ||
1898 | pi->conf_state |= L2CAP_CONF_STATE2_DEVICE; | ||
1899 | if (!l2cap_mode_supported(pi->mode, pi->conn->feat_mask)) | ||
1900 | return -ECONNREFUSED; | ||
1901 | break; | ||
1902 | default: | ||
1903 | pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask); | ||
1904 | break; | ||
1905 | } | ||
1906 | |||
1907 | done: | ||
1908 | if (pi->mode != rfc.mode) { | ||
1909 | result = L2CAP_CONF_UNACCEPT; | ||
1910 | rfc.mode = pi->mode; | ||
1911 | |||
1912 | if (pi->num_conf_rsp == 1) | ||
1913 | return -ECONNREFUSED; | ||
1914 | |||
1915 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, | ||
1916 | sizeof(rfc), (unsigned long) &rfc); | ||
1917 | } | ||
1918 | |||
1919 | |||
1828 | if (result == L2CAP_CONF_SUCCESS) { | 1920 | if (result == L2CAP_CONF_SUCCESS) { |
1829 | /* Configure output options and let the other side know | 1921 | /* Configure output options and let the other side know |
1830 | * which ones we don't like. */ | 1922 | * which ones we don't like. */ |
1831 | 1923 | ||
1832 | if (rfc.mode == L2CAP_MODE_BASIC) { | 1924 | if (mtu < L2CAP_DEFAULT_MIN_MTU) |
1833 | if (mtu < pi->omtu) | 1925 | result = L2CAP_CONF_UNACCEPT; |
1834 | result = L2CAP_CONF_UNACCEPT; | 1926 | else { |
1835 | else { | 1927 | pi->omtu = mtu; |
1836 | pi->omtu = mtu; | 1928 | pi->conf_state |= L2CAP_CONF_MTU_DONE; |
1837 | pi->conf_state |= L2CAP_CONF_OUTPUT_DONE; | 1929 | } |
1838 | } | 1930 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu); |
1839 | 1931 | ||
1840 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu); | 1932 | switch (rfc.mode) { |
1841 | } else { | 1933 | case L2CAP_MODE_BASIC: |
1934 | pi->fcs = L2CAP_FCS_NONE; | ||
1935 | pi->conf_state |= L2CAP_CONF_MODE_DONE; | ||
1936 | break; | ||
1937 | |||
1938 | case L2CAP_MODE_ERTM: | ||
1939 | pi->remote_tx_win = rfc.txwin_size; | ||
1940 | pi->remote_max_tx = rfc.max_transmit; | ||
1941 | pi->max_pdu_size = rfc.max_pdu_size; | ||
1942 | |||
1943 | rfc.retrans_timeout = L2CAP_DEFAULT_RETRANS_TO; | ||
1944 | rfc.monitor_timeout = L2CAP_DEFAULT_MONITOR_TO; | ||
1945 | |||
1946 | pi->conf_state |= L2CAP_CONF_MODE_DONE; | ||
1947 | break; | ||
1948 | |||
1949 | case L2CAP_MODE_STREAMING: | ||
1950 | pi->remote_tx_win = rfc.txwin_size; | ||
1951 | pi->max_pdu_size = rfc.max_pdu_size; | ||
1952 | |||
1953 | pi->conf_state |= L2CAP_CONF_MODE_DONE; | ||
1954 | break; | ||
1955 | |||
1956 | default: | ||
1842 | result = L2CAP_CONF_UNACCEPT; | 1957 | result = L2CAP_CONF_UNACCEPT; |
1843 | 1958 | ||
1844 | memset(&rfc, 0, sizeof(rfc)); | 1959 | memset(&rfc, 0, sizeof(rfc)); |
1845 | rfc.mode = L2CAP_MODE_BASIC; | 1960 | rfc.mode = pi->mode; |
1961 | } | ||
1846 | 1962 | ||
1847 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, | 1963 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, |
1848 | sizeof(rfc), (unsigned long) &rfc); | 1964 | sizeof(rfc), (unsigned long) &rfc); |
1849 | } | ||
1850 | } | ||
1851 | 1965 | ||
1966 | if (result == L2CAP_CONF_SUCCESS) | ||
1967 | pi->conf_state |= L2CAP_CONF_OUTPUT_DONE; | ||
1968 | } | ||
1852 | rsp->scid = cpu_to_le16(pi->dcid); | 1969 | rsp->scid = cpu_to_le16(pi->dcid); |
1853 | rsp->result = cpu_to_le16(result); | 1970 | rsp->result = cpu_to_le16(result); |
1854 | rsp->flags = cpu_to_le16(0x0000); | 1971 | rsp->flags = cpu_to_le16(0x0000); |
@@ -1856,6 +1973,73 @@ static int l2cap_parse_conf_req(struct sock *sk, void *data) | |||
1856 | return ptr - data; | 1973 | return ptr - data; |
1857 | } | 1974 | } |
1858 | 1975 | ||
1976 | static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result) | ||
1977 | { | ||
1978 | struct l2cap_pinfo *pi = l2cap_pi(sk); | ||
1979 | struct l2cap_conf_req *req = data; | ||
1980 | void *ptr = req->data; | ||
1981 | int type, olen; | ||
1982 | unsigned long val; | ||
1983 | struct l2cap_conf_rfc rfc; | ||
1984 | |||
1985 | BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data); | ||
1986 | |||
1987 | while (len >= L2CAP_CONF_OPT_SIZE) { | ||
1988 | len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); | ||
1989 | |||
1990 | switch (type) { | ||
1991 | case L2CAP_CONF_MTU: | ||
1992 | if (val < L2CAP_DEFAULT_MIN_MTU) { | ||
1993 | *result = L2CAP_CONF_UNACCEPT; | ||
1994 | pi->omtu = L2CAP_DEFAULT_MIN_MTU; | ||
1995 | } else | ||
1996 | pi->omtu = val; | ||
1997 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu); | ||
1998 | break; | ||
1999 | |||
2000 | case L2CAP_CONF_FLUSH_TO: | ||
2001 | pi->flush_to = val; | ||
2002 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, | ||
2003 | 2, pi->flush_to); | ||
2004 | break; | ||
2005 | |||
2006 | case L2CAP_CONF_RFC: | ||
2007 | if (olen == sizeof(rfc)) | ||
2008 | memcpy(&rfc, (void *)val, olen); | ||
2009 | |||
2010 | if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) && | ||
2011 | rfc.mode != pi->mode) | ||
2012 | return -ECONNREFUSED; | ||
2013 | |||
2014 | pi->mode = rfc.mode; | ||
2015 | pi->fcs = 0; | ||
2016 | |||
2017 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, | ||
2018 | sizeof(rfc), (unsigned long) &rfc); | ||
2019 | break; | ||
2020 | } | ||
2021 | } | ||
2022 | |||
2023 | if (*result == L2CAP_CONF_SUCCESS) { | ||
2024 | switch (rfc.mode) { | ||
2025 | case L2CAP_MODE_ERTM: | ||
2026 | pi->remote_tx_win = rfc.txwin_size; | ||
2027 | pi->retrans_timeout = rfc.retrans_timeout; | ||
2028 | pi->monitor_timeout = rfc.monitor_timeout; | ||
2029 | pi->max_pdu_size = le16_to_cpu(rfc.max_pdu_size); | ||
2030 | break; | ||
2031 | case L2CAP_MODE_STREAMING: | ||
2032 | pi->max_pdu_size = le16_to_cpu(rfc.max_pdu_size); | ||
2033 | break; | ||
2034 | } | ||
2035 | } | ||
2036 | |||
2037 | req->dcid = cpu_to_le16(pi->dcid); | ||
2038 | req->flags = cpu_to_le16(0x0000); | ||
2039 | |||
2040 | return ptr - data; | ||
2041 | } | ||
2042 | |||
1859 | static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags) | 2043 | static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags) |
1860 | { | 2044 | { |
1861 | struct l2cap_conf_rsp *rsp = data; | 2045 | struct l2cap_conf_rsp *rsp = data; |
@@ -2042,6 +2226,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
2042 | 2226 | ||
2043 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, | 2227 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, |
2044 | l2cap_build_conf_req(sk, req), req); | 2228 | l2cap_build_conf_req(sk, req), req); |
2229 | l2cap_pi(sk)->num_conf_req++; | ||
2045 | break; | 2230 | break; |
2046 | 2231 | ||
2047 | case L2CAP_CR_PEND: | 2232 | case L2CAP_CR_PEND: |
@@ -2100,10 +2285,17 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
2100 | 2285 | ||
2101 | /* Complete config. */ | 2286 | /* Complete config. */ |
2102 | len = l2cap_parse_conf_req(sk, rsp); | 2287 | len = l2cap_parse_conf_req(sk, rsp); |
2103 | if (len < 0) | 2288 | if (len < 0) { |
2289 | struct l2cap_disconn_req req; | ||
2290 | req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid); | ||
2291 | req.scid = cpu_to_le16(l2cap_pi(sk)->scid); | ||
2292 | l2cap_send_cmd(conn, l2cap_get_ident(conn), | ||
2293 | L2CAP_DISCONN_REQ, sizeof(req), &req); | ||
2104 | goto unlock; | 2294 | goto unlock; |
2295 | } | ||
2105 | 2296 | ||
2106 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp); | 2297 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp); |
2298 | l2cap_pi(sk)->num_conf_rsp++; | ||
2107 | 2299 | ||
2108 | /* Reset config buffer. */ | 2300 | /* Reset config buffer. */ |
2109 | l2cap_pi(sk)->conf_len = 0; | 2301 | l2cap_pi(sk)->conf_len = 0; |
@@ -2121,6 +2313,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
2121 | u8 buf[64]; | 2313 | u8 buf[64]; |
2122 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, | 2314 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, |
2123 | l2cap_build_conf_req(sk, buf), buf); | 2315 | l2cap_build_conf_req(sk, buf), buf); |
2316 | l2cap_pi(sk)->num_conf_req++; | ||
2124 | } | 2317 | } |
2125 | 2318 | ||
2126 | unlock: | 2319 | unlock: |
@@ -2150,16 +2343,29 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
2150 | break; | 2343 | break; |
2151 | 2344 | ||
2152 | case L2CAP_CONF_UNACCEPT: | 2345 | case L2CAP_CONF_UNACCEPT: |
2153 | if (++l2cap_pi(sk)->conf_retry < L2CAP_CONF_MAX_RETRIES) { | 2346 | if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) { |
2154 | char req[128]; | 2347 | int len = cmd->len - sizeof(*rsp); |
2155 | /* It does not make sense to adjust L2CAP parameters | 2348 | char req[64]; |
2156 | * that are currently defined in the spec. We simply | 2349 | |
2157 | * resend config request that we sent earlier. It is | 2350 | /* throw out any old stored conf requests */ |
2158 | * stupid, but it helps qualification testing which | 2351 | result = L2CAP_CONF_SUCCESS; |
2159 | * expects at least some response from us. */ | 2352 | len = l2cap_parse_conf_rsp(sk, rsp->data, |
2160 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, | 2353 | len, req, &result); |
2161 | l2cap_build_conf_req(sk, req), req); | 2354 | if (len < 0) { |
2162 | goto done; | 2355 | struct l2cap_disconn_req req; |
2356 | req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid); | ||
2357 | req.scid = cpu_to_le16(l2cap_pi(sk)->scid); | ||
2358 | l2cap_send_cmd(conn, l2cap_get_ident(conn), | ||
2359 | L2CAP_DISCONN_REQ, sizeof(req), &req); | ||
2360 | goto done; | ||
2361 | } | ||
2362 | |||
2363 | l2cap_send_cmd(conn, l2cap_get_ident(conn), | ||
2364 | L2CAP_CONF_REQ, len, req); | ||
2365 | l2cap_pi(sk)->num_conf_req++; | ||
2366 | if (result != L2CAP_CONF_SUCCESS) | ||
2367 | goto done; | ||
2368 | break; | ||
2163 | } | 2369 | } |
2164 | 2370 | ||
2165 | default: | 2371 | default: |