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

Cache object: f7a55123ada8a3be354e354f98e1d432


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