diff options
Diffstat (limited to 'freebsd/sys/netinet/sctp_output.c')
-rw-r--r-- | freebsd/sys/netinet/sctp_output.c | 370 |
1 files changed, 210 insertions, 160 deletions
diff --git a/freebsd/sys/netinet/sctp_output.c b/freebsd/sys/netinet/sctp_output.c index b01ec41f..3890ea11 100644 --- a/freebsd/sys/netinet/sctp_output.c +++ b/freebsd/sys/netinet/sctp_output.c @@ -4291,10 +4291,12 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, if (net->port) { mtu -= sizeof(struct udphdr); } - if ((stcb != NULL) && (stcb->asoc.smallest_mtu > mtu)) { - sctp_mtu_size_reset(inp, &stcb->asoc, mtu); + if (mtu < net->mtu) { + if ((stcb != NULL) && (stcb->asoc.smallest_mtu > mtu)) { + sctp_mtu_size_reset(inp, &stcb->asoc, mtu); + } + net->mtu = mtu; } - net->mtu = mtu; } } else if (ro->ro_rt == NULL) { /* route was freed */ @@ -4336,7 +4338,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, * at the SCTP layer. So use the value from * the IP layer. */ - flowlabel = ntohl(((struct in6pcb *)inp)->in6p_flowinfo); + flowlabel = ntohl(((struct inpcb *)inp)->inp_flow); } flowlabel &= 0x000fffff; len = SCTP_MIN_OVERHEAD; @@ -4391,7 +4393,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, * at the SCTP layer. So use the value from * the IP layer. */ - tos_value = (ntohl(((struct in6pcb *)inp)->in6p_flowinfo) >> 20) & 0xff; + tos_value = (ntohl(((struct inpcb *)inp)->inp_flow) >> 20) & 0xff; } tos_value &= 0xfc; if (ecn_ok) { @@ -4649,10 +4651,12 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, if (net->port) { mtu -= sizeof(struct udphdr); } - if ((stcb != NULL) && (stcb->asoc.smallest_mtu > mtu)) { - sctp_mtu_size_reset(inp, &stcb->asoc, mtu); + if (mtu < net->mtu) { + if ((stcb != NULL) && (stcb->asoc.smallest_mtu > mtu)) { + sctp_mtu_size_reset(inp, &stcb->asoc, mtu); + } + net->mtu = mtu; } - net->mtu = mtu; } } else if (ifp) { if (ND_IFINFO(ifp)->linkmtu && @@ -4968,7 +4972,10 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked struct mbuf * sctp_arethere_unrecognized_parameters(struct mbuf *in_initpkt, - int param_offset, int *abort_processing, struct sctp_chunkhdr *cp, int *nat_friendly) + int param_offset, int *abort_processing, + struct sctp_chunkhdr *cp, + int *nat_friendly, + int *cookie_found) { /* * Given a mbuf containing an INIT or INIT-ACK with the param_offset @@ -4986,17 +4993,20 @@ sctp_arethere_unrecognized_parameters(struct mbuf *in_initpkt, */ struct sctp_paramhdr *phdr, params; - struct mbuf *mat, *op_err; + struct mbuf *mat, *m_tmp, *op_err, *op_err_last; int at, limit, pad_needed; uint16_t ptype, plen, padded_size; - int err_at; *abort_processing = 0; + if (cookie_found != NULL) { + *cookie_found = 0; + } mat = in_initpkt; - err_at = 0; limit = ntohs(cp->chunk_length) - sizeof(struct sctp_init_chunk); at = param_offset; op_err = NULL; + op_err_last = NULL; + pad_needed = 0; SCTPDBG(SCTP_DEBUG_OUTPUT1, "Check for unrecognized param's\n"); phdr = sctp_get_next_param(mat, at, ¶ms, sizeof(params)); while ((phdr != NULL) && ((size_t)limit >= sizeof(struct sctp_paramhdr))) { @@ -5019,12 +5029,17 @@ sctp_arethere_unrecognized_parameters(struct mbuf *in_initpkt, switch (ptype) { /* Param's with variable size */ case SCTP_HEARTBEAT_INFO: - case SCTP_STATE_COOKIE: case SCTP_UNRECOG_PARAM: case SCTP_ERROR_CAUSE_IND: /* ok skip fwd */ at += padded_size; break; + case SCTP_STATE_COOKIE: + if (cookie_found != NULL) { + *cookie_found = 1; + } + at += padded_size; + break; /* Param's with variable size within a range */ case SCTP_CHUNK_LIST: case SCTP_SUPPORTED_CHUNK_EXT: @@ -5113,55 +5128,44 @@ sctp_arethere_unrecognized_parameters(struct mbuf *in_initpkt, break; case SCTP_HOSTNAME_ADDRESS: { - /* We can NOT handle HOST NAME addresses!! */ + /* Hostname parameters are deprecated. */ + struct sctp_gen_error_cause *cause; int l_len; SCTPDBG(SCTP_DEBUG_OUTPUT1, "Can't handle hostname addresses.. abort processing\n"); *abort_processing = 1; - if (op_err == NULL) { - /* Ok need to try to get a mbuf */ + sctp_m_freem(op_err); + op_err = NULL; + op_err_last = NULL; #ifdef INET6 - l_len = SCTP_MIN_OVERHEAD; + l_len = SCTP_MIN_OVERHEAD; #else - l_len = SCTP_MIN_V4_OVERHEAD; + l_len = SCTP_MIN_V4_OVERHEAD; #endif - l_len += sizeof(struct sctp_chunkhdr); - l_len += sizeof(struct sctp_gen_error_cause); - op_err = sctp_get_mbuf_for_msg(l_len, 0, M_NOWAIT, 1, MT_DATA); - if (op_err) { - SCTP_BUF_LEN(op_err) = 0; - /* - * Pre-reserve space for IP, - * SCTP, and chunk header. - */ + l_len += sizeof(struct sctp_chunkhdr); + l_len += sizeof(struct sctp_gen_error_cause); + op_err = sctp_get_mbuf_for_msg(l_len, 0, M_NOWAIT, 1, MT_DATA); + if (op_err != NULL) { + /* + * Pre-reserve space for IP, SCTP, + * and chunk header. + */ #ifdef INET6 - SCTP_BUF_RESV_UF(op_err, sizeof(struct ip6_hdr)); + SCTP_BUF_RESV_UF(op_err, sizeof(struct ip6_hdr)); #else - SCTP_BUF_RESV_UF(op_err, sizeof(struct ip)); -#endif - SCTP_BUF_RESV_UF(op_err, sizeof(struct sctphdr)); - SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr)); - } - } - if (op_err) { - /* If we have space */ - struct sctp_gen_error_cause cause; - - if (err_at % 4) { - uint32_t cpthis = 0; - - pad_needed = 4 - (err_at % 4); - m_copyback(op_err, err_at, pad_needed, (caddr_t)&cpthis); - err_at += pad_needed; - } - cause.code = htons(SCTP_CAUSE_UNRESOLVABLE_ADDR); - cause.length = htons((uint16_t)(sizeof(struct sctp_gen_error_cause) + plen)); - m_copyback(op_err, err_at, sizeof(struct sctp_gen_error_cause), (caddr_t)&cause); - err_at += sizeof(struct sctp_gen_error_cause); + SCTP_BUF_RESV_UF(op_err, sizeof(struct ip)); +#endif + SCTP_BUF_RESV_UF(op_err, sizeof(struct sctphdr)); + SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr)); + SCTP_BUF_LEN(op_err) = sizeof(struct sctp_gen_error_cause); + cause = mtod(op_err, struct sctp_gen_error_cause *); + cause->code = htons(SCTP_CAUSE_UNRESOLVABLE_ADDR); + cause->length = htons((uint16_t)(sizeof(struct sctp_gen_error_cause) + plen)); SCTP_BUF_NEXT(op_err) = SCTP_M_COPYM(mat, at, plen, M_NOWAIT); if (SCTP_BUF_NEXT(op_err) == NULL) { sctp_m_freem(op_err); - return (NULL); + op_err = NULL; + op_err_last = NULL; } } return (op_err); @@ -5197,37 +5201,55 @@ sctp_arethere_unrecognized_parameters(struct mbuf *in_initpkt, #endif SCTP_BUF_RESV_UF(op_err, sizeof(struct sctphdr)); SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr)); + op_err_last = op_err; } } - if (op_err) { + if (op_err != NULL) { /* If we have space */ - struct sctp_paramhdr s; - - if (err_at % 4) { - uint32_t cpthis = 0; + struct sctp_paramhdr *param; - pad_needed = 4 - (err_at % 4); - m_copyback(op_err, err_at, pad_needed, (caddr_t)&cpthis); - err_at += pad_needed; + if (pad_needed > 0) { + op_err_last = sctp_add_pad_tombuf(op_err_last, pad_needed); } - s.param_type = htons(SCTP_UNRECOG_PARAM); - s.param_length = htons((uint16_t)sizeof(struct sctp_paramhdr) + plen); - m_copyback(op_err, err_at, sizeof(struct sctp_paramhdr), (caddr_t)&s); - err_at += sizeof(struct sctp_paramhdr); - SCTP_BUF_NEXT(op_err) = SCTP_M_COPYM(mat, at, plen, M_NOWAIT); - if (SCTP_BUF_NEXT(op_err) == NULL) { + if (op_err_last == NULL) { + sctp_m_freem(op_err); + op_err = NULL; + op_err_last = NULL; + goto more_processing; + } + if (M_TRAILINGSPACE(op_err_last) < (int)sizeof(struct sctp_paramhdr)) { + m_tmp = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), 0, M_NOWAIT, 1, MT_DATA); + if (m_tmp == NULL) { + sctp_m_freem(op_err); + op_err = NULL; + op_err_last = NULL; + goto more_processing; + } + SCTP_BUF_LEN(m_tmp) = 0; + SCTP_BUF_NEXT(m_tmp) = NULL; + SCTP_BUF_NEXT(op_err_last) = m_tmp; + op_err_last = m_tmp; + } + param = (struct sctp_paramhdr *)(mtod(op_err_last, caddr_t)+SCTP_BUF_LEN(op_err_last)); + param->param_type = htons(SCTP_UNRECOG_PARAM); + param->param_length = htons((uint16_t)sizeof(struct sctp_paramhdr) + plen); + SCTP_BUF_LEN(op_err_last) += sizeof(struct sctp_paramhdr); + SCTP_BUF_NEXT(op_err_last) = SCTP_M_COPYM(mat, at, plen, M_NOWAIT); + if (SCTP_BUF_NEXT(op_err_last) == NULL) { sctp_m_freem(op_err); - /* - * we are out of memory but - * we still need to have a - * look at what to do (the - * system is in trouble - * though). - */ op_err = NULL; + op_err_last = NULL; goto more_processing; + } else { + while (SCTP_BUF_NEXT(op_err_last) != NULL) { + op_err_last = SCTP_BUF_NEXT(op_err_last); + } + } + if (plen % 4 != 0) { + pad_needed = 4 - (plen % 4); + } else { + pad_needed = 0; } - err_at += plen; } } more_processing: @@ -5248,7 +5270,11 @@ sctp_arethere_unrecognized_parameters(struct mbuf *in_initpkt, invalid_size: SCTPDBG(SCTP_DEBUG_OUTPUT1, "abort flag set\n"); *abort_processing = 1; - if ((op_err == NULL) && phdr) { + sctp_m_freem(op_err); + op_err = NULL; + op_err_last = NULL; + if (phdr != NULL) { + struct sctp_paramhdr *param; int l_len; #ifdef INET6 l_len = SCTP_MIN_OVERHEAD; @@ -5267,25 +5293,15 @@ invalid_size: #endif SCTP_BUF_RESV_UF(op_err, sizeof(struct sctphdr)); SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr)); + SCTP_BUF_LEN(op_err) = 2 * sizeof(struct sctp_paramhdr); + param = mtod(op_err, struct sctp_paramhdr *); + param->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION); + param->param_length = htons(2 * sizeof(struct sctp_paramhdr)); + param++; + param->param_type = htons(ptype); + param->param_length = htons(plen); } } - if ((op_err) && phdr) { - struct sctp_paramhdr s; - - if (err_at % 4) { - uint32_t cpthis = 0; - - pad_needed = 4 - (err_at % 4); - m_copyback(op_err, err_at, pad_needed, (caddr_t)&cpthis); - err_at += pad_needed; - } - s.param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION); - s.param_length = htons(sizeof(s) + sizeof(struct sctp_paramhdr)); - m_copyback(op_err, err_at, sizeof(s), (caddr_t)&s); - err_at += sizeof(s); - /* Only copy back the p-hdr that caused the issue */ - m_copyback(op_err, err_at, sizeof(struct sctp_paramhdr), (caddr_t)phdr); - } return (op_err); } @@ -5565,7 +5581,9 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, abort_flag = 0; op_err = sctp_arethere_unrecognized_parameters(init_pkt, (offset + sizeof(struct sctp_init_chunk)), - &abort_flag, (struct sctp_chunkhdr *)init_chk, &nat_friendly); + &abort_flag, + (struct sctp_chunkhdr *)init_chk, + &nat_friendly, NULL); if (abort_flag) { do_a_abort: if (op_err == NULL) { @@ -5584,8 +5602,7 @@ do_a_abort: m = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA); if (m == NULL) { /* No memory, INIT timer will re-attempt. */ - if (op_err) - sctp_m_freem(op_err); + sctp_m_freem(op_err); return; } chunk_len = (uint16_t)sizeof(struct sctp_init_ack_chunk); @@ -5774,8 +5791,11 @@ do_a_abort: net->ro._s_addr = sctp_source_address_selection(inp, stcb, (sctp_route_t *)&net->ro, net, 0, vrf_id); - if (net->ro._s_addr == NULL) + if (net->ro._s_addr == NULL) { + sctp_m_freem(op_err); + sctp_m_freem(m); return; + } net->src_addr_selected = 1; @@ -5804,8 +5824,11 @@ do_a_abort: net->ro._s_addr = sctp_source_address_selection(inp, stcb, (sctp_route_t *)&net->ro, net, 0, vrf_id); - if (net->ro._s_addr == NULL) + if (net->ro._s_addr == NULL) { + sctp_m_freem(op_err); + sctp_m_freem(m); return; + } net->src_addr_selected = 1; } @@ -5876,6 +5899,7 @@ do_a_abort: so = inp->sctp_socket; if (so == NULL) { /* memory problem */ + sctp_m_freem(op_err); sctp_m_freem(m); return; } else { @@ -6802,15 +6826,19 @@ sctp_sendall_completes(void *ptr, uint32_t val SCTP_UNUSED) */ /* now free everything */ + if (ca->inp) { + /* Lets clear the flag to allow others to run. */ + ca->inp->sctp_flags &= ~SCTP_PCB_FLAGS_SND_ITERATOR_UP; + } sctp_m_freem(ca->m); SCTP_FREE(ca, SCTP_M_COPYAL); } static struct mbuf * -sctp_copy_out_all(struct uio *uio, int len) +sctp_copy_out_all(struct uio *uio, ssize_t len) { struct mbuf *ret, *at; - int left, willcpy, cancpy, error; + ssize_t left, willcpy, cancpy, error; ret = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_WAITOK, 1, MT_DATA); if (ret == NULL) { @@ -6825,17 +6853,17 @@ sctp_copy_out_all(struct uio *uio, int len) at = ret; while (left > 0) { /* Align data to the end */ - error = uiomove(mtod(at, caddr_t), willcpy, uio); + error = uiomove(mtod(at, caddr_t), (int)willcpy, uio); if (error) { err_out_now: sctp_m_freem(at); return (NULL); } - SCTP_BUF_LEN(at) = willcpy; + SCTP_BUF_LEN(at) = (int)willcpy; SCTP_BUF_NEXT_PKT(at) = SCTP_BUF_NEXT(at) = 0; left -= willcpy; if (left > 0) { - SCTP_BUF_NEXT(at) = sctp_get_mbuf_for_msg(left, 0, M_WAITOK, 1, MT_DATA); + SCTP_BUF_NEXT(at) = sctp_get_mbuf_for_msg((unsigned int)left, 0, M_WAITOK, 1, MT_DATA); if (SCTP_BUF_NEXT(at) == NULL) { goto err_out_now; } @@ -6855,6 +6883,14 @@ sctp_sendall(struct sctp_inpcb *inp, struct uio *uio, struct mbuf *m, int ret; struct sctp_copy_all *ca; + if (inp->sctp_flags & SCTP_PCB_FLAGS_SND_ITERATOR_UP) { + /* There is another. */ + return (EBUSY); + } + if (uio->uio_resid > SCTP_MAX_SENDALL_LIMIT) { + /* You must be less than the max! */ + return (EMSGSIZE); + } SCTP_MALLOC(ca, struct sctp_copy_all *, sizeof(struct sctp_copy_all), SCTP_M_COPYAL); if (ca == NULL) { @@ -6875,7 +6911,7 @@ sctp_sendall(struct sctp_inpcb *inp, struct uio *uio, struct mbuf *m, ca->sndrcv.sinfo_flags &= ~SCTP_SENDALL; /* get length and mbuf chain */ if (uio) { - ca->sndlen = (int)uio->uio_resid; + ca->sndlen = uio->uio_resid; ca->m = sctp_copy_out_all(uio, ca->sndlen); if (ca->m == NULL) { SCTP_FREE(ca, SCTP_M_COPYAL); @@ -6891,6 +6927,7 @@ sctp_sendall(struct sctp_inpcb *inp, struct uio *uio, struct mbuf *m, ca->sndlen += SCTP_BUF_LEN(mat); } } + inp->sctp_flags |= SCTP_PCB_FLAGS_SND_ITERATOR_UP; ret = sctp_initiate_iterator(NULL, sctp_sendall_iterator, NULL, SCTP_PCB_ANY_FLAGS, SCTP_PCB_ANY_FEATURES, SCTP_ASOC_ANY_STATE, @@ -8979,7 +9016,7 @@ sctp_queue_op_err(struct sctp_tcb *stcb, struct mbuf *op_err) int sctp_send_cookie_echo(struct mbuf *m, - int offset, + int offset, int limit, struct sctp_tcb *stcb, struct sctp_nets *net) { @@ -9005,18 +9042,30 @@ sctp_send_cookie_echo(struct mbuf *m, } ptype = ntohs(phdr->param_type); plen = ntohs(phdr->param_length); + if (plen < sizeof(struct sctp_paramhdr)) { + return (-6); + } if (ptype == SCTP_STATE_COOKIE) { int pad; /* found the cookie */ - if ((pad = (plen % 4))) { - plen += 4 - pad; + if (at + plen > limit) { + return (-7); } cookie = SCTP_M_COPYM(m, at, plen, M_NOWAIT); if (cookie == NULL) { /* No memory */ return (-2); } + if ((pad = (plen % 4)) > 0) { + pad = 4 - pad; + } + if (pad > 0) { + cookie = sctp_pad_lastmbuf(cookie, pad, NULL); + if (cookie == NULL) { + return (-8); + } + } #ifdef SCTP_MBUF_LOGGING if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { sctp_log_mbc(cookie, SCTP_MBUF_ICOPY); @@ -9042,7 +9091,7 @@ sctp_send_cookie_echo(struct mbuf *m, chk->rec.chunk_id.id = SCTP_COOKIE_ECHO; chk->rec.chunk_id.can_take_data = 0; chk->flags = CHUNK_FLAGS_FRAGMENT_OK; - chk->send_size = plen; + chk->send_size = SCTP_SIZE32(plen); chk->sent = SCTP_DATAGRAM_UNSENT; chk->snd_count = 0; chk->asoc = &stcb->asoc; @@ -9068,7 +9117,6 @@ sctp_send_heartbeat_ack(struct sctp_tcb *stcb, struct sctp_chunkhdr *chdr; struct sctp_tmit_chunk *chk; - if (net == NULL) /* must have a net pointer */ return; @@ -9086,13 +9134,8 @@ sctp_send_heartbeat_ack(struct sctp_tcb *stcb, chdr = mtod(outchain, struct sctp_chunkhdr *); chdr->chunk_type = SCTP_HEARTBEAT_ACK; chdr->chunk_flags = 0; - if (chk_length % 4) { - /* need pad */ - uint32_t cpthis = 0; - int padlen; - - padlen = 4 - (chk_length % 4); - m_copyback(outchain, chk_length, padlen, (caddr_t)&cpthis); + if (chk_length % 4 != 0) { + sctp_pad_lastmbuf(outchain, 4 - (chk_length % 4), NULL); } sctp_alloc_a_chunk(stcb, chk); if (chk == NULL) { @@ -12372,7 +12415,7 @@ sctp_copy_it_in(struct sctp_tcb *stcb, struct sctp_sndrcvinfo *srcv, struct uio *uio, struct sctp_nets *net, - int max_send_len, + ssize_t max_send_len, int user_marks_eor, int *error) { @@ -12518,7 +12561,7 @@ sctp_lower_sosend(struct socket *so, struct thread *p ) { - unsigned int sndlen = 0, max_len; + ssize_t sndlen = 0, max_len, local_add_more; int error, len; struct mbuf *top = NULL; int queue_only = 0, queue_only_for_init = 0; @@ -12540,7 +12583,7 @@ sctp_lower_sosend(struct socket *so, int got_all_of_the_send = 0; int hold_tcblock = 0; int non_blocking = 0; - uint32_t local_add_more, local_soresv = 0; + ssize_t local_soresv = 0; uint16_t port; uint16_t sinfo_flags; sctp_assoc_t sinfo_assoc_id; @@ -12570,12 +12613,12 @@ sctp_lower_sosend(struct socket *so, SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); return (EINVAL); } - sndlen = (unsigned int)uio->uio_resid; + sndlen = uio->uio_resid; } else { top = SCTP_HEADER_TO_CHAIN(i_pak); sndlen = SCTP_HEADER_LEN(i_pak); } - SCTPDBG(SCTP_DEBUG_OUTPUT1, "Send called addr:%p send length %d\n", + SCTPDBG(SCTP_DEBUG_OUTPUT1, "Send called addr:%p send length %zu\n", (void *)addr, sndlen); if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && @@ -12636,6 +12679,12 @@ sctp_lower_sosend(struct socket *so, sinfo_flags = inp->def_send.sinfo_flags; sinfo_assoc_id = inp->def_send.sinfo_assoc_id; } + if (flags & MSG_EOR) { + sinfo_flags |= SCTP_EOR; + } + if (flags & MSG_EOF) { + sinfo_flags |= SCTP_EOF; + } if (sinfo_flags & SCTP_SENDALL) { /* its a sendall */ error = sctp_sendall(inp, uio, top, srcv); @@ -12753,7 +12802,8 @@ sctp_lower_sosend(struct socket *so, stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, inp->sctp_ep.pre_open_stream_count, inp->sctp_ep.port, - p); + p, + SCTP_INITIALIZE_AUTH_PARAMS); if (stcb == NULL) { /* Error is setup for us in the call */ goto out_unlocked; @@ -12782,9 +12832,6 @@ sctp_lower_sosend(struct socket *so, SCTP_SET_STATE(stcb, SCTP_STATE_COOKIE_WAIT); (void)SCTP_GETTIME_TIMEVAL(&asoc->time_entered); - /* initialize authentication params for the assoc */ - sctp_initialize_auth_params(inp, stcb); - if (control) { if (sctp_process_cmsgs_for_init(stcb, control, &error)) { sctp_free_assoc(inp, stcb, SCTP_PCBFREE_FORCE, @@ -12805,9 +12852,17 @@ sctp_lower_sosend(struct socket *so, } } else asoc = &stcb->asoc; - if (srcv == NULL) + if (srcv == NULL) { srcv = (struct sctp_sndrcvinfo *)&asoc->def_send; - if (srcv->sinfo_flags & SCTP_ADDR_OVER) { + sinfo_flags = srcv->sinfo_flags; + if (flags & MSG_EOR) { + sinfo_flags |= SCTP_EOR; + } + if (flags & MSG_EOF) { + sinfo_flags |= SCTP_EOF; + } + } + if (sinfo_flags & SCTP_ADDR_OVER) { if (addr) net = sctp_findnet(stcb, addr); else @@ -12831,20 +12886,20 @@ sctp_lower_sosend(struct socket *so, free_cnt_applied = 1; if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NO_FRAGMENT)) { - if (sndlen > asoc->smallest_mtu) { + if (sndlen > (ssize_t)asoc->smallest_mtu) { SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EMSGSIZE); error = EMSGSIZE; goto out_unlocked; } } if (SCTP_SO_IS_NBIO(so) - || (flags & MSG_NBIO) + || (flags & (MSG_NBIO | MSG_DONTWAIT)) != 0 ) { non_blocking = 1; } /* would we block? */ if (non_blocking) { - uint32_t amount; + ssize_t amount; if (hold_tcblock == 0) { SCTP_TCB_LOCK(stcb); @@ -12859,13 +12914,13 @@ sctp_lower_sosend(struct socket *so, if ((SCTP_SB_LIMIT_SND(so) < (amount + inqueue_bytes + stcb->asoc.sb_send_resv)) || (stcb->asoc.chunks_on_out_queue >= SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue))) { SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EWOULDBLOCK); - if (sndlen > SCTP_SB_LIMIT_SND(so)) + if (sndlen > (ssize_t)SCTP_SB_LIMIT_SND(so)) error = EMSGSIZE; else error = EWOULDBLOCK; goto out_unlocked; } - stcb->asoc.sb_send_resv += sndlen; + stcb->asoc.sb_send_resv += (uint32_t)sndlen; SCTP_TCB_UNLOCK(stcb); hold_tcblock = 0; } else { @@ -12914,7 +12969,7 @@ sctp_lower_sosend(struct socket *so, (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED) || (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_ACK_SENT) || (asoc->state & SCTP_STATE_SHUTDOWN_PENDING)) { - if (srcv->sinfo_flags & SCTP_ABORT) { + if (sinfo_flags & SCTP_ABORT) { ; } else { SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ECONNRESET); @@ -12929,9 +12984,9 @@ sctp_lower_sosend(struct socket *so, } #endif /* __rtems__ */ /* Are we aborting? */ - if (srcv->sinfo_flags & SCTP_ABORT) { + if (sinfo_flags & SCTP_ABORT) { struct mbuf *mm; - int tot_demand, tot_out = 0, max_out; + ssize_t tot_demand, tot_out = 0, max_out; SCTP_STAT_INCR(sctps_sends_with_abort); if ((SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_WAIT) || @@ -12965,7 +13020,7 @@ sctp_lower_sosend(struct socket *so, error = EMSGSIZE; goto out; } - mm = sctp_get_mbuf_for_msg(tot_demand, 0, M_WAITOK, 1, MT_DATA); + mm = sctp_get_mbuf_for_msg((unsigned int)tot_demand, 0, M_WAITOK, 1, MT_DATA); } if (mm == NULL) { SCTP_LTRACE_ERR_RET(NULL, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOMEM); @@ -12985,7 +13040,7 @@ sctp_lower_sosend(struct socket *so, ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT); ph->param_length = htons((uint16_t)(sizeof(struct sctp_paramhdr) + tot_out)); ph++; - SCTP_BUF_LEN(mm) = tot_out + sizeof(struct sctp_paramhdr); + SCTP_BUF_LEN(mm) = (int)(tot_out + sizeof(struct sctp_paramhdr)); if (top == NULL) { error = uiomove((caddr_t)ph, (int)tot_out, uio); if (error) { @@ -13026,12 +13081,7 @@ sctp_lower_sosend(struct socket *so, /* Calculate the maximum we can send */ inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb)); if (SCTP_SB_LIMIT_SND(so) > inqueue_bytes) { - if (non_blocking) { - /* we already checked for non-blocking above. */ - max_len = sndlen; - } else { - max_len = SCTP_SB_LIMIT_SND(so) - inqueue_bytes; - } + max_len = SCTP_SB_LIMIT_SND(so) - inqueue_bytes; } else { max_len = 0; } @@ -13048,7 +13098,7 @@ sctp_lower_sosend(struct socket *so, /* Unless E_EOR mode is on, we must make a send FIT in one call. */ if ((user_marks_eor == 0) && - (sndlen > SCTP_SB_LIMIT_SND(stcb->sctp_socket))) { + (sndlen > (ssize_t)SCTP_SB_LIMIT_SND(stcb->sctp_socket))) { /* It will NEVER fit */ SCTP_LTRACE_ERR_RET(NULL, stcb, net, SCTP_FROM_SCTP_OUTPUT, EMSGSIZE); error = EMSGSIZE; @@ -13065,7 +13115,7 @@ sctp_lower_sosend(struct socket *so, } if (user_marks_eor) { - local_add_more = min(SCTP_SB_LIMIT_SND(so), SCTP_BASE_SYSCTL(sctp_add_more_threshold)); + local_add_more = (ssize_t)min(SCTP_SB_LIMIT_SND(so), SCTP_BASE_SYSCTL(sctp_add_more_threshold)); } else { /*- * For non-eeor the whole message must fit in @@ -13078,7 +13128,7 @@ sctp_lower_sosend(struct socket *so, goto skip_preblock; } if (((max_len <= local_add_more) && - (SCTP_SB_LIMIT_SND(so) >= local_add_more)) || + ((ssize_t)SCTP_SB_LIMIT_SND(so) >= local_add_more)) || (max_len == 0) || ((stcb->asoc.chunks_on_out_queue + stcb->asoc.stream_queue_cnt) >= SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue))) { /* No room right now ! */ @@ -13086,7 +13136,7 @@ sctp_lower_sosend(struct socket *so, inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb)); while ((SCTP_SB_LIMIT_SND(so) < (inqueue_bytes + local_add_more)) || ((stcb->asoc.stream_queue_cnt + stcb->asoc.chunks_on_out_queue) >= SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue))) { - SCTPDBG(SCTP_DEBUG_OUTPUT1, "pre_block limit:%u <(inq:%d + %d) || (%d+%d > %d)\n", + SCTPDBG(SCTP_DEBUG_OUTPUT1, "pre_block limit:%u <(inq:%d + %zd) || (%d+%d > %d)\n", (unsigned int)SCTP_SB_LIMIT_SND(so), inqueue_bytes, local_add_more, @@ -13138,7 +13188,7 @@ skip_preblock: * case NOTE: uio will be null when top/mbuf is passed */ if (sndlen == 0) { - if (srcv->sinfo_flags & SCTP_EOF) { + if (sinfo_flags & SCTP_EOF) { got_all_of_the_send = 1; goto dataless_eof; } else { @@ -13187,7 +13237,7 @@ skip_preblock: } sctp_snd_sb_alloc(stcb, sp->length); atomic_add_int(&asoc->stream_queue_cnt, 1); - if (srcv->sinfo_flags & SCTP_UNORDERED) { + if (sinfo_flags & SCTP_UNORDERED) { SCTP_STAT_INCR(sctps_sends_with_unord); } TAILQ_INSERT_TAIL(&strm->outqueue, sp, next); @@ -13219,16 +13269,16 @@ skip_preblock: else max_len = 0; - if ((max_len > SCTP_BASE_SYSCTL(sctp_add_more_threshold)) || + if ((max_len > (ssize_t)SCTP_BASE_SYSCTL(sctp_add_more_threshold)) || (max_len && (SCTP_SB_LIMIT_SND(so) < SCTP_BASE_SYSCTL(sctp_add_more_threshold))) || - (uio->uio_resid && (uio->uio_resid <= (int)max_len))) { + (uio->uio_resid && (uio->uio_resid <= max_len))) { sndout = 0; new_tail = NULL; if (hold_tcblock) { SCTP_TCB_UNLOCK(stcb); hold_tcblock = 0; } - mm = sctp_copy_resume(uio, max_len, user_marks_eor, &error, &sndout, &new_tail); + mm = sctp_copy_resume(uio, (int)max_len, user_marks_eor, &error, &sndout, &new_tail); if ((mm == NULL) || error) { if (mm) { sctp_m_freem(mm); @@ -13262,15 +13312,15 @@ skip_preblock: sctp_snd_sb_alloc(stcb, sndout); atomic_add_int(&sp->length, sndout); len += sndout; - if (srcv->sinfo_flags & SCTP_SACK_IMMEDIATELY) { + if (sinfo_flags & SCTP_SACK_IMMEDIATELY) { sp->sinfo_flags |= SCTP_SACK_IMMEDIATELY; } /* Did we reach EOR? */ if ((uio->uio_resid == 0) && ((user_marks_eor == 0) || - (srcv->sinfo_flags & SCTP_EOF) || - (user_marks_eor && (srcv->sinfo_flags & SCTP_EOR)))) { + (sinfo_flags & SCTP_EOF) || + (user_marks_eor && (sinfo_flags & SCTP_EOR)))) { sp->msg_is_complete = 1; } else { sp->msg_is_complete = 0; @@ -13291,7 +13341,7 @@ skip_preblock: SCTP_TCB_LOCK(stcb); hold_tcblock = 1; } - sctp_prune_prsctp(stcb, asoc, srcv, sndlen); + sctp_prune_prsctp(stcb, asoc, srcv, (int)sndlen); inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb)); if (SCTP_SB_LIMIT_SND(so) > inqueue_bytes) max_len = SCTP_SB_LIMIT_SND(so) - inqueue_bytes; @@ -13388,10 +13438,10 @@ skip_preblock: stcb, SCTP_OUTPUT_FROM_USR_SEND, SCTP_SO_LOCKED); } - if (hold_tcblock == 1) { - SCTP_TCB_UNLOCK(stcb); - hold_tcblock = 0; - } + } + if (hold_tcblock == 1) { + SCTP_TCB_UNLOCK(stcb); + hold_tcblock = 0; } SOCKBUF_LOCK(&so->so_snd); /*- @@ -13413,7 +13463,7 @@ skip_preblock: min(SCTP_BASE_SYSCTL(sctp_add_more_threshold), SCTP_SB_LIMIT_SND(so)))) { if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_BLK_LOGGING_ENABLE) { sctp_log_block(SCTP_BLOCK_LOG_INTO_BLK, - asoc, (size_t)uio->uio_resid); + asoc, uio->uio_resid); } be.error = 0; stcb->block_entry = &be; @@ -13472,7 +13522,7 @@ skip_preblock: /* We send in a 0, since we do NOT have any locks */ error = sctp_msg_append(stcb, net, top, srcv, 0); top = NULL; - if (srcv->sinfo_flags & SCTP_EOF) { + if (sinfo_flags & SCTP_EOF) { /* * This should only happen for Panda for the mbuf * send case, which does NOT yet support EEOR mode. @@ -13487,7 +13537,7 @@ skip_preblock: } dataless_eof: /* EOF thing ? */ - if ((srcv->sinfo_flags & SCTP_EOF) && + if ((sinfo_flags & SCTP_EOF) && (got_all_of_the_send == 1)) { SCTP_STAT_INCR(sctps_sends_with_eof); error = 0; |