diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index 3165dab5c550..06869b21d283 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -2381,7 +2381,6 @@ sctp_generic_sendmsg (td, uap) struct sctp_sndrcvinfo sinfo, *u_sinfo = NULL; struct socket *so; struct file *fp = NULL; - int use_rcvinfo = 1; int error = 0, len; struct sockaddr *to = NULL; #ifdef KTRACE @@ -2434,7 +2433,7 @@ sctp_generic_sendmsg (td, uap) CURVNET_SET(so->so_vnet); error = sctp_lower_sosend(so, to, &auio, (struct mbuf *)NULL, (struct mbuf *)NULL, - uap->flags, use_rcvinfo, u_sinfo, td); + uap->flags, u_sinfo, td); CURVNET_RESTORE(); if (error) { if (auio.uio_resid != len && (error == ERESTART || @@ -2485,7 +2484,6 @@ sctp_generic_sendmsg_iov(td, uap) struct sctp_sndrcvinfo sinfo, *u_sinfo = NULL; struct socket *so; struct file *fp = NULL; - int use_rcvinfo = 1; int error=0, len, i; struct sockaddr *to = NULL; #ifdef KTRACE @@ -2552,7 +2550,7 @@ sctp_generic_sendmsg_iov(td, uap) CURVNET_SET(so->so_vnet); error = sctp_lower_sosend(so, to, &auio, (struct mbuf *)NULL, (struct mbuf *)NULL, - uap->flags, use_rcvinfo, u_sinfo, td); + uap->flags, u_sinfo, td); CURVNET_RESTORE(); if (error) { if (auio.uio_resid != len && (error == ERESTART || diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 87b914375d3d..38ad9d972582 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -12158,7 +12158,7 @@ sctp_sosend(struct socket *so, error = sctp_lower_sosend(so, addr_to_use, uio, top, control, flags, - use_rcvinfo, &srcv + use_rcvinfo ? &srcv : NULL ,p ); return (error); @@ -12172,7 +12172,6 @@ sctp_lower_sosend(struct socket *so, struct mbuf *i_pak, struct mbuf *control, int flags, - int use_rcvinfo, struct sctp_sndrcvinfo *srcv , struct thread *p @@ -12200,8 +12199,10 @@ sctp_lower_sosend(struct socket *so, int got_all_of_the_send = 0; int hold_tcblock = 0; int non_blocking = 0; - int temp_flags = 0; uint32_t local_add_more, local_soresv = 0; + uint16_t port; + uint16_t sinfo_flags; + sctp_assoc_t sinfo_assoc_id; error = 0; net = NULL; @@ -12236,38 +12237,6 @@ sctp_lower_sosend(struct socket *so, SCTPDBG(SCTP_DEBUG_OUTPUT1, "Send called addr:%p send length %d\n", addr, sndlen); - /** - * Pre-screen address, if one is given the sin-len - * must be set correctly! - */ - if (addr) { - switch (addr->sa_family) { -#if defined(INET) - case AF_INET: - if (addr->sa_len != sizeof(struct sockaddr_in)) { - SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); - error = EINVAL; - goto out_unlocked; - } - break; -#endif -#if defined(INET6) - case AF_INET6: - if (addr->sa_len != sizeof(struct sockaddr_in6)) { - SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); - error = EINVAL; - goto out_unlocked; - } - break; -#endif - default: - SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EAFNOSUPPORT); - error = EAFNOSUPPORT; - goto out_unlocked; - } - } - hold_tcblock = 0; - if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && (inp->sctp_socket->so_qlimit)) { /* The listener can NOT send */ @@ -12275,22 +12244,67 @@ sctp_lower_sosend(struct socket *so, error = ENOTCONN; goto out_unlocked; } - if ((use_rcvinfo) && srcv) { - if (INVALID_SINFO_FLAG(srcv->sinfo_flags) || - PR_SCTP_INVALID_POLICY(srcv->sinfo_flags)) { + /** + * Pre-screen address, if one is given the sin-len + * must be set correctly! + */ + if (addr) { + union sctp_sockstore *raddr = (union sctp_sockstore *)addr; + + switch (raddr->sa.sa_family) { +#if defined(INET) + case AF_INET: + if (raddr->sin.sin_len != sizeof(struct sockaddr_in)) { + SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); + error = EINVAL; + goto out_unlocked; + } + port = raddr->sin.sin_port; + break; +#endif +#if defined(INET6) + case AF_INET6: + if (raddr->sin6.sin6_len != sizeof(struct sockaddr_in6)) { + SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); + error = EINVAL; + goto out_unlocked; + } + port = raddr->sin6.sin6_port; + break; +#endif + default: + SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EAFNOSUPPORT); + error = EAFNOSUPPORT; + goto out_unlocked; + } + } else + port = 0; + + if (srcv) { + sinfo_flags = srcv->sinfo_flags; + sinfo_assoc_id = srcv->sinfo_assoc_id; + if (INVALID_SINFO_FLAG(sinfo_flags) || + PR_SCTP_INVALID_POLICY(sinfo_flags)) { SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); error = EINVAL; goto out_unlocked; } if (srcv->sinfo_flags) SCTP_STAT_INCR(sctps_sends_with_flags); - - if (srcv->sinfo_flags & SCTP_SENDALL) { - /* its a sendall */ - error = sctp_sendall(inp, uio, top, srcv); - top = NULL; - goto out_unlocked; - } + } else { + sinfo_flags = inp->def_send.sinfo_flags; + sinfo_assoc_id = inp->def_send.sinfo_assoc_id; + } + if (sinfo_flags & SCTP_SENDALL) { + /* its a sendall */ + error = sctp_sendall(inp, uio, top, srcv); + top = NULL; + goto out_unlocked; + } + if ((sinfo_flags & SCTP_ADDR_OVER) && (addr == NULL)) { + SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); + error = EINVAL; + goto out_unlocked; } /* now we must find the assoc */ if ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) || @@ -12306,80 +12320,8 @@ sctp_lower_sosend(struct socket *so, SCTP_TCB_LOCK(stcb); hold_tcblock = 1; SCTP_INP_RUNLOCK(inp); - if (addr) { - /* Must locate the net structure if addr given */ - net = sctp_findnet(stcb, addr); - if (net) { - /* validate port was 0 or correct */ - struct sockaddr_in *sin; - - sin = (struct sockaddr_in *)addr; - if ((sin->sin_port != 0) && - (sin->sin_port != stcb->rport)) { - net = NULL; - } - } - temp_flags |= SCTP_ADDR_OVER; - } else - net = stcb->asoc.primary_destination; - if (addr && (net == NULL)) { - /* Could not find address, was it legal */ - if (addr->sa_family == AF_INET) { - struct sockaddr_in *sin; - - sin = (struct sockaddr_in *)addr; - if (sin->sin_addr.s_addr == 0) { - if ((sin->sin_port == 0) || - (sin->sin_port == stcb->rport)) { - net = stcb->asoc.primary_destination; - } - } - } else { - struct sockaddr_in6 *sin6; - - sin6 = (struct sockaddr_in6 *)addr; - if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { - if ((sin6->sin6_port == 0) || - (sin6->sin6_port == stcb->rport)) { - net = stcb->asoc.primary_destination; - } - } - } - } - if (net == NULL) { - SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); - error = EINVAL; - goto out_unlocked; - } - } else if (use_rcvinfo && srcv && srcv->sinfo_assoc_id) { - stcb = sctp_findassociation_ep_asocid(inp, srcv->sinfo_assoc_id, 0); - if (stcb) { - if (addr) - /* - * Must locate the net structure if addr - * given - */ - net = sctp_findnet(stcb, addr); - else - net = stcb->asoc.primary_destination; - if ((srcv->sinfo_flags & SCTP_ADDR_OVER) && - ((net == NULL) || (addr == NULL))) { - struct sockaddr_in *sin; - - if (addr == NULL) { - SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); - error = EINVAL; - goto out_unlocked; - } - sin = (struct sockaddr_in *)addr; - /* Validate port is 0 or correct */ - if ((sin->sin_port != 0) && - (sin->sin_port != stcb->rport)) { - net = NULL; - } - } - } - hold_tcblock = 0; + } else if (sinfo_assoc_id) { + stcb = sctp_findassociation_ep_asocid(inp, sinfo_assoc_id, 0); } else if (addr) { /*- * Since we did not use findep we must @@ -12452,10 +12394,8 @@ sctp_lower_sosend(struct socket *so, */ uint32_t vrf_id; - if ((use_rcvinfo) && (srcv) && - ((srcv->sinfo_flags & SCTP_ABORT) || - ((srcv->sinfo_flags & SCTP_EOF) && - (sndlen == 0)))) { + if ((sinfo_flags & SCTP_ABORT) || + ((sinfo_flags & SCTP_EOF) && (sndlen == 0))) { /*- * User asks to abort a non-existant assoc, * or EOF a non-existant assoc with no data @@ -12584,10 +12524,25 @@ sctp_lower_sosend(struct socket *so, * structure may now have an update and thus we may need to * change it BEFORE we append the message. */ - net = stcb->asoc.primary_destination; - asoc = &stcb->asoc; } } + if (srcv == NULL) + srcv = (struct sctp_sndrcvinfo *)&stcb->asoc.def_send; + if (srcv->sinfo_flags & SCTP_ADDR_OVER) { + if (addr) + net = sctp_findnet(stcb, addr); + else + net = NULL; + if ((net == NULL) || + ((port != 0) && (port != stcb->rport))) { + SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); + error = EINVAL; + goto out_unlocked; + } + } else { + net = stcb->asoc.primary_destination; + } + if ((SCTP_SO_IS_NBIO(so) || (flags & MSG_NBIO) )) { @@ -12658,10 +12613,6 @@ sctp_lower_sosend(struct socket *so, (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)) { queue_only = 1; } - if ((use_rcvinfo == 0) || (srcv == NULL)) { - /* Grab the default stuff from the asoc */ - srcv = (struct sctp_sndrcvinfo *)&stcb->asoc.def_send; - } /* we are now done with all control */ if (control) { sctp_m_freem(control); @@ -12671,8 +12622,7 @@ sctp_lower_sosend(struct socket *so, (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED) || (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) || (asoc->state & SCTP_STATE_SHUTDOWN_PENDING)) { - if ((use_rcvinfo) && - (srcv->sinfo_flags & SCTP_ABORT)) { + if (srcv->sinfo_flags & SCTP_ABORT) { ; } else { SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ECONNRESET); @@ -12684,16 +12634,6 @@ sctp_lower_sosend(struct socket *so, if (p) { p->td_ru.ru_msgsnd++; } - if (stcb) { - if (((srcv->sinfo_flags | temp_flags) & SCTP_ADDR_OVER) == 0) { - net = stcb->asoc.primary_destination; - } - } - if (net == NULL) { - SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); - error = EINVAL; - goto out_unlocked; - } if ((net->flight_size > net->cwnd) && (asoc->sctp_cmt_on_off == 0)) { /*- diff --git a/sys/netinet/sctp_uio.h b/sys/netinet/sctp_uio.h index e3fbc3e6d505..1cd54654ca6b 100644 --- a/sys/netinet/sctp_uio.h +++ b/sys/netinet/sctp_uio.h @@ -982,6 +982,23 @@ union sctp_sockstore { struct sockaddr sa; }; + +/***********************************/ +/* And something for us old timers */ +/***********************************/ + +#ifndef ntohll +#include +#define ntohll(x) be64toh(x) +#endif + +#ifndef htonll +#include +#define htonll(x) htobe64(x) +#endif +/***********************************/ + + struct xsctp_inpcb { uint32_t last; uint32_t flags; @@ -1079,7 +1096,6 @@ sctp_lower_sosend(struct socket *so, struct mbuf *i_pak, struct mbuf *control, int flags, - int use_rcvinfo, struct sctp_sndrcvinfo *srcv ,struct thread *p );