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 <gleb...@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 ***
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to