aboutsummaryrefslogtreecommitdiffstats
path: root/net
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
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')
-rw-r--r--net/sctp/associola.c1
-rw-r--r--net/sctp/output.c7
-rw-r--r--net/sctp/outqueue.c34
-rw-r--r--net/sctp/sm_sideeffect.c27
-rw-r--r--net/sctp/sm_statefuns.c16
5 files changed, 53 insertions, 32 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 35b6a023a6d0..ff1dc5bd936c 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -1025,6 +1025,7 @@ static void sctp_assoc_bh_rcv(struct work_struct *work)
1025 struct sctp_chunk *chunk; 1025 struct sctp_chunk *chunk;
1026 struct sock *sk; 1026 struct sock *sk;
1027 struct sctp_inq *inqueue; 1027 struct sctp_inq *inqueue;
1028 struct sctp_outq *outq;
1028 int state; 1029 int state;
1029 sctp_subtype_t subtype; 1030 sctp_subtype_t subtype;
1030 int error = 0; 1031 int error = 0;
diff --git a/net/sctp/output.c b/net/sctp/output.c
index 6d45bae93b46..abcd00dc05eb 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -157,7 +157,8 @@ void sctp_packet_free(struct sctp_packet *packet)
157 * packet can be sent only after receiving the COOKIE_ACK. 157 * packet can be sent only after receiving the COOKIE_ACK.
158 */ 158 */
159sctp_xmit_t sctp_packet_transmit_chunk(struct sctp_packet *packet, 159sctp_xmit_t sctp_packet_transmit_chunk(struct sctp_packet *packet,
160 struct sctp_chunk *chunk) 160 struct sctp_chunk *chunk,
161 int one_packet)
161{ 162{
162 sctp_xmit_t retval; 163 sctp_xmit_t retval;
163 int error = 0; 164 int error = 0;
@@ -175,7 +176,9 @@ sctp_xmit_t sctp_packet_transmit_chunk(struct sctp_packet *packet,
175 /* If we have an empty packet, then we can NOT ever 176 /* If we have an empty packet, then we can NOT ever
176 * return PMTU_FULL. 177 * return PMTU_FULL.
177 */ 178 */
178 retval = sctp_packet_append_chunk(packet, chunk); 179 if (!one_packet)
180 retval = sctp_packet_append_chunk(packet,
181 chunk);
179 } 182 }
180 break; 183 break;
181 184
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index ace6770e9048..70ead8dc3485 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -702,6 +702,7 @@ int sctp_outq_uncork(struct sctp_outq *q)
702 return error; 702 return error;
703} 703}
704 704
705
705/* 706/*
706 * Try to flush an outqueue. 707 * Try to flush an outqueue.
707 * 708 *
@@ -725,6 +726,7 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
725 sctp_xmit_t status; 726 sctp_xmit_t status;
726 int error = 0; 727 int error = 0;
727 int start_timer = 0; 728 int start_timer = 0;
729 int one_packet = 0;
728 730
729 /* These transports have chunks to send. */ 731 /* These transports have chunks to send. */
730 struct list_head transport_list; 732 struct list_head transport_list;
@@ -830,20 +832,33 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
830 if (sctp_test_T_bit(chunk)) { 832 if (sctp_test_T_bit(chunk)) {
831 packet->vtag = asoc->c.my_vtag; 833 packet->vtag = asoc->c.my_vtag;
832 } 834 }
833 case SCTP_CID_SACK: 835 /* The following chunks are "response" chunks, i.e.
834 case SCTP_CID_HEARTBEAT: 836 * they are generated in response to something we
837 * received. If we are sending these, then we can
838 * send only 1 packet containing these chunks.
839 */
835 case SCTP_CID_HEARTBEAT_ACK: 840 case SCTP_CID_HEARTBEAT_ACK:
836 case SCTP_CID_SHUTDOWN:
837 case SCTP_CID_SHUTDOWN_ACK: 841 case SCTP_CID_SHUTDOWN_ACK:
838 case SCTP_CID_ERROR:
839 case SCTP_CID_COOKIE_ECHO:
840 case SCTP_CID_COOKIE_ACK: 842 case SCTP_CID_COOKIE_ACK:
841 case SCTP_CID_ECN_ECNE: 843 case SCTP_CID_COOKIE_ECHO:
844 case SCTP_CID_ERROR:
842 case SCTP_CID_ECN_CWR: 845 case SCTP_CID_ECN_CWR:
843 case SCTP_CID_ASCONF:
844 case SCTP_CID_ASCONF_ACK: 846 case SCTP_CID_ASCONF_ACK:
847 one_packet = 1;
848 /* Fall throught */
849
850 case SCTP_CID_SACK:
851 case SCTP_CID_HEARTBEAT:
852 case SCTP_CID_SHUTDOWN:
853 case SCTP_CID_ECN_ECNE:
854 case SCTP_CID_ASCONF:
845 case SCTP_CID_FWD_TSN: 855 case SCTP_CID_FWD_TSN:
846 sctp_packet_transmit_chunk(packet, chunk); 856 status = sctp_packet_transmit_chunk(packet, chunk,
857 one_packet);
858 if (status != SCTP_XMIT_OK) {
859 /* put the chunk back */
860 list_add(&chunk->list, &q->control_chunk_list);
861 }
847 break; 862 break;
848 863
849 default: 864 default:
@@ -974,7 +989,7 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
974 atomic_read(&chunk->skb->users) : -1); 989 atomic_read(&chunk->skb->users) : -1);
975 990
976 /* Add the chunk to the packet. */ 991 /* Add the chunk to the packet. */
977 status = sctp_packet_transmit_chunk(packet, chunk); 992 status = sctp_packet_transmit_chunk(packet, chunk, 0);
978 993
979 switch (status) { 994 switch (status) {
980 case SCTP_XMIT_PMTU_FULL: 995 case SCTP_XMIT_PMTU_FULL:
@@ -1239,7 +1254,6 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
1239 * Make sure the empty queue handler will get run later. 1254 * Make sure the empty queue handler will get run later.
1240 */ 1255 */
1241 q->empty = (list_empty(&q->out_chunk_list) && 1256 q->empty = (list_empty(&q->out_chunk_list) &&
1242 list_empty(&q->control_chunk_list) &&
1243 list_empty(&q->retransmit)); 1257 list_empty(&q->retransmit));
1244 if (!q->empty) 1258 if (!q->empty)
1245 goto finish; 1259 goto finish;
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;
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 0c9d5a6950fe..b66a41d03c0d 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -795,8 +795,6 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep,
795 sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, 795 sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START,
796 SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); 796 SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
797 797
798 sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL());
799
800 /* This will send the COOKIE ACK */ 798 /* This will send the COOKIE ACK */
801 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); 799 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
802 800
@@ -883,7 +881,6 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(const struct sctp_endpoint *ep,
883 if (asoc->autoclose) 881 if (asoc->autoclose)
884 sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, 882 sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START,
885 SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); 883 SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
886 sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL());
887 884
888 /* It may also notify its ULP about the successful 885 /* It may also notify its ULP about the successful
889 * establishment of the association with a Communication Up 886 * establishment of the association with a Communication Up
@@ -1781,7 +1778,6 @@ static sctp_disposition_t sctp_sf_do_dupcook_b(const struct sctp_endpoint *ep,
1781 goto nomem; 1778 goto nomem;
1782 1779
1783 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); 1780 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
1784 sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL());
1785 1781
1786 /* RFC 2960 5.1 Normal Establishment of an Association 1782 /* RFC 2960 5.1 Normal Establishment of an Association
1787 * 1783 *
@@ -1898,12 +1894,13 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(const struct sctp_endpoint *ep,
1898 1894
1899 } 1895 }
1900 } 1896 }
1901 sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL());
1902 1897
1903 repl = sctp_make_cookie_ack(new_asoc, chunk); 1898 repl = sctp_make_cookie_ack(new_asoc, chunk);
1904 if (!repl) 1899 if (!repl)
1905 goto nomem; 1900 goto nomem;
1906 1901
1902 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
1903
1907 if (ev) 1904 if (ev)
1908 sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, 1905 sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
1909 SCTP_ULPEVENT(ev)); 1906 SCTP_ULPEVENT(ev));
@@ -1911,9 +1908,6 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(const struct sctp_endpoint *ep,
1911 sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, 1908 sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
1912 SCTP_ULPEVENT(ai_ev)); 1909 SCTP_ULPEVENT(ai_ev));
1913 1910
1914 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
1915 sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL());
1916
1917 return SCTP_DISPOSITION_CONSUME; 1911 return SCTP_DISPOSITION_CONSUME;
1918 1912
1919nomem: 1913nomem:
@@ -3970,9 +3964,6 @@ sctp_disposition_t sctp_sf_unk_chunk(const struct sctp_endpoint *ep,
3970 return sctp_sf_pdiscard(ep, asoc, type, arg, commands); 3964 return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
3971 break; 3965 break;
3972 case SCTP_CID_ACTION_DISCARD_ERR: 3966 case SCTP_CID_ACTION_DISCARD_ERR:
3973 /* Discard the packet. */
3974 sctp_sf_pdiscard(ep, asoc, type, arg, commands);
3975
3976 /* Generate an ERROR chunk as response. */ 3967 /* Generate an ERROR chunk as response. */
3977 hdr = unk_chunk->chunk_hdr; 3968 hdr = unk_chunk->chunk_hdr;
3978 err_chunk = sctp_make_op_error(asoc, unk_chunk, 3969 err_chunk = sctp_make_op_error(asoc, unk_chunk,
@@ -3982,6 +3973,9 @@ sctp_disposition_t sctp_sf_unk_chunk(const struct sctp_endpoint *ep,
3982 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, 3973 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
3983 SCTP_CHUNK(err_chunk)); 3974 SCTP_CHUNK(err_chunk));
3984 } 3975 }
3976
3977 /* Discard the packet. */
3978 sctp_sf_pdiscard(ep, asoc, type, arg, commands);
3985 return SCTP_DISPOSITION_CONSUME; 3979 return SCTP_DISPOSITION_CONSUME;
3986 break; 3980 break;
3987 case SCTP_CID_ACTION_SKIP: 3981 case SCTP_CID_ACTION_SKIP: