summaryrefslogtreecommitdiffstats
path: root/sys/netinet/sctp_output.c
diff options
context:
space:
mode:
authortuexen <tuexen@FreeBSD.org>2013-09-09 21:40:07 +0000
committertuexen <tuexen@FreeBSD.org>2013-09-09 21:40:07 +0000
commit545d815a3b9493ec2dee3f291049b47655c1ec46 (patch)
tree71300da87495b770e0e18e4bd893a73084493d94 /sys/netinet/sctp_output.c
parent980d9d1fc0bf3e302c44772111a4c1edeaeb55e6 (diff)
downloadFreeBSD-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
Diffstat (limited to 'sys/netinet/sctp_output.c')
-rw-r--r--sys/netinet/sctp_output.c72
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,
OpenPOWER on IntegriCloud