svn commit: r294541 - in head/sys: conf kern

Gleb Smirnoff glebius at FreeBSD.org
Fri Jan 22 02:23:19 UTC 2016


Author: glebius
Date: Fri Jan 22 02:23:18 2016
New Revision: 294541
URL: https://svnweb.freebsd.org/changeset/base/294541

Log:
  - Separate sendfile(2) implementation from uipc_syscalls.c into
    separate file.  Claim my copyright.
  - Provide more comments, better function and structure names.
  - Sort out unneeded includes from resulting two files.
  
  No functional changes.

Added:
  head/sys/kern/kern_sendfile.c
     - copied, changed from r294536, head/sys/kern/uipc_syscalls.c
Modified:
  head/sys/conf/files
  head/sys/kern/uipc_syscalls.c

Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files	Fri Jan 22 02:07:48 2016	(r294540)
+++ head/sys/conf/files	Fri Jan 22 02:23:18 2016	(r294541)
@@ -3213,6 +3213,7 @@ kern/kern_rmlock.c		standard
 kern/kern_rwlock.c		standard
 kern/kern_sdt.c			optional kdtrace_hooks
 kern/kern_sema.c		standard
+kern/kern_sendfile.c		standard
 kern/kern_sharedpage.c		standard
 kern/kern_shutdown.c		standard
 kern/kern_sig.c			standard

Copied and modified: head/sys/kern/kern_sendfile.c (from r294536, head/sys/kern/uipc_syscalls.c)
==============================================================================
--- head/sys/kern/uipc_syscalls.c	Thu Jan 21 22:53:12 2016	(r294536, copy source)
+++ head/sys/kern/kern_sendfile.c	Fri Jan 22 02:23:18 2016	(r294541)
@@ -1,8 +1,5 @@
 /*-
- * Copyright (c) 1982, 1986, 1989, 1990, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * sendfile(2) and related extensions:
+ * Copyright (c) 2013-2015 Gleb Smirnoff <glebius at FreeBSD.org>
  * Copyright (c) 1998, David Greenman. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -28,55 +25,33 @@
  * 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.
- *
- *	@(#)uipc_syscalls.c	8.4 (Berkeley) 2/21/94
  */
 
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
-#include "opt_capsicum.h"
-#include "opt_inet.h"
-#include "opt_inet6.h"
 #include "opt_compat.h"
-#include "opt_ktrace.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/capsicum.h>
-#include <sys/condvar.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/mman.h>
 #include <sys/mount.h>
 #include <sys/mbuf.h>
 #include <sys/protosw.h>
 #include <sys/rwlock.h>
 #include <sys/sf_buf.h>
-#include <sys/sysent.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
-#include <sys/signalvar.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>
 
@@ -84,1736 +59,68 @@ __FBSDID("$FreeBSD$");
 #include <security/mac/mac_framework.h>
 
 #include <vm/vm.h>
-#include <vm/vm_param.h>
 #include <vm/vm_object.h>
-#include <vm/vm_page.h>
 #include <vm/vm_pager.h>
