diff options
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/l2cap.c | 39 |
1 files changed, 38 insertions, 1 deletions
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index f604405fe667..c50c05738fb6 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c | |||
@@ -2602,6 +2602,42 @@ static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 fla | |||
2602 | return ptr - data; | 2602 | return ptr - data; |
2603 | } | 2603 | } |
2604 | 2604 | ||
2605 | static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len) | ||
2606 | { | ||
2607 | struct l2cap_pinfo *pi = l2cap_pi(sk); | ||
2608 | int type, olen; | ||
2609 | unsigned long val; | ||
2610 | struct l2cap_conf_rfc rfc; | ||
2611 | |||
2612 | BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len); | ||
2613 | |||
2614 | if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING)) | ||
2615 | return; | ||
2616 | |||
2617 | while (len >= L2CAP_CONF_OPT_SIZE) { | ||
2618 | len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); | ||
2619 | |||
2620 | switch (type) { | ||
2621 | case L2CAP_CONF_RFC: | ||
2622 | if (olen == sizeof(rfc)) | ||
2623 | memcpy(&rfc, (void *)val, olen); | ||
2624 | goto done; | ||
2625 | } | ||
2626 | } | ||
2627 | |||
2628 | done: | ||
2629 | switch (rfc.mode) { | ||
2630 | case L2CAP_MODE_ERTM: | ||
2631 | pi->remote_tx_win = rfc.txwin_size; | ||
2632 | pi->retrans_timeout = rfc.retrans_timeout; | ||
2633 | pi->monitor_timeout = rfc.monitor_timeout; | ||
2634 | pi->mps = le16_to_cpu(rfc.max_pdu_size); | ||
2635 | break; | ||
2636 | case L2CAP_MODE_STREAMING: | ||
2637 | pi->mps = le16_to_cpu(rfc.max_pdu_size); | ||
2638 | } | ||
2639 | } | ||
2640 | |||
2605 | static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) | 2641 | static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) |
2606 | { | 2642 | { |
2607 | struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data; | 2643 | struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data; |
@@ -2881,6 +2917,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
2881 | struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; | 2917 | struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; |
2882 | u16 scid, flags, result; | 2918 | u16 scid, flags, result; |
2883 | struct sock *sk; | 2919 | struct sock *sk; |
2920 | int len = cmd->len - sizeof(*rsp); | ||
2884 | 2921 | ||
2885 | scid = __le16_to_cpu(rsp->scid); | 2922 | scid = __le16_to_cpu(rsp->scid); |
2886 | flags = __le16_to_cpu(rsp->flags); | 2923 | flags = __le16_to_cpu(rsp->flags); |
@@ -2895,11 +2932,11 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
2895 | 2932 | ||
2896 | switch (result) { | 2933 | switch (result) { |
2897 | case L2CAP_CONF_SUCCESS: | 2934 | case L2CAP_CONF_SUCCESS: |
2935 | l2cap_conf_rfc_get(sk, rsp->data, len); | ||
2898 | break; | 2936 | break; |
2899 | 2937 | ||
2900 | case L2CAP_CONF_UNACCEPT: | 2938 | case L2CAP_CONF_UNACCEPT: |
2901 | if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) { | 2939 | if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) { |
2902 | int len = cmd->len - sizeof(*rsp); | ||
2903 | char req[64]; | 2940 | char req[64]; |
2904 | 2941 | ||
2905 | if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { | 2942 | if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { |