From 1b181171ae63e565fff3af7d33d65d39a0d9e4cf Mon Sep 17 00:00:00 2001 From: rrs Date: Thu, 18 Jan 2007 09:58:43 +0000 Subject: - most all includes (#include <>) migrate to the sctp_os_bsd.h file - Finally all splxx() are removed - Count error fixed in mapping array which might cause a wrong cumack generation. - Invariants around panic for case D + printf when no invariants. - one-to-one model race condition fixed by using a pre-formed connection and then completing the work so accept won't happen on a non-formed association. - Some additional paranoia checks in sctp_output. - Locks that were missing in the accept code. Approved by: gnn --- sys/netinet/sctp_output.c | 112 ++++++++++++---------------------------------- 1 file changed, 28 insertions(+), 84 deletions(-) (limited to 'sys/netinet/sctp_output.c') diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index a6c129d..d1ceb6b 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -33,69 +33,8 @@ #include __FBSDID("$FreeBSD$"); -#include "opt_ipsec.h" -#include "opt_compat.h" -#include "opt_inet6.h" -#include "opt_inet.h" -#include "opt_sctp.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef INET6 -#include -#endif - -#include -#include - -#include -#include - -#include - -#include - -#include -#include -#include -#include -#include -#include - -#ifdef INET6 -#include -#include -#include -#include - -#include - -#include - -#endif /* INET6 */ - - - -#ifndef in6pcb -#define in6pcb inpcb -#endif - -#ifdef IPSEC -#include -#include -#endif /* IPSEC */ - #include +#include #include #include #include @@ -5085,6 +5024,7 @@ out_gu: } sp->some_taken = some_taken; sp->length += to_move; + chk->data = NULL; sctp_free_a_chunk(stcb, chk); SCTP_TCB_SEND_UNLOCK(stcb); goto out_gu; @@ -5957,6 +5897,15 @@ again_one_more_time: } if (((chk->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) == SCTP_DATA_LAST_FRAG) && ((chk->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG) == 0)) + /* + * Count number of + * user msg's that + * were fragmented + * we do this by + * counting when we + * see a LAST + * fragment only. + */ SCTP_STAT_INCR_COUNTER64(sctps_fragusrmsgs); } if ((mtu == 0) || (r_mtu == 0) || (one_chunk)) { @@ -7726,6 +7675,10 @@ sctp_send_sack(struct sctp_tcb *stcb) mergeable = 1; } } + if (limit_reached) { + /* Reached the limit stop */ + break; + } jstart = 0; offset += 8; } @@ -9223,11 +9176,10 @@ sctp_sosend(struct socket *so, ) { struct sctp_inpcb *inp; - int s, error, use_rcvinfo = 0; + int error, use_rcvinfo = 0; struct sctp_sndrcvinfo srcv; inp = (struct sctp_inpcb *)so->so_pcb; - s = splnet(); if (control) { /* process cmsg snd/rcv info (maybe a assoc-id) */ if (sctp_find_cmsg(SCTP_SNDRCV, (void *)&srcv, control, @@ -9238,7 +9190,6 @@ sctp_sosend(struct socket *so, } error = sctp_lower_sosend(so, addr, uio, top, control, flags, use_rcvinfo, &srcv, p); - splx(s); return (error); } @@ -9259,7 +9210,12 @@ sctp_lower_sosend(struct socket *so, unsigned int sndlen, max_len; int error, len; struct mbuf *top = NULL; - int s, queue_only = 0, queue_only_for_init = 0; + +#if defined(__NetBSD__) || defined(__OpenBSD_) + int s; + +#endif + int queue_only = 0, queue_only_for_init = 0; int free_cnt_applied = 0; int un_sent = 0; int now_filled = 0; @@ -9284,7 +9240,6 @@ sctp_lower_sosend(struct socket *so, t_inp = inp = (struct sctp_inpcb *)so->so_pcb; if (inp == NULL) { error = EFAULT; - splx(s); goto out_unlocked; } atomic_add_int(&inp->total_sends, 1); @@ -9295,20 +9250,17 @@ sctp_lower_sosend(struct socket *so, top = SCTP_HEADER_TO_CHAIN(i_pak); } - s = splnet(); hold_tcblock = 0; if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && (inp->sctp_socket->so_qlimit)) { /* The listener can NOT send */ error = EFAULT; - splx(s); goto out_unlocked; } if ((use_rcvinfo) && srcv) { if (INVALID_SINFO_FLAG(srcv->sinfo_flags) || PR_SCTP_INVALID_POLICY(srcv->sinfo_flags)) { error = EINVAL; - splx(s); goto out_unlocked; } if (srcv->sinfo_flags) @@ -9318,7 +9270,6 @@ sctp_lower_sosend(struct socket *so, /* its a sendall */ error = sctp_sendall(inp, uio, top, srcv); top = NULL; - splx(s); goto out_unlocked; } } @@ -9329,7 +9280,6 @@ sctp_lower_sosend(struct socket *so, if (stcb == NULL) { SCTP_INP_RUNLOCK(inp); error = ENOTCONN; - splx(s); goto out_unlocked; } hold_tcblock = 0; @@ -9378,14 +9328,12 @@ sctp_lower_sosend(struct socket *so, (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE)) { /* Should I really unlock ? */ error = EFAULT; - splx(s); goto out_unlocked; } if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) && (addr->sa_family == AF_INET6)) { error = EINVAL; - splx(s); goto out_unlocked; } SCTP_INP_WLOCK(inp); @@ -9404,11 +9352,9 @@ sctp_lower_sosend(struct socket *so, if (stcb == NULL) { if (inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) { error = ENOTCONN; - splx(s); goto out_unlocked; } else if (addr == NULL) { error = ENOENT; - splx(s); goto out_unlocked; } else { /* @@ -9424,14 +9370,12 @@ sctp_lower_sosend(struct socket *so, * or EOF a non-existant assoc with no data */ error = ENOENT; - splx(s); goto out_unlocked; } /* get an asoc/stcb struct */ stcb = sctp_aloc_assoc(inp, addr, 1, &error, 0); if (stcb == NULL) { /* Error is setup for us in the call */ - splx(s); goto out_unlocked; } if (create_lock_applied) { @@ -9505,7 +9449,12 @@ sctp_lower_sosend(struct socket *so, if (had_lock) { SCTP_TCB_LOCK(stcb); } - asoc->strmout = tmp_str; + if (asoc->strmout == NULL) { + asoc->strmout = tmp_str; + } else { + SCTP_FREE(asoc->strmout); + asoc->strmout = tmp_str; + } } for (i = 0; i < asoc->streamoutcnt; i++) { /* @@ -9567,7 +9516,6 @@ sctp_lower_sosend(struct socket *so, sctp_max_chunks_on_queue)) { error = EWOULDBLOCK; atomic_add_int(&stcb->sctp_ep->total_nospaces, 1); - splx(s); goto out_unlocked; } } @@ -9612,7 +9560,6 @@ sctp_lower_sosend(struct socket *so, ; } else { error = ECONNRESET; - splx(s); goto out_unlocked; } } @@ -9741,7 +9688,6 @@ sctp_lower_sosend(struct socket *so, SCTP_TCB_UNLOCK(stcb); hold_tcblock = 0; } - splx(s); /* Is the stream no. valid? */ if (srcv->sinfo_stream >= asoc->streamoutcnt) { /* Invalid stream number */ @@ -10279,7 +10225,6 @@ skip_out_eof: } if ((queue_only == 0) && (nagle_applies == 0) && (stcb->asoc.peers_rwnd && un_sent)) { /* we can attempt to send too. */ - s = splnet(); if (hold_tcblock == 0) { /* * If there is activity recv'ing sacks no need to @@ -10292,7 +10237,6 @@ skip_out_eof: } else { sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_USR_SEND); } - splx(s); } else if ((queue_only == 0) && (stcb->asoc.peers_rwnd == 0) && (stcb->asoc.total_flight == 0)) { -- cgit v1.1