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 /*      $NetBSD: uipc_syscalls.c,v 1.134.4.3 2010/03/28 15:32:00 snj Exp $      */
    2 
    3 /*-
    4  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Andrew Doran.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   29  * POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 
   32 /*
   33  * Copyright (c) 1982, 1986, 1989, 1990, 1993
   34  *      The Regents of the University of California.  All rights reserved.
   35  *
   36  * Redistribution and use in source and binary forms, with or without
   37  * modification, are permitted provided that the following conditions
   38  * are met:
   39  * 1. Redistributions of source code must retain the above copyright
   40  *    notice, this list of conditions and the following disclaimer.
   41  * 2. Redistributions in binary form must reproduce the above copyright
   42  *    notice, this list of conditions and the following disclaimer in the
   43  *    documentation and/or other materials provided with the distribution.
   44  * 3. Neither the name of the University nor the names of its contributors
   45  *    may be used to endorse or promote products derived from this software
   46  *    without specific prior written permission.
   47  *
   48  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   49  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   50  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   51  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   52  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   53  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   54  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   55  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   56  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   57  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   58  * SUCH DAMAGE.
   59  *
   60  *      @(#)uipc_syscalls.c     8.6 (Berkeley) 2/14/95
   61  */
   62 
   63 #include <sys/cdefs.h>
   64 __KERNEL_RCSID(0, "$NetBSD: uipc_syscalls.c,v 1.134.4.3 2010/03/28 15:32:00 snj Exp $");
   65 
   66 #include "opt_pipe.h"
   67 
   68 #include <sys/param.h>
   69 #include <sys/systm.h>
   70 #include <sys/filedesc.h>
   71 #include <sys/proc.h>
   72 #include <sys/file.h>
   73 #include <sys/buf.h>
   74 #include <sys/malloc.h>
   75 #include <sys/mbuf.h>
   76 #include <sys/protosw.h>
   77 #include <sys/socket.h>
   78 #include <sys/socketvar.h>
   79 #include <sys/signalvar.h>
   80 #include <sys/un.h>
   81 #include <sys/ktrace.h>
   82 #include <sys/event.h>
   83 
   84 #include <sys/mount.h>
   85 #include <sys/syscallargs.h>
   86 
   87 #include <uvm/uvm_extern.h>
   88 
   89 /*
   90  * System call interface to the socket abstraction.
   91  */
   92 extern const struct fileops socketops;
   93 
   94 int
   95 sys___socket30(struct lwp *l, const struct sys___socket30_args *uap, register_t *retval)
   96 {
   97         /* {
   98                 syscallarg(int) domain;
   99                 syscallarg(int) type;
  100                 syscallarg(int) protocol;
  101         } */
  102         int             fd, error;
  103 
  104         error = fsocreate(SCARG(uap, domain), NULL, SCARG(uap, type),
  105                          SCARG(uap, protocol), l, &fd);
  106         if (error == 0)
  107                 *retval = fd;
  108         return error;
  109 }
  110 
  111 /* ARGSUSED */
  112 int
  113 sys_bind(struct lwp *l, const struct sys_bind_args *uap, register_t *retval)
  114 {
  115         /* {
  116                 syscallarg(int)                         s;
  117                 syscallarg(const struct sockaddr *)     name;
  118                 syscallarg(unsigned int)                namelen;
  119         } */
  120         struct mbuf     *nam;
  121         int             error;
  122 
  123         error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
  124             MT_SONAME);
  125         if (error)
  126                 return error;
  127 
  128         return do_sys_bind(l, SCARG(uap, s), nam);
  129 }
  130 
  131 int
  132 do_sys_bind(struct lwp *l, int fd, struct mbuf *nam)
  133 {
  134         struct socket   *so;
  135         int             error;
  136 
  137         if ((error = fd_getsock(fd, &so)) != 0) {
  138                 m_freem(nam);
  139                 return (error);
  140         }
  141         MCLAIM(nam, so->so_mowner);
  142         error = sobind(so, nam, l);
  143         m_freem(nam);
  144         fd_putfile(fd);
  145         return error;
  146 }
  147 
  148 /* ARGSUSED */
  149 int
  150 sys_listen(struct lwp *l, const struct sys_listen_args *uap, register_t *retval)
  151 {
  152         /* {
  153                 syscallarg(int) s;
  154                 syscallarg(int) backlog;
  155         } */
  156         struct socket   *so;
  157         int             error;
  158 
  159         if ((error = fd_getsock(SCARG(uap, s), &so)) != 0)
  160                 return (error);
  161         error = solisten(so, SCARG(uap, backlog), l);
  162         fd_putfile(SCARG(uap, s));
  163         return error;
  164 }
  165 
  166 int
  167 do_sys_accept(struct lwp *l, int sock, struct mbuf **name, register_t *new_sock)
  168 {
  169         file_t          *fp, *fp2;
  170         struct mbuf     *nam;
  171         int             error, fd;
  172         struct socket   *so, *so2;
  173 
  174         if ((fp = fd_getfile(sock)) == NULL)
  175                 return (EBADF);
  176         if (fp->f_type != DTYPE_SOCKET) {
  177                 fd_putfile(sock);
  178                 return (ENOTSOCK);
  179         }
  180         if ((error = fd_allocfile(&fp2, &fd)) != 0) {
  181                 fd_putfile(sock);
  182                 return (error);
  183         }
  184         nam = m_get(M_WAIT, MT_SONAME);
  185         *new_sock = fd;
  186         so = fp->f_data;
  187         solock(so);
  188         if (!(so->so_proto->pr_flags & PR_LISTEN)) {
  189                 error = EOPNOTSUPP;
  190                 goto bad;
  191         }
  192         if ((so->so_options & SO_ACCEPTCONN) == 0) {
  193                 error = EINVAL;
  194                 goto bad;
  195         }
  196         if (so->so_nbio && so->so_qlen == 0) {
  197                 error = EWOULDBLOCK;
  198                 goto bad;
  199         }
  200         while (so->so_qlen == 0 && so->so_error == 0) {
  201                 if (so->so_state & SS_CANTRCVMORE) {
  202                         so->so_error = ECONNABORTED;
  203                         break;
  204                 }
  205                 error = sowait(so, true, 0);
  206                 if (error) {
  207                         goto bad;
  208                 }
  209         }
  210         if (so->so_error) {
  211                 error = so->so_error;
  212                 so->so_error = 0;
  213                 goto bad;
  214         }
  215         /* connection has been removed from the listen queue */
  216         KNOTE(&so->so_rcv.sb_sel.sel_klist, NOTE_SUBMIT);
  217         so2 = TAILQ_FIRST(&so->so_q);
  218         if (soqremque(so2, 1) == 0)
  219                 panic("accept");
  220         fp2->f_type = DTYPE_SOCKET;
  221         fp2->f_flag = fp->f_flag;
  222         fp2->f_ops = &socketops;
  223         fp2->f_data = so2;
  224         error = soaccept(so2, nam);
  225         sounlock(so);
  226         if (error) {
  227                 /* an error occurred, free the file descriptor and mbuf */
  228                 m_freem(nam);
  229                 mutex_enter(&fp2->f_lock);
  230                 fp2->f_count++;
  231                 mutex_exit(&fp2->f_lock);
  232                 closef(fp2);
  233                 fd_abort(curproc, NULL, fd);
  234         } else {
  235                 fd_affix(curproc, fp2, fd);
  236                 *name = nam;
  237         }
  238         fd_putfile(sock);
  239         return (error);
  240  bad:
  241         sounlock(so);
  242         m_freem(nam);
  243         fd_putfile(sock);
  244         fd_abort(curproc, fp2, fd);
  245         return (error);
  246 }
  247 
  248 int
  249 sys_accept(struct lwp *l, const struct sys_accept_args *uap, register_t *retval)
  250 {
  251         /* {
  252                 syscallarg(int)                 s;
  253                 syscallarg(struct sockaddr *)   name;
  254                 syscallarg(unsigned int *)      anamelen;
  255         } */
  256         int error, fd;
  257         struct mbuf *name;
  258 
  259         error = do_sys_accept(l, SCARG(uap, s), &name, retval);
  260         if (error != 0)
  261                 return error;
  262         error = copyout_sockname(SCARG(uap, name), SCARG(uap, anamelen),
  263             MSG_LENUSRSPACE, name);
  264         if (name != NULL)
  265                 m_free(name);
  266         if (error != 0) {
  267                 fd = (int)*retval;
  268                 if (fd_getfile(fd) != NULL)
  269                         (void)fd_close(fd);
  270         }
  271         return error;
  272 }
  273 
  274 /* ARGSUSED */
  275 int
  276 sys_connect(struct lwp *l, const struct sys_connect_args *uap, register_t *retval)
  277 {
  278         /* {
  279                 syscallarg(int)                         s;
  280                 syscallarg(const struct sockaddr *)     name;
  281                 syscallarg(unsigned int)                namelen;
  282         } */
  283         int             error;
  284         struct mbuf     *nam;
  285 
  286         error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
  287             MT_SONAME);
  288         if (error)
  289                 return error;
  290         return do_sys_connect(l,  SCARG(uap, s), nam);
  291 }
  292 
  293 int
  294 do_sys_connect(struct lwp *l, int fd, struct mbuf *nam)
  295 {
  296         struct socket   *so;
  297         int             error;
  298         int             interrupted = 0;
  299 
  300         if ((error = fd_getsock(fd, &so)) != 0) {
  301                 m_freem(nam);
  302                 return (error);
  303         }
  304         solock(so);
  305         MCLAIM(nam, so->so_mowner);
  306         if ((so->so_state & SS_ISCONNECTING) != 0) {
  307                 error = EALREADY;
  308                 goto out;
  309         }
  310 
  311         error = soconnect(so, nam, l);
  312         if (error)
  313                 goto bad;
  314         if (so->so_nbio && (so->so_state & SS_ISCONNECTING) != 0) {
  315                 error = EINPROGRESS;
  316                 goto out;
  317         }
  318         while ((so->so_state & SS_ISCONNECTING) != 0 && so->so_error == 0) {
  319                 error = sowait(so, true, 0);
  320                 if (__predict_false((so->so_state & SS_ISDRAINING) != 0)) {
  321                         error = EPIPE;
  322                         interrupted = 1;
  323                         break;
  324                 }
  325                 if (error) {
  326                         if (error == EINTR || error == ERESTART)
  327                                 interrupted = 1;
  328                         break;
  329                 }
  330         }
  331         if (error == 0) {
  332                 error = so->so_error;
  333                 so->so_error = 0;
  334         }
  335  bad:
  336         if (!interrupted)
  337                 so->so_state &= ~SS_ISCONNECTING;
  338         if (error == ERESTART)
  339                 error = EINTR;
  340  out:
  341         sounlock(so);
  342         fd_putfile(fd);
  343         m_freem(nam);
  344         return (error);
  345 }
  346 
  347 int
  348 sys_socketpair(struct lwp *l, const struct sys_socketpair_args *uap, register_t *retval)
  349 {
  350         /* {
  351                 syscallarg(int)         domain;
  352                 syscallarg(int)         type;
  353                 syscallarg(int)         protocol;
  354                 syscallarg(int *)       rsv;
  355         } */
  356         file_t          *fp1, *fp2;
  357         struct socket   *so1, *so2;
  358         int             fd, error, sv[2];
  359         proc_t          *p;
  360 
  361         p = curproc;
  362         error = socreate(SCARG(uap, domain), &so1, SCARG(uap, type),
  363             SCARG(uap, protocol), l, NULL);
  364         if (error)
  365                 return (error);
  366         error = socreate(SCARG(uap, domain), &so2, SCARG(uap, type),
  367             SCARG(uap, protocol), l, so1);
  368         if (error)
  369                 goto free1;
  370         if ((error = fd_allocfile(&fp1, &fd)) != 0)
  371                 goto free2;
  372         sv[0] = fd;
  373         fp1->f_flag = FREAD|FWRITE;
  374         fp1->f_type = DTYPE_SOCKET;
  375         fp1->f_ops = &socketops;
  376         fp1->f_data = so1;
  377         if ((error = fd_allocfile(&fp2, &fd)) != 0)
  378                 goto free3;
  379         fp2->f_flag = FREAD|FWRITE;
  380         fp2->f_type = DTYPE_SOCKET;
  381         fp2->f_ops = &socketops;
  382         fp2->f_data = so2;
  383         sv[1] = fd;
  384         solock(so1);
  385         error = soconnect2(so1, so2);
  386         if (error == 0 && SCARG(uap, type) == SOCK_DGRAM) {
  387                 /*
  388                  * Datagram socket connection is asymmetric.
  389                  */
  390                 error = soconnect2(so2, so1);
  391         }
  392         sounlock(so1);
  393         if (error == 0)
  394                 error = copyout(sv, SCARG(uap, rsv), 2 * sizeof(int));
  395         if (error == 0) {
  396                 fd_affix(p, fp2, sv[1]);
  397                 fd_affix(p, fp1, sv[0]);
  398                 return (0);
  399         }
  400         fd_abort(p, fp2, sv[1]);
  401  free3:
  402         fd_abort(p, fp1, sv[0]);
  403  free2:
  404         (void)soclose(so2);
  405  free1:
  406         (void)soclose(so1);
  407         return (error);
  408 }
  409 
  410 int
  411 sys_sendto(struct lwp *l, const struct sys_sendto_args *uap, register_t *retval)
  412 {
  413         /* {
  414                 syscallarg(int)                         s;
  415                 syscallarg(const void *)                buf;
  416                 syscallarg(size_t)                      len;
  417                 syscallarg(int)                         flags;
  418                 syscallarg(const struct sockaddr *)     to;
  419                 syscallarg(unsigned int)                tolen;
  420         } */
  421         struct msghdr   msg;
  422         struct iovec    aiov;
  423 
  424         msg.msg_name = __UNCONST(SCARG(uap, to)); /* XXXUNCONST kills const */
  425         msg.msg_namelen = SCARG(uap, tolen);
  426         msg.msg_iov = &aiov;
  427         msg.msg_iovlen = 1;
  428         msg.msg_control = NULL;
  429         msg.msg_flags = 0;
  430         aiov.iov_base = __UNCONST(SCARG(uap, buf)); /* XXXUNCONST kills const */
  431         aiov.iov_len = SCARG(uap, len);
  432         return do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
  433 }
  434 
  435 int
  436 sys_sendmsg(struct lwp *l, const struct sys_sendmsg_args *uap, register_t *retval)
  437 {
  438         /* {
  439                 syscallarg(int)                         s;
  440                 syscallarg(const struct msghdr *)       msg;
  441                 syscallarg(int)                         flags;
  442         } */
  443         struct msghdr   msg;
  444         int             error;
  445 
  446         error = copyin(SCARG(uap, msg), &msg, sizeof(msg));
  447         if (error)
  448                 return (error);
  449 
  450         msg.msg_flags = MSG_IOVUSRSPACE;
  451         return do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
  452 }
  453 
  454 int
  455 do_sys_sendmsg(struct lwp *l, int s, struct msghdr *mp, int flags,
  456                 register_t *retsize)
  457 {
  458         struct uio      auio;
  459         int             i, len, error, iovlen;
  460         struct mbuf     *to, *control;
  461         struct socket   *so;
  462         struct iovec    *tiov;
  463         struct iovec    aiov[UIO_SMALLIOV], *iov = aiov;
  464         struct iovec    *ktriov = NULL;
  465 
  466         ktrkuser("msghdr", mp, sizeof *mp);
  467 
  468         /* If the caller passed us stuff in mbufs, we must free them */
  469         if (mp->msg_flags & MSG_NAMEMBUF)
  470                 to = mp->msg_name;
  471         else
  472                 to = NULL;
  473 
  474         if (mp->msg_flags & MSG_CONTROLMBUF)
  475                 control = mp->msg_control;
  476         else
  477                 control = NULL;
  478 
  479         if (mp->msg_flags & MSG_IOVUSRSPACE) {
  480                 if ((unsigned int)mp->msg_iovlen > UIO_SMALLIOV) {
  481                         if ((unsigned int)mp->msg_iovlen > IOV_MAX) {
  482                                 error = EMSGSIZE;
  483                                 goto bad;
  484                         }
  485                         iov = malloc(sizeof(struct iovec) * mp->msg_iovlen,
  486                             M_IOV, M_WAITOK);
  487                 }
  488                 if (mp->msg_iovlen != 0) {
  489                         error = copyin(mp->msg_iov, iov,
  490                             (size_t)(mp->msg_iovlen * sizeof(struct iovec)));
  491                         if (error)
  492                                 goto bad;
  493                 }
  494                 mp->msg_iov = iov;
  495         }
  496 
  497         auio.uio_iov = mp->msg_iov;
  498         auio.uio_iovcnt = mp->msg_iovlen;
  499         auio.uio_rw = UIO_WRITE;
  500         auio.uio_offset = 0;                    /* XXX */
  501         auio.uio_resid = 0;
  502         KASSERT(l == curlwp);
  503         auio.uio_vmspace = l->l_proc->p_vmspace;
  504 
  505         for (i = 0, tiov = mp->msg_iov; i < mp->msg_iovlen; i++, tiov++) {
  506 #if 0
  507                 /* cannot happen; iov_len is unsigned */
  508                 if (tiov->iov_len < 0) {
  509                         error = EINVAL;
  510                         goto bad;
  511                 }
  512 #endif
  513                 /*
  514                  * Writes return ssize_t because -1 is returned on error.
  515                  * Therefore, we must restrict the length to SSIZE_MAX to
  516                  * avoid garbage return values.
  517                  */
  518                 auio.uio_resid += tiov->iov_len;
  519                 if (tiov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
  520                         error = EINVAL;
  521                         goto bad;
  522                 }
  523         }
  524 
  525         if (mp->msg_name && to == NULL) {
  526                 error = sockargs(&to, mp->msg_name, mp->msg_namelen,
  527                     MT_SONAME);
  528                 if (error)
  529                         goto bad;
  530         }
  531 
  532         if (mp->msg_control) {
  533                 if (mp->msg_controllen < CMSG_ALIGN(sizeof(struct cmsghdr))) {
  534                         error = EINVAL;
  535                         goto bad;
  536                 }
  537                 if (control == NULL) {
  538                         error = sockargs(&control, mp->msg_control,
  539                             mp->msg_controllen, MT_CONTROL);
  540                         if (error)
  541                                 goto bad;
  542                 }
  543         }
  544 
  545         if (ktrpoint(KTR_GENIO)) {
  546                 iovlen = auio.uio_iovcnt * sizeof(struct iovec);
  547                 ktriov = malloc(iovlen, M_TEMP, M_WAITOK);
  548                 memcpy(ktriov, auio.uio_iov, iovlen);
  549         }
  550 
  551         if ((error = fd_getsock(s, &so)) != 0)
  552                 goto bad;
  553 
  554         if (mp->msg_name)
  555                 MCLAIM(to, so->so_mowner);
  556         if (mp->msg_control)
  557                 MCLAIM(control, so->so_mowner);
  558 
  559         len = auio.uio_resid;
  560         error = (*so->so_send)(so, to, &auio, NULL, control, flags, l);
  561         /* Protocol is responsible for freeing 'control' */
  562         control = NULL;
  563 
  564         fd_putfile(s);
  565 
  566         if (error) {
  567                 if (auio.uio_resid != len && (error == ERESTART ||
  568                     error == EINTR || error == EWOULDBLOCK))
  569                         error = 0;
  570                 if (error == EPIPE && (flags & MSG_NOSIGNAL) == 0) {
  571                         mutex_enter(proc_lock);
  572                         psignal(l->l_proc, SIGPIPE);
  573                         mutex_exit(proc_lock);
  574                 }
  575         }
  576         if (error == 0)
  577                 *retsize = len - auio.uio_resid;
  578 
  579 bad:
  580         if (ktriov != NULL) {
  581                 ktrgeniov(s, UIO_WRITE, ktriov, *retsize, error);
  582                 free(ktriov, M_TEMP);
  583         }
  584 
  585         if (iov != aiov)
  586                 free(iov, M_IOV);
  587         if (to)
  588                 m_freem(to);
  589         if (control)
  590                 m_freem(control);
  591 
  592         return (error);
  593 }
  594 
  595 int
  596 sys_recvfrom(struct lwp *l, const struct sys_recvfrom_args *uap, register_t *retval)
  597 {
  598         /* {
  599                 syscallarg(int)                 s;
  600                 syscallarg(void *)              buf;
  601                 syscallarg(size_t)              len;
  602                 syscallarg(int)                 flags;
  603                 syscallarg(struct sockaddr *)   from;
  604                 syscallarg(unsigned int *)      fromlenaddr;
  605         } */
  606         struct msghdr   msg;
  607         struct iovec    aiov;
  608         int             error;
  609         struct mbuf     *from;
  610 
  611         msg.msg_name = NULL;
  612         msg.msg_iov = &aiov;
  613         msg.msg_iovlen = 1;
  614         aiov.iov_base = SCARG(uap, buf);
  615         aiov.iov_len = SCARG(uap, len);
  616         msg.msg_control = NULL;
  617         msg.msg_flags = SCARG(uap, flags) & MSG_USERFLAGS;
  618 
  619         error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from, NULL, retval);
  620         if (error != 0)
  621                 return error;
  622 
  623         error = copyout_sockname(SCARG(uap, from), SCARG(uap, fromlenaddr),
  624             MSG_LENUSRSPACE, from);
  625         if (from != NULL)
  626                 m_free(from);
  627         return error;
  628 }
  629 
  630 int
  631 sys_recvmsg(struct lwp *l, const struct sys_recvmsg_args *uap, register_t *retval)
  632 {
  633         /* {
  634                 syscallarg(int)                 s;
  635                 syscallarg(struct msghdr *)     msg;
  636                 syscallarg(int)                 flags;
  637         } */
  638         struct msghdr   msg;
  639         int             error;
  640         struct mbuf     *from, *control;
  641 
  642         error = copyin(SCARG(uap, msg), &msg, sizeof(msg));
  643         if (error)
  644                 return (error);
  645 
  646         msg.msg_flags = (SCARG(uap, flags) & MSG_USERFLAGS) | MSG_IOVUSRSPACE;
  647 
  648         error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from,
  649             msg.msg_control != NULL ? &control : NULL, retval);
  650         if (error != 0)
  651                 return error;
  652 
  653         if (msg.msg_control != NULL)
  654                 error = copyout_msg_control(l, &msg, control);
  655 
  656         if (error == 0)
  657                 error = copyout_sockname(msg.msg_name, &msg.msg_namelen, 0,
  658                         from);
  659         if (from != NULL)
  660                 m_free(from);
  661         if (error == 0) {
  662                 ktrkuser("msghdr", &msg, sizeof msg);
  663                 error = copyout(&msg, SCARG(uap, msg), sizeof(msg));
  664         }
  665 
  666         return (error);
  667 }
  668 
  669 /*
  670  * Adjust for a truncated SCM_RIGHTS control message.
  671  *  This means closing any file descriptors that aren't present
  672  *  in the returned buffer.
  673  *  m is the mbuf holding the (already externalized) SCM_RIGHTS message.
  674  */
  675 static void
  676 free_rights(struct mbuf *m)
  677 {
  678         int nfd;
  679         int i;
  680         int *fdv;
  681 
  682         nfd = m->m_len < CMSG_SPACE(sizeof(int)) ? 0
  683             : (m->m_len - CMSG_SPACE(sizeof(int))) / sizeof(int) + 1;
  684         fdv = (int *) CMSG_DATA(mtod(m,struct cmsghdr *));
  685         for (i = 0; i < nfd; i++) {
  686                 if (fd_getfile(fdv[i]) != NULL)
  687                         (void)fd_close(fdv[i]);
  688         }
  689 }
  690 
  691 void
  692 free_control_mbuf(struct lwp *l, struct mbuf *control, struct mbuf *uncopied)
  693 {
  694         struct mbuf *next;
  695         struct cmsghdr *cmsg;
  696         bool do_free_rights = false;
  697 
  698         while (control != NULL) {
  699                 cmsg = mtod(control, struct cmsghdr *);
  700                 if (control == uncopied)
  701                         do_free_rights = true;
  702                 if (do_free_rights && cmsg->cmsg_level == SOL_SOCKET
  703                     && cmsg->cmsg_type == SCM_RIGHTS)
  704                         free_rights(control);
  705                 next = control->m_next;
  706                 m_free(control);
  707                 control = next;
  708         }
  709 }
  710 
  711 /* Copy socket control/CMSG data to user buffer, frees the mbuf */
  712 int
  713 copyout_msg_control(struct lwp *l, struct msghdr *mp, struct mbuf *control)
  714 {
  715         int i, len, error = 0;
  716         struct cmsghdr *cmsg;
  717         struct mbuf *m;
  718         char *q;
  719 
  720         len = mp->msg_controllen;
  721         if (len <= 0 || control == 0) {
  722                 mp->msg_controllen = 0;
  723                 free_control_mbuf(l, control, control);
  724                 return 0;
  725         }
  726 
  727         q = (char *)mp->msg_control;
  728 
  729         for (m = control; m != NULL; ) {
  730                 cmsg = mtod(m, struct cmsghdr *);
  731                 i = m->m_len;
  732                 if (len < i) {
  733                         mp->msg_flags |= MSG_CTRUNC;
  734                         if (cmsg->cmsg_level == SOL_SOCKET
  735                             && cmsg->cmsg_type == SCM_RIGHTS)
  736                                 /* Do not truncate me ... */
  737                                 break;
  738                         i = len;
  739                 }
  740                 error = copyout(mtod(m, void *), q, i);
  741                 ktrkuser("msgcontrol", mtod(m, void *), i);
  742                 if (error != 0) {
  743                         /* We must free all the SCM_RIGHTS */
  744                         m = control;
  745                         break;
  746                 }
  747                 m = m->m_next;
  748                 if (m)
  749                         i = ALIGN(i);
  750                 q += i;
  751                 len -= i;
  752                 if (len <= 0)
  753                         break;
  754         }
  755 
  756         free_control_mbuf(l, control, m);
  757 
  758         mp->msg_controllen = q - (char *)mp->msg_control;
  759         return error;
  760 }
  761 
  762 int
  763 do_sys_recvmsg(struct lwp *l, int s, struct msghdr *mp, struct mbuf **from,
  764     struct mbuf **control, register_t *retsize)
  765 {
  766         struct uio      auio;
  767         struct iovec    aiov[UIO_SMALLIOV], *iov = aiov;
  768         struct iovec    *tiov;
  769         int             i, len, error, iovlen;
  770         struct socket   *so;
  771         struct iovec    *ktriov;
  772 
  773         ktrkuser("msghdr", mp, sizeof *mp);
  774 
  775         *from = NULL;
  776         if (control != NULL)
  777                 *control = NULL;
  778 
  779         if ((error = fd_getsock(s, &so)) != 0)
  780                 return (error);
  781 
  782         if (mp->msg_flags & MSG_IOVUSRSPACE) {
  783                 if ((unsigned int)mp->msg_iovlen > UIO_SMALLIOV) {
  784                         if ((unsigned int)mp->msg_iovlen > IOV_MAX) {
  785                                 error = EMSGSIZE;
  786                                 goto out;
  787                         }
  788                         iov = malloc(sizeof(struct iovec) * mp->msg_iovlen,
  789                             M_IOV, M_WAITOK);
  790                 }
  791                 if (mp->msg_iovlen != 0) {
  792                         error = copyin(mp->msg_iov, iov,
  793                             (size_t)(mp->msg_iovlen * sizeof(struct iovec)));
  794                         if (error)
  795                                 goto out;
  796                 }
  797                 auio.uio_iov = iov;
  798         } else
  799                 auio.uio_iov = mp->msg_iov;
  800         auio.uio_iovcnt = mp->msg_iovlen;
  801         auio.uio_rw = UIO_READ;
  802         auio.uio_offset = 0;                    /* XXX */
  803         auio.uio_resid = 0;
  804         KASSERT(l == curlwp);
  805         auio.uio_vmspace = l->l_proc->p_vmspace;
  806 
  807         tiov = auio.uio_iov;
  808         for (i = 0; i < mp->msg_iovlen; i++, tiov++) {
  809 #if 0
  810                 /* cannot happen iov_len is unsigned */
  811                 if (tiov->iov_len < 0) {
  812                         error = EINVAL;
  813                         goto out;
  814                 }
  815 #endif
  816                 /*
  817                  * Reads return ssize_t because -1 is returned on error.
  818                  * Therefore we must restrict the length to SSIZE_MAX to
  819                  * avoid garbage return values.
  820                  */
  821                 auio.uio_resid += tiov->iov_len;
  822                 if (tiov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
  823                         error = EINVAL;
  824                         goto out;
  825                 }
  826         }
  827 
  828         ktriov = NULL;
  829         if (ktrpoint(KTR_GENIO)) {
  830                 iovlen = auio.uio_iovcnt * sizeof(struct iovec);
  831                 ktriov = malloc(iovlen, M_TEMP, M_WAITOK);
  832                 memcpy(ktriov, auio.uio_iov, iovlen);
  833         }
  834 
  835         len = auio.uio_resid;
  836         mp->msg_flags &= MSG_USERFLAGS;
  837         error = (*so->so_receive)(so, from, &auio, NULL, control,
  838             &mp->msg_flags);
  839         len -= auio.uio_resid;
  840         *retsize = len;
  841         if (error != 0 && len != 0
  842             && (error == ERESTART || error == EINTR || error == EWOULDBLOCK))
  843                 /* Some data transferred */
  844                 error = 0;
  845 
  846         if (ktriov != NULL) {
  847                 ktrgeniov(s, UIO_READ, ktriov, len, error);
  848                 free(ktriov, M_TEMP);
  849         }
  850 
  851         if (error != 0) {
  852                 m_freem(*from);
  853                 *from = NULL;
  854                 if (control != NULL) {
  855                         free_control_mbuf(l, *control, *control);
  856                         *control = NULL;
  857                 }
  858         }
  859  out:
  860         if (iov != aiov)
  861                 free(iov, M_IOV);
  862         fd_putfile(s);
  863         return (error);
  864 }
  865 
  866 
  867 /* ARGSUSED */
  868 int
  869 sys_shutdown(struct lwp *l, const struct sys_shutdown_args *uap, register_t *retval)
  870 {
  871         /* {
  872                 syscallarg(int) s;
  873                 syscallarg(int) how;
  874         } */
  875         struct socket   *so;
  876         int             error;
  877 
  878         if ((error = fd_getsock(SCARG(uap, s), &so)) != 0)
  879                 return (error);
  880         solock(so);
  881         error = soshutdown(so, SCARG(uap, how));
  882         sounlock(so);
  883         fd_putfile(SCARG(uap, s));
  884         return (error);
  885 }
  886 
  887 /* ARGSUSED */
  888 int
  889 sys_setsockopt(struct lwp *l, const struct sys_setsockopt_args *uap, register_t *retval)
  890 {
  891         /* {
  892                 syscallarg(int)                 s;
  893                 syscallarg(int)                 level;
  894                 syscallarg(int)                 name;
  895                 syscallarg(const void *)        val;
  896                 syscallarg(unsigned int)        valsize;
  897         } */
  898         struct sockopt  sopt;
  899         struct socket   *so;
  900         int             error;
  901         unsigned int    len;
  902 
  903         len = SCARG(uap, valsize);
  904         if (len > 0 && SCARG(uap, val) == NULL)
  905                 return (EINVAL);
  906 
  907         if (len > MCLBYTES)
  908                 return (EINVAL);
  909 
  910         if ((error = fd_getsock(SCARG(uap, s), &so)) != 0)
  911                 return (error);
  912 
  913         sockopt_init(&sopt, SCARG(uap, level), SCARG(uap, name), len);
  914 
  915         if (len > 0) {
  916                 error = copyin(SCARG(uap, val), sopt.sopt_data, len);
  917                 if (error)
  918                         goto out;
  919         }
  920 
  921         error = sosetopt(so, &sopt);
  922 
  923  out:
  924         sockopt_destroy(&sopt);
  925         fd_putfile(SCARG(uap, s));
  926         return (error);
  927 }
  928 
  929 /* ARGSUSED */
  930 int
  931 sys_getsockopt(struct lwp *l, const struct sys_getsockopt_args *uap, register_t *retval)
  932 {
  933         /* {
  934                 syscallarg(int)                 s;
  935                 syscallarg(int)                 level;
  936                 syscallarg(int)                 name;
  937                 syscallarg(void *)              val;
  938                 syscallarg(unsigned int *)      avalsize;
  939         } */
  940         struct sockopt  sopt;
  941         struct socket   *so;
  942         unsigned int    valsize, len;
  943         int             error;
  944 
  945         if (SCARG(uap, val) != NULL) {
  946                 error = copyin(SCARG(uap, avalsize), &valsize, sizeof(valsize));
  947                 if (error)
  948                         return (error);
  949         } else
  950                 valsize = 0;
  951 
  952         if ((error = fd_getsock(SCARG(uap, s), &so)) != 0)
  953                 return (error);
  954 
  955         sockopt_init(&sopt, SCARG(uap, level), SCARG(uap, name), 0);
  956 
  957         error = sogetopt(so, &sopt);
  958         if (error)
  959                 goto out;
  960 
  961         if (valsize > 0) {
  962                 len = min(valsize, sopt.sopt_size);
  963                 error = copyout(sopt.sopt_data, SCARG(uap, val), len);
  964                 if (error)
  965                         goto out;
  966 
  967                 error = copyout(&len, SCARG(uap, avalsize), sizeof(len));
  968                 if (error)
  969                         goto out;
  970         }
  971 
  972  out:
  973         sockopt_destroy(&sopt);
  974         fd_putfile(SCARG(uap, s));
  975         return (error);
  976 }
  977 
  978 #ifdef PIPE_SOCKETPAIR
  979 /* ARGSUSED */
  980 int
  981 sys_pipe(struct lwp *l, const void *v, register_t *retval)
  982 {
  983         file_t          *rf, *wf;
  984         struct socket   *rso, *wso;
  985         int             fd, error;
  986         proc_t          *p;
  987 
  988         p = curproc;
  989         if ((error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, l, NULL)) != 0)
  990                 return (error);
  991         if ((error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, l, rso)) != 0)
  992                 goto free1;
  993         /* remember this socket pair implements a pipe */
  994         wso->so_state |= SS_ISAPIPE;
  995         rso->so_state |= SS_ISAPIPE;
  996         if ((error = fd_allocfile(&rf, &fd)) != 0)
  997                 goto free2;
  998         retval[0] = fd;
  999         rf->f_flag = FREAD;
 1000         rf->f_type = DTYPE_SOCKET;
 1001         rf->f_ops = &socketops;
 1002         rf->f_data = rso;
 1003         if ((error = fd_allocfile(&wf, &fd)) != 0)
 1004                 goto free3;
 1005         wf->f_flag = FWRITE;
 1006         wf->f_type = DTYPE_SOCKET;
 1007         wf->f_ops = &socketops;
 1008         wf->f_data = wso;
 1009         retval[1] = fd;
 1010         solock(wso);
 1011         error = unp_connect2(wso, rso, PRU_CONNECT2);
 1012         sounlock(wso);
 1013         if (error != 0)
 1014                 goto free4;
 1015         fd_affix(p, wf, (int)retval[1]);
 1016         fd_affix(p, rf, (int)retval[0]);
 1017         return (0);
 1018  free4:
 1019         fd_abort(p, wf, (int)retval[1]);
 1020  free3:
 1021         fd_abort(p, rf, (int)retval[0]);
 1022  free2:
 1023         (void)soclose(wso);
 1024  free1:
 1025         (void)soclose(rso);
 1026         return (error);
 1027 }
 1028 #endif /* PIPE_SOCKETPAIR */
 1029 
 1030 /*
 1031  * Get socket name.
 1032  */
 1033 /* ARGSUSED */
 1034 int
 1035 do_sys_getsockname(struct lwp *l, int fd, int which, struct mbuf **nam)
 1036 {
 1037         struct socket   *so;
 1038         struct mbuf     *m;
 1039         int             error;
 1040 
 1041         if ((error = fd_getsock(fd, &so)) != 0)
 1042                 return error;
 1043 
 1044         m = m_getclr(M_WAIT, MT_SONAME);
 1045         MCLAIM(m, so->so_mowner);
 1046 
 1047         solock(so);
 1048         if (which == PRU_PEERADDR
 1049             && (so->so_state & (SS_ISCONNECTED | SS_ISCONFIRMING)) == 0) {
 1050                 error = ENOTCONN;
 1051         } else {
 1052                 *nam = m;
 1053                 error = (*so->so_proto->pr_usrreq)(so, which, NULL, m, NULL,
 1054                     NULL);
 1055         }
 1056         sounlock(so);
 1057         if (error != 0)
 1058                 m_free(m);
 1059         fd_putfile(fd);
 1060         return error;
 1061 }
 1062 
 1063 int
 1064 copyout_sockname(struct sockaddr *asa, unsigned int *alen, int flags,
 1065     struct mbuf *addr)
 1066 {
 1067         int len;
 1068         int error;
 1069 
 1070         if (asa == NULL)
 1071                 /* Assume application not interested */
 1072                 return 0;
 1073 
 1074         if (flags & MSG_LENUSRSPACE) {
 1075                 error = copyin(alen, &len, sizeof(len));
 1076                 if (error)
 1077                         return error;
 1078         } else
 1079                 len = *alen;
 1080         if (len < 0)
 1081                 return EINVAL;
 1082 
 1083         if (addr == NULL) {
 1084                 len = 0;
 1085                 error = 0;
 1086         } else {
 1087                 if (len > addr->m_len)
 1088                         len = addr->m_len;
 1089                 /* Maybe this ought to copy a chain ? */
 1090                 ktrkuser("sockname", mtod(addr, void *), len);
 1091                 error = copyout(mtod(addr, void *), asa, len);
 1092         }
 1093 
 1094         if (error == 0) {
 1095                 if (flags & MSG_LENUSRSPACE)
 1096                         error = copyout(&len, alen, sizeof(len));
 1097                 else
 1098                         *alen = len;
 1099         }
 1100 
 1101         return error;
 1102 }
 1103 
 1104 /*
 1105  * Get socket name.
 1106  */
 1107 /* ARGSUSED */
 1108 int
 1109 sys_getsockname(struct lwp *l, const struct sys_getsockname_args *uap, register_t *retval)
 1110 {
 1111         /* {
 1112                 syscallarg(int)                 fdes;
 1113                 syscallarg(struct sockaddr *)   asa;
 1114                 syscallarg(unsigned int *)      alen;
 1115         } */
 1116         struct mbuf     *m;
 1117         int             error;
 1118 
 1119         error = do_sys_getsockname(l, SCARG(uap, fdes), PRU_SOCKADDR, &m);
 1120         if (error != 0)
 1121                 return error;
 1122 
 1123         error = copyout_sockname(SCARG(uap, asa), SCARG(uap, alen),
 1124             MSG_LENUSRSPACE, m);
 1125         if (m != NULL)
 1126                 m_free(m);
 1127         return error;
 1128 }
 1129 
 1130 /*
 1131  * Get name of peer for connected socket.
 1132  */
 1133 /* ARGSUSED */
 1134 int
 1135 sys_getpeername(struct lwp *l, const struct sys_getpeername_args *uap, register_t *retval)
 1136 {
 1137         /* {
 1138                 syscallarg(int)                 fdes;
 1139                 syscallarg(struct sockaddr *)   asa;
 1140                 syscallarg(unsigned int *)      alen;
 1141         } */
 1142         struct mbuf     *m;
 1143         int             error;
 1144 
 1145         error = do_sys_getsockname(l, SCARG(uap, fdes), PRU_PEERADDR, &m);
 1146         if (error != 0)
 1147                 return error;
 1148 
 1149         error = copyout_sockname(SCARG(uap, asa), SCARG(uap, alen),
 1150             MSG_LENUSRSPACE, m);
 1151         if (m != NULL)
 1152                 m_free(m);
 1153         return error;
 1154 }
 1155 
 1156 /*
 1157  * XXX In a perfect world, we wouldn't pass around socket control
 1158  * XXX arguments in mbufs, and this could go away.
 1159  */
 1160 int
 1161 sockargs(struct mbuf **mp, const void *bf, size_t buflen, int type)
 1162 {
 1163         struct sockaddr *sa;
 1164         struct mbuf     *m;
 1165         int             error;
 1166 
 1167         /*
 1168          * We can't allow socket names > UCHAR_MAX in length, since that
 1169          * will overflow sa_len.  Control data more than a page size in
 1170          * length is just too much.
 1171          */
 1172         if (buflen > (type == MT_SONAME ? UCHAR_MAX : PAGE_SIZE))
 1173                 return (EINVAL);
 1174 
 1175         /* Allocate an mbuf to hold the arguments. */
 1176         m = m_get(M_WAIT, type);
 1177         /* can't claim.  don't who to assign it to. */
 1178         if (buflen > MLEN) {
 1179                 /*
 1180                  * Won't fit into a regular mbuf, so we allocate just
 1181                  * enough external storage to hold the argument.
 1182                  */
 1183                 MEXTMALLOC(m, buflen, M_WAITOK);
 1184         }
 1185         m->m_len = buflen;
 1186         error = copyin(bf, mtod(m, void *), buflen);
 1187         if (error) {
 1188                 (void) m_free(m);
 1189                 return (error);
 1190         }
 1191         ktrkuser("sockargs", mtod(m, void *), buflen);
 1192         *mp = m;
 1193         if (type == MT_SONAME) {
 1194                 sa = mtod(m, struct sockaddr *);
 1195 #if BYTE_ORDER != BIG_ENDIAN
 1196                 /*
 1197                  * 4.3BSD compat thing - need to stay, since bind(2),
 1198                  * connect(2), sendto(2) were not versioned for COMPAT_43.
 1199                  */
 1200                 if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
 1201                         sa->sa_family = sa->sa_len;
 1202 #endif
 1203                 sa->sa_len = buflen;
 1204         }
 1205         return (0);
 1206 }

Cache object: c818e3a5eeee7daa36a2ec8de95d354c


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