Author: tuexen
Date: Sun May 31 12:56:22 2015
New Revision: 283826
URL: https://svnweb.freebsd.org/changeset/base/283826

Log:
  MFC r283662:
  
  Fix a bug where messages would not be sent in SHUTDOWN_RECEIVED state.
  This problem was reported by Mark Bonnekessel and Markus Boese.
  Thanks to Irene Ruengeler for helping me to fix the cause of
  the problem. It can be tested with the following packetdrill script:
  
  +0.0 socket(..., SOCK_STREAM, IPPROTO_SCTP) = 3
  +0.0 fcntl(3, F_GETFL) = 0x2 (flags O_RDWR)
  +0.0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
  // Check the handshake with an empty(!) cookie
  +0.1 connect(3, ..., ...) = -1 EINPROGRESS (Operation now in progress)
  +0.0 > sctp: INIT[flgs=0, tag=1, a_rwnd=..., os=..., is=..., tsn=0, ...]
  +0.1 < sctp: INIT_ACK[flgs=0, tag=2, a_rwnd=10000, os=1, is=1, tsn=0, 
STATE_COOKIE[len=4, val=...]]
  +0.0 > sctp: COOKIE_ECHO[flgs=0, len=4, val=...]
  +0.1 < sctp: COOKIE_ACK[flgs=0]
  +0.0 getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
  +0.0 write(3, ..., 1024) = 1024
  +0.0 > sctp: DATA[flgs=BE, len=1040, tsn=0, sid=0, ssn=0, ppid=0]
  +0.0 write(3, ..., 1024) = 1024 // Pending due to Nagle
  +0.0 < sctp: SHUTDOWN[flgs=0, cum_tsn=0]
  +0.0 > sctp: DATA[flgs=BE, len=1040, tsn=1, sid=0, ssn=1, ppid=0]
  +0.0 < sctp: SACK[flgs=0, cum_tsn=1, a_rwnd=10000, gaps=[], dups=[]] // Do we 
need another SHUTDOWN here?
  +0.0 > sctp: SHUTDOWN_ACK[flgs=0]
  +0.0 < sctp: SHUTDOWN_COMPLETE[flgs=0]
  +0.0 close(3) = 0

Modified:
  stable/10/sys/netinet/sctp_asconf.c
  stable/10/sys/netinet/sctp_output.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/netinet/sctp_asconf.c
==============================================================================
--- stable/10/sys/netinet/sctp_asconf.c Sun May 31 12:53:16 2015        
(r283825)
+++ stable/10/sys/netinet/sctp_asconf.c Sun May 31 12:56:22 2015        
(r283826)
@@ -1977,7 +1977,8 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *
                         * sent when the state goes open.
                         */
                        if (status == 0 &&
-                           SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
+                           ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
+                           (SCTP_GET_STATE(&stcb->asoc) == 
SCTP_STATE_SHUTDOWN_RECEIVED))) {
 #ifdef SCTP_TIMER_BASED_ASCONF
                                sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, inp,
                                    stcb, stcb->asoc.primary_destination);
@@ -2225,7 +2226,8 @@ sctp_asconf_iterator_stcb(struct sctp_in
                         * count of queued params.  If in the non-open
                         * state, these get sent when the assoc goes open.
                         */
-                       if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
+                       if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
+                           (SCTP_GET_STATE(&stcb->asoc) == 
SCTP_STATE_SHUTDOWN_RECEIVED)) {
                                if (status >= 0) {
                                        num_queued++;
                                }
@@ -2285,7 +2287,8 @@ sctp_set_primary_ip_address_sa(struct sc
                    "set_primary_ip_address_sa: queued on tcb=%p, ",
                    (void *)stcb);
                SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
-               if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
+               if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
+                   (SCTP_GET_STATE(&stcb->asoc) == 
SCTP_STATE_SHUTDOWN_RECEIVED)) {
 #ifdef SCTP_TIMER_BASED_ASCONF
                        sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
                            stcb->sctp_ep, stcb,
@@ -2321,7 +2324,8 @@ sctp_set_primary_ip_address(struct sctp_
                                SCTPDBG(SCTP_DEBUG_ASCONF1, 
"set_primary_ip_address: queued on stcb=%p, ",
                                    (void *)stcb);
                                SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, 
&ifa->address.sa);
-                               if (SCTP_GET_STATE(&stcb->asoc) == 
SCTP_STATE_OPEN) {
+                               if ((SCTP_GET_STATE(&stcb->asoc) == 
SCTP_STATE_OPEN) ||
+                                   (SCTP_GET_STATE(&stcb->asoc) == 
SCTP_STATE_SHUTDOWN_RECEIVED)) {
 #ifdef SCTP_TIMER_BASED_ASCONF
                                        sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
                                            stcb->sctp_ep, stcb,

Modified: stable/10/sys/netinet/sctp_output.c
==============================================================================
--- stable/10/sys/netinet/sctp_output.c Sun May 31 12:53:16 2015        
(r283825)
+++ stable/10/sys/netinet/sctp_output.c Sun May 31 12:56:22 2015        
(r283826)
@@ -8551,7 +8551,8 @@ again_one_more_time:
                        omtu = 0;
                        break;
                }
-               if ((((asoc->state & SCTP_STATE_OPEN) == SCTP_STATE_OPEN) &&
+               if ((((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
+                   (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) &&
                    (skip_data_for_this_net == 0)) ||
                    (cookie)) {
                        TAILQ_FOREACH_SAFE(chk, &asoc->send_queue, sctp_next, 
nchk) {
_______________________________________________
svn-src-stable-10@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-stable-10
To unsubscribe, send any mail to "svn-src-stable-10-unsubscr...@freebsd.org"

Reply via email to