Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 15 Jul 2017 16:55:02 +0000 (UTC)
From:      Dmitry Chagin <dchagin@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r321017 - in stable/10/sys: compat/freebsd32 conf kern netinet sys
Message-ID:  <201707151655.v6FGt2B7048200@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: dchagin
Date: Sat Jul 15 16:55:02 2017
New Revision: 321017
URL: https://svnweb.freebsd.org/changeset/base/321017

Log:
  MFC r272823:
  
  Move the SCTP syscalls to netinet with the rest of the SCTP code.  The
  syscalls themselves are tightly coupled with the network stack and
  therefore should not be in the generic socket code.
  
  The following four syscalls have been marked as NOSTD so they can be
  dynamically registered in sctp_syscalls_init() function:
    sys_sctp_peeloff
    sys_sctp_generic_sendmsg
    sys_sctp_generic_sendmsg_iov
    sys_sctp_generic_recvmsg
  
  The syscalls are also set up to be dynamically registered when COMPAT32
  option is configured.
  
  As a side effect of moving the SCTP syscalls, getsock_cap needs to be
  made available outside of the uipc_syscalls.c source file.  A proper
  prototype has been added to the sys/socketvar.h header file.
  
  API tests from the SCTP reference implementation have been run to ensure
  compatibility. (http://code.google.com/p/sctp-refimpl/source/checkout)

Added:
  stable/10/sys/netinet/sctp_syscalls.c
     - copied unchanged from r272823, head/sys/netinet/sctp_syscalls.c
Modified:
  stable/10/sys/compat/freebsd32/syscalls.master
  stable/10/sys/conf/files
  stable/10/sys/kern/syscalls.master
  stable/10/sys/kern/uipc_syscalls.c
  stable/10/sys/sys/socketvar.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/compat/freebsd32/syscalls.master
==============================================================================
--- stable/10/sys/compat/freebsd32/syscalls.master	Sat Jul 15 16:52:40 2017	(r321016)
+++ stable/10/sys/compat/freebsd32/syscalls.master	Sat Jul 15 16:55:02 2017	(r321017)
@@ -845,14 +845,14 @@
 468	AUE_NULL	UNIMPL	nosys
 469	AUE_NULL	UNIMPL	__getpath_fromfd
 470	AUE_NULL	UNIMPL	__getpath_fromaddr
-471	AUE_NULL	NOPROTO	{ int sctp_peeloff(int sd, uint32_t name); }
-472	AUE_NULL	NOPROTO	{ int sctp_generic_sendmsg(int sd, caddr_t msg, int mlen, \
+471	AUE_NULL	NOPROTO|NOSTD	{ int sctp_peeloff(int sd, uint32_t name); }
+472	AUE_NULL	NOPROTO|NOSTD	{ int sctp_generic_sendmsg(int sd, caddr_t msg, int mlen, \
 				    caddr_t to, __socklen_t tolen, \
 				    struct sctp_sndrcvinfo *sinfo, int flags); }
-473	AUE_NULL	NOPROTO	{ int sctp_generic_sendmsg_iov(int sd, struct iovec *iov, int iovlen, \
+473	AUE_NULL	NOPROTO|NOSTD	{ int sctp_generic_sendmsg_iov(int sd, struct iovec *iov, int iovlen, \
 				    caddr_t to, __socklen_t tolen, \
 				    struct sctp_sndrcvinfo *sinfo, int flags); }
-474	AUE_NULL	NOPROTO	{ int sctp_generic_recvmsg(int sd, struct iovec *iov, int iovlen, \
+474	AUE_NULL	NOPROTO|NOSTD	{ int sctp_generic_recvmsg(int sd, struct iovec *iov, int iovlen, \
 				    struct sockaddr * from, __socklen_t *fromlenaddr, \
 				    struct sctp_sndrcvinfo *sinfo, int *msg_flags); }
 #ifdef PAD64_REQUIRED

Modified: stable/10/sys/conf/files
==============================================================================
--- stable/10/sys/conf/files	Sat Jul 15 16:52:40 2017	(r321016)
+++ stable/10/sys/conf/files	Sat Jul 15 16:55:02 2017	(r321017)
@@ -3570,6 +3570,7 @@ netinet/sctp_output.c		optional inet sctp | inet6 sctp
 netinet/sctp_pcb.c		optional inet sctp | inet6 sctp
 netinet/sctp_peeloff.c		optional inet sctp | inet6 sctp
 netinet/sctp_ss_functions.c	optional inet sctp | inet6 sctp
+netinet/sctp_syscalls.c		optional inet sctp | inet6 sctp
 netinet/sctp_sysctl.c		optional inet sctp | inet6 sctp
 netinet/sctp_timer.c		optional inet sctp | inet6 sctp
 netinet/sctp_usrreq.c		optional inet sctp | inet6 sctp

Modified: stable/10/sys/kern/syscalls.master
==============================================================================
--- stable/10/sys/kern/syscalls.master	Sat Jul 15 16:52:40 2017	(r321016)
+++ stable/10/sys/kern/syscalls.master	Sat Jul 15 16:55:02 2017	(r321017)
@@ -837,14 +837,14 @@
 468	AUE_NULL	UNIMPL	nosys
 469	AUE_NULL	UNIMPL	__getpath_fromfd
 470	AUE_NULL	UNIMPL	__getpath_fromaddr
-471	AUE_NULL	STD	{ int sctp_peeloff(int sd, uint32_t name); }
-472     AUE_NULL        STD    { int sctp_generic_sendmsg(int sd, caddr_t msg, int mlen, \
+471	AUE_NULL	NOSTD	{ int sctp_peeloff(int sd, uint32_t name); }
+472     AUE_NULL        NOSTD	{ int sctp_generic_sendmsg(int sd, caddr_t msg, int mlen, \
 	                            caddr_t to, __socklen_t tolen, \
 				    struct sctp_sndrcvinfo *sinfo, int flags); }
-473     AUE_NULL        STD    { int sctp_generic_sendmsg_iov(int sd, struct iovec *iov, int iovlen, \
+473     AUE_NULL        NOSTD	{ int sctp_generic_sendmsg_iov(int sd, struct iovec *iov, int iovlen, \
 	                            caddr_t to, __socklen_t tolen, \
 				    struct sctp_sndrcvinfo *sinfo, int flags); }
-474     AUE_NULL        STD    { int sctp_generic_recvmsg(int sd, struct iovec *iov, int iovlen, \
+474     AUE_NULL        NOSTD	{ int sctp_generic_recvmsg(int sd, struct iovec *iov, int iovlen, \
 				    struct sockaddr * from, __socklen_t *fromlenaddr, \
 				    struct sctp_sndrcvinfo *sinfo, int *msg_flags); }
 475	AUE_PREAD	STD	{ ssize_t pread(int fd, void *buf, \

Modified: stable/10/sys/kern/uipc_syscalls.c
==============================================================================
--- stable/10/sys/kern/uipc_syscalls.c	Sat Jul 15 16:52:40 2017	(r321016)
+++ stable/10/sys/kern/uipc_syscalls.c	Sat Jul 15 16:55:02 2017	(r321017)
@@ -38,7 +38,6 @@ __FBSDID("$FreeBSD$");
 #include "opt_capsicum.h"
 #include "opt_inet.h"
 #include "opt_inet6.h"
-#include "opt_sctp.h"
 #include "opt_compat.h"
 #include "opt_ktrace.h"
 
@@ -92,13 +91,6 @@ __FBSDID("$FreeBSD$");
 #include <vm/vm_kern.h>
 #include <vm/vm_extern.h>
 
-#if defined(INET) || defined(INET6)
-#ifdef SCTP
-#include <netinet/sctp.h>
-#include <netinet/sctp_peeloff.h>
-#endif /* SCTP */
-#endif /* INET || INET6 */
-
 /*
  * Flags for accept1() and kern_accept4(), in addition to SOCK_CLOEXEC
  * and SOCK_NONBLOCK.
@@ -157,7 +149,7 @@ SYSCTL_PROC(_kern_ipc, OID_AUTO, sfstat, CTLTYPE_OPAQU
  * capability rights are present.
  * A reference on the file entry is held upon returning.
  */
-static int
+int
 getsock_cap(struct filedesc *fdp, int fd, cap_rights_t *rightsp,
     struct file **fpp, u_int *fflagp)
 {
@@ -2573,485 +2565,4 @@ out:
 		error = EINTR;
 
 	return (error);
-}
-
-/*
- * SCTP syscalls.
- * Functionality only compiled in if SCTP is defined in the kernel Makefile,
- * otherwise all return EOPNOTSUPP.
- * XXX: We should make this loadable one day.
- */
-int
-sys_sctp_peeloff(td, uap)
-	struct thread *td;
-	struct sctp_peeloff_args /* {
-		int	sd;
-		caddr_t	name;
-	} */ *uap;
-{
-#if (defined(INET) || defined(INET6)) && defined(SCTP)
-	struct file *nfp = NULL;
-	struct socket *head, *so;
-	cap_rights_t rights;
-	u_int fflag;
-	int error, fd;
-
-	AUDIT_ARG_FD(uap->sd);
-	error = fgetsock(td, uap->sd, cap_rights_init(&rights, CAP_PEELOFF),
-	    &head, &fflag);
-	if (error != 0)
-		goto done2;
-	if (head->so_proto->pr_protocol != IPPROTO_SCTP) {
-		error = EOPNOTSUPP;
-		goto done;
-	}
-	error = sctp_can_peel_off(head, (sctp_assoc_t)uap->name);
-	if (error != 0)
-		goto done;
-	/*
-	 * At this point we know we do have a assoc to pull
-	 * we proceed to get the fd setup. This may block
-	 * but that is ok.
-	 */
-
-	error = falloc(td, &nfp, &fd, 0);
-	if (error != 0)
-		goto done;
-	td->td_retval[0] = fd;
-
-	CURVNET_SET(head->so_vnet);
-	so = sonewconn(head, SS_ISCONNECTED);
-	if (so == NULL) {
-		error = ENOMEM;
-		goto noconnection;
-	}
-	/*
-	 * Before changing the flags on the socket, we have to bump the
-	 * reference count.  Otherwise, if the protocol calls sofree(),
-	 * the socket will be released due to a zero refcount.
-	 */
-        SOCK_LOCK(so);
-        soref(so);                      /* file descriptor reference */
-        SOCK_UNLOCK(so);
-
-	ACCEPT_LOCK();
-
-	TAILQ_REMOVE(&head->so_comp, so, so_list);
-	head->so_qlen--;
-	so->so_state |= (head->so_state & SS_NBIO);
-	so->so_state &= ~SS_NOFDREF;
-	so->so_qstate &= ~SQ_COMP;
-	so->so_head = NULL;
-	ACCEPT_UNLOCK();
-	finit(nfp, fflag, DTYPE_SOCKET, so, &socketops);
-	error = sctp_do_peeloff(head, so, (sctp_assoc_t)uap->name);
-	if (error != 0)
-		goto noconnection;
-	if (head->so_sigio != NULL)
-		fsetown(fgetown(&head->so_sigio), &so->so_sigio);
-
-noconnection:
-	/*
-	 * close the new descriptor, assuming someone hasn't ripped it
-	 * out from under us.
-	 */
-	if (error != 0)
-		fdclose(td->td_proc->p_fd, nfp, fd, td);
-
-	/*
-	 * Release explicitly held references before returning.
-	 */
-	CURVNET_RESTORE();
-done:
-	if (nfp != NULL)
-		fdrop(nfp, td);
-	fputsock(head);
-done2:
-	return (error);
-#else  /* SCTP */
-	return (EOPNOTSUPP);
-#endif /* SCTP */
-}
-
-int
-sys_sctp_generic_sendmsg (td, uap)
-	struct thread *td;
-	struct sctp_generic_sendmsg_args /* {
-		int sd,
-		caddr_t msg,
-		int mlen,
-		caddr_t to,
-		__socklen_t tolen,
-		struct sctp_sndrcvinfo *sinfo,
-		int flags
-	} */ *uap;
-{
-#if (defined(INET) || defined(INET6)) && defined(SCTP)
-	struct sctp_sndrcvinfo sinfo, *u_sinfo = NULL;
-	struct socket *so;
-	struct file *fp = NULL;
-	struct sockaddr *to = NULL;
-#ifdef KTRACE
-	struct uio *ktruio = NULL;
-#endif
-	struct uio auio;
-	struct iovec iov[1];
-	cap_rights_t rights;
-	int error = 0, len;
-
-	if (uap->sinfo != NULL) {
-		error = copyin(uap->sinfo, &sinfo, sizeof (sinfo));
-		if (error != 0)
-			return (error);
-		u_sinfo = &sinfo;
-	}
-
-	cap_rights_init(&rights, CAP_SEND);
-	if (uap->tolen != 0) {
-		error = getsockaddr(&to, uap->to, uap->tolen);
-		if (error != 0) {
-			to = NULL;
-			goto sctp_bad2;
-		}
-		cap_rights_set(&rights, CAP_CONNECT);
-	}
-
-	AUDIT_ARG_FD(uap->sd);
-	error = getsock_cap(td->td_proc->p_fd, uap->sd, &rights, &fp, NULL);
-	if (error != 0)
-		goto sctp_bad;
-#ifdef KTRACE
-	if (to && (KTRPOINT(td, KTR_STRUCT)))
-		ktrsockaddr(to);
-#endif
-
-	iov[0].iov_base = uap->msg;
-	iov[0].iov_len = uap->mlen;
-
-	so = (struct socket *)fp->f_data;
-	if (so->so_proto->pr_protocol != IPPROTO_SCTP) {
-		error = EOPNOTSUPP;
-		goto sctp_bad;
-	}
-#ifdef MAC
-	error = mac_socket_check_send(td->td_ucred, so);
-	if (error != 0)
-		goto sctp_bad;
-#endif /* MAC */
-
-	auio.uio_iov =  iov;
-	auio.uio_iovcnt = 1;
-	auio.uio_segflg = UIO_USERSPACE;
-	auio.uio_rw = UIO_WRITE;
-	auio.uio_td = td;
-	auio.uio_offset = 0;			/* XXX */
-	auio.uio_resid = 0;
-	len = auio.uio_resid = uap->mlen;
-	CURVNET_SET(so->so_vnet);
-	error = sctp_lower_sosend(so, to, &auio, (struct mbuf *)NULL,
-	    (struct mbuf *)NULL, uap->flags, u_sinfo, td);
-	CURVNET_RESTORE();
-	if (error != 0) {
-		if (auio.uio_resid != len && (error == ERESTART ||
-		    error == EINTR || error == EWOULDBLOCK))
-			error = 0;
-		/* Generation of SIGPIPE can be controlled per socket. */
-		if (error == EPIPE && !(so->so_options & SO_NOSIGPIPE) &&
-		    !(uap->flags & MSG_NOSIGNAL)) {
-			PROC_LOCK(td->td_proc);
-			tdsignal(td, SIGPIPE);
-			PROC_UNLOCK(td->td_proc);
-		}
-	}
-	if (error == 0)
-		td->td_retval[0] = len - auio.uio_resid;
-#ifdef KTRACE
-	if (ktruio != NULL) {
-		ktruio->uio_resid = td->td_retval[0];
-		ktrgenio(uap->sd, UIO_WRITE, ktruio, error);
-	}
-#endif /* KTRACE */
-sctp_bad:
-	if (fp != NULL)
-		fdrop(fp, td);
-sctp_bad2:
-	free(to, M_SONAME);
-	return (error);
-#else  /* SCTP */
-	return (EOPNOTSUPP);
-#endif /* SCTP */
-}
-
-int
-sys_sctp_generic_sendmsg_iov(td, uap)
-	struct thread *td;
-	struct sctp_generic_sendmsg_iov_args /* {
-		int sd,
-		struct iovec *iov,
-		int iovlen,
-		caddr_t to,
-		__socklen_t tolen,
-		struct sctp_sndrcvinfo *sinfo,
-		int flags
-	} */ *uap;
-{
-#if (defined(INET) || defined(INET6)) && defined(SCTP)
-	struct sctp_sndrcvinfo sinfo, *u_sinfo = NULL;
-	struct socket *so;
-	struct file *fp = NULL;
-	struct sockaddr *to = NULL;
-#ifdef KTRACE
-	struct uio *ktruio = NULL;
-#endif
-	struct uio auio;
-	struct iovec *iov, *tiov;
-	cap_rights_t rights;
-	ssize_t len;
-	int error, i;
-
-	if (uap->sinfo != NULL) {
-		error = copyin(uap->sinfo, &sinfo, sizeof (sinfo));
-		if (error != 0)
-			return (error);
-		u_sinfo = &sinfo;
-	}
-	cap_rights_init(&rights, CAP_SEND);
-	if (uap->tolen != 0) {
-		error = getsockaddr(&to, uap->to, uap->tolen);
-		if (error != 0) {
-			to = NULL;
-			goto sctp_bad2;
-		}
-		cap_rights_set(&rights, CAP_CONNECT);
-	}
-
-	AUDIT_ARG_FD(uap->sd);
-	error = getsock_cap(td->td_proc->p_fd, uap->sd, &rights, &fp, NULL);
-	if (error != 0)
-		goto sctp_bad1;
-
-#ifdef COMPAT_FREEBSD32
-	if (SV_CURPROC_FLAG(SV_ILP32))
-		error = freebsd32_copyiniov((struct iovec32 *)uap->iov,
-		    uap->iovlen, &iov, EMSGSIZE);
-	else
-#endif
-		error = copyiniov(uap->iov, uap->iovlen, &iov, EMSGSIZE);
-	if (error != 0)
-		goto sctp_bad1;
-#ifdef KTRACE
-	if (to && (KTRPOINT(td, KTR_STRUCT)))
-		ktrsockaddr(to);
-#endif
-
-	so = (struct socket *)fp->f_data;
-	if (so->so_proto->pr_protocol != IPPROTO_SCTP) {
-		error = EOPNOTSUPP;
-		goto sctp_bad;
-	}
-#ifdef MAC
-	error = mac_socket_check_send(td->td_ucred, so);
-	if (error != 0)
-		goto sctp_bad;
-#endif /* MAC */
-
-	auio.uio_iov = iov;
-	auio.uio_iovcnt = uap->iovlen;
-	auio.uio_segflg = UIO_USERSPACE;
-	auio.uio_rw = UIO_WRITE;
-	auio.uio_td = td;
-	auio.uio_offset = 0;			/* XXX */
-	auio.uio_resid = 0;
-	tiov = iov;
-	for (i = 0; i <uap->iovlen; i++, tiov++) {
-		if ((auio.uio_resid += tiov->iov_len) < 0) {
-			error = EINVAL;
-			goto sctp_bad;
-		}
-	}
-	len = auio.uio_resid;
-	CURVNET_SET(so->so_vnet);
-	error = sctp_lower_sosend(so, to, &auio,
-		    (struct mbuf *)NULL, (struct mbuf *)NULL,
-		    uap->flags, u_sinfo, td);
-	CURVNET_RESTORE();
-	if (error != 0) {
-		if (auio.uio_resid != len && (error == ERESTART ||
-		    error == EINTR || error == EWOULDBLOCK))
-			error = 0;
-		/* Generation of SIGPIPE can be controlled per socket */
-		if (error == EPIPE && !(so->so_options & SO_NOSIGPIPE) &&
-		    !(uap->flags & MSG_NOSIGNAL)) {
-			PROC_LOCK(td->td_proc);
-			tdsignal(td, SIGPIPE);
-			PROC_UNLOCK(td->td_proc);
-		}
-	}
-	if (error == 0)
-		td->td_retval[0] = len - auio.uio_resid;
-#ifdef KTRACE
-	if (ktruio != NULL) {
-		ktruio->uio_resid = td->td_retval[0];
-		ktrgenio(uap->sd, UIO_WRITE, ktruio, error);
-	}
-#endif /* KTRACE */
-sctp_bad:
-	free(iov, M_IOV);
-sctp_bad1:
-	if (fp != NULL)
-		fdrop(fp, td);
-sctp_bad2:
-	free(to, M_SONAME);
-	return (error);
-#else  /* SCTP */
-	return (EOPNOTSUPP);
-#endif /* SCTP */
-}
-
-int
-sys_sctp_generic_recvmsg(td, uap)
-	struct thread *td;
-	struct sctp_generic_recvmsg_args /* {
-		int sd,
-		struct iovec *iov,
-		int iovlen,
-		struct sockaddr *from,
-		__socklen_t *fromlenaddr,
-		struct sctp_sndrcvinfo *sinfo,
-		int *msg_flags
-	} */ *uap;
-{
-#if (defined(INET) || defined(INET6)) && defined(SCTP)
-	uint8_t sockbufstore[256];
-	struct uio auio;
-	struct iovec *iov, *tiov;
-	struct sctp_sndrcvinfo sinfo;
-	struct socket *so;
-	struct file *fp = NULL;
-	struct sockaddr *fromsa;
-	cap_rights_t rights;
-#ifdef KTRACE
-	struct uio *ktruio = NULL;
-#endif
-	ssize_t len;
-	int error, fromlen, i, msg_flags;
-
-	AUDIT_ARG_FD(uap->sd);
-	error = getsock_cap(td->td_proc->p_fd, uap->sd,
-	    cap_rights_init(&rights, CAP_RECV), &fp, NULL);
-	if (error != 0)
-		return (error);
-#ifdef COMPAT_FREEBSD32
-	if (SV_CURPROC_FLAG(SV_ILP32))
-		error = freebsd32_copyiniov((struct iovec32 *)uap->iov,
-		    uap->iovlen, &iov, EMSGSIZE);
-	else
-#endif
-		error = copyiniov(uap->iov, uap->iovlen, &iov, EMSGSIZE);
-	if (error != 0)
-		goto out1;
-
-	so = fp->f_data;
-	if (so->so_proto->pr_protocol != IPPROTO_SCTP) {
-		error = EOPNOTSUPP;
-		goto out;
-	}
-#ifdef MAC
-	error = mac_socket_check_receive(td->td_ucred, so);
-	if (error != 0)
-		goto out;
-#endif /* MAC */
-
-	if (uap->fromlenaddr != NULL) {
-		error = copyin(uap->fromlenaddr, &fromlen, sizeof (fromlen));
-		if (error != 0)
-			goto out;
-	} else {
-		fromlen = 0;
-	}
-	if (uap->msg_flags) {
-		error = copyin(uap->msg_flags, &msg_flags, sizeof (int));
-		if (error != 0)
-			goto out;
-	} else {
-		msg_flags = 0;
-	}
-	auio.uio_iov = iov;
-	auio.uio_iovcnt = uap->iovlen;
-	auio.uio_segflg = UIO_USERSPACE;
-	auio.uio_rw = UIO_READ;
-	auio.uio_td = td;
-	auio.uio_offset = 0;			/* XXX */
-	auio.uio_resid = 0;
-	tiov = iov;
-	for (i = 0; i <uap->iovlen; i++, tiov++) {
-		if ((auio.uio_resid += tiov->iov_len) < 0) {
-			error = EINVAL;
-			goto out;
-		}
-	}
-	len = auio.uio_resid;
-	fromsa = (struct sockaddr *)sockbufstore;
-
-#ifdef KTRACE
-	if (KTRPOINT(td, KTR_GENIO))
-		ktruio = cloneuio(&auio);
-#endif /* KTRACE */
-	memset(&sinfo, 0, sizeof(struct sctp_sndrcvinfo));
-	CURVNET_SET(so->so_vnet);
-	error = sctp_sorecvmsg(so, &auio, (struct mbuf **)NULL,
-		    fromsa, fromlen, &msg_flags,
-		    (struct sctp_sndrcvinfo *)&sinfo, 1);
-	CURVNET_RESTORE();
-	if (error != 0) {
-		if (auio.uio_resid != len && (error == ERESTART ||
-		    error == EINTR || error == EWOULDBLOCK))
-			error = 0;
-	} else {
-		if (uap->sinfo)
-			error = copyout(&sinfo, uap->sinfo, sizeof (sinfo));
-	}
-#ifdef KTRACE
-	if (ktruio != NULL) {
-		ktruio->uio_resid = len - auio.uio_resid;
-		ktrgenio(uap->sd, UIO_READ, ktruio, error);
-	}
-#endif /* KTRACE */
-	if (error != 0)
-		goto out;
-	td->td_retval[0] = len - auio.uio_resid;
-
-	if (fromlen && uap->from) {
-		len = fromlen;
-		if (len <= 0 || fromsa == 0)
-			len = 0;
-		else {
-			len = MIN(len, fromsa->sa_len);
-			error = copyout(fromsa, uap->from, (size_t)len);
-			if (error != 0)
-				goto out;
-		}
-		error = copyout(&len, uap->fromlenaddr, sizeof (socklen_t));
-		if (error != 0)
-			goto out;
-	}
-#ifdef KTRACE
-	if (KTRPOINT(td, KTR_STRUCT))
-		ktrsockaddr(fromsa);
-#endif
-	if (uap->msg_flags) {
-		error = copyout(&msg_flags, uap->msg_flags, sizeof (int));
-		if (error != 0)
-			goto out;
-	}
-out:
-	free(iov, M_IOV);
-out1:
-	if (fp != NULL)
-		fdrop(fp, td);
-
-	return (error);
-#else  /* SCTP */
-	return (EOPNOTSUPP);
-#endif /* SCTP */
 }

Copied: stable/10/sys/netinet/sctp_syscalls.c (from r272823, head/sys/netinet/sctp_syscalls.c)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ stable/10/sys/netinet/sctp_syscalls.c	Sat Jul 15 16:55:02 2017	(r321017, copy of r272823, head/sys/netinet/sctp_syscalls.c)
@@ -0,0 +1,588 @@
+/*-
+ * Copyright (c) 1982, 1986, 1989, 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_capsicum.h"
+#include "opt_inet.h"
+#include "opt_inet6.h"
+#include "opt_sctp.h"
+#include "opt_compat.h"
+#include "opt_ktrace.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/capsicum.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/sysproto.h>
+#include <sys/malloc.h>
+#include <sys/filedesc.h>
+#include <sys/event.h>
+#include <sys/proc.h>
+#include <sys/fcntl.h>
+#include <sys/file.h>
+#include <sys/filio.h>
+#include <sys/jail.h>
+#include <sys/mount.h>
+#include <sys/mbuf.h>
+#include <sys/protosw.h>
+#include <sys/sf_buf.h>
+#include <sys/sysent.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/signalvar.h>
+#include <sys/syscall.h>
+#include <sys/syscallsubr.h>
+#include <sys/sysctl.h>
+#include <sys/uio.h>
+#include <sys/vnode.h>
+#ifdef KTRACE
+#include <sys/ktrace.h>
+#endif
+#ifdef COMPAT_FREEBSD32
+#include <compat/freebsd32/freebsd32_util.h>
+#endif
+
+#include <net/vnet.h>
+
+#include <security/audit/audit.h>
+#include <security/mac/mac_framework.h>
+
+#include <netinet/sctp.h>
+#include <netinet/sctp_peeloff.h>
+
+static struct syscall_helper_data sctp_syscalls[] = {
+	SYSCALL_INIT_HELPER(sctp_peeloff),
+	SYSCALL_INIT_HELPER(sctp_generic_sendmsg),
+	SYSCALL_INIT_HELPER(sctp_generic_sendmsg_iov),
+	SYSCALL_INIT_HELPER(sctp_generic_recvmsg),
+	SYSCALL_INIT_LAST
+};
+
+static void
+sctp_syscalls_init(void *unused __unused)
+{
+	int error;
+
+	error = syscall_helper_register(sctp_syscalls);
+	KASSERT((error == 0),
+	    ("%s: syscall_helper_register failed for sctp syscalls", __func__));
+#ifdef COMPAT_FREEBSD32
+	error = syscall32_helper_register(sctp_syscalls);
+	KASSERT((error == 0),
+	    ("%s: syscall32_helper_register failed for sctp syscalls",
+	    __func__));
+#endif
+}
+SYSINIT(sctp_syscalls, SI_SUB_SYSCALLS, SI_ORDER_ANY, sctp_syscalls_init, NULL);
+
+/*
+ * SCTP syscalls.
+ * Functionality only compiled in if SCTP is defined in the kernel Makefile,
+ * otherwise all return EOPNOTSUPP.
+ * XXX: We should make this loadable one day.
+ */
+int
+sys_sctp_peeloff(td, uap)
+	struct thread *td;
+	struct sctp_peeloff_args /* {
+		int	sd;
+		caddr_t	name;
+	} */ *uap;
+{
+#if (defined(INET) || defined(INET6)) && defined(SCTP)
+	struct file *nfp = NULL;
+	struct socket *head, *so;
+	cap_rights_t rights;
+	u_int fflag;
+	int error, fd;
+
+	AUDIT_ARG_FD(uap->sd);
+	error = fgetsock(td, uap->sd, cap_rights_init(&rights, CAP_PEELOFF),
+	    &head, &fflag);
+	if (error != 0)
+		goto done2;
+	if (head->so_proto->pr_protocol != IPPROTO_SCTP) {
+		error = EOPNOTSUPP;
+		goto done;
+	}
+	error = sctp_can_peel_off(head, (sctp_assoc_t)uap->name);
+	if (error != 0)
+		goto done;
+	/*
+	 * At this point we know we do have a assoc to pull
+	 * we proceed to get the fd setup. This may block
+	 * but that is ok.
+	 */
+
+	error = falloc(td, &nfp, &fd, 0);
+	if (error != 0)
+		goto done;
+	td->td_retval[0] = fd;
+
+	CURVNET_SET(head->so_vnet);
+	so = sonewconn(head, SS_ISCONNECTED);
+	if (so == NULL) {
+		error = ENOMEM;
+		goto noconnection;
+	}
+	/*
+	 * Before changing the flags on the socket, we have to bump the
+	 * reference count.  Otherwise, if the protocol calls sofree(),
+	 * the socket will be released due to a zero refcount.
+	 */
+        SOCK_LOCK(so);
+        soref(so);                      /* file descriptor reference */
+        SOCK_UNLOCK(so);
+
+	ACCEPT_LOCK();
+
+	TAILQ_REMOVE(&head->so_comp, so, so_list);
+	head->so_qlen--;
+	so->so_state |= (head->so_state & SS_NBIO);
+	so->so_state &= ~SS_NOFDREF;
+	so->so_qstate &= ~SQ_COMP;
+	so->so_head = NULL;
+	ACCEPT_UNLOCK();
+	finit(nfp, fflag, DTYPE_SOCKET, so, &socketops);
+	error = sctp_do_peeloff(head, so, (sctp_assoc_t)uap->name);
+	if (error != 0)
+		goto noconnection;
+	if (head->so_sigio != NULL)
+		fsetown(fgetown(&head->so_sigio), &so->so_sigio);
+
+noconnection:
+	/*
+	 * close the new descriptor, assuming someone hasn't ripped it
+	 * out from under us.
+	 */
+	if (error != 0)
+		fdclose(td->td_proc->p_fd, nfp, fd, td);
+
+	/*
+	 * Release explicitly held references before returning.
+	 */
+	CURVNET_RESTORE();
+done:
+	if (nfp != NULL)
+		fdrop(nfp, td);
+	fputsock(head);
+done2:
+	return (error);
+#else  /* SCTP */
+	return (EOPNOTSUPP);
+#endif /* SCTP */
+}
+
+int
+sys_sctp_generic_sendmsg (td, uap)
+	struct thread *td;
+	struct sctp_generic_sendmsg_args /* {
+		int sd,
+		caddr_t msg,
+		int mlen,
+		caddr_t to,
+		__socklen_t tolen,
+		struct sctp_sndrcvinfo *sinfo,
+		int flags
+	} */ *uap;
+{
+#if (defined(INET) || defined(INET6)) && defined(SCTP)
+	struct sctp_sndrcvinfo sinfo, *u_sinfo = NULL;
+	struct socket *so;
+	struct file *fp = NULL;
+	struct sockaddr *to = NULL;
+#ifdef KTRACE
+	struct uio *ktruio = NULL;
+#endif
+	struct uio auio;
+	struct iovec iov[1];
+	cap_rights_t rights;
+	int error = 0, len;
+
+	if (uap->sinfo != NULL) {
+		error = copyin(uap->sinfo, &sinfo, sizeof (sinfo));
+		if (error != 0)
+			return (error);
+		u_sinfo = &sinfo;
+	}
+
+	cap_rights_init(&rights, CAP_SEND);
+	if (uap->tolen != 0) {
+		error = getsockaddr(&to, uap->to, uap->tolen);
+		if (error != 0) {
+			to = NULL;
+			goto sctp_bad2;
+		}
+		cap_rights_set(&rights, CAP_CONNECT);
+	}
+
+	AUDIT_ARG_FD(uap->sd);
+	error = getsock_cap(td->td_proc->p_fd, uap->sd, &rights, &fp, NULL);
+	if (error != 0)
+		goto sctp_bad;
+#ifdef KTRACE
+	if (to && (KTRPOINT(td, KTR_STRUCT)))
+		ktrsockaddr(to);
+#endif
+
+	iov[0].iov_base = uap->msg;
+	iov[0].iov_len = uap->mlen;
+
+	so = (struct socket *)fp->f_data;
+	if (so->so_proto->pr_protocol != IPPROTO_SCTP) {
+		error = EOPNOTSUPP;
+		goto sctp_bad;
+	}
+#ifdef MAC
+	error = mac_socket_check_send(td->td_ucred, so);
+	if (error != 0)
+		goto sctp_bad;
+#endif /* MAC */
+
+	auio.uio_iov =  iov;
+	auio.uio_iovcnt = 1;
+	auio.uio_segflg = UIO_USERSPACE;
+	auio.uio_rw = UIO_WRITE;
+	auio.uio_td = td;
+	auio.uio_offset = 0;			/* XXX */
+	auio.uio_resid = 0;
+	len = auio.uio_resid = uap->mlen;
+	CURVNET_SET(so->so_vnet);
+	error = sctp_lower_sosend(so, to, &auio, (struct mbuf *)NULL,
+	    (struct mbuf *)NULL, uap->flags, u_sinfo, td);
+	CURVNET_RESTORE();
+	if (error != 0) {
+		if (auio.uio_resid != len && (error == ERESTART ||
+		    error == EINTR || error == EWOULDBLOCK))
+			error = 0;
+		/* Generation of SIGPIPE can be controlled per socket. */
+		if (error == EPIPE && !(so->so_options & SO_NOSIGPIPE) &&
+		    !(uap->flags & MSG_NOSIGNAL)) {
+			PROC_LOCK(td->td_proc);
+			tdsignal(td, SIGPIPE);
+			PROC_UNLOCK(td->td_proc);
+		}
+	}
+	if (error == 0)
+		td->td_retval[0] = len - auio.uio_resid;
+#ifdef KTRACE
+	if (ktruio != NULL) {
+		ktruio->uio_resid = td->td_retval[0];
+		ktrgenio(uap->sd, UIO_WRITE, ktruio, error);
+	}
+#endif /* KTRACE */
+sctp_bad:
+	if (fp != NULL)
+		fdrop(fp, td);
+sctp_bad2:
+	free(to, M_SONAME);
+	return (error);
+#else  /* SCTP */
+	return (EOPNOTSUPP);
+#endif /* SCTP */
+}
+
+int
+sys_sctp_generic_sendmsg_iov(td, uap)
+	struct thread *td;
+	struct sctp_generic_sendmsg_iov_args /* {
+		int sd,
+		struct iovec *iov,
+		int iovlen,
+		caddr_t to,
+		__socklen_t tolen,
+		struct sctp_sndrcvinfo *sinfo,
+		int flags
+	} */ *uap;
+{
+#if (defined(INET) || defined(INET6)) && defined(SCTP)
+	struct sctp_sndrcvinfo sinfo, *u_sinfo = NULL;
+	struct socket *so;
+	struct file *fp = NULL;
+	struct sockaddr *to = NULL;
+#ifdef KTRACE
+	struct uio *ktruio = NULL;
+#endif
+	struct uio auio;
+	struct iovec *iov, *tiov;
+	cap_rights_t rights;
+	ssize_t len;
+	int error, i;
+
+	if (uap->sinfo != NULL) {
+		error = copyin(uap->sinfo, &sinfo, sizeof (sinfo));
+		if (error != 0)
+			return (error);
+		u_sinfo = &sinfo;
+	}
+	cap_rights_init(&rights, CAP_SEND);
+	if (uap->tolen != 0) {
+		error = getsockaddr(&to, uap->to, uap->tolen);
+		if (error != 0) {
+			to = NULL;
+			goto sctp_bad2;
+		}
+		cap_rights_set(&rights, CAP_CONNECT);
+	}
+
+	AUDIT_ARG_FD(uap->sd);
+	error = getsock_cap(td->td_proc->p_fd, uap->sd, &rights, &fp, NULL);
+	if (error != 0)
+		goto sctp_bad1;
+
+#ifdef COMPAT_FREEBSD32
+	if (SV_CURPROC_FLAG(SV_ILP32))
+		error = freebsd32_copyiniov((struct iovec32 *)uap->iov,
+		    uap->iovlen, &iov, EMSGSIZE);
+	else
+#endif
+		error = copyiniov(uap->iov, uap->iovlen, &iov, EMSGSIZE);
+	if (error != 0)
+		goto sctp_bad1;
+#ifdef KTRACE
+	if (to && (KTRPOINT(td, KTR_STRUCT)))
+		ktrsockaddr(to);
+#endif
+
+	so = (struct socket *)fp->f_data;
+	if (so->so_proto->pr_protocol != IPPROTO_SCTP) {
+		error = EOPNOTSUPP;
+		goto sctp_bad;
+	}
+#ifdef MAC
+	error = mac_socket_check_send(td->td_ucred, so);
+	if (error != 0)
+		goto sctp_bad;
+#endif /* MAC */
+
+	auio.uio_iov = iov;
+	auio.uio_iovcnt = uap->iovlen;
+	auio.uio_segflg = UIO_USERSPACE;
+	auio.uio_rw = UIO_WRITE;
+	auio.uio_td = td;
+	auio.uio_offset = 0;			/* XXX */
+	auio.uio_resid = 0;
+	tiov = iov;
+	for (i = 0; i <uap->iovlen; i++, tiov++) {
+		if ((auio.uio_resid += tiov->iov_len) < 0) {
+			error = EINVAL;
+			goto sctp_bad;
+		}
+	}
+	len = auio.uio_resid;
+	CURVNET_SET(so->so_vnet);
+	error = sctp_lower_sosend(so, to, &auio,
+		    (struct mbuf *)NULL, (struct mbuf *)NULL,
+		    uap->flags, u_sinfo, td);
+	CURVNET_RESTORE();
+	if (error != 0) {
+		if (auio.uio_resid != len && (error == ERESTART ||
+		    error == EINTR || error == EWOULDBLOCK))
+			error = 0;
+		/* Generation of SIGPIPE can be controlled per socket */
+		if (error == EPIPE && !(so->so_options & SO_NOSIGPIPE) &&
+		    !(uap->flags & MSG_NOSIGNAL)) {
+			PROC_LOCK(td->td_proc);
+			tdsignal(td, SIGPIPE);
+			PROC_UNLOCK(td->td_proc);
+		}
+	}
+	if (error == 0)
+		td->td_retval[0] = len - auio.uio_resid;
+#ifdef KTRACE
+	if (ktruio != NULL) {
+		ktruio->uio_resid = td->td_retval[0];
+		ktrgenio(uap->sd, UIO_WRITE, ktruio, error);

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201707151655.v6FGt2B7048200>