Date: Thu, 28 Oct 2010 18:50:35 +0000 (UTC) From: Michael Tuexen <tuexen@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org Subject: svn commit: r214470 - in stable/8/sys: kern netinet Message-ID: <201010281850.o9SIoZXI023112@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: tuexen Date: Thu Oct 28 18:50:35 2010 New Revision: 214470 URL: http://svn.freebsd.org/changeset/base/214470 Log: MFC 212242: Implement correct handling of address parameter and sendinfo for SCTP send calls. Modified: stable/8/sys/kern/uipc_syscalls.c stable/8/sys/netinet/sctp_output.c stable/8/sys/netinet/sctp_uio.h Directory Properties: stable/8/sys/ (props changed) stable/8/sys/amd64/include/xen/ (props changed) stable/8/sys/cddl/contrib/opensolaris/ (props changed) stable/8/sys/contrib/dev/acpica/ (props changed) stable/8/sys/contrib/pf/ (props changed) stable/8/sys/dev/xen/xenpci/ (props changed) Modified: stable/8/sys/kern/uipc_syscalls.c ============================================================================== --- stable/8/sys/kern/uipc_syscalls.c Thu Oct 28 18:15:07 2010 (r214469) +++ stable/8/sys/kern/uipc_syscalls.c Thu Oct 28 18:50:35 2010 (r214470) @@ -2385,7 +2385,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 @@ -2438,7 +2437,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 || @@ -2489,7 +2488,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 @@ -2556,7 +2554,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 || Modified: stable/8/sys/netinet/sctp_output.c ============================================================================== --- stable/8/sys/netinet/sctp_output.c Thu Oct 28 18:15:07 2010 (r214469) +++ stable/8/sys/netinet/sctp_output.c Thu Oct 28 18:50:35 2010 (r214470) @@ -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,28 +12237,39 @@ sctp_lower_sosend(struct socket *so, SCTPDBG(SCTP_DEBUG_OUTPUT1, "Send called addr:%p send length %d\n", addr, sndlen); + if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && + (inp->sctp_socket->so_qlimit)) { + /* The listener can NOT send */ + SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, ENOTCONN); + error = ENOTCONN; + goto out_unlocked; + } /** * Pre-screen address, if one is given the sin-len * must be set correctly! */ if (addr) { - switch (addr->sa_family) { + union sctp_sockstore *raddr = (union sctp_sockstore *)addr; + + switch (raddr->sa.sa_family) { #if defined(INET) case AF_INET: - if (addr->sa_len != sizeof(struct sockaddr_in)) { + 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 (addr->sa_len != sizeof(struct sockaddr_in6)) { + 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: @@ -12265,32 +12277,34 @@ sctp_lower_sosend(struct socket *so, error = EAFNOSUPPORT; goto out_unlocked; } - } - hold_tcblock = 0; + } else + port = 0; - if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && - (inp->sctp_socket->so_qlimit)) { - /* The listener can NOT send */ - SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, ENOTCONN); - error = ENOTCONN; - goto out_unlocked; - } - if ((use_rcvinfo) && srcv) { - if (INVALID_SINFO_FLAG(srcv->sinfo_flags) || - PR_SCTP_INVALID_POLICY(srcv->sinfo_flags)) { + 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)) { /*- Modified: stable/8/sys/netinet/sctp_uio.h ============================================================================== --- stable/8/sys/netinet/sctp_uio.h Thu Oct 28 18:15:07 2010 (r214469) +++ stable/8/sys/netinet/sctp_uio.h Thu Oct 28 18:50:35 2010 (r214470) @@ -982,6 +982,23 @@ union sctp_sockstore { struct sockaddr sa; }; + +/***********************************/ +/* And something for us old timers */ +/***********************************/ + +#ifndef ntohll +#include <sys/endian.h> +#define ntohll(x) be64toh(x) +#endif + +#ifndef htonll +#include <sys/endian.h> +#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 );
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201010281850.o9SIoZXI023112>