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

Cache object: b1a567649eb8d17f7eccd95522cd3896


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