home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / kern / uipc_syscalls.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-17  |  26.1 KB  |  1,225 lines

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