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

Cache object: 5e4f6c32e3225d8ff80157b4f682a4a9


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