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$");
   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/sysent.h>
   61 #include <sys/uio.h>
   62 #include <sys/un.h>
   63 #include <sys/unpcb.h>
   64 #ifdef KTRACE
   65 #include <sys/ktrace.h>
   66 #endif
   67 #ifdef COMPAT_FREEBSD32
   68 #include <compat/freebsd32/freebsd32_util.h>
   69 #endif
   70 
   71 #include <net/vnet.h>
   72 
   73 #include <security/audit/audit.h>
   74 #include <security/mac/mac_framework.h>
   75 
   76 static int sendit(struct thread *td, int s, struct msghdr *mp, int flags);
   77 static int recvit(struct thread *td, int s, struct msghdr *mp, void *namelenp);
   78 
   79 static int accept1(struct thread *td, int s, struct sockaddr *uname,
   80                    socklen_t *anamelen, int flags);
   81 static int getsockname1(struct thread *td, struct getsockname_args *uap,
   82                         int compat);
   83 static int getpeername1(struct thread *td, struct getpeername_args *uap,
   84                         int compat);
   85 static int sockargs(struct mbuf **, char *, socklen_t, int);
   86 
   87 /*
   88  * Convert a user file descriptor to a kernel file entry and check if required
   89  * capability rights are present.
   90  * If required copy of current set of capability rights is returned.
   91  * A reference on the file entry is held upon returning.
   92  */
   93 int
   94 getsock_cap(struct thread *td, int fd, cap_rights_t *rightsp,
   95     struct file **fpp, u_int *fflagp, struct filecaps *havecapsp)
   96 {
   97         struct file *fp;
   98         int error;
   99 
  100         error = fget_cap(td, fd, rightsp, &fp, havecapsp);
  101         if (error != 0)
  102                 return (error);
  103         if (fp->f_type != DTYPE_SOCKET) {
  104                 fdrop(fp, td);
  105                 if (havecapsp != NULL)
  106                         filecaps_free(havecapsp);
  107                 return (ENOTSOCK);
  108         }
  109         if (fflagp != NULL)
  110                 *fflagp = fp->f_flag;
  111         *fpp = fp;
  112         return (0);
  113 }
  114 
  115 /*
  116  * System call interface to the socket abstraction.
  117  */
  118 #if defined(COMPAT_43)
  119 #define COMPAT_OLDSOCK
  120 #endif
  121 
  122 int
  123 sys_socket(struct thread *td, struct socket_args *uap)
  124 {
  125 
  126         return (kern_socket(td, uap->domain, uap->type, uap->protocol));
  127 }
  128 
  129 int
  130 kern_socket(struct thread *td, int domain, int type, int protocol)
  131 {
  132         struct socket *so;
  133         struct file *fp;
  134         int fd, error, oflag, fflag;
  135 
  136         AUDIT_ARG_SOCKET(domain, type, protocol);
  137 
  138         oflag = 0;
  139         fflag = 0;
  140         if ((type & SOCK_CLOEXEC) != 0) {
  141                 type &= ~SOCK_CLOEXEC;
  142                 oflag |= O_CLOEXEC;
  143         }
  144         if ((type & SOCK_NONBLOCK) != 0) {
  145                 type &= ~SOCK_NONBLOCK;
  146                 fflag |= FNONBLOCK;
  147         }
  148 
  149 #ifdef MAC
  150         error = mac_socket_check_create(td->td_ucred, domain, type, protocol);
  151         if (error != 0)
  152                 return (error);
  153 #endif
  154         error = falloc(td, &fp, &fd, oflag);
  155         if (error != 0)
  156                 return (error);
  157         /* An extra reference on `fp' has been held for us by falloc(). */
  158         error = socreate(domain, &so, type, protocol, td->td_ucred, td);
  159         if (error != 0) {
  160                 fdclose(td, fp, fd);
  161         } else {
  162                 finit(fp, FREAD | FWRITE | fflag, DTYPE_SOCKET, so, &socketops);
  163                 if ((fflag & FNONBLOCK) != 0)
  164                         (void) fo_ioctl(fp, FIONBIO, &fflag, td->td_ucred, td);
  165                 td->td_retval[0] = fd;
  166         }
  167         fdrop(fp, td);
  168         return (error);
  169 }
  170 
  171 int
  172 sys_bind(struct thread *td, struct bind_args *uap)
  173 {
  174         struct sockaddr *sa;
  175         int error;
  176 
  177         error = getsockaddr(&sa, uap->name, uap->namelen);
  178         if (error == 0) {
  179                 error = kern_bindat(td, AT_FDCWD, uap->s, sa);
  180                 free(sa, M_SONAME);
  181         }
  182         return (error);
  183 }
  184 
  185 int
  186 kern_bindat(struct thread *td, int dirfd, int fd, struct sockaddr *sa)
  187 {
  188         struct socket *so;
  189         struct file *fp;
  190         int error;
  191 
  192 #ifdef CAPABILITY_MODE
  193         if (IN_CAPABILITY_MODE(td) && (dirfd == AT_FDCWD))
  194                 return (ECAPMODE);
  195 #endif
  196 
  197         AUDIT_ARG_FD(fd);
  198         AUDIT_ARG_SOCKADDR(td, dirfd, sa);
  199         error = getsock_cap(td, fd, &cap_bind_rights,
  200             &fp, NULL, NULL);
  201         if (error != 0)
  202                 return (error);
  203         so = fp->f_data;
  204 #ifdef KTRACE
  205         if (KTRPOINT(td, KTR_STRUCT))
  206                 ktrsockaddr(sa);
  207 #endif
  208 #ifdef MAC
  209         error = mac_socket_check_bind(td->td_ucred, so, sa);
  210         if (error == 0) {
  211 #endif
  212                 if (dirfd == AT_FDCWD)
  213                         error = sobind(so, sa, td);
  214                 else
  215                         error = sobindat(dirfd, so, sa, td);
  216 #ifdef MAC
  217         }
  218 #endif
  219         fdrop(fp, td);
  220         return (error);
  221 }
  222 
  223 int
  224 sys_bindat(struct thread *td, struct bindat_args *uap)
  225 {
  226         struct sockaddr *sa;
  227         int error;
  228 
  229         error = getsockaddr(&sa, uap->name, uap->namelen);
  230         if (error == 0) {
  231                 error = kern_bindat(td, uap->fd, uap->s, sa);
  232                 free(sa, M_SONAME);
  233         }
  234         return (error);
  235 }
  236 
  237 int
  238 sys_listen(struct thread *td, struct listen_args *uap)
  239 {
  240 
  241         return (kern_listen(td, uap->s, uap->backlog));
  242 }
  243 
  244 int
  245 kern_listen(struct thread *td, int s, int backlog)
  246 {
  247         struct socket *so;
  248         struct file *fp;
  249         int error;
  250 
  251         AUDIT_ARG_FD(s);
  252         error = getsock_cap(td, s, &cap_listen_rights,
  253             &fp, NULL, 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                         error = solisten(so, backlog, td);
  261                 fdrop(fp, td);
  262         }
  263         return (error);
  264 }
  265 
  266 /*
  267  * accept1()
  268  */
  269 static int
  270 accept1(td, s, uname, anamelen, flags)
  271         struct thread *td;
  272         int s;
  273         struct sockaddr *uname;
  274         socklen_t *anamelen;
  275         int flags;
  276 {
  277         struct sockaddr *name;
  278         socklen_t namelen;
  279         struct file *fp;
  280         int error;
  281 
  282         if (uname == NULL)
  283                 return (kern_accept4(td, s, NULL, NULL, flags, NULL));
  284 
  285         error = copyin(anamelen, &namelen, sizeof (namelen));
  286         if (error != 0)
  287                 return (error);
  288 
  289         error = kern_accept4(td, s, &name, &namelen, flags, &fp);
  290 
  291         if (error != 0)
  292                 return (error);
  293 
  294         if (error == 0 && uname != NULL) {
  295 #ifdef COMPAT_OLDSOCK
  296                 if (SV_PROC_FLAG(td->td_proc, SV_AOUT) &&
  297                     (flags & ACCEPT4_COMPAT) != 0)
  298                         ((struct osockaddr *)name)->sa_family =
  299                             name->sa_family;
  300 #endif
  301                 error = copyout(name, uname, namelen);
  302         }
  303         if (error == 0)
  304                 error = copyout(&namelen, anamelen,
  305                     sizeof(namelen));
  306         if (error != 0)
  307                 fdclose(td, fp, td->td_retval[0]);
  308         fdrop(fp, td);
  309         free(name, M_SONAME);
  310         return (error);
  311 }
  312 
  313 int
  314 kern_accept(struct thread *td, int s, struct sockaddr **name,
  315     socklen_t *namelen, struct file **fp)
  316 {
  317         return (kern_accept4(td, s, name, namelen, ACCEPT4_INHERIT, fp));
  318 }
  319 
  320 int
  321 kern_accept4(struct thread *td, int s, struct sockaddr **name,
  322     socklen_t *namelen, int flags, struct file **fp)
  323 {
  324         struct file *headfp, *nfp = NULL;
  325         struct sockaddr *sa = NULL;
  326         struct socket *head, *so;
  327         struct filecaps fcaps;
  328         u_int fflag;
  329         pid_t pgid;
  330         int error, fd, tmp;
  331 
  332         if (name != NULL)
  333                 *name = NULL;
  334 
  335         AUDIT_ARG_FD(s);
  336         error = getsock_cap(td, s, &cap_accept_rights,
  337             &headfp, &fflag, &fcaps);
  338         if (error != 0)
  339                 return (error);
  340         head = headfp->f_data;
  341         if (!SOLISTENING(head)) {
  342                 error = EINVAL;
  343                 goto done;
  344         }
  345 #ifdef MAC
  346         error = mac_socket_check_accept(td->td_ucred, head);
  347         if (error != 0)
  348                 goto done;
  349 #endif
  350         error = falloc_caps(td, &nfp, &fd,
  351             (flags & SOCK_CLOEXEC) ? O_CLOEXEC : 0, &fcaps);
  352         if (error != 0)
  353                 goto done;
  354         SOCK_LOCK(head);
  355         if (!SOLISTENING(head)) {
  356                 SOCK_UNLOCK(head);
  357                 error = EINVAL;
  358                 goto noconnection;
  359         }
  360 
  361         error = solisten_dequeue(head, &so, flags);
  362         if (error != 0)
  363                 goto noconnection;
  364 
  365         /* An extra reference on `nfp' has been held for us by falloc(). */
  366         td->td_retval[0] = fd;
  367 
  368         /* Connection has been removed from the listen queue. */
  369         KNOTE_UNLOCKED(&head->so_rdsel.si_note, 0);
  370 
  371         if (flags & ACCEPT4_INHERIT) {
  372                 pgid = fgetown(&head->so_sigio);
  373                 if (pgid != 0)
  374                         fsetown(pgid, &so->so_sigio);
  375         } else {
  376                 fflag &= ~(FNONBLOCK | FASYNC);
  377                 if (flags & SOCK_NONBLOCK)
  378                         fflag |= FNONBLOCK;
  379         }
  380 
  381         finit(nfp, fflag, DTYPE_SOCKET, so, &socketops);
  382         /* Sync socket nonblocking/async state with file flags */
  383         tmp = fflag & FNONBLOCK;
  384         (void) fo_ioctl(nfp, FIONBIO, &tmp, td->td_ucred, td);
  385         tmp = fflag & FASYNC;
  386         (void) fo_ioctl(nfp, FIOASYNC, &tmp, td->td_ucred, td);
  387         error = soaccept(so, &sa);
  388         if (error != 0)
  389                 goto noconnection;
  390         if (sa == NULL) {
  391                 if (name)
  392                         *namelen = 0;
  393                 goto done;
  394         }
  395         AUDIT_ARG_SOCKADDR(td, AT_FDCWD, sa);
  396         if (name) {
  397                 /* check sa_len before it is destroyed */
  398                 if (*namelen > sa->sa_len)
  399                         *namelen = sa->sa_len;
  400 #ifdef KTRACE
  401                 if (KTRPOINT(td, KTR_STRUCT))
  402                         ktrsockaddr(sa);
  403 #endif
  404                 *name = sa;
  405                 sa = NULL;
  406         }
  407 noconnection:
  408         free(sa, M_SONAME);
  409 
  410         /*
  411          * close the new descriptor, assuming someone hasn't ripped it
  412          * out from under us.
  413          */
  414         if (error != 0)
  415                 fdclose(td, nfp, fd);
  416 
  417         /*
  418          * Release explicitly held references before returning.  We return
  419          * a reference on nfp to the caller on success if they request it.
  420          */
  421 done:
  422         if (nfp == NULL)
  423                 filecaps_free(&fcaps);
  424         if (fp != NULL) {
  425                 if (error == 0) {
  426                         *fp = nfp;
  427                         nfp = NULL;
  428                 } else
  429                         *fp = NULL;
  430         }
  431         if (nfp != NULL)
  432                 fdrop(nfp, td);
  433         fdrop(headfp, td);
  434         return (error);
  435 }
  436 
  437 int
  438 sys_accept(td, uap)
  439         struct thread *td;
  440         struct accept_args *uap;
  441 {
  442 
  443         return (accept1(td, uap->s, uap->name, uap->anamelen, ACCEPT4_INHERIT));
  444 }
  445 
  446 int
  447 sys_accept4(td, uap)
  448         struct thread *td;
  449         struct accept4_args *uap;
  450 {
  451 
  452         if (uap->flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
  453                 return (EINVAL);
  454 
  455         return (accept1(td, uap->s, uap->name, uap->anamelen, uap->flags));
  456 }
  457 
  458 #ifdef COMPAT_OLDSOCK
  459 int
  460 oaccept(struct thread *td, struct oaccept_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;
  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         error = soconnectat(dirfd, so, sa, td);
  515         if (error != 0)
  516                 goto bad;
  517         if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
  518                 error = EINPROGRESS;
  519                 goto done1;
  520         }
  521         SOCK_LOCK(so);
  522         while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
  523                 error = msleep(&so->so_timeo, &so->so_lock, PSOCK | PCATCH,
  524                     "connec", 0);
  525                 if (error != 0)
  526                         break;
  527         }
  528         if (error == 0) {
  529                 error = so->so_error;
  530                 so->so_error = 0;
  531         }
  532         SOCK_UNLOCK(so);
  533 bad:
  534         if (error == ERESTART)
  535                 error = EINTR;
  536 done1:
  537         fdrop(fp, td);
  538         return (error);
  539 }
  540 
  541 int
  542 sys_connectat(struct thread *td, struct connectat_args *uap)
  543 {
  544         struct sockaddr *sa;
  545         int error;
  546 
  547         error = getsockaddr(&sa, uap->name, uap->namelen);
  548         if (error == 0) {
  549                 error = kern_connectat(td, uap->fd, uap->s, sa);
  550                 free(sa, M_SONAME);
  551         }
  552         return (error);
  553 }
  554 
  555 int
  556 kern_socketpair(struct thread *td, int domain, int type, int protocol,
  557     int *rsv)
  558 {
  559         struct file *fp1, *fp2;
  560         struct socket *so1, *so2;
  561         int fd, error, oflag, fflag;
  562 
  563         AUDIT_ARG_SOCKET(domain, type, protocol);
  564 
  565         oflag = 0;
  566         fflag = 0;
  567         if ((type & SOCK_CLOEXEC) != 0) {
  568                 type &= ~SOCK_CLOEXEC;
  569                 oflag |= O_CLOEXEC;
  570         }
  571         if ((type & SOCK_NONBLOCK) != 0) {
  572                 type &= ~SOCK_NONBLOCK;
  573                 fflag |= FNONBLOCK;
  574         }
  575 #ifdef MAC
  576         /* We might want to have a separate check for socket pairs. */
  577         error = mac_socket_check_create(td->td_ucred, domain, type,
  578             protocol);
  579         if (error != 0)
  580                 return (error);
  581 #endif
  582         error = socreate(domain, &so1, type, protocol, td->td_ucred, td);
  583         if (error != 0)
  584                 return (error);
  585         error = socreate(domain, &so2, type, protocol, td->td_ucred, td);
  586         if (error != 0)
  587                 goto free1;
  588         /* On success extra reference to `fp1' and 'fp2' is set by falloc. */
  589         error = falloc(td, &fp1, &fd, oflag);
  590         if (error != 0)
  591                 goto free2;
  592         rsv[0] = fd;
  593         fp1->f_data = so1;      /* so1 already has ref count */
  594         error = falloc(td, &fp2, &fd, oflag);
  595         if (error != 0)
  596                 goto free3;
  597         fp2->f_data = so2;      /* so2 already has ref count */
  598         rsv[1] = fd;
  599         error = soconnect2(so1, so2);
  600         if (error != 0)
  601                 goto free4;
  602         if (type == SOCK_DGRAM) {
  603                 /*
  604                  * Datagram socket connection is asymmetric.
  605                  */
  606                  error = soconnect2(so2, so1);
  607                  if (error != 0)
  608                         goto free4;
  609         } else if (so1->so_proto->pr_flags & PR_CONNREQUIRED) {
  610                 struct unpcb *unp, *unp2;
  611                 unp = sotounpcb(so1);
  612                 unp2 = sotounpcb(so2);
  613                 /* 
  614                  * No need to lock the unps, because the sockets are brand-new.
  615                  * No other threads can be using them yet
  616                  */
  617                 unp_copy_peercred(td, unp, unp2, unp);
  618         }
  619         finit(fp1, FREAD | FWRITE | fflag, DTYPE_SOCKET, fp1->f_data,
  620             &socketops);
  621         finit(fp2, FREAD | FWRITE | fflag, DTYPE_SOCKET, fp2->f_data,
  622             &socketops);
  623         if ((fflag & FNONBLOCK) != 0) {
  624                 (void) fo_ioctl(fp1, FIONBIO, &fflag, td->td_ucred, td);
  625                 (void) fo_ioctl(fp2, FIONBIO, &fflag, td->td_ucred, td);
  626         }
  627         fdrop(fp1, td);
  628         fdrop(fp2, td);
  629         return (0);
  630 free4:
  631         fdclose(td, fp2, rsv[1]);
  632         fdrop(fp2, td);
  633 free3:
  634         fdclose(td, fp1, rsv[0]);
  635         fdrop(fp1, td);
  636 free2:
  637         if (so2 != NULL)
  638                 (void)soclose(so2);
  639 free1:
  640         if (so1 != NULL)
  641                 (void)soclose(so1);
  642         return (error);
  643 }
  644 
  645 int
  646 sys_socketpair(struct thread *td, struct socketpair_args *uap)
  647 {
  648         int error, sv[2];
  649 
  650         error = kern_socketpair(td, uap->domain, uap->type,
  651             uap->protocol, sv);
  652         if (error != 0)
  653                 return (error);
  654         error = copyout(sv, uap->rsv, 2 * sizeof(int));
  655         if (error != 0) {
  656                 (void)kern_close(td, sv[0]);
  657                 (void)kern_close(td, sv[1]);
  658         }
  659         return (error);
  660 }
  661 
  662 static int
  663 sendit(struct thread *td, int s, struct msghdr *mp, int flags)
  664 {
  665         struct mbuf *control;
  666         struct sockaddr *to;
  667         int error;
  668 
  669 #ifdef CAPABILITY_MODE
  670         if (IN_CAPABILITY_MODE(td) && (mp->msg_name != NULL))
  671                 return (ECAPMODE);
  672 #endif
  673 
  674         if (mp->msg_name != NULL) {
  675                 error = getsockaddr(&to, mp->msg_name, mp->msg_namelen);
  676                 if (error != 0) {
  677                         to = NULL;
  678                         goto bad;
  679                 }
  680                 mp->msg_name = to;
  681         } else {
  682                 to = NULL;
  683         }
  684 
  685         if (mp->msg_control) {
  686                 if (mp->msg_controllen < sizeof(struct cmsghdr)
  687 #ifdef COMPAT_OLDSOCK
  688                     && (mp->msg_flags != MSG_COMPAT ||
  689                     !SV_PROC_FLAG(td->td_proc, SV_AOUT))
  690 #endif
  691                 ) {
  692                         error = EINVAL;
  693                         goto bad;
  694                 }
  695                 error = sockargs(&control, mp->msg_control,
  696                     mp->msg_controllen, MT_CONTROL);
  697                 if (error != 0)
  698                         goto bad;
  699 #ifdef COMPAT_OLDSOCK
  700                 if (mp->msg_flags == MSG_COMPAT &&
  701                     SV_PROC_FLAG(td->td_proc, SV_AOUT)) {
  702                         struct cmsghdr *cm;
  703 
  704                         M_PREPEND(control, sizeof(*cm), M_WAITOK);
  705                         cm = mtod(control, struct cmsghdr *);
  706                         cm->cmsg_len = control->m_len;
  707                         cm->cmsg_level = SOL_SOCKET;
  708                         cm->cmsg_type = SCM_RIGHTS;
  709                 }
  710 #endif
  711         } else {
  712                 control = NULL;
  713         }
  714 
  715         error = kern_sendit(td, s, mp, flags, control, UIO_USERSPACE);
  716 
  717 bad:
  718         free(to, M_SONAME);
  719         return (error);
  720 }
  721 
  722 int
  723 kern_sendit(struct thread *td, int s, struct msghdr *mp, int flags,
  724     struct mbuf *control, enum uio_seg segflg)
  725 {
  726         struct file *fp;
  727         struct uio auio;
  728         struct iovec *iov;
  729         struct socket *so;
  730         cap_rights_t *rights;
  731 #ifdef KTRACE
  732         struct uio *ktruio = NULL;
  733 #endif
  734         ssize_t len;
  735         int i, error;
  736 
  737         AUDIT_ARG_FD(s);
  738         rights = &cap_send_rights;
  739         if (mp->msg_name != NULL) {
  740                 AUDIT_ARG_SOCKADDR(td, AT_FDCWD, mp->msg_name);
  741                 rights = &cap_send_connect_rights;
  742         }
  743         error = getsock_cap(td, s, rights, &fp, NULL, NULL);
  744         if (error != 0) {
  745                 m_freem(control);
  746                 return (error);
  747         }
  748         so = (struct socket *)fp->f_data;
  749 
  750 #ifdef KTRACE
  751         if (mp->msg_name != NULL && KTRPOINT(td, KTR_STRUCT))
  752                 ktrsockaddr(mp->msg_name);
  753 #endif
  754 #ifdef MAC
  755         if (mp->msg_name != NULL) {
  756                 error = mac_socket_check_connect(td->td_ucred, so,
  757                     mp->msg_name);
  758                 if (error != 0) {
  759                         m_freem(control);
  760                         goto bad;
  761                 }
  762         }
  763         error = mac_socket_check_send(td->td_ucred, so);
  764         if (error != 0) {
  765                 m_freem(control);
  766                 goto bad;
  767         }
  768 #endif
  769 
  770         auio.uio_iov = mp->msg_iov;
  771         auio.uio_iovcnt = mp->msg_iovlen;
  772         auio.uio_segflg = segflg;
  773         auio.uio_rw = UIO_WRITE;
  774         auio.uio_td = td;
  775         auio.uio_offset = 0;                    /* XXX */
  776         auio.uio_resid = 0;
  777         iov = mp->msg_iov;
  778         for (i = 0; i < mp->msg_iovlen; i++, iov++) {
  779                 if ((auio.uio_resid += iov->iov_len) < 0) {
  780                         error = EINVAL;
  781                         m_freem(control);
  782                         goto bad;
  783                 }
  784         }
  785 #ifdef KTRACE
  786         if (KTRPOINT(td, KTR_GENIO))
  787                 ktruio = cloneuio(&auio);
  788 #endif
  789         len = auio.uio_resid;
  790         error = sosend(so, mp->msg_name, &auio, 0, control, flags, td);
  791         if (error != 0) {
  792                 if (auio.uio_resid != len && (error == ERESTART ||
  793                     error == EINTR || error == EWOULDBLOCK))
  794                         error = 0;
  795                 /* Generation of SIGPIPE can be controlled per socket */
  796                 if (error == EPIPE && !(so->so_options & SO_NOSIGPIPE) &&
  797                     !(flags & MSG_NOSIGNAL)) {
  798                         PROC_LOCK(td->td_proc);
  799                         tdsignal(td, SIGPIPE);
  800                         PROC_UNLOCK(td->td_proc);
  801                 }
  802         }
  803         if (error == 0)
  804                 td->td_retval[0] = len - auio.uio_resid;
  805 #ifdef KTRACE
  806         if (ktruio != NULL) {
  807                 ktruio->uio_resid = td->td_retval[0];
  808                 ktrgenio(s, UIO_WRITE, ktruio, error);
  809         }
  810 #endif
  811 bad:
  812         fdrop(fp, td);
  813         return (error);
  814 }
  815 
  816 int
  817 sys_sendto(struct thread *td, struct sendto_args *uap)
  818 {
  819         struct msghdr msg;
  820         struct iovec aiov;
  821 
  822         msg.msg_name = __DECONST(void *, uap->to);
  823         msg.msg_namelen = uap->tolen;
  824         msg.msg_iov = &aiov;
  825         msg.msg_iovlen = 1;
  826         msg.msg_control = 0;
  827 #ifdef COMPAT_OLDSOCK
  828         if (SV_PROC_FLAG(td->td_proc, SV_AOUT))
  829                 msg.msg_flags = 0;
  830 #endif
  831         aiov.iov_base = __DECONST(void *, uap->buf);
  832         aiov.iov_len = uap->len;
  833         return (sendit(td, uap->s, &msg, uap->flags));
  834 }
  835 
  836 #ifdef COMPAT_OLDSOCK
  837 int
  838 osend(struct thread *td, struct osend_args *uap)
  839 {
  840         struct msghdr msg;
  841         struct iovec aiov;
  842 
  843         msg.msg_name = 0;
  844         msg.msg_namelen = 0;
  845         msg.msg_iov = &aiov;
  846         msg.msg_iovlen = 1;
  847         aiov.iov_base = __DECONST(void *, uap->buf);
  848         aiov.iov_len = uap->len;
  849         msg.msg_control = 0;
  850         msg.msg_flags = 0;
  851         return (sendit(td, uap->s, &msg, uap->flags));
  852 }
  853 
  854 int
  855 osendmsg(struct thread *td, struct osendmsg_args *uap)
  856 {
  857         struct msghdr msg;
  858         struct iovec *iov;
  859         int error;
  860 
  861         error = copyin(uap->msg, &msg, sizeof (struct omsghdr));
  862         if (error != 0)
  863                 return (error);
  864         error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
  865         if (error != 0)
  866                 return (error);
  867         msg.msg_iov = iov;
  868         msg.msg_flags = MSG_COMPAT;
  869         error = sendit(td, uap->s, &msg, uap->flags);
  870         free(iov, M_IOV);
  871         return (error);
  872 }
  873 #endif
  874 
  875 int
  876 sys_sendmsg(struct thread *td, struct sendmsg_args *uap)
  877 {
  878         struct msghdr msg;
  879         struct iovec *iov;
  880         int error;
  881 
  882         error = copyin(uap->msg, &msg, sizeof (msg));
  883         if (error != 0)
  884                 return (error);
  885         error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
  886         if (error != 0)
  887                 return (error);
  888         msg.msg_iov = iov;
  889 #ifdef COMPAT_OLDSOCK
  890         if (SV_PROC_FLAG(td->td_proc, SV_AOUT))
  891                 msg.msg_flags = 0;
  892 #endif
  893         error = sendit(td, uap->s, &msg, uap->flags);
  894         free(iov, M_IOV);
  895         return (error);
  896 }
  897 
  898 int
  899 kern_recvit(struct thread *td, int s, struct msghdr *mp, enum uio_seg fromseg,
  900     struct mbuf **controlp)
  901 {
  902         struct uio auio;
  903         struct iovec *iov;
  904         struct mbuf *control, *m;
  905         caddr_t ctlbuf;
  906         struct file *fp;
  907         struct socket *so;
  908         struct sockaddr *fromsa = NULL;
  909 #ifdef KTRACE
  910         struct uio *ktruio = NULL;
  911 #endif
  912         ssize_t len;
  913         int error, i;
  914 
  915         if (controlp != NULL)
  916                 *controlp = NULL;
  917 
  918         AUDIT_ARG_FD(s);
  919         error = getsock_cap(td, s, &cap_recv_rights,
  920             &fp, NULL, NULL);
  921         if (error != 0)
  922                 return (error);
  923         so = fp->f_data;
  924 
  925 #ifdef MAC
  926         error = mac_socket_check_receive(td->td_ucred, so);
  927         if (error != 0) {
  928                 fdrop(fp, td);
  929                 return (error);
  930         }
  931 #endif
  932 
  933         auio.uio_iov = mp->msg_iov;
  934         auio.uio_iovcnt = mp->msg_iovlen;
  935         auio.uio_segflg = UIO_USERSPACE;
  936         auio.uio_rw = UIO_READ;
  937         auio.uio_td = td;
  938         auio.uio_offset = 0;                    /* XXX */
  939         auio.uio_resid = 0;
  940         iov = mp->msg_iov;
  941         for (i = 0; i < mp->msg_iovlen; i++, iov++) {
  942                 if ((auio.uio_resid += iov->iov_len) < 0) {
  943                         fdrop(fp, td);
  944                         return (EINVAL);
  945                 }
  946         }
  947 #ifdef KTRACE
  948         if (KTRPOINT(td, KTR_GENIO))
  949                 ktruio = cloneuio(&auio);
  950 #endif
  951         control = NULL;
  952         len = auio.uio_resid;
  953         error = soreceive(so, &fromsa, &auio, NULL,
  954             (mp->msg_control || controlp) ? &control : NULL,
  955             &mp->msg_flags);
  956         if (error != 0) {
  957                 if (auio.uio_resid != len && (error == ERESTART ||
  958                     error == EINTR || error == EWOULDBLOCK))
  959                         error = 0;
  960         }
  961         if (fromsa != NULL)
  962                 AUDIT_ARG_SOCKADDR(td, AT_FDCWD, fromsa);
  963 #ifdef KTRACE
  964         if (ktruio != NULL) {
  965                 ktruio->uio_resid = len - auio.uio_resid;
  966                 ktrgenio(s, UIO_READ, ktruio, error);
  967         }
  968 #endif
  969         if (error != 0)
  970                 goto out;
  971         td->td_retval[0] = len - auio.uio_resid;
  972         if (mp->msg_name) {
  973                 len = mp->msg_namelen;
  974                 if (len <= 0 || fromsa == NULL)
  975                         len = 0;
  976                 else {
  977                         /* save sa_len before it is destroyed by MSG_COMPAT */
  978                         len = MIN(len, fromsa->sa_len);
  979 #ifdef COMPAT_OLDSOCK
  980                         if ((mp->msg_flags & MSG_COMPAT) != 0 &&
  981                             SV_PROC_FLAG(td->td_proc, SV_AOUT))
  982                                 ((struct osockaddr *)fromsa)->sa_family =
  983                                     fromsa->sa_family;
  984 #endif
  985                         if (fromseg == UIO_USERSPACE) {
  986                                 error = copyout(fromsa, mp->msg_name,
  987                                     (unsigned)len);
  988                                 if (error != 0)
  989                                         goto out;
  990                         } else
  991                                 bcopy(fromsa, mp->msg_name, len);
  992                 }
  993                 mp->msg_namelen = len;
  994         }
  995         if (mp->msg_control && controlp == NULL) {
  996 #ifdef COMPAT_OLDSOCK
  997                 /*
  998                  * We assume that old recvmsg calls won't receive access
  999                  * rights and other control info, esp. as control info
 1000                  * is always optional and those options didn't exist in 4.3.
 1001                  * If we receive rights, trim the cmsghdr; anything else
 1002                  * is tossed.
 1003                  */
 1004                 if (control && (mp->msg_flags & MSG_COMPAT) != 0 &&
 1005                     SV_PROC_FLAG(td->td_proc, SV_AOUT)) {
 1006                         if (mtod(control, struct cmsghdr *)->cmsg_level !=
 1007                             SOL_SOCKET ||
 1008                             mtod(control, struct cmsghdr *)->cmsg_type !=
 1009                             SCM_RIGHTS) {
 1010                                 mp->msg_controllen = 0;
 1011                                 goto out;
 1012                         }
 1013                         control->m_len -= sizeof (struct cmsghdr);
 1014                         control->m_data += sizeof (struct cmsghdr);
 1015                 }
 1016 #endif
 1017                 ctlbuf = mp->msg_control;
 1018                 len = mp->msg_controllen;
 1019                 mp->msg_controllen = 0;
 1020                 for (m = control; m != NULL && len >= m->m_len; m = m->m_next) {
 1021                         if ((error = copyout(mtod(m, caddr_t), ctlbuf,
 1022                             m->m_len)) != 0)
 1023                                 goto out;
 1024 
 1025                         ctlbuf += m->m_len;
 1026                         len -= m->m_len;
 1027                         mp->msg_controllen += m->m_len;
 1028                 }
 1029                 if (m != NULL) {
 1030                         mp->msg_flags |= MSG_CTRUNC;
 1031                         m_dispose_extcontrolm(m);
 1032                 }
 1033         }
 1034 out:
 1035         fdrop(fp, td);
 1036 #ifdef KTRACE
 1037         if (fromsa && KTRPOINT(td, KTR_STRUCT))
 1038                 ktrsockaddr(fromsa);
 1039 #endif
 1040         free(fromsa, M_SONAME);
 1041 
 1042         if (error == 0 && controlp != NULL)
 1043                 *controlp = control;
 1044         else if (control != NULL) {
 1045                 if (error != 0)
 1046                         m_dispose_extcontrolm(control);
 1047                 m_freem(control);
 1048         }
 1049 
 1050         return (error);
 1051 }
 1052 
 1053 static int
 1054 recvit(struct thread *td, int s, struct msghdr *mp, void *namelenp)
 1055 {
 1056         int error;
 1057 
 1058         error = kern_recvit(td, s, mp, UIO_USERSPACE, NULL);
 1059         if (error != 0)
 1060                 return (error);
 1061         if (namelenp != NULL) {
 1062                 error = copyout(&mp->msg_namelen, namelenp, sizeof (socklen_t));
 1063 #ifdef COMPAT_OLDSOCK
 1064                 if ((mp->msg_flags & MSG_COMPAT) != 0 &&
 1065                     SV_PROC_FLAG(td->td_proc, SV_AOUT))
 1066                         error = 0;      /* old recvfrom didn't check */
 1067 #endif
 1068         }
 1069         return (error);
 1070 }
 1071 
 1072 int
 1073 sys_recvfrom(struct thread *td, struct recvfrom_args *uap)
 1074 {
 1075         struct msghdr msg;
 1076         struct iovec aiov;
 1077         int error;
 1078 
 1079         if (uap->fromlenaddr) {
 1080                 error = copyin(uap->fromlenaddr,
 1081                     &msg.msg_namelen, sizeof (msg.msg_namelen));
 1082                 if (error != 0)
 1083                         goto done2;
 1084         } else {
 1085                 msg.msg_namelen = 0;
 1086         }
 1087         msg.msg_name = uap->from;
 1088         msg.msg_iov = &aiov;
 1089         msg.msg_iovlen = 1;
 1090         aiov.iov_base = uap->buf;
 1091         aiov.iov_len = uap->len;
 1092         msg.msg_control = 0;
 1093         msg.msg_flags = uap->flags;
 1094         error = recvit(td, uap->s, &msg, uap->fromlenaddr);
 1095 done2:
 1096         return (error);
 1097 }
 1098 
 1099 #ifdef COMPAT_OLDSOCK
 1100 int
 1101 orecvfrom(struct thread *td, struct recvfrom_args *uap)
 1102 {
 1103 
 1104         uap->flags |= MSG_COMPAT;
 1105         return (sys_recvfrom(td, uap));
 1106 }
 1107 #endif
 1108 
 1109 #ifdef COMPAT_OLDSOCK
 1110 int
 1111 orecv(struct thread *td, struct orecv_args *uap)
 1112 {
 1113         struct msghdr msg;
 1114         struct iovec aiov;
 1115 
 1116         msg.msg_name = 0;
 1117         msg.msg_namelen = 0;
 1118         msg.msg_iov = &aiov;
 1119         msg.msg_iovlen = 1;
 1120         aiov.iov_base = uap->buf;
 1121         aiov.iov_len = uap->len;
 1122         msg.msg_control = 0;
 1123         msg.msg_flags = uap->flags;
 1124         return (recvit(td, uap->s, &msg, NULL));
 1125 }
 1126 
 1127 /*
 1128  * Old recvmsg.  This code takes advantage of the fact that the old msghdr
 1129  * overlays the new one, missing only the flags, and with the (old) access
 1130  * rights where the control fields are now.
 1131  */
 1132 int
 1133 orecvmsg(struct thread *td, struct orecvmsg_args *uap)
 1134 {
 1135         struct msghdr msg;
 1136         struct iovec *iov;
 1137         int error;
 1138 
 1139         error = copyin(uap->msg, &msg, sizeof (struct omsghdr));
 1140         if (error != 0)
 1141                 return (error);
 1142         error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
 1143         if (error != 0)
 1144                 return (error);
 1145         msg.msg_flags = uap->flags | MSG_COMPAT;
 1146         msg.msg_iov = iov;
 1147         error = recvit(td, uap->s, &msg, &uap->msg->msg_namelen);
 1148         if (msg.msg_controllen && error == 0)
 1149                 error = copyout(&msg.msg_controllen,
 1150                     &uap->msg->msg_accrightslen, sizeof (int));
 1151         free(iov, M_IOV);
 1152         return (error);
 1153 }
 1154 #endif
 1155 
 1156 int
 1157 sys_recvmsg(struct thread *td, struct recvmsg_args *uap)
 1158 {
 1159         struct msghdr msg;
 1160         struct iovec *uiov, *iov;
 1161         int error;
 1162 
 1163         error = copyin(uap->msg, &msg, sizeof (msg));
 1164         if (error != 0)
 1165                 return (error);
 1166         error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
 1167         if (error != 0)
 1168                 return (error);
 1169         msg.msg_flags = uap->flags;
 1170 #ifdef COMPAT_OLDSOCK
 1171         if (SV_PROC_FLAG(td->td_proc, SV_AOUT))
 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, const 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 = __DECONST(void *, 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 && SV_PROC_FLAG(td->td_proc, SV_AOUT))
 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 && SV_PROC_FLAG(td->td_proc, SV_AOUT))
 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                     SV_CURPROC_FLAG(SV_AOUT))
 1523                         buflen = MLEN;          /* unix domain compat. hack */
 1524                 else
 1525 #endif
 1526                         if (buflen > MCLBYTES)
 1527                                 return (EINVAL);
 1528         }
 1529         m = m_get2(buflen, M_WAITOK, type, 0);
 1530         m->m_len = buflen;
 1531         error = copyin(buf, mtod(m, void *), buflen);
 1532         if (error != 0)
 1533                 (void) m_free(m);
 1534         else {
 1535                 *mp = m;
 1536                 if (type == MT_SONAME) {
 1537                         sa = mtod(m, struct sockaddr *);
 1538 
 1539 #if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
 1540                         if (sa->sa_family == 0 && sa->sa_len < AF_MAX &&
 1541                             SV_CURPROC_FLAG(SV_AOUT))
 1542                                 sa->sa_family = sa->sa_len;
 1543 #endif
 1544                         sa->sa_len = buflen;
 1545                 }
 1546         }
 1547         return (error);
 1548 }
 1549 
 1550 int
 1551 getsockaddr(struct sockaddr **namp, const struct sockaddr *uaddr, size_t len)
 1552 {
 1553         struct sockaddr *sa;
 1554         int error;
 1555 
 1556         if (len > SOCK_MAXADDRLEN)
 1557                 return (ENAMETOOLONG);
 1558         if (len < offsetof(struct sockaddr, sa_data[0]))
 1559                 return (EINVAL);
 1560         sa = malloc(len, M_SONAME, M_WAITOK);
 1561         error = copyin(uaddr, sa, len);
 1562         if (error != 0) {
 1563                 free(sa, M_SONAME);
 1564         } else {
 1565 #if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
 1566                 if (sa->sa_family == 0 && sa->sa_len < AF_MAX &&
 1567                     SV_CURPROC_FLAG(SV_AOUT))
 1568                         sa->sa_family = sa->sa_len;
 1569 #endif
 1570                 sa->sa_len = len;
 1571                 *namp = sa;
 1572         }
 1573         return (error);
 1574 }
 1575 
 1576 /*
 1577  * Dispose of externalized rights from an SCM_RIGHTS message.  This function
 1578  * should be used in error or truncation cases to avoid leaking file descriptors
 1579  * into the recipient's (the current thread's) table.
 1580  */
 1581 void
 1582 m_dispose_extcontrolm(struct mbuf *m)
 1583 {
 1584         struct cmsghdr *cm;
 1585         struct file *fp;
 1586         struct thread *td;
 1587         socklen_t clen, datalen;
 1588         int error, fd, *fds, nfd;
 1589 
 1590         td = curthread;
 1591         for (; m != NULL; m = m->m_next) {
 1592                 if (m->m_type != MT_EXTCONTROL)
 1593                         continue;
 1594                 cm = mtod(m, struct cmsghdr *);
 1595                 clen = m->m_len;
 1596                 while (clen > 0) {
 1597                         if (clen < sizeof(*cm))
 1598                                 panic("%s: truncated mbuf %p", __func__, m);
 1599                         datalen = CMSG_SPACE(cm->cmsg_len - CMSG_SPACE(0));
 1600                         if (clen < datalen)
 1601                                 panic("%s: truncated mbuf %p", __func__, m);
 1602 
 1603                         if (cm->cmsg_level == SOL_SOCKET &&
 1604                             cm->cmsg_type == SCM_RIGHTS) {
 1605                                 fds = (int *)CMSG_DATA(cm);
 1606                                 nfd = (cm->cmsg_len - CMSG_SPACE(0)) /
 1607                                     sizeof(int);
 1608 
 1609                                 while (nfd-- > 0) {
 1610                                         fd = *fds++;
 1611                                         error = fget(td, fd, &cap_no_rights,
 1612                                             &fp);
 1613                                         if (error == 0) {
 1614                                                 fdclose(td, fp, fd);
 1615                                                 fdrop(fp, td);
 1616                                         }
 1617                                 }
 1618                         }
 1619                         clen -= datalen;
 1620                         cm = (struct cmsghdr *)((uint8_t *)cm + datalen);
 1621                 }
 1622                 m_chtype(m, MT_CONTROL);
 1623         }
 1624 }

Cache object: d698addd8792c20a6b5e4a948df4439a


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