aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVlad Yasevich <vyasevich@gmail.com>2014-10-03 18:16:20 -0400
committerDavid S. Miller <davem@davemloft.net>2014-10-06 00:21:45 -0400
commitbdf6fa52f01b941d4a80372d56de465bdbbd1d23 (patch)
tree6f37046e3268e0123dd1abbe26065fa59c3b79d6
parentf408c3d956c987844dcb7c6837abfbb0331fb7f6 (diff)
sctp: handle association restarts when the socket is closed.
Currently association restarts do not take into consideration the state of the socket. When a restart happens, the current assocation simply transitions into established state. This creates a condition where a remote system, through a the restart procedure, may create a local association that is no way reachable by user. The conditions to trigger this are as follows: 1) Remote does not acknoledge some data causing data to remain outstanding. 2) Local application calls close() on the socket. Since data is still outstanding, the association is placed in SHUTDOWN_PENDING state. However, the socket is closed. 3) The remote tries to create a new association, triggering a restart on the local system. The association moves from SHUTDOWN_PENDING to ESTABLISHED. At this point, it is no longer reachable by any socket on the local system. This patch addresses the above situation by moving the newly ESTABLISHED association into SHUTDOWN-SENT state and bundling a SHUTDOWN after the COOKIE-ACK chunk. This way, the restarted associate immidiately enters the shutdown procedure and forces the termination of the unreachable association. Reported-by: David Laight <David.Laight@aculab.com> Signed-off-by: Vlad Yasevich <vyasevich@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/sctp/command.h2
-rw-r--r--net/sctp/sm_statefuns.c19
2 files changed, 17 insertions, 4 deletions
diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h
index f22538e68245..d4a20d00461c 100644
--- a/include/net/sctp/command.h
+++ b/include/net/sctp/command.h
@@ -115,7 +115,7 @@ typedef enum {
115 * analysis of the state functions, but in reality just taken from 115 * analysis of the state functions, but in reality just taken from
116 * thin air in the hopes othat we don't trigger a kernel panic. 116 * thin air in the hopes othat we don't trigger a kernel panic.
117 */ 117 */
118#define SCTP_MAX_NUM_COMMANDS 14 118#define SCTP_MAX_NUM_COMMANDS 20
119 119
120typedef union { 120typedef union {
121 void *zero_all; /* Set to NULL to clear the entire union */ 121 void *zero_all; /* Set to NULL to clear the entire union */
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index d3f1ea460c50..c8f606324134 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -1775,9 +1775,22 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(struct net *net,
1775 /* Update the content of current association. */ 1775 /* Update the content of current association. */
1776 sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc)); 1776 sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc));
1777 sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev)); 1777 sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
1778 sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 1778 if (sctp_state(asoc, SHUTDOWN_PENDING) &&
1779 SCTP_STATE(SCTP_STATE_ESTABLISHED)); 1779 (sctp_sstate(asoc->base.sk, CLOSING) ||
1780 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); 1780 sock_flag(asoc->base.sk, SOCK_DEAD))) {
1781 /* if were currently in SHUTDOWN_PENDING, but the socket
1782 * has been closed by user, don't transition to ESTABLISHED.
1783 * Instead trigger SHUTDOWN bundled with COOKIE_ACK.
1784 */
1785 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
1786 return sctp_sf_do_9_2_start_shutdown(net, ep, asoc,
1787 SCTP_ST_CHUNK(0), NULL,
1788 commands);
1789 } else {
1790 sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
1791 SCTP_STATE(SCTP_STATE_ESTABLISHED));
1792 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
1793 }
1781 return SCTP_DISPOSITION_CONSUME; 1794 return SCTP_DISPOSITION_CONSUME;
1782 1795
1783nomem_ev: 1796nomem_ev: