The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/compat/svr4/svr4_stream.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 1998 Mark Newton.  All rights reserved.
    3  * Copyright (c) 1994, 1996 Christos Zoulas.  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 Christos Zoulas.
   16  * 4. The name of the author may not be used to endorse or promote products
   17  *    derived from this software without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   29  */
   30 
   31 /*
   32  * Pretend that we have streams...
   33  * Yes, this is gross.
   34  *
   35  * ToDo: The state machine for getmsg needs re-thinking
   36  */
   37 
   38 #include <sys/cdefs.h>
   39 __FBSDID("$FreeBSD: src/sys/compat/svr4/svr4_stream.c,v 1.49.2.3 2005/03/29 07:24:48 das Exp $");
   40 
   41 #define COMPAT_43 1
   42 
   43 #include "opt_mac.h"
   44 
   45 #include <sys/param.h>
   46 #include <sys/systm.h>
   47 #include <sys/fcntl.h>
   48 #include <sys/filedesc.h>
   49 #include <sys/filio.h>
   50 #include <sys/lock.h>
   51 #include <sys/malloc.h>
   52 #include <sys/file.h>           /* Must come after sys/malloc.h */
   53 #include <sys/mac.h>
   54 #include <sys/mbuf.h>
   55 #include <sys/mutex.h>
   56 #include <sys/proc.h>
   57 #include <sys/protosw.h>
   58 #include <sys/signal.h>
   59 #include <sys/signalvar.h>
   60 #include <sys/socket.h>
   61 #include <sys/socketvar.h>
   62 #include <sys/stat.h>
   63 #include <sys/syscallsubr.h>
   64 #include <sys/sysproto.h>
   65 #include <sys/uio.h>
   66 #include <sys/ktrace.h>         /* Must come after sys/uio.h */
   67 #include <sys/un.h>
   68 
   69 #include <netinet/in.h>
   70 
   71 #include <compat/svr4/svr4.h>
   72 #include <compat/svr4/svr4_types.h>
   73 #include <compat/svr4/svr4_util.h>
   74 #include <compat/svr4/svr4_signal.h>
   75 #include <compat/svr4/svr4_proto.h>
   76 #include <compat/svr4/svr4_stropts.h>
   77 #include <compat/svr4/svr4_timod.h>
   78 #include <compat/svr4/svr4_sockmod.h>
   79 #include <compat/svr4/svr4_ioctl.h>
   80 #include <compat/svr4/svr4_socket.h>
   81 
   82 /* Utils */
   83 static int clean_pipe(struct thread *, const char *);
   84 static void getparm(struct file *, struct svr4_si_sockparms *);
   85 static int svr4_do_putmsg(struct thread *, struct svr4_sys_putmsg_args *,
   86                                struct file *);
   87 static int svr4_do_getmsg(struct thread *, struct svr4_sys_getmsg_args *,
   88                                struct file *);
   89 
   90 /* Address Conversions */
   91 static void sockaddr_to_netaddr_in(struct svr4_strmcmd *,
   92                                         const struct sockaddr_in *);
   93 static void sockaddr_to_netaddr_un(struct svr4_strmcmd *,
   94                                         const struct sockaddr_un *);
   95 static void netaddr_to_sockaddr_in(struct sockaddr_in *,
   96                                         const struct svr4_strmcmd *);
   97 static void netaddr_to_sockaddr_un(struct sockaddr_un *,
   98                                         const struct svr4_strmcmd *);
   99 
  100 /* stream ioctls */
  101 static int i_nread(struct file *, struct thread *, register_t *, int,
  102                         u_long, caddr_t);
  103 static int i_fdinsert(struct file *, struct thread *, register_t *, int,
  104                            u_long, caddr_t);
  105 static int i_str(struct file *, struct thread *, register_t *, int,
  106                         u_long, caddr_t);
  107 static int i_setsig(struct file *, struct thread *, register_t *, int,
  108                         u_long, caddr_t);
  109 static int i_getsig(struct file *, struct thread *, register_t *, int,
  110                         u_long, caddr_t);
  111 static int _i_bind_rsvd(struct file *, struct thread *, register_t *, int,
  112                              u_long, caddr_t);
  113 static int _i_rele_rsvd(struct file *, struct thread *, register_t *, int,
  114                              u_long, caddr_t);
  115 
  116 /* i_str sockmod calls */
  117 static int sockmod(struct file *, int, struct svr4_strioctl *,
  118                               struct thread *);
  119 static int si_listen(struct file *, int, struct svr4_strioctl *,
  120                               struct thread *);
  121 static int si_ogetudata(struct file *, int, struct svr4_strioctl *,
  122                               struct thread *);
  123 static int si_sockparams(struct file *, int, struct svr4_strioctl *,
  124                               struct thread *);
  125 static int si_shutdown  (struct file *, int, struct svr4_strioctl *,
  126                               struct thread *);
  127 static int si_getudata(struct file *, int, struct svr4_strioctl *,
  128                               struct thread *);
  129 
  130 /* i_str timod calls */
  131 static int timod(struct file *, int, struct svr4_strioctl *, struct thread *);
  132 static int ti_getinfo(struct file *, int, struct svr4_strioctl *,
  133                               struct thread *);
  134 static int ti_bind(struct file *, int, struct svr4_strioctl *, struct thread *);
  135 
  136 /* infrastructure */
  137 static int svr4_sendit(struct thread *td, int s, struct msghdr *mp, int flags);
  138 
  139 static int svr4_recvit(struct thread *td, int s, struct msghdr *mp,
  140                             caddr_t namelenp);
  141 
  142 /* <sigh>  Ok, so we shouldn't use sendit() in uipc_syscalls.c because
  143  * it isn't part of a "public" interface;  We're supposed to use
  144  * pru_sosend instead.  Same goes for recvit()/pru_soreceive() for
  145  * that matter.  Solution:  Suck sendit()/recvit() into here where we
  146  * can do what we like.
  147  * 
  148  * I hate code duplication. 
  149  * 
  150  * I will take out all the #ifdef COMPAT_OLDSOCK gumph, though.
  151  */
  152 static int
  153 svr4_sendit(td, s, mp, flags)
  154         register struct thread *td;
  155         int s;
  156         register struct msghdr *mp;
  157         int flags;
  158 {
  159         struct uio auio;
  160         register struct iovec *iov;
  161         register int i;
  162         struct mbuf *control;
  163         struct sockaddr *to;
  164         int len, error;
  165         struct socket *so;
  166 #ifdef KTRACE
  167         struct uio *ktruio = NULL;
  168 #endif
  169 
  170         if ((error = fgetsock(td, s, &so, NULL)) != 0)
  171                 return (error);
  172 
  173 #ifdef MAC
  174         SOCK_LOCK(so);
  175         error = mac_check_socket_send(td->td_ucred, so);
  176         SOCK_UNLOCK(so);
  177         if (error)
  178                 goto done1;
  179 #endif
  180 
  181         auio.uio_iov = mp->msg_iov;
  182         auio.uio_iovcnt = mp->msg_iovlen;
  183         auio.uio_segflg = UIO_USERSPACE;
  184         auio.uio_rw = UIO_WRITE;
  185         auio.uio_td = td;
  186         auio.uio_offset = 0;                    /* XXX */
  187         auio.uio_resid = 0;
  188         iov = mp->msg_iov;
  189         for (i = 0; i < mp->msg_iovlen; i++, iov++) {
  190                 if ((auio.uio_resid += iov->iov_len) < 0) {
  191                         error = EINVAL;
  192                         goto done1;
  193                 }
  194         }
  195         if (mp->msg_name) {
  196                 error = getsockaddr(&to, mp->msg_name, mp->msg_namelen);
  197                 if (error)
  198                         goto done1;
  199         } else {
  200                 to = 0;
  201         }
  202         if (mp->msg_control) {
  203                 if (mp->msg_controllen < sizeof(struct cmsghdr)) {
  204                         error = EINVAL;
  205                         goto bad;
  206                 }
  207                 error = sockargs(&control, mp->msg_control,
  208                     mp->msg_controllen, MT_CONTROL);
  209                 if (error)
  210                         goto bad;
  211         } else {
  212                 control = 0;
  213         }
  214 #ifdef KTRACE
  215         if (KTRPOINT(td, KTR_GENIO))
  216                 ktruio = cloneuio(&auio);
  217 #endif
  218         len = auio.uio_resid;
  219         error = so->so_proto->pr_usrreqs->pru_sosend(so, to, &auio, 0, control,
  220                                                      flags, td);
  221         if (error) {
  222                 if (auio.uio_resid != len && (error == ERESTART ||
  223                     error == EINTR || error == EWOULDBLOCK))
  224                         error = 0;
  225                 if (error == EPIPE) {
  226                         PROC_LOCK(td->td_proc);
  227                         psignal(td->td_proc, SIGPIPE);
  228                         PROC_UNLOCK(td->td_proc);
  229                 }
  230         }
  231         if (error == 0)
  232                 td->td_retval[0] = len - auio.uio_resid;
  233 #ifdef KTRACE
  234         if (ktruio != NULL) {
  235                 ktruio->uio_resid = td->td_retval[0];
  236                 ktrgenio(s, UIO_WRITE, ktruio, error);
  237         }
  238 #endif
  239 bad:
  240         if (to)
  241                 FREE(to, M_SONAME);
  242 done1:
  243         fputsock(so);
  244         return (error);
  245 }
  246 
  247 static int
  248 svr4_recvit(td, s, mp, namelenp)
  249         register struct thread *td;
  250         int s;
  251         register struct msghdr *mp;
  252         caddr_t namelenp;
  253 {
  254         struct uio auio;
  255         register struct iovec *iov;
  256         register int i;
  257         int len, error;
  258         struct mbuf *m, *control = 0;
  259         caddr_t ctlbuf;
  260         struct socket *so;
  261         struct sockaddr *fromsa = 0;
  262 #ifdef KTRACE
  263         struct uio *ktruio = NULL;
  264 #endif
  265 
  266         if ((error = fgetsock(td, s, &so, NULL)) != 0)
  267                 return (error);
  268 
  269 #ifdef MAC
  270         SOCK_LOCK(so);
  271         error = mac_check_socket_receive(td->td_ucred, so);
  272         SOCK_UNLOCK(so);
  273         if (error)
  274                 goto done1;
  275 #endif
  276 
  277         auio.uio_iov = mp->msg_iov;
  278         auio.uio_iovcnt = mp->msg_iovlen;
  279         auio.uio_segflg = UIO_USERSPACE;
  280         auio.uio_rw = UIO_READ;
  281         auio.uio_td = td;
  282         auio.uio_offset = 0;                    /* XXX */
  283         auio.uio_resid = 0;
  284         iov = mp->msg_iov;
  285         for (i = 0; i < mp->msg_iovlen; i++, iov++) {
  286                 if ((auio.uio_resid += iov->iov_len) < 0) {
  287                         error = EINVAL;
  288                         goto done1;
  289                 }
  290         }
  291 #ifdef KTRACE
  292         if (KTRPOINT(td, KTR_GENIO)) 
  293                 ktruio = cloneuio(&auio);
  294 #endif
  295         len = auio.uio_resid;
  296         error = so->so_proto->pr_usrreqs->pru_soreceive(so, &fromsa, &auio,
  297             (struct mbuf **)0, mp->msg_control ? &control : (struct mbuf **)0,
  298             &mp->msg_flags);
  299         if (error) {
  300                 if (auio.uio_resid != len && (error == ERESTART ||
  301                     error == EINTR || error == EWOULDBLOCK))
  302                         error = 0;
  303         }
  304 #ifdef KTRACE
  305         if (ktruio != NULL) {
  306                 ktruio->uio_resid = len - auio.uio_resid;
  307                 ktrgenio(s, UIO_READ, ktruio, error);
  308         }
  309 #endif
  310         if (error)
  311                 goto out;
  312         td->td_retval[0] = len - auio.uio_resid;
  313         if (mp->msg_name) {
  314                 len = mp->msg_namelen;
  315                 if (len <= 0 || fromsa == 0)
  316                         len = 0;
  317                 else {
  318                         /* save sa_len before it is destroyed by MSG_COMPAT */
  319                         len = MIN(len, fromsa->sa_len);
  320                         error = copyout(fromsa,
  321                             (caddr_t)mp->msg_name, (unsigned)len);
  322                         if (error)
  323                                 goto out;
  324                 }
  325                 mp->msg_namelen = len;
  326                 if (namelenp &&
  327                     (error = copyout((caddr_t)&len, namelenp, sizeof (int)))) {
  328                         goto out;
  329                 }
  330         }
  331         if (mp->msg_control) {
  332                 len = mp->msg_controllen;
  333                 m = control;
  334                 mp->msg_controllen = 0;
  335                 ctlbuf = (caddr_t) mp->msg_control;
  336 
  337                 while (m && len > 0) {
  338                         unsigned int tocopy;
  339 
  340                         if (len >= m->m_len) 
  341                                 tocopy = m->m_len;
  342                         else {
  343                                 mp->msg_flags |= MSG_CTRUNC;
  344                                 tocopy = len;
  345                         }
  346                 
  347                         if ((error = copyout((caddr_t)mtod(m, caddr_t),
  348                                         ctlbuf, tocopy)) != 0)
  349                                 goto out;
  350 
  351                         ctlbuf += tocopy;
  352                         len -= tocopy;
  353                         m = m->m_next;
  354                 }
  355                 mp->msg_controllen = ctlbuf - (caddr_t)mp->msg_control;
  356         }
  357 out:
  358         if (fromsa)
  359                 FREE(fromsa, M_SONAME);
  360         if (control)
  361                 m_freem(control);
  362 done1:
  363         fputsock(so);
  364         return (error);
  365 }
  366 
  367 #ifdef DEBUG_SVR4
  368 static void bufprint(u_char *, size_t);
  369 static int show_ioc(const char *, struct svr4_strioctl *);
  370 static int show_strbuf(struct svr4_strbuf *);
  371 static void show_msg(const char *, int, struct svr4_strbuf *, 
  372                           struct svr4_strbuf *, int);
  373 
  374 static void
  375 bufprint(buf, len)
  376         u_char *buf;
  377         size_t len;
  378 {
  379         size_t i;
  380 
  381         uprintf("\n\t");
  382         for (i = 0; i < len; i++) {
  383                 uprintf("%x ", buf[i]);
  384                 if (i && (i % 16) == 0) 
  385                         uprintf("\n\t");
  386         }
  387 }
  388 
  389 static int
  390 show_ioc(str, ioc)
  391         const char              *str;
  392         struct svr4_strioctl    *ioc;
  393 {
  394         u_char *ptr = NULL;
  395         int len;
  396         int error;
  397 
  398         len = ioc->len;
  399         if (len > 1024)
  400                 len = 1024;
  401 
  402         if (len > 0) {
  403                 ptr = (u_char *) malloc(len, M_TEMP, M_WAITOK);
  404                 if ((error = copyin(ioc->buf, ptr, len)) != 0) {
  405                         free((char *) ptr, M_TEMP);
  406                         return error;
  407                 }
  408         }
  409 
  410         uprintf("%s cmd = %ld, timeout = %d, len = %d, buf = %p { ",
  411             str, ioc->cmd, ioc->timeout, ioc->len, ioc->buf);
  412 
  413         if (ptr != NULL)
  414                 bufprint(ptr, len);
  415 
  416         uprintf("}\n");
  417 
  418         if (ptr != NULL)
  419                 free((char *) ptr, M_TEMP);
  420         return 0;
  421 }
  422 
  423 
  424 static int
  425 show_strbuf(str)
  426         struct svr4_strbuf *str;
  427 {
  428         int error;
  429         u_char *ptr = NULL;
  430         int maxlen = str->maxlen;
  431         int len = str->len;
  432 
  433         if (maxlen > 8192)
  434                 maxlen = 8192;
  435 
  436         if (maxlen < 0)
  437                 maxlen = 0;
  438 
  439         if (len >= maxlen)
  440                 len = maxlen;
  441 
  442         if (len > 0) {
  443             ptr = (u_char *) malloc(len, M_TEMP, M_WAITOK);
  444 
  445             if ((error = copyin(str->buf, ptr, len)) != 0) {
  446                     free((char *) ptr, M_TEMP);
  447                     return error;
  448             }
  449         }
  450 
  451         uprintf(", { %d, %d, %p=[ ", str->maxlen, str->len, str->buf);
  452 
  453         if (ptr)
  454                 bufprint(ptr, len);
  455 
  456         uprintf("]}");
  457 
  458         if (ptr)
  459                 free((char *) ptr, M_TEMP);
  460 
  461         return 0;
  462 }
  463 
  464 
  465 static void
  466 show_msg(str, fd, ctl, dat, flags)
  467         const char              *str;
  468         int                      fd;
  469         struct svr4_strbuf      *ctl;
  470         struct svr4_strbuf      *dat;
  471         int                      flags;
  472 {
  473         struct svr4_strbuf      buf;
  474         int error;
  475 
  476         uprintf("%s(%d", str, fd);
  477         if (ctl != NULL) {
  478                 if ((error = copyin(ctl, &buf, sizeof(buf))) != 0)
  479                         return;
  480                 show_strbuf(&buf);
  481         }
  482         else 
  483                 uprintf(", NULL");
  484 
  485         if (dat != NULL) {
  486                 if ((error = copyin(dat, &buf, sizeof(buf))) != 0)
  487                         return;
  488                 show_strbuf(&buf);
  489         }
  490         else 
  491                 uprintf(", NULL");
  492 
  493         uprintf(", %x);\n", flags);
  494 }
  495 
  496 #endif /* DEBUG_SVR4 */
  497 
  498 /*
  499  * We are faced with an interesting situation. On svr4 unix sockets
  500  * are really pipes. But we really have sockets, and we might as
  501  * well use them. At the point where svr4 calls TI_BIND, it has
  502  * already created a named pipe for the socket using mknod(2).
  503  * We need to create a socket with the same name when we bind,
  504  * so we need to remove the pipe before, otherwise we'll get address
  505  * already in use. So we *carefully* remove the pipe, to avoid
  506  * using this as a random file removal tool. We use system calls
  507  * to avoid code duplication.
  508  */
  509 static int
  510 clean_pipe(td, path)
  511         struct thread *td;
  512         const char *path;
  513 {
  514         struct lstat_args la;
  515         struct unlink_args ua;
  516         struct stat st;
  517         int error;
  518         caddr_t sg = stackgap_init();
  519         size_t l = strlen(path) + 1;
  520         void *tpath;
  521 
  522         if ((tpath = stackgap_alloc(&sg, l)) == NULL)
  523                 return ENAMETOOLONG;
  524         la.ub = stackgap_alloc(&sg, sizeof(struct stat));
  525 
  526         if ((error = copyout(path, tpath, l)) != 0)
  527                 return error;
  528 
  529         la.path = tpath;
  530 
  531         if ((error = lstat(td, &la)) != 0)
  532                 return 0;
  533 
  534         if ((error = copyin(la.ub, &st, sizeof(st))) != 0)
  535                 return 0;
  536 
  537         /*
  538          * Make sure we are dealing with a mode 0 named pipe.
  539          */
  540         if ((st.st_mode & S_IFMT) != S_IFIFO)
  541                 return 0;
  542 
  543         if ((st.st_mode & ALLPERMS) != 0)
  544                 return 0;
  545 
  546         ua.path = la.path;
  547 
  548         if ((error = unlink(td, &ua)) != 0) {
  549                 DPRINTF(("clean_pipe: unlink failed %d\n", error));
  550                 return error;
  551         }
  552 
  553         return 0;
  554 }
  555 
  556 
  557 static void
  558 sockaddr_to_netaddr_in(sc, sain)
  559         struct svr4_strmcmd *sc;
  560         const struct sockaddr_in *sain;
  561 {
  562         struct svr4_netaddr_in *na;
  563         na = SVR4_ADDROF(sc);
  564 
  565         na->family = sain->sin_family;
  566         na->port = sain->sin_port;
  567         na->addr = sain->sin_addr.s_addr;
  568         DPRINTF(("sockaddr_in -> netaddr %d %d %lx\n", na->family, na->port,
  569                  na->addr));
  570 }
  571 
  572 
  573 static void
  574 sockaddr_to_netaddr_un(sc, saun)
  575         struct svr4_strmcmd *sc;
  576         const struct sockaddr_un *saun;
  577 {
  578         struct svr4_netaddr_un *na;
  579         char *dst, *edst = ((char *) sc) + sc->offs + sizeof(na->family) + 1  -
  580             sizeof(*sc);
  581         const char *src;
  582 
  583         na = SVR4_ADDROF(sc);
  584         na->family = saun->sun_family;
  585         for (src = saun->sun_path, dst = na->path; (*dst++ = *src++) != '\0'; )
  586                 if (dst == edst)
  587                         break;
  588         DPRINTF(("sockaddr_un -> netaddr %d %s\n", na->family, na->path));
  589 }
  590 
  591 
  592 static void
  593 netaddr_to_sockaddr_in(sain, sc)
  594         struct sockaddr_in *sain;
  595         const struct svr4_strmcmd *sc;
  596 {
  597         const struct svr4_netaddr_in *na;
  598 
  599 
  600         na = SVR4_C_ADDROF(sc);
  601         memset(sain, 0, sizeof(*sain));
  602         sain->sin_len = sizeof(*sain);
  603         sain->sin_family = na->family;
  604         sain->sin_port = na->port;
  605         sain->sin_addr.s_addr = na->addr;
  606         DPRINTF(("netaddr -> sockaddr_in %d %d %x\n", sain->sin_family,
  607                  sain->sin_port, sain->sin_addr.s_addr));
  608 }
  609 
  610 
  611 static void
  612 netaddr_to_sockaddr_un(saun, sc)
  613         struct sockaddr_un *saun;
  614         const struct svr4_strmcmd *sc;
  615 {
  616         const struct svr4_netaddr_un *na;
  617         char *dst, *edst = &saun->sun_path[sizeof(saun->sun_path) - 1];
  618         const char *src;
  619 
  620         na = SVR4_C_ADDROF(sc);
  621         memset(saun, 0, sizeof(*saun));
  622         saun->sun_family = na->family;
  623         for (src = na->path, dst = saun->sun_path; (*dst++ = *src++) != '\0'; )
  624                 if (dst == edst)
  625                         break;
  626         saun->sun_len = dst - saun->sun_path;
  627         DPRINTF(("netaddr -> sockaddr_un %d %s\n", saun->sun_family,
  628                  saun->sun_path));
  629 }
  630 
  631 
  632 static void
  633 getparm(fp, pa)
  634         struct file *fp;
  635         struct svr4_si_sockparms *pa;
  636 {
  637         struct svr4_strm *st;
  638         struct socket *so;
  639 
  640         st = svr4_stream_get(fp);
  641         if (st == NULL)
  642                 return;
  643 
  644         so = fp->f_data;
  645 
  646         pa->family = st->s_family;
  647 
  648         switch (so->so_type) {
  649         case SOCK_DGRAM:
  650                 pa->type = SVR4_T_CLTS;
  651                 pa->protocol = IPPROTO_UDP;
  652                 DPRINTF(("getparm(dgram)\n"));
  653                 return;
  654 
  655         case SOCK_STREAM:
  656                 pa->type = SVR4_T_COTS;  /* What about T_COTS_ORD? XXX */
  657                 pa->protocol = IPPROTO_IP;
  658                 DPRINTF(("getparm(stream)\n"));
  659                 return;
  660 
  661         case SOCK_RAW:
  662                 pa->type = SVR4_T_CLTS;
  663                 pa->protocol = IPPROTO_RAW;
  664                 DPRINTF(("getparm(raw)\n"));
  665                 return;
  666 
  667         default:
  668                 pa->type = 0;
  669                 pa->protocol = 0;
  670                 DPRINTF(("getparm(type %d?)\n", so->so_type));
  671                 return;
  672         }
  673 }
  674 
  675 
  676 static int
  677 si_ogetudata(fp, fd, ioc, td)
  678         struct file             *fp;
  679         int                      fd;
  680         struct svr4_strioctl    *ioc;
  681         struct thread           *td;
  682 {
  683         int error;
  684         struct svr4_si_oudata ud;
  685         struct svr4_si_sockparms pa;
  686 
  687         if (ioc->len != sizeof(ud) && ioc->len != sizeof(ud) - sizeof(int)) {
  688                 DPRINTF(("SI_OGETUDATA: Wrong size %d != %d\n",
  689                          sizeof(ud), ioc->len));
  690                 return EINVAL;
  691         }
  692 
  693         if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0)
  694                 return error;
  695 
  696         getparm(fp, &pa);
  697 
  698         switch (pa.family) {
  699         case AF_INET:
  700             ud.tidusize = 16384;
  701             ud.addrsize = sizeof(struct svr4_sockaddr_in);
  702             if (pa.type == SVR4_SOCK_STREAM) 
  703                     ud.etsdusize = 1;
  704             else
  705                     ud.etsdusize = 0;
  706             break;
  707 
  708         case AF_LOCAL:
  709             ud.tidusize = 65536;
  710             ud.addrsize = 128;
  711             ud.etsdusize = 128;
  712             break;
  713 
  714         default:
  715             DPRINTF(("SI_OGETUDATA: Unsupported address family %d\n",
  716                      pa.family));
  717             return ENOSYS;
  718         }
  719 
  720         /* I have no idea what these should be! */
  721         ud.optsize = 128;
  722         ud.tsdusize = 128;
  723 
  724         ud.servtype = pa.type;
  725 
  726         /* XXX: Fixme */
  727         ud.so_state = 0;
  728         ud.so_options = 0;
  729         return copyout(&ud, ioc->buf, ioc->len);
  730 }
  731 
  732 
  733 static int
  734 si_sockparams(fp, fd, ioc, td)
  735         struct file             *fp;
  736         int                      fd;
  737         struct svr4_strioctl    *ioc;
  738         struct thread           *td;
  739 {
  740         struct svr4_si_sockparms pa;
  741 
  742         getparm(fp, &pa);
  743         return copyout(&pa, ioc->buf, sizeof(pa));
  744 }
  745 
  746 
  747 static int
  748 si_listen(fp, fd, ioc, td)
  749         struct file             *fp;
  750         int                      fd;
  751         struct svr4_strioctl    *ioc;
  752         struct thread           *td;
  753 {
  754         int error;
  755         struct svr4_strm *st = svr4_stream_get(fp);
  756         struct svr4_strmcmd lst;
  757         struct listen_args la;
  758 
  759         if (st == NULL)
  760                 return EINVAL;
  761 
  762         if (ioc->len < 0 || ioc->len > sizeof(lst))
  763                 return EINVAL;
  764 
  765         if ((error = copyin(ioc->buf, &lst, ioc->len)) != 0)
  766                 return error;
  767 
  768         if (lst.cmd != SVR4_TI_OLD_BIND_REQUEST) {
  769                 DPRINTF(("si_listen: bad request %ld\n", lst.cmd));
  770                 return EINVAL;
  771         }
  772 
  773         /*
  774          * We are making assumptions again...
  775          */
  776         la.s = fd;
  777         DPRINTF(("SI_LISTEN: fileno %d backlog = %d\n", fd, 5));
  778         la.backlog = 5;
  779 
  780         if ((error = listen(td, &la)) != 0) {
  781                 DPRINTF(("SI_LISTEN: listen failed %d\n", error));
  782                 return error;
  783         }
  784 
  785         st->s_cmd = SVR4_TI__ACCEPT_WAIT;
  786         lst.cmd = SVR4_TI_BIND_REPLY;
  787 
  788         switch (st->s_family) {
  789         case AF_INET:
  790                 /* XXX: Fill the length here */
  791                 break;
  792 
  793         case AF_LOCAL:
  794                 lst.len = 140;
  795                 lst.pad[28] = 0x00000000;       /* magic again */
  796                 lst.pad[29] = 0x00000800;       /* magic again */
  797                 lst.pad[30] = 0x80001400;       /* magic again */
  798                 break;
  799 
  800         default:
  801                 DPRINTF(("SI_LISTEN: Unsupported address family %d\n",
  802                     st->s_family));
  803                 return ENOSYS;
  804         }
  805 
  806 
  807         if ((error = copyout(&lst, ioc->buf, ioc->len)) != 0)
  808                 return error;
  809 
  810         return 0;
  811 }
  812 
  813 
  814 static int
  815 si_getudata(fp, fd, ioc, td)
  816         struct file             *fp;
  817         int                      fd;
  818         struct svr4_strioctl    *ioc;
  819         struct thread           *td;
  820 {
  821         int error;
  822         struct svr4_si_udata ud;
  823 
  824         if (sizeof(ud) != ioc->len) {
  825                 DPRINTF(("SI_GETUDATA: Wrong size %d != %d\n",
  826                          sizeof(ud), ioc->len));
  827                 return EINVAL;
  828         }
  829 
  830         if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0)
  831                 return error;
  832 
  833         getparm(fp, &ud.sockparms);
  834 
  835         switch (ud.sockparms.family) {
  836         case AF_INET:
  837             DPRINTF(("getudata_inet\n"));
  838             ud.tidusize = 16384;
  839             ud.tsdusize = 16384;
  840             ud.addrsize = sizeof(struct svr4_sockaddr_in);
  841             if (ud.sockparms.type == SVR4_SOCK_STREAM) 
  842                     ud.etsdusize = 1;
  843             else
  844                     ud.etsdusize = 0;
  845             ud.optsize = 0;
  846             break;
  847 
  848         case AF_LOCAL:
  849             DPRINTF(("getudata_local\n"));
  850             ud.tidusize = 65536;
  851             ud.tsdusize = 128;
  852             ud.addrsize = 128;
  853             ud.etsdusize = 128;
  854             ud.optsize = 128;
  855             break;
  856 
  857         default:
  858             DPRINTF(("SI_GETUDATA: Unsupported address family %d\n",
  859                      ud.sockparms.family));
  860             return ENOSYS;
  861         }
  862 
  863 
  864         ud.servtype = ud.sockparms.type;
  865         DPRINTF(("ud.servtype = %d\n", ud.servtype));
  866         /* XXX: Fixme */
  867         ud.so_state = 0;
  868         ud.so_options = 0;
  869         return copyout(&ud, ioc->buf, sizeof(ud));
  870 }
  871 
  872 
  873 static int
  874 si_shutdown(fp, fd, ioc, td)
  875         struct file             *fp;
  876         int                      fd;
  877         struct svr4_strioctl    *ioc;
  878         struct thread           *td;
  879 {
  880         int error;
  881         struct shutdown_args ap;
  882 
  883         if (ioc->len != sizeof(ap.how)) {
  884                 DPRINTF(("SI_SHUTDOWN: Wrong size %d != %d\n",
  885                          sizeof(ap.how), ioc->len));
  886                 return EINVAL;
  887         }
  888 
  889         if ((error = copyin(ioc->buf, &ap.how, ioc->len)) != 0)
  890                 return error;
  891 
  892         ap.s = fd;
  893 
  894         return shutdown(td, &ap);
  895 }
  896 
  897 
  898 static int
  899 sockmod(fp, fd, ioc, td)
  900         struct file             *fp;
  901         int                      fd;
  902         struct svr4_strioctl    *ioc;
  903         struct thread           *td;
  904 {
  905         switch (ioc->cmd) {
  906         case SVR4_SI_OGETUDATA:
  907                 DPRINTF(("SI_OGETUDATA\n"));
  908                 return si_ogetudata(fp, fd, ioc, td);
  909 
  910         case SVR4_SI_SHUTDOWN:
  911                 DPRINTF(("SI_SHUTDOWN\n"));
  912                 return si_shutdown(fp, fd, ioc, td);
  913 
  914         case SVR4_SI_LISTEN:
  915                 DPRINTF(("SI_LISTEN\n"));
  916                 return si_listen(fp, fd, ioc, td);
  917 
  918         case SVR4_SI_SETMYNAME:
  919                 DPRINTF(("SI_SETMYNAME\n"));
  920                 return 0;
  921 
  922         case SVR4_SI_SETPEERNAME:
  923                 DPRINTF(("SI_SETPEERNAME\n"));
  924                 return 0;
  925 
  926         case SVR4_SI_GETINTRANSIT:
  927                 DPRINTF(("SI_GETINTRANSIT\n"));
  928                 return 0;
  929 
  930         case SVR4_SI_TCL_LINK:
  931                 DPRINTF(("SI_TCL_LINK\n"));
  932                 return 0;
  933 
  934         case SVR4_SI_TCL_UNLINK:
  935                 DPRINTF(("SI_TCL_UNLINK\n"));
  936                 return 0;
  937 
  938         case SVR4_SI_SOCKPARAMS:
  939                 DPRINTF(("SI_SOCKPARAMS\n"));
  940                 return si_sockparams(fp, fd, ioc, td);
  941 
  942         case SVR4_SI_GETUDATA:
  943                 DPRINTF(("SI_GETUDATA\n"));
  944                 return si_getudata(fp, fd, ioc, td);
  945 
  946         default:
  947                 DPRINTF(("Unknown sockmod ioctl %lx\n", ioc->cmd));
  948                 return 0;
  949 
  950         }
  951 }
  952 
  953 
  954 static int
  955 ti_getinfo(fp, fd, ioc, td)
  956         struct file             *fp;
  957         int                      fd;
  958         struct svr4_strioctl    *ioc;
  959         struct thread           *td;
  960 {
  961         int error;
  962         struct svr4_infocmd info;
  963 
  964         memset(&info, 0, sizeof(info));
  965 
  966         if (ioc->len < 0 || ioc->len > sizeof(info))
  967                 return EINVAL;
  968 
  969         if ((error = copyin(ioc->buf, &info, ioc->len)) != 0)
  970                 return error;
  971 
  972         if (info.cmd != SVR4_TI_INFO_REQUEST)
  973                 return EINVAL;
  974 
  975         info.cmd = SVR4_TI_INFO_REPLY;
  976         info.tsdu = 0;
  977         info.etsdu = 1;
  978         info.cdata = -2;
  979         info.ddata = -2;
  980         info.addr = 16;
  981         info.opt = -1;
  982         info.tidu = 16384;
  983         info.serv = 2;
  984         info.current = 0;
  985         info.provider = 2;
  986 
  987         ioc->len = sizeof(info);
  988         if ((error = copyout(&info, ioc->buf, ioc->len)) != 0)
  989                 return error;
  990 
  991         return 0;
  992 }
  993 
  994 
  995 static int
  996 ti_bind(fp, fd, ioc, td)
  997         struct file             *fp;
  998         int                      fd;
  999         struct svr4_strioctl    *ioc;
 1000         struct thread           *td;
 1001 {
 1002         int error;
 1003         struct svr4_strm *st = svr4_stream_get(fp);
 1004         struct sockaddr_in sain;
 1005         struct sockaddr_un saun;
 1006         caddr_t sg;
 1007         void *skp, *sup = NULL;
 1008         int sasize;
 1009         struct svr4_strmcmd bnd;
 1010         struct bind_args ba;
 1011 
 1012         if (st == NULL) {
 1013                 DPRINTF(("ti_bind: bad file descriptor\n"));
 1014                 return EINVAL;
 1015         }
 1016 
 1017         if (ioc->len < 0 || ioc->len > sizeof(bnd))
 1018                 return EINVAL;
 1019 
 1020         if ((error = copyin(ioc->buf, &bnd, ioc->len)) != 0)
 1021                 return error;
 1022 
 1023         if (bnd.cmd != SVR4_TI_OLD_BIND_REQUEST) {
 1024                 DPRINTF(("ti_bind: bad request %ld\n", bnd.cmd));
 1025                 return EINVAL;
 1026         }
 1027 
 1028         switch (st->s_family) {
 1029         case AF_INET:
 1030                 skp = &sain;
 1031                 sasize = sizeof(sain);
 1032 
 1033                 if (bnd.offs == 0)
 1034                         goto reply;
 1035 
 1036                 netaddr_to_sockaddr_in(&sain, &bnd);
 1037 
 1038                 DPRINTF(("TI_BIND: fam %d, port %d, addr %x\n",
 1039                          sain.sin_family, sain.sin_port,
 1040                          sain.sin_addr.s_addr));
 1041                 break;
 1042 
 1043         case AF_LOCAL:
 1044                 skp = &saun;
 1045                 sasize = sizeof(saun);
 1046                 if (bnd.offs == 0)
 1047                         goto reply;
 1048 
 1049                 netaddr_to_sockaddr_un(&saun, &bnd);
 1050 
 1051                 if (saun.sun_path[0] == '\0')
 1052                         goto reply;
 1053 
 1054                 DPRINTF(("TI_BIND: fam %d, path %s\n",
 1055                          saun.sun_family, saun.sun_path));
 1056 
 1057                 if ((error = clean_pipe(td, saun.sun_path)) != 0)
 1058                         return error;
 1059 
 1060                 bnd.pad[28] = 0x00001000;       /* magic again */
 1061                 break;
 1062 
 1063         default:
 1064                 DPRINTF(("TI_BIND: Unsupported address family %d\n",
 1065                          st->s_family));
 1066                 return ENOSYS;
 1067         }
 1068 
 1069         sg = stackgap_init();
 1070         sup = stackgap_alloc(&sg, sasize);
 1071 
 1072         if ((error = copyout(skp, sup, sasize)) != 0)
 1073                 return error;
 1074 
 1075         ba.s = fd;
 1076         DPRINTF(("TI_BIND: fileno %d\n", fd));
 1077         ba.name = (void *) sup;
 1078         ba.namelen = sasize;
 1079 
 1080         if ((error = bind(td, &ba)) != 0) {
 1081                 DPRINTF(("TI_BIND: bind failed %d\n", error));
 1082                 return error;
 1083         }
 1084 
 1085 reply:
 1086         if (sup == NULL) {
 1087                 memset(&bnd, 0, sizeof(bnd));
 1088                 bnd.len = sasize + 4;
 1089                 bnd.offs = 0x10;        /* XXX */
 1090         }
 1091 
 1092         bnd.cmd = SVR4_TI_BIND_REPLY;
 1093 
 1094         if ((error = copyout(&bnd, ioc->buf, ioc->len)) != 0)
 1095                 return error;
 1096 
 1097         return 0;
 1098 }
 1099 
 1100 
 1101 static int
 1102 timod(fp, fd, ioc, td)
 1103         struct file             *fp;
 1104         int                      fd;
 1105         struct svr4_strioctl    *ioc;
 1106         struct thread           *td;
 1107 {
 1108         switch (ioc->cmd) {
 1109         case SVR4_TI_GETINFO:
 1110                 DPRINTF(("TI_GETINFO\n"));
 1111                 return ti_getinfo(fp, fd, ioc, td);
 1112 
 1113         case SVR4_TI_OPTMGMT:
 1114                 DPRINTF(("TI_OPTMGMT\n"));
 1115                 return 0;
 1116 
 1117         case SVR4_TI_BIND:
 1118                 DPRINTF(("TI_BIND\n"));
 1119                 return ti_bind(fp, fd, ioc, td);
 1120 
 1121         case SVR4_TI_UNBIND:
 1122                 DPRINTF(("TI_UNBIND\n"));
 1123                 return 0;
 1124 
 1125         default:
 1126                 DPRINTF(("Unknown timod ioctl %lx\n", ioc->cmd));
 1127                 return 0;
 1128         }
 1129 }
 1130 
 1131 
 1132 int
 1133 svr4_stream_ti_ioctl(fp, td, retval, fd, cmd, dat)
 1134         struct file *fp;
 1135         struct thread *td;
 1136         register_t *retval;
 1137         int fd;
 1138         u_long cmd;
 1139         caddr_t dat;
 1140 {
 1141         struct svr4_strbuf skb, *sub = (struct svr4_strbuf *) dat;
 1142         struct svr4_strm *st = svr4_stream_get(fp);
 1143         int error;
 1144         void *skp, *sup;
 1145         struct sockaddr_in sain;
 1146         struct sockaddr_un saun;
 1147         struct svr4_strmcmd sc;
 1148         int sasize, oldsasize;
 1149         caddr_t sg;
 1150         int *lenp;
 1151 
 1152         DPRINTF(("svr4_stream_ti_ioctl\n"));
 1153 
 1154         if (st == NULL)
 1155                 return EINVAL;
 1156 
 1157         sc.offs = 0x10;
 1158         
 1159         if ((error = copyin(sub, &skb, sizeof(skb))) != 0) {
 1160                 DPRINTF(("ti_ioctl: error copying in strbuf\n"));
 1161                 return error;
 1162         }
 1163 
 1164         switch (st->s_family) {
 1165         case AF_INET:
 1166                 skp = &sain;
 1167                 sasize = sizeof(sain);
 1168                 break;
 1169 
 1170         case AF_LOCAL:
 1171                 skp = &saun;
 1172                 sasize = sizeof(saun);
 1173                 break;
 1174 
 1175         default:
 1176                 DPRINTF(("ti_ioctl: Unsupported address family %d\n",
 1177                          st->s_family));
 1178                 return ENOSYS;
 1179         }
 1180 
 1181         sg = stackgap_init();
 1182         sup = stackgap_alloc(&sg, sasize);
 1183         lenp = stackgap_alloc(&sg, sizeof(*lenp));
 1184 
 1185         if ((error = copyout(&sasize, lenp, sizeof(*lenp))) != 0) {
 1186                 DPRINTF(("ti_ioctl: error copying out lenp\n"));
 1187                 return error;
 1188         }
 1189 
 1190         switch (cmd) {
 1191         case SVR4_TI_GETMYNAME:
 1192                 DPRINTF(("TI_GETMYNAME\n"));
 1193                 {
 1194                         struct getsockname_args ap;
 1195                         ap.fdes = fd;
 1196                         ap.asa = sup;
 1197                         ap.alen = lenp;
 1198                         if ((error = getsockname(td, &ap)) != 0) {
 1199                                 DPRINTF(("ti_ioctl: getsockname error\n"));
 1200                                 return error;
 1201                         }
 1202                 }
 1203                 break;
 1204 
 1205         case SVR4_TI_GETPEERNAME:
 1206                 DPRINTF(("TI_GETPEERNAME\n"));
 1207                 {
 1208                         struct getpeername_args ap;
 1209                         ap.fdes = fd;
 1210                         ap.asa = sup;
 1211                         ap.alen = lenp;
 1212                         if ((error = getpeername(td, &ap)) != 0) {
 1213                                 DPRINTF(("ti_ioctl: getpeername error\n"));
 1214                                 return error;
 1215                         }
 1216                 }
 1217                 break;
 1218 
 1219         case SVR4_TI_SETMYNAME:
 1220                 DPRINTF(("TI_SETMYNAME\n"));
 1221                 return 0;
 1222 
 1223         case SVR4_TI_SETPEERNAME:
 1224                 DPRINTF(("TI_SETPEERNAME\n"));
 1225                 return 0;
 1226         default:
 1227                 DPRINTF(("ti_ioctl: Unknown ioctl %lx\n", cmd));
 1228                 return ENOSYS;
 1229         }
 1230 
 1231         if ((error = copyin(sup, skp, sasize)) != 0) {
 1232                 DPRINTF(("ti_ioctl: error copying in socket data\n"));
 1233                 return error;
 1234         }
 1235 
 1236         oldsasize = sasize;
 1237 
 1238         if ((error = copyin(lenp, &sasize, sizeof(*lenp))) != 0) {
 1239                 DPRINTF(("ti_ioctl: error copying in socket size\n"));
 1240                 return error;
 1241         }
 1242 
 1243         if (sasize < 0 || sasize > oldsasize)
 1244                 return EINVAL;
 1245 
 1246         switch (st->s_family) {
 1247         case AF_INET:
 1248                 sockaddr_to_netaddr_in(&sc, &sain);
 1249                 skb.len = sasize;
 1250                 break;
 1251 
 1252         case AF_LOCAL:
 1253                 sockaddr_to_netaddr_un(&sc, &saun);
 1254                 skb.len = sasize + 4;
 1255                 break;
 1256 
 1257         default:
 1258                 return ENOSYS;
 1259         }
 1260 
 1261 
 1262         if ((error = copyout(SVR4_ADDROF(&sc), skb.buf, sasize)) != 0) {
 1263                 DPRINTF(("ti_ioctl: error copying out socket data\n"));
 1264                 return error;
 1265         }
 1266 
 1267 
 1268         if ((error = copyout(&skb, sub, sizeof(skb))) != 0) {
 1269                 DPRINTF(("ti_ioctl: error copying out strbuf\n"));
 1270                 return error;
 1271         }
 1272 
 1273         return error;
 1274 }
 1275 
 1276 
 1277 
 1278 
 1279 static int
 1280 i_nread(fp, td, retval, fd, cmd, dat)
 1281         struct file *fp;
 1282         struct thread *td;
 1283         register_t *retval;
 1284         int fd;
 1285         u_long cmd;
 1286         caddr_t dat;
 1287 {
 1288         int error;
 1289         int nread = 0;  
 1290 
 1291         /*
 1292          * We are supposed to return the message length in nread, and the
 1293          * number of messages in retval. We don't have the notion of number
 1294          * of stream messages, so we just find out if we have any bytes waiting
 1295          * for us, and if we do, then we assume that we have at least one
 1296          * message waiting for us.
 1297          */
 1298         if ((error = fo_ioctl(fp, FIONREAD, (caddr_t) &nread, td->td_ucred,
 1299             td)) != 0)
 1300                 return error;
 1301 
 1302         if (nread != 0)
 1303                 *retval = 1;
 1304         else
 1305                 *retval = 0;
 1306 
 1307         return copyout(&nread, dat, sizeof(nread));
 1308 }
 1309 
 1310 static int
 1311 i_fdinsert(fp, td, retval, fd, cmd, dat)
 1312         struct file *fp;
 1313         struct thread *td;
 1314         register_t *retval;
 1315         int fd;
 1316         u_long cmd;
 1317         caddr_t dat;
 1318 {
 1319         /*
 1320          * Major hack again here. We assume that we are using this to
 1321          * implement accept(2). If that is the case, we have already
 1322          * called accept, and we have stored the file descriptor in
 1323          * afd. We find the file descriptor that the code wants to use
 1324          * in fd insert, and then we dup2() our accepted file descriptor
 1325          * to it.
 1326          */
 1327         int error;
 1328         struct svr4_strm *st = svr4_stream_get(fp);
 1329         struct svr4_strfdinsert fdi;
 1330         struct dup2_args d2p;
 1331         struct close_args clp;
 1332 
 1333         if (st == NULL) {
 1334                 DPRINTF(("fdinsert: bad file type\n"));
 1335                 return EINVAL;
 1336         }
 1337 
 1338         if (st->s_afd == -1) {
 1339                 DPRINTF(("fdinsert: accept fd not found\n"));
 1340                 return ENOENT;
 1341         }
 1342 
 1343         if ((error = copyin(dat, &fdi, sizeof(fdi))) != 0) {
 1344                 DPRINTF(("fdinsert: copyin failed %d\n", error));
 1345                 return error;
 1346         }
 1347 
 1348         d2p.from = st->s_afd;
 1349         d2p.to = fdi.fd;
 1350 
 1351         if ((error = dup2(td, &d2p)) != 0) {
 1352                 DPRINTF(("fdinsert: dup2(%d, %d) failed %d\n", 
 1353                     st->s_afd, fdi.fd, error));
 1354                 return error;
 1355         }
 1356 
 1357         clp.fd = st->s_afd;
 1358 
 1359         if ((error = close(td, &clp)) != 0) {
 1360                 DPRINTF(("fdinsert: close(%d) failed %d\n", 
 1361                     st->s_afd, error));
 1362                 return error;
 1363         }
 1364 
 1365         st->s_afd = -1;
 1366 
 1367         *retval = 0;
 1368         return 0;
 1369 }
 1370 
 1371 
 1372 static int
 1373 _i_bind_rsvd(fp, td, retval, fd, cmd, dat)
 1374         struct file *fp;
 1375         struct thread *td;
 1376         register_t *retval;
 1377         int fd;
 1378         u_long cmd;
 1379         caddr_t dat;
 1380 {
 1381         struct mkfifo_args ap;
 1382 
 1383         /*
 1384          * This is a supposed to be a kernel and library only ioctl.
 1385          * It gets called before ti_bind, when we have a unix 
 1386          * socket, to physically create the socket transport and
 1387          * ``reserve'' it. I don't know how this get reserved inside
 1388          * the kernel, but we are going to create it nevertheless.
 1389          */
 1390         ap.path = dat;
 1391         ap.mode = S_IFIFO;
 1392 
 1393         return mkfifo(td, &ap);
 1394 }
 1395 
 1396 static int
 1397 _i_rele_rsvd(fp, td, retval, fd, cmd, dat)
 1398         struct file *fp;
 1399         struct thread *td;
 1400         register_t *retval;
 1401         int fd;
 1402         u_long cmd;
 1403         caddr_t dat;
 1404 {
 1405         struct unlink_args ap;
 1406 
 1407         /*
 1408          * This is a supposed to be a kernel and library only ioctl.
 1409          * I guess it is supposed to release the socket.
 1410          */
 1411         ap.path = dat;
 1412 
 1413         return unlink(td, &ap);
 1414 }
 1415 
 1416 static int
 1417 i_str(fp, td, retval, fd, cmd, dat)
 1418         struct file *fp;
 1419         struct thread *td;
 1420         register_t *retval;
 1421         int fd;
 1422         u_long cmd;
 1423         caddr_t dat;
 1424 {
 1425         int                      error;
 1426         struct svr4_strioctl     ioc;
 1427 
 1428         if ((error = copyin(dat, &ioc, sizeof(ioc))) != 0)
 1429                 return error;
 1430 
 1431 #ifdef DEBUG_SVR4
 1432         if ((error = show_ioc(">", &ioc)) != 0)
 1433                 return error;
 1434 #endif /* DEBUG_SVR4 */
 1435 
 1436         switch (ioc.cmd & 0xff00) {
 1437         case SVR4_SIMOD:
 1438                 if ((error = sockmod(fp, fd, &ioc, td)) != 0)
 1439                         return error;
 1440                 break;
 1441 
 1442         case SVR4_TIMOD:
 1443                 if ((error = timod(fp, fd, &ioc, td)) != 0)
 1444                         return error;
 1445                 break;
 1446 
 1447         default:
 1448                 DPRINTF(("Unimplemented module %c %ld\n",
 1449                          (char) (cmd >> 8), cmd & 0xff));
 1450                 return 0;
 1451         }
 1452 
 1453 #ifdef DEBUG_SVR4
 1454         if ((error = show_ioc("<", &ioc)) != 0)
 1455                 return error;
 1456 #endif /* DEBUG_SVR4 */
 1457         return copyout(&ioc, dat, sizeof(ioc));
 1458 }
 1459 
 1460 static int
 1461 i_setsig(fp, td, retval, fd, cmd, dat)
 1462         struct file *fp;
 1463         struct thread *td;
 1464         register_t *retval;
 1465         int fd;
 1466         u_long cmd;
 1467         caddr_t dat;
 1468 {
 1469         /* 
 1470          * This is the best we can do for now; we cannot generate
 1471          * signals only for specific events so the signal mask gets
 1472          * ignored; we save it just to pass it to a possible I_GETSIG...
 1473          *
 1474          * We alse have to fix the O_ASYNC fcntl bit, so the
 1475          * process will get SIGPOLLs.
 1476          */
 1477         int error;
 1478         register_t oflags, flags;
 1479         struct svr4_strm *st = svr4_stream_get(fp);
 1480 
 1481         if (st == NULL) {
 1482                 DPRINTF(("i_setsig: bad file descriptor\n"));
 1483                 return EINVAL;
 1484         }
 1485         /* get old status flags */
 1486         error = kern_fcntl(td, fd, F_GETFL, 0);
 1487         if (error)
 1488                 return (error);
 1489 
 1490         oflags = td->td_retval[0];
 1491 
 1492         /* update the flags */
 1493         if (dat != NULL) {
 1494                 int mask;
 1495 
 1496                 flags = oflags | O_ASYNC;
 1497                 if ((error = copyin(dat, &mask, sizeof(mask))) != 0) {
 1498                           DPRINTF(("i_setsig: bad eventmask pointer\n"));
 1499                           return error;
 1500                 }
 1501                 if (mask & SVR4_S_ALLMASK) {
 1502                           DPRINTF(("i_setsig: bad eventmask data %x\n", mask));
 1503                           return EINVAL;
 1504                 }
 1505                 st->s_eventmask = mask;
 1506         }
 1507         else {
 1508                 flags = oflags & ~O_ASYNC;
 1509                 st->s_eventmask = 0;
 1510         }
 1511 
 1512         /* set the new flags, if changed */
 1513         if (flags != oflags) {
 1514                 error = kern_fcntl(td, fd, F_SETFL, flags);
 1515                 if (error)
 1516                         return (error);
 1517                 flags = td->td_retval[0];
 1518         }
 1519 
 1520         /* set up SIGIO receiver if needed */
 1521         if (dat != NULL)
 1522                 return (kern_fcntl(td, fd, F_SETOWN, td->td_proc->p_pid));
 1523         return 0;
 1524 }
 1525 
 1526 static int
 1527 i_getsig(fp, td, retval, fd, cmd, dat)
 1528         struct file *fp;
 1529         struct thread *td;
 1530         register_t *retval;
 1531         int fd;
 1532         u_long cmd;
 1533         caddr_t dat;
 1534 {
 1535         int error;
 1536 
 1537         if (dat != NULL) {
 1538                 struct svr4_strm *st = svr4_stream_get(fp);
 1539 
 1540                 if (st == NULL) {
 1541                         DPRINTF(("i_getsig: bad file descriptor\n"));
 1542                         return EINVAL;
 1543                 }
 1544                 if ((error = copyout(&st->s_eventmask, dat, 
 1545                                      sizeof(st->s_eventmask))) != 0) {
 1546                         DPRINTF(("i_getsig: bad eventmask pointer\n"));
 1547                         return error;
 1548                 }
 1549         }
 1550         return 0;
 1551 }
 1552 
 1553 int
 1554 svr4_stream_ioctl(fp, td, retval, fd, cmd, dat)
 1555         struct file *fp;
 1556         struct thread *td;
 1557         register_t *retval;
 1558         int fd;
 1559         u_long cmd;
 1560         caddr_t dat;
 1561 {
 1562         *retval = 0;
 1563 
 1564         /*
 1565          * All the following stuff assumes "sockmod" is pushed...
 1566          */
 1567         switch (cmd) {
 1568         case SVR4_I_NREAD:
 1569                 DPRINTF(("I_NREAD\n"));
 1570                 return i_nread(fp, td, retval, fd, cmd, dat);
 1571 
 1572         case SVR4_I_PUSH:
 1573                 DPRINTF(("I_PUSH %p\n", dat));
 1574 #if defined(DEBUG_SVR4)
 1575                 show_strbuf((struct svr4_strbuf *)dat);
 1576 #endif
 1577                 return 0;
 1578 
 1579         case SVR4_I_POP:
 1580                 DPRINTF(("I_POP\n"));
 1581                 return 0;
 1582 
 1583         case SVR4_I_LOOK:
 1584                 DPRINTF(("I_LOOK\n"));
 1585                 return 0;
 1586 
 1587         case SVR4_I_FLUSH:
 1588                 DPRINTF(("I_FLUSH\n"));
 1589                 return 0;
 1590 
 1591         case SVR4_I_SRDOPT:
 1592                 DPRINTF(("I_SRDOPT\n"));
 1593                 return 0;
 1594 
 1595         case SVR4_I_GRDOPT:
 1596                 DPRINTF(("I_GRDOPT\n"));
 1597                 return 0;
 1598 
 1599         case SVR4_I_STR:
 1600                 DPRINTF(("I_STR\n"));
 1601                 return i_str(fp, td, retval, fd, cmd, dat);
 1602 
 1603         case SVR4_I_SETSIG:
 1604                 DPRINTF(("I_SETSIG\n"));
 1605                 return i_setsig(fp, td, retval, fd, cmd, dat);
 1606 
 1607         case SVR4_I_GETSIG:
 1608                 DPRINTF(("I_GETSIG\n"));
 1609                 return i_getsig(fp, td, retval, fd, cmd, dat);
 1610 
 1611         case SVR4_I_FIND:
 1612                 DPRINTF(("I_FIND\n"));
 1613                 /*
 1614                  * Here we are not pushing modules really, we just
 1615                  * pretend all are present
 1616                  */
 1617                 *retval = 0;
 1618                 return 0;
 1619 
 1620         case SVR4_I_LINK:
 1621                 DPRINTF(("I_LINK\n"));
 1622                 return 0;
 1623 
 1624         case SVR4_I_UNLINK:
 1625                 DPRINTF(("I_UNLINK\n"));
 1626                 return 0;
 1627 
 1628         case SVR4_I_ERECVFD:
 1629                 DPRINTF(("I_ERECVFD\n"));
 1630                 return 0;
 1631 
 1632         case SVR4_I_PEEK:
 1633                 DPRINTF(("I_PEEK\n"));
 1634                 return 0;
 1635 
 1636         case SVR4_I_FDINSERT:
 1637                 DPRINTF(("I_FDINSERT\n"));
 1638                 return i_fdinsert(fp, td, retval, fd, cmd, dat);
 1639 
 1640         case SVR4_I_SENDFD:
 1641                 DPRINTF(("I_SENDFD\n"));
 1642                 return 0;
 1643 
 1644         case SVR4_I_RECVFD:
 1645                 DPRINTF(("I_RECVFD\n"));
 1646                 return 0;
 1647 
 1648         case SVR4_I_SWROPT:
 1649                 DPRINTF(("I_SWROPT\n"));
 1650                 return 0;
 1651 
 1652         case SVR4_I_GWROPT:
 1653                 DPRINTF(("I_GWROPT\n"));
 1654                 return 0;
 1655 
 1656         case SVR4_I_LIST:
 1657                 DPRINTF(("I_LIST\n"));
 1658                 return 0;
 1659 
 1660         case SVR4_I_PLINK:
 1661                 DPRINTF(("I_PLINK\n"));
 1662                 return 0;
 1663 
 1664         case SVR4_I_PUNLINK:
 1665                 DPRINTF(("I_PUNLINK\n"));
 1666                 return 0;
 1667 
 1668         case SVR4_I_SETEV:
 1669                 DPRINTF(("I_SETEV\n"));
 1670                 return 0;
 1671 
 1672         case SVR4_I_GETEV:
 1673                 DPRINTF(("I_GETEV\n"));
 1674                 return 0;
 1675 
 1676         case SVR4_I_STREV:
 1677                 DPRINTF(("I_STREV\n"));
 1678                 return 0;
 1679 
 1680         case SVR4_I_UNSTREV:
 1681                 DPRINTF(("I_UNSTREV\n"));
 1682                 return 0;
 1683 
 1684         case SVR4_I_FLUSHBAND:
 1685                 DPRINTF(("I_FLUSHBAND\n"));
 1686                 return 0;
 1687 
 1688         case SVR4_I_CKBAND:
 1689                 DPRINTF(("I_CKBAND\n"));
 1690                 return 0;
 1691 
 1692         case SVR4_I_GETBAND:
 1693                 DPRINTF(("I_GETBANK\n"));
 1694                 return 0;
 1695 
 1696         case SVR4_I_ATMARK:
 1697                 DPRINTF(("I_ATMARK\n"));
 1698                 return 0;
 1699 
 1700         case SVR4_I_SETCLTIME:
 1701                 DPRINTF(("I_SETCLTIME\n"));
 1702                 return 0;
 1703 
 1704         case SVR4_I_GETCLTIME:
 1705                 DPRINTF(("I_GETCLTIME\n"));
 1706                 return 0;
 1707 
 1708         case SVR4_I_CANPUT:
 1709                 DPRINTF(("I_CANPUT\n"));
 1710                 return 0;
 1711 
 1712         case SVR4__I_BIND_RSVD:
 1713                 DPRINTF(("_I_BIND_RSVD\n"));
 1714                 return _i_bind_rsvd(fp, td, retval, fd, cmd, dat);
 1715 
 1716         case SVR4__I_RELE_RSVD:
 1717                 DPRINTF(("_I_RELE_RSVD\n"));
 1718                 return _i_rele_rsvd(fp, td, retval, fd, cmd, dat);
 1719 
 1720         default:
 1721                 DPRINTF(("unimpl cmd = %lx\n", cmd));
 1722                 break;
 1723         }
 1724 
 1725         return 0;
 1726 }
 1727 
 1728 
 1729 
 1730 int
 1731 svr4_sys_putmsg(td, uap)
 1732         register struct thread *td;
 1733         struct svr4_sys_putmsg_args *uap;
 1734 {
 1735         struct file     *fp;
 1736         int error;
 1737 
 1738         if ((error = fget(td, uap->fd, &fp)) != 0) {
 1739 #ifdef DEBUG_SVR4
 1740                 uprintf("putmsg: bad fp\n");
 1741 #endif
 1742                 return EBADF;
 1743         }
 1744         error = svr4_do_putmsg(td, uap, fp);
 1745         fdrop(fp, td);
 1746         return (error);
 1747 }
 1748 
 1749 static int
 1750 svr4_do_putmsg(td, uap, fp)
 1751         struct thread *td;
 1752         struct svr4_sys_putmsg_args *uap;
 1753         struct file     *fp;
 1754 {
 1755         struct svr4_strbuf dat, ctl;
 1756         struct svr4_strmcmd sc;
 1757         struct sockaddr_in sain;
 1758         struct sockaddr_un saun;
 1759         void *skp, *sup;
 1760         int sasize, *retval;
 1761         struct svr4_strm *st;
 1762         int error;
 1763         caddr_t sg;
 1764 
 1765         retval = td->td_retval;
 1766 
 1767 #ifdef DEBUG_SVR4
 1768         show_msg(">putmsg", uap->fd, uap->ctl,
 1769                  uap->dat, uap->flags);
 1770 #endif /* DEBUG_SVR4 */
 1771 
 1772         FILE_LOCK_ASSERT(fp, MA_NOTOWNED);
 1773 
 1774         if (uap->ctl != NULL) {
 1775           if ((error = copyin(uap->ctl, &ctl, sizeof(ctl))) != 0) {
 1776 #ifdef DEBUG_SVR4
 1777             uprintf("putmsg: copyin(): %d\n", error);
 1778 #endif
 1779             return error;
 1780           }
 1781         }
 1782         else
 1783                 ctl.len = -1;
 1784 
 1785         if (uap->dat != NULL) {
 1786           if ((error = copyin(uap->dat, &dat, sizeof(dat))) != 0) {
 1787 #ifdef DEBUG_SVR4
 1788             uprintf("putmsg: copyin(): %d (2)\n", error);
 1789 #endif
 1790             return error;
 1791           }
 1792         }
 1793         else
 1794                 dat.len = -1;
 1795 
 1796         /*
 1797          * Only for sockets for now.
 1798          */
 1799         if ((st = svr4_stream_get(fp)) == NULL) {
 1800                 DPRINTF(("putmsg: bad file type\n"));
 1801                 return EINVAL;
 1802         }
 1803 
 1804         if (ctl.len < 0 || ctl.len > sizeof(sc)) {
 1805                 DPRINTF(("putmsg: Bad control size %d != %d\n", ctl.len,
 1806                          sizeof(struct svr4_strmcmd)));
 1807                 return EINVAL;
 1808         }
 1809 
 1810         if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0)
 1811                 return error;
 1812 
 1813         switch (st->s_family) {
 1814         case AF_INET:
 1815                 if (sc.len != sizeof(sain)) {
 1816                         if (sc.cmd == SVR4_TI_DATA_REQUEST) {
 1817                                 struct write_args wa;
 1818 
 1819                                 /* Solaris seems to use sc.cmd = 3 to
 1820                                  * send "expedited" data.  telnet uses
 1821                                  * this for options processing, sending EOF,
 1822                                  * etc.  I'm sure other things use it too.
 1823                                  * I don't have any documentation
 1824                                  * on it, so I'm making a guess that this
 1825                                  * is how it works. newton@atdot.dotat.org XXX
 1826                                  */
 1827                                 DPRINTF(("sending expedited data ??\n"));
 1828                                 wa.fd = uap->fd;
 1829                                 wa.buf = dat.buf;
 1830                                 wa.nbyte = dat.len;
 1831                                 return write(td, &wa);
 1832                         }
 1833                         DPRINTF(("putmsg: Invalid inet length %ld\n", sc.len));
 1834                         return EINVAL;
 1835                 }
 1836                 netaddr_to_sockaddr_in(&sain, &sc);
 1837                 skp = &sain;
 1838                 sasize = sizeof(sain);
 1839                 error = sain.sin_family != st->s_family;
 1840                 break;
 1841 
 1842         case AF_LOCAL:
 1843                 if (ctl.len == 8) {
 1844                         /* We are doing an accept; succeed */
 1845                         DPRINTF(("putmsg: Do nothing\n"));
 1846                         *retval = 0;
 1847                         return 0;
 1848                 }
 1849                 else {
 1850                         /* Maybe we've been given a device/inode pair */
 1851                         dev_t *dev = SVR4_ADDROF(&sc);
 1852                         ino_t *ino = (ino_t *) &dev[1];
 1853                         skp = svr4_find_socket(td, fp, *dev, *ino);
 1854                         if (skp == NULL) {
 1855                                 skp = &saun;
 1856                                 /* I guess we have it by name */
 1857                                 netaddr_to_sockaddr_un(skp, &sc);
 1858                         }
 1859                         sasize = sizeof(saun);
 1860                 }
 1861                 break;
 1862 
 1863         default:
 1864                 DPRINTF(("putmsg: Unsupported address family %d\n",
 1865                          st->s_family));
 1866                 return ENOSYS;
 1867         }
 1868 
 1869         sg = stackgap_init();
 1870         sup = stackgap_alloc(&sg, sasize);
 1871 
 1872         if ((error = copyout(skp, sup, sasize)) != 0)
 1873                 return error;
 1874 
 1875         switch (st->s_cmd = sc.cmd) {
 1876         case SVR4_TI_CONNECT_REQUEST:   /* connect      */
 1877                 {
 1878                         struct connect_args co;
 1879 
 1880                         co.s = uap->fd;
 1881                         co.name = (void *) sup;
 1882                         co.namelen = (int) sasize;
 1883                         
 1884                         return connect(td, &co);
 1885                 }
 1886 
 1887         case SVR4_TI_SENDTO_REQUEST:    /* sendto       */
 1888                 {
 1889                         struct msghdr msg;
 1890                         struct iovec aiov;
 1891 
 1892                         msg.msg_name = (caddr_t) sup;
 1893                         msg.msg_namelen = sasize;
 1894                         msg.msg_iov = &aiov;
 1895                         msg.msg_iovlen = 1;
 1896                         msg.msg_control = 0;
 1897                         msg.msg_flags = 0;
 1898                         aiov.iov_base = dat.buf;
 1899                         aiov.iov_len = dat.len;
 1900 #if 0
 1901                         error = so->so_proto->pr_usrreqs->pru_sosend(so, 0, 
 1902                                               uio, 0, 0, 0, uio->uio_td);
 1903 #endif
 1904                         error = svr4_sendit(td, uap->fd, &msg,
 1905                                        uap->flags);
 1906                         DPRINTF(("sendto_request error: %d\n", error));
 1907                         *retval = 0;
 1908                         return error;
 1909                 }
 1910 
 1911         default:
 1912                 DPRINTF(("putmsg: Unimplemented command %lx\n", sc.cmd));
 1913                 return ENOSYS;
 1914         }
 1915 }
 1916 
 1917 int
 1918 svr4_sys_getmsg(td, uap)
 1919         struct thread *td;
 1920         struct svr4_sys_getmsg_args *uap;
 1921 {
 1922         struct file     *fp;
 1923         int error;
 1924 
 1925         if ((error = fget(td, uap->fd, &fp)) != 0) {
 1926 #ifdef DEBUG_SVR4
 1927                 uprintf("getmsg: bad fp\n");
 1928 #endif
 1929                 return EBADF;
 1930         }
 1931         error = svr4_do_getmsg(td, uap, fp);
 1932         fdrop(fp, td);
 1933         return (error);
 1934 }
 1935 
 1936 int
 1937 svr4_do_getmsg(td, uap, fp)
 1938         register struct thread *td;
 1939         struct svr4_sys_getmsg_args *uap;
 1940         struct file *fp;
 1941 {
 1942         struct getpeername_args ga;
 1943         struct accept_args aa;
 1944         struct svr4_strbuf dat, ctl;
 1945         struct svr4_strmcmd sc;
 1946         int error, *retval;
 1947         struct msghdr msg;
 1948         struct iovec aiov;
 1949         struct sockaddr_in sain;
 1950         struct sockaddr_un saun;
 1951         void *skp, *sup;
 1952         int sasize;
 1953         struct svr4_strm *st;
 1954         int *flen;
 1955         int fl;
 1956         caddr_t sg;
 1957 
 1958         retval = td->td_retval;
 1959 
 1960         FILE_LOCK_ASSERT(fp, MA_NOTOWNED);
 1961 
 1962         memset(&sc, 0, sizeof(sc));
 1963 
 1964 #ifdef DEBUG_SVR4
 1965         show_msg(">getmsg", uap->fd, uap->ctl,
 1966                  uap->dat, 0);
 1967 #endif /* DEBUG_SVR4 */
 1968 
 1969         if (uap->ctl != NULL) {
 1970                 if ((error = copyin(uap->ctl, &ctl, sizeof(ctl))) != 0)
 1971                         return error;
 1972                 if (ctl.len < 0)
 1973                         return EINVAL;
 1974         }
 1975         else {
 1976                 ctl.len = -1;
 1977                 ctl.maxlen = 0;
 1978         }
 1979 
 1980         if (uap->dat != NULL) {
 1981                 if ((error = copyin(uap->dat, &dat, sizeof(dat))) != 0)
 1982                         return error;
 1983         }
 1984         else {
 1985                 dat.len = -1;
 1986                 dat.maxlen = 0;
 1987         }
 1988 
 1989         /*
 1990          * Only for sockets for now.
 1991          */
 1992         if ((st = svr4_stream_get(fp)) == NULL) {
 1993                 DPRINTF(("getmsg: bad file type\n"));
 1994                 return EINVAL;
 1995         }
 1996 
 1997         if (ctl.maxlen == -1 || dat.maxlen == -1) {
 1998                 DPRINTF(("getmsg: Cannot handle -1 maxlen (yet)\n"));
 1999                 return ENOSYS;
 2000         }
 2001 
 2002         switch (st->s_family) {
 2003         case AF_INET:
 2004                 skp = &sain;
 2005                 sasize = sizeof(sain);
 2006                 break;
 2007 
 2008         case AF_LOCAL:
 2009                 skp = &saun;
 2010                 sasize = sizeof(saun);
 2011                 break;
 2012 
 2013         default:
 2014                 DPRINTF(("getmsg: Unsupported address family %d\n",
 2015                          st->s_family));
 2016                 return ENOSYS;
 2017         }
 2018 
 2019         sg = stackgap_init();
 2020         sup = stackgap_alloc(&sg, sasize);
 2021         flen = (int *) stackgap_alloc(&sg, sizeof(*flen));
 2022 
 2023         fl = sasize;
 2024         if ((error = copyout(&fl, flen, sizeof(fl))) != 0)
 2025                 return error;
 2026 
 2027         switch (st->s_cmd) {
 2028         case SVR4_TI_CONNECT_REQUEST:
 2029                 DPRINTF(("getmsg: TI_CONNECT_REQUEST\n"));
 2030                 /*
 2031                  * We do the connect in one step, so the putmsg should
 2032                  * have gotten the error.
 2033                  */
 2034                 sc.cmd = SVR4_TI_OK_REPLY;
 2035                 sc.len = 0;
 2036 
 2037                 ctl.len = 8;
 2038                 dat.len = -1;
 2039                 fl = 1;
 2040                 st->s_cmd = sc.cmd;
 2041                 break;
 2042 
 2043         case SVR4_TI_OK_REPLY:
 2044                 DPRINTF(("getmsg: TI_OK_REPLY\n"));
 2045                 /*
 2046                  * We are immediately after a connect reply, so we send
 2047                  * a connect verification.
 2048                  */
 2049 
 2050                 ga.fdes = uap->fd;
 2051                 ga.asa = (void *) sup;
 2052                 ga.alen = flen;
 2053                 
 2054                 if ((error = getpeername(td, &ga)) != 0) {
 2055                         DPRINTF(("getmsg: getpeername failed %d\n", error));
 2056                         return error;
 2057                 }
 2058 
 2059                 if ((error = copyin(sup, skp, sasize)) != 0)
 2060                         return error;
 2061                 
 2062                 sc.cmd = SVR4_TI_CONNECT_REPLY;
 2063                 sc.pad[0] = 0x4;
 2064                 sc.offs = 0x18;
 2065                 sc.pad[1] = 0x14;
 2066                 sc.pad[2] = 0x04000402;
 2067 
 2068                 switch (st->s_family) {
 2069                 case AF_INET:
 2070                         sc.len = sasize;
 2071                         sockaddr_to_netaddr_in(&sc, &sain);
 2072                         break;
 2073 
 2074                 case AF_LOCAL:
 2075                         sc.len = sasize + 4;
 2076                         sockaddr_to_netaddr_un(&sc, &saun);
 2077                         break;
 2078 
 2079                 default:
 2080                         return ENOSYS;
 2081                 }
 2082 
 2083                 ctl.len = 40;
 2084                 dat.len = -1;
 2085                 fl = 0;
 2086                 st->s_cmd = sc.cmd;
 2087                 break;
 2088 
 2089         case SVR4_TI__ACCEPT_OK:
 2090                 DPRINTF(("getmsg: TI__ACCEPT_OK\n"));
 2091                 /*
 2092                  * We do the connect in one step, so the putmsg should
 2093                  * have gotten the error.
 2094                  */
 2095                 sc.cmd = SVR4_TI_OK_REPLY;
 2096                 sc.len = 1;
 2097 
 2098                 ctl.len = 8;
 2099                 dat.len = -1;
 2100                 fl = 1;
 2101                 st->s_cmd = SVR4_TI__ACCEPT_WAIT;
 2102                 break;
 2103 
 2104         case SVR4_TI__ACCEPT_WAIT:
 2105                 DPRINTF(("getmsg: TI__ACCEPT_WAIT\n"));
 2106                 /*
 2107                  * We are after a listen, so we try to accept...
 2108                  */
 2109                 aa.s = uap->fd;
 2110                 aa.name = (void *) sup;
 2111                 aa.anamelen = flen;
 2112                 
 2113                 if ((error = accept(td, &aa)) != 0) {
 2114                         DPRINTF(("getmsg: accept failed %d\n", error));
 2115                         return error;
 2116                 }
 2117 
 2118                 st->s_afd = *retval;
 2119 
 2120                 DPRINTF(("getmsg: Accept fd = %d\n", st->s_afd));
 2121 
 2122                 if ((error = copyin(sup, skp, sasize)) != 0)
 2123                         return error;
 2124                 
 2125                 sc.cmd = SVR4_TI_ACCEPT_REPLY;
 2126                 sc.offs = 0x18;
 2127                 sc.pad[0] = 0x0;
 2128 
 2129                 switch (st->s_family) {
 2130                 case AF_INET:
 2131                         sc.pad[1] = 0x28;
 2132                         sockaddr_to_netaddr_in(&sc, &sain);
 2133                         ctl.len = 40;
 2134                         sc.len = sasize;
 2135                         break;
 2136 
 2137                 case AF_LOCAL:
 2138                         sc.pad[1] = 0x00010000;
 2139                         sc.pad[2] = 0xf6bcdaa0; /* I don't know what that is */
 2140                         sc.pad[3] = 0x00010000;
 2141                         ctl.len = 134;
 2142                         sc.len = sasize + 4;
 2143                         break;
 2144 
 2145                 default:
 2146                         return ENOSYS;
 2147                 }
 2148 
 2149                 dat.len = -1;
 2150                 fl = 0;
 2151                 st->s_cmd = SVR4_TI__ACCEPT_OK;
 2152                 break;
 2153 
 2154         case SVR4_TI_SENDTO_REQUEST:
 2155                 DPRINTF(("getmsg: TI_SENDTO_REQUEST\n"));
 2156                 if (ctl.maxlen > 36 && ctl.len < 36)
 2157                     ctl.len = 36;
 2158 
 2159                 if (ctl.len > sizeof(sc))
 2160                         ctl.len = sizeof(sc);
 2161 
 2162                 if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0)
 2163                         return error;
 2164 
 2165                 switch (st->s_family) {
 2166                 case AF_INET:
 2167                         sockaddr_to_netaddr_in(&sc, &sain);
 2168                         break;
 2169 
 2170                 case AF_LOCAL:
 2171                         sockaddr_to_netaddr_un(&sc, &saun);
 2172                         break;
 2173 
 2174                 default:
 2175                         return ENOSYS;
 2176                 }
 2177 
 2178                 msg.msg_name = (caddr_t) sup;
 2179                 msg.msg_namelen = sasize;
 2180                 msg.msg_iov = &aiov;
 2181                 msg.msg_iovlen = 1;
 2182                 msg.msg_control = 0;
 2183                 aiov.iov_base = dat.buf;
 2184                 aiov.iov_len = dat.maxlen;
 2185                 msg.msg_flags = 0;
 2186 
 2187                 error = svr4_recvit(td, uap->fd, &msg, (caddr_t) flen);
 2188 
 2189                 if (error) {
 2190                         DPRINTF(("getmsg: recvit failed %d\n", error));
 2191                         return error;
 2192                 }
 2193 
 2194                 if ((error = copyin(msg.msg_name, skp, sasize)) != 0)
 2195                         return error;
 2196 
 2197                 sc.cmd = SVR4_TI_RECVFROM_IND;
 2198 
 2199                 switch (st->s_family) {
 2200                 case AF_INET:
 2201                         sc.len = sasize;
 2202                         sockaddr_to_netaddr_in(&sc, &sain);
 2203                         break;
 2204 
 2205                 case AF_LOCAL:
 2206                         sc.len = sasize + 4;
 2207                         sockaddr_to_netaddr_un(&sc, &saun);
 2208                         break;
 2209 
 2210                 default:
 2211                         return ENOSYS;
 2212                 }
 2213 
 2214                 dat.len = *retval;
 2215                 fl = 0;
 2216                 st->s_cmd = sc.cmd;
 2217                 break;
 2218 
 2219         default:
 2220                 st->s_cmd = sc.cmd;
 2221                 if (st->s_cmd == SVR4_TI_CONNECT_REQUEST) {
 2222                         struct read_args ra;
 2223 
 2224                         /* More weirdness:  Again, I can't find documentation
 2225                          * to back this up, but when a process does a generic
 2226                          * "getmsg()" call it seems that the command field is
 2227                          * zero and the length of the data area is zero.  I
 2228                          * think processes expect getmsg() to fill in dat.len
 2229                          * after reading at most dat.maxlen octets from the
 2230                          * stream.  Since we're using sockets I can let 
 2231                          * read() look after it and frob return values
 2232                          * appropriately (or inappropriately :-)
 2233                          *   -- newton@atdot.dotat.org        XXX
 2234                          */
 2235                         ra.fd = uap->fd;
 2236                         ra.buf = dat.buf;
 2237                         ra.nbyte = dat.maxlen;
 2238                         if ((error = read(td, &ra)) != 0) {
 2239                                 return error;
 2240                         }
 2241                         dat.len = *retval;
 2242                         *retval = 0;
 2243                         st->s_cmd = SVR4_TI_SENDTO_REQUEST;
 2244                         break;
 2245                 }
 2246                 DPRINTF(("getmsg: Unknown state %x\n", st->s_cmd));
 2247                 return EINVAL;
 2248         }
 2249 
 2250         if (uap->ctl) {
 2251                 if (ctl.len > sizeof(sc))
 2252                         ctl.len = sizeof(sc);
 2253                 if (ctl.len != -1)
 2254                         if ((error = copyout(&sc, ctl.buf, ctl.len)) != 0)
 2255                                 return error;
 2256 
 2257                 if ((error = copyout(&ctl, uap->ctl, sizeof(ctl))) != 0)
 2258                         return error;
 2259         }
 2260 
 2261         if (uap->dat) {
 2262                 if ((error = copyout(&dat, uap->dat, sizeof(dat))) != 0)
 2263                         return error;
 2264         }
 2265 
 2266         if (uap->flags) { /* XXX: Need translation */
 2267                 if ((error = copyout(&fl, uap->flags, sizeof(fl))) != 0)
 2268                         return error;
 2269         }
 2270 
 2271         *retval = 0;
 2272 
 2273 #ifdef DEBUG_SVR4
 2274         show_msg("<getmsg", uap->fd, uap->ctl,
 2275                  uap->dat, fl);
 2276 #endif /* DEBUG_SVR4 */
 2277         return error;
 2278 }
 2279 
 2280 int svr4_sys_send(td, uap)
 2281         struct thread *td;
 2282         struct svr4_sys_send_args *uap;
 2283 {
 2284         struct osend_args osa;
 2285         osa.s = uap->s;
 2286         osa.buf = uap->buf;
 2287         osa.len = uap->len;
 2288         osa.flags = uap->flags;
 2289         return osend(td, &osa);
 2290 }
 2291 
 2292 int svr4_sys_recv(td, uap)
 2293         struct thread *td;
 2294         struct svr4_sys_recv_args *uap;
 2295 {
 2296         struct orecv_args ora;
 2297         ora.s = uap->s;
 2298         ora.buf = uap->buf;
 2299         ora.len = uap->len;
 2300         ora.flags = uap->flags;
 2301         return orecv(td, &ora);
 2302 }
 2303 
 2304 /* 
 2305  * XXX This isn't necessary, but it's handy for inserting debug code into
 2306  * sendto().  Let's leave it here for now...
 2307  */     
 2308 int
 2309 svr4_sys_sendto(td, uap)
 2310         struct thread *td;
 2311         struct svr4_sys_sendto_args *uap;
 2312 {
 2313         struct sendto_args sa;
 2314 
 2315         sa.s = uap->s;
 2316         sa.buf = uap->buf;
 2317         sa.len = uap->len;
 2318         sa.flags = uap->flags;
 2319         sa.to = (caddr_t)uap->to;
 2320         sa.tolen = uap->tolen;
 2321 
 2322         DPRINTF(("calling sendto()\n"));
 2323         return sendto(td, &sa);
 2324 }
 2325 

Cache object: 953852806b451b3aa18ac58df0a368f0


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.