LCOV - code coverage report
Current view: top level - kern - uipc_syscalls.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 700 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 26 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: uipc_syscalls.c,v 1.178 2018/07/30 12:22:14 mpi 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/fcntl.h>
      40             : #include <sys/file.h>
      41             : #include <sys/ioctl.h>
      42             : #include <sys/malloc.h>
      43             : #include <sys/event.h>
      44             : #include <sys/mbuf.h>
      45             : #include <sys/protosw.h>
      46             : #include <sys/socket.h>
      47             : #include <sys/socketvar.h>
      48             : #include <sys/signalvar.h>
      49             : #include <sys/pledge.h>
      50             : #include <sys/unpcb.h>
      51             : #include <sys/un.h>
      52             : #ifdef KTRACE
      53             : #include <sys/ktrace.h>
      54             : #endif
      55             : 
      56             : #include <sys/mount.h>
      57             : #include <sys/syscallargs.h>
      58             : 
      59             : #include <sys/domain.h>
      60             : #include <netinet/in.h>
      61             : #include <net/route.h>
      62             : 
      63             : /*
      64             :  * System call interface to the socket abstraction.
      65             :  */
      66             : extern  struct fileops socketops;
      67             : 
      68             : int     copyaddrout(struct proc *, struct mbuf *, struct sockaddr *, socklen_t,
      69             :             socklen_t *);
      70             : 
      71             : uint16_t dnsjackport;
      72             : 
      73             : int
      74           0 : sys_socket(struct proc *p, void *v, register_t *retval)
      75             : {
      76             :         struct sys_socket_args /* {
      77             :                 syscallarg(int) domain;
      78             :                 syscallarg(int) type;
      79             :                 syscallarg(int) protocol;
      80           0 :         } */ *uap = v;
      81           0 :         struct filedesc *fdp = p->p_fd;
      82           0 :         struct socket *so;
      83           0 :         struct file *fp;
      84           0 :         int type = SCARG(uap, type);
      85           0 :         int domain = SCARG(uap, domain);
      86           0 :         int fd, cloexec, nonblock, fflag, error;
      87             :         unsigned int ss = 0;
      88             : 
      89           0 :         if ((type & SOCK_DNS) && !(domain == AF_INET || domain == AF_INET6))
      90           0 :                 return (EINVAL);
      91             : 
      92           0 :         if (ISSET(type, SOCK_DNS))
      93           0 :                 ss |= SS_DNS;
      94           0 :         error = pledge_socket(p, domain, ss);
      95           0 :         if (error)
      96           0 :                 return (error);
      97             : 
      98           0 :         type &= ~(SOCK_CLOEXEC | SOCK_NONBLOCK | SOCK_DNS);
      99           0 :         cloexec = (SCARG(uap, type) & SOCK_CLOEXEC) ? UF_EXCLOSE : 0;
     100           0 :         nonblock = SCARG(uap, type) & SOCK_NONBLOCK;
     101           0 :         fflag = FREAD | FWRITE | (nonblock ? FNONBLOCK : 0);
     102             : 
     103           0 :         error = socreate(SCARG(uap, domain), &so, type, SCARG(uap, protocol));
     104           0 :         if (error)
     105           0 :                 return (error);
     106             : 
     107           0 :         KERNEL_LOCK();
     108           0 :         fdplock(fdp);
     109           0 :         error = falloc(p, &fp, &fd);
     110           0 :         if (error) {
     111           0 :                 fdpunlock(fdp);
     112           0 :                 soclose(so, MSG_DONTWAIT);
     113           0 :         } else {
     114           0 :                 fp->f_flag = fflag;
     115           0 :                 fp->f_type = DTYPE_SOCKET;
     116           0 :                 fp->f_ops = &socketops;
     117           0 :                 so->so_state |= ss;
     118           0 :                 fp->f_data = so;
     119           0 :                 fdinsert(fdp, fd, cloexec, fp);
     120           0 :                 fdpunlock(fdp);
     121           0 :                 FRELE(fp, p);
     122           0 :                 *retval = fd;
     123             :         }
     124           0 :         KERNEL_UNLOCK();
     125           0 :         return (error);
     126           0 : }
     127             : 
     128             : static inline int
     129           0 : isdnssocket(struct socket *so)
     130             : {
     131           0 :         return (so->so_state & SS_DNS);
     132             : }
     133             : 
     134             : /* For SS_DNS sockets, only allow port DNS (port 53) */ 
     135             : static int
     136           0 : dns_portcheck(struct proc *p, struct socket *so, void *nam, u_int *namelen)
     137             : {
     138             :         int error = EINVAL;
     139             : 
     140           0 :         switch (so->so_proto->pr_domain->dom_family) {
     141             :         case AF_INET:
     142           0 :                 if (*namelen < sizeof(struct sockaddr_in))
     143             :                         break;
     144           0 :                 if (((struct sockaddr_in *)nam)->sin_port == htons(53))
     145           0 :                         error = 0;
     146           0 :                 if (dnsjackport) {
     147             :                         struct sockaddr_in sin;
     148             :                         memset(&sin, 0, sizeof(sin));
     149             :                         sin.sin_len = sizeof(sin);
     150             :                         sin.sin_family = AF_INET;
     151           0 :                         sin.sin_port = htons(dnsjackport);
     152             :                         sin.sin_addr.s_addr = INADDR_LOOPBACK;
     153           0 :                         memcpy(nam, &sin, sizeof(sin));
     154           0 :                         *namelen = sizeof(sin);
     155           0 :                 }
     156             :                 break;
     157             : #ifdef INET6
     158             :         case AF_INET6:
     159           0 :                 if (*namelen < sizeof(struct sockaddr_in6))
     160             :                         break;
     161           0 :                 if (((struct sockaddr_in6 *)nam)->sin6_port == htons(53))
     162           0 :                         error = 0;
     163           0 :                 if (dnsjackport) {
     164           0 :                         struct sockaddr_in6 sin6;
     165           0 :                         memset(&sin6, 0, sizeof(sin6));
     166             :                         sin6.sin6_len = sizeof(sin6);
     167             :                         sin6.sin6_family = AF_INET6;
     168           0 :                         sin6.sin6_port = htons(dnsjackport);
     169           0 :                         sin6.sin6_addr = in6addr_loopback;
     170           0 :                         memcpy(nam, &sin6, sizeof(sin6));
     171           0 :                         *namelen = sizeof(sin6);
     172           0 :                 }
     173             : #endif
     174             :         }
     175           0 :         if (error && p->p_p->ps_flags & PS_PLEDGE)
     176           0 :                 return (pledge_fail(p, EPERM, PLEDGE_DNS));
     177           0 :         return error;
     178           0 : }
     179             : 
     180             : int
     181           0 : sys_bind(struct proc *p, void *v, register_t *retval)
     182             : {
     183             :         struct sys_bind_args /* {
     184             :                 syscallarg(int) s;
     185             :                 syscallarg(const struct sockaddr *) name;
     186             :                 syscallarg(socklen_t) namelen;
     187           0 :         } */ *uap = v;
     188           0 :         struct file *fp;
     189           0 :         struct mbuf *nam;
     190             :         struct socket *so;
     191             :         int s, error;
     192             : 
     193           0 :         if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
     194           0 :                 return (error);
     195           0 :         so = fp->f_data;
     196           0 :         error = pledge_socket(p, so->so_proto->pr_domain->dom_family,
     197           0 :             so->so_state);
     198           0 :         if (error)
     199             :                 goto out;
     200           0 :         error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
     201             :             MT_SONAME);
     202           0 :         if (error)
     203             :                 goto out;
     204             : #ifdef KTRACE
     205           0 :         if (KTRPOINT(p, KTR_STRUCT))
     206           0 :                 ktrsockaddr(p, mtod(nam, caddr_t), SCARG(uap, namelen));
     207             : #endif
     208           0 :         s = solock(so);
     209           0 :         error = sobind(so, nam, p);
     210           0 :         sounlock(so, s);
     211           0 :         m_freem(nam);
     212             : out:
     213           0 :         FRELE(fp, p);
     214           0 :         return (error);
     215           0 : }
     216             : 
     217             : int
     218           0 : sys_listen(struct proc *p, void *v, register_t *retval)
     219             : {
     220             :         struct sys_listen_args /* {
     221             :                 syscallarg(int) s;
     222             :                 syscallarg(int) backlog;
     223           0 :         } */ *uap = v;
     224           0 :         struct file *fp;
     225             :         struct socket *so;
     226             :         int error;
     227             : 
     228           0 :         if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
     229           0 :                 return (error);
     230           0 :         so = fp->f_data;
     231           0 :         error = solisten(so, SCARG(uap, backlog));
     232           0 :         FRELE(fp, p);
     233           0 :         return (error);
     234           0 : }
     235             : 
     236             : int
     237           0 : sys_accept(struct proc *p, void *v, register_t *retval)
     238             : {
     239             :         struct sys_accept_args /* {
     240             :                 syscallarg(int) s;
     241             :                 syscallarg(struct sockaddr *) name;
     242             :                 syscallarg(socklen_t *) anamelen;
     243           0 :         } */ *uap = v;
     244             : 
     245           0 :         return (doaccept(p, SCARG(uap, s), SCARG(uap, name),
     246           0 :             SCARG(uap, anamelen), SOCK_NONBLOCK_INHERIT, retval));
     247             : }
     248             : 
     249             : int
     250           0 : sys_accept4(struct proc *p, void *v, register_t *retval)
     251             : {
     252             :         struct sys_accept4_args /* {
     253             :                 syscallarg(int) s;
     254             :                 syscallarg(struct sockaddr *) name;
     255             :                 syscallarg(socklen_t *) anamelen;
     256             :                 syscallarg(socklen_t *) int flags;
     257           0 :         } */ *uap = v;
     258             : 
     259           0 :         if (SCARG(uap, flags) & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
     260           0 :                 return (EINVAL);
     261             : 
     262           0 :         return (doaccept(p, SCARG(uap, s), SCARG(uap, name),
     263           0 :             SCARG(uap, anamelen), SCARG(uap, flags), retval));
     264           0 : }
     265             : 
     266             : int
     267           0 : doaccept(struct proc *p, int sock, struct sockaddr *name, socklen_t *anamelen,
     268             :     int flags, register_t *retval)
     269             : {
     270           0 :         struct filedesc *fdp = p->p_fd;
     271           0 :         struct file *fp, *headfp;
     272             :         struct mbuf *nam;
     273           0 :         socklen_t namelen;
     274           0 :         int error, s, tmpfd;
     275             :         struct socket *head, *so;
     276             :         int cloexec, nflag;
     277             : 
     278           0 :         cloexec = (flags & SOCK_CLOEXEC) ? UF_EXCLOSE : 0;
     279             : 
     280           0 :         if (name && (error = copyin(anamelen, &namelen, sizeof (namelen))))
     281           0 :                 return (error);
     282           0 :         if ((error = getsock(p, sock, &fp)) != 0)
     283           0 :                 return (error);
     284             : 
     285           0 :         headfp = fp;
     286             : 
     287           0 :         fdplock(fdp);
     288           0 :         error = falloc(p, &fp, &tmpfd);
     289           0 :         fdpunlock(fdp);
     290           0 :         if (error) {
     291           0 :                 FRELE(headfp, p);
     292           0 :                 return (error);
     293             :         }
     294             : 
     295           0 :         nam = m_get(M_WAIT, MT_SONAME);
     296             : 
     297           0 :         head = headfp->f_data;
     298           0 :         s = solock(head);
     299           0 :         if (isdnssocket(head) || (head->so_options & SO_ACCEPTCONN) == 0) {
     300             :                 error = EINVAL;
     301           0 :                 goto out;
     302             :         }
     303           0 :         if ((headfp->f_flag & FNONBLOCK) && head->so_qlen == 0) {
     304           0 :                 if (head->so_state & SS_CANTRCVMORE)
     305           0 :                         error = ECONNABORTED;
     306             :                 else
     307             :                         error = EWOULDBLOCK;
     308             :                 goto out;
     309             :         }
     310           0 :         while (head->so_qlen == 0 && head->so_error == 0) {
     311           0 :                 if (head->so_state & SS_CANTRCVMORE) {
     312           0 :                         head->so_error = ECONNABORTED;
     313           0 :                         break;
     314             :                 }
     315           0 :                 error = sosleep(head, &head->so_timeo, PSOCK | PCATCH, "netcon",
     316             :                     0);
     317           0 :                 if (error)
     318             :                         goto out;
     319             :         }
     320           0 :         if (head->so_error) {
     321             :                 error = head->so_error;
     322           0 :                 head->so_error = 0;
     323           0 :                 goto out;
     324             :         }
     325             : 
     326             :         /*
     327             :          * Do not sleep after we have taken the socket out of the queue.
     328             :          */
     329           0 :         so = TAILQ_FIRST(&head->so_q);
     330           0 :         if (soqremque(so, 1) == 0)
     331           0 :                 panic("accept");
     332             : 
     333             :         /* Figure out whether the new socket should be non-blocking. */
     334           0 :         nflag = flags & SOCK_NONBLOCK_INHERIT ? (headfp->f_flag & FNONBLOCK)
     335           0 :             : (flags & SOCK_NONBLOCK ? FNONBLOCK : 0);
     336             : 
     337             :         /* connection has been removed from the listen queue */
     338           0 :         KNOTE(&head->so_rcv.sb_sel.si_note, NOTE_SUBMIT);
     339             : 
     340           0 :         fp->f_type = DTYPE_SOCKET;
     341           0 :         fp->f_flag = FREAD | FWRITE | nflag;
     342           0 :         fp->f_ops = &socketops;
     343           0 :         error = soaccept(so, nam);
     344           0 :         if (!error && name != NULL)
     345           0 :                 error = copyaddrout(p, nam, name, namelen, anamelen);
     346             : out:
     347           0 :         if (!error) {
     348             :                 sounlock(head, s);
     349           0 :                 fdplock(fdp);
     350           0 :                 fp->f_data = so;
     351           0 :                 fdinsert(fdp, tmpfd, cloexec, fp);
     352           0 :                 fdpunlock(fdp);
     353           0 :                 FRELE(fp, p);
     354           0 :                 *retval = tmpfd;
     355           0 :         } else {
     356             :                 sounlock(head, s);
     357           0 :                 fdplock(fdp);
     358           0 :                 fdremove(fdp, tmpfd);
     359           0 :                 closef(fp, p);
     360           0 :                 fdpunlock(fdp);
     361             :         }
     362             : 
     363           0 :         m_freem(nam);
     364           0 :         FRELE(headfp, p);
     365           0 :         return (error);
     366           0 : }
     367             : 
     368             : int
     369           0 : sys_connect(struct proc *p, void *v, register_t *retval)
     370             : {
     371             :         struct sys_connect_args /* {
     372             :                 syscallarg(int) s;
     373             :                 syscallarg(const struct sockaddr *) name;
     374             :                 syscallarg(socklen_t) namelen;
     375           0 :         } */ *uap = v;
     376           0 :         struct file *fp;
     377             :         struct socket *so;
     378           0 :         struct mbuf *nam = NULL;
     379             :         int error, s, interrupted = 0;
     380             : 
     381           0 :         if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
     382           0 :                 return (error);
     383           0 :         so = fp->f_data;
     384           0 :         s = solock(so);
     385           0 :         if (so->so_state & SS_ISCONNECTING) {
     386             :                 error = EALREADY;
     387           0 :                 goto out;
     388             :         }
     389           0 :         error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
     390             :             MT_SONAME);
     391           0 :         if (error)
     392             :                 goto out;
     393           0 :         error = pledge_socket(p, so->so_proto->pr_domain->dom_family,
     394           0 :             so->so_state);
     395           0 :         if (error)
     396             :                 goto out;
     397             : #ifdef KTRACE
     398           0 :         if (KTRPOINT(p, KTR_STRUCT))
     399           0 :                 ktrsockaddr(p, mtod(nam, caddr_t), SCARG(uap, namelen));
     400             : #endif
     401             : 
     402           0 :         if (isdnssocket(so)) {
     403           0 :                 u_int namelen = nam->m_len;
     404           0 :                 error = dns_portcheck(p, so, mtod(nam, void *), &namelen);
     405           0 :                 if (error)
     406           0 :                         goto out;
     407           0 :                 nam->m_len = namelen;
     408           0 :         }
     409             : 
     410           0 :         error = soconnect(so, nam);
     411           0 :         if (error)
     412             :                 goto bad;
     413           0 :         if ((fp->f_flag & FNONBLOCK) && (so->so_state & SS_ISCONNECTING)) {
     414             :                 error = EINPROGRESS;
     415           0 :                 goto out;
     416             :         }
     417           0 :         while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
     418           0 :                 error = sosleep(so, &so->so_timeo, PSOCK | PCATCH,
     419             :                     "netcon2", 0);
     420           0 :                 if (error) {
     421           0 :                         if (error == EINTR || error == ERESTART)
     422           0 :                                 interrupted = 1;
     423             :                         break;
     424             :                 }
     425             :         }
     426           0 :         if (error == 0) {
     427           0 :                 error = so->so_error;
     428           0 :                 so->so_error = 0;
     429           0 :         }
     430             : bad:
     431           0 :         if (!interrupted)
     432           0 :                 so->so_state &= ~SS_ISCONNECTING;
     433             : out:
     434           0 :         sounlock(so, s);
     435           0 :         FRELE(fp, p);
     436           0 :         m_freem(nam);
     437           0 :         if (error == ERESTART)
     438           0 :                 error = EINTR;
     439           0 :         return (error);
     440           0 : }
     441             : 
     442             : int
     443           0 : sys_socketpair(struct proc *p, void *v, register_t *retval)
     444             : {
     445             :         struct sys_socketpair_args /* {
     446             :                 syscallarg(int) domain;
     447             :                 syscallarg(int) type;
     448             :                 syscallarg(int) protocol;
     449             :                 syscallarg(int *) rsv;
     450           0 :         } */ *uap = v;
     451           0 :         struct filedesc *fdp = p->p_fd;
     452           0 :         struct file *fp1, *fp2;
     453           0 :         struct socket *so1, *so2;
     454           0 :         int type, cloexec, nonblock, fflag, error, sv[2];
     455             : 
     456           0 :         type  = SCARG(uap, type) & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
     457           0 :         cloexec = (SCARG(uap, type) & SOCK_CLOEXEC) ? UF_EXCLOSE : 0;
     458           0 :         nonblock = SCARG(uap, type) & SOCK_NONBLOCK;
     459           0 :         fflag = FREAD | FWRITE | (nonblock ? FNONBLOCK : 0);
     460             : 
     461           0 :         error = socreate(SCARG(uap, domain), &so1, type, SCARG(uap, protocol));
     462           0 :         if (error)
     463           0 :                 return (error);
     464           0 :         error = socreate(SCARG(uap, domain), &so2, type, SCARG(uap, protocol));
     465           0 :         if (error)
     466             :                 goto free1;
     467             : 
     468           0 :         error = soconnect2(so1, so2);
     469           0 :         if (error != 0)
     470             :                 goto free2;
     471             : 
     472           0 :         if ((SCARG(uap, type) & SOCK_TYPE_MASK) == SOCK_DGRAM) {
     473             :                 /*
     474             :                  * Datagram socket connection is asymmetric.
     475             :                  */
     476           0 :                 error = soconnect2(so2, so1);
     477           0 :                 if (error != 0)
     478             :                         goto free2;
     479             :         }
     480           0 :         KERNEL_LOCK();
     481           0 :         fdplock(fdp);
     482           0 :         if ((error = falloc(p, &fp1, &sv[0])) != 0)
     483             :                 goto free3;
     484           0 :         fp1->f_flag = fflag;
     485           0 :         fp1->f_type = DTYPE_SOCKET;
     486           0 :         fp1->f_ops = &socketops;
     487           0 :         fp1->f_data = so1;
     488           0 :         if ((error = falloc(p, &fp2, &sv[1])) != 0)
     489             :                 goto free4;
     490           0 :         fp2->f_flag = fflag;
     491           0 :         fp2->f_type = DTYPE_SOCKET;
     492           0 :         fp2->f_ops = &socketops;
     493           0 :         fp2->f_data = so2;
     494           0 :         error = copyout(sv, SCARG(uap, rsv), 2 * sizeof (int));
     495           0 :         if (error == 0) {
     496             : #ifdef KTRACE
     497           0 :                 if (KTRPOINT(p, KTR_STRUCT))
     498           0 :                         ktrfds(p, sv, 2);
     499             : #endif
     500           0 :                 fdinsert(fdp, sv[0], cloexec, fp1);
     501           0 :                 fdinsert(fdp, sv[1], cloexec, fp2);
     502           0 :                 fdpunlock(fdp);
     503           0 :                 FRELE(fp1, p);
     504           0 :                 FRELE(fp2, p);
     505           0 :                 KERNEL_UNLOCK();
     506           0 :                 return (0);
     507             :         }
     508           0 :         fdremove(fdp, sv[1]);
     509           0 :         closef(fp2, p);
     510           0 :         so2 = NULL;
     511             : free4:
     512           0 :         fdremove(fdp, sv[0]);
     513           0 :         closef(fp1, p);
     514           0 :         so1 = NULL;
     515             : free3:
     516           0 :         fdpunlock(fdp);
     517           0 :         KERNEL_UNLOCK();
     518             : free2:
     519           0 :         if (so2 != NULL)
     520           0 :                 (void)soclose(so2, 0);
     521             : free1:
     522           0 :         if (so1 != NULL)
     523           0 :                 (void)soclose(so1, 0);
     524           0 :         return (error);
     525           0 : }
     526             : 
     527             : int
     528           0 : sys_sendto(struct proc *p, void *v, register_t *retval)
     529             : {
     530             :         struct sys_sendto_args /* {
     531             :                 syscallarg(int) s;
     532             :                 syscallarg(const void *) buf;
     533             :                 syscallarg(size_t) len;
     534             :                 syscallarg(int) flags;
     535             :                 syscallarg(const struct sockaddr *) to;
     536             :                 syscallarg(socklen_t) tolen;
     537           0 :         } */ *uap = v;
     538           0 :         struct msghdr msg;
     539           0 :         struct iovec aiov;
     540             : 
     541           0 :         msg.msg_name = (caddr_t)SCARG(uap, to);
     542           0 :         msg.msg_namelen = SCARG(uap, tolen);
     543           0 :         msg.msg_iov = &aiov;
     544           0 :         msg.msg_iovlen = 1;
     545           0 :         msg.msg_control = 0;
     546           0 :         msg.msg_flags = 0;
     547           0 :         aiov.iov_base = (char *)SCARG(uap, buf);
     548           0 :         aiov.iov_len = SCARG(uap, len);
     549           0 :         return (sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval));
     550           0 : }
     551             : 
     552             : int
     553           0 : sys_sendmsg(struct proc *p, void *v, register_t *retval)
     554             : {
     555             :         struct sys_sendmsg_args /* {
     556             :                 syscallarg(int) s;
     557             :                 syscallarg(const struct msghdr *) msg;
     558             :                 syscallarg(int) flags;
     559           0 :         } */ *uap = v;
     560           0 :         struct msghdr msg;
     561           0 :         struct iovec aiov[UIO_SMALLIOV], *iov;
     562             :         int error;
     563             : 
     564           0 :         error = copyin(SCARG(uap, msg), &msg, sizeof (msg));
     565           0 :         if (error)
     566           0 :                 return (error);
     567             : #ifdef KTRACE
     568           0 :         if (KTRPOINT(p, KTR_STRUCT))
     569           0 :                 ktrmsghdr(p, &msg);
     570             : #endif
     571             : 
     572           0 :         if (msg.msg_iovlen > IOV_MAX)
     573           0 :                 return (EMSGSIZE);
     574           0 :         if (msg.msg_iovlen > UIO_SMALLIOV)
     575           0 :                 iov = mallocarray(msg.msg_iovlen, sizeof(struct iovec),
     576             :                     M_IOV, M_WAITOK);
     577             :         else
     578           0 :                 iov = aiov;
     579           0 :         if (msg.msg_iovlen &&
     580           0 :             (error = copyin(msg.msg_iov, iov,
     581           0 :                     (unsigned)(msg.msg_iovlen * sizeof (struct iovec)))))
     582             :                 goto done;
     583             : #ifdef KTRACE
     584           0 :         if (msg.msg_iovlen && KTRPOINT(p, KTR_STRUCT))
     585           0 :                 ktriovec(p, iov, msg.msg_iovlen);
     586             : #endif
     587           0 :         msg.msg_iov = iov;
     588           0 :         msg.msg_flags = 0;
     589           0 :         error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
     590             : done:
     591           0 :         if (iov != aiov)
     592           0 :                 free(iov, M_IOV, sizeof(struct iovec) * msg.msg_iovlen);
     593           0 :         return (error);
     594           0 : }
     595             : 
     596             : int
     597           0 : sendit(struct proc *p, int s, struct msghdr *mp, int flags, register_t *retsize)
     598             : {
     599           0 :         struct file *fp;
     600           0 :         struct uio auio;
     601             :         struct iovec *iov;
     602             :         int i;
     603           0 :         struct mbuf *to, *control;
     604             :         struct socket *so;
     605             :         size_t len;
     606             :         int error;
     607             : #ifdef KTRACE
     608             :         struct iovec *ktriov = NULL;
     609             :         int iovlen = 0;
     610             : #endif
     611             : 
     612           0 :         to = NULL;
     613             : 
     614           0 :         if ((error = getsock(p, s, &fp)) != 0)
     615           0 :                 return (error);
     616           0 :         so = fp->f_data;
     617           0 :         if (fp->f_flag & FNONBLOCK)
     618           0 :                 flags |= MSG_DONTWAIT;
     619             : 
     620           0 :         error = pledge_sendit(p, mp->msg_name);
     621           0 :         if (error)
     622             :                 goto bad;
     623             : 
     624           0 :         auio.uio_iov = mp->msg_iov;
     625           0 :         auio.uio_iovcnt = mp->msg_iovlen;
     626           0 :         auio.uio_segflg = UIO_USERSPACE;
     627           0 :         auio.uio_rw = UIO_WRITE;
     628           0 :         auio.uio_procp = p;
     629           0 :         auio.uio_offset = 0;                    /* XXX */
     630           0 :         auio.uio_resid = 0;
     631           0 :         iov = mp->msg_iov;
     632           0 :         for (i = 0; i < mp->msg_iovlen; i++, iov++) {
     633             :                 /* Don't allow sum > SSIZE_MAX */
     634           0 :                 if (iov->iov_len > SSIZE_MAX ||
     635           0 :                     (auio.uio_resid += iov->iov_len) > SSIZE_MAX) {
     636             :                         error = EINVAL;
     637           0 :                         goto bad;
     638             :                 }
     639             :         }
     640           0 :         if (mp->msg_name) {
     641           0 :                 error = sockargs(&to, mp->msg_name, mp->msg_namelen,
     642             :                     MT_SONAME);
     643           0 :                 if (error)
     644             :                         goto bad;
     645           0 :                 if (isdnssocket(so)) {
     646           0 :                         u_int namelen = mp->msg_namelen;
     647           0 :                         error = dns_portcheck(p, so, mtod(to, caddr_t),
     648             :                             &namelen);
     649           0 :                         if (error)
     650           0 :                                 goto bad;
     651           0 :                         mp->msg_namelen = namelen;
     652           0 :                 }
     653             : #ifdef KTRACE
     654           0 :                 if (KTRPOINT(p, KTR_STRUCT))
     655           0 :                         ktrsockaddr(p, mtod(to, caddr_t), mp->msg_namelen);
     656             : #endif
     657             :         }
     658           0 :         if (mp->msg_control) {
     659           0 :                 if (mp->msg_controllen < CMSG_ALIGN(sizeof(struct cmsghdr))) {
     660             :                         error = EINVAL;
     661           0 :                         goto bad;
     662             :                 }
     663           0 :                 error = sockargs(&control, mp->msg_control,
     664             :                     mp->msg_controllen, MT_CONTROL);
     665           0 :                 if (error)
     666             :                         goto bad;
     667             : #ifdef KTRACE
     668           0 :                 if (KTRPOINT(p, KTR_STRUCT) && mp->msg_controllen)
     669           0 :                         ktrcmsghdr(p, mtod(control, char *),
     670             :                             mp->msg_controllen);
     671             : #endif
     672             :         } else
     673           0 :                 control = 0;
     674             : #ifdef KTRACE
     675           0 :         if (KTRPOINT(p, KTR_GENIO)) {
     676           0 :                 ktriov = mallocarray(auio.uio_iovcnt, sizeof(struct iovec),
     677             :                     M_TEMP, M_WAITOK);
     678           0 :                 iovlen = auio.uio_iovcnt * sizeof (struct iovec);
     679             : 
     680           0 :                 memcpy(ktriov, auio.uio_iov, iovlen);
     681           0 :         }
     682             : #endif
     683           0 :         len = auio.uio_resid;
     684           0 :         error = sosend(so, to, &auio, NULL, control, flags);
     685           0 :         if (error) {
     686           0 :                 if (auio.uio_resid != len && (error == ERESTART ||
     687           0 :                     error == EINTR || error == EWOULDBLOCK))
     688           0 :                         error = 0;
     689           0 :                 if (error == EPIPE && (flags & MSG_NOSIGNAL) == 0) {
     690           0 :                         KERNEL_LOCK();
     691           0 :                         ptsignal(p, SIGPIPE, STHREAD);
     692           0 :                         KERNEL_UNLOCK();
     693           0 :                 }
     694             :         }
     695           0 :         if (error == 0) {
     696           0 :                 *retsize = len - auio.uio_resid;
     697           0 :                 mtx_enter(&fp->f_mtx);
     698           0 :                 fp->f_wxfer++;
     699           0 :                 fp->f_wbytes += *retsize;
     700           0 :                 mtx_leave(&fp->f_mtx);
     701           0 :         }
     702             : #ifdef KTRACE
     703           0 :         if (ktriov != NULL) {
     704           0 :                 if (error == 0)
     705           0 :                         ktrgenio(p, s, UIO_WRITE, ktriov, *retsize);
     706           0 :                 free(ktriov, M_TEMP, iovlen);
     707           0 :         }
     708             : #endif
     709             : bad:
     710           0 :         FRELE(fp, p);
     711           0 :         m_freem(to);
     712           0 :         return (error);
     713           0 : }
     714             : 
     715             : int
     716           0 : sys_recvfrom(struct proc *p, void *v, register_t *retval)
     717             : {
     718             :         struct sys_recvfrom_args /* {
     719             :                 syscallarg(int) s;
     720             :                 syscallarg(void *) buf;
     721             :                 syscallarg(size_t) len;
     722             :                 syscallarg(int) flags;
     723             :                 syscallarg(struct sockaddr *) from;
     724             :                 syscallarg(socklen_t *) fromlenaddr;
     725           0 :         } */ *uap = v;
     726           0 :         struct msghdr msg;
     727           0 :         struct iovec aiov;
     728             :         int error;
     729             : 
     730           0 :         if (SCARG(uap, fromlenaddr)) {
     731           0 :                 error = copyin(SCARG(uap, fromlenaddr),
     732           0 :                     &msg.msg_namelen, sizeof (msg.msg_namelen));
     733           0 :                 if (error)
     734           0 :                         return (error);
     735             :         } else
     736           0 :                 msg.msg_namelen = 0;
     737           0 :         msg.msg_name = (caddr_t)SCARG(uap, from);
     738           0 :         msg.msg_iov = &aiov;
     739           0 :         msg.msg_iovlen = 1;
     740           0 :         aiov.iov_base = SCARG(uap, buf);
     741           0 :         aiov.iov_len = SCARG(uap, len);
     742           0 :         msg.msg_control = 0;
     743           0 :         msg.msg_flags = SCARG(uap, flags);
     744           0 :         return (recvit(p, SCARG(uap, s), &msg,
     745           0 :             (caddr_t)SCARG(uap, fromlenaddr), retval));
     746           0 : }
     747             : 
     748             : int
     749           0 : sys_recvmsg(struct proc *p, void *v, register_t *retval)
     750             : {
     751             :         struct sys_recvmsg_args /* {
     752             :                 syscallarg(int) s;
     753             :                 syscallarg(struct msghdr *) msg;
     754             :                 syscallarg(int) flags;
     755           0 :         } */ *uap = v;
     756           0 :         struct msghdr msg;
     757           0 :         struct iovec aiov[UIO_SMALLIOV], *uiov, *iov;
     758             :         int error;
     759             : 
     760           0 :         error = copyin(SCARG(uap, msg), &msg, sizeof (msg));
     761           0 :         if (error)
     762           0 :                 return (error);
     763             : 
     764           0 :         if (msg.msg_iovlen > IOV_MAX)
     765           0 :                 return (EMSGSIZE);
     766           0 :         if (msg.msg_iovlen > UIO_SMALLIOV)
     767           0 :                 iov = mallocarray(msg.msg_iovlen, sizeof(struct iovec),
     768             :                     M_IOV, M_WAITOK);
     769             :         else
     770           0 :                 iov = aiov;
     771           0 :         msg.msg_flags = SCARG(uap, flags);
     772           0 :         if (msg.msg_iovlen > 0) {
     773           0 :                 error = copyin(msg.msg_iov, iov,
     774           0 :                     msg.msg_iovlen * sizeof(struct iovec));
     775           0 :                 if (error)
     776             :                         goto done;
     777             :         }
     778           0 :         uiov = msg.msg_iov;
     779           0 :         msg.msg_iov = iov;
     780           0 :         if ((error = recvit(p, SCARG(uap, s), &msg, NULL, retval)) == 0) {
     781           0 :                 msg.msg_iov = uiov;
     782             : #ifdef KTRACE
     783           0 :                 if (KTRPOINT(p, KTR_STRUCT)) {
     784           0 :                         ktrmsghdr(p, &msg);
     785           0 :                         if (msg.msg_iovlen)
     786           0 :                                 ktriovec(p, iov, msg.msg_iovlen);
     787             :                 }
     788             : #endif
     789           0 :                 error = copyout(&msg, SCARG(uap, msg), sizeof(msg));
     790           0 :         }
     791             : done:
     792           0 :         if (iov != aiov)
     793           0 :                 free(iov, M_IOV, sizeof(struct iovec) * msg.msg_iovlen);
     794           0 :         return (error);
     795           0 : }
     796             : 
     797             : int
     798           0 : recvit(struct proc *p, int s, struct msghdr *mp, caddr_t namelenp,
     799             :     register_t *retsize)
     800             : {
     801           0 :         struct file *fp;
     802           0 :         struct uio auio;
     803             :         struct iovec *iov;
     804             :         int i;
     805             :         size_t len;
     806             :         int error;
     807           0 :         struct mbuf *from = NULL, *control = NULL;
     808             : #ifdef KTRACE
     809             :         struct iovec *ktriov = NULL;
     810             :         int iovlen = 0;
     811             : #endif
     812             : 
     813           0 :         if ((error = getsock(p, s, &fp)) != 0)
     814           0 :                 return (error);
     815             : 
     816           0 :         auio.uio_iov = mp->msg_iov;
     817           0 :         auio.uio_iovcnt = mp->msg_iovlen;
     818           0 :         auio.uio_segflg = UIO_USERSPACE;
     819           0 :         auio.uio_rw = UIO_READ;
     820           0 :         auio.uio_procp = p;
     821           0 :         auio.uio_offset = 0;                    /* XXX */
     822           0 :         auio.uio_resid = 0;
     823           0 :         iov = mp->msg_iov;
     824           0 :         for (i = 0; i < mp->msg_iovlen; i++, iov++) {
     825             :                 /* Don't allow sum > SSIZE_MAX */
     826           0 :                 if (iov->iov_len > SSIZE_MAX ||
     827           0 :                     (auio.uio_resid += iov->iov_len) > SSIZE_MAX) {
     828             :                         error = EINVAL;
     829           0 :                         goto out;
     830             :                 }
     831             :         }
     832             : #ifdef KTRACE
     833           0 :         if (KTRPOINT(p, KTR_GENIO)) {
     834           0 :                 ktriov = mallocarray(auio.uio_iovcnt, sizeof(struct iovec),
     835             :                     M_TEMP, M_WAITOK);
     836           0 :                 iovlen = auio.uio_iovcnt * sizeof (struct iovec);
     837             : 
     838           0 :                 memcpy(ktriov, auio.uio_iov, iovlen);
     839           0 :         }
     840             : #endif
     841           0 :         len = auio.uio_resid;
     842           0 :         if (fp->f_flag & FNONBLOCK)
     843           0 :                 mp->msg_flags |= MSG_DONTWAIT;
     844           0 :         error = soreceive(fp->f_data, &from, &auio, NULL,
     845           0 :                           mp->msg_control ? &control : NULL,
     846           0 :                           &mp->msg_flags,
     847           0 :                           mp->msg_control ? mp->msg_controllen : 0);
     848           0 :         if (error) {
     849           0 :                 if (auio.uio_resid != len && (error == ERESTART ||
     850           0 :                     error == EINTR || error == EWOULDBLOCK))
     851           0 :                         error = 0;
     852             :         }
     853             : #ifdef KTRACE
     854           0 :         if (ktriov != NULL) {
     855           0 :                 if (error == 0)
     856           0 :                         ktrgenio(p, s, UIO_READ, ktriov, len - auio.uio_resid);
     857           0 :                 free(ktriov, M_TEMP, iovlen);
     858           0 :         }
     859             : #endif
     860           0 :         if (error)
     861             :                 goto out;
     862           0 :         *retsize = len - auio.uio_resid;
     863           0 :         if (mp->msg_name) {
     864           0 :                 socklen_t alen;
     865             : 
     866           0 :                 if (from == NULL)
     867           0 :                         alen = 0;
     868             :                 else {
     869           0 :                         alen = from->m_len;
     870           0 :                         error = copyout(mtod(from, caddr_t), mp->msg_name,
     871           0 :                             MIN(alen, mp->msg_namelen));
     872           0 :                         if (error)
     873           0 :                                 goto out;
     874             : #ifdef KTRACE
     875           0 :                         if (KTRPOINT(p, KTR_STRUCT))
     876           0 :                                 ktrsockaddr(p, mtod(from, caddr_t), alen);
     877             : #endif
     878             :                 }
     879           0 :                 mp->msg_namelen = alen;
     880           0 :                 if (namelenp &&
     881           0 :                     (error = copyout(&alen, namelenp, sizeof(alen)))) {
     882           0 :                         goto out;
     883             :                 }
     884           0 :         }
     885           0 :         if (mp->msg_control) {
     886           0 :                 len = mp->msg_controllen;
     887           0 :                 if (len <= 0 || control == NULL)
     888           0 :                         len = 0;
     889             :                 else {
     890             :                         struct mbuf *m = control;
     891             :                         caddr_t cp = mp->msg_control;
     892             : 
     893           0 :                         do {
     894           0 :                                 i = m->m_len;
     895           0 :                                 if (len < i) {
     896           0 :                                         mp->msg_flags |= MSG_CTRUNC;
     897           0 :                                         i = len;
     898           0 :                                 }
     899           0 :                                 error = copyout(mtod(m, caddr_t), cp, i);
     900             : #ifdef KTRACE
     901           0 :                                 if (KTRPOINT(p, KTR_STRUCT) && error == 0 && i)
     902           0 :                                         ktrcmsghdr(p, mtod(m, char *), i);
     903             : #endif
     904           0 :                                 if (m->m_next)
     905           0 :                                         i = ALIGN(i);
     906           0 :                                 cp += i;
     907           0 :                                 len -= i;
     908           0 :                                 if (error != 0 || len <= 0)
     909             :                                         break;
     910           0 :                         } while ((m = m->m_next) != NULL);
     911           0 :                         len = cp - (caddr_t)mp->msg_control;
     912             :                 }
     913           0 :                 mp->msg_controllen = len;
     914           0 :         }
     915           0 :         if (!error) {
     916           0 :                 mtx_enter(&fp->f_mtx);
     917           0 :                 fp->f_rxfer++;
     918           0 :                 fp->f_rbytes += *retsize;
     919           0 :                 mtx_leave(&fp->f_mtx);
     920           0 :         }
     921             : out:
     922           0 :         FRELE(fp, p);
     923           0 :         m_freem(from);
     924           0 :         m_freem(control);
     925           0 :         return (error);
     926           0 : }
     927             : 
     928             : int
     929           0 : sys_shutdown(struct proc *p, void *v, register_t *retval)
     930             : {
     931             :         struct sys_shutdown_args /* {
     932             :                 syscallarg(int) s;
     933             :                 syscallarg(int) how;
     934           0 :         } */ *uap = v;
     935           0 :         struct file *fp;
     936             :         int error;
     937             : 
     938           0 :         if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
     939           0 :                 return (error);
     940           0 :         error = soshutdown(fp->f_data, SCARG(uap, how));
     941           0 :         FRELE(fp, p);
     942           0 :         return (error);
     943           0 : }
     944             : 
     945             : int
     946           0 : sys_setsockopt(struct proc *p, void *v, register_t *retval)
     947             : {
     948             :         struct sys_setsockopt_args /* {
     949             :                 syscallarg(int) s;
     950             :                 syscallarg(int) level;
     951             :                 syscallarg(int) name;
     952             :                 syscallarg(const void *) val;
     953             :                 syscallarg(socklen_t) valsize;
     954           0 :         } */ *uap = v;
     955           0 :         struct file *fp;
     956             :         struct mbuf *m = NULL;
     957             :         struct socket *so;
     958             :         int s, error;
     959             : 
     960             : 
     961           0 :         if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
     962           0 :                 return (error);
     963           0 :         error = pledge_sockopt(p, 1, SCARG(uap, level), SCARG(uap, name));
     964           0 :         if (error)
     965             :                 goto bad;
     966           0 :         if (SCARG(uap, valsize) > MCLBYTES) {
     967             :                 error = EINVAL;
     968           0 :                 goto bad;
     969             :         }
     970           0 :         if (SCARG(uap, val)) {
     971           0 :                 m = m_get(M_WAIT, MT_SOOPTS);
     972           0 :                 if (SCARG(uap, valsize) > MLEN) {
     973           0 :                         MCLGET(m, M_DONTWAIT);
     974           0 :                         if ((m->m_flags & M_EXT) == 0) {
     975             :                                 error = ENOBUFS;
     976           0 :                                 goto bad;
     977             :                         }
     978             :                 }
     979           0 :                 if (m == NULL) {
     980             :                         error = ENOBUFS;
     981           0 :                         goto bad;
     982             :                 }
     983           0 :                 error = copyin(SCARG(uap, val), mtod(m, caddr_t),
     984           0 :                     SCARG(uap, valsize));
     985           0 :                 if (error) {
     986             :                         goto bad;
     987             :                 }
     988           0 :                 m->m_len = SCARG(uap, valsize);
     989           0 :         }
     990           0 :         so = fp->f_data;
     991           0 :         s = solock(so);
     992           0 :         error = sosetopt(so, SCARG(uap, level), SCARG(uap, name), m);
     993           0 :         sounlock(so, s);
     994             : bad:
     995           0 :         m_freem(m);
     996           0 :         FRELE(fp, p);
     997           0 :         return (error);
     998           0 : }
     999             : 
    1000             : int
    1001           0 : sys_getsockopt(struct proc *p, void *v, register_t *retval)
    1002             : {
    1003             :         struct sys_getsockopt_args /* {
    1004             :                 syscallarg(int) s;
    1005             :                 syscallarg(int) level;
    1006             :                 syscallarg(int) name;
    1007             :                 syscallarg(void *) val;
    1008             :                 syscallarg(socklen_t *) avalsize;
    1009           0 :         } */ *uap = v;
    1010           0 :         struct file *fp;
    1011             :         struct mbuf *m = NULL;
    1012           0 :         socklen_t valsize;
    1013             :         struct socket *so;
    1014             :         int s, error;
    1015             : 
    1016           0 :         if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
    1017           0 :                 return (error);
    1018           0 :         error = pledge_sockopt(p, 0, SCARG(uap, level), SCARG(uap, name));
    1019           0 :         if (error)
    1020             :                 goto out;
    1021           0 :         if (SCARG(uap, val)) {
    1022           0 :                 error = copyin(SCARG(uap, avalsize),
    1023             :                     &valsize, sizeof (valsize));
    1024           0 :                 if (error)
    1025             :                         goto out;
    1026             :         } else
    1027           0 :                 valsize = 0;
    1028           0 :         m = m_get(M_WAIT, MT_SOOPTS);
    1029           0 :         so = fp->f_data;
    1030           0 :         s = solock(so);
    1031           0 :         error = sogetopt(so, SCARG(uap, level), SCARG(uap, name), m);
    1032           0 :         sounlock(so, s);
    1033           0 :         if (error == 0 && SCARG(uap, val) && valsize && m != NULL) {
    1034           0 :                 if (valsize > m->m_len)
    1035           0 :                         valsize = m->m_len;
    1036           0 :                 error = copyout(mtod(m, caddr_t), SCARG(uap, val), valsize);
    1037           0 :                 if (error == 0)
    1038           0 :                         error = copyout(&valsize,
    1039           0 :                             SCARG(uap, avalsize), sizeof (valsize));
    1040             :         }
    1041           0 :         m_free(m);
    1042             : out:
    1043           0 :         FRELE(fp, p);
    1044           0 :         return (error);
    1045           0 : }
    1046             : 
    1047             : /*
    1048             :  * Get socket name.
    1049             :  */
    1050             : int
    1051           0 : sys_getsockname(struct proc *p, void *v, register_t *retval)
    1052             : {
    1053             :         struct sys_getsockname_args /* {
    1054             :                 syscallarg(int) fdes;
    1055             :                 syscallarg(struct sockaddr *) asa;
    1056             :                 syscallarg(socklen_t *) alen;
    1057           0 :         } */ *uap = v;
    1058           0 :         struct file *fp;
    1059             :         struct socket *so;
    1060             :         struct mbuf *m = NULL;
    1061           0 :         socklen_t len;
    1062             :         int error, s;
    1063             : 
    1064           0 :         if ((error = getsock(p, SCARG(uap, fdes), &fp)) != 0)
    1065           0 :                 return (error);
    1066           0 :         error = copyin(SCARG(uap, alen), &len, sizeof (len));
    1067           0 :         if (error)
    1068             :                 goto bad;
    1069           0 :         so = fp->f_data;
    1070           0 :         error = pledge_socket(p, -1, so->so_state);
    1071           0 :         if (error)
    1072             :                 goto bad;
    1073           0 :         m = m_getclr(M_WAIT, MT_SONAME);
    1074           0 :         s = solock(so);
    1075           0 :         error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0, p);
    1076           0 :         sounlock(so, s);
    1077           0 :         if (error)
    1078             :                 goto bad;
    1079           0 :         error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen));
    1080             : bad:
    1081           0 :         FRELE(fp, p);
    1082           0 :         m_freem(m);
    1083           0 :         return (error);
    1084           0 : }
    1085             : 
    1086             : /*
    1087             :  * Get name of peer for connected socket.
    1088             :  */
    1089             : int
    1090           0 : sys_getpeername(struct proc *p, void *v, register_t *retval)
    1091             : {
    1092             :         struct sys_getpeername_args /* {
    1093             :                 syscallarg(int) fdes;
    1094             :                 syscallarg(struct sockaddr *) asa;
    1095             :                 syscallarg(socklen_t *) alen;
    1096           0 :         } */ *uap = v;
    1097           0 :         struct file *fp;
    1098             :         struct socket *so;
    1099             :         struct mbuf *m = NULL;
    1100           0 :         socklen_t len;
    1101             :         int error, s;
    1102             : 
    1103           0 :         if ((error = getsock(p, SCARG(uap, fdes), &fp)) != 0)
    1104           0 :                 return (error);
    1105           0 :         so = fp->f_data;
    1106           0 :         error = pledge_socket(p, -1, so->so_state);
    1107           0 :         if (error)
    1108             :                 goto bad;
    1109           0 :         if ((so->so_state & SS_ISCONNECTED) == 0) {
    1110             :                 error = ENOTCONN;
    1111           0 :                 goto bad;
    1112             :         }
    1113           0 :         error = copyin(SCARG(uap, alen), &len, sizeof (len));
    1114           0 :         if (error)
    1115             :                 goto bad;
    1116           0 :         m = m_getclr(M_WAIT, MT_SONAME);
    1117           0 :         s = solock(so);
    1118           0 :         error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0, p);
    1119           0 :         sounlock(so, s);
    1120           0 :         if (error)
    1121             :                 goto bad;
    1122           0 :         error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen));
    1123             : bad:
    1124           0 :         FRELE(fp, p);
    1125           0 :         m_freem(m);
    1126           0 :         return (error);
    1127           0 : }
    1128             : 
    1129             : int
    1130           0 : sockargs(struct mbuf **mp, const void *buf, size_t buflen, int type)
    1131             : {
    1132             :         struct sockaddr *sa;
    1133             :         struct mbuf *m;
    1134             :         int error;
    1135             : 
    1136             :         /*
    1137             :          * We can't allow socket names > UCHAR_MAX in length, since that
    1138             :          * will overflow sa_len. Also, control data more than MCLBYTES in
    1139             :          * length is just too much.
    1140             :          * Memory for sa_len and sa_family must exist.
    1141             :          */
    1142           0 :         if ((buflen > (type == MT_SONAME ? UCHAR_MAX : MCLBYTES)) ||
    1143           0 :             (type == MT_SONAME && buflen < offsetof(struct sockaddr, sa_data)))
    1144           0 :                 return (EINVAL);
    1145             : 
    1146             :         /* Allocate an mbuf to hold the arguments. */
    1147           0 :         m = m_get(M_WAIT, type);
    1148           0 :         if (buflen > MLEN) {
    1149           0 :                 MCLGET(m, M_WAITOK);
    1150           0 :                 if ((m->m_flags & M_EXT) == 0) {
    1151           0 :                         m_free(m);
    1152           0 :                         return ENOBUFS;
    1153             :                 }
    1154             :         }
    1155           0 :         m->m_len = buflen;
    1156           0 :         error = copyin(buf, mtod(m, caddr_t), buflen);
    1157           0 :         if (error) {
    1158           0 :                 (void) m_free(m);
    1159           0 :                 return (error);
    1160             :         }
    1161           0 :         *mp = m;
    1162           0 :         if (type == MT_SONAME) {
    1163           0 :                 sa = mtod(m, struct sockaddr *);
    1164           0 :                 sa->sa_len = buflen;
    1165           0 :         }
    1166           0 :         return (0);
    1167           0 : }
    1168             : 
    1169             : int
    1170           0 : getsock(struct proc *p, int fdes, struct file **fpp)
    1171             : {
    1172             :         struct file *fp;
    1173             : 
    1174           0 :         fp = fd_getfile(p->p_fd, fdes);
    1175           0 :         if (fp == NULL)
    1176           0 :                 return (EBADF);
    1177           0 :         if (fp->f_type != DTYPE_SOCKET) {
    1178           0 :                 FRELE(fp, p);
    1179           0 :                 return (ENOTSOCK);
    1180             :         }
    1181           0 :         *fpp = fp;
    1182             : 
    1183           0 :         return (0);
    1184           0 : }
    1185             : 
    1186             : int
    1187           0 : sys_setrtable(struct proc *p, void *v, register_t *retval)
    1188             : {
    1189             :         struct sys_setrtable_args /* {
    1190             :                 syscallarg(int) rtableid;
    1191           0 :         } */ *uap = v;
    1192             :         int rtableid, error;
    1193             : 
    1194           0 :         rtableid = SCARG(uap, rtableid);
    1195             : 
    1196           0 :         if (p->p_p->ps_rtableid == (u_int)rtableid)
    1197           0 :                 return (0);
    1198           0 :         if (p->p_p->ps_rtableid != 0 && (error = suser(p)) != 0)
    1199           0 :                 return (error);
    1200           0 :         if (rtableid < 0 || !rtable_exists((u_int)rtableid))
    1201           0 :                 return (EINVAL);
    1202             : 
    1203           0 :         p->p_p->ps_rtableid = (u_int)rtableid;
    1204           0 :         return (0);
    1205           0 : }
    1206             : 
    1207             : int
    1208           0 : sys_getrtable(struct proc *p, void *v, register_t *retval)
    1209             : {
    1210           0 :         *retval = (int)p->p_p->ps_rtableid;
    1211           0 :         return (0);
    1212             : }
    1213             : 
    1214             : int
    1215           0 : copyaddrout(struct proc *p, struct mbuf *name, struct sockaddr *sa,
    1216             :     socklen_t buflen, socklen_t *outlen)
    1217             : {
    1218             :         int error;
    1219           0 :         socklen_t namelen = name->m_len;
    1220             : 
    1221             :         /* SHOULD COPY OUT A CHAIN HERE */
    1222           0 :         error = copyout(mtod(name, caddr_t), sa, MIN(buflen, namelen));
    1223           0 :         if (error == 0) {
    1224             : #ifdef KTRACE
    1225           0 :                 if (KTRPOINT(p, KTR_STRUCT))
    1226           0 :                         ktrsockaddr(p, mtod(name, caddr_t), namelen);
    1227             : #endif
    1228           0 :                 error = copyout(&namelen, outlen, sizeof(*outlen));
    1229           0 :         }
    1230             : 
    1231           0 :         return (error);
    1232           0 : }

Generated by: LCOV version 1.13