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-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

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

Cache object: d0b228488f8a239d9e3e14f176bf3ab1


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