The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/uipc_syscalls.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 1982, 1986, 1989, 1990, 1993
    3  *      The Regents of the University of California.  All rights reserved.
    4  *
    5  * sendfile(2) and related extensions:
    6  * Copyright (c) 1998, David Greenman. All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 4. Neither the name of the University nor the names of its contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  *
   32  *      @(#)uipc_syscalls.c     8.4 (Berkeley) 2/21/94
   33  */
   34 
   35 #include <sys/cdefs.h>
   36 __FBSDID("$FreeBSD: releng/8.0/sys/kern/uipc_syscalls.c 197855 2009-10-08 11:28:32Z kib $");
   37 
   38 #include "opt_inet.h"
   39 #include "opt_inet6.h"
   40 #include "opt_sctp.h"
   41 #include "opt_compat.h"
   42 #include "opt_ktrace.h"
   43 
   44 #include <sys/param.h>
   45 #include <sys/systm.h>
   46 #include <sys/kernel.h>
   47 #include <sys/lock.h>
   48 #include <sys/mutex.h>
   49 #include <sys/sysproto.h>
   50 #include <sys/malloc.h>
   51 #include <sys/filedesc.h>
   52 #include <sys/event.h>
   53 #include <sys/proc.h>
   54 #include <sys/fcntl.h>
   55 #include <sys/file.h>
   56 #include <sys/filio.h>
   57 #include <sys/mount.h>
   58 #include <sys/mbuf.h>
   59 #include <sys/protosw.h>
   60 #include <sys/sf_buf.h>
   61 #include <sys/socket.h>
   62 #include <sys/socketvar.h>
   63 #include <sys/signalvar.h>
   64 #include <sys/syscallsubr.h>
   65 #include <sys/sysctl.h>
   66 #include <sys/uio.h>
   67 #include <sys/vnode.h>
   68 #ifdef KTRACE
   69 #include <sys/ktrace.h>
   70 #endif
   71 
   72 #include <net/vnet.h>
   73 
   74 #include <security/audit/audit.h>
   75 #include <security/mac/mac_framework.h>
   76 
   77 #include <vm/vm.h>
   78 #include <vm/vm_object.h>
   79 #include <vm/vm_page.h>
   80 #include <vm/vm_pageout.h>
   81 #include <vm/vm_kern.h>
   82 #include <vm/vm_extern.h>
   83 
   84 #if defined(INET) || defined(INET6)
   85 #ifdef SCTP
   86 #include <netinet/sctp.h>
   87 #include <netinet/sctp_peeloff.h>
   88 #endif /* SCTP */
   89 #endif /* INET || INET6 */
   90 
   91 static int sendit(struct thread *td, int s, struct msghdr *mp, int flags);
   92 static int recvit(struct thread *td, int s, struct msghdr *mp, void *namelenp);
   93 
   94 static int accept1(struct thread *td, struct accept_args *uap, int compat);
   95 static int do_sendfile(struct thread *td, struct sendfile_args *uap, int compat);
   96 static int getsockname1(struct thread *td, struct getsockname_args *uap,
   97                         int compat);
   98 static int getpeername1(struct thread *td, struct getpeername_args *uap,
   99                         int compat);
  100 
  101 /*
  102  * NSFBUFS-related variables and associated sysctls
  103  */
  104 int nsfbufs;
  105 int nsfbufspeak;
  106 int nsfbufsused;
  107 
  108 SYSCTL_INT(_kern_ipc, OID_AUTO, nsfbufs, CTLFLAG_RDTUN, &nsfbufs, 0,
  109     "Maximum number of sendfile(2) sf_bufs available");
  110 SYSCTL_INT(_kern_ipc, OID_AUTO, nsfbufspeak, CTLFLAG_RD, &nsfbufspeak, 0,
  111     "Number of sendfile(2) sf_bufs at peak usage");
  112 SYSCTL_INT(_kern_ipc, OID_AUTO, nsfbufsused, CTLFLAG_RD, &nsfbufsused, 0,
  113     "Number of sendfile(2) sf_bufs in use");
  114 
  115 /*
  116  * Convert a user file descriptor to a kernel file entry.  A reference on the
  117  * file entry is held upon returning.  This is lighter weight than
  118  * fgetsock(), which bumps the socket reference drops the file reference
  119  * count instead, as this approach avoids several additional mutex operations
  120  * associated with the additional reference count.  If requested, return the
  121  * open file flags.
  122  */
  123 static int
  124 getsock(struct filedesc *fdp, int fd, struct file **fpp, u_int *fflagp)
  125 {
  126         struct file *fp;
  127         int error;
  128 
  129         fp = NULL;
  130         if (fdp == NULL || (fp = fget_unlocked(fdp, fd)) == NULL) {
  131                 error = EBADF;
  132         } else if (fp->f_type != DTYPE_SOCKET) {
  133                 fdrop(fp, curthread);
  134                 fp = NULL;
  135                 error = ENOTSOCK;
  136         } else {
  137                 if (fflagp != NULL)
  138                         *fflagp = fp->f_flag;
  139                 error = 0;
  140         }
  141         *fpp = fp;
  142         return (error);
  143 }
  144 
  145 /*
  146  * System call interface to the socket abstraction.
  147  */
  148 #if defined(COMPAT_43)
  149 #define COMPAT_OLDSOCK
  150 #endif
  151 
  152 int
  153 socket(td, uap)
  154         struct thread *td;
  155         struct socket_args /* {
  156                 int     domain;
  157                 int     type;
  158                 int     protocol;
  159         } */ *uap;
  160 {
  161         struct filedesc *fdp;
  162         struct socket *so;
  163         struct file *fp;
  164         int fd, error;
  165 
  166         AUDIT_ARG_SOCKET(uap->domain, uap->type, uap->protocol);
  167 #ifdef MAC
  168         error = mac_socket_check_create(td->td_ucred, uap->domain, uap->type,
  169             uap->protocol);
  170         if (error)
  171                 return (error);
  172 #endif
  173         fdp = td->td_proc->p_fd;
  174         error = falloc(td, &fp, &fd);
  175         if (error)
  176                 return (error);
  177         /* An extra reference on `fp' has been held for us by falloc(). */
  178         error = socreate(uap->domain, &so, uap->type, uap->protocol,
  179             td->td_ucred, td);
  180         if (error) {
  181                 fdclose(fdp, fp, fd, td);
  182         } else {
  183                 finit(fp, FREAD | FWRITE, DTYPE_SOCKET, so, &socketops);
  184                 td->td_retval[0] = fd;
  185         }
  186         fdrop(fp, td);
  187         return (error);
  188 }
  189 
  190 /* ARGSUSED */
  191 int
  192 bind(td, uap)
  193         struct thread *td;
  194         struct bind_args /* {
  195                 int     s;
  196                 caddr_t name;
  197                 int     namelen;
  198         } */ *uap;
  199 {
  200         struct sockaddr *sa;
  201         int error;
  202 
  203         if ((error = getsockaddr(&sa, uap->name, uap->namelen)) != 0)
  204                 return (error);
  205 
  206         error = kern_bind(td, uap->s, sa);
  207         free(sa, M_SONAME);
  208         return (error);
  209 }
  210 
  211 int
  212 kern_bind(td, fd, sa)
  213         struct thread *td;
  214         int fd;
  215         struct sockaddr *sa;
  216 {
  217         struct socket *so;
  218         struct file *fp;
  219         int error;
  220 
  221         AUDIT_ARG_FD(fd);
  222         error = getsock(td->td_proc->p_fd, fd, &fp, NULL);
  223         if (error)
  224                 return (error);
  225         so = fp->f_data;
  226 #ifdef KTRACE
  227         if (KTRPOINT(td, KTR_STRUCT))
  228                 ktrsockaddr(sa);
  229 #endif
  230 #ifdef MAC
  231         error = mac_socket_check_bind(td->td_ucred, so, sa);
  232         if (error == 0)
  233 #endif
  234                 error = sobind(so, sa, td);
  235         fdrop(fp, td);
  236         return (error);
  237 }
  238 
  239 /* ARGSUSED */
  240 int
  241 listen(td, uap)
  242         struct thread *td;
  243         struct listen_args /* {
  244                 int     s;
  245                 int     backlog;
  246         } */ *uap;
  247 {
  248         struct socket *so;
  249         struct file *fp;
  250         int error;
  251 
  252         AUDIT_ARG_FD(uap->s);
  253         error = getsock(td->td_proc->p_fd, uap->s, &fp, NULL);
  254         if (error == 0) {
  255                 so = fp->f_data;
  256 #ifdef MAC
  257                 error = mac_socket_check_listen(td->td_ucred, so);
  258                 if (error == 0) {
  259 #endif
  260                         CURVNET_SET(so->so_vnet);
  261                         error = solisten(so, uap->backlog, td);
  262                         CURVNET_RESTORE();
  263 #ifdef MAC
  264                 }
  265 #endif
  266                 fdrop(fp, td);
  267         }
  268         return(error);
  269 }
  270 
  271 /*
  272  * accept1()
  273  */
  274 static int
  275 accept1(td, uap, compat)
  276         struct thread *td;
  277         struct accept_args /* {
  278                 int     s;
  279                 struct sockaddr * __restrict name;
  280                 socklen_t       * __restrict anamelen;
  281         } */ *uap;
  282         int compat;
  283 {
  284         struct sockaddr *name;
  285         socklen_t namelen;
  286         struct file *fp;
  287         int error;
  288 
  289         if (uap->name == NULL)
  290                 return (kern_accept(td, uap->s, NULL, NULL, NULL));
  291 
  292         error = copyin(uap->anamelen, &namelen, sizeof (namelen));
  293         if (error)
  294                 return (error);
  295 
  296         error = kern_accept(td, uap->s, &name, &namelen, &fp);
  297 
  298         /*
  299          * return a namelen of zero for older code which might
  300          * ignore the return value from accept.
  301          */
  302         if (error) {
  303                 (void) copyout(&namelen,
  304                     uap->anamelen, sizeof(*uap->anamelen));
  305                 return (error);
  306         }
  307 
  308         if (error == 0 && name != NULL) {
  309 #ifdef COMPAT_OLDSOCK
  310                 if (compat)
  311                         ((struct osockaddr *)name)->sa_family =
  312                             name->sa_family;
  313 #endif
  314                 error = copyout(name, uap->name, namelen);
  315         }
  316         if (error == 0)
  317                 error = copyout(&namelen, uap->anamelen,
  318                     sizeof(namelen));
  319         if (error)
  320                 fdclose(td->td_proc->p_fd, fp, td->td_retval[0], td);
  321         fdrop(fp, td);
  322         free(name, M_SONAME);
  323         return (error);
  324 }
  325 
  326 int
  327 kern_accept(struct thread *td, int s, struct sockaddr **name,
  328     socklen_t *namelen, struct file **fp)
  329 {
  330         struct filedesc *fdp;
  331         struct file *headfp, *nfp = NULL;
  332         struct sockaddr *sa = NULL;
  333         int error;
  334         struct socket *head, *so;
  335         int fd;
  336         u_int fflag;
  337         pid_t pgid;
  338         int tmp;
  339 
  340         if (name) {
  341                 *name = NULL;
  342                 if (*namelen < 0)
  343                         return (EINVAL);
  344         }
  345 
  346         AUDIT_ARG_FD(s);
  347         fdp = td->td_proc->p_fd;
  348         error = getsock(fdp, s, &headfp, &fflag);
  349         if (error)
  350                 return (error);
  351         head = headfp->f_data;
  352         if ((head->so_options & SO_ACCEPTCONN) == 0) {
  353                 error = EINVAL;
  354                 goto done;
  355         }
  356 #ifdef MAC
  357         error = mac_socket_check_accept(td->td_ucred, head);
  358         if (error != 0)
  359                 goto done;
  360 #endif
  361         error = falloc(td, &nfp, &fd);
  362         if (error)
  363                 goto done;
  364         ACCEPT_LOCK();
  365         if ((head->so_state & SS_NBIO) && TAILQ_EMPTY(&head->so_comp)) {
  366                 ACCEPT_UNLOCK();
  367                 error = EWOULDBLOCK;
  368                 goto noconnection;
  369         }
  370         while (TAILQ_EMPTY(&head->so_comp) && head->so_error == 0) {
  371                 if (head->so_rcv.sb_state & SBS_CANTRCVMORE) {
  372                         head->so_error = ECONNABORTED;
  373                         break;
  374                 }
  375                 error = msleep(&head->so_timeo, &accept_mtx, PSOCK | PCATCH,
  376                     "accept", 0);
  377                 if (error) {
  378                         ACCEPT_UNLOCK();
  379                         goto noconnection;
  380                 }
  381         }
  382         if (head->so_error) {
  383                 error = head->so_error;
  384                 head->so_error = 0;
  385                 ACCEPT_UNLOCK();
  386                 goto noconnection;
  387         }
  388         so = TAILQ_FIRST(&head->so_comp);
  389         KASSERT(!(so->so_qstate & SQ_INCOMP), ("accept1: so SQ_INCOMP"));
  390         KASSERT(so->so_qstate & SQ_COMP, ("accept1: so not SQ_COMP"));
  391 
  392         /*
  393          * Before changing the flags on the socket, we have to bump the
  394          * reference count.  Otherwise, if the protocol calls sofree(),
  395          * the socket will be released due to a zero refcount.
  396          */
  397         SOCK_LOCK(so);                  /* soref() and so_state update */
  398         soref(so);                      /* file descriptor reference */
  399 
  400         TAILQ_REMOVE(&head->so_comp, so, so_list);
  401         head->so_qlen--;
  402         so->so_state |= (head->so_state & SS_NBIO);
  403         so->so_qstate &= ~SQ_COMP;
  404         so->so_head = NULL;
  405 
  406         SOCK_UNLOCK(so);
  407         ACCEPT_UNLOCK();
  408 
  409         /* An extra reference on `nfp' has been held for us by falloc(). */
  410         td->td_retval[0] = fd;
  411 
  412         /* connection has been removed from the listen queue */
  413         KNOTE_UNLOCKED(&head->so_rcv.sb_sel.si_note, 0);
  414 
  415         pgid = fgetown(&head->so_sigio);
  416         if (pgid != 0)
  417                 fsetown(pgid, &so->so_sigio);
  418 
  419         finit(nfp, fflag, DTYPE_SOCKET, so, &socketops);
  420         /* Sync socket nonblocking/async state with file flags */
  421         tmp = fflag & FNONBLOCK;
  422         (void) fo_ioctl(nfp, FIONBIO, &tmp, td->td_ucred, td);
  423         tmp = fflag & FASYNC;
  424         (void) fo_ioctl(nfp, FIOASYNC, &tmp, td->td_ucred, td);
  425         sa = 0;
  426         CURVNET_SET(so->so_vnet);
  427         error = soaccept(so, &sa);
  428         CURVNET_RESTORE();
  429         if (error) {
  430                 /*
  431                  * return a namelen of zero for older code which might
  432                  * ignore the return value from accept.
  433                  */
  434                 if (name)
  435                         *namelen = 0;
  436                 goto noconnection;
  437         }
  438         if (sa == NULL) {
  439                 if (name)
  440                         *namelen = 0;
  441                 goto done;
  442         }
  443         if (name) {
  444                 /* check sa_len before it is destroyed */
  445                 if (*namelen > sa->sa_len)
  446                         *namelen = sa->sa_len;
  447 #ifdef KTRACE
  448                 if (KTRPOINT(td, KTR_STRUCT))
  449                         ktrsockaddr(sa);
  450 #endif
  451                 *name = sa;
  452                 sa = NULL;
  453         }
  454 noconnection:
  455         if (sa)
  456                 free(sa, M_SONAME);
  457 
  458         /*
  459          * close the new descriptor, assuming someone hasn't ripped it
  460          * out from under us.
  461          */
  462         if (error)
  463                 fdclose(fdp, nfp, fd, td);
  464 
  465         /*
  466          * Release explicitly held references before returning.  We return
  467          * a reference on nfp to the caller on success if they request it.
  468          */
  469 done:
  470         if (fp != NULL) {
  471                 if (error == 0) {
  472                         *fp = nfp;
  473                         nfp = NULL;
  474                 } else
  475                         *fp = NULL;
  476         }
  477         if (nfp != NULL)
  478                 fdrop(nfp, td);
  479         fdrop(headfp, td);
  480         return (error);
  481 }
  482 
  483 int
  484 accept(td, uap)
  485         struct thread *td;
  486         struct accept_args *uap;
  487 {
  488 
  489         return (accept1(td, uap, 0));
  490 }
  491 
  492 #ifdef COMPAT_OLDSOCK
  493 int
  494 oaccept(td, uap)
  495         struct thread *td;
  496         struct accept_args *uap;
  497 {
  498 
  499         return (accept1(td, uap, 1));
  500 }
  501 #endif /* COMPAT_OLDSOCK */
  502 
  503 /* ARGSUSED */
  504 int
  505 connect(td, uap)
  506         struct thread *td;
  507         struct connect_args /* {
  508                 int     s;
  509                 caddr_t name;
  510                 int     namelen;
  511         } */ *uap;
  512 {
  513         struct sockaddr *sa;
  514         int error;
  515 
  516         error = getsockaddr(&sa, uap->name, uap->namelen);
  517         if (error)
  518                 return (error);
  519 
  520         error = kern_connect(td, uap->s, sa);
  521         free(sa, M_SONAME);
  522         return (error);
  523 }
  524 
  525 
  526 int
  527 kern_connect(td, fd, sa)
  528         struct thread *td;
  529         int fd;
  530         struct sockaddr *sa;
  531 {
  532         struct socket *so;
  533         struct file *fp;
  534         int error;
  535         int interrupted = 0;
  536 
  537         AUDIT_ARG_FD(fd);
  538         error = getsock(td->td_proc->p_fd, fd, &fp, NULL);
  539         if (error)
  540                 return (error);
  541         so = fp->f_data;
  542         if (so->so_state & SS_ISCONNECTING) {
  543                 error = EALREADY;
  544                 goto done1;
  545         }
  546 #ifdef KTRACE
  547         if (KTRPOINT(td, KTR_STRUCT))
  548                 ktrsockaddr(sa);
  549 #endif
  550 #ifdef MAC
  551         error = mac_socket_check_connect(td->td_ucred, so, sa);
  552         if (error)
  553                 goto bad;
  554 #endif
  555         error = soconnect(so, sa, td);
  556         if (error)
  557                 goto bad;
  558         if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
  559                 error = EINPROGRESS;
  560                 goto done1;
  561         }
  562         SOCK_LOCK(so);
  563         while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
  564                 error = msleep(&so->so_timeo, SOCK_MTX(so), PSOCK | PCATCH,
  565                     "connec", 0);
  566                 if (error) {
  567                         if (error == EINTR || error == ERESTART)
  568                                 interrupted = 1;
  569                         break;
  570                 }
  571         }
  572         if (error == 0) {
  573                 error = so->so_error;
  574                 so->so_error = 0;
  575         }
  576         SOCK_UNLOCK(so);
  577 bad:
  578         if (!interrupted)
  579                 so->so_state &= ~SS_ISCONNECTING;
  580         if (error == ERESTART)
  581                 error = EINTR;
  582 done1:
  583         fdrop(fp, td);
  584         return (error);
  585 }
  586 
  587 int
  588 kern_socketpair(struct thread *td, int domain, int type, int protocol,
  589     int *rsv)
  590 {
  591         struct filedesc *fdp = td->td_proc->p_fd;
  592         struct file *fp1, *fp2;
  593         struct socket *so1, *so2;
  594         int fd, error;
  595 
  596         AUDIT_ARG_SOCKET(domain, type, protocol);
  597 #ifdef MAC
  598         /* We might want to have a separate check for socket pairs. */
  599         error = mac_socket_check_create(td->td_ucred, domain, type,
  600             protocol);
  601         if (error)
  602                 return (error);
  603 #endif
  604         error = socreate(domain, &so1, type, protocol, td->td_ucred, td);
  605         if (error)
  606                 return (error);
  607         error = socreate(domain, &so2, type, protocol, td->td_ucred, td);
  608         if (error)
  609                 goto free1;
  610         /* On success extra reference to `fp1' and 'fp2' is set by falloc. */
  611         error = falloc(td, &fp1, &fd);
  612         if (error)
  613                 goto free2;
  614         rsv[0] = fd;
  615         fp1->f_data = so1;      /* so1 already has ref count */
  616         error = falloc(td, &fp2, &fd);
  617         if (error)
  618                 goto free3;
  619         fp2->f_data = so2;      /* so2 already has ref count */
  620         rsv[1] = fd;
  621         error = soconnect2(so1, so2);
  622         if (error)
  623                 goto free4;
  624         if (type == SOCK_DGRAM) {
  625                 /*
  626                  * Datagram socket connection is asymmetric.
  627                  */
  628                  error = soconnect2(so2, so1);
  629                  if (error)
  630                         goto free4;
  631         }
  632         finit(fp1, FREAD | FWRITE, DTYPE_SOCKET, fp1->f_data, &socketops);
  633         finit(fp2, FREAD | FWRITE, DTYPE_SOCKET, fp2->f_data, &socketops);
  634         fdrop(fp1, td);
  635         fdrop(fp2, td);
  636         return (0);
  637 free4:
  638         fdclose(fdp, fp2, rsv[1], td);
  639         fdrop(fp2, td);
  640 free3:
  641         fdclose(fdp, fp1, rsv[0], td);
  642         fdrop(fp1, td);
  643 free2:
  644         if (so2 != NULL)
  645                 (void)soclose(so2);
  646 free1:
  647         if (so1 != NULL)
  648                 (void)soclose(so1);
  649         return (error);
  650 }
  651 
  652 int
  653 socketpair(struct thread *td, struct socketpair_args *uap)
  654 {
  655         int error, sv[2];
  656 
  657         error = kern_socketpair(td, uap->domain, uap->type,
  658             uap->protocol, sv);
  659         if (error)
  660                 return (error);
  661         error = copyout(sv, uap->rsv, 2 * sizeof(int));
  662         if (error) {
  663                 (void)kern_close(td, sv[0]);
  664                 (void)kern_close(td, sv[1]);
  665         }
  666         return (error);
  667 }
  668 
  669 static int
  670 sendit(td, s, mp, flags)
  671         struct thread *td;
  672         int s;
  673         struct msghdr *mp;
  674         int flags;
  675 {
  676         struct mbuf *control;
  677         struct sockaddr *to;
  678         int error;
  679 
  680         if (mp->msg_name != NULL) {
  681                 error = getsockaddr(&to, mp->msg_name, mp->msg_namelen);
  682                 if (error) {
  683                         to = NULL;
  684                         goto bad;
  685                 }
  686                 mp->msg_name = to;
  687         } else {
  688                 to = NULL;
  689         }
  690 
  691         if (mp->msg_control) {
  692                 if (mp->msg_controllen < sizeof(struct cmsghdr)
  693 #ifdef COMPAT_OLDSOCK
  694                     && mp->msg_flags != MSG_COMPAT
  695 #endif
  696                 ) {
  697                         error = EINVAL;
  698                         goto bad;
  699                 }
  700                 error = sockargs(&control, mp->msg_control,
  701                     mp->msg_controllen, MT_CONTROL);
  702                 if (error)
  703                         goto bad;
  704 #ifdef COMPAT_OLDSOCK
  705                 if (mp->msg_flags == MSG_COMPAT) {
  706                         struct cmsghdr *cm;
  707 
  708                         M_PREPEND(control, sizeof(*cm), M_WAIT);
  709                         cm = mtod(control, struct cmsghdr *);
  710                         cm->cmsg_len = control->m_len;
  711                         cm->cmsg_level = SOL_SOCKET;
  712                         cm->cmsg_type = SCM_RIGHTS;
  713                 }
  714 #endif
  715         } else {
  716                 control = NULL;
  717         }
  718 
  719         error = kern_sendit(td, s, mp, flags, control, UIO_USERSPACE);
  720 
  721 bad:
  722         if (to)
  723                 free(to, M_SONAME);
  724         return (error);
  725 }
  726 
  727 int
  728 kern_sendit(td, s, mp, flags, control, segflg)
  729         struct thread *td;
  730         int s;
  731         struct msghdr *mp;
  732         int flags;
  733         struct mbuf *control;
  734         enum uio_seg segflg;
  735 {
  736         struct file *fp;
  737         struct uio auio;
  738         struct iovec *iov;
  739         struct socket *so;
  740         int i;
  741         int len, error;
  742 #ifdef KTRACE
  743         struct uio *ktruio = NULL;
  744 #endif
  745 
  746         AUDIT_ARG_FD(s);
  747         error = getsock(td->td_proc->p_fd, s, &fp, NULL);
  748         if (error)
  749                 return (error);
  750         so = (struct socket *)fp->f_data;
  751 
  752 #ifdef MAC
  753         if (mp->msg_name != NULL) {
  754                 error = mac_socket_check_connect(td->td_ucred, so,
  755                     mp->msg_name);
  756                 if (error)
  757                         goto bad;
  758         }
  759         error = mac_socket_check_send(td->td_ucred, so);
  760         if (error)
  761                 goto bad;
  762 #endif
  763 
  764         auio.uio_iov = mp->msg_iov;
  765         auio.uio_iovcnt = mp->msg_iovlen;
  766         auio.uio_segflg = segflg;
  767         auio.uio_rw = UIO_WRITE;
  768         auio.uio_td = td;
  769         auio.uio_offset = 0;                    /* XXX */
  770         auio.uio_resid = 0;
  771         iov = mp->msg_iov;
  772         for (i = 0; i < mp->msg_iovlen; i++, iov++) {
  773                 if ((auio.uio_resid += iov->iov_len) < 0) {
  774                         error = EINVAL;
  775                         goto bad;
  776                 }
  777         }
  778 #ifdef KTRACE
  779         if (KTRPOINT(td, KTR_GENIO))
  780                 ktruio = cloneuio(&auio);
  781 #endif
  782         len = auio.uio_resid;
  783         error = sosend(so, mp->msg_name, &auio, 0, control, flags, td);
  784         if (error) {
  785                 if (auio.uio_resid != len && (error == ERESTART ||
  786                     error == EINTR || error == EWOULDBLOCK))
  787                         error = 0;
  788                 /* Generation of SIGPIPE can be controlled per socket */
  789                 if (error == EPIPE && !(so->so_options & SO_NOSIGPIPE) &&
  790                     !(flags & MSG_NOSIGNAL)) {
  791                         PROC_LOCK(td->td_proc);
  792                         psignal(td->td_proc, SIGPIPE);
  793                         PROC_UNLOCK(td->td_proc);
  794                 }
  795         }
  796         if (error == 0)
  797                 td->td_retval[0] = len - auio.uio_resid;
  798 #ifdef KTRACE
  799         if (ktruio != NULL) {
  800                 ktruio->uio_resid = td->td_retval[0];
  801                 ktrgenio(s, UIO_WRITE, ktruio, error);
  802         }
  803 #endif
  804 bad:
  805         fdrop(fp, td);
  806         return (error);
  807 }
  808 
  809 int
  810 sendto(td, uap)
  811         struct thread *td;
  812         struct sendto_args /* {
  813                 int     s;
  814                 caddr_t buf;
  815                 size_t  len;
  816                 int     flags;
  817                 caddr_t to;
  818                 int     tolen;
  819         } */ *uap;
  820 {
  821         struct msghdr msg;
  822         struct iovec aiov;
  823         int error;
  824 
  825         msg.msg_name = uap->to;
  826         msg.msg_namelen = uap->tolen;
  827         msg.msg_iov = &aiov;
  828         msg.msg_iovlen = 1;
  829         msg.msg_control = 0;
  830 #ifdef COMPAT_OLDSOCK
  831         msg.msg_flags = 0;
  832 #endif
  833         aiov.iov_base = uap->buf;
  834         aiov.iov_len = uap->len;
  835         error = sendit(td, uap->s, &msg, uap->flags);
  836         return (error);
  837 }
  838 
  839 #ifdef COMPAT_OLDSOCK
  840 int
  841 osend(td, uap)
  842         struct thread *td;
  843         struct osend_args /* {
  844                 int     s;
  845                 caddr_t buf;
  846                 int     len;
  847                 int     flags;
  848         } */ *uap;
  849 {
  850         struct msghdr msg;
  851         struct iovec aiov;
  852         int error;
  853 
  854         msg.msg_name = 0;
  855         msg.msg_namelen = 0;
  856         msg.msg_iov = &aiov;
  857         msg.msg_iovlen = 1;
  858         aiov.iov_base = uap->buf;
  859         aiov.iov_len = uap->len;
  860         msg.msg_control = 0;
  861         msg.msg_flags = 0;
  862         error = sendit(td, uap->s, &msg, uap->flags);
  863         return (error);
  864 }
  865 
  866 int
  867 osendmsg(td, uap)
  868         struct thread *td;
  869         struct osendmsg_args /* {
  870                 int     s;
  871                 caddr_t msg;
  872                 int     flags;
  873         } */ *uap;
  874 {
  875         struct msghdr msg;
  876         struct iovec *iov;
  877         int error;
  878 
  879         error = copyin(uap->msg, &msg, sizeof (struct omsghdr));
  880         if (error)
  881                 return (error);
  882         error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
  883         if (error)
  884                 return (error);
  885         msg.msg_iov = iov;
  886         msg.msg_flags = MSG_COMPAT;
  887         error = sendit(td, uap->s, &msg, uap->flags);
  888         free(iov, M_IOV);
  889         return (error);
  890 }
  891 #endif
  892 
  893 int
  894 sendmsg(td, uap)
  895         struct thread *td;
  896         struct sendmsg_args /* {
  897                 int     s;
  898                 caddr_t msg;
  899                 int     flags;
  900         } */ *uap;
  901 {
  902         struct msghdr msg;
  903         struct iovec *iov;
  904         int error;
  905 
  906         error = copyin(uap->msg, &msg, sizeof (msg));
  907         if (error)
  908                 return (error);
  909         error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
  910         if (error)
  911                 return (error);
  912         msg.msg_iov = iov;
  913 #ifdef COMPAT_OLDSOCK
  914         msg.msg_flags = 0;
  915 #endif
  916         error = sendit(td, uap->s, &msg, uap->flags);
  917         free(iov, M_IOV);
  918         return (error);
  919 }
  920 
  921 int
  922 kern_recvit(td, s, mp, fromseg, controlp)
  923         struct thread *td;
  924         int s;
  925         struct msghdr *mp;
  926         enum uio_seg fromseg;
  927         struct mbuf **controlp;
  928 {
  929         struct uio auio;
  930         struct iovec *iov;
  931         int i;
  932         socklen_t len;
  933         int error;
  934         struct mbuf *m, *control = 0;
  935         caddr_t ctlbuf;
  936         struct file *fp;
  937         struct socket *so;
  938         struct sockaddr *fromsa = 0;
  939 #ifdef KTRACE
  940         struct uio *ktruio = NULL;
  941 #endif
  942 
  943         if(controlp != NULL)
  944                 *controlp = 0;
  945 
  946         AUDIT_ARG_FD(s);
  947         error = getsock(td->td_proc->p_fd, s, &fp, NULL);
  948         if (error)
  949                 return (error);
  950         so = fp->f_data;
  951 
  952 #ifdef MAC
  953         error = mac_socket_check_receive(td->td_ucred, so);
  954         if (error) {
  955                 fdrop(fp, td);
  956                 return (error);
  957         }
  958 #endif
  959 
  960         auio.uio_iov = mp->msg_iov;
  961         auio.uio_iovcnt = mp->msg_iovlen;
  962         auio.uio_segflg = UIO_USERSPACE;
  963         auio.uio_rw = UIO_READ;
  964         auio.uio_td = td;
  965         auio.uio_offset = 0;                    /* XXX */
  966         auio.uio_resid = 0;
  967         iov = mp->msg_iov;
  968         for (i = 0; i < mp->msg_iovlen; i++, iov++) {
  969                 if ((auio.uio_resid += iov->iov_len) < 0) {
  970                         fdrop(fp, td);
  971                         return (EINVAL);
  972                 }
  973         }
  974 #ifdef KTRACE
  975         if (KTRPOINT(td, KTR_GENIO))
  976                 ktruio = cloneuio(&auio);
  977 #endif
  978         len = auio.uio_resid;
  979         CURVNET_SET(so->so_vnet);
  980         error = soreceive(so, &fromsa, &auio, (struct mbuf **)0,
  981             (mp->msg_control || controlp) ? &control : (struct mbuf **)0,
  982             &mp->msg_flags);
  983         CURVNET_RESTORE();
  984         if (error) {
  985                 if (auio.uio_resid != (int)len && (error == ERESTART ||
  986                     error == EINTR || error == EWOULDBLOCK))
  987                         error = 0;
  988         }
  989 #ifdef KTRACE
  990         if (ktruio != NULL) {
  991                 ktruio->uio_resid = (int)len - auio.uio_resid;
  992                 ktrgenio(s, UIO_READ, ktruio, error);
  993         }
  994 #endif
  995         if (error)
  996                 goto out;
  997         td->td_retval[0] = (int)len - auio.uio_resid;
  998         if (mp->msg_name) {
  999                 len = mp->msg_namelen;
 1000                 if (len <= 0 || fromsa == 0)
 1001                         len = 0;
 1002                 else {
 1003                         /* save sa_len before it is destroyed by MSG_COMPAT */
 1004                         len = MIN(len, fromsa->sa_len);
 1005 #ifdef COMPAT_OLDSOCK
 1006                         if (mp->msg_flags & MSG_COMPAT)
 1007                                 ((struct osockaddr *)fromsa)->sa_family =
 1008                                     fromsa->sa_family;
 1009 #endif
 1010                         if (fromseg == UIO_USERSPACE) {
 1011                                 error = copyout(fromsa, mp->msg_name,
 1012                                     (unsigned)len);
 1013                                 if (error)
 1014                                         goto out;
 1015                         } else
 1016                                 bcopy(fromsa, mp->msg_name, len);
 1017                 }
 1018                 mp->msg_namelen = len;
 1019         }
 1020         if (mp->msg_control && controlp == NULL) {
 1021 #ifdef COMPAT_OLDSOCK
 1022                 /*
 1023                  * We assume that old recvmsg calls won't receive access
 1024                  * rights and other control info, esp. as control info
 1025                  * is always optional and those options didn't exist in 4.3.
 1026                  * If we receive rights, trim the cmsghdr; anything else
 1027                  * is tossed.
 1028                  */
 1029                 if (control && mp->msg_flags & MSG_COMPAT) {
 1030                         if (mtod(control, struct cmsghdr *)->cmsg_level !=
 1031                             SOL_SOCKET ||
 1032                             mtod(control, struct cmsghdr *)->cmsg_type !=
 1033                             SCM_RIGHTS) {
 1034                                 mp->msg_controllen = 0;
 1035                                 goto out;
 1036                         }
 1037                         control->m_len -= sizeof (struct cmsghdr);
 1038                         control->m_data += sizeof (struct cmsghdr);
 1039                 }
 1040 #endif
 1041                 len = mp->msg_controllen;
 1042                 m = control;
 1043                 mp->msg_controllen = 0;
 1044                 ctlbuf = mp->msg_control;
 1045 
 1046                 while (m && len > 0) {
 1047                         unsigned int tocopy;
 1048 
 1049                         if (len >= m->m_len)
 1050                                 tocopy = m->m_len;
 1051                         else {
 1052                                 mp->msg_flags |= MSG_CTRUNC;
 1053                                 tocopy = len;
 1054                         }
 1055 
 1056                         if ((error = copyout(mtod(m, caddr_t),
 1057                                         ctlbuf, tocopy)) != 0)
 1058                                 goto out;
 1059 
 1060                         ctlbuf += tocopy;
 1061                         len -= tocopy;
 1062                         m = m->m_next;
 1063                 }
 1064                 mp->msg_controllen = ctlbuf - (caddr_t)mp->msg_control;
 1065         }
 1066 out:
 1067         fdrop(fp, td);
 1068 #ifdef KTRACE
 1069         if (fromsa && KTRPOINT(td, KTR_STRUCT))
 1070                 ktrsockaddr(fromsa);
 1071 #endif
 1072         if (fromsa)
 1073                 free(fromsa, M_SONAME);
 1074 
 1075         if (error == 0 && controlp != NULL)  
 1076                 *controlp = control;
 1077         else  if (control)
 1078                 m_freem(control);
 1079 
 1080         return (error);
 1081 }
 1082 
 1083 static int
 1084 recvit(td, s, mp, namelenp)
 1085         struct thread *td;
 1086         int s;
 1087         struct msghdr *mp;
 1088         void *namelenp;
 1089 {
 1090         int error;
 1091 
 1092         error = kern_recvit(td, s, mp, UIO_USERSPACE, NULL);
 1093         if (error)
 1094                 return (error);
 1095         if (namelenp) {
 1096                 error = copyout(&mp->msg_namelen, namelenp, sizeof (socklen_t));
 1097 #ifdef COMPAT_OLDSOCK
 1098                 if (mp->msg_flags & MSG_COMPAT)
 1099                         error = 0;      /* old recvfrom didn't check */
 1100 #endif
 1101         }
 1102         return (error);
 1103 }
 1104 
 1105 int
 1106 recvfrom(td, uap)
 1107         struct thread *td;
 1108         struct recvfrom_args /* {
 1109                 int     s;
 1110                 caddr_t buf;
 1111                 size_t  len;
 1112                 int     flags;
 1113                 struct sockaddr * __restrict    from;
 1114                 socklen_t * __restrict fromlenaddr;
 1115         } */ *uap;
 1116 {
 1117         struct msghdr msg;
 1118         struct iovec aiov;
 1119         int error;
 1120 
 1121         if (uap->fromlenaddr) {
 1122                 error = copyin(uap->fromlenaddr,
 1123                     &msg.msg_namelen, sizeof (msg.msg_namelen));
 1124                 if (error)
 1125                         goto done2;
 1126         } else {
 1127                 msg.msg_namelen = 0;
 1128         }
 1129         msg.msg_name = uap->from;
 1130         msg.msg_iov = &aiov;
 1131         msg.msg_iovlen = 1;
 1132         aiov.iov_base = uap->buf;
 1133         aiov.iov_len = uap->len;
 1134         msg.msg_control = 0;
 1135         msg.msg_flags = uap->flags;
 1136         error = recvit(td, uap->s, &msg, uap->fromlenaddr);
 1137 done2:
 1138         return(error);
 1139 }
 1140 
 1141 #ifdef COMPAT_OLDSOCK
 1142 int
 1143 orecvfrom(td, uap)
 1144         struct thread *td;
 1145         struct recvfrom_args *uap;
 1146 {
 1147 
 1148         uap->flags |= MSG_COMPAT;
 1149         return (recvfrom(td, uap));
 1150 }
 1151 #endif
 1152 
 1153 #ifdef COMPAT_OLDSOCK
 1154 int
 1155 orecv(td, uap)
 1156         struct thread *td;
 1157         struct orecv_args /* {
 1158                 int     s;
 1159                 caddr_t buf;
 1160                 int     len;
 1161                 int     flags;
 1162         } */ *uap;
 1163 {
 1164         struct msghdr msg;
 1165         struct iovec aiov;
 1166         int error;
 1167 
 1168         msg.msg_name = 0;
 1169         msg.msg_namelen = 0;
 1170         msg.msg_iov = &aiov;
 1171         msg.msg_iovlen = 1;
 1172         aiov.iov_base = uap->buf;
 1173         aiov.iov_len = uap->len;
 1174         msg.msg_control = 0;
 1175         msg.msg_flags = uap->flags;
 1176         error = recvit(td, uap->s, &msg, NULL);
 1177         return (error);
 1178 }
 1179 
 1180 /*
 1181  * Old recvmsg.  This code takes advantage of the fact that the old msghdr
 1182  * overlays the new one, missing only the flags, and with the (old) access
 1183  * rights where the control fields are now.
 1184  */
 1185 int
 1186 orecvmsg(td, uap)
 1187         struct thread *td;
 1188         struct orecvmsg_args /* {
 1189                 int     s;
 1190                 struct  omsghdr *msg;
 1191                 int     flags;
 1192         } */ *uap;
 1193 {
 1194         struct msghdr msg;
 1195         struct iovec *iov;
 1196         int error;
 1197 
 1198         error = copyin(uap->msg, &msg, sizeof (struct omsghdr));
 1199         if (error)
 1200                 return (error);
 1201         error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
 1202         if (error)
 1203                 return (error);
 1204         msg.msg_flags = uap->flags | MSG_COMPAT;
 1205         msg.msg_iov = iov;
 1206         error = recvit(td, uap->s, &msg, &uap->msg->msg_namelen);
 1207         if (msg.msg_controllen && error == 0)
 1208                 error = copyout(&msg.msg_controllen,
 1209                     &uap->msg->msg_accrightslen, sizeof (int));
 1210         free(iov, M_IOV);
 1211         return (error);
 1212 }
 1213 #endif
 1214 
 1215 int
 1216 recvmsg(td, uap)
 1217         struct thread *td;
 1218         struct recvmsg_args /* {
 1219                 int     s;
 1220                 struct  msghdr *msg;
 1221                 int     flags;
 1222         } */ *uap;
 1223 {
 1224         struct msghdr msg;
 1225         struct iovec *uiov, *iov;
 1226         int error;
 1227 
 1228         error = copyin(uap->msg, &msg, sizeof (msg));
 1229         if (error)
 1230                 return (error);
 1231         error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
 1232         if (error)
 1233                 return (error);
 1234         msg.msg_flags = uap->flags;
 1235 #ifdef COMPAT_OLDSOCK
 1236         msg.msg_flags &= ~MSG_COMPAT;
 1237 #endif
 1238         uiov = msg.msg_iov;
 1239         msg.msg_iov = iov;
 1240         error = recvit(td, uap->s, &msg, NULL);
 1241         if (error == 0) {
 1242                 msg.msg_iov = uiov;
 1243                 error = copyout(&msg, uap->msg, sizeof(msg));
 1244         }
 1245         free(iov, M_IOV);
 1246         return (error);
 1247 }
 1248 
 1249 /* ARGSUSED */
 1250 int
 1251 shutdown(td, uap)
 1252         struct thread *td;
 1253         struct shutdown_args /* {
 1254                 int     s;
 1255                 int     how;
 1256         } */ *uap;
 1257 {
 1258         struct socket *so;
 1259         struct file *fp;
 1260         int error;
 1261 
 1262         AUDIT_ARG_FD(uap->s);
 1263         error = getsock(td->td_proc->p_fd, uap->s, &fp, NULL);
 1264         if (error == 0) {
 1265                 so = fp->f_data;
 1266                 error = soshutdown(so, uap->how);
 1267                 fdrop(fp, td);
 1268         }
 1269         return (error);
 1270 }
 1271 
 1272 /* ARGSUSED */
 1273 int
 1274 setsockopt(td, uap)
 1275         struct thread *td;
 1276         struct setsockopt_args /* {
 1277                 int     s;
 1278                 int     level;
 1279                 int     name;
 1280                 caddr_t val;
 1281                 int     valsize;
 1282         } */ *uap;
 1283 {
 1284 
 1285         return (kern_setsockopt(td, uap->s, uap->level, uap->name,
 1286             uap->val, UIO_USERSPACE, uap->valsize));
 1287 }
 1288 
 1289 int
 1290 kern_setsockopt(td, s, level, name, val, valseg, valsize)
 1291         struct thread *td;
 1292         int s;
 1293         int level;
 1294         int name;
 1295         void *val;
 1296         enum uio_seg valseg;
 1297         socklen_t valsize;
 1298 {
 1299         int error;
 1300         struct socket *so;
 1301         struct file *fp;
 1302         struct sockopt sopt;
 1303 
 1304         if (val == NULL && valsize != 0)
 1305                 return (EFAULT);
 1306         if ((int)valsize < 0)
 1307                 return (EINVAL);
 1308 
 1309         sopt.sopt_dir = SOPT_SET;
 1310         sopt.sopt_level = level;
 1311         sopt.sopt_name = name;
 1312         sopt.sopt_val = val;
 1313         sopt.sopt_valsize = valsize;
 1314         switch (valseg) {
 1315         case UIO_USERSPACE:
 1316                 sopt.sopt_td = td;
 1317                 break;
 1318         case UIO_SYSSPACE:
 1319                 sopt.sopt_td = NULL;
 1320                 break;
 1321         default:
 1322                 panic("kern_setsockopt called with bad valseg");
 1323         }
 1324 
 1325         AUDIT_ARG_FD(s);
 1326         error = getsock(td->td_proc->p_fd, s, &fp, NULL);
 1327         if (error == 0) {
 1328                 so = fp->f_data;
 1329                 CURVNET_SET(so->so_vnet);
 1330                 error = sosetopt(so, &sopt);
 1331                 CURVNET_RESTORE();
 1332                 fdrop(fp, td);
 1333         }
 1334         return(error);
 1335 }
 1336 
 1337 /* ARGSUSED */
 1338 int
 1339 getsockopt(td, uap)
 1340         struct thread *td;
 1341         struct getsockopt_args /* {
 1342                 int     s;
 1343                 int     level;
 1344                 int     name;
 1345                 void * __restrict       val;
 1346                 socklen_t * __restrict avalsize;
 1347         } */ *uap;
 1348 {
 1349         socklen_t valsize;
 1350         int     error;
 1351 
 1352         if (uap->val) {
 1353                 error = copyin(uap->avalsize, &valsize, sizeof (valsize));
 1354                 if (error)
 1355                         return (error);
 1356         }
 1357 
 1358         error = kern_getsockopt(td, uap->s, uap->level, uap->name,
 1359             uap->val, UIO_USERSPACE, &valsize);
 1360 
 1361         if (error == 0)
 1362                 error = copyout(&valsize, uap->avalsize, sizeof (valsize));
 1363         return (error);
 1364 }
 1365 
 1366 /*
 1367  * Kernel version of getsockopt.
 1368  * optval can be a userland or userspace. optlen is always a kernel pointer.
 1369  */
 1370 int
 1371 kern_getsockopt(td, s, level, name, val, valseg, valsize)
 1372         struct thread *td;
 1373         int s;
 1374         int level;
 1375         int name;
 1376         void *val;
 1377         enum uio_seg valseg;
 1378         socklen_t *valsize;
 1379 {
 1380         int error;
 1381         struct  socket *so;
 1382         struct file *fp;
 1383         struct  sockopt sopt;
 1384 
 1385         if (val == NULL)
 1386                 *valsize = 0;
 1387         if ((int)*valsize < 0)
 1388                 return (EINVAL);
 1389 
 1390         sopt.sopt_dir = SOPT_GET;
 1391         sopt.sopt_level = level;
 1392         sopt.sopt_name = name;
 1393         sopt.sopt_val = val;
 1394         sopt.sopt_valsize = (size_t)*valsize; /* checked non-negative above */
 1395         switch (valseg) {
 1396         case UIO_USERSPACE:
 1397                 sopt.sopt_td = td;
 1398                 break;
 1399         case UIO_SYSSPACE:
 1400                 sopt.sopt_td = NULL;
 1401                 break;
 1402         default:
 1403                 panic("kern_getsockopt called with bad valseg");
 1404         }
 1405 
 1406         AUDIT_ARG_FD(s);
 1407         error = getsock(td->td_proc->p_fd, s, &fp, NULL);
 1408         if (error == 0) {
 1409                 so = fp->f_data;
 1410                 CURVNET_SET(so->so_vnet);
 1411                 error = sogetopt(so, &sopt);
 1412                 CURVNET_RESTORE();
 1413                 *valsize = sopt.sopt_valsize;
 1414                 fdrop(fp, td);
 1415         }
 1416         return (error);
 1417 }
 1418 
 1419 /*
 1420  * getsockname1() - Get socket name.
 1421  */
 1422 /* ARGSUSED */
 1423 static int
 1424 getsockname1(td, uap, compat)
 1425         struct thread *td;
 1426         struct getsockname_args /* {
 1427                 int     fdes;
 1428                 struct sockaddr * __restrict asa;
 1429                 socklen_t * __restrict alen;
 1430         } */ *uap;
 1431         int compat;
 1432 {
 1433         struct sockaddr *sa;
 1434         socklen_t len;
 1435         int error;
 1436 
 1437         error = copyin(uap->alen, &len, sizeof(len));
 1438         if (error)
 1439                 return (error);
 1440 
 1441         error = kern_getsockname(td, uap->fdes, &sa, &len);
 1442         if (error)
 1443                 return (error);
 1444 
 1445         if (len != 0) {
 1446 #ifdef COMPAT_OLDSOCK
 1447                 if (compat)
 1448                         ((struct osockaddr *)sa)->sa_family = sa->sa_family;
 1449 #endif
 1450                 error = copyout(sa, uap->asa, (u_int)len);
 1451         }
 1452         free(sa, M_SONAME);
 1453         if (error == 0)
 1454                 error = copyout(&len, uap->alen, sizeof(len));
 1455         return (error);
 1456 }
 1457 
 1458 int
 1459 kern_getsockname(struct thread *td, int fd, struct sockaddr **sa,
 1460     socklen_t *alen)
 1461 {
 1462         struct socket *so;
 1463         struct file *fp;
 1464         socklen_t len;
 1465         int error;
 1466 
 1467         if (*alen < 0)
 1468                 return (EINVAL);
 1469 
 1470         AUDIT_ARG_FD(fd);
 1471         error = getsock(td->td_proc->p_fd, fd, &fp, NULL);
 1472         if (error)
 1473                 return (error);
 1474         so = fp->f_data;
 1475         *sa = NULL;
 1476         CURVNET_SET(so->so_vnet);
 1477         error = (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, sa);
 1478         CURVNET_RESTORE();
 1479         if (error)
 1480                 goto bad;
 1481         if (*sa == NULL)
 1482                 len = 0;
 1483         else
 1484                 len = MIN(*alen, (*sa)->sa_len);
 1485         *alen = len;
 1486 #ifdef KTRACE
 1487         if (KTRPOINT(td, KTR_STRUCT))
 1488                 ktrsockaddr(*sa);
 1489 #endif
 1490 bad:
 1491         fdrop(fp, td);
 1492         if (error && *sa) {
 1493                 free(*sa, M_SONAME);
 1494                 *sa = NULL;
 1495         }
 1496         return (error);
 1497 }
 1498 
 1499 int
 1500 getsockname(td, uap)
 1501         struct thread *td;
 1502         struct getsockname_args *uap;
 1503 {
 1504 
 1505         return (getsockname1(td, uap, 0));
 1506 }
 1507 
 1508 #ifdef COMPAT_OLDSOCK
 1509 int
 1510 ogetsockname(td, uap)
 1511         struct thread *td;
 1512         struct getsockname_args *uap;
 1513 {
 1514 
 1515         return (getsockname1(td, uap, 1));
 1516 }
 1517 #endif /* COMPAT_OLDSOCK */
 1518 
 1519 /*
 1520  * getpeername1() - Get name of peer for connected socket.
 1521  */
 1522 /* ARGSUSED */
 1523 static int
 1524 getpeername1(td, uap, compat)
 1525         struct thread *td;
 1526         struct getpeername_args /* {
 1527                 int     fdes;
 1528                 struct sockaddr * __restrict    asa;
 1529                 socklen_t * __restrict  alen;
 1530         } */ *uap;
 1531         int compat;
 1532 {
 1533         struct sockaddr *sa;
 1534         socklen_t len;
 1535         int error;
 1536 
 1537         error = copyin(uap->alen, &len, sizeof (len));
 1538         if (error)
 1539                 return (error);
 1540 
 1541         error = kern_getpeername(td, uap->fdes, &sa, &len);
 1542         if (error)
 1543                 return (error);
 1544 
 1545         if (len != 0) {
 1546 #ifdef COMPAT_OLDSOCK
 1547                 if (compat)
 1548                         ((struct osockaddr *)sa)->sa_family = sa->sa_family;
 1549 #endif
 1550                 error = copyout(sa, uap->asa, (u_int)len);
 1551         }
 1552         free(sa, M_SONAME);
 1553         if (error == 0)
 1554                 error = copyout(&len, uap->alen, sizeof(len));
 1555         return (error);
 1556 }
 1557 
 1558 int
 1559 kern_getpeername(struct thread *td, int fd, struct sockaddr **sa,
 1560     socklen_t *alen)
 1561 {
 1562         struct socket *so;
 1563         struct file *fp;
 1564         socklen_t len;
 1565         int error;
 1566 
 1567         if (*alen < 0)
 1568                 return (EINVAL);
 1569 
 1570         AUDIT_ARG_FD(fd);
 1571         error = getsock(td->td_proc->p_fd, fd, &fp, NULL);
 1572         if (error)
 1573                 return (error);
 1574         so = fp->f_data;
 1575         if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) {
 1576                 error = ENOTCONN;
 1577                 goto done;
 1578         }
 1579         *sa = NULL;
 1580         CURVNET_SET(so->so_vnet);
 1581         error = (*so->so_proto->pr_usrreqs->pru_peeraddr)(so, sa);
 1582         CURVNET_RESTORE();
 1583         if (error)
 1584                 goto bad;
 1585         if (*sa == NULL)
 1586                 len = 0;
 1587         else
 1588                 len = MIN(*alen, (*sa)->sa_len);
 1589         *alen = len;
 1590 #ifdef KTRACE
 1591         if (KTRPOINT(td, KTR_STRUCT))
 1592                 ktrsockaddr(*sa);
 1593 #endif
 1594 bad:
 1595         if (error && *sa) {
 1596                 free(*sa, M_SONAME);
 1597                 *sa = NULL;
 1598         }
 1599 done:
 1600         fdrop(fp, td);
 1601         return (error);
 1602 }
 1603 
 1604 int
 1605 getpeername(td, uap)
 1606         struct thread *td;
 1607         struct getpeername_args *uap;
 1608 {
 1609 
 1610         return (getpeername1(td, uap, 0));
 1611 }
 1612 
 1613 #ifdef COMPAT_OLDSOCK
 1614 int
 1615 ogetpeername(td, uap)
 1616         struct thread *td;
 1617         struct ogetpeername_args *uap;
 1618 {
 1619 
 1620         /* XXX uap should have type `getpeername_args *' to begin with. */
 1621         return (getpeername1(td, (struct getpeername_args *)uap, 1));
 1622 }
 1623 #endif /* COMPAT_OLDSOCK */
 1624 
 1625 int
 1626 sockargs(mp, buf, buflen, type)
 1627         struct mbuf **mp;
 1628         caddr_t buf;
 1629         int buflen, type;
 1630 {
 1631         struct sockaddr *sa;
 1632         struct mbuf *m;
 1633         int error;
 1634 
 1635         if ((u_int)buflen > MLEN) {
 1636 #ifdef COMPAT_OLDSOCK
 1637                 if (type == MT_SONAME && (u_int)buflen <= 112)
 1638                         buflen = MLEN;          /* unix domain compat. hack */
 1639                 else
 1640 #endif
 1641                         if ((u_int)buflen > MCLBYTES)
 1642                                 return (EINVAL);
 1643         }
 1644         m = m_get(M_WAIT, type);
 1645         if ((u_int)buflen > MLEN)
 1646                 MCLGET(m, M_WAIT);
 1647         m->m_len = buflen;
 1648         error = copyin(buf, mtod(m, caddr_t), (u_int)buflen);
 1649         if (error)
 1650                 (void) m_free(m);
 1651         else {
 1652                 *mp = m;
 1653                 if (type == MT_SONAME) {
 1654                         sa = mtod(m, struct sockaddr *);
 1655 
 1656 #if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
 1657                         if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
 1658                                 sa->sa_family = sa->sa_len;
 1659 #endif
 1660                         sa->sa_len = buflen;
 1661                 }
 1662         }
 1663         return (error);
 1664 }
 1665 
 1666 int
 1667 getsockaddr(namp, uaddr, len)
 1668         struct sockaddr **namp;
 1669         caddr_t uaddr;
 1670         size_t len;
 1671 {
 1672         struct sockaddr *sa;
 1673         int error;
 1674 
 1675         if (len > SOCK_MAXADDRLEN)
 1676                 return (ENAMETOOLONG);
 1677         if (len < offsetof(struct sockaddr, sa_data[0]))
 1678                 return (EINVAL);
 1679         sa = malloc(len, M_SONAME, M_WAITOK);
 1680         error = copyin(uaddr, sa, len);
 1681         if (error) {
 1682                 free(sa, M_SONAME);
 1683         } else {
 1684 #if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
 1685                 if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
 1686                         sa->sa_family = sa->sa_len;
 1687 #endif
 1688                 sa->sa_len = len;
 1689                 *namp = sa;
 1690         }
 1691         return (error);
 1692 }
 1693 
 1694 #include <sys/condvar.h>
 1695 
 1696 struct sendfile_sync {
 1697         struct mtx      mtx;
 1698         struct cv       cv;
 1699         unsigned        count;
 1700 };
 1701 
 1702 /*
 1703  * Detach mapped page and release resources back to the system.
 1704  */
 1705 void
 1706 sf_buf_mext(void *addr, void *args)
 1707 {
 1708         vm_page_t m;
 1709         struct sendfile_sync *sfs;
 1710 
 1711         m = sf_buf_page(args);
 1712         sf_buf_free(args);
 1713         vm_page_lock_queues();
 1714         vm_page_unwire(m, 0);
 1715         /*
 1716          * Check for the object going away on us. This can
 1717          * happen since we don't hold a reference to it.
 1718          * If so, we're responsible for freeing the page.
 1719          */
 1720         if (m->wire_count == 0 && m->object == NULL)
 1721                 vm_page_free(m);
 1722         vm_page_unlock_queues();
 1723         if (addr == NULL)
 1724                 return;
 1725         sfs = addr;
 1726         mtx_lock(&sfs->mtx);
 1727         KASSERT(sfs->count> 0, ("Sendfile sync botchup count == 0"));
 1728         if (--sfs->count == 0)
 1729                 cv_signal(&sfs->cv);
 1730         mtx_unlock(&sfs->mtx);
 1731 }
 1732 
 1733 /*
 1734  * sendfile(2)
 1735  *
 1736  * int sendfile(int fd, int s, off_t offset, size_t nbytes,
 1737  *       struct sf_hdtr *hdtr, off_t *sbytes, int flags)
 1738  *
 1739  * Send a file specified by 'fd' and starting at 'offset' to a socket
 1740  * specified by 's'. Send only 'nbytes' of the file or until EOF if nbytes ==
 1741  * 0.  Optionally add a header and/or trailer to the socket output.  If
 1742  * specified, write the total number of bytes sent into *sbytes.
 1743  */
 1744 int
 1745 sendfile(struct thread *td, struct sendfile_args *uap)
 1746 {
 1747 
 1748         return (do_sendfile(td, uap, 0));
 1749 }
 1750 
 1751 static int
 1752 do_sendfile(struct thread *td, struct sendfile_args *uap, int compat)
 1753 {
 1754         struct sf_hdtr hdtr;
 1755         struct uio *hdr_uio, *trl_uio;
 1756         int error;
 1757 
 1758         hdr_uio = trl_uio = NULL;
 1759 
 1760         if (uap->hdtr != NULL) {
 1761                 error = copyin(uap->hdtr, &hdtr, sizeof(hdtr));
 1762                 if (error)
 1763                         goto out;
 1764                 if (hdtr.headers != NULL) {
 1765                         error = copyinuio(hdtr.headers, hdtr.hdr_cnt, &hdr_uio);
 1766                         if (error)
 1767                                 goto out;
 1768                 }
 1769                 if (hdtr.trailers != NULL) {
 1770                         error = copyinuio(hdtr.trailers, hdtr.trl_cnt, &trl_uio);
 1771                         if (error)
 1772                                 goto out;
 1773 
 1774                 }
 1775         }
 1776 
 1777         error = kern_sendfile(td, uap, hdr_uio, trl_uio, compat);
 1778 out:
 1779         if (hdr_uio)
 1780                 free(hdr_uio, M_IOV);
 1781         if (trl_uio)
 1782                 free(trl_uio, M_IOV);
 1783         return (error);
 1784 }
 1785 
 1786 #ifdef COMPAT_FREEBSD4
 1787 int
 1788 freebsd4_sendfile(struct thread *td, struct freebsd4_sendfile_args *uap)
 1789 {
 1790         struct sendfile_args args;
 1791 
 1792         args.fd = uap->fd;
 1793         args.s = uap->s;
 1794         args.offset = uap->offset;
 1795         args.nbytes = uap->nbytes;
 1796         args.hdtr = uap->hdtr;
 1797         args.sbytes = uap->sbytes;
 1798         args.flags = uap->flags;
 1799 
 1800         return (do_sendfile(td, &args, 1));
 1801 }
 1802 #endif /* COMPAT_FREEBSD4 */
 1803 
 1804 int
 1805 kern_sendfile(struct thread *td, struct sendfile_args *uap,
 1806     struct uio *hdr_uio, struct uio *trl_uio, int compat)
 1807 {
 1808         struct file *sock_fp;
 1809         struct vnode *vp;
 1810         struct vm_object *obj = NULL;
 1811         struct socket *so = NULL;
 1812         struct mbuf *m = NULL;
 1813         struct sf_buf *sf;
 1814         struct vm_page *pg;
 1815         off_t off, xfsize, fsbytes = 0, sbytes = 0, rem = 0;
 1816         int error, hdrlen = 0, mnw = 0;
 1817         int vfslocked;
 1818         struct sendfile_sync *sfs = NULL;
 1819 
 1820         /*
 1821          * The file descriptor must be a regular file and have a
 1822          * backing VM object.
 1823          * File offset must be positive.  If it goes beyond EOF
 1824          * we send only the header/trailer and no payload data.
 1825          */
 1826         AUDIT_ARG_FD(uap->fd);
 1827         if ((error = fgetvp_read(td, uap->fd, &vp)) != 0)
 1828                 goto out;
 1829         vfslocked = VFS_LOCK_GIANT(vp->v_mount);
 1830         vn_lock(vp, LK_SHARED | LK_RETRY);
 1831         if (vp->v_type == VREG) {
 1832                 obj = vp->v_object;
 1833                 if (obj != NULL) {
 1834                         /*
 1835                          * Temporarily increase the backing VM
 1836                          * object's reference count so that a forced
 1837                          * reclamation of its vnode does not
 1838                          * immediately destroy it.
 1839                          */
 1840                         VM_OBJECT_LOCK(obj);
 1841                         if ((obj->flags & OBJ_DEAD) == 0) {
 1842                                 vm_object_reference_locked(obj);
 1843                                 VM_OBJECT_UNLOCK(obj);
 1844                         } else {
 1845                                 VM_OBJECT_UNLOCK(obj);
 1846                                 obj = NULL;
 1847                         }
 1848                 }
 1849         }
 1850         VOP_UNLOCK(vp, 0);
 1851         VFS_UNLOCK_GIANT(vfslocked);
 1852         if (obj == NULL) {
 1853                 error = EINVAL;
 1854                 goto out;
 1855         }
 1856         if (uap->offset < 0) {
 1857                 error = EINVAL;
 1858                 goto out;
 1859         }
 1860 
 1861         /*
 1862          * The socket must be a stream socket and connected.
 1863          * Remember if it a blocking or non-blocking socket.
 1864          */
 1865         if ((error = getsock(td->td_proc->p_fd, uap->s, &sock_fp,
 1866             NULL)) != 0)
 1867                 goto out;
 1868         so = sock_fp->f_data;
 1869         if (so->so_type != SOCK_STREAM) {
 1870                 error = EINVAL;
 1871                 goto out;
 1872         }
 1873         if ((so->so_state & SS_ISCONNECTED) == 0) {
 1874                 error = ENOTCONN;
 1875                 goto out;
 1876         }
 1877         /*
 1878          * Do not wait on memory allocations but return ENOMEM for
 1879          * caller to retry later.
 1880          * XXX: Experimental.
 1881          */
 1882         if (uap->flags & SF_MNOWAIT)
 1883                 mnw = 1;
 1884 
 1885         if (uap->flags & SF_SYNC) {
 1886                 sfs = malloc(sizeof *sfs, M_TEMP, M_WAITOK);
 1887                 memset(sfs, 0, sizeof *sfs);
 1888                 mtx_init(&sfs->mtx, "sendfile", MTX_DEF, 0);
 1889                 cv_init(&sfs->cv, "sendfile");
 1890         }
 1891 
 1892 #ifdef MAC
 1893         error = mac_socket_check_send(td->td_ucred, so);
 1894         if (error)
 1895                 goto out;
 1896 #endif
 1897 
 1898         /* If headers are specified copy them into mbufs. */
 1899         if (hdr_uio != NULL) {
 1900                 hdr_uio->uio_td = td;
 1901                 hdr_uio->uio_rw = UIO_WRITE;
 1902                 if (hdr_uio->uio_resid > 0) {
 1903                         /*
 1904                          * In FBSD < 5.0 the nbytes to send also included
 1905                          * the header.  If compat is specified subtract the
 1906                          * header size from nbytes.
 1907                          */
 1908                         if (compat) {
 1909                                 if (uap->nbytes > hdr_uio->uio_resid)
 1910                                         uap->nbytes -= hdr_uio->uio_resid;
 1911                                 else
 1912                                         uap->nbytes = 0;
 1913                         }
 1914                         m = m_uiotombuf(hdr_uio, (mnw ? M_NOWAIT : M_WAITOK),
 1915                             0, 0, 0);
 1916                         if (m == NULL) {
 1917                                 error = mnw ? EAGAIN : ENOBUFS;
 1918                                 goto out;
 1919                         }
 1920                         hdrlen = m_length(m, NULL);
 1921                 }
 1922         }
 1923 
 1924         /*
 1925          * Protect against multiple writers to the socket.
 1926          *
 1927          * XXXRW: Historically this has assumed non-interruptibility, so now
 1928          * we implement that, but possibly shouldn't.
 1929          */
 1930         (void)sblock(&so->so_snd, SBL_WAIT | SBL_NOINTR);
 1931 
 1932         /*
 1933          * Loop through the pages of the file, starting with the requested
 1934          * offset. Get a file page (do I/O if necessary), map the file page
 1935          * into an sf_buf, attach an mbuf header to the sf_buf, and queue
 1936          * it on the socket.
 1937          * This is done in two loops.  The inner loop turns as many pages
 1938          * as it can, up to available socket buffer space, without blocking
 1939          * into mbufs to have it bulk delivered into the socket send buffer.
 1940          * The outer loop checks the state and available space of the socket
 1941          * and takes care of the overall progress.
 1942          */
 1943         for (off = uap->offset, rem = uap->nbytes; ; ) {
 1944                 int loopbytes = 0;
 1945                 int space = 0;
 1946                 int done = 0;
 1947 
 1948                 /*
 1949                  * Check the socket state for ongoing connection,
 1950                  * no errors and space in socket buffer.
 1951                  * If space is low allow for the remainder of the
 1952                  * file to be processed if it fits the socket buffer.
 1953                  * Otherwise block in waiting for sufficient space
 1954                  * to proceed, or if the socket is nonblocking, return
 1955                  * to userland with EAGAIN while reporting how far
 1956                  * we've come.
 1957                  * We wait until the socket buffer has significant free
 1958                  * space to do bulk sends.  This makes good use of file
 1959                  * system read ahead and allows packet segmentation
 1960                  * offloading hardware to take over lots of work.  If
 1961                  * we were not careful here we would send off only one
 1962                  * sfbuf at a time.
 1963                  */
 1964                 SOCKBUF_LOCK(&so->so_snd);
 1965                 if (so->so_snd.sb_lowat < so->so_snd.sb_hiwat / 2)
 1966                         so->so_snd.sb_lowat = so->so_snd.sb_hiwat / 2;
 1967 retry_space:
 1968                 if (so->so_snd.sb_state & SBS_CANTSENDMORE) {
 1969                         error = EPIPE;
 1970                         SOCKBUF_UNLOCK(&so->so_snd);
 1971                         goto done;
 1972                 } else if (so->so_error) {
 1973                         error = so->so_error;
 1974                         so->so_error = 0;
 1975                         SOCKBUF_UNLOCK(&so->so_snd);
 1976                         goto done;
 1977                 }
 1978                 space = sbspace(&so->so_snd);
 1979                 if (space < rem &&
 1980                     (space <= 0 ||
 1981                      space < so->so_snd.sb_lowat)) {
 1982                         if (so->so_state & SS_NBIO) {
 1983                                 SOCKBUF_UNLOCK(&so->so_snd);
 1984                                 error = EAGAIN;
 1985                                 goto done;
 1986                         }
 1987                         /*
 1988                          * sbwait drops the lock while sleeping.
 1989                          * When we loop back to retry_space the
 1990                          * state may have changed and we retest
 1991                          * for it.
 1992                          */
 1993                         error = sbwait(&so->so_snd);
 1994                         /*
 1995                          * An error from sbwait usually indicates that we've
 1996                          * been interrupted by a signal. If we've sent anything
 1997                          * then return bytes sent, otherwise return the error.
 1998                          */
 1999                         if (error) {
 2000                                 SOCKBUF_UNLOCK(&so->so_snd);
 2001                                 goto done;
 2002                         }
 2003                         goto retry_space;
 2004                 }
 2005                 SOCKBUF_UNLOCK(&so->so_snd);
 2006 
 2007                 /*
 2008                  * Reduce space in the socket buffer by the size of
 2009                  * the header mbuf chain.
 2010                  * hdrlen is set to 0 after the first loop.
 2011                  */
 2012                 space -= hdrlen;
 2013 
 2014                 /*
 2015                  * Loop and construct maximum sized mbuf chain to be bulk
 2016                  * dumped into socket buffer.
 2017                  */
 2018                 while(space > loopbytes) {
 2019                         vm_pindex_t pindex;
 2020                         vm_offset_t pgoff;
 2021                         struct mbuf *m0;
 2022 
 2023                         VM_OBJECT_LOCK(obj);
 2024                         /*
 2025                          * Calculate the amount to transfer.
 2026                          * Not to exceed a page, the EOF,
 2027                          * or the passed in nbytes.
 2028                          */
 2029                         pgoff = (vm_offset_t)(off & PAGE_MASK);
 2030                         xfsize = omin(PAGE_SIZE - pgoff,
 2031                             obj->un_pager.vnp.vnp_size - uap->offset -
 2032                             fsbytes - loopbytes);
 2033                         if (uap->nbytes)
 2034                                 rem = (uap->nbytes - fsbytes - loopbytes);
 2035                         else
 2036                                 rem = obj->un_pager.vnp.vnp_size -
 2037                                     uap->offset - fsbytes - loopbytes;
 2038                         xfsize = omin(rem, xfsize);
 2039                         if (xfsize <= 0) {
 2040                                 VM_OBJECT_UNLOCK(obj);
 2041                                 done = 1;               /* all data sent */
 2042                                 break;
 2043                         }
 2044                         /*
 2045                          * Don't overflow the send buffer.
 2046                          * Stop here and send out what we've
 2047                          * already got.
 2048                          */
 2049                         if (space < loopbytes + xfsize) {
 2050                                 VM_OBJECT_UNLOCK(obj);
 2051                                 break;
 2052                         }
 2053 
 2054                         /*
 2055                          * Attempt to look up the page.  Allocate
 2056                          * if not found or wait and loop if busy.
 2057                          */
 2058                         pindex = OFF_TO_IDX(off);
 2059                         pg = vm_page_grab(obj, pindex, VM_ALLOC_NOBUSY |
 2060                             VM_ALLOC_NORMAL | VM_ALLOC_WIRED | VM_ALLOC_RETRY);
 2061 
 2062                         /*
 2063                          * Check if page is valid for what we need,
 2064                          * otherwise initiate I/O.
 2065                          * If we already turned some pages into mbufs,
 2066                          * send them off before we come here again and
 2067                          * block.
 2068                          */
 2069                         if (pg->valid && vm_page_is_valid(pg, pgoff, xfsize))
 2070                                 VM_OBJECT_UNLOCK(obj);
 2071                         else if (m != NULL)
 2072                                 error = EAGAIN; /* send what we already got */
 2073                         else if (uap->flags & SF_NODISKIO)
 2074                                 error = EBUSY;
 2075                         else {
 2076                                 int bsize, resid;
 2077 
 2078                                 /*
 2079                                  * Ensure that our page is still around
 2080                                  * when the I/O completes.
 2081                                  */
 2082                                 vm_page_io_start(pg);
 2083                                 VM_OBJECT_UNLOCK(obj);
 2084 
 2085                                 /*
 2086                                  * Get the page from backing store.
 2087                                  */
 2088                                 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
 2089                                 error = vn_lock(vp, LK_SHARED);
 2090                                 if (error != 0)
 2091                                         goto after_read;
 2092                                 bsize = vp->v_mount->mnt_stat.f_iosize;
 2093 
 2094                                 /*
 2095                                  * XXXMAC: Because we don't have fp->f_cred
 2096                                  * here, we pass in NOCRED.  This is probably
 2097                                  * wrong, but is consistent with our original
 2098                                  * implementation.
 2099                                  */
 2100                                 error = vn_rdwr(UIO_READ, vp, NULL, MAXBSIZE,
 2101                                     trunc_page(off), UIO_NOCOPY, IO_NODELOCKED |
 2102                                     IO_VMIO | ((MAXBSIZE / bsize) << IO_SEQSHIFT),
 2103                                     td->td_ucred, NOCRED, &resid, td);
 2104                                 VOP_UNLOCK(vp, 0);
 2105                         after_read:
 2106                                 VFS_UNLOCK_GIANT(vfslocked);
 2107                                 VM_OBJECT_LOCK(obj);
 2108                                 vm_page_io_finish(pg);
 2109                                 if (!error)
 2110                                         VM_OBJECT_UNLOCK(obj);
 2111                                 mbstat.sf_iocnt++;
 2112                         }
 2113                         if (error) {
 2114                                 vm_page_lock_queues();
 2115                                 vm_page_unwire(pg, 0);
 2116                                 /*
 2117                                  * See if anyone else might know about
 2118                                  * this page.  If not and it is not valid,
 2119                                  * then free it.
 2120                                  */
 2121                                 if (pg->wire_count == 0 && pg->valid == 0 &&
 2122                                     pg->busy == 0 && !(pg->oflags & VPO_BUSY) &&
 2123                                     pg->hold_count == 0) {
 2124                                         vm_page_free(pg);
 2125                                 }
 2126                                 vm_page_unlock_queues();
 2127                                 VM_OBJECT_UNLOCK(obj);
 2128                                 if (error == EAGAIN)
 2129                                         error = 0;      /* not a real error */
 2130                                 break;
 2131                         }
 2132 
 2133                         /*
 2134                          * Get a sendfile buf.  We usually wait as long
 2135                          * as necessary, but this wait can be interrupted.
 2136                          */
 2137                         if ((sf = sf_buf_alloc(pg,
 2138                             (mnw ? SFB_NOWAIT : SFB_CATCH))) == NULL) {
 2139                                 mbstat.sf_allocfail++;
 2140                                 vm_page_lock_queues();
 2141                                 vm_page_unwire(pg, 0);
 2142                                 /*
 2143                                  * XXX: Not same check as above!?
 2144                                  */
 2145                                 if (pg->wire_count == 0 && pg->object == NULL)
 2146                                         vm_page_free(pg);
 2147                                 vm_page_unlock_queues();
 2148                                 error = (mnw ? EAGAIN : EINTR);
 2149                                 break;
 2150                         }
 2151 
 2152                         /*
 2153                          * Get an mbuf and set it up as having
 2154                          * external storage.
 2155                          */
 2156                         m0 = m_get((mnw ? M_NOWAIT : M_WAITOK), MT_DATA);
 2157                         if (m0 == NULL) {
 2158                                 error = (mnw ? EAGAIN : ENOBUFS);
 2159                                 sf_buf_mext((void *)sf_buf_kva(sf), sf);
 2160                                 break;
 2161                         }
 2162                         MEXTADD(m0, sf_buf_kva(sf), PAGE_SIZE, sf_buf_mext,
 2163                             sfs, sf, M_RDONLY, EXT_SFBUF);
 2164                         m0->m_data = (char *)sf_buf_kva(sf) + pgoff;
 2165                         m0->m_len = xfsize;
 2166 
 2167                         /* Append to mbuf chain. */
 2168                         if (m != NULL)
 2169                                 m_cat(m, m0);
 2170                         else
 2171                                 m = m0;
 2172 
 2173                         /* Keep track of bits processed. */
 2174                         loopbytes += xfsize;
 2175                         off += xfsize;
 2176 
 2177                         if (sfs != NULL) {
 2178                                 mtx_lock(&sfs->mtx);
 2179                                 sfs->count++;
 2180                                 mtx_unlock(&sfs->mtx);
 2181                         }
 2182                 }
 2183 
 2184                 /* Add the buffer chain to the socket buffer. */
 2185                 if (m != NULL) {
 2186                         int mlen, err;
 2187 
 2188                         mlen = m_length(m, NULL);
 2189                         SOCKBUF_LOCK(&so->so_snd);
 2190                         if (so->so_snd.sb_state & SBS_CANTSENDMORE) {
 2191                                 error = EPIPE;
 2192                                 SOCKBUF_UNLOCK(&so->so_snd);
 2193                                 goto done;
 2194                         }
 2195                         SOCKBUF_UNLOCK(&so->so_snd);
 2196                         CURVNET_SET(so->so_vnet);
 2197                         /* Avoid error aliasing. */
 2198                         err = (*so->so_proto->pr_usrreqs->pru_send)
 2199                                     (so, 0, m, NULL, NULL, td);
 2200                         CURVNET_RESTORE();
 2201                         if (err == 0) {
 2202                                 /*
 2203                                  * We need two counters to get the
 2204                                  * file offset and nbytes to send
 2205                                  * right:
 2206                                  * - sbytes contains the total amount
 2207                                  *   of bytes sent, including headers.
 2208                                  * - fsbytes contains the total amount
 2209                                  *   of bytes sent from the file.
 2210                                  */
 2211                                 sbytes += mlen;
 2212                                 fsbytes += mlen;
 2213                                 if (hdrlen) {
 2214                                         fsbytes -= hdrlen;
 2215                                         hdrlen = 0;
 2216                                 }
 2217                         } else if (error == 0)
 2218                                 error = err;
 2219                         m = NULL;       /* pru_send always consumes */
 2220                 }
 2221 
 2222                 /* Quit outer loop on error or when we're done. */
 2223                 if (done) 
 2224                         break;
 2225                 if (error)
 2226                         goto done;
 2227         }
 2228 
 2229         /*
 2230          * Send trailers. Wimp out and use writev(2).
 2231          */
 2232         if (trl_uio != NULL) {
 2233                 sbunlock(&so->so_snd);
 2234                 error = kern_writev(td, uap->s, trl_uio);
 2235                 if (error == 0)
 2236                         sbytes += td->td_retval[0];
 2237                 goto out;
 2238         }
 2239 
 2240 done:
 2241         sbunlock(&so->so_snd);
 2242 out:
 2243         /*
 2244          * If there was no error we have to clear td->td_retval[0]
 2245          * because it may have been set by writev.
 2246          */
 2247         if (error == 0) {
 2248                 td->td_retval[0] = 0;
 2249         }
 2250         if (uap->sbytes != NULL) {
 2251                 copyout(&sbytes, uap->sbytes, sizeof(off_t));
 2252         }
 2253         if (obj != NULL)
 2254                 vm_object_deallocate(obj);
 2255         if (vp != NULL) {
 2256                 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
 2257                 vrele(vp);
 2258                 VFS_UNLOCK_GIANT(vfslocked);
 2259         }
 2260         if (so)
 2261                 fdrop(sock_fp, td);
 2262         if (m)
 2263                 m_freem(m);
 2264 
 2265         if (sfs != NULL) {
 2266                 mtx_lock(&sfs->mtx);
 2267                 if (sfs->count != 0)
 2268                         cv_wait(&sfs->cv, &sfs->mtx);
 2269                 KASSERT(sfs->count == 0, ("sendfile sync still busy"));
 2270                 cv_destroy(&sfs->cv);
 2271                 mtx_destroy(&sfs->mtx);
 2272                 free(sfs, M_TEMP);
 2273         }
 2274 
 2275         if (error == ERESTART)
 2276                 error = EINTR;
 2277 
 2278         return (error);
 2279 }
 2280 
 2281 /*
 2282  * SCTP syscalls.
 2283  * Functionality only compiled in if SCTP is defined in the kernel Makefile,
 2284  * otherwise all return EOPNOTSUPP.
 2285  * XXX: We should make this loadable one day.
 2286  */
 2287 int
 2288 sctp_peeloff(td, uap)
 2289         struct thread *td;
 2290         struct sctp_peeloff_args /* {
 2291                 int     sd;
 2292                 caddr_t name;
 2293         } */ *uap;
 2294 {
 2295 #if (defined(INET) || defined(INET6)) && defined(SCTP)
 2296         struct filedesc *fdp;
 2297         struct file *nfp = NULL;
 2298         int error;
 2299         struct socket *head, *so;
 2300         int fd;
 2301         u_int fflag;
 2302 
 2303         fdp = td->td_proc->p_fd;
 2304         AUDIT_ARG_FD(uap->sd);
 2305         error = fgetsock(td, uap->sd, &head, &fflag);
 2306         if (error)
 2307                 goto done2;
 2308         error = sctp_can_peel_off(head, (sctp_assoc_t)uap->name);
 2309         if (error)
 2310                 goto done2;
 2311         /*
 2312          * At this point we know we do have a assoc to pull
 2313          * we proceed to get the fd setup. This may block
 2314          * but that is ok.
 2315          */
 2316 
 2317         error = falloc(td, &nfp, &fd);
 2318         if (error)
 2319                 goto done;
 2320         td->td_retval[0] = fd;
 2321 
 2322         so = sonewconn(head, SS_ISCONNECTED);
 2323         if (so == NULL) 
 2324                 goto noconnection;
 2325         /*
 2326          * Before changing the flags on the socket, we have to bump the
 2327          * reference count.  Otherwise, if the protocol calls sofree(),
 2328          * the socket will be released due to a zero refcount.
 2329          */
 2330         SOCK_LOCK(so);
 2331         soref(so);                      /* file descriptor reference */
 2332         SOCK_UNLOCK(so);
 2333 
 2334         ACCEPT_LOCK();
 2335 
 2336         TAILQ_REMOVE(&head->so_comp, so, so_list);
 2337         head->so_qlen--;
 2338         so->so_state |= (head->so_state & SS_NBIO);
 2339         so->so_state &= ~SS_NOFDREF;
 2340         so->so_qstate &= ~SQ_COMP;
 2341         so->so_head = NULL;
 2342         ACCEPT_UNLOCK();
 2343         finit(nfp, fflag, DTYPE_SOCKET, so, &socketops);
 2344         error = sctp_do_peeloff(head, so, (sctp_assoc_t)uap->name);
 2345         if (error)
 2346                 goto noconnection;
 2347         if (head->so_sigio != NULL)
 2348                 fsetown(fgetown(&head->so_sigio), &so->so_sigio);
 2349 
 2350 noconnection:
 2351         /*
 2352          * close the new descriptor, assuming someone hasn't ripped it
 2353          * out from under us.
 2354          */
 2355         if (error)
 2356                 fdclose(fdp, nfp, fd, td);
 2357 
 2358         /*
 2359          * Release explicitly held references before returning.
 2360          */
 2361 done:
 2362         if (nfp != NULL)
 2363                 fdrop(nfp, td);
 2364         fputsock(head);
 2365 done2:
 2366         return (error);
 2367 #else  /* SCTP */
 2368         return (EOPNOTSUPP);
 2369 #endif /* SCTP */
 2370 }
 2371 
 2372 int
 2373 sctp_generic_sendmsg (td, uap)
 2374         struct thread *td;
 2375         struct sctp_generic_sendmsg_args /* {
 2376                 int sd, 
 2377                 caddr_t msg, 
 2378                 int mlen, 
 2379                 caddr_t to, 
 2380                 __socklen_t tolen, 
 2381                 struct sctp_sndrcvinfo *sinfo, 
 2382                 int flags
 2383         } */ *uap;
 2384 {
 2385 #if (defined(INET) || defined(INET6)) && defined(SCTP)
 2386         struct sctp_sndrcvinfo sinfo, *u_sinfo = NULL;
 2387         struct socket *so;
 2388         struct file *fp = NULL;
 2389         int use_rcvinfo = 1;
 2390         int error = 0, len;
 2391         struct sockaddr *to = NULL;
 2392 #ifdef KTRACE
 2393         struct uio *ktruio = NULL;
 2394 #endif
 2395         struct uio auio;
 2396         struct iovec iov[1];
 2397 
 2398         if (uap->sinfo) {
 2399                 error = copyin(uap->sinfo, &sinfo, sizeof (sinfo));
 2400                 if (error)
 2401                         return (error);
 2402                 u_sinfo = &sinfo;
 2403         }
 2404         if (uap->tolen) {
 2405                 error = getsockaddr(&to, uap->to, uap->tolen);
 2406                 if (error) {
 2407                         to = NULL;
 2408                         goto sctp_bad2;
 2409                 }
 2410         }
 2411 
 2412         AUDIT_ARG_FD(uap->sd);
 2413         error = getsock(td->td_proc->p_fd, uap->sd, &fp, NULL);
 2414         if (error)
 2415                 goto sctp_bad;
 2416 #ifdef KTRACE
 2417         if (KTRPOINT(td, KTR_STRUCT))
 2418                 ktrsockaddr(to);
 2419 #endif
 2420 
 2421         iov[0].iov_base = uap->msg;
 2422         iov[0].iov_len = uap->mlen;
 2423 
 2424         so = (struct socket *)fp->f_data;
 2425 #ifdef MAC
 2426         error = mac_socket_check_send(td->td_ucred, so);
 2427         if (error)
 2428                 goto sctp_bad;
 2429 #endif /* MAC */
 2430 
 2431         auio.uio_iov =  iov;
 2432         auio.uio_iovcnt = 1;
 2433         auio.uio_segflg = UIO_USERSPACE;
 2434         auio.uio_rw = UIO_WRITE;
 2435         auio.uio_td = td;
 2436         auio.uio_offset = 0;                    /* XXX */
 2437         auio.uio_resid = 0;
 2438         len = auio.uio_resid = uap->mlen;
 2439         error = sctp_lower_sosend(so, to, &auio,
 2440                     (struct mbuf *)NULL, (struct mbuf *)NULL,
 2441                     uap->flags, use_rcvinfo, u_sinfo, td);
 2442         if (error) {
 2443                 if (auio.uio_resid != len && (error == ERESTART ||
 2444                     error == EINTR || error == EWOULDBLOCK))
 2445                         error = 0;
 2446                 /* Generation of SIGPIPE can be controlled per socket. */
 2447                 if (error == EPIPE && !(so->so_options & SO_NOSIGPIPE) &&
 2448                     !(uap->flags & MSG_NOSIGNAL)) {
 2449                         PROC_LOCK(td->td_proc);
 2450                         psignal(td->td_proc, SIGPIPE);
 2451                         PROC_UNLOCK(td->td_proc);
 2452                 }
 2453         }
 2454         if (error == 0)
 2455                 td->td_retval[0] = len - auio.uio_resid;
 2456 #ifdef KTRACE
 2457         if (ktruio != NULL) {
 2458                 ktruio->uio_resid = td->td_retval[0];
 2459                 ktrgenio(uap->sd, UIO_WRITE, ktruio, error);
 2460         }
 2461 #endif /* KTRACE */
 2462 sctp_bad:
 2463         if (fp)
 2464                 fdrop(fp, td);
 2465 sctp_bad2:
 2466         if (to)
 2467                 free(to, M_SONAME);
 2468         return (error);
 2469 #else  /* SCTP */
 2470         return (EOPNOTSUPP);
 2471 #endif /* SCTP */
 2472 }
 2473 
 2474 int
 2475 sctp_generic_sendmsg_iov(td, uap)
 2476         struct thread *td;
 2477         struct sctp_generic_sendmsg_iov_args /* {
 2478                 int sd, 
 2479                 struct iovec *iov, 
 2480                 int iovlen, 
 2481                 caddr_t to, 
 2482                 __socklen_t tolen, 
 2483                 struct sctp_sndrcvinfo *sinfo, 
 2484                 int flags
 2485         } */ *uap;
 2486 {
 2487 #if (defined(INET) || defined(INET6)) && defined(SCTP)
 2488         struct sctp_sndrcvinfo sinfo, *u_sinfo = NULL;
 2489         struct socket *so;
 2490         struct file *fp = NULL;
 2491         int use_rcvinfo = 1;
 2492         int error=0, len, i;
 2493         struct sockaddr *to = NULL;
 2494 #ifdef KTRACE
 2495         struct uio *ktruio = NULL;
 2496 #endif
 2497         struct uio auio;
 2498         struct iovec *iov, *tiov;
 2499 
 2500         if (uap->sinfo) {
 2501                 error = copyin(uap->sinfo, &sinfo, sizeof (sinfo));
 2502                 if (error)
 2503                         return (error);
 2504                 u_sinfo = &sinfo;
 2505         }
 2506         if (uap->tolen) {
 2507                 error = getsockaddr(&to, uap->to, uap->tolen);
 2508                 if (error) {
 2509                         to = NULL;
 2510                         goto sctp_bad2;
 2511                 }
 2512         }
 2513 
 2514         AUDIT_ARG_FD(uap->sd);
 2515         error = getsock(td->td_proc->p_fd, uap->sd, &fp, NULL);
 2516         if (error)
 2517                 goto sctp_bad1;
 2518 
 2519         error = copyiniov(uap->iov, uap->iovlen, &iov, EMSGSIZE);
 2520         if (error)
 2521                 goto sctp_bad1;
 2522 #ifdef KTRACE
 2523         if (KTRPOINT(td, KTR_STRUCT))
 2524                 ktrsockaddr(to);
 2525 #endif
 2526 
 2527         so = (struct socket *)fp->f_data;
 2528 #ifdef MAC
 2529         error = mac_socket_check_send(td->td_ucred, so);
 2530         if (error)
 2531                 goto sctp_bad;
 2532 #endif /* MAC */
 2533 
 2534         auio.uio_iov =  iov;
 2535         auio.uio_iovcnt = uap->iovlen;
 2536         auio.uio_segflg = UIO_USERSPACE;
 2537         auio.uio_rw = UIO_WRITE;
 2538         auio.uio_td = td;
 2539         auio.uio_offset = 0;                    /* XXX */
 2540         auio.uio_resid = 0;
 2541         tiov = iov;
 2542         for (i = 0; i <uap->iovlen; i++, tiov++) {
 2543                 if ((auio.uio_resid += tiov->iov_len) < 0) {
 2544                         error = EINVAL;
 2545                         goto sctp_bad;
 2546                 }
 2547         }
 2548         len = auio.uio_resid;
 2549         error = sctp_lower_sosend(so, to, &auio,
 2550                     (struct mbuf *)NULL, (struct mbuf *)NULL,
 2551                     uap->flags, use_rcvinfo, u_sinfo, td);
 2552         if (error) {
 2553                 if (auio.uio_resid != len && (error == ERESTART ||
 2554                     error == EINTR || error == EWOULDBLOCK))
 2555                         error = 0;
 2556                 /* Generation of SIGPIPE can be controlled per socket */
 2557                 if (error == EPIPE && !(so->so_options & SO_NOSIGPIPE) &&
 2558                     !(uap->flags & MSG_NOSIGNAL)) {
 2559                         PROC_LOCK(td->td_proc);
 2560                         psignal(td->td_proc, SIGPIPE);
 2561                         PROC_UNLOCK(td->td_proc);
 2562                 }
 2563         }
 2564         if (error == 0)
 2565                 td->td_retval[0] = len - auio.uio_resid;
 2566 #ifdef KTRACE
 2567         if (ktruio != NULL) {
 2568                 ktruio->uio_resid = td->td_retval[0];
 2569                 ktrgenio(uap->sd, UIO_WRITE, ktruio, error);
 2570         }
 2571 #endif /* KTRACE */
 2572 sctp_bad:
 2573         free(iov, M_IOV);
 2574 sctp_bad1:
 2575         if (fp)
 2576                 fdrop(fp, td);
 2577 sctp_bad2:
 2578         if (to)
 2579                 free(to, M_SONAME);
 2580         return (error);
 2581 #else  /* SCTP */
 2582         return (EOPNOTSUPP);
 2583 #endif /* SCTP */
 2584 }
 2585 
 2586 int
 2587 sctp_generic_recvmsg(td, uap)
 2588         struct thread *td;
 2589         struct sctp_generic_recvmsg_args /* {
 2590                 int sd, 
 2591                 struct iovec *iov, 
 2592                 int iovlen,
 2593                 struct sockaddr *from, 
 2594                 __socklen_t *fromlenaddr,
 2595                 struct sctp_sndrcvinfo *sinfo, 
 2596                 int *msg_flags
 2597         } */ *uap;
 2598 {
 2599 #if (defined(INET) || defined(INET6)) && defined(SCTP)
 2600         u_int8_t sockbufstore[256];
 2601         struct uio auio;
 2602         struct iovec *iov, *tiov;
 2603         struct sctp_sndrcvinfo sinfo;
 2604         struct socket *so;
 2605         struct file *fp = NULL;
 2606         struct sockaddr *fromsa;
 2607         int fromlen;
 2608         int len, i, msg_flags;
 2609         int error = 0;
 2610 #ifdef KTRACE
 2611         struct uio *ktruio = NULL;
 2612 #endif
 2613 
 2614         AUDIT_ARG_FD(uap->sd);
 2615         error = getsock(td->td_proc->p_fd, uap->sd, &fp, NULL);
 2616         if (error) {
 2617                 return (error);
 2618         }
 2619         error = copyiniov(uap->iov, uap->iovlen, &iov, EMSGSIZE);
 2620         if (error) {
 2621                 goto out1;
 2622         }
 2623 
 2624         so = fp->f_data;
 2625 #ifdef MAC
 2626         error = mac_socket_check_receive(td->td_ucred, so);
 2627         if (error) {
 2628                 goto out;
 2629                 return (error);
 2630         }
 2631 #endif /* MAC */
 2632 
 2633         if (uap->fromlenaddr) {
 2634                 error = copyin(uap->fromlenaddr,
 2635                     &fromlen, sizeof (fromlen));
 2636                 if (error) {
 2637                         goto out;
 2638                 }
 2639         } else {
 2640                 fromlen = 0;
 2641         }
 2642         if(uap->msg_flags) {
 2643                 error = copyin(uap->msg_flags, &msg_flags, sizeof (int));
 2644                 if (error) {
 2645                         goto out;
 2646                 }
 2647         } else {
 2648                 msg_flags = 0;
 2649         }
 2650         auio.uio_iov = iov;
 2651         auio.uio_iovcnt = uap->iovlen;
 2652         auio.uio_segflg = UIO_USERSPACE;
 2653         auio.uio_rw = UIO_READ;
 2654         auio.uio_td = td;
 2655         auio.uio_offset = 0;                    /* XXX */
 2656         auio.uio_resid = 0;
 2657         tiov = iov;
 2658         for (i = 0; i <uap->iovlen; i++, tiov++) {
 2659                 if ((auio.uio_resid += tiov->iov_len) < 0) {
 2660                         error = EINVAL;
 2661                         goto out;
 2662                 }
 2663         }
 2664         len = auio.uio_resid;
 2665         fromsa = (struct sockaddr *)sockbufstore;
 2666 
 2667 #ifdef KTRACE
 2668         if (KTRPOINT(td, KTR_GENIO))
 2669                 ktruio = cloneuio(&auio);
 2670 #endif /* KTRACE */
 2671         error = sctp_sorecvmsg(so, &auio, (struct mbuf **)NULL,
 2672                     fromsa, fromlen, &msg_flags,
 2673                     (struct sctp_sndrcvinfo *)&sinfo, 1);
 2674         if (error) {
 2675                 if (auio.uio_resid != (int)len && (error == ERESTART ||
 2676                     error == EINTR || error == EWOULDBLOCK))
 2677                         error = 0;
 2678         } else {
 2679                 if (uap->sinfo)
 2680                         error = copyout(&sinfo, uap->sinfo, sizeof (sinfo));
 2681         }
 2682 #ifdef KTRACE
 2683         if (ktruio != NULL) {
 2684                 ktruio->uio_resid = (int)len - auio.uio_resid;
 2685                 ktrgenio(uap->sd, UIO_READ, ktruio, error);
 2686         }
 2687 #endif /* KTRACE */
 2688         if (error)
 2689                 goto out;
 2690         td->td_retval[0] = (int)len - auio.uio_resid;
 2691 
 2692         if (fromlen && uap->from) {
 2693                 len = fromlen;
 2694                 if (len <= 0 || fromsa == 0)
 2695                         len = 0;
 2696                 else {
 2697                         len = MIN(len, fromsa->sa_len);
 2698                         error = copyout(fromsa, uap->from, (unsigned)len);
 2699                         if (error)
 2700                                 goto out;
 2701                 }
 2702                 error = copyout(&len, uap->fromlenaddr, sizeof (socklen_t));
 2703                 if (error) {
 2704                         goto out;
 2705                 }
 2706         }
 2707 #ifdef KTRACE
 2708         if (KTRPOINT(td, KTR_STRUCT))
 2709                 ktrsockaddr(fromsa);
 2710 #endif
 2711         if (uap->msg_flags) {
 2712                 error = copyout(&msg_flags, uap->msg_flags, sizeof (int));
 2713                 if (error) {
 2714                         goto out;
 2715                 }
 2716         }
 2717 out:
 2718         free(iov, M_IOV);
 2719 out1:
 2720         if (fp) 
 2721                 fdrop(fp, td);
 2722 
 2723         return (error);
 2724 #else  /* SCTP */
 2725         return (EOPNOTSUPP);
 2726 #endif /* SCTP */
 2727 }

Cache object: ec5fbf75aed11f2182c2ec84a44372ac


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.