diff options
author | Gustavo F. Padovan <padovan@profusion.mobi> | 2010-05-01 15:15:40 -0400 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2010-05-10 03:28:48 -0400 |
commit | 1c7621596d11b9c3e19eb88a818758dee4901c95 (patch) | |
tree | 7eccf73c1739964e83cbc7ea5bce53fd4372a07c /net/bluetooth/l2cap.c | |
parent | 7b1c0049be3aabc18831ada339dbcf41ba8c81fd (diff) |
Bluetooth: Fix configuration of the MPS value
We were accepting values bigger than we can accept. This was leading
ERTM to drop packets because of wrong FCS checks.
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth/l2cap.c')
-rw-r--r-- | net/bluetooth/l2cap.c | 36 |
1 files changed, 20 insertions, 16 deletions
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index c50c05738fb6..94be5dbb2569 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c | |||
@@ -1606,21 +1606,21 @@ static inline int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, siz | |||
1606 | 1606 | ||
1607 | __skb_queue_head_init(&sar_queue); | 1607 | __skb_queue_head_init(&sar_queue); |
1608 | control = L2CAP_SDU_START; | 1608 | control = L2CAP_SDU_START; |
1609 | skb = l2cap_create_iframe_pdu(sk, msg, pi->max_pdu_size, control, len); | 1609 | skb = l2cap_create_iframe_pdu(sk, msg, pi->remote_mps, control, len); |
1610 | if (IS_ERR(skb)) | 1610 | if (IS_ERR(skb)) |
1611 | return PTR_ERR(skb); | 1611 | return PTR_ERR(skb); |
1612 | 1612 | ||
1613 | __skb_queue_tail(&sar_queue, skb); | 1613 | __skb_queue_tail(&sar_queue, skb); |
1614 | len -= pi->max_pdu_size; | 1614 | len -= pi->remote_mps; |
1615 | size +=pi->max_pdu_size; | 1615 | size += pi->remote_mps; |
1616 | control = 0; | 1616 | control = 0; |
1617 | 1617 | ||
1618 | while (len > 0) { | 1618 | while (len > 0) { |
1619 | size_t buflen; | 1619 | size_t buflen; |
1620 | 1620 | ||
1621 | if (len > pi->max_pdu_size) { | 1621 | if (len > pi->remote_mps) { |
1622 | control |= L2CAP_SDU_CONTINUE; | 1622 | control |= L2CAP_SDU_CONTINUE; |
1623 | buflen = pi->max_pdu_size; | 1623 | buflen = pi->remote_mps; |
1624 | } else { | 1624 | } else { |
1625 | control |= L2CAP_SDU_END; | 1625 | control |= L2CAP_SDU_END; |
1626 | buflen = len; | 1626 | buflen = len; |
@@ -1701,7 +1701,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms | |||
1701 | case L2CAP_MODE_ERTM: | 1701 | case L2CAP_MODE_ERTM: |
1702 | case L2CAP_MODE_STREAMING: | 1702 | case L2CAP_MODE_STREAMING: |
1703 | /* Entire SDU fits into one PDU */ | 1703 | /* Entire SDU fits into one PDU */ |
1704 | if (len <= pi->max_pdu_size) { | 1704 | if (len <= pi->remote_mps) { |
1705 | control = L2CAP_SDU_UNSEGMENTED; | 1705 | control = L2CAP_SDU_UNSEGMENTED; |
1706 | skb = l2cap_create_iframe_pdu(sk, msg, len, control, 0); | 1706 | skb = l2cap_create_iframe_pdu(sk, msg, len, control, 0); |
1707 | if (IS_ERR(skb)) { | 1707 | if (IS_ERR(skb)) { |
@@ -2330,7 +2330,7 @@ done: | |||
2330 | rfc.monitor_timeout = 0; | 2330 | rfc.monitor_timeout = 0; |
2331 | rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE); | 2331 | rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE); |
2332 | if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10) | 2332 | if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10) |
2333 | rfc.max_pdu_size = pi->conn->mtu - 10; | 2333 | rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10); |
2334 | 2334 | ||
2335 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, | 2335 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, |
2336 | sizeof(rfc), (unsigned long) &rfc); | 2336 | sizeof(rfc), (unsigned long) &rfc); |
@@ -2353,7 +2353,7 @@ done: | |||
2353 | rfc.monitor_timeout = 0; | 2353 | rfc.monitor_timeout = 0; |
2354 | rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE); | 2354 | rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE); |
2355 | if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10) | 2355 | if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10) |
2356 | rfc.max_pdu_size = pi->conn->mtu - 10; | 2356 | rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10); |
2357 | 2357 | ||
2358 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, | 2358 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, |
2359 | sizeof(rfc), (unsigned long) &rfc); | 2359 | sizeof(rfc), (unsigned long) &rfc); |
@@ -2482,7 +2482,10 @@ done: | |||
2482 | case L2CAP_MODE_ERTM: | 2482 | case L2CAP_MODE_ERTM: |
2483 | pi->remote_tx_win = rfc.txwin_size; | 2483 | pi->remote_tx_win = rfc.txwin_size; |
2484 | pi->remote_max_tx = rfc.max_transmit; | 2484 | pi->remote_max_tx = rfc.max_transmit; |
2485 | pi->max_pdu_size = rfc.max_pdu_size; | 2485 | if (rfc.max_pdu_size > pi->conn->mtu - 10) |
2486 | rfc.max_pdu_size = le16_to_cpu(pi->conn->mtu - 10); | ||
2487 | |||
2488 | pi->remote_mps = le16_to_cpu(rfc.max_pdu_size); | ||
2486 | 2489 | ||
2487 | rfc.retrans_timeout = L2CAP_DEFAULT_RETRANS_TO; | 2490 | rfc.retrans_timeout = L2CAP_DEFAULT_RETRANS_TO; |
2488 | rfc.monitor_timeout = L2CAP_DEFAULT_MONITOR_TO; | 2491 | rfc.monitor_timeout = L2CAP_DEFAULT_MONITOR_TO; |
@@ -2495,7 +2498,10 @@ done: | |||
2495 | break; | 2498 | break; |
2496 | 2499 | ||
2497 | case L2CAP_MODE_STREAMING: | 2500 | case L2CAP_MODE_STREAMING: |
2498 | pi->max_pdu_size = rfc.max_pdu_size; | 2501 | if (rfc.max_pdu_size > pi->conn->mtu - 10) |
2502 | rfc.max_pdu_size = le16_to_cpu(pi->conn->mtu - 10); | ||
2503 | |||
2504 | pi->remote_mps = le16_to_cpu(rfc.max_pdu_size); | ||
2499 | 2505 | ||
2500 | pi->conf_state |= L2CAP_CONF_MODE_DONE; | 2506 | pi->conf_state |= L2CAP_CONF_MODE_DONE; |
2501 | 2507 | ||
@@ -2574,11 +2580,10 @@ static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, | |||
2574 | pi->remote_tx_win = rfc.txwin_size; | 2580 | pi->remote_tx_win = rfc.txwin_size; |
2575 | pi->retrans_timeout = rfc.retrans_timeout; | 2581 | pi->retrans_timeout = rfc.retrans_timeout; |
2576 | pi->monitor_timeout = rfc.monitor_timeout; | 2582 | pi->monitor_timeout = rfc.monitor_timeout; |
2577 | pi->max_pdu_size = le16_to_cpu(rfc.max_pdu_size); | 2583 | pi->mps = le16_to_cpu(rfc.max_pdu_size); |
2578 | break; | 2584 | break; |
2579 | case L2CAP_MODE_STREAMING: | 2585 | case L2CAP_MODE_STREAMING: |
2580 | pi->max_pdu_size = le16_to_cpu(rfc.max_pdu_size); | 2586 | pi->mps = le16_to_cpu(rfc.max_pdu_size); |
2581 | break; | ||
2582 | } | 2587 | } |
2583 | } | 2588 | } |
2584 | 2589 | ||
@@ -3753,7 +3758,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk | |||
3753 | * Receiver will miss it and start proper recovery | 3758 | * Receiver will miss it and start proper recovery |
3754 | * procedures and ask retransmission. | 3759 | * procedures and ask retransmission. |
3755 | */ | 3760 | */ |
3756 | if (len > L2CAP_DEFAULT_MAX_PDU_SIZE) | 3761 | if (len > pi->mps) |
3757 | goto drop; | 3762 | goto drop; |
3758 | 3763 | ||
3759 | if (l2cap_check_fcs(pi, skb)) | 3764 | if (l2cap_check_fcs(pi, skb)) |
@@ -3784,8 +3789,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk | |||
3784 | if (pi->fcs == L2CAP_FCS_CRC16) | 3789 | if (pi->fcs == L2CAP_FCS_CRC16) |
3785 | len -= 2; | 3790 | len -= 2; |
3786 | 3791 | ||
3787 | if (len > L2CAP_DEFAULT_MAX_PDU_SIZE || len < 4 | 3792 | if (len > pi->mps || len < 4 || __is_sframe(control)) |
3788 | || __is_sframe(control)) | ||
3789 | goto drop; | 3793 | goto drop; |
3790 | 3794 | ||
3791 | if (l2cap_check_fcs(pi, skb)) | 3795 | if (l2cap_check_fcs(pi, skb)) |