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 /*      $OpenBSD: uipc_syscalls.c,v 1.211 2023/01/27 21:01:59 mvs 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/namei.h>
   39 #include <sys/pool.h>
   40 #include <sys/proc.h>
   41 #include <sys/fcntl.h>
   42 #include <sys/kernel.h>
   43 #include <sys/file.h>
   44 #include <sys/vnode.h>
   45 #include <sys/malloc.h>
   46 #include <sys/event.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/pledge.h>
   53 #ifdef KTRACE
   54 #include <sys/ktrace.h>
   55 #endif
   56 #include <sys/unistd.h>
   57 
   58 #include <sys/mount.h>
   59 #include <sys/syscallargs.h>
   60 
   61 #include <sys/domain.h>
   62 #include <netinet/in.h>
   63 #include <netinet/ip.h>
   64 #include <net/route.h>
   65 #include <netinet/in_pcb.h>
   66 #include <net/rtable.h>
   67 
   68 int     copyaddrout(struct proc *, struct mbuf *, struct sockaddr *, socklen_t,
   69             socklen_t *);
   70 
   71 int
   72 sys_socket(struct proc *p, 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         struct filedesc *fdp = p->p_fd;
   80         struct socket *so;
   81         struct file *fp;
   82         int type = SCARG(uap, type);
   83         int domain = SCARG(uap, domain);
   84         int fd, cloexec, nonblock, fflag, error;
   85         unsigned int ss = 0;
   86 
   87         if ((type & SOCK_DNS) && !(domain == AF_INET || domain == AF_INET6))
   88                 return (EINVAL);
   89 
   90         if (ISSET(type, SOCK_DNS))
   91                 ss |= SS_DNS;
   92         error = pledge_socket(p, domain, ss);
   93         if (error)
   94                 return (error);
   95 
   96         type &= ~(SOCK_CLOEXEC | SOCK_NONBLOCK | SOCK_DNS);
   97         cloexec = (SCARG(uap, type) & SOCK_CLOEXEC) ? UF_EXCLOSE : 0;
   98         nonblock = SCARG(uap, type) & SOCK_NONBLOCK;
   99         fflag = FREAD | FWRITE | (nonblock ? FNONBLOCK : 0);
  100 
  101         error = socreate(SCARG(uap, domain), &so, type, SCARG(uap, protocol));
  102         if (error)
  103                 return (error);
  104 
  105         fdplock(fdp);
  106         error = falloc(p, &fp, &fd);
  107         if (error) {
  108                 fdpunlock(fdp);
  109                 soclose(so, MSG_DONTWAIT);
  110         } else {
  111                 fp->f_flag = fflag;
  112                 fp->f_type = DTYPE_SOCKET;
  113                 fp->f_ops = &socketops;
  114                 so->so_state |= ss;
  115                 fp->f_data = so;
  116                 fdinsert(fdp, fd, cloexec, fp);
  117                 fdpunlock(fdp);
  118                 FRELE(fp, p);
  119                 *retval = fd;
  120         }
  121         return (error);
  122 }
  123 
  124 static inline int
  125 isdnssocket(struct socket *so)
  126 {
  127         return (so->so_state & SS_DNS);
  128 }
  129 
  130 /* For SS_DNS sockets, only allow port DNS (port 53) */
  131 static int
  132 dns_portcheck(struct proc *p, struct socket *so, void *nam, size_t namelen)
  133 {
  134         int error = EINVAL;
  135 
  136         switch (so->so_proto->pr_domain->dom_family) {
  137         case AF_INET:
  138                 if (namelen < sizeof(struct sockaddr_in))
  139                         break;
  140                 if (((struct sockaddr_in *)nam)->sin_port == htons(53))
  141                         error = 0;
  142                 break;
  143 #ifdef INET6
  144         case AF_INET6:
  145                 if (namelen < sizeof(struct sockaddr_in6))
  146                         break;
  147                 if (((struct sockaddr_in6 *)nam)->sin6_port == htons(53))
  148                         error = 0;
  149 #endif
  150         }
  151         if (error && p->p_p->ps_flags & PS_PLEDGE)
  152                 return (pledge_fail(p, EPERM, PLEDGE_DNS));
  153         return error;
  154 }
  155 
  156 int
  157 sys_bind(struct proc *p, void *v, register_t *retval)
  158 {
  159         struct sys_bind_args /* {
  160                 syscallarg(int) s;
  161                 syscallarg(const struct sockaddr *) name;
  162                 syscallarg(socklen_t) namelen;
  163         } */ *uap = v;
  164         struct file *fp;
  165         struct mbuf *nam;
  166         struct socket *so;
  167         int error;
  168 
  169         if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
  170                 return (error);
  171         so = fp->f_data;
  172         error = pledge_socket(p, so->so_proto->pr_domain->dom_family,
  173             so->so_state);
  174         if (error)
  175                 goto out;
  176         if (so->so_state & SS_YP) {
  177                 error = ENOTSOCK;
  178                 goto out;
  179         }
  180         error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
  181             MT_SONAME);
  182         if (error)
  183                 goto out;
  184 #ifdef KTRACE
  185         if (KTRPOINT(p, KTR_STRUCT))
  186                 ktrsockaddr(p, mtod(nam, caddr_t), SCARG(uap, namelen));
  187 #endif
  188         solock(so);
  189         error = sobind(so, nam, p);
  190         sounlock(so);
  191         m_freem(nam);
  192 out:
  193         FRELE(fp, p);
  194         return (error);
  195 }
  196 
  197 int
  198 sys_listen(struct proc *p, void *v, register_t *retval)
  199 {
  200         struct sys_listen_args /* {
  201                 syscallarg(int) s;
  202                 syscallarg(int) backlog;
  203         } */ *uap = v;
  204         struct file *fp;
  205         struct socket *so;
  206         int error;
  207 
  208         if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
  209                 return (error);
  210         so = fp->f_data;
  211         if (so->so_state & SS_YP)
  212                 return ENOTSOCK;
  213         solock(so);
  214         error = solisten(so, SCARG(uap, backlog));
  215         sounlock(so);
  216         FRELE(fp, p);
  217         return (error);
  218 }
  219 
  220 int
  221 sys_accept(struct proc *p, void *v, register_t *retval)
  222 {
  223         struct sys_accept_args /* {
  224                 syscallarg(int) s;
  225                 syscallarg(struct sockaddr *) name;
  226                 syscallarg(socklen_t *) anamelen;
  227         } */ *uap = v;
  228 
  229         return (doaccept(p, SCARG(uap, s), SCARG(uap, name),
  230             SCARG(uap, anamelen), SOCK_NONBLOCK_INHERIT, retval));
  231 }
  232 
  233 int
  234 sys_accept4(struct proc *p, void *v, register_t *retval)
  235 {
  236         struct sys_accept4_args /* {
  237                 syscallarg(int) s;
  238                 syscallarg(struct sockaddr *) name;
  239                 syscallarg(socklen_t *) anamelen;
  240                 syscallarg(socklen_t *) int flags;
  241         } */ *uap = v;
  242 
  243         if (SCARG(uap, flags) & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
  244                 return (EINVAL);
  245 
  246         return (doaccept(p, SCARG(uap, s), SCARG(uap, name),
  247             SCARG(uap, anamelen), SCARG(uap, flags), retval));
  248 }
  249 
  250 int
  251 doaccept(struct proc *p, int sock, struct sockaddr *name, socklen_t *anamelen,
  252     int flags, register_t *retval)
  253 {
  254         struct filedesc *fdp = p->p_fd;
  255         struct file *fp, *headfp;
  256         struct mbuf *nam;
  257         socklen_t namelen;
  258         int error, tmpfd;
  259         struct socket *head, *so;
  260         int cloexec, nflag, persocket;
  261 
  262         cloexec = (flags & SOCK_CLOEXEC) ? UF_EXCLOSE : 0;
  263 
  264         if (name && (error = copyin(anamelen, &namelen, sizeof (namelen))))
  265                 return (error);
  266         if ((error = getsock(p, sock, &fp)) != 0)
  267                 return (error);
  268 
  269         headfp = fp;
  270 
  271         fdplock(fdp);
  272         error = falloc(p, &fp, &tmpfd);
  273         fdpunlock(fdp);
  274         if (error) {
  275                 FRELE(headfp, p);
  276                 return (error);
  277         }
  278 
  279         nam = m_get(M_WAIT, MT_SONAME);
  280 
  281         head = headfp->f_data;
  282         solock(head);
  283 
  284         persocket = solock_persocket(head);
  285 
  286         if (isdnssocket(head) || (head->so_options & SO_ACCEPTCONN) == 0) {
  287                 error = EINVAL;
  288                 goto out_unlock;
  289         }
  290         if ((headfp->f_flag & FNONBLOCK) && head->so_qlen == 0) {
  291                 if (head->so_rcv.sb_state & SS_CANTRCVMORE)
  292                         error = ECONNABORTED;
  293                 else
  294                         error = EWOULDBLOCK;
  295                 goto out_unlock;
  296         }
  297         while (head->so_qlen == 0 && head->so_error == 0) {
  298                 if (head->so_rcv.sb_state & SS_CANTRCVMORE) {
  299                         head->so_error = ECONNABORTED;
  300                         break;
  301                 }
  302                 error = sosleep_nsec(head, &head->so_timeo, PSOCK | PCATCH,
  303                     "netcon", INFSLP);
  304                 if (error)
  305                         goto out_unlock;
  306         }
  307         if (head->so_error) {
  308                 error = head->so_error;
  309                 head->so_error = 0;
  310                 goto out_unlock;
  311         }
  312 
  313         /*
  314          * Do not sleep after we have taken the socket out of the queue.
  315          */
  316         so = TAILQ_FIRST(&head->so_q);
  317 
  318         if (persocket)
  319                 solock(so);
  320 
  321         if (soqremque(so, 1) == 0)
  322                 panic("accept");
  323 
  324         /* Figure out whether the new socket should be non-blocking. */
  325         nflag = flags & SOCK_NONBLOCK_INHERIT ? (headfp->f_flag & FNONBLOCK)
  326             : (flags & SOCK_NONBLOCK ? FNONBLOCK : 0);
  327 
  328         /* connection has been removed from the listen queue */
  329         KNOTE(&head->so_rcv.sb_klist, 0);
  330 
  331         if (persocket)
  332                 sounlock(head);
  333 
  334         fp->f_type = DTYPE_SOCKET;
  335         fp->f_flag = FREAD | FWRITE | nflag;
  336         fp->f_ops = &socketops;
  337         fp->f_data = so;
  338 
  339         error = soaccept(so, nam);
  340 
  341         if (persocket)
  342                 sounlock(so);
  343         else
  344                 sounlock(head);
  345 
  346         if (error)
  347                 goto out;
  348 
  349         if (name != NULL) {
  350                 error = copyaddrout(p, nam, name, namelen, anamelen);
  351                 if (error)
  352                         goto out;
  353         }
  354 
  355         fdplock(fdp);
  356         fdinsert(fdp, tmpfd, cloexec, fp);
  357         fdpunlock(fdp);
  358         FRELE(fp, p);
  359         *retval = tmpfd;
  360 
  361         m_freem(nam);
  362         FRELE(headfp, p);
  363 
  364         return 0;
  365 
  366 out_unlock:
  367         sounlock(head);
  368 out:
  369         fdplock(fdp);
  370         fdremove(fdp, tmpfd);
  371         fdpunlock(fdp);
  372         closef(fp, p);
  373 
  374         m_freem(nam);
  375         FRELE(headfp, p);
  376 
  377         return (error);
  378 }
  379 
  380 int
  381 sys_connect(struct proc *p, void *v, register_t *retval)
  382 {
  383         struct sys_connect_args /* {
  384                 syscallarg(int) s;
  385                 syscallarg(const struct sockaddr *) name;
  386                 syscallarg(socklen_t) namelen;
  387         } */ *uap = v;
  388         struct file *fp;
  389         struct socket *so;
  390         struct mbuf *nam;
  391         int error, interrupted = 0;
  392 
  393         if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
  394                 return (error);
  395         so = fp->f_data;
  396         error = pledge_socket(p, so->so_proto->pr_domain->dom_family,
  397             so->so_state);
  398         if (error)
  399                 goto out;
  400         if (so->so_state & SS_YP) {
  401                 error = ENOTSOCK;
  402                 goto out;
  403         }
  404         error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
  405             MT_SONAME);
  406         if (error)
  407                 goto out;
  408 #ifdef KTRACE
  409         if (KTRPOINT(p, KTR_STRUCT))
  410                 ktrsockaddr(p, mtod(nam, caddr_t), SCARG(uap, namelen));
  411 #endif
  412         solock(so);
  413         if (isdnssocket(so)) {
  414                 error = dns_portcheck(p, so, mtod(nam, void *), nam->m_len);
  415                 if (error)
  416                         goto unlock;
  417         }
  418         if (so->so_state & SS_ISCONNECTING) {
  419                 error = EALREADY;
  420                 goto unlock;
  421         }
  422         error = soconnect(so, nam);
  423         if (error)
  424                 goto bad;
  425         if ((fp->f_flag & FNONBLOCK) && (so->so_state & SS_ISCONNECTING)) {
  426                 error = EINPROGRESS;
  427                 goto unlock;
  428         }
  429         while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
  430                 error = sosleep_nsec(so, &so->so_timeo, PSOCK | PCATCH,
  431                     "netcon2", INFSLP);
  432                 if (error) {
  433                         if (error == EINTR || error == ERESTART)
  434                                 interrupted = 1;
  435                         break;
  436                 }
  437         }
  438         if (error == 0) {
  439                 error = so->so_error;
  440                 so->so_error = 0;
  441         }
  442 bad:
  443         if (!interrupted)
  444                 so->so_state &= ~SS_ISCONNECTING;
  445 unlock:
  446         sounlock(so);
  447         m_freem(nam);
  448 out:
  449         FRELE(fp, p);
  450         if (error == ERESTART)
  451                 error = EINTR;
  452         return (error);
  453 }
  454 
  455 int
  456 sys_socketpair(struct proc *p, void *v, register_t *retval)
  457 {
  458         struct sys_socketpair_args /* {
  459                 syscallarg(int) domain;
  460                 syscallarg(int) type;
  461                 syscallarg(int) protocol;
  462                 syscallarg(int *) rsv;
  463         } */ *uap = v;
  464         struct filedesc *fdp = p->p_fd;
  465         struct file *fp1 = NULL, *fp2 = NULL;
  466         struct socket *so1, *so2;
  467         int type, cloexec, nonblock, fflag, error, sv[2];
  468 
  469         type  = SCARG(uap, type) & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
  470         cloexec = (SCARG(uap, type) & SOCK_CLOEXEC) ? UF_EXCLOSE : 0;
  471         nonblock = SCARG(uap, type) & SOCK_NONBLOCK;
  472         fflag = FREAD | FWRITE | (nonblock ? FNONBLOCK : 0);
  473 
  474         error = socreate(SCARG(uap, domain), &so1, type, SCARG(uap, protocol));
  475         if (error)
  476                 return (error);
  477         error = socreate(SCARG(uap, domain), &so2, type, SCARG(uap, protocol));
  478         if (error)
  479                 goto free1;
  480 
  481         error = soconnect2(so1, so2);
  482         if (error != 0)
  483                 goto free2;
  484 
  485         if ((SCARG(uap, type) & SOCK_TYPE_MASK) == SOCK_DGRAM) {
  486                 /*
  487                  * Datagram socket connection is asymmetric.
  488                  */
  489                 error = soconnect2(so2, so1);
  490                 if (error != 0)
  491                         goto free2;
  492         }
  493         fdplock(fdp);
  494         if ((error = falloc(p, &fp1, &sv[0])) != 0)
  495                 goto free3;
  496         fp1->f_flag = fflag;
  497         fp1->f_type = DTYPE_SOCKET;
  498         fp1->f_ops = &socketops;
  499         fp1->f_data = so1;
  500         if ((error = falloc(p, &fp2, &sv[1])) != 0)
  501                 goto free4;
  502         fp2->f_flag = fflag;
  503         fp2->f_type = DTYPE_SOCKET;
  504         fp2->f_ops = &socketops;
  505         fp2->f_data = so2;
  506         error = copyout(sv, SCARG(uap, rsv), 2 * sizeof (int));
  507         if (error == 0) {
  508                 fdinsert(fdp, sv[0], cloexec, fp1);
  509                 fdinsert(fdp, sv[1], cloexec, fp2);
  510                 fdpunlock(fdp);
  511 #ifdef KTRACE
  512                 if (KTRPOINT(p, KTR_STRUCT))
  513                         ktrfds(p, sv, 2);
  514 #endif
  515                 FRELE(fp1, p);
  516                 FRELE(fp2, p);
  517                 return (0);
  518         }
  519         fdremove(fdp, sv[1]);
  520 free4:
  521         fdremove(fdp, sv[0]);
  522 free3:
  523         fdpunlock(fdp);
  524 
  525         if (fp2 != NULL) {
  526                 closef(fp2, p);
  527                 so2 = NULL;
  528         }
  529         if (fp1 != NULL) {
  530                 closef(fp1, p);
  531                 so1 = NULL;
  532         }
  533 free2:
  534         if (so2 != NULL)
  535                 (void)soclose(so2, 0);
  536 free1:
  537         if (so1 != NULL)
  538                 (void)soclose(so1, 0);
  539         return (error);
  540 }
  541 
  542 int
  543 sys_sendto(struct proc *p, void *v, register_t *retval)
  544 {
  545         struct sys_sendto_args /* {
  546                 syscallarg(int) s;
  547                 syscallarg(const void *) buf;
  548                 syscallarg(size_t) len;
  549                 syscallarg(int) flags;
  550                 syscallarg(const struct sockaddr *) to;
  551                 syscallarg(socklen_t) tolen;
  552         } */ *uap = v;
  553         struct msghdr msg;
  554         struct iovec aiov;
  555 
  556         msg.msg_name = (caddr_t)SCARG(uap, to);
  557         msg.msg_namelen = SCARG(uap, tolen);
  558         msg.msg_iov = &aiov;
  559         msg.msg_iovlen = 1;
  560         msg.msg_control = NULL;
  561         msg.msg_flags = 0;
  562         aiov.iov_base = (char *)SCARG(uap, buf);
  563         aiov.iov_len = SCARG(uap, len);
  564         return (sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval));
  565 }
  566 
  567 int
  568 sys_sendmsg(struct proc *p, void *v, register_t *retval)
  569 {
  570         struct sys_sendmsg_args /* {
  571                 syscallarg(int) s;
  572                 syscallarg(const struct msghdr *) msg;
  573                 syscallarg(int) flags;
  574         } */ *uap = v;
  575         struct msghdr msg;
  576         struct iovec aiov[UIO_SMALLIOV], *iov;
  577         int error;
  578 
  579         error = copyin(SCARG(uap, msg), &msg, sizeof (msg));
  580         if (error)
  581                 return (error);
  582 #ifdef KTRACE
  583         if (KTRPOINT(p, KTR_STRUCT))
  584                 ktrmsghdr(p, &msg);
  585 #endif
  586 
  587         if (msg.msg_iovlen > IOV_MAX)
  588                 return (EMSGSIZE);
  589         if (msg.msg_iovlen > UIO_SMALLIOV)
  590                 iov = mallocarray(msg.msg_iovlen, sizeof(struct iovec),
  591                     M_IOV, M_WAITOK);
  592         else
  593                 iov = aiov;
  594         if (msg.msg_iovlen &&
  595             (error = copyin(msg.msg_iov, iov,
  596                     msg.msg_iovlen * sizeof (struct iovec))))
  597                 goto done;
  598 #ifdef KTRACE
  599         if (msg.msg_iovlen && KTRPOINT(p, KTR_STRUCT))
  600                 ktriovec(p, iov, msg.msg_iovlen);
  601 #endif
  602         msg.msg_iov = iov;
  603         msg.msg_flags = 0;
  604         error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
  605 done:
  606         if (iov != aiov)
  607                 free(iov, M_IOV, sizeof(struct iovec) * msg.msg_iovlen);
  608         return (error);
  609 }
  610 
  611 int
  612 sys_sendmmsg(struct proc *p, void *v, register_t *retval)
  613 {
  614         struct sys_sendmmsg_args /* {
  615                 syscallarg(int)                 s;
  616                 syscallarg(struct mmsghdr *)    mmsg;
  617                 syscallarg(unsigned int)        vlen;
  618                 syscallarg(int)                 flags;
  619         } */ *uap = v;
  620         struct mmsghdr mmsg, *mmsgp;
  621         struct iovec aiov[UIO_SMALLIOV], *iov = aiov, *uiov;
  622         size_t iovlen = UIO_SMALLIOV;
  623         register_t retsnd;
  624         unsigned int vlen, dgrams;
  625         int error = 0, flags, s;
  626 
  627         s = SCARG(uap, s);
  628         flags = SCARG(uap, flags);
  629 
  630         /* Arbitrarily capped at 1024 datagrams. */
  631         vlen = SCARG(uap, vlen);
  632         if (vlen > 1024)
  633                 vlen = 1024;
  634 
  635         mmsgp = SCARG(uap, mmsg);
  636         for (dgrams = 0; dgrams < vlen; dgrams++) {
  637                 error = copyin(&mmsgp[dgrams], &mmsg, sizeof(mmsg));
  638                 if (error)
  639                         break;
  640 
  641 #ifdef KTRACE
  642                 if (KTRPOINT(p, KTR_STRUCT))
  643                         ktrmmsghdr(p, &mmsg);
  644 #endif
  645 
  646                 if (mmsg.msg_hdr.msg_iovlen > IOV_MAX) {
  647                         error = EMSGSIZE;
  648                         break;
  649                 }
  650 
  651                 if (mmsg.msg_hdr.msg_iovlen > iovlen) {
  652                         if (iov != aiov)
  653                                 free(iov, M_IOV, iovlen *
  654                                     sizeof(struct iovec));
  655 
  656                         iovlen = mmsg.msg_hdr.msg_iovlen;
  657                         iov = mallocarray(iovlen, sizeof(struct iovec),
  658                             M_IOV, M_WAITOK);
  659                 }
  660 
  661                 if (mmsg.msg_hdr.msg_iovlen > 0) {
  662                         error = copyin(mmsg.msg_hdr.msg_iov, iov,
  663                             mmsg.msg_hdr.msg_iovlen * sizeof(struct iovec));
  664                         if (error)
  665                                 break;
  666                 }
  667 
  668 #ifdef KTRACE
  669                 if (mmsg.msg_hdr.msg_iovlen && KTRPOINT(p, KTR_STRUCT))
  670                         ktriovec(p, iov, mmsg.msg_hdr.msg_iovlen);
  671 #endif
  672 
  673                 uiov = mmsg.msg_hdr.msg_iov;
  674                 mmsg.msg_hdr.msg_iov = iov;
  675                 mmsg.msg_hdr.msg_flags = 0;
  676 
  677                 error = sendit(p, s, &mmsg.msg_hdr, flags, &retsnd);
  678                 if (error)
  679                         break;
  680 
  681                 mmsg.msg_hdr.msg_iov = uiov;
  682                 mmsg.msg_len = retsnd;
  683 
  684                 error = copyout(&mmsg, &mmsgp[dgrams], sizeof(mmsg));
  685                 if (error)
  686                         break;
  687         }
  688 
  689         if (iov != aiov)
  690                 free(iov, M_IOV, sizeof(struct iovec) * iovlen);
  691 
  692         *retval = dgrams;
  693 
  694         if (error && dgrams > 0)
  695                 error = 0;
  696 
  697         return (error);
  698 }
  699 
  700 int
  701 sendit(struct proc *p, int s, struct msghdr *mp, int flags, register_t *retsize)
  702 {
  703         struct file *fp;
  704         struct uio auio;
  705         struct iovec *iov;
  706         int i;
  707         struct mbuf *to, *control;
  708         struct socket *so;
  709         size_t len;
  710         int error;
  711 #ifdef KTRACE
  712         struct iovec *ktriov = NULL;
  713         int iovlen = 0;
  714 #endif
  715 
  716         to = NULL;
  717 
  718         if ((error = getsock(p, s, &fp)) != 0)
  719                 return (error);
  720         so = fp->f_data;
  721         if (fp->f_flag & FNONBLOCK)
  722                 flags |= MSG_DONTWAIT;
  723 
  724         error = pledge_sendit(p, mp->msg_name);
  725         if (error)
  726                 goto bad;
  727 
  728         auio.uio_iov = mp->msg_iov;
  729         auio.uio_iovcnt = mp->msg_iovlen;
  730         auio.uio_segflg = UIO_USERSPACE;
  731         auio.uio_rw = UIO_WRITE;
  732         auio.uio_procp = p;
  733         auio.uio_offset = 0;                    /* XXX */
  734         auio.uio_resid = 0;
  735         iov = mp->msg_iov;
  736         for (i = 0; i < mp->msg_iovlen; i++, iov++) {
  737                 /* Don't allow sum > SSIZE_MAX */
  738                 if (iov->iov_len > SSIZE_MAX ||
  739                     (auio.uio_resid += iov->iov_len) > SSIZE_MAX) {
  740                         error = EINVAL;
  741                         goto bad;
  742                 }
  743         }
  744         if (mp->msg_name) {
  745                 error = sockargs(&to, mp->msg_name, mp->msg_namelen,
  746                     MT_SONAME);
  747                 if (error)
  748                         goto bad;
  749                 if (isdnssocket(so)) {
  750                         error = dns_portcheck(p, so, mtod(to, caddr_t),
  751                             mp->msg_namelen);
  752                         if (error)
  753                                 goto bad;
  754                 }
  755 #ifdef KTRACE
  756                 if (KTRPOINT(p, KTR_STRUCT))
  757                         ktrsockaddr(p, mtod(to, caddr_t), mp->msg_namelen);
  758 #endif
  759         }
  760         if (mp->msg_control) {
  761                 if (mp->msg_controllen < CMSG_ALIGN(sizeof(struct cmsghdr))) {
  762                         error = EINVAL;
  763                         goto bad;
  764                 }
  765                 error = sockargs(&control, mp->msg_control,
  766                     mp->msg_controllen, MT_CONTROL);
  767                 if (error)
  768                         goto bad;
  769 #ifdef KTRACE
  770                 if (KTRPOINT(p, KTR_STRUCT) && mp->msg_controllen)
  771                         ktrcmsghdr(p, mtod(control, char *),
  772                             mp->msg_controllen);
  773 #endif
  774         } else
  775                 control = NULL;
  776 #ifdef KTRACE
  777         if (KTRPOINT(p, KTR_GENIO)) {
  778                 ktriov = mallocarray(auio.uio_iovcnt, sizeof(struct iovec),
  779                     M_TEMP, M_WAITOK);
  780                 iovlen = auio.uio_iovcnt * sizeof (struct iovec);
  781 
  782                 memcpy(ktriov, auio.uio_iov, iovlen);
  783         }
  784 #endif
  785         len = auio.uio_resid;
  786         error = sosend(so, to, &auio, NULL, control, flags);
  787         if (error) {
  788                 if (auio.uio_resid != len && (error == ERESTART ||
  789                     error == EINTR || error == EWOULDBLOCK))
  790                         error = 0;
  791                 if (error == EPIPE && (flags & MSG_NOSIGNAL) == 0) {
  792                         KERNEL_LOCK();
  793                         ptsignal(p, SIGPIPE, STHREAD);
  794                         KERNEL_UNLOCK();
  795                 }
  796         }
  797         if (error == 0) {
  798                 *retsize = len - auio.uio_resid;
  799                 mtx_enter(&fp->f_mtx);
  800                 fp->f_wxfer++;
  801                 fp->f_wbytes += *retsize;
  802                 mtx_leave(&fp->f_mtx);
  803         }
  804 #ifdef KTRACE
  805         if (ktriov != NULL) {
  806                 if (error == 0)
  807                         ktrgenio(p, s, UIO_WRITE, ktriov, *retsize);
  808                 free(ktriov, M_TEMP, iovlen);
  809         }
  810 #endif
  811 bad:
  812         FRELE(fp, p);
  813         m_freem(to);
  814         return (error);
  815 }
  816 
  817 int
  818 sys_recvfrom(struct proc *p, void *v, register_t *retval)
  819 {
  820         struct sys_recvfrom_args /* {
  821                 syscallarg(int) s;
  822                 syscallarg(void *) buf;
  823                 syscallarg(size_t) len;
  824                 syscallarg(int) flags;
  825                 syscallarg(struct sockaddr *) from;
  826                 syscallarg(socklen_t *) fromlenaddr;
  827         } */ *uap = v;
  828         struct msghdr msg;
  829         struct iovec aiov;
  830         int error;
  831 
  832         if (SCARG(uap, fromlenaddr)) {
  833                 error = copyin(SCARG(uap, fromlenaddr),
  834                     &msg.msg_namelen, sizeof (msg.msg_namelen));
  835                 if (error)
  836                         return (error);
  837         } else
  838                 msg.msg_namelen = 0;
  839         msg.msg_name = (caddr_t)SCARG(uap, from);
  840         msg.msg_iov = &aiov;
  841         msg.msg_iovlen = 1;
  842         aiov.iov_base = SCARG(uap, buf);
  843         aiov.iov_len = SCARG(uap, len);
  844         msg.msg_control = NULL;
  845         msg.msg_flags = SCARG(uap, flags);
  846         return (recvit(p, SCARG(uap, s), &msg,
  847             (caddr_t)SCARG(uap, fromlenaddr), retval));
  848 }
  849 
  850 int
  851 sys_recvmsg(struct proc *p, void *v, register_t *retval)
  852 {
  853         struct sys_recvmsg_args /* {
  854                 syscallarg(int) s;
  855                 syscallarg(struct msghdr *) msg;
  856                 syscallarg(int) flags;
  857         } */ *uap = v;
  858         struct msghdr msg;
  859         struct iovec aiov[UIO_SMALLIOV], *uiov, *iov;
  860         int error;
  861 
  862         error = copyin(SCARG(uap, msg), &msg, sizeof (msg));
  863         if (error)
  864                 return (error);
  865 
  866         if (msg.msg_iovlen > IOV_MAX)
  867                 return (EMSGSIZE);
  868         if (msg.msg_iovlen > UIO_SMALLIOV)
  869                 iov = mallocarray(msg.msg_iovlen, sizeof(struct iovec),
  870                     M_IOV, M_WAITOK);
  871         else
  872                 iov = aiov;
  873         msg.msg_flags = SCARG(uap, flags);
  874         if (msg.msg_iovlen > 0) {
  875                 error = copyin(msg.msg_iov, iov,
  876                     msg.msg_iovlen * sizeof(struct iovec));
  877                 if (error)
  878                         goto done;
  879         }
  880         uiov = msg.msg_iov;
  881         msg.msg_iov = iov;
  882         if ((error = recvit(p, SCARG(uap, s), &msg, NULL, retval)) == 0) {
  883                 msg.msg_iov = uiov;
  884 #ifdef KTRACE
  885                 if (KTRPOINT(p, KTR_STRUCT)) {
  886                         ktrmsghdr(p, &msg);
  887                         if (msg.msg_iovlen)
  888                                 ktriovec(p, iov, msg.msg_iovlen);
  889                 }
  890 #endif
  891                 error = copyout(&msg, SCARG(uap, msg), sizeof(msg));
  892         }
  893 done:
  894         if (iov != aiov)
  895                 free(iov, M_IOV, sizeof(struct iovec) * msg.msg_iovlen);
  896         return (error);
  897 }
  898 
  899 int
  900 sys_recvmmsg(struct proc *p, void *v, register_t *retval)
  901 {
  902         struct sys_recvmmsg_args /* {
  903                 syscallarg(int)                 s;
  904                 syscallarg(struct mmsghdr *)    mmsg;
  905                 syscallarg(unsigned int)        vlen;
  906                 syscallarg(int)                 flags;
  907                 syscallarg(struct timespec *)   timeout;
  908         } */ *uap = v;
  909         struct mmsghdr mmsg, *mmsgp;
  910         struct timespec ts, now, *timeout;
  911         struct iovec aiov[UIO_SMALLIOV], *uiov, *iov = aiov;
  912         size_t iovlen = UIO_SMALLIOV;
  913         register_t retrec;
  914         unsigned int vlen, dgrams;
  915         int error = 0, flags, s;
  916 
  917         timeout = SCARG(uap, timeout);
  918         if (timeout != NULL) {
  919                 error = copyin(timeout, &ts, sizeof(ts));
  920                 if (error)
  921                         return (error);
  922 #ifdef KTRACE
  923                 if (KTRPOINT(p, KTR_STRUCT))
  924                         ktrreltimespec(p, &ts);
  925 #endif
  926                 if (!timespecisvalid(&ts))
  927                         return (EINVAL);
  928 
  929                 getnanotime(&now);
  930                 timespecadd(&now, &ts, &ts);
  931         }
  932 
  933         s = SCARG(uap, s);
  934         flags = SCARG(uap, flags);
  935 
  936         /* Arbitrarily capped at 1024 datagrams. */
  937         vlen = SCARG(uap, vlen);
  938         if (vlen > 1024)
  939                 vlen = 1024;
  940 
  941         mmsgp = SCARG(uap, mmsg);
  942         for (dgrams = 0; dgrams < vlen;) {
  943                 error = copyin(&mmsgp[dgrams], &mmsg, sizeof(mmsg));
  944                 if (error)
  945                         break;
  946 
  947                 if (mmsg.msg_hdr.msg_iovlen > IOV_MAX) {
  948                         error = EMSGSIZE;
  949                         break;
  950                 }
  951 
  952                 if (mmsg.msg_hdr.msg_iovlen > iovlen) {
  953                         if (iov != aiov)
  954                                 free(iov, M_IOV, iovlen *
  955                                     sizeof(struct iovec));
  956 
  957                         iovlen = mmsg.msg_hdr.msg_iovlen;
  958                         iov = mallocarray(iovlen, sizeof(struct iovec),
  959                             M_IOV, M_WAITOK);
  960                 }
  961 
  962                 if (mmsg.msg_hdr.msg_iovlen > 0) {
  963                         error = copyin(mmsg.msg_hdr.msg_iov, iov,
  964                             mmsg.msg_hdr.msg_iovlen * sizeof(struct iovec));
  965                         if (error)
  966                                 break;
  967                 }
  968 
  969                 uiov = mmsg.msg_hdr.msg_iov;
  970                 mmsg.msg_hdr.msg_iov = iov;
  971                 mmsg.msg_hdr.msg_flags = flags & ~MSG_WAITFORONE;
  972 
  973                 error = recvit(p, s, &mmsg.msg_hdr, NULL, &retrec);
  974                 if (error) {
  975                         if (error == EAGAIN && dgrams > 0)
  976                                 error = 0;
  977                         break;
  978                 }
  979 
  980                 if (flags & MSG_WAITFORONE)
  981                         flags |= MSG_DONTWAIT;
  982 
  983                 mmsg.msg_hdr.msg_iov = uiov;
  984                 mmsg.msg_len = retrec;
  985 #ifdef KTRACE
  986                 if (KTRPOINT(p, KTR_STRUCT)) {
  987                         ktrmmsghdr(p, &mmsg);
  988                         if (mmsg.msg_hdr.msg_iovlen)
  989                                 ktriovec(p, iov, mmsg.msg_hdr.msg_iovlen);
  990                 }
  991 #endif
  992 
  993                 error = copyout(&mmsg, &mmsgp[dgrams], sizeof(mmsg));
  994                 if (error)
  995                         break;
  996 
  997                 dgrams++;
  998                 if (mmsg.msg_hdr.msg_flags & MSG_OOB)
  999                         break;
 1000 
 1001                 if (timeout != NULL) {
 1002                         getnanotime(&now);
 1003                         timespecsub(&now, &ts, &now);
 1004                         if (now.tv_sec > 0)
 1005                                 break;
 1006                 }
 1007         }
 1008 
 1009         if (iov != aiov)
 1010                 free(iov, M_IOV, iovlen * sizeof(struct iovec));
 1011 
 1012         *retval = dgrams;
 1013 
 1014         /*
 1015          * If we succeeded at least once, return 0, hopefully so->so_error
 1016          * will catch it next time.
 1017          */
 1018         if (error && dgrams > 0) {
 1019                 struct file *fp;
 1020                 struct socket *so;
 1021 
 1022                 if (getsock(p, s, &fp) == 0) {
 1023                         so = (struct socket *)fp->f_data;
 1024                         so->so_error = error;
 1025 
 1026                         FRELE(fp, p);
 1027                 }
 1028                 error = 0;
 1029         }
 1030 
 1031         return (error);
 1032 }
 1033 
 1034 int
 1035 recvit(struct proc *p, int s, struct msghdr *mp, caddr_t namelenp,
 1036     register_t *retsize)
 1037 {
 1038         struct file *fp;
 1039         struct uio auio;
 1040         struct iovec *iov;
 1041         int i;
 1042         size_t len;
 1043         int error;
 1044         struct mbuf *from = NULL, *control = NULL;
 1045 #ifdef KTRACE
 1046         struct iovec *ktriov = NULL;
 1047         int iovlen = 0, kmsgflags;
 1048 #endif
 1049 
 1050         if ((error = getsock(p, s, &fp)) != 0)
 1051                 return (error);
 1052 
 1053         auio.uio_iov = mp->msg_iov;
 1054         auio.uio_iovcnt = mp->msg_iovlen;
 1055         auio.uio_segflg = UIO_USERSPACE;
 1056         auio.uio_rw = UIO_READ;
 1057         auio.uio_procp = p;
 1058         auio.uio_offset = 0;                    /* XXX */
 1059         auio.uio_resid = 0;
 1060         iov = mp->msg_iov;
 1061         for (i = 0; i < mp->msg_iovlen; i++, iov++) {
 1062                 /* Don't allow sum > SSIZE_MAX */
 1063                 if (iov->iov_len > SSIZE_MAX ||
 1064                     (auio.uio_resid += iov->iov_len) > SSIZE_MAX) {
 1065                         error = EINVAL;
 1066                         goto out;
 1067                 }
 1068         }
 1069 #ifdef KTRACE
 1070         if (KTRPOINT(p, KTR_GENIO)) {
 1071                 ktriov = mallocarray(auio.uio_iovcnt, sizeof(struct iovec),
 1072                     M_TEMP, M_WAITOK);
 1073                 iovlen = auio.uio_iovcnt * sizeof (struct iovec);
 1074 
 1075                 memcpy(ktriov, auio.uio_iov, iovlen);
 1076         }
 1077         kmsgflags = mp->msg_flags;
 1078 #endif
 1079         len = auio.uio_resid;
 1080         if (fp->f_flag & FNONBLOCK)
 1081                 mp->msg_flags |= MSG_DONTWAIT;
 1082         error = soreceive(fp->f_data, &from, &auio, NULL,
 1083                           mp->msg_control ? &control : NULL,
 1084                           &mp->msg_flags,
 1085                           mp->msg_control ? mp->msg_controllen : 0);
 1086         if (error) {
 1087                 if (auio.uio_resid != len && (error == ERESTART ||
 1088                     error == EINTR || error == EWOULDBLOCK))
 1089                         error = 0;
 1090         }
 1091 #ifdef KTRACE
 1092         if (ktriov != NULL) {
 1093                 if (error == 0)
 1094                         ktrgenio(p, s, UIO_READ, ktriov, len - auio.uio_resid);
 1095                 free(ktriov, M_TEMP, iovlen);
 1096         }
 1097 #endif
 1098         if (error)
 1099                 goto out;
 1100         *retsize = len - auio.uio_resid;
 1101         if (mp->msg_name) {
 1102                 socklen_t alen;
 1103 
 1104                 if (from == NULL)
 1105                         alen = 0;
 1106                 else {
 1107                         alen = from->m_len;
 1108                         error = copyout(mtod(from, caddr_t), mp->msg_name,
 1109                             MIN(alen, mp->msg_namelen));
 1110                         if (error)
 1111                                 goto out;
 1112 #ifdef KTRACE
 1113                         if (KTRPOINT(p, KTR_STRUCT))
 1114                                 ktrsockaddr(p, mtod(from, caddr_t), alen);
 1115 #endif
 1116                 }
 1117                 mp->msg_namelen = alen;
 1118                 if (namelenp &&
 1119                     (error = copyout(&alen, namelenp, sizeof(alen)))) {
 1120                         goto out;
 1121                 }
 1122         }
 1123         if (mp->msg_control) {
 1124                 len = mp->msg_controllen;
 1125                 if (len <= 0 || control == NULL)
 1126                         len = 0;
 1127                 else {
 1128                         struct mbuf *m = control;
 1129                         caddr_t cp = mp->msg_control;
 1130 
 1131                         do {
 1132                                 i = m->m_len;
 1133                                 if (len < i) {
 1134                                         mp->msg_flags |= MSG_CTRUNC;
 1135                                         i = len;
 1136                                 }
 1137                                 error = copyout(mtod(m, caddr_t), cp, i);
 1138 #ifdef KTRACE
 1139                                 if (KTRPOINT(p, KTR_STRUCT) && error == 0 && i) {
 1140                                         /* msg_flags potentially incorrect */
 1141                                         int rmsgflags = mp->msg_flags;
 1142 
 1143                                         mp->msg_flags = kmsgflags;
 1144                                         ktrcmsghdr(p, mtod(m, char *), i);
 1145                                         mp->msg_flags = rmsgflags;
 1146                                 }
 1147 #endif
 1148                                 if (m->m_next)
 1149                                         i = ALIGN(i);
 1150                                 cp += i;
 1151                                 len -= i;
 1152                                 if (error != 0 || len <= 0)
 1153                                         break;
 1154                         } while ((m = m->m_next) != NULL);
 1155                         len = cp - (caddr_t)mp->msg_control;
 1156                 }
 1157                 mp->msg_controllen = len;
 1158         }
 1159         if (!error) {
 1160                 mtx_enter(&fp->f_mtx);
 1161                 fp->f_rxfer++;
 1162                 fp->f_rbytes += *retsize;
 1163                 mtx_leave(&fp->f_mtx);
 1164         }
 1165 out:
 1166         FRELE(fp, p);
 1167         m_freem(from);
 1168         m_freem(control);
 1169         return (error);
 1170 }
 1171 
 1172 int
 1173 sys_shutdown(struct proc *p, void *v, register_t *retval)
 1174 {
 1175         struct sys_shutdown_args /* {
 1176                 syscallarg(int) s;
 1177                 syscallarg(int) how;
 1178         } */ *uap = v;
 1179         struct file *fp;
 1180         int error;
 1181 
 1182         if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
 1183                 return (error);
 1184         error = soshutdown(fp->f_data, SCARG(uap, how));
 1185         FRELE(fp, p);
 1186         return (error);
 1187 }
 1188 
 1189 int
 1190 sys_setsockopt(struct proc *p, void *v, register_t *retval)
 1191 {
 1192         struct sys_setsockopt_args /* {
 1193                 syscallarg(int) s;
 1194                 syscallarg(int) level;
 1195                 syscallarg(int) name;
 1196                 syscallarg(const void *) val;
 1197                 syscallarg(socklen_t) valsize;
 1198         } */ *uap = v;
 1199         struct file *fp;
 1200         struct mbuf *m = NULL;
 1201         struct socket *so;
 1202         int error;
 1203 
 1204 
 1205         if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
 1206                 return (error);
 1207         error = pledge_sockopt(p, 1, SCARG(uap, level), SCARG(uap, name));
 1208         if (error)
 1209                 goto bad;
 1210         if (SCARG(uap, valsize) > MCLBYTES) {
 1211                 error = EINVAL;
 1212                 goto bad;
 1213         }
 1214         if (SCARG(uap, val)) {
 1215                 m = m_get(M_WAIT, MT_SOOPTS);
 1216                 if (SCARG(uap, valsize) > MLEN) {
 1217                         MCLGET(m, M_DONTWAIT);
 1218                         if ((m->m_flags & M_EXT) == 0) {
 1219                                 error = ENOBUFS;
 1220                                 goto bad;
 1221                         }
 1222                 }
 1223                 if (m == NULL) {
 1224                         error = ENOBUFS;
 1225                         goto bad;
 1226                 }
 1227                 error = copyin(SCARG(uap, val), mtod(m, caddr_t),
 1228                     SCARG(uap, valsize));
 1229                 if (error) {
 1230                         goto bad;
 1231                 }
 1232                 m->m_len = SCARG(uap, valsize);
 1233         }
 1234         so = fp->f_data;
 1235         solock(so);
 1236         error = sosetopt(so, SCARG(uap, level), SCARG(uap, name), m);
 1237         sounlock(so);
 1238 bad:
 1239         m_freem(m);
 1240         FRELE(fp, p);
 1241         return (error);
 1242 }
 1243 
 1244 int
 1245 sys_getsockopt(struct proc *p, void *v, register_t *retval)
 1246 {
 1247         struct sys_getsockopt_args /* {
 1248                 syscallarg(int) s;
 1249                 syscallarg(int) level;
 1250                 syscallarg(int) name;
 1251                 syscallarg(void *) val;
 1252                 syscallarg(socklen_t *) avalsize;
 1253         } */ *uap = v;
 1254         struct file *fp;
 1255         struct mbuf *m = NULL;
 1256         socklen_t valsize;
 1257         struct socket *so;
 1258         int error;
 1259 
 1260         if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
 1261                 return (error);
 1262         error = pledge_sockopt(p, 0, SCARG(uap, level), SCARG(uap, name));
 1263         if (error)
 1264                 goto out;
 1265         if (SCARG(uap, val)) {
 1266                 error = copyin(SCARG(uap, avalsize),
 1267                     &valsize, sizeof (valsize));
 1268                 if (error)
 1269                         goto out;
 1270         } else
 1271                 valsize = 0;
 1272         m = m_get(M_WAIT, MT_SOOPTS);
 1273         so = fp->f_data;
 1274         error = sogetopt(so, SCARG(uap, level), SCARG(uap, name), m);
 1275         if (error == 0 && SCARG(uap, val) && valsize && m != NULL) {
 1276                 if (valsize > m->m_len)
 1277                         valsize = m->m_len;
 1278                 error = copyout(mtod(m, caddr_t), SCARG(uap, val), valsize);
 1279                 if (error == 0)
 1280                         error = copyout(&valsize,
 1281                             SCARG(uap, avalsize), sizeof (valsize));
 1282         }
 1283         m_free(m);
 1284 out:
 1285         FRELE(fp, p);
 1286         return (error);
 1287 }
 1288 
 1289 /*
 1290  * Get socket name.
 1291  */
 1292 int
 1293 sys_getsockname(struct proc *p, void *v, register_t *retval)
 1294 {
 1295         struct sys_getsockname_args /* {
 1296                 syscallarg(int) fdes;
 1297                 syscallarg(struct sockaddr *) asa;
 1298                 syscallarg(socklen_t *) alen;
 1299         } */ *uap = v;
 1300         struct file *fp;
 1301         struct socket *so;
 1302         struct mbuf *m = NULL;
 1303         socklen_t len;
 1304         int error;
 1305 
 1306         if ((error = getsock(p, SCARG(uap, fdes), &fp)) != 0)
 1307                 return (error);
 1308         error = copyin(SCARG(uap, alen), &len, sizeof (len));
 1309         if (error)
 1310                 goto bad;
 1311         so = fp->f_data;
 1312         if (so->so_state & SS_YP) {
 1313                 error = ENOTSOCK;
 1314                 goto bad;
 1315         }
 1316         error = pledge_socket(p, -1, so->so_state);
 1317         if (error)
 1318                 goto bad;
 1319         if (so->so_state & SS_YP) {
 1320                 error = ENOTSOCK;
 1321                 goto bad;
 1322         }
 1323         m = m_getclr(M_WAIT, MT_SONAME);
 1324         solock_shared(so);
 1325         error = pru_sockaddr(so, m);
 1326         sounlock_shared(so);
 1327         if (error)
 1328                 goto bad;
 1329         error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen));
 1330 bad:
 1331         FRELE(fp, p);
 1332         m_freem(m);
 1333         return (error);
 1334 }
 1335 
 1336 /*
 1337  * Get name of peer for connected socket.
 1338  */
 1339 int
 1340 sys_getpeername(struct proc *p, void *v, register_t *retval)
 1341 {
 1342         struct sys_getpeername_args /* {
 1343                 syscallarg(int) fdes;
 1344                 syscallarg(struct sockaddr *) asa;
 1345                 syscallarg(socklen_t *) alen;
 1346         } */ *uap = v;
 1347         struct file *fp;
 1348         struct socket *so;
 1349         struct mbuf *m = NULL;
 1350         socklen_t len;
 1351         int error;
 1352 
 1353         if ((error = getsock(p, SCARG(uap, fdes), &fp)) != 0)
 1354                 return (error);
 1355         so = fp->f_data;
 1356         error = pledge_socket(p, -1, so->so_state);
 1357         if (error)
 1358                 goto bad;
 1359         if (so->so_state & SS_YP) {
 1360                 error = ENOTSOCK;
 1361                 goto bad;
 1362         }
 1363         if ((so->so_state & SS_ISCONNECTED) == 0) {
 1364                 error = ENOTCONN;
 1365                 goto bad;
 1366         }
 1367         error = copyin(SCARG(uap, alen), &len, sizeof (len));
 1368         if (error)
 1369                 goto bad;
 1370         m = m_getclr(M_WAIT, MT_SONAME);
 1371         solock_shared(so);
 1372         error = pru_peeraddr(so, m);
 1373         sounlock_shared(so);
 1374         if (error)
 1375                 goto bad;
 1376         error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen));
 1377 bad:
 1378         FRELE(fp, p);
 1379         m_freem(m);
 1380         return (error);
 1381 }
 1382 
 1383 int
 1384 sockargs(struct mbuf **mp, const void *buf, size_t buflen, int type)
 1385 {
 1386         struct sockaddr *sa;
 1387         struct mbuf *m;
 1388         int error;
 1389 
 1390         /*
 1391          * We can't allow socket names > UCHAR_MAX in length, since that
 1392          * will overflow sa_len. Also, control data more than MCLBYTES in
 1393          * length is just too much.
 1394          * Memory for sa_len and sa_family must exist.
 1395          */
 1396         if ((buflen > (type == MT_SONAME ? UCHAR_MAX : MCLBYTES)) ||
 1397             (type == MT_SONAME && buflen < offsetof(struct sockaddr, sa_data)))
 1398                 return (EINVAL);
 1399 
 1400         /* Allocate an mbuf to hold the arguments. */
 1401         m = m_get(M_WAIT, type);
 1402         if (buflen > MLEN) {
 1403                 MCLGET(m, M_WAITOK);
 1404                 if ((m->m_flags & M_EXT) == 0) {
 1405                         m_free(m);
 1406                         return ENOBUFS;
 1407                 }
 1408         }
 1409         m->m_len = buflen;
 1410         error = copyin(buf, mtod(m, caddr_t), buflen);
 1411         if (error) {
 1412                 (void) m_free(m);
 1413                 return (error);
 1414         }
 1415         *mp = m;
 1416         if (type == MT_SONAME) {
 1417                 sa = mtod(m, struct sockaddr *);
 1418                 sa->sa_len = buflen;
 1419         }
 1420         return (0);
 1421 }
 1422 
 1423 int
 1424 getsock(struct proc *p, int fdes, struct file **fpp)
 1425 {
 1426         struct file *fp;
 1427 
 1428         fp = fd_getfile(p->p_fd, fdes);
 1429         if (fp == NULL)
 1430                 return (EBADF);
 1431         if (fp->f_type != DTYPE_SOCKET) {
 1432                 FRELE(fp, p);
 1433                 return (ENOTSOCK);
 1434         }
 1435         *fpp = fp;
 1436 
 1437         return (0);
 1438 }
 1439 
 1440 int
 1441 sys_setrtable(struct proc *p, void *v, register_t *retval)
 1442 {
 1443         struct sys_setrtable_args /* {
 1444                 syscallarg(int) rtableid;
 1445         } */ *uap = v;
 1446         u_int ps_rtableid = p->p_p->ps_rtableid;
 1447         int rtableid, error;
 1448 
 1449         rtableid = SCARG(uap, rtableid);
 1450 
 1451         if (ps_rtableid == rtableid)
 1452                 return (0);
 1453         if (ps_rtableid != 0 && (error = suser(p)) != 0)
 1454                 return (error);
 1455         if (rtableid < 0 || !rtable_exists((u_int)rtableid))
 1456                 return (EINVAL);
 1457 
 1458         p->p_p->ps_rtableid = (u_int)rtableid;
 1459         return (0);
 1460 }
 1461 
 1462 int
 1463 sys_getrtable(struct proc *p, void *v, register_t *retval)
 1464 {
 1465         *retval = (int)p->p_p->ps_rtableid;
 1466         return (0);
 1467 }
 1468 
 1469 int
 1470 copyaddrout(struct proc *p, struct mbuf *name, struct sockaddr *sa,
 1471     socklen_t buflen, socklen_t *outlen)
 1472 {
 1473         int error;
 1474         socklen_t namelen = name->m_len;
 1475 
 1476         /* SHOULD COPY OUT A CHAIN HERE */
 1477         error = copyout(mtod(name, caddr_t), sa, MIN(buflen, namelen));
 1478         if (error == 0) {
 1479 #ifdef KTRACE
 1480                 if (KTRPOINT(p, KTR_STRUCT))
 1481                         ktrsockaddr(p, mtod(name, caddr_t), namelen);
 1482 #endif
 1483                 error = copyout(&namelen, outlen, sizeof(*outlen));
 1484         }
 1485 
 1486         return (error);
 1487 }
 1488 
 1489 #ifndef SMALL_KERNEL
 1490 int
 1491 ypsockargs(struct mbuf **mp, const void *buf, size_t buflen, int type)
 1492 {
 1493         struct sockaddr *sa;
 1494         struct mbuf *m;
 1495 
 1496         /*
 1497          * We can't allow socket names > UCHAR_MAX in length, since that
 1498          * will overflow sa_len. Also, control data more than MCLBYTES in
 1499          * length is just too much.
 1500          * Memory for sa_len and sa_family must exist.
 1501          */
 1502         if ((buflen > (type == MT_SONAME ? UCHAR_MAX : MCLBYTES)) ||
 1503             (type == MT_SONAME && buflen < offsetof(struct sockaddr, sa_data)))
 1504                 return (EINVAL);
 1505 
 1506         /* Allocate an mbuf to hold the arguments. */
 1507         m = m_get(M_WAIT, type);
 1508         if (buflen > MLEN) {
 1509                 MCLGET(m, M_WAITOK);
 1510                 if ((m->m_flags & M_EXT) == 0) {
 1511                         m_free(m);
 1512                         return ENOBUFS;
 1513                 }
 1514         }
 1515         m->m_len = buflen;
 1516         bcopy(buf, mtod(m, caddr_t), buflen);
 1517         *mp = m;
 1518         if (type == MT_SONAME) {
 1519                 sa = mtod(m, struct sockaddr *);
 1520                 sa->sa_len = buflen;
 1521         }
 1522         return (0);
 1523 }
 1524 #endif /* SMALL_KERNEL */
 1525 
 1526 int
 1527 sys_ypconnect(struct proc *p, void *v, register_t *retval)
 1528 {
 1529 #ifdef SMALL_KERNEL
 1530         return EAFNOSUPPORT;
 1531 #else
 1532         struct sys_ypconnect_args /* {
 1533                 syscallarg(int) type;
 1534         } */ *uap = v;
 1535         struct nameidata nid;
 1536         struct vattr va;
 1537         struct uio uio;
 1538         struct iovec iov;
 1539         struct filedesc *fdp = p->p_fd;
 1540         struct socket *so;
 1541         struct file *fp;
 1542         struct flock fl;
 1543         char *name;
 1544         struct mbuf *nam = NULL;
 1545         int error, fd = -1;
 1546         struct ypbinding {
 1547                 u_short ypbind_port;
 1548                 int status;
 1549                 in_addr_t in;
 1550                 u_short ypserv_udp_port;
 1551                 u_short garbage;
 1552                 u_short ypserv_tcp_port;
 1553         } __packed data;
 1554         struct sockaddr_in ypsin;
 1555 
 1556         if (!domainname[0] || strchr(domainname, '/'))
 1557                 return EAFNOSUPPORT;
 1558 
 1559         switch (SCARG(uap, type)) {
 1560         case SOCK_STREAM:
 1561         case SOCK_DGRAM:
 1562                 break;
 1563         default:
 1564                 return EAFNOSUPPORT;
 1565         }
 1566 
 1567         if (p->p_p->ps_flags & PS_CHROOT)
 1568                 return EACCES;
 1569         name = pool_get(&namei_pool, PR_WAITOK);
 1570         snprintf(name, MAXPATHLEN, "/var/yp/binding/%s.2", domainname);
 1571         NDINIT(&nid, 0, NOFOLLOW|LOCKLEAF|KERNELPATH, UIO_SYSSPACE, name, p);
 1572         nid.ni_pledge = PLEDGE_RPATH;
 1573 
 1574         KERNEL_LOCK();
 1575         error = namei(&nid);
 1576         pool_put(&namei_pool, name);
 1577         if (error)
 1578                 goto out;
 1579         error = VOP_GETATTR(nid.ni_vp, &va, p->p_ucred, p);
 1580         if (error)
 1581                 goto verror;
 1582         if (nid.ni_vp->v_type != VREG || va.va_size != sizeof data) {
 1583                 error = EFTYPE;
 1584                 goto verror;
 1585         }
 1586 
 1587         /*
 1588          * Check that a lock is held on the file (hopefully by ypbind),
 1589          * otherwise the file might be old
 1590          */
 1591         fl.l_start = 0;
 1592         fl.l_len = 0;
 1593         fl.l_pid = 0;
 1594         fl.l_type = F_WRLCK;
 1595         fl.l_whence = SEEK_SET;
 1596         error = VOP_ADVLOCK(nid.ni_vp, fdp, F_GETLK, &fl, F_POSIX);
 1597         if (error)
 1598                 goto verror;
 1599         if (fl.l_type == F_UNLCK) {
 1600                 error = EOWNERDEAD;
 1601                 goto verror;
 1602         }
 1603 
 1604         iov.iov_base = &data;
 1605         iov.iov_len = sizeof data;
 1606         uio.uio_iov = &iov;
 1607         uio.uio_iovcnt = 1;
 1608         uio.uio_offset = 0;
 1609         uio.uio_resid = iov.iov_len;
 1610         uio.uio_segflg = UIO_SYSSPACE;
 1611         uio.uio_rw = UIO_READ;
 1612         uio.uio_procp = p;
 1613 
 1614         error = VOP_READ(nid.ni_vp, &uio, 0, p->p_ucred);
 1615         if (error) {
 1616 verror:
 1617                 if (nid.ni_vp)
 1618                         vput(nid.ni_vp);
 1619 out:
 1620                 KERNEL_UNLOCK();
 1621                 return (error);
 1622         }
 1623         vput(nid.ni_vp);
 1624         KERNEL_UNLOCK();
 1625 
 1626         bzero(&ypsin, sizeof ypsin);
 1627         ypsin.sin_len = sizeof ypsin;
 1628         ypsin.sin_family = AF_INET;
 1629         if (SCARG(uap, type) == SOCK_STREAM)
 1630                 ypsin.sin_port = data.ypserv_tcp_port;
 1631         else
 1632                 ypsin.sin_port = data.ypserv_udp_port;
 1633         if (ntohs(ypsin.sin_port) >= IPPORT_RESERVED || ntohs(ypsin.sin_port) == 20)
 1634                 return EPERM;
 1635         memcpy(&ypsin.sin_addr.s_addr, &data.in, sizeof ypsin.sin_addr.s_addr);
 1636 
 1637         error = socreate(AF_INET, &so, SCARG(uap, type), 0);
 1638         if (error)
 1639                 return (error);
 1640 
 1641         error = ypsockargs(&nam, &ypsin, sizeof ypsin, MT_SONAME);
 1642         if (error) {
 1643                 soclose(so, MSG_DONTWAIT);
 1644                 return (error);
 1645         }
 1646 
 1647 #ifdef KTRACE
 1648         if (KTRPOINT(p, KTR_STRUCT))
 1649                 ktrsockaddr(p, mtod(nam, caddr_t), sizeof(struct sockaddr_in));
 1650 #endif
 1651         solock(so);
 1652 
 1653         /* Secure YP maps require reserved ports */
 1654         if (suser(p) == 0)
 1655                 sotoinpcb(so)->inp_flags |= INP_LOWPORT;
 1656 
 1657         error = soconnect(so, nam);
 1658         while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
 1659                 error = sosleep_nsec(so, &so->so_timeo, PSOCK | PCATCH,
 1660                     "netcon2", INFSLP);
 1661                 if (error)
 1662                         break;
 1663         }
 1664         m_freem(nam);
 1665         so->so_state |= SS_YP;          /* impose some restrictions */
 1666         sounlock(so);
 1667         if (error) {
 1668                 soclose(so, MSG_DONTWAIT);
 1669                 return (error);
 1670         }
 1671 
 1672         fdplock(fdp);
 1673         error = falloc(p, &fp, &fd);
 1674         if (error) {
 1675                 fdpunlock(fdp);
 1676                 soclose(so, MSG_DONTWAIT);
 1677                 return (error);
 1678         }
 1679 
 1680         fp->f_flag = FREAD | FWRITE | FNONBLOCK;
 1681         fp->f_type = DTYPE_SOCKET;
 1682         fp->f_ops = &socketops;
 1683         fp->f_data = so;
 1684         fdinsert(fdp, fd, UF_EXCLOSE, fp);
 1685         fdpunlock(fdp);
 1686         FRELE(fp, p);
 1687         *retval = fd;
 1688         return (error);
 1689 #endif /* SMALL_KERNEL */
 1690 }

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.