* Fix a bug where PR-SCTP settings are ignore when using implicit
association setup. * Fix a bug where message with illegal stream ids are not deleted. * Fix a crash when reporting back unsent messages from the send_queue. * Fix a bug related to INIT retransmission when the socket is already closed. * Fix a bug where associations were stalled when partial delivery API was enabled. * Fix a bug where the receive buffer size was smaller than the partial_delivery_point. Approved by: re, rrs (mentor) MFC after: One day.
This commit is contained in:
parent
68a5590836
commit
810ec53688
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=196260
@ -900,7 +900,7 @@ sctp_deliver_reasm_check(struct sctp_tcb *stcb, struct sctp_association *asoc)
|
||||
{
|
||||
struct sctp_tmit_chunk *chk;
|
||||
uint16_t nxt_todel;
|
||||
uint32_t tsize;
|
||||
uint32_t tsize, pd_point;
|
||||
|
||||
doit_again:
|
||||
chk = TAILQ_FIRST(&asoc->reasmqueue);
|
||||
@ -920,8 +920,13 @@ sctp_deliver_reasm_check(struct sctp_tcb *stcb, struct sctp_association *asoc)
|
||||
* Yep the first one is here and its ok to deliver
|
||||
* but should we?
|
||||
*/
|
||||
if ((sctp_is_all_msg_on_reasm(asoc, &tsize) ||
|
||||
(tsize >= stcb->sctp_ep->partial_delivery_point))) {
|
||||
if (stcb->sctp_socket) {
|
||||
pd_point = min(SCTP_SB_LIMIT_RCV(stcb->sctp_socket) >> SCTP_PARTIAL_DELIVERY_SHIFT,
|
||||
stcb->sctp_ep->partial_delivery_point);
|
||||
} else {
|
||||
pd_point = stcb->sctp_ep->partial_delivery_point;
|
||||
}
|
||||
if (sctp_is_all_msg_on_reasm(asoc, &tsize) || (tsize >= pd_point)) {
|
||||
|
||||
/*
|
||||
* Yes, we setup to start reception, by
|
||||
@ -2824,7 +2829,7 @@ void
|
||||
sctp_service_queues(struct sctp_tcb *stcb, struct sctp_association *asoc)
|
||||
{
|
||||
struct sctp_tmit_chunk *chk;
|
||||
uint32_t tsize;
|
||||
uint32_t tsize, pd_point;
|
||||
uint16_t nxt_todel;
|
||||
|
||||
if (asoc->fragmented_delivery_inprogress) {
|
||||
@ -2860,8 +2865,13 @@ sctp_service_queues(struct sctp_tcb *stcb, struct sctp_association *asoc)
|
||||
* be here or 1/4 the socket buffer max or nothing on the
|
||||
* delivery queue and something can be delivered.
|
||||
*/
|
||||
if ((sctp_is_all_msg_on_reasm(asoc, &tsize) ||
|
||||
(tsize >= stcb->sctp_ep->partial_delivery_point))) {
|
||||
if (stcb->sctp_socket) {
|
||||
pd_point = min(SCTP_SB_LIMIT_RCV(stcb->sctp_socket) >> SCTP_PARTIAL_DELIVERY_SHIFT,
|
||||
stcb->sctp_ep->partial_delivery_point);
|
||||
} else {
|
||||
pd_point = stcb->sctp_ep->partial_delivery_point;
|
||||
}
|
||||
if (sctp_is_all_msg_on_reasm(asoc, &tsize) || (tsize >= pd_point)) {
|
||||
asoc->fragmented_delivery_inprogress = 1;
|
||||
asoc->tsn_last_delivered = chk->rec.data.TSN_seq - 1;
|
||||
asoc->str_of_pdapi = chk->rec.data.stream_number;
|
||||
@ -5192,7 +5202,7 @@ sctp_handle_sack(struct mbuf *m, int offset,
|
||||
/* sa_ignore NO_NULL_CHK */
|
||||
sctp_free_bufspace(stcb, asoc, tp1, 1);
|
||||
sctp_m_freem(tp1->data);
|
||||
if (PR_SCTP_BUF_ENABLED(tp1->flags)) {
|
||||
if (asoc->peer_supports_prsctp && PR_SCTP_BUF_ENABLED(tp1->flags)) {
|
||||
asoc->sent_queue_cnt_removeable--;
|
||||
}
|
||||
}
|
||||
@ -6289,10 +6299,11 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
|
||||
ctl->pdapi_aborted = 1;
|
||||
sv = stcb->asoc.control_pdapi;
|
||||
stcb->asoc.control_pdapi = ctl;
|
||||
sctp_notify_partial_delivery_indication(stcb,
|
||||
sctp_ulp_notify(SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION,
|
||||
stcb,
|
||||
SCTP_PARTIAL_DELIVERY_ABORTED,
|
||||
SCTP_HOLDS_LOCK,
|
||||
str_seq);
|
||||
(void *)&str_seq,
|
||||
SCTP_SO_NOT_LOCKED);
|
||||
stcb->asoc.control_pdapi = sv;
|
||||
break;
|
||||
} else if ((ctl->sinfo_stream == stseq->stream) &&
|
||||
@ -7786,7 +7797,7 @@ sctp_handle_nr_sack(struct mbuf *m, int offset,
|
||||
/* sa_ignore NO_NULL_CHK */
|
||||
sctp_free_bufspace(stcb, asoc, tp1, 1);
|
||||
sctp_m_freem(tp1->data);
|
||||
if (PR_SCTP_BUF_ENABLED(tp1->flags)) {
|
||||
if (asoc->peer_supports_prsctp && PR_SCTP_BUF_ENABLED(tp1->flags)) {
|
||||
asoc->sent_queue_cnt_removeable--;
|
||||
}
|
||||
}
|
||||
|
@ -278,18 +278,38 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb,
|
||||
unsigned int newcnt;
|
||||
struct sctp_stream_out *outs;
|
||||
struct sctp_stream_queue_pending *sp;
|
||||
struct sctp_tmit_chunk *chk, *chk_next;
|
||||
|
||||
/* cut back on number of streams */
|
||||
/* abandon the upper streams */
|
||||
newcnt = ntohs(init->num_inbound_streams);
|
||||
/* This if is probably not needed but I am cautious */
|
||||
if (!TAILQ_EMPTY(&asoc->send_queue)) {
|
||||
chk = TAILQ_FIRST(&asoc->send_queue);
|
||||
while (chk) {
|
||||
chk_next = TAILQ_NEXT(chk, sctp_next);
|
||||
if (chk->rec.data.stream_number >= newcnt) {
|
||||
TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next);
|
||||
asoc->send_queue_cnt--;
|
||||
if (chk->data != NULL) {
|
||||
sctp_free_bufspace(stcb, asoc, chk, 1);
|
||||
sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
|
||||
SCTP_NOTIFY_DATAGRAM_UNSENT, chk, SCTP_SO_NOT_LOCKED);
|
||||
if (chk->data) {
|
||||
sctp_m_freem(chk->data);
|
||||
chk->data = NULL;
|
||||
}
|
||||
}
|
||||
sctp_free_a_chunk(stcb, chk);
|
||||
/* sa_ignore FREED_MEMORY */
|
||||
}
|
||||
chk = chk_next;
|
||||
}
|
||||
}
|
||||
if (asoc->strmout) {
|
||||
/* First make sure no data chunks are trapped */
|
||||
for (i = newcnt; i < asoc->pre_open_streams; i++) {
|
||||
outs = &asoc->strmout[i];
|
||||
sp = TAILQ_FIRST(&outs->outqueue);
|
||||
while (sp) {
|
||||
TAILQ_REMOVE(&outs->outqueue, sp,
|
||||
next);
|
||||
TAILQ_REMOVE(&outs->outqueue, sp, next);
|
||||
asoc->stream_queue_cnt--;
|
||||
sctp_ulp_notify(SCTP_NOTIFY_SPECIAL_SP_FAIL,
|
||||
stcb, SCTP_NOTIFY_DATAGRAM_UNSENT,
|
||||
@ -301,16 +321,13 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb,
|
||||
sctp_free_remote_addr(sp->net);
|
||||
sp->net = NULL;
|
||||
/* Free the chunk */
|
||||
SCTP_PRINTF("sp:%p tcb:%p weird free case\n",
|
||||
sp, stcb);
|
||||
|
||||
sctp_free_a_strmoq(stcb, sp);
|
||||
/* sa_ignore FREED_MEMORY */
|
||||
sp = TAILQ_FIRST(&outs->outqueue);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* cut back the count and abandon the upper streams */
|
||||
/* cut back the count */
|
||||
asoc->pre_open_streams = newcnt;
|
||||
}
|
||||
SCTP_TCB_SEND_UNLOCK(stcb);
|
||||
|
@ -4200,7 +4200,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
|
||||
/* place in my tag */
|
||||
init->init.initiate_tag = htonl(stcb->asoc.my_vtag);
|
||||
/* set up some of the credits. */
|
||||
init->init.a_rwnd = htonl(max(SCTP_SB_LIMIT_RCV(inp->sctp_socket),
|
||||
init->init.a_rwnd = htonl(max(inp->sctp_socket ? SCTP_SB_LIMIT_RCV(inp->sctp_socket) : 0,
|
||||
SCTP_MINIMAL_RWND));
|
||||
|
||||
init->init.num_outbound_streams = htons(stcb->asoc.pre_open_streams);
|
||||
@ -4411,7 +4411,6 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
|
||||
net->port, so_locked, NULL);
|
||||
SCTPDBG(SCTP_DEBUG_OUTPUT4, "lowlevel_output - %d\n", ret);
|
||||
SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks);
|
||||
sctp_timer_start(SCTP_TIMER_TYPE_INIT, inp, stcb, net);
|
||||
(void)SCTP_GETTIME_TIMEVAL(&net->last_sent_time);
|
||||
}
|
||||
|
||||
@ -5786,61 +5785,58 @@ sctp_get_frag_point(struct sctp_tcb *stcb,
|
||||
}
|
||||
|
||||
static void
|
||||
sctp_set_prsctp_policy(struct sctp_tcb *stcb,
|
||||
struct sctp_stream_queue_pending *sp)
|
||||
sctp_set_prsctp_policy(struct sctp_stream_queue_pending *sp)
|
||||
{
|
||||
sp->pr_sctp_on = 0;
|
||||
if (stcb->asoc.peer_supports_prsctp) {
|
||||
/*
|
||||
* We assume that the user wants PR_SCTP_TTL if the user provides a
|
||||
* positive lifetime but does not specify any PR_SCTP policy. This
|
||||
* is a BAD assumption and causes problems at least with the
|
||||
* U-Vancovers MPI folks. I will change this to be no policy means
|
||||
* NO PR-SCTP.
|
||||
*/
|
||||
if (PR_SCTP_ENABLED(sp->sinfo_flags)) {
|
||||
sp->act_flags |= PR_SCTP_POLICY(sp->sinfo_flags);
|
||||
sp->pr_sctp_on = 1;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
switch (PR_SCTP_POLICY(sp->sinfo_flags)) {
|
||||
case CHUNK_FLAGS_PR_SCTP_BUF:
|
||||
/*
|
||||
* We assume that the user wants PR_SCTP_TTL if the user
|
||||
* provides a positive lifetime but does not specify any
|
||||
* PR_SCTP policy. This is a BAD assumption and causes
|
||||
* problems at least with the U-Vancovers MPI folks. I will
|
||||
* change this to be no policy means NO PR-SCTP.
|
||||
* Time to live is a priority stored in tv_sec when doing
|
||||
* the buffer drop thing.
|
||||
*/
|
||||
if (PR_SCTP_ENABLED(sp->sinfo_flags)) {
|
||||
sp->act_flags |= PR_SCTP_POLICY(sp->sinfo_flags);
|
||||
sp->pr_sctp_on = 1;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
switch (PR_SCTP_POLICY(sp->sinfo_flags)) {
|
||||
case CHUNK_FLAGS_PR_SCTP_BUF:
|
||||
/*
|
||||
* Time to live is a priority stored in tv_sec when
|
||||
* doing the buffer drop thing.
|
||||
*/
|
||||
sp->ts.tv_sec = sp->timetolive;
|
||||
sp->ts.tv_usec = 0;
|
||||
break;
|
||||
case CHUNK_FLAGS_PR_SCTP_TTL:
|
||||
{
|
||||
struct timeval tv;
|
||||
sp->ts.tv_sec = sp->timetolive;
|
||||
sp->ts.tv_usec = 0;
|
||||
break;
|
||||
case CHUNK_FLAGS_PR_SCTP_TTL:
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
(void)SCTP_GETTIME_TIMEVAL(&sp->ts);
|
||||
tv.tv_sec = sp->timetolive / 1000;
|
||||
tv.tv_usec = (sp->timetolive * 1000) % 1000000;
|
||||
/*
|
||||
* TODO sctp_constants.h needs alternative
|
||||
* time macros when _KERNEL is undefined.
|
||||
*/
|
||||
timevaladd(&sp->ts, &tv);
|
||||
}
|
||||
break;
|
||||
case CHUNK_FLAGS_PR_SCTP_RTX:
|
||||
(void)SCTP_GETTIME_TIMEVAL(&sp->ts);
|
||||
tv.tv_sec = sp->timetolive / 1000;
|
||||
tv.tv_usec = (sp->timetolive * 1000) % 1000000;
|
||||
/*
|
||||
* Time to live is a the number or retransmissions
|
||||
* stored in tv_sec.
|
||||
* TODO sctp_constants.h needs alternative time
|
||||
* macros when _KERNEL is undefined.
|
||||
*/
|
||||
sp->ts.tv_sec = sp->timetolive;
|
||||
sp->ts.tv_usec = 0;
|
||||
break;
|
||||
default:
|
||||
SCTPDBG(SCTP_DEBUG_USRREQ1,
|
||||
"Unknown PR_SCTP policy %u.\n",
|
||||
PR_SCTP_POLICY(sp->sinfo_flags));
|
||||
break;
|
||||
timevaladd(&sp->ts, &tv);
|
||||
}
|
||||
break;
|
||||
case CHUNK_FLAGS_PR_SCTP_RTX:
|
||||
/*
|
||||
* Time to live is a the number or retransmissions stored in
|
||||
* tv_sec.
|
||||
*/
|
||||
sp->ts.tv_sec = sp->timetolive;
|
||||
sp->ts.tv_usec = 0;
|
||||
break;
|
||||
default:
|
||||
SCTPDBG(SCTP_DEBUG_USRREQ1,
|
||||
"Unknown PR_SCTP policy %u.\n",
|
||||
PR_SCTP_POLICY(sp->sinfo_flags));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -5911,7 +5907,7 @@ sctp_msg_append(struct sctp_tcb *stcb,
|
||||
sp->tail_mbuf = NULL;
|
||||
sp->length = 0;
|
||||
at = m;
|
||||
sctp_set_prsctp_policy(stcb, sp);
|
||||
sctp_set_prsctp_policy(sp);
|
||||
/*
|
||||
* We could in theory (for sendall) sifa the length in, but we would
|
||||
* still have to hunt through the chain since we need to setup the
|
||||
@ -7138,7 +7134,7 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb, struct sctp_nets *net,
|
||||
}
|
||||
/* We only re-set the policy if it is on */
|
||||
if (sp->pr_sctp_on) {
|
||||
sctp_set_prsctp_policy(stcb, sp);
|
||||
sctp_set_prsctp_policy(sp);
|
||||
asoc->pr_sctp_cnt++;
|
||||
chk->pr_sctp_on = 1;
|
||||
} else {
|
||||
@ -12285,7 +12281,7 @@ sctp_copy_it_in(struct sctp_tcb *stcb,
|
||||
sp->addr_over = 0;
|
||||
}
|
||||
atomic_add_int(&sp->net->ref_count, 1);
|
||||
sctp_set_prsctp_policy(stcb, sp);
|
||||
sctp_set_prsctp_policy(sp);
|
||||
}
|
||||
out_now:
|
||||
return (sp);
|
||||
|
@ -4547,8 +4547,11 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
|
||||
|
||||
stcb->asoc.control_pdapi = sq;
|
||||
strseq = (sq->sinfo_stream << 16) | sq->sinfo_ssn;
|
||||
sctp_notify_partial_delivery_indication(stcb,
|
||||
SCTP_PARTIAL_DELIVERY_ABORTED, 1, strseq);
|
||||
sctp_ulp_notify(SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION,
|
||||
stcb,
|
||||
SCTP_PARTIAL_DELIVERY_ABORTED,
|
||||
(void *)&strseq,
|
||||
SCTP_SO_LOCKED);
|
||||
stcb->asoc.control_pdapi = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -588,7 +588,7 @@ sctp_recover_sent_list(struct sctp_tcb *stcb)
|
||||
/* sa_ignore NO_NULL_CHK */
|
||||
sctp_free_bufspace(stcb, asoc, chk, 1);
|
||||
sctp_m_freem(chk->data);
|
||||
if (PR_SCTP_BUF_ENABLED(chk->flags)) {
|
||||
if (asoc->peer_supports_prsctp && PR_SCTP_BUF_ENABLED(chk->flags)) {
|
||||
asoc->sent_queue_cnt_removeable--;
|
||||
}
|
||||
}
|
||||
@ -757,7 +757,7 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb,
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (PR_SCTP_TTL_ENABLED(chk->flags)) {
|
||||
if (stcb->asoc.peer_supports_prsctp && PR_SCTP_TTL_ENABLED(chk->flags)) {
|
||||
/* Is it expired? */
|
||||
if ((now.tv_sec > chk->rec.data.timetodrop.tv_sec) ||
|
||||
((chk->rec.data.timetodrop.tv_sec == now.tv_sec) &&
|
||||
@ -772,7 +772,7 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb,
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (PR_SCTP_RTX_ENABLED(chk->flags)) {
|
||||
if (stcb->asoc.peer_supports_prsctp && PR_SCTP_RTX_ENABLED(chk->flags)) {
|
||||
/* Has it been retransmitted tv_sec times? */
|
||||
if (chk->snd_count > chk->rec.data.timetodrop.tv_sec) {
|
||||
if (chk->data) {
|
||||
|
@ -1484,6 +1484,7 @@ sctp_timeout_handler(void *t)
|
||||
SCTP_INP_INCR_REF(inp);
|
||||
if ((inp->sctp_socket == 0) &&
|
||||
((tmr->type != SCTP_TIMER_TYPE_INPKILL) &&
|
||||
(tmr->type != SCTP_TIMER_TYPE_INIT) &&
|
||||
(tmr->type != SCTP_TIMER_TYPE_SEND) &&
|
||||
(tmr->type != SCTP_TIMER_TYPE_RECV) &&
|
||||
(tmr->type != SCTP_TIMER_TYPE_HEARTBEAT) &&
|
||||
@ -2984,8 +2985,6 @@ sctp_notify_send_failed(struct sctp_tcb *stcb, uint32_t error,
|
||||
ssf->ssf_info.sinfo_assoc_id = sctp_get_associd(stcb);
|
||||
ssf->ssf_assoc_id = sctp_get_associd(stcb);
|
||||
|
||||
SCTP_BUF_NEXT(m_notify) = chk->data;
|
||||
SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed);
|
||||
if (chk->data) {
|
||||
/*
|
||||
* trim off the sctp chunk header(it should be there)
|
||||
@ -2996,6 +2995,8 @@ sctp_notify_send_failed(struct sctp_tcb *stcb, uint32_t error,
|
||||
chk->send_size -= sizeof(struct sctp_data_chunk);
|
||||
}
|
||||
}
|
||||
SCTP_BUF_NEXT(m_notify) = chk->data;
|
||||
SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed);
|
||||
/* Steal off the mbuf */
|
||||
chk->data = NULL;
|
||||
/*
|
||||
@ -3146,9 +3147,13 @@ sctp_notify_adaptation_layer(struct sctp_tcb *stcb,
|
||||
}
|
||||
|
||||
/* This always must be called with the read-queue LOCKED in the INP */
|
||||
void
|
||||
static void
|
||||
sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb, uint32_t error,
|
||||
int nolock, uint32_t val)
|
||||
uint32_t val, int so_locked
|
||||
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
|
||||
SCTP_UNUSED
|
||||
#endif
|
||||
)
|
||||
{
|
||||
struct mbuf *m_notify;
|
||||
struct sctp_pdapi_event *pdapi;
|
||||
@ -3189,9 +3194,6 @@ sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb, uint32_t error,
|
||||
control->tail_mbuf = m_notify;
|
||||
control->held_length = 0;
|
||||
control->length = 0;
|
||||
if (nolock == 0) {
|
||||
SCTP_INP_READ_LOCK(stcb->sctp_ep);
|
||||
}
|
||||
sb = &stcb->sctp_socket->so_rcv;
|
||||
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
|
||||
sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBALLOC, SCTP_BUF_LEN(m_notify));
|
||||
@ -3208,12 +3210,30 @@ sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb, uint32_t error,
|
||||
/* we really should not see this case */
|
||||
TAILQ_INSERT_TAIL(&stcb->sctp_ep->read_queue, control, next);
|
||||
}
|
||||
if (nolock == 0) {
|
||||
SCTP_INP_READ_UNLOCK(stcb->sctp_ep);
|
||||
}
|
||||
if (stcb->sctp_ep && stcb->sctp_socket) {
|
||||
/* This should always be the case */
|
||||
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
|
||||
struct socket *so;
|
||||
|
||||
so = SCTP_INP_SO(stcb->sctp_ep);
|
||||
if (!so_locked) {
|
||||
atomic_add_int(&stcb->asoc.refcnt, 1);
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
SCTP_SOCKET_LOCK(so, 1);
|
||||
SCTP_TCB_LOCK(stcb);
|
||||
atomic_subtract_int(&stcb->asoc.refcnt, 1);
|
||||
if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
|
||||
SCTP_SOCKET_UNLOCK(so, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
|
||||
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
|
||||
if (!so_locked) {
|
||||
SCTP_SOCKET_UNLOCK(so, 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -3540,9 +3560,9 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
|
||||
|
||||
val = *((uint32_t *) data);
|
||||
|
||||
sctp_notify_partial_delivery_indication(stcb, error, 0, val);
|
||||
sctp_notify_partial_delivery_indication(stcb, error, val, so_locked);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SCTP_NOTIFY_STRDATA_ERR:
|
||||
break;
|
||||
case SCTP_NOTIFY_ASSOC_ABORTED:
|
||||
@ -3585,11 +3605,9 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
|
||||
case SCTP_NOTIFY_STR_RESET_FAILED_OUT:
|
||||
sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), (SCTP_STRRESET_OUTBOUND_STR | SCTP_STRRESET_FAILED));
|
||||
break;
|
||||
|
||||
case SCTP_NOTIFY_STR_RESET_FAILED_IN:
|
||||
sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), (SCTP_STRRESET_INBOUND_STR | SCTP_STRRESET_FAILED));
|
||||
break;
|
||||
|
||||
case SCTP_NOTIFY_ASCONF_ADD_IP:
|
||||
sctp_notify_peer_addr_change(stcb, SCTP_ADDR_ADDED, data,
|
||||
error);
|
||||
@ -3671,8 +3689,10 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, int holds_lock, int so_locked
|
||||
sctp_free_bufspace(stcb, asoc, chk, 1);
|
||||
sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
|
||||
SCTP_NOTIFY_DATAGRAM_SENT, chk, so_locked);
|
||||
sctp_m_freem(chk->data);
|
||||
chk->data = NULL;
|
||||
if (chk->data) {
|
||||
sctp_m_freem(chk->data);
|
||||
chk->data = NULL;
|
||||
}
|
||||
}
|
||||
sctp_free_a_chunk(stcb, chk);
|
||||
/* sa_ignore FREED_MEMORY */
|
||||
@ -3689,8 +3709,10 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, int holds_lock, int so_locked
|
||||
sctp_free_bufspace(stcb, asoc, chk, 1);
|
||||
sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
|
||||
SCTP_NOTIFY_DATAGRAM_UNSENT, chk, so_locked);
|
||||
sctp_m_freem(chk->data);
|
||||
chk->data = NULL;
|
||||
if (chk->data) {
|
||||
sctp_m_freem(chk->data);
|
||||
chk->data = NULL;
|
||||
}
|
||||
}
|
||||
sctp_free_a_chunk(stcb, chk);
|
||||
/* sa_ignore FREED_MEMORY */
|
||||
@ -5346,6 +5368,38 @@ sctp_sorecvmsg(struct socket *so,
|
||||
}
|
||||
goto restart;
|
||||
}
|
||||
if ((control->length == 0) &&
|
||||
(control->end_added == 1)) {
|
||||
/*
|
||||
* Do we also need to check for (control->pdapi_aborted ==
|
||||
* 1)?
|
||||
*/
|
||||
if (hold_rlock == 0) {
|
||||
hold_rlock = 1;
|
||||
SCTP_INP_READ_LOCK(inp);
|
||||
}
|
||||
TAILQ_REMOVE(&inp->read_queue, control, next);
|
||||
if (control->data) {
|
||||
#ifdef INVARIANTS
|
||||
panic("control->data not null but control->length == 0");
|
||||
#else
|
||||
SCTP_PRINTF("Strange, data left in the control buffer. Cleaning up.\n");
|
||||
sctp_m_freem(control->data);
|
||||
control->data = NULL;
|
||||
#endif
|
||||
}
|
||||
if (control->aux_data) {
|
||||
sctp_m_free(control->aux_data);
|
||||
control->aux_data = NULL;
|
||||
}
|
||||
sctp_free_remote_addr(control->whoFrom);
|
||||
sctp_free_a_readq(stcb, control);
|
||||
if (hold_rlock) {
|
||||
hold_rlock = 0;
|
||||
SCTP_INP_READ_UNLOCK(inp);
|
||||
}
|
||||
goto restart;
|
||||
}
|
||||
if (control->length == 0) {
|
||||
if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE)) &&
|
||||
(filling_sinfo)) {
|
||||
|
@ -234,10 +234,6 @@ int sctp_cmpaddr(struct sockaddr *, struct sockaddr *);
|
||||
void sctp_print_address(struct sockaddr *);
|
||||
void sctp_print_address_pkt(struct ip *, struct sctphdr *);
|
||||
|
||||
void
|
||||
sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb,
|
||||
uint32_t error, int no_lock, uint32_t strseq);
|
||||
|
||||
int
|
||||
sctp_release_pr_sctp_chunk(struct sctp_tcb *, struct sctp_tmit_chunk *,
|
||||
int, int
|
||||
|
Loading…
Reference in New Issue
Block a user