Author: tuexen
Date: Thu Sep  3 22:15:56 2015
New Revision: 287444
URL: https://svnweb.freebsd.org/changeset/base/287444

Log:
  Fix a bug where two SHUTDOWN_ACK chunks were sent if a SHUTDOWN chunk was
  received acking all outstanding data.

Modified:
  head/sys/netinet/sctp_input.c

Modified: head/sys/netinet/sctp_input.c
==============================================================================
--- head/sys/netinet/sctp_input.c       Thu Sep  3 20:47:13 2015        
(r287443)
+++ head/sys/netinet/sctp_input.c       Thu Sep  3 22:15:56 2015        
(r287444)
@@ -867,6 +867,7 @@ sctp_handle_shutdown(struct sctp_shutdow
 {
        struct sctp_association *asoc;
        int some_on_streamwheel;
+       int old_state;
 
 #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
        struct socket *so;
@@ -885,11 +886,11 @@ sctp_handle_shutdown(struct sctp_shutdow
        if (ntohs(cp->ch.chunk_length) != sizeof(struct sctp_shutdown_chunk)) {
                /* Shutdown NOT the expected size */
                return;
-       } else {
-               sctp_update_acked(stcb, cp, abort_flag);
-               if (*abort_flag) {
-                       return;
-               }
+       }
+       old_state = SCTP_GET_STATE(asoc);
+       sctp_update_acked(stcb, cp, abort_flag);
+       if (*abort_flag) {
+               return;
        }
        if (asoc->control_pdapi) {
                /*
@@ -959,12 +960,16 @@ sctp_handle_shutdown(struct sctp_shutdow
                    (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
                        SCTP_STAT_DECR_GAUGE32(sctps_currestab);
                }
-               SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT);
                SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
-               sctp_stop_timers_for_shutdown(stcb);
-               sctp_send_shutdown_ack(stcb, net);
-               sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK, stcb->sctp_ep,
-                   stcb, net);
+               if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT) {
+                       SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT);
+                       sctp_stop_timers_for_shutdown(stcb);
+                       sctp_send_shutdown_ack(stcb, net);
+                       sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK,
+                           stcb->sctp_ep, stcb, net);
+               } else if (old_state == SCTP_STATE_SHUTDOWN_ACK_SENT) {
+                       sctp_send_shutdown_ack(stcb, net);
+               }
        }
 }
 
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to