diff options
| author | Michael Tuexen <tuexen@fh-muenster.de> | 2022-03-29 21:00:12 +0200 |
|---|---|---|
| committer | Michael Tuexen <tuexen@fh-muenster.de> | 2022-03-29 21:00:12 +0200 |
| commit | 0586533e653e1b0a5b077e11bf0f6302dbdc8f75 (patch) | |
| tree | d2cfd3cb6cb4d33dba8d43f126a31d2ffda930d0 | |
| parent | e7ddfc29ba21ad70733099eec28b81c53f35a3c1 (diff) | |
Retire stcb send lock.
| -rwxr-xr-x | usrsctplib/netinet/sctp_input.c | 11 | ||||
| -rwxr-xr-x | usrsctplib/netinet/sctp_lock_userspace.h | 6 | ||||
| -rwxr-xr-x | usrsctplib/netinet/sctp_output.c | 962 | ||||
| -rwxr-xr-x | usrsctplib/netinet/sctp_pcb.c | 12 | ||||
| -rwxr-xr-x | usrsctplib/netinet/sctp_process_lock.h | 34 | ||||
| -rwxr-xr-x | usrsctplib/netinet/sctp_ss_functions.c | 70 | ||||
| -rwxr-xr-x | usrsctplib/netinet/sctp_timer.c | 4 | ||||
| -rwxr-xr-x | usrsctplib/netinet/sctp_uio.h | 4 | ||||
| -rwxr-xr-x | usrsctplib/netinet/sctp_usrreq.c | 4 | ||||
| -rwxr-xr-x | usrsctplib/netinet/sctputil.c | 12 |
10 files changed, 523 insertions, 596 deletions
diff --git a/usrsctplib/netinet/sctp_input.c b/usrsctplib/netinet/sctp_input.c index ed03405..e7d2056 100755 --- a/usrsctplib/netinet/sctp_input.c +++ b/usrsctplib/netinet/sctp_input.c @@ -197,13 +197,14 @@ sctp_is_there_unsent_data(struct sctp_tcb *stcb, int so_locked) struct sctp_stream_queue_pending *sp; struct sctp_association *asoc; + SCTP_TCB_LOCK_ASSERT(stcb); + /* This function returns if any stream has true unsent data on it. * Note that as it looks through it will clean up any places that * have old data that has been sent but left at top of stream queue. */ asoc = &stcb->asoc; unsent_data = 0; - SCTP_TCB_SEND_LOCK(stcb); if (!stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) { /* Check to see if some data queued */ for (i = 0; i < stcb->asoc.streamoutcnt; i++) { @@ -250,7 +251,6 @@ sctp_is_there_unsent_data(struct sctp_tcb *stcb, int so_locked) } } } - SCTP_TCB_SEND_UNLOCK(stcb); return (unsent_data); } @@ -262,6 +262,8 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb) struct sctp_nets *lnet; unsigned int i; + SCTP_TCB_LOCK_ASSERT(stcb); + init = &cp->init; asoc = &stcb->asoc; /* save off parameters */ @@ -279,7 +281,6 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb) } } } - SCTP_TCB_SEND_LOCK(stcb); if (asoc->pre_open_streams > ntohs(init->num_inbound_streams)) { unsigned int newcnt; struct sctp_stream_out *outs; @@ -339,7 +340,6 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb) /* cut back the count */ asoc->pre_open_streams = newcnt; } - SCTP_TCB_SEND_UNLOCK(stcb); asoc->streamoutcnt = asoc->pre_open_streams; if (asoc->strmout) { for (i = 0; i < asoc->streamoutcnt; i++) { @@ -2007,8 +2007,6 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, SCTP_TCB_LOCK(stcb); atomic_subtract_int(&stcb->asoc.refcnt, 1); /* send up all the data */ - SCTP_TCB_SEND_LOCK(stcb); - 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; @@ -2095,7 +2093,6 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, */ LIST_INSERT_HEAD(head, stcb, sctp_asocs); - SCTP_TCB_SEND_UNLOCK(stcb); SCTP_INP_WUNLOCK(stcb->sctp_ep); SCTP_INP_INFO_WUNLOCK(); #if defined(__APPLE__) && !defined(__Userspace__) diff --git a/usrsctplib/netinet/sctp_lock_userspace.h b/usrsctplib/netinet/sctp_lock_userspace.h index 99f1a89..f3b9b3d 100755 --- a/usrsctplib/netinet/sctp_lock_userspace.h +++ b/usrsctplib/netinet/sctp_lock_userspace.h @@ -114,12 +114,6 @@ __FBSDID("$FreeBSD$"); #define SCTP_ASOC_CREATE_LOCK_CONTENDED(_inp) (0) /* Don't know if this is possible */ -#define SCTP_TCB_SEND_LOCK_INIT(_tcb) -#define SCTP_TCB_SEND_LOCK_DESTROY(_tcb) -#define SCTP_TCB_SEND_LOCK(_tcb) -#define SCTP_TCB_SEND_UNLOCK(_tcb) -#define SCTP_TCB_SEND_LOCK_ASSERT(_tcb) - #define SCTP_INP_INCR_REF(_inp) #define SCTP_INP_DECR_REF(_inp) diff --git a/usrsctplib/netinet/sctp_output.c b/usrsctplib/netinet/sctp_output.c index d826a01..84552dd 100755 --- a/usrsctplib/netinet/sctp_output.c +++ b/usrsctplib/netinet/sctp_output.c @@ -6128,7 +6128,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, /* scope_id is only for v6 */ stc.scope_id = 0; if ((IN4_ISPRIVATE_ADDRESS(&src4->sin_addr)) || - (IN4_ISPRIVATE_ADDRESS(&dst4->sin_addr))){ + (IN4_ISPRIVATE_ADDRESS(&dst4->sin_addr))) { stc.ipv4_scope = 1; } /* Must use the address in this case */ @@ -6897,13 +6897,15 @@ static int sctp_msg_append(struct sctp_tcb *stcb, struct sctp_nets *net, struct mbuf *m, - struct sctp_sndrcvinfo *srcv, int hold_stcb_lock) + struct sctp_sndrcvinfo *srcv) { int error = 0; struct mbuf *at; struct sctp_stream_queue_pending *sp = NULL; struct sctp_stream_out *strm; + SCTP_TCB_LOCK_ASSERT(stcb); + /* Given an mbuf chain, put it * into the association send queue and * place it on the wheel @@ -6974,18 +6976,12 @@ sctp_msg_append(struct sctp_tcb *stcb, sctp_auth_key_acquire(stcb, sp->auth_keyid); sp->holds_key_ref = 1; } - if (hold_stcb_lock == 0) { - SCTP_TCB_SEND_LOCK(stcb); - } strm = &stcb->asoc.strmout[srcv->sinfo_stream]; sctp_snd_sb_alloc(stcb, sp->length); atomic_add_int(&stcb->asoc.stream_queue_cnt, 1); TAILQ_INSERT_TAIL(&strm->outqueue, sp, next); stcb->asoc.ss_functions.sctp_ss_add_to_stream(stcb, &stcb->asoc, strm, sp); m = NULL; - if (hold_stcb_lock == 0) { - SCTP_TCB_SEND_UNLOCK(stcb); - } out_now: if (m) { sctp_m_freem(m); @@ -7228,9 +7224,8 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr, atomic_subtract_int(&stcb->asoc.refcnt, 1); goto no_chunk_output; } else { - if (m) { - ret = sctp_msg_append(stcb, net, m, - &ca->sndrcv, 1); + if (m != NULL) { + ret = sctp_msg_append(stcb, net, m, &ca->sndrcv); } asoc = &stcb->asoc; if (ca->sndrcv.sinfo_flags & SCTP_EOF) { @@ -7752,7 +7747,6 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb, int leading; uint8_t rcv_flags = 0; uint8_t some_taken; - uint8_t send_lock_up = 0; SCTP_TCB_LOCK_ASSERT(stcb); asoc = &stcb->asoc; @@ -7760,10 +7754,6 @@ one_more_time: /*sa_ignore FREED_MEMORY*/ sp = TAILQ_FIRST(&strq->outqueue); if (sp == NULL) { - if (send_lock_up == 0) { - SCTP_TCB_SEND_LOCK(stcb); - send_lock_up = 1; - } sp = TAILQ_FIRST(&strq->outqueue); if (sp) { goto one_more_time; @@ -7777,10 +7767,6 @@ one_more_time: strq->last_msg_incomplete = 0; } to_move = 0; - if (send_lock_up) { - SCTP_TCB_SEND_UNLOCK(stcb); - send_lock_up = 0; - } goto out_of; } if ((sp->msg_is_complete) && (sp->length == 0)) { @@ -7791,16 +7777,11 @@ one_more_time: */ if ((sp->put_last_out == 0) && (sp->discard_rest == 0)) { SCTP_PRINTF("Gak, put out entire msg with NO end!-1\n"); - SCTP_PRINTF("sender_done:%d len:%d msg_comp:%d put_last_out:%d send_lock:%d\n", + SCTP_PRINTF("sender_done:%d len:%d msg_comp:%d put_last_out:%d\n", sp->sender_all_done, sp->length, sp->msg_is_complete, - sp->put_last_out, - send_lock_up); - } - if (send_lock_up == 0) { - SCTP_TCB_SEND_LOCK(stcb); - send_lock_up = 1; + sp->put_last_out); } atomic_subtract_int(&asoc->stream_queue_cnt, 1); TAILQ_REMOVE(&strq->outqueue, sp, next); @@ -7819,11 +7800,6 @@ one_more_time: sp->data = NULL; } sctp_free_a_strmoq(stcb, sp, so_locked); - /* we can't be locked to it */ - if (send_lock_up) { - SCTP_TCB_SEND_UNLOCK(stcb); - send_lock_up = 0; - } /* back to get the next msg */ goto one_more_time; } else { @@ -7842,10 +7818,6 @@ one_more_time: to_move = 0; goto out_of; } else if (sp->discard_rest) { - if (send_lock_up == 0) { - SCTP_TCB_SEND_LOCK(stcb); - send_lock_up = 1; - } /* Whack down the size */ atomic_subtract_int(&stcb->asoc.total_output_queue_size, sp->length); if ((stcb->sctp_socket != NULL) && @@ -7866,7 +7838,6 @@ one_more_time: } } some_taken = sp->some_taken; -re_look: length = sp->length; if (sp->msg_is_complete) { /* The message is complete */ @@ -7891,28 +7862,9 @@ re_look: } } else { to_move = sctp_can_we_split_this(stcb, length, space_left, frag_point, eeor_mode); - if (to_move) { - /*- - * We use a snapshot of length in case it - * is expanding during the compare. - */ - uint32_t llen; - - llen = length; - if (to_move >= llen) { - to_move = llen; - if (send_lock_up == 0) { - /*- - * We are taking all of an incomplete msg - * thus we need a send lock. - */ - SCTP_TCB_SEND_LOCK(stcb); - send_lock_up = 1; - if (sp->msg_is_complete) { - /* the sender finished the msg */ - goto re_look; - } - } + if (to_move > 0) { + if (to_move >= length) { + to_move = length; } if (sp->some_taken == 0) { rcv_flags |= SCTP_DATA_FIRST_FRAG; @@ -7950,10 +7902,6 @@ re_look: if (to_move >= length) { /* we think we can steal the whole thing */ - if ((sp->sender_all_done == 0) && (send_lock_up == 0)) { - SCTP_TCB_SEND_LOCK(stcb); - send_lock_up = 1; - } if (to_move < sp->length) { /* bail, it changed */ goto dont_do_it; @@ -7984,7 +7932,7 @@ re_look: /* Now lets work our way down and compact it */ m = sp->data; while (m && (SCTP_BUF_LEN(m) == 0)) { - sp->data = SCTP_BUF_NEXT(m); + sp->data = SCTP_BUF_NEXT(m); SCTP_BUF_NEXT(m) = NULL; if (sp->tail_mbuf == m) { /*- @@ -8045,10 +7993,6 @@ re_look: * all the data if there is no leading space, so we * must put the data back and restore. */ - if (send_lock_up == 0) { - SCTP_TCB_SEND_LOCK(stcb); - send_lock_up = 1; - } if (sp->data == NULL) { /* unsteal the data */ sp->data = chk->data; @@ -8160,8 +8104,8 @@ re_look: * earlier in previous loop prior to padding. */ -#ifdef SCTP_ASOCLOG_OF_TSNS SCTP_TCB_LOCK_ASSERT(stcb); +#ifdef SCTP_ASOCLOG_OF_TSNS if (asoc->tsn_out_at >= SCTP_TSN_LOG_SIZE) { asoc->tsn_out_at = 0; asoc->tsn_out_wrapped = 1; @@ -8219,16 +8163,11 @@ re_look: /* All done pull and kill the message */ if (sp->put_last_out == 0) { SCTP_PRINTF("Gak, put out entire msg with NO end!-2\n"); - SCTP_PRINTF("sender_done:%d len:%d msg_comp:%d put_last_out:%d send_lock:%d\n", + SCTP_PRINTF("sender_done:%d len:%d msg_comp:%d put_last_out:%d\n", sp->sender_all_done, sp->length, sp->msg_is_complete, - sp->put_last_out, - send_lock_up); - } - if (send_lock_up == 0) { - SCTP_TCB_SEND_LOCK(stcb); - send_lock_up = 1; + sp->put_last_out); } atomic_subtract_int(&asoc->stream_queue_cnt, 1); TAILQ_REMOVE(&strq->outqueue, sp, next); @@ -8253,9 +8192,6 @@ re_look: TAILQ_INSERT_TAIL(&asoc->send_queue, chk, sctp_next); asoc->send_queue_cnt++; out_of: - if (send_lock_up) { - SCTP_TCB_SEND_UNLOCK(stcb); - } return (to_move); } @@ -12877,6 +12813,8 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb, int can_send_out_req=0; uint32_t seq; + SCTP_TCB_LOCK_ASSERT(stcb); + asoc = &stcb->asoc; if (asoc->stream_reset_outstanding) { /*- @@ -12945,7 +12883,8 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb, seq = stcb->asoc.str_reset_seq_out; if (can_send_out_req) { int ret; - ret = sctp_add_stream_reset_out(stcb, chk, seq, (stcb->asoc.str_reset_seq_in - 1), (stcb->asoc.sending_seq - 1)); + + ret = sctp_add_stream_reset_out(stcb, chk, seq, (stcb->asoc.str_reset_seq_in - 1), (stcb->asoc.sending_seq - 1)); if (ret) { seq++; asoc->stream_reset_outstanding++; @@ -12977,7 +12916,6 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb, /* Ok now we proceed with copying the old out stuff and * initializing the new stuff. */ - SCTP_TCB_SEND_LOCK(stcb); stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, false); for (i = 0; i < stcb->asoc.streamoutcnt; i++) { TAILQ_INIT(&stcb->asoc.strmout[i].outqueue); @@ -13028,7 +12966,6 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb, } stcb->asoc.strm_realoutsize = stcb->asoc.streamoutcnt + adding_o; SCTP_FREE(oldstream, SCTP_M_STRMO); - SCTP_TCB_SEND_UNLOCK(stcb); } skip_stuff: if ((add_stream & 1) && (adding_o > 0)) { @@ -13464,7 +13401,7 @@ int sctp_lower_sosend(struct socket *so, struct sockaddr *addr, struct uio *uio, - struct mbuf *i_pak, + struct mbuf *top, struct mbuf *control, int flags, struct sctp_sndrcvinfo *srcv @@ -13485,9 +13422,8 @@ sctp_lower_sosend(struct socket *so, #endif ssize_t sndlen = 0, max_len, local_add_more; int error; - struct mbuf *top = NULL; int queue_only = 0, queue_only_for_init = 0; - int free_cnt_applied = 0; + bool free_cnt_applied = false; int un_sent; int now_filled = 0; unsigned int inqueue_bytes = 0; @@ -13499,12 +13435,12 @@ sctp_lower_sosend(struct socket *so, struct sctp_association *asoc; struct sctp_inpcb *t_inp; int user_marks_eor; - int create_lock_applied = 0; + bool create_lock_applied = false; int nagle_applies = 0; - int some_on_control = 0; - int got_all_of_the_send = 0; - int hold_tcblock = 0; - int non_blocking = 0; + bool some_on_control; + bool got_all_of_the_send = false; + bool hold_tcblock = false; + bool non_blocking = false; ssize_t local_soresv = 0; uint16_t port; uint16_t sinfo_flags; @@ -13513,27 +13449,22 @@ sctp_lower_sosend(struct socket *so, error = 0; net = NULL; stcb = NULL; - asoc = NULL; #if defined(__APPLE__) && !defined(__Userspace__) sctp_lock_assert(so); #endif t_inp = inp = (struct sctp_inpcb *)so->so_pcb; if (inp == NULL) { - SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, EINVAL); error = EINVAL; - if (i_pak) { - SCTP_RELEASE_PKT(i_pak); - } - return (error); + goto out_unlocked; } - if ((uio == NULL) && (i_pak == NULL)) { - SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); - return (EINVAL); + if ((uio == NULL) && (top == NULL)) { + error = EINVAL; + goto out_unlocked; } user_marks_eor = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR); atomic_add_int(&inp->total_sends, 1); - if (uio) { + if (uio != NULL) { #if defined(__APPLE__) && !defined(__Userspace__) #if defined(APPLE_LEOPARD) if (uio->uio_resid < 0) { @@ -13543,8 +13474,8 @@ sctp_lower_sosend(struct socket *so, #else if (uio->uio_resid < 0) { #endif - SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); - return (EINVAL); + error = EINVAL; + goto out_unlocked; } #if defined(__APPLE__) && !defined(__Userspace__) #if defined(APPLE_LEOPARD) @@ -13556,31 +13487,24 @@ sctp_lower_sosend(struct socket *so, sndlen = uio->uio_resid; #endif } else { - top = SCTP_HEADER_TO_CHAIN(i_pak); - sndlen = SCTP_HEADER_LEN(i_pak); + sndlen = SCTP_HEADER_LEN(top); } SCTPDBG(SCTP_DEBUG_OUTPUT1, "Send called addr:%p send length %zd\n", - (void *)addr, - sndlen); + (void *)addr, sndlen); if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && SCTP_IS_LISTENING(inp)) { - /* The listener can NOT send */ - SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, ENOTCONN); - error = ENOTCONN; + /* The listener can NOT send. */ + error = EINVAL; goto out_unlocked; } - /** - * Pre-screen address, if one is given the sin-len - * must be set correctly! - */ - if (addr) { + if (addr != NULL) { union sctp_sockstore *raddr = (union sctp_sockstore *)addr; + switch (raddr->sa.sa_family) { #ifdef INET case AF_INET: #ifdef HAVE_SIN_LEN if (raddr->sin.sin_len != sizeof(struct sockaddr_in)) { - SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); error = EINVAL; goto out_unlocked; } @@ -13592,7 +13516,6 @@ sctp_lower_sosend(struct socket *so, case AF_INET6: #ifdef HAVE_SIN6_LEN if (raddr->sin6.sin6_len != sizeof(struct sockaddr_in6)) { - SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); error = EINVAL; goto out_unlocked; } @@ -13604,7 +13527,6 @@ sctp_lower_sosend(struct socket *so, case AF_CONN: #ifdef HAVE_SCONN_LEN if (raddr->sconn.sconn_len != sizeof(struct sockaddr_conn)) { - SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); error = EINVAL; goto out_unlocked; } @@ -13613,23 +13535,22 @@ sctp_lower_sosend(struct socket *so, break; #endif default: - SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EAFNOSUPPORT); error = EAFNOSUPPORT; goto out_unlocked; } - } else + } else { port = 0; + } - if (srcv) { + if (srcv != NULL) { sinfo_flags = srcv->sinfo_flags; sinfo_assoc_id = srcv->sinfo_assoc_id; if (INVALID_SINFO_FLAG(sinfo_flags) || PR_SCTP_INVALID_POLICY(sinfo_flags)) { - SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); error = EINVAL; goto out_unlocked; } - if (srcv->sinfo_flags) + if (srcv->sinfo_flags != 0) SCTP_STAT_INCR(sctps_sends_with_flags); } else { sinfo_flags = inp->def_send.sinfo_flags; @@ -13644,63 +13565,71 @@ sctp_lower_sosend(struct socket *so, } #endif if (sinfo_flags & SCTP_SENDALL) { - /* its a sendall */ error = sctp_sendall(inp, uio, top, srcv); top = NULL; goto out_unlocked; } if ((sinfo_flags & SCTP_ADDR_OVER) && (addr == NULL)) { - SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); error = EINVAL; goto out_unlocked; } - /* now we must find the assoc */ + /* Now we must find the association. */ + SCTP_INP_RLOCK(inp); if ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) || (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { - SCTP_INP_RLOCK(inp); stcb = LIST_FIRST(&inp->sctp_asoc_list); - if (stcb) { + if (stcb != NULL) { SCTP_TCB_LOCK(stcb); - hold_tcblock = 1; + hold_tcblock = true; } SCTP_INP_RUNLOCK(inp); - } else if (sinfo_assoc_id) { - stcb = sctp_findassociation_ep_asocid(inp, sinfo_assoc_id, 1); + } else if (sinfo_assoc_id > SCTP_ALL_ASSOC) { + stcb = sctp_findasoc_ep_asocid_locked(inp, sinfo_assoc_id, 1); + SCTP_INP_RUNLOCK(inp); if (stcb != NULL) { - hold_tcblock = 1; + SCTP_TCB_LOCK_ASSERT(stcb); + hold_tcblock = true; } - } else if (addr) { + } else if (addr != NULL) { /*- * Since we did not use findep we must * increment it, and if we don't find a tcb * decrement it. */ - SCTP_INP_WLOCK(inp); SCTP_INP_INCR_REF(inp); - SCTP_INP_WUNLOCK(inp); + SCTP_INP_RUNLOCK(inp); stcb = sctp_findassociation_ep_addr(&t_inp, addr, &net, NULL, NULL); if (stcb == NULL) { SCTP_INP_WLOCK(inp); SCTP_INP_DECR_REF(inp); SCTP_INP_WUNLOCK(inp); } else { - hold_tcblock = 1; + SCTP_TCB_LOCK_ASSERT(stcb); + hold_tcblock = true; } + } else { + SCTP_INP_RUNLOCK(inp); + } + +#ifdef INVARIANTS + if (stcb != NULL) { + SCTP_TCB_LOCK_ASSERT(stcb); + KASSERT(hold_tcblock, ("tcb lock hold, hold_tcblock is false")); + } else { + KASSERT(!hold_tcblock, ("hold_tcblock is true, but stcb is NULL")); } - if ((stcb == NULL) && (addr)) { +#endif + if ((stcb == NULL) && (addr != NULL)) { /* Possible implicit send? */ SCTP_ASOC_CREATE_LOCK(inp); - create_lock_applied = 1; + create_lock_applied = true; if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE)) { - /* Should I really unlock ? */ - SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, EINVAL); error = EINVAL; goto out_unlocked; } if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) && (addr->sa_family == AF_INET6)) { - SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); error = EINVAL; goto out_unlocked; } @@ -13719,20 +13648,21 @@ sctp_lower_sosend(struct socket *so, SCTP_INP_DECR_REF(inp); SCTP_INP_WUNLOCK(inp); } else { - hold_tcblock = 1; + SCTP_TCB_LOCK_ASSERT(stcb); + hold_tcblock = true; + SCTP_ASOC_CREATE_UNLOCK(inp); + create_lock_applied = false; } - if (error) { + if (error != 0) { goto out_unlocked; } if (t_inp != inp) { - SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOTCONN); error = ENOTCONN; goto out_unlocked; } } if (stcb == NULL) { if (addr == NULL) { - SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOENT); error = ENOENT; goto out_unlocked; } else { @@ -13745,17 +13675,12 @@ sctp_lower_sosend(struct socket *so, * User asks to abort a non-existent assoc, * or EOF a non-existent assoc with no data */ - SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOENT); error = ENOENT; goto out_unlocked; } /* get an asoc/stcb struct */ vrf_id = inp->def_vrf_id; -#ifdef INVARIANTS - if (create_lock_applied == 0) { - panic("Error, should hold create lock and I don't?"); - } -#endif + KASSERT(create_lock_applied, ("create_lock_applied is false")); stcb = sctp_aloc_assoc_connected(inp, addr, &error, 0, 0, vrf_id, inp->sctp_ep.pre_open_stream_count, inp->sctp_ep.port, @@ -13766,28 +13691,26 @@ sctp_lower_sosend(struct socket *so, #endif SCTP_INITIALIZE_AUTH_PARAMS); if (stcb == NULL) { - /* Error is setup for us in the call */ + /* error is setup for us in the call. */ + KASSERT(error != 0, ("error is 0 although stcb is NULL")); goto out_unlocked; } - hold_tcblock = 1; - if (create_lock_applied) { - SCTP_ASOC_CREATE_UNLOCK(inp); - create_lock_applied = 0; - } else { - SCTP_PRINTF("Huh-3? create lock should have been on??\n"); - } + SCTP_TCB_LOCK_ASSERT(stcb); + hold_tcblock = true; + SCTP_ASOC_CREATE_UNLOCK(inp); + create_lock_applied = false; /* Turn on queue only flag to prevent data from being sent */ queue_only = 1; - asoc = &stcb->asoc; SCTP_SET_STATE(stcb, SCTP_STATE_COOKIE_WAIT); - (void)SCTP_GETTIME_TIMEVAL(&asoc->time_entered); - - if (control) { + (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered); + if (control != NULL) { if (sctp_process_cmsgs_for_init(stcb, control, &error)) { sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_6); - hold_tcblock = 0; + hold_tcblock = false; stcb = NULL; + KASSERT(error != 0, + ("error is 0 although sctp_process_cmsgs_for_init() indicated an error")); goto out_unlocked; } } @@ -13800,8 +13723,27 @@ sctp_lower_sosend(struct socket *so, * change it BEFORE we append the message. */ } - } else - asoc = &stcb->asoc; + } + + KASSERT(!create_lock_applied, ("create_lock_applied is true")); + KASSERT(stcb != NULL, ("stcb is NULL")); + KASSERT(hold_tcblock, ("hold_tcblock is false")); + SCTP_TCB_LOCK_ASSERT(stcb); + asoc = &stcb->asoc; + if ((asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) || + (asoc->state & SCTP_STATE_WAS_ABORTED)) { + if (asoc->state & SCTP_STATE_WAS_ABORTED) { + /* XXX: Could also be ECONNABORTED, not enough info. */ + error = ECONNRESET; + } else { + error = ENOTCONN; + } + goto out_unlocked; + } + /* Keep the stcb from being freed under our feet. */ + atomic_add_int(&asoc->refcnt, 1); + free_cnt_applied = true; + if (srcv == NULL) { srcv = (struct sctp_sndrcvinfo *)&asoc->def_send; sinfo_flags = srcv->sinfo_flags; @@ -13815,38 +13757,33 @@ sctp_lower_sosend(struct socket *so, #endif } if (sinfo_flags & SCTP_ADDR_OVER) { - if (addr) + if (addr != NULL) net = sctp_findnet(stcb, addr); else net = NULL; if ((net == NULL) || ((port != 0) && (port != stcb->rport))) { - SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); error = EINVAL; goto out_unlocked; } } else { - if (stcb->asoc.alternate) { - net = stcb->asoc.alternate; + if (asoc->alternate != NULL) { + net = asoc->alternate; } else { - net = stcb->asoc.primary_destination; + net = asoc->primary_destination; } } atomic_add_int(&stcb->total_sends, 1); - /* Keep the stcb from being freed under our feet */ - atomic_add_int(&asoc->refcnt, 1); - free_cnt_applied = 1; if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NO_FRAGMENT)) { if (sndlen > (ssize_t)asoc->smallest_mtu) { - SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EMSGSIZE); error = EMSGSIZE; goto out_unlocked; } } #if defined(__Userspace__) - if (inp->recv_callback) { - non_blocking = 1; + if (inp->recv_callback != NULL) { + non_blocking = true; } #endif if (SCTP_SO_IS_NBIO(so) @@ -13854,51 +13791,36 @@ sctp_lower_sosend(struct socket *so, || (flags & (MSG_NBIO | MSG_DONTWAIT)) != 0 #endif ) { - non_blocking = 1; + non_blocking = true; } /* would we block? */ if (non_blocking) { ssize_t amount; - if (hold_tcblock == 0) { - SCTP_TCB_LOCK(stcb); - hold_tcblock = 1; - } - inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb)); + inqueue_bytes = asoc->total_output_queue_size - (asoc->chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb)); if (user_marks_eor == 0) { amount = sndlen; } else { amount = 1; } - if ((SCTP_SB_LIMIT_SND(so) < (amount + inqueue_bytes + stcb->asoc.sb_send_resv)) || - (stcb->asoc.chunks_on_out_queue >= SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue))) { - SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EWOULDBLOCK); - if (sndlen > (ssize_t)SCTP_SB_LIMIT_SND(so)) + if ((SCTP_SB_LIMIT_SND(so) < (amount + inqueue_bytes + asoc->sb_send_resv)) || + (asoc->chunks_on_out_queue >= SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue))) { + if ((sndlen > (ssize_t)SCTP_SB_LIMIT_SND(so)) && + (user_marks_eor == 0)) { error = EMSGSIZE; - else + } else { error = EWOULDBLOCK; + } goto out_unlocked; } - stcb->asoc.sb_send_resv += (uint32_t)sndlen; - SCTP_TCB_UNLOCK(stcb); - hold_tcblock = 0; + asoc->sb_send_resv += (uint32_t)sndlen; } else { - atomic_add_int(&stcb->asoc.sb_send_resv, (int)sndlen); + atomic_add_int(&asoc->sb_send_resv, (int)sndlen); } local_soresv = sndlen; - if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { - SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ECONNRESET); - error = ECONNRESET; - goto out_unlocked; - } - if (create_lock_applied) { - SCTP_ASOC_CREATE_UNLOCK(inp); - create_lock_applied = 0; - } /* Is the stream no. valid? */ if (srcv->sinfo_stream >= asoc->streamoutcnt) { /* Invalid stream number */ - SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); error = EINVAL; goto out_unlocked; } @@ -13912,33 +13834,24 @@ sctp_lower_sosend(struct socket *so, } else { error = EINVAL; } - SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, error); goto out_unlocked; } if ((SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_WAIT) || (SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_ECHOED)) { queue_only = 1; } - /* we are now done with all control */ - if (control) { - sctp_m_freem(control); - control = NULL; - } if ((SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_SENT) || (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED) || (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_ACK_SENT) || (asoc->state & SCTP_STATE_SHUTDOWN_PENDING)) { - if (sinfo_flags & SCTP_ABORT) { - ; - } else { - SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ECONNRESET); - error = ECONNRESET; + if ((sinfo_flags & SCTP_ABORT) == 0) { + error = EPIPE; goto out_unlocked; } } /* Ok, we will attempt a msgsnd :> */ #if !(defined(_WIN32) || defined(__Userspace__)) - if (p) { + if (p != NULL) { #if defined(__FreeBSD__) p->td_ru.ru_msgsnd++; #else @@ -13946,92 +13859,102 @@ sctp_lower_sosend(struct socket *so, #endif } #endif + + KASSERT(stcb != NULL, ("stcb is NULL")); + KASSERT(hold_tcblock, ("hold_tcblock is false")); + SCTP_TCB_LOCK_ASSERT(stcb); + KASSERT((asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) == 0, + ("Association about to be freed")); + KASSERT((asoc->state & SCTP_STATE_WAS_ABORTED) == 0, + ("Association was aborted")); + /* Are we aborting? */ if (sinfo_flags & SCTP_ABORT) { struct mbuf *mm; + struct sctp_paramhdr *ph; ssize_t tot_demand, tot_out = 0, max_out; SCTP_STAT_INCR(sctps_sends_with_abort); if ((SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_WAIT) || (SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_ECHOED)) { - /* It has to be up before we abort */ - /* how big is the user initiated abort? */ - SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); + /* It has to be up before we abort. */ error = EINVAL; goto out; } - if (hold_tcblock) { - SCTP_TCB_UNLOCK(stcb); - hold_tcblock = 0; - } - if (top) { - struct mbuf *cntm = NULL; + /* How big is the user initiated abort? */ + if (top != NULL) { + struct mbuf *cntm; - mm = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), 0, M_WAITOK, 1, MT_DATA); if (sndlen != 0) { for (cntm = top; cntm; cntm = SCTP_BUF_NEXT(cntm)) { tot_out += SCTP_BUF_LEN(cntm); } } + mm = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), 0, M_NOWAIT, 1, MT_DATA); } else { /* Must fit in a MTU */ tot_out = sndlen; tot_demand = (tot_out + sizeof(struct sctp_paramhdr)); if (tot_demand > SCTP_DEFAULT_ADD_MORE) { - /* To big */ - SCTP_LTRACE_ERR_RET(NULL, stcb, net, SCTP_FROM_SCTP_OUTPUT, EMSGSIZE); error = EMSGSIZE; - goto out; + goto out_unlocked; } - mm = sctp_get_mbuf_for_msg((unsigned int)tot_demand, 0, M_WAITOK, 1, MT_DATA); + mm = sctp_get_mbuf_for_msg((unsigned int)tot_demand, 0, M_NOWAIT, 1, MT_DATA); } if (mm == NULL) { - SCTP_LTRACE_ERR_RET(NULL, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOMEM); error = ENOMEM; - goto out; + goto out_unlocked; } max_out = asoc->smallest_mtu - sizeof(struct sctp_paramhdr); max_out -= sizeof(struct sctp_abort_msg); if (tot_out > max_out) { tot_out = max_out; } - if (mm) { - struct sctp_paramhdr *ph; - - /* now move forward the data pointer */ - ph = mtod(mm, struct sctp_paramhdr *); - ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT); - ph->param_length = htons((uint16_t)(sizeof(struct sctp_paramhdr) + tot_out)); - ph++; - SCTP_BUF_LEN(mm) = (int)(tot_out + sizeof(struct sctp_paramhdr)); - if (top == NULL) { + ph = mtod(mm, struct sctp_paramhdr *); + ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT); + ph->param_length = htons((uint16_t)(sizeof(struct sctp_paramhdr) + tot_out)); + ph++; + SCTP_BUF_LEN(mm) = (int)(tot_out + sizeof(struct sctp_paramhdr)); + if (top == NULL) { + SCTP_TCB_UNLOCK(stcb); + hold_tcblock = false; #if defined(__APPLE__) && !defined(__Userspace__) - SCTP_SOCKET_UNLOCK(so, 0); + SCTP_SOCKET_UNLOCK(so, 0); #endif - error = uiomove((caddr_t)ph, (int)tot_out, uio); + error = uiomove((caddr_t)ph, (int)tot_out, uio); #if defined(__APPLE__) && !defined(__Userspace__) - SCTP_SOCKET_LOCK(so, 0); + SCTP_SOCKET_LOCK(so, 0); #endif - if (error) { - /*- - * Here if we can't get his data we - * still abort we just don't get to - * send the users note :-0 - */ - sctp_m_freem(mm); - mm = NULL; - } - } else { - if (sndlen != 0) { - SCTP_BUF_NEXT(mm) = top; + SCTP_TCB_LOCK(stcb); + hold_tcblock = true; + if ((asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) || + (asoc->state & SCTP_STATE_WAS_ABORTED)) { + sctp_m_freem(mm); + if (asoc->state & SCTP_STATE_WAS_ABORTED) { + /* XXX: Could also be ECONNABORTED, not enough info. */ + error = ECONNRESET; + } else { + error = ENOTCONN; } + goto out_unlocked; + } + if (error != 0) { + /*- + * Here if we can't get his data we + * still abort we just don't get to + * send the users note :-0 + */ + sctp_m_freem(mm); + mm = NULL; + error = 0; + } + } else { + if (sndlen != 0) { + SCTP_BUF_NEXT(mm) = top; } } - if (hold_tcblock == 0) { - SCTP_TCB_LOCK(stcb); - } - atomic_subtract_int(&stcb->asoc.refcnt, 1); - free_cnt_applied = 0; + atomic_subtract_int(&asoc->refcnt, 1); + free_cnt_applied = false; /* release this lock, otherwise we hang on ourselves */ #if defined(__FreeBSD__) && !defined(__Userspace__) NET_EPOCH_ENTER(et); @@ -14040,8 +13963,6 @@ sctp_lower_sosend(struct socket *so, #if defined(__FreeBSD__) && !defined(__Userspace__) NET_EPOCH_EXIT(et); #endif - /* now relock the stcb so everything is sane */ - hold_tcblock = 0; stcb = NULL; /* In this case top is already chained to mm * avoid double free, since we free it below if @@ -14053,43 +13974,39 @@ sctp_lower_sosend(struct socket *so, } goto out_unlocked; } + + KASSERT(stcb != NULL, ("stcb is NULL")); + KASSERT(hold_tcblock, ("hold_tcblock is false")); + SCTP_TCB_LOCK_ASSERT(stcb); + KASSERT((asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) == 0, + ("Association about to be freed")); + KASSERT((asoc->state & SCTP_STATE_WAS_ABORTED) == 0, + ("Association was aborted")); + /* Calculate the maximum we can send */ - inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb)); + inqueue_bytes = asoc->total_output_queue_size - (asoc->chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb)); if (SCTP_SB_LIMIT_SND(so) > inqueue_bytes) { max_len = SCTP_SB_LIMIT_SND(so) - inqueue_bytes; } else { max_len = 0; } - if (hold_tcblock) { - SCTP_TCB_UNLOCK(stcb); - hold_tcblock = 0; - } - if (asoc->strmout == NULL) { - /* huh? software error */ - SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EFAULT); - error = EFAULT; - goto out_unlocked; - } - /* Unless E_EOR mode is on, we must make a send FIT in one call. */ if ((user_marks_eor == 0) && (sndlen > (ssize_t)SCTP_SB_LIMIT_SND(stcb->sctp_socket))) { - /* It will NEVER fit */ - SCTP_LTRACE_ERR_RET(NULL, stcb, net, SCTP_FROM_SCTP_OUTPUT, EMSGSIZE); + /* It will NEVER fit. */ error = EMSGSIZE; goto out_unlocked; } - if ((uio == NULL) && user_marks_eor) { + if ((uio == NULL) && (user_marks_eor != 0)) { /*- * We do not support eeor mode for * sending with mbuf chains (like sendfile). */ - SCTP_LTRACE_ERR_RET(NULL, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); error = EINVAL; goto out_unlocked; } - if (user_marks_eor) { + if (user_marks_eor != 0) { local_add_more = (ssize_t)min(SCTP_SB_LIMIT_SND(so), SCTP_BASE_SYSCTL(sctp_add_more_threshold)); } else { /*- @@ -14101,21 +14018,20 @@ sctp_lower_sosend(struct socket *so, if (non_blocking) { goto skip_preblock; } - if (((max_len <= local_add_more) && - ((ssize_t)SCTP_SB_LIMIT_SND(so) >= local_add_more)) || + if (((max_len <= local_add_more) && ((ssize_t)SCTP_SB_LIMIT_SND(so) >= local_add_more)) || (max_len == 0) || - ((stcb->asoc.chunks_on_out_queue+stcb->asoc.stream_queue_cnt) >= SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue))) { - /* No room right now ! */ + ((asoc->chunks_on_out_queue + asoc->stream_queue_cnt) >= SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue))) { + /* No room right now! */ + inqueue_bytes = asoc->total_output_queue_size - (asoc->chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb)); SOCKBUF_LOCK(&so->so_snd); - inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb)); while ((SCTP_SB_LIMIT_SND(so) < (inqueue_bytes + local_add_more)) || - ((stcb->asoc.stream_queue_cnt + stcb->asoc.chunks_on_out_queue) >= SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue))) { + ((asoc->stream_queue_cnt + asoc->chunks_on_out_queue) >= SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue))) { SCTPDBG(SCTP_DEBUG_OUTPUT1,"pre_block limit:%u <(inq:%d + %zd) || (%d+%d > %d)\n", (unsigned int)SCTP_SB_LIMIT_SND(so), inqueue_bytes, local_add_more, - stcb->asoc.stream_queue_cnt, - stcb->asoc.chunks_on_out_queue, + asoc->stream_queue_cnt, + asoc->chunks_on_out_queue, SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue)); if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_BLK_LOGGING_ENABLE) { sctp_log_block(SCTP_BLOCK_LOG_INTO_BLKA, asoc, sndlen); @@ -14124,31 +14040,44 @@ sctp_lower_sosend(struct socket *so, #if !(defined(_WIN32) && !defined(__Userspace__)) stcb->block_entry = &be; #endif + SCTP_TCB_UNLOCK(stcb); + hold_tcblock = false; error = sbwait(&so->so_snd); - stcb->block_entry = NULL; if (error || so->so_error || be.error) { if (error == 0) { - if (so->so_error) + if (so->so_error != 0) { error = so->so_error; - if (be.error) { + } + if (be.error != 0) { error = be.error; } } SOCKBUF_UNLOCK(&so->so_snd); goto out_unlocked; } + SOCKBUF_UNLOCK(&so->so_snd); + SCTP_TCB_LOCK(stcb); + hold_tcblock = true; + if ((asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) || + (asoc->state & SCTP_STATE_WAS_ABORTED)) { + if (asoc->state & SCTP_STATE_WAS_ABORTED) { + /* XXX: Could also be ECONNABORTED, not enough info. */ + error = ECONNRESET; + } else { + error = ENOTCONN; + } + goto out_unlocked; + } + stcb->block_entry = NULL; if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_BLK_LOGGING_ENABLE) { sctp_log_block(SCTP_BLOCK_LOG_OUTOF_BLK, - asoc, stcb->asoc.total_output_queue_size); + asoc, asoc->total_output_queue_size); } - if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { - SOCKBUF_UNLOCK(&so->so_snd); - goto out_unlocked; - } - inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb)); + inqueue_bytes = asoc->total_output_queue_size - (asoc->chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb)); + SOCKBUF_LOCK(&so->so_snd); } if (SCTP_SB_LIMIT_SND(so) > inqueue_bytes) { - max_len = SCTP_SB_LIMIT_SND(so) - inqueue_bytes; + max_len = SCTP_SB_LIMIT_SND(so) - inqueue_bytes; } else { max_len = 0; } @@ -14156,9 +14085,14 @@ sctp_lower_sosend(struct socket *so, } skip_preblock: - if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { - goto out_unlocked; - } + KASSERT(stcb != NULL, ("stcb is NULL")); + KASSERT(hold_tcblock, ("hold_tcblock is false")); + SCTP_TCB_LOCK_ASSERT(stcb); + KASSERT((asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) == 0, + ("Association about to be freed")); + KASSERT((asoc->state & SCTP_STATE_WAS_ABORTED) == 0, + ("Association was aborted")); + #if defined(__APPLE__) && !defined(__Userspace__) error = sblock(&so->so_snd, SBLOCKWAIT(flags)); #endif @@ -14168,38 +14102,47 @@ skip_preblock: */ if (sndlen == 0) { if (sinfo_flags & SCTP_EOF) { - got_all_of_the_send = 1; + got_all_of_the_send = true; goto dataless_eof; } else { - SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); error = EINVAL; goto out; } } + if (top == NULL) { struct sctp_stream_queue_pending *sp; struct sctp_stream_out *strm; uint32_t sndout; - SCTP_TCB_SEND_LOCK(stcb); if ((asoc->stream_locked) && - (asoc->stream_locked_on != srcv->sinfo_stream)) { - SCTP_TCB_SEND_UNLOCK(stcb); - SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); + (asoc->stream_locked_on != srcv->sinfo_stream)) { error = EINVAL; goto out; } - strm = &stcb->asoc.strmout[srcv->sinfo_stream]; + strm = &asoc->strmout[srcv->sinfo_stream]; if (strm->last_msg_incomplete == 0) { do_a_copy_in: - SCTP_TCB_SEND_UNLOCK(stcb); + SCTP_TCB_UNLOCK(stcb); + hold_tcblock = false; sp = sctp_copy_it_in(stcb, asoc, srcv, uio, net, max_len, user_marks_eor, &error); - if (error) { + SCTP_TCB_LOCK(stcb); + hold_tcblock = true; + if ((asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) || + (asoc->state & SCTP_STATE_WAS_ABORTED)) { + if (asoc->state & SCTP_STATE_WAS_ABORTED) { + /* XXX: Could also be ECONNABORTED, not enough info. */ + error = ECONNRESET; + } else { + error = ENOTCONN; + } + goto out; + } + if (error != 0) { goto out; } - SCTP_TCB_SEND_LOCK(stcb); /* The out streams might be reallocated. */ - strm = &stcb->asoc.strmout[srcv->sinfo_stream]; + strm = &asoc->strmout[srcv->sinfo_stream]; if (sp->msg_is_complete) { strm->last_msg_incomplete = 0; asoc->stream_locked = 0; @@ -14208,9 +14151,9 @@ skip_preblock: * case of an interrupt. */ strm->last_msg_incomplete = 1; - if (stcb->asoc.idata_supported == 0) { + if (asoc->idata_supported == 0) { asoc->stream_locked = 1; - asoc->stream_locked_on = srcv->sinfo_stream; + asoc->stream_locked_on = srcv->sinfo_stream; } sp->sender_all_done = 0; } @@ -14221,7 +14164,7 @@ skip_preblock: } sp->processing = 1; TAILQ_INSERT_TAIL(&strm->outqueue, sp, next); - stcb->asoc.ss_functions.sctp_ss_add_to_stream(stcb, asoc, strm, sp); + asoc->ss_functions.sctp_ss_add_to_stream(stcb, asoc, strm, sp); } else { sp = TAILQ_LAST(&strm->outqueue, sctp_streamhead); if (sp == NULL) { @@ -14234,16 +14177,22 @@ skip_preblock: #endif 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); + if (sp->processing != 0) { error = EINVAL; goto out; } else { sp->processing = 1; } } - SCTP_TCB_SEND_UNLOCK(stcb); + + KASSERT(stcb != NULL, ("stcb is NULL")); + KASSERT(hold_tcblock, ("hold_tcblock is false")); + SCTP_TCB_LOCK_ASSERT(stcb); + KASSERT((asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) == 0, + ("Association about to be freed")); + KASSERT((asoc->state & SCTP_STATE_WAS_ABORTED) == 0, + ("Association was aborted")); + #if defined(__APPLE__) && !defined(__Userspace__) #if defined(APPLE_LEOPARD) while (uio->uio_resid > 0) { @@ -14256,32 +14205,30 @@ skip_preblock: /* How much room do we have? */ struct mbuf *new_tail, *mm; - inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb)); - if (SCTP_SB_LIMIT_SND(so) > inqueue_bytes) + inqueue_bytes = asoc->total_output_queue_size - (asoc->chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb)); + if (SCTP_SB_LIMIT_SND(so) > inqueue_bytes) { max_len = SCTP_SB_LIMIT_SND(so) - inqueue_bytes; - else + } else { max_len = 0; - + } if ((max_len > (ssize_t)SCTP_BASE_SYSCTL(sctp_add_more_threshold)) || - (max_len && (SCTP_SB_LIMIT_SND(so) < SCTP_BASE_SYSCTL(sctp_add_more_threshold))) || + ((max_len > 0 ) && (SCTP_SB_LIMIT_SND(so) < SCTP_BASE_SYSCTL(sctp_add_more_threshold))) || #if defined(__APPLE__) && !defined(__Userspace__) #if defined(APPLE_LEOPARD) - (uio->uio_resid && (uio->uio_resid <= max_len))) { + (uio->uio_resid <= max_len)) { #else - (uio_resid(uio) && (uio_resid(uio) <= max_len))) { + (uio_resid(uio) <= max_len)) { #endif #else - (uio->uio_resid && (uio->uio_resid <= max_len))) { + (uio->uio_resid <= max_len)) { #endif - sndout = 0; - new_tail = NULL; - if (hold_tcblock) { - SCTP_TCB_UNLOCK(stcb); - hold_tcblock = 0; - } + SCTP_TCB_UNLOCK(stcb); + hold_tcblock = false; #if defined(__APPLE__) && !defined(__Userspace__) SCTP_SOCKET_UNLOCK(so, 0); #endif + sndout = 0; + new_tail = NULL; #if defined(__FreeBSD__) || defined(__Userspace__) mm = sctp_copy_resume(uio, (int)max_len, user_marks_eor, &error, &sndout, &new_tail); #else @@ -14290,43 +14237,40 @@ skip_preblock: #if defined(__APPLE__) && !defined(__Userspace__) SCTP_SOCKET_LOCK(so, 0); #endif - if ((mm == NULL) || error) { - if (mm) { - sctp_m_freem(mm); - } - SCTP_TCB_SEND_LOCK(stcb); - if (((stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) == 0) && - ((stcb->asoc.state & SCTP_STATE_WAS_ABORTED) == 0) && - (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) || - (stcb->asoc.state & SCTP_STATE_WAS_ABORTED)) { - /* we need to get out. + SCTP_TCB_LOCK(stcb); + hold_tcblock = true; + if ((asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) || + (asoc->state & SCTP_STATE_WAS_ABORTED)) { + /* We need to get out. * Peer probably aborted. */ sctp_m_freem(mm); - if (stcb->asoc.state & SCTP_STATE_WAS_ABORTED) { - SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ECONNRESET); + if (asoc->state & SCTP_STATE_WAS_ABORTED) { + /* XXX: Could also be ECONNABORTED, not enough info. */ error = ECONNRESET; + } else { + error = ENOTCONN; } - SCTP_TCB_SEND_UNLOCK(stcb); goto out; } - if (sp->tail_mbuf) { - /* tack it to the end */ + if ((mm == NULL) || (error != 0)) { + if (mm != NULL) { + sctp_m_freem(mm); + } + if (sp != NULL) { + sp->processing = 0; + } + goto out; + } + /* Update the mbuf and count */ + if (sp->tail_mbuf != NULL) { + /* Tack it to the end. */ SCTP_BUF_NEXT(sp->tail_mbuf) = mm; - sp->tail_mbuf = new_tail; } else { - /* A stolen mbuf */ + /* A stolen mbuf. */ sp->data = mm; - sp->tail_mbuf = new_tail; } + sp->tail_mbuf = new_tail; sctp_snd_sb_alloc(stcb, sndout); atomic_add_int(&sp->length, sndout); if (sinfo_flags & SCTP_SACK_IMMEDIATELY) { @@ -14350,8 +14294,16 @@ skip_preblock: } else { sp->msg_is_complete = 0; } - SCTP_TCB_SEND_UNLOCK(stcb); } + + KASSERT(stcb != NULL, ("stcb is NULL")); + KASSERT(hold_tcblock, ("hold_tcblock is false")); + SCTP_TCB_LOCK_ASSERT(stcb); + KASSERT((asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) == 0, + ("Association about to be freed")); + KASSERT((asoc->state & SCTP_STATE_WAS_ABORTED) == 0, + ("Association was aborted")); + #if defined(__APPLE__) && !defined(__Userspace__) #if defined(APPLE_LEOPARD) if (uio->uio_resid == 0) { @@ -14367,12 +14319,8 @@ skip_preblock: /* PR-SCTP? */ if ((asoc->prsctp_supported) && (asoc->sent_queue_cnt_removeable > 0)) { /* This is ugly but we must assure locking order */ - if (hold_tcblock == 0) { - SCTP_TCB_LOCK(stcb); - hold_tcblock = 1; - } sctp_prune_prsctp(stcb, asoc, srcv, (int)sndlen); - inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb)); + inqueue_bytes = asoc->total_output_queue_size - (asoc->chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb)); if (SCTP_SB_LIMIT_SND(so) > inqueue_bytes) max_len = SCTP_SB_LIMIT_SND(so) - inqueue_bytes; else @@ -14380,25 +14328,17 @@ skip_preblock: if (max_len > 0) { continue; } - SCTP_TCB_UNLOCK(stcb); - hold_tcblock = 0; } /* 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 */ if (queue_only_for_init) { - if (hold_tcblock == 0) { - SCTP_TCB_LOCK(stcb); - hold_tcblock = 1; - } if (SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) { /* a collision took us forward? */ queue_only = 0; @@ -14425,11 +14365,11 @@ skip_preblock: } asoc->ifp_had_enobuf = 0; } - un_sent = stcb->asoc.total_output_queue_size - stcb->asoc.total_flight; + un_sent = asoc->total_output_queue_size - asoc->total_flight; if ((sctp_is_feature_off(inp, SCTP_PCB_FLAGS_NODELAY)) && - (stcb->asoc.total_flight > 0) && - (stcb->asoc.stream_queue_cnt < SCTP_MAX_DATA_BUNDLING) && - (un_sent < (int)(stcb->asoc.smallest_mtu - SCTP_MIN_OVERHEAD))) { + (asoc->total_flight > 0) && + (asoc->stream_queue_cnt < SCTP_MAX_DATA_BUNDLING) && + (un_sent < (int)(asoc->smallest_mtu - SCTP_MIN_OVERHEAD))) { /*- * Ok, Nagle is set on and we have data outstanding. * Don't send anything and let SACKs drive out the @@ -14450,13 +14390,14 @@ skip_preblock: } if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_BLK_LOGGING_ENABLE) { sctp_misc_ints(SCTP_CWNDLOG_PRESEND, queue_only_for_init, queue_only, - nagle_applies, un_sent); - sctp_misc_ints(SCTP_CWNDLOG_PRESEND, stcb->asoc.total_output_queue_size, - stcb->asoc.total_flight, - stcb->asoc.chunks_on_out_queue, stcb->asoc.total_flight_count); + nagle_applies, un_sent); + sctp_misc_ints(SCTP_CWNDLOG_PRESEND, asoc->total_output_queue_size, + asoc->total_flight, + asoc->chunks_on_out_queue, asoc->total_flight_count); } - if (queue_only_for_init) + if (queue_only_for_init) { queue_only_for_init = 0; + } if ((queue_only == 0) && (nagle_applies == 0)) { /*- * need to start chunk output @@ -14468,27 +14409,12 @@ skip_preblock: #if defined(__FreeBSD__) && !defined(__Userspace__) NET_EPOCH_ENTER(et); #endif - if (hold_tcblock == 0) { - if (SCTP_TCB_TRYLOCK(stcb)) { - hold_tcblock = 1; - sctp_chunk_output(inp, - stcb, - SCTP_OUTPUT_FROM_USR_SEND, SCTP_SO_LOCKED); - } - } else { - sctp_chunk_output(inp, - stcb, - SCTP_OUTPUT_FROM_USR_SEND, SCTP_SO_LOCKED); - } + sctp_chunk_output(inp, stcb, + SCTP_OUTPUT_FROM_USR_SEND, SCTP_SO_LOCKED); #if defined(__FreeBSD__) && !defined(__Userspace__) NET_EPOCH_EXIT(et); #endif } - if (hold_tcblock == 1) { - SCTP_TCB_UNLOCK(stcb); - hold_tcblock = 0; - } - SOCKBUF_LOCK(&so->so_snd); /*- * This is a bit strange, but I think it will * work. The total_output_queue_size is locked and @@ -14503,33 +14429,34 @@ skip_preblock: * size we KNOW we will get to sleep safely with the * wakeup flag in place. */ - inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb)); + inqueue_bytes = asoc->total_output_queue_size - (asoc->chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb)); + SOCKBUF_LOCK(&so->so_snd); if (SCTP_SB_LIMIT_SND(so) <= (inqueue_bytes + - min(SCTP_BASE_SYSCTL(sctp_add_more_threshold), SCTP_SB_LIMIT_SND(so)))) { + min(SCTP_BASE_SYSCTL(sctp_add_more_threshold), SCTP_SB_LIMIT_SND(so)))) { if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_BLK_LOGGING_ENABLE) { #if defined(__APPLE__) && !defined(__Userspace__) #if defined(APPLE_LEOPARD) sctp_log_block(SCTP_BLOCK_LOG_INTO_BLK, - asoc, uio->uio_resid); + asoc, uio->uio_resid); #else sctp_log_block(SCTP_BLOCK_LOG_INTO_BLK, - asoc, uio_resid(uio)); + asoc, uio_resid(uio)); #endif #else sctp_log_block(SCTP_BLOCK_LOG_INTO_BLK, - asoc, uio->uio_resid); + asoc, uio->uio_resid); #endif } be.error = 0; #if !(defined(_WIN32) && !defined(__Userspace__)) stcb->block_entry = &be; #endif + SCTP_TCB_UNLOCK(stcb); + hold_tcblock = false; #if defined(__APPLE__) && !defined(__Userspace__) sbunlock(&so->so_snd, 1); #endif error = sbwait(&so->so_snd); - stcb->block_entry = NULL; - if (error || so->so_error || be.error) { if (error == 0) { if (so->so_error) @@ -14539,45 +14466,57 @@ skip_preblock: } } SOCKBUF_UNLOCK(&so->so_snd); - SCTP_TCB_SEND_LOCK(stcb); - if (((stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) == 0) && - ((stcb->asoc.state & SCTP_STATE_WAS_ABORTED) == 0) && + SCTP_TCB_LOCK(stcb); + hold_tcblock = true; + stcb->block_entry = NULL; + if (((asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) == 0) && + ((asoc->state & SCTP_STATE_WAS_ABORTED) == 0) && (sp != NULL)) { sp->processing = 0; } - SCTP_TCB_SEND_UNLOCK(stcb); goto out_unlocked; } #if defined(__APPLE__) && !defined(__Userspace__) error = sblock(&so->so_snd, SBLOCKWAIT(flags)); #endif - if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_BLK_LOGGING_ENABLE) { - sctp_log_block(SCTP_BLOCK_LOG_OUTOF_BLK, - asoc, stcb->asoc.total_output_queue_size); - } } SOCKBUF_UNLOCK(&so->so_snd); - SCTP_TCB_SEND_LOCK(stcb); - 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; + if (!hold_tcblock) { + SCTP_TCB_LOCK(stcb); + hold_tcblock = true; + if ((asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) || + (asoc->state & SCTP_STATE_WAS_ABORTED)) { + if (asoc->state & SCTP_STATE_WAS_ABORTED) { + /* XXX: Could also be ECONNABORTED, not enough info. */ + error = ECONNRESET; + } else { + error = ENOTCONN; + } + goto out; + } + } + stcb->block_entry = NULL; + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_BLK_LOGGING_ENABLE) { + sctp_log_block(SCTP_BLOCK_LOG_OUTOF_BLK, + asoc, asoc->total_output_queue_size); } - SCTP_TCB_SEND_UNLOCK(stcb); - } - SCTP_TCB_SEND_LOCK(stcb); - 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; } - if (sp) { + + KASSERT(stcb != NULL, ("stcb is NULL")); + KASSERT(hold_tcblock, ("hold_tcblock is false")); + SCTP_TCB_LOCK_ASSERT(stcb); + KASSERT((asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) == 0, + ("Association about to be freed")); + KASSERT((asoc->state & SCTP_STATE_WAS_ABORTED) == 0, + ("Association was aborted")); + + if (sp != NULL) { if (sp->msg_is_complete == 0) { strm->last_msg_incomplete = 1; - if (stcb->asoc.idata_supported == 0) { + if (asoc->idata_supported == 0) { asoc->stream_locked = 1; - asoc->stream_locked_on = srcv->sinfo_stream; + asoc->stream_locked_on = srcv->sinfo_stream; } } else { sp->sender_all_done = 1; @@ -14590,7 +14529,6 @@ skip_preblock: strm->last_msg_incomplete = 0; asoc->stream_locked = 0; } - SCTP_TCB_SEND_UNLOCK(stcb); #if defined(__APPLE__) && !defined(__Userspace__) #if defined(APPLE_LEOPARD) if (uio->uio_resid == 0) { @@ -14600,29 +14538,32 @@ skip_preblock: #else if (uio->uio_resid == 0) { #endif - got_all_of_the_send = 1; + got_all_of_the_send = true; } } else { - /* We send in a 0, since we do NOT have any locks */ - error = sctp_msg_append(stcb, net, top, srcv, 0); + error = sctp_msg_append(stcb, net, top, srcv); top = NULL; - if (sinfo_flags & SCTP_EOF) { - got_all_of_the_send = 1; + if ((sinfo_flags & SCTP_EOF) != 0) { + got_all_of_the_send = true; } } - if (error) { + if (error != 0) { goto out; } + dataless_eof: + KASSERT(stcb != NULL, ("stcb is NULL")); + KASSERT(hold_tcblock, ("hold_tcblock is false")); + SCTP_TCB_LOCK_ASSERT(stcb); + KASSERT((asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) == 0, + ("Association about to be freed")); + KASSERT((asoc->state & SCTP_STATE_WAS_ABORTED) == 0, + ("Association was aborted")); + /* EOF thing ? */ - if ((sinfo_flags & SCTP_EOF) && - (got_all_of_the_send == 1)) { + if ((sinfo_flags & SCTP_EOF) && got_all_of_the_send) { SCTP_STAT_INCR(sctps_sends_with_eof); error = 0; - if (hold_tcblock == 0) { - SCTP_TCB_LOCK(stcb); - hold_tcblock = 1; - } if (TAILQ_EMPTY(&asoc->send_queue) && TAILQ_EMPTY(&asoc->sent_queue) && sctp_is_there_unsent_data(stcb, SCTP_SO_LOCKED) == 0) { @@ -14641,10 +14582,10 @@ dataless_eof: } SCTP_SET_STATE(stcb, SCTP_STATE_SHUTDOWN_SENT); sctp_stop_timers_for_shutdown(stcb); - if (stcb->asoc.alternate) { - netp = stcb->asoc.alternate; + if (asoc->alternate != NULL) { + netp = asoc->alternate; } else { - netp = stcb->asoc.primary_destination; + netp = asoc->primary_destination; } sctp_send_shutdown(stcb, netp); sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, @@ -14666,10 +14607,6 @@ dataless_eof: if ((SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_SENT) && (SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_RECEIVED) && (SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_ACK_SENT)) { - if (hold_tcblock == 0) { - SCTP_TCB_LOCK(stcb); - hold_tcblock = 1; - } if ((*asoc->ss_functions.sctp_ss_is_user_msgs_incomplete)(stcb, asoc)) { SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_PARTIAL_MSG_LEFT); } @@ -14682,8 +14619,8 @@ dataless_eof: abort_anyway: if (free_cnt_applied) { - atomic_subtract_int(&stcb->asoc.refcnt, 1); - free_cnt_applied = 0; + atomic_subtract_int(&asoc->refcnt, 1); + free_cnt_applied = false; } SCTP_SNPRINTF(msg, sizeof(msg), "%s:%d at %s", __FILE__, __LINE__, __func__); @@ -14697,9 +14634,9 @@ dataless_eof: #if defined(__FreeBSD__) && !defined(__Userspace__) NET_EPOCH_EXIT(et); #endif - /* now relock the stcb so everything is sane */ - hold_tcblock = 0; + hold_tcblock = false; stcb = NULL; + error = ECONNABORTED; goto out; } sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb, @@ -14708,15 +14645,18 @@ dataless_eof: } } } + skip_out_eof: - if (!TAILQ_EMPTY(&stcb->asoc.control_send_queue)) { - some_on_control = 1; - } + KASSERT(stcb != NULL, ("stcb is NULL")); + KASSERT(hold_tcblock, ("hold_tcblock is false")); + SCTP_TCB_LOCK_ASSERT(stcb); + KASSERT((asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) == 0, + ("Association about to be freed")); + KASSERT((asoc->state & SCTP_STATE_WAS_ABORTED) == 0, + ("Association was aborted")); + + some_on_control = !TAILQ_EMPTY(&asoc->control_send_queue); if (queue_only_for_init) { - if (hold_tcblock == 0) { - SCTP_TCB_LOCK(stcb); - hold_tcblock = 1; - } if (SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) { /* a collision took us forward? */ queue_only = 0; @@ -14732,8 +14672,17 @@ skip_out_eof: queue_only = 1; } } + + KASSERT(stcb != NULL, ("stcb is NULL")); + KASSERT(hold_tcblock, ("hold_tcblock is false")); + SCTP_TCB_LOCK_ASSERT(stcb); + KASSERT((asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) == 0, + ("Association about to be freed")); + KASSERT((asoc->state & SCTP_STATE_WAS_ABORTED) == 0, + ("Association was aborted")); + if ((net->flight_size > net->cwnd) && - (stcb->asoc.sctp_cmt_on_off == 0)) { + (asoc->sctp_cmt_on_off == 0)) { SCTP_STAT_INCR(sctps_send_cwnd_avoid); queue_only = 1; } else if (asoc->ifp_had_enobuf) { @@ -14743,11 +14692,11 @@ skip_out_eof: } asoc->ifp_had_enobuf = 0; } - un_sent = stcb->asoc.total_output_queue_size - stcb->asoc.total_flight; + un_sent = asoc->total_output_queue_size - asoc->total_flight; if ((sctp_is_feature_off(inp, SCTP_PCB_FLAGS_NODELAY)) && - (stcb->asoc.total_flight > 0) && - (stcb->asoc.stream_queue_cnt < SCTP_MAX_DATA_BUNDLING) && - (un_sent < (int)(stcb->asoc.smallest_mtu - SCTP_MIN_OVERHEAD))) { + (asoc->total_flight > 0) && + (asoc->stream_queue_cnt < SCTP_MAX_DATA_BUNDLING) && + (un_sent < (int)(asoc->smallest_mtu - SCTP_MIN_OVERHEAD))) { /*- * Ok, Nagle is set on and we have data outstanding. * Don't send anything and let SACKs drive out the @@ -14769,42 +14718,34 @@ skip_out_eof: if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_BLK_LOGGING_ENABLE) { sctp_misc_ints(SCTP_CWNDLOG_PRESEND, queue_only_for_init, queue_only, nagle_applies, un_sent); - sctp_misc_ints(SCTP_CWNDLOG_PRESEND, stcb->asoc.total_output_queue_size, - stcb->asoc.total_flight, - stcb->asoc.chunks_on_out_queue, stcb->asoc.total_flight_count); + sctp_misc_ints(SCTP_CWNDLOG_PRESEND, asoc->total_output_queue_size, + asoc->total_flight, + asoc->chunks_on_out_queue, asoc->total_flight_count); } + + KASSERT(stcb != NULL, ("stcb is NULL")); + KASSERT(hold_tcblock, ("hold_tcblock is false")); + SCTP_TCB_LOCK_ASSERT(stcb); + KASSERT((asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) == 0, + ("Association about to be freed")); + KASSERT((asoc->state & SCTP_STATE_WAS_ABORTED) == 0, + ("Association was aborted")); + #if defined(__FreeBSD__) && !defined(__Userspace__) NET_EPOCH_ENTER(et); #endif - if ((queue_only == 0) && (nagle_applies == 0) && (stcb->asoc.peers_rwnd && un_sent)) { - /* we can attempt to send too. */ - if (hold_tcblock == 0) { - /* If there is activity recv'ing sacks no need to send */ - if (SCTP_TCB_TRYLOCK(stcb)) { - sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_USR_SEND, SCTP_SO_LOCKED); - hold_tcblock = 1; - } - } else { - sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_USR_SEND, SCTP_SO_LOCKED); - } + if ((queue_only == 0) && (nagle_applies == 0) && (asoc->peers_rwnd && un_sent)) { + sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_USR_SEND, SCTP_SO_LOCKED); } else if ((queue_only == 0) && - (stcb->asoc.peers_rwnd == 0) && - (stcb->asoc.total_flight == 0)) { + (asoc->peers_rwnd == 0) && + (asoc->total_flight == 0)) { /* We get to have a probe outstanding */ - if (hold_tcblock == 0) { - hold_tcblock = 1; - SCTP_TCB_LOCK(stcb); - } sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_USR_SEND, SCTP_SO_LOCKED); } else if (some_on_control) { int num_out, reason; /* Here we do control only */ - if (hold_tcblock == 0) { - hold_tcblock = 1; - SCTP_TCB_LOCK(stcb); - } - (void)sctp_med_chunk_output(inp, stcb, &stcb->asoc, &num_out, + (void)sctp_med_chunk_output(inp, stcb, asoc, &num_out, &reason, 1, 1, &now, &now_filled, sctp_get_frag_point(stcb), SCTP_SO_LOCKED); @@ -14813,46 +14754,51 @@ skip_out_eof: NET_EPOCH_EXIT(et); #endif SCTPDBG(SCTP_DEBUG_OUTPUT1, "USR Send complete qo:%d prw:%d unsent:%d tf:%d cooq:%d toqs:%d err:%d\n", - queue_only, stcb->asoc.peers_rwnd, un_sent, - stcb->asoc.total_flight, stcb->asoc.chunks_on_out_queue, - stcb->asoc.total_output_queue_size, error); + queue_only, asoc->peers_rwnd, un_sent, + asoc->total_flight, asoc->chunks_on_out_queue, + asoc->total_output_queue_size, error); + + KASSERT(stcb != NULL, ("stcb is NULL")); + KASSERT(hold_tcblock, ("hold_tcblock is false")); + SCTP_TCB_LOCK_ASSERT(stcb); + KASSERT((asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) == 0, + ("Association about to be freed")); + KASSERT((asoc->state & SCTP_STATE_WAS_ABORTED) == 0, + ("Association was aborted")); out: #if defined(__APPLE__) && !defined(__Userspace__) sbunlock(&so->so_snd, 1); #endif out_unlocked: - - if (local_soresv && stcb) { - atomic_subtract_int(&stcb->asoc.sb_send_resv, (int)sndlen); - } if (create_lock_applied) { SCTP_ASOC_CREATE_UNLOCK(inp); } - if ((stcb) && hold_tcblock) { - SCTP_TCB_UNLOCK(stcb); - } - if (stcb && free_cnt_applied) { - atomic_subtract_int(&stcb->asoc.refcnt, 1); - } + if (stcb != NULL) { + if (local_soresv) { + atomic_subtract_int(&asoc->sb_send_resv, (int)sndlen); + } + if (hold_tcblock) { + SCTP_TCB_UNLOCK(stcb); + } + if (free_cnt_applied) { + atomic_subtract_int(&asoc->refcnt, 1); + } #ifdef INVARIANTS #if defined(__FreeBSD__) && !defined(__Userspace__) - if (stcb) { if (mtx_owned(&stcb->tcb_mtx)) { panic("Leaving with tcb mtx owned?"); } - if (mtx_owned(&stcb->tcb_send_mtx)) { - panic("Leaving with tcb send mtx owned?"); - } - } #endif #endif - if (top) { + } + if (top != NULL) { sctp_m_freem(top); } - if (control) { + if (control != NULL) { sctp_m_freem(control); } + SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, error); return (error); } diff --git a/usrsctplib/netinet/sctp_pcb.c b/usrsctplib/netinet/sctp_pcb.c index a104557..649a201 100755 --- a/usrsctplib/netinet/sctp_pcb.c +++ b/usrsctplib/netinet/sctp_pcb.c @@ -5078,7 +5078,6 @@ sctp_aloc_assoc_locked(struct sctp_inpcb *inp, struct sockaddr *firstaddr, asoc = &stcb->asoc; SCTP_TCB_LOCK_INIT(stcb); - SCTP_TCB_SEND_LOCK_INIT(stcb); stcb->rport = rport; /* setup back pointer's */ stcb->sctp_ep = inp; @@ -5086,7 +5085,6 @@ sctp_aloc_assoc_locked(struct sctp_inpcb *inp, struct sockaddr *firstaddr, if ((err = sctp_init_asoc(inp, stcb, override_tag, initial_tsn, vrf_id, o_streams))) { /* failed */ SCTP_TCB_LOCK_DESTROY(stcb); - SCTP_TCB_SEND_LOCK_DESTROY(stcb); SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asoc), stcb); SCTP_DECR_ASOC_COUNT(); *error = err; @@ -5117,7 +5115,6 @@ sctp_aloc_assoc_locked(struct sctp_inpcb *inp, struct sockaddr *firstaddr, SCTP_DECR_ASOC_COUNT(); SCTP_TCB_UNLOCK(stcb); SCTP_TCB_LOCK_DESTROY(stcb); - SCTP_TCB_SEND_LOCK_DESTROY(stcb); LIST_REMOVE(stcb, sctp_asocs); LIST_REMOVE(stcb, sctp_tcbasocidhash); SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asoc), stcb); @@ -5470,6 +5467,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre #if defined(__APPLE__) && !defined(__Userspace__) sctp_lock_assert(SCTP_INP_SO(inp)); #endif + SCTP_TCB_LOCK_ASSERT(stcb); #ifdef SCTP_LOG_CLOSING sctp_log_closing(inp, stcb, 6); @@ -5481,7 +5479,6 @@ 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; @@ -5518,7 +5515,6 @@ 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); @@ -5589,7 +5585,6 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre sctp_sorwakeup(inp, so); sctp_sowwakeup(inp, so); } - SCTP_TCB_SEND_UNLOCK(stcb); SCTP_TCB_UNLOCK(stcb); #ifdef SCTP_LOG_CLOSING @@ -5619,12 +5614,10 @@ 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) || @@ -5675,7 +5668,6 @@ 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); } @@ -5940,10 +5932,8 @@ 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); if (from_inpcbfree == SCTP_NORMAL_PROC) { SCTP_INP_INFO_WUNLOCK(); SCTP_INP_RLOCK(inp); diff --git a/usrsctplib/netinet/sctp_process_lock.h b/usrsctplib/netinet/sctp_process_lock.h index bbc2845..165c6e4 100755 --- a/usrsctplib/netinet/sctp_process_lock.h +++ b/usrsctplib/netinet/sctp_process_lock.h @@ -80,12 +80,6 @@ #define SCTP_IPI_COUNT_DESTROY() #endif -#define SCTP_TCB_SEND_LOCK_INIT(_tcb) -#define SCTP_TCB_SEND_LOCK_DESTROY(_tcb) -#define SCTP_TCB_SEND_LOCK(_tcb) -#define SCTP_TCB_SEND_UNLOCK(_tcb) -#define SCTP_TCB_SEND_LOCK_ASSERT(_tcb) - /* Lock for INP */ #define SCTP_INP_LOCK_INIT(_inp) #define SCTP_INP_LOCK_DESTROY(_inp) @@ -219,16 +213,6 @@ #define SCTP_INP_RLOCK_ASSERT(_tcb) #define SCTP_INP_WLOCK_ASSERT(_tcb) -#define SCTP_TCB_SEND_LOCK_INIT(_tcb) \ - InitializeCriticalSection(&(_tcb)->tcb_send_mtx) -#define SCTP_TCB_SEND_LOCK_DESTROY(_tcb) \ - DeleteCriticalSection(&(_tcb)->tcb_send_mtx) -#define SCTP_TCB_SEND_LOCK(_tcb) \ - EnterCriticalSection(&(_tcb)->tcb_send_mtx) -#define SCTP_TCB_SEND_UNLOCK(_tcb) \ - LeaveCriticalSection(&(_tcb)->tcb_send_mtx) -#define SCTP_TCB_SEND_LOCK_ASSERT(_tcb) - #define SCTP_INP_INCR_REF(_inp) atomic_add_int(&((_inp)->refcount), 1) #define SCTP_INP_DECR_REF(_inp) atomic_subtract_int(&((_inp)->refcount), 1) @@ -423,24 +407,6 @@ #define SCTP_INP_INCR_REF(_inp) atomic_add_int(&((_inp)->refcount), 1) #define SCTP_INP_DECR_REF(_inp) atomic_subtract_int(&((_inp)->refcount), 1) -#define SCTP_TCB_SEND_LOCK_INIT(_tcb) \ - (void)pthread_mutex_init(&(_tcb)->tcb_send_mtx, &SCTP_BASE_VAR(mtx_attr)) -#define SCTP_TCB_SEND_LOCK_DESTROY(_tcb) \ - (void)pthread_mutex_destroy(&(_tcb)->tcb_send_mtx) -#ifdef INVARIANTS -#define SCTP_TCB_SEND_LOCK(_tcb) \ - KASSERT(pthread_mutex_lock(&(_tcb)->tcb_send_mtx) == 0, ("%s:%d: tcb_send_mtx already locked", __FILE__, __LINE__)) -#define SCTP_TCB_SEND_UNLOCK(_tcb) \ - KASSERT(pthread_mutex_unlock(&(_tcb)->tcb_send_mtx) == 0, ("%s:%d: tcb_send_mtx not locked", __FILE__, __LINE__)) -#else -#define SCTP_TCB_SEND_LOCK(_tcb) \ - (void)pthread_mutex_lock(&(_tcb)->tcb_send_mtx) -#define SCTP_TCB_SEND_UNLOCK(_tcb) \ - (void)pthread_mutex_unlock(&(_tcb)->tcb_send_mtx) -#endif -#define SCTP_TCB_SEND_LOCK_ASSERT(_tcb) \ - KASSERT(pthread_mutex_trylock(&(_tcb)->tcb_send_mtx) == EBUSY, ("%s:%d: tcb_send_mtx not locked", __FILE__, __LINE__)) - #define SCTP_ASOC_CREATE_LOCK_INIT(_inp) \ (void)pthread_mutex_init(&(_inp)->inp_create_mtx, &SCTP_BASE_VAR(mtx_attr)) #define SCTP_ASOC_CREATE_LOCK_DESTROY(_inp) \ diff --git a/usrsctplib/netinet/sctp_ss_functions.c b/usrsctplib/netinet/sctp_ss_functions.c index 8db0f47..d6323d2 100755 --- a/usrsctplib/netinet/sctp_ss_functions.c +++ b/usrsctplib/netinet/sctp_ss_functions.c @@ -58,7 +58,7 @@ sctp_ss_default_init(struct sctp_tcb *stcb, struct sctp_association *asoc) { uint16_t i; - SCTP_TCB_SEND_LOCK_ASSERT(stcb); + SCTP_TCB_LOCK_ASSERT(stcb); asoc->ss_data.locked_on_sending = NULL; asoc->ss_data.last_out_stream = NULL; @@ -81,7 +81,7 @@ static void sctp_ss_default_clear(struct sctp_tcb *stcb, struct sctp_association *asoc, bool clear_values SCTP_UNUSED) { - SCTP_TCB_SEND_LOCK_ASSERT(stcb); + SCTP_TCB_LOCK_ASSERT(stcb); while (!TAILQ_EMPTY(&asoc->ss_data.out.wheel)) { struct sctp_stream_out *strq; @@ -98,6 +98,8 @@ sctp_ss_default_clear(struct sctp_tcb *stcb, struct sctp_association *asoc, static void sctp_ss_default_init_stream(struct sctp_tcb *stcb, struct sctp_stream_out *strq, struct sctp_stream_out *with_strq) { + SCTP_TCB_LOCK_ASSERT(stcb); + if (with_strq != NULL) { if (stcb->asoc.ss_data.locked_on_sending == with_strq) { stcb->asoc.ss_data.locked_on_sending = strq; @@ -115,7 +117,7 @@ sctp_ss_default_add(struct sctp_tcb *stcb, struct sctp_association *asoc, struct sctp_stream_out *strq, struct sctp_stream_queue_pending *sp SCTP_UNUSED) { - SCTP_TCB_SEND_LOCK_ASSERT(stcb); + SCTP_TCB_LOCK_ASSERT(stcb); /* Add to wheel if not already on it and stream queue not empty */ if (!TAILQ_EMPTY(&strq->outqueue) && !strq->ss_params.scheduled) { @@ -129,6 +131,8 @@ sctp_ss_default_add(struct sctp_tcb *stcb, struct sctp_association *asoc, static bool sctp_ss_default_is_empty(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_association *asoc) { + SCTP_TCB_LOCK_ASSERT(stcb); + return (TAILQ_EMPTY(&asoc->ss_data.out.wheel)); } @@ -137,7 +141,7 @@ sctp_ss_default_remove(struct sctp_tcb *stcb, struct sctp_association *asoc, struct sctp_stream_out *strq, struct sctp_stream_queue_pending *sp SCTP_UNUSED) { - SCTP_TCB_SEND_LOCK_ASSERT(stcb); + SCTP_TCB_LOCK_ASSERT(stcb); /* Remove from wheel if stream queue is empty and actually is on the wheel */ if (TAILQ_EMPTY(&strq->outqueue) && strq->ss_params.scheduled) { @@ -168,6 +172,8 @@ sctp_ss_default_select(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_nets *net, { struct sctp_stream_out *strq, *strqt; + SCTP_TCB_LOCK_ASSERT(stcb); + if (asoc->ss_data.locked_on_sending != NULL) { KASSERT(asoc->ss_data.locked_on_sending->ss_params.scheduled, ("locked_on_sending %p not scheduled", @@ -228,6 +234,8 @@ sctp_ss_default_scheduled(struct sctp_tcb *stcb, KASSERT(strq != NULL, ("strq is NULL")); KASSERT(strq->ss_params.scheduled, ("strq %p is not scheduled", (void *)strq)); + SCTP_TCB_LOCK_ASSERT(stcb); + asoc->ss_data.last_out_stream = strq; if (asoc->idata_supported == 0) { sp = TAILQ_FIRST(&strq->outqueue); @@ -246,6 +254,8 @@ static void sctp_ss_default_packet_done(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_nets *net SCTP_UNUSED, struct sctp_association *asoc SCTP_UNUSED) { + SCTP_TCB_LOCK_ASSERT(stcb); + /* Nothing to be done here */ return; } @@ -254,6 +264,8 @@ static int sctp_ss_default_get_value(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_association *asoc SCTP_UNUSED, struct sctp_stream_out *strq SCTP_UNUSED, uint16_t *value SCTP_UNUSED) { + SCTP_TCB_LOCK_ASSERT(stcb); + /* Nothing to be done here */ return (-1); } @@ -262,6 +274,8 @@ static int sctp_ss_default_set_value(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_association *asoc SCTP_UNUSED, struct sctp_stream_out *strq SCTP_UNUSED, uint16_t value SCTP_UNUSED) { + SCTP_TCB_LOCK_ASSERT(stcb); + /* Nothing to be done here */ return (-1); } @@ -272,6 +286,8 @@ sctp_ss_default_is_user_msgs_incomplete(struct sctp_tcb *stcb SCTP_UNUSED, struc struct sctp_stream_out *strq; struct sctp_stream_queue_pending *sp; + SCTP_TCB_LOCK_ASSERT(stcb); + if (asoc->stream_queue_cnt != 1) { return (false); } @@ -297,7 +313,7 @@ sctp_ss_rr_add(struct sctp_tcb *stcb, struct sctp_association *asoc, { struct sctp_stream_out *strqt; - SCTP_TCB_SEND_LOCK_ASSERT(stcb); + SCTP_TCB_LOCK_ASSERT(stcb); if (!TAILQ_EMPTY(&strq->outqueue) && !strq->ss_params.scheduled) { if (TAILQ_EMPTY(&asoc->ss_data.out.wheel)) { @@ -327,6 +343,8 @@ static struct sctp_stream_out * sctp_ss_rrp_select(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_nets *net SCTP_UNUSED, struct sctp_association *asoc) { + SCTP_TCB_LOCK_ASSERT(stcb); + return (asoc->ss_data.last_out_stream); } @@ -336,6 +354,8 @@ sctp_ss_rrp_packet_done(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_nets *net { struct sctp_stream_out *strq, *strqt; + SCTP_TCB_LOCK_ASSERT(stcb); + strqt = asoc->ss_data.last_out_stream; KASSERT(strqt == NULL || strqt->ss_params.scheduled, ("last_out_stream %p not scheduled", (void *)strqt)); @@ -388,7 +408,7 @@ static void sctp_ss_prio_clear(struct sctp_tcb *stcb, struct sctp_association *asoc, bool clear_values) { - SCTP_TCB_SEND_LOCK_ASSERT(stcb); + SCTP_TCB_LOCK_ASSERT(stcb); while (!TAILQ_EMPTY(&asoc->ss_data.out.wheel)) { struct sctp_stream_out *strq; @@ -408,6 +428,8 @@ sctp_ss_prio_clear(struct sctp_tcb *stcb, struct sctp_association *asoc, static void sctp_ss_prio_init_stream(struct sctp_tcb *stcb, struct sctp_stream_out *strq, struct sctp_stream_out *with_strq) { + SCTP_TCB_LOCK_ASSERT(stcb); + if (with_strq != NULL) { if (stcb->asoc.ss_data.locked_on_sending == with_strq) { stcb->asoc.ss_data.locked_on_sending = strq; @@ -431,7 +453,7 @@ sctp_ss_prio_add(struct sctp_tcb *stcb, struct sctp_association *asoc, { struct sctp_stream_out *strqt; - SCTP_TCB_SEND_LOCK_ASSERT(stcb); + SCTP_TCB_LOCK_ASSERT(stcb); /* Add to wheel if not already on it and stream queue not empty */ if (!TAILQ_EMPTY(&strq->outqueue) && !strq->ss_params.scheduled) { @@ -457,7 +479,7 @@ static void sctp_ss_prio_remove(struct sctp_tcb *stcb, struct sctp_association *asoc, struct sctp_stream_out *strq, struct sctp_stream_queue_pending *sp SCTP_UNUSED) { - SCTP_TCB_SEND_LOCK_ASSERT(stcb); + SCTP_TCB_LOCK_ASSERT(stcb); /* Remove from wheel if stream queue is empty and actually is on the wheel */ if (TAILQ_EMPTY(&strq->outqueue) && strq->ss_params.scheduled) { @@ -488,6 +510,8 @@ sctp_ss_prio_select(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_nets *net, { struct sctp_stream_out *strq, *strqt, *strqn; + SCTP_TCB_LOCK_ASSERT(stcb); + if (asoc->ss_data.locked_on_sending != NULL) { KASSERT(asoc->ss_data.locked_on_sending->ss_params.scheduled, ("locked_on_sending %p not scheduled", @@ -544,6 +568,8 @@ static int sctp_ss_prio_get_value(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_association *asoc SCTP_UNUSED, struct sctp_stream_out *strq, uint16_t *value) { + SCTP_TCB_LOCK_ASSERT(stcb); + if (strq == NULL) { return (-1); } @@ -555,6 +581,8 @@ static int sctp_ss_prio_set_value(struct sctp_tcb *stcb, struct sctp_association *asoc, struct sctp_stream_out *strq, uint16_t value) { + SCTP_TCB_LOCK_ASSERT(stcb); + if (strq == NULL) { return (-1); } @@ -572,7 +600,7 @@ static void sctp_ss_fb_clear(struct sctp_tcb *stcb, struct sctp_association *asoc, bool clear_values) { - SCTP_TCB_SEND_LOCK_ASSERT(stcb); + SCTP_TCB_LOCK_ASSERT(stcb); while (!TAILQ_EMPTY(&asoc->ss_data.out.wheel)) { struct sctp_stream_out *strq; @@ -592,6 +620,8 @@ sctp_ss_fb_clear(struct sctp_tcb *stcb, struct sctp_association *asoc, static void sctp_ss_fb_init_stream(struct sctp_tcb *stcb, struct sctp_stream_out *strq, struct sctp_stream_out *with_strq) { + SCTP_TCB_LOCK_ASSERT(stcb); + if (with_strq != NULL) { if (stcb->asoc.ss_data.locked_on_sending == with_strq) { stcb->asoc.ss_data.locked_on_sending = strq; @@ -613,7 +643,7 @@ static void sctp_ss_fb_add(struct sctp_tcb *stcb, struct sctp_association *asoc, struct sctp_stream_out *strq, struct sctp_stream_queue_pending *sp SCTP_UNUSED) { - SCTP_TCB_SEND_LOCK_ASSERT(stcb); + SCTP_TCB_LOCK_ASSERT(stcb); if (!TAILQ_EMPTY(&strq->outqueue) && !strq->ss_params.scheduled) { if (strq->ss_params.ss.fb.rounds < 0) @@ -628,7 +658,7 @@ static void sctp_ss_fb_remove(struct sctp_tcb *stcb, struct sctp_association *asoc, struct sctp_stream_out *strq, struct sctp_stream_queue_pending *sp SCTP_UNUSED) { - SCTP_TCB_SEND_LOCK_ASSERT(stcb); + SCTP_TCB_LOCK_ASSERT(stcb); /* Remove from wheel if stream queue is empty and actually is on the wheel */ if (TAILQ_EMPTY(&strq->outqueue) && strq->ss_params.scheduled) { @@ -659,6 +689,8 @@ sctp_ss_fb_select(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_nets *net, { struct sctp_stream_out *strq = NULL, *strqt; + SCTP_TCB_LOCK_ASSERT(stcb); + if (asoc->ss_data.locked_on_sending != NULL) { KASSERT(asoc->ss_data.locked_on_sending->ss_params.scheduled, ("locked_on_sending %p not scheduled", @@ -702,6 +734,8 @@ sctp_ss_fb_scheduled(struct sctp_tcb *stcb, struct sctp_nets *net SCTP_UNUSED, struct sctp_stream_out *strqt; int subtract; + SCTP_TCB_LOCK_ASSERT(stcb); + if (asoc->idata_supported == 0) { sp = TAILQ_FIRST(&strq->outqueue); if ((sp != NULL) && (sp->some_taken == 1)) { @@ -743,7 +777,7 @@ sctp_ss_fcfs_init(struct sctp_tcb *stcb, struct sctp_association *asoc) struct sctp_stream_queue_pending *sp; uint16_t i; - SCTP_TCB_SEND_LOCK_ASSERT(stcb); + SCTP_TCB_LOCK_ASSERT(stcb); TAILQ_INIT(&asoc->ss_data.out.list); /* @@ -779,7 +813,7 @@ sctp_ss_fcfs_clear(struct sctp_tcb *stcb, struct sctp_association *asoc, { struct sctp_stream_queue_pending *sp; - SCTP_TCB_SEND_LOCK_ASSERT(stcb); + SCTP_TCB_LOCK_ASSERT(stcb); while (!TAILQ_EMPTY(&asoc->ss_data.out.list)) { sp = TAILQ_FIRST(&asoc->ss_data.out.list); @@ -794,6 +828,8 @@ sctp_ss_fcfs_clear(struct sctp_tcb *stcb, struct sctp_association *asoc, static void sctp_ss_fcfs_init_stream(struct sctp_tcb *stcb, struct sctp_stream_out *strq, struct sctp_stream_out *with_strq) { + SCTP_TCB_LOCK_ASSERT(stcb); + if (with_strq != NULL) { if (stcb->asoc.ss_data.locked_on_sending == with_strq) { stcb->asoc.ss_data.locked_on_sending = strq; @@ -810,7 +846,7 @@ static void sctp_ss_fcfs_add(struct sctp_tcb *stcb, struct sctp_association *asoc, struct sctp_stream_out *strq SCTP_UNUSED, struct sctp_stream_queue_pending *sp) { - SCTP_TCB_SEND_LOCK_ASSERT(stcb); + SCTP_TCB_LOCK_ASSERT(stcb); if (!sp->scheduled) { TAILQ_INSERT_TAIL(&asoc->ss_data.out.list, sp, ss_next); @@ -822,6 +858,8 @@ sctp_ss_fcfs_add(struct sctp_tcb *stcb, struct sctp_association *asoc, static bool sctp_ss_fcfs_is_empty(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_association *asoc) { + SCTP_TCB_LOCK_ASSERT(stcb); + return (TAILQ_EMPTY(&asoc->ss_data.out.list)); } @@ -829,7 +867,7 @@ static void sctp_ss_fcfs_remove(struct sctp_tcb *stcb, struct sctp_association *asoc, struct sctp_stream_out *strq SCTP_UNUSED, struct sctp_stream_queue_pending *sp) { - SCTP_TCB_SEND_LOCK_ASSERT(stcb); + SCTP_TCB_LOCK_ASSERT(stcb); if (sp->scheduled) { TAILQ_REMOVE(&asoc->ss_data.out.list, sp, ss_next); @@ -845,6 +883,8 @@ sctp_ss_fcfs_select(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_nets *net, struct sctp_stream_out *strq; struct sctp_stream_queue_pending *sp; + SCTP_TCB_LOCK_ASSERT(stcb); + if (asoc->ss_data.locked_on_sending) { return (asoc->ss_data.locked_on_sending); } diff --git a/usrsctplib/netinet/sctp_timer.c b/usrsctplib/netinet/sctp_timer.c index e9ccdf1..84d56b1 100755 --- a/usrsctplib/netinet/sctp_timer.c +++ b/usrsctplib/netinet/sctp_timer.c @@ -1365,8 +1365,7 @@ sctp_audit_stream_queues_for_size(struct sctp_inpcb *inp, struct sctp_tcb *stcb) KASSERT(inp != NULL, ("inp is NULL")); KASSERT(stcb != NULL, ("stcb is NULL")); - - SCTP_TCB_SEND_LOCK(stcb); + SCTP_TCB_LOCK_ASSERT(stcb); KASSERT(TAILQ_EMPTY(&stcb->asoc.send_queue), ("send_queue not empty")); KASSERT(TAILQ_EMPTY(&stcb->asoc.sent_queue), ("sent_queue not empty")); @@ -1400,7 +1399,6 @@ sctp_audit_stream_queues_for_size(struct sctp_inpcb *inp, struct sctp_tcb *stcb) SCTP_PRINTF("Hmm, stream queue cnt at %d I counted %d in stream out wheel\n", stcb->asoc.stream_queue_cnt, chks_in_queue); } - SCTP_TCB_SEND_UNLOCK(stcb); if (chks_in_queue) { /* call the output queue function */ sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED); diff --git a/usrsctplib/netinet/sctp_uio.h b/usrsctplib/netinet/sctp_uio.h index 18956f1..9daf847 100755 --- a/usrsctplib/netinet/sctp_uio.h +++ b/usrsctplib/netinet/sctp_uio.h @@ -34,7 +34,7 @@ #if defined(__FreeBSD__) && !defined(__Userspace__) #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_uio.h 365071 2020-09-01 21:19:14Z mjg $"); +__FBSDID("$FreeBSD$"); #endif #ifndef _NETINET_SCTP_UIO_H_ @@ -1277,7 +1277,7 @@ int sctp_lower_sosend(struct socket *so, struct sockaddr *addr, struct uio *uio, - struct mbuf *i_pak, + struct mbuf *top, struct mbuf *control, int flags, struct sctp_sndrcvinfo *srcv diff --git a/usrsctplib/netinet/sctp_usrreq.c b/usrsctplib/netinet/sctp_usrreq.c index 1756bf4..5957031 100755 --- a/usrsctplib/netinet/sctp_usrreq.c +++ b/usrsctplib/netinet/sctp_usrreq.c @@ -4768,12 +4768,10 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, } SCTP_FIND_STCB(inp, stcb, av->assoc_id); if (stcb) { - SCTP_TCB_SEND_LOCK(stcb); stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, true); stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value]; stcb->asoc.stream_scheduling_module = av->assoc_value; stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc); - SCTP_TCB_SEND_UNLOCK(stcb); SCTP_TCB_UNLOCK(stcb); } else { if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || @@ -4791,12 +4789,10 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, SCTP_INP_RLOCK(inp); LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { SCTP_TCB_LOCK(stcb); - SCTP_TCB_SEND_LOCK(stcb); stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, true); stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value]; stcb->asoc.stream_scheduling_module = av->assoc_value; stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc); - SCTP_TCB_SEND_UNLOCK(stcb); SCTP_TCB_UNLOCK(stcb); } SCTP_INP_RUNLOCK(inp); diff --git a/usrsctplib/netinet/sctputil.c b/usrsctplib/netinet/sctputil.c index 55d3a15..fe733df 100755 --- a/usrsctplib/netinet/sctputil.c +++ b/usrsctplib/netinet/sctputil.c @@ -1330,7 +1330,7 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOMEM); return (ENOMEM); } - SCTP_TCB_SEND_LOCK(stcb); + SCTP_TCB_LOCK(stcb); for (i = 0; i < asoc->streamoutcnt; i++) { /* * inbound side must be set to 0xffff, also NOTE when we get @@ -1359,7 +1359,7 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, asoc->strmout[i].state = SCTP_STREAM_OPENING; } asoc->ss_functions.sctp_ss_init(stcb, asoc); - SCTP_TCB_SEND_UNLOCK(stcb); + SCTP_TCB_UNLOCK(stcb); /* Now the mapping array */ asoc->mapping_array_size = SCTP_INITIAL_MAPPING_ARRAY; @@ -4549,6 +4549,8 @@ sctp_abort_notification(struct sctp_tcb *stcb, bool from_peer, bool timeout, sctp_unlock_assert(SCTP_INP_SO(stcb->sctp_ep)); } #endif + SCTP_TCB_LOCK_ASSERT(stcb); + if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED))) { @@ -4559,11 +4561,9 @@ sctp_abort_notification(struct sctp_tcb *stcb, bool from_peer, bool timeout, (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, so_locked); - SCTP_TCB_SEND_UNLOCK(stcb); if (from_peer) { sctp_ulp_notify(SCTP_NOTIFY_ASSOC_REM_ABORTED, stcb, error, abort, so_locked); } else { @@ -5548,6 +5548,8 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1, sctp_unlock_assert(SCTP_INP_SO(stcb->sctp_ep)); } #endif + SCTP_TCB_LOCK_ASSERT(stcb); + sid = tp1->rec.data.sid; mid = tp1->rec.data.mid; if (sent || !(tp1->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG)) { @@ -5654,7 +5656,6 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1, * Still no eom found. That means there * is stuff left on the stream out queue.. yuck. */ - SCTP_TCB_SEND_LOCK(stcb); strq = &stcb->asoc.strmout[sid]; sp = TAILQ_FIRST(&strq->outqueue); if (sp != NULL) { @@ -5739,7 +5740,6 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1, sp->length = 0; } } - SCTP_TCB_SEND_UNLOCK(stcb); } if (do_wakeup_routine) { #if defined(__APPLE__) && !defined(__Userspace__) |
