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

Cache object: 467455ffd395a76be18e801f2a2275b6


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