[ 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  -  FREEBSD8  -  FREEBSD7  -  FREEBSD72  -  FREEBSD71  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  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  -  OPENSOLARIS  -  minix-3-1-1  -  FREEBSD-LIBC  -  FREEBSD7-LIBC  -  FREEBSD6-LIBC  -  GLIBC27 
SearchContext: -  none  -  excerpts  -  bigexcerpts 

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

Cache object: c4fce0ca3a285451769fe2e2426a7de7


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