aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Tuexen <tuexen@FreeBSD.org>2023-05-03 15:30:50 +0000
committerMichael Tuexen <tuexen@FreeBSD.org>2023-05-03 15:33:49 +0000
commitd9ae4adff2715cfab4a941037ec15aa07108efa1 (patch)
treed85d91786e135c2ab5740788bdfe0cad71e8dbce
parent81f964e2ffb7cd5d30df0a5c3877900cca4fdd07 (diff)
downloadsrc-d9ae4adff2715cfab4a941037ec15aa07108efa1.tar.gz
src-d9ae4adff2715cfab4a941037ec15aa07108efa1.zip
sctp: improve shutdown(..., SHUT_WR) handling
When shutdown(..., SHUT_WR) is called in the front states, send a SHUTDOWN chunk when a COOKIE ACK chunk is received and there is no outstanding data. MFC after: 1 week
-rw-r--r--sys/netinet/sctp_input.c22
1 files changed, 16 insertions, 6 deletions
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index 26abf4953164..fc362d091a22 100644
--- a/sys/netinet/sctp_input.c
+++ b/sys/netinet/sctp_input.c
@@ -2782,16 +2782,13 @@ sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp SCTP_UNUSED,
__LINE__);
}
sctp_stop_all_cookie_timers(stcb);
+ sctp_toss_old_cookies(stcb, asoc);
/* process according to association state */
if (SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_ECHOED) {
/* state change only needed when I am in right state */
SCTPDBG(SCTP_DEBUG_INPUT2, "moving to OPEN state\n");
SCTP_SET_STATE(stcb, SCTP_STATE_OPEN);
sctp_start_net_timers(stcb);
- if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
- sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
- stcb->sctp_ep, stcb, NULL);
- }
/* update RTO */
SCTP_STAT_INCR_COUNTER32(sctps_activeestab);
SCTP_STAT_INCR_GAUGE32(sctps_currestab);
@@ -2815,6 +2812,21 @@ sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp SCTP_UNUSED,
}
}
+ if ((asoc->state & SCTP_STATE_SHUTDOWN_PENDING) &&
+ TAILQ_EMPTY(&asoc->send_queue) &&
+ TAILQ_EMPTY(&asoc->sent_queue) &&
+ (asoc->stream_queue_cnt == 0)) {
+ SCTP_STAT_DECR_GAUGE32(sctps_currestab);
+ SCTP_SET_STATE(stcb, SCTP_STATE_SHUTDOWN_SENT);
+ sctp_stop_timers_for_shutdown(stcb);
+ sctp_send_shutdown(stcb, net);
+ sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
+ stcb->sctp_ep, stcb, net);
+ sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
+ stcb->sctp_ep, stcb, NULL);
+ sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_LOCKED);
+ }
+
if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
/*
* We don't need to do the asconf thing, nor hb or
@@ -2850,8 +2862,6 @@ sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp SCTP_UNUSED,
}
}
closed_socket:
- /* Toss the cookie if I can */
- sctp_toss_old_cookies(stcb, asoc);
/* Restart the timer if we have pending data */
TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) {
if (chk->whoTo != NULL) {