diff options
author | Gordon Tetlow <gordon@FreeBSD.org> | 2020-09-02 16:24:32 +0000 |
---|---|---|
committer | Gordon Tetlow <gordon@FreeBSD.org> | 2020-09-02 16:24:32 +0000 |
commit | 411de40890ab22367a6eeaaedc9bb8d0668273b3 (patch) | |
tree | 5c19c1878e0039854702c1484198451581d2613a | |
parent | b4e4841f6486fcec94645a0ec2a340f8c8eff19a (diff) | |
download | src-test2-411de40890ab22367a6eeaaedc9bb8d0668273b3.tar.gz src-test2-411de40890ab22367a6eeaaedc9bb8d0668273b3.zip |
Notes
-rw-r--r-- | sys/netinet/sctp_input.c | 3 | ||||
-rw-r--r-- | sys/netinet/sctp_output.c | 49 | ||||
-rw-r--r-- | sys/netinet/sctp_pcb.c | 9 | ||||
-rw-r--r-- | sys/netinet/sctp_structs.h | 1 | ||||
-rw-r--r-- | sys/netinet/sctputil.c | 17 | ||||
-rw-r--r-- | sys/netinet/sctputil.h | 2 |
6 files changed, 56 insertions, 25 deletions
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index aeb9c1eb8bf9..19e369cef78c 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -839,7 +839,6 @@ sctp_handle_abort(struct sctp_abort_chunk *abort, SCTP_TCB_LOCK(stcb); atomic_subtract_int(&stcb->asoc.refcnt, 1); #endif - SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_WAS_ABORTED); (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_8); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) @@ -1989,7 +1988,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, /* send up all the data */ SCTP_TCB_SEND_LOCK(stcb); - sctp_report_all_outbound(stcb, 0, 1, SCTP_SO_LOCKED); + sctp_report_all_outbound(stcb, 0, SCTP_SO_LOCKED); for (i = 0; i < stcb->asoc.streamoutcnt; i++) { stcb->asoc.strmout[i].chunks_on_queues = 0; #if defined(SCTP_DETAILED_STR_STATS) diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 7874c899b430..719d9562cd1f 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -13159,11 +13159,10 @@ skip_preblock: error = EINVAL; goto out; } - SCTP_TCB_SEND_UNLOCK(stcb); - strm = &stcb->asoc.strmout[srcv->sinfo_stream]; if (strm->last_msg_incomplete == 0) { do_a_copy_in: + SCTP_TCB_SEND_UNLOCK(stcb); sp = sctp_copy_it_in(stcb, asoc, srcv, uio, net, max_len, user_marks_eor, &error); if (error) { goto out; @@ -13189,13 +13188,11 @@ skip_preblock: if (srcv->sinfo_flags & SCTP_UNORDERED) { SCTP_STAT_INCR(sctps_sends_with_unord); } + sp->processing = 1; TAILQ_INSERT_TAIL(&strm->outqueue, sp, next); stcb->asoc.ss_functions.sctp_ss_add_to_stream(stcb, asoc, strm, sp, 1); - SCTP_TCB_SEND_UNLOCK(stcb); } else { - SCTP_TCB_SEND_LOCK(stcb); sp = TAILQ_LAST(&strm->outqueue, sctp_streamhead); - SCTP_TCB_SEND_UNLOCK(stcb); if (sp == NULL) { /* ???? Huh ??? last msg is gone */ #ifdef INVARIANTS @@ -13207,7 +13204,16 @@ skip_preblock: goto do_a_copy_in; } + if (sp->processing) { + SCTP_TCB_SEND_UNLOCK(stcb); + SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); + error = EINVAL; + goto out; + } else { + sp->processing = 1; + } } + SCTP_TCB_SEND_UNLOCK(stcb); while (uio->uio_resid > 0) { /* How much room do we have? */ struct mbuf *new_tail, *mm; @@ -13232,20 +13238,29 @@ skip_preblock: if (mm) { sctp_m_freem(mm); } + SCTP_TCB_SEND_LOCK(stcb); + if (sp != NULL) { + sp->processing = 0; + } + SCTP_TCB_SEND_UNLOCK(stcb); goto out; } /* Update the mbuf and count */ SCTP_TCB_SEND_LOCK(stcb); - if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { + if ((stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) || + (stcb->asoc.state & SCTP_STATE_WAS_ABORTED)) { /* * we need to get out. Peer probably * aborted. */ sctp_m_freem(mm); - if (stcb->asoc.state & SCTP_PCB_FLAGS_WAS_ABORTED) { + if (stcb->asoc.state & SCTP_STATE_WAS_ABORTED) { SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ECONNRESET); error = ECONNRESET; } + if (sp != NULL) { + sp->processing = 0; + } SCTP_TCB_SEND_UNLOCK(stcb); goto out; } @@ -13305,6 +13320,11 @@ skip_preblock: /* wait for space now */ if (non_blocking) { /* Non-blocking io in place out */ + SCTP_TCB_SEND_LOCK(stcb); + if (sp != NULL) { + sp->processing = 0; + } + SCTP_TCB_SEND_UNLOCK(stcb); goto skip_out_eof; } /* What about the INIT, send it maybe */ @@ -13428,6 +13448,11 @@ skip_preblock: } } SOCKBUF_UNLOCK(&so->so_snd); + SCTP_TCB_SEND_LOCK(stcb); + if (sp != NULL) { + sp->processing = 0; + } + SCTP_TCB_SEND_UNLOCK(stcb); goto out_unlocked; } @@ -13437,12 +13462,19 @@ skip_preblock: } } SOCKBUF_UNLOCK(&so->so_snd); + SCTP_TCB_SEND_LOCK(stcb); if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { + if (sp != NULL) { + sp->processing = 0; + } + SCTP_TCB_SEND_UNLOCK(stcb); goto out_unlocked; } + SCTP_TCB_SEND_UNLOCK(stcb); } SCTP_TCB_SEND_LOCK(stcb); - if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { + if ((stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) || + (stcb->asoc.state & SCTP_STATE_WAS_ABORTED)) { SCTP_TCB_SEND_UNLOCK(stcb); goto out_unlocked; } @@ -13458,6 +13490,7 @@ skip_preblock: strm->last_msg_incomplete = 0; asoc->stream_locked = 0; } + sp->processing = 0; } else { SCTP_PRINTF("Huh no sp TSNH?\n"); strm->last_msg_incomplete = 0; diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c index 211a9786ecdc..6d6d7b41c9e5 100644 --- a/sys/netinet/sctp_pcb.c +++ b/sys/netinet/sctp_pcb.c @@ -4722,6 +4722,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre /* there is no asoc, really TSNH :-0 */ return (1); } + SCTP_TCB_SEND_LOCK(stcb); if (stcb->asoc.alternate) { sctp_free_remote_addr(stcb->asoc.alternate); stcb->asoc.alternate = NULL; @@ -4756,6 +4757,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre /* nope, reader or writer in the way */ sctp_timer_start(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL); /* no asoc destroyed */ + SCTP_TCB_SEND_UNLOCK(stcb); SCTP_TCB_UNLOCK(stcb); #ifdef SCTP_LOG_CLOSING sctp_log_closing(inp, stcb, 8); @@ -4853,6 +4855,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre SCTP_CLEAR_SUBSTATE(stcb, SCTP_STATE_IN_ACCEPT_QUEUE); sctp_timer_start(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL); } + SCTP_TCB_SEND_UNLOCK(stcb); SCTP_TCB_UNLOCK(stcb); if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) || (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) @@ -4886,10 +4889,12 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre if (from_inpcbfree == SCTP_NORMAL_PROC) { atomic_add_int(&stcb->asoc.refcnt, 1); + SCTP_TCB_SEND_UNLOCK(stcb); SCTP_TCB_UNLOCK(stcb); SCTP_INP_INFO_WLOCK(); SCTP_INP_WLOCK(inp); SCTP_TCB_LOCK(stcb); + SCTP_TCB_SEND_LOCK(stcb); } /* Double check the GONE flag */ if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) || @@ -4938,6 +4943,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre SCTP_INP_INFO_WUNLOCK(); SCTP_INP_WUNLOCK(inp); } + SCTP_TCB_SEND_UNLOCK(stcb); SCTP_TCB_UNLOCK(stcb); return (0); } @@ -4981,7 +4987,6 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre * in case. */ /* anything on the wheel needs to be removed */ - SCTP_TCB_SEND_LOCK(stcb); for (i = 0; i < asoc->streamoutcnt; i++) { struct sctp_stream_out *outs; @@ -5012,7 +5017,6 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre sctp_free_a_strmoq(stcb, sp, SCTP_SO_LOCKED); } } - SCTP_TCB_SEND_UNLOCK(stcb); /* sa_ignore FREED_MEMORY */ TAILQ_FOREACH_SAFE(strrst, &asoc->resetHead, next_resp, nstrrst) { TAILQ_REMOVE(&asoc->resetHead, strrst, next_resp); @@ -5214,6 +5218,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre /* Insert new items here :> */ /* Get rid of LOCK */ + SCTP_TCB_SEND_UNLOCK(stcb); SCTP_TCB_UNLOCK(stcb); SCTP_TCB_LOCK_DESTROY(stcb); SCTP_TCB_SEND_LOCK_DESTROY(stcb); diff --git a/sys/netinet/sctp_structs.h b/sys/netinet/sctp_structs.h index 10d9e2d82f5e..14c2749de55c 100644 --- a/sys/netinet/sctp_structs.h +++ b/sys/netinet/sctp_structs.h @@ -535,6 +535,7 @@ struct sctp_stream_queue_pending { uint8_t sender_all_done; uint8_t put_last_out; uint8_t discard_rest; + uint8_t processing; }; /* diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c index 8b78a96fa9a3..d9a45e2f75e1 100644 --- a/sys/netinet/sctputil.c +++ b/sys/netinet/sctputil.c @@ -3858,7 +3858,7 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb, } void -sctp_report_all_outbound(struct sctp_tcb *stcb, uint16_t error, int holds_lock, int so_locked +sctp_report_all_outbound(struct sctp_tcb *stcb, uint16_t error, int so_locked #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) SCTP_UNUSED #endif @@ -3884,9 +3884,6 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, uint16_t error, int holds_lock, return; } /* now through all the gunk freeing chunks */ - if (holds_lock == 0) { - SCTP_TCB_SEND_LOCK(stcb); - } /* sent queue SHOULD be empty */ TAILQ_FOREACH_SAFE(chk, &asoc->sent_queue, sctp_next, nchk) { TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next); @@ -3963,10 +3960,6 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, uint16_t error, int holds_lock, /* sa_ignore FREED_MEMORY */ } } - - if (holds_lock == 0) { - SCTP_TCB_SEND_UNLOCK(stcb); - } } void @@ -3990,8 +3983,11 @@ sctp_abort_notification(struct sctp_tcb *stcb, uint8_t from_peer, uint16_t error (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) { return; } + SCTP_TCB_SEND_LOCK(stcb); + SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_WAS_ABORTED); /* Tell them we lost the asoc */ - sctp_report_all_outbound(stcb, error, 0, so_locked); + sctp_report_all_outbound(stcb, error, so_locked); + SCTP_TCB_SEND_UNLOCK(stcb); if (from_peer) { sctp_ulp_notify(SCTP_NOTIFY_ASSOC_REM_ABORTED, stcb, error, abort, so_locked); } else { @@ -4023,7 +4019,6 @@ sctp_abort_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb, if (stcb != NULL) { /* We have a TCB to abort, send notification too */ sctp_abort_notification(stcb, 0, 0, NULL, SCTP_SO_NOT_LOCKED); - SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_WAS_ABORTED); /* Ok, now lets free it */ #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) so = SCTP_INP_SO(inp); @@ -4133,8 +4128,6 @@ sctp_abort_an_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb, } } return; - } else { - SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_WAS_ABORTED); } /* notify the peer */ sctp_send_abort_tcb(stcb, op_err, so_locked); diff --git a/sys/netinet/sctputil.h b/sys/netinet/sctputil.h index a82813b18d56..9bd1d9514feb 100644 --- a/sys/netinet/sctputil.h +++ b/sys/netinet/sctputil.h @@ -163,7 +163,7 @@ sctp_pull_off_control_to_new_inp(struct sctp_inpcb *old_inp, void sctp_stop_timers_for_shutdown(struct sctp_tcb *); void -sctp_report_all_outbound(struct sctp_tcb *, uint16_t, int, int +sctp_report_all_outbound(struct sctp_tcb *, uint16_t, int #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) SCTP_UNUSED #endif |