aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Tuexen <tuexen@FreeBSD.org>2023-08-09 02:17:52 +0000
committerMichael Tuexen <tuexen@FreeBSD.org>2024-01-11 12:31:09 +0000
commita2f048084999dca10f774412eb69839a0b0aea83 (patch)
treea982c8d851b3285546ae1c6ea3626f43c8b291b4
parent31acdb17668ec28798fdace1f1f192d18ec50765 (diff)
downloadsrc-a2f048084999dca10f774412eb69839a0b0aea83.tar.gz
src-a2f048084999dca10f774412eb69839a0b0aea83.zip
sctp: another cleanup
No functional change intended. (cherry picked from commit 85e5480df95e6bca38910f44f6e9b4d7773904ed)
-rw-r--r--sys/netinet/sctp_usrreq.c226
1 files changed, 106 insertions, 120 deletions
diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c
index 4e43c8c72f40..b28bfc66af8d 100644
--- a/sys/netinet/sctp_usrreq.c
+++ b/sys/netinet/sctp_usrreq.c
@@ -663,7 +663,10 @@ connected_type:
int
sctp_disconnect(struct socket *so)
{
+ struct epoch_tracker et;
struct sctp_inpcb *inp;
+ struct sctp_association *asoc;
+ struct sctp_tcb *stcb;
inp = (struct sctp_inpcb *)so->so_pcb;
if (inp == NULL) {
@@ -671,134 +674,117 @@ sctp_disconnect(struct socket *so)
return (ENOTCONN);
}
SCTP_INP_RLOCK(inp);
- if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
- (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
- if (LIST_EMPTY(&inp->sctp_asoc_list)) {
- /* No connection */
- SCTP_INP_RUNLOCK(inp);
- return (0);
- } else {
- struct epoch_tracker et;
- struct sctp_association *asoc;
- struct sctp_tcb *stcb;
-
- stcb = LIST_FIRST(&inp->sctp_asoc_list);
- if (stcb == NULL) {
- SCTP_INP_RUNLOCK(inp);
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
- return (EINVAL);
- }
- SCTP_TCB_LOCK(stcb);
- asoc = &stcb->asoc;
- if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
- /* We are about to be freed, out of here */
- SCTP_TCB_UNLOCK(stcb);
- SCTP_INP_RUNLOCK(inp);
- return (0);
- }
- NET_EPOCH_ENTER(et);
- if (((so->so_options & SO_LINGER) && (so->so_linger == 0)) ||
- (SCTP_SBAVAIL(&so->so_rcv) > 0)) {
- if (SCTP_GET_STATE(stcb) != SCTP_STATE_COOKIE_WAIT) {
- /* Left with Data unread */
- struct mbuf *op_err;
+ KASSERT(inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE ||
+ inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL,
+ ("Not a one-to-one style socket"));
+ stcb = LIST_FIRST(&inp->sctp_asoc_list);
+ if (stcb == NULL) {
+ SCTP_INP_RUNLOCK(inp);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
+ return (ENOTCONN);
+ }
+ SCTP_TCB_LOCK(stcb);
+ asoc = &stcb->asoc;
+ if (asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) {
+ /* We are about to be freed, out of here */
+ SCTP_TCB_UNLOCK(stcb);
+ SCTP_INP_RUNLOCK(inp);
+ return (0);
+ }
+ NET_EPOCH_ENTER(et);
+ if (((so->so_options & SO_LINGER) && (so->so_linger == 0)) ||
+ (SCTP_SBAVAIL(&so->so_rcv) > 0)) {
+ if (SCTP_GET_STATE(stcb) != SCTP_STATE_COOKIE_WAIT) {
+ /* Left with Data unread */
+ struct mbuf *op_err;
- op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
- sctp_send_abort_tcb(stcb, op_err, SCTP_SO_LOCKED);
- SCTP_STAT_INCR_COUNTER32(sctps_aborted);
- }
- SCTP_INP_RUNLOCK(inp);
- if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) ||
- (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
- SCTP_STAT_DECR_GAUGE32(sctps_currestab);
- }
- (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
- SCTP_FROM_SCTP_USRREQ + SCTP_LOC_3);
- /* No unlock tcb assoc is gone */
- NET_EPOCH_EXIT(et);
- return (0);
+ op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
+ sctp_send_abort_tcb(stcb, op_err, SCTP_SO_LOCKED);
+ SCTP_STAT_INCR_COUNTER32(sctps_aborted);
+ }
+ SCTP_INP_RUNLOCK(inp);
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
+ SCTP_STAT_DECR_GAUGE32(sctps_currestab);
+ }
+ (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
+ SCTP_FROM_SCTP_USRREQ + SCTP_LOC_3);
+ /* No unlock tcb assoc is gone */
+ NET_EPOCH_EXIT(et);
+ return (0);
+ }
+ if (TAILQ_EMPTY(&asoc->send_queue) &&
+ TAILQ_EMPTY(&asoc->sent_queue) &&
+ (asoc->stream_queue_cnt == 0)) {
+ /* there is nothing queued to send, so done */
+ if ((*asoc->ss_functions.sctp_ss_is_user_msgs_incomplete) (stcb, asoc)) {
+ goto abort_anyway;
+ }
+ if ((SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_SENT) &&
+ (SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
+ /* only send SHUTDOWN 1st time thru */
+ struct sctp_nets *netp;
+
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
+ SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
- if (TAILQ_EMPTY(&asoc->send_queue) &&
- TAILQ_EMPTY(&asoc->sent_queue) &&
- (asoc->stream_queue_cnt == 0)) {
- /* there is nothing queued to send, so done */
- if ((*asoc->ss_functions.sctp_ss_is_user_msgs_incomplete) (stcb, asoc)) {
- goto abort_anyway;
- }
- if ((SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_SENT) &&
- (SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
- /* only send SHUTDOWN 1st time thru */
- struct sctp_nets *netp;
-
- if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) ||
- (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
- SCTP_STAT_DECR_GAUGE32(sctps_currestab);
- }
- SCTP_SET_STATE(stcb, SCTP_STATE_SHUTDOWN_SENT);
- sctp_stop_timers_for_shutdown(stcb);
- if (stcb->asoc.alternate) {
- netp = stcb->asoc.alternate;
- } else {
- netp = stcb->asoc.primary_destination;
- }
- sctp_send_shutdown(stcb, netp);
- sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
- stcb->sctp_ep, stcb, netp);
- sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
- stcb->sctp_ep, stcb, NULL);
- sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
- }
+ SCTP_SET_STATE(stcb, SCTP_STATE_SHUTDOWN_SENT);
+ sctp_stop_timers_for_shutdown(stcb);
+ if (stcb->asoc.alternate) {
+ netp = stcb->asoc.alternate;
} else {
- /*
- * we still got (or just got) data to send,
- * so set SHUTDOWN_PENDING
- */
- /*
- * XXX sockets draft says that SCTP_EOF
- * should be sent with no data. currently,
- * we will allow user data to be sent first
- * and move to SHUTDOWN-PENDING
- */
- SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_SHUTDOWN_PENDING);
- if ((*asoc->ss_functions.sctp_ss_is_user_msgs_incomplete) (stcb, asoc)) {
- SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_PARTIAL_MSG_LEFT);
- }
- if (TAILQ_EMPTY(&asoc->send_queue) &&
- TAILQ_EMPTY(&asoc->sent_queue) &&
- (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
- struct mbuf *op_err;
-
- abort_anyway:
- op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
- stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ + SCTP_LOC_4;
- sctp_send_abort_tcb(stcb, op_err, SCTP_SO_LOCKED);
- SCTP_STAT_INCR_COUNTER32(sctps_aborted);
- if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) ||
- (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
- SCTP_STAT_DECR_GAUGE32(sctps_currestab);
- }
- SCTP_INP_RUNLOCK(inp);
- (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
- SCTP_FROM_SCTP_USRREQ + SCTP_LOC_5);
- NET_EPOCH_EXIT(et);
- return (0);
- } else {
- sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
- }
+ netp = stcb->asoc.primary_destination;
+ }
+ sctp_send_shutdown(stcb, netp);
+ sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
+ stcb->sctp_ep, stcb, netp);
+ sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
+ stcb->sctp_ep, stcb, NULL);
+ sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
+ }
+ } else {
+ /*
+ * we still got (or just got) data to send, so set
+ * SHUTDOWN_PENDING
+ */
+ /*
+ * XXX sockets draft says that SCTP_EOF should be sent with
+ * no data. currently, we will allow user data to be sent
+ * first and move to SHUTDOWN-PENDING
+ */
+ SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_SHUTDOWN_PENDING);
+ if ((*asoc->ss_functions.sctp_ss_is_user_msgs_incomplete) (stcb, asoc)) {
+ SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_PARTIAL_MSG_LEFT);
+ }
+ if (TAILQ_EMPTY(&asoc->send_queue) &&
+ TAILQ_EMPTY(&asoc->sent_queue) &&
+ (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
+ struct mbuf *op_err;
+
+ abort_anyway:
+ op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
+ stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ + SCTP_LOC_4;
+ sctp_send_abort_tcb(stcb, op_err, SCTP_SO_LOCKED);
+ SCTP_STAT_INCR_COUNTER32(sctps_aborted);
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
+ SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
- soisdisconnecting(so);
- NET_EPOCH_EXIT(et);
- SCTP_TCB_UNLOCK(stcb);
SCTP_INP_RUNLOCK(inp);
+ (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
+ SCTP_FROM_SCTP_USRREQ + SCTP_LOC_5);
+ NET_EPOCH_EXIT(et);
return (0);
+ } else {
+ sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
}
- /* not reached */
- } else {
- /* UDP model does not support this */
- SCTP_INP_RUNLOCK(inp);
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
- return (EOPNOTSUPP);
}
+ soisdisconnecting(so);
+ NET_EPOCH_EXIT(et);
+ SCTP_TCB_UNLOCK(stcb);
+ SCTP_INP_RUNLOCK(inp);
+ return (0);
}
int