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  * SPDX-License-Identifier: BSD-3-Clause
    3  *
    4  * Copyright (c) 1982, 1986, 1989, 1990, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. Neither the name of the University nor the names of its contributors
   16  *    may be used to endorse or promote products derived from this software
   17  *    without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  *
   31  *      @(#)uipc_syscalls.c     8.4 (Berkeley) 2/21/94
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 __FBSDID("$FreeBSD: releng/12.0/sys/kern/uipc_syscalls.c 343790 2019-02-05 18:11:15Z emaste $");
   36 
   37 #include "opt_capsicum.h"
   38 #include "opt_inet.h"
   39 #include "opt_inet6.h"
   40 #include "opt_ktrace.h"
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/capsicum.h>
   45 #include <sys/kernel.h>
   46 #include <sys/lock.h>
   47 #include <sys/mutex.h>
   48 #include <sys/sysproto.h>
   49 #include <sys/malloc.h>
   50 #include <sys/filedesc.h>
   51 #include <sys/proc.h>
   52 #include <sys/filio.h>
   53 #include <sys/jail.h>
   54 #include <sys/mbuf.h>
   55 #include <sys/protosw.h>
   56 #include <sys/rwlock.h>
   57 #include <sys/socket.h>
   58 #include <sys/socketvar.h>
   59 #include <sys/syscallsubr.h>
   60 #include <sys/uio.h>
   61 #include <sys/un.h>
   62 #include <sys/unpcb.h>
   63 #ifdef KTRACE
   64 #include <sys/ktrace.h>
   65 #endif
   66 #ifdef COMPAT_FREEBSD32
   67 #include <compat/freebsd32/freebsd32_util.h>
   68 #endif
   69 
   70 #include <net/vnet.h>
   71 
   72 #include <security/audit/audit.h>
   73 #include <security/mac/mac_framework.h>
   74 
   75 static int sendit(struct thread *td, int s, struct msghdr *mp, int flags);
   76 static int recvit(struct thread *td, int s, struct msghdr *mp, void *namelenp);
   77 
   78 static int accept1(struct thread *td, int s, struct sockaddr *uname,
   79                    socklen_t *anamelen, int flags);
   80 static int getsockname1(struct thread *td, struct getsockname_args *uap,
   81                         int compat);
   82 static int getpeername1(struct thread *td, struct getpeername_args *uap,
   83                         int compat);
   84 static int sockargs(struct mbuf **, char *, socklen_t, int);
   85 
   86 /*
   87  * Convert a user file descriptor to a kernel file entry and check if required
   88  * capability rights are present.
   89  * If required copy of current set of capability rights is returned.
   90  * A reference on the file entry is held upon returning.
   91  */
   92 int
   93 getsock_cap(struct thread *td, int fd, cap_rights_t *rightsp,
   94     struct file **fpp, u_int *fflagp, struct filecaps *havecapsp)
   95 {
   96         struct file *fp;
   97         int error;
   98 
   99         error = fget_cap(td, fd, rightsp, &fp, havecapsp);
  100         if (error != 0)
  101                 return (error);
  102         if (fp->f_type != DTYPE_SOCKET) {
  103                 fdrop(fp, td);
  104                 if (havecapsp != NULL)
  105                         filecaps_free(havecapsp);
  106                 return (ENOTSOCK);
  107         }
  108         if (fflagp != NULL)
  109                 *fflagp = fp->f_flag;
  110         *fpp = fp;
  111         return (0);
  112 }
  113 
  114 /*
  115  * System call interface to the socket abstraction.
  116  */
  117 #if defined(COMPAT_43)
  118 #define COMPAT_OLDSOCK
  119 #endif
  120 
  121 int
  122 sys_socket(struct thread *td, struct socket_args *uap)
  123 {
  124 
  125         return (kern_socket(td, uap->domain, uap->type, uap->protocol));
  126 }
  127 
  128 int
  129 kern_socket(struct thread *td, int domain, int type, int protocol)
  130 {
  131         struct socket *so;
  132         struct file *fp;
  133         int fd, error, oflag, fflag;
  134 
  135         AUDIT_ARG_SOCKET(domain, type, protocol);
  136 
  137         oflag = 0;
  138         fflag = 0;
  139         if ((type & SOCK_CLOEXEC) != 0) {
  140                 type &= ~SOCK_CLOEXEC;
  141                 oflag |= O_CLOEXEC;
  142         }
  143         if ((type & SOCK_NONBLOCK) != 0) {
  144                 type &= ~SOCK_NONBLOCK;
  145                 fflag |= FNONBLOCK;
  146         }
  147 
  148 #ifdef MAC
  149         error = mac_socket_check_create(td->td_ucred, domain, type, protocol);
  150         if (error != 0)
  151                 return (error);
  152 #endif
  153         error = falloc(td, &fp, &fd, oflag);
  154         if (error != 0)
  155                 return (error);
  156         /* An extra reference on `fp' has been held for us by falloc(). */
  157         error = socreate(domain, &so, type, protocol, td->td_ucred, td);
  158         if (error != 0) {
  159                 fdclose(td, fp, fd);
  160         } else {
  161                 finit(fp, FREAD | FWRITE | fflag, DTYPE_SOCKET, so, &socketops);
  162                 if ((fflag & FNONBLOCK) != 0)
  163                         (void) fo_ioctl(fp, FIONBIO, &fflag, td->td_ucred, td);
  164                 td->td_retval[0] = fd;
  165         }
  166         fdrop(fp, td);
  167         return (error);
  168 }
  169 
  170 int
  171 sys_bind(struct thread *td, struct bind_args *uap)
  172 {
  173         struct sockaddr *sa;
  174         int error;
  175 
  176         error = getsockaddr(&sa, uap->name, uap->namelen);
  177         if (error == 0) {
  178                 error = kern_bindat(td, AT_FDCWD, uap->s, sa);
  179                 free(sa, M_SONAME);
  180         }
  181         return (error);
  182 }
  183 
  184 int
  185 kern_bindat(struct thread *td, int dirfd, int fd, struct sockaddr *sa)
  186 {
  187         struct socket *so;
  188         struct file *fp;
  189         int error;
  190 
  191 #ifdef CAPABILITY_MODE
  192         if (IN_CAPABILITY_MODE(td) && (dirfd == AT_FDCWD))
  193                 return (ECAPMODE);
  194 #endif
  195 
  196         AUDIT_ARG_FD(fd);
  197         AUDIT_ARG_SOCKADDR(td, dirfd, sa);
  198         error = getsock_cap(td, fd, &cap_bind_rights,
  199             &fp, NULL, NULL);
  200         if (error != 0)
  201                 return (error);
  202         so = fp->f_data;
  203 #ifdef KTRACE
  204         if (KTRPOINT(td, KTR_STRUCT))
  205                 ktrsockaddr(sa);
  206 #endif
  207 #ifdef MAC
  208         error = mac_socket_check_bind(td->td_ucred, so, sa);
  209         if (error == 0) {
  210 #endif
  211                 if (dirfd == AT_FDCWD)
  212                         error = sobind(so, sa, td);
  213                 else
  214                         error = sobindat(dirfd, so, sa, td);
  215 #ifdef MAC
  216         }
  217 #endif
  218         fdrop(fp, td);
  219         return (error);
  220 }
  221 
  222 int
  223 sys_bindat(struct thread *td, struct bindat_args *uap)
  224 {
  225         struct sockaddr *sa;
  226         int error;
  227 
  228         error = getsockaddr(&sa, uap->name, uap->namelen);
  229         if (error == 0) {
  230                 error = kern_bindat(td, uap->fd, uap->s, sa);
  231                 free(sa, M_SONAME);
  232         }
  233         return (error);
  234 }
  235 
  236 int
  237 sys_listen(struct thread *td, struct listen_args *uap)
  238 {
  239 
  240         return (kern_listen(td, uap->s, uap->backlog));
  241 }
  242 
  243 int
  244 kern_listen(struct thread *td, int s, int backlog)
  245 {
  246         struct socket *so;
  247         struct file *fp;
  248         int error;
  249 
  250         AUDIT_ARG_FD(s);
  251         error = getsock_cap(td, s, &cap_listen_rights,
  252             &fp, NULL, NULL);
  253         if (error == 0) {
  254                 so = fp->f_data;
  255 #ifdef MAC
  256                 error = mac_socket_check_listen(td->td_ucred, so);
  257                 if (error == 0)
  258 #endif
  259                         error = solisten(so, backlog, td);
  260                 fdrop(fp, td);
  261         }
  262         return (error);
  263 }
  264 
  265 /*
  266  * accept1()
  267  */
  268 static int
  269 accept1(td, s, uname, anamelen, flags)
  270         struct thread *td;
  271         int s;
  272         struct sockaddr *uname;
  273         socklen_t *anamelen;
  274         int flags;
  275 {
  276         struct sockaddr *name;
  277         socklen_t namelen;
  278         struct file *fp;
  279         int error;
  280 
  281         if (uname == NULL)
  282                 return (kern_accept4(td, s, NULL, NULL, flags, NULL));
  283 
  284         error = copyin(anamelen, &namelen, sizeof (namelen));
  285         if (error != 0)
  286                 return (error);
  287 
  288         error = kern_accept4(td, s, &name, &namelen, flags, &fp);
  289 
  290         if (error != 0)
  291                 return (error);
  292 
  293         if (error == 0 && uname != NULL) {
  294 #ifdef COMPAT_OLDSOCK
  295                 if (flags & ACCEPT4_COMPAT)
  296                         ((struct osockaddr *)name)->sa_family =
  297                             name->sa_family;
  298 #endif
  299                 error = copyout(name, uname, namelen);
  300         }
  301         if (error == 0)
  302                 error = copyout(&namelen, anamelen,
  303                     sizeof(namelen));
  304         if (error != 0)
  305                 fdclose(td, fp, td->td_retval[0]);
  306         fdrop(fp, td);
  307         free(name, M_SONAME);
  308         return (error);
  309 }
  310 
  311 int
  312 kern_accept(struct thread *td, int s, struct sockaddr **name,
  313     socklen_t *namelen, struct file **fp)
  314 {
  315         return (kern_accept4(td, s, name, namelen, ACCEPT4_INHERIT, fp));
  316 }
  317 
  318 int
  319 kern_accept4(struct thread *td, int s, struct sockaddr **name,
  320     socklen_t *namelen, int flags, struct file **fp)
  321 {
  322         struct file *headfp, *nfp = NULL;
  323         struct sockaddr *sa = NULL;
  324         struct socket *head, *so;
  325         struct filecaps fcaps;
  326         u_int fflag;
  327         pid_t pgid;
  328         int error, fd, tmp;
  329 
  330         if (name != NULL)
  331                 *name = NULL;
  332 
  333         AUDIT_ARG_FD(s);
  334         error = getsock_cap(td, s, &cap_accept_rights,
  335             &headfp, &fflag, &fcaps);
  336         if (error != 0)
  337                 return (error);
  338         head = headfp->f_data;
  339         if ((head->so_options & SO_ACCEPTCONN) == 0) {
  340                 error = EINVAL;
  341                 goto done;
  342         }
  343 #ifdef MAC
  344         error = mac_socket_check_accept(td->td_ucred, head);
  345         if (error != 0)
  346                 goto done;
  347 #endif
  348         error = falloc_caps(td, &nfp, &fd,
  349             (flags & SOCK_CLOEXEC) ? O_CLOEXEC : 0, &fcaps);
  350         if (error != 0)
  351                 goto done;
  352         SOCK_LOCK(head);
  353         if (!SOLISTENING(head)) {
  354                 SOCK_UNLOCK(head);
  355                 error = EINVAL;
  356                 goto noconnection;
  357         }
  358 
  359         error = solisten_dequeue(head, &so, flags);
  360         if (error != 0)
  361                 goto noconnection;
  362 
  363         /* An extra reference on `nfp' has been held for us by falloc(). */
  364         td->td_retval[0] = fd;
  365 
  366         /* Connection has been removed from the listen queue. */
  367         KNOTE_UNLOCKED(&head->so_rdsel.si_note, 0);
  368 
  369         if (flags & ACCEPT4_INHERIT) {
  370                 pgid = fgetown(&head->so_sigio);
  371                 if (pgid != 0)
  372                         fsetown(pgid, &so->so_sigio);
  373         } else {
  374                 fflag &= ~(FNONBLOCK | FASYNC);
  375                 if (flags & SOCK_NONBLOCK)
  376                         fflag |= FNONBLOCK;
  377         }
  378 
  379         finit(nfp, fflag, DTYPE_SOCKET, so, &socketops);
  380         /* Sync socket nonblocking/async state with file flags */
  381         tmp = fflag & FNONBLOCK;
  382         (void) fo_ioctl(nfp, FIONBIO, &tmp, td->td_ucred, td);
  383         tmp = fflag & FASYNC;
  384         (void) fo_ioctl(nfp, FIOASYNC, &tmp, td->td_ucred, td);
  385         error = soaccept(so, &sa);
  386         if (error != 0)
  387                 goto noconnection;
  388         if (sa == NULL) {
  389                 if (name)
  390                         *namelen = 0;
  391                 goto done;
  392         }
  393         AUDIT_ARG_SOCKADDR(td, AT_FDCWD, sa);
  394         if (name) {
  395                 /* check sa_len before it is destroyed */
  396                 if (*namelen > sa->sa_len)
  397                         *namelen = sa->sa_len;
  398 #ifdef KTRACE
  399                 if (KTRPOINT(td, KTR_STRUCT))
  400                         ktrsockaddr(sa);
  401 #endif
  402                 *name = sa;
  403                 sa = NULL;
  404         }
  405 noconnection:
  406         free(sa, M_SONAME);
  407 
  408         /*
  409          * close the new descriptor, assuming someone hasn't ripped it
  410          * out from under us.
  411          */
  412         if (error != 0)
  413                 fdclose(td, nfp, fd);
  414 
  415         /*
  416          * Release explicitly held references before returning.  We return
  417          * a reference on nfp to the caller on success if they request it.
  418          */
  419 done:
  420         if (nfp == NULL)
  421                 filecaps_free(&fcaps);
  422         if (fp != NULL) {
  423                 if (error == 0) {
  424                         *fp = nfp;
  425                         nfp = NULL;
  426                 } else
  427                         *fp = NULL;
  428         }
  429         if (nfp != NULL)
  430                 fdrop(nfp, td);
  431         fdrop(headfp, td);
  432         return (error);
  433 }
  434 
  435 int
  436 sys_accept(td, uap)
  437         struct thread *td;
  438         struct accept_args *uap;
  439 {
  440 
  441         return (accept1(td, uap->s, uap->name, uap->anamelen, ACCEPT4_INHERIT));
  442 }
  443 
  444 int
  445 sys_accept4(td, uap)
  446         struct thread *td;
  447         struct accept4_args *uap;
  448 {
  449 
  450         if (uap->flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
  451                 return (EINVAL);
  452 
  453         return (accept1(td, uap->s, uap->name, uap->anamelen, uap->flags));
  454 }
  455 
  456 #ifdef COMPAT_OLDSOCK
  457 int
  458 oaccept(td, uap)
  459         struct thread *td;
  460         struct accept_args *uap;
  461 {
  462 
  463         return (accept1(td, uap->s, uap->name, uap->anamelen,
  464             ACCEPT4_INHERIT | ACCEPT4_COMPAT));
  465 }
  466 #endif /* COMPAT_OLDSOCK */
  467 
  468 int
  469 sys_connect(struct thread *td, struct connect_args *uap)
  470 {
  471         struct sockaddr *sa;
  472         int error;
  473 
  474         error = getsockaddr(&sa, uap->name, uap->namelen);
  475         if (error == 0) {
  476                 error = kern_connectat(td, AT_FDCWD, uap->s, sa);
  477                 free(sa, M_SONAME);
  478         }
  479         return (error);
  480 }
  481 
  482 int
  483 kern_connectat(struct thread *td, int dirfd, int fd, struct sockaddr *sa)
  484 {
  485         struct socket *so;
  486         struct file *fp;
  487         int error, interrupted = 0;
  488 
  489 #ifdef CAPABILITY_MODE
  490         if (IN_CAPABILITY_MODE(td) && (dirfd == AT_FDCWD))
  491                 return (ECAPMODE);
  492 #endif
  493 
  494         AUDIT_ARG_FD(fd);
  495         AUDIT_ARG_SOCKADDR(td, dirfd, sa);
  496         error = getsock_cap(td, fd, &cap_connect_rights,
  497             &fp, NULL, NULL);
  498         if (error != 0)
  499                 return (error);
  500         so = fp->f_data;
  501         if (so->so_state & SS_ISCONNECTING) {
  502                 error = EALREADY;
  503                 goto done1;
  504         }
  505 #ifdef KTRACE
  506         if (KTRPOINT(td, KTR_STRUCT))
  507                 ktrsockaddr(sa);
  508 #endif
  509 #ifdef MAC
  510         error = mac_socket_check_connect(td->td_ucred, so, sa);
  511         if (error != 0)
  512                 goto bad;
  513 #endif
  514         if (dirfd == AT_FDCWD)
  515                 error = soconnect(so, sa, td);
  516         else
  517                 error = soconnectat(dirfd, so, sa, td);
  518         if (error != 0)
  519                 goto bad;
  520         if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
  521                 error = EINPROGRESS;
  522                 goto done1;
  523         }
  524         SOCK_LOCK(so);
  525         while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
  526                 error = msleep(&so->so_timeo, &so->so_lock, PSOCK | PCATCH,
  527                     "connec", 0);
  528                 if (error != 0) {
  529                         if (error == EINTR || error == ERESTART)
  530                                 interrupted = 1;
  531                         break;
  532                 }
  533         }
  534         if (error == 0) {
  535                 error = so->so_error;
  536                 so->so_error = 0;
  537         }
  538         SOCK_UNLOCK(so);
  539 bad:
  540         if (!interrupted)
  541                 so->so_state &= ~SS_ISCONNECTING;
  542         if (error == ERESTART)
  543                 error = EINTR;
  544 done1:
  545         fdrop(fp, td);
  546         return (error);
  547 }
  548 
  549 int
  550 sys_connectat(struct thread *td, struct connectat_args *uap)
  551 {
  552         struct sockaddr *sa;
  553         int error;
  554 
  555         error = getsockaddr(&sa, uap->name, uap->namelen);
  556         if (error == 0) {
  557                 error = kern_connectat(td, uap->fd, uap->s, sa);
  558                 free(sa, M_SONAME);
  559         }
  560         return (error);
  561 }
  562 
  563 int
  564 kern_socketpair(struct thread *td, int domain, int type, int protocol,
  565     int *rsv)
  566 {
  567         struct file *fp1, *fp2;
  568         struct socket *so1, *so2;
  569         int fd, error, oflag, fflag;
  570 
  571         AUDIT_ARG_SOCKET(domain, type, protocol);
  572 
  573         oflag = 0;
  574         fflag = 0;
  575         if ((type & SOCK_CLOEXEC) != 0) {
  576                 type &= ~SOCK_CLOEXEC;
  577                 oflag |= O_CLOEXEC;
  578         }
  579         if ((type & SOCK_NONBLOCK) != 0) {
  580                 type &= ~SOCK_NONBLOCK;
  581                 fflag |= FNONBLOCK;
  582         }
  583 #ifdef MAC
  584         /* We might want to have a separate check for socket pairs. */
  585         error = mac_socket_check_create(td->td_ucred, domain, type,
  586             protocol);
  587         if (error != 0)
  588                 return (error);
  589 #endif
  590         error = socreate(domain, &so1, type, protocol, td->td_ucred, td);
  591         if (error != 0)
  592                 return (error);
  593         error = socreate(domain, &so2, type, protocol, td->td_ucred, td);
  594         if (error != 0)
  595                 goto free1;
  596         /* On success extra reference to `fp1' and 'fp2' is set by falloc. */
  597         error = falloc(td, &fp1, &fd, oflag);
  598         if (error != 0)
  599                 goto free2;
  600         rsv[0] = fd;
  601         fp1->f_data = so1;      /* so1 already has ref count */
  602         error = falloc(td, &fp2, &fd, oflag);
  603         if (error != 0)
  604                 goto free3;
  605         fp2->f_data = so2;      /* so2 already has ref count */
  606         rsv[1] = fd;
  607         error = soconnect2(so1, so2);
  608         if (error != 0)
  609                 goto free4;
  610         if (type == SOCK_DGRAM) {
  611                 /*
  612                  * Datagram socket connection is asymmetric.
  613                  */
  614                  error = soconnect2(so2, so1);
  615                  if (error != 0)
  616                         goto free4;
  617         } else if (so1->so_proto->pr_flags & PR_CONNREQUIRED) {
  618                 struct unpcb *unp, *unp2;
  619                 unp = sotounpcb(so1);
  620                 unp2 = sotounpcb(so2);
  621                 /* 
  622                  * No need to lock the unps, because the sockets are brand-new.
  623                  * No other threads can be using them yet
  624                  */
  625                 unp_copy_peercred(td, unp, unp2, unp);
  626         }
  627         finit(fp1, FREAD | FWRITE | fflag, DTYPE_SOCKET, fp1->f_data,
  628             &socketops);
  629         finit(fp2, FREAD | FWRITE | fflag, DTYPE_SOCKET, fp2->f_data,
  630             &socketops);
  631         if ((fflag & FNONBLOCK) != 0) {
  632                 (void) fo_ioctl(fp1, FIONBIO, &fflag, td->td_ucred, td);
  633                 (void) fo_ioctl(fp2, FIONBIO, &fflag, td->td_ucred, td);
  634         }
  635         fdrop(fp1, td);
  636         fdrop(fp2, td);
  637         return (0);
  638 free4:
  639         fdclose(td, fp2, rsv[1]);
  640         fdrop(fp2, td);
  641 free3:
  642         fdclose(td, fp1, rsv[0]);
  643         fdrop(fp1, td);
  644 free2:
  645         if (so2 != NULL)
  646                 (void)soclose(so2);
  647 free1:
  648         if (so1 != NULL)
  649                 (void)soclose(so1);
  650         return (error);
  651 }
  652 
  653 int
  654 sys_socketpair(struct thread *td, struct socketpair_args *uap)
  655 {
  656         int error, sv[2];
  657 
  658         error = kern_socketpair(td, uap->domain, uap->type,
  659             uap->protocol, sv);
  660         if (error != 0)
  661                 return (error);
  662         error = copyout(sv, uap->rsv, 2 * sizeof(int));
  663         if (error != 0) {
  664                 (void)kern_close(td, sv[0]);
  665                 (void)kern_close(td, sv[1]);
  666         }
  667         return (error);
  668 }
  669 
  670 static int
  671 sendit(struct thread *td, int s, struct msghdr *mp, int flags)
  672 {
  673         struct mbuf *control;
  674         struct sockaddr *to;
  675         int error;
  676 
  677 #ifdef CAPABILITY_MODE
  678         if (IN_CAPABILITY_MODE(td) && (mp->msg_name != NULL))
  679                 return (ECAPMODE);
  680 #endif
  681 
  682         if (mp->msg_name != NULL) {
  683                 error = getsockaddr(&to, mp->msg_name, mp->msg_namelen);
  684                 if (error != 0) {
  685                         to = NULL;
  686                         goto bad;
  687                 }
  688                 mp->msg_name = to;
  689         } else {
  690                 to = NULL;
  691         }
  692 
  693         if (mp->msg_control) {
  694                 if (mp->msg_controllen < sizeof(struct cmsghdr)
  695 #ifdef COMPAT_OLDSOCK
  696                     && mp->msg_flags != MSG_COMPAT
  697 #endif
  698                 ) {
  699                         error = EINVAL;
  700                         goto bad;
  701                 }
  702                 error = sockargs(&control, mp->msg_control,
  703                     mp->msg_controllen, MT_CONTROL);
  704                 if (error != 0)
  705                         goto bad;
  706 #ifdef COMPAT_OLDSOCK
  707                 if (mp->msg_flags == MSG_COMPAT) {
  708                         struct cmsghdr *cm;
  709 
  710                         M_PREPEND(control, sizeof(*cm), M_WAITOK);
  711                         cm = mtod(control, struct cmsghdr *);
  712                         cm->cmsg_len = control->m_len;
  713                         cm->cmsg_level = SOL_SOCKET;
  714                         cm->cmsg_type = SCM_RIGHTS;
  715                 }
  716 #endif
  717         } else {
  718                 control = NULL;
  719         }
  720 
  721         error = kern_sendit(td, s, mp, flags, control, UIO_USERSPACE);
  722 
  723 bad:
  724         free(to, M_SONAME);
  725         return (error);
  726 }
  727 
  728 int
  729 kern_sendit(struct thread *td, int s, struct msghdr *mp, int flags,
  730     struct mbuf *control, enum uio_seg segflg)
  731 {
  732         struct file *fp;
  733         struct uio auio;
  734         struct iovec *iov;
  735         struct socket *so;
  736         cap_rights_t *rights;
  737 #ifdef KTRACE
  738         struct uio *ktruio = NULL;
  739 #endif
  740         ssize_t len;
  741         int i, error;
  742 
  743         AUDIT_ARG_FD(s);
  744         rights = &cap_send_rights;
  745         if (mp->msg_name != NULL) {
  746                 AUDIT_ARG_SOCKADDR(td, AT_FDCWD, mp->msg_name);
  747                 rights = &cap_send_connect_rights;
  748         }
  749         error = getsock_cap(td, s, rights, &fp, NULL, NULL);
  750         if (error != 0) {
  751                 m_freem(control);
  752                 return (error);
  753         }
  754         so = (struct socket *)fp->f_data;
  755 
  756 #ifdef KTRACE
  757         if (mp->msg_name != NULL && KTRPOINT(td, KTR_STRUCT))
  758                 ktrsockaddr(mp->msg_name);
  759 #endif
  760 #ifdef MAC
  761         if (mp->msg_name != NULL) {
  762                 error = mac_socket_check_connect(td->td_ucred, so,
  763                     mp->msg_name);
  764                 if (error != 0) {
  765                         m_freem(control);
  766                         goto bad;
  767                 }
  768         }
  769         error = mac_socket_check_send(td->td_ucred, so);
  770         if (error != 0) {
  771                 m_freem(control);
  772                 goto bad;
  773         }
  774 #endif
  775 
  776         auio.uio_iov = mp->msg_iov;
  777         auio.uio_iovcnt = mp->msg_iovlen;
  778         auio.uio_segflg = segflg;
  779         auio.uio_rw = UIO_WRITE;
  780         auio.uio_td = td;
  781         auio.uio_offset = 0;                    /* XXX */
  782         auio.uio_resid = 0;
  783         iov = mp->msg_iov;
  784         for (i = 0; i < mp->msg_iovlen; i++, iov++) {
  785                 if ((auio.uio_resid += iov->iov_len) < 0) {
  786                         error = EINVAL;
  787                         m_freem(control);
  788                         goto bad;
  789                 }
  790         }
  791 #ifdef KTRACE
  792         if (KTRPOINT(td, KTR_GENIO))
  793                 ktruio = cloneuio(&auio);
  794 #endif
  795         len = auio.uio_resid;
  796         error = sosend(so, mp->msg_name, &auio, 0, control, flags, td);
  797         if (error != 0) {
  798                 if (auio.uio_resid != len && (error == ERESTART ||
  799                     error == EINTR || error == EWOULDBLOCK))
  800                         error = 0;
  801                 /* Generation of SIGPIPE can be controlled per socket */
  802                 if (error == EPIPE && !(so->so_options & SO_NOSIGPIPE) &&
  803                     !(flags & MSG_NOSIGNAL)) {
  804                         PROC_LOCK(td->td_proc);
  805                         tdsignal(td, SIGPIPE);
  806                         PROC_UNLOCK(td->td_proc);
  807                 }
  808         }
  809         if (error == 0)
  810                 td->td_retval[0] = len - auio.uio_resid;
  811 #ifdef KTRACE
  812         if (ktruio != NULL) {
  813                 ktruio->uio_resid = td->td_retval[0];
  814                 ktrgenio(s, UIO_WRITE, ktruio, error);
  815         }
  816 #endif
  817 bad:
  818         fdrop(fp, td);
  819         return (error);
  820 }
  821 
  822 int
  823 sys_sendto(struct thread *td, struct sendto_args *uap)
  824 {
  825         struct msghdr msg;
  826         struct iovec aiov;
  827 
  828         msg.msg_name = uap->to;
  829         msg.msg_namelen = uap->tolen;
  830         msg.msg_iov = &aiov;
  831         msg.msg_iovlen = 1;
  832         msg.msg_control = 0;
  833 #ifdef COMPAT_OLDSOCK
  834         msg.msg_flags = 0;
  835 #endif
  836         aiov.iov_base = uap->buf;
  837         aiov.iov_len = uap->len;
  838         return (sendit(td, uap->s, &msg, uap->flags));
  839 }
  840 
  841 #ifdef COMPAT_OLDSOCK
  842 int
  843 osend(struct thread *td, struct osend_args *uap)
  844 {
  845         struct msghdr msg;
  846         struct iovec aiov;
  847 
  848         msg.msg_name = 0;
  849         msg.msg_namelen = 0;
  850         msg.msg_iov = &aiov;
  851         msg.msg_iovlen = 1;
  852         aiov.iov_base = uap->buf;
  853         aiov.iov_len = uap->len;
  854         msg.msg_control = 0;
  855         msg.msg_flags = 0;
  856         return (sendit(td, uap->s, &msg, uap->flags));
  857 }
  858 
  859 int
  860 osendmsg(struct thread *td, struct osendmsg_args *uap)
  861 {
  862         struct msghdr msg;
  863         struct iovec *iov;
  864         int error;
  865 
  866         error = copyin(uap->msg, &msg, sizeof (struct omsghdr));
  867         if (error != 0)
  868                 return (error);
  869         error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
  870         if (error != 0)
  871                 return (error);
  872         msg.msg_iov = iov;
  873         msg.msg_flags = MSG_COMPAT;
  874         error = sendit(td, uap->s, &msg, uap->flags);
  875         free(iov, M_IOV);
  876         return (error);
  877 }
  878 #endif
  879 
  880 int
  881 sys_sendmsg(struct thread *td, struct sendmsg_args *uap)
  882 {
  883         struct msghdr msg;
  884         struct iovec *iov;
  885         int error;
  886 
  887         error = copyin(uap->msg, &msg, sizeof (msg));
  888         if (error != 0)
  889                 return (error);
  890         error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
  891         if (error != 0)
  892                 return (error);
  893         msg.msg_iov = iov;
  894 #ifdef COMPAT_OLDSOCK
  895         msg.msg_flags = 0;
  896 #endif
  897         error = sendit(td, uap->s, &msg, uap->flags);
  898         free(iov, M_IOV);
  899         return (error);
  900 }
  901 
  902 int
  903 kern_recvit(struct thread *td, int s, struct msghdr *mp, enum uio_seg fromseg,
  904     struct mbuf **controlp)
  905 {
  906         struct uio auio;
  907         struct iovec *iov;
  908         struct mbuf *control, *m;
  909         caddr_t ctlbuf;
  910         struct file *fp;
  911         struct socket *so;
  912         struct sockaddr *fromsa = NULL;
  913 #ifdef KTRACE
  914         struct uio *ktruio = NULL;
  915 #endif
  916         ssize_t len;
  917         int error, i;
  918 
  919         if (controlp != NULL)
  920                 *controlp = NULL;
  921 
  922         AUDIT_ARG_FD(s);
  923         error = getsock_cap(td, s, &cap_recv_rights,
  924             &fp, NULL, NULL);
  925         if (error != 0)
  926                 return (error);
  927         so = fp->f_data;
  928 
  929 #ifdef MAC
  930         error = mac_socket_check_receive(td->td_ucred, so);
  931         if (error != 0) {
  932                 fdrop(fp, td);
  933                 return (error);
  934         }
  935 #endif
  936 
  937         auio.uio_iov = mp->msg_iov;
  938         auio.uio_iovcnt = mp->msg_iovlen;
  939         auio.uio_segflg = UIO_USERSPACE;
  940         auio.uio_rw = UIO_READ;
  941         auio.uio_td = td;
  942         auio.uio_offset = 0;                    /* XXX */
  943         auio.uio_resid = 0;
  944         iov = mp->msg_iov;
  945         for (i = 0; i < mp->msg_iovlen; i++, iov++) {
  946                 if ((auio.uio_resid += iov->iov_len) < 0) {
  947                         fdrop(fp, td);
  948                         return (EINVAL);
  949                 }
  950         }
  951 #ifdef KTRACE
  952         if (KTRPOINT(td, KTR_GENIO))
  953                 ktruio = cloneuio(&auio);
  954 #endif
  955         control = NULL;
  956         len = auio.uio_resid;
  957         error = soreceive(so, &fromsa, &auio, NULL,
  958             (mp->msg_control || controlp) ? &control : NULL,
  959             &mp->msg_flags);
  960         if (error != 0) {
  961                 if (auio.uio_resid != len && (error == ERESTART ||
  962                     error == EINTR || error == EWOULDBLOCK))
  963                         error = 0;
  964         }
  965         if (fromsa != NULL)
  966                 AUDIT_ARG_SOCKADDR(td, AT_FDCWD, fromsa);
  967 #ifdef KTRACE
  968         if (ktruio != NULL) {
  969                 ktruio->uio_resid = len - auio.uio_resid;
  970                 ktrgenio(s, UIO_READ, ktruio, error);
  971         }
  972 #endif
  973         if (error != 0)
  974                 goto out;
  975         td->td_retval[0] = len - auio.uio_resid;
  976         if (mp->msg_name) {
  977                 len = mp->msg_namelen;
  978                 if (len <= 0 || fromsa == NULL)
  979                         len = 0;
  980                 else {
  981                         /* save sa_len before it is destroyed by MSG_COMPAT */
  982                         len = MIN(len, fromsa->sa_len);
  983 #ifdef COMPAT_OLDSOCK
  984                         if (mp->msg_flags & MSG_COMPAT)
  985                                 ((struct osockaddr *)fromsa)->sa_family =
  986                                     fromsa->sa_family;
  987 #endif
  988                         if (fromseg == UIO_USERSPACE) {
  989                                 error = copyout(fromsa, mp->msg_name,
  990                                     (unsigned)len);
  991                                 if (error != 0)
  992                                         goto out;
  993                         } else
  994                                 bcopy(fromsa, mp->msg_name, len);
  995                 }
  996                 mp->msg_namelen = len;
  997         }
  998         if (mp->msg_control && controlp == NULL) {
  999 #ifdef COMPAT_OLDSOCK
 1000                 /*
 1001                  * We assume that old recvmsg calls won't receive access
 1002                  * rights and other control info, esp. as control info
 1003                  * is always optional and those options didn't exist in 4.3.
 1004                  * If we receive rights, trim the cmsghdr; anything else
 1005                  * is tossed.
 1006                  */
 1007                 if (control && mp->msg_flags & MSG_COMPAT) {
 1008                         if (mtod(control, struct cmsghdr *)->cmsg_level !=
 1009                             SOL_SOCKET ||
 1010                             mtod(control, struct cmsghdr *)->cmsg_type !=
 1011                             SCM_RIGHTS) {
 1012                                 mp->msg_controllen = 0;
 1013                                 goto out;
 1014                         }
 1015                         control->m_len -= sizeof (struct cmsghdr);
 1016                         control->m_data += sizeof (struct cmsghdr);
 1017                 }
 1018 #endif
 1019                 ctlbuf = mp->msg_control;
 1020                 len = mp->msg_controllen;
 1021                 mp->msg_controllen = 0;
 1022                 for (m = control; m != NULL && len >= m->m_len; m = m->m_next) {
 1023                         if ((error = copyout(mtod(m, caddr_t), ctlbuf,
 1024                             m->m_len)) != 0)
 1025                                 goto out;
 1026 
 1027                         ctlbuf += m->m_len;
 1028                         len -= m->m_len;
 1029                         mp->msg_controllen += m->m_len;
 1030                 }
 1031                 if (m != NULL) {
 1032                         mp->msg_flags |= MSG_CTRUNC;
 1033                         m_dispose_extcontrolm(m);
 1034                 }
 1035         }
 1036 out:
 1037         fdrop(fp, td);
 1038 #ifdef KTRACE
 1039         if (fromsa && KTRPOINT(td, KTR_STRUCT))
 1040                 ktrsockaddr(fromsa);
 1041 #endif
 1042         free(fromsa, M_SONAME);
 1043 
 1044         if (error == 0 && controlp != NULL)
 1045                 *controlp = control;
 1046         else if (control != NULL) {
 1047                 if (error != 0)
 1048                         m_dispose_extcontrolm(control);
 1049                 m_freem(control);
 1050         }
 1051 
 1052         return (error);
 1053 }
 1054 
 1055 static int
 1056 recvit(struct thread *td, int s, struct msghdr *mp, void *namelenp)
 1057 {
 1058         int error;
 1059 
 1060         error = kern_recvit(td, s, mp, UIO_USERSPACE, NULL);
 1061         if (error != 0)
 1062                 return (error);
 1063         if (namelenp != NULL) {
 1064                 error = copyout(&mp->msg_namelen, namelenp, sizeof (socklen_t));
 1065 #ifdef COMPAT_OLDSOCK
 1066                 if (mp->msg_flags & MSG_COMPAT)
 1067                         error = 0;      /* old recvfrom didn't check */
 1068 #endif
 1069         }
 1070         return (error);
 1071 }
 1072 
 1073 int
 1074 sys_recvfrom(struct thread *td, struct recvfrom_args *uap)
 1075 {
 1076         struct msghdr msg;
 1077         struct iovec aiov;
 1078         int error;
 1079 
 1080         if (uap->fromlenaddr) {
 1081                 error = copyin(uap->fromlenaddr,
 1082                     &msg.msg_namelen, sizeof (msg.msg_namelen));
 1083                 if (error != 0)
 1084                         goto done2;
 1085         } else {
 1086                 msg.msg_namelen = 0;
 1087         }
 1088         msg.msg_name = uap->from;
 1089         msg.msg_iov = &aiov;
 1090         msg.msg_iovlen = 1;
 1091         aiov.iov_base = uap->buf;
 1092         aiov.iov_len = uap->len;
 1093         msg.msg_control = 0;
 1094         msg.msg_flags = uap->flags;
 1095         error = recvit(td, uap->s, &msg, uap->fromlenaddr);
 1096 done2:
 1097         return (error);
 1098 }
 1099 
 1100 #ifdef COMPAT_OLDSOCK
 1101 int
 1102 orecvfrom(struct thread *td, struct recvfrom_args *uap)
 1103 {
 1104 
 1105         uap->flags |= MSG_COMPAT;
 1106         return (sys_recvfrom(td, uap));
 1107 }
 1108 #endif
 1109 
 1110 #ifdef COMPAT_OLDSOCK
 1111 int
 1112 orecv(struct thread *td, struct orecv_args *uap)
 1113 {
 1114         struct msghdr msg;
 1115         struct iovec aiov;
 1116 
 1117         msg.msg_name = 0;
 1118         msg.msg_namelen = 0;
 1119         msg.msg_iov = &aiov;
 1120         msg.msg_iovlen = 1;
 1121         aiov.iov_base = uap->buf;
 1122         aiov.iov_len = uap->len;
 1123         msg.msg_control = 0;
 1124         msg.msg_flags = uap->flags;
 1125         return (recvit(td, uap->s, &msg, NULL));
 1126 }
 1127 
 1128 /*
 1129  * Old recvmsg.  This code takes advantage of the fact that the old msghdr
 1130  * overlays the new one, missing only the flags, and with the (old) access
 1131  * rights where the control fields are now.
 1132  */
 1133 int
 1134 orecvmsg(struct thread *td, struct orecvmsg_args *uap)
 1135 {
 1136         struct msghdr msg;
 1137         struct iovec *iov;
 1138         int error;
 1139 
 1140         error = copyin(uap->msg, &msg, sizeof (struct omsghdr));
 1141         if (error != 0)
 1142                 return (error);
 1143         error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
 1144         if (error != 0)
 1145                 return (error);
 1146         msg.msg_flags = uap->flags | MSG_COMPAT;
 1147         msg.msg_iov = iov;
 1148         error = recvit(td, uap->s, &msg, &uap->msg->msg_namelen);
 1149         if (msg.msg_controllen && error == 0)
 1150                 error = copyout(&msg.msg_controllen,
 1151                     &uap->msg->msg_accrightslen, sizeof (int));
 1152         free(iov, M_IOV);
 1153         return (error);
 1154 }
 1155 #endif
 1156 
 1157 int
 1158 sys_recvmsg(struct thread *td, struct recvmsg_args *uap)
 1159 {
 1160         struct msghdr msg;
 1161         struct iovec *uiov, *iov;
 1162         int error;
 1163 
 1164         error = copyin(uap->msg, &msg, sizeof (msg));
 1165         if (error != 0)
 1166                 return (error);
 1167         error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
 1168         if (error != 0)
 1169                 return (error);
 1170         msg.msg_flags = uap->flags;
 1171 #ifdef COMPAT_OLDSOCK
 1172         msg.msg_flags &= ~MSG_COMPAT;
 1173 #endif
 1174         uiov = msg.msg_iov;
 1175         msg.msg_iov = iov;
 1176         error = recvit(td, uap->s, &msg, NULL);
 1177         if (error == 0) {
 1178                 msg.msg_iov = uiov;
 1179                 error = copyout(&msg, uap->msg, sizeof(msg));
 1180         }
 1181         free(iov, M_IOV);
 1182         return (error);
 1183 }
 1184 
 1185 int
 1186 sys_shutdown(struct thread *td, struct shutdown_args *uap)
 1187 {
 1188 
 1189         return (kern_shutdown(td, uap->s, uap->how));
 1190 }
 1191 
 1192 int
 1193 kern_shutdown(struct thread *td, int s, int how)
 1194 {
 1195         struct socket *so;
 1196         struct file *fp;
 1197         int error;
 1198 
 1199         AUDIT_ARG_FD(s);
 1200         error = getsock_cap(td, s, &cap_shutdown_rights,
 1201             &fp, NULL, NULL);
 1202         if (error == 0) {
 1203                 so = fp->f_data;
 1204                 error = soshutdown(so, how);
 1205                 /*
 1206                  * Previous versions did not return ENOTCONN, but 0 in
 1207                  * case the socket was not connected. Some important
 1208                  * programs like syslogd up to r279016, 2015-02-19,
 1209                  * still depend on this behavior.
 1210                  */
 1211                 if (error == ENOTCONN &&
 1212                     td->td_proc->p_osrel < P_OSREL_SHUTDOWN_ENOTCONN)
 1213                         error = 0;
 1214                 fdrop(fp, td);
 1215         }
 1216         return (error);
 1217 }
 1218 
 1219 int
 1220 sys_setsockopt(struct thread *td, struct setsockopt_args *uap)
 1221 {
 1222 
 1223         return (kern_setsockopt(td, uap->s, uap->level, uap->name,
 1224             uap->val, UIO_USERSPACE, uap->valsize));
 1225 }
 1226 
 1227 int
 1228 kern_setsockopt(struct thread *td, int s, int level, int name, void *val,
 1229     enum uio_seg valseg, socklen_t valsize)
 1230 {
 1231         struct socket *so;
 1232         struct file *fp;
 1233         struct sockopt sopt;
 1234         int error;
 1235 
 1236         if (val == NULL && valsize != 0)
 1237                 return (EFAULT);
 1238         if ((int)valsize < 0)
 1239                 return (EINVAL);
 1240 
 1241         sopt.sopt_dir = SOPT_SET;
 1242         sopt.sopt_level = level;
 1243         sopt.sopt_name = name;
 1244         sopt.sopt_val = val;
 1245         sopt.sopt_valsize = valsize;
 1246         switch (valseg) {
 1247         case UIO_USERSPACE:
 1248                 sopt.sopt_td = td;
 1249                 break;
 1250         case UIO_SYSSPACE:
 1251                 sopt.sopt_td = NULL;
 1252                 break;
 1253         default:
 1254                 panic("kern_setsockopt called with bad valseg");
 1255         }
 1256 
 1257         AUDIT_ARG_FD(s);
 1258         error = getsock_cap(td, s, &cap_setsockopt_rights,
 1259             &fp, NULL, NULL);
 1260         if (error == 0) {
 1261                 so = fp->f_data;
 1262                 error = sosetopt(so, &sopt);
 1263                 fdrop(fp, td);
 1264         }
 1265         return(error);
 1266 }
 1267 
 1268 int
 1269 sys_getsockopt(struct thread *td, struct getsockopt_args *uap)
 1270 {
 1271         socklen_t valsize;
 1272         int error;
 1273 
 1274         if (uap->val) {
 1275                 error = copyin(uap->avalsize, &valsize, sizeof (valsize));
 1276                 if (error != 0)
 1277                         return (error);
 1278         }
 1279 
 1280         error = kern_getsockopt(td, uap->s, uap->level, uap->name,
 1281             uap->val, UIO_USERSPACE, &valsize);
 1282 
 1283         if (error == 0)
 1284                 error = copyout(&valsize, uap->avalsize, sizeof (valsize));
 1285         return (error);
 1286 }
 1287 
 1288 /*
 1289  * Kernel version of getsockopt.
 1290  * optval can be a userland or userspace. optlen is always a kernel pointer.
 1291  */
 1292 int
 1293 kern_getsockopt(struct thread *td, int s, int level, int name, void *val,
 1294     enum uio_seg valseg, socklen_t *valsize)
 1295 {
 1296         struct socket *so;
 1297         struct file *fp;
 1298         struct sockopt sopt;
 1299         int error;
 1300 
 1301         if (val == NULL)
 1302                 *valsize = 0;
 1303         if ((int)*valsize < 0)
 1304                 return (EINVAL);
 1305 
 1306         sopt.sopt_dir = SOPT_GET;
 1307         sopt.sopt_level = level;
 1308         sopt.sopt_name = name;
 1309         sopt.sopt_val = val;
 1310         sopt.sopt_valsize = (size_t)*valsize; /* checked non-negative above */
 1311         switch (valseg) {
 1312         case UIO_USERSPACE:
 1313                 sopt.sopt_td = td;
 1314                 break;
 1315         case UIO_SYSSPACE:
 1316                 sopt.sopt_td = NULL;
 1317                 break;
 1318         default:
 1319                 panic("kern_getsockopt called with bad valseg");
 1320         }
 1321 
 1322         AUDIT_ARG_FD(s);
 1323         error = getsock_cap(td, s, &cap_getsockopt_rights,
 1324             &fp, NULL, NULL);
 1325         if (error == 0) {
 1326                 so = fp->f_data;
 1327                 error = sogetopt(so, &sopt);
 1328                 *valsize = sopt.sopt_valsize;
 1329                 fdrop(fp, td);
 1330         }
 1331         return (error);
 1332 }
 1333 
 1334 /*
 1335  * getsockname1() - Get socket name.
 1336  */
 1337 static int
 1338 getsockname1(struct thread *td, struct getsockname_args *uap, int compat)
 1339 {
 1340         struct sockaddr *sa;
 1341         socklen_t len;
 1342         int error;
 1343 
 1344         error = copyin(uap->alen, &len, sizeof(len));
 1345         if (error != 0)
 1346                 return (error);
 1347 
 1348         error = kern_getsockname(td, uap->fdes, &sa, &len);
 1349         if (error != 0)
 1350                 return (error);
 1351 
 1352         if (len != 0) {
 1353 #ifdef COMPAT_OLDSOCK
 1354                 if (compat)
 1355                         ((struct osockaddr *)sa)->sa_family = sa->sa_family;
 1356 #endif
 1357                 error = copyout(sa, uap->asa, (u_int)len);
 1358         }
 1359         free(sa, M_SONAME);
 1360         if (error == 0)
 1361                 error = copyout(&len, uap->alen, sizeof(len));
 1362         return (error);
 1363 }
 1364 
 1365 int
 1366 kern_getsockname(struct thread *td, int fd, struct sockaddr **sa,
 1367     socklen_t *alen)
 1368 {
 1369         struct socket *so;
 1370         struct file *fp;
 1371         socklen_t len;
 1372         int error;
 1373 
 1374         AUDIT_ARG_FD(fd);
 1375         error = getsock_cap(td, fd, &cap_getsockname_rights,
 1376             &fp, NULL, NULL);
 1377         if (error != 0)
 1378                 return (error);
 1379         so = fp->f_data;
 1380         *sa = NULL;
 1381         CURVNET_SET(so->so_vnet);
 1382         error = (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, sa);
 1383         CURVNET_RESTORE();
 1384         if (error != 0)
 1385                 goto bad;
 1386         if (*sa == NULL)
 1387                 len = 0;
 1388         else
 1389                 len = MIN(*alen, (*sa)->sa_len);
 1390         *alen = len;
 1391 #ifdef KTRACE
 1392         if (KTRPOINT(td, KTR_STRUCT))
 1393                 ktrsockaddr(*sa);
 1394 #endif
 1395 bad:
 1396         fdrop(fp, td);
 1397         if (error != 0 && *sa != NULL) {
 1398                 free(*sa, M_SONAME);
 1399                 *sa = NULL;
 1400         }
 1401         return (error);
 1402 }
 1403 
 1404 int
 1405 sys_getsockname(struct thread *td, struct getsockname_args *uap)
 1406 {
 1407 
 1408         return (getsockname1(td, uap, 0));
 1409 }
 1410 
 1411 #ifdef COMPAT_OLDSOCK
 1412 int
 1413 ogetsockname(struct thread *td, struct getsockname_args *uap)
 1414 {
 1415 
 1416         return (getsockname1(td, uap, 1));
 1417 }
 1418 #endif /* COMPAT_OLDSOCK */
 1419 
 1420 /*
 1421  * getpeername1() - Get name of peer for connected socket.
 1422  */
 1423 static int
 1424 getpeername1(struct thread *td, struct getpeername_args *uap, int compat)
 1425 {
 1426         struct sockaddr *sa;
 1427         socklen_t len;
 1428         int error;
 1429 
 1430         error = copyin(uap->alen, &len, sizeof (len));
 1431         if (error != 0)
 1432                 return (error);
 1433 
 1434         error = kern_getpeername(td, uap->fdes, &sa, &len);
 1435         if (error != 0)
 1436                 return (error);
 1437 
 1438         if (len != 0) {
 1439 #ifdef COMPAT_OLDSOCK
 1440                 if (compat)
 1441                         ((struct osockaddr *)sa)->sa_family = sa->sa_family;
 1442 #endif
 1443                 error = copyout(sa, uap->asa, (u_int)len);
 1444         }
 1445         free(sa, M_SONAME);
 1446         if (error == 0)
 1447                 error = copyout(&len, uap->alen, sizeof(len));
 1448         return (error);
 1449 }
 1450 
 1451 int
 1452 kern_getpeername(struct thread *td, int fd, struct sockaddr **sa,
 1453     socklen_t *alen)
 1454 {
 1455         struct socket *so;
 1456         struct file *fp;
 1457         socklen_t len;
 1458         int error;
 1459 
 1460         AUDIT_ARG_FD(fd);
 1461         error = getsock_cap(td, fd, &cap_getpeername_rights,
 1462             &fp, NULL, NULL);
 1463         if (error != 0)
 1464                 return (error);
 1465         so = fp->f_data;
 1466         if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) {
 1467                 error = ENOTCONN;
 1468                 goto done;
 1469         }
 1470         *sa = NULL;
 1471         CURVNET_SET(so->so_vnet);
 1472         error = (*so->so_proto->pr_usrreqs->pru_peeraddr)(so, sa);
 1473         CURVNET_RESTORE();
 1474         if (error != 0)
 1475                 goto bad;
 1476         if (*sa == NULL)
 1477                 len = 0;
 1478         else
 1479                 len = MIN(*alen, (*sa)->sa_len);
 1480         *alen = len;
 1481 #ifdef KTRACE
 1482         if (KTRPOINT(td, KTR_STRUCT))
 1483                 ktrsockaddr(*sa);
 1484 #endif
 1485 bad:
 1486         if (error != 0 && *sa != NULL) {
 1487                 free(*sa, M_SONAME);
 1488                 *sa = NULL;
 1489         }
 1490 done:
 1491         fdrop(fp, td);
 1492         return (error);
 1493 }
 1494 
 1495 int
 1496 sys_getpeername(struct thread *td, struct getpeername_args *uap)
 1497 {
 1498 
 1499         return (getpeername1(td, uap, 0));
 1500 }
 1501 
 1502 #ifdef COMPAT_OLDSOCK
 1503 int
 1504 ogetpeername(struct thread *td, struct ogetpeername_args *uap)
 1505 {
 1506 
 1507         /* XXX uap should have type `getpeername_args *' to begin with. */
 1508         return (getpeername1(td, (struct getpeername_args *)uap, 1));
 1509 }
 1510 #endif /* COMPAT_OLDSOCK */
 1511 
 1512 static int
 1513 sockargs(struct mbuf **mp, char *buf, socklen_t buflen, int type)
 1514 {
 1515         struct sockaddr *sa;
 1516         struct mbuf *m;
 1517         int error;
 1518 
 1519         if (buflen > MLEN) {
 1520 #ifdef COMPAT_OLDSOCK
 1521                 if (type == MT_SONAME && buflen <= 112)
 1522                         buflen = MLEN;          /* unix domain compat. hack */
 1523                 else
 1524 #endif
 1525                         if (buflen > MCLBYTES)
 1526                                 return (EINVAL);
 1527         }
 1528         m = m_get2(buflen, M_WAITOK, type, 0);
 1529         m->m_len = buflen;
 1530         error = copyin(buf, mtod(m, void *), buflen);
 1531         if (error != 0)
 1532                 (void) m_free(m);
 1533         else {
 1534                 *mp = m;
 1535                 if (type == MT_SONAME) {
 1536                         sa = mtod(m, struct sockaddr *);
 1537 
 1538 #if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
 1539                         if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
 1540                                 sa->sa_family = sa->sa_len;
 1541 #endif
 1542                         sa->sa_len = buflen;
 1543                 }
 1544         }
 1545         return (error);
 1546 }
 1547 
 1548 int
 1549 getsockaddr(struct sockaddr **namp, caddr_t uaddr, size_t len)
 1550 {
 1551         struct sockaddr *sa;
 1552         int error;
 1553 
 1554         if (len > SOCK_MAXADDRLEN)
 1555                 return (ENAMETOOLONG);
 1556         if (len < offsetof(struct sockaddr, sa_data[0]))
 1557                 return (EINVAL);
 1558         sa = malloc(len, M_SONAME, M_WAITOK);
 1559         error = copyin(uaddr, sa, len);
 1560         if (error != 0) {
 1561                 free(sa, M_SONAME);
 1562         } else {
 1563 #if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
 1564                 if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
 1565                         sa->sa_family = sa->sa_len;
 1566 #endif
 1567                 sa->sa_len = len;
 1568                 *namp = sa;
 1569         }
 1570         return (error);
 1571 }
 1572 
 1573 /*
 1574  * Dispose of externalized rights from an SCM_RIGHTS message.  This function
 1575  * should be used in error or truncation cases to avoid leaking file descriptors
 1576  * into the recipient's (the current thread's) table.
 1577  */
 1578 void
 1579 m_dispose_extcontrolm(struct mbuf *m)
 1580 {
 1581         struct cmsghdr *cm;
 1582         struct file *fp;
 1583         struct thread *td;
 1584         socklen_t clen, datalen;
 1585         int error, fd, *fds, nfd;
 1586 
 1587         td = curthread;
 1588         for (; m != NULL; m = m->m_next) {
 1589                 if (m->m_type != MT_EXTCONTROL)
 1590                         continue;
 1591                 cm = mtod(m, struct cmsghdr *);
 1592                 clen = m->m_len;
 1593                 while (clen > 0) {
 1594                         if (clen < sizeof(*cm))
 1595                                 panic("%s: truncated mbuf %p", __func__, m);
 1596                         datalen = CMSG_SPACE(cm->cmsg_len - CMSG_SPACE(0));
 1597                         if (clen < datalen)
 1598                                 panic("%s: truncated mbuf %p", __func__, m);
 1599 
 1600                         if (cm->cmsg_level == SOL_SOCKET &&
 1601                             cm->cmsg_type == SCM_RIGHTS) {
 1602                                 fds = (int *)CMSG_DATA(cm);
 1603                                 nfd = (cm->cmsg_len - CMSG_SPACE(0)) /
 1604                                     sizeof(int);
 1605 
 1606                                 while (nfd-- > 0) {
 1607                                         fd = *fds++;
 1608                                         error = fget(td, fd, &cap_no_rights,
 1609                                             &fp);
 1610                                         if (error == 0) {
 1611                                                 fdclose(td, fp, fd);
 1612                                                 fdrop(fp, td);
 1613                                         }
 1614                                 }
 1615                         }
 1616                         clen -= datalen;
 1617                         cm = (struct cmsghdr *)((uint8_t *)cm + datalen);
 1618                 }
 1619                 m_chtype(m, MT_CONTROL);
 1620         }
 1621 }

Cache object: 0f3d34970ba29186006d70e3812d9efb


[ 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.