aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/sm_sideeffect.c
diff options
context:
space:
mode:
authorVlad Yasevich <vladislav.yasevich@hp.com>2008-06-19 19:08:18 -0400
committerDavid S. Miller <davem@davemloft.net>2008-06-19 19:08:18 -0400
commit2e3216cd54b142ba605e87522e15f42e0c4e3996 (patch)
treeda4d7a6ff4811d9f38b81c70f08b221b575e1254 /net/sctp/sm_sideeffect.c
parent7115e632f90952454ab6426e0d2151327162a30f (diff)
sctp: Follow security requirement of responding with 1 packet
RFC 4960, Section 11.4. Protection of Non-SCTP-Capable Hosts When an SCTP stack receives a packet containing multiple control or DATA chunks and the processing of the packet requires the sending of multiple chunks in response, the sender of the response chunk(s) MUST NOT send more than one packet. If bundling is supported, multiple response chunks that fit into a single packet MAY be bundled together into one single response packet. If bundling is not supported, then the sender MUST NOT send more than one response chunk and MUST discard all other responses. Note that this rule does NOT apply to a SACK chunk, since a SACK chunk is, in itself, a response to DATA and a SACK does not require a response of more DATA. We implement this by not servicing our outqueue until we reach the end of the packet. This enables maximum bundling. We also identify 'response' chunks and make sure that we only send 1 packet when sending such chunks. Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp/sm_sideeffect.c')
-rw-r--r--net/sctp/sm_sideeffect.c27
1 files changed, 18 insertions, 9 deletions
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index b083312c725a..9732c797e8ed 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -664,7 +664,7 @@ static int sctp_cmd_process_sack(sctp_cmd_seq_t *cmds,
664 struct sctp_association *asoc, 664 struct sctp_association *asoc,
665 struct sctp_sackhdr *sackh) 665 struct sctp_sackhdr *sackh)
666{ 666{
667 int err; 667 int err = 0;
668 668
669 if (sctp_outq_sack(&asoc->outqueue, sackh)) { 669 if (sctp_outq_sack(&asoc->outqueue, sackh)) {
670 /* There are no more TSNs awaiting SACK. */ 670 /* There are no more TSNs awaiting SACK. */
@@ -672,11 +672,6 @@ static int sctp_cmd_process_sack(sctp_cmd_seq_t *cmds,
672 SCTP_ST_OTHER(SCTP_EVENT_NO_PENDING_TSN), 672 SCTP_ST_OTHER(SCTP_EVENT_NO_PENDING_TSN),
673 asoc->state, asoc->ep, asoc, NULL, 673 asoc->state, asoc->ep, asoc, NULL,
674 GFP_ATOMIC); 674 GFP_ATOMIC);
675 } else {
676 /* Windows may have opened, so we need
677 * to check if we have DATA to transmit
678 */
679 err = sctp_outq_flush(&asoc->outqueue, 0);
680 } 675 }
681 676
682 return err; 677 return err;
@@ -1481,8 +1476,15 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
1481 break; 1476 break;
1482 1477
1483 case SCTP_CMD_DISCARD_PACKET: 1478 case SCTP_CMD_DISCARD_PACKET:
1484 /* We need to discard the whole packet. */ 1479 /* We need to discard the whole packet.
1480 * Uncork the queue since there might be
1481 * responses pending
1482 */
1485 chunk->pdiscard = 1; 1483 chunk->pdiscard = 1;
1484 if (asoc) {
1485 sctp_outq_uncork(&asoc->outqueue);
1486 local_cork = 0;
1487 }
1486 break; 1488 break;
1487 1489
1488 case SCTP_CMD_RTO_PENDING: 1490 case SCTP_CMD_RTO_PENDING:
@@ -1553,8 +1555,15 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
1553 } 1555 }
1554 1556
1555out: 1557out:
1556 if (local_cork) 1558 /* If this is in response to a received chunk, wait until
1557 sctp_outq_uncork(&asoc->outqueue); 1559 * we are done with the packet to open the queue so that we don't
1560 * send multiple packets in response to a single request.
1561 */
1562 if (asoc && SCTP_EVENT_T_CHUNK == event_type && chunk) {
1563 if (chunk->end_of_packet || chunk->singleton)
1564 sctp_outq_uncork(&asoc->outqueue);
1565 } else if (local_cork)
1566 sctp_outq_uncork(&asoc->outqueue);
1558 return error; 1567 return error;
1559nomem: 1568nomem:
1560 error = -ENOMEM; 1569 error = -ENOMEM;