diff options
author | tuexen <tuexen@FreeBSD.org> | 2013-09-09 21:40:07 +0000 |
---|---|---|
committer | tuexen <tuexen@FreeBSD.org> | 2013-09-09 21:40:07 +0000 |
commit | 545d815a3b9493ec2dee3f291049b47655c1ec46 (patch) | |
tree | 71300da87495b770e0e18e4bd893a73084493d94 | |
parent | 980d9d1fc0bf3e302c44772111a4c1edeaeb55e6 (diff) | |
download | FreeBSD-src-545d815a3b9493ec2dee3f291049b47655c1ec46.zip FreeBSD-src-545d815a3b9493ec2dee3f291049b47655c1ec46.tar.gz |
Fix the aborting of association with the iterator using an empty
user initiated error cause (using SCTP_ABORT|SCTP_SENDALL).
Approved by: re (delphij)
MFC after: 1 week
-rw-r--r-- | sys/netinet/sctp_output.c | 72 |
1 files changed, 35 insertions, 37 deletions
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 3d76b7e..34edf5b 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -6412,7 +6412,7 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr, /* TSNH */ return; } - if ((ca->m) && ca->sndlen) { + if (ca->sndlen > 0) { m = SCTP_M_COPYM(ca->m, 0, M_COPYALL, M_NOWAIT); if (m == NULL) { /* can't copy so we are done */ @@ -6441,38 +6441,40 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr, } if (ca->sndrcv.sinfo_flags & SCTP_ABORT) { /* Abort this assoc with m as the user defined reason */ - if (m) { + if (m != NULL) { + SCTP_BUF_PREPEND(m, sizeof(struct sctp_paramhdr), M_NOWAIT); + } else { + m = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), + 0, M_NOWAIT, 1, MT_DATA); + SCTP_BUF_LEN(m) = sizeof(struct sctp_paramhdr); + } + if (m != NULL) { struct sctp_paramhdr *ph; - SCTP_BUF_PREPEND(m, sizeof(struct sctp_paramhdr), M_NOWAIT); - if (m) { - ph = mtod(m, struct sctp_paramhdr *); - ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT); - ph->param_length = htons(sizeof(struct sctp_paramhdr) + ca->sndlen); - } - /* - * We add one here to keep the assoc from - * dis-appearing on us. - */ - atomic_add_int(&stcb->asoc.refcnt, 1); - sctp_abort_an_association(inp, stcb, m, SCTP_SO_NOT_LOCKED); - /* - * sctp_abort_an_association calls sctp_free_asoc() - * free association will NOT free it since we - * incremented the refcnt .. we do this to prevent - * it being freed and things getting tricky since we - * could end up (from free_asoc) calling inpcb_free - * which would get a recursive lock call to the - * iterator lock.. But as a consequence of that the - * stcb will return to us un-locked.. since - * free_asoc returns with either no TCB or the TCB - * unlocked, we must relock.. to unlock in the - * iterator timer :-0 - */ - SCTP_TCB_LOCK(stcb); - atomic_add_int(&stcb->asoc.refcnt, -1); - goto no_chunk_output; + ph = mtod(m, struct sctp_paramhdr *); + ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT); + ph->param_length = htons(sizeof(struct sctp_paramhdr) + ca->sndlen); } + /* + * We add one here to keep the assoc from dis-appearing on + * us. + */ + atomic_add_int(&stcb->asoc.refcnt, 1); + sctp_abort_an_association(inp, stcb, m, SCTP_SO_NOT_LOCKED); + /* + * sctp_abort_an_association calls sctp_free_asoc() free + * association will NOT free it since we incremented the + * refcnt .. we do this to prevent it being freed and things + * getting tricky since we could end up (from free_asoc) + * calling inpcb_free which would get a recursive lock call + * to the iterator lock.. But as a consequence of that the + * stcb will return to us un-locked.. since free_asoc + * returns with either no TCB or the TCB unlocked, we must + * relock.. to unlock in the iterator timer :-0 + */ + SCTP_TCB_LOCK(stcb); + atomic_add_int(&stcb->asoc.refcnt, -1); + goto no_chunk_output; } else { if (m) { ret = sctp_msg_append(stcb, net, m, @@ -6566,8 +6568,7 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr, if ((sctp_is_feature_off(inp, SCTP_PCB_FLAGS_NODELAY)) && (stcb->asoc.total_flight > 0) && - (un_sent < (int)(stcb->asoc.smallest_mtu - SCTP_MIN_OVERHEAD)) - ) { + (un_sent < (int)(stcb->asoc.smallest_mtu - SCTP_MIN_OVERHEAD))) { do_chunk_output = 0; } if (do_chunk_output) @@ -6696,13 +6697,10 @@ sctp_sendall(struct sctp_inpcb *inp, struct uio *uio, struct mbuf *m, /* Gather the length of the send */ struct mbuf *mat; - mat = m; ca->sndlen = 0; - while (m) { - ca->sndlen += SCTP_BUF_LEN(m); - m = SCTP_BUF_NEXT(m); + for (mat = m; mat; mat = SCTP_BUF_NEXT(mat)) { + ca->sndlen += SCTP_BUF_LEN(mat); } - ca->m = mat; } ret = sctp_initiate_iterator(NULL, sctp_sendall_iterator, NULL, SCTP_PCB_ANY_FLAGS, SCTP_PCB_ANY_FEATURES, |