-#include <vm/vm_kern.h>
-#include <vm/vm_extern.h>
-#include <vm/uma.h>
-
-/*
- * Flags for accept1() and kern_accept4(), in addition to SOCK_CLOEXEC
- * and SOCK_NONBLOCK.
- */
-#define	ACCEPT4_INHERIT	0x1
-#define	ACCEPT4_COMPAT	0x2
-
-static int sendit(struct thread *td, int s, struct msghdr *mp, int flags);
-static int recvit(struct thread *td, int s, struct msghdr *mp, void *namelenp);
-
-static int accept1(struct thread *td, int s, struct sockaddr *uname,
-		   socklen_t *anamelen, int flags);
-static int do_sendfile(struct thread *td, struct sendfile_args *uap,
-		   int compat);
-static int getsockname1(struct thread *td, struct getsockname_args *uap,
-			int compat);
-static int getpeername1(struct thread *td, struct getpeername_args *uap,
-			int compat);
-
-counter_u64_t sfstat[sizeof(struct sfstat) / sizeof(uint64_t)];
-
-static void
-sfstat_init(const void *unused)
-{
-
-	COUNTER_ARRAY_ALLOC(sfstat, sizeof(struct sfstat) / sizeof(uint64_t),
-	    M_WAITOK);
-}
-SYSINIT(sfstat, SI_SUB_MBUF, SI_ORDER_FIRST, sfstat_init, NULL);
-
-static int
-sfstat_sysctl(SYSCTL_HANDLER_ARGS)
-{
-	struct sfstat s;
-
-	COUNTER_ARRAY_COPY(sfstat, &s, sizeof(s) / sizeof(uint64_t));
-	if (req->newptr)
-		COUNTER_ARRAY_ZERO(sfstat, sizeof(s) / sizeof(uint64_t));
-	return (SYSCTL_OUT(req, &s, sizeof(s)));
-}
-SYSCTL_PROC(_kern_ipc, OID_AUTO, sfstat, CTLTYPE_OPAQUE | CTLFLAG_RW,
-    NULL, 0, sfstat_sysctl, "I", "sendfile statistics");
-
-/*
- * Convert a user file descriptor to a kernel file entry and check if required
- * capability rights are present.
- * A reference on the file entry is held upon returning.
- */
-int
-getsock_cap(struct thread *td, int fd, cap_rights_t *rightsp,
-    struct file **fpp, u_int *fflagp)
-{
-	struct file *fp;
-	int error;
-
-	error = fget_unlocked(td->td_proc->p_fd, fd, rightsp, &fp, NULL);
-	if (error != 0)
-		return (error);
-	if (fp->f_type != DTYPE_SOCKET) {
-		fdrop(fp, td);
-		return (ENOTSOCK);
-	}
-	if (fflagp != NULL)
-		*fflagp = fp->f_flag;
-	*fpp = fp;
-	return (0);
-}
-
-/*
- * System call interface to the socket abstraction.
- */
-#if defined(COMPAT_43)
-#define COMPAT_OLDSOCK
-#endif
-
-int
-sys_socket(td, uap)
-	struct thread *td;
-	struct socket_args /* {
-		int	domain;
-		int	type;
-		int	protocol;
-	} */ *uap;
-{
-	struct socket *so;
-	struct file *fp;
-	int fd, error, type, oflag, fflag;
-
-	AUDIT_ARG_SOCKET(uap->domain, uap->type, uap->protocol);
-
-	type = uap->type;
-	oflag = 0;
-	fflag = 0;
-	if ((type & SOCK_CLOEXEC) != 0) {
-		type &= ~SOCK_CLOEXEC;
-		oflag |= O_CLOEXEC;
-	}
-	if ((type & SOCK_NONBLOCK) != 0) {
-		type &= ~SOCK_NONBLOCK;
-		fflag |= FNONBLOCK;
-	}
-
-#ifdef MAC
-	error = mac_socket_check_create(td->td_ucred, uap->domain, type,
-	    uap->protocol);
-	if (error != 0)
-		return (error);
-#endif
-	error = falloc(td, &fp, &fd, oflag);
-	if (error != 0)
-		return (error);
-	/* An extra reference on `fp' has been held for us by falloc(). */
-	error = socreate(uap->domain, &so, type, uap->protocol,
-	    td->td_ucred, td);
-	if (error != 0) {
-		fdclose(td, fp, fd);
-	} else {
-		finit(fp, FREAD | FWRITE | fflag, DTYPE_SOCKET, so, &socketops);
-		if ((fflag & FNONBLOCK) != 0)
-			(void) fo_ioctl(fp, FIONBIO, &fflag, td->td_ucred, td);
-		td->td_retval[0] = fd;
-	}
-	fdrop(fp, td);
-	return (error);
-}
-
-/* ARGSUSED */
-int
-sys_bind(td, uap)
-	struct thread *td;
-	struct bind_args /* {
-		int	s;
-		caddr_t	name;
-		int	namelen;
-	} */ *uap;
-{
-	struct sockaddr *sa;
-	int error;
-
-	error = getsockaddr(&sa, uap->name, uap->namelen);
-	if (error == 0) {
-		error = kern_bindat(td, AT_FDCWD, uap->s, sa);
-		free(sa, M_SONAME);
-	}
-	return (error);
-}
-
-int
-kern_bindat(struct thread *td, int dirfd, int fd, struct sockaddr *sa)
-{
-	struct socket *so;
-	struct file *fp;
-	cap_rights_t rights;
-	int error;
-
-	AUDIT_ARG_FD(fd);
-	AUDIT_ARG_SOCKADDR(td, dirfd, sa);
-	error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_BIND),
-	    &fp, NULL);
-	if (error != 0)
-		return (error);
-	so = fp->f_data;
-#ifdef KTRACE
-	if (KTRPOINT(td, KTR_STRUCT))
-		ktrsockaddr(sa);
-#endif
-#ifdef MAC
-	error = mac_socket_check_bind(td->td_ucred, so, sa);
-	if (error == 0) {
-#endif
-		if (dirfd == AT_FDCWD)
-			error = sobind(so, sa, td);
-		else
-			error = sobindat(dirfd, so, sa, td);
-#ifdef MAC
-	}
-#endif
-	fdrop(fp, td);
-	return (error);
-}
-
-/* ARGSUSED */
-int
-sys_bindat(td, uap)
-	struct thread *td;
-	struct bindat_args /* {
-		int	fd;
-		int	s;
-		caddr_t	name;
-		int	namelen;
-	} */ *uap;
-{
-	struct sockaddr *sa;
-	int error;
-
-	error = getsockaddr(&sa, uap->name, uap->namelen);
-	if (error == 0) {
-		error = kern_bindat(td, uap->fd, uap->s, sa);
-		free(sa, M_SONAME);
-	}
-	return (error);
-}
-
-/* ARGSUSED */
-int
-sys_listen(td, uap)
-	struct thread *td;
-	struct listen_args /* {
-		int	s;
-		int	backlog;
-	} */ *uap;
-{
-	struct socket *so;
-	struct file *fp;
-	cap_rights_t rights;
-	int error;
-
-	AUDIT_ARG_FD(uap->s);
-	error = getsock_cap(td, uap->s, cap_rights_init(&rights, CAP_LISTEN),
-	    &fp, NULL);
-	if (error == 0) {
-		so = fp->f_data;
-#ifdef MAC
-		error = mac_socket_check_listen(td->td_ucred, so);
-		if (error == 0)
-#endif
-			error = solisten(so, uap->backlog, td);
-		fdrop(fp, td);
-	}
-	return(error);
-}
 
 /*
- * accept1()
- */
-static int
-accept1(td, s, uname, anamelen, flags)
-	struct thread *td;
-	int s;
-	struct sockaddr *uname;
-	socklen_t *anamelen;
-	int flags;
-{
-	struct sockaddr *name;
-	socklen_t namelen;
-	struct file *fp;
-	int error;
-
-	if (uname == NULL)
-		return (kern_accept4(td, s, NULL, NULL, flags, NULL));
-
-	error = copyin(anamelen, &namelen, sizeof (namelen));
-	if (error != 0)
-		return (error);
-
-	error = kern_accept4(td, s, &name, &namelen, flags, &fp);
-
-	if (error != 0)
-		return (error);
-
-	if (error == 0 && uname != NULL) {
-#ifdef COMPAT_OLDSOCK
-		if (flags & ACCEPT4_COMPAT)
-			((struct osockaddr *)name)->sa_family =
-			    name->sa_family;
-#endif
-		error = copyout(name, uname, namelen);
-	}
-	if (error == 0)
-		error = copyout(&namelen, anamelen,
-		    sizeof(namelen));
-	if (error != 0)
-		fdclose(td, fp, td->td_retval[0]);
-	fdrop(fp, td);
-	free(name, M_SONAME);
-	return (error);
-}
-
-int
-kern_accept(struct thread *td, int s, struct sockaddr **name,
-    socklen_t *namelen, struct file **fp)
-{
-	return (kern_accept4(td, s, name, namelen, ACCEPT4_INHERIT, fp));
-}
-
-int
-kern_accept4(struct thread *td, int s, struct sockaddr **name,
-    socklen_t *namelen, int flags, struct file **fp)
-{
-	struct file *headfp, *nfp = NULL;
-	struct sockaddr *sa = NULL;
-	struct socket *head, *so;
-	cap_rights_t rights;
-	u_int fflag;
-	pid_t pgid;
-	int error, fd, tmp;
-
-	if (name != NULL)
-		*name = NULL;
-
-	AUDIT_ARG_FD(s);
-	error = getsock_cap(td, s, cap_rights_init(&rights, CAP_ACCEPT),
-	    &headfp, &fflag);
-	if (error != 0)
-		return (error);
-	head = headfp->f_data;
-	if ((head->so_options & SO_ACCEPTCONN) == 0) {
-		error = EINVAL;
-		goto done;
-	}
-#ifdef MAC
-	error = mac_socket_check_accept(td->td_ucred, head);
-	if (error != 0)
-		goto done;
-#endif
-	error = falloc(td, &nfp, &fd, (flags & SOCK_CLOEXEC) ? O_CLOEXEC : 0);
-	if (error != 0)
-		goto done;
-	ACCEPT_LOCK();
-	if ((head->so_state & SS_NBIO) && TAILQ_EMPTY(&head->so_comp)) {
-		ACCEPT_UNLOCK();
-		error = EWOULDBLOCK;
-		goto noconnection;
-	}
-	while (TAILQ_EMPTY(&head->so_comp) && head->so_error == 0) {
-		if (head->so_rcv.sb_state & SBS_CANTRCVMORE) {
-			head->so_error = ECONNABORTED;
-			break;
-		}
-		error = msleep(&head->so_timeo, &accept_mtx, PSOCK | PCATCH,
-		    "accept", 0);
-		if (error != 0) {
-			ACCEPT_UNLOCK();
-			goto noconnection;
-		}
-	}
-	if (head->so_error) {
-		error = head->so_error;
-		head->so_error = 0;
-		ACCEPT_UNLOCK();
-		goto noconnection;
-	}
-	so = TAILQ_FIRST(&head->so_comp);
-	KASSERT(!(so->so_qstate & SQ_INCOMP), ("accept1: so SQ_INCOMP"));
-	KASSERT(so->so_qstate & SQ_COMP, ("accept1: so not SQ_COMP"));
-
-	/*
-	 * 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() and so_state update */
-	soref(so);			/* file descriptor reference */
-
-	TAILQ_REMOVE(&head->so_comp, so, so_list);
-	head->so_qlen--;
-	if (flags & ACCEPT4_INHERIT)
-		so->so_state |= (head->so_state & SS_NBIO);
-	else
-		so->so_state |= (flags & SOCK_NONBLOCK) ? SS_NBIO : 0;
-	so->so_qstate &= ~SQ_COMP;
-	so->so_head = NULL;
-
-	SOCK_UNLOCK(so);
-	ACCEPT_UNLOCK();
-
-	/* An extra reference on `nfp' has been held for us by falloc(). */
-	td->td_retval[0] = fd;
-
-	/* connection has been removed from the listen queue */
-	KNOTE_UNLOCKED(&head->so_rcv.sb_sel.si_note, 0);
-
-	if (flags & ACCEPT4_INHERIT) {
-		pgid = fgetown(&head->so_sigio);
-		if (pgid != 0)
-			fsetown(pgid, &so->so_sigio);
-	} else {
-		fflag &= ~(FNONBLOCK | FASYNC);
-		if (flags & SOCK_NONBLOCK)
-			fflag |= FNONBLOCK;
-	}
-
-	finit(nfp, fflag, DTYPE_SOCKET, so, &socketops);
-	/* Sync socket nonblocking/async state with file flags */
-	tmp = fflag & FNONBLOCK;
-	(void) fo_ioctl(nfp, FIONBIO, &tmp, td->td_ucred, td);
-	tmp = fflag & FASYNC;
-	(void) fo_ioctl(nfp, FIOASYNC, &tmp, td->td_ucred, td);
-	sa = 0;
-	error = soaccept(so, &sa);
-	if (error != 0)
-		goto noconnection;
-	if (sa == NULL) {
-		if (name)
-			*namelen = 0;
-		goto done;
-	}
-	AUDIT_ARG_SOCKADDR(td, AT_FDCWD, sa);
-	if (name) {
-		/* check sa_len before it is destroyed */
-		if (*namelen > sa->sa_len)
-			*namelen = sa->sa_len;
-#ifdef KTRACE
-		if (KTRPOINT(td, KTR_STRUCT))
-			ktrsockaddr(sa);
-#endif
-		*name = sa;
-		sa = NULL;
-	}
-noconnection:
-	free(sa, M_SONAME);
-
-	/*
-	 * close the new descriptor, assuming someone hasn't ripped it
-	 * out from under us.
-	 */
-	if (error != 0)
-		fdclose(td, nfp, fd);
-
-	/*
-	 * Release explicitly held references before returning.  We return
-	 * a reference on nfp to the caller on success if they request it.
-	 */
-done:
-	if (fp != NULL) {
-		if (error == 0) {
-			*fp = nfp;
-			nfp = NULL;
-		} else
-			*fp = NULL;
-	}
-	if (nfp != NULL)
-		fdrop(nfp, td);
-	fdrop(headfp, td);
-	return (error);
-}
-
-int
-sys_accept(td, uap)
-	struct thread *td;
-	struct accept_args *uap;
-{
-
-	return (accept1(td, uap->s, uap->name, uap->anamelen, ACCEPT4_INHERIT));
-}
-
-int
-sys_accept4(td, uap)
-	struct thread *td;
-	struct accept4_args *uap;
-{
-
-	if (uap->flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
-		return (EINVAL);
-
-	return (accept1(td, uap->s, uap->name, uap->anamelen, uap->flags));
-}
-
-#ifdef COMPAT_OLDSOCK
-int
-oaccept(td, uap)
-	struct thread *td;
-	struct accept_args *uap;
-{
-
-	return (accept1(td, uap->s, uap->name, uap->anamelen,
-	    ACCEPT4_INHERIT | ACCEPT4_COMPAT));
-}
-#endif /* COMPAT_OLDSOCK */
-
-/* ARGSUSED */
-int
-sys_connect(td, uap)
-	struct thread *td;
-	struct connect_args /* {
-		int	s;
-		caddr_t	name;
-		int	namelen;
-	} */ *uap;
-{
-	struct sockaddr *sa;
-	int error;
-
-	error = getsockaddr(&sa, uap->name, uap->namelen);
-	if (error == 0) {
-		error = kern_connectat(td, AT_FDCWD, uap->s, sa);
-		free(sa, M_SONAME);
-	}
-	return (error);
-}
-
-int
-kern_connectat(struct thread *td, int dirfd, int fd, struct sockaddr *sa)
-{
-	struct socket *so;
-	struct file *fp;
-	cap_rights_t rights;
-	int error, interrupted = 0;
-
-	AUDIT_ARG_FD(fd);
-	AUDIT_ARG_SOCKADDR(td, dirfd, sa);
-	error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_CONNECT),
-	    &fp, NULL);
-	if (error != 0)
-		return (error);
-	so = fp->f_data;
-	if (so->so_state & SS_ISCONNECTING) {
-		error = EALREADY;
-		goto done1;
-	}
-#ifdef KTRACE
-	if (KTRPOINT(td, KTR_STRUCT))
-		ktrsockaddr(sa);
-#endif
-#ifdef MAC
-	error = mac_socket_check_connect(td->td_ucred, so, sa);
-	if (error != 0)
-		goto bad;
-#endif
-	if (dirfd == AT_FDCWD)
-		error = soconnect(so, sa, td);
-	else
-		error = soconnectat(dirfd, so, sa, td);
-	if (error != 0)
-		goto bad;
-	if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
-		error = EINPROGRESS;
-		goto done1;
-	}
-	SOCK_LOCK(so);
-	while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
-		error = msleep(&so->so_timeo, SOCK_MTX(so), PSOCK | PCATCH,
-		    "connec", 0);
-		if (error != 0) {
-			if (error == EINTR || error == ERESTART)
-				interrupted = 1;
-			break;
-		}
-	}
-	if (error == 0) {
-		error = so->so_error;
-		so->so_error = 0;
-	}
-	SOCK_UNLOCK(so);
-bad:
-	if (!interrupted)
-		so->so_state &= ~SS_ISCONNECTING;
-	if (error == ERESTART)
-		error = EINTR;
-done1:
-	fdrop(fp, td);
-	return (error);
-}
-
-/* ARGSUSED */
-int
-sys_connectat(td, uap)
-	struct thread *td;
-	struct connectat_args /* {
-		int	fd;
-		int	s;
-		caddr_t	name;
-		int	namelen;
-	} */ *uap;
-{
-	struct sockaddr *sa;
-	int error;
-
-	error = getsockaddr(&sa, uap->name, uap->namelen);
-	if (error == 0) {
-		error = kern_connectat(td, uap->fd, uap->s, sa);
-		free(sa, M_SONAME);
-	}
-	return (error);
-}
-
-int
-kern_socketpair(struct thread *td, int domain, int type, int protocol,
-    int *rsv)
-{
-	struct file *fp1, *fp2;
-	struct socket *so1, *so2;
-	int fd, error, oflag, fflag;
-
-	AUDIT_ARG_SOCKET(domain, type, protocol);
-
-	oflag = 0;
-	fflag = 0;
-	if ((type & SOCK_CLOEXEC) != 0) {
-		type &= ~SOCK_CLOEXEC;
-		oflag |= O_CLOEXEC;
-	}
-	if ((type & SOCK_NONBLOCK) != 0) {
-		type &= ~SOCK_NONBLOCK;
-		fflag |= FNONBLOCK;
-	}
-#ifdef MAC
-	/* We might want to have a separate check for socket pairs. */
-	error = mac_socket_check_create(td->td_ucred, domain, type,
-	    protocol);
-	if (error != 0)
-		return (error);
-#endif
-	error = socreate(domain, &so1, type, protocol, td->td_ucred, td);
-	if (error != 0)
-		return (error);
-	error = socreate(domain, &so2, type, protocol, td->td_ucred, td);
-	if (error != 0)
-		goto free1;
-	/* On success extra reference to `fp1' and 'fp2' is set by falloc. */
-	error = falloc(td, &fp1, &fd, oflag);
-	if (error != 0)
-		goto free2;
-	rsv[0] = fd;
-	fp1->f_data = so1;	/* so1 already has ref count */
-	error = falloc(td, &fp2, &fd, oflag);
-	if (error != 0)
-		goto free3;
-	fp2->f_data = so2;	/* so2 already has ref count */
-	rsv[1] = fd;
-	error = soconnect2(so1, so2);
-	if (error != 0)
-		goto free4;
-	if (type == SOCK_DGRAM) {
-		/*
-		 * Datagram socket connection is asymmetric.
-		 */
-		 error = soconnect2(so2, so1);
-		 if (error != 0)
-			goto free4;
-	}
-	finit(fp1, FREAD | FWRITE | fflag, DTYPE_SOCKET, fp1->f_data,
-	    &socketops);
-	finit(fp2, FREAD | FWRITE | fflag, DTYPE_SOCKET, fp2->f_data,
-	    &socketops);
-	if ((fflag & FNONBLOCK) != 0) {
-		(void) fo_ioctl(fp1, FIONBIO, &fflag, td->td_ucred, td);
-		(void) fo_ioctl(fp2, FIONBIO, &fflag, td->td_ucred, td);
-	}
-	fdrop(fp1, td);
-	fdrop(fp2, td);
-	return (0);
-free4:
-	fdclose(td, fp2, rsv[1]);
-	fdrop(fp2, td);
-free3:
-	fdclose(td, fp1, rsv[0]);
-	fdrop(fp1, td);
-free2:
-	if (so2 != NULL)
-		(void)soclose(so2);
-free1:
-	if (so1 != NULL)
-		(void)soclose(so1);
-	return (error);
-}
-
-int
-sys_socketpair(struct thread *td, struct socketpair_args *uap)
-{
-	int error, sv[2];
-
-	error = kern_socketpair(td, uap->domain, uap->type,
-	    uap->protocol, sv);
-	if (error != 0)
-		return (error);
-	error = copyout(sv, uap->rsv, 2 * sizeof(int));
-	if (error != 0) {
-		(void)kern_close(td, sv[0]);
-		(void)kern_close(td, sv[1]);
-	}
-	return (error);
-}
-
-static int
-sendit(td, s, mp, flags)
-	struct thread *td;
-	int s;
-	struct msghdr *mp;
-	int flags;
-{
-	struct mbuf *control;
-	struct sockaddr *to;
-	int error;
-
-#ifdef CAPABILITY_MODE
-	if (IN_CAPABILITY_MODE(td) && (mp->msg_name != NULL))
-		return (ECAPMODE);
-#endif
-
-	if (mp->msg_name != NULL) {
-		error = getsockaddr(&to, mp->msg_name, mp->msg_namelen);
-		if (error != 0) {
-			to = NULL;
-			goto bad;
-		}
-		mp->msg_name = to;
-	} else {
-		to = NULL;
-	}
-
-	if (mp->msg_control) {
-		if (mp->msg_controllen < sizeof(struct cmsghdr)
-#ifdef COMPAT_OLDSOCK
-		    && mp->msg_flags != MSG_COMPAT
-#endif
-		) {
-			error = EINVAL;
-			goto bad;
-		}
-		error = sockargs(&control, mp->msg_control,
-		    mp->msg_controllen, MT_CONTROL);
-		if (error != 0)
-			goto bad;
-#ifdef COMPAT_OLDSOCK
-		if (mp->msg_flags == MSG_COMPAT) {
-			struct cmsghdr *cm;
-
-			M_PREPEND(control, sizeof(*cm), M_WAITOK);
-			cm = mtod(control, struct cmsghdr *);
-			cm->cmsg_len = control->m_len;
-			cm->cmsg_level = SOL_SOCKET;
-			cm->cmsg_type = SCM_RIGHTS;
-		}
-#endif
-	} else {
-		control = NULL;
-	}
-
-	error = kern_sendit(td, s, mp, flags, control, UIO_USERSPACE);
-
-bad:
-	free(to, M_SONAME);
-	return (error);
-}
-
-int
-kern_sendit(td, s, mp, flags, control, segflg)
-	struct thread *td;
-	int s;
-	struct msghdr *mp;
-	int flags;
-	struct mbuf *control;
-	enum uio_seg segflg;
-{
-	struct file *fp;
-	struct uio auio;
-	struct iovec *iov;
-	struct socket *so;
-	cap_rights_t rights;
-#ifdef KTRACE
-	struct uio *ktruio = NULL;
-#endif
-	ssize_t len;
-	int i, error;
-
-	AUDIT_ARG_FD(s);
-	cap_rights_init(&rights, CAP_SEND);
-	if (mp->msg_name != NULL) {
-		AUDIT_ARG_SOCKADDR(td, AT_FDCWD, mp->msg_name);
-		cap_rights_set(&rights, CAP_CONNECT);
-	}
-	error = getsock_cap(td, s, &rights, &fp, NULL);
-	if (error != 0)
-		return (error);
-	so = (struct socket *)fp->f_data;
-
-#ifdef KTRACE
-	if (mp->msg_name != NULL && KTRPOINT(td, KTR_STRUCT))
-		ktrsockaddr(mp->msg_name);
-#endif
-#ifdef MAC
-	if (mp->msg_name != NULL) {
-		error = mac_socket_check_connect(td->td_ucred, so,
-		    mp->msg_name);
-		if (error != 0)
-			goto bad;
-	}
-	error = mac_socket_check_send(td->td_ucred, so);
-	if (error != 0)
-		goto bad;
-#endif
-
-	auio.uio_iov = mp->msg_iov;
-	auio.uio_iovcnt = mp->msg_iovlen;
-	auio.uio_segflg = segflg;
-	auio.uio_rw = UIO_WRITE;
-	auio.uio_td = td;
-	auio.uio_offset = 0;			/* XXX */
-	auio.uio_resid = 0;
-	iov = mp->msg_iov;
-	for (i = 0; i < mp->msg_iovlen; i++, iov++) {
-		if ((auio.uio_resid += iov->iov_len) < 0) {
-			error = EINVAL;
-			goto bad;
-		}
-	}
-#ifdef KTRACE
-	if (KTRPOINT(td, KTR_GENIO))
-		ktruio = cloneuio(&auio);
-#endif
-	len = auio.uio_resid;
-	error = sosend(so, mp->msg_name, &auio, 0, control, flags, td);
-	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) &&
-		    !(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(s, UIO_WRITE, ktruio, error);
-	}
-#endif
-bad:
-	fdrop(fp, td);
-	return (error);
-}
-
-int
-sys_sendto(td, uap)
-	struct thread *td;
-	struct sendto_args /* {
-		int	s;
-		caddr_t	buf;
-		size_t	len;
-		int	flags;
-		caddr_t	to;
-		int	tolen;
-	} */ *uap;
-{
-	struct msghdr msg;
-	struct iovec aiov;
-
-	msg.msg_name = uap->to;
-	msg.msg_namelen = uap->tolen;
-	msg.msg_iov = &aiov;
-	msg.msg_iovlen = 1;
-	msg.msg_control = 0;
-#ifdef COMPAT_OLDSOCK
-	msg.msg_flags = 0;
-#endif
-	aiov.iov_base = uap->buf;
-	aiov.iov_len = uap->len;
-	return (sendit(td, uap->s, &msg, uap->flags));
-}
-
-#ifdef COMPAT_OLDSOCK
-int
-osend(td, uap)
-	struct thread *td;
-	struct osend_args /* {
-		int	s;
-		caddr_t	buf;
-		int	len;
-		int	flags;
-	} */ *uap;
-{
-	struct msghdr msg;
-	struct iovec aiov;
-
-	msg.msg_name = 0;
-	msg.msg_namelen = 0;
-	msg.msg_iov = &aiov;
-	msg.msg_iovlen = 1;
-	aiov.iov_base = uap->buf;
-	aiov.iov_len = uap->len;
-	msg.msg_control = 0;
-	msg.msg_flags = 0;
-	return (sendit(td, uap->s, &msg, uap->flags));
-}
-
-int
-osendmsg(td, uap)
-	struct thread *td;
-	struct osendmsg_args /* {
-		int	s;
-		caddr_t	msg;
-		int	flags;
-	} */ *uap;
-{
-	struct msghdr msg;
-	struct iovec *iov;
-	int error;
-
-	error = copyin(uap->msg, &msg, sizeof (struct omsghdr));
-	if (error != 0)
-		return (error);
-	error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
-	if (error != 0)
-		return (error);
-	msg.msg_iov = iov;
-	msg.msg_flags = MSG_COMPAT;
-	error = sendit(td, uap->s, &msg, uap->flags);
-	free(iov, M_IOV);
-	return (error);
-}
-#endif
-
-int
-sys_sendmsg(td, uap)

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


More information about the svn-src-head mailing list