aboutsummaryrefslogtreecommitdiff
path: root/sys/netinet/sctp_output.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet/sctp_output.c')
-rw-r--r--sys/netinet/sctp_output.c41
1 files changed, 34 insertions, 7 deletions
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c
index b7e040ff2679..e80573e36838 100644
--- a/sys/netinet/sctp_output.c
+++ b/sys/netinet/sctp_output.c
@@ -4612,7 +4612,7 @@ sctp_are_there_new_addresses(struct sctp_association *asoc,
void
sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
struct mbuf *init_pkt, int iphlen, int offset, struct sctphdr *sh,
- struct sctp_init_chunk *init_chk, uint32_t vrf_id)
+ struct sctp_init_chunk *init_chk, uint32_t vrf_id, int hold_inp_lock)
{
struct sctp_association *asoc;
struct mbuf *m, *m_at, *m_tmp, *m_cookie, *op_err, *mp_last;
@@ -4636,6 +4636,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
int abort_flag, padval;
int num_ext;
int p_len;
+ struct socket *so;
if (stcb)
asoc = &stcb->asoc;
@@ -4947,6 +4948,9 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
} else {
uint32_t vtag, itsn;
+ if (hold_inp_lock) {
+ SCTP_INP_RUNLOCK(inp);
+ }
if (asoc) {
atomic_add_int(&asoc->refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
@@ -4963,12 +4967,22 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
/* get a TSN to use too */
initackm_out->msg.init.initial_tsn = htonl(sctp_select_initial_TSN(&inp->sctp_ep));
}
+ if (hold_inp_lock) {
+ SCTP_INP_RLOCK(inp);
+ }
}
/* save away my tag to */
stc.my_vtag = initackm_out->msg.init.initiate_tag;
/* set up some of the credits. */
- initackm_out->msg.init.a_rwnd = htonl(max(SCTP_SB_LIMIT_RCV(inp->sctp_socket), SCTP_MINIMAL_RWND));
+ so = inp->sctp_socket;
+ if (so == NULL) {
+ /* memory problem */
+ sctp_m_freem(m);
+ return;
+ } else {
+ initackm_out->msg.init.a_rwnd = htonl(max(SCTP_SB_LIMIT_RCV(so), SCTP_MINIMAL_RWND));
+ }
/* set what I want */
his_limit = ntohs(init_chk->init.num_inbound_streams);
/* choose what I want */
@@ -10962,7 +10976,10 @@ sctp_lower_sosend(struct socket *so,
if (inp == NULL) {
SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, EFAULT);
error = EFAULT;
- goto out_unlocked;
+ if (i_pak) {
+ SCTP_RELEASE_PKT(i_pak);
+ }
+ return (error);
}
if ((uio == NULL) && (i_pak == NULL)) {
SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
@@ -11193,6 +11210,11 @@ sctp_lower_sosend(struct socket *so,
}
/* 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
stcb = sctp_aloc_assoc(inp, addr, 1, &error, 0, vrf_id,
p
);
@@ -11342,11 +11364,16 @@ sctp_lower_sosend(struct socket *so,
}
}
/* Keep the stcb from being freed under our feet */
- if (free_cnt_applied)
+ if (free_cnt_applied) {
+#ifdef INVARIANTS
panic("refcnt already incremented");
- atomic_add_int(&stcb->asoc.refcnt, 1);
- free_cnt_applied = 1;
-
+#else
+ printf("refcnt:1 already incremented?\n");
+#endif
+ } else {
+ atomic_add_int(&stcb->asoc.refcnt, 1);
+ free_cnt_applied = 1;
+ }
if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ECONNRESET);
error = ECONNRESET